| Index: tools/telemetry/telemetry/browser_backend.py
|
| diff --git a/tools/telemetry/telemetry/browser_backend.py b/tools/telemetry/telemetry/browser_backend.py
|
| index 57c4f93dd6716119a960447b6c9f23a4c2b1d47d..01257f5497dda8806df877b3120d3993092e222f 100644
|
| --- a/tools/telemetry/telemetry/browser_backend.py
|
| +++ b/tools/telemetry/telemetry/browser_backend.py
|
| @@ -11,6 +11,7 @@ import sys
|
| import weakref
|
|
|
| from telemetry import browser_gone_exception
|
| +from telemetry import extension_page
|
| from telemetry import tab
|
| from telemetry import tracing_backend
|
| from telemetry import user_agent
|
| @@ -23,26 +24,19 @@ class BrowserConnectionGoneException(
|
| browser_gone_exception.BrowserGoneException):
|
| pass
|
|
|
| -
|
| -class TabController(object):
|
| +class ContextControler(object):
|
| def __init__(self, browser, browser_backend):
|
| self._browser = browser
|
| self._browser_backend = browser_backend
|
| -
|
| # Stores web socket debugger URLs in iteration order.
|
| - self._tab_list = []
|
| + self._context_list = []
|
| # Maps debugger URLs to Tab objects.
|
| - self._tab_dict = weakref.WeakValueDictionary()
|
| -
|
| - self._UpdateTabList()
|
| -
|
| - def New(self, timeout=None):
|
| - self._browser_backend.Request('new', timeout=timeout)
|
| - return self[-1]
|
| + self._context_dict = weakref.WeakValueDictionary()
|
| + self._UpdateContextList()
|
|
|
| def DoesDebuggerUrlExist(self, url):
|
| - self._UpdateTabList()
|
| - return url in self._tab_list
|
| + self._UpdateContextList()
|
| + return url in self._context_list
|
|
|
| def CloseTab(self, debugger_url, timeout=None):
|
| # TODO(dtu): crbug.com/160946, allow closing the last tab on some platforms.
|
| @@ -81,52 +75,118 @@ class TabController(object):
|
| return tab_info['url']
|
|
|
| def __iter__(self):
|
| - self._UpdateTabList()
|
| - return self._tab_list.__iter__()
|
| + self._UpdateContextList()
|
| + return self._context_list.__iter__()
|
|
|
| def __len__(self):
|
| - self._UpdateTabList()
|
| - return len(self._tab_list)
|
| + self._UpdateContextList()
|
| + return len(self._context_list)
|
|
|
| def __getitem__(self, index):
|
| - self._UpdateTabList()
|
| + self._UpdateContextList()
|
| # This dereference will propagate IndexErrors.
|
| - debugger_url = self._tab_list[index]
|
| + debugger_url = self._context_list[index]
|
| + return self._GetContextObjectForDebugger(debugger_url)
|
| +
|
| + def FindByUrl(self, url):
|
| + for tab_info in self._ListContexts():
|
| + if tab_info['url'] == url:
|
| + return self._GetContextObjectForDebugger(
|
| + tab_info.get('webSocketDebuggerUrl'))
|
| + return None
|
| +
|
| + def GetAllForUrl(self, url):
|
| + return [self._GetContextObjectForDebugger(
|
| + tab_info.get('webSocketDebuggerUrl'))
|
| + for tab_info in self._ListContexts()
|
| + if tab_info['url'] == url]
|
| +
|
| + def _GetContextObjectForDebugger(self, debugger_url):
|
| # Lazily get/create a Tab object.
|
| - tab_object = self._tab_dict.get(debugger_url)
|
| + tab_object = self._context_dict.get(debugger_url)
|
| if not tab_object:
|
| - tab_object = tab.Tab(self._browser, self, debugger_url)
|
| - self._tab_dict[debugger_url] = tab_object
|
| + tab_object = self._CreateContextObject(debugger_url)
|
| + self._context_dict[debugger_url] = tab_object
|
| return tab_object
|
|
|
| - def _ListTabs(self, timeout=None):
|
| + def _ListContexts(self, timeout=None):
|
| try:
|
| data = self._browser_backend.Request('', timeout=timeout)
|
| all_contexts = json.loads(data)
|
| - tabs = [ctx for ctx in all_contexts
|
| - if not ctx['url'].startswith('chrome-extension://')]
|
| - return tabs
|
| + contexts = self._FilterContexts(all_contexts)
|
| + return contexts
|
| except (socket.error, httplib.BadStatusLine, urllib2.URLError):
|
| if not self._browser_backend.IsBrowserRunning():
|
| raise browser_gone_exception.BrowserGoneException()
|
| raise BrowserConnectionGoneException()
|
|
|
| - def _UpdateTabList(self):
|
| + def _UpdateContextList(self):
|
| def GetDebuggerUrl(tab_info):
|
| if 'webSocketDebuggerUrl' not in tab_info:
|
| return None
|
| return tab_info['webSocketDebuggerUrl']
|
| - new_tab_list = map(GetDebuggerUrl, self._ListTabs())
|
| - self._tab_list = [t for t in self._tab_list if t in new_tab_list]
|
| - self._tab_list += [t for t in new_tab_list if t not in self._tab_list]
|
| -
|
| - def _FindTabInfo(self, debugger_url):
|
| - for tab_info in self._ListTabs():
|
| + new_context_list = map(GetDebuggerUrl, self._ListContexts())
|
| + self._context_list = [t for t in self._context_list
|
| + if t in new_context_list]
|
| + self._context_list += [t for t in new_context_list
|
| + if t not in self._context_list]
|
| +
|
| + def _FindContextInfo(self, debugger_url):
|
| + for tab_info in self._ListContexts():
|
| if tab_info.get('webSocketDebuggerUrl') == debugger_url:
|
| return tab_info
|
| return None
|
|
|
|
|
| +class TabController(ContextControler):
|
| + def __init__(self, browser, browser_backend):
|
| + super(TabController, self).__init__(browser, browser_backend)
|
| +
|
| + def _CreateContextObject(self, debugger_url):
|
| + return tab.Tab(self._browser, self, debugger_url)
|
| +
|
| + def _FilterContexts(self, all_contexts):
|
| + return [ctx for ctx in all_contexts
|
| + if not ctx['url'].startswith('chrome-extension://')]
|
| +
|
| + def New(self, timeout=None):
|
| + self._browser_backend.Request('new', timeout=timeout)
|
| + return self[-1]
|
| +
|
| + def CloseTab(self, debugger_url, timeout=None):
|
| + # TODO(dtu): crbug.com/160946, allow closing the last tab on some platforms.
|
| + # For now, just create a new tab before closing the last tab.
|
| + if len(self) <= 1:
|
| + self.New()
|
| +
|
| + tab_id = debugger_url.split('/')[-1]
|
| + try:
|
| + response = self._browser_backend.Request('close/%s' % tab_id,
|
| + timeout=timeout)
|
| + except urllib2.HTTPError:
|
| + raise Exception('Unable to close tab, tab id not found: %s' % tab_id)
|
| + assert response == 'Target is closing'
|
| +
|
| + util.WaitFor(lambda: not self._FindContextInfo(debugger_url), timeout=5)
|
| + self._UpdateContextList()
|
| +
|
| + def GetTabUrl(self, debugger_url):
|
| + tab_info = self._FindContextInfo(debugger_url)
|
| + assert tab_info is not None
|
| + return tab_info['url']
|
| +
|
| +class ExtensionController(ContextControler):
|
| + def __init__(self, browser, browser_backend):
|
| + super(ExtensionController, self).__init__(browser, browser_backend)
|
| +
|
| + def _CreateContextObject(self, debugger_url):
|
| + return extension_page.ExtensionPage(
|
| + tab.Tab(self._browser, self, debugger_url))
|
| +
|
| + def _FilterContexts(self, all_contexts):
|
| + return [ctx for ctx in all_contexts
|
| + if ctx['url'].startswith('chrome-extension://')]
|
| +
|
| class BrowserBackend(object):
|
| """A base class for browser backends. Provides basic functionality
|
| once a remote-debugger port has been established."""
|
| @@ -137,6 +197,7 @@ class BrowserBackend(object):
|
|
|
| def __init__(self, is_content_shell, options):
|
| self.tabs = None
|
| + self.extensions = None
|
| self.browser_type = options.browser_type
|
| self.is_content_shell = is_content_shell
|
| self.options = options
|
| @@ -155,6 +216,8 @@ class BrowserBackend(object):
|
|
|
| def SetBrowser(self, browser):
|
| self.tabs = TabController(browser, self)
|
| + if not self.is_content_shell:
|
| + self.extensions = ExtensionController(browser, self)
|
|
|
| def GetBrowserStartupArgs(self):
|
| args = []
|
|
|