summaryrefslogtreecommitdiffstats
path: root/mobile/android/geckoview/src/androidTest/assets
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
commit2aa4a82499d4becd2284cdb482213d541b8804dd (patch)
treeb80bf8bf13c3766139fbacc530efd0dd9d54394c /mobile/android/geckoview/src/androidTest/assets
parentInitial commit. (diff)
downloadfirefox-upstream.tar.xz
firefox-upstream.zip
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'mobile/android/geckoview/src/androidTest/assets')
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/moz.build69
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/.eslintrc.js14
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/background.js140
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/button/beasts-32-light.pngbin0 -> 1395 bytes
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/button/beasts-32.pngbin0 -> 1093 bytes
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/button/expected.pngbin0 -> 1074 bytes
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/button/geo-19.pngbin0 -> 225 bytes
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/button/geo-38.pngbin0 -> 225 bytes
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/button/icon.svg1
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/content.js4
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/manifest.json41
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/test-open-popup-browser-action.html11
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/test-open-popup-browser-action.js7
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/test-open-popup-page-action.html11
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/test-open-popup-page-action.js7
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/test-popup.html9
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/test-popup.js3
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/borderify-missing-id.xpibin0 -> 1827 bytes
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/borderify-unsigned.xpibin0 -> 1882 bytes
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/borderify.xpibin0 -> 9221 bytes
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/borderify/borderify.js1
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/borderify/icons/border-48.pngbin0 -> 225 bytes
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/borderify/icons/icon.svg1
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/borderify/manifest.json20
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/browsing-data-built-in/background.js44
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/browsing-data-built-in/manifest.json15
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/browsing-data/background.js8
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/browsing-data/manifest.json15
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/download-flags-false/download.js3
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/download-flags-false/manifest.json17
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/download-flags-true/download.js16
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/download-flags-true/manifest.json17
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/dummy.xpibin0 -> 544 bytes
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/dummy/dummy.js1
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/dummy/manifest.json21
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/extension-page-restore/manifest.json14
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/extension-page-restore/tab-script.js5
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/extension-page-restore/tab.html9
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/extension-page-update/background-script.js7
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/extension-page-update/manifest.json26
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/extension-page-update/tab-script.js2
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/extension-page-update/tab.html9
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/extension-page-update/tabs.js1
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/messaging-content/manifest.json24
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/messaging-content/messaging.js29
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/messaging-iframe/manifest.json25
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/messaging-iframe/messaging.js11
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/messaging/background.js28
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/messaging/icons/border-48.pngbin0 -> 225 bytes
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/messaging/manifest.json21
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/notification-test/background.js6
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/notification-test/manifest.json17
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/openoptionspage-1/background.js1
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/openoptionspage-1/manifest.json22
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/openoptionspage-2/background.js1
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/openoptionspage-2/manifest.json22
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/page-history/manifest.json11
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/page-history/page.html8
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/redirect-to-android-resource/background.js39
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/redirect-to-android-resource/manifest.json25
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/redirect-to-android-resource/web-accessible-script.js3
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/tabs-activate-remove-2/background.js16
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/tabs-activate-remove-2/manifest.json17
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/tabs-activate-remove/background.js16
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/tabs-activate-remove/manifest.json17
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/tabs-create-2/background.js4
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/tabs-create-2/manifest.json18
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/tabs-create-remove/background.js3
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/tabs-create-remove/manifest.json16
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/tabs-create/background.js1
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/tabs-create/manifest.json17
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/tabs-remove/background.js3
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/tabs-remove/manifest.json17
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/test-support/TestSupportChild.jsm37
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/test-support/background.js88
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/test-support/manifest.json41
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/test-support/test-api.js205
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/test-support/test-schema.json174
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/test-support/test-support.js48
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/update-1/borderify.js1
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/update-1/manifest.json18
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/update-2/borderify.js1
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/update-2/manifest.json17
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/update-postpone-1/background.js3
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/update-postpone-1/borderify.js1
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/update-postpone-1/manifest.json21
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/update-postpone-2/borderify.js1
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/update-postpone-2/manifest.json17
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/update-with-perms-1/borderify.js1
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/update-with-perms-1/manifest.json18
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/update-with-perms-2/borderify.js1
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/update-with-perms-2/manifest.json20
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-aria-comboboxes.html11
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-checkbox.html11
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-clipboard.html8
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-collection.html19
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-expandable.html8
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-headings.html11
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-links.html12
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-live-region-atomic.html8
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-live-region-descendant.html8
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-live-region-image-labeled-by.html12
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-live-region-image.html11
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-live-region.html8
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-move-caret-accessibility-focus.html8
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-mutation.html8
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-range.html8
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-scroll.html8
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-selectable.html12
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-text-entry-node.html10
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-tree.html8
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/audio/owl.mp3bin0 -> 67430 bytes
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/autoplay.html11
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/badVideoPath.html11
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/beforeunload.html14
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/clickToReload.html10
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/colors.html14
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/data_uri.html10
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/download.html16
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/fixedbottom.html16
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/fixedpercent.html25
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/fixedvh.html25
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/form_blank.html14
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/forms.html31
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/forms2.html24
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/forms3.html14
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/forms4.html14
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/forms_autocomplete.html23
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/forms_id_value.html12
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/fullscreen.html9
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/getusermedia_xorigin_container.html49
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/getusermedia_xorigin_iframe.html36
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/hello.html10
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/hello2.html9
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/hungScript.html14
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/iframe_100_percent_height_no_scrollable.html56
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/iframe_100_percent_height_scrollable.html56
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/iframe_98vh_no_scrollable.html50
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/iframe_98vh_scrollable.html50
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/iframe_hello.html10
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/iframe_redirect_automation.html10
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/iframe_redirect_local.html10
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/iframe_unknown_protocol.html10
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/images/test.gifbin0 -> 23961 bytes
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/inputs.html22
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/links.html24
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/loremIpsum.html16
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/manifest.webmanifest17
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/media_session_default1.html13
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/media_session_dom1.html99
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/mp4.html11
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/newSession.html10
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/newSession_child.html9
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/ogg.html11
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/popup.html12
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/prompts.html26
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/push/push.html10
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/push/push.js44
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/push/sw.js26
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/reflect_local_storage_into_title.html17
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/resubmit.html12
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/root_100_percent_height.html36
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/root_100vh.html35
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/root_98vh.html35
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/saveState.html18
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/scroll.html46
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/selectionAction_frame.html6
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/simple_redirect.sjs5
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/titleChange.html16
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/touch.html54
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/touchstart.html37
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/trackers.html14
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/transparent.gifbin0 -> 43 bytes
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/update_manifest.json40
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/videos/gizmo.webmbin0 -> 159035 bytes
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/videos/short.mp4bin0 -> 13651 bytes
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/videos/video.oggbin0 -> 285310 bytes
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/viewport.html16
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/webm.html11
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/worker/open_window.html11
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/worker/open_window.js15
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/worker/open_window_target.html9
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/worker/service-worker.js15
183 files changed, 3370 insertions, 0 deletions
diff --git a/mobile/android/geckoview/src/androidTest/assets/moz.build b/mobile/android/geckoview/src/androidTest/assets/moz.build
new file mode 100644
index 0000000000..bba1358dd2
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/moz.build
@@ -0,0 +1,69 @@
+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
+# vim: set filetype=python:
+# 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/.
+
+addons = {
+ "browsing-data": [
+ "background.js",
+ "manifest.json",
+ ],
+ "tabs-activate-remove": [
+ "background.js",
+ "manifest.json",
+ ],
+ "tabs-activate-remove-2": [
+ "background.js",
+ "manifest.json",
+ ],
+ "update-1": [
+ "borderify.js",
+ "manifest.json",
+ ],
+ "update-2": [
+ "borderify.js",
+ "manifest.json",
+ ],
+ "update-postpone-1": [
+ "background.js",
+ "borderify.js",
+ "manifest.json",
+ ],
+ "update-postpone-2": [
+ "borderify.js",
+ "manifest.json",
+ ],
+ "update-with-perms-1": [
+ "borderify.js",
+ "manifest.json",
+ ],
+ "update-with-perms-2": [
+ "borderify.js",
+ "manifest.json",
+ ],
+ "page-history": [
+ "page.html",
+ "manifest.json",
+ ],
+ "download-flags-true": [
+ "download.js",
+ "manifest.json",
+ ],
+ "download-flags-false": [
+ "download.js",
+ "manifest.json",
+ ],
+}
+
+for addon, files in addons.items():
+ indir = "web_extensions/%s" % addon
+ xpi = "%s.xpi" % indir
+ inputs = [indir]
+ for file in files:
+ inputs.append("%s/%s" % (indir, file))
+ GeneratedFile(
+ xpi, script="/toolkit/mozapps/extensions/test/create_xpi.py", inputs=inputs
+ )
+
+ TEST_HARNESS_FILES.testing.mochitest.tests.junit += ["!%s" % xpi]
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/.eslintrc.js b/mobile/android/geckoview/src/androidTest/assets/web_extensions/.eslintrc.js
new file mode 100644
index 0000000000..41c5ed8080
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/.eslintrc.js
@@ -0,0 +1,14 @@
+"use strict";
+
+module.exports = {
+ env: {
+ webextensions: true,
+ },
+ globals: {
+ ExtensionAPI: true,
+ // available to frameScripts
+ addMessageListener: false,
+ content: false,
+ sendAsyncMessage: false,
+ },
+};
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/background.js b/mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/background.js
new file mode 100644
index 0000000000..e4e54cc4d2
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/background.js
@@ -0,0 +1,140 @@
+const port = browser.runtime.connectNative("browser");
+port.onMessage.addListener(message => {
+ handleMessage(message, null);
+});
+
+browser.runtime.onMessage.addListener((message, sender) => {
+ handleMessage(message, sender.tab.id);
+});
+
+browser.pageAction.onClicked.addListener(tab => {
+ port.postMessage({ method: "onClicked", tabId: tab.id, type: "pageAction" });
+});
+
+browser.browserAction.onClicked.addListener(tab => {
+ port.postMessage({
+ method: "onClicked",
+ tabId: tab.id,
+ type: "browserAction",
+ });
+});
+
+function handlePageActionMessage(message, tabId) {
+ switch (message.action) {
+ case "enable":
+ browser.pageAction.show(tabId);
+ break;
+
+ case "disable":
+ browser.pageAction.hide(tabId);
+ break;
+
+ case "setPopup":
+ browser.pageAction.setPopup({
+ tabId,
+ popup: message.popup,
+ });
+ break;
+
+ case "setTitle":
+ browser.pageAction.setTitle({
+ tabId,
+ title: message.title,
+ });
+ break;
+
+ case "setIcon":
+ browser.pageAction.setIcon({
+ tabId,
+ imageData: message.imageData,
+ path: message.path,
+ });
+ break;
+
+ default:
+ throw new Error(`Page Action does not support ${message.action}`);
+ }
+}
+
+function handleBrowserActionMessage(message, tabId) {
+ switch (message.action) {
+ case "enable":
+ browser.browserAction.enable(tabId);
+ break;
+
+ case "disable":
+ browser.browserAction.disable(tabId);
+ break;
+
+ case "setBadgeText":
+ browser.browserAction.setBadgeText({
+ tabId,
+ text: message.text,
+ });
+ break;
+
+ case "setBadgeTextColor":
+ browser.browserAction.setBadgeTextColor({
+ tabId,
+ color: message.color,
+ });
+ break;
+
+ case "setBadgeBackgroundColor":
+ browser.browserAction.setBadgeBackgroundColor({
+ tabId,
+ color: message.color,
+ });
+ break;
+
+ case "setPopup":
+ browser.browserAction.setPopup({
+ tabId,
+ popup: message.popup,
+ });
+ break;
+
+ case "setTitle":
+ browser.browserAction.setTitle({
+ tabId,
+ title: message.title,
+ });
+ break;
+
+ case "setIcon":
+ browser.browserAction.setIcon({
+ tabId,
+ imageData: message.imageData,
+ path: message.path,
+ });
+ break;
+
+ default:
+ throw new Error(`Browser Action does not support ${message.action}`);
+ }
+}
+
+function handleMessage(message, tabId) {
+ switch (message.type) {
+ case "ping":
+ port.postMessage({ method: "pong" });
+ return;
+
+ case "load":
+ browser.tabs.update(tabId, {
+ url: message.url,
+ });
+ return;
+
+ case "browserAction":
+ handleBrowserActionMessage(message, tabId);
+ return;
+
+ case "pageAction":
+ handlePageActionMessage(message, tabId);
+ return;
+
+ default:
+ throw new Error(`Unsupported message type ${message.type}`);
+ }
+}
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/button/beasts-32-light.png b/mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/button/beasts-32-light.png
new file mode 100644
index 0000000000..dbed714c56
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/button/beasts-32-light.png
Binary files differ
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/button/beasts-32.png b/mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/button/beasts-32.png
new file mode 100644
index 0000000000..89863ccec7
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/button/beasts-32.png
Binary files differ
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/button/expected.png b/mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/button/expected.png
new file mode 100644
index 0000000000..aea2c19784
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/button/expected.png
Binary files differ
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/button/geo-19.png b/mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/button/geo-19.png
new file mode 100644
index 0000000000..90687de26d
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/button/geo-19.png
Binary files differ
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/button/geo-38.png b/mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/button/geo-38.png
new file mode 100644
index 0000000000..90687de26d
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/button/geo-38.png
Binary files differ
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/button/icon.svg b/mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/button/icon.svg
new file mode 100644
index 0000000000..dd1fae7d15
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/button/icon.svg
@@ -0,0 +1 @@
+<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'><svg enable-background="new 0 0 500 500" height="500px" id="Layer_1" version="1.1" viewBox="0 0 500 500" width="500px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><path clip-rule="evenodd" d="M131.889,150.061v63.597h-27.256 c-20.079,0-36.343,16.263-36.343,36.342v181.711c0,20.078,16.264,36.34,36.343,36.34h290.734c20.078,0,36.345-16.262,36.345-36.34 V250c0-20.079-16.267-36.342-36.345-36.342h-27.254v-63.597c0-65.232-52.882-118.111-118.112-118.111 S131.889,84.828,131.889,150.061z M177.317,213.658v-63.597c0-40.157,32.525-72.685,72.683-72.685 c40.158,0,72.685,32.528,72.685,72.685v63.597H177.317z M213.658,313.599c0-20.078,16.263-36.341,36.342-36.341 s36.341,16.263,36.341,36.341c0,12.812-6.634,24.079-16.625,30.529c0,0,3.55,21.446,7.542,46.699 c0,7.538-6.087,13.625-13.629,13.625h-27.258c-7.541,0-13.627-6.087-13.627-13.625l7.542-46.699 C220.294,337.678,213.658,326.41,213.658,313.599z" fill="#010101" fill-rule="evenodd"/></svg> \ No newline at end of file
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/content.js b/mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/content.js
new file mode 100644
index 0000000000..eaa2467df0
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/content.js
@@ -0,0 +1,4 @@
+const port = browser.runtime.connectNative("browser");
+port.onMessage.addListener(message => {
+ browser.runtime.sendMessage(message);
+});
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/manifest.json b/mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/manifest.json
new file mode 100644
index 0000000000..0d0b3978df
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/manifest.json
@@ -0,0 +1,41 @@
+{
+ "manifest_version": 2,
+ "name": "actions",
+ "version": "1.0",
+ "description": "Defines Page and Browser actions",
+ "applications": {
+ "gecko": {
+ "id": "actions@tests.mozilla.org"
+ }
+ },
+ "browser_action": {
+ "default_title": "Test action default",
+ "theme_icons": [{
+ "light": "button/beasts-32-light.png",
+ "dark": "button/beasts-32.png",
+ "size": 32
+ }]
+ },
+ "page_action": {
+ "default_title": "Test action default",
+ "default_icon": {
+ "19": "button/geo-19.png",
+ "38": "button/geo-38.png"
+ }
+ },
+ "background": {
+ "scripts": ["background.js"]
+ },
+ "content_scripts": [
+ {
+ "matches": ["<all_urls>"],
+ "js": ["content.js"]
+ }
+ ],
+ "permissions": [
+ "tabs",
+ "geckoViewAddons",
+ "nativeMessaging",
+ "nativeMessagingFromContent"
+ ]
+}
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/test-open-popup-browser-action.html b/mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/test-open-popup-browser-action.html
new file mode 100644
index 0000000000..fd9d0a26fd
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/test-open-popup-browser-action.html
@@ -0,0 +1,11 @@
+<html>
+<head>
+ <meta charset="utf-8">
+ <script type="text/javascript" src="test-open-popup-browser-action.js"></script>
+</head>
+<body>
+ <body style="height: 100%">
+ <p>Hello, world!</p>
+ </body>
+</body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/test-open-popup-browser-action.js b/mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/test-open-popup-browser-action.js
new file mode 100644
index 0000000000..cde31235ac
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/test-open-popup-browser-action.js
@@ -0,0 +1,7 @@
+window.addEventListener("DOMContentLoaded", init);
+
+function init() {
+ document.body.addEventListener("click", event => {
+ browser.browserAction.openPopup();
+ });
+}
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/test-open-popup-page-action.html b/mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/test-open-popup-page-action.html
new file mode 100644
index 0000000000..bbf5c5d61d
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/test-open-popup-page-action.html
@@ -0,0 +1,11 @@
+<html>
+<head>
+ <meta charset="utf-8">
+ <script type="text/javascript" src="test-open-popup-page-action.js"></script>
+</head>
+<body>
+ <body style="height: 100%">
+ <p>Hello, world!</p>
+ </body>
+</body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/test-open-popup-page-action.js b/mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/test-open-popup-page-action.js
new file mode 100644
index 0000000000..f16d96333f
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/test-open-popup-page-action.js
@@ -0,0 +1,7 @@
+window.addEventListener("DOMContentLoaded", init);
+
+function init() {
+ document.body.addEventListener("click", event => {
+ browser.pageAction.openPopup();
+ });
+}
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/test-popup.html b/mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/test-popup.html
new file mode 100644
index 0000000000..80fce17886
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/test-popup.html
@@ -0,0 +1,9 @@
+<html>
+ <head>
+ <meta charset="utf-8">
+ <script src="test-popup.js"></script>
+ </head>
+ <body>
+ <h1> HELLO </h1>
+ </body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/test-popup.js b/mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/test-popup.js
new file mode 100644
index 0000000000..47271e744c
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/test-popup.js
@@ -0,0 +1,3 @@
+window.addEventListener("DOMContentLoaded", () => {
+ window.close();
+});
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/borderify-missing-id.xpi b/mobile/android/geckoview/src/androidTest/assets/web_extensions/borderify-missing-id.xpi
new file mode 100644
index 0000000000..19ce0d7f0f
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/borderify-missing-id.xpi
Binary files differ
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/borderify-unsigned.xpi b/mobile/android/geckoview/src/androidTest/assets/web_extensions/borderify-unsigned.xpi
new file mode 100644
index 0000000000..fd395d13df
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/borderify-unsigned.xpi
Binary files differ
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/borderify.xpi b/mobile/android/geckoview/src/androidTest/assets/web_extensions/borderify.xpi
new file mode 100644
index 0000000000..1ed97f1047
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/borderify.xpi
Binary files differ
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/borderify/borderify.js b/mobile/android/geckoview/src/androidTest/assets/web_extensions/borderify/borderify.js
new file mode 100644
index 0000000000..9c3728b381
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/borderify/borderify.js
@@ -0,0 +1 @@
+document.body.style.border = "5px solid red";
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/borderify/icons/border-48.png b/mobile/android/geckoview/src/androidTest/assets/web_extensions/borderify/icons/border-48.png
new file mode 100644
index 0000000000..90687de26d
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/borderify/icons/border-48.png
Binary files differ
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/borderify/icons/icon.svg b/mobile/android/geckoview/src/androidTest/assets/web_extensions/borderify/icons/icon.svg
new file mode 100644
index 0000000000..dd1fae7d15
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/borderify/icons/icon.svg
@@ -0,0 +1 @@
+<?xml version="1.0" ?><!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd'><svg enable-background="new 0 0 500 500" height="500px" id="Layer_1" version="1.1" viewBox="0 0 500 500" width="500px" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><path clip-rule="evenodd" d="M131.889,150.061v63.597h-27.256 c-20.079,0-36.343,16.263-36.343,36.342v181.711c0,20.078,16.264,36.34,36.343,36.34h290.734c20.078,0,36.345-16.262,36.345-36.34 V250c0-20.079-16.267-36.342-36.345-36.342h-27.254v-63.597c0-65.232-52.882-118.111-118.112-118.111 S131.889,84.828,131.889,150.061z M177.317,213.658v-63.597c0-40.157,32.525-72.685,72.683-72.685 c40.158,0,72.685,32.528,72.685,72.685v63.597H177.317z M213.658,313.599c0-20.078,16.263-36.341,36.342-36.341 s36.341,16.263,36.341,36.341c0,12.812-6.634,24.079-16.625,30.529c0,0,3.55,21.446,7.542,46.699 c0,7.538-6.087,13.625-13.629,13.625h-27.258c-7.541,0-13.627-6.087-13.627-13.625l7.542-46.699 C220.294,337.678,213.658,326.41,213.658,313.599z" fill="#010101" fill-rule="evenodd"/></svg> \ No newline at end of file
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/borderify/manifest.json b/mobile/android/geckoview/src/androidTest/assets/web_extensions/borderify/manifest.json
new file mode 100644
index 0000000000..75db8fc0aa
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/borderify/manifest.json
@@ -0,0 +1,20 @@
+{
+ "manifest_version": 2,
+ "name": "Borderify",
+ "version": "1.0",
+ "description": "Adds a red border to all webpages matching example.com.",
+ "applications": {
+ "gecko": {
+ "id": "borderify@tests.mozilla.org"
+ }
+ },
+ "icons": {
+ "48": "icons/border-48.png"
+ },
+ "content_scripts": [
+ {
+ "matches": ["*://*.example.com/*"],
+ "js": ["borderify.js"]
+ }
+ ]
+}
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/browsing-data-built-in/background.js b/mobile/android/geckoview/src/androidTest/assets/web_extensions/browsing-data-built-in/background.js
new file mode 100644
index 0000000000..d0ae54b3dd
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/browsing-data-built-in/background.js
@@ -0,0 +1,44 @@
+const port = browser.runtime.connectNative("browser");
+
+async function apiCall(message) {
+ const { type, since, removalOptions, dataTypes } = message;
+ switch (type) {
+ case "clear-downloads":
+ await browser.browsingData.removeDownloads({ since });
+ break;
+ case "clear-form-data":
+ await browser.browsingData.removeFormData({ since });
+ break;
+ case "clear-history":
+ await browser.browsingData.removeHistory({ since });
+ break;
+ case "clear-passwords":
+ await browser.browsingData.removePasswords({ since });
+ break;
+ case "clear":
+ await browser.browsingData.remove(removalOptions, dataTypes);
+ break;
+ case "get-settings":
+ return browser.browsingData.settings();
+ }
+ return null;
+}
+
+port.onMessage.addListener(async message => {
+ const { uuid } = message;
+ try {
+ const result = await apiCall(message);
+ port.postMessage({
+ type: "response",
+ result,
+ uuid,
+ });
+ } catch (exception) {
+ const { message } = exception;
+ port.postMessage({
+ type: "error",
+ error: message,
+ uuid,
+ });
+ }
+});
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/browsing-data-built-in/manifest.json b/mobile/android/geckoview/src/androidTest/assets/web_extensions/browsing-data-built-in/manifest.json
new file mode 100644
index 0000000000..23df4d8338
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/browsing-data-built-in/manifest.json
@@ -0,0 +1,15 @@
+{
+ "manifest_version": 2,
+ "name": "BrowsingData",
+ "browser_specific_settings": {
+ "gecko": {
+ "id": "browsing-data-settings@tests.mozilla.org"
+ }
+ },
+ "version": "1.0",
+ "description": "Tests the browsingData API",
+ "background": {
+ "scripts": ["background.js"]
+ },
+ "permissions": ["browsingData", "geckoViewAddons", "nativeMessaging"]
+}
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/browsing-data/background.js b/mobile/android/geckoview/src/androidTest/assets/web_extensions/browsing-data/background.js
new file mode 100644
index 0000000000..4597e3328b
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/browsing-data/background.js
@@ -0,0 +1,8 @@
+browser.browsingData.removeDownloads({ since: 10001 });
+browser.browsingData.removeFormData({ since: 10002 });
+browser.browsingData.removeHistory({ since: 10003 });
+browser.browsingData.removePasswords({ since: 10004 });
+browser.browsingData.remove(
+ { since: 10005 },
+ { downloads: true, cookies: true }
+);
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/browsing-data/manifest.json b/mobile/android/geckoview/src/androidTest/assets/web_extensions/browsing-data/manifest.json
new file mode 100644
index 0000000000..f7af03c25e
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/browsing-data/manifest.json
@@ -0,0 +1,15 @@
+{
+ "manifest_version": 2,
+ "name": "BrowsingData",
+ "browser_specific_settings": {
+ "gecko": {
+ "id": "browsing-data@tests.mozilla.org"
+ }
+ },
+ "version": "1.0",
+ "description": "Tests the browsingData API",
+ "background": {
+ "scripts": ["background.js"]
+ },
+ "permissions": ["browsingData"]
+}
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/download-flags-false/download.js b/mobile/android/geckoview/src/androidTest/assets/web_extensions/download-flags-false/download.js
new file mode 100644
index 0000000000..68f51ea5d8
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/download-flags-false/download.js
@@ -0,0 +1,3 @@
+browser.downloads.download({
+ url: "http://localhost:4245/assets/www/images/test.gif",
+});
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/download-flags-false/manifest.json b/mobile/android/geckoview/src/androidTest/assets/web_extensions/download-flags-false/manifest.json
new file mode 100644
index 0000000000..67adf58933
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/download-flags-false/manifest.json
@@ -0,0 +1,17 @@
+{
+ "manifest_version": 2,
+ "name": "Download",
+ "version": "1.0",
+ "applications": {
+ "gecko": {
+ "id": "download-flags-false@tests.mozilla.org"
+ }
+ },
+ "description": "Downloads a file",
+ "background": {
+ "scripts": ["download.js"]
+ },
+ "permissions": [
+ "downloads"
+ ]
+}
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/download-flags-true/download.js b/mobile/android/geckoview/src/androidTest/assets/web_extensions/download-flags-true/download.js
new file mode 100644
index 0000000000..4bb06a5cbb
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/download-flags-true/download.js
@@ -0,0 +1,16 @@
+browser.downloads.download({
+ url: "http://localhost:4245/assets/www/images/test.gif",
+ filename: "banana.gif",
+ method: "POST",
+ body: "postbody",
+ headers: [
+ {
+ name: "User-Agent",
+ value: "Mozilla Firefox",
+ },
+ ],
+ allowHttpErrors: true,
+ conflictAction: "overwrite",
+ saveAs: true,
+ incognito: true,
+});
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/download-flags-true/manifest.json b/mobile/android/geckoview/src/androidTest/assets/web_extensions/download-flags-true/manifest.json
new file mode 100644
index 0000000000..70332e226e
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/download-flags-true/manifest.json
@@ -0,0 +1,17 @@
+{
+ "manifest_version": 2,
+ "name": "Download",
+ "version": "1.0",
+ "applications": {
+ "gecko": {
+ "id": "download-flags-true@tests.mozilla.org"
+ }
+ },
+ "description": "Downloads a file",
+ "background": {
+ "scripts": ["download.js"]
+ },
+ "permissions": [
+ "downloads"
+ ]
+}
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/dummy.xpi b/mobile/android/geckoview/src/androidTest/assets/web_extensions/dummy.xpi
new file mode 100644
index 0000000000..0e0f549ceb
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/dummy.xpi
Binary files differ
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/dummy/dummy.js b/mobile/android/geckoview/src/androidTest/assets/web_extensions/dummy/dummy.js
new file mode 100644
index 0000000000..2a49c0d665
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/dummy/dummy.js
@@ -0,0 +1 @@
+console.log("Hi, I'm a dummy.");
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/dummy/manifest.json b/mobile/android/geckoview/src/androidTest/assets/web_extensions/dummy/manifest.json
new file mode 100644
index 0000000000..88a563ec7d
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/dummy/manifest.json
@@ -0,0 +1,21 @@
+{
+ "manifest_version": 2,
+ "name": "Dummy",
+ "version": "1.0",
+ "applications": {
+ "gecko": {
+ "id": "dummy@tests.mozilla.org"
+ }
+ },
+ "description": "Doesn't do anything.",
+ "options_ui": {
+ "open_in_tab": true,
+ "page": "options.html"
+ },
+ "content_scripts": [
+ {
+ "matches": ["*://*.example.com/*"],
+ "js": ["dummy.js"]
+ }
+ ]
+}
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/extension-page-restore/manifest.json b/mobile/android/geckoview/src/androidTest/assets/web_extensions/extension-page-restore/manifest.json
new file mode 100644
index 0000000000..d8c41e78b4
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/extension-page-restore/manifest.json
@@ -0,0 +1,14 @@
+{
+ "manifest_version": 2,
+ "name": "Test messages sent from extensions when restoring",
+ "version": "1.0",
+ "applications": {
+ "gecko": {
+ "id": "extension-page-restoring@tests.mozilla.org"
+ }
+ },
+ "permissions": [
+ "geckoViewAddons",
+ "nativeMessaging"
+ ]
+}
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/extension-page-restore/tab-script.js b/mobile/android/geckoview/src/androidTest/assets/web_extensions/extension-page-restore/tab-script.js
new file mode 100644
index 0000000000..66866bbd37
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/extension-page-restore/tab-script.js
@@ -0,0 +1,5 @@
+browser.runtime.sendNativeMessage("browser1", "HELLO_FROM_PAGE_1");
+browser.runtime.sendNativeMessage("browser2", "HELLO_FROM_PAGE_2");
+
+const port = browser.runtime.connectNative("browser1");
+port.postMessage("HELLO_FROM_PORT");
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/extension-page-restore/tab.html b/mobile/android/geckoview/src/androidTest/assets/web_extensions/extension-page-restore/tab.html
new file mode 100644
index 0000000000..f87c77a5d2
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/extension-page-restore/tab.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html><html>
+<head>
+ <meta charset="utf-8">
+</head>
+<body>
+ <h1>Hello World!</h1>
+ <script src=tab-script.js></script>
+</body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/extension-page-update/background-script.js b/mobile/android/geckoview/src/androidTest/assets/web_extensions/extension-page-update/background-script.js
new file mode 100644
index 0000000000..43e2b44f96
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/extension-page-update/background-script.js
@@ -0,0 +1,7 @@
+browser.runtime.onMessage.addListener(notify);
+
+function notify(message) {
+ if (message.action == "showTab") {
+ browser.tabs.update({ url: "/tab.html" });
+ }
+}
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/extension-page-update/manifest.json b/mobile/android/geckoview/src/androidTest/assets/web_extensions/extension-page-update/manifest.json
new file mode 100644
index 0000000000..31ce6e022f
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/extension-page-update/manifest.json
@@ -0,0 +1,26 @@
+{
+ "manifest_version": 2,
+ "name": "Mozilla Android Components - Tabs Update Test",
+ "version": "1.0",
+ "background": {
+ "scripts": ["background-script.js"]
+ },
+ "applications": {
+ "gecko": {
+ "id": "extension-page-update@tests.mozilla.org"
+ }
+ },
+ "content_scripts": [
+ {
+ "matches": ["*://*.example.com/*"],
+ "js": ["tabs.js"],
+ "run_at": "document_idle"
+ }
+ ],
+ "permissions": [
+ "geckoViewAddons",
+ "nativeMessaging",
+ "tabs",
+ "<all_urls>"
+ ]
+}
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/extension-page-update/tab-script.js b/mobile/android/geckoview/src/androidTest/assets/web_extensions/extension-page-update/tab-script.js
new file mode 100644
index 0000000000..011f3bb301
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/extension-page-update/tab-script.js
@@ -0,0 +1,2 @@
+// Let's test privileged APIs
+browser.runtime.sendNativeMessage("browser", "HELLO_FROM_PAGE");
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/extension-page-update/tab.html b/mobile/android/geckoview/src/androidTest/assets/web_extensions/extension-page-update/tab.html
new file mode 100644
index 0000000000..f87c77a5d2
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/extension-page-update/tab.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html><html>
+<head>
+ <meta charset="utf-8">
+</head>
+<body>
+ <h1>Hello World!</h1>
+ <script src=tab-script.js></script>
+</body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/extension-page-update/tabs.js b/mobile/android/geckoview/src/androidTest/assets/web_extensions/extension-page-update/tabs.js
new file mode 100644
index 0000000000..ef5fbf6ce3
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/extension-page-update/tabs.js
@@ -0,0 +1 @@
+browser.runtime.sendMessage({ action: "showTab" });
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/messaging-content/manifest.json b/mobile/android/geckoview/src/androidTest/assets/web_extensions/messaging-content/manifest.json
new file mode 100644
index 0000000000..aa2b239aef
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/messaging-content/manifest.json
@@ -0,0 +1,24 @@
+{
+ "manifest_version": 2,
+ "name": "messaging",
+ "version": "1.0",
+ "description": "Test messaging between app and web extension",
+ "applications": {
+ "gecko": {
+ "id": "messaging-content@tests.mozilla.org"
+ }
+ },
+ "content_scripts": [
+ {
+ "matches": [
+ "*://*.example.com/*"
+ ],
+ "js": ["messaging.js"]
+ }
+ ],
+ "permissions": [
+ "geckoViewAddons",
+ "nativeMessaging",
+ "nativeMessagingFromContent"
+ ]
+}
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/messaging-content/messaging.js b/mobile/android/geckoview/src/androidTest/assets/web_extensions/messaging-content/messaging.js
new file mode 100644
index 0000000000..1c8323df53
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/messaging-content/messaging.js
@@ -0,0 +1,29 @@
+// This message should not be handled
+browser.runtime.sendNativeMessage("badNativeApi", "errorerrorerror");
+
+async function runTest() {
+ const response = await browser.runtime.sendNativeMessage(
+ "browser",
+ "testContentBrowserMessage"
+ );
+
+ browser.runtime.sendNativeMessage("browser", `response: ${response}`);
+
+ const port = browser.runtime.connectNative("browser");
+ port.onMessage.addListener(response => {
+ if (response.action === "disconnect") {
+ port.disconnect();
+ return;
+ }
+
+ port.postMessage(`response: ${response.message}`);
+ });
+
+ port.onDisconnect.addListener(() =>
+ browser.runtime.sendNativeMessage("browser", { type: "portDisconnected" })
+ );
+
+ port.postMessage("testContentPortMessage");
+}
+
+runTest();
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/messaging-iframe/manifest.json b/mobile/android/geckoview/src/androidTest/assets/web_extensions/messaging-iframe/manifest.json
new file mode 100644
index 0000000000..78605f460b
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/messaging-iframe/manifest.json
@@ -0,0 +1,25 @@
+{
+ "manifest_version": 2,
+ "name": "messaging",
+ "version": "1.0",
+ "description": "Test messaging between app and web extension",
+ "applications": {
+ "gecko": {
+ "id": "messaging-iframe@tests.mozilla.org"
+ }
+ },
+ "content_scripts": [
+ {
+ "matches": [
+ "*://localhost/*"
+ ],
+ "js": ["messaging.js"],
+ "all_frames": true
+ }
+ ],
+ "permissions": [
+ "geckoViewAddons",
+ "nativeMessaging",
+ "nativeMessagingFromContent"
+ ]
+}
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/messaging-iframe/messaging.js b/mobile/android/geckoview/src/androidTest/assets/web_extensions/messaging-iframe/messaging.js
new file mode 100644
index 0000000000..eb4ad3d8f9
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/messaging-iframe/messaging.js
@@ -0,0 +1,11 @@
+browser.runtime.sendNativeMessage("badNativeApi", "errorerrorerror");
+
+async function runTest() {
+ await browser.runtime.sendNativeMessage(
+ "browser",
+ "testContentBrowserMessage"
+ );
+ browser.runtime.connectNative("browser");
+}
+
+runTest();
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/messaging/background.js b/mobile/android/geckoview/src/androidTest/assets/web_extensions/messaging/background.js
new file mode 100644
index 0000000000..20deb53ae7
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/messaging/background.js
@@ -0,0 +1,28 @@
+browser.runtime.sendNativeMessage("badNativeApi", "errorerrorerror");
+
+async function runTest() {
+ const response = await browser.runtime.sendNativeMessage(
+ "browser",
+ "testBackgroundBrowserMessage"
+ );
+
+ browser.runtime.sendNativeMessage("browser", `response: ${response}`);
+
+ const port = browser.runtime.connectNative("browser");
+ port.onMessage.addListener(response => {
+ if (response.action === "disconnect") {
+ port.disconnect();
+ return;
+ }
+
+ port.postMessage(`response: ${response.message}`);
+ });
+
+ port.onDisconnect.addListener(() =>
+ browser.runtime.sendNativeMessage("browser", { type: "portDisconnected" })
+ );
+
+ port.postMessage("testBackgroundPortMessage");
+}
+
+runTest();
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/messaging/icons/border-48.png b/mobile/android/geckoview/src/androidTest/assets/web_extensions/messaging/icons/border-48.png
new file mode 100644
index 0000000000..90687de26d
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/messaging/icons/border-48.png
Binary files differ
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/messaging/manifest.json b/mobile/android/geckoview/src/androidTest/assets/web_extensions/messaging/manifest.json
new file mode 100644
index 0000000000..e61380311b
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/messaging/manifest.json
@@ -0,0 +1,21 @@
+{
+ "manifest_version": 2,
+ "name": "messaging",
+ "version": "1.0",
+ "description": "Test messaging between app and web extension",
+ "icons": {
+ "48": "icons/border-48.png"
+ },
+ "applications": {
+ "gecko": {
+ "id": "messaging@tests.mozilla.org"
+ }
+ },
+ "background": {
+ "scripts": ["background.js"]
+ },
+ "permissions": [
+ "geckoViewAddons",
+ "nativeMessaging"
+ ]
+}
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/notification-test/background.js b/mobile/android/geckoview/src/androidTest/assets/web_extensions/notification-test/background.js
new file mode 100644
index 0000000000..463010d1d5
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/notification-test/background.js
@@ -0,0 +1,6 @@
+browser.notifications.create("cake-notification", {
+ type: "basic",
+ title: "Time for cake!",
+ iconUrl: "http://example.com/img.svg",
+ message: "Something something cake",
+});
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/notification-test/manifest.json b/mobile/android/geckoview/src/androidTest/assets/web_extensions/notification-test/manifest.json
new file mode 100644
index 0000000000..69821d8d85
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/notification-test/manifest.json
@@ -0,0 +1,17 @@
+{
+ "manifest_version": 2,
+ "name": "Notification test",
+ "version": "1.0",
+ "description": "Send a notification.",
+ "browser_specific_settings": {
+ "gecko": {
+ "id": "notification@example.com"
+ }
+ },
+ "background": {
+ "scripts": ["background.js"]
+ },
+ "permissions": [
+ "notifications"
+ ]
+}
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/openoptionspage-1/background.js b/mobile/android/geckoview/src/androidTest/assets/web_extensions/openoptionspage-1/background.js
new file mode 100644
index 0000000000..1872c48d00
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/openoptionspage-1/background.js
@@ -0,0 +1 @@
+browser.runtime.openOptionsPage();
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/openoptionspage-1/manifest.json b/mobile/android/geckoview/src/androidTest/assets/web_extensions/openoptionspage-1/manifest.json
new file mode 100644
index 0000000000..380b0657fb
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/openoptionspage-1/manifest.json
@@ -0,0 +1,22 @@
+{
+ "manifest_version": 2,
+ "name": "openOptionsPage-1",
+ "version": "1.0",
+ "description": "Opens options page in a new tab.",
+ "applications": {
+ "gecko": {
+ "id": "openoptionspage1@tests.mozilla.org"
+ }
+ },
+ "background": {
+ "scripts": ["background.js"]
+ },
+ "permissions": [
+ "tabs"
+ ],
+ "options_ui": {
+ "page": "options.html",
+ "browser_style": true,
+ "open_in_tab": true
+ }
+}
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/openoptionspage-2/background.js b/mobile/android/geckoview/src/androidTest/assets/web_extensions/openoptionspage-2/background.js
new file mode 100644
index 0000000000..1872c48d00
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/openoptionspage-2/background.js
@@ -0,0 +1 @@
+browser.runtime.openOptionsPage();
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/openoptionspage-2/manifest.json b/mobile/android/geckoview/src/androidTest/assets/web_extensions/openoptionspage-2/manifest.json
new file mode 100644
index 0000000000..217034851f
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/openoptionspage-2/manifest.json
@@ -0,0 +1,22 @@
+{
+ "manifest_version": 2,
+ "name": "openOptionsPage-2",
+ "version": "1.0",
+ "description": "Opens options page via delegate.",
+ "applications": {
+ "gecko": {
+ "id": "openoptionspage2@tests.mozilla.org"
+ }
+ },
+ "background": {
+ "scripts": ["background.js"]
+ },
+ "permissions": [
+ "tabs"
+ ],
+ "options_ui": {
+ "page": "options.html",
+ "browser_style": true,
+ "open_in_tab": false
+ }
+}
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/page-history/manifest.json b/mobile/android/geckoview/src/androidTest/assets/web_extensions/page-history/manifest.json
new file mode 100644
index 0000000000..89befc953b
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/page-history/manifest.json
@@ -0,0 +1,11 @@
+{
+ "manifest_version": 2,
+ "name": "Page History",
+ "version": "1.0",
+ "applications": {
+ "gecko": {
+ "id": "page-history@tests.mozilla.org"
+ }
+ },
+ "description": "Can load a WebExtension Page."
+}
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/page-history/page.html b/mobile/android/geckoview/src/androidTest/assets/web_extensions/page-history/page.html
new file mode 100644
index 0000000000..eb16e3b850
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/page-history/page.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html><html>
+<head>
+ <meta charset="utf-8">
+</head>
+<body>
+ <h1> Hello, World! </h1>
+</body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/redirect-to-android-resource/background.js b/mobile/android/geckoview/src/androidTest/assets/web_extensions/redirect-to-android-resource/background.js
new file mode 100644
index 0000000000..fdf088a505
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/redirect-to-android-resource/background.js
@@ -0,0 +1,39 @@
+"use strict";
+
+function setupRedirect(fromUrl, redirectUrl) {
+ browser.webRequest.onBeforeRequest.addListener(
+ details => {
+ console.log(`Extension redirects from ${fromUrl} to ${redirectUrl}`);
+ return { redirectUrl };
+ },
+ { urls: [fromUrl] },
+ ["blocking"]
+ );
+}
+
+// Intercepts all script requests from androidTest/assets/www/trackers.html.
+// Scripts are executed in order of appearance in the page and block the
+// page's "load" event, so the test runner can just wait for the page to
+// have loaded and then check the page content to verify that the requests
+// were intercepted as expected.
+setupRedirect(
+ "http://trackertest.org/tracker.js",
+ "data:text/javascript,document.body.textContent='start'"
+);
+setupRedirect(
+ "https://tracking.example.com/tracker.js",
+ browser.runtime.getURL("web-accessible-script.js")
+);
+setupRedirect(
+ "https://itisatracker.org/tracker.js",
+ `data:text/javascript,document.body.textContent+=',end'`
+);
+
+// Work around bug 1300234 to ensure that the webRequest listener has been
+// registered before we resume the test. API result doesn't matter, we just
+// want to make a roundtrip.
+var listenerReady = browser.webRequest.getSecurityInfo("").catch(() => {});
+
+listenerReady.then(() => {
+ browser.runtime.sendNativeMessage("browser", "setupReadyStartTest");
+});
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/redirect-to-android-resource/manifest.json b/mobile/android/geckoview/src/androidTest/assets/web_extensions/redirect-to-android-resource/manifest.json
new file mode 100644
index 0000000000..11ef641ae9
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/redirect-to-android-resource/manifest.json
@@ -0,0 +1,25 @@
+{
+ "name": "redirect-to-android-resource",
+ "description": "Redirects script requests from trackers.html to moz-extension:-resource packaged in the APK (resource://android/...)",
+ "manifest_version": 2,
+ "version": "1",
+ "applications": {
+ "gecko": {
+ "id": "redirect-to-android-resource@tests.mozilla.org"
+ }
+ },
+ "background": {
+ "scripts": ["background.js"]
+ },
+ "permissions": [
+ "geckoViewAddons",
+ "nativeMessaging",
+ "webRequest",
+ "webRequestBlocking",
+ "http://localhost/",
+ "http://trackertest.org/",
+ "https://tracking.example.com/",
+ "https://itisatracker.org/tracker.js"
+ ],
+ "web_accessible_resources": ["web-accessible-script.js"]
+}
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/redirect-to-android-resource/web-accessible-script.js b/mobile/android/geckoview/src/androidTest/assets/web_extensions/redirect-to-android-resource/web-accessible-script.js
new file mode 100644
index 0000000000..a26c4cc91c
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/redirect-to-android-resource/web-accessible-script.js
@@ -0,0 +1,3 @@
+"use strict";
+
+document.body.textContent += ",extension-was-here";
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/tabs-activate-remove-2/background.js b/mobile/android/geckoview/src/androidTest/assets/web_extensions/tabs-activate-remove-2/background.js
new file mode 100644
index 0000000000..f8ecef0215
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/tabs-activate-remove-2/background.js
@@ -0,0 +1,16 @@
+browser.tabs.onActivated.addListener(async tabChange => {
+ const activeTabs = await browser.tabs.query({ active: true });
+ const currentWindow = await browser.tabs.query({
+ currentWindow: true,
+ active: true,
+ });
+
+ if (
+ activeTabs.length === 1 &&
+ activeTabs[0].id == tabChange.tabId &&
+ currentWindow.length === 1 &&
+ currentWindow[0].id === tabChange.tabId
+ ) {
+ browser.tabs.remove(tabChange.tabId);
+ }
+});
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/tabs-activate-remove-2/manifest.json b/mobile/android/geckoview/src/androidTest/assets/web_extensions/tabs-activate-remove-2/manifest.json
new file mode 100644
index 0000000000..4a5b79ab32
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/tabs-activate-remove-2/manifest.json
@@ -0,0 +1,17 @@
+{
+ "applications": {
+ "gecko": {
+ "id": "set-tab-active-2@tests.mozilla.org"
+ }
+ },
+ "manifest_version": 2,
+ "name": "messaging",
+ "version": "1.0",
+ "description": "Removes the activated Tab.",
+ "background": {
+ "scripts": ["background.js"]
+ },
+ "permissions": [
+ "tabs"
+ ]
+}
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/tabs-activate-remove/background.js b/mobile/android/geckoview/src/androidTest/assets/web_extensions/tabs-activate-remove/background.js
new file mode 100644
index 0000000000..f8ecef0215
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/tabs-activate-remove/background.js
@@ -0,0 +1,16 @@
+browser.tabs.onActivated.addListener(async tabChange => {
+ const activeTabs = await browser.tabs.query({ active: true });
+ const currentWindow = await browser.tabs.query({
+ currentWindow: true,
+ active: true,
+ });
+
+ if (
+ activeTabs.length === 1 &&
+ activeTabs[0].id == tabChange.tabId &&
+ currentWindow.length === 1 &&
+ currentWindow[0].id === tabChange.tabId
+ ) {
+ browser.tabs.remove(tabChange.tabId);
+ }
+});
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/tabs-activate-remove/manifest.json b/mobile/android/geckoview/src/androidTest/assets/web_extensions/tabs-activate-remove/manifest.json
new file mode 100644
index 0000000000..493e6befb0
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/tabs-activate-remove/manifest.json
@@ -0,0 +1,17 @@
+{
+ "applications": {
+ "gecko": {
+ "id": "set-tab-active@tests.mozilla.org"
+ }
+ },
+ "manifest_version": 2,
+ "name": "messaging",
+ "version": "1.0",
+ "description": "Removes the activated Tab.",
+ "background": {
+ "scripts": ["background.js"]
+ },
+ "permissions": [
+ "tabs"
+ ]
+}
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/tabs-create-2/background.js b/mobile/android/geckoview/src/androidTest/assets/web_extensions/tabs-create-2/background.js
new file mode 100644
index 0000000000..835e156b86
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/tabs-create-2/background.js
@@ -0,0 +1,4 @@
+browser.tabs.create({
+ url: "https://www.mozilla.org/en-US/",
+ cookieStoreId: "1",
+});
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/tabs-create-2/manifest.json b/mobile/android/geckoview/src/androidTest/assets/web_extensions/tabs-create-2/manifest.json
new file mode 100644
index 0000000000..995a85a9a0
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/tabs-create-2/manifest.json
@@ -0,0 +1,18 @@
+{
+ "manifest_version": 2,
+ "name": "messaging",
+ "version": "1.0",
+ "description": "Creates a tab with a contextual identity.",
+ "applications": {
+ "gecko": {
+ "id": "tabs-create-2@tests.mozilla.org"
+ }
+ },
+ "background": {
+ "scripts": ["background.js"]
+ },
+ "permissions": [
+ "tabs",
+ "cookies"
+ ]
+}
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/tabs-create-remove/background.js b/mobile/android/geckoview/src/androidTest/assets/web_extensions/tabs-create-remove/background.js
new file mode 100644
index 0000000000..a1f55a3a4f
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/tabs-create-remove/background.js
@@ -0,0 +1,3 @@
+browser.tabs.create({}).then(tab => {
+ browser.tabs.remove(tab.id);
+});
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/tabs-create-remove/manifest.json b/mobile/android/geckoview/src/androidTest/assets/web_extensions/tabs-create-remove/manifest.json
new file mode 100644
index 0000000000..25f348def8
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/tabs-create-remove/manifest.json
@@ -0,0 +1,16 @@
+{
+ "manifest_version": 2,
+ "name": "messaging",
+ "version": "1.0",
+ "description": "Creates and removes a tab.",
+ "applications" : {
+ "gecko": {
+ "id": "tabs-create-remove@tests.mozilla.org"
+ }
+ },
+ "background": {
+ "scripts": ["background.js"]
+ },
+ "permissions": [
+ ]
+}
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/tabs-create/background.js b/mobile/android/geckoview/src/androidTest/assets/web_extensions/tabs-create/background.js
new file mode 100644
index 0000000000..6fbd381e61
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/tabs-create/background.js
@@ -0,0 +1 @@
+browser.tabs.create({ url: "https://www.mozilla.org/en-US/" });
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/tabs-create/manifest.json b/mobile/android/geckoview/src/androidTest/assets/web_extensions/tabs-create/manifest.json
new file mode 100644
index 0000000000..af0d40020f
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/tabs-create/manifest.json
@@ -0,0 +1,17 @@
+{
+ "manifest_version": 2,
+ "name": "messaging",
+ "version": "1.0",
+ "description": "Creates a tab.",
+ "applications": {
+ "gecko": {
+ "id": "tabs-create@tests.mozilla.org"
+ }
+ },
+ "background": {
+ "scripts": ["background.js"]
+ },
+ "permissions": [
+ "tabs"
+ ]
+}
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/tabs-remove/background.js b/mobile/android/geckoview/src/androidTest/assets/web_extensions/tabs-remove/background.js
new file mode 100644
index 0000000000..c6ec7aee33
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/tabs-remove/background.js
@@ -0,0 +1,3 @@
+browser.tabs.query({ url: "*://*/*?tabToClose" }).then(([tab]) => {
+ browser.tabs.remove(tab.id);
+});
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/tabs-remove/manifest.json b/mobile/android/geckoview/src/androidTest/assets/web_extensions/tabs-remove/manifest.json
new file mode 100644
index 0000000000..bd5c977ba0
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/tabs-remove/manifest.json
@@ -0,0 +1,17 @@
+{
+ "manifest_version": 2,
+ "name": "messaging",
+ "version": "1.0",
+ "description": "Removes an existing tab.",
+ "applications": {
+ "gecko": {
+ "id": "tabs-remove@tests.mozilla.org"
+ }
+ },
+ "background": {
+ "scripts": ["background.js"]
+ },
+ "permissions": [
+ "tabs"
+ ]
+}
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/test-support/TestSupportChild.jsm b/mobile/android/geckoview/src/androidTest/assets/web_extensions/test-support/TestSupportChild.jsm
new file mode 100644
index 0000000000..23d82f2623
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/test-support/TestSupportChild.jsm
@@ -0,0 +1,37 @@
+/* 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/. */
+
+const { GeckoViewActorChild } = ChromeUtils.import(
+ "resource://gre/modules/GeckoViewActorChild.jsm"
+);
+
+const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
+
+const EXPORTED_SYMBOLS = ["TestSupportChild"];
+
+class TestSupportChild extends GeckoViewActorChild {
+ receiveMessage(aMsg) {
+ debug`receiveMessage: ${aMsg.name}`;
+
+ switch (aMsg.name) {
+ case "FlushApzRepaints":
+ return new Promise(resolve => {
+ const repaintDone = () => {
+ debug`APZ flush done`;
+ Services.obs.removeObserver(repaintDone, "apz-repaints-flushed");
+ resolve();
+ };
+ Services.obs.addObserver(repaintDone, "apz-repaints-flushed");
+ if (this.contentWindow.windowUtils.flushApzRepaints()) {
+ debug`Flushed APZ repaints, waiting for callback...`;
+ } else {
+ debug`Flushing APZ repaints was a no-op, triggering callback directly...`;
+ repaintDone();
+ }
+ });
+ }
+ return null;
+ }
+}
+const { debug } = TestSupportChild.initLogging("GeckoViewTestSupport");
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/test-support/background.js b/mobile/android/geckoview/src/androidTest/assets/web_extensions/test-support/background.js
new file mode 100644
index 0000000000..d074446039
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/test-support/background.js
@@ -0,0 +1,88 @@
+/* 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/. */
+
+const port = browser.runtime.connectNative("browser");
+
+const APIS = {
+ AddHistogram({ id, value }) {
+ browser.test.addHistogram(id, value);
+ },
+ Eval({ code }) {
+ // eslint-disable-next-line no-eval
+ return eval(`(async () => {
+ ${code}
+ })()`);
+ },
+ SetScalar({ id, value }) {
+ browser.test.setScalar(id, value);
+ },
+ GetRequestedLocales() {
+ return browser.test.getRequestedLocales();
+ },
+ GetLinkColor({ uri, selector }) {
+ return browser.test.getLinkColor(uri, selector);
+ },
+ GetPidForTab({ tab }) {
+ return browser.test.getPidForTab(tab.id);
+ },
+ GetPrefs({ prefs }) {
+ return browser.test.getPrefs(prefs);
+ },
+ GetActive({ tab }) {
+ return browser.test.getActive(tab.id);
+ },
+ RemoveCertOverride({ host, port }) {
+ browser.test.removeCertOverride(host, port);
+ },
+ RestorePrefs({ oldPrefs }) {
+ return browser.test.restorePrefs(oldPrefs);
+ },
+ SetPrefs({ oldPrefs, newPrefs }) {
+ return browser.test.setPrefs(oldPrefs, newPrefs);
+ },
+ SetResolutionAndScaleTo({ resolution }) {
+ return browser.test.setResolutionAndScaleTo(resolution);
+ },
+ FlushApzRepaints({ tab }) {
+ return browser.test.flushApzRepaints(tab.id);
+ },
+};
+
+port.onMessage.addListener(async message => {
+ const impl = APIS[message.type];
+ apiCall(message, impl);
+});
+
+browser.runtime.onConnect.addListener(contentPort => {
+ contentPort.onMessage.addListener(message => {
+ message.args.tab = contentPort.sender.tab;
+
+ const impl = APIS[message.type];
+ apiCall(message, impl);
+ });
+});
+
+function apiCall(message, impl) {
+ const { id, args } = message;
+ try {
+ sendResponse(id, impl(args));
+ } catch (error) {
+ sendResponse(id, Promise.reject(error));
+ }
+}
+
+function sendResponse(id, response) {
+ Promise.resolve(response).then(
+ value => sendSyncResponse(id, value),
+ reason => sendSyncResponse(id, null, reason)
+ );
+}
+
+function sendSyncResponse(id, response, exception) {
+ port.postMessage({
+ id,
+ response: JSON.stringify(response),
+ exception: exception && exception.toString(),
+ });
+}
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/test-support/manifest.json b/mobile/android/geckoview/src/androidTest/assets/web_extensions/test-support/manifest.json
new file mode 100644
index 0000000000..91f332eb84
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/test-support/manifest.json
@@ -0,0 +1,41 @@
+{
+ "manifest_version": 2,
+ "name": "Test support",
+ "version": "1.0",
+ "description": "Helper script for GeckoView tests",
+ "applications": {
+ "gecko": {
+ "id": "test-support@tests.mozilla.org"
+ }
+ },
+ "content_scripts": [
+ {
+ "matches": ["<all_urls>"],
+ "js": ["test-support.js"],
+ "run_at": "document_start"
+ }
+ ],
+ "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self';",
+ "background": {
+ "scripts": ["background.js"]
+ },
+ "experiment_apis": {
+ "test": {
+ "schema": "test-schema.json",
+ "parent": {
+ "scopes": ["addon_parent"],
+ "script": "test-api.js",
+ "events": ["startup"],
+ "paths": [["test"]]
+ }
+ }
+ },
+ "options_ui": {
+ "page": "dummy.html"
+ },
+ "permissions": [
+ "geckoViewAddons",
+ "nativeMessaging",
+ "nativeMessagingFromContent"
+ ]
+}
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/test-support/test-api.js b/mobile/android/geckoview/src/androidTest/assets/web_extensions/test-support/test-api.js
new file mode 100644
index 0000000000..1ed6c40554
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/test-support/test-api.js
@@ -0,0 +1,205 @@
+/* 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/. */
+
+"use strict";
+
+const { E10SUtils } = ChromeUtils.import(
+ "resource://gre/modules/E10SUtils.jsm"
+);
+const { Preferences } = ChromeUtils.import(
+ "resource://gre/modules/Preferences.jsm"
+);
+const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
+
+function linkColorFrameScript() {
+ addMessageListener("HistoryDelegateTest:GetLinkColor", function onMessage(
+ message
+ ) {
+ const { selector, uri } = message.data;
+
+ if (content.document.documentURI != uri) {
+ return;
+ }
+ const element = content.document.querySelector(selector);
+ if (!element) {
+ sendAsyncMessage("HistoryDelegateTest:GetLinkColor", {
+ ok: false,
+ error: "No element for " + selector,
+ });
+ return;
+ }
+ const color = content.windowUtils.getVisitedDependentComputedStyle(
+ element,
+ "",
+ "color"
+ );
+ sendAsyncMessage("HistoryDelegateTest:GetLinkColor", { ok: true, color });
+ });
+}
+
+function setResolutionAndScaleToFrameScript(resolution) {
+ addMessageListener("PanZoomControllerTest:SetResolutionAndScaleTo", () => {
+ content.window.visualViewport.addEventListener("resize", () => {
+ sendAsyncMessage("PanZoomControllerTest:SetResolutionAndScaleTo");
+ });
+ content.windowUtils.setResolutionAndScaleTo(resolution);
+ });
+}
+
+this.test = class extends ExtensionAPI {
+ onStartup() {
+ ChromeUtils.registerWindowActor("TestSupport", {
+ child: {
+ moduleURI:
+ "resource://android/assets/web_extensions/test-support/TestSupportChild.jsm",
+ },
+ allFrames: true,
+ });
+ }
+
+ onShutdown(isAppShutdown) {
+ if (isAppShutdown) {
+ return;
+ }
+ ChromeUtils.unregisterWindowActor("TestSupport");
+ }
+
+ getAPI(context) {
+ return {
+ test: {
+ /* Set prefs and returns set of saved prefs */
+ async setPrefs(oldPrefs, newPrefs) {
+ // Save old prefs
+ Object.assign(
+ oldPrefs,
+ ...Object.keys(newPrefs)
+ .filter(key => !(key in oldPrefs))
+ .map(key => ({ [key]: Preferences.get(key, null) }))
+ );
+
+ // Set new prefs
+ Preferences.set(newPrefs);
+ return oldPrefs;
+ },
+
+ /* Restore prefs to old value. */
+ async restorePrefs(oldPrefs) {
+ for (const [name, value] of Object.entries(oldPrefs)) {
+ if (value === null) {
+ Preferences.reset(name);
+ } else {
+ Preferences.set(name, value);
+ }
+ }
+ },
+
+ /* Get pref values. */
+ async getPrefs(prefs) {
+ return Preferences.get(prefs);
+ },
+
+ /* Gets link color for a given selector. */
+ async getLinkColor(uri, selector) {
+ const frameScript = `data:text/javascript,(${encodeURI(
+ linkColorFrameScript
+ )}).call(this)`;
+ Services.mm.loadFrameScript(frameScript, true);
+
+ return new Promise((resolve, reject) => {
+ const onMessage = message => {
+ Services.mm.removeMessageListener(
+ "HistoryDelegateTest:GetLinkColor",
+ onMessage
+ );
+ if (message.data.ok) {
+ resolve(message.data.color);
+ } else {
+ reject(message.data.error);
+ }
+ };
+
+ Services.mm.addMessageListener(
+ "HistoryDelegateTest:GetLinkColor",
+ onMessage
+ );
+ Services.mm.broadcastAsyncMessage(
+ "HistoryDelegateTest:GetLinkColor",
+ { uri, selector }
+ );
+ });
+ },
+
+ async getRequestedLocales() {
+ return Services.locale.requestedLocales;
+ },
+
+ async getPidForTab(tabId) {
+ const tab = context.extension.tabManager.get(tabId);
+ const pids = E10SUtils.getBrowserPids(tab.browser);
+ return pids[0];
+ },
+
+ async addHistogram(id, value) {
+ return Services.telemetry.getHistogramById(id).add(value);
+ },
+
+ removeCertOverride(host, port) {
+ const overrideService = Cc[
+ "@mozilla.org/security/certoverride;1"
+ ].getService(Ci.nsICertOverrideService);
+ overrideService.clearValidityOverride(host, port);
+ },
+
+ async setScalar(id, value) {
+ return Services.telemetry.scalarSet(id, value);
+ },
+
+ async setResolutionAndScaleTo(resolution) {
+ const frameScript = `data:text/javascript,(${encodeURI(
+ setResolutionAndScaleToFrameScript
+ )}).call(this, ${resolution})`;
+ Services.mm.loadFrameScript(frameScript, true);
+
+ return new Promise(resolve => {
+ const onMessage = () => {
+ Services.mm.removeMessageListener(
+ "PanZoomControllerTest:SetResolutionAndScaleTo",
+ onMessage
+ );
+ resolve();
+ };
+
+ Services.mm.addMessageListener(
+ "PanZoomControllerTest:SetResolutionAndScaleTo",
+ onMessage
+ );
+ Services.mm.broadcastAsyncMessage(
+ "PanZoomControllerTest:SetResolutionAndScaleTo"
+ );
+ });
+ },
+
+ async getActive(tabId) {
+ const tab = context.extension.tabManager.get(tabId);
+ return tab.browser.docShellIsActive;
+ },
+
+ async flushApzRepaints(tabId) {
+ const tab = context.extension.tabManager.get(tabId);
+ const { browsingContext } = tab.browser;
+
+ // TODO: Note that `waitUntilApzStable` in apz_test_utils.js does
+ // flush APZ repaints in the parent process (i.e. calling
+ // nsIDOMWindowUtils.flushApzRepaints for the parent process) before
+ // flushApzRepaints is called for the target content document, if we
+ // still meet intermittent failures, we might want to do it here as
+ // well.
+ await browsingContext.currentWindowGlobal
+ .getActor("TestSupport")
+ .sendQuery("FlushApzRepaints");
+ },
+ },
+ };
+ }
+};
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/test-support/test-schema.json b/mobile/android/geckoview/src/androidTest/assets/web_extensions/test-support/test-schema.json
new file mode 100644
index 0000000000..65ab7d4848
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/test-support/test-schema.json
@@ -0,0 +1,174 @@
+[
+ {
+ "namespace": "test",
+ "description": "Additional APIs for test support in GeckoView.",
+ "functions": [
+ {
+ "name": "setPrefs",
+ "type": "function",
+ "async": true,
+ "description": "Set prefs and return a set of saved prefs",
+ "parameters": [
+ {
+ "name": "oldPrefs",
+ "type": "object",
+ "properties": {},
+ "additionalProperties": {"type": "any"}
+ },
+ {
+ "name": "newPrefs",
+ "type": "object",
+ "properties": {},
+ "additionalProperties": {"type": "any"}
+ }
+ ]
+ },
+ {
+ "name": "restorePrefs",
+ "type": "function",
+ "async": true,
+ "description": "Restore prefs to old value",
+ "parameters": [
+ {
+ "type": "any",
+ "name": "oldPrefs"
+ }
+ ]
+ },
+ {
+ "name": "getPrefs",
+ "type": "function",
+ "async": true,
+ "description": "Get pref values.",
+ "parameters": [
+ {
+ "name": "prefs",
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ ]
+ },
+ {
+ "name": "getLinkColor",
+ "type": "function",
+ "async": true,
+ "description": "Get resolved color for link for a given page and selector.",
+ "parameters": [
+ {
+ "type": "string",
+ "name": "uri"
+ },
+ {
+ "type": "string",
+ "name": "selector"
+ }
+ ]
+ },
+ {
+ "name": "getRequestedLocales",
+ "type": "function",
+ "async": true,
+ "description": "Gets the requested locales.",
+ "parameters": []
+ },
+ {
+ "name": "addHistogram",
+ "type": "function",
+ "async": true,
+ "description": "Add a sample with the given value to the histogram with the given id.",
+ "parameters": [
+ {
+ "type": "string",
+ "name": "id"
+ },
+ {
+ "type": "any",
+ "name": "value"
+ }
+ ]
+ },
+ {
+ "name": "removeCertOverride",
+ "type": "function",
+ "async": true,
+ "description": "Revokes SSL certificate overrides for the given host+port.",
+ "parameters": [
+ {
+ "type": "string",
+ "name": "host"
+ },
+ {
+ "type": "number",
+ "name": "port"
+ }
+ ]
+ },
+ {
+ "name": "setScalar",
+ "type": "function",
+ "async": true,
+ "description": "Set the given value to the scalar with the given id.",
+ "parameters": [
+ {
+ "type": "string",
+ "name": "id"
+ },
+ {
+ "type": "any",
+ "name": "value"
+ }
+ ]
+ },
+ {
+ "name": "setResolutionAndScaleTo",
+ "type": "function",
+ "async": true,
+ "description": "Invokes nsIDOMWindowUtils.setResolutionAndScaleTo.",
+ "parameters": [
+ {
+ "type": "number",
+ "name": "resolution"
+ }
+ ]
+ },
+ {
+ "name": "getActive",
+ "type": "function",
+ "async": true,
+ "description": "Returns true if the docShell is active for given tab.",
+ "parameters": [
+ {
+ "type": "number",
+ "name": "tabId"
+ }
+ ]
+ },
+ {
+ "name": "getPidForTab",
+ "type": "function",
+ "async": true,
+ "description": "Gets the top-level pid belonging to tabId.",
+ "parameters": [
+ {
+ "type": "number",
+ "name": "tabId"
+ }
+ ]
+ },
+ {
+ "name": "flushApzRepaints",
+ "type": "function",
+ "async": true,
+ "description": "Invokes nsIDOMWindowUtils.flushApzRepaints for the document of the tabId.",
+ "parameters": [
+ {
+ "type": "number",
+ "name": "tabId"
+ }
+ ]
+ }
+ ]
+ }
+]
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/test-support/test-support.js b/mobile/android/geckoview/src/androidTest/assets/web_extensions/test-support/test-support.js
new file mode 100644
index 0000000000..c0f073e81d
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/test-support/test-support.js
@@ -0,0 +1,48 @@
+/* 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/. */
+
+let backgroundPort = null;
+let nativePort = null;
+
+window.addEventListener("pageshow", () => {
+ backgroundPort = browser.runtime.connect();
+ nativePort = browser.runtime.connectNative("browser");
+
+ nativePort.onMessage.addListener(message => {
+ if (message.type) {
+ // This is a session-specific webExtensionApiCall.
+ // Forward to the background script.
+ backgroundPort.postMessage(message);
+ } else if (message.eval) {
+ try {
+ // Using eval here is the whole point of this WebExtension so we can
+ // safely ignore the eslint warning.
+ const response = window.eval(message.eval); // eslint-disable-line no-eval
+ sendResponse(message.id, response);
+ } catch (ex) {
+ sendSyncResponse(message.id, null, ex);
+ }
+ }
+ });
+
+ function sendResponse(id, response, exception) {
+ Promise.resolve(response).then(
+ value => sendSyncResponse(id, value),
+ reason => sendSyncResponse(id, null, reason)
+ );
+ }
+
+ function sendSyncResponse(id, response, exception) {
+ nativePort.postMessage({
+ id,
+ response: JSON.stringify(response),
+ exception: exception && exception.toString(),
+ });
+ }
+});
+
+window.addEventListener("pagehide", () => {
+ backgroundPort.disconnect();
+ nativePort.disconnect();
+});
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/update-1/borderify.js b/mobile/android/geckoview/src/androidTest/assets/web_extensions/update-1/borderify.js
new file mode 100644
index 0000000000..9c3728b381
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/update-1/borderify.js
@@ -0,0 +1 @@
+document.body.style.border = "5px solid red";
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/update-1/manifest.json b/mobile/android/geckoview/src/androidTest/assets/web_extensions/update-1/manifest.json
new file mode 100644
index 0000000000..10515bf76a
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/update-1/manifest.json
@@ -0,0 +1,18 @@
+{
+ "manifest_version": 2,
+ "name": "update",
+ "browser_specific_settings": {
+ "gecko": {
+ "id": "update@example.com",
+ "update_url": "https://example.org/tests/junit/update_manifest.json"
+ }
+ },
+ "version": "1.0",
+ "description": "Adds a red border to all webpages matching example.com.",
+ "content_scripts": [
+ {
+ "matches": ["*://*.example.com/*"],
+ "js": ["borderify.js"]
+ }
+ ]
+} \ No newline at end of file
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/update-2/borderify.js b/mobile/android/geckoview/src/androidTest/assets/web_extensions/update-2/borderify.js
new file mode 100644
index 0000000000..3529928d82
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/update-2/borderify.js
@@ -0,0 +1 @@
+document.body.style.border = "5px solid blue";
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/update-2/manifest.json b/mobile/android/geckoview/src/androidTest/assets/web_extensions/update-2/manifest.json
new file mode 100644
index 0000000000..c820403671
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/update-2/manifest.json
@@ -0,0 +1,17 @@
+{
+ "manifest_version": 2,
+ "name": "update",
+ "browser_specific_settings": {
+ "gecko": {
+ "id": "update@example.com"
+ }
+ },
+ "version": "2.0",
+ "description": "Adds a blue border to all webpages matching example.com.",
+ "content_scripts": [
+ {
+ "matches": ["*://*.example.com/*"],
+ "js": ["borderify.js"]
+ }
+ ]
+} \ No newline at end of file
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/update-postpone-1/background.js b/mobile/android/geckoview/src/androidTest/assets/web_extensions/update-postpone-1/background.js
new file mode 100644
index 0000000000..a301506ca7
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/update-postpone-1/background.js
@@ -0,0 +1,3 @@
+browser.runtime.onUpdateAvailable.addListener(details => {
+ // Do nothing, this is just here to prevent auto update.
+});
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/update-postpone-1/borderify.js b/mobile/android/geckoview/src/androidTest/assets/web_extensions/update-postpone-1/borderify.js
new file mode 100644
index 0000000000..9c3728b381
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/update-postpone-1/borderify.js
@@ -0,0 +1 @@
+document.body.style.border = "5px solid red";
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/update-postpone-1/manifest.json b/mobile/android/geckoview/src/androidTest/assets/web_extensions/update-postpone-1/manifest.json
new file mode 100644
index 0000000000..31007b9c3b
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/update-postpone-1/manifest.json
@@ -0,0 +1,21 @@
+{
+ "manifest_version": 2,
+ "name": "update",
+ "browser_specific_settings": {
+ "gecko": {
+ "id": "update-postpone@example.com",
+ "update_url": "https://example.org/tests/junit/update_manifest.json"
+ }
+ },
+ "background": {
+ "scripts": ["background.js"]
+ },
+ "version": "1.0",
+ "description": "Adds a red border to all webpages matching example.com.",
+ "content_scripts": [
+ {
+ "matches": ["*://*.example.com/*"],
+ "js": ["borderify.js"]
+ }
+ ]
+} \ No newline at end of file
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/update-postpone-2/borderify.js b/mobile/android/geckoview/src/androidTest/assets/web_extensions/update-postpone-2/borderify.js
new file mode 100644
index 0000000000..3529928d82
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/update-postpone-2/borderify.js
@@ -0,0 +1 @@
+document.body.style.border = "5px solid blue";
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/update-postpone-2/manifest.json b/mobile/android/geckoview/src/androidTest/assets/web_extensions/update-postpone-2/manifest.json
new file mode 100644
index 0000000000..92204752dd
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/update-postpone-2/manifest.json
@@ -0,0 +1,17 @@
+{
+ "manifest_version": 2,
+ "name": "update",
+ "browser_specific_settings": {
+ "gecko": {
+ "id": "update-postpone@example.com"
+ }
+ },
+ "version": "2.0",
+ "description": "Adds a blue border to all webpages matching example.com.",
+ "content_scripts": [
+ {
+ "matches": ["*://*.example.com/*"],
+ "js": ["borderify.js"]
+ }
+ ]
+} \ No newline at end of file
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/update-with-perms-1/borderify.js b/mobile/android/geckoview/src/androidTest/assets/web_extensions/update-with-perms-1/borderify.js
new file mode 100644
index 0000000000..9c3728b381
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/update-with-perms-1/borderify.js
@@ -0,0 +1 @@
+document.body.style.border = "5px solid red";
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/update-with-perms-1/manifest.json b/mobile/android/geckoview/src/androidTest/assets/web_extensions/update-with-perms-1/manifest.json
new file mode 100644
index 0000000000..2dedeebc25
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/update-with-perms-1/manifest.json
@@ -0,0 +1,18 @@
+{
+ "manifest_version": 2,
+ "name": "update",
+ "browser_specific_settings": {
+ "gecko": {
+ "id": "update-with-perms@example.com",
+ "update_url": "https://example.org/tests/junit/update_manifest.json"
+ }
+ },
+ "version": "1.0",
+ "description": "Adds a red border to all webpages matching example.com.",
+ "content_scripts": [
+ {
+ "matches": ["*://*.example.com/*"],
+ "js": ["borderify.js"]
+ }
+ ]
+} \ No newline at end of file
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/update-with-perms-2/borderify.js b/mobile/android/geckoview/src/androidTest/assets/web_extensions/update-with-perms-2/borderify.js
new file mode 100644
index 0000000000..3529928d82
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/update-with-perms-2/borderify.js
@@ -0,0 +1 @@
+document.body.style.border = "5px solid blue";
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/update-with-perms-2/manifest.json b/mobile/android/geckoview/src/androidTest/assets/web_extensions/update-with-perms-2/manifest.json
new file mode 100644
index 0000000000..4debd1371c
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/update-with-perms-2/manifest.json
@@ -0,0 +1,20 @@
+{
+ "manifest_version": 2,
+ "name": "update",
+ "browser_specific_settings": {
+ "gecko": {
+ "id": "update-with-perms@example.com"
+ }
+ },
+ "version": "2.0",
+ "description": "Adds a blue border to all webpages matching example.com.",
+ "content_scripts": [
+ {
+ "matches": ["*://*.example.com/*"],
+ "js": ["borderify.js"]
+ }
+ ],
+ "permissions": [
+ "tabs"
+ ]
+} \ No newline at end of file
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-aria-comboboxes.html b/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-aria-comboboxes.html
new file mode 100644
index 0000000000..f0a8953265
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-aria-comboboxes.html
@@ -0,0 +1,11 @@
+<html>
+<head>
+ <meta charset="utf-8">
+</head>
+<body>
+<div contenteditable role="combobox" aria-label="ARIA 1.0 combobox"></div>
+<div role="combobox">
+ <input type="text" aria-label="ARIA 1.1 combobox">
+</div>
+</body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-checkbox.html b/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-checkbox.html
new file mode 100644
index 0000000000..c2977b13af
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-checkbox.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html><html>
+<head>
+ <meta charset="utf-8">
+</head>
+<body>
+ <label>
+ <input type='checkbox' aria-describedby='desc'>many option
+ </label>
+ <div id='desc'>description</div>
+</body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-clipboard.html b/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-clipboard.html
new file mode 100644
index 0000000000..d0541fb478
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-clipboard.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html><html>
+<head>
+ <meta charset="utf-8">
+</head>
+<body>
+ <input value='hello cruel world' id='input'>
+</body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-collection.html b/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-collection.html
new file mode 100644
index 0000000000..517e1800bf
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-collection.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html><html>
+<head>
+ <meta charset="utf-8">
+</head>
+<body>
+ <ul>
+ <li>One</li>
+ <li>Two</li>
+ </ul>
+ <ul>
+ <li>1
+ <ul>
+ <li>1.1</li>
+ <li>1.2</li>
+ </ul>
+ </li>
+ </ul>
+</body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-expandable.html b/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-expandable.html
new file mode 100644
index 0000000000..dab9f5fabe
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-expandable.html
@@ -0,0 +1,8 @@
+<html>
+<head>
+ <meta charset="utf-8">
+</head>
+<body>
+ <button onclick="this.setAttribute('aria-expanded', this.getAttribute('aria-expanded') == 'false')" aria-expanded="false">button</button>
+</body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-headings.html b/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-headings.html
new file mode 100644
index 0000000000..280bbd89d7
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-headings.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html><html>
+<head>
+ <meta charset="utf-8">
+</head>
+<body>
+ <a href=\"%23\">preamble</a>
+ <h1>Fried cheese</h1><p>with club sauce.</p>
+ <a href="#"><h2>Popcorn shrimp</h2></a><button>with club sauce.</button>
+ <h3>Chicken fingers</h3><p>with spicy club sauce.</p>
+</body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-links.html b/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-links.html
new file mode 100644
index 0000000000..25d9b494e8
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-links.html
@@ -0,0 +1,12 @@
+<html>
+<head>
+ <meta charset="utf-8">
+</head>
+<body>
+<a href="/">a with href</a>
+<a>a with no attributes</a>
+<a name="anchor">a with name</a>
+<a onclick=";">a with onclick</a>
+<span role="link">span with role link</span>
+</body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-live-region-atomic.html b/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-live-region-atomic.html
new file mode 100644
index 0000000000..116f39bb93
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-live-region-atomic.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html><html>
+<head>
+ <meta charset="utf-8">
+</head>
+<body>
+ <div aria-live='polite' aria-atomic='true' id='container'>The time is <p>3pm</p></div>
+</body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-live-region-descendant.html b/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-live-region-descendant.html
new file mode 100644
index 0000000000..9d06bfb75a
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-live-region-descendant.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html><html>
+<head>
+ <meta charset="utf-8">
+</head>
+<body>
+ <div aria-live='polite'><p id='to_show'>I will be shown</p></div>
+</body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-live-region-image-labeled-by.html b/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-live-region-image-labeled-by.html
new file mode 100644
index 0000000000..9d06903535
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-live-region-image-labeled-by.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html><html>
+<head>
+ <meta charset="utf-8">
+</head>
+<body>
+ <img src='data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=='
+ aria-live='polite'
+ aria-labelledby='l1'>
+ <span id='l1'>Hello</span>
+ <span id='l2'>Goodbye</span>
+</body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-live-region-image.html b/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-live-region-image.html
new file mode 100644
index 0000000000..b9ffbabdfa
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-live-region-image.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html><html>
+<head>
+ <meta charset="utf-8">
+</head>
+<body>
+ <div aria-live='polite' aria-atomic='true'>
+ This picture is
+ <img src='data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==' alt='happy'>
+ </div>
+</body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-live-region.html b/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-live-region.html
new file mode 100644
index 0000000000..e964f961fb
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-live-region.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html><html>
+<head>
+ <meta charset="utf-8">
+</head>
+<body>
+ <div id="to_change"aria-live="polite"></div>
+</body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-move-caret-accessibility-focus.html b/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-move-caret-accessibility-focus.html
new file mode 100644
index 0000000000..8b27956552
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-move-caret-accessibility-focus.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html><html>
+<head>
+ <meta charset="utf-8">
+</head>
+<body>
+ <p>Hello <a href='foo'>sweet</a>, sweet <span>world</span>
+</body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-mutation.html b/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-mutation.html
new file mode 100644
index 0000000000..7e48211c0f
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-mutation.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html><html>
+<head>
+ <meta charset="utf-8">
+</head>
+<body>
+ <div><p id='to_show'>I will be shown</p></div>
+</body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-range.html b/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-range.html
new file mode 100644
index 0000000000..44056fe285
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-range.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html><html>
+<head>
+ <meta charset="utf-8">
+</head>
+<body>
+ <input type="range" aria-label="Rating" min="1" max="10" value="4"><input type="range" aria-label="Stars" min="1" max="5" step="0.5" value="4.5"><input type="range" aria-label="Percent" min="0" max="1" step="0.01" value="0.83">
+</body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-scroll.html b/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-scroll.html
new file mode 100644
index 0000000000..f67cdaef5b
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-scroll.html
@@ -0,0 +1,8 @@
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width initial-scale=1">
+<body style="margin: 0;">
+ <div style="height: 100vh;"></div>
+ <button>Hello</button>
+ <p style="margin: 0;">Lorem ipsum dolor sit amet, consectetur adipiscing elit,
+ sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
+</body>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-selectable.html b/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-selectable.html
new file mode 100644
index 0000000000..a6900be862
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-selectable.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html><html>
+<head>
+ <meta charset="utf-8">
+</head>
+<body>
+ <ul style="list-style-type: none;" role="listbox">
+ <li id="li" role="option" onclick="this.setAttribute('aria-selected',
+ this.getAttribute('aria-selected') == 'true' ? 'false' : 'true')">1</li>
+ <li role="option" aria-selected="false">2</li>
+ </ul>
+</body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-text-entry-node.html b/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-text-entry-node.html
new file mode 100644
index 0000000000..c8552e0571
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-text-entry-node.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html><html>
+<head>
+ <meta charset="utf-8">
+</head>
+<body>
+ <input aria-label='Name' aria-describedby='desc' value='Tobias'>
+ <div id='desc'>description</div>
+ <input aria-label='Last' value='Funke' required>
+</body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-tree.html b/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-tree.html
new file mode 100644
index 0000000000..64cc1c909e
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/accessibility/test-tree.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html><html>
+<head>
+ <meta charset="utf-8">
+</head>
+<body>
+ <label for='name'>Name:</label><input id='name' type='text' value='Julie'><button>Submit</button>
+</body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/audio/owl.mp3 b/mobile/android/geckoview/src/androidTest/assets/www/audio/owl.mp3
new file mode 100644
index 0000000000..9fafa32f93
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/audio/owl.mp3
Binary files differ
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/autoplay.html b/mobile/android/geckoview/src/androidTest/assets/www/autoplay.html
new file mode 100644
index 0000000000..24cbf474bd
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/autoplay.html
@@ -0,0 +1,11 @@
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>WEBM Video</title>
+ </head>
+ <body>
+ <video preload autoplay>
+ <source src="videos/gizmo.webm"></source>
+ </video>
+ </body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/badVideoPath.html b/mobile/android/geckoview/src/androidTest/assets/www/badVideoPath.html
new file mode 100644
index 0000000000..d9b34843fd
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/badVideoPath.html
@@ -0,0 +1,11 @@
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Bad Video Path</title>
+ </head>
+ <body>
+ <video controls preload>
+ <source src="videos/fileDoesNotExist.ogg"></source>
+ </video>
+ </body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/beforeunload.html b/mobile/android/geckoview/src/androidTest/assets/www/beforeunload.html
new file mode 100644
index 0000000000..6cbe6d60ed
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/beforeunload.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html><html>
+<head>
+ <meta charset="utf-8">
+</head>
+<body onbeforeunload="return beforeUnload()">
+ <a id=navigateAway href="./hello.html">Click Me</a>
+ <a id=navigateAway2 href="./hello2.html">Click Me</a>
+ <script>
+ function beforeUnload() {
+ return "Please don't leave.";
+ }
+ </script>
+</body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/clickToReload.html b/mobile/android/geckoview/src/androidTest/assets/www/clickToReload.html
new file mode 100644
index 0000000000..beddd2cdb4
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/clickToReload.html
@@ -0,0 +1,10 @@
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Hello, world!</title>
+ <meta name="viewport" content="initial-scale=1.0">
+ </head>
+ <body style="height: 100%" onclick="window.location.reload()">
+ <p>Hello, world!</p>
+ </body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/colors.html b/mobile/android/geckoview/src/androidTest/assets/www/colors.html
new file mode 100644
index 0000000000..299240dc35
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/colors.html
@@ -0,0 +1,14 @@
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Colours</title>
+ </head>
+ <!-- background contains one extra transparent.gif because we want trick the
+ contentful paint detection; We want to make sure the background is loaded
+ before the test starts so we always wait for the contentful paint timestamp
+ to exist, however, gradient isn't considered as contentful per spec, so Gecko
+ wouldn't generate a timestamp for it. Hence, we added a transparent gif
+ to the image list to trick the detection. !-->
+ <body style="overflow:hidden; height:100%; width:100%; margin: 0px; padding: 0px; background: url('/assets/www/transparent.gif'), linear-gradient(135deg, red, white);">
+ </body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/data_uri.html b/mobile/android/geckoview/src/androidTest/assets/www/data_uri.html
new file mode 100644
index 0000000000..675f4b973d
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/data_uri.html
@@ -0,0 +1,10 @@
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Link with a giant data URI</title>
+ </head>
+ <body>
+ <a href="insert uri here" id="smallLink">Open small link</a>
+ <a href="insert uri here" id="largeLink">Open large link</a>
+</body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/download.html b/mobile/android/geckoview/src/androidTest/assets/www/download.html
new file mode 100644
index 0000000000..45d71a410c
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/download.html
@@ -0,0 +1,16 @@
+<html>
+ <head>
+ <meta charset="utf-8">
+ </head>
+ <body>
+ <script>
+ const blob = new Blob(["Downloaded Data"], {type: "text/plain"});
+ const element = document.createElement("a");
+ element.href = URL.createObjectURL(blob);
+ element.download = "download.txt";
+ element.style.display = "none";
+ document.body.appendChild(element);
+ element.click();
+ </script>
+ </body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/fixedbottom.html b/mobile/android/geckoview/src/androidTest/assets/www/fixedbottom.html
new file mode 100644
index 0000000000..59bb166358
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/fixedbottom.html
@@ -0,0 +1,16 @@
+<html>
+ <head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1">
+ <title>Fixed bottom element</title>
+ </head>
+ <!-- background contains one extra transparent.gif because we want trick the
+ contentful paint detection; We want to make sure the background is loaded
+ before the test starts so we always wait for the contentful paint timestamp
+ to exist, however, gradient isn't considered as contentful per spec, so Gecko
+ wouldn't generate a timestamp for it. Hence, we added a transparent gif
+ to the image list to trick the detection. !-->
+ <body style="overflow:hidden; height:100%; width:100%; margin: 0px; padding: 0px; background: url('/assets/www/transparent.gif'), linear-gradient(135deg, blue, blue);">
+ <div id="bottom-banner" style="width:100%;position:fixed;bottom:0;left:0;background-color:lime;height:10%;"></div>
+ </body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/fixedpercent.html b/mobile/android/geckoview/src/androidTest/assets/www/fixedpercent.html
new file mode 100644
index 0000000000..2f63093df3
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/fixedpercent.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, minimum-scale=0.5">
+<style>
+html {
+ width: 100%;
+ height: 100%;
+ scrollbar-width: none;
+}
+body {
+ width: 200%;
+ height: 2000px;
+ margin: 0;
+ padding: 0;
+}
+
+#fixed-element {
+ width: 100%;
+ height: 200%;
+ position: fixed;
+ top: 0px;
+ background-color: green;
+}
+</style>
+<div id="fixed-element"></div>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/fixedvh.html b/mobile/android/geckoview/src/androidTest/assets/www/fixedvh.html
new file mode 100644
index 0000000000..516a6c4bb5
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/fixedvh.html
@@ -0,0 +1,25 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, minimum-scale=0.5">
+<style>
+html {
+ width: 100%;
+ height: 100%;
+ scrollbar-width: none;
+}
+body {
+ width: 200%;
+ height: 2000px;
+ margin: 0;
+ padding: 0;
+}
+
+#fixed-element {
+ width: 100%;
+ height: 200vh;
+ position: fixed;
+ top: 0px;
+ background-color: green;
+}
+</style>
+<div id="fixed-element"></div>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/form_blank.html b/mobile/android/geckoview/src/androidTest/assets/www/form_blank.html
new file mode 100644
index 0000000000..b55a1eb31d
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/form_blank.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Forms</title>
+ <meta name="viewport" content="minimum-scale=1,width=device-width">
+ </head>
+ <body>
+ <form id="form1" name="form1" action="form_blank.html" method="get" target="_blank">
+ <input type="text" id="search" value="foo">
+ <input type="submit">
+ </form>
+ </body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/forms.html b/mobile/android/geckoview/src/androidTest/assets/www/forms.html
new file mode 100644
index 0000000000..6dbd24a6a6
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/forms.html
@@ -0,0 +1,31 @@
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Forms</title>
+ <meta name="viewport" content="minimum-scale=1,width=device-width">
+ </head>
+ <body>
+ <form id="form1">
+ <input type="text" id="user1" value="foo">
+ <input type="password" id="pass1" value="foo">
+ <input type="email" id="email1" value="@">
+ <input type="number" id="number1" value="0">
+ <input type="tel" id="tel1" value="0">
+ <input type="submit" value="submit">
+ </form>
+ <input type="Text" id="user2" value="foo">
+ <input type="PassWord" id="pass2" maxlength="8" value="foo">
+ <input type="button" id="button1" value="foo"/>
+ <input type="checkbox" id="checkbox1"/>
+ <input type="hidden" id="hidden1" value="foo"/>
+
+ <iframe id="iframe"></iframe>
+ </body>
+ <script>
+ addEventListener("load", function(e) {
+ if (window.parent === window) {
+ document.getElementById("iframe").contentWindow.location.href = window.location.href;
+ }
+ });
+ </script>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/forms2.html b/mobile/android/geckoview/src/androidTest/assets/www/forms2.html
new file mode 100644
index 0000000000..309144c824
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/forms2.html
@@ -0,0 +1,24 @@
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Forms2</title>
+ </head>
+ <body>
+ <form>
+ <fieldset>
+ <input type="text" id="firstname">
+ <input type="text" id="lastname">
+ <input type="text" id="user1" value="foo">
+ <input type="password" id="pass1" value="foo" autofocus>
+ </fieldset>
+ </form>
+ <iframe id="iframe"></iframe>
+ <script>
+ addEventListener("load", function(e) {
+ if (window.parent === window) {
+ document.getElementById("iframe").contentWindow.location.href = window.location.href;
+ }
+ });
+ </script>
+ </body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/forms3.html b/mobile/android/geckoview/src/androidTest/assets/www/forms3.html
new file mode 100644
index 0000000000..073e576d06
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/forms3.html
@@ -0,0 +1,14 @@
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Forms</title>
+ <meta name="viewport" content="minimum-scale=1,width=device-width">
+ </head>
+ <body>
+ <form id="form1">
+ <input type="text" id="user1" placeholder="username">
+ <input type="password" id="pass1" placeholder="password">
+ <input type="submit" value="submit">
+ </form>
+ </body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/forms4.html b/mobile/android/geckoview/src/androidTest/assets/www/forms4.html
new file mode 100644
index 0000000000..ce43a268f4
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/forms4.html
@@ -0,0 +1,14 @@
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Forms</title>
+ <meta name="viewport" content="minimum-scale=1,width=device-width">
+ </head>
+ <body>
+ <form id="form1">
+ <input type="text" id="user1">
+ <input type="password" id="pass1" autocomplete="new-password">
+ <input type="submit" value="submit">
+ </form>
+ </body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/forms_autocomplete.html b/mobile/android/geckoview/src/androidTest/assets/www/forms_autocomplete.html
new file mode 100644
index 0000000000..ad47079344
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/forms_autocomplete.html
@@ -0,0 +1,23 @@
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Forms</title>
+ <meta name="viewport" content="minimum-scale=1,width=device-width">
+ </head>
+ <body>
+ <form>
+ <input type="text" autocomplete="email" autofocus>
+ <input type="text" autocomplete="username">
+ <input type="password">
+ <input type="submit" value="submit">
+ </form>
+ <iframe id="iframe"></iframe>
+ <script>
+ addEventListener("load", function(e) {
+ if (window.parent === window) {
+ document.getElementById("iframe").contentWindow.location.href = window.location.href;
+ }
+ });
+ </script>
+ </body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/forms_id_value.html b/mobile/android/geckoview/src/androidTest/assets/www/forms_id_value.html
new file mode 100644
index 0000000000..0288b43645
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/forms_id_value.html
@@ -0,0 +1,12 @@
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Forms ID Value</title>
+ <meta name="viewport" content="minimum-scale=1,width=device-width">
+ </head>
+ <body>
+ <form id="form1">
+ <input type="password" id="value">
+ </form>
+ </body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/fullscreen.html b/mobile/android/geckoview/src/androidTest/assets/www/fullscreen.html
new file mode 100644
index 0000000000..97b40f7f96
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/fullscreen.html
@@ -0,0 +1,9 @@
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Fullscreen</title>
+ </head>
+ <body>
+ <div id="fullscreen">Fullscreen Div</div>
+ </body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/getusermedia_xorigin_container.html b/mobile/android/geckoview/src/androidTest/assets/www/getusermedia_xorigin_container.html
new file mode 100644
index 0000000000..7e7b9457e7
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/getusermedia_xorigin_container.html
@@ -0,0 +1,49 @@
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>GetUserMedia from cross-origin iframe: the container document</title>
+ </head>
+ <body>
+ <iframe id="iframe_no_allow" src="http://127.0.0.1:4245/assets/www/getusermedia_xorigin_iframe.html"></iframe>
+ <iframe id="iframe" allow="camera;microphone" src="http://127.0.0.1:4245/assets/www/getusermedia_xorigin_iframe.html"></iframe>
+ <script>
+ "use strict";
+
+ let iframeWindow;
+ let generation = 1;
+
+ async function Send(obj) {
+ obj.gen = generation++;
+ iframeWindow.postMessage(obj, "http://127.0.0.1:4245");
+ while(true) {
+ const {data: {gen, result}} = await new Promise(r => window.onmessage = r);
+ if (gen == obj.gen) {
+ return result;
+ }
+ }
+ }
+
+ function Start(constraints) {
+ if (iframeWindow) {
+ return "iframe mode already decided";
+ }
+ iframeWindow = document.getElementById("iframe").contentWindow;
+ return Send({name: "start", constraints});
+ }
+
+ function StartNoAllow(constraints) {
+ if (iframeWindow) {
+ return "iframe mode already decided";
+ }
+ iframeWindow = document.getElementById("iframe_no_allow").contentWindow;
+ return Send({name: "start", constraints});
+ }
+
+ async function Stop() {
+ const result = await Send({name: "stop"});
+ iframeWindow = undefined;
+ return result;
+ }
+ </script>
+ </body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/getusermedia_xorigin_iframe.html b/mobile/android/geckoview/src/androidTest/assets/www/getusermedia_xorigin_iframe.html
new file mode 100644
index 0000000000..8f79d03ed1
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/getusermedia_xorigin_iframe.html
@@ -0,0 +1,36 @@
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>GetUserMedia from cross-origin iframe: the iframe document</title>
+ </head>
+ <body>
+ <script>
+ "use strict";
+
+ let stream;
+ window.addEventListener("message", async ({data: {name, gen, constraints}}) => {
+ if (name == "start") {
+ try {
+ stream = await navigator.mediaDevices.getUserMedia(constraints);
+ Send({gen, result: "ok"});
+ } catch(e) {
+ Send({gen, result: `${e}`});
+ }
+ } else if (name == "stop") {
+ const result = !!stream;
+ if (stream) {
+ for (const t of stream.getTracks()) {
+ t.stop();
+ }
+ stream = undefined;
+ }
+ Send({gen, result});
+ }
+ });
+
+ function Send(obj) {
+ window.parent.postMessage(obj, "http://localhost:4245");
+ }
+ </script>
+ </body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/hello.html b/mobile/android/geckoview/src/androidTest/assets/www/hello.html
new file mode 100644
index 0000000000..f7a862bf17
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/hello.html
@@ -0,0 +1,10 @@
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Hello, world!</title>
+ <link rel="manifest" href="manifest.webmanifest">
+ </head>
+ <body>
+ <p>Hello, world!</p>
+ </body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/hello2.html b/mobile/android/geckoview/src/androidTest/assets/www/hello2.html
new file mode 100644
index 0000000000..88218a18f6
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/hello2.html
@@ -0,0 +1,9 @@
+<html>
+<head>
+<meta charset="utf-8">
+<title>Hello, world! Again!</title>
+</head>
+<body>
+<p>Hello, world! Again!</p>
+</body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/hungScript.html b/mobile/android/geckoview/src/androidTest/assets/www/hungScript.html
new file mode 100644
index 0000000000..5b3faee9ec
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/hungScript.html
@@ -0,0 +1,14 @@
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Hung Script</title>
+ </head>
+ <body><div id="content"></div></body>
+ <script>
+ var start = new Date().getTime();
+ document.getElementById("content").innerHTML = "Started";
+ // eslint-disable-next-line no-empty
+ while((new Date().getTime() - start) < 5000 ) {};
+ document.getElementById("content").innerHTML = "Finished";
+ </script>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/iframe_100_percent_height_no_scrollable.html b/mobile/android/geckoview/src/androidTest/assets/www/iframe_100_percent_height_no_scrollable.html
new file mode 100644
index 0000000000..289d04a5e3
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/iframe_100_percent_height_no_scrollable.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<html>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, user-scalable=no">
+<style>
+html {
+ height: 100%;
+ width: 100%;
+ /* background contains one extra transparent.gif because we want trick the
+ contentful paint detection; We want to make sure the background is loaded
+ before the test starts so we always wait for the contentful paint timestamp
+ to exist, however, gradient isn't considered as contentful per spec, so Gecko
+ wouldn't generate a timestamp for it. Hence, we added a transparent gif
+ to the image list to trick the detection. */
+ background: url('/assets/www/transparent.gif'), linear-gradient(135deg, red, white);
+}
+body {
+ height: 100%;
+ width: 100%;
+ margin: 0px;
+ padding: 0px;
+}
+iframe {
+ height: 100%;
+ width: 100%;
+ margin: 0px;
+ padding: 0px;
+ border: none;
+ display: block;
+}
+</style>
+<iframe frameborder=0 srcdoc="<!DOCTYPE HTML>
+ <html>
+ <style>
+ html, body {
+ height: 100%;
+ width: 100%;
+ margin: 0px;
+ padding: 0px;
+ }
+ </style>
+ <body>
+ <div style='width: 100%; height: 100%; background-color: green;'></div>
+ <script>
+ if (parent.document.location.search.startsWith('?event')) {
+ document.querySelector('div').addEventListener('touchstart', e => {
+ if (parent.document.location.search == '?event-prevent') {
+ e.preventDefault();
+ }
+ });
+ }
+ </script>
+ </body>
+ </html>">
+</iframe>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/iframe_100_percent_height_scrollable.html b/mobile/android/geckoview/src/androidTest/assets/www/iframe_100_percent_height_scrollable.html
new file mode 100644
index 0000000000..967df79f12
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/iframe_100_percent_height_scrollable.html
@@ -0,0 +1,56 @@
+<!DOCTYPE html>
+<html>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, user-scalable=no">
+<style>
+html {
+ height: 100%;
+ width: 100%;
+ /* background contains one extra transparent.gif because we want trick the
+ contentful paint detection; We want to make sure the background is loaded
+ before the test starts so we always wait for the contentful paint timestamp
+ to exist, however, gradient isn't considered as contentful per spec, so Gecko
+ wouldn't generate a timestamp for it. Hence, we added a transparent gif
+ to the image list to trick the detection. */
+ background: url('/assets/www/transparent.gif'), linear-gradient(135deg, red, white);
+}
+body {
+ height: 100%;
+ width: 100%;
+ margin: 0px;
+ padding: 0px;
+}
+iframe {
+ height: 100%;
+ width: 100%;
+ margin: 0px;
+ padding: 0px;
+ border: none;
+ display: block;
+}
+</style>
+<iframe frameborder=0 srcdoc="<!DOCTYPE HTML>
+ <html>
+ <style>
+ html, body {
+ height: 100%;
+ width: 100%;
+ margin: 0px;
+ padding: 0px;
+ }
+ </style>
+ <body>
+ <div style='width: 100%; height: 500vh; background-color: green;'></div>
+ <script>
+ if (parent.document.location.search.startsWith('?event')) {
+ document.querySelector('div').addEventListener('touchstart', e => {
+ if (parent.document.location.search == '?event-prevent') {
+ e.preventDefault();
+ }
+ });
+ }
+ </script>
+ </body>
+ </html>">
+</iframe>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/iframe_98vh_no_scrollable.html b/mobile/android/geckoview/src/androidTest/assets/www/iframe_98vh_no_scrollable.html
new file mode 100644
index 0000000000..5ab95fe411
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/iframe_98vh_no_scrollable.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, user-scalable=no">
+<style>
+html, body {
+ margin: 0px;
+ padding: 0px;
+ /* background contains one extra transparent.gif because we want trick the
+ contentful paint detection; We want to make sure the background is loaded
+ before the test starts so we always wait for the contentful paint timestamp
+ to exist, however, gradient isn't considered as contentful per spec, so Gecko
+ wouldn't generate a timestamp for it. Hence, we added a transparent gif
+ to the image list to trick the detection. */
+ background: url('/assets/www/transparent.gif'), linear-gradient(135deg, red, white);
+}
+iframe {
+ margin: 0px;
+ padding: 0px;
+ height: 98vh;
+ width: 100%;
+ border: none;
+ display: block;
+}
+</style>
+<iframe frameborder=0 srcdoc="<!DOCTYPE HTML>
+ <html>
+ <style>
+ html, body {
+ height: 100%;
+ width: 100%;
+ margin: 0px;
+ padding: 0px;
+ }
+ </style>
+ <body>
+ <div style='width: 100%; height: 100%; background-color: green;'></div>
+ <script>
+ if (parent.document.location.search.startsWith('?event')) {
+ document.querySelector('div').addEventListener('touchstart', e => {
+ if (parent.document.location.search == '?event-prevent') {
+ e.preventDefault();
+ }
+ });
+ }
+ </script>
+ </body>
+ </html>">
+</iframe>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/iframe_98vh_scrollable.html b/mobile/android/geckoview/src/androidTest/assets/www/iframe_98vh_scrollable.html
new file mode 100644
index 0000000000..ebd30addda
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/iframe_98vh_scrollable.html
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, user-scalable=no">
+<style>
+html, body {
+ margin: 0px;
+ padding: 0px;
+ /* background contains one extra transparent.gif because we want trick the
+ contentful paint detection; We want to make sure the background is loaded
+ before the test starts so we always wait for the contentful paint timestamp
+ to exist, however, gradient isn't considered as contentful per spec, so Gecko
+ wouldn't generate a timestamp for it. Hence, we added a transparent gif
+ to the image list to trick the detection. */
+ background: url('/assets/www/transparent.gif'), linear-gradient(135deg, red, white);
+}
+iframe {
+ margin: 0px;
+ padding: 0px;
+ height: 98vh;
+ width: 100%;
+ border: none;
+ display: block;
+}
+</style>
+<iframe frameborder=0 srcdoc="<!DOCTYPE HTML>
+ <html>
+ <style>
+ html, body {
+ height: 100%;
+ width: 100%;
+ margin: 0px;
+ padding: 0px;
+ }
+ </style>
+ <body>
+ <div style='width: 100%; height: 500vh; background-color: green;'></div>
+ <script>
+ if (parent.document.location.search.startsWith('?event')) {
+ document.querySelector('div').addEventListener('touchstart', e => {
+ if (parent.document.location.search == '?event-prevent') {
+ e.preventDefault();
+ }
+ });
+ }
+ </script>
+ </body>
+ </html>">
+</iframe>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/iframe_hello.html b/mobile/android/geckoview/src/androidTest/assets/www/iframe_hello.html
new file mode 100644
index 0000000000..531ddcb2b6
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/iframe_hello.html
@@ -0,0 +1,10 @@
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Hello, world!</title>
+ </head>
+ <body>
+ <p>Hello, world! From Top Level.</p>
+ <iframe src="hello.html"></iframe>
+ </body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/iframe_redirect_automation.html b/mobile/android/geckoview/src/androidTest/assets/www/iframe_redirect_automation.html
new file mode 100644
index 0000000000..b98e7b1c1d
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/iframe_redirect_automation.html
@@ -0,0 +1,10 @@
+<html>
+<head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+</head>
+<body>
+Some stuff
+<iframe src="http://example.org/tests/junit/simple_redirect.sjs?http://example.org"></iframe>
+</body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/iframe_redirect_local.html b/mobile/android/geckoview/src/androidTest/assets/www/iframe_redirect_local.html
new file mode 100644
index 0000000000..fd9ca37cc7
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/iframe_redirect_local.html
@@ -0,0 +1,10 @@
+<html>
+<head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1.0">
+</head>
+<body>
+Some stuff
+<iframe src="http://jigsaw.w3.org/HTTP/300/301.html"></iframe>
+</body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/iframe_unknown_protocol.html b/mobile/android/geckoview/src/androidTest/assets/www/iframe_unknown_protocol.html
new file mode 100644
index 0000000000..b785eda99e
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/iframe_unknown_protocol.html
@@ -0,0 +1,10 @@
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Hello, world!</title>
+ </head>
+ <body>
+ <p>Hello, world! From Top Level.</p>
+ <iframe src="foo://bar"></iframe>
+ </body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/images/test.gif b/mobile/android/geckoview/src/androidTest/assets/www/images/test.gif
new file mode 100644
index 0000000000..ba3b541c31
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/images/test.gif
Binary files differ
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/inputs.html b/mobile/android/geckoview/src/androidTest/assets/www/inputs.html
new file mode 100644
index 0000000000..431aaf70a4
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/inputs.html
@@ -0,0 +1,22 @@
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Inputs</title>
+ </head>
+ <body>
+ <div id="text">lorem</div>
+ <input type="text" id="input" value="ipsum">
+ <textarea id="textarea">dolor</textarea>
+ <div id="contenteditable" contenteditable="true">sit</div>
+ <iframe id="iframe" src="selectionAction_frame.html"></iframe>
+ <iframe id="designmode" src="selectionAction_frame.html"></iframe>
+ </body>
+ <script>
+ addEventListener("load", function() {
+ document.getElementById("iframe").contentDocument.body.textContent = "amet";
+ var designmode = document.getElementById("designmode");
+ designmode.contentDocument.body.textContent = "consectetur";
+ designmode.contentDocument.designMode = "on";
+ });
+ </script>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/links.html b/mobile/android/geckoview/src/androidTest/assets/www/links.html
new file mode 100644
index 0000000000..7fc7b17444
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/links.html
@@ -0,0 +1,24 @@
+<html>
+<head>
+<meta charset="utf-8">
+<title>Links</title>
+<style>
+:link {
+ color: rgb(0, 0, 255);
+}
+
+:visited {
+ color: rgb(255, 0, 0);
+}
+</style>
+</head>
+<body>
+<ul>
+ <li><a id="mozilla" href="https://mozilla.org">Mozilla</a></li>
+ <li><a id="firefox" href="https://getfirefox.com">Get Firefox!</a></li>
+ <li><a id="bugzilla" href="https://bugzilla.mozilla.org">Bugzilla</a></li>
+ <li><a id="testpilot" href="https://testpilot.firefox.com">Test Pilot</a></li>
+ <li><a id="fxa" href="https://accounts.firefox.com">Firefox Accounts</a></li>
+</ul>
+</body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/loremIpsum.html b/mobile/android/geckoview/src/androidTest/assets/www/loremIpsum.html
new file mode 100644
index 0000000000..d4654ca34c
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/loremIpsum.html
@@ -0,0 +1,16 @@
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Lorem ipsum</title>
+ </head>
+ <body>
+ <p style="font-family: monospace; width: 20ch;">
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor
+ incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud
+ exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure
+ dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.
+ Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt
+ mollit <a href="#">anim id</a> est laborum.
+ </p>
+ </body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/manifest.webmanifest b/mobile/android/geckoview/src/androidTest/assets/www/manifest.webmanifest
new file mode 100644
index 0000000000..5528465ba2
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/manifest.webmanifest
@@ -0,0 +1,17 @@
+{
+ "name": "App",
+ "short_name": "app",
+ "start_url": "./start/index.html",
+ "display": "standalone",
+ "background_color": "#c0ffeeee",
+ "theme_color": "cadetblue",
+ "icons": [{
+ "src": "images/test.gif",
+ "sizes": "192x192",
+ "type": "image/gif"
+ }],
+ "related_applications": [{
+ "platform": "play",
+ "url": "https://play.google.com/store/apps/details?id=my.first.webapp"
+ }]
+} \ No newline at end of file
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/media_session_default1.html b/mobile/android/geckoview/src/androidTest/assets/www/media_session_default1.html
new file mode 100644
index 0000000000..34ea6c5b62
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/media_session_default1.html
@@ -0,0 +1,13 @@
+<html>
+ <head><title>MediaSessionDefaultTest1</title></head>
+ <body>
+ <script>
+ const audio1 = document.createElement("audio");
+ audio1.src = "audio/owl.mp3";
+
+ window.onload = () => {
+ audio1.play();
+ };
+ </script>
+ </body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/media_session_dom1.html b/mobile/android/geckoview/src/androidTest/assets/www/media_session_dom1.html
new file mode 100644
index 0000000000..9557088928
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/media_session_dom1.html
@@ -0,0 +1,99 @@
+<html>
+ <head><title>MediaSessionDOMTest1</title></head>
+ <body>
+ <script>
+ function updatePositionState(event) {
+ if (event.target != active) {
+ return;
+ }
+ navigator.mediaSession.setPositionState({
+ duration: parseFloat(event.target.duration),
+ position: parseFloat(event.target.currentTime),
+ playbackRate: 1,
+ });
+ }
+
+ function updateMetadata() {
+ navigator.mediaSession.metadata = active.metadata;
+ }
+
+ function getTrack(offset) {
+ console.log("" + active.id + " " + offset);
+ const nextId = Math.min(tracks.length - 1,
+ Math.max(0, parseInt(active.id) + offset));
+ return tracks[nextId];
+ }
+
+ navigator.mediaSession.setActionHandler("play", async () => {
+ updateMetadata();
+ await active.play();
+ });
+
+ navigator.mediaSession.setActionHandler("pause", () => {
+ active.pause();
+ });
+
+ navigator.mediaSession.setActionHandler("previoustrack", () => {
+ active = getTrack(-1);
+ });
+
+ navigator.mediaSession.setActionHandler("nexttrack", () => {
+ active = getTrack(1);
+ });
+
+ const audio1 = document.createElement("audio");
+ audio1.src = "audio/owl.mp3";
+ audio1.addEventListener("timeupdate", updatePositionState);
+ audio1.metadata = new window.MediaMetadata({
+ title: "hoot",
+ artist: "owl",
+ album: "hoots",
+ artwork: [{
+ src: "images/test.gif",
+ type: "image/gif",
+ sizes: "265x199"
+ }]
+ });
+ audio1.id = 0;
+
+ const audio2 = document.createElement("audio");
+ audio2.src = "audio/owl.mp3";
+ audio2.addEventListener("timeupdate", updatePositionState);
+ audio2.metadata = new window.MediaMetadata({
+ title: "hoot2",
+ artist: "stillowl",
+ album: "dahoots",
+ artwork: [{
+ src: "images/test.gif",
+ type: "image/gif",
+ sizes: "265x199"
+ }]
+ });
+ audio2.id = 1;
+
+ const audio3 = document.createElement("audio");
+ audio3.src = "audio/owl.mp3";
+ audio3.addEventListener("timeupdate", updatePositionState);
+ audio3.metadata = new window.MediaMetadata({
+ title: "hoot3",
+ artist: "immaowl",
+ album: "mahoots",
+ artwork: [{
+ src: "images/test.gif",
+ type: "image/gif",
+ sizes: "265x199"
+ }]
+ });
+ audio3.id = 2;
+
+ const tracks = [audio1, audio2, audio3];
+ let active = audio1;
+
+ window.onload = async () => {
+ active = getTrack(0);
+ updateMetadata();
+ await active.play();
+ };
+ </script>
+ </body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/mp4.html b/mobile/android/geckoview/src/androidTest/assets/www/mp4.html
new file mode 100644
index 0000000000..09909fac69
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/mp4.html
@@ -0,0 +1,11 @@
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>MP4 Video</title>
+ </head>
+ <body>
+ <video controls preload>
+ <source src="videos/short.mp4"></source>
+ </video>
+ </body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/newSession.html b/mobile/android/geckoview/src/androidTest/assets/www/newSession.html
new file mode 100644
index 0000000000..51a761ca6b
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/newSession.html
@@ -0,0 +1,10 @@
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Hello, world!</title>
+ </head>
+ <body>
+ <a id="targetBlankLink" target="_blank" rel="opener" href="newSession_child.html">target="_blank"</a>
+ <a id="noOpenerLink" target="_blank" rel="noopener" href="http://example.com">rel="noopener"</a>
+ </body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/newSession_child.html b/mobile/android/geckoview/src/androidTest/assets/www/newSession_child.html
new file mode 100644
index 0000000000..c01539fcdf
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/newSession_child.html
@@ -0,0 +1,9 @@
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Hello, world!</title>
+ </head>
+ <body>
+ <p>I'm the child</p>
+ </body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/ogg.html b/mobile/android/geckoview/src/androidTest/assets/www/ogg.html
new file mode 100644
index 0000000000..dd478d3b3f
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/ogg.html
@@ -0,0 +1,11 @@
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>OGG Video</title>
+ </head>
+ <body>
+ <video controls preload>
+ <source src="videos/video.ogg"></source>
+ </video>
+ </body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/popup.html b/mobile/android/geckoview/src/androidTest/assets/www/popup.html
new file mode 100644
index 0000000000..03a8515159
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/popup.html
@@ -0,0 +1,12 @@
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Hello, world!</title>
+ </head>
+ <body>
+ <p>Launching popup...</p>
+ <script>
+ window.open("hello.html");
+ </script>
+ </body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/prompts.html b/mobile/android/geckoview/src/androidTest/assets/www/prompts.html
new file mode 100644
index 0000000000..d95a2c51e3
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/prompts.html
@@ -0,0 +1,26 @@
+<!DOCTYPE html>
+<html>
+ <head>
+ <meta charset="utf-8">
+ </head>
+ <body>
+ <select id="selectexample">
+ <option>1</option>
+ <option>2</option>
+ </select>
+
+ <input type="date" id="dateexample" />
+
+ <input type="month" id="monthexample" />
+
+ <input type="week" id="weekexample" />
+
+ <input type="time" id="timeexample" />
+
+ <input type="datetime-local" id="datetimelocalexample" />
+
+ <input type="color" id="colorexample" value="#ffffff" />
+
+ <input type="file" id="fileexample" accept="image/*,.pdf" capture="user" />
+ </body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/push/push.html b/mobile/android/geckoview/src/androidTest/assets/www/push/push.html
new file mode 100644
index 0000000000..05727e2523
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/push/push.html
@@ -0,0 +1,10 @@
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Push API test</title>
+ </head>
+ <body>
+ <p>Hello, world!</p>
+ <script src="push.js"></script>
+ </body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/push/push.js b/mobile/android/geckoview/src/androidTest/assets/www/push/push.js
new file mode 100644
index 0000000000..f6eac1696e
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/push/push.js
@@ -0,0 +1,44 @@
+window.doSubscribe = async function(applicationServerKey) {
+ const registration = await navigator.serviceWorker.register("./sw.js");
+ const sub = await registration.pushManager.subscribe({
+ applicationServerKey,
+ });
+ return sub.toJSON();
+};
+
+window.doGetSubscription = async function() {
+ const registration = await navigator.serviceWorker.register("./sw.js");
+ const sub = await registration.pushManager.getSubscription();
+ if (sub) {
+ return sub.toJSON();
+ }
+
+ return null;
+};
+
+window.doUnsubscribe = async function() {
+ const registration = await navigator.serviceWorker.register("./sw.js");
+ const sub = await registration.pushManager.getSubscription();
+ sub.unsubscribe();
+ return {};
+};
+
+window.doWaitForPushEvent = function() {
+ return new Promise(resolve => {
+ navigator.serviceWorker.addEventListener("message", function(e) {
+ if (e.data.type === "push") {
+ resolve(e.data.payload);
+ }
+ });
+ });
+};
+
+window.doWaitForSubscriptionChange = function() {
+ return new Promise(resolve => {
+ navigator.serviceWorker.addEventListener("message", function(e) {
+ if (e.data.type === "pushsubscriptionchange") {
+ resolve(e.data.type);
+ }
+ });
+ });
+};
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/push/sw.js b/mobile/android/geckoview/src/androidTest/assets/www/push/sw.js
new file mode 100644
index 0000000000..1ebbf50053
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/push/sw.js
@@ -0,0 +1,26 @@
+self.addEventListener("install", function() {
+ self.skipWaiting();
+});
+
+self.addEventListener("activate", function(e) {
+ e.waitUntil(self.clients.claim());
+});
+
+self.addEventListener("push", async function(e) {
+ const clients = await self.clients.matchAll();
+ clients.forEach(function(client) {
+ client.postMessage({ type: "push", payload: e.data.text() });
+ });
+
+ try {
+ const { title, body } = e.data.json();
+ self.registration.showNotification(title, { body });
+ } catch (e) {}
+});
+
+self.addEventListener("pushsubscriptionchange", async function(e) {
+ const clients = await self.clients.matchAll();
+ clients.forEach(function(client) {
+ client.postMessage({ type: "pushsubscriptionchange" });
+ });
+});
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/reflect_local_storage_into_title.html b/mobile/android/geckoview/src/androidTest/assets/www/reflect_local_storage_into_title.html
new file mode 100644
index 0000000000..b8eafee9aa
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/reflect_local_storage_into_title.html
@@ -0,0 +1,17 @@
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>no title</title>
+ <script>
+ // If we have a query string, save it to the local storage.
+ if (window.location.search.length > 0) {
+ const value = window.location.search.substr(1);
+ localStorage.setItem("ctx", value);
+ }
+
+ // Set the title to reflect the local storage value.
+ document.title = "storage=" + localStorage.getItem("ctx");
+ </script>
+ </head>
+ <body></body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/resubmit.html b/mobile/android/geckoview/src/androidTest/assets/www/resubmit.html
new file mode 100644
index 0000000000..d6e05a77de
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/resubmit.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+</head>
+<body>
+ <form action="hello.html" method="post">
+ <input id=text>
+ <button id=submit>Submit</button>
+ </form>
+</body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/root_100_percent_height.html b/mobile/android/geckoview/src/androidTest/assets/www/root_100_percent_height.html
new file mode 100644
index 0000000000..1f778fcae4
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/root_100_percent_height.html
@@ -0,0 +1,36 @@
+<!DOCTYPE html>
+<html>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, user-scalable=no">
+<style>
+html {
+ height: 100%;
+ width: 100%;
+ /* background contains one extra transparent.gif because we want trick the
+ contentful paint detection; We want to make sure the background is loaded
+ before the test starts so we always wait for the contentful paint timestamp
+ to exist, however, gradient isn't considered as contentful per spec, so Gecko
+ wouldn't generate a timestamp for it. Hence, we added a transparent gif
+ to the image list to trick the detection. */
+ background: url('/assets/www/transparent.gif'), linear-gradient(135deg, red, white);
+}
+body {
+ height: 100%;
+ width: 100%;
+ margin: 0px;
+ padding: 0px;
+}
+</style>
+<body>
+<div style="width: 100%; height: 100%; background-color: green;"></div>
+<script>
+ if (document.location.search.startsWith('?event')) {
+ document.querySelector('div').addEventListener('touchstart', e => {
+ if (document.location.search == '?event-prevent') {
+ e.preventDefault();
+ }
+ });
+ }
+</script>
+</body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/root_100vh.html b/mobile/android/geckoview/src/androidTest/assets/www/root_100vh.html
new file mode 100644
index 0000000000..ca0666fcbc
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/root_100vh.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, user-scalable=no">
+<style>
+html {
+ height: 100%;
+ width: 100%;
+ /* background contains one extra transparent.gif because we want trick the
+ contentful paint detection; We want to make sure the background is loaded
+ before the test starts so we always wait for the contentful paint timestamp
+ to exist, however, gradient isn't considered as contentful per spec, so Gecko
+ wouldn't generate a timestamp for it. Hence, we added a transparent gif
+ to the image list to trick the detection. */
+ background: url('/assets/www/transparent.gif'), linear-gradient(135deg, red, white);
+}
+body {
+ width: 100%;
+ margin: 0px;
+ padding: 0px;
+}
+</style>
+<body>
+<div style="width: 100%; height: 100vh; background-color: green;"></div>
+<script>
+ if (document.location.search.startsWith('?event')) {
+ document.querySelector('div').addEventListener('touchstart', e => {
+ if (document.location.search == '?event-prevent') {
+ e.preventDefault();
+ }
+ });
+ }
+</script>
+</body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/root_98vh.html b/mobile/android/geckoview/src/androidTest/assets/www/root_98vh.html
new file mode 100644
index 0000000000..ced7f4298a
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/root_98vh.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<html>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, user-scalable=no">
+<style>
+html {
+ height: 100%;
+ width: 100%;
+ /* background contains one extra transparent.gif because we want trick the
+ contentful paint detection; We want to make sure the background is loaded
+ before the test starts so we always wait for the contentful paint timestamp
+ to exist, however, gradient isn't considered as contentful per spec, so Gecko
+ wouldn't generate a timestamp for it. Hence, we added a transparent gif
+ to the image list to trick the detection. */
+ background: url('/assets/www/transparent.gif'), linear-gradient(135deg, red, white);
+}
+body {
+ width: 100%;
+ margin: 0px;
+ padding: 0px;
+}
+</style>
+<body>
+<div style="width: 100%; height: 98vh; background-color: green;"></div>
+<script>
+ if (document.location.search.startsWith('?event')) {
+ document.querySelector('div').addEventListener('touchstart', e => {
+ if (document.location.search == '?event-prevent') {
+ e.preventDefault();
+ }
+ });
+ }
+</script>
+</body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/saveState.html b/mobile/android/geckoview/src/androidTest/assets/www/saveState.html
new file mode 100644
index 0000000000..f576c29664
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/saveState.html
@@ -0,0 +1,18 @@
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Hello, world!</title>
+ <meta name="viewport" content="width=device-width,initial-scale=1">
+ <style>
+ p {
+ height: 300vh;
+ }
+ </style>
+ </head>
+ <body>
+ <form id="form">
+ <input type="text" id="name">
+ </form>
+ <p>Hello, world!</p>
+ </body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/scroll.html b/mobile/android/geckoview/src/androidTest/assets/www/scroll.html
new file mode 100644
index 0000000000..9c92eae839
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/scroll.html
@@ -0,0 +1,46 @@
+<html>
+ <head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=0.5">
+ <style type="text/css">
+body {
+ margin: 0;
+ /* background contains one extra transparent.gif because we want trick the
+ contentful paint detection; We want to make sure the background is loaded
+ before the test starts so we always wait for the contentful paint timestamp
+ to exist, however, gradient isn't considered as contentful per spec, so Gecko
+ wouldn't generate a timestamp for it. Hence, we added a transparent gif
+ to the image list to trick the detection. */
+ background: url('/assets/www/transparent.gif'), linear-gradient(135deg, red, white);
+}
+
+#one {
+ background-color: red;
+ width: 200vw;
+ height: 50vh;
+}
+
+#two {
+ background-color: green;
+ width: 200vw;
+ height: 50vh;
+}
+
+#three {
+ background-color: blue;
+ width: 200vw;
+ height: 200vh;
+}
+ </style>
+ </head>
+ <body>
+ <div id="one"></div>
+ <div id="two"></div>
+ <div id="three"></div>
+ <script>
+ document.getElementById('two').addEventListener('touchstart', e => {
+ console.log('not preventing default');
+ });
+ </script>
+ </body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/selectionAction_frame.html b/mobile/android/geckoview/src/androidTest/assets/www/selectionAction_frame.html
new file mode 100644
index 0000000000..99197658b7
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/selectionAction_frame.html
@@ -0,0 +1,6 @@
+<html>
+ <head>
+ <meta charset="utf-8">
+ </head>
+ <body></body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/simple_redirect.sjs b/mobile/android/geckoview/src/androidTest/assets/www/simple_redirect.sjs
new file mode 100644
index 0000000000..b6249cadff
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/simple_redirect.sjs
@@ -0,0 +1,5 @@
+function handleRequest(request, response)
+{
+ response.setStatusLine(request.httpVersion, 301, "Moved Permanently");
+ response.setHeader("Location", request.queryString, false);
+}
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/titleChange.html b/mobile/android/geckoview/src/androidTest/assets/www/titleChange.html
new file mode 100644
index 0000000000..3e89774bf2
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/titleChange.html
@@ -0,0 +1,16 @@
+<html>
+<head>
+ <meta charset="utf-8">
+</head>
+<header><title>Title1</title></header>
+ <body>
+ <script>
+ addEventListener("load", function() {
+ setTimeout(function() {
+ document.title = "Title2";
+ }, 100);
+ });
+ </script>
+ </body>
+ <iframe src="hello.html"></iframe>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/touch.html b/mobile/android/geckoview/src/androidTest/assets/www/touch.html
new file mode 100644
index 0000000000..431a280fd9
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/touch.html
@@ -0,0 +1,54 @@
+<html>
+ <head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="height=device-height,width=device-width,initial-scale=1.0">
+ <style type="text/css">
+body {
+ width: 100%;
+ height: 100%;
+ margin: 0;
+ padding: 0px;
+ /* background contains one extra transparent.gif because we want trick the
+ contentful paint detection; We want to make sure the background is loaded
+ before the test starts so we always wait for the contentful paint timestamp
+ to exist, however, gradient isn't considered as contentful per spec, so Gecko
+ wouldn't generate a timestamp for it. Hence, we added a transparent gif
+ to the image list to trick the detection. */
+ background: url('/assets/www/transparent.gif'), linear-gradient(135deg, red, white);
+}
+
+#one {
+ background-color: red;
+ width: 100%;
+ height: 33%
+}
+
+#two {
+ background-color: green;
+ width: 100%;
+ height: 33%
+}
+
+#three {
+ background-color: blue;
+ width: 100%;
+ height: 33%
+}
+ </style>
+ </head>
+ <body>
+ <div id="one"></div>
+ <div id="two"></div>
+ <div id="three"></div>
+ <script>
+ document.getElementById('two').addEventListener('touchstart', e => {
+ console.log('preventing default');
+ e.preventDefault();
+ });
+
+ document.getElementById('three').addEventListener('touchstart', e => {
+ console.log('not preventing default');
+ });
+ </script>
+ </body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/touchstart.html b/mobile/android/geckoview/src/androidTest/assets/www/touchstart.html
new file mode 100644
index 0000000000..dae3e933e7
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/touchstart.html
@@ -0,0 +1,37 @@
+<html>
+ <head>
+ <meta charset="utf-8">
+ <meta name="viewport" content="width=device-width, initial-scale=0.5">
+ <style type="text/css">
+body {
+ margin: 0;
+ /* background contains one extra transparent.gif because we want trick the
+ contentful paint detection; We want to make sure the background is loaded
+ before the test starts so we always wait for the contentful paint timestamp
+ to exist, however, gradient isn't considered as contentful per spec, so Gecko
+ wouldn't generate a timestamp for it. Hence, we added a transparent gif
+ to the image list to trick the detection. */
+ background: url('/assets/www/transparent.gif'), linear-gradient(135deg, red, white);
+}
+
+#one {
+ background-color: red;
+ width: 200%;
+ height: 100vh;
+}
+#two {
+ background-color: blue;
+ width: 200%;
+ height: 800vh;
+}
+ </style>
+ </head>
+ <body>
+ <div id="one"></div>
+ <div id="two"></div>
+ <script>
+ document.getElementById("two").addEventListener("touchstart", e => {
+ });
+ </script>
+ </body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/trackers.html b/mobile/android/geckoview/src/androidTest/assets/www/trackers.html
new file mode 100644
index 0000000000..8d92c70721
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/trackers.html
@@ -0,0 +1,14 @@
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Trackers</title>
+ </head>
+ <body>
+ <p>Trackers</p>
+
+ <!-- test-track-simple -->
+ <script src="http://trackertest.org/tracker.js"></script>
+ <script src="https://tracking.example.com/tracker.js"></script>
+ <script src="https://itisatracker.org/tracker.js"></script>
+ </body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/transparent.gif b/mobile/android/geckoview/src/androidTest/assets/www/transparent.gif
new file mode 100644
index 0000000000..e565824aaf
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/transparent.gif
Binary files differ
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/update_manifest.json b/mobile/android/geckoview/src/androidTest/assets/www/update_manifest.json
new file mode 100644
index 0000000000..7b2de1f278
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/update_manifest.json
@@ -0,0 +1,40 @@
+{
+ "addons": {
+ "update@example.com": {
+ "updates": [
+ {
+ "version": "1.0",
+ "update_link": "https://example.org/tests/junit/update-1.xpi"
+ },
+ {
+ "version": "2.0",
+ "update_link": "https://example.org/tests/junit/update-2.xpi"
+ }
+ ]
+ },
+ "update-postpone@example.com": {
+ "updates": [
+ {
+ "version": "1.0",
+ "update_link": "https://example.org/tests/junit/update-postpone-1.xpi"
+ },
+ {
+ "version": "2.0",
+ "update_link": "https://example.org/tests/junit/update-postpone-2.xpi"
+ }
+ ]
+ },
+ "update-with-perms@example.com": {
+ "updates": [
+ {
+ "version": "1.0",
+ "update_link": "https://example.org/tests/junit/update-with-perms-1.xpi"
+ },
+ {
+ "version": "2.0",
+ "update_link": "https://example.org/tests/junit/update-with-perms-2.xpi"
+ }
+ ]
+ }
+ }
+}
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/videos/gizmo.webm b/mobile/android/geckoview/src/androidTest/assets/www/videos/gizmo.webm
new file mode 100644
index 0000000000..518531a93f
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/videos/gizmo.webm
Binary files differ
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/videos/short.mp4 b/mobile/android/geckoview/src/androidTest/assets/www/videos/short.mp4
new file mode 100644
index 0000000000..a674b7eb68
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/videos/short.mp4
Binary files differ
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/videos/video.ogg b/mobile/android/geckoview/src/androidTest/assets/www/videos/video.ogg
new file mode 100644
index 0000000000..ac7ece3519
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/videos/video.ogg
Binary files differ
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/viewport.html b/mobile/android/geckoview/src/androidTest/assets/www/viewport.html
new file mode 100644
index 0000000000..9594246ed9
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/viewport.html
@@ -0,0 +1,16 @@
+<html>
+<head>
+<meta charset="utf-8">
+<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
+<style type="text/css">
+#wide {
+ background-color: rgb(200, 0, 0);
+ width: 100%;
+ height: 40px;
+}
+</style>
+</head>
+<body>
+<div id="wide"></div>
+</body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/webm.html b/mobile/android/geckoview/src/androidTest/assets/www/webm.html
new file mode 100644
index 0000000000..f329582575
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/webm.html
@@ -0,0 +1,11 @@
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>WebM Video</title>
+ </head>
+ <body>
+ <video controls preload>
+ <source src="videos/gizmo.webm"></source>
+ </video>
+ </body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/worker/open_window.html b/mobile/android/geckoview/src/androidTest/assets/www/worker/open_window.html
new file mode 100644
index 0000000000..03b4c86200
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/worker/open_window.html
@@ -0,0 +1,11 @@
+<html>
+ <head>
+ <meta charset="utf-8">
+ <title>Open Window test</title>
+ </head>
+ <body>
+ <p>Hello, world!</p>
+ <script type="text/javascript" src="./open_window.js">
+ </script>
+ </body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/worker/open_window.js b/mobile/android/geckoview/src/androidTest/assets/www/worker/open_window.js
new file mode 100644
index 0000000000..05bd68c797
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/worker/open_window.js
@@ -0,0 +1,15 @@
+navigator.serviceWorker.register("./service-worker.js", {
+ scope: ".",
+});
+
+function showNotification() {
+ Notification.requestPermission(function(result) {
+ if (result === "granted") {
+ navigator.serviceWorker.ready.then(function(registration) {
+ registration.showNotification("Open Window Notification", {
+ body: "Hello",
+ });
+ });
+ }
+ });
+}
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/worker/open_window_target.html b/mobile/android/geckoview/src/androidTest/assets/www/worker/open_window_target.html
new file mode 100644
index 0000000000..83cfc49234
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/worker/open_window_target.html
@@ -0,0 +1,9 @@
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Open Window test target</title>
+</head>
+<body>
+<p>Hello, world!</p>
+</body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/worker/service-worker.js b/mobile/android/geckoview/src/androidTest/assets/www/worker/service-worker.js
new file mode 100644
index 0000000000..aa0d292193
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/worker/service-worker.js
@@ -0,0 +1,15 @@
+self.addEventListener("install", function() {
+ console.log("install");
+ self.skipWaiting();
+});
+
+self.addEventListener("activate", function(e) {
+ console.log("activate");
+ e.waitUntil(self.clients.claim());
+});
+
+self.onnotificationclick = function(event) {
+ console.log("onnotificationclick");
+ self.clients.openWindow("open_window_target.html");
+ event.notification.close();
+};