summaryrefslogtreecommitdiffstats
path: root/tools/telemetry
diff options
context:
space:
mode:
authorachuith@chromium.org <achuith@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-02-13 22:08:34 +0000
committerachuith@chromium.org <achuith@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-02-13 22:08:34 +0000
commited1744f6ce3d1d2d57fbf5cb9b10e733b6fc4534 (patch)
tree8768482f9afa1ef74a876e724073da1cbdb51e5d /tools/telemetry
parent069fa64d19fd03b444c009d1f85c6b13c2cb1a4b (diff)
downloadchromium_src-ed1744f6ce3d1d2d57fbf5cb9b10e733b6fc4534.zip
chromium_src-ed1744f6ce3d1d2d57fbf5cb9b10e733b6fc4534.tar.gz
chromium_src-ed1744f6ce3d1d2d57fbf5cb9b10e733b6fc4534.tar.bz2
Telemetry support for extensions.
* Browser has new properties supports_extensions and extensions (of type ExtensionDict) * BrowserBackend ctor takes additional arg supports_extensions. * BrowserBackend has new properties supports_extensions and extension_dict_backend (of type ExtensionDictBackend) * BrowserBackend._WaitForBrowserToComeUp waits for all extensions to load and be interactive. * BrowserBackend.ExtensionsNotSupportedException is raised for android browser and content shell. * Add class ExtensionToLoad which is a wrapper for an extension_path. * Add extension_to_load (of type ExtensionToLoad) to BrowserOptions. * Add SupportsOptions to PossibleBrowser, to test extensions support. Returns False for android and content_shell when BrowserOptions.extensions_to_load is not empty * Add ExtensionPage which derives from WebContents * Add ExtensionDictBackend which is a dictionary of ExtensionPage instances with extension ids as keys. * Add ExtensionDict which passes through to ExtensionDictBackend, except it uses ExtensionToLoad instances as keys. * Import crx_id for determining extension id from extension path. * Simple extension manifest.json and background.js for unit tests. * Unit tests for single and multiple extensions. BUG=169954 TEST=browser test. Review URL: https://codereview.chromium.org/11882033 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@182316 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'tools/telemetry')
-rw-r--r--tools/telemetry/telemetry/android_browser_backend.py11
-rw-r--r--tools/telemetry/telemetry/android_browser_finder.py8
-rw-r--r--tools/telemetry/telemetry/browser.py25
-rw-r--r--tools/telemetry/telemetry/browser_backend.py37
-rw-r--r--tools/telemetry/telemetry/browser_finder.py2
-rw-r--r--tools/telemetry/telemetry/browser_options.py1
-rw-r--r--tools/telemetry/telemetry/cros_browser_backend.py6
-rw-r--r--tools/telemetry/telemetry/cros_browser_finder.py10
-rw-r--r--tools/telemetry/telemetry/crx_id.py16
-rw-r--r--tools/telemetry/telemetry/desktop_browser_backend.py8
-rw-r--r--tools/telemetry/telemetry/desktop_browser_finder.py8
-rw-r--r--tools/telemetry/telemetry/extension_dict.py26
-rw-r--r--tools/telemetry/telemetry/extension_dict_backend.py81
-rw-r--r--tools/telemetry/telemetry/extension_page.py12
-rw-r--r--tools/telemetry/telemetry/extension_to_load.py15
-rw-r--r--tools/telemetry/telemetry/extension_unittest.py74
-rw-r--r--tools/telemetry/telemetry/possible_browser.py4
-rw-r--r--tools/telemetry/unittest_data/simple_extension/background.js8
-rw-r--r--tools/telemetry/unittest_data/simple_extension/manifest.json9
19 files changed, 340 insertions, 21 deletions
diff --git a/tools/telemetry/telemetry/android_browser_backend.py b/tools/telemetry/telemetry/android_browser_backend.py
index 6e2e76a..290e71d 100644
--- a/tools/telemetry/telemetry/android_browser_backend.py
+++ b/tools/telemetry/telemetry/android_browser_backend.py
@@ -17,9 +17,14 @@ from telemetry import browser_gone_exception
class AndroidBrowserBackend(browser_backend.BrowserBackend):
"""The backend for controlling a browser instance running on Android.
"""
- def __init__(self, options, adb, package,
- is_content_shell, cmdline_file, activity, devtools_remote_port):
- super(AndroidBrowserBackend, self).__init__(is_content_shell, options)
+ def __init__(self, options, adb, package, is_content_shell,
+ cmdline_file, activity, devtools_remote_port):
+ super(AndroidBrowserBackend, self).__init__(
+ is_content_shell=is_content_shell,
+ supports_extensions=False, options=options)
+ if len(options.extensions_to_load) > 0:
+ raise browser_backend.ExtensionsNotSupportedException(
+ 'Android browser does not support extensions.')
# Initialize fields so that an explosion during init doesn't break in Close.
self._options = options
self._adb = adb
diff --git a/tools/telemetry/telemetry/android_browser_finder.py b/tools/telemetry/telemetry/android_browser_finder.py
index 37c0b99..da85327 100644
--- a/tools/telemetry/telemetry/android_browser_finder.py
+++ b/tools/telemetry/telemetry/android_browser_finder.py
@@ -44,8 +44,7 @@ CONTENT_SHELL_DEVTOOLS_REMOTE_PORT = (
class PossibleAndroidBrowser(possible_browser.PossibleBrowser):
"""A launchable android browser instance."""
def __init__(self, browser_type, options, *args):
- super(PossibleAndroidBrowser, self).__init__(
- browser_type, options)
+ super(PossibleAndroidBrowser, self).__init__(browser_type, options)
self._args = args
def __repr__(self):
@@ -61,6 +60,11 @@ class PossibleAndroidBrowser(possible_browser.PossibleBrowser):
backend.SetBrowser(b)
return b
+ def SupportsOptions(self, options):
+ if len(options.extensions_to_load) != 0:
+ return False
+ return True
+
def FindAllAvailableBrowsers(options, logging=real_logging):
"""Finds all the desktop browsers available on this machine."""
if not adb_commands.IsAndroidSupported():
diff --git a/tools/telemetry/telemetry/browser.py b/tools/telemetry/telemetry/browser.py
index 25591e6..e336884 100644
--- a/tools/telemetry/telemetry/browser.py
+++ b/tools/telemetry/telemetry/browser.py
@@ -3,13 +3,14 @@
# found in the LICENSE file.
import os
+from telemetry import browser_backend
from telemetry import browser_credentials
+from telemetry import extension_dict
from telemetry import tab_list
from telemetry import temporary_http_server
from telemetry import wpr_modes
from telemetry import wpr_server
-
class Browser(object):
"""A running browser instance that can be controlled in a limited way.
@@ -21,12 +22,16 @@ class Browser(object):
with browser_to_create.Create() as browser:
... do all your operations on browser here
"""
- def __init__(self, browser_backend, platform):
- self._browser_backend = browser_backend
+ def __init__(self, backend, platform):
+ self._browser_backend = backend
self._http_server = None
self._wpr_server = None
self._platform = platform
- self._tabs = tab_list.TabList(browser_backend.tab_list_backend)
+ self._tabs = tab_list.TabList(backend.tab_list_backend)
+ self._extensions = None
+ if backend.supports_extensions:
+ self._extensions = extension_dict.ExtensionDict(
+ backend.extension_dict_backend)
self.credentials = browser_credentials.BrowserCredentials()
def __enter__(self):
@@ -49,6 +54,10 @@ class Browser(object):
return self._browser_backend.is_content_shell
@property
+ def supports_extensions(self):
+ return self._browser_backend.supports_extensions
+
+ @property
def supports_tab_control(self):
return self._browser_backend.supports_tab_control
@@ -57,6 +66,14 @@ class Browser(object):
return self._tabs
@property
+ def extensions(self):
+ """Returns the extension dictionary if it exists."""
+ if not self.supports_extensions:
+ raise browser_backend.ExtensionsNotSupportedException(
+ 'Extensions not supported')
+ return self._extensions
+
+ @property
def supports_tracing(self):
return self._browser_backend.supports_tracing
diff --git a/tools/telemetry/telemetry/browser_backend.py b/tools/telemetry/telemetry/browser_backend.py
index 7c7c685..374c867 100644
--- a/tools/telemetry/telemetry/browser_backend.py
+++ b/tools/telemetry/telemetry/browser_backend.py
@@ -10,6 +10,7 @@ import re
import sys
from telemetry import browser_gone_exception
+from telemetry import extension_dict_backend
from telemetry import options_for_unittests
from telemetry import tab_list_backend
from telemetry import tracing_backend
@@ -18,15 +19,19 @@ from telemetry import util
from telemetry import wpr_modes
from telemetry import wpr_server
+class ExtensionsNotSupportedException(Exception):
+ pass
+
class BrowserBackend(object):
"""A base class for browser backends. Provides basic functionality
once a remote-debugger port has been established."""
WEBPAGEREPLAY_HOST = '127.0.0.1'
- def __init__(self, is_content_shell, options):
+ def __init__(self, is_content_shell, supports_extensions, options):
self.browser_type = options.browser_type
self.is_content_shell = is_content_shell
+ self._supports_extensions = supports_extensions
self.options = options
self._browser = None
self._port = None
@@ -47,6 +52,10 @@ class BrowserBackend(object):
'such as about:flags settings, cookies, and '
'extensions.\n')
self._tab_list_backend = tab_list_backend.TabListBackend(self)
+ self._extension_dict_backend = None
+ if supports_extensions:
+ self._extension_dict_backend = \
+ extension_dict_backend.ExtensionDictBackend(self)
def SetBrowser(self, browser):
self._browser = browser
@@ -57,9 +66,18 @@ class BrowserBackend(object):
return self._browser
@property
+ def supports_extensions(self):
+ """True if this browser backend supports extensions."""
+ return self._supports_extensions
+
+ @property
def tab_list_backend(self):
return self._tab_list_backend
+ @property
+ def extension_dict_backend(self):
+ return self._extension_dict_backend
+
def GetBrowserStartupArgs(self):
args = []
args.extend(self.options.extra_browser_args)
@@ -73,6 +91,12 @@ class BrowserBackend(object):
self.webpagereplay_remote_https_port))
args.extend(user_agent.GetChromeUserAgentArgumentFromType(
self.options.browser_user_agent_type))
+
+ extensions = ','.join(
+ [extension.path for extension in self.options.extensions_to_load])
+ if len(self.options.extensions_to_load) > 0:
+ args.append('--load-extension=%s' % extensions)
+
return args
@property
@@ -92,6 +116,17 @@ class BrowserBackend(object):
except util.TimeoutException:
raise browser_gone_exception.BrowserGoneException()
+ def AllExtensionsLoaded():
+ for e in self.options.extensions_to_load:
+ extension_id = e.extension_id()
+ if not extension_id in self._extension_dict_backend:
+ return False
+ extension_object = self._extension_dict_backend[extension_id]
+ extension_object.WaitForDocumentReadyStateToBeInteractiveOrBetter()
+ return True
+ if self._supports_extensions:
+ util.WaitFor(AllExtensionsLoaded, timeout=30)
+
def _PostBrowserStartupInitialization(self):
# Detect version information.
data = self.Request('version')
diff --git a/tools/telemetry/telemetry/browser_finder.py b/tools/telemetry/telemetry/browser_finder.py
index afc7930..8ec6c3a 100644
--- a/tools/telemetry/telemetry/browser_finder.py
+++ b/tools/telemetry/telemetry/browser_finder.py
@@ -53,7 +53,7 @@ def FindBrowser(options):
return None
matching_browsers = [b for b in browsers
- if b.browser_type == options.browser_type]
+ if b.browser_type == options.browser_type and b.SupportsOptions(options)]
if len(matching_browsers) == 1:
return matching_browsers[0]
diff --git a/tools/telemetry/telemetry/browser_options.py b/tools/telemetry/telemetry/browser_options.py
index 631499c..cb714e8 100644
--- a/tools/telemetry/telemetry/browser_options.py
+++ b/tools/telemetry/telemetry/browser_options.py
@@ -26,6 +26,7 @@ class BrowserOptions(optparse.Values):
self.extra_browser_args = []
self.extra_wpr_args = []
self.show_stdout = False
+ self.extensions_to_load = []
self.cros_remote = None
self.wpr_mode = wpr_modes.WPR_OFF
diff --git a/tools/telemetry/telemetry/cros_browser_backend.py b/tools/telemetry/telemetry/cros_browser_backend.py
index bdb73fc..28b3bce 100644
--- a/tools/telemetry/telemetry/cros_browser_backend.py
+++ b/tools/telemetry/telemetry/cros_browser_backend.py
@@ -9,11 +9,11 @@ from telemetry import browser_backend
from telemetry import util
class CrOSBrowserBackend(browser_backend.BrowserBackend):
- def __init__(self, browser_type, options, is_content_shell, cri):
- super(CrOSBrowserBackend, self).__init__(is_content_shell, options)
+ def __init__(self, browser_type, options, cri):
+ super(CrOSBrowserBackend, self).__init__(is_content_shell=False,
+ supports_extensions=True, options=options)
# Initialize fields so that an explosion during init doesn't break in Close.
self._options = options
- assert not is_content_shell
self._cri = cri
self._browser_type = browser_type
diff --git a/tools/telemetry/telemetry/cros_browser_finder.py b/tools/telemetry/telemetry/cros_browser_finder.py
index f9b5847..593d0b9 100644
--- a/tools/telemetry/telemetry/cros_browser_finder.py
+++ b/tools/telemetry/telemetry/cros_browser_finder.py
@@ -16,10 +16,9 @@ ALL_BROWSER_TYPES = ','.join([
])
class PossibleCrOSBrowser(possible_browser.PossibleBrowser):
- """A launchable android browser instance."""
+ """A launchable chromeos browser instance."""
def __init__(self, browser_type, options, *args):
- super(PossibleCrOSBrowser, self).__init__(
- browser_type, options)
+ super(PossibleCrOSBrowser, self).__init__(browser_type, options)
self._args = args
def __repr__(self):
@@ -32,6 +31,9 @@ class PossibleCrOSBrowser(possible_browser.PossibleBrowser):
backend.SetBrowser(b)
return b
+ def SupportsOptions(self, options):
+ return True
+
def FindAllAvailableBrowsers(options):
"""Finds all the desktop browsers available on this machine."""
if options.cros_remote == None:
@@ -75,4 +77,4 @@ def FindAllAvailableBrowsers(options):
if not cri.FileExistsOnDevice('/opt/google/chrome/chrome'):
logging.warn('Could not find a chrome on ' % cri.hostname)
- return [PossibleCrOSBrowser('cros-chrome', options, False, cri)]
+ return [PossibleCrOSBrowser('cros-chrome', options, cri)]
diff --git a/tools/telemetry/telemetry/crx_id.py b/tools/telemetry/telemetry/crx_id.py
new file mode 100644
index 0000000..2e637da
--- /dev/null
+++ b/tools/telemetry/telemetry/crx_id.py
@@ -0,0 +1,16 @@
+# Copyright (c) 2012 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.
+from __future__ import absolute_import
+
+import os
+import sys
+
+def __init__():
+ path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))
+ sys.path.append(path)
+
+__init__()
+
+from crx_id import crx_id # pylint: disable=F0401
+GetCRXAppID = crx_id.GetCRXAppID
diff --git a/tools/telemetry/telemetry/desktop_browser_backend.py b/tools/telemetry/telemetry/desktop_browser_backend.py
index a0e3d45..cb4d7c92 100644
--- a/tools/telemetry/telemetry/desktop_browser_backend.py
+++ b/tools/telemetry/telemetry/desktop_browser_backend.py
@@ -14,7 +14,9 @@ class DesktopBrowserBackend(browser_backend.BrowserBackend):
Mac or Windows.
"""
def __init__(self, options, executable, is_content_shell):
- super(DesktopBrowserBackend, self).__init__(is_content_shell, options)
+ super(DesktopBrowserBackend, self).__init__(
+ is_content_shell=is_content_shell,
+ supports_extensions=not is_content_shell, options=options)
# Initialize fields so that an explosion during init doesn't break in Close.
self._proc = None
@@ -25,6 +27,10 @@ class DesktopBrowserBackend(browser_backend.BrowserBackend):
if not self._executable:
raise Exception('Cannot create browser, no executable found!')
+ if len(options.extensions_to_load) > 0 and is_content_shell:
+ raise browser_backend.ExtensionsNotSupportedException(
+ 'Content shell does not support extensions.')
+
self._port = util.GetAvailableLocalPort()
args = [self._executable]
diff --git a/tools/telemetry/telemetry/desktop_browser_finder.py b/tools/telemetry/telemetry/desktop_browser_finder.py
index 0264a41..2f2243d 100644
--- a/tools/telemetry/telemetry/desktop_browser_finder.py
+++ b/tools/telemetry/telemetry/desktop_browser_finder.py
@@ -40,6 +40,11 @@ class PossibleDesktopBrowser(possible_browser.PossibleBrowser):
backend.SetBrowser(b)
return b
+ def SupportsOptions(self, options):
+ if (len(options.extensions_to_load) != 0) and self._is_content_shell:
+ return False
+ return True
+
def FindAllAvailableBrowsers(options):
"""Finds all the desktop browsers available on this machine."""
browsers = []
@@ -122,8 +127,7 @@ def FindAllAvailableBrowsers(options):
pass
if found:
browsers.append(
- PossibleDesktopBrowser('system', options,
- 'google-chrome', False))
+ PossibleDesktopBrowser('system', options, 'google-chrome', False))
# Win32-specific options.
if sys.platform.startswith('win'):
diff --git a/tools/telemetry/telemetry/extension_dict.py b/tools/telemetry/telemetry/extension_dict.py
new file mode 100644
index 0000000..5f84af7
--- /dev/null
+++ b/tools/telemetry/telemetry/extension_dict.py
@@ -0,0 +1,26 @@
+# Copyright (c) 2012 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.
+
+from telemetry import extension_to_load
+
+class ExtensionDict(object):
+ """Dictionary of ExtensionPage instances, with extension_id as key"""
+
+ def __init__(self, extension_dict_backend):
+ self._extension_dict_backend = extension_dict_backend
+
+ def __getitem__(self, load_extension):
+ """Given an ExtensionToLoad instance, returns the corresponding
+ ExtensionPage instance."""
+ if not isinstance(load_extension, extension_to_load.ExtensionToLoad):
+ raise Exception("Input param must be of type ExtensionToLoad")
+ return self._extension_dict_backend.__getitem__(
+ load_extension.extension_id())
+
+ def __contains__(self, load_extension):
+ """Checks if this ExtensionToLoad instance has been loaded"""
+ if not isinstance(load_extension, extension_to_load.ExtensionToLoad):
+ raise Exception("Input param must be of type ExtensionToLoad")
+ return self._extension_dict_backend.__contains__(
+ load_extension.extension_id())
diff --git a/tools/telemetry/telemetry/extension_dict_backend.py b/tools/telemetry/telemetry/extension_dict_backend.py
new file mode 100644
index 0000000..22f686f
--- /dev/null
+++ b/tools/telemetry/telemetry/extension_dict_backend.py
@@ -0,0 +1,81 @@
+# Copyright (c) 2012 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 httplib
+import json
+import re
+import socket
+import urllib2
+import weakref
+
+from telemetry import browser_gone_exception
+from telemetry import extension_page
+from telemetry import inspector_backend
+
+class BrowserConnectionGoneException(
+ browser_gone_exception.BrowserGoneException):
+ pass
+
+class ExtensionDictBackend(object):
+ def __init__(self, browser_backend):
+ self._browser_backend = browser_backend
+ # Maps extension ids to ExtensionPage objects.
+ self._extension_dict = weakref.WeakValueDictionary()
+
+ def __getitem__(self, extension_id):
+ extension_object = self._extension_dict.get(extension_id)
+ if not extension_object:
+ extension_object = self._CreateExtensionObject(extension_id)
+ if extension_object:
+ self._extension_dict[extension_id] = extension_object
+ return extension_object
+
+ def __contains__(self, extension_id):
+ return extension_id in self._GetExtensionIds()
+
+ @staticmethod
+ def _ExtractExtensionId(url):
+ m = re.match(r"(chrome-extension://)([^/]+)", url)
+ assert m
+ return m.group(2)
+
+ @staticmethod
+ def _GetExtensionId(extension_info):
+ if 'url' not in extension_info:
+ return None
+ return ExtensionDictBackend._ExtractExtensionId(extension_info['url'])
+
+ def _CreateExtensionObject(self, extension_id):
+ extension_info = self._FindExtensionInfo(extension_id)
+ if not extension_info or not 'webSocketDebuggerUrl' in extension_info:
+ return None
+ return extension_page.ExtensionPage(
+ self._CreateInspectorBackendForDebuggerUrl(
+ extension_info['webSocketDebuggerUrl']))
+
+ def _CreateInspectorBackendForDebuggerUrl(self, debugger_url):
+ return inspector_backend.InspectorBackend(self._browser_backend.browser,
+ self._browser_backend,
+ debugger_url)
+
+ def _FindExtensionInfo(self, extension_id):
+ for extension_info in self._GetExtensionInfoList():
+ if self._GetExtensionId(extension_info) == extension_id:
+ return extension_info
+ return None
+
+ def _GetExtensionInfoList(self, timeout=None):
+ try:
+ data = self._browser_backend.Request('', timeout=timeout)
+ return self._FilterExtensions(json.loads(data))
+ except (socket.error, httplib.BadStatusLine, urllib2.URLError):
+ if not self._browser_backend.IsBrowserRunning():
+ raise browser_gone_exception.BrowserGoneException()
+ raise BrowserConnectionGoneException()
+
+ def _FilterExtensions(self, all_pages):
+ return [page_info for page_info in all_pages
+ if page_info['url'].startswith('chrome-extension://')]
+
+ def _GetExtensionIds(self):
+ return map(self._GetExtensionId, self._GetExtensionInfoList())
diff --git a/tools/telemetry/telemetry/extension_page.py b/tools/telemetry/telemetry/extension_page.py
new file mode 100644
index 0000000..59ed2fb
--- /dev/null
+++ b/tools/telemetry/telemetry/extension_page.py
@@ -0,0 +1,12 @@
+# Copyright (c) 2012 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.
+from telemetry import web_contents
+
+class ExtensionPage(web_contents.WebContents):
+ """Represents a an extension page in the browser"""
+ def __init__(self, inspector_backend):
+ super(ExtensionPage, self).__init__(inspector_backend)
+
+ def __del__(self):
+ super(ExtensionPage, self).__del__()
diff --git a/tools/telemetry/telemetry/extension_to_load.py b/tools/telemetry/telemetry/extension_to_load.py
new file mode 100644
index 0000000..608156d
--- /dev/null
+++ b/tools/telemetry/telemetry/extension_to_load.py
@@ -0,0 +1,15 @@
+# Copyright (c) 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 os
+
+from telemetry import crx_id
+
+class ExtensionToLoad(object):
+ def __init__(self, path):
+ if not os.path.isdir(path):
+ raise Exception('Extension path not a directory %s' % path)
+ self.path = path
+
+ def extension_id(self):
+ return crx_id.GetCRXAppID(os.path.abspath(self.path))
diff --git a/tools/telemetry/telemetry/extension_unittest.py b/tools/telemetry/telemetry/extension_unittest.py
new file mode 100644
index 0000000..f0578229
--- /dev/null
+++ b/tools/telemetry/telemetry/extension_unittest.py
@@ -0,0 +1,74 @@
+# Copyright (c) 2012 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 os
+import shutil
+import tempfile
+import unittest
+
+from telemetry import browser_finder
+from telemetry import extension_to_load
+from telemetry import options_for_unittests
+
+class ExtensionTest(unittest.TestCase):
+ def testExtension(self):
+ extension_path = os.path.join(os.path.dirname(__file__),
+ '..', 'unittest_data', 'simple_extension')
+ load_extension = extension_to_load.ExtensionToLoad(extension_path)
+
+ options = options_for_unittests.GetCopy()
+ options.extensions_to_load = [load_extension]
+ browser_to_create = browser_finder.FindBrowser(options)
+ if not browser_to_create:
+ # Could not find a browser that supports extensions.
+ return
+
+ with browser_to_create.Create() as b:
+ extension = b.extensions[load_extension]
+ assert extension
+ extension.ExecuteJavaScript("setTestVar('abcdef')")
+ self.assertEquals('abcdef', extension.EvaluateJavaScript("_testVar"))
+
+class MultipleExtensionTest(unittest.TestCase):
+ def setUp(self):
+ """ Copy the manifest and background.js files of simple_extension to a
+ number of temporary directories to load as extensions"""
+ self._extension_dirs = [tempfile.mkdtemp()
+ for i in range(3)] # pylint: disable=W0612
+ src_extension_dir = os.path.abspath(os.path.join(os.path.dirname(__file__),
+ '..', 'unittest_data', 'simple_extension'))
+ manifest_path = os.path.join(src_extension_dir, 'manifest.json')
+ script_path = os.path.join(src_extension_dir, 'background.js')
+ for d in self._extension_dirs:
+ shutil.copy(manifest_path, d)
+ shutil.copy(script_path, d)
+ self._extensions_to_load = [extension_to_load.ExtensionToLoad(d)
+ for d in self._extension_dirs]
+ options = options_for_unittests.GetCopy()
+ options.extensions_to_load = self._extensions_to_load
+ browser_to_create = browser_finder.FindBrowser(options)
+ self._browser = None
+ # May not find a browser that supports extensions.
+ if browser_to_create:
+ self._browser = browser_to_create.Create()
+
+ def tearDown(self):
+ if self._browser:
+ self._browser.Close()
+ for d in self._extension_dirs:
+ shutil.rmtree(d)
+
+ def testMultipleExtensions(self):
+ if not self._browser:
+ return
+
+ # Test contains.
+ loaded_extensions = filter(lambda e: e in self._browser.extensions,
+ self._extensions_to_load)
+ self.assertEqual(len(loaded_extensions), len(self._extensions_to_load))
+
+ for load_extension in self._extensions_to_load:
+ extension = self._browser.extensions[load_extension]
+ assert extension
+ extension.ExecuteJavaScript("setTestVar('abcdef')")
+ self.assertEquals('abcdef', extension.EvaluateJavaScript("_testVar"))
diff --git a/tools/telemetry/telemetry/possible_browser.py b/tools/telemetry/telemetry/possible_browser.py
index 2cb995f..13772af 100644
--- a/tools/telemetry/telemetry/possible_browser.py
+++ b/tools/telemetry/telemetry/possible_browser.py
@@ -20,3 +20,7 @@ class PossibleBrowser(object):
def Create(self):
raise NotImplementedError()
+
+ def SupportsOptions(self, options):
+ """Tests for extension support."""
+ raise NotImplementedError()
diff --git a/tools/telemetry/unittest_data/simple_extension/background.js b/tools/telemetry/unittest_data/simple_extension/background.js
new file mode 100644
index 0000000..28b5760
--- /dev/null
+++ b/tools/telemetry/unittest_data/simple_extension/background.js
@@ -0,0 +1,8 @@
+// Copyright (c) 2012 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.
+
+var _testVar;
+function setTestVar(x) {
+ _testVar = x;
+}
diff --git a/tools/telemetry/unittest_data/simple_extension/manifest.json b/tools/telemetry/unittest_data/simple_extension/manifest.json
new file mode 100644
index 0000000..d4bb6a3
--- /dev/null
+++ b/tools/telemetry/unittest_data/simple_extension/manifest.json
@@ -0,0 +1,9 @@
+{
+ "description": "Simple test extension which has just a background script",
+ "name": "Simple Telemetry Test Extension",
+ "background": {
+ "scripts": ["background.js"]
+ },
+ "manifest_version": 2,
+ "version": "0.1"
+}