Chromium Code Reviews| Index: tools/telemetry/telemetry/browser_backend.py |
| =================================================================== |
| --- tools/telemetry/telemetry/browser_backend.py (revision 176402) |
| +++ tools/telemetry/telemetry/browser_backend.py (working copy) |
| @@ -11,6 +11,7 @@ |
| 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 @@ |
| browser_gone_exception.BrowserGoneException): |
| pass |
| - |
| -class TabController(object): |
| +class ContextControler(object): |
|
nduca
2013/01/15 05:31:06
I think we should leave TabController alone and cr
|
| 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._context_dict = weakref.WeakValueDictionary() |
| + self._UpdateContextList() |
| - self._UpdateTabList() |
| - |
| - def New(self, timeout=None): |
| - self._browser_backend.Request('new', timeout=timeout) |
| - return self[-1] |
| - |
| 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 @@ |
| 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): |
|
nduca
2013/01/15 05:31:06
I'd like to avoid this.
|
| + for tab_info in self._ListContexts(): |
| + if tab_info['url'] == url: |
| + return self._GetContextObjectForDebugger( |
| + tab_info.get('webSocketDebuggerUrl')) |
| + return None |
|
nduca
2013/01/15 05:31:06
Should ExtensionToLoad() should have an id? The us
|
| + |
| + 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] |
| + 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 _FindTabInfo(self, debugger_url): |
| - for tab_info in self._ListTabs(): |
| + 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 @@ |
| 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 @@ |
| def SetBrowser(self, browser): |
| self.tabs = TabController(browser, self) |
| + if not self.is_content_shell: |
| + self.extensions = ExtensionController(browser, self) |
| def GetBrowserStartupArgs(self): |
| args = [] |