def _CreateAndConnectBrowserInspectorWebsocketIfNeeded(self): if not self._browser_inspector_websocket: self._browser_inspector_websocket = ( inspector_websocket.InspectorWebsocket()) self._browser_inspector_websocket.Connect( BROWSER_INSPECTOR_WEBSOCKET_URL % self._devtools_port, timeout=10)
def testAsyncRequest(self): inspector = inspector_websocket.InspectorWebsocket() fake_socket = FakeSocket(self._fake_timer) # pylint: disable=protected-access inspector._socket = fake_socket response_count = [0] def callback0(response): response_count[0] += 1 self.assertEqual(2, response_count[0]) self.assertEqual('response1', response['result']['data']) def callback1(response): response_count[0] += 1 self.assertEqual(1, response_count[0]) self.assertEqual('response2', response['result']['data']) request1 = {'method': 'Test.foo'} inspector.AsyncRequest(request1, callback0) request2 = {'method': 'Test.foo'} inspector.AsyncRequest(request2, callback1) fake_socket.AddResponse('{"id": 5555555, "result": {}}', 1) inspector.DispatchNotifications(10) self.assertEqual(0, response_count[0]) fake_socket.AddResponse( '{"id": %d, "result": {"data": "response2"}}' % request2['id'], 1) fake_socket.AddResponse( '{"id": %d, "result": {"data": "response1"}}' % request1['id'], 2) inspector.DispatchNotifications(10) inspector.DispatchNotifications(10) self.assertEqual(2, response_count[0]) fake_socket.AddResponse('{"id": 6666666, "result": {}}', 1) inspector.DispatchNotifications(10) self.assertEqual(2, response_count[0])
def GetSystemInfo(self, timeout=10): websocket = inspector_websocket.InspectorWebsocket() try: websocket.Connect(self._browser_target_ws, timeout) # Add extra request to debug the crash # (crbug.com/917211). # TODO: remove this once the bug is addressed. if os.name == 'nt': debug_request = { 'method': 'Target.setDiscoverTargets', 'params': { 'discover': True, } } websocket.SyncRequest(debug_request, timeout) req = {'method': 'SystemInfo.getInfo'} res = websocket.SyncRequest(req, timeout) finally: websocket.Disconnect() if 'error' in res: return None return system_info.SystemInfo.FromDict( camel_case.ToUnderscore(res['result']))
def __init__(self, app, devtools_client, context, timeout=120): self._websocket = inspector_websocket.InspectorWebsocket() self._websocket.RegisterDomain( 'Inspector', self._HandleInspectorDomainNotification) self._app = app self._devtools_client = devtools_client # Be careful when using the context object, since the data may be # outdated since this is never updated once InspectorBackend is # created. Consider an updating strategy for this. (For an example # of the subtlety, see the logic for self.url property.) self._context = context logging.debug('InspectorBackend._Connect() to %s', self.debugger_url) try: self._websocket.Connect(self.debugger_url, timeout) self._console = inspector_console.InspectorConsole(self._websocket) self._memory = inspector_memory.InspectorMemory(self._websocket) self._page = inspector_page.InspectorPage( self._websocket, timeout=timeout) self._runtime = inspector_runtime.InspectorRuntime(self._websocket) self._serviceworker = inspector_serviceworker.InspectorServiceWorker( self._websocket, timeout=timeout) self._storage = inspector_storage.InspectorStorage(self._websocket) except (websocket.WebSocketException, exceptions.TimeoutException, py_utils.TimeoutException) as e: self._ConvertExceptionFromInspectorWebsocket(e)
def _CreateAndConnectBrowserInspectorWebsocketIfNeeded(self): if not self._browser_inspector_websocket: self._browser_inspector_websocket = ( inspector_websocket.InspectorWebsocket()) # This may be the first call against the target browser, which # may take a long time to start in Debug builds. Use a larger timeout. self._browser_inspector_websocket.Connect( self._devtools_config.browser_target_url, timeout=_FIRST_CALL_TIMEOUT)
def __init__(self, devtools_port, app_backend, browser_target): """Create an object with the details needed to identify a DevTools agent. TODO(crbug.com/946996): This object also now establishes some of the initial connections to the DevTools agent, but is still called a "Config" due to historical reasons. The distinction between _DevToolsClientConfig and _DevToolsClientBackend is, in fact, no longer useful and both classes should be merged into one. Args: app_backend: The app that contains the DevTools agent. devtools_port: The devtools_port uniquely identifies the DevTools agent. browser_target: An optional string to override the default path used to establish a websocket connection with the browser inspector. """ self._app_backend = app_backend self._browser_target = browser_target or '/devtools/browser' self._forwarder = None self._devtools_http = None self._browser_websocket = None self._created = False self._local_port = None self._remote_port = None try: platform_backend = self.app_backend.platform_backend self._forwarder = platform_backend.forwarder_factory.Create( local_port=None, # Forwarder will choose an available port. remote_port=devtools_port, reverse=True) self._local_port = self._forwarder._local_port self._remote_port = self._forwarder._remote_port # Ensure that the agent is alive and ready. This will raise a # devtools_http.DevToolsClientConnectionError if not ready. self._devtools_http = devtools_http.DevToolsHttp(self.local_port) self._CheckHttpReady() if self.supports_tracing: # Ensure that the inspector websocket is ready. This may raise a # inspector_websocket.WebSocketException or socket.error if not ready. self._browser_websocket = inspector_websocket.InspectorWebsocket( ) self._browser_websocket.Connect(self.browser_target_url, timeout=10) except _DEVTOOLS_CONNECTION_ERRORS as exc: logging.info('DevTools agent at %s not ready yet: %s', self, exc) self.Close() except Exception: # pylint: disable=broad-except logging.exception('Unexpected error checkig if %s is ready', self) self.Close() except: # A more basic exception was raised, e.g. KeyboardInterrupt, should still # close but also re-raise the exception. self.Close() raise
def __init__(self, devtools_port): self._inspector_websocket = inspector_websocket.InspectorWebsocket() self._inspector_websocket.RegisterDomain( 'Tracing', self._NotificationHandler) self._inspector_websocket.Connect( 'ws://127.0.0.1:%i/devtools/browser' % devtools_port) self._trace_events = [] self._is_tracing_running = False self._has_received_all_tracing_data = False
def testSocketErrorOtherThanEAGAIN(self): inspector = inspector_websocket.InspectorWebsocket() fake_socket = FakeSocket(self._mock_timer) # pylint: disable=protected-access inspector._socket = fake_socket error = socket.error(errno.EPIPE, "error string") fake_socket.AddResponse(error, 4) self.assertRaises(socket.error, inspector._Receive)
def GetSystemInfo(self, timeout=10): req = {'method': 'SystemInfo.getInfo'} websocket = inspector_websocket.InspectorWebsocket() try: websocket.Connect(self._browser_target_ws, timeout) res = websocket.SyncRequest(req, timeout) finally: websocket.Disconnect() if 'error' in res: return None return system_info.SystemInfo.FromDict( camel_case.ToUnderscore(res['result']))
def testEAGAIN(self): inspector = inspector_websocket.InspectorWebsocket() fake_socket = FakeSocket(self._fake_timer) # pylint: disable=protected-access inspector._socket = fake_socket error = socket.error(errno.EAGAIN, "error string") fake_socket.AddResponse(error, 4) fake_socket.AddResponse('{"asdf": "qwer"}', 5) result = inspector._Receive(10) self.assertEqual(result, {"asdf" : "qwer"})
def _Connect(self): assert not self._ws assert not self._target_descriptor for target_descriptor in json.loads(self._HttpRequest('/list')): if target_descriptor['type'] == 'page': self._target_descriptor = target_descriptor break if self._target_descriptor['url'] != 'about:blank': raise DevToolsConnectionException( 'Looks like devtools connection was made to a different instance.' ) self._ws = inspector_websocket.InspectorWebsocket() self._ws.Connect(self._target_descriptor['webSocketDebuggerUrl'], timeout=_WEBSOCKET_TIMEOUT_SECONDS)
def _IsInspectorWebsocketReady(self): ws = inspector_websocket.InspectorWebsocket() try: ws.Connect(self.browser_target_url, timeout=10) except (websocket.WebSocketException, socket.error) as exc: logging.info('Websocket at %s not yet ready: %s', self, exc) return False except Exception as exc: # pylint: disable=broad-except logging.exception('Unexpected error checking if %s is ready.', self) return False else: return True finally: ws.Disconnect()
def testDispatchNotification(self): inspector = inspector_websocket.InspectorWebsocket() fake_socket = FakeSocket(self._fake_timer) # pylint: disable=protected-access inspector._socket = fake_socket results = [] def OnTestEvent(result): results.append(result) inspector.RegisterDomain('Test', OnTestEvent) fake_socket.AddResponse('{"method": "Test.foo"}', 5) inspector.DispatchNotifications(10) self.assertEqual(1, len(results)) self.assertEqual('Test.foo', results[0]['method'])
def _LogPageLoadInternal(self, url, clear_cache): """Returns the collection of requests made to load a given URL. Assumes that DevTools is available on http://localhost:DEVTOOLS_PORT. Args: url: URL to load. clear_cache: Whether to clear the HTTP cache. Returns: [inspector_network.InspectorNetworkResponseData, ...] """ self._main_frame_id = None self._please_stop = False r = httplib.HTTPConnection(device_setup.DEVTOOLS_HOSTNAME, device_setup.DEVTOOLS_PORT) r.request('GET', '/json') response = r.getresponse() if response.status != 200: logging.error('Cannot connect to the remote target.') return None json_response = json.loads(response.read()) r.close() websocket_url = json_response[0]['webSocketDebuggerUrl'] ws = inspector_websocket.InspectorWebsocket() ws.Connect(websocket_url) inspector = inspector_network.InspectorNetwork(ws) if clear_cache: inspector.ClearCache() ws.SyncRequest({'method': 'Page.enable'}) ws.RegisterDomain('Page', self._PageDataReceived) inspector.StartMonitoringNetwork() ws.SendAndIgnoreResponse({ 'method': 'Page.navigate', 'params': { 'url': url } }) while not self._please_stop: try: ws.DispatchNotifications() except websocket.WebSocketTimeoutException as e: logging.warning('Exception: ' + str(e)) break if not self._please_stop: logging.warning('Finished with timeout instead of page load') inspector.StopMonitoringNetwork() return inspector.GetResponseData()
def testDispatchNotificationTimedOut(self): inspector = inspector_websocket.InspectorWebsocket() fake_socket = FakeSocket(self._fake_timer) # pylint: disable=protected-access inspector._socket = fake_socket results = [] def OnTestEvent(result): results.append(result) inspector.RegisterDomain('Test', OnTestEvent) fake_socket.AddResponse('{"method": "Test.foo"}', 11) with self.assertRaises( websocket.WebSocketTimeoutException): inspector.DispatchNotifications(timeout=10) self.assertEqual(0, len(results))
def IsDevToolsAgentAvailable(port, app_backend): """Returns True if a DevTools agent is available on the given port.""" if (isinstance(app_backend, browser_backend.BrowserBackend) and app_backend.supports_tracing): inspector_websocket_instance = inspector_websocket.InspectorWebsocket() try: if not _IsInspectorWebsocketAvailable(inspector_websocket_instance, port): return False finally: inspector_websocket_instance.Disconnect() devtools_http_instance = devtools_http.DevToolsHttp(port) try: return _IsDevToolsAgentAvailable(devtools_http_instance) finally: devtools_http_instance.Disconnect()
def GetSystemInfo(self, timeout=10): req = {'method': 'SystemInfo.getInfo'} websocket = inspector_websocket.InspectorWebsocket() try: if self._page: websocket.Connect('ws://127.0.0.1:%i/devtools/page/%i' % (self._port, self._page)) else: websocket.Connect('ws://127.0.0.1:%i/devtools/browser' % self._port) res = websocket.SyncRequest(req, timeout) finally: websocket.Disconnect() if 'error' in res: return None return system_info.SystemInfo.FromDict( camel_case.ToUnderscore(res['result']))
def _Connect(self, devtools_port, browser_target): """Attempt to connect to the DevTools client. Args: devtools_port: The devtools_port uniquely identifies the DevTools agent. browser_target: An optional string to override the default path used to establish a websocket connection with the browser inspector. Raises: Any of _DEVTOOLS_CONNECTION_ERRORS if failed to establish the connection. """ self._browser_target = browser_target or '/devtools/browser' self._forwarder = self.platform_backend.forwarder_factory.Create( local_port=None, # Forwarder will choose an available port. remote_port=devtools_port, reverse=True) self._local_port = self._forwarder._local_port self._remote_port = self._forwarder._remote_port self._devtools_http = devtools_http.DevToolsHttp(self.local_port) # If the agent is not alive and ready, trying to get the branch number will # raise a devtools_http.DevToolsClientConnectionError. branch_number = self.GetChromeBranchNumber() if branch_number < MIN_SUPPORTED_BRANCH_NUMBER: raise UnsupportedVersionError( 'Chrome branch number %d is no longer supported' % branch_number) # Ensure that the inspector websocket is ready. This may raise a # inspector_websocket.WebSocketException or socket.error if not ready. self._browser_websocket = inspector_websocket.InspectorWebsocket() self._browser_websocket.Connect(self.browser_target_url, timeout=10) chrome_tracing_devtools_manager.RegisterDevToolsClient(self) # If there is a trace_config it means that Telemetry has already started # Chrome tracing via a startup config. The TracingBackend also needs needs # this config to initialize itself correctly. trace_config = (self.platform_backend.tracing_controller_backend. GetChromeTraceConfig()) self._tracing_backend = tracing_backend.TracingBackend( self._browser_websocket, trace_config)
def _LogTracingInternal(self, url): self._main_frame_id = None self._please_stop = False r = httplib.HTTPConnection('localhost', device_setup.DEVTOOLS_PORT) r.request('GET', '/json') response = r.getresponse() if response.status != 200: logging.error('Cannot connect to the remote target.') return None json_response = json.loads(response.read()) r.close() websocket_url = json_response[0]['webSocketDebuggerUrl'] ws = inspector_websocket.InspectorWebsocket() ws.Connect(websocket_url) ws.RegisterDomain('Tracing', self._TracingDataReceived) logging.warning( 'Tracing.start: ' + str(ws.SyncRequest({ 'method': 'Tracing.start', 'options': 'zork' }))) ws.SendAndIgnoreResponse({ 'method': 'Page.navigate', 'params': { 'url': url } }) while not self._please_stop: try: ws.DispatchNotifications() except websocket.WebSocketTimeoutException: break if not self._please_stop: logging.warning('Finished with timeout instead of page load') return { 'events': self._tracing_data, 'end': ws.SyncRequest({'method': 'Tracing.end'}) }
def _Connect(self, devtools_port, browser_target): """Attempt to connect to the DevTools client. Args: devtools_port: The devtools_port uniquely identifies the DevTools agent. browser_target: An optional string to override the default path used to establish a websocket connection with the browser inspector. Raises: Any of _DEVTOOLS_CONNECTION_ERRORS if failed to establish the connection. """ self._browser_target = browser_target or '/devtools/browser' self._forwarder = self.platform_backend.forwarder_factory.Create( local_port=None, # Forwarder will choose an available port. remote_port=devtools_port, reverse=True) self._local_port = self._forwarder._local_port self._remote_port = self._forwarder._remote_port self._devtools_http = devtools_http.DevToolsHttp(self.local_port) # If the agent is not alive and ready, this will raise a # devtools_http.DevToolsClientConnectionError. self.GetVersion() # Ensure that the inspector websocket is ready. This may raise a # inspector_websocket.WebSocketException or socket.error if not ready. self._browser_websocket = inspector_websocket.InspectorWebsocket() self._browser_websocket.Connect(self.browser_target_url, timeout=10) chrome_tracing_devtools_manager.RegisterDevToolsClient(self) # Telemetry has started Chrome tracing if there is a trace config, we use # this info to create the TracingBackend in the correct state. is_tracing_running = bool( self.platform_backend.tracing_controller_backend.GetChromeTraceConfig()) self._tracing_backend = tracing_backend.TracingBackend( self._browser_websocket, is_tracing_running)
def _CreateAndConnectBrowserInspectorWebsocketIfNeeded(self): if not self._browser_inspector_websocket: self._browser_inspector_websocket = ( inspector_websocket.InspectorWebsocket()) self._browser_inspector_websocket.Connect( self._BrowserTargetWebSocket(), timeout=10)
def testUnregisterDomainWithUnregisteredDomain(self): inspector = inspector_websocket.InspectorWebsocket() with self.assertRaises(AssertionError): inspector.UnregisterDomain('Test')
def _Connect(cls, hostname, port): websocket_url = cls._GetWebSocketUrl(hostname, port) ws = inspector_websocket.InspectorWebsocket() ws.Connect(websocket_url) return ws
def _CreateAndConnectBrowserInspectorWebsocketIfNeeded(self): if not self._browser_inspector_websocket: self._browser_inspector_websocket = ( inspector_websocket.InspectorWebsocket()) self._browser_inspector_websocket.Connect( self._devtools_config.browser_target_url, timeout=10)