Update sdk/platform-tools to version 26.0.0.
[android_tools.git] / sdk / platform-tools / systrace / catapult / telemetry / telemetry / internal / backends / chrome_inspector / devtools_http.py
blobfecd7680fdccbe89379451765c1ef950ef1da47c
1 # Copyright 2014 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.
5 import errno
6 import httplib
7 import json
8 import socket
9 import sys
11 from telemetry.core import exceptions
14 class DevToolsClientConnectionError(exceptions.Error):
15 pass
18 class DevToolsClientUrlError(DevToolsClientConnectionError):
19 pass
22 class DevToolsHttp(object):
23 """A helper class to send and parse DevTools HTTP requests.
25 This class maintains a persistent http connection to Chrome devtools.
26 Ideally, owners of instances of this class should call Disconnect() before
27 disposing of the instance. Otherwise, the connection will not be closed until
28 the instance is garbage collected.
29 """
31 def __init__(self, devtools_port):
32 self._devtools_port = devtools_port
33 self._conn = None
35 def __del__(self):
36 self.Disconnect()
38 def _Connect(self, timeout):
39 """Attempts to establish a connection to Chrome devtools."""
40 assert not self._conn
41 try:
42 host_port = '127.0.0.1:%i' % self._devtools_port
43 self._conn = httplib.HTTPConnection(host_port, timeout=timeout)
44 except (socket.error, httplib.HTTPException) as e:
45 raise DevToolsClientConnectionError, (e,), sys.exc_info()[2]
47 def Disconnect(self):
48 """Closes the HTTP connection."""
49 if not self._conn:
50 return
52 try:
53 self._conn.close()
54 except (socket.error, httplib.HTTPException) as e:
55 raise DevToolsClientConnectionError, (e,), sys.exc_info()[2]
56 finally:
57 self._conn = None
59 def Request(self, path, timeout=30):
60 """Sends a request to Chrome devtools.
62 This method lazily creates an HTTP connection, if one does not already
63 exist.
65 Args:
66 path: The DevTools URL path, without the /json/ prefix.
67 timeout: Timeout defaults to 30 seconds.
69 Raises:
70 DevToolsClientConnectionError: If the connection fails.
71 """
72 assert timeout
74 if not self._conn:
75 self._Connect(timeout)
77 endpoint = '/json'
78 if path:
79 endpoint += '/' + path
80 if self._conn.sock:
81 self._conn.sock.settimeout(timeout)
82 else:
83 self._conn.timeout = timeout
85 try:
86 # By default, httplib avoids going through the default system proxy.
87 self._conn.request('GET', endpoint)
88 response = self._conn.getresponse()
89 return response.read()
90 except (socket.error, httplib.HTTPException) as e:
91 self.Disconnect()
92 if isinstance(e, socket.error) and e.errno == errno.ECONNREFUSED:
93 raise DevToolsClientUrlError, (e,), sys.exc_info()[2]
94 raise DevToolsClientConnectionError, (e,), sys.exc_info()[2]
96 def RequestJson(self, path, timeout=30):
97 """Sends a request and parse the response as JSON.
99 Args:
100 path: The DevTools URL path, without the /json/ prefix.
101 timeout: Timeout defaults to 30 seconds.
103 Raises:
104 DevToolsClientConnectionError: If the connection fails.
105 ValueError: If the response is not a valid JSON.
107 return json.loads(self.Request(path, timeout))