Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(201)

Unified Diff: tools/telemetry/telemetry/internal/backends/chrome_inspector/devtools_client_backend.py

Issue 1647513002: Delete tools/telemetry. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: tools/telemetry/telemetry/internal/backends/chrome_inspector/devtools_client_backend.py
diff --git a/tools/telemetry/telemetry/internal/backends/chrome_inspector/devtools_client_backend.py b/tools/telemetry/telemetry/internal/backends/chrome_inspector/devtools_client_backend.py
deleted file mode 100644
index 123629ec359410a4f73061838cca5d6bca3e6eea..0000000000000000000000000000000000000000
--- a/tools/telemetry/telemetry/internal/backends/chrome_inspector/devtools_client_backend.py
+++ /dev/null
@@ -1,475 +0,0 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import logging
-import re
-import socket
-import sys
-
-from telemetry.core import exceptions
-from telemetry import decorators
-from telemetry.internal.backends import browser_backend
-from telemetry.internal.backends.chrome_inspector import devtools_http
-from telemetry.internal.backends.chrome_inspector import inspector_backend
-from telemetry.internal.backends.chrome_inspector import inspector_websocket
-from telemetry.internal.backends.chrome_inspector import memory_backend
-from telemetry.internal.backends.chrome_inspector import tracing_backend
-from telemetry.internal.backends.chrome_inspector import websocket
-from telemetry.internal.platform.tracing_agent import chrome_tracing_agent
-from telemetry.internal.platform.tracing_agent import (
- chrome_tracing_devtools_manager)
-from telemetry.timeline import trace_data as trace_data_module
-
-
-BROWSER_INSPECTOR_WEBSOCKET_URL = 'ws://127.0.0.1:%i/devtools/browser'
-
-
-class TabNotFoundError(exceptions.Error):
- pass
-
-
-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 _IsInspectorWebsocketAvailable(inspector_websocket_instance, port):
- try:
- inspector_websocket_instance.Connect(BROWSER_INSPECTOR_WEBSOCKET_URL % port)
- except websocket.WebSocketException:
- return False
- except socket.error:
- return False
- except Exception as e:
- sys.stderr.write('Unidentified exception while checking if wesocket is'
- 'available on port %i. Exception message: %s\n' %
- (port, e.message))
- return False
- else:
- return True
-
-
-# TODO(nednguyen): Find a more reliable way to check whether the devtool agent
-# is still alive.
-def _IsDevToolsAgentAvailable(devtools_http_instance):
- try:
- devtools_http_instance.Request('')
- except devtools_http.DevToolsClientConnectionError:
- return False
- else:
- return True
-
-
-class DevToolsClientBackend(object):
- """An object that communicates with Chrome's devtools.
-
- This class owns a map of InspectorBackends. It is responsible for creating
- them and destroying them.
- """
- def __init__(self, devtools_port, remote_devtools_port, app_backend):
- """Creates a new DevToolsClientBackend.
-
- A DevTools agent must exist on the given devtools_port.
-
- Args:
- devtools_port: The port to use to connect to DevTools agent.
- remote_devtools_port: In some cases (e.g., app running on
- Android device, devtools_port is the forwarded port on the
- host platform. We also need to know the remote_devtools_port
- so that we can uniquely identify the DevTools agent.
- app_backend: For the app that contains the DevTools agent.
- """
- self._devtools_port = devtools_port
- self._remote_devtools_port = remote_devtools_port
- self._devtools_http = devtools_http.DevToolsHttp(devtools_port)
- self._browser_inspector_websocket = None
- self._tracing_backend = None
- self._memory_backend = None
- self._app_backend = app_backend
- self._devtools_context_map_backend = _DevToolsContextMapBackend(
- self._app_backend, self)
-
- if not self.supports_tracing:
- return
- chrome_tracing_devtools_manager.RegisterDevToolsClient(
- self, self._app_backend.platform_backend)
-
- # Telemetry has started Chrome tracing if there is trace config, so start
- # tracing on this newly created devtools client if needed.
- trace_config = (self._app_backend.platform_backend
- .tracing_controller_backend.GetChromeTraceConfig())
- if not trace_config:
- self._CreateTracingBackendIfNeeded(is_tracing_running=False)
- return
-
- if self.support_startup_tracing:
- self._CreateTracingBackendIfNeeded(is_tracing_running=True)
- return
-
- self._CreateTracingBackendIfNeeded(is_tracing_running=False)
- self.StartChromeTracing(
- trace_config=trace_config,
- custom_categories=trace_config.tracing_category_filter.filter_string)
-
- @property
- def remote_port(self):
- return self._remote_devtools_port
-
- @property
- def supports_tracing(self):
- if not isinstance(self._app_backend, browser_backend.BrowserBackend):
- return False
- return self._app_backend.supports_tracing
-
- @property
- def supports_overriding_memory_pressure_notifications(self):
- if not isinstance(self._app_backend, browser_backend.BrowserBackend):
- return False
- return self._app_backend.supports_overriding_memory_pressure_notifications
-
-
- @property
- def is_tracing_running(self):
- if not self.supports_tracing:
- return False
- if not self._tracing_backend:
- return False
- return self._tracing_backend.is_tracing_running
-
- @property
- def support_startup_tracing(self):
- # Startup tracing with --trace-config-file flag was not supported until
- # Chromium branch number 2512 (see crrev.com/1309243004 and
- # crrev.com/1353583002).
- if not chrome_tracing_agent.ChromeTracingAgent.IsStartupTracingSupported(
- self._app_backend.platform_backend):
- return False
- # TODO(zhenw): Remove this once stable Chrome and reference browser have
- # passed 2512.
- return self.GetChromeBranchNumber() >= 2512
-
- def IsAlive(self):
- """Whether the DevTools server is available and connectable."""
- return (self._devtools_http and
- _IsDevToolsAgentAvailable(self._devtools_http))
-
- def Close(self):
- if self._tracing_backend:
- self._tracing_backend.Close()
- self._tracing_backend = None
- if self._memory_backend:
- self._memory_backend.Close()
- self._memory_backend = None
-
- if self._devtools_context_map_backend:
- self._devtools_context_map_backend.Clear()
-
- # Close the browser inspector socket last (in case the backend needs to
- # interact with it before closing).
- if self._browser_inspector_websocket:
- self._browser_inspector_websocket.Disconnect()
- self._browser_inspector_websocket = None
-
- assert self._devtools_http
- self._devtools_http.Disconnect()
- self._devtools_http = None
-
-
- @decorators.Cache
- def GetChromeBranchNumber(self):
- # Detect version information.
- resp = self._devtools_http.RequestJson('version')
- if 'Protocol-Version' in resp:
- if 'Browser' in resp:
- branch_number_match = re.search(r'Chrome/\d+\.\d+\.(\d+)\.\d+',
- resp['Browser'])
- else:
- branch_number_match = re.search(
- r'Chrome/\d+\.\d+\.(\d+)\.\d+ (Mobile )?Safari',
- resp['User-Agent'])
-
- if branch_number_match:
- branch_number = int(branch_number_match.group(1))
- if branch_number:
- return branch_number
-
- # Branch number can't be determined, so fail any branch number checks.
- return 0
-
- def _ListInspectableContexts(self):
- return self._devtools_http.RequestJson('')
-
- def RequestNewTab(self, timeout):
- """Creates a new tab.
-
- Returns:
- A JSON string as returned by DevTools. Example:
- {
- "description": "",
- "devtoolsFrontendUrl":
- "/devtools/inspector.html?ws=host:port/devtools/page/id-string",
- "id": "id-string",
- "title": "Page Title",
- "type": "page",
- "url": "url",
- "webSocketDebuggerUrl": "ws://host:port/devtools/page/id-string"
- }
-
- Raises:
- devtools_http.DevToolsClientConnectionError
- """
- return self._devtools_http.Request('new', timeout=timeout)
-
- def CloseTab(self, tab_id, timeout):
- """Closes the tab with the given id.
-
- Raises:
- devtools_http.DevToolsClientConnectionError
- TabNotFoundError
- """
- try:
- return self._devtools_http.Request('close/%s' % tab_id,
- timeout=timeout)
- except devtools_http.DevToolsClientUrlError:
- error = TabNotFoundError(
- 'Unable to close tab, tab id not found: %s' % tab_id)
- raise error, None, sys.exc_info()[2]
-
- def ActivateTab(self, tab_id, timeout):
- """Activates the tab with the given id.
-
- Raises:
- devtools_http.DevToolsClientConnectionError
- TabNotFoundError
- """
- try:
- return self._devtools_http.Request('activate/%s' % tab_id,
- timeout=timeout)
- except devtools_http.DevToolsClientUrlError:
- error = TabNotFoundError(
- 'Unable to activate tab, tab id not found: %s' % tab_id)
- raise error, None, sys.exc_info()[2]
-
- def GetUrl(self, tab_id):
- """Returns the URL of the tab with |tab_id|, as reported by devtools.
-
- Raises:
- devtools_http.DevToolsClientConnectionError
- """
- for c in self._ListInspectableContexts():
- if c['id'] == tab_id:
- return c['url']
- return None
-
- def IsInspectable(self, tab_id):
- """Whether the tab with |tab_id| is inspectable, as reported by devtools.
-
- Raises:
- devtools_http.DevToolsClientConnectionError
- """
- contexts = self._ListInspectableContexts()
- return tab_id in [c['id'] for c in contexts]
-
- def GetUpdatedInspectableContexts(self):
- """Returns an updated instance of _DevToolsContextMapBackend."""
- contexts = self._ListInspectableContexts()
- self._devtools_context_map_backend._Update(contexts)
- return self._devtools_context_map_backend
-
- def _CreateTracingBackendIfNeeded(self, is_tracing_running=False):
- assert self.supports_tracing
- if not self._tracing_backend:
- self._CreateAndConnectBrowserInspectorWebsocketIfNeeded()
- self._tracing_backend = tracing_backend.TracingBackend(
- self._browser_inspector_websocket, is_tracing_running)
-
- def _CreateMemoryBackendIfNeeded(self):
- assert self.supports_overriding_memory_pressure_notifications
- if not self._memory_backend:
- self._CreateAndConnectBrowserInspectorWebsocketIfNeeded()
- self._memory_backend = memory_backend.MemoryBackend(
- self._browser_inspector_websocket)
-
- 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)
-
- def IsChromeTracingSupported(self):
- if not self.supports_tracing:
- return False
- self._CreateTracingBackendIfNeeded()
- return self._tracing_backend.IsTracingSupported()
-
- def StartChromeTracing(
- self, trace_config, custom_categories=None, timeout=10):
- """
- Args:
- trace_config: An tracing_config.TracingConfig instance.
- custom_categories: An optional string containing a list of
- comma separated categories that will be traced
- instead of the default category set. Example: use
- "webkit,cc,disabled-by-default-cc.debug" to trace only
- those three event categories.
- """
- assert trace_config and trace_config.enable_chrome_trace
- self._CreateTracingBackendIfNeeded()
- return self._tracing_backend.StartTracing(
- trace_config, custom_categories, timeout)
-
- def StopChromeTracing(self, trace_data_builder, timeout=30):
- assert self.is_tracing_running
- try:
- context_map = self.GetUpdatedInspectableContexts()
- for context in context_map.contexts:
- if context['type'] not in ['iframe', 'page', 'webview']:
- continue
- context_id = context['id']
- backend = context_map.GetInspectorBackend(context_id)
- success = backend.EvaluateJavaScript(
- "console.time('" + backend.id + "');" +
- "console.timeEnd('" + backend.id + "');" +
- "console.time.toString().indexOf('[native code]') != -1;")
- if not success:
- raise Exception('Page stomped on console.time')
- trace_data_builder.AddEventsTo(
- trace_data_module.TAB_ID_PART, [backend.id])
- finally:
- self._tracing_backend.StopTracing(trace_data_builder, timeout)
-
- def DumpMemory(self, timeout=30):
- """Dumps memory.
-
- Returns:
- GUID of the generated dump if successful, None otherwise.
-
- Raises:
- TracingTimeoutException: If more than |timeout| seconds has passed
- since the last time any data is received.
- TracingUnrecoverableException: If there is a websocket error.
- TracingUnexpectedResponseException: If the response contains an error
- or does not contain the expected result.
- """
- self._CreateTracingBackendIfNeeded()
- return self._tracing_backend.DumpMemory(timeout)
-
- def SetMemoryPressureNotificationsSuppressed(self, suppressed, timeout=30):
- """Enable/disable suppressing memory pressure notifications.
-
- Args:
- suppressed: If true, memory pressure notifications will be suppressed.
- timeout: The timeout in seconds.
-
- Raises:
- MemoryTimeoutException: If more than |timeout| seconds has passed
- since the last time any data is received.
- MemoryUnrecoverableException: If there is a websocket error.
- MemoryUnexpectedResponseException: If the response contains an error
- or does not contain the expected result.
- """
- self._CreateMemoryBackendIfNeeded()
- return self._memory_backend.SetMemoryPressureNotificationsSuppressed(
- suppressed, timeout)
-
- def SimulateMemoryPressureNotification(self, pressure_level, timeout=30):
- """Simulate a memory pressure notification.
-
- Args:
- pressure level: The memory pressure level of the notification ('moderate'
- or 'critical').
- timeout: The timeout in seconds.
-
- Raises:
- MemoryTimeoutException: If more than |timeout| seconds has passed
- since the last time any data is received.
- MemoryUnrecoverableException: If there is a websocket error.
- MemoryUnexpectedResponseException: If the response contains an error
- or does not contain the expected result.
- """
- self._CreateMemoryBackendIfNeeded()
- return self._memory_backend.SimulateMemoryPressureNotification(
- pressure_level, timeout)
-
-
-class _DevToolsContextMapBackend(object):
- def __init__(self, app_backend, devtools_client):
- self._app_backend = app_backend
- self._devtools_client = devtools_client
- self._contexts = None
- self._inspector_backends_dict = {}
-
- @property
- def contexts(self):
- """The most up to date contexts data.
-
- Returned in the order returned by devtools agent."""
- return self._contexts
-
- def GetContextInfo(self, context_id):
- for context in self._contexts:
- if context['id'] == context_id:
- return context
- raise KeyError('Cannot find a context with id=%s' % context_id)
-
- def GetInspectorBackend(self, context_id):
- """Gets an InspectorBackend instance for the given context_id.
-
- This lazily creates InspectorBackend for the context_id if it does
- not exist yet. Otherwise, it will return the cached instance."""
- if context_id in self._inspector_backends_dict:
- return self._inspector_backends_dict[context_id]
-
- for context in self._contexts:
- if context['id'] == context_id:
- new_backend = inspector_backend.InspectorBackend(
- self._app_backend.app, self._devtools_client, context)
- self._inspector_backends_dict[context_id] = new_backend
- return new_backend
-
- raise KeyError('Cannot find a context with id=%s' % context_id)
-
- def _Update(self, contexts):
- # Remove InspectorBackend that is not in the current inspectable
- # contexts list.
- context_ids = [context['id'] for context in contexts]
- for context_id in self._inspector_backends_dict.keys():
- if context_id not in context_ids:
- backend = self._inspector_backends_dict[context_id]
- backend.Disconnect()
- del self._inspector_backends_dict[context_id]
-
- valid_contexts = []
- for context in contexts:
- # If the context does not have webSocketDebuggerUrl, skip it.
- # If an InspectorBackend is already created for the tab,
- # webSocketDebuggerUrl will be missing, and this is expected.
- context_id = context['id']
- if context_id not in self._inspector_backends_dict:
- if 'webSocketDebuggerUrl' not in context:
- logging.debug('webSocketDebuggerUrl missing, removing %s'
- % context_id)
- continue
- valid_contexts.append(context)
- self._contexts = valid_contexts
-
- def Clear(self):
- for backend in self._inspector_backends_dict.values():
- backend.Disconnect()
- self._inspector_backends_dict = {}
- self._contexts = None

Powered by Google App Engine
This is Rietveld 408576698