diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:47:55 +0000 |
commit | 26a029d407be480d791972afb5975cf62c9360a6 (patch) | |
tree | f435a8308119effd964b339f76abb83a57c29483 /testing/firefox-ui/tests/functional | |
parent | Initial commit. (diff) | |
download | firefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz firefox-26a029d407be480d791972afb5975cf62c9360a6.zip |
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'testing/firefox-ui/tests/functional')
7 files changed, 483 insertions, 0 deletions
diff --git a/testing/firefox-ui/tests/functional/manifest.toml b/testing/firefox-ui/tests/functional/manifest.toml new file mode 100644 index 0000000000..f3d5fce3d6 --- /dev/null +++ b/testing/firefox-ui/tests/functional/manifest.toml @@ -0,0 +1,5 @@ +[DEFAULT] + +["include:safebrowsing/manifest.toml"] + +["include:security/manifest.toml"] diff --git a/testing/firefox-ui/tests/functional/safebrowsing/manifest.toml b/testing/firefox-ui/tests/functional/safebrowsing/manifest.toml new file mode 100644 index 0000000000..d1a4f5cd04 --- /dev/null +++ b/testing/firefox-ui/tests/functional/safebrowsing/manifest.toml @@ -0,0 +1,14 @@ +[DEFAULT] + +["test_initial_download.py"] +skip-if = [ + "debug", # The GAPI key isn't available in debug or sanitizer builds + "asan", + "tsan", + "ccov && os == 'win'", # Bug 1805893 + "cc_type == 'clang' && os == 'win'", # Bug 1565818 +] + +["test_notification.py"] + +["test_warning_pages.py"] diff --git a/testing/firefox-ui/tests/functional/safebrowsing/test_initial_download.py b/testing/firefox-ui/tests/functional/safebrowsing/test_initial_download.py new file mode 100644 index 0000000000..4013c51d5b --- /dev/null +++ b/testing/firefox-ui/tests/functional/safebrowsing/test_initial_download.py @@ -0,0 +1,135 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +import os +from functools import reduce + +from marionette_driver import Wait +from marionette_harness import MarionetteTestCase + + +class TestSafeBrowsingInitialDownload(MarionetteTestCase): + v2_file_extensions = [ + "vlpset", + "sbstore", + ] + + v4_file_extensions = [ + "vlpset", + "metadata", + ] + + prefs_download_lists = [ + "urlclassifier.blockedTable", + "urlclassifier.downloadAllowTable", + "urlclassifier.downloadBlockTable", + "urlclassifier.malwareTable", + "urlclassifier.phishTable", + "urlclassifier.trackingTable", + "urlclassifier.trackingWhitelistTable", + ] + + prefs_provider_update_time = { + # Force an immediate download of the safebrowsing files + "browser.safebrowsing.provider.mozilla.nextupdatetime": 1, + } + + prefs_safebrowsing = { + "browser.safebrowsing.debug": True, + "browser.safebrowsing.update.enabled": True, + } + + def get_safebrowsing_files(self, is_v4): + files = [] + + if is_v4: + my_file_extensions = self.v4_file_extensions + else: # v2 + my_file_extensions = self.v2_file_extensions + + for pref_name in self.prefs_download_lists: + base_names = self.marionette.get_pref(pref_name).split(",") + + # moztest- lists are not saved to disk + # pylint --py3k: W1639 + base_names = list( + filter(lambda x: not x.startswith("moztest-"), base_names) + ) + + for ext in my_file_extensions: + files.extend( + [ + "{name}.{ext}".format(name=f, ext=ext) + for f in base_names + if f and f.endswith("-proto") == is_v4 + ] + ) + + return set(sorted(files)) + + def setUp(self): + super(TestSafeBrowsingInitialDownload, self).setUp() + + self.safebrowsing_v2_files = self.get_safebrowsing_files(False) + if any( + f.startswith("goog-") or f.startswith("googpub-") + for f in self.safebrowsing_v2_files + ): + self.prefs_provider_update_time.update( + { + "browser.safebrowsing.provider.google.nextupdatetime": 1, + } + ) + + self.safebrowsing_v4_files = self.get_safebrowsing_files(True) + if any( + f.startswith("goog-") or f.startswith("googpub-") + for f in self.safebrowsing_v4_files + ): + self.prefs_provider_update_time.update( + { + "browser.safebrowsing.provider.google4.nextupdatetime": 1, + } + ) + + # Force the preferences for the new profile + enforce_prefs = self.prefs_safebrowsing + enforce_prefs.update(self.prefs_provider_update_time) + self.marionette.enforce_gecko_prefs(enforce_prefs) + + self.safebrowsing_path = os.path.join( + self.marionette.instance.profile.profile, "safebrowsing" + ) + + def tearDown(self): + try: + # Restart with a fresh profile + self.marionette.restart(in_app=False, clean=True) + finally: + super(TestSafeBrowsingInitialDownload, self).tearDown() + + def test_safe_browsing_initial_download(self): + def check_downloaded(_): + return reduce( + lambda state, pref: state and int(self.marionette.get_pref(pref)) != 1, + list(self.prefs_provider_update_time), + True, + ) + + try: + Wait(self.marionette, timeout=170).until( + check_downloaded, + message="Not all safebrowsing files have been downloaded", + ) + finally: + files_on_disk_toplevel = os.listdir(self.safebrowsing_path) + for f in self.safebrowsing_v2_files: + self.assertIn(f, files_on_disk_toplevel) + + if len(self.safebrowsing_v4_files) > 0: + files_on_disk_google4 = os.listdir( + os.path.join(self.safebrowsing_path, "google4") + ) + for f in self.safebrowsing_v4_files: + self.assertIn(f, files_on_disk_google4) diff --git a/testing/firefox-ui/tests/functional/safebrowsing/test_notification.py b/testing/firefox-ui/tests/functional/safebrowsing/test_notification.py new file mode 100644 index 0000000000..2489542381 --- /dev/null +++ b/testing/firefox-ui/tests/functional/safebrowsing/test_notification.py @@ -0,0 +1,132 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +import time + +from marionette_driver import By, Wait, expected +from marionette_harness import MarionetteTestCase, WindowManagerMixin + + +class TestSafeBrowsingNotificationBar(WindowManagerMixin, MarionetteTestCase): + def setUp(self): + super(TestSafeBrowsingNotificationBar, self).setUp() + + self.test_data = [ + # Unwanted software URL + {"unsafe_page": "https://www.itisatrap.org/firefox/unwanted.html"}, + # Phishing URL info + {"unsafe_page": "https://www.itisatrap.org/firefox/its-a-trap.html"}, + # Malware URL object + {"unsafe_page": "https://www.itisatrap.org/firefox/its-an-attack.html"}, + ] + + self.default_homepage = self.marionette.get_pref("browser.startup.homepage") + + self.marionette.set_pref("browser.safebrowsing.phishing.enabled", True) + self.marionette.set_pref("browser.safebrowsing.malware.enabled", True) + + # Give the browser a little time, because SafeBrowsing.jsm takes a while + # between start up and adding the example urls to the db. + # hg.mozilla.org/mozilla-central/file/46aebcd9481e/browser/base/content/browser.js#l1194 + time.sleep(3) + + # Run this test in a new tab. + new_tab = self.open_tab() + self.marionette.switch_to_window(new_tab) + + def tearDown(self): + try: + self.marionette.clear_pref("browser.safebrowsing.phishing.enabled") + self.marionette.clear_pref("browser.safebrowsing.malware.enabled") + + self.remove_permission("https://www.itisatrap.org", "safe-browsing") + self.close_all_tabs() + finally: + super(TestSafeBrowsingNotificationBar, self).tearDown() + + def test_notification_bar(self): + for item in self.test_data: + unsafe_page = item["unsafe_page"] + + # Return to the unsafe page + # Check "ignore warning" link then notification bar's "get me out" button + self.marionette.navigate(unsafe_page) + # Wait for the DOM to receive events for about:blocked + time.sleep(1) + self.check_ignore_warning_link(unsafe_page) + self.check_get_me_out_of_here_button() + + # Return to the unsafe page + # Check "ignore warning" link then notification bar's "X" button + self.marionette.navigate(unsafe_page) + # Wait for the DOM to receive events for about:blocked + time.sleep(1) + self.check_ignore_warning_link(unsafe_page) + self.check_x_button() + + def get_final_url(self, url): + self.marionette.navigate(url) + return self.marionette.get_url() + + def remove_permission(self, host, permission): + with self.marionette.using_context("chrome"): + self.marionette.execute_script( + """ + let uri = Services.io.newURI(arguments[0], null, null); + let principal = Services.scriptSecurityManager.createContentPrincipal(uri, {}); + Services.perms.removeFromPrincipal(principal, arguments[1]); + """, + script_args=[host, permission], + ) + + def check_ignore_warning_link(self, unsafe_page): + button = self.marionette.find_element(By.ID, "seeDetailsButton") + button.click() + time.sleep(1) + link = self.marionette.find_element(By.ID, "ignore_warning_link") + link.click() + + Wait(self.marionette, timeout=self.marionette.timeout.page_load).until( + expected.element_present(By.ID, "main-feature"), + message='Expected target element "#main-feature" has not been found', + ) + self.assertEqual(self.marionette.get_url(), self.get_final_url(unsafe_page)) + + # Clean up here since the permission gets set in this function + self.remove_permission("https://www.itisatrap.org", "safe-browsing") + + def check_get_me_out_of_here_button(self): + with self.marionette.using_context("chrome"): + notification_box = self.marionette.find_element( + By.CSS_SELECTOR, 'vbox.notificationbox-stack[slot="selected"]' + ) + message = notification_box.find_element( + By.CSS_SELECTOR, "notification-message" + ) + button_container = message.get_property("buttonContainer") + button = button_container.find_element( + By.CSS_SELECTOR, 'button[label="Get me out of here!"]' + ) + button.click() + + Wait(self.marionette, timeout=self.marionette.timeout.page_load).until( + lambda mn: self.default_homepage in mn.get_url(), + message="The default home page has not been loaded", + ) + + def check_x_button(self): + with self.marionette.using_context("chrome"): + notification_box = self.marionette.find_element( + By.CSS_SELECTOR, 'vbox.notificationbox-stack[slot="selected"]' + ) + message = notification_box.find_element( + By.CSS_SELECTOR, "notification-message[value=blocked-badware-page]" + ) + button = message.get_property("closeButtonEl") + button.click() + + Wait(self.marionette, timeout=self.marionette.timeout.page_load).until( + expected.element_stale(button), + message="The notification bar has not been closed", + ) diff --git a/testing/firefox-ui/tests/functional/safebrowsing/test_warning_pages.py b/testing/firefox-ui/tests/functional/safebrowsing/test_warning_pages.py new file mode 100644 index 0000000000..1e5b3e2f56 --- /dev/null +++ b/testing/firefox-ui/tests/functional/safebrowsing/test_warning_pages.py @@ -0,0 +1,138 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +import time + +from marionette_driver import By, Wait, expected +from marionette_harness import MarionetteTestCase, WindowManagerMixin + + +class TestSafeBrowsingWarningPages(WindowManagerMixin, MarionetteTestCase): + def setUp(self): + super(TestSafeBrowsingWarningPages, self).setUp() + + self.urls = [ + # Unwanted software URL + "https://www.itisatrap.org/firefox/unwanted.html", + # Phishing URL + "https://www.itisatrap.org/firefox/its-a-trap.html", + # Malware URL + "https://www.itisatrap.org/firefox/its-an-attack.html", + ] + + self.default_homepage = self.marionette.get_pref("browser.startup.homepage") + self.support_page = self.marionette.absolute_url("support.html?topic=") + + self.marionette.set_pref("app.support.baseURL", self.support_page) + self.marionette.set_pref("browser.safebrowsing.phishing.enabled", True) + self.marionette.set_pref("browser.safebrowsing.malware.enabled", True) + + # Give the browser a little time, because SafeBrowsing.jsm takes a + # while between start up and adding the example urls to the db. + # hg.mozilla.org/mozilla-central/file/46aebcd9481e/browser/base/content/browser.js#l1194 + time.sleep(3) + + # Run this test in a new tab. + new_tab = self.open_tab() + self.marionette.switch_to_window(new_tab) + + def tearDown(self): + try: + self.marionette.clear_pref("app.support.baseURL") + self.marionette.clear_pref("browser.safebrowsing.malware.enabled") + self.marionette.clear_pref("browser.safebrowsing.phishing.enabled") + + self.remove_permission("https://www.itisatrap.org", "safe-browsing") + self.close_all_tabs() + finally: + super(TestSafeBrowsingWarningPages, self).tearDown() + + def test_warning_pages(self): + for unsafe_page in self.urls: + # Load a test page, then test the get me out button + self.marionette.navigate(unsafe_page) + # Wait for the DOM to receive events for about:blocked + time.sleep(1) + self.check_get_me_out_of_here_button(unsafe_page) + + # Load the test page again, then test the report button + self.marionette.navigate(unsafe_page) + # Wait for the DOM to receive events for about:blocked + time.sleep(1) + self.check_report_link(unsafe_page) + + # Load the test page again, then test the ignore warning button + self.marionette.navigate(unsafe_page) + # Wait for the DOM to receive events for about:blocked + time.sleep(1) + self.check_ignore_warning_button(unsafe_page) + + def get_final_url(self, url): + self.marionette.navigate(url) + return self.marionette.get_url() + + def remove_permission(self, host, permission): + with self.marionette.using_context("chrome"): + self.marionette.execute_script( + """ + let uri = Services.io.newURI(arguments[0], null, null); + let principal = Services.scriptSecurityManager.createContentPrincipal(uri, {}); + Services.perms.removeFromPrincipal(principal, arguments[1]); + """, + script_args=[host, permission], + ) + + def check_get_me_out_of_here_button(self, unsafe_page): + button = self.marionette.find_element(By.ID, "goBackButton") + button.click() + + Wait(self.marionette, timeout=self.marionette.timeout.page_load).until( + lambda mn: self.default_homepage in mn.get_url() + ) + + def check_report_link(self, unsafe_page): + # Get the URL of the support site for phishing and malware. This may result in a redirect. + with self.marionette.using_context("chrome"): + url = self.marionette.execute_script( + """ + return Services.urlFormatter.formatURLPref("app.support.baseURL") + + "phishing-malware"; + """ + ) + + button = self.marionette.find_element(By.ID, "seeDetailsButton") + button.click() + link = self.marionette.find_element(By.ID, "firefox_support") + link.click() + + # Wait for the button to become stale, whereby a longer timeout is needed + # here to not fail in case of slow connections. + Wait(self.marionette, timeout=self.marionette.timeout.page_load).until( + expected.element_stale(button) + ) + + # Wait for page load to be completed, so we can verify the URL even if a redirect happens. + # TODO: Bug 1140470: use replacement for mozmill's waitforPageLoad + expected_url = self.get_final_url(url) + Wait(self.marionette, timeout=self.marionette.timeout.page_load).until( + lambda mn: expected_url == mn.get_url(), + message="The expected URL '{}' has not been loaded".format(expected_url), + ) + + topic = self.marionette.find_element(By.ID, "topic") + self.assertEqual(topic.text, "phishing-malware") + + def check_ignore_warning_button(self, unsafe_page): + button = self.marionette.find_element(By.ID, "seeDetailsButton") + button.click() + link = self.marionette.find_element(By.ID, "ignore_warning_link") + link.click() + + Wait(self.marionette, timeout=self.marionette.timeout.page_load).until( + expected.element_present(By.ID, "main-feature") + ) + self.assertEqual(self.marionette.get_url(), self.get_final_url(unsafe_page)) + + # Clean up by removing safe browsing permission for unsafe page + self.remove_permission("https://www.itisatrap.org", "safe-browsing") diff --git a/testing/firefox-ui/tests/functional/security/manifest.toml b/testing/firefox-ui/tests/functional/security/manifest.toml new file mode 100644 index 0000000000..72bea151e7 --- /dev/null +++ b/testing/firefox-ui/tests/functional/security/manifest.toml @@ -0,0 +1,3 @@ +[DEFAULT] + +["test_ssl_status_after_restart.py"] diff --git a/testing/firefox-ui/tests/functional/security/test_ssl_status_after_restart.py b/testing/firefox-ui/tests/functional/security/test_ssl_status_after_restart.py new file mode 100644 index 0000000000..3684433f6f --- /dev/null +++ b/testing/firefox-ui/tests/functional/security/test_ssl_status_after_restart.py @@ -0,0 +1,56 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +from marionette_driver import By, Wait +from marionette_harness import MarionetteTestCase, WindowManagerMixin + + +class TestSSLStatusAfterRestart(WindowManagerMixin, MarionetteTestCase): + def setUp(self): + super(TestSSLStatusAfterRestart, self).setUp() + self.marionette.set_context("chrome") + + self.test_url = "https://www.itisatrap.org/" + + # Set browser to restore previous session + self.marionette.set_pref("browser.startup.page", 3) + # Disable rcwn to make cache behavior deterministic + self.marionette.set_pref("network.http.rcwn.enable", False) + + def tearDown(self): + self.marionette.clear_pref("browser.startup.page") + self.marionette.clear_pref("network.http.rcwn.enable") + + super(TestSSLStatusAfterRestart, self).tearDown() + + def test_ssl_status_after_restart(self): + with self.marionette.using_context("content"): + self.marionette.navigate(self.test_url) + self.verify_certificate_status(self.test_url) + + self.marionette.restart(in_app=True) + + self.verify_certificate_status(self.test_url) + + def verify_certificate_status(self, url): + with self.marionette.using_context("content"): + Wait(self.marionette).until( + lambda _: self.marionette.get_url() == url, + message="Expected URL loaded", + ) + + identity_box = self.marionette.find_element(By.ID, "identity-box") + self.assertEqual(identity_box.get_attribute("pageproxystate"), "valid") + + class_list = self.marionette.execute_script( + """ + const names = []; + for (const name of arguments[0].classList) { + names.push(name); + } + return names; + """, + script_args=[identity_box], + ) + self.assertIn("verifiedDomain", class_list) |