tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 90424972214a70dbb9007e6f32a7573b337efb57
parent a09f544f744b748285c8336368cf1a1d6cf62659
Author: Alexandre Lissy <lissyx+mozillians@lissyx.dyndns.org>
Date:   Wed, 19 Nov 2025 17:46:18 +0000

Bug 259356 - Add integration testing of XDG handling via Marionette r=whimboo,mossop

Differential Revision: https://phabricator.services.mozilla.com/D213186

Diffstat:
Mtoolkit/xre/test/marionette/manifest.toml | 2++
Atoolkit/xre/test/marionette/xdg_config/manifest.toml | 19+++++++++++++++++++
Atoolkit/xre/test/marionette/xdg_config/test_xdg_config_legacy_existing.py | 32++++++++++++++++++++++++++++++++
Atoolkit/xre/test/marionette/xdg_config/test_xdg_config_legacy_forced.py | 23+++++++++++++++++++++++
Atoolkit/xre/test/marionette/xdg_config/test_xdg_config_new.py | 18++++++++++++++++++
Atoolkit/xre/test/marionette/xdg_config/test_xdg_config_new_env.py | 23+++++++++++++++++++++++
Atoolkit/xre/test/marionette/xdg_config/test_xdg_config_new_env_invalid.py | 23+++++++++++++++++++++++
Atoolkit/xre/test/marionette/xdg_config/test_xdg_config_new_existing.py | 33+++++++++++++++++++++++++++++++++
Atoolkit/xre/test/marionette/xdg_config/xdg_config_home_test_case.py | 140+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mtools/lint/dot-mozilla-reference.yml | 1+
10 files changed, 314 insertions(+), 0 deletions(-)

diff --git a/toolkit/xre/test/marionette/manifest.toml b/toolkit/xre/test/marionette/manifest.toml @@ -1,5 +1,7 @@ [DEFAULT] +["include:xdg_config/manifest.toml"] + ["test_exitcode.py"] ["test_fission_autostart.py"] diff --git a/toolkit/xre/test/marionette/xdg_config/manifest.toml b/toolkit/xre/test/marionette/xdg_config/manifest.toml @@ -0,0 +1,19 @@ +[DEFAULT] + +["test_xdg_config_legacy_existing.py"] +run-if = ["os == 'linux'"] + +["test_xdg_config_legacy_forced.py"] +run-if = ["os == 'linux'"] + +["test_xdg_config_new.py"] +run-if = ["os == 'linux'"] + +["test_xdg_config_new_env.py"] +run-if = ["os == 'linux'"] + +["test_xdg_config_new_env_invalid.py"] +run-if = ["os == 'linux'"] + +["test_xdg_config_new_existing.py"] +run-if = ["os == 'linux'"] diff --git a/toolkit/xre/test/marionette/xdg_config/test_xdg_config_legacy_existing.py b/toolkit/xre/test/marionette/xdg_config/test_xdg_config_legacy_existing.py @@ -0,0 +1,32 @@ +import os +import sys + +import mozfile + +sys.path.append(os.path.dirname(__file__)) + +from xdg_config_home_test_case import XdgConfigHomeTestCase + + +class TestXdgConfigHomeLegacyExisting(XdgConfigHomeTestCase): + + def setUp(self): + assert "XDG_CONFIG_HOME" not in self._env.keys() + self._env.update({"XDG_CONFIG_HOME": f"{self.homedir}/.config-test/"}) + self.product_root = self.make_product_root(os.path.join(".mozilla", "firefox")) + super().setUp() + + def tearDown(self): + mozfile.remove(self.product_root) + assert not os.path.exists(self.product_root) + super().tearDown() + + def test_profile_dir(self): + self.client.navigate(self.about_support) + + profile_subdir = self.get_asserted_profile_subdir() + print(f"profile_subdir={profile_subdir}") + self.assertTrue( + profile_subdir.startswith(".mozilla/firefox"), + "Profile is under '.mozilla/firefox'", + ) diff --git a/toolkit/xre/test/marionette/xdg_config/test_xdg_config_legacy_forced.py b/toolkit/xre/test/marionette/xdg_config/test_xdg_config_legacy_forced.py @@ -0,0 +1,23 @@ +import os +import sys + +sys.path.append(os.path.dirname(__file__)) + +from xdg_config_home_test_case import XdgConfigHomeTestCase + + +class TestXdgConfigHomeLegacy(XdgConfigHomeTestCase): + + def setUp(self): + assert "MOZ_LEGACY_HOME" not in self._env.keys() + self._env.update({"MOZ_LEGACY_HOME": "1"}) + super().setUp() + + def test_profile_dir(self): + self.client.navigate(self.about_support) + + profile_subdir = self.get_asserted_profile_subdir() + self.assertTrue( + profile_subdir.startswith(".mozilla/firefox"), + "Profile is under .mozilla/firefox", + ) diff --git a/toolkit/xre/test/marionette/xdg_config/test_xdg_config_new.py b/toolkit/xre/test/marionette/xdg_config/test_xdg_config_new.py @@ -0,0 +1,18 @@ +import os +import sys + +sys.path.append(os.path.dirname(__file__)) + +from xdg_config_home_test_case import XdgConfigHomeTestCase + + +class TestXdgConfigHomeNew(XdgConfigHomeTestCase): + + def test_profile_dir(self): + self.client.navigate(self.about_support) + + profile_subdir = self.get_asserted_profile_subdir() + self.assertTrue( + profile_subdir.startswith(".config/mozilla/firefox"), + "Profile is under $HOME/.config/mozilla/firefox", + ) diff --git a/toolkit/xre/test/marionette/xdg_config/test_xdg_config_new_env.py b/toolkit/xre/test/marionette/xdg_config/test_xdg_config_new_env.py @@ -0,0 +1,23 @@ +import os +import sys + +sys.path.append(os.path.dirname(__file__)) + +from xdg_config_home_test_case import XdgConfigHomeTestCase + + +class TestXdgConfigHomeNewEnv(XdgConfigHomeTestCase): + + def setUp(self): + assert "XDG_CONFIG_HOME" not in self._env.keys() + self._env.update({"XDG_CONFIG_HOME": f"{self.homedir}/mozXDG-config-dir"}) + super().setUp() + + def test_profile_dir(self): + self.client.navigate(self.about_support) + + profile_subdir = self.get_asserted_profile_subdir() + self.assertTrue( + profile_subdir.startswith("mozXDG-config-dir/mozilla/firefox"), + "Profile is under 'mozXDG-config-dir/mozilla/firefox'", + ) diff --git a/toolkit/xre/test/marionette/xdg_config/test_xdg_config_new_env_invalid.py b/toolkit/xre/test/marionette/xdg_config/test_xdg_config_new_env_invalid.py @@ -0,0 +1,23 @@ +import os +import sys + +sys.path.append(os.path.dirname(__file__)) + +from xdg_config_home_test_case import XdgConfigHomeTestCase + + +class TestXdgConfigHomeNewEnvInvalid(XdgConfigHomeTestCase): + + def setUp(self): + assert "XDG_CONFIG_HOME" not in self._env.keys() + self._env.update({"XDG_CONFIG_HOME": "$HOME/mozXDG-config-dir"}) + super().setUp() + + def test_profile_dir(self): + self.client.navigate(self.about_support) + + profile_subdir = self.get_asserted_profile_subdir() + self.assertTrue( + profile_subdir.startswith(".config/mozilla/firefox"), + "Profile is under '.config/mozilla/firefox'", + ) diff --git a/toolkit/xre/test/marionette/xdg_config/test_xdg_config_new_existing.py b/toolkit/xre/test/marionette/xdg_config/test_xdg_config_new_existing.py @@ -0,0 +1,33 @@ +import os +import sys + +import mozfile + +sys.path.append(os.path.dirname(__file__)) + +from xdg_config_home_test_case import XdgConfigHomeTestCase + + +class TestXdgConfigHomeNewExisting(XdgConfigHomeTestCase): + + def setUp(self): + assert "XDG_CONFIG_HOME" not in self._env.keys() + self._env.update({"XDG_CONFIG_HOME": f"{self.homedir}/.config-test/"}) + self.product_root = self.make_product_root( + os.path.join(".config-test", "mozilla", "firefox") + ) + super().setUp() + + def tearDown(self): + mozfile.remove(self.product_root) + assert not os.path.exists(self.product_root) + super().tearDown() + + def test_profile_dir(self): + self.client.navigate(self.about_support) + + profile_subdir = self.get_asserted_profile_subdir() + self.assertTrue( + profile_subdir.startswith(".config-test/mozilla/firefox"), + "Profile is under '.config-test/mozilla/firefox'", + ) diff --git a/toolkit/xre/test/marionette/xdg_config/xdg_config_home_test_case.py b/toolkit/xre/test/marionette/xdg_config/xdg_config_home_test_case.py @@ -0,0 +1,140 @@ +import os +import subprocess +import tempfile + +import mozfile +from marionette_driver.marionette import Marionette +from marionette_harness import MarionetteTestCase + + +class XdgConfigHomeTestCase(MarionetteTestCase): + about_support = "about:support" + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self._created_dirs = [] + + self.tmproot = tempfile.mkdtemp(prefix="mozrunner-xdg_config-test") + + self.bin = None + self.tmphome = os.path.join(self.tmproot, "DEFAULT") + self.homedir = self.get_home_root() + + self._env = os.environ.copy() + self._env.update({"HOME": self.homedir}) + + self.process_handler = None + + def setUp(self): + super().setUp() + + if not self.bin: + self.bin = self.marionette.instance.binary + + self._cmd = [ + self.bin, + "--headless", + "-marionette", + "-remote-allow-system-access", + ] + + self.marionette.quit(in_app=False) + self.client = Marionette(host="127.0.0.1", port=2828) + + self.start() + self.client.start_session() + + def tearDown(self): + self.process_handler.kill() + self.process_handler.wait() + self.process_handler = None + + self.client = None + + super().tearDown() + + self.cleanup() + + def start(self): + self.assert_safe_homedir() + _env = self._env.copy() + self.process_handler = subprocess.Popen(self._cmd, env=self._env) + + def assert_safe_homedir(self): + assert ( + "mozrunner-xdg_config-test" in self.homedir + ), f"HOME is not real user's home: {self.homedir}" + + def get_home_root(self): + rv = tempfile.mkdtemp(prefix="{}.".format("run"), dir=self.tmproot) + self._created_dirs.append(rv) + return rv + + def make_product_root(self, subpath): + product_root = os.path.join(self.homedir, subpath) + assert not os.path.exists(product_root), f"no {product_root}" + os.makedirs(product_root) + + profiles_ini_path = os.path.join(product_root, "profiles.ini") + assert not os.path.exists(profiles_ini_path) + with open(profiles_ini_path, "w") as profiles_ini: + profiles_ini.write( + """ +[General] +StartWithLastProfile=1 +Version=2 +""" + ) + return product_root + + def find_one_existing_test_run_directory(self): + dirs = os.listdir(self.tmproot) + test_dir = list(filter(lambda e: e.startswith("run."), dirs)) + assert len(test_dir) == 1 + return os.path.join(self.tmproot, test_dir[0]) + + def find_one_profile_run_dir(self): + test_dir_walk = list(os.walk(self.homedir)) + maybe_profile = list( + filter(lambda e: "compatibility.ini" in e[2], test_dir_walk) + ) + assert len(maybe_profile) == 1 + (profile_dir, _, _) = maybe_profile[0] + return profile_dir + + def cleanup(self): + for d in self._created_dirs: + mozfile.remove(d) + assert not os.path.exists(d) + + if self.tmproot: + mozfile.remove(self.tmproot) + assert not os.path.exists(self.tmproot) + + def get_process_env_value(self, name): + with self.client.using_context(self.client.CONTEXT_CHROME): + rv = self.client.execute_script( + f""" + return Services.env.get("{name}"); + """ + ) + return rv + + def get_profile_dir(self): + with self.client.using_context(self.client.CONTEXT_CHROME): + rv = self.client.execute_script( + """ + return Services.dirsvc.get("ProfD", Ci.nsIFile).path; + """ + ) + return rv + + def get_asserted_profile_subdir(self): + profile_dir = self.get_profile_dir() + common = os.path.commonpath((self.homedir, profile_dir)) + self.assertTrue( + len(common) > 0, + f"Profile dir {profile_dir} is a subdir of homedir: {self.homedir}", + ) + + return os.path.relpath(profile_dir, self.homedir) diff --git a/tools/lint/dot-mozilla-reference.yml b/tools/lint/dot-mozilla-reference.yml @@ -39,5 +39,6 @@ avoid-dot-mozilla-without-xdg: - toolkit/crashreporter/crash_helper_server/src/logging/env.rs - toolkit/moz.configure - toolkit/xre/nsXREDirProvider.cpp + - toolkit/xre/test/marionette/xdg_config/test_xdg_config_legacy_existing.py - toolkit/tests/gtest/TestXREAppDir.cpp - xpcom/io/nsAppFileLocationProvider.cpp