| # Copyright 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. |
| |
| """Finds browsers that can be controlled by telemetry.""" |
| |
| import logging |
| import operator |
| |
| from telemetry import decorators |
| from telemetry.internal.backends.chrome import android_browser_finder |
| from telemetry.internal.backends.chrome import cros_browser_finder |
| from telemetry.internal.backends.chrome import desktop_browser_finder |
| from telemetry.internal.backends.chrome import ios_browser_finder |
| from telemetry.internal.browser import browser_finder_exceptions |
| from telemetry.internal.platform import device_finder |
| |
| BROWSER_FINDERS = [ |
| desktop_browser_finder, |
| android_browser_finder, |
| cros_browser_finder, |
| ios_browser_finder, |
| ] |
| |
| |
| def FindAllBrowserTypes(options): |
| return reduce(operator.add, |
| [bf.FindAllBrowserTypes(options) for bf in BROWSER_FINDERS]) |
| |
| |
| @decorators.Cache |
| def FindBrowser(options): |
| """Finds the best PossibleBrowser object given a BrowserOptions object. |
| |
| Args: |
| A BrowserOptions object. |
| |
| Returns: |
| A PossibleBrowser object. |
| |
| Raises: |
| BrowserFinderException: Options improperly set, or an error occurred. |
| """ |
| if options.__class__.__name__ == '_FakeBrowserFinderOptions': |
| return options.fake_possible_browser |
| if options.browser_type == 'exact' and options.browser_executable == None: |
| raise browser_finder_exceptions.BrowserFinderException( |
| '--browser=exact requires --browser-executable to be set.') |
| if options.browser_type != 'exact' and options.browser_executable != None: |
| raise browser_finder_exceptions.BrowserFinderException( |
| '--browser-executable requires --browser=exact.') |
| |
| if options.browser_type == 'cros-chrome' and options.cros_remote == None: |
| raise browser_finder_exceptions.BrowserFinderException( |
| 'browser_type=cros-chrome requires cros_remote be set.') |
| if (options.browser_type != 'cros-chrome' and |
| options.browser_type != 'cros-chrome-guest' and |
| options.cros_remote != None): |
| raise browser_finder_exceptions.BrowserFinderException( |
| '--remote requires --browser=cros-chrome or cros-chrome-guest.') |
| |
| devices = device_finder.GetDevicesMatchingOptions(options) |
| browsers = [] |
| default_browsers = [] |
| for device in devices: |
| for finder in BROWSER_FINDERS: |
| if(options.browser_type and options.browser_type != 'any' and |
| options.browser_type not in finder.FindAllBrowserTypes(options)): |
| continue |
| curr_browsers = finder.FindAllAvailableBrowsers(options, device) |
| new_default_browser = finder.SelectDefaultBrowser(curr_browsers) |
| if new_default_browser: |
| default_browsers.append(new_default_browser) |
| browsers.extend(curr_browsers) |
| |
| if options.browser_type == None: |
| if default_browsers: |
| default_browser = sorted(default_browsers, |
| key=lambda b: b.last_modification_time())[-1] |
| |
| logging.warning('--browser omitted. Using most recent local build: %s' % |
| default_browser.browser_type) |
| default_browser.UpdateExecutableIfNeeded() |
| return default_browser |
| |
| if len(browsers) == 1: |
| logging.warning('--browser omitted. Using only available browser: %s' % |
| browsers[0].browser_type) |
| browsers[0].UpdateExecutableIfNeeded() |
| return browsers[0] |
| |
| raise browser_finder_exceptions.BrowserTypeRequiredException( |
| '--browser must be specified. Available browsers:\n%s' % |
| '\n'.join(sorted(set([b.browser_type for b in browsers])))) |
| |
| if options.browser_type == 'any': |
| types = FindAllBrowserTypes(options) |
| def CompareBrowsersOnTypePriority(x, y): |
| x_idx = types.index(x.browser_type) |
| y_idx = types.index(y.browser_type) |
| return x_idx - y_idx |
| browsers.sort(CompareBrowsersOnTypePriority) |
| if len(browsers) >= 1: |
| browsers[0].UpdateExecutableIfNeeded() |
| return browsers[0] |
| else: |
| return None |
| |
| matching_browsers = [b for b in browsers |
| if b.browser_type == options.browser_type and b.SupportsOptions(options)] |
| |
| chosen_browser = None |
| if len(matching_browsers) == 1: |
| chosen_browser = matching_browsers[0] |
| elif len(matching_browsers) > 1: |
| logging.warning('Multiple browsers of the same type found: %s' % ( |
| repr(matching_browsers))) |
| chosen_browser = sorted(matching_browsers, |
| key=lambda b: b.last_modification_time())[-1] |
| |
| if chosen_browser: |
| logging.info('Chose browser: %s' % (repr(chosen_browser))) |
| chosen_browser.UpdateExecutableIfNeeded() |
| |
| return chosen_browser |
| |
| |
| @decorators.Cache |
| def GetAllAvailableBrowsers(options, device): |
| """Returns a list of available browsers on the device. |
| |
| Args: |
| options: A BrowserOptions object. |
| device: The target device, which can be None. |
| |
| Returns: |
| A list of browser instances. |
| |
| Raises: |
| BrowserFinderException: Options are improperly set, or an error occurred. |
| """ |
| if not device: |
| return [] |
| possible_browsers = [] |
| for browser_finder in BROWSER_FINDERS: |
| possible_browsers.extend( |
| browser_finder.FindAllAvailableBrowsers(options, device)) |
| return possible_browsers |
| |
| |
| @decorators.Cache |
| def GetAllAvailableBrowserTypes(options): |
| """Returns a list of available browser types. |
| |
| Args: |
| options: A BrowserOptions object. |
| |
| Returns: |
| A list of browser type strings. |
| |
| Raises: |
| BrowserFinderException: Options are improperly set, or an error occurred. |
| """ |
| devices = device_finder.GetDevicesMatchingOptions(options) |
| possible_browsers = [] |
| for device in devices: |
| possible_browsers.extend(GetAllAvailableBrowsers(options, device)) |
| type_list = set([browser.browser_type for browser in possible_browsers]) |
| # The reference build should be available for mac, linux and win, but the |
| # desktop browser finder won't return it in the list of browsers. |
| for browser in possible_browsers: |
| if (browser.target_os == 'darwin' or browser.target_os.startswith('linux') |
| or browser.target_os.startswith('win')): |
| type_list.add('reference') |
| break |
| type_list = list(type_list) |
| type_list.sort() |
| return type_list |