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.
8 from telemetry.core.backends.chrome import inspector_backend
11 def DebuggerUrlToId(debugger_url):
12 return debugger_url.split('/')[-1]
15 class InspectorBackendList(collections.Sequence):
16 """A dynamic sequence of active InspectorBackends."""
18 def __init__(self, browser_backend, backend_wrapper):
22 browser_backend: The BrowserBackend instance to query for
24 backend_wrapper: A public interface for wrapping each
25 InspectorBackend. It must accept an argument of the
26 InspectorBackend to wrap, and an argument of the
27 InspectorBackendList, and may expose whatever methods
28 are desired on top of that backend.
30 self._browser_backend = browser_backend
31 # A ordered mapping of context IDs to inspectable contexts.
32 self._inspectable_contexts_dict = collections.OrderedDict()
33 # A cache of inspector backends, by context ID.
34 self._inspector_backend_dict = {}
35 # A wrapper class for InspectorBackends.
36 self._backend_wrapper = backend_wrapper
38 def GetContextInfo(self, context_id):
39 return self._inspectable_contexts_dict[context_id]
41 def ShouldIncludeContext(self, _context):
42 """Override this method to control which contexts are included."""
45 #TODO(nednguyen): Remove this method and turn inspector_backend_list API to
46 # dictionary-like API (crbug.com/398467)
47 def __getitem__(self, index):
49 if index >= len(self._inspectable_contexts_dict.keys()):
50 logging.error('About to explode: _inspectable_contexts_dict.keys() = %s',
53 "keys": self._inspectable_contexts_dict.keys()
55 context_id = self._inspectable_contexts_dict.keys()[index]
56 return self.GetBackendFromContextId(context_id)
58 def GetBackendFromContextId(self, context_id):
60 if context_id not in self._inspectable_contexts_dict:
61 raise KeyError('Cannot find a context with id=%s' % context_id)
62 if context_id not in self._inspector_backend_dict:
63 backend = inspector_backend.InspectorBackend(
64 self._browser_backend,
65 self._inspectable_contexts_dict[context_id])
66 backend = self._backend_wrapper(backend, self)
67 self._inspector_backend_dict[context_id] = backend
68 return self._inspector_backend_dict[context_id]
72 return self._inspectable_contexts_dict.keys().__iter__()
76 return len(self._inspectable_contexts_dict)
79 contexts = self._browser_backend.ListInspectableContexts()
80 context_ids = [context['id'] for context in contexts]
82 # Append all new inspectable contexts to the dict.
83 for context in contexts:
84 if not self.ShouldIncludeContext(context):
86 if context['id'] in self._inspectable_contexts_dict:
88 self._inspectable_contexts_dict[context['id']] = context
90 # Remove all inspectable contexts that have gone away from the dict.
91 for context_id in self._inspectable_contexts_dict.keys():
92 if context_id not in context_ids:
93 del self._inspectable_contexts_dict[context_id]
95 # Also remove inspectable contexts that have no websocketDebuggerUrls.
96 context = next(context for context in contexts
97 if context['id'] == context_id)
98 if (context_id not in self._inspector_backend_dict.keys() and
99 'webSocketDebuggerUrl' not in context):
100 logging.debug('webSocketDebuggerUrl missing, removing %s'
102 del self._inspectable_contexts_dict[context_id]
104 # Clean up any backends for contexts that have gone away.
105 for context_id in self._inspector_backend_dict.keys():
106 if context_id not in self._inspectable_contexts_dict:
107 del self._inspector_backend_dict[context_id]