Bug 1570756 [wpt PR 18239] - [tools] Various Chrome for Android improvements, a=testonly

Automatic update from web-platform-tests
[wpt] Support detecting Chrome for Android version

Consequently, we can now install the correct ChromeDriver version.

* The change also includes some drive-by whitespace fixes in the file.

--
Allow custom package names for Chrome Android

1. [wptrunner] chrome_android now honours (and requires) the
   --package-name flag instead of hardcoding the package name.
2. [wpt] chrome_android now chooses the correct official package name
   depending on the channel.
3. [wpt] chrome_android correctly sets browser_version.
4. [wpt] drive-by change: update the logic for adding --binary-arg &
   --webdriver-arg in chrome & chrome_android (now they both add
   --enable-experimental... to binary_arg and --disable-build-check to
   webdriver_arg when running dev or canary channel).

--

wpt-commits: cc864ad313dafdaefa90b483818ed5a603803a41, 2a4e78b2c66b7a6589c50c44dda31e5cf215421f
wpt-pr: 18239
This commit is contained in:
Robert Ma 2019-08-06 17:27:19 +00:00 committed by moz-wptsync-bot
parent 9ad90874ea
commit ef1dbe597e
5 changed files with 78 additions and 38 deletions

View File

@ -7,17 +7,16 @@ connect to the device. Run `adb devices` to verify.
Currently, Android support is a prototype with some known issues: Currently, Android support is a prototype with some known issues:
* We install ChromeDriver corresponding to the Chrome version on your *host*, * If you have previously run `./wpt run` against Chrome, you might need to
so you will need a special flag to bypass ChromeDriver's version check if the remove `_venv/bin/chromedriver` so that we can install the correct
test device runs a different version of Chrome from your host. ChromeDriver corresponding to your Chrome for Android version.
* The package name is hard coded. If you are testing a custom build, you will
need to search and replace `com.android.chrome` in `tools/`.
* We do not support reftests at the moment. * We do not support reftests at the moment.
* You will need to manually kill Chrome (all channels) before running tests.
Note: rooting the device or installing a root CA is no longer required. Note: rooting the device or installing a root CA is no longer required.
Example: Example (assuming you have Chrome Canary installed on your phone):
```bash ```bash
./wpt run --webdriver-arg=--disable-build-check --test-type=testharness chrome_android TESTS ./wpt run --test-type=testharness --channel=canary chrome_android TESTS
``` ```

View File

@ -36,6 +36,7 @@ def handle_remove_readonly(func, path, exc):
else: else:
raise raise
class Browser(object): class Browser(object):
__metaclass__ = ABCMeta __metaclass__ = ABCMeta
@ -534,28 +535,32 @@ class Chrome(Browser):
self.chromium_platform_string(), revision, self.platform_string()) self.chromium_platform_string(), revision, self.platform_string())
return url return url
def _latest_chromedriver_url(self, browser_binary=None): def _latest_chromedriver_url(self, chrome_version):
chrome_version = self.version(browser_binary)
assert chrome_version, "Cannot detect the version of Chrome"
# Remove channel suffixes (e.g. " dev"). # Remove channel suffixes (e.g. " dev").
chrome_version = chrome_version.split(' ')[0] chrome_version = chrome_version.split(' ')[0]
return (self._official_chromedriver_url(chrome_version) or return (self._official_chromedriver_url(chrome_version) or
self._chromium_chromedriver_url(chrome_version)) self._chromium_chromedriver_url(chrome_version))
def install_webdriver(self, dest=None, channel=None, browser_binary=None): def install_webdriver_by_version(self, version, dest=None):
assert version, "Cannot install ChromeDriver without Chrome version"
if dest is None: if dest is None:
dest = os.pwd dest = os.pwd
if browser_binary is None: url = self._latest_chromedriver_url(version)
browser_binary = self.find_binary(channel)
url = self._latest_chromedriver_url(browser_binary)
self.logger.info("Downloading ChromeDriver from %s" % url) self.logger.info("Downloading ChromeDriver from %s" % url)
unzip(get(url).raw, dest) unzip(get(url).raw, dest)
chromedriver_dir = os.path.join(dest, 'chromedriver_%s' % self.platform_string()) chromedriver_dir = os.path.join(
dest, 'chromedriver_%s' % self.platform_string())
if os.path.isfile(os.path.join(chromedriver_dir, "chromedriver")): if os.path.isfile(os.path.join(chromedriver_dir, "chromedriver")):
shutil.move(os.path.join(chromedriver_dir, "chromedriver"), dest) shutil.move(os.path.join(chromedriver_dir, "chromedriver"), dest)
shutil.rmtree(chromedriver_dir) shutil.rmtree(chromedriver_dir)
return find_executable("chromedriver", dest) return find_executable("chromedriver", dest)
def install_webdriver(self, dest=None, channel=None, browser_binary=None):
if browser_binary is None:
browser_binary = self.find_binary(channel)
return self.install_webdriver_by_version(
self.version(browser_binary), dest)
def version(self, binary=None, webdriver_binary=None): def version(self, binary=None, webdriver_binary=None):
if not binary: if not binary:
self.logger.warning("No browser binary provided.") self.logger.warning("No browser binary provided.")
@ -585,21 +590,43 @@ class ChromeAndroid(Browser):
product = "chrome_android" product = "chrome_android"
requirements = "requirements_chrome_android.txt" requirements = "requirements_chrome_android.txt"
def __init__(self, logger):
super(ChromeAndroid, self).__init__(logger)
def install(self, dest=None, channel=None): def install(self, dest=None, channel=None):
raise NotImplementedError raise NotImplementedError
def find_binary(self, venv_path=None, channel=None): def find_binary(self, venv_path=None, channel=None):
raise NotImplementedError if channel in ("beta", "dev", "canary"):
return "com.chrome." + channel
return "com.android.chrome"
def find_webdriver(self, channel=None): def find_webdriver(self, channel=None):
return find_executable("chromedriver") return find_executable("chromedriver")
def install_webdriver(self, dest=None, channel=None, browser_binary=None): def install_webdriver(self, dest=None, channel=None, browser_binary=None):
if browser_binary is None:
browser_binary = self.find_binary(channel)
chrome = Chrome(self.logger) chrome = Chrome(self.logger)
return chrome.install_webdriver(dest, channel) return chrome.install_webdriver_by_version(
self.version(browser_binary), dest)
def version(self, binary=None, webdriver_binary=None): def version(self, binary=None, webdriver_binary=None):
return None if not binary:
self.logger.warning("No package name provided.")
return None
command = ['adb', 'shell', 'dumpsys', 'package', binary]
try:
output = call(*command)
except (subprocess.CalledProcessError, OSError):
self.logger.warning("Failed to call %s" % " ".join(command))
return None
match = re.search(r'versionName=(.*)', output)
if not match:
self.logger.warning("Failed to find versionName")
return None
return match.group(1)
class ChromeiOS(Browser): class ChromeiOS(Browser):
@ -699,6 +726,7 @@ class Opera(Browser):
if m: if m:
return m.group(0) return m.group(0)
class EdgeChromium(Browser): class EdgeChromium(Browser):
"""MicrosoftEdge-specific interface.""" """MicrosoftEdge-specific interface."""
platform = { platform = {
@ -725,16 +753,16 @@ class EdgeChromium(Browser):
os.path.expandvars("$SYSTEMDRIVE\\Program Files\\Microsoft\\Edge Dev\\Application"), os.path.expandvars("$SYSTEMDRIVE\\Program Files\\Microsoft\\Edge Dev\\Application"),
os.path.expandvars("$SYSTEMDRIVE\\Program Files (x86)\\Microsoft\\Edge Beta\\Application"), os.path.expandvars("$SYSTEMDRIVE\\Program Files (x86)\\Microsoft\\Edge Beta\\Application"),
os.path.expandvars("$SYSTEMDRIVE\\Program Files (x86)\\Microsoft\\Edge Dev\\Application"), os.path.expandvars("$SYSTEMDRIVE\\Program Files (x86)\\Microsoft\\Edge Dev\\Application"),
os.path.expanduser("~\\AppData\Local\\Microsoft\\Edge SxS\\Application"),] os.path.expanduser("~\\AppData\Local\\Microsoft\\Edge SxS\\Application")]
return find_executable(binaryname, os.pathsep.join(winpaths)) return find_executable(binaryname, os.pathsep.join(winpaths))
if self.platform == "macos": if self.platform == "macos":
binaryname = "Microsoft Edge Canary" binaryname = "Microsoft Edge Canary"
binary = find_executable(binaryname) binary = find_executable(binaryname)
if not binary: if not binary:
macpaths = ["/Applications/Microsoft Edge.app/Contents/MacOS", macpaths = ["/Applications/Microsoft Edge.app/Contents/MacOS",
os.path.expanduser("~/Applications/Microsoft Edge.app/Contents/MacOS"), os.path.expanduser("~/Applications/Microsoft Edge.app/Contents/MacOS"),
"/Applications/Microsoft Edge Canary.app/Contents/MacOS", "/Applications/Microsoft Edge Canary.app/Contents/MacOS",
os.path.expanduser("~/Applications/Microsoft Edge Canary.app/Contents/MacOS")] os.path.expanduser("~/Applications/Microsoft Edge Canary.app/Contents/MacOS")]
return find_executable("Microsoft Edge Canary", os.pathsep.join(macpaths)) return find_executable("Microsoft Edge Canary", os.pathsep.join(macpaths))
return binary return binary
@ -797,6 +825,7 @@ class EdgeChromium(Browser):
self.logger.warning("Failed to find Edge binary.") self.logger.warning("Failed to find Edge binary.")
return None return None
class Edge(Browser): class Edge(Browser):
"""Edge-specific interface.""" """Edge-specific interface."""

View File

@ -6,6 +6,7 @@ import sys
latest_channels = { latest_channels = {
'firefox': 'nightly', 'firefox': 'nightly',
'chrome': 'dev', 'chrome': 'dev',
'chrome_android': 'dev',
'edgechromium': 'dev', 'edgechromium': 'dev',
'safari': 'preview', 'safari': 'preview',
'servo': 'nightly' 'servo': 'nightly'

View File

@ -281,7 +281,7 @@ class Chrome(BrowserSetup):
logger.info("Downloading chromedriver") logger.info("Downloading chromedriver")
webdriver_binary = self.browser.install_webdriver( webdriver_binary = self.browser.install_webdriver(
dest=self.venv.bin_path, dest=self.venv.bin_path,
browser_binary=kwargs["binary"] browser_binary=kwargs["binary"],
) )
else: else:
logger.info("Using webdriver binary %s" % webdriver_binary) logger.info("Using webdriver binary %s" % webdriver_binary)
@ -290,8 +290,8 @@ class Chrome(BrowserSetup):
kwargs["webdriver_binary"] = webdriver_binary kwargs["webdriver_binary"] = webdriver_binary
else: else:
raise WptrunError("Unable to locate or install chromedriver binary") raise WptrunError("Unable to locate or install chromedriver binary")
if kwargs["browser_channel"] == "dev": if browser_channel in ("dev", "canary"):
logger.info("Automatically turning on experimental features for Chrome Dev") logger.info("Automatically turning on experimental features for Chrome Dev/Canary")
kwargs["binary_args"].append("--enable-experimental-web-platform-features") kwargs["binary_args"].append("--enable-experimental-web-platform-features")
# HACK(Hexcles): work around https://github.com/web-platform-tests/wpt/issues/16448 # HACK(Hexcles): work around https://github.com/web-platform-tests/wpt/issues/16448
kwargs["webdriver_args"].append("--disable-build-check") kwargs["webdriver_args"].append("--disable-build-check")
@ -302,6 +302,10 @@ class ChromeAndroid(BrowserSetup):
browser_cls = browser.ChromeAndroid browser_cls = browser.ChromeAndroid
def setup_kwargs(self, kwargs): def setup_kwargs(self, kwargs):
browser_channel = kwargs["browser_channel"]
if kwargs["package_name"] is None:
kwargs["package_name"] = self.browser.find_binary(
channel=browser_channel)
if kwargs["webdriver_binary"] is None: if kwargs["webdriver_binary"] is None:
webdriver_binary = self.browser.find_webdriver() webdriver_binary = self.browser.find_webdriver()
@ -310,7 +314,10 @@ class ChromeAndroid(BrowserSetup):
if install: if install:
logger.info("Downloading chromedriver") logger.info("Downloading chromedriver")
webdriver_binary = self.browser.install_webdriver(dest=self.venv.bin_path) webdriver_binary = self.browser.install_webdriver(
dest=self.venv.bin_path,
browser_binary=kwargs["package_name"],
)
else: else:
logger.info("Using webdriver binary %s" % webdriver_binary) logger.info("Using webdriver binary %s" % webdriver_binary)
@ -318,6 +325,11 @@ class ChromeAndroid(BrowserSetup):
kwargs["webdriver_binary"] = webdriver_binary kwargs["webdriver_binary"] = webdriver_binary
else: else:
raise WptrunError("Unable to locate or install chromedriver binary") raise WptrunError("Unable to locate or install chromedriver binary")
if browser_channel in ("dev", "canary"):
logger.info("Automatically turning on experimental features for Chrome Dev/Canary")
kwargs["binary_args"].append("--enable-experimental-web-platform-features")
# HACK(Hexcles): work around https://github.com/web-platform-tests/wpt/issues/16448
kwargs["webdriver_args"].append("--disable-build-check")
class ChromeiOS(BrowserSetup): class ChromeiOS(BrowserSetup):
@ -626,8 +638,10 @@ def setup_wptrunner(venv, prompt=True, install_browser=False, **kwargs):
# Only update browser_version if it was not given as a command line # Only update browser_version if it was not given as a command line
# argument, so that it can be overridden on the command line. # argument, so that it can be overridden on the command line.
if not kwargs["browser_version"]: if not kwargs["browser_version"]:
kwargs["browser_version"] = setup_cls.browser.version(binary=kwargs.get("binary"), kwargs["browser_version"] = setup_cls.browser.version(
webdriver_binary=kwargs.get("webdriver_binary")) binary=kwargs.get("binary") or kwargs.get("package_name"),
webdriver_binary=kwargs.get("webdriver_binary"),
)
return kwargs return kwargs

View File

@ -25,11 +25,12 @@ _wptserve_ports = set()
def check_args(**kwargs): def check_args(**kwargs):
require_arg(kwargs, "package_name")
require_arg(kwargs, "webdriver_binary") require_arg(kwargs, "webdriver_binary")
def browser_kwargs(test_type, run_info_data, config, **kwargs): def browser_kwargs(test_type, run_info_data, config, **kwargs):
return {"binary": kwargs["binary"], return {"package_name": kwargs["package_name"],
"webdriver_binary": kwargs["webdriver_binary"], "webdriver_binary": kwargs["webdriver_binary"],
"webdriver_args": kwargs.get("webdriver_args")} "webdriver_args": kwargs.get("webdriver_args")}
@ -45,15 +46,13 @@ def executor_kwargs(test_type, server_config, cache_manager, run_info_data,
executor_kwargs = chrome_executor_kwargs(test_type, server_config, executor_kwargs = chrome_executor_kwargs(test_type, server_config,
cache_manager, run_info_data, cache_manager, run_info_data,
**kwargs) **kwargs)
# Remove unsupported options on mobile.
del executor_kwargs["capabilities"]["goog:chromeOptions"]["prefs"] del executor_kwargs["capabilities"]["goog:chromeOptions"]["prefs"]
del executor_kwargs["capabilities"]["goog:chromeOptions"]["useAutomationExtension"] del executor_kwargs["capabilities"]["goog:chromeOptions"]["useAutomationExtension"]
# TODO(Hexcles): browser_channel should be properly supported. assert kwargs["package_name"], "missing --package-name"
package_name = "com.android.chrome" # stable channel
# Required to start on mobile
executor_kwargs["capabilities"]["goog:chromeOptions"]["androidPackage"] = \ executor_kwargs["capabilities"]["goog:chromeOptions"]["androidPackage"] = \
package_name kwargs["package_name"]
# Map wptrunner args to chromeOptions.
return executor_kwargs return executor_kwargs
@ -71,12 +70,10 @@ class ChromeAndroidBrowser(Browser):
``wptrunner.webdriver.ChromeDriverServer``. ``wptrunner.webdriver.ChromeDriverServer``.
""" """
def __init__(self, logger, binary, webdriver_binary="chromedriver", def __init__(self, logger, package_name, webdriver_binary="chromedriver",
webdriver_args=None): webdriver_args=None):
"""Creates a new representation of Chrome. The `binary` argument gives
the browser binary to use for testing."""
Browser.__init__(self, logger) Browser.__init__(self, logger)
self.binary = binary self.package_name = package_name
self.server = ChromeDriverServer(self.logger, self.server = ChromeDriverServer(self.logger,
binary=webdriver_binary, binary=webdriver_binary,
args=webdriver_args) args=webdriver_args)