def Start(self, startup_args, startup_url=None): self.device.adb.Logcat(clear=True) self.platform_backend.DismissCrashDialogIfNeeded() user_agent_dict = user_agent.GetChromeUserAgentDictFromType( self.browser_options.browser_user_agent_type) command_line_name = self._backend_settings.command_line_name with flag_changer.CustomCommandLineFlags(self.device, command_line_name, startup_args): # Stop existing browser, if any. This is done *after* setting the # command line flags, in case some other Android process manages to # trigger Chrome's startup before we do. self._StopBrowser() self._SetupProfile() self.device.StartActivity(intent.Intent( package=self._backend_settings.package, activity=self._backend_settings.activity, action=None, data=startup_url, category=None, extras=user_agent_dict), blocking=True) try: self.BindDevToolsClient() except: self.Close() raise
def main(): adapter = WPTAndroidAdapter() adapter.parse_args() if adapter.options.verbose: if adapter.options.verbose == 1: logger.setLevel(logging.INFO) else: logger.setLevel(logging.DEBUG) devil_chromium.Initialize() # Only 1 device is supported for Android locally, this will work well with # sharding support via swarming infra. device = device_utils.DeviceUtils.HealthyDevices()[0] flags_file = FLAGS_FILE_MAP[adapter.options.product] all_flags = HOST_RESOLVER_ARGS + adapter.pass_through_binary_args logger.info('Setting flags in ' + flags_file + ' to: ' + str(all_flags)) flags = flag_changer.CustomCommandLineFlags(device, flags_file, all_flags) # WPT setup for chrome and webview requires that PATH contains adb. platform_tools_path = os.path.dirname(devil_env.config.FetchPath('adb')) os.environ['PATH'] = ':'.join([platform_tools_path] + os.environ['PATH'].split(':')) with flags: if adapter.options.product == 'android_webview': run_android_webview(device, adapter) elif adapter.options.product == 'chrome_android': run_chrome_android(device, adapter)
def _Setup(device, database_filename): """Sets up a device and returns an instance of RemoteChromeController.""" chrome_controller = prefetch_predictor_common.Setup(device) chrome_package = OPTIONS.ChromePackage() device.ForceStop(chrome_package.package) chrome_controller.ResetBrowserState() device_database_filename = prefetch_predictor_common.DatabaseDevicePath() owner = group = None # Make sure that the speculative prefetch predictor is enabled to ensure # that the disk database is re-created. with flag_changer.CustomCommandLineFlags(device, chrome_package.cmdline_file, ['--disable-fre']): # Launch Chrome for the first time to recreate the local state. launch_intent = intent.Intent(action='android.intent.action.MAIN', package=chrome_package.package, activity=chrome_package.activity) device.StartActivity(launch_intent, blocking=True) time.sleep(5) device.ForceStop(chrome_package.package) assert device.FileExists(device_database_filename) stats = device.StatPath(device_database_filename) owner = stats['st_owner'] group = stats['st_group'] # Now push the database. Needs to be done after the first launch, otherwise # the profile directory is owned by root. Also change the owner of the # database, since adb push sets it to root. database_content = open(database_filename, 'r').read() device.WriteFile(device_database_filename, database_content, force_push=True) command = 'chown %s:%s \'%s\'' % (owner, group, device_database_filename) device.RunShellCommand(command, as_root=True)
def Start(self): self.device.adb.Logcat(clear=True) if self.browser_options.startup_url: url = self.browser_options.startup_url elif self.browser_options.profile_dir: url = None else: # If we have no existing tabs start with a blank page since default # startup with the NTP can lead to race conditions with Telemetry url = 'about:blank' self.platform_backend.DismissCrashDialogIfNeeded() user_agent_dict = user_agent.GetChromeUserAgentDictFromType( self.browser_options.browser_user_agent_type) browser_startup_args = self.GetBrowserStartupArgs() command_line_name = self._backend_settings.command_line_name with flag_changer.CustomCommandLineFlags(self.device, command_line_name, browser_startup_args): # Stop existing browser, if any. This is done *after* setting the # command line flags, in case some other Android process manages to # trigger Chrome's startup before we do. self._StopBrowser() self._SetupProfile() self.device.StartActivity(intent.Intent( package=self._backend_settings.package, activity=self._backend_settings.activity, action=None, data=url, category=None, extras=user_agent_dict), blocking=True) remote_devtools_port = self._backend_settings.GetDevtoolsRemotePort( self.device) # Setting local_port=0 allows the forwarder to pick an available port. self._forwarder = self.platform_backend.forwarder_factory.Create( forwarders.PortPair(0, remote_devtools_port), reverse=True) self._port = self._forwarder.port_pair.local_port try: self._WaitForBrowserToComeUp(remote_devtools_port) except exceptions.BrowserGoneException: logging.critical('Failed to connect to browser.') if not (self.device.HasRoot() or self.device.NeedsSU()): logging.critical( 'Resolve this by either: ' '(1) Flashing to a userdebug build OR ' '(2) Manually enabling web debugging in Chrome at ' 'Settings > Developer tools > Enable USB Web debugging.' ) self.Close() raise except: self.Close() raise
def testFlagChanger_removeFlags(self): self.device.RemovePath(self.cmdline_path, force=True) self.assertFalse(self.device.PathExists(self.cmdline_path)) with flag_changer.CustomCommandLineFlags(self.device, _CMDLINE_FILE, ['--some', '--flags']): self.assertTrue(self.device.PathExists(self.cmdline_path)) self.assertFalse(self.device.PathExists(self.cmdline_path))
def Start(self): """Start an Android app and wait for it to finish launching. If the app has webviews, the app is launched with the suitable command line arguments. AppStory derivations can customize the wait-for-ready-state to wait for a more specific event if needed. """ if self._app_has_webviews: webview_startup_args = self.GetWebviewStartupArgs() command_line_name = (android_browser_backend_settings. ANDROID_WEBVIEW.command_line_name) with flag_changer.CustomCommandLineFlags(self.device, command_line_name, webview_startup_args): self._LaunchAndWaitForApplication() else: self._LaunchAndWaitForApplication() self._is_running = True
def Start(self): self.device.adb.Logcat(clear=True) if self.browser_options.startup_url: url = self.browser_options.startup_url elif self.browser_options.profile_dir: url = None else: # If we have no existing tabs start with a blank page since default # startup with the NTP can lead to race conditions with Telemetry url = 'about:blank' self.platform_backend.DismissCrashDialogIfNeeded() user_agent_dict = user_agent.GetChromeUserAgentDictFromType( self.browser_options.browser_user_agent_type) browser_startup_args = self.GetBrowserStartupArgs() command_line_name = self._backend_settings.command_line_name with flag_changer.CustomCommandLineFlags(self.device, command_line_name, browser_startup_args): # Stop existing browser, if any. This is done *after* setting the # command line flags, in case some other Android process manages to # trigger Chrome's startup before we do. self._StopBrowser() self._SetupProfile() self.device.StartActivity(intent.Intent( package=self._backend_settings.package, activity=self._backend_settings.activity, action=None, data=url, category=None, extras=user_agent_dict), blocking=True) try: self.BindDevToolsClient() except: self.Close() raise
def main(): adapter = WPTAndroidAdapter() adapter.parse_args() # Only 1 device is supported for Android locally, this will work well with # sharding support via swarming infra. device = device_utils.DeviceUtils.HealthyDevices()[0] flags_file = FLAGS_FILE_MAP[adapter.options.product] all_flags = HOST_RESOLVER_ARGS + adapter.options.binary_arg flags = flag_changer.CustomCommandLineFlags(device, flags_file, all_flags) # WPT setup for chrome and webview requires that PATH contains adb. os.environ['PATH'] = ':'.join([PLATFORM_TOOLS] + os.environ['PATH'].split(':')) with flags: if adapter.options.product == 'android_webview': run_android_webview(device, adapter) elif adapter.options.product == 'chrome_android': run_chrome_android(device, adapter)
def RunChrome(device, cold, chrome_args, package_info): """Runs Chrome on the device. Args: device: (DeviceUtils) device to run the tests on. cold: (bool) Whether caches should be dropped. chrome_args: ([str]) List of arguments to pass to Chrome. package_info: (PackageInfo) Chrome package info. """ if not device.HasRoot(): device.EnableRoot() cmdline_file = package_info.cmdline_file package = package_info.package with flag_changer.CustomCommandLineFlags(device, cmdline_file, chrome_args): device.ForceStop(package) if cold: chrome_setup.ResetChromeLocalState(device, package) cache_control.CacheControl(device).DropRamCaches() start_intent = intent.Intent(package=package, data='about:blank', activity=package_info.activity) try: device.StartActivity(start_intent, blocking=True) print('\n\n' ' +---------------------------------------------+\n' ' | Chrome launched, press Ctrl-C to interrupt. |\n' ' +---------------------------------------------+') while True: time.sleep(1) except KeyboardInterrupt: pass finally: device.ForceStop(package)
def Start(self): self.device.adb.Logcat(clear=True) if self.browser_options.startup_url: url = self.browser_options.startup_url elif self.browser_options.profile_dir: url = None else: # If we have no existing tabs start with a blank page since default # startup with the NTP can lead to race conditions with Telemetry url = 'about:blank' self.platform_backend.DismissCrashDialogIfNeeded() user_agent_dict = user_agent.GetChromeUserAgentDictFromType( self.browser_options.browser_user_agent_type) browser_startup_args = self.GetBrowserStartupArgs() command_line_name = self._backend_settings.command_line_name with flag_changer.CustomCommandLineFlags(self.device, command_line_name, browser_startup_args): # Stop existing browser, if any. This is done *after* setting the # command line flags, in case some other Android process manages to # trigger Chrome's startup before we do. self._StopBrowser() if self.device.HasRoot() or self.device.NeedsSU(): if self.browser_options.profile_dir: self.platform_backend.PushProfile( self._backend_settings.package, self.browser_options.profile_dir) elif not self.browser_options.dont_override_profile: self.platform_backend.RemoveProfile( self._backend_settings.package, self._backend_settings.profile_ignore_list) self.device.StartActivity(intent.Intent( package=self._backend_settings.package, activity=self._backend_settings.activity, action=None, data=url, category=None, extras=user_agent_dict), blocking=True) # TODO(crbug.com/404771): Move port forwarding to network_controller. remote_devtools_port = self._backend_settings.GetDevtoolsRemotePort( self.device) try: # Release reserved port right before forwarding host to device. self._port_keeper.Release() assert self._port == self._port_keeper.port, ( 'Android browser backend must use reserved port by _port_keeper' ) self.platform_backend.ForwardHostToDevice( self._port, remote_devtools_port) except Exception: logging.exception('Failed to forward %s to %s.', str(self._port), str(remote_devtools_port)) logging.warning('Currently forwarding:') try: for line in self.device.adb.ForwardList().splitlines(): logging.warning(' %s', line) except Exception: # pylint: disable=broad-except logging.warning('Exception raised while listing forwarded ' 'connections.') logging.warning('Host tcp ports in use:') try: for line in subprocess.check_output(['netstat', '-t']).splitlines(): logging.warning(' %s', line) except Exception: # pylint: disable=broad-except logging.warning( 'Exception raised while listing tcp ports.') logging.warning('Device unix domain sockets in use:') try: for line in self.device.ReadFile( '/proc/net/unix', as_root=True, force_pull=True).splitlines(): logging.warning(' %s', line) except Exception: # pylint: disable=broad-except logging.warning( 'Exception raised while listing unix domain sockets.') raise try: self._WaitForBrowserToComeUp(remote_devtools_port) except exceptions.BrowserGoneException: logging.critical('Failed to connect to browser.') if not (self.device.HasRoot() or self.device.NeedsSU()): logging.critical( 'Resolve this by either: ' '(1) Flashing to a userdebug build OR ' '(2) Manually enabling web debugging in Chrome at ' 'Settings > Developer tools > Enable USB Web debugging.' ) self.Close() raise except: self.Close() raise
def RunOnce(device, url, speculated_url, parallel_url, warmup, skip_launcher_activity, speculation_mode, delay_to_may_launch_url, delay_to_launch_url, cold, pinning_benchmark, pin_filename, pin_offset, pin_length, extra_brief_memory_mb, chrome_args, reset_chrome_state): """Runs a test on a device once. Args: device: (DeviceUtils) device to run the tests on. url: (str) URL to load. End of the redirect chain when using a parallel request. speculated_url: (str) Speculated URL. parallel_url: ([str]) URL to load in parallel, typically the start of the redirect chain. warmup: (bool) Whether to call warmup. skip_launcher_activity: (bool) Whether to skip the launcher activity. speculation_mode: (str) Speculation Mode. delay_to_may_launch_url: (int) Delay to mayLaunchUrl() in ms. delay_to_launch_url: (int) Delay to launchUrl() in ms. cold: (bool) Whether the page cache should be dropped. pinning_benchmark: (bool) Whether to perform the 'pinning benchmark'. pin_filename: (str) The file to pin on the device. pin_offset: (int) Start offset of the range to pin. pin_length: (int) Number of bytes to pin. extra_brief_memory_mb: (int) Number of MiB to consume before starting Chrome. Applies only to the 'pinning benchmark' scenario. chrome_args: ([str]) List of arguments to pass to Chrome. reset_chrome_state: (bool) Whether to reset the Chrome local state before the run. Returns: The output line (str), like this (one line only): <warmup>,<prerender_mode>,<delay_to_may_launch_url>,<delay_to_launch>, <intent_sent_ms>,<page_load_started_ms>,<page_load_finished_ms>, <first_contentful_paint> or None on error. """ if not device.HasRoot(): device.EnableRoot() timeout_s = 64 logcat_timeout = int(timeout_s + delay_to_may_launch_url / 1000. + delay_to_launch_url / 1000.) with flag_changer.CustomCommandLineFlags(device, _COMMAND_LINE_FILE, chrome_args): launch_intent = intent.Intent( action='android.intent.action.MAIN', package=_TEST_APP_PACKAGE_NAME, activity='org.chromium.customtabs.test.MainActivity', extras={ 'url': str(url), 'speculated_url': str(speculated_url), 'parallel_url': str(parallel_url), 'warmup': warmup, 'skip_launcher_activity': skip_launcher_activity, 'speculation_mode': str(speculation_mode), 'delay_to_may_launch_url': delay_to_may_launch_url, 'delay_to_launch_url': delay_to_launch_url, 'pinning_benchmark': pinning_benchmark, 'pin_filename': str(pin_filename), 'pin_offset': pin_offset, 'pin_length': pin_length, 'extra_brief_memory_mb': extra_brief_memory_mb, 'timeout': timeout_s }) result_line_re = re.compile(r'CUSTOMTABSBENCHCSV.*: (.*)') logcat_monitor = device.GetLogcatMonitor(clear=True) logcat_monitor.Start() device.ForceStop(_CHROME_PACKAGE) device.ForceStop(_TEST_APP_PACKAGE_NAME) if reset_chrome_state: chrome_setup.ResetChromeLocalState(device, _CHROME_PACKAGE) if cold: cache_control.CacheControl(device).DropRamCaches() device.StartActivity(launch_intent, blocking=True) match = None try: match = logcat_monitor.WaitFor(result_line_re, timeout=logcat_timeout) except device_errors.CommandTimeoutError as _: logging.warning('Timeout waiting for the result line') logcat_monitor.Stop() logcat_monitor.Close() return match.group(1) if match is not None else None
def main(): parser = argparse.ArgumentParser(description=""" Configures WebView to start recording a netlog. This script chooses a suitable netlog filename for the application, and will pull the netlog off the device when the user terminates the script (with ctrl-C). For a more complete usage guide, open your web browser to: https://chromium.googlesource.com/chromium/src/+/HEAD/android_webview/docs/net-debugging.md """) parser.add_argument( '--package', required=True, type=str, help='Package name of the application you intend to use.') parser.add_argument('--force', default=False, action='store_true', help='Suppress user checks.') script_common.AddEnvironmentArguments(parser) script_common.AddDeviceArguments(parser) logging_common.AddLoggingArguments(parser) args = parser.parse_args() logging_common.InitializeLogging(args) devil_chromium.Initialize(adb_path=args.adb_path) # Only use a single device, for the sake of simplicity (of implementation and # user experience). devices = device_utils.DeviceUtils.HealthyDevices(device_arg=args.devices) device = devices[0] if len(devices) > 1: raise device_errors.MultipleDevicesError(devices) package_name = args.package device_netlog_file_name = 'netlog.json' device_netlog_path = os.path.join( device.GetApplicationDataDirectory(package_name), 'app_webview', device_netlog_file_name) CheckAppNotRunning(device, package_name, args.force) # Append to the existing flags, to allow users to experiment with other # features/flags enabled. The CustomCommandLineFlags will restore the original # flag state after the user presses 'ctrl-C'. changer = flag_changer.FlagChanger(device, WEBVIEW_COMMAND_LINE) new_flags = changer.GetCurrentFlags() new_flags.append('--log-net-log={}'.format(device_netlog_path)) logging.info('Running with flags %r', new_flags) with flag_changer.CustomCommandLineFlags(device, WEBVIEW_COMMAND_LINE, new_flags): print( 'Netlog will start recording as soon as app starts up. Press ctrl-C ' 'to stop recording.') _WaitUntilCtrlC() host_netlog_path = 'netlog.json' print('Pulling netlog to "%s"' % host_netlog_path) # The netlog file will be under the app's uid, which the default shell doesn't # have permission to read (but root does). Prefer this to EnableRoot(), which # restarts the adb daemon. device.PullFile(device_netlog_path, host_netlog_path, as_root=True) device.RemovePath(device_netlog_path, as_root=True)
def Open(self): """Overridden connection creation.""" if self._wpr_attributes: assert self._wpr_attributes.chrome_env_override == {}, \ 'Remote controller doesn\'t support chrome environment variables.' package_info = OPTIONS.ChromePackage() self._device.ForceStop(package_info.package) with flag_changer.CustomCommandLineFlags(self._device, package_info.cmdline_file, self._GetChromeArguments()): self._DismissCrashDialogIfNeeded() start_intent = intent.Intent(package=package_info.package, activity=package_info.activity, data='about:blank') self._device.adb.Logcat(clear=True, dump=True) self._device.StartActivity(start_intent, blocking=True) try: for attempt_id in xrange(self.DEVTOOLS_CONNECTION_ATTEMPTS): logging.info('Devtools connection attempt %d' % attempt_id) # Adb forwarding does not provide a way to print the port number if # it is allocated atomically by the OS by passing port=0, but we need # dynamically allocated listening port here to handle parallel run on # different devices. host_side_port = _AllocateTcpListeningPort() logging.info( 'Allocated host sided listening port for devtools ' 'connection: %d', host_side_port) try: with device_setup.ForwardPort( self._device, 'tcp:%d' % host_side_port, 'localabstract:chrome_devtools_remote'): try: connection = devtools_monitor.DevToolsConnection( OPTIONS.devtools_hostname, host_side_port) self._StartConnection(connection) except socket.error as e: if e.errno != errno.ECONNRESET: raise time.sleep( self. DEVTOOLS_CONNECTION_ATTEMPT_INTERVAL_SECONDS ) continue yield connection if self._slow_death: self._device.adb.Shell( 'am start com.google.android.launcher') time.sleep(self.TIME_TO_IDLE_SECONDS) break except device_errors.AdbCommandFailedError as error: _KNOWN_ADB_FORWARDER_FAILURES = [ 'cannot bind to socket: Address already in use', 'cannot rebind existing socket: Resource temporarily unavailable' ] for message in _KNOWN_ADB_FORWARDER_FAILURES: if message in error.message: break else: raise continue else: raise ChromeControllerInternalError( 'Failed to connect to Chrome devtools after {} ' 'attempts.'.format(self.DEVTOOLS_CONNECTION_ATTEMPTS)) except ChromeControllerError._PASSTHROUGH_WHITE_LIST: raise except Exception: logcat = ''.join( [l + '\n' for l in self._device.adb.Logcat(dump=True)]) raise ChromeControllerError(log=logcat) finally: self._device.ForceStop(package_info.package) self._DismissCrashDialogIfNeeded()
def RunOnce(device, url, warmup, speculation_mode, delay_to_may_launch_url, delay_to_launch_url, cold, chrome_args, reset_chrome_state): """Runs a test on a device once. Args: device: (DeviceUtils) device to run the tests on. url: (str) URL to load. warmup: (bool) Whether to call warmup. speculation_mode: (str) Speculation Mode. delay_to_may_launch_url: (int) Delay to mayLaunchUrl() in ms. delay_to_launch_url: (int) Delay to launchUrl() in ms. cold: (bool) Whether the page cache should be dropped. chrome_args: ([str]) List of arguments to pass to Chrome. reset_chrome_state: (bool) Whether to reset the Chrome local state before the run. Returns: The output line (str), like this (one line only): <warmup>,<prerender_mode>,<delay_to_may_launch_url>,<delay_to_launch>, <intent_sent_ms>,<page_load_started_ms>,<page_load_finished_ms>, <first_contentful_paint> or None on error. """ if not device.HasRoot(): device.EnableRoot() timeout_s = 20 logcat_timeout = int(timeout_s + delay_to_may_launch_url / 1000. + delay_to_launch_url / 1000.) + 3 with flag_changer.CustomCommandLineFlags(device, _COMMAND_LINE_FILE, chrome_args): launch_intent = intent.Intent( action='android.intent.action.MAIN', package=_TEST_APP_PACKAGE_NAME, activity='org.chromium.customtabs.test.MainActivity', extras={ 'url': str(url), 'warmup': warmup, 'speculation_mode': str(speculation_mode), 'delay_to_may_launch_url': delay_to_may_launch_url, 'delay_to_launch_url': delay_to_launch_url, 'timeout': timeout_s }) result_line_re = re.compile(r'CUSTOMTABSBENCH.*: (.*)') logcat_monitor = device.GetLogcatMonitor(clear=True) logcat_monitor.Start() device.ForceStop(_CHROME_PACKAGE) device.ForceStop(_TEST_APP_PACKAGE_NAME) if reset_chrome_state: chrome_setup.ResetChromeLocalState(device, _CHROME_PACKAGE) if cold: cache_control.CacheControl(device).DropRamCaches() device.StartActivity(launch_intent, blocking=True) match = None try: match = logcat_monitor.WaitFor(result_line_re, timeout=logcat_timeout) except device_errors.CommandTimeoutError as _: logging.warning('Timeout waiting for the result line') logcat_monitor.Stop() logcat_monitor.Close() return match.group(1) if match is not None else None