1# Copyright 2012 The Chromium Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5"""Finds browsers that can be controlled by telemetry.""" 6 7import logging 8import operator 9 10from telemetry import decorators 11from telemetry.core.backends.chrome import android_browser_finder 12from telemetry.core.backends.chrome import cros_browser_finder 13from telemetry.core.backends.chrome import desktop_browser_finder 14from telemetry.core.backends.chrome import ios_browser_finder 15from telemetry.core.backends.remote import trybot_browser_finder 16from telemetry.core.backends.webdriver import webdriver_desktop_browser_finder 17 18BROWSER_FINDERS = [ 19 desktop_browser_finder, 20 android_browser_finder, 21 cros_browser_finder, 22 ios_browser_finder, 23 trybot_browser_finder, 24 webdriver_desktop_browser_finder, 25 ] 26 27 28class BrowserTypeRequiredException(Exception): 29 pass 30 31 32class BrowserFinderException(Exception): 33 pass 34 35 36def FindAllBrowserTypes(options): 37 return reduce(operator.add, 38 [bf.FindAllBrowserTypes(options) for bf in BROWSER_FINDERS]) 39 40 41@decorators.Cache 42def FindBrowser(options): 43 """Finds the best PossibleBrowser object given a BrowserOptions object. 44 45 Args: 46 A BrowserOptions object. 47 48 Returns: 49 A PossibleBrowser object. 50 51 Raises: 52 BrowserFinderException: Options improperly set, or an error occurred. 53 """ 54 if options.browser_type == 'exact' and options.browser_executable == None: 55 raise BrowserFinderException( 56 '--browser=exact requires --browser-executable to be set.') 57 if options.browser_type != 'exact' and options.browser_executable != None: 58 raise BrowserFinderException( 59 '--browser-executable requires --browser=exact.') 60 61 if options.browser_type == 'cros-chrome' and options.cros_remote == None: 62 raise BrowserFinderException( 63 'browser_type=cros-chrome requires cros_remote be set.') 64 if (options.browser_type != 'cros-chrome' and 65 options.browser_type != 'cros-chrome-guest' and 66 options.cros_remote != None): 67 raise BrowserFinderException( 68 '--remote requires --browser=cros-chrome or cros-chrome-guest.') 69 70 browsers = [] 71 default_browsers = [] 72 for finder in BROWSER_FINDERS: 73 if(options.browser_type and options.browser_type != 'any' and 74 options.browser_type not in finder.FindAllBrowserTypes(options)): 75 continue 76 curr_browsers = finder.FindAllAvailableBrowsers(options) 77 new_default_browser = finder.SelectDefaultBrowser(curr_browsers) 78 if new_default_browser: 79 default_browsers.append(new_default_browser) 80 browsers.extend(curr_browsers) 81 82 if options.browser_type == None: 83 if default_browsers: 84 default_browser = sorted(default_browsers, 85 key=lambda b: b.last_modification_time())[-1] 86 87 logging.warning('--browser omitted. Using most recent local build: %s' % 88 default_browser.browser_type) 89 default_browser.UpdateExecutableIfNeeded() 90 return default_browser 91 92 if len(browsers) == 1: 93 logging.warning('--browser omitted. Using only available browser: %s' % 94 browsers[0].browser_type) 95 browsers[0].UpdateExecutableIfNeeded() 96 return browsers[0] 97 98 raise BrowserTypeRequiredException( 99 '--browser must be specified. Available browsers:\n%s' % 100 '\n'.join(sorted(set([b.browser_type for b in browsers])))) 101 102 if options.browser_type == 'any': 103 types = FindAllBrowserTypes(options) 104 def CompareBrowsersOnTypePriority(x, y): 105 x_idx = types.index(x.browser_type) 106 y_idx = types.index(y.browser_type) 107 return x_idx - y_idx 108 browsers.sort(CompareBrowsersOnTypePriority) 109 if len(browsers) >= 1: 110 browsers[0].UpdateExecutableIfNeeded() 111 return browsers[0] 112 else: 113 return None 114 115 matching_browsers = [b for b in browsers 116 if b.browser_type == options.browser_type and b.SupportsOptions(options)] 117 118 chosen_browser = None 119 if len(matching_browsers) == 1: 120 chosen_browser = matching_browsers[0] 121 elif len(matching_browsers) > 1: 122 logging.warning('Multiple browsers of the same type found: %s' % ( 123 repr(matching_browsers))) 124 chosen_browser = sorted(matching_browsers, 125 key=lambda b: b.last_modification_time())[-1] 126 127 if chosen_browser: 128 logging.info('Chose browser: %s' % (repr(chosen_browser))) 129 chosen_browser.UpdateExecutableIfNeeded() 130 131 return chosen_browser 132 133 134@decorators.Cache 135def GetAllAvailableBrowserTypes(options): 136 """Returns a list of available browser types. 137 138 Args: 139 options: A BrowserOptions object. 140 141 Returns: 142 A list of browser type strings. 143 144 Raises: 145 BrowserFinderException: Options are improperly set, or an error occurred. 146 """ 147 browsers = [] 148 for finder in BROWSER_FINDERS: 149 browsers.extend(finder.FindAllAvailableBrowsers(options)) 150 151 type_list = set([browser.browser_type for browser in browsers]) 152 type_list = list(type_list) 153 type_list.sort() 154 return type_list 155