def SetUpEnvironment(self, browser_options): super(PossibleAndroidBrowser, self).SetUpEnvironment(browser_options) self._platform_backend.DismissCrashDialogIfNeeded() device = self._platform_backend.device startup_args = self.GetBrowserStartupArgs(self._browser_options) device.adb.Logcat(clear=True) # use legacy commandline path if in compatibility mode self._flag_changer = flag_changer.FlagChanger( device, self._backend_settings.command_line_name, use_legacy_path= compat_mode_options.LEGACY_COMMAND_LINE_PATH in browser_options.compatibility_mode) self._flag_changer.ReplaceFlags(startup_args, log_flags=False) formatted_args = format_for_logging.ShellFormat( startup_args, trim=browser_options.trim_logs) logging.info('Flags set on device were %s', formatted_args) # Stop any existing browser found already running on the device. 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._platform_backend.StopApplication(self._backend_settings.package) self._SetupProfile() # Remove any old crash dumps self._platform_backend.device.RemovePath( self._platform_backend.GetDumpLocation(self._backend_settings.package), recursive=True, force=True)
def launch(device): # --persistent is required to have Settings.Global.DEBUG_APP be set, which # we currently use to allow reading of flags. https://crbug.com/784947 if not nokill: cmd = ['am', 'set-debug-app', '--persistent', debug_process_name] if wait_for_java_debugger: cmd[-1:-1] = ['-w'] # Ignore error since it will fail if apk is not debuggable. device.RunShellCommand(cmd, check_return=False) # The flags are first updated with input args. if command_line_flags_file: changer = flag_changer.FlagChanger(device, command_line_flags_file) flags = [] if argv: flags = shlex.split(argv) try: changer.ReplaceFlags(flags) except device_errors.AdbShellCommandFailedError: logging.exception('Failed to set flags') if url is None: # Simulate app icon click if no url is present. cmd = ['monkey', '-p', package_name, '-c', 'android.intent.category.LAUNCHER', '1'] device.RunShellCommand(cmd, check_return=True) else: launch_intent = intent.Intent(action='android.intent.action.VIEW', activity=view_activity, data=url, package=package_name) device.StartActivity(launch_intent)
def testFlagChanger_restoreFlags(self): if not self.device.HasRoot(): self.skipTest('Test needs a rooted device') # Write some custom chrome command line flags. self.device.WriteFile(self.cmdline_path, 'chrome --some --old --flags') # Write some more flags on a command line file in the legacy location. self.device.WriteFile(self.cmdline_path_legacy, 'some --stray --flags', as_root=True) self.assertTrue(self.device.PathExists(self.cmdline_path_legacy)) changer = flag_changer.FlagChanger(self.device, _CMDLINE_FILE) # Legacy command line file is removed, ensuring Chrome picks up the # right file. self.assertFalse(self.device.PathExists(self.cmdline_path_legacy)) # Write some new files, and check they are set. new_flags = ['--my', '--new', '--flags=with special value'] self.assertItemsEqual(changer.ReplaceFlags(new_flags), new_flags) # Restore and go back to the old flags. self.assertItemsEqual(changer.Restore(), ['--some', '--old', '--flags'])
def launch(device): # Set debug app in order to enable reading command line flags on user # builds. cmd = ['am', 'set-debug-app', debug_process_name] if wait_for_java_debugger: cmd[-1:-1] = ['-w'] # Ignore error since it will fail if apk is not debuggable. device.RunShellCommand(cmd, check_return=False) # The flags are first updated with input args. if command_line_flags_file: changer = flag_changer.FlagChanger(device, command_line_flags_file) flags = [] if argv: flags = shlex.split(argv) changer.ReplaceFlags(flags) # Then launch the apk. if url is None: # Simulate app icon click if no url is present. cmd = [ 'monkey', '-p', package_name, '-c', 'android.intent.category.LAUNCHER', '1' ] device.RunShellCommand(cmd, check_return=True) else: launch_intent = intent.Intent(action='android.intent.action.VIEW', activity=view_activity, data=url, package=package_name) device.StartActivity(launch_intent)
def _StartForwarder(self): """Sets up forwarding of device ports to the host, and configures chrome to use those ports. """ if not self._wpr_server: logging.warning('No host WPR server to forward to.') return print 'Starting device forwarder...' forwarder.Forwarder.Map([(0, self._host_http_port), (0, self._host_https_port)], self._device) device_http = forwarder.Forwarder.DevicePortForHostPort( self._host_http_port) device_https = forwarder.Forwarder.DevicePortForHostPort( self._host_https_port) self._flag_changer = flag_changer.FlagChanger(self._device, self._cmdline_file) self._flag_changer.AddFlags([ '--host-resolver-rules=MAP * 127.0.0.1,EXCLUDE localhost', '--testing-fixed-http-port=%s' % device_http, '--testing-fixed-https-port=%s' % device_https, # Allows to selectively avoid certificate errors in Chrome. Unlike # --ignore-certificate-errors this allows exercising the HTTP disk cache # and avoids re-establishing socket connections. The value is taken from # the WprGo documentation at: # https://github.com/catapult-project/catapult/blob/master/web_page_replay_go/README.md '--ignore-certificate-errors-spki-list=' + 'PhrPvGIaAMmd29hj8BCZOq096yj7uMpRNHpn5PDxI6I=', # The flag --ignore-certificate-errors-spki-list (above) requires # specifying the profile directory, otherwise it is silently ignored. '--user-data-dir=/data/data/{}'.format(self._package) ])
def update_flags(device): changer = flag_changer.FlagChanger(device, args.name) if remote_args is not None: flags = changer.ReplaceFlags(remote_args) else: flags = changer.GetCurrentFlags() return (device, device.build_description, flags)
def testFlagChanger_removeLegacyCmdLine(self): self.device.WriteFile(self.cmdline_path_legacy, 'chrome --old --stuff') self.assertTrue(self.device.PathExists(self.cmdline_path_legacy)) changer = flag_changer.FlagChanger(self.device, 'chrome-command-line') self.assertEquals( changer._cmdline_path, # pylint: disable=protected-access self.cmdline_path) self.assertFalse(self.device.PathExists(self.cmdline_path_legacy))
def _DisplayArgs(devices, device_args_file): print 'Current flags (in {%s}):' % device_args_file for d in devices: changer = flag_changer.FlagChanger(d, device_args_file) flags = changer.GetCurrentFlags() if flags: quoted_flags = ' '.join(pipes.quote(f) for f in flags) else: quoted_flags = '( empty )' print ' %s (%s): %s' % (d, d.build_description, quoted_flags)
def _DisplayArgs(devices, device_args_file): print 'Existing flags per-device (via /data/local/tmp/%s):' % device_args_file for d in devices: changer = flag_changer.FlagChanger(d, device_args_file) flags = changer.GetCurrentFlags() if flags: quoted_flags = ' '.join(pipes.quote(f) for f in flags) else: quoted_flags = '( empty )' print ' %s (%s): %s' % (d, d.build_description, quoted_flags)
def __init__(self, device, package_info, cold, url): self._device = device self._package_info = package_info self._cold = cold self._logcat_monitor = self._device.GetLogcatMonitor() self._url = url self._trace_file = None self._trace_finish_re = re.compile( r' Completed startup tracing to (.*)') self._flag_changer = flag_changer.FlagChanger( self._device, self._package_info.cmdline_file)
def _CreateFlagChangerIfNeeded(self, device): if str(device) not in self._flag_changers: cmdline_file = 'test-cmdline-file' if self._test_instance.use_apk_under_test_flags_file: if self._test_instance.package_info: cmdline_file = self._test_instance.package_info.cmdline_file else: raise Exception('No PackageInfo found but' '--use-apk-under-test-flags-file is specified.') self._flag_changers[str(device)] = flag_changer.FlagChanger( device, cmdline_file)
class ChromeStartupTracingAgent(tracing_agents.TracingAgent): def __init__(self, presentation.device, package_info, cold, url): tracing_agents.TracingAgent.__init__(self) self._device = presentation.device self._package_info = package_info self._cold = cold self._logcat_monitor = self._device.GetLogcatMonitor() self._url = url self._trace_file = None self._trace_finish_re = re.compile(r' Completed startup tracing to (.*)') self._flag_changer = flag_changer.FlagChanger( self._device, self._package_info.cmdline_file)
def _CreateFlagChangerIfNeeded(self, device): if str(device) not in self._flag_changers: cmdline_file = 'test-cmdline-file' if self._test_instance.use_apk_under_test_flags_file: if self._test_instance.package_info: cmdline_file = self._test_instance.package_info.cmdline_file else: logging.warning( 'No PackageInfo found, falling back to using flag file %s', cmdline_file) self._flag_changers[str(device)] = flag_changer.FlagChanger( device, cmdline_file)
def __init__(self, device, package_info, webapk_package, cold, url, trace_time=None): tracing_agents.TracingAgent.__init__(self) self._device = device self._package_info = package_info self._webapk_package = webapk_package self._cold = cold self._logcat_monitor = self._device.GetLogcatMonitor() self._url = url self._trace_time = trace_time self._trace_file = None self._trace_finish_re = re.compile(r' Completed startup tracing to (.*)') self._flag_changer = flag_changer.FlagChanger( self._device, self._package_info.cmdline_file)
def SetUpEnvironment(self, browser_options): super(PossibleAndroidBrowser, self).SetUpEnvironment(browser_options) self._platform_backend.DismissCrashDialogIfNeeded() device = self._platform_backend.device startup_args = self.GetBrowserStartupArgs(self._browser_options) device.adb.Logcat(clear=True) self._flag_changer = flag_changer.FlagChanger( device, self._backend_settings.command_line_name) self._flag_changer.ReplaceFlags(startup_args) # Stop any existing browser found already running on the device. 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._platform_backend.StopApplication(self._backend_settings.package) self._SetupProfile()
def launch(device): # The flags are first updated with input args. changer = flag_changer.FlagChanger(device, device_args_file) flags = [] if input_args: flags = shlex.split(input_args) changer.ReplaceFlags(flags) # Then launch the apk. if url is None: # Simulate app icon click if no url is present. cmd = ['monkey', '-p', apk_package, '-c', 'android.intent.category.LAUNCHER', '1'] device.RunShellCommand(cmd, check_return=True) else: launch_intent = intent.Intent( action='android.intent.action.VIEW', package=apk_package, data=url) device.StartActivity(launch_intent)
def update_flags(device): if device.IsUserBuild() and is_webview: raise device_errors.CommandFailedError( 'WebView only respects flags on a userdebug or eng device, yours ' 'is a user build.', device) elif device.IsUserBuild(): logging.warning( 'Your device (%s) is a user build; Chrome may or may not pick up ' 'your commandline flags. Check your ' '"command_line_on_non_rooted_enabled" preference, or switch ' 'devices.', device) changer = flag_changer.FlagChanger(device, args.name) if remote_args is not None: flags = changer.ReplaceFlags(remote_args) else: flags = changer.GetCurrentFlags() return (device, device.build_description, flags)
def FlagReplacer(device, command_line_path, new_flags): """Replaces chrome flags in a context, restores them afterwards. Args: device: Device to target, from DeviceUtils. Can be None, in which case this context manager is a no-op. command_line_path: Full path to the command-line file. new_flags: Flags to replace. """ # If we're logging requests from a local desktop chrome instance there is no # device. if not device: yield return changer = flag_changer.FlagChanger(device, command_line_path) changer.ReplaceFlags(new_flags) try: yield finally: changer.Restore()
def _StartForwarder(self): """Sets up forwarding of device ports to the host, and configures chrome to use those ports. """ if not self._wpr_server: logging.warning('No host WPR server to forward to.') return print 'Starting device forwarder...' forwarder.Forwarder.Map([(0, self._host_http_port), (0, self._host_https_port)], self._device) device_http = forwarder.Forwarder.DevicePortForHostPort( self._host_http_port) device_https = forwarder.Forwarder.DevicePortForHostPort( self._host_https_port) self._flag_changer = flag_changer.FlagChanger(self._device, self._cmdline_file) self._flag_changer.AddFlags([ '--host-resolver-rules="MAP * 127.0.0.1,EXCLUDE localhost"', '--testing-fixed-http-port=%s' % device_http, '--testing-fixed-https-port=%s' % device_https ])
def __init__(self, test_options, device, shard_index, test_pkg, additional_flags=None): """Create a new TestRunner. Args: test_options: An InstrumentationOptions object. device: Attached android device. shard_index: Shard index. test_pkg: A TestPackage object. additional_flags: A list of additional flags to add to the command line. """ super(TestRunner, self).__init__(device, test_options.tool) self._lighttp_port = constants.LIGHTTPD_RANDOM_PORT_FIRST + shard_index self._logcat_monitor = None self.coverage_device_file = None self.coverage_dir = test_options.coverage_dir self.coverage_host_file = None self.options = test_options package_info_candidates = [ a for a in constants.PACKAGE_INFO.itervalues() if a.test_package == test_pkg.GetPackageName() ] assert len(package_info_candidates) < 2, ( 'Multiple packages have the same test package') self.package_info = (package_info_candidates[0] if package_info_candidates else None) self.test_pkg = test_pkg # Use the correct command line file for the package under test. if self.package_info and self.package_info.cmdline_file: self.flags = flag_changer.FlagChanger( self.device, self.package_info.cmdline_file) if additional_flags: self.flags.AddFlags(additional_flags) else: self.flags = None
def testFlagChanger(self): if not self.device.HasRoot(): self.skipTest('Test needs a rooted device') # Write some custom chrome command line flags. self.device.WriteFile(self.cmdline_path, 'chrome --custom --flags') # Write some more flags on a command line file in the legacy location. self.device.WriteFile(self.cmdline_path_legacy, 'some --stray --flags', as_root=True) self.assertTrue(self.device.PathExists(self.cmdline_path_legacy)) changer = flag_changer.FlagChanger(self.device, _CMDLINE_FILE) # Legacy command line file is removed, ensuring Chrome picks up the # right file. self.assertFalse(self.device.PathExists(self.cmdline_path_legacy)) changer.ReplaceFlags(['--my', '--new', '--flags']) # TODO(perezju): assert that new flags are now set. changer.Restore()
def _CreateFlagChangerIfNeeded(self, device): if str(device) not in self._flag_changers: self._flag_changers[str(device)] = flag_changer.FlagChanger( device, "test-cmdline-file")
def _CreateFlagChangerIfNeeded(self, device): if not str(device) in self._flag_changers: self._flag_changers[str(device)] = flag_changer.FlagChanger( device, self._test_instance.package_info.cmdline_file)
def flags_helper(d): changer = flag_changer.FlagChanger(d, command_line_flags_file) return changer.GetCurrentFlags()
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 update(device): changer = flag_changer.FlagChanger(device, command_line_flags_file) changer.ReplaceFlags(flags)
def run_test(options, crash_dir, symbols_dir, platform, additional_arguments=[]): global failure print '# Run content_shell and make it crash.' if platform == 'android': device = GetDevice() failure = None clear_android_dumps(options, device) apk_path = os.path.join(options.build_dir, 'apks', 'ContentShell.apk') apk = apk_helper.ApkHelper(apk_path) view_activity = apk.GetViewActivityName() package_name = apk.GetPackageName() device.RunShellCommand( ['am', 'set-debug-app', '--persistent', package_name]) changer = flag_changer.FlagChanger(device, 'content-shell-command-line') changer.ReplaceFlags([ '--enable-crash-reporter', '--crash-dumps-dir=%s' % ANDROID_CRASH_DIR ]) launch_intent = intent.Intent(action='android.intent.action.VIEW', activity=view_activity, data='chrome://crash', package=package_name) device.StartActivity(launch_intent) else: cmd = [ options.binary, '--run-web-tests', 'chrome://crash', '--enable-crash-reporter', '--crash-dumps-dir=%s' % crash_dir ] cmd += additional_arguments if options.verbose: print ' '.join(cmd) failure = 'Failed to run content_shell.' if options.verbose: subprocess.check_call(cmd) else: # On Windows, using os.devnull can cause check_call to never return, # so use a temporary file for the output. with tempfile.TemporaryFile() as tmpfile: subprocess.check_call(cmd, stdout=tmpfile, stderr=tmpfile) print '# Retrieve crash dump.' if platform == 'android': dmp_file = get_android_dump(crash_dir) else: dmp_dir = crash_dir # TODO(crbug.com/782923): This test should not reach directly into the # Crashpad database, but instead should use crashpad_database_util. if platform == 'darwin': dmp_dir = os.path.join(dmp_dir, 'pending') elif platform == 'win32': dmp_dir = os.path.join(dmp_dir, 'reports') dmp_files = glob.glob(os.path.join(dmp_dir, '*.dmp')) failure = 'Expected 1 crash dump, found %d.' % len(dmp_files) if len(dmp_files) != 1: raise Exception(failure) dmp_file = dmp_files[0] if platform not in ('darwin', 'win32', 'android'): minidump = os.path.join(crash_dir, 'minidump') dmp_to_minidump = os.path.join(BREAKPAD_TOOLS_DIR, 'dmp2minidump.py') cmd = [dmp_to_minidump, dmp_file, minidump] if options.verbose: print ' '.join(cmd) failure = 'Failed to run dmp_to_minidump.' subprocess.check_call(cmd) else: minidump = dmp_file print '# Symbolize crash dump.' if platform == 'win32': cdb_exe = os.path.join(options.build_dir, 'cdb', 'cdb.exe') cmd = [ cdb_exe, '-y', options.build_dir, '-c', '.lines;.excr;k30;q', '-z', dmp_file ] if options.verbose: print ' '.join(cmd) failure = 'Failed to run cdb.exe.' proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stack = proc.communicate()[0] else: minidump_stackwalk = os.path.join(options.build_dir, 'minidump_stackwalk') cmd = [minidump_stackwalk, minidump, symbols_dir] if options.verbose: print ' '.join(cmd) failure = 'Failed to run minidump_stackwalk.' proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stack = proc.communicate()[0] # Check whether the stack contains a CrashIntentionally symbol. found_symbol = 'CrashIntentionally' in stack os.remove(dmp_file) if options.no_symbols: if found_symbol: if options.verbose: print stack failure = 'Found unexpected reference to CrashIntentionally in stack' raise Exception(failure) else: if not found_symbol: if options.verbose: print stack failure = 'Could not find reference to CrashIntentionally in stack.' raise Exception(failure)
def __init__(self, device, backend_settings, startup_args): cmdline_file = backend_settings.GetCommandLineFile( device.IsUserBuild()) self._flag_changer = flag_changer.FlagChanger(device, cmdline_file) self._args = [_QuoteIfNeeded(arg) for arg in startup_args]
def main(argv): option_parser = optparse.OptionParser() option_parser.add_option('-l', '--low', help='Simulate Activity#onLowMemory()', action='store_true') option_parser.add_option( '-t', '--trim', help=('Simulate Activity#onTrimMemory(...) with ' + ', '.join(ACTION_TRIM.keys())), type='string') option_parser.add_option('-b', '--browser', default=DEFAULT_BROWSER, help=('Which browser to use. One of ' + ', '.join(constants.PACKAGE_INFO.keys()) + ' [default: %default]'), type='string') (options, args) = option_parser.parse_args(argv) if len(args) > 1: print 'Unknown argument: ', args[1:] option_parser.print_help() sys.exit(1) if options.low and options.trim: option_parser.error('options --low and --trim are mutually exclusive') if not options.low and not options.trim: option_parser.print_help() sys.exit(1) action = None if options.low: action = ACTION_LOW elif options.trim in ACTION_TRIM.keys(): action = ACTION_TRIM[options.trim] if action is None: option_parser.print_help() sys.exit(1) if not options.browser in constants.PACKAGE_INFO.keys(): option_parser.error('Unknown browser option ' + options.browser) devil_chromium.Initialize() package_info = constants.PACKAGE_INFO[options.browser] package = package_info.package activity = package_info.activity devices = device_utils.DeviceUtils.HealthyDevices() if not devices: raise device_errors.NoDevicesError() elif len(devices) > 1: logging.warning('Multiple devices attached. Using %s.', str(devices[0])) device = devices[0] try: device.EnableRoot() except device_errors.CommandFailedError as e: # Try to change the flags and start the activity anyway. # TODO(jbudorick) Handle this exception appropriately after interface # conversions are finished. logging.error(str(e)) flags = flag_changer.FlagChanger(device, package_info.cmdline_file) flags.AddFlags([ENABLE_TEST_INTENTS_FLAG]) device.StartActivity( intent.Intent(package=package, activity=activity, action=action))
def _SetChromeFlags(self, package_info): print 'Setting Chrome flags...' changer = flag_changer.FlagChanger(self._device, package_info.cmdline_file) changer.AddFlags(['--no-sandbox', '--disable-fre']) return changer