blob: 61c75ffc78a30e19f3dd190bc2c060a60d42566e [file] [log] [blame]
# Copyright 2013 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 json
from telemetry.core import exceptions
from telemetry.core import util
from telemetry.internal.backends.chrome_inspector import inspector_backend_list
from telemetry.internal.browser import tab
class TabUnexpectedResponseException(exceptions.DevtoolsTargetCrashException):
pass
class TabListBackend(inspector_backend_list.InspectorBackendList):
"""A dynamic sequence of tab.Tabs in UI order."""
def __init__(self, browser_backend):
super(TabListBackend, self).__init__(browser_backend)
def New(self, timeout):
"""Makes a new tab.
Returns:
A Tab object.
Raises:
devtools_http.DevToolsClientConnectionError
"""
if not self._browser_backend.supports_tab_control:
raise NotImplementedError("Browser doesn't support tab control.")
response = self._browser_backend.devtools_client.RequestNewTab(timeout)
try:
response = json.loads(response)
context_id = response['id']
except (KeyError, ValueError):
raise TabUnexpectedResponseException(
app=self._browser_backend.browser,
msg='Received response: %s' % response)
return self.GetBackendFromContextId(context_id)
def CloseTab(self, tab_id, timeout=300):
"""Closes the tab with the given debugger_url.
Raises:
devtools_http.DevToolsClientConnectionError
devtools_client_backend.TabNotFoundError
TabUnexpectedResponseException
exceptions.TimeoutException
"""
assert self._browser_backend.supports_tab_control
# 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(timeout)
response = self._browser_backend.devtools_client.CloseTab(tab_id, timeout)
if response != 'Target is closing':
raise TabUnexpectedResponseException(
app=self._browser_backend.browser,
msg='Received response: %s' % response)
util.WaitFor(lambda: tab_id not in self.IterContextIds(), timeout=5)
def ActivateTab(self, tab_id, timeout=30):
"""Activates the tab with the given debugger_url.
Raises:
devtools_http.DevToolsClientConnectionError
devtools_client_backend.TabNotFoundError
TabUnexpectedResponseException
"""
assert self._browser_backend.supports_tab_control
response = self._browser_backend.devtools_client.ActivateTab(tab_id,
timeout)
if response != 'Target activated':
raise TabUnexpectedResponseException(
app=self._browser_backend.browser,
msg='Received response: %s' % response)
def Get(self, index, ret):
"""Returns self[index] if it exists, or ret if index is out of bounds."""
if len(self) <= index:
return ret
return self[index]
def ShouldIncludeContext(self, context):
if 'type' in context:
return (context['type'] == 'page' or
context['url'] == 'chrome://media-router/')
# TODO: For compatibility with Chrome before r177683.
# This check is not completely correct, see crbug.com/190592.
return not context['url'].startswith('chrome-extension://')
def CreateWrapper(self, inspector_backend):
return tab.Tab(inspector_backend, self, self._browser_backend.browser)
def _HandleDevToolsConnectionError(self, error):
if not self._browser_backend.IsAppRunning():
error.AddDebuggingMessage('The browser is not running. It probably '
'crashed.')
elif not self._browser_backend.HasBrowserFinishedLaunching():
error.AddDebuggingMessage('The browser exists but cannot be reached.')
else:
error.AddDebuggingMessage('The browser exists and can be reached. '
'The devtools target probably crashed.')