| # 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 |
| |
| 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 fuchsia_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, |
| fuchsia_browser_finder, |
| ] |
| |
| |
| def _GetBrowserFinders(supported_platforms): |
| if not supported_platforms or 'all' in supported_platforms: |
| return BROWSER_FINDERS |
| browser_finders = [] |
| if any(p in supported_platforms for p in ['mac', 'linux', 'win']): |
| browser_finders.append(desktop_browser_finder) |
| if 'android' in supported_platforms: |
| browser_finders.append(android_browser_finder) |
| if 'chromeos' in supported_platforms: |
| browser_finders.append(cros_browser_finder) |
| if 'fuchsia' in supported_platforms: |
| browser_finders.append(fuchsia_browser_finder) |
| return browser_finders |
| |
| |
| def FindAllBrowserTypes(browser_finders=None): |
| browsers = [] |
| if not browser_finders: |
| browser_finders = BROWSER_FINDERS |
| for bf in browser_finders: |
| browsers.extend(bf.FindAllBrowserTypes()) |
| return browsers |
| |
| def _IsCrosBrowser(options): |
| return (options.browser_type in |
| ['cros-chrome', 'cros-chrome-guest', 'lacros-chrome']) |
| |
| @decorators.Cache |
| def FindBrowser(options): |
| """Finds the best PossibleBrowser object given a BrowserOptions object. |
| |
| Args: |
| A BrowserFinderOptions object. |
| |
| Returns: |
| A PossibleBrowser object. None if browser does not exist in DUT. |
| |
| 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 is 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 (not _IsCrosBrowser(options) and |
| options.cros_remote != None): |
| raise browser_finder_exceptions.BrowserFinderException( |
| '--remote requires --browser=[la]cros-chrome[-guest].') |
| |
| devices = device_finder.GetDevicesMatchingOptions(options) |
| browsers = [] |
| default_browsers = [] |
| |
| browser_finders = _GetBrowserFinders(options.target_platforms) |
| |
| 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()): |
| 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 not browsers: |
| return None |
| |
| if options.browser_type is None: |
| if default_browsers: |
| default_browser = max(default_browsers, |
| key=lambda b: b.last_modification_time) |
| 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({b.browser_type for b in browsers}))) |
| |
| chosen_browser = None |
| if options.browser_type == 'any': |
| types = FindAllBrowserTypes(browser_finders) |
| chosen_browser = min(browsers, key=lambda b: types.index(b.browser_type)) |
| else: |
| matching_browsers = [ |
| b for b in browsers |
| if b.browser_type == options.browser_type and |
| b.SupportsOptions(options.browser_options)] |
| if not matching_browsers: |
| logging.warning('Cannot find any matched browser') |
| return None |
| if len(matching_browsers) > 1: |
| logging.warning('Multiple browsers of the same type found: %r', |
| matching_browsers) |
| chosen_browser = max(matching_browsers, |
| key=lambda b: b.last_modification_time) |
| |
| if chosen_browser: |
| logging.info('Chose browser: %r', 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 = {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 |
| return sorted(list(type_list)) |