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