Upstream version 5.34.98.0
[platform/framework/web/crosswalk.git] / src / tools / telemetry / telemetry / core / temporary_http_server.py
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4 import os
5 import re
6 import socket
7 import subprocess
8 import sys
9 import urlparse
10
11 from telemetry.core import util
12
13 class TemporaryHTTPServer(object):
14   def __init__(self, browser_backend, paths):
15     self._server = None
16     self._devnull = None
17     self._forwarder = None
18
19     for path in paths:
20       assert os.path.exists(path), '%s does not exist.' % path
21     self._paths = set(map(os.path.realpath, paths))
22
23     common_prefix = os.path.commonprefix(self._paths)
24     if os.path.isdir(common_prefix):
25       self._base_dir = common_prefix
26     else:
27       self._base_dir = os.path.dirname(common_prefix)
28
29     self._devnull = open(os.devnull, 'w')
30     cmd = [sys.executable, '-m', 'memory_cache_http_server']
31     cmd.extend(self._paths)
32     env = os.environ.copy()
33     env['PYTHONPATH'] = os.path.abspath(os.path.dirname(__file__))
34     self._server = subprocess.Popen(cmd, cwd=self._base_dir,
35         env=env, stdout=subprocess.PIPE, stderr=self._devnull)
36
37     port_re = re.compile(
38         '.*(?P<protocol>HTTPS?) server started on (?P<host>.*):(?P<port>\d+)')
39     while self._server.poll() == None:
40       m = port_re.match(self._server.stdout.readline())
41       if m:
42         port = int(m.group('port'))
43         break
44
45     self._forwarder = browser_backend.CreateForwarder(
46         util.PortPair(port, browser_backend.GetRemotePort(port)))
47
48     def IsServerUp():
49       return not socket.socket().connect_ex(('localhost', port))
50     util.WaitFor(IsServerUp, 10)
51
52   @property
53   def paths(self):
54     return self._paths
55
56   def __enter__(self):
57     return self
58
59   def __exit__(self, *args):
60     self.Close()
61
62   def __del__(self):
63     self.Close()
64
65   def Close(self):
66     if self._forwarder:
67       self._forwarder.Close()
68       self._forwarder = None
69     if self._server:
70       # TODO(tonyg): Should this block until it goes away?
71       self._server.kill()
72       self._server = None
73     if self._devnull:
74       self._devnull.close()
75       self._devnull = None
76
77   @property
78   def url(self):
79     return self._forwarder.url
80
81   def UrlOf(self, path):
82     relative_path = os.path.relpath(path, self._base_dir)
83     # Preserve trailing slash or backslash.
84     # It doesn't matter in a file path, but it does matter in a URL.
85     if path.endswith(os.sep) or (os.altsep and path.endswith(os.altsep)):
86       relative_path += '/'
87     return urlparse.urljoin(self.url, relative_path.replace(os.sep, '/'))