diff options
author | nduca@chromium.org <nduca@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-09-07 07:02:46 +0000 |
---|---|---|
committer | nduca@chromium.org <nduca@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-09-07 07:02:46 +0000 |
commit | 44a8aacef75d0de3db8278d72386f110b4eb9bcc (patch) | |
tree | 9edc0df75192b1e84a51a179d6037c49e9f888bb /tools | |
parent | aa92aca78bb3fa8c98335daa87db2c7dee3d3c46 (diff) | |
download | chromium_src-44a8aacef75d0de3db8278d72386f110b4eb9bcc.zip chromium_src-44a8aacef75d0de3db8278d72386f110b4eb9bcc.tar.gz chromium_src-44a8aacef75d0de3db8278d72386f110b4eb9bcc.tar.bz2 |
chrome_remote_control: Detect chrome android in addition to content shell
TBR=dtu@chromium.org
Review URL: https://chromiumcodereview.appspot.com/10916136
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@155348 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'tools')
14 files changed, 245 insertions, 92 deletions
diff --git a/tools/chrome_remote_control/chrome_remote_control/__init__.py b/tools/chrome_remote_control/chrome_remote_control/__init__.py index ebc83d2..8a0e7a8 100644 --- a/tools/chrome_remote_control/chrome_remote_control/__init__.py +++ b/tools/chrome_remote_control/chrome_remote_control/__init__.py @@ -9,3 +9,19 @@ from browser_options import * from browser import * from tab import * from util import * + +def CreateBrowser(type): + """Shorthand way to create a browser of a given type + + However, note that the preferred way to create a browser is: + options = BrowserOptions() + _, leftover_args, = options.CreateParser().parse_args() + browser_to_create = FindBrowser(options) + return browser_to_create.Create() + + as it creates more opportunities for customization and + error handling.""" + browser_to_create = FindBrowser(BrowserOptions(type)) + if not browser_to_create: + raise Exception("No browser of type %s found" % type) + return browser_to_create.Create() diff --git a/tools/chrome_remote_control/chrome_remote_control/adb_commands.py b/tools/chrome_remote_control/chrome_remote_control/adb_commands.py index 7a5ad30..db492490 100644 --- a/tools/chrome_remote_control/chrome_remote_control/adb_commands.py +++ b/tools/chrome_remote_control/chrome_remote_control/adb_commands.py @@ -107,3 +107,12 @@ class ADBCommands(object): def Push(self, local, remote): return self._adb.Adb().Push(local, remote) + + def Pull(self, remote, local): + return self._adb.Adb().Pull(remote, local) + + def FileExistsOnDevice(self, file_name): + return self._adb.FileExistsOnDevice(file_name) + + def IsRootEnabled(self): + return self._adb.IsRootEnabled() diff --git a/tools/chrome_remote_control/chrome_remote_control/android_browser_backend.py b/tools/chrome_remote_control/chrome_remote_control/android_browser_backend.py index 58249cb..92810f8 100644 --- a/tools/chrome_remote_control/chrome_remote_control/android_browser_backend.py +++ b/tools/chrome_remote_control/chrome_remote_control/android_browser_backend.py @@ -38,17 +38,20 @@ class AndroidBrowserBackend(browser_backend.BrowserBackend): args = [pseudo_exec_name, "--disable-fre", "--no-first-run"] - # Kill old broser. + # Kill old browser. self._adb.KillAll(self._package) - self._adb.KillAll('forawrder') + self._adb.KillAll('forwarder') self._adb.Forward('tcp:9222', self._devtools_remote_port) - # Set up temporary dir if needed. As far as we can tell, content_shell - # doesn't have persisted data, so --user-data-dir isn't needed. + # Chrome Android doesn't listen to --user-data-dir. + # TODO: symlink the app's Default, files and cache dir + # to somewhere safe. if not is_content_shell and not options.dont_override_profile: - self._tmpdir = "/sdcard/chrome_remote_control_data" - self._adb.RunShellCommand('rm -r %s' % self._tmpdir) - args.append("--user-data-dir=%s" % self._tmpdir) + # Set up the temp dir + # self._tmpdir = "/sdcard/chrome_remote_control_data" + # self._adb.RunShellCommand('rm -r %s' % self._tmpdir) + # args.append("--user-data-dir=%s" % self._tmpdir) + pass # Set up the command line. args.extend(options.extra_browser_args) @@ -57,6 +60,41 @@ class AndroidBrowserBackend(browser_backend.BrowserBackend): f.flush() self._adb.Push(f.name, cmdline_file) + # Force devtools protocol on, if not already done. + if not is_content_shell: + # Make sure we can find the apps' prefs file + app_data_dir = "/data/data/%s" % self._package + prefs_file = (app_data_dir + + "/app_chrome/Default/Preferences") + if not self._adb.FileExistsOnDevice(prefs_file): + logging.critical( + "android_browser_backend: Could not find preferences file " + + "%s for %s" % (prefs_file, self._package)) + raise browser_backend.BrowserGoneException("Missing preferences file.") + + with tempfile.NamedTemporaryFile() as raw_f: + self._adb.Pull(prefs_file, raw_f.name) + with open(raw_f.name, 'r') as f: + txt_in = f.read() + preferences = json.loads(txt_in) + changed = False + if "devtools" not in preferences: + preferences["devtools"] = {} + changed = True + if "remote_enabled" not in preferences["devtools"]: + preferences["devtools"]["remote_enabled"] = True + changed = True + if preferences["devtools"]["remote_enabled"] != True: + preferences["devtools"]["remote_enabled"] = True + changed = True + if changed: + logging.warning("Manually enabled devtools protocol on %s" % + self._package) + with open(raw_f.name, 'w') as f: + txt = json.dumps(preferences, indent=2) + f.write(txt) + self._adb.Push(raw_f.name, prefs_file) + # Start it up! self._adb.StartActivity(self._package, self._activity, diff --git a/tools/chrome_remote_control/chrome_remote_control/android_browser_finder.py b/tools/chrome_remote_control/chrome_remote_control/android_browser_finder.py index 8889883..ff2d960 100644 --- a/tools/chrome_remote_control/chrome_remote_control/android_browser_finder.py +++ b/tools/chrome_remote_control/chrome_remote_control/android_browser_finder.py @@ -5,6 +5,7 @@ import os as real_os import sys as real_sys import subprocess as real_subprocess import logging +import re import chrome_remote_control.android_browser_backend as android_browser_backend import chrome_remote_control.adb_commands as real_adb_commands @@ -14,28 +15,19 @@ import possible_browser """Finds android browsers that can be controlled by chrome_remote_control.""" -ALL_BROWSER_TYPES = 'android-content-shell' - -# Commmand line -# content-shell: /data/local/tmp/content-shell-command-line -# or /data/local/tmp/chrome-command-line -# clank: /data/local/chrome-command-line - -# --remote-debugging-port=9222 -# --disable-fre - -# Forwarding command: -# adb forward tcp:xxxx localabstract:chrome_devtools-remote - -# Package names: -# org.chromium.content_shell -# com.android.chrome # m18 accidentally used this for a while -# com.google.android.apps.chrome +ALL_BROWSER_TYPES = ','.join([ + 'android-content-shell', + 'android-chrome' + 'android-jb-system-chrome' + ]) CHROME_PACKAGE = 'com.google.android.apps.chrome' CHROME_ACTIVITY = '.Main' CHROME_COMMAND_LINE = '/data/local/chrome-command-line' -CHROME_DEVTOOLS_REMOTE_PORT = 'localabstract:chrome_devtools-remote' +CHROME_DEVTOOLS_REMOTE_PORT = 'localabstract:chrome_devtools_remote' + +CHROME_JB_SYSTEM_PACKAGE = 'com.android.chrome' +CHROME_JB_SYSTEM_DEVTOOLS_REMOTE_PORT = 'localabstract:chrome_devtools_remote' CONTENT_SHELL_PACKAGE = 'org.chromium.content_shell' CONTENT_SHELL_ACTIVITY = '.ContentShellActivity' @@ -75,7 +67,17 @@ def FindAllAvailableBrowsers(options, # See if adb even works. try: with open(real_os.devnull, 'w') as devnull: - subprocess.call('adb', stdout=devnull, stderr=devnull) + proc = subprocess.Popen(['adb', 'devices'], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + stdin=devnull) + stdout, stderr = proc.communicate() + if re.search(re.escape("????????????\tno permissions"), stdout) != None: + logging.warning( + ("adb devices reported a permissions error. Consider " + "restarting adb as root:")) + logging.warning(" adb kill-server") + logging.warning(" sudo `which adb` devices\n\n") except OSError: logging.info('No adb command found. ' + 'Will not try searching for Android browsers.') @@ -100,6 +102,13 @@ def FindAllAvailableBrowsers(options, adb = adb_commands.ADBCommands(device=device) + # See if adb is root + if not adb.IsRootEnabled(): + logging.warn('ADB is not root. Please make it root by doing:') + logging.warn(' adb root') + return [] + + packages = adb.RunShellCommand('pm list packages') if 'package:' + CONTENT_SHELL_PACKAGE in packages: b = PossibleAndroidBrowser('android-content-shell', @@ -110,4 +119,23 @@ def FindAllAvailableBrowsers(options, CONTENT_SHELL_DEVTOOLS_REMOTE_PORT) browsers.append(b) + if 'package:' + CHROME_PACKAGE in packages: + b = PossibleAndroidBrowser('android-chrome', + options, adb, + CHROME_PACKAGE, False, + CHROME_COMMAND_LINE, + CHROME_ACTIVITY, + CHROME_DEVTOOLS_REMOTE_PORT) + browsers.append(b) + + if 'package:' + CHROME_JB_SYSTEM_PACKAGE in packages: + b = PossibleAndroidBrowser('android-jb-system-chrome', + options, adb, + CHROME_JB_SYSTEM_PACKAGE, False, + CHROME_COMMAND_LINE, + CHROME_ACTIVITY, + CHROME_JB_SYSTEM_DEVTOOLS_REMOTE_PORT) + browsers.append(b) + + return browsers diff --git a/tools/chrome_remote_control/chrome_remote_control/android_browser_finder_unittest.py b/tools/chrome_remote_control/chrome_remote_control/android_browser_finder_unittest.py index be0c6e3..9818901 100644 --- a/tools/chrome_remote_control/chrome_remote_control/android_browser_finder_unittest.py +++ b/tools/chrome_remote_control/chrome_remote_control/android_browser_finder_unittest.py @@ -10,19 +10,33 @@ import browser_options # adb not even found # android_browser_finder not returning -class StubSubprocess(object): +class PopenStub(object): def __init__(self): - self.call_hook = None + self.communicate_result = None + def communicate(self): + if self.communicate_result == None: + raise Exception("Should not be called") + return self.communicate_result - def call(self, *args, **kwargs): - if not self.call_hook: - raise Exception('Should not be reached.') - return self.call_hook(*args, **kwargs) - -class StubADBCommands(object): +class SubprocessStub(object): + def __init__(self): + self.Popen_hook = None + self.Popen_result = None + import subprocess as real_subprocess + self.PIPE = real_subprocess.PIPE + + def Popen(self, *args, **kwargs): + if self.Popen_hook: + return self.Popen_hook(*args, **kwargs) + if not self.Popen_result: + raise Exception("Should not be called") + return self.Popen_result + +class ADBCommandsStub(object): def __init__(self, module, device): self._module = module self._device = device + self.is_root_enabled = True def RunShellCommand(self, args): if isinstance(args, basestring): @@ -31,14 +45,17 @@ class StubADBCommands(object): handler = self._module.shell_command_handlers[args[0]] return handler(args) -class StubADBCommandsModule(object): + def IsRootEnabled(self): + return self.is_root_enabled + +class ADBCommandsModuleStub(object): def __init__(self): self.attached_devices = [] self.shell_command_handlers = {} - def StubADBCommandsConstructor(device=None): - return StubADBCommands(self, device) - self.ADBCommands = StubADBCommandsConstructor + def ADBCommandsStubConstructor(device=None): + return ADBCommandsStub(self, device) + self.ADBCommands = ADBCommandsStubConstructor def IsAndroidSupported(self): return True @@ -50,10 +67,10 @@ class AndroidBrowserFinderTest(unittest.TestCase): def test_no_adb(self): options = browser_options.BrowserOptions() - subprocess_stub = StubSubprocess() + subprocess_stub = SubprocessStub() def NoADB(*args, **kargs): raise OSError('not found') - subprocess_stub.call_hook = NoADB + subprocess_stub.Popen_hook = NoADB browsers = android_browser_finder.FindAllAvailableBrowsers( options, subprocess_stub) self.assertEquals(0, len(browsers)) @@ -61,21 +78,61 @@ class AndroidBrowserFinderTest(unittest.TestCase): def test_adb_no_devices(self): options = browser_options.BrowserOptions() - subprocess_stub = StubSubprocess() - subprocess_stub.call_hook = lambda *args, **kargs: 0 - adb_commands_module_stub = StubADBCommandsModule() + subprocess_stub = SubprocessStub() + popen_stub = PopenStub() + popen_stub.communicate_result = ("", "") + subprocess_stub.Popen_result = popen_stub + + adb_commands_module_stub = ADBCommandsModuleStub() browsers = android_browser_finder.FindAllAvailableBrowsers( options, subprocess_stub, adb_commands_module_stub) self.assertEquals(0, len(browsers)) + + def test_adb_permissions_error(self): + options = browser_options.BrowserOptions() + + subprocess_stub = SubprocessStub() + popen_stub = PopenStub() + popen_stub.communicate_result = ( + """List of devices attached +????????????\tno permissions""", + """* daemon not running. starting it now on port 5037 * +* daemon started successfully * +""") + subprocess_stub.Popen_result = popen_stub + + adb_commands_module_stub = ADBCommandsModuleStub() + + warnings = [] + class TempFilter(logging.Filter): + def filter(self, record): + warnings.append(record) + return 0 + temp_filter = TempFilter() + + try: + logger = logging.getLogger() + logger.addFilter(temp_filter) + + browsers = android_browser_finder.FindAllAvailableBrowsers( + options, subprocess_stub, adb_commands_module_stub) + finally: + logger.removeFilter(temp_filter) + self.assertEquals(3, len(warnings)) + self.assertEquals(0, len(browsers)) + + def test_adb_two_devices(self): options = browser_options.BrowserOptions() - subprocess_stub = StubSubprocess() - subprocess_stub.call_hook = lambda *args, **kargs: 0 - adb_commands_module_stub = StubADBCommandsModule() + subprocess_stub = SubprocessStub() + popen_stub = PopenStub() + popen_stub.communicate_result = ("", "") + subprocess_stub.Popen_result = popen_stub + adb_commands_module_stub = ADBCommandsModuleStub() adb_commands_module_stub.attached_devices = ['015d14fec128220c', - '015d14fec128220d'] + '015d14fec128220d'] warnings = [] class TempFilter(logging.Filter): @@ -98,9 +155,11 @@ class AndroidBrowserFinderTest(unittest.TestCase): def test_adb_one_device(self): options = browser_options.BrowserOptions() - subprocess_stub = StubSubprocess() - subprocess_stub.call_hook = lambda *args, **kargs: 0 - adb_commands_module_stub = StubADBCommandsModule() + subprocess_stub = SubprocessStub() + popen_stub = PopenStub() + popen_stub.communicate_result = ("", "") + subprocess_stub.Popen_result = popen_stub + adb_commands_module_stub = ADBCommandsModuleStub() adb_commands_module_stub.attached_devices = ['015d14fec128220c'] def OnPM(args): diff --git a/tools/chrome_remote_control/chrome_remote_control/browser_backend.py b/tools/chrome_remote_control/chrome_remote_control/browser_backend.py index e041690..17d2111 100644 --- a/tools/chrome_remote_control/chrome_remote_control/browser_backend.py +++ b/tools/chrome_remote_control/chrome_remote_control/browser_backend.py @@ -32,7 +32,7 @@ class BrowserBackend(object): else: return True try: - util.WaitFor(IsBrowserUp, timeout=15) + util.WaitFor(IsBrowserUp, timeout=30) except util.TimeoutException: raise BrowserGoneException() diff --git a/tools/chrome_remote_control/chrome_remote_control/browser_finder.py b/tools/chrome_remote_control/chrome_remote_control/browser_finder.py index b0151e0..f85bb85 100644 --- a/tools/chrome_remote_control/chrome_remote_control/browser_finder.py +++ b/tools/chrome_remote_control/chrome_remote_control/browser_finder.py @@ -18,7 +18,8 @@ class BrowserTypeRequiredException(Exception): def FindBrowser(options): """Finds the best PossibleBrowser object to run given the provided BrowserOptions object. The returned possiblity object can then be used to - connect to and control the located browser.""" + connect to and control the located browser. + """ if options.browser_type == 'exact' and options.browser_executable == None: raise Exception("browser_type=exact requires browser_executable be set.") diff --git a/tools/chrome_remote_control/chrome_remote_control/browser_options.py b/tools/chrome_remote_control/chrome_remote_control/browser_options.py index 1661cde..fef48ca 100644 --- a/tools/chrome_remote_control/chrome_remote_control/browser_options.py +++ b/tools/chrome_remote_control/chrome_remote_control/browser_options.py @@ -8,46 +8,55 @@ import shlex import browser_finder class BrowserOptions(optparse.Values): - """Options to be used for disocvering and launching browsers.""" + """Options to be used for discovering and launching a browser.""" - def __init__(self): + def __init__(self, type = None): optparse.Values.__init__(self) self.dont_override_profile = False self.show_stdout = False self.browser_executable = None - self._browser_type = None + self.browser_type = type self.chrome_root = None self.android_device = None self.extra_browser_args = [] def CreateParser(self, *args, **kwargs): parser = optparse.OptionParser(*args, **kwargs) - parser.add_option('--browser', + + # Selection group + group = optparse.OptionGroup(parser, "Which browser to use") + group.add_option('--browser', dest='browser_type', default=None, help='Browser type to run, ' 'in order of priority. Supported values: list,%s' % browser_finder.ALL_BROWSER_TYPES) - parser.add_option('--dont-override-profile', action='store_true', - dest='dont_override_profile', - help='Uses the regular user profile instead of a clean one') - parser.add_option('--browser-executable', + group.add_option('--browser-executable', dest='browser_executable', help='The exact browser to run.') - parser.add_option('--chrome-root', + group.add_option('--chrome-root', dest='chrome_root', help='Where to look for chrome builds.' 'Defaults to searching parent dirs by default.') - parser.add_option('--extra-browser-args', + group.add_option('--device', + dest='android_device', + help='The android device ID to use' + 'If not specified, only 0 or 1 connected devcies are supported.') + parser.add_option_group(group) + + # Browser options + group = optparse.OptionGroup(parser, "Browser options") + group.add_option('--dont-override-profile', action='store_true', + dest='dont_override_profile', + help='Uses the regular user profile instead of a clean one') + group.add_option('--extra-browser-args', dest='extra_browser_args_as_string', help='Additional arguments to pass to the browser when it starts') - parser.add_option('--show-stdout', + group.add_option('--show-stdout', action='store_true', help="When possible, will display the stdout of the process") - parser.add_option('--device', - dest='android_device', - help='The android device ID to use' - 'If not specified, only 0 or 1 connected devcies are supported.') + parser.add_option_group(group) + real_parse = parser.parse_args def ParseArgs(args=None): defaults = parser.get_default_values() @@ -75,14 +84,6 @@ class BrowserOptions(optparse.Values): parser.parse_args = ParseArgs return parser - @property - def browser_types_to_use(self): - return self._browser_types_to_use - - @browser_types_to_use.setter - def browser_types_to_use(self, value): - self._browser_types_to_use = value.split(',') - """ This global variable can be set to a BrowserOptions object by the test harness to allow multiple unit tests to use a specific browser, in face of multiple diff --git a/tools/chrome_remote_control/chrome_remote_control/browser_unittest.py b/tools/chrome_remote_control/chrome_remote_control/browser_unittest.py index 24f856e..1666196 100644 --- a/tools/chrome_remote_control/chrome_remote_control/browser_unittest.py +++ b/tools/chrome_remote_control/chrome_remote_control/browser_unittest.py @@ -28,18 +28,16 @@ class BrowserTest(unittest.TestCase): testJS = ("window.chrome.gpuBenchmarking !== undefined ||" + "chrome.Interval !== undefined") - flag1 = "--enable-benchmarking" - flag2 = "--enable-gpu-benchmarking" + flag1 = "--user-agent=chrome_remote_control" options.extra_browser_args.append(flag1) - options.extra_browser_args.append(flag2) try: browser_to_create = browser_finder.FindBrowser(options) with browser_to_create.Create() as b: with b.ConnectToNthTab(0) as t: t.page.Navigate("http://www.google.com/") t.WaitForDocumentReadyStateToBeInteractiveOrBetter() - self.assertTrue(t.runtime.Evaluate(testJS)) + self.assertEquals(t.runtime.Evaluate('navigator.userAgent'), + 'chrome_remote_control') finally: - options.extra_browser_args.remove(flag2) options.extra_browser_args.remove(flag1) diff --git a/tools/chrome_remote_control/chrome_remote_control/run_tests.py b/tools/chrome_remote_control/chrome_remote_control/run_tests.py index 40505dd..e7bff2c 100644 --- a/tools/chrome_remote_control/chrome_remote_control/run_tests.py +++ b/tools/chrome_remote_control/chrome_remote_control/run_tests.py @@ -107,6 +107,11 @@ def Main(args, start_dir, top_level_dir): else: logging.basicConfig(level=logging.WARNING) + import browser_finder + if browser_finder.FindBrowser(default_options) == None: + logging.error("No browser found. Cannot run tests.\n") + return 1 + browser_options.options_for_unittests = default_options olddir = os.getcwd() num_errors = 0 diff --git a/tools/chrome_remote_control/chrome_remote_control/tab_runtime.py b/tools/chrome_remote_control/chrome_remote_control/tab_runtime.py index 827e1c28..eaedca2 100644 --- a/tools/chrome_remote_control/chrome_remote_control/tab_runtime.py +++ b/tools/chrome_remote_control/chrome_remote_control/tab_runtime.py @@ -50,11 +50,10 @@ class TabRuntime(object): if "error" in res: raise EvaluateException(res["error"]["message"]) - if res["result"]["wasThrown"]: + if "wasThrown" in res["result"] and res["result"]["wasThrown"]: # TODO(nduca): propagate stacks from javascript up to the python # exception. raise EvaluateException(res["result"]["result"]["description"]) if res["result"]["result"]["type"] == 'undefined': return None return res["result"]["result"]["value"] - diff --git a/tools/chrome_remote_control/chrome_remote_control/util.py b/tools/chrome_remote_control/chrome_remote_control/util.py index 5ea4fbd..2d15810 100644 --- a/tools/chrome_remote_control/chrome_remote_control/util.py +++ b/tools/chrome_remote_control/chrome_remote_control/util.py @@ -13,7 +13,10 @@ def WaitFor(condition, timeout): while not condition(): if time.time() - start_time > timeout: if condition.__name__ == '<lambda>': - condition_string = inspect.getsource(condition).strip() + try: + condition_string = inspect.getsource(condition).strip() + except IOError: + condition_string = condition.__name__ else: condition_string = condition.__name__ raise TimeoutException('Timed out while waiting %ds for %s.' % diff --git a/tools/chrome_remote_control/examples/list_available_browsers b/tools/chrome_remote_control/examples/list_available_browsers index 1e3639b..c868a5d 100755 --- a/tools/chrome_remote_control/examples/list_available_browsers +++ b/tools/chrome_remote_control/examples/list_available_browsers @@ -12,14 +12,9 @@ import chrome_remote_control def Main(args): options = chrome_remote_control.BrowserOptions() - parser = options.CreateParser( - "list_available_browsers <sitelist>") - options, args = parser.parse_args() - browser_to_create = chrome_remote_control.FindAllPossibleBrowsers(options) - if not len(browser_to_create): - sys.stderr.write("No browsers found.\n") - return 1 - print ",".join([b.type for b in browser_to_create]) + options.browser_type = 'list'; + parser = options.CreateParser("list_available_browsers") + parser.parse_args() return 0 if __name__ == "__main__": diff --git a/tools/gpu/gpu_tools/page_scroller.py b/tools/gpu/gpu_tools/page_scroller.py index 0dbb909..0f8ca6a 100644 --- a/tools/gpu/gpu_tools/page_scroller.py +++ b/tools/gpu/gpu_tools/page_scroller.py @@ -15,7 +15,6 @@ import scroll import page_set import url_test - def Main(args): options = chrome_remote_control.BrowserOptions() parser = options.CreateParser("page_scroller <pageset>") @@ -36,6 +35,8 @@ def Run(output_stream, options, ps): results_writer.writerow(['URL', 'FPS', 'Mean Frame Time (s)', '% Dropped Frames', 'First Paint Time (s)']) possible_browser = chrome_remote_control.FindBrowser(options) + if not possible_browser: + raise Exception('No browser found. Can not continue') with possible_browser.Create() as b: for result in url_test.UrlTest(b, scroll.Scroll, ps): if not result.DidScroll(): |