brizental pushed to branch tor-browser-149.0a1-16.0-2 at The Tor Project / Applications / Tor Browser Commits: 863fc44a by Beatriz Rizental at 2026-03-24T14:25:12-03:00 BB 43243 [android]: Keep processing pending inits after failure This is in the process of being uplifted. Bug 2021618: bugzilla.mozilla.org/show_bug.cgi?id=2021618 Differential Revision: https://phabricator.services.mozilla.com/D286669 - - - - - 33b1e93e by Beatriz Rizental at 2026-03-24T14:25:12-03:00 BB 43243 [android]: Start GeckoEngineSession early when Marionette enabled This is in the process of being uplifted. Bug 2021884: https://bugzilla.mozilla.org/show_bug.cgi?id=2021884 Differential Revision: https://phabricator.services.mozilla.com/D286676 - - - - - 24ce6582 by Beatriz Rizental at 2026-03-24T14:25:13-03:00 BB 43243: Modify mozharness scripts for Base Browser - - - - - 7 changed files: - mobile/android/fenix/app/src/main/java/org/mozilla/fenix/FenixApplication.kt - mobile/shared/modules/geckoview/DelayedInit.sys.mjs - + mobile/shared/modules/geckoview/test/xpcshell/test_DelayedInit.js - mobile/shared/modules/geckoview/test/xpcshell/xpcshell.toml - testing/mozharness/configs/android/android14-x86_64.py - testing/mozharness/configs/android/android_common.py - testing/mozharness/scripts/android_emulator_unittest.py Changes: ===================================== mobile/android/fenix/app/src/main/java/org/mozilla/fenix/FenixApplication.kt ===================================== @@ -507,6 +507,12 @@ open class FenixApplication : Application(), Provider, ThemeProvider { logElapsedTime(logger, "Starting Relay feature integration") { components.relayFeatureIntegration.start() } + + // If running Marionette tests a GeckoEngineSession needs to be + // started and that must happen on the main thread. + logElapsedTime(logger, "Maybe setup Marionette") { + maybeSetupMarionette() + } } } @@ -675,6 +681,13 @@ open class FenixApplication : Application(), Provider, ThemeProvider { FxNimbus.initialize { nimbus } } + private fun maybeSetupMarionette() { + // If Marionette is enabled, start a GeckoEngineSession immediatelly. + if (System.getenv("MOZ_MARIONETTE") == "1") { + components.core.engine.speculativeCreateSession(components.appStore.state.mode.isPrivate) + } + } + /** * Initiate Megazord sequence! Megazord Battle Mode! * ===================================== mobile/shared/modules/geckoview/DelayedInit.sys.mjs ===================================== @@ -96,7 +96,11 @@ var Impl = { return false; } this.complete = true; - this.fn.call(); + try { + this.fn.call(); + } catch (e) { + console.error("Error running init", e); + } this.fn = null; return true; }, ===================================== mobile/shared/modules/geckoview/test/xpcshell/test_DelayedInit.js ===================================== @@ -0,0 +1,48 @@ +/* Any copyright is dedicated to the Public Domain. +http://creativecommons.org/publicdomain/zero/1.0/ */ +"use strict"; + +const { DelayedInit } = ChromeUtils.importESModule( + "resource://gre/modules/DelayedInit.sys.mjs" +); + +add_task(async function test_delayed_init_continues_queue_on_failure() { + const results = []; + const waitMs = 0; + + DelayedInit.schedule( + () => { + results.push("first"); + }, + null, + null, + waitMs + ); + + DelayedInit.schedule( + () => { + results.push("second"); + throw new Error("Deliberate error for testing"); + }, + null, + null, + waitMs + ); + + DelayedInit.schedule( + () => { + results.push("third"); + }, + null, + null, + waitMs + ); + + await new Promise(resolve => ChromeUtils.idleDispatch(resolve)); + + Assert.deepEqual( + results, + ["first", "second", "third"], + "Queue processes all inits even when one fails" + ); +}); ===================================== mobile/shared/modules/geckoview/test/xpcshell/xpcshell.toml ===================================== @@ -7,6 +7,8 @@ prefs = "browser.crashReports.onDemand=true" ["test_ChildCrashHandler.js"] +["test_DelayedInit.js"] + ["test_GeckoViewAppConstants.js"] ["test_RemoteSettingsCrashPull.js"] ===================================== testing/mozharness/configs/android/android14-x86_64.py ===================================== @@ -11,8 +11,9 @@ config = { "emulator_avd_name": "mozemulator-android34-x86_64", "emulator_process_name": "qemu-system-x86_64", "emulator_extra_args": [ - "-gpu", - "on", + "-no-window", + "-no-audio", + "-no-boot-anim", "-skip-adb-auth", "-verbose", "-show-kernel", ===================================== testing/mozharness/configs/android/android_common.py ===================================== @@ -315,6 +315,19 @@ config = { "--deviceSerial=%(device_serial)s", ], }, + "marionette": { + "run_filename": "runtests.py", + "testsdir": "marionette/harness/marionette_harness", + "install": True, + "options": [ + "-vv", + "--address=127.0.0.1:2828", + "--app=fennec", + ], + "tests": [ + "%(abs_marionette_manifest_dir)s/unit-tests.toml", + ], + }, }, # end suite_definitions "structured_suites": [ "mochitest-media", ===================================== testing/mozharness/scripts/android_emulator_unittest.py ===================================== @@ -7,15 +7,18 @@ import copy import datetime import json import os +import socket import subprocess import sys +import tempfile +import time # load modules from parent dir here = os.path.abspath(os.path.dirname(__file__)) sys.path.insert(1, os.path.dirname(here)) from mozharness.base.log import WARNING -from mozharness.base.script import BaseScript, PreScriptAction +from mozharness.base.script import BaseScript, PostScriptAction, PreScriptAction from mozharness.mozilla.automation import TBPL_RETRY from mozharness.mozilla.mozbase import MozbaseMixin from mozharness.mozilla.testing.android import AndroidMixin @@ -26,7 +29,7 @@ from mozharness.mozilla.testing.codecoverage import ( from mozharness.mozilla.testing.testbase import TestingMixin, testing_config_options SUITE_DEFAULT_E10S = ["geckoview-junit", "mochitest", "reftest"] -SUITE_NO_E10S = ["cppunittest", "gtest", "jittest", "xpcshell"] +SUITE_NO_E10S = ["cppunittest", "gtest", "jittest", "xpcshell", "marionette"] SUITE_REPEATABLE = ["mochitest", "reftest", "xpcshell"] @@ -178,6 +181,15 @@ class AndroidEmulatorTest( "times in which case the test must contain at least one of the given tags.", }, ], + [ + ["--package-name"], + { + "action": "store", + "default": None, + "dest": "package_name", + "help": "The Android package name for the app being installed.", + }, + ], ] + copy.deepcopy(testing_config_options) + copy.deepcopy(code_coverage_config_options) @@ -228,6 +240,7 @@ class AndroidEmulatorTest( self.enable_isolated_zygote_process = c.get("enable_isolated_zygote_process") self.extra_prefs = c.get("extra_prefs") self.test_tags = c.get("test_tags") + self.package_name = c.get("package_name") or self.query_package_name() def query_abs_dirs(self): if self.abs_dirs: @@ -329,6 +342,16 @@ class AndroidEmulatorTest( "error_summary_file": error_summary_file, "xpcshell_extra": c.get("xpcshell_extra", ""), "gtest_dir": os.path.join(dirs["abs_test_install_dir"], "gtest"), + "abs_marionette_manifest_dir": os.path.join( + dirs["abs_test_install_dir"], + "marionette", + "tests", + "testing", + "marionette", + "harness", + "marionette_harness", + "tests", + ), } user_paths = self._get_mozharness_test_paths(self.test_suite) @@ -345,7 +368,7 @@ class AndroidEmulatorTest( if "%(app)" in option: # only query package name if requested - cmd.extend([option % {"app": self.query_package_name()}]) + cmd.extend([option % {"app": self.package_name}]) else: option = option % str_format_values if option: @@ -409,6 +432,7 @@ class AndroidEmulatorTest( self.config["suite_definitions"][self.test_suite].get("tests"), None, try_tests, + str_format_values=str_format_values, ) ) @@ -449,6 +473,7 @@ class AndroidEmulatorTest( }, ), ("xpcshell", {"xpcshell": "xpcshell"}), + ("marionette", {"marionette": "marionette"}), ] suites = [] for category, all_suites in all: @@ -473,6 +498,61 @@ class AndroidEmulatorTest( # in the base class, this checks for mozinstall, but we don't use it pass + def _configure_marionette_virtualenv(self, action): + dirs = self.query_abs_dirs() + requirements = os.path.join( + dirs["abs_test_install_dir"], "config", "marionette_requirements.txt" + ) + if not os.path.isfile(requirements): + self.fatal(f"Could not find marionette requirements file: {requirements}") + + self.register_virtualenv_module(requirements=[requirements]) + + def _marionette_setup(self): + adb = self.query_exe("adb") + + self.run_command([adb, "forward", "tcp:2828", "tcp:2828"]) + + with tempfile.NamedTemporaryFile(suffix=".yaml") as tmp_file: + tmp_file.write( + b"""args: +- --marionette +- --remote-allow-system-access +""" + ) + tmp_file.flush() + + remote_path = f"/data/local/tmp/{self.package_name}-geckoview-config.yaml" + self.run_command([adb, "push", tmp_file.name, remote_path]) + + self.run_command([ + adb, + "shell", + "am", + "start", + "-S", + "-W", + "-n", + f"{self.package_name}/org.mozilla.gecko.BrowserApp", + ]) + + # Wait for Marionette to be ready + for attempt in range(5): + try: + self.info( + f"Checking Marionette on 127.0.0.1:2828 (attempt {attempt + 1}/5)" + ) + socket.create_connection(("127.0.0.1", 2828), 10).close() + self.info("Marionette is reachable") + break + except OSError: + if attempt == 4: + self.fatal( + "Timed out waiting for 127.0.0.1:2828 to become reachable" + ) + self.info("Marionette not reachable yet, retrying in 10s") + time.sleep(10) + @PreScriptAction("create-virtualenv") def pre_create_virtualenv(self, action): dirs = self.query_abs_dirs() @@ -488,6 +568,9 @@ class AndroidEmulatorTest( if requirements: self.register_virtualenv_module(requirements=[requirements]) + if ("marionette", "marionette") in suites: + self._configure_marionette_virtualenv(action) + def download_and_extract(self): """ Download and extract product APK, tests.zip, and host utils. @@ -525,6 +608,9 @@ class AndroidEmulatorTest( for per_test_suite, suite in suites: self.test_suite = suite + if self.test_suite == "marionette": + self._marionette_setup() + try: cwd = self._query_tests_dir(self.test_suite) except Exception: @@ -594,6 +680,19 @@ class AndroidEmulatorTest( % (suite_category, suite, tbpl_status), ) + @PostScriptAction("run-tests") + def marionette_teardown(self, *args, **kwargs): + if ("marionette", "marionette") in self._query_suites(): + adb = self.query_exe("adb") + self.run_command([adb, "shell", "am", "force-stop", self.package_name]) + self.run_command([adb, "uninstall", self.package_name]) + self.run_command([ + adb, + "shell", + "rm", + f"/data/local/tmp/{self.package_name}-geckoview-config.yaml", + ]) + if __name__ == "__main__": test = AndroidEmulatorTest() View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/dd75620... -- View it on GitLab: https://gitlab.torproject.org/tpo/applications/tor-browser/-/compare/dd75620... You're receiving this email because of your account on gitlab.torproject.org. Manage all notifications: https://gitlab.torproject.org/-/profile/notifications | Help: https://gitlab.torproject.org/help
participants (1)
-
brizental (@brizental)