summaryrefslogtreecommitdiffstats
path: root/mobile/android/geckoview
diff options
context:
space:
mode:
Diffstat (limited to 'mobile/android/geckoview')
-rw-r--r--mobile/android/geckoview/api.txt11
-rw-r--r--mobile/android/geckoview/build.gradle8
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/test-open-popup-browser-action.js2
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/actions/test-open-popup-page-action.js2
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/borderify-mv3/borderify.js1
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/borderify-mv3/icons/border-48.pngbin0 -> 225 bytes
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/borderify-mv3/icons/icon.svg1
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/borderify-mv3/manifest.json26
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/borderify/manifest.json3
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/optional-permission-request/clickToRequestPermission.html11
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/optional-permission-request/manifest.json14
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/optional-permission-request/request-permission.js10
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/redirect-to-android-resource/background.js2
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/test-support/test-support.js2
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/web_extensions/update-postpone-1/background.js2
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/clickToReplace.html10
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/context_menu_blob_buffered.html2
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/context_menu_blob_full.html2
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/forms.html2
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/pull-to-refresh-subframe.html2
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/push/sw.js2
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/scroll.html2
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/touch-action.html2
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/touch.html2
-rw-r--r--mobile/android/geckoview/src/androidTest/assets/www/touchstart.html2
-rw-r--r--mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/AutocompleteTest.kt2
-rw-r--r--mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/BaseSessionTest.kt1
-rw-r--r--mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/GeckoAppShellTest.kt1
-rw-r--r--mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/GeckoSessionTestRuleTest.kt1
-rw-r--r--mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/GeolocationTest.kt3
-rw-r--r--mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/HistoryDelegateTest.kt5
-rw-r--r--mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/LocaleTest.kt12
-rw-r--r--mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/NavigationDelegateTest.kt163
-rw-r--r--mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/OpenWindowTest.kt8
-rw-r--r--mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/PdfCreationTest.kt12
-rw-r--r--mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/PermissionDelegateTest.kt54
-rw-r--r--mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/ProgressDelegateTest.kt22
-rw-r--r--mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/RuntimeSettingsTest.kt3
-rw-r--r--mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/ScreenshotTest.kt5
-rw-r--r--mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/SelectionActionDelegateTest.kt18
-rw-r--r--mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/TestContentProvider.java19
-rw-r--r--mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/TextInputDelegateTest.kt42
-rw-r--r--mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/TrackingPermissionService.java3
-rw-r--r--mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/VideoCaptureTest.kt58
-rw-r--r--mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/WebExtensionTest.kt168
-rw-r--r--mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/WebNotificationTest.kt15
-rw-r--r--mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/WebPushTest.kt3
-rw-r--r--mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rule/GeckoSessionTestRule.java3
-rw-r--r--mobile/android/geckoview/src/main/java/org/mozilla/gecko/AndroidGamepadManager.java2
-rw-r--r--mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoAppShell.java15
-rw-r--r--mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoDragAndDrop.java6
-rw-r--r--mobile/android/geckoview/src/main/java/org/mozilla/gecko/InputMethods.java9
-rw-r--r--mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/MediaDrmProxy.java1
-rw-r--r--mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/LocaleUtils.java32
-rw-r--r--mobile/android/geckoview/src/main/java/org/mozilla/geckoview/ContentInputStream.java17
-rw-r--r--mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoInputConnection.java47
-rw-r--r--mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java26
-rw-r--r--mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java30
-rw-r--r--mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSessionSettings.java4
-rw-r--r--mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoView.java6
-rw-r--r--mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebExtension.java54
-rw-r--r--mobile/android/geckoview/src/main/java/org/mozilla/geckoview/doc-files/CHANGELOG.md25
-rw-r--r--mobile/android/geckoview/src/test/java/org/mozilla/gecko/util/LocaleUtilsTest.java47
63 files changed, 882 insertions, 183 deletions
diff --git a/mobile/android/geckoview/api.txt b/mobile/android/geckoview/api.txt
index 86869c0abe..30c4d35585 100644
--- a/mobile/android/geckoview/api.txt
+++ b/mobile/android/geckoview/api.txt
@@ -51,6 +51,7 @@ import java.lang.Boolean;
import java.lang.CharSequence;
import java.lang.Class;
import java.lang.Comparable;
+import java.lang.Deprecated;
import java.lang.Double;
import java.lang.Exception;
import java.lang.Float;
@@ -85,6 +86,7 @@ import org.mozilla.geckoview.CompositorController;
import org.mozilla.geckoview.ContentBlocking;
import org.mozilla.geckoview.ContentBlockingController;
import org.mozilla.geckoview.CrashHandler;
+import org.mozilla.geckoview.DeprecationSchedule;
import org.mozilla.geckoview.ExperimentDelegate;
import org.mozilla.geckoview.GeckoDisplay;
import org.mozilla.geckoview.GeckoResult;
@@ -967,7 +969,7 @@ package org.mozilla.geckoview {
method @NonNull public GeckoRuntimeSettings.Builder preferredColorScheme(int);
method @NonNull public GeckoRuntimeSettings.Builder remoteDebuggingEnabled(boolean);
method @NonNull public GeckoRuntimeSettings.Builder screenSizeOverride(int, int);
- method @NonNull public GeckoRuntimeSettings.Builder telemetryDelegate(@NonNull RuntimeTelemetry.Delegate);
+ method @Deprecated @DeprecationSchedule(id="geckoview-gvst",version=127) @NonNull public GeckoRuntimeSettings.Builder telemetryDelegate(@NonNull RuntimeTelemetry.Delegate);
method @NonNull public GeckoRuntimeSettings.Builder translationsOfferPopup(boolean);
method @NonNull public GeckoRuntimeSettings.Builder trustedRecursiveResolverMode(int);
method @NonNull public GeckoRuntimeSettings.Builder trustedRecursiveResolverUri(@NonNull String);
@@ -1262,7 +1264,8 @@ package org.mozilla.geckoview {
method @UiThread default public void onCanGoForward(@NonNull GeckoSession, boolean);
method @Nullable @UiThread default public GeckoResult<String> onLoadError(@NonNull GeckoSession, @Nullable String, @NonNull WebRequestError);
method @Nullable @UiThread default public GeckoResult<AllowOrDeny> onLoadRequest(@NonNull GeckoSession, @NonNull GeckoSession.NavigationDelegate.LoadRequest);
- method @UiThread default public void onLocationChange(@NonNull GeckoSession, @Nullable String, @NonNull List<GeckoSession.PermissionDelegate.ContentPermission>);
+ method @Deprecated @DeprecationSchedule(id="geckoview-onlocationchange",version=127) @UiThread default public void onLocationChange(@NonNull GeckoSession, @Nullable String, @NonNull List<GeckoSession.PermissionDelegate.ContentPermission>);
+ method @UiThread default public void onLocationChange(@NonNull GeckoSession, @Nullable String, @NonNull List<GeckoSession.PermissionDelegate.ContentPermission>, @NonNull Boolean);
method @Nullable @UiThread default public GeckoResult<GeckoSession> onNewSession(@NonNull GeckoSession, @NonNull String);
method @Nullable @UiThread default public GeckoResult<AllowOrDeny> onSubframeLoadRequest(@NonNull GeckoSession, @NonNull GeckoSession.NavigationDelegate.LoadRequest);
field public static final int LOAD_REQUEST_IS_REDIRECT = 8388608;
@@ -2674,12 +2677,16 @@ package org.mozilla.geckoview {
field @Nullable public final String downloadUrl;
field public final boolean enabled;
field @Nullable public final String fullDescription;
+ field @NonNull public final String[] grantedOptionalOrigins;
+ field @NonNull public final String[] grantedOptionalPermissions;
field @Nullable public final String homepageUrl;
field @NonNull public final Image icon;
field @Nullable public final String incognito;
field public final boolean isRecommended;
field @Nullable public final String name;
field public final boolean openOptionsPageInTab;
+ field @NonNull public final String[] optionalOrigins;
+ field @NonNull public final String[] optionalPermissions;
field @Nullable public final String optionsPageUrl;
field @NonNull public final String[] origins;
field @NonNull public final String[] permissions;
diff --git a/mobile/android/geckoview/build.gradle b/mobile/android/geckoview/build.gradle
index 32224dd5a2..6e5826655d 100644
--- a/mobile/android/geckoview/build.gradle
+++ b/mobile/android/geckoview/build.gradle
@@ -155,6 +155,10 @@ android {
aidl = true
}
+ publishing {
+ singleVariant('withGeckoBinariesDebug')
+ }
+
namespace 'org.mozilla.geckoview'
}
@@ -229,7 +233,7 @@ dependencies {
implementation "androidx.legacy:legacy-support-v4:1.0.0"
implementation "com.google.android.gms:play-services-fido:20.0.1"
- implementation "org.yaml:snakeyaml:2.0"
+ implementation "org.yaml:snakeyaml:2.2"
implementation "androidx.lifecycle:lifecycle-common:2.6.1"
implementation "androidx.lifecycle:lifecycle-process:2.6.1"
@@ -514,7 +518,7 @@ android.libraryVariants.all configureVariantDebugLevel
// be somewhere where the Android plugin is available so that we can fish the
// path to "android.jar".
task("generateSDKBindings", type: JavaExec) {
- classpath project(':annotations').jar.archivePath
+ classpath project(':annotations').jar.archiveFile
classpath project(':annotations').compileJava.classpath
classpath project(':annotations').sourceSets.main.runtimeClasspath
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
index cde31235ac..421859dfa2 100644
--- 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
@@ -1,7 +1,7 @@
window.addEventListener("DOMContentLoaded", init);
function init() {
- document.body.addEventListener("click", event => {
+ document.body.addEventListener("click", () => {
browser.browserAction.openPopup();
});
}
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
index f16d96333f..6e38fc7858 100644
--- 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
@@ -1,7 +1,7 @@
window.addEventListener("DOMContentLoaded", init);
function init() {
- document.body.addEventListener("click", event => {
+ document.body.addEventListener("click", () => {
browser.pageAction.openPopup();
});
}
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/borderify-mv3/borderify.js b/mobile/android/geckoview/src/androidTest/assets/web_extensions/borderify-mv3/borderify.js
new file mode 100644
index 0000000000..9c3728b381
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/borderify-mv3/borderify.js
@@ -0,0 +1 @@
+document.body.style.border = "5px solid red";
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/borderify-mv3/icons/border-48.png b/mobile/android/geckoview/src/androidTest/assets/web_extensions/borderify-mv3/icons/border-48.png
new file mode 100644
index 0000000000..90687de26d
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/borderify-mv3/icons/border-48.png
Binary files differ
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/borderify-mv3/icons/icon.svg b/mobile/android/geckoview/src/androidTest/assets/web_extensions/borderify-mv3/icons/icon.svg
new file mode 100644
index 0000000000..dd1fae7d15
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/borderify-mv3/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-mv3/manifest.json b/mobile/android/geckoview/src/androidTest/assets/web_extensions/borderify-mv3/manifest.json
new file mode 100644
index 0000000000..f1dbe5fe71
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/borderify-mv3/manifest.json
@@ -0,0 +1,26 @@
+{
+ "manifest_version": 3,
+ "name": "Borderify",
+ "version": "1.0",
+ "description": "Adds a red border to all webpages matching example.com.",
+ "browser_specific_settings": {
+ "gecko": {
+ "id": "borderify@tests.mozilla.org"
+ }
+ },
+ "icons": {
+ "48": "icons/border-48.png"
+ },
+ "content_scripts": [
+ {
+ "matches": ["*://*.example.com/*"],
+ "js": ["borderify.js"]
+ }
+ ],
+ "options_ui": {
+ "page": "dummy.html"
+ },
+ "granted_host_permissions": true,
+ "optional_permissions": ["clipboardRead", "*://opt-host-perm.example.com/*"],
+ "host_permissions": ["*://host-perm.example.com/*"]
+}
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
index 4e3daf6708..4ea4eb093e 100644
--- a/mobile/android/geckoview/src/androidTest/assets/web_extensions/borderify/manifest.json
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/borderify/manifest.json
@@ -19,5 +19,6 @@
],
"options_ui": {
"page": "dummy.html"
- }
+ },
+ "optional_permissions": ["clipboardRead", "*://developer.mozilla.org/*"]
}
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/optional-permission-request/clickToRequestPermission.html b/mobile/android/geckoview/src/androidTest/assets/web_extensions/optional-permission-request/clickToRequestPermission.html
new file mode 100644
index 0000000000..e6ddcb8c8d
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/optional-permission-request/clickToRequestPermission.html
@@ -0,0 +1,11 @@
+<html>
+ <head>
+ <meta charset="utf-8" />
+ <title>Hello, world!</title>
+ <meta name="viewport" content="initial-scale=1.0" />
+ <script type="text/javascript" src="request-permission.js"></script>
+ </head>
+ <body style="height: 100%">
+ <p>Hello, world!</p>
+ </body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/optional-permission-request/manifest.json b/mobile/android/geckoview/src/androidTest/assets/web_extensions/optional-permission-request/manifest.json
new file mode 100644
index 0000000000..0644eb637f
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/optional-permission-request/manifest.json
@@ -0,0 +1,14 @@
+{
+ "manifest_version": 3,
+ "name": "optional-permission-request",
+ "browser_specific_settings": {
+ "gecko": {
+ "id": "optional-permission-request@example.com"
+ }
+ },
+ "version": "1.0",
+ "description": "Request optional extension permissions.",
+ "permissions": ["nativeMessaging", "geckoViewAddons"],
+ "granted_host_permissions": true,
+ "optional_permissions": ["geolocation", "*://example.com/*", "activeTab"]
+}
diff --git a/mobile/android/geckoview/src/androidTest/assets/web_extensions/optional-permission-request/request-permission.js b/mobile/android/geckoview/src/androidTest/assets/web_extensions/optional-permission-request/request-permission.js
new file mode 100644
index 0000000000..bae3ceea6f
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/optional-permission-request/request-permission.js
@@ -0,0 +1,10 @@
+window.onload = () => {
+ document.body.addEventListener("click", async () => {
+ const perms = {
+ permissions: ["activeTab"],
+ origins: ["*://example.com/*"],
+ };
+ const response = await browser.permissions.request(perms);
+ browser.runtime.sendNativeMessage("browser", `${response}`);
+ });
+};
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
index fdf088a505..e77d482e14 100644
--- 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
@@ -2,7 +2,7 @@
function setupRedirect(fromUrl, redirectUrl) {
browser.webRequest.onBeforeRequest.addListener(
- details => {
+ () => {
console.log(`Extension redirects from ${fromUrl} to ${redirectUrl}`);
return { redirectUrl };
},
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
index 18e047ca1a..f47f42d12e 100644
--- 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
@@ -30,7 +30,7 @@ function connectNativePort() {
}
});
- function sendResponse(id, response, exception) {
+ function sendResponse(id, response) {
Promise.resolve(response).then(
value => sendSyncResponse(id, value),
reason => sendSyncResponse(id, null, reason)
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
index a301506ca7..8266ad8258 100644
--- 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
@@ -1,3 +1,3 @@
-browser.runtime.onUpdateAvailable.addListener(details => {
+browser.runtime.onUpdateAvailable.addListener(() => {
// Do nothing, this is just here to prevent auto update.
});
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/clickToReplace.html b/mobile/android/geckoview/src/androidTest/assets/www/clickToReplace.html
new file mode 100644
index 0000000000..6d583586f1
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/assets/www/clickToReplace.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.replace('replacedUrl')">
+ <p>Hello, world!</p>
+ </body>
+</html>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/context_menu_blob_buffered.html b/mobile/android/geckoview/src/androidTest/assets/www/context_menu_blob_buffered.html
index 9849747a41..950e48129e 100644
--- a/mobile/android/geckoview/src/androidTest/assets/www/context_menu_blob_buffered.html
+++ b/mobile/android/geckoview/src/androidTest/assets/www/context_menu_blob_buffered.html
@@ -8,7 +8,7 @@
<video id="video" controls preload></video>
</body>
<script>
- window.addEventListener("DOMContentLoaded", function (e) {
+ window.addEventListener("DOMContentLoaded", function () {
const video = document.getElementById("video");
const mediaSource = new MediaSource();
video.src = URL.createObjectURL(mediaSource);
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/context_menu_blob_full.html b/mobile/android/geckoview/src/androidTest/assets/www/context_menu_blob_full.html
index 5ebc2bddba..175d14bddf 100644
--- a/mobile/android/geckoview/src/androidTest/assets/www/context_menu_blob_full.html
+++ b/mobile/android/geckoview/src/androidTest/assets/www/context_menu_blob_full.html
@@ -8,7 +8,7 @@
<div id="image_container"></div>
</body>
<script>
- window.addEventListener("DOMContentLoaded", function (e) {
+ window.addEventListener("DOMContentLoaded", function () {
const svg = `<svg viewBox="0 0 100 100" xmlns="http://www.w3.org/2000/svg">
<circle cx="50" cy="50" r="50" stroke="orange" fill="transparent" stroke-width="5"/>
</svg>`;
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/forms.html b/mobile/android/geckoview/src/androidTest/assets/www/forms.html
index 06c2ed64db..5d3ce9345e 100644
--- a/mobile/android/geckoview/src/androidTest/assets/www/forms.html
+++ b/mobile/android/geckoview/src/androidTest/assets/www/forms.html
@@ -24,7 +24,7 @@
<iframe id="iframe"></iframe>
</body>
<script>
- addEventListener("load", function (e) {
+ addEventListener("load", function () {
if (window.parent === window) {
document.getElementById("iframe").contentWindow.location.href =
window.location.href;
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/pull-to-refresh-subframe.html b/mobile/android/geckoview/src/androidTest/assets/www/pull-to-refresh-subframe.html
index d1a421c0a3..4fadaf063f 100644
--- a/mobile/android/geckoview/src/androidTest/assets/www/pull-to-refresh-subframe.html
+++ b/mobile/android/geckoview/src/androidTest/assets/www/pull-to-refresh-subframe.html
@@ -70,7 +70,7 @@
.getElementById("three")
.scrollTo({ top: 200, behavior: "instant" });
- document.getElementById("four").addEventListener("touchstart", e => {
+ document.getElementById("four").addEventListener("touchstart", () => {
console.log("not preventing default");
});
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/push/sw.js b/mobile/android/geckoview/src/androidTest/assets/www/push/sw.js
index 2e51383205..5c0acdb981 100644
--- a/mobile/android/geckoview/src/androidTest/assets/www/push/sw.js
+++ b/mobile/android/geckoview/src/androidTest/assets/www/push/sw.js
@@ -22,7 +22,7 @@ self.addEventListener("push", async function (e) {
} catch (e) {}
});
-self.addEventListener("pushsubscriptionchange", async function (e) {
+self.addEventListener("pushsubscriptionchange", async function () {
const clients = await self.clients.matchAll();
clients.forEach(function (client) {
client.postMessage({ type: "pushsubscriptionchange" });
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/scroll.html b/mobile/android/geckoview/src/androidTest/assets/www/scroll.html
index e906e45686..ecc35e690c 100644
--- a/mobile/android/geckoview/src/androidTest/assets/www/scroll.html
+++ b/mobile/android/geckoview/src/androidTest/assets/www/scroll.html
@@ -51,7 +51,7 @@
e.preventDefault();
});
- document.getElementById("three").addEventListener("touchstart", e => {
+ document.getElementById("three").addEventListener("touchstart", () => {
console.log("not preventing default");
});
</script>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/touch-action.html b/mobile/android/geckoview/src/androidTest/assets/www/touch-action.html
index 62266b6ef7..bf315cfb7e 100644
--- a/mobile/android/geckoview/src/androidTest/assets/www/touch-action.html
+++ b/mobile/android/geckoview/src/androidTest/assets/www/touch-action.html
@@ -41,7 +41,7 @@
}
div.style.touchAction = searchParams.get("touch-action");
if (searchParams.has("event")) {
- div.addEventListener("touchstart", e => {});
+ div.addEventListener("touchstart", () => {});
}
</script>
</body>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/touch.html b/mobile/android/geckoview/src/androidTest/assets/www/touch.html
index ba3bc098a9..6852a0f4fe 100644
--- a/mobile/android/geckoview/src/androidTest/assets/www/touch.html
+++ b/mobile/android/geckoview/src/androidTest/assets/www/touch.html
@@ -50,7 +50,7 @@
e.preventDefault();
});
- document.getElementById("three").addEventListener("touchstart", e => {
+ document.getElementById("three").addEventListener("touchstart", () => {
console.log("not preventing default");
});
</script>
diff --git a/mobile/android/geckoview/src/androidTest/assets/www/touchstart.html b/mobile/android/geckoview/src/androidTest/assets/www/touchstart.html
index 9ee1f461a7..42d1787ef1 100644
--- a/mobile/android/geckoview/src/androidTest/assets/www/touchstart.html
+++ b/mobile/android/geckoview/src/androidTest/assets/www/touchstart.html
@@ -31,7 +31,7 @@
<div id="one"></div>
<div id="two"></div>
<script>
- document.getElementById("two").addEventListener("touchstart", e => {});
+ document.getElementById("two").addEventListener("touchstart", () => {});
</script>
</body>
</html>
diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/AutocompleteTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/AutocompleteTest.kt
index fbfe2fe46d..dddba77768 100644
--- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/AutocompleteTest.kt
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/AutocompleteTest.kt
@@ -2407,7 +2407,7 @@ class AutocompleteTest : BaseSessionTest() {
"Hint should match",
option.hint,
equalTo(LoginSaveOption.Hint.GENERATED))
- */
+ */
assertThat(
"Password should not be empty",
diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/BaseSessionTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/BaseSessionTest.kt
index 655db7248f..d57cd8f157 100644
--- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/BaseSessionTest.kt
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/BaseSessionTest.kt
@@ -36,6 +36,7 @@ open class BaseSessionTest(
const val RESUBMIT_CONFIRM = "/assets/www/resubmit.html"
const val BEFORE_UNLOAD = "/assets/www/beforeunload.html"
const val CLICK_TO_RELOAD_HTML_PATH = "/assets/www/clickToReload.html"
+ const val CLICK_TO_REPLACE_HTML_PATH = "/assets/www/clickToReplace.html"
const val CLIPBOARD_READ_HTML_PATH = "/assets/www/clipboard_read.html"
const val CONTENT_CRASH_URL = "about:crashcontent"
const val DND_HTML_PATH = "/assets/www/dnd.html"
diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/GeckoAppShellTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/GeckoAppShellTest.kt
index c05820012d..75204a2f5d 100644
--- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/GeckoAppShellTest.kt
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/GeckoAppShellTest.kt
@@ -86,6 +86,7 @@ class GeckoAppShellTest : BaseSessionTest() {
// This is waiting and holding the test harness open while Android Lifecycle events complete
mainSession.waitUntilCalled(object : GeckoSession.ContentDelegate, GeckoSession.NavigationDelegate {
@GeckoSessionTestRule.AssertCalled(count = 2)
+ @Suppress("OVERRIDE_DEPRECATION")
override fun onLocationChange(
session: GeckoSession,
url: String?,
diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/GeckoSessionTestRuleTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/GeckoSessionTestRuleTest.kt
index d6380bf5bf..2ec305f913 100644
--- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/GeckoSessionTestRuleTest.kt
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/GeckoSessionTestRuleTest.kt
@@ -1115,6 +1115,7 @@ class GeckoSessionTestRuleTest : BaseSessionTest(noErrorCollector = true) {
@NullDelegate(NavigationDelegate::class)
fun delegateDuringNextWait_throwOnNullDelegate() {
mainSession.delegateDuringNextWait(object : NavigationDelegate {
+ @Suppress("OVERRIDE_DEPRECATION")
override fun onLocationChange(session: GeckoSession, url: String?, perms: MutableList<PermissionDelegate.ContentPermission>) {
}
})
diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/GeolocationTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/GeolocationTest.kt
index 1bb568123c..4deac5fb66 100644
--- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/GeolocationTest.kt
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/GeolocationTest.kt
@@ -72,8 +72,7 @@ class GeolocationTest : BaseSessionTest() {
override fun onContentPermissionRequest(
session: GeckoSession,
perm: GeckoSession.PermissionDelegate.ContentPermission,
- ):
- GeckoResult<Int> {
+ ): GeckoResult<Int> {
return GeckoResult.fromValue(GeckoSession.PermissionDelegate.ContentPermission.VALUE_ALLOW)
}
override fun onAndroidPermissionsRequest(
diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/HistoryDelegateTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/HistoryDelegateTest.kt
index 370594a93f..2d2f4bb4af 100644
--- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/HistoryDelegateTest.kt
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/HistoryDelegateTest.kt
@@ -250,6 +250,11 @@ class HistoryDelegateTest : BaseSessionTest() {
}
@Test fun onHistoryStateChangeSavingState() {
+ // TODO: Bug 1884334
+ val geckoPrefs = sessionRule.getPrefs(
+ "fission.disableSessionHistoryInParent",
+ )
+ assumeThat(geckoPrefs[0] as Boolean, equalTo(true))
// TODO: Bug 1837551
assumeThat(sessionRule.env.isFission, equalTo(false))
diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/LocaleTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/LocaleTest.kt
index 69deac1c89..608681d7d9 100644
--- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/LocaleTest.kt
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/LocaleTest.kt
@@ -40,4 +40,16 @@ class LocaleTest : BaseSessionTest() {
equalTo(listOf("en-GB", "en-US", "en-FR")),
)
}
+
+ @Test
+ fun acceptLangaugeFormat() {
+ // No way to override default language settings from unit test.
+ // So we only test this on current settings.
+
+ val intlAcceptLanauge = "intl.accept_languages"
+ val prefValue = (sessionRule.getPrefs(intlAcceptLanauge)[0] as String).split(",")
+ for (value in prefValue) {
+ assertThat("Accept-Lanauge format should be language or language-region", value.filter { it == '-' }.count(), lessThanOrEqualTo(1))
+ }
+ }
}
diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/NavigationDelegateTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/NavigationDelegateTest.kt
index aab32cd01d..839ac4b468 100644
--- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/NavigationDelegateTest.kt
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/NavigationDelegateTest.kt
@@ -67,8 +67,7 @@ class NavigationDelegateTest : BaseSessionTest() {
override fun onLoadRequest(
session: GeckoSession,
request: LoadRequest,
- ):
- GeckoResult<AllowOrDeny>? {
+ ): GeckoResult<AllowOrDeny>? {
assertThat(
"URI should be " + testLoader.getUri(),
request.uri,
@@ -123,6 +122,7 @@ class NavigationDelegateTest : BaseSessionTest() {
if (errorPageUrl != null) {
sessionRule.waitUntilCalled(object : ContentDelegate, NavigationDelegate {
@AssertCalled(count = 1, order = [1])
+ @Suppress("OVERRIDE_DEPRECATION")
override fun onLocationChange(
session: GeckoSession,
url: String?,
@@ -492,8 +492,7 @@ class NavigationDelegateTest : BaseSessionTest() {
override fun onLoadRequest(
session: GeckoSession,
request: LoadRequest,
- ):
- GeckoResult<AllowOrDeny>? {
+ ): GeckoResult<AllowOrDeny>? {
assertThat("The URLs must match", request.uri, equalTo(forEachCall(uri, httpsUri)))
return null
}
@@ -552,8 +551,7 @@ class NavigationDelegateTest : BaseSessionTest() {
override fun onLoadRequest(
session: GeckoSession,
request: LoadRequest,
- ):
- GeckoResult<AllowOrDeny>? {
+ ): GeckoResult<AllowOrDeny>? {
assertThat("The URLs must match", request.uri, equalTo(forEachCall(uri, httpsUri)))
return null
}
@@ -593,6 +591,7 @@ class NavigationDelegateTest : BaseSessionTest() {
sessionRule.waitUntilCalled(object : ContentDelegate, NavigationDelegate {
@AssertCalled(count = 1, order = [1])
+ @Suppress("OVERRIDE_DEPRECATION")
override fun onLocationChange(
session: GeckoSession,
url: String?,
@@ -611,8 +610,7 @@ class NavigationDelegateTest : BaseSessionTest() {
override fun onLoadRequest(
session: GeckoSession,
request: LoadRequest,
- ):
- GeckoResult<AllowOrDeny>? {
+ ): GeckoResult<AllowOrDeny>? {
assertThat("The URLs must match", request.uri, equalTo(forEachCall(uri, httpsUri)))
return null
}
@@ -646,6 +644,7 @@ class NavigationDelegateTest : BaseSessionTest() {
// No good way to wait for loading about:blank error page. Use onLocaitonChange etc.
sessionRule.waitUntilCalled(object : ContentDelegate, NavigationDelegate {
+ @Suppress("OVERRIDE_DEPRECATION")
override fun onLocationChange(
session: GeckoSession,
url: String?,
@@ -665,8 +664,7 @@ class NavigationDelegateTest : BaseSessionTest() {
override fun onLoadRequest(
session: GeckoSession,
request: LoadRequest,
- ):
- GeckoResult<AllowOrDeny>? {
+ ): GeckoResult<AllowOrDeny>? {
// We set http scheme only in case it's not iFrame
assertThat("The URLs must match", request.uri, equalTo(uri))
return null
@@ -717,8 +715,7 @@ class NavigationDelegateTest : BaseSessionTest() {
override fun onLoadRequest(
session: GeckoSession,
request: LoadRequest,
- ):
- GeckoResult<AllowOrDeny>? {
+ ): GeckoResult<AllowOrDeny>? {
assertThat(
"URI should be HTTP then redirected to HTTPS",
request.uri,
@@ -774,8 +771,7 @@ class NavigationDelegateTest : BaseSessionTest() {
override fun onSubframeLoadRequest(
session: GeckoSession,
request: LoadRequest,
- ):
- GeckoResult<AllowOrDeny>? {
+ ): GeckoResult<AllowOrDeny>? {
assertThat("URI should not be null", request.uri, notNullValue())
assertThat("URI should match", request.uri, endsWith(iframeUri))
return null
@@ -862,8 +858,7 @@ class NavigationDelegateTest : BaseSessionTest() {
override fun onLoadRequest(
session: GeckoSession,
request: LoadRequest,
- ):
- GeckoResult<AllowOrDeny>? {
+ ): GeckoResult<AllowOrDeny>? {
assertThat("Session should not be null", session, notNullValue())
assertThat("URI should not be null", request.uri, notNullValue())
assertThat(
@@ -913,8 +908,7 @@ class NavigationDelegateTest : BaseSessionTest() {
override fun onLoadRequest(
session: GeckoSession,
request: LoadRequest,
- ):
- GeckoResult<AllowOrDeny>? {
+ ): GeckoResult<AllowOrDeny>? {
assertThat("Session should not be null", session, notNullValue())
assertThat("App requested this load", request.isDirectNavigation, equalTo(true))
assertThat("URI should not be null", request.uri, notNullValue())
@@ -927,8 +921,7 @@ class NavigationDelegateTest : BaseSessionTest() {
override fun onSubframeLoadRequest(
session: GeckoSession,
request: LoadRequest,
- ):
- GeckoResult<AllowOrDeny>? {
+ ): GeckoResult<AllowOrDeny>? {
assertThat("Session should not be null", session, notNullValue())
assertThat("App did not request this load", request.isDirectNavigation, equalTo(false))
assertThat("URI should not be null", request.uri, notNullValue())
@@ -960,8 +953,7 @@ class NavigationDelegateTest : BaseSessionTest() {
override fun onLoadRequest(
session: GeckoSession,
request: LoadRequest,
- ):
- GeckoResult<AllowOrDeny>? {
+ ): GeckoResult<AllowOrDeny>? {
assertThat("Session should not be null", session, notNullValue())
assertThat("URI should not be null", request.uri, notNullValue())
assertThat(
@@ -1023,8 +1015,7 @@ class NavigationDelegateTest : BaseSessionTest() {
override fun onLoadRequest(
session: GeckoSession,
request: LoadRequest,
- ):
- GeckoResult<AllowOrDeny>? {
+ ): GeckoResult<AllowOrDeny>? {
assertThat("URL should match", request.uri, equalTo(forEachCall(uri, redirectUri)))
assertThat(
"From app should be correct",
@@ -1447,8 +1438,7 @@ class NavigationDelegateTest : BaseSessionTest() {
override fun onLoadRequest(
session: GeckoSession,
request: LoadRequest,
- ):
- GeckoResult<AllowOrDeny>? {
+ ): GeckoResult<AllowOrDeny>? {
assertThat("Session should not be null", session, notNullValue())
assertThat("URI should not be null", request.uri, notNullValue())
assertThat("URI should match", request.uri, endsWith(HELLO_HTML_PATH))
@@ -1478,10 +1468,12 @@ class NavigationDelegateTest : BaseSessionTest() {
session: GeckoSession,
url: String?,
perms: MutableList<PermissionDelegate.ContentPermission>,
+ hasUserGesture: Boolean,
) {
assertThat("Session should not be null", session, notNullValue())
assertThat("URL should not be null", url, notNullValue())
assertThat("URL should match", url, endsWith(HELLO_HTML_PATH))
+ assertThat("Should not have user gesture", hasUserGesture, equalTo(false))
}
@AssertCalled(count = 1, order = [2])
@@ -1514,8 +1506,10 @@ class NavigationDelegateTest : BaseSessionTest() {
session: GeckoSession,
url: String?,
perms: MutableList<PermissionDelegate.ContentPermission>,
+ hasUserGesture: Boolean,
) {
assertThat("URL should match the provided data URL", url, equalTo(dataUrl))
+ assertThat("Should not have user gesture", hasUserGesture, equalTo(false))
}
@AssertCalled(count = 1)
@@ -1542,6 +1536,7 @@ class NavigationDelegateTest : BaseSessionTest() {
// Test that if we unset the navigation delegate during a load, the load still proceeds.
var onLocationCount = 0
mainSession.navigationDelegate = object : NavigationDelegate {
+ @Suppress("OVERRIDE_DEPRECATION")
override fun onLocationChange(
session: GeckoSession,
url: String?,
@@ -1587,12 +1582,14 @@ class NavigationDelegateTest : BaseSessionTest() {
session: GeckoSession,
url: String?,
perms: MutableList<PermissionDelegate.ContentPermission>,
+ hasUserGesture: Boolean,
) {
assertThat(
"URL should be a data URL",
url,
equalTo(createDataUri(dataString, mimeType)),
)
+ assertThat("Should not have user gesture", hasUserGesture, equalTo(false))
}
@AssertCalled(count = 1)
@@ -1612,8 +1609,10 @@ class NavigationDelegateTest : BaseSessionTest() {
session: GeckoSession,
url: String?,
perms: MutableList<PermissionDelegate.ContentPermission>,
+ hasUserGesture: Boolean,
) {
assertThat("URL should be a data URL", url, startsWith("data:"))
+ assertThat("Should not have user gesture", hasUserGesture, equalTo(false))
}
@AssertCalled(count = 1)
@@ -1641,8 +1640,10 @@ class NavigationDelegateTest : BaseSessionTest() {
session: GeckoSession,
url: String?,
perms: MutableList<PermissionDelegate.ContentPermission>,
+ hasUserGesture: Boolean,
) {
assertThat("URL should match", url, equalTo(createDataUri(bytes, "text/html")))
+ assertThat("Should not have user gesture", hasUserGesture, equalTo(false))
}
@AssertCalled(count = 1)
@@ -1683,8 +1684,10 @@ class NavigationDelegateTest : BaseSessionTest() {
session: GeckoSession,
url: String?,
perms: MutableList<PermissionDelegate.ContentPermission>,
+ hasUserGesture: Boolean,
) {
assertThat("URL should match", url, equalTo(createDataUri(bytes, mimeType)))
+ assertThat("Should not have user gesture", hasUserGesture, equalTo(false))
}
@AssertCalled(count = 1)
@@ -1714,8 +1717,7 @@ class NavigationDelegateTest : BaseSessionTest() {
override fun onLoadRequest(
session: GeckoSession,
request: LoadRequest,
- ):
- GeckoResult<AllowOrDeny>? {
+ ): GeckoResult<AllowOrDeny>? {
assertThat("URI should match", request.uri, endsWith(HELLO_HTML_PATH))
assertThat(
"Trigger URL should be null",
@@ -1740,8 +1742,10 @@ class NavigationDelegateTest : BaseSessionTest() {
session: GeckoSession,
url: String?,
perms: MutableList<PermissionDelegate.ContentPermission>,
+ hasUserGesture: Boolean,
) {
assertThat("URL should match", url, endsWith(HELLO_HTML_PATH))
+ assertThat("Should not have user gesture", hasUserGesture, equalTo(false))
}
@AssertCalled(count = 1, order = [2])
@@ -1774,8 +1778,10 @@ class NavigationDelegateTest : BaseSessionTest() {
session: GeckoSession,
url: String?,
perms: MutableList<PermissionDelegate.ContentPermission>,
+ hasUserGesture: Boolean,
) {
assertThat("URL should match", url, endsWith(HELLO2_HTML_PATH))
+ assertThat("Should not have user gesture", hasUserGesture, equalTo(false))
}
})
@@ -1787,8 +1793,7 @@ class NavigationDelegateTest : BaseSessionTest() {
override fun onLoadRequest(
session: GeckoSession,
request: LoadRequest,
- ):
- GeckoResult<AllowOrDeny>? {
+ ): GeckoResult<AllowOrDeny>? {
assertThat(
"Load should not be direct",
request.isDirectNavigation,
@@ -1802,8 +1807,10 @@ class NavigationDelegateTest : BaseSessionTest() {
session: GeckoSession,
url: String?,
perms: MutableList<PermissionDelegate.ContentPermission>,
+ hasUserGesture: Boolean,
) {
assertThat("URL should match", url, endsWith(HELLO_HTML_PATH))
+ assertThat("Should not have user gesture", hasUserGesture, equalTo(false))
}
@AssertCalled(count = 1, order = [2])
@@ -1830,8 +1837,7 @@ class NavigationDelegateTest : BaseSessionTest() {
override fun onLoadRequest(
session: GeckoSession,
request: LoadRequest,
- ):
- GeckoResult<AllowOrDeny>? {
+ ): GeckoResult<AllowOrDeny>? {
assertThat(
"Load should not be direct",
request.isDirectNavigation,
@@ -1845,8 +1851,10 @@ class NavigationDelegateTest : BaseSessionTest() {
session: GeckoSession,
url: String?,
perms: MutableList<PermissionDelegate.ContentPermission>,
+ hasUserGesture: Boolean,
) {
assertThat("URL should match", url, endsWith(HELLO2_HTML_PATH))
+ assertThat("Should not have user gesture", hasUserGesture, equalTo(false))
}
@AssertCalled(count = 1, order = [2])
@@ -1872,8 +1880,7 @@ class NavigationDelegateTest : BaseSessionTest() {
override fun onLoadRequest(
session: GeckoSession,
request: LoadRequest,
- ):
- GeckoResult<AllowOrDeny>? {
+ ): GeckoResult<AllowOrDeny>? {
if (request.uri.endsWith(HELLO_HTML_PATH)) {
return GeckoResult.deny()
} else {
@@ -1913,8 +1920,7 @@ class NavigationDelegateTest : BaseSessionTest() {
override fun onLoadRequest(
session: GeckoSession,
request: LoadRequest,
- ):
- GeckoResult<AllowOrDeny>? {
+ ): GeckoResult<AllowOrDeny>? {
assertThat("URI should be correct", request.uri, endsWith(NEW_SESSION_CHILD_HTML_PATH))
assertThat(
"Trigger URL should match",
@@ -1969,8 +1975,7 @@ class NavigationDelegateTest : BaseSessionTest() {
override fun onLoadRequest(
session: GeckoSession,
request: LoadRequest,
- ):
- GeckoResult<AllowOrDeny>? {
+ ): GeckoResult<AllowOrDeny>? {
assertThat("URI should be correct", request.uri, endsWith(NEW_SESSION_CHILD_HTML_PATH))
assertThat(
"Trigger URL should be null",
@@ -2080,8 +2085,7 @@ class NavigationDelegateTest : BaseSessionTest() {
override fun onLoadRequest(
session: GeckoSession,
request: LoadRequest,
- ):
- GeckoResult<AllowOrDeny>? {
+ ): GeckoResult<AllowOrDeny>? {
// Pretend we handled the target="_blank" link click.
if (request.uri.endsWith(NEW_SESSION_CHILD_HTML_PATH)) {
return GeckoResult.deny()
@@ -2102,8 +2106,7 @@ class NavigationDelegateTest : BaseSessionTest() {
override fun onLoadRequest(
session: GeckoSession,
request: LoadRequest,
- ):
- GeckoResult<AllowOrDeny>? {
+ ): GeckoResult<AllowOrDeny>? {
assertThat(
"URI must match",
request.uri,
@@ -2151,8 +2154,7 @@ class NavigationDelegateTest : BaseSessionTest() {
mainSession.waitUntilCalled(object : NavigationDelegate {
@AssertCalled(count = 1, order = [1])
- override fun onLoadRequest(session: GeckoSession, request: LoadRequest):
- GeckoResult<AllowOrDeny>? {
+ override fun onLoadRequest(session: GeckoSession, request: LoadRequest): GeckoResult<AllowOrDeny>? {
assertThat(
"URL should be correct",
request.uri,
@@ -2172,8 +2174,7 @@ class NavigationDelegateTest : BaseSessionTest() {
}
@AssertCalled(count = 1, order = [2])
- override fun onNewSession(session: GeckoSession, uri: String):
- GeckoResult<GeckoSession>? {
+ override fun onNewSession(session: GeckoSession, uri: String): GeckoResult<GeckoSession>? {
assertThat("URL should be correct", uri, endsWith("form_blank.html?"))
return null
}
@@ -2621,6 +2622,7 @@ class NavigationDelegateTest : BaseSessionTest() {
session: GeckoSession,
url: String?,
perms: MutableList<PermissionDelegate.ContentPermission>,
+ hasUserGesture: Boolean,
) {
currentUrl = url
}
@@ -2702,8 +2704,7 @@ class NavigationDelegateTest : BaseSessionTest() {
override fun onLoadRequest(
session: GeckoSession,
request: LoadRequest,
- ):
- GeckoResult<AllowOrDeny>? {
+ ): GeckoResult<AllowOrDeny>? {
assertThat(
"Load should not be direct",
request.isDirectNavigation,
@@ -2717,8 +2718,10 @@ class NavigationDelegateTest : BaseSessionTest() {
session: GeckoSession,
url: String?,
perms: MutableList<PermissionDelegate.ContentPermission>,
+ hasUserGesture: Boolean,
) {
assertThat("URI should match", url, endsWith("#test1"))
+ assertThat("Should not have user gesture", hasUserGesture, equalTo(false))
}
})
@@ -2729,8 +2732,7 @@ class NavigationDelegateTest : BaseSessionTest() {
override fun onLoadRequest(
session: GeckoSession,
request: LoadRequest,
- ):
- GeckoResult<AllowOrDeny>? {
+ ): GeckoResult<AllowOrDeny>? {
return null
}
@@ -2739,13 +2741,20 @@ class NavigationDelegateTest : BaseSessionTest() {
session: GeckoSession,
url: String?,
perms: MutableList<PermissionDelegate.ContentPermission>,
+ hasUserGesture: Boolean,
) {
assertThat("URI should match", url, endsWith("#test2"))
+ assertThat("Should not have user gesture", hasUserGesture, equalTo(false))
}
})
}
@Test fun purgeHistory() {
+ // TODO: Bug 1884334
+ val geckoPrefs = sessionRule.getPrefs(
+ "fission.disableSessionHistoryInParent",
+ )
+ assumeThat(geckoPrefs[0] as Boolean, equalTo(true))
// TODO: Bug 1837551
assumeThat(sessionRule.env.isFission, equalTo(false))
@@ -2830,6 +2839,54 @@ class NavigationDelegateTest : BaseSessionTest() {
})
}
+ @WithDisplay(width = 100, height = 100)
+ @Test
+ fun locationReplaceOnUserGesture() {
+ mainSession.loadUri("$TEST_ENDPOINT$CLICK_TO_REPLACE_HTML_PATH")
+ mainSession.waitForPageStop()
+
+ mainSession.synthesizeTap(50, 50)
+
+ sessionRule.waitUntilCalled(object : NavigationDelegate {
+ @AssertCalled(count = 1)
+ override fun onLocationChange(
+ session: GeckoSession,
+ url: String?,
+ perms: MutableList<PermissionDelegate.ContentPermission>,
+ hasUserGesture: Boolean,
+ ) {
+ assertThat("Should have a user gesture", hasUserGesture, equalTo(true))
+ assertThat(
+ "Location should be replaced to replacedUrl",
+ url,
+ equalTo("replacedUrl"),
+ )
+ }
+ })
+ }
+
+ @WithDisplay(width = 100, height = 100)
+ @Test
+ fun locationNotReplaceOnNoUserGesture() {
+ mainSession.loadUri("$TEST_ENDPOINT$HELLO_HTML_PATH")
+ sessionRule.waitForPageStop()
+
+ sessionRule.forCallbacksDuringWait(object : NavigationDelegate {
+ @AssertCalled(count = 1, order = [2])
+ override fun onLocationChange(
+ session: GeckoSession,
+ url: String?,
+ perms: MutableList<PermissionDelegate.ContentPermission>,
+ hasUserGesture: Boolean,
+ ) {
+ assertThat("Session should not be null", session, notNullValue())
+ assertThat("URL should not be null", url, notNullValue())
+ assertThat("URL should match", url, endsWith(HELLO_HTML_PATH))
+ assertThat("Should not have user gesture", hasUserGesture, equalTo(false))
+ }
+ })
+ }
+
@Test fun loadAfterLoad() {
mainSession.delegateDuringNextWait(object : NavigationDelegate {
@AssertCalled(count = 2)
@@ -3078,6 +3135,11 @@ class NavigationDelegateTest : BaseSessionTest() {
}
@Test fun goBackFromHistory() {
+ // TODO: Bug 1884334
+ val geckoPrefs = sessionRule.getPrefs(
+ "fission.disableSessionHistoryInParent",
+ )
+ assumeThat(geckoPrefs[0] as Boolean, equalTo(true))
// TODO: Bug 1837551
assumeThat(sessionRule.env.isFission, equalTo(false))
@@ -3119,6 +3181,7 @@ class NavigationDelegateTest : BaseSessionTest() {
var lastTitle: String? = ""
sessionRule.delegateDuringNextWait(object : NavigationDelegate, ContentDelegate {
@AssertCalled(count = 1)
+ @Suppress("OVERRIDE_DEPRECATION")
override fun onLocationChange(
session: GeckoSession,
url: String?,
diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/OpenWindowTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/OpenWindowTest.kt
index 335535bbb4..b7aed020b4 100644
--- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/OpenWindowTest.kt
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/OpenWindowTest.kt
@@ -64,7 +64,7 @@ class OpenWindowTest : BaseSessionTest() {
@NullDelegate(ServiceWorkerDelegate::class)
fun openWindowNullDelegate() {
sessionRule.delegateUntilTestEnd(object : ContentDelegate, NavigationDelegate {
- override fun onLocationChange(session: GeckoSession, url: String?, perms: MutableList<PermissionDelegate.ContentPermission>) {
+ override fun onLocationChange(session: GeckoSession, url: String?, perms: MutableList<PermissionDelegate.ContentPermission>, hasUserGesture: Boolean) {
// we should not open the target url
assertThat("URL should notmatch", url, not(createTestUrl(OPEN_WINDOW_TARGET_PATH)))
}
@@ -76,7 +76,7 @@ class OpenWindowTest : BaseSessionTest() {
@Test
fun openWindowNullResult() {
sessionRule.delegateUntilTestEnd(object : ContentDelegate, NavigationDelegate {
- override fun onLocationChange(session: GeckoSession, url: String?, perms: MutableList<PermissionDelegate.ContentPermission>) {
+ override fun onLocationChange(session: GeckoSession, url: String?, perms: MutableList<PermissionDelegate.ContentPermission>, hasUserGesture: Boolean) {
// we should not open the target url
assertThat("URL should notmatch", url, not(createTestUrl(OPEN_WINDOW_TARGET_PATH)))
}
@@ -103,7 +103,7 @@ class OpenWindowTest : BaseSessionTest() {
openPageClickNotification()
sessionRule.waitUntilCalled(object : ContentDelegate, NavigationDelegate {
@AssertCalled(count = 1, order = [1])
- override fun onLocationChange(session: GeckoSession, url: String?, perms: MutableList<PermissionDelegate.ContentPermission>) {
+ override fun onLocationChange(session: GeckoSession, url: String?, perms: MutableList<PermissionDelegate.ContentPermission>, hasUserGesture: Boolean) {
assertThat("Should be on the main session", session, equalTo(mainSession))
assertThat("URL should match", url, equalTo(createTestUrl(OPEN_WINDOW_TARGET_PATH)))
}
@@ -130,7 +130,7 @@ class OpenWindowTest : BaseSessionTest() {
openPageClickNotification()
sessionRule.waitUntilCalled(object : ContentDelegate, NavigationDelegate {
@AssertCalled(count = 1, order = [1])
- override fun onLocationChange(session: GeckoSession, url: String?, perms: MutableList<PermissionDelegate.ContentPermission>) {
+ override fun onLocationChange(session: GeckoSession, url: String?, perms: MutableList<PermissionDelegate.ContentPermission>, hasUserGesture: Boolean) {
assertThat("Should be on the target session", session, equalTo(targetSession))
assertThat("URL should match", url, equalTo(createTestUrl(OPEN_WINDOW_TARGET_PATH)))
}
diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/PdfCreationTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/PdfCreationTest.kt
index 627c076fc4..de9f282484 100644
--- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/PdfCreationTest.kt
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/PdfCreationTest.kt
@@ -177,4 +177,16 @@ class PdfCreationTest : BaseSessionTest() {
}
}
}
+
+ @NullDelegate(Autofill.Delegate::class)
+ @Test
+ fun dontTryToOpenNullContent() {
+ // Bug 1881927.
+ assumeThat(sessionRule.env.isIsolatedProcess, equalTo(false))
+ activityRule.scenario.onActivity {
+ TestContentProvider.setNullTestData("application/pdf")
+ mainSession.loadUri("content://org.mozilla.geckoview.test.provider/pdf")
+ mainSession.waitForPageStop()
+ }
+ }
}
diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/PermissionDelegateTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/PermissionDelegateTest.kt
index 9ab2d2515f..6b39d410eb 100644
--- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/PermissionDelegateTest.kt
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/PermissionDelegateTest.kt
@@ -214,8 +214,7 @@ class PermissionDelegateTest : BaseSessionTest() {
override fun onContentPermissionRequest(
session: GeckoSession,
perm: ContentPermission,
- ):
- GeckoResult<Int> {
+ ): GeckoResult<Int> {
assertThat("URI should match", perm.uri, endsWith(url))
assertThat(
"Type should match",
@@ -275,7 +274,7 @@ class PermissionDelegateTest : BaseSessionTest() {
mainSession.delegateDuringNextWait(object : NavigationDelegate {
@AssertCalled(count = 1)
- override fun onLocationChange(session: GeckoSession, url: String?, perms: MutableList<ContentPermission>) {
+ override fun onLocationChange(session: GeckoSession, url: String?, perms: MutableList<ContentPermission>, hasUserGesture: Boolean) {
var permFound2 = false
for (perm in perms) {
if (perm.permission == PermissionDelegate.PERMISSION_GEOLOCATION &&
@@ -302,8 +301,7 @@ class PermissionDelegateTest : BaseSessionTest() {
override fun onContentPermissionRequest(
session: GeckoSession,
perm: ContentPermission,
- ):
- GeckoResult<Int> {
+ ): GeckoResult<Int> {
return GeckoResult.fromValue(ContentPermission.VALUE_DENY)
}
@@ -342,7 +340,7 @@ class PermissionDelegateTest : BaseSessionTest() {
mainSession.delegateDuringNextWait(object : NavigationDelegate {
@AssertCalled(count = 1)
- override fun onLocationChange(session: GeckoSession, url: String?, perms: MutableList<ContentPermission>) {
+ override fun onLocationChange(session: GeckoSession, url: String?, perms: MutableList<ContentPermission>, hasUserGesture: Boolean) {
var permFound2 = false
for (perm in perms) {
if (perm.permission == PermissionDelegate.PERMISSION_GEOLOCATION &&
@@ -462,6 +460,7 @@ class PermissionDelegateTest : BaseSessionTest() {
session: GeckoSession,
url: String?,
perms: MutableList<ContentPermission>,
+ hasUserGesture: Boolean,
) {
for (perm in perms) {
if (perm.permission == PermissionDelegate.PERMISSION_TRACKING) {
@@ -501,6 +500,7 @@ class PermissionDelegateTest : BaseSessionTest() {
assertTrackingProtectionPermission(null)
mainSession.loadTestPath(HELLO_HTML_PATH)
+ mainSession.waitForPageStop()
assertTrackingProtectionPermission(ContentPermission.VALUE_DENY)
}
@@ -515,8 +515,7 @@ class PermissionDelegateTest : BaseSessionTest() {
override fun onContentPermissionRequest(
session: GeckoSession,
perm: ContentPermission,
- ):
- GeckoResult<Int> {
+ ): GeckoResult<Int> {
assertThat("URI should match", perm.uri, endsWith(url))
assertThat(
"Type should match",
@@ -551,7 +550,7 @@ class PermissionDelegateTest : BaseSessionTest() {
mainSession.delegateDuringNextWait(object : NavigationDelegate {
@AssertCalled(count = 1)
- override fun onLocationChange(session: GeckoSession, url: String?, perms: MutableList<ContentPermission>) {
+ override fun onLocationChange(session: GeckoSession, url: String?, perms: MutableList<ContentPermission>, hasUserGesture: Boolean) {
var permFound2 = false
for (perm in perms) {
if (perm.permission == PermissionDelegate.PERMISSION_DESKTOP_NOTIFICATION &&
@@ -587,8 +586,7 @@ class PermissionDelegateTest : BaseSessionTest() {
override fun onContentPermissionRequest(
session: GeckoSession,
perm: ContentPermission,
- ):
- GeckoResult<Int> {
+ ): GeckoResult<Int> {
return GeckoResult.fromValue(ContentPermission.VALUE_DENY)
}
})
@@ -617,7 +615,7 @@ class PermissionDelegateTest : BaseSessionTest() {
mainSession.delegateDuringNextWait(object : NavigationDelegate {
@AssertCalled(count = 1)
- override fun onLocationChange(session: GeckoSession, url: String?, perms: MutableList<ContentPermission>) {
+ override fun onLocationChange(session: GeckoSession, url: String?, perms: MutableList<ContentPermission>, hasUserGesture: Boolean) {
var permFound2 = false
for (perm in perms) {
if (perm.permission == PermissionDelegate.PERMISSION_DESKTOP_NOTIFICATION &&
@@ -649,8 +647,7 @@ class PermissionDelegateTest : BaseSessionTest() {
mainSession.waitUntilCalled(object : PermissionDelegate {
@AssertCalled(count = 2)
- override fun onContentPermissionRequest(session: GeckoSession, perm: ContentPermission):
- GeckoResult<Int> {
+ override fun onContentPermissionRequest(session: GeckoSession, perm: ContentPermission): GeckoResult<Int> {
val expectedType = if (sessionRule.currentCall.counter == 1) PermissionDelegate.PERMISSION_AUTOPLAY_AUDIBLE else PermissionDelegate.PERMISSION_AUTOPLAY_INAUDIBLE
assertThat("Type should match", perm.permission, equalTo(expectedType))
return GeckoResult.fromValue(ContentPermission.VALUE_DENY)
@@ -670,8 +667,7 @@ class PermissionDelegateTest : BaseSessionTest() {
override fun onContentPermissionRequest(
session: GeckoSession,
perm: ContentPermission,
- ):
- GeckoResult<Int> {
+ ): GeckoResult<Int> {
assertThat("URI should match", perm.uri, endsWith(url))
assertThat(
"Type should match",
@@ -707,7 +703,7 @@ class PermissionDelegateTest : BaseSessionTest() {
mainSession.delegateDuringNextWait(object : NavigationDelegate {
@AssertCalled(count = 1)
- override fun onLocationChange(session: GeckoSession, url: String?, perms: MutableList<ContentPermission>) {
+ override fun onLocationChange(session: GeckoSession, url: String?, perms: MutableList<ContentPermission>, hasUserGesture: Boolean) {
var permFound2 = false
for (perm in perms) {
if (perm.permission == PermissionDelegate.PERMISSION_DESKTOP_NOTIFICATION &&
@@ -736,8 +732,7 @@ class PermissionDelegateTest : BaseSessionTest() {
override fun onContentPermissionRequest(
session: GeckoSession,
perm: ContentPermission,
- ):
- GeckoResult<Int> {
+ ): GeckoResult<Int> {
assertThat("URI should match", perm.uri, endsWith(url))
assertThat(
"Type should match",
@@ -777,7 +772,7 @@ class PermissionDelegateTest : BaseSessionTest() {
session2.delegateDuringNextWait(object : NavigationDelegate {
@AssertCalled(count = 1)
- override fun onLocationChange(session: GeckoSession, url: String?, perms: MutableList<ContentPermission>) {
+ override fun onLocationChange(session: GeckoSession, url: String?, perms: MutableList<ContentPermission>, hasUserGesture: Boolean) {
var permFound2 = false
for (perm in perms) {
if (perm.permission == PermissionDelegate.PERMISSION_DESKTOP_NOTIFICATION &&
@@ -805,8 +800,7 @@ class PermissionDelegateTest : BaseSessionTest() {
override fun onContentPermissionRequest(
session: GeckoSession,
perm: ContentPermission,
- ):
- GeckoResult<Int> {
+ ): GeckoResult<Int> {
assertThat("URI should match", perm.uri, endsWith(url))
assertThat(
"Type should match",
@@ -841,7 +835,7 @@ class PermissionDelegateTest : BaseSessionTest() {
mainSession.delegateDuringNextWait(object : NavigationDelegate {
@AssertCalled(count = 1)
- override fun onLocationChange(session: GeckoSession, url: String?, perms: MutableList<ContentPermission>) {
+ override fun onLocationChange(session: GeckoSession, url: String?, perms: MutableList<ContentPermission>, hasUserGesture: Boolean) {
var permFound2 = false
for (perm in perms) {
if (perm.permission == PermissionDelegate.PERMISSION_DESKTOP_NOTIFICATION &&
@@ -876,8 +870,7 @@ class PermissionDelegateTest : BaseSessionTest() {
override fun onContentPermissionRequest(
session: GeckoSession,
perm: ContentPermission,
- ):
- GeckoResult<Int> {
+ ): GeckoResult<Int> {
assertThat("URI should match", perm.uri, endsWith(url))
assertThat(
"Type should match",
@@ -919,7 +912,7 @@ class PermissionDelegateTest : BaseSessionTest() {
mainSession.delegateDuringNextWait(object : NavigationDelegate {
@AssertCalled(count = 1)
- override fun onLocationChange(session: GeckoSession, url: String?, perms: MutableList<ContentPermission>) {
+ override fun onLocationChange(session: GeckoSession, url: String?, perms: MutableList<ContentPermission>, hasUserGesture: Boolean) {
var permFound2 = false
for (perm in perms) {
if (perm.permission == PermissionDelegate.PERMISSION_DESKTOP_NOTIFICATION &&
@@ -954,8 +947,7 @@ class PermissionDelegateTest : BaseSessionTest() {
override fun onContentPermissionRequest(
session: GeckoSession,
perm: ContentPermission,
- ):
- GeckoResult<Int> {
+ ): GeckoResult<Int> {
assertThat("URI should match", perm.uri, endsWith(url))
assertThat(
"Type should match",
@@ -1000,8 +992,7 @@ class PermissionDelegateTest : BaseSessionTest() {
override fun onContentPermissionRequest(
session: GeckoSession,
perm: ContentPermission,
- ):
- GeckoResult<Int> {
+ ): GeckoResult<Int> {
return GeckoResult.fromValue(ContentPermission.VALUE_PROMPT)
}
})
@@ -1026,8 +1017,7 @@ class PermissionDelegateTest : BaseSessionTest() {
override fun onContentPermissionRequest(
session: GeckoSession,
perm: ContentPermission,
- ):
- GeckoResult<Int> {
+ ): GeckoResult<Int> {
assertThat("URI should match", perm.uri, endsWith(url))
assertThat(
"Type should match",
diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/ProgressDelegateTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/ProgressDelegateTest.kt
index 3097452da8..f8046ed2ed 100644
--- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/ProgressDelegateTest.kt
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/ProgressDelegateTest.kt
@@ -33,7 +33,7 @@ class ProgressDelegateTest : BaseSessionTest() {
ProgressDelegate,
NavigationDelegate {
@AssertCalled
- override fun onLocationChange(session: GeckoSession, url: String?, perms: MutableList<ContentPermission>) {
+ override fun onLocationChange(session: GeckoSession, url: String?, perms: MutableList<ContentPermission>, hasUserGesture: Boolean) {
assertThat("LocationChange is called", url, endsWith(path))
}
@@ -448,6 +448,11 @@ class ProgressDelegateTest : BaseSessionTest() {
@WithDisplay(width = 400, height = 400)
@Test
fun saveAndRestoreStateNewSession() {
+ // TODO: Bug 1884334
+ val geckoPrefs = sessionRule.getPrefs(
+ "fission.disableSessionHistoryInParent",
+ )
+ assumeThat(geckoPrefs[0] as Boolean, equalTo(true))
// TODO: Bug 1837551
assumeThat(sessionRule.env.isFission, equalTo(false))
val helloUri = createTestUrl(HELLO_HTML_PATH)
@@ -467,6 +472,7 @@ class ProgressDelegateTest : BaseSessionTest() {
session: GeckoSession,
url: String?,
perms: MutableList<ContentPermission>,
+ hasUserGesture: Boolean,
) {
assertThat("URI should match", url, equalTo(startUri))
}
@@ -487,7 +493,7 @@ class ProgressDelegateTest : BaseSessionTest() {
session.goBack()
session.waitUntilCalled(object : NavigationDelegate {
- override fun onLocationChange(session: GeckoSession, url: String?, perms: MutableList<ContentPermission>) {
+ override fun onLocationChange(session: GeckoSession, url: String?, perms: MutableList<ContentPermission>, hasUserGesture: Boolean) {
assertThat("History should be preserved", url, equalTo(helloUri))
}
})
@@ -511,7 +517,7 @@ class ProgressDelegateTest : BaseSessionTest() {
sessionRule.forCallbacksDuringWait(object : NavigationDelegate {
@AssertCalled
- override fun onLocationChange(session: GeckoSession, url: String?, perms: MutableList<ContentPermission>) {
+ override fun onLocationChange(session: GeckoSession, url: String?, perms: MutableList<ContentPermission>, hasUserGesture: Boolean) {
assertThat("URI should match", url, equalTo(startUri))
}
})
@@ -532,6 +538,11 @@ class ProgressDelegateTest : BaseSessionTest() {
@WithDisplay(width = 400, height = 400)
@Test
fun flushSessionState() {
+ // TODO: Bug 1884334
+ val geckoPrefs = sessionRule.getPrefs(
+ "fission.disableSessionHistoryInParent",
+ )
+ assumeThat(geckoPrefs[0] as Boolean, equalTo(true))
// TODO: Bug 1837551
assumeThat(sessionRule.env.isFission, equalTo(false))
val startUri = createTestUrl(SAVE_STATE_PATH)
@@ -568,6 +579,11 @@ class ProgressDelegateTest : BaseSessionTest() {
@NullDelegate(GeckoSession.HistoryDelegate::class)
@Test
fun noHistoryDelegateOnSessionStateChange() {
+ // TODO: Bug 1884334
+ val geckoPrefs = sessionRule.getPrefs(
+ "fission.disableSessionHistoryInParent",
+ )
+ assumeThat(geckoPrefs[0] as Boolean, equalTo(true))
// TODO: Bug 1837551
assumeThat(sessionRule.env.isFission, equalTo(false))
mainSession.loadTestPath(HELLO_HTML_PATH)
diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/RuntimeSettingsTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/RuntimeSettingsTest.kt
index 6504af8a4c..2b690726f3 100644
--- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/RuntimeSettingsTest.kt
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/RuntimeSettingsTest.kt
@@ -277,8 +277,7 @@ class RuntimeSettingsTest : BaseSessionTest() {
mainSession.loadUri("about:config")
mainSession.waitUntilCalled(object : NavigationDelegate {
@AssertCalled
- override fun onLoadError(session: GeckoSession, uri: String?, error: WebRequestError):
- GeckoResult<String>? {
+ override fun onLoadError(session: GeckoSession, uri: String?, error: WebRequestError): GeckoResult<String>? {
assertThat("about:config should not load.", uri, equalTo("about:config"))
return null
}
diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/ScreenshotTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/ScreenshotTest.kt
index cee16f3f4c..f3141c661c 100644
--- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/ScreenshotTest.kt
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/ScreenshotTest.kt
@@ -203,6 +203,11 @@ class ScreenshotTest : BaseSessionTest() {
@WithDisplay(height = SCREEN_HEIGHT, width = SCREEN_WIDTH)
@Test
fun capturePixelsWhileSessionDeactivated() {
+ // TODO: Bug 1884334
+ val geckoPrefs = sessionRule.getPrefs(
+ "fission.disableSessionHistoryInParent",
+ )
+ assumeThat(geckoPrefs[0] as Boolean, equalTo(true))
// TODO: Bug 1837551
assumeThat(sessionRule.env.isFission, equalTo(false))
val screenshotFile = getComparisonScreenshot(SCREEN_WIDTH, SCREEN_HEIGHT)
diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/SelectionActionDelegateTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/SelectionActionDelegateTest.kt
index e5e8ec6ce2..d3e52cda6a 100644
--- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/SelectionActionDelegateTest.kt
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/SelectionActionDelegateTest.kt
@@ -393,8 +393,7 @@ class SelectionActionDelegateTest : BaseSessionTest() {
override fun onShowClipboardPermissionRequest(
session: GeckoSession,
perm: ClipboardPermission,
- ):
- GeckoResult<AllowOrDeny> {
+ ): GeckoResult<AllowOrDeny> {
assertThat(
"Type should match",
perm.type,
@@ -408,8 +407,7 @@ class SelectionActionDelegateTest : BaseSessionTest() {
override fun onAlertPrompt(
session: GeckoSession,
prompt: PromptDelegate.AlertPrompt,
- ):
- GeckoResult<PromptDelegate.PromptResponse> {
+ ): GeckoResult<PromptDelegate.PromptResponse> {
assertThat("Message should match", "allow", equalTo(prompt.message))
result.complete(null)
return GeckoResult.fromValue(prompt.dismiss())
@@ -440,8 +438,7 @@ class SelectionActionDelegateTest : BaseSessionTest() {
override fun onShowClipboardPermissionRequest(
session: GeckoSession,
perm: ClipboardPermission,
- ):
- GeckoResult<AllowOrDeny>? {
+ ): GeckoResult<AllowOrDeny>? {
assertThat(
"Type should match",
perm.type,
@@ -454,8 +451,7 @@ class SelectionActionDelegateTest : BaseSessionTest() {
override fun onAlertPrompt(
session: GeckoSession,
prompt: PromptDelegate.AlertPrompt,
- ):
- GeckoResult<PromptDelegate.PromptResponse> {
+ ): GeckoResult<PromptDelegate.PromptResponse> {
assertThat("Message should match", "deny", equalTo(prompt.message))
result.complete(null)
return GeckoResult.fromValue(prompt.dismiss())
@@ -486,8 +482,7 @@ class SelectionActionDelegateTest : BaseSessionTest() {
override fun onShowClipboardPermissionRequest(
session: GeckoSession,
perm: ClipboardPermission,
- ):
- GeckoResult<AllowOrDeny>? {
+ ): GeckoResult<AllowOrDeny>? {
assertThat(
"Type should match",
perm.type,
@@ -533,8 +528,7 @@ class SelectionActionDelegateTest : BaseSessionTest() {
override fun onShowClipboardPermissionRequest(
session: GeckoSession,
perm: ClipboardPermission,
- ):
- GeckoResult<AllowOrDeny>? {
+ ): GeckoResult<AllowOrDeny>? {
assertThat(
"Type should match",
perm.type,
diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/TestContentProvider.java b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/TestContentProvider.java
index 787448a859..b0591b693e 100644
--- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/TestContentProvider.java
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/TestContentProvider.java
@@ -18,6 +18,7 @@ public class TestContentProvider extends ContentProvider {
private static final String LOGTAG = "TestContentProvider";
private static byte[] sTestData;
private static String sMimeType;
+ private static boolean sAllowNullData = false;
@Override
public boolean onCreate() {
@@ -62,7 +63,10 @@ public class TestContentProvider extends ContentProvider {
public ParcelFileDescriptor openFile(final Uri uri, final String mode)
throws FileNotFoundException {
if (sTestData == null) {
- throw new FileNotFoundException("No test data for: " + uri);
+ if (!sAllowNullData) {
+ throw new FileNotFoundException("No test data for: " + uri);
+ }
+ return null;
}
ParcelFileDescriptor[] pipe = null;
@@ -98,6 +102,19 @@ public class TestContentProvider extends ContentProvider {
*/
public static void setTestData(final byte[] data, final String mimeType) {
sTestData = data;
+ sAllowNullData = false;
+ sMimeType = mimeType;
+ }
+
+ /**
+ * Set null that is used from content resolver but don't throw when calling openFile.
+ *
+ * @param data test data
+ * @param mimeType A mime type of test data.
+ */
+ public static void setNullTestData(final String mimeType) {
+ sTestData = null;
+ sAllowNullData = true;
sMimeType = mimeType;
}
}
diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/TextInputDelegateTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/TextInputDelegateTest.kt
index 7e4015a246..ca21d0a61d 100644
--- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/TextInputDelegateTest.kt
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/TextInputDelegateTest.kt
@@ -537,7 +537,8 @@ class TextInputDelegateTest : BaseSessionTest() {
"Can commit text (select before)",
ic,
"foobarfoo",
- 5, /* checkGecko */
+ 5,
+ /* checkGecko */
false,
)
}
@@ -641,7 +642,8 @@ class TextInputDelegateTest : BaseSessionTest() {
"Can set new composing region text",
ic,
"frabar",
- 6, /* checkGecko */
+ 6,
+ /* checkGecko */
false,
)
@@ -826,7 +828,13 @@ class TextInputDelegateTest : BaseSessionTest() {
}.joinToString("")
setupContent(content)
val ic = mainSession.textInput.onCreateInputConnection(EditorInfo())!!
- assertText("Can set large initial text", ic, content, /* checkGecko */ false)
+ assertText(
+ "Can set large initial text",
+ ic,
+ content,
+ /* checkGecko */
+ false,
+ )
}
@SdkSuppress(minSdkVersion = Build.VERSION_CODES.N_MR1)
@@ -1279,6 +1287,25 @@ class TextInputDelegateTest : BaseSessionTest() {
assertText("commit abc", ic, "abc")
}
+ // Bug 1837931 - When 2nd commitText uses -1 as newCursorPosition into batch mode, text
+ // cannot insert correct position.
+ @WithDisplay(width = 512, height = 512)
+ // Child process updates require having a display.
+ @Test
+ fun inputConnection_multiple_commitText_into_batchEdit() {
+ setupContent("")
+ val ic = mainSession.textInput.onCreateInputConnection(EditorInfo())!!
+
+ // Emulate GBoard's InputConnection API calls
+ ic.beginBatchEdit()
+ ic.commitText("( ", 1)
+ ic.commitText(")", -1)
+ ic.endBatchEdit()
+ processChildEvents()
+
+ assertText("commit ()", ic, "( )")
+ }
+
// Bug 1593683 - Cursor is jumping when using the arrow keys in input field on GBoard
@WithDisplay(width = 512, height = 512)
// Child process updates require having a display.
@@ -1294,7 +1321,14 @@ class TextInputDelegateTest : BaseSessionTest() {
pressKey(ic, KeyEvent.KEYCODE_DPAD_LEFT)
pressKey(ic, KeyEvent.KEYCODE_DPAD_LEFT)
pressKey(ic, KeyEvent.KEYCODE_DPAD_LEFT)
- assertSelection("IME caret is moved to top", ic, 0, 0, /* checkGecko */ false)
+ assertSelection(
+ "IME caret is moved to top",
+ ic,
+ 0,
+ 0,
+ /* checkGecko */
+ false,
+ )
setComposingText(ic, "bar", 1)
finishComposingText(ic)
diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/TrackingPermissionService.java b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/TrackingPermissionService.java
index 141849589e..4b7bcabee5 100644
--- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/TrackingPermissionService.java
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/TrackingPermissionService.java
@@ -36,7 +36,8 @@ public class TrackingPermissionService extends TestRuntimeService {
public void onLocationChange(
final @NonNull GeckoSession session,
final @Nullable String url,
- final @NonNull List<ContentPermission> perms) {
+ final @NonNull List<ContentPermission> perms,
+ final @NonNull Boolean hasUserGesture) {
for (ContentPermission perm : perms) {
if (perm.permission == PermissionDelegate.PERMISSION_TRACKING) {
mContentPermission = perm;
diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/VideoCaptureTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/VideoCaptureTest.kt
new file mode 100644
index 0000000000..7e1f8b1275
--- /dev/null
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/VideoCaptureTest.kt
@@ -0,0 +1,58 @@
+package org.mozilla.geckoview.test
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import androidx.test.platform.app.InstrumentationRegistry
+import org.junit.Assert.assertEquals
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.webrtc.CameraEnumerationAndroid.CaptureFormat
+import org.webrtc.CameraEnumerator
+import org.webrtc.CameraVideoCapturer
+import org.webrtc.CameraVideoCapturer.CameraEventsHandler
+import org.webrtc.videoengine.VideoCaptureAndroid
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+class VideoCaptureTest {
+ // Always throw exception.
+ class BadCameraEnumerator : CameraEnumerator {
+ override fun getDeviceNames(): Array<String?>? {
+ throw java.lang.RuntimeException("")
+ }
+
+ override fun isFrontFacing(deviceName: String?): Boolean {
+ throw java.lang.RuntimeException("")
+ }
+
+ override fun isBackFacing(deviceName: String?): Boolean {
+ throw java.lang.RuntimeException("")
+ }
+
+ override fun isInfrared(deviceName: String?): Boolean {
+ throw java.lang.RuntimeException("")
+ }
+
+ override fun getSupportedFormats(deviceName: String?): List<CaptureFormat?>? {
+ throw java.lang.RuntimeException("")
+ }
+
+ override fun createCapturer(
+ deviceName: String?,
+ eventsHandler: CameraEventsHandler?,
+ ): CameraVideoCapturer? {
+ throw java.lang.RuntimeException("")
+ }
+ }
+
+ @Test
+ fun constructWithBadEnumerator() {
+ val ctr = VideoCaptureAndroid::class.java.getDeclaredConstructors()[0].apply { isAccessible = true }
+ val capture = ctr.newInstance(
+ InstrumentationRegistry.getInstrumentation().targetContext,
+ "my camera",
+ BadCameraEnumerator(),
+ ) as VideoCaptureAndroid
+ assertEquals(false, capture.canCapture())
+ }
+}
diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/WebExtensionTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/WebExtensionTest.kt
index 126e52da34..702ba4d23b 100644
--- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/WebExtensionTest.kt
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/WebExtensionTest.kt
@@ -7,6 +7,7 @@ package org.mozilla.geckoview.test
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.MediumTest
import org.hamcrest.MatcherAssert.assertThat
+import org.hamcrest.Matchers
import org.hamcrest.Matchers.greaterThan
import org.hamcrest.core.IsEqual.equalTo
import org.hamcrest.core.StringEndsWith.endsWith
@@ -90,6 +91,14 @@ class WebExtensionTest : BaseSessionTest() {
assertTrue(borderify.isBuiltIn)
+ assertArrayEquals(
+ arrayOf("*://developer.mozilla.org/*"),
+ borderify.metaData.optionalOrigins,
+ )
+ assertArrayEquals(
+ arrayOf("clipboardRead"),
+ borderify.metaData.optionalPermissions,
+ )
mainSession.reload()
sessionRule.waitForPageStop()
@@ -109,6 +118,156 @@ class WebExtensionTest : BaseSessionTest() {
assertBodyBorderEqualTo("")
}
+ @Test
+ fun verifyOptionalAndOriginsPermissionsMV3() {
+ mainSession.loadUri("https://example.com")
+ sessionRule.waitForPageStop()
+
+ // First let's check that the color of the border is empty before loading
+ // the WebExtension
+ assertBodyBorderEqualTo("")
+
+ // Load the WebExtension that will add a border to the body
+ val borderify = sessionRule.waitForResult(
+ controller.installBuiltIn(
+ "resource://android/assets/web_extensions/borderify-mv3/",
+ ),
+ )
+
+ assertArrayEquals(
+ arrayOf("clipboardRead"),
+ borderify.metaData.optionalPermissions,
+ )
+
+ val expectedOptionalOrigins = arrayOf(
+ "*://*.example.com/*",
+ "*://opt-host-perm.example.com/*",
+ "*://host-perm.example.com/*",
+ )
+
+ expectedOptionalOrigins.sort()
+ borderify.metaData.optionalOrigins.sort()
+
+ assertArrayEquals(
+ expectedOptionalOrigins,
+ borderify.metaData.optionalOrigins,
+ )
+
+ mainSession.reload()
+ sessionRule.waitForPageStop()
+
+ // Check that the WebExtension was applied by checking the border color
+ assertBodyBorderEqualTo("red")
+
+ // Uninstall WebExtension and check again
+ sessionRule.waitForResult(controller.uninstall(borderify))
+
+ mainSession.reload()
+ sessionRule.waitForPageStop()
+
+ // Check that the WebExtension was not applied after being uninstalled
+ assertBodyBorderEqualTo("")
+ }
+
+ @WithDisplay(width = 100, height = 100)
+ @Test
+ fun grantedOptionalPermissions() {
+ sessionRule.setPrefsUntilTestEnd(
+ mapOf(
+ "xpinstall.signatures.required" to false,
+ "extensions.install.requireBuiltInCerts" to false,
+ "extensions.update.requireBuiltInCerts" to false,
+ ),
+ )
+
+ val extension = sessionRule.waitForResult(
+ controller.ensureBuiltIn(
+ "resource://android/assets/web_extensions/optional-permission-request/",
+ "optional-permission-request@example.com",
+ ),
+ )
+
+ assertEquals("optional-permission-request@example.com", extension.id)
+
+ mainSession.loadUri("${extension.metaData.baseUrl}clickToRequestPermission.html")
+ sessionRule.waitForPageStop()
+
+ var grantedOptionalPermissions = extension.metaData.grantedOptionalPermissions
+ var grantedOptionalOrigins = extension.metaData.grantedOptionalOrigins
+
+ assertThat(
+ "grantedOptionalPermissions must be 0.",
+ grantedOptionalPermissions.size,
+ equalTo(0),
+ )
+ assertThat("grantedOptionalOrigins must be 0.", grantedOptionalOrigins.size, equalTo(0))
+
+ // click triggers permissions.request
+ mainSession.synthesizeTap(50, 50)
+
+ sessionRule.delegateUntilTestEnd(object : WebExtensionController.PromptDelegate {
+ override fun onOptionalPrompt(
+ extension: WebExtension,
+ permissions: Array<String>,
+ origins: Array<String>,
+ ): GeckoResult<AllowOrDeny> {
+ return GeckoResult.allow()
+ }
+ })
+
+ var result = GeckoResult<String>()
+ mainSession.webExtensionController.setMessageDelegate(
+ extension,
+ object : WebExtension.MessageDelegate {
+ override fun onMessage(
+ nativeApp: String,
+ message: Any,
+ sender: WebExtension.MessageSender,
+ ): GeckoResult<Any>? {
+ result.complete(message as String)
+ return null
+ }
+ },
+ "browser",
+ )
+
+ result = GeckoResult<String>()
+ val message = sessionRule.waitForResult(result)
+ assertThat("Permission request should be accepted.", message, equalTo("true"))
+
+ val updatedExtension = sessionRule.waitForResult(
+ // Adds "internal:privateBrowsingAllowed"
+ controller.setAllowedInPrivateBrowsing(extension, true),
+ )
+
+ grantedOptionalPermissions = updatedExtension.metaData.grantedOptionalPermissions
+ grantedOptionalOrigins = updatedExtension.metaData.grantedOptionalOrigins
+
+ assertThat(
+ "grantedOptionalPermissions must be 1.",
+ grantedOptionalPermissions.size,
+ equalTo(1),
+ )
+ assertThat("grantedOptionalOrigins must be 1.", grantedOptionalOrigins.size, equalTo(1))
+ assertThat(
+ "grantedOptionalOrigins must be *://example.com/*.",
+ grantedOptionalOrigins.first(),
+ equalTo("*://example.com/*"),
+ )
+
+ // geolocation is part of the manifest but not requested/granted.
+ assertFalse(grantedOptionalPermissions.contains("geolocation"))
+
+ // "internal:privateBrowsingAllowed" must not be part of grantedOptionalPermissions.
+ assertThat(
+ "grantedOptionalPermissions must be activeTab.",
+ grantedOptionalPermissions.first(),
+ equalTo("activeTab"),
+ )
+
+ sessionRule.waitForResult(controller.uninstall(extension))
+ }
+
private fun assertBodyBorderEqualTo(expected: String) {
val color = mainSession.evaluateJS("document.body.style.borderColor")
assertThat(
@@ -1618,6 +1777,11 @@ class WebExtensionTest : BaseSessionTest() {
// - verifies that the messages are received when restoring the tab in a fresh session
@Test
fun testRestoringExtensionPagePreservesMessages() {
+ // TODO: Bug 1884334
+ val geckoPrefs = sessionRule.getPrefs(
+ "fission.disableSessionHistoryInParent",
+ )
+ assumeThat(geckoPrefs[0] as Boolean, Matchers.equalTo(true))
// TODO: Bug 1837551
assumeThat(sessionRule.env.isFission, equalTo(false))
@@ -2138,7 +2302,7 @@ class WebExtensionTest : BaseSessionTest() {
mainSession.waitUntilCalled(object : NavigationDelegate, ProgressDelegate {
@GeckoSessionTestRule.AssertCalled(count = 1)
- override fun onLocationChange(session: GeckoSession, url: String?, perms: MutableList<PermissionDelegate.ContentPermission>) {
+ override fun onLocationChange(session: GeckoSession, url: String?, perms: MutableList<PermissionDelegate.ContentPermission>, hasUserGesture: Boolean) {
assertThat(
"Url should load example.com first",
url,
@@ -2160,7 +2324,7 @@ class WebExtensionTest : BaseSessionTest() {
val pageStop = GeckoResult<Boolean>()
mainSession.delegateUntilTestEnd(object : NavigationDelegate, ProgressDelegate {
- override fun onLocationChange(session: GeckoSession, url: String?, perms: MutableList<PermissionDelegate.ContentPermission>) {
+ override fun onLocationChange(session: GeckoSession, url: String?, perms: MutableList<PermissionDelegate.ContentPermission>, hasUserGesture: Boolean) {
page = url
}
diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/WebNotificationTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/WebNotificationTest.kt
index 469fd049ce..358134313a 100644
--- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/WebNotificationTest.kt
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/WebNotificationTest.kt
@@ -31,8 +31,7 @@ class WebNotificationTest : BaseSessionTest() {
// Grant "desktop notification" permission
mainSession.delegateUntilTestEnd(object : PermissionDelegate {
- override fun onContentPermissionRequest(session: GeckoSession, perm: PermissionDelegate.ContentPermission):
- GeckoResult<Int>? {
+ override fun onContentPermissionRequest(session: GeckoSession, perm: PermissionDelegate.ContentPermission): GeckoResult<Int>? {
assertThat("Should grant DESKTOP_NOTIFICATIONS permission", perm.permission, equalTo(PermissionDelegate.PERMISSION_DESKTOP_NOTIFICATION))
return GeckoResult.fromValue(PermissionDelegate.ContentPermission.VALUE_ALLOW)
}
@@ -336,7 +335,11 @@ class WebNotificationTest : BaseSessionTest() {
// Test that we can serialize a notification
val parcel = Parcel.obtain()
- notification.writeToParcel(parcel, /* ignored */ -1)
+ notification.writeToParcel(
+ parcel,
+ /* ignored */
+ -1,
+ )
assertThat("Promise should have been resolved.", promiseResult.value as Double, equalTo(1.0))
}
@@ -375,7 +378,11 @@ class WebNotificationTest : BaseSessionTest() {
// Test that we can serialize a notification with an imageUrl.length >= 150
val parcel = Parcel.obtain()
- notification.writeToParcel(parcel, /* ignored */ -1)
+ notification.writeToParcel(
+ parcel,
+ /* ignored */
+ -1,
+ )
parcel.setDataPosition(0)
val serializedNotification = WebNotification.CREATOR.createFromParcel(parcel)
diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/WebPushTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/WebPushTest.kt
index a2e6d58f3a..609275526c 100644
--- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/WebPushTest.kt
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/WebPushTest.kt
@@ -60,8 +60,7 @@ class WebPushTest : BaseSessionTest() {
sessionRule.setPrefsUntilTestEnd(mapOf("dom.webnotifications.requireuserinteraction" to false))
// Grant "desktop notification" permission
mainSession.delegateUntilTestEnd(object : PermissionDelegate {
- override fun onContentPermissionRequest(session: GeckoSession, perm: GeckoSession.PermissionDelegate.ContentPermission):
- GeckoResult<Int>? {
+ override fun onContentPermissionRequest(session: GeckoSession, perm: GeckoSession.PermissionDelegate.ContentPermission): GeckoResult<Int>? {
assertThat("Should grant DESKTOP_NOTIFICATIONS permission", perm.permission, equalTo(GeckoSession.PermissionDelegate.PERMISSION_DESKTOP_NOTIFICATION))
return GeckoResult.fromValue(GeckoSession.PermissionDelegate.ContentPermission.VALUE_ALLOW)
}
diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rule/GeckoSessionTestRule.java b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rule/GeckoSessionTestRule.java
index 9c9a9d6188..727f403931 100644
--- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rule/GeckoSessionTestRule.java
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/rule/GeckoSessionTestRule.java
@@ -831,7 +831,8 @@ public class GeckoSessionTestRule implements TestRule {
public void onLocationChange(
@NonNull GeckoSession session,
@Nullable String url,
- @NonNull List<ContentPermission> perms) {}
+ @NonNull List<ContentPermission> perms,
+ @NonNull Boolean hasUserGesture) {}
@Override
public void onShutdown() {}
diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/AndroidGamepadManager.java b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/AndroidGamepadManager.java
index 99be57fc12..3672428a98 100644
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/AndroidGamepadManager.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/AndroidGamepadManager.java
@@ -159,9 +159,9 @@ public class AndroidGamepadManager {
/* package */ static void doStart(final Context context) {
ThreadUtils.assertOnUiThread();
if (!sStarted) {
+ sStarted = true;
scanForGamepads();
addDeviceListener(context);
- sStarted = true;
}
}
diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoAppShell.java b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoAppShell.java
index 568fc3a0bb..bcd5762a92 100644
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoAppShell.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoAppShell.java
@@ -46,7 +46,6 @@ import android.os.Looper;
import android.os.PowerManager;
import android.os.Vibrator;
import android.provider.Settings;
-import android.text.TextUtils;
import android.util.Log;
import android.view.ContextThemeWrapper;
import android.view.Display;
@@ -1527,20 +1526,6 @@ public class GeckoAppShell {
}
}
- private static String getLanguageTag(final Locale locale) {
- final StringBuilder out = new StringBuilder(locale.getLanguage());
- final String country = locale.getCountry();
- final String variant = locale.getVariant();
- if (!TextUtils.isEmpty(country)) {
- out.append('-').append(country);
- }
- if (!TextUtils.isEmpty(variant)) {
- out.append('-').append(variant);
- }
- // e.g. "en", "en-US", or "en-US-POSIX".
- return out.toString();
- }
-
@WrapForJNI
public static String[] getDefaultLocales() {
// XXX We may have to convert some language codes such as "id" vs "in".
diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoDragAndDrop.java b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoDragAndDrop.java
index 9c1473d4e7..d529449d5a 100644
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoDragAndDrop.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoDragAndDrop.java
@@ -42,7 +42,11 @@ public class GeckoDragAndDrop {
private final Bitmap mBitmap;
public DrawDragImage(final Bitmap bitmap) {
- mBitmap = bitmap;
+ if (bitmap != null && bitmap.getWidth() > 0 && bitmap.getHeight() > 0) {
+ mBitmap = bitmap;
+ return;
+ }
+ mBitmap = null;
}
@Override
diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/InputMethods.java b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/InputMethods.java
index 120098a931..56fd0d9853 100644
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/InputMethods.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/InputMethods.java
@@ -6,11 +6,13 @@
package org.mozilla.gecko;
import android.content.Context;
+import android.os.Build;
import android.provider.Settings.Secure;
import android.view.View;
import android.view.inputmethod.InputMethodInfo;
import android.view.inputmethod.InputMethodManager;
import java.util.Collection;
+import java.util.Locale;
public final class InputMethods {
public static final String METHOD_ANDROID_LATINIME = "com.android.inputmethod.latin/.LatinIME";
@@ -99,6 +101,13 @@ public final class InputMethods {
return METHOD_SONY.equals(inputMethod);
}
+ // Workaround for bug 1818268 - Unexpected crash on Galaxy J7
+ public static boolean dontOverrideCommitText() {
+ return Build.VERSION.SDK_INT == 23
+ && Build.MANUFACTURER.toLowerCase(Locale.ROOT).equals("samsung")
+ && Build.MODEL.startsWith("SM-J700F");
+ }
+
// TODO: Replace usages by definition in EditorInfoCompat once available (bug 1385726).
public static final int IME_FLAG_NO_PERSONALIZED_LEARNING = 0x1000000;
}
diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/MediaDrmProxy.java b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/MediaDrmProxy.java
index 1bfab37063..4ab8b10f9f 100644
--- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/MediaDrmProxy.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/media/MediaDrmProxy.java
@@ -23,6 +23,7 @@ public final class MediaDrmProxy {
private static final String WIDEVINE_KEY_SYSTEM = "com.widevine.alpha";
@WrapForJNI private static final String AAC = "audio/mp4a-latm";
@WrapForJNI private static final String AVC = "video/avc";
+ @WrapForJNI private static final String AV1 = "video/av01";
@WrapForJNI private static final String VORBIS = "audio/vorbis";
@WrapForJNI private static final String VP8 = "video/x-vnd.on2.vp8";
@WrapForJNI private static final String VP9 = "video/x-vnd.on2.vp9";
diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/LocaleUtils.java b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/LocaleUtils.java
new file mode 100644
index 0000000000..8e4addc7b0
--- /dev/null
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/util/LocaleUtils.java
@@ -0,0 +1,32 @@
+/* -*- Mode: Java; c-basic-offset: 2; tab-width: 20; indent-tabs-mode: nil; -*- */
+/* vim: set ts=2 et sw=2: */
+/* 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/. */
+
+package org.mozilla.gecko.util;
+
+import android.text.TextUtils;
+import java.util.Locale;
+
+public class LocaleUtils {
+ // Locale.getLanguage() may return legacy language code until Java 17
+ // https://developer.android.com/reference/java/util/Locale#legacy_language_codes
+ public static String getLanguageTagForAcceptLanguage(final Locale locale) {
+ String language = locale.getLanguage();
+ if (language.equals("in")) {
+ language = "id";
+ } else if (language.equals("iw")) {
+ language = "he";
+ } else if (language.equals("ji")) {
+ language = "yi";
+ }
+ final StringBuilder out = new StringBuilder(language);
+ final String country = locale.getCountry();
+ if (!TextUtils.isEmpty(country)) {
+ out.append('-').append(country);
+ }
+ // e.g. "en", "en-US"
+ return out.toString();
+ }
+}
diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/ContentInputStream.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/ContentInputStream.java
index aa3f5c3174..bc9eff98f0 100644
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/ContentInputStream.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/ContentInputStream.java
@@ -37,6 +37,11 @@ import org.mozilla.gecko.annotation.WrapForJNI;
try {
mFd = cr.openAssetFileDescriptor(uri, "r");
+ if (mFd == null) {
+ Log.e(LOGTAG, "Cannot open the uri: " + aUri + " (no file descriptor)");
+ close();
+ return;
+ }
setInputStream(mFd.createInputStream());
if (!checkHeaders(HEADERS)) {
@@ -127,7 +132,17 @@ import org.mozilla.gecko.annotation.WrapForJNI;
|| isExported(context, uri)
|| wasGrantedPermission(context, uri)) {
final ContentResolver cr = context.getContentResolver();
- cr.openAssetFileDescriptor(uri, "r").close();
+ if (cr == null) {
+ Log.e(LOGTAG, "No content resolver");
+ return false;
+ }
+ final AssetFileDescriptor fd = cr.openAssetFileDescriptor(uri, "r");
+ if (fd == null) {
+ // The descriptor can be null because the provider crashed.
+ Log.e(LOGTAG, "No asset file descriptor");
+ return false;
+ }
+ fd.close();
Log.d(LOGTAG, "The uri is readable: " + uri);
return true;
}
diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoInputConnection.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoInputConnection.java
index 5426adb501..2e8f2e55d7 100644
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoInputConnection.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoInputConnection.java
@@ -655,6 +655,53 @@ import org.mozilla.gecko.util.ThreadUtils;
return replaceComposingSpanWithSelection()
&& mKeyInputConnection.commitText(text, newCursorPosition);
}
+
+ // Bug 1818268 - Unexpected crash on Galaxy J7
+ if (InputMethods.dontOverrideCommitText()) {
+ return super.commitText(text, newCursorPosition);
+ }
+
+ // Default implementation is
+ // 1. Set selection
+ // 2. Call Editable.replace
+ // 3. Set selection in Editable.replace
+ //
+ // However, this results in additional IPC in Gecko and unexpected selection before replacing
+ // text.
+ // When changing text in Gecko, the selection will be updated, so the default implementation is
+ // not compatible with Gecko's text handling.
+ // Therefore, we set the selection after replacing the text. However, if there is a composition,
+ // the selection may be an IME cursor, not a standard selection. In such cases, this step is not
+ // necessary.
+ final Editable content = getEditable();
+ if (content != null) {
+ final int compositionStart = getComposingSpanStart(content);
+ final int compositionEnd = getComposingSpanEnd(content);
+
+ if (compositionStart < 0 || compositionEnd < 0) {
+ // No composition
+ int selStart = Math.max(Selection.getSelectionStart(content), 0);
+ int selEnd = Math.max(Selection.getSelectionEnd(content), 0);
+ if (selStart > selEnd) {
+ final int tmp = selEnd;
+ selEnd = selStart;
+ selStart = tmp;
+ }
+
+ beginBatchEdit();
+ content.replace(selStart, selEnd, text);
+
+ int cursorPosition =
+ newCursorPosition > 0
+ ? selStart + text.length() + newCursorPosition - 1
+ : selStart + newCursorPosition;
+ cursorPosition = Math.min(Math.max(0, cursorPosition), content.length());
+ Selection.setSelection(content, cursorPosition);
+ endBatchEdit();
+ return true;
+ }
+ }
+
return super.commitText(text, newCursorPosition);
}
diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java
index 3da044e603..0a80b02b04 100644
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoRuntimeSettings.java
@@ -27,6 +27,7 @@ import java.util.Locale;
import org.mozilla.gecko.EventDispatcher;
import org.mozilla.gecko.GeckoSystemStateListener;
import org.mozilla.gecko.util.GeckoBundle;
+import org.mozilla.gecko.util.LocaleUtils;
@AnyThread
public final class GeckoRuntimeSettings extends RuntimeSettings {
@@ -462,6 +463,8 @@ public final class GeckoRuntimeSettings extends RuntimeSettings {
* @param delegate the delegate that will handle telemetry
* @return The builder instance.
*/
+ @Deprecated
+ @DeprecationSchedule(id = "geckoview-gvst", version = 127)
public @NonNull Builder telemetryDelegate(final @NonNull RuntimeTelemetry.Delegate delegate) {
getSettings().mTelemetryProxy = new RuntimeTelemetry.Proxy(delegate);
getSettings().mTelemetryEnabled.set(true);
@@ -1054,7 +1057,7 @@ public final class GeckoRuntimeSettings extends RuntimeSettings {
}
}
// OS prefs come second:
- for (final String locale : getDefaultLocales()) {
+ for (final String locale : getSystemLocalesForAcceptLanguage()) {
final String localeLowerCase = locale.toLowerCase(Locale.ROOT);
if (!locales.containsKey(localeLowerCase)) {
locales.put(localeLowerCase, locale);
@@ -1064,35 +1067,22 @@ public final class GeckoRuntimeSettings extends RuntimeSettings {
return TextUtils.join(",", locales.values());
}
- private static String[] getDefaultLocales() {
+ private static String[] getSystemLocalesForAcceptLanguage() {
if (VERSION.SDK_INT >= 24) {
final LocaleList localeList = LocaleList.getDefault();
final String[] locales = new String[localeList.size()];
for (int i = 0; i < localeList.size(); i++) {
- locales[i] = localeList.get(i).toLanguageTag();
+ // accept-language should be language or language-region format.
+ locales[i] = LocaleUtils.getLanguageTagForAcceptLanguage(localeList.get(i));
}
return locales;
}
final String[] locales = new String[1];
final Locale locale = Locale.getDefault();
- locales[0] = locale.toLanguageTag();
+ locales[0] = LocaleUtils.getLanguageTagForAcceptLanguage(locale);
return locales;
}
- private static String getLanguageTag(final Locale locale) {
- final StringBuilder out = new StringBuilder(locale.getLanguage());
- final String country = locale.getCountry();
- final String variant = locale.getVariant();
- if (!TextUtils.isEmpty(country)) {
- out.append('-').append(country);
- }
- if (!TextUtils.isEmpty(variant)) {
- out.append('-').append(variant);
- }
- // e.g. "en", "en-US", or "en-US-POSIX".
- return out.toString();
- }
-
/**
* Sets whether Web Manifest processing support is enabled.
*
diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java
index f8f7f858e3..85b3abf9a9 100644
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java
@@ -685,7 +685,11 @@ public class GeckoSession {
final GeckoBundle[] perms = message.getBundleArray("permissions");
final List<PermissionDelegate.ContentPermission> permList =
PermissionDelegate.ContentPermission.fromBundleArray(perms);
- delegate.onLocationChange(GeckoSession.this, message.getString("uri"), permList);
+ delegate.onLocationChange(
+ GeckoSession.this,
+ message.getString("uri"),
+ permList,
+ message.getBoolean("hasUserGesture"));
}
delegate.onCanGoBack(GeckoSession.this, message.getBoolean("canGoBack"));
delegate.onCanGoForward(GeckoSession.this, message.getBoolean("canGoForward"));
@@ -1928,7 +1932,7 @@ public class GeckoSession {
// https://searchfox.org/mozilla-central/source/docshell/base/nsIWebNavigation.idl
//
// We do not use the same values directly in order to insulate ourselves from
- // changes in Gecko. Instead, the flags are converted in GeckoViewNavigation.jsm.
+ // changes in Gecko. Instead, the flags are converted in GeckoViewNavigation.sys.mjs.
/** Default load flag, no special considerations. */
public static final int LOAD_FLAGS_NONE = 0;
@@ -4935,17 +4939,39 @@ public class GeckoSession {
/**
* A view has started loading content from the network.
*
+ * @deprecated use {@link #onLocationChange(GeckoSession, String,
+ * List<PermissionDelegate.ContentPermission>, Boolean) onLocationChange} instead
* @param session The GeckoSession that initiated the callback.
* @param url The resource being loaded.
* @param perms The permissions currently associated with this url.
*/
@UiThread
+ @Deprecated
+ @DeprecationSchedule(id = "geckoview-onlocationchange", version = 127)
default void onLocationChange(
@NonNull GeckoSession session,
@Nullable String url,
final @NonNull List<PermissionDelegate.ContentPermission> perms) {}
/**
+ * A view has started loading content from the network.
+ *
+ * @param session The GeckoSession that initiated the callback.
+ * @param url The resource being loaded.
+ * @param perms The permissions currently associated with this url.
+ * @param hasUserGesture Whether or not there was an active user gesture when the location
+ * change was requested.
+ */
+ @UiThread
+ default void onLocationChange(
+ @NonNull GeckoSession session,
+ @Nullable String url,
+ final @NonNull List<PermissionDelegate.ContentPermission> perms,
+ final @NonNull Boolean hasUserGesture) {
+ session.getNavigationDelegate().onLocationChange(session, url, perms);
+ }
+
+ /**
* The view's ability to go back has changed.
*
* @param session The GeckoSession that initiated the callback.
diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSessionSettings.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSessionSettings.java
index 046f7a3072..14f6b14c47 100644
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSessionSettings.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSessionSettings.java
@@ -203,7 +203,7 @@ public final class GeckoSessionSettings implements Parcelable {
})
public @interface DisplayMode {}
- // This needs to match GeckoViewSettings.jsm
+ // This needs to match GeckoViewSettings.sys.mjs
/** "browser" value of the display member in Web App Manifests */
public static final int DISPLAY_MODE_BROWSER = 0;
@@ -225,7 +225,7 @@ public final class GeckoSessionSettings implements Parcelable {
})
public @interface UserAgentMode {}
- // This needs to match GeckoViewSettingsChild.js and GeckoViewSettings.jsm
+ // This needs to match GeckoViewSettingsChild.js and GeckoViewSettings.sys.mjs
/** The user agent mode is mobile device */
public static final int USER_AGENT_MODE_MOBILE = 0;
diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoView.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoView.java
index 74eccaeb15..2271ff71f7 100644
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoView.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoView.java
@@ -767,6 +767,9 @@ public class GeckoView extends FrameLayout implements GeckoDisplay.NewSurfacePro
if (super.onKeyUp(keyCode, event)) {
return true;
}
+ if (AndroidGamepadManager.handleKeyEvent(event)) {
+ return true;
+ }
return mSession != null && mSession.getTextInput().onKeyUp(keyCode, event);
}
@@ -775,6 +778,9 @@ public class GeckoView extends FrameLayout implements GeckoDisplay.NewSurfacePro
if (super.onKeyDown(keyCode, event)) {
return true;
}
+ if (AndroidGamepadManager.handleKeyEvent(event)) {
+ return true;
+ }
return mSession != null && mSession.getTextInput().onKeyDown(keyCode, event);
}
diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebExtension.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebExtension.java
index d553a1aa3f..1caa5508ed 100644
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebExtension.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebExtension.java
@@ -1688,7 +1688,7 @@ public class WebExtension {
* in Firefox. </a>
*/
public static class SignedStateFlags {
- // Keep in sync with AddonManager.jsm
+ // Keep in sync with AddonManager.sys.mjs
/**
* This extension may be signed but by a certificate that doesn't chain to our our trusted
* certificate.
@@ -1820,6 +1820,50 @@ public class WebExtension {
public final @NonNull String[] permissions;
/**
+ * API <a
+ * href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/optional_permissions">optional
+ * permissions</a> requested or granted to this extension.
+ *
+ * <p>Permission identifiers match entries in the manifest, see <a
+ * href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions#API_permissions">
+ * API permissions </a>.
+ */
+ public final @NonNull String[] optionalPermissions;
+
+ /**
+ * API <a
+ * href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/optional_permissions">optional
+ * permissions</a> granted to this extension.
+ *
+ * <p>Permission identifiers match entries in the manifest, see <a
+ * href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions#API_permissions">
+ * API permissions </a>.
+ */
+ public final @NonNull String[] grantedOptionalPermissions;
+
+ /**
+ * API <a
+ * href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/optional_permissions">
+ * optional origin permissions</a> requested or granted to this extension.
+ *
+ * <p>Permission identifiers match entries in the manifest, see <a
+ * href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions#API_permissions">
+ * API permissions </a>.
+ */
+ public final @NonNull String[] optionalOrigins;
+
+ /**
+ * API <a
+ * href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/optional_permissions">
+ * optional origin permissions</a> granted to this extension.
+ *
+ * <p>Permission identifiers match entries in the manifest, see <a
+ * href="https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/manifest.json/permissions#API_permissions">
+ * API permissions </a>.
+ */
+ public final @NonNull String[] grantedOptionalOrigins;
+
+ /**
* Host permissions requested or granted to this extension.
*
* <p>See <a
@@ -1999,6 +2043,10 @@ public class WebExtension {
protected MetaData() {
icon = null;
permissions = null;
+ optionalPermissions = null;
+ grantedOptionalPermissions = null;
+ grantedOptionalOrigins = null;
+ optionalOrigins = null;
origins = null;
name = null;
description = null;
@@ -2029,6 +2077,10 @@ public class WebExtension {
/* package */ MetaData(final GeckoBundle bundle) {
// We only expose permissions that the embedder should prompt for
permissions = bundle.getStringArray("promptPermissions");
+ optionalPermissions = bundle.getStringArray("optionalPermissions");
+ grantedOptionalPermissions = bundle.getStringArray("grantedOptionalPermissions");
+ optionalOrigins = bundle.getStringArray("optionalOrigins");
+ grantedOptionalOrigins = bundle.getStringArray("grantedOptionalOrigins");
origins = bundle.getStringArray("origins");
description = bundle.getString("description");
version = bundle.getString("version");
diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/doc-files/CHANGELOG.md b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/doc-files/CHANGELOG.md
index 10a6eb16cd..5776cf5afc 100644
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/doc-files/CHANGELOG.md
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/doc-files/CHANGELOG.md
@@ -13,6 +13,27 @@ exclude: true
⚠️ breaking change and deprecation notices
+## v125
+- ⚠️ Deprecated [`GeckoSession.NavigationDelegate.onLocationChange`][125.1], to be removed in v127.
+([bug 1837601]({{bugzilla}}1837601))
+- Added [`GeckoSession.NavigationDelegate.onLocationChange#hasUserGesture`][125.2]. This indicates if a location change was requested
+while a user gesture was active (e.g., a tap).
+([bug 1837601]({{bugzilla}}1837601))
+- Added [`WebExtension.MetaData.optionalPermissions`][125.3] and [`WebExtension.MetaData.optionalOrigins`][125.4] which expose the optional and origin optional permissions of an extension ([bug 1811900]({{bugzilla}}1811900)).
+- ⚠️ Deprecated [`RuntimeTelemetry`][125.5], [`GeckoRuntimeSettings.getTelemetryDelegate`][125.6] and [`GeckoRuntimeSettings.telemetryDelegate`][125.7], to be removed in v127.
+([bug 1877836]({{bugzilla}}1877836))
+- Added [`WebExtension.MetaData.grantedOptionalPermissions`][125.8] and [`WebExtension.MetaData.grantedOptionalOrigins`][125.9] which expose the granted optional and origin optional permissions of an extension ([bug 1879543]({{bugzilla}}1879543)).
+
+[125.1]: {{javadoc_uri}}/GeckoSession.NavigationDelegate#onLocationChange(org.mozilla.geckoview.GeckoSession,java.lang.String,java.util.List)
+[125.2]: {{javadoc_uri}}/GeckoSession.NavigationDelegate#onLocationChange(org.mozilla.geckoview.GeckoSession,java.lang.String,java.util.List,boolean)
+[125.3]: {{javadoc_uri}}/WebExtension.MetaData.html#optionalPermissions
+[125.4]: {{javadoc_uri}}/WebExtension.MetaData.html#optionalOrigins
+[125.5]: {{javadoc_uri}}/RuntimeTelemetry.html
+[125.6]: {{javadoc_uri}}/GeckoRuntimeSettings.html#getTelemetryDelegate
+[125.7]: {{javadoc_uri}}/GeckoRuntimeSettings.html#telemetryDelegate
+[125.8]: {{javadoc_uri}}/WebExtension.MetaData.html#grantedOptionalPermissions
+[125.9]: {{javadoc_uri}}/WebExtension.MetaData.html#grantedOptionalOrigins
+
## v124
- Added [`GeckoRuntimeSettings#setTrustedRecursiveResolverMode`][124.1] to enable DNS-over-HTTPS using different resolver modes ([bug 1591533]({{bugzilla}}1591533)).
@@ -36,7 +57,7 @@ exclude: true
[123.1]: {{javadoc_uri}}/TranslationsController.RuntimeTranslation.html#checkPairDownloadSize(java.lang.String,java.lang.String)
[123.2]: {{javadoc_uri}}/TranslationsController.TranslationsException.html#ERROR_MODEL_LANGUAGE_REQUIRED
-[121.3]: {{javadoc_uri}}/GeckoSession.html#sendPlacementAttributionEvent(String)
+[123.3]: {{javadoc_uri}}/GeckoSession.html#sendPlacementAttributionEvent(String)
## v122
- ⚠️ Removed [`onGetNimbusFeature`][115.5], please use `ExperimentDelegate.onGetExperimentFeature` instead.
@@ -1519,4 +1540,4 @@ to allow adding gecko profiler markers.
[65.24]: {{javadoc_uri}}/CrashReporter.html#sendCrashReport(android.content.Context,android.os.Bundle,java.lang.String)
[65.25]: {{javadoc_uri}}/GeckoResult.html
-[api-version]: ff5a513251f19534bbf4ebe0084909665d00a227
+[api-version]: fc9fd590333bebf38058b7abddbb7a860cd6e4de
diff --git a/mobile/android/geckoview/src/test/java/org/mozilla/gecko/util/LocaleUtilsTest.java b/mobile/android/geckoview/src/test/java/org/mozilla/gecko/util/LocaleUtilsTest.java
new file mode 100644
index 0000000000..bc6dcc0ced
--- /dev/null
+++ b/mobile/android/geckoview/src/test/java/org/mozilla/gecko/util/LocaleUtilsTest.java
@@ -0,0 +1,47 @@
+/* Any copyright is dedicated to the Public Domain.
+http://creativecommons.org/publicdomain/zero/1.0/ */
+
+package org.mozilla.gecko.util;
+
+import static org.junit.Assert.*;
+
+import android.test.suitebuilder.annotation.SmallTest;
+import java.util.Locale;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+@RunWith(RobolectricTestRunner.class)
+@SmallTest
+public class LocaleUtilsTest {
+ @Test
+ public void languageTagForAcceptLanguage() {
+ assertEquals(
+ LocaleUtils.getLanguageTagForAcceptLanguage(Locale.forLanguageTag("zn-Hans-CN")), "zn-CN");
+ assertEquals(
+ LocaleUtils.getLanguageTagForAcceptLanguage(Locale.forLanguageTag("zn-Hant-TW")), "zn-TW");
+
+ // If builder is Java 17+, Locale.getLanguage doesn't repelace with old language code.
+ // But we should keep this to make things understandable.
+ assertEquals(
+ LocaleUtils.getLanguageTagForAcceptLanguage(Locale.forLanguageTag("id-ID")), "id-ID");
+ assertEquals(
+ LocaleUtils.getLanguageTagForAcceptLanguage(Locale.forLanguageTag("in-ID")), "id-ID");
+
+ assertEquals(
+ LocaleUtils.getLanguageTagForAcceptLanguage(Locale.forLanguageTag("yi-US")), "yi-US");
+ assertEquals(
+ LocaleUtils.getLanguageTagForAcceptLanguage(Locale.forLanguageTag("ji-US")), "yi-US");
+
+ assertEquals(
+ LocaleUtils.getLanguageTagForAcceptLanguage(Locale.forLanguageTag("he-IL")), "he-IL");
+ assertEquals(
+ LocaleUtils.getLanguageTagForAcceptLanguage(Locale.forLanguageTag("iw-IL")), "he-IL");
+
+ // Android 14 may add extension (Bug 1873578)
+ assertEquals(
+ LocaleUtils.getLanguageTagForAcceptLanguage(
+ Locale.forLanguageTag("en-US-u-fw-mon-mu-celsius")),
+ "en-US");
+ }
+}