예제 #1
0
 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)
예제 #2
0
  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])
예제 #3
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']))
예제 #4
0
  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)
예제 #5
0
 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)
예제 #6
0
    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
예제 #7
0
  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']))
예제 #10
0
  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"})
예제 #11
0
 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)
예제 #12
0
 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()
예제 #13
0
  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()
예제 #15
0
  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))
예제 #16
0
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']))
예제 #18
0
    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'})
     }
예제 #20
0
  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)
예제 #21
0
 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)
예제 #22
0
 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
예제 #24
0
 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)