diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 01:13:33 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 01:13:33 +0000 |
commit | 086c044dc34dfc0f74fbe41f4ecb402b2cd34884 (patch) | |
tree | a4f824bd33cb075dd5aa3eb5a0a94af221bbe83a /mobile | |
parent | Adding debian version 124.0.1-1. (diff) | |
download | firefox-086c044dc34dfc0f74fbe41f4ecb402b2cd34884.tar.xz firefox-086c044dc34dfc0f74fbe41f4ecb402b2cd34884.zip |
Merging upstream version 125.0.1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'mobile')
123 files changed, 1159 insertions, 330 deletions
diff --git a/mobile/android/actors/GeckoViewContentParent.sys.mjs b/mobile/android/actors/GeckoViewContentParent.sys.mjs index 354489054a..e666040b5e 100644 --- a/mobile/android/actors/GeckoViewContentParent.sys.mjs +++ b/mobile/android/actors/GeckoViewContentParent.sys.mjs @@ -62,7 +62,7 @@ export class GeckoViewContentParent extends GeckoViewActorParent { const progressListener = { QueryInterface: ChromeUtils.generateQI(["nsIWebProgressListener"]), - onLocationChange(aWebProgress, aRequest, aLocationURI, aFlags) { + onLocationChange(aWebProgress) { if (!aWebProgress.isTopLevel) { return; } diff --git a/mobile/android/actors/SelectionActionDelegateChild.sys.mjs b/mobile/android/actors/SelectionActionDelegateChild.sys.mjs index 9f05906e09..f9c09de11f 100644 --- a/mobile/android/actors/SelectionActionDelegateChild.sys.mjs +++ b/mobile/android/actors/SelectionActionDelegateChild.sys.mjs @@ -97,17 +97,17 @@ export class SelectionActionDelegateChild extends GeckoViewActorChild { { id: "org.mozilla.geckoview.COLLAPSE_TO_START", predicate: e => !e.collapsed && e.selectionEditable, - perform: e => this.docShell.doCommand("cmd_moveLeft"), + perform: () => this.docShell.doCommand("cmd_moveLeft"), }, { id: "org.mozilla.geckoview.COLLAPSE_TO_END", predicate: e => !e.collapsed && e.selectionEditable, - perform: e => this.docShell.doCommand("cmd_moveRight"), + perform: () => this.docShell.doCommand("cmd_moveRight"), }, { id: "org.mozilla.geckoview.UNSELECT", predicate: e => !e.collapsed && !e.selectionEditable, - perform: e => this.docShell.doCommand("cmd_selectNone"), + perform: () => this.docShell.doCommand("cmd_selectNone"), }, { id: "org.mozilla.geckoview.SELECT_ALL", @@ -134,7 +134,7 @@ export class SelectionActionDelegateChild extends GeckoViewActorChild { } return true; }, - perform: e => this.docShell.doCommand("cmd_selectAll"), + perform: () => this.docShell.doCommand("cmd_selectAll"), }, ]; diff --git a/mobile/android/annotations/build.gradle b/mobile/android/annotations/build.gradle index 147531b251..aa531dd0a9 100644 --- a/mobile/android/annotations/build.gradle +++ b/mobile/android/annotations/build.gradle @@ -10,5 +10,7 @@ dependencies { implementation 'com.android.tools.lint:lint-checks:30.4.2' } -sourceCompatibility = JavaVersion.VERSION_17 -targetCompatibility = JavaVersion.VERSION_17 +java { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 +} diff --git a/mobile/android/app/geckoview-prefs.js b/mobile/android/app/geckoview-prefs.js index d71f7f49e8..6d136b1a0a 100644 --- a/mobile/android/app/geckoview-prefs.js +++ b/mobile/android/app/geckoview-prefs.js @@ -142,12 +142,10 @@ pref("browser.sessionstore.max_tabs_undo", 10); pref("browser.sessionstore.privacy_level", 0); pref("browser.sessionstore.resume_from_crash", true); -// Bug 1809922 to enable translations -#ifdef NIGHTLY_BUILD - pref("browser.translations.enable", true); - // Used for mocking data for GeckoView Translations tests, should use in addition with an automation check. - pref("browser.translations.geckoview.enableAllTestMocks", false); -#endif +// Enables the translations engine +pref("browser.translations.enable", true); +// Used for mocking data for GeckoView Translations tests, should use in addition with an automation check. +pref("browser.translations.geckoview.enableAllTestMocks", false); // SSL error page behaviour (bug 437372) pref("browser.xul.error_pages.expert_bad_cert", false); @@ -214,7 +212,7 @@ pref("dom.webshare.enabled", true); pref("extensions.abuseReport.amWebAPI.enabled", false); // Disable add-ons that are not installed by the user in all scopes by default (See the SCOPE -// constants in AddonManager.jsm for values to use here, and Bug 1405528 for a rationale) +// constants in AddonManager.sys.mjs for values to use here, and Bug 1405528 for a rationale) pref("extensions.autoDisableScopes", 15); pref("extensions.enabledScopes", 5); diff --git a/mobile/android/chrome/geckoview/SessionStateAggregator.js b/mobile/android/chrome/geckoview/SessionStateAggregator.js index ede17328ac..e41c31ba06 100644 --- a/mobile/android/chrome/geckoview/SessionStateAggregator.js +++ b/mobile/android/chrome/geckoview/SessionStateAggregator.js @@ -29,7 +29,6 @@ const DEFAULT_INTERVAL_MS = 1500; const TIMEOUT_DISABLED_PREF = "browser.sessionstore.debug.no_auto_updates"; const PREF_INTERVAL = "browser.sessionstore.interval"; -const PREF_SESSION_COLLECTION = "browser.sessionstore.platform_collection"; class Handler { constructor(store) { @@ -96,7 +95,7 @@ class StateChangeNotifier extends Handler { /** * @see nsIWebProgressListener.onStateChange */ - onStateChange(webProgress, request, stateFlags, status) { + onStateChange(webProgress, request, stateFlags) { // Ignore state changes for subframes because we're only interested in the // top-document starting or stopping its load. if (!webProgress.isTopLevel || webProgress.DOMWindow != this.mm.content) { @@ -206,7 +205,7 @@ class SessionHistoryListener extends Handler { }); } - handleEvent(event) { + handleEvent() { this.collect(); } @@ -218,30 +217,30 @@ class SessionHistoryListener extends Handler { this.collect(); } - OnHistoryNewEntry(newURI, oldIndex) { + OnHistoryNewEntry() { // We ought to collect the previously current entry as well, see bug 1350567. // TODO: Reenable partial history collection for performance // this.collectFrom(oldIndex); this.collect(); } - OnHistoryGotoIndex(index, gotoURI) { + OnHistoryGotoIndex() { // We ought to collect the previously current entry as well, see bug 1350567. // TODO: Reenable partial history collection for performance // this.collectFrom(LAST_INDEX); this.collect(); } - OnHistoryPurge(numEntries) { + OnHistoryPurge() { this.collect(); } - OnHistoryReload(reloadURI, reloadFlags) { + OnHistoryReload() { this.collect(); return true; } - OnHistoryReplaceEntry(index) { + OnHistoryReplaceEntry() { this.collect(); } } @@ -607,7 +606,7 @@ class SessionStateAggregator extends GeckoViewChildModule { this.messageQueue, ]; - if (!Services.prefs.getBoolPref(PREF_SESSION_COLLECTION, false)) { + if (!Services.appinfo.sessionStorePlatformCollection) { this.handlers.push( new FormDataListener(this), new ScrollPositionListener(this) diff --git a/mobile/android/chrome/geckoview/config.js b/mobile/android/chrome/geckoview/config.js index 1cf92416ac..9b1226a330 100644 --- a/mobile/android/chrome/geckoview/config.js +++ b/mobile/android/chrome/geckoview/config.js @@ -147,7 +147,7 @@ var NewPrefDialog = { // New prefs create dialog only allows creating a non-existing preference, doesn't allow for // Changing an existing one on-the-fly, tap existing/displayed line item pref for that - create: function AC_create(aEvent) { + create: function AC_create() { if (this._positiveButton.getAttribute("disabled") == "true") { return; } @@ -342,7 +342,7 @@ var AboutConfig = { }, // If scrolling at the bottom, maybe add some more entries - onScroll: function AC_onScroll(aEvent) { + onScroll: function AC_onScroll() { if ( this._prefsContainer.scrollHeight - (window.pageYOffset + window.innerHeight) < diff --git a/mobile/android/chrome/geckoview/geckoview.js b/mobile/android/chrome/geckoview/geckoview.js index 6dc5ed4610..dc7ceab7f8 100644 --- a/mobile/android/chrome/geckoview/geckoview.js +++ b/mobile/android/chrome/geckoview/geckoview.js @@ -255,7 +255,7 @@ var ModuleManager = { this._moduleByActorName[aActorName].receiveMessage(aMessage); }, - onEvent(aEvent, aData, aCallback) { + onEvent(aEvent, aData) { debug`onEvent ${aEvent} ${aData}`; switch (aEvent) { case "GeckoView:UpdateModuleState": { @@ -865,11 +865,11 @@ function startup() { ModuleManager.afterBrowserRemotenessChange(switchId); } - browser.addEventListener("WillChangeBrowserRemoteness", event => + browser.addEventListener("WillChangeBrowserRemoteness", () => ModuleManager.willChangeBrowserRemoteness() ); - browser.addEventListener("DidChangeBrowserRemoteness", event => + browser.addEventListener("DidChangeBrowserRemoteness", () => ModuleManager.didChangeBrowserRemoteness() ); diff --git a/mobile/android/components/extensions/ext-android.js b/mobile/android/components/extensions/ext-android.js index b53c390f36..2576a42ba5 100644 --- a/mobile/android/components/extensions/ext-android.js +++ b/mobile/android/components/extensions/ext-android.js @@ -197,7 +197,7 @@ global.makeGlobalEvent = function makeGlobalEvent( name, register: fire => { const listener2 = { - onEvent(event, data, callback) { + onEvent(event, data) { listener(fire, data); }, }; diff --git a/mobile/android/components/extensions/ext-browserAction.js b/mobile/android/components/extensions/ext-browserAction.js index 3a91e913f9..de693274d6 100644 --- a/mobile/android/components/extensions/ext-browserAction.js +++ b/mobile/android/components/extensions/ext-browserAction.js @@ -28,7 +28,7 @@ const BROWSER_ACTION_PROPERTIES = [ class BrowserAction extends BrowserActionBase { constructor(extension, clickDelegate) { - const tabContext = new TabContext(tabId => this.getContextData(null)); + const tabContext = new TabContext(() => this.getContextData(null)); super(tabContext, extension); this.clickDelegate = clickDelegate; this.helper = new ExtensionActionHelper({ @@ -86,7 +86,7 @@ this.browserAction = class extends ExtensionAPIPersistent { return GeckoViewWebExtension.browserActions.get(extension); } - async onManifestEntry(entryName) { + async onManifestEntry() { const { extension } = this; this.action = new BrowserAction(extension, this); await this.action.loadIconData(); diff --git a/mobile/android/components/extensions/ext-downloads.js b/mobile/android/components/extensions/ext-downloads.js index 6422440d54..1dd5b558e1 100644 --- a/mobile/android/components/extensions/ext-downloads.js +++ b/mobile/android/components/extensions/ext-downloads.js @@ -146,7 +146,7 @@ class DownloadItem { this.downloads = class extends ExtensionAPIPersistent { PERSISTENT_EVENTS = { - onChanged({ fire }, params) { + onChanged({ fire }) { const listener = (eventName, event) => { const { delta, downloadItem } = event; const { extension } = this; @@ -248,23 +248,23 @@ this.downloads = class extends ExtensionAPIPersistent { }); }, - removeFile(downloadId) { + removeFile() { throw new ExtensionError("Not implemented"); }, - search(query) { + search() { throw new ExtensionError("Not implemented"); }, - pause(downloadId) { + pause() { throw new ExtensionError("Not implemented"); }, - resume(downloadId) { + resume() { throw new ExtensionError("Not implemented"); }, - cancel(downloadId) { + cancel() { throw new ExtensionError("Not implemented"); }, @@ -272,19 +272,19 @@ this.downloads = class extends ExtensionAPIPersistent { throw new ExtensionError("Not implemented"); }, - erase(query) { + erase() { throw new ExtensionError("Not implemented"); }, - open(downloadId) { + open() { throw new ExtensionError("Not implemented"); }, - show(downloadId) { + show() { throw new ExtensionError("Not implemented"); }, - getFileIcon(downloadId, options) { + getFileIcon() { throw new ExtensionError("Not implemented"); }, diff --git a/mobile/android/components/extensions/ext-pageAction.js b/mobile/android/components/extensions/ext-pageAction.js index 04973379f1..18eeb241b1 100644 --- a/mobile/android/components/extensions/ext-pageAction.js +++ b/mobile/android/components/extensions/ext-pageAction.js @@ -26,7 +26,7 @@ const PAGE_ACTION_PROPERTIES = [ class PageAction extends PageActionBase { constructor(extension, clickDelegate) { - const tabContext = new TabContext(tabId => this.getContextData(null)); + const tabContext = new TabContext(() => this.getContextData(null)); super(tabContext, extension); this.clickDelegate = clickDelegate; this.helper = new ExtensionActionHelper({ @@ -80,7 +80,7 @@ this.pageAction = class extends ExtensionAPIPersistent { return GeckoViewWebExtension.pageActions.get(extension); } - async onManifestEntry(entryName) { + async onManifestEntry() { const { extension } = this; const action = new PageAction(extension, this); await action.loadIconData(); diff --git a/mobile/android/components/extensions/ext-tabs.js b/mobile/android/components/extensions/ext-tabs.js index 88d3d9e83a..66c7417379 100644 --- a/mobile/android/components/extensions/ext-tabs.js +++ b/mobile/android/components/extensions/ext-tabs.js @@ -28,7 +28,7 @@ const tabListener = { } }, - onLocationChange(browser, webProgress, request, locationURI, flags) { + onLocationChange(browser, webProgress, request) { if (webProgress.isTopLevel) { const { tab } = browser.ownerGlobal; @@ -103,7 +103,7 @@ this.tabs = class extends ExtensionAPIPersistent { } PERSISTENT_EVENTS = { - onActivated({ fire, context }, params) { + onActivated({ fire, context }) { const listener = (eventName, event) => { const { windowId, tabId, isPrivate } = event; if (isPrivate && !context.privateBrowsingAllowed) { @@ -140,7 +140,7 @@ this.tabs = class extends ExtensionAPIPersistent { }); }, }), - onUpdated({ fire }, params) { + onUpdated({ fire }) { const { tabManager } = this.extension; const restricted = ["url", "favIconUrl", "title"]; @@ -328,7 +328,7 @@ this.tabs = class extends ExtensionAPIPersistent { onAttached: new EventManager({ context, name: "tabs.onAttached", - register: fire => { + register: () => { return () => {}; }, }).api(), @@ -336,7 +336,7 @@ this.tabs = class extends ExtensionAPIPersistent { onDetached: new EventManager({ context, name: "tabs.onDetached", - register: fire => { + register: () => { return () => {}; }, }).api(), @@ -351,7 +351,7 @@ this.tabs = class extends ExtensionAPIPersistent { onReplaced: new EventManager({ context, name: "tabs.onReplaced", - register: fire => { + register: () => { return () => {}; }, }).api(), @@ -359,7 +359,7 @@ this.tabs = class extends ExtensionAPIPersistent { onMoved: new EventManager({ context, name: "tabs.onMoved", - register: fire => { + register: () => { return () => {}; }, }).api(), @@ -378,7 +378,6 @@ this.tabs = class extends ExtensionAPIPersistent { index, openInReaderMode, pinned, - title, url, } = {}) { if (active === null) { diff --git a/mobile/android/components/extensions/test/mochitest/test_ext_tabs_events.html b/mobile/android/components/extensions/test/mochitest/test_ext_tabs_events.html index cd708d942a..19aaf07f92 100644 --- a/mobile/android/components/extensions/test/mochitest/test_ext_tabs_events.html +++ b/mobile/android/components/extensions/test/mochitest/test_ext_tabs_events.html @@ -106,7 +106,7 @@ add_task(async function testTabRemovalEvent() { async function background() { function awaitLoad(tabId) { return new Promise(resolve => { - browser.tabs.onUpdated.addListener(function listener(tabId_, changed, tab) { + browser.tabs.onUpdated.addListener(function listener(tabId_, changed) { if (tabId == tabId_ && changed.status == "complete") { browser.tabs.onUpdated.removeListener(listener); resolve(); @@ -115,7 +115,7 @@ add_task(async function testTabRemovalEvent() { }); } - chrome.tabs.onRemoved.addListener((tabId, info) => { + chrome.tabs.onRemoved.addListener((tabId) => { browser.test.log("Make sure the removed tab is not available in the tabs.query callback."); chrome.tabs.query({}, tabs => { for (const tab of tabs) { diff --git a/mobile/android/components/extensions/test/mochitest/test_ext_tabs_executeScript.html b/mobile/android/components/extensions/test/mochitest/test_ext_tabs_executeScript.html index 09e42d73cf..ab722f48d7 100644 --- a/mobile/android/components/extensions/test/mochitest/test_ext_tabs_executeScript.html +++ b/mobile/android/components/extensions/test/mochitest/test_ext_tabs_executeScript.html @@ -40,7 +40,7 @@ add_task(async function testExecuteScript() { browser.tabs.executeScript({ file: "script.js", code: "42", - }).then(result => { + }).then(() => { browser.test.fail("Expected not to be able to execute a script with both file and code"); }, error => { browser.test.assertTrue(/a 'code' or a 'file' property, but not both/.test(error.message), @@ -99,7 +99,7 @@ add_task(async function testExecuteScript() { browser.tabs.executeScript({ code: "window", - }).then(result => { + }).then(() => { browser.test.fail("Expected error when returning non-structured-clonable object"); }, error => { browser.test.assertEq("<anonymous code>", error.fileName, "Got expected fileName"); @@ -109,7 +109,7 @@ add_task(async function testExecuteScript() { browser.tabs.executeScript({ code: "Promise.resolve(window)", - }).then(result => { + }).then(() => { browser.test.fail("Expected error when returning non-structured-clonable object"); }, error => { browser.test.assertEq("<anonymous code>", error.fileName, "Got expected fileName"); @@ -119,7 +119,7 @@ add_task(async function testExecuteScript() { browser.tabs.executeScript({ file: "script3.js", - }).then(result => { + }).then(() => { browser.test.fail("Expected error when returning non-structured-clonable object"); }, error => { const expected = /Script '.*script3.js' result is non-structured-clonable data/; @@ -130,7 +130,7 @@ add_task(async function testExecuteScript() { browser.tabs.executeScript({ frameId: Number.MAX_SAFE_INTEGER, code: "42", - }).then(result => { + }).then(() => { browser.test.fail("Expected error when specifying invalid frame ID"); }, error => { browser.test.assertEq( @@ -143,7 +143,7 @@ add_task(async function testExecuteScript() { browser.tabs.create({url: "http://example.net/", active: false}).then(async tab => { await browser.tabs.executeScript(tab.id, { code: "42", - }).then(result => { + }).then(() => { browser.test.fail("Expected error when trying to execute on invalid domain"); }, error => { browser.test.assertEq(`Missing host permission for the tab`, diff --git a/mobile/android/components/extensions/test/mochitest/test_ext_tabs_onUpdated.html b/mobile/android/components/extensions/test/mochitest/test_ext_tabs_onUpdated.html index 8d96e79cc2..1ec815c8c7 100644 --- a/mobile/android/components/extensions/test/mochitest/test_ext_tabs_onUpdated.html +++ b/mobile/android/components/extensions/test/mochitest/test_ext_tabs_onUpdated.html @@ -44,7 +44,7 @@ add_task(async function test_onUpdated() { } }); - browser.runtime.onMessage.addListener(async msg => { + browser.runtime.onMessage.addListener(async () => { if (collectedSequence.length !== expectedSequence.length) { browser.test.assertEq( JSON.stringify(expectedSequence), diff --git a/mobile/android/components/extensions/test/mochitest/test_ext_tabs_sendMessage.html b/mobile/android/components/extensions/test/mochitest/test_ext_tabs_sendMessage.html index 320ce4dde6..4709fbe31c 100644 --- a/mobile/android/components/extensions/test/mochitest/test_ext_tabs_sendMessage.html +++ b/mobile/android/components/extensions/test/mochitest/test_ext_tabs_sendMessage.html @@ -31,7 +31,7 @@ add_task(async function tabsSendMessageReply() { // eslint-disable-next-line prefer-const let firstTab; const promiseResponse = new Promise(resolve => { - browser.runtime.onMessage.addListener((msg, sender, respond) => { + browser.runtime.onMessage.addListener((msg, sender) => { if (msg == "content-script-ready") { const tabId = sender.tab.id; @@ -170,7 +170,7 @@ add_task(async function tabsSendHidden() { background: async function() { let resolveContent; - browser.runtime.onMessage.addListener((msg, sender) => { + browser.runtime.onMessage.addListener((msg) => { if (msg[0] == "content-ready") { resolveContent(msg[1]); } @@ -220,7 +220,7 @@ add_task(async function tabsSendHidden() { // properties of the possibly-hidden content window. const href = window.location.href; - browser.runtime.onMessage.addListener((msg, sender) => { + browser.runtime.onMessage.addListener((msg) => { browser.test.assertEq(href, msg, "Should be in the expected content window"); return Promise.resolve(href); diff --git a/mobile/android/components/extensions/test/xpcshell/test_ext_native_messaging_geckoview.js b/mobile/android/components/extensions/test/xpcshell/test_ext_native_messaging_geckoview.js index 3ba2e26139..43bc138e7f 100644 --- a/mobile/android/components/extensions/test/xpcshell/test_ext_native_messaging_geckoview.js +++ b/mobile/android/components/extensions/test/xpcshell/test_ext_native_messaging_geckoview.js @@ -34,7 +34,7 @@ class EmbedderPort { onPortDisconnect() { Assert.ok(false, "onPortDisconnect not expected to be called"); } - onPortMessage(holder) { + onPortMessage() { Assert.ok(false, "onPortMessage not expected to be called"); } triggerPortDisconnect() { diff --git a/mobile/android/components/geckoview/FilePickerDelegate.sys.mjs b/mobile/android/components/geckoview/FilePickerDelegate.sys.mjs index 3972017b40..52d1b93233 100644 --- a/mobile/android/components/geckoview/FilePickerDelegate.sys.mjs +++ b/mobile/android/components/geckoview/FilePickerDelegate.sys.mjs @@ -15,14 +15,14 @@ const { debug, warn } = GeckoViewUtils.initLogging("FilePickerDelegate"); export class FilePickerDelegate { /* ---------- nsIFilePicker ---------- */ - init(aParent, aTitle, aMode) { + init(aBrowsingContext, aTitle, aMode) { if ( aMode === Ci.nsIFilePicker.modeGetFolder || aMode === Ci.nsIFilePicker.modeSave ) { throw Components.Exception("", Cr.NS_ERROR_NOT_IMPLEMENTED); } - this._prompt = new lazy.GeckoViewPrompter(aParent); + this._prompt = new lazy.GeckoViewPrompter(aBrowsingContext); this._msg = { type: "file", title: aTitle, diff --git a/mobile/android/components/geckoview/GeckoViewPrompter.sys.mjs b/mobile/android/components/geckoview/GeckoViewPrompter.sys.mjs index f81c155678..5c4b91c2de 100644 --- a/mobile/android/components/geckoview/GeckoViewPrompter.sys.mjs +++ b/mobile/android/components/geckoview/GeckoViewPrompter.sys.mjs @@ -140,7 +140,7 @@ export class GeckoViewPrompter { // Spin this thread while we wait for a result Services.tm.spinEventLoopUntil( - "GeckoViewPrompter.jsm:showPrompt", + "GeckoViewPrompter.sys.mjs:showPrompt", () => this._domWin.closed || result !== undefined ); } finally { diff --git a/mobile/android/components/geckoview/GeckoViewPush.sys.mjs b/mobile/android/components/geckoview/GeckoViewPush.sys.mjs index d6625942e8..ee315b850f 100644 --- a/mobile/android/components/geckoview/GeckoViewPush.sys.mjs +++ b/mobile/android/components/geckoview/GeckoViewPush.sys.mjs @@ -22,7 +22,6 @@ const OBSERVER_TOPIC_SUBSCRIPTION_MODIFIED = "push-subscription-modified"; function createSubscription({ scope, - principal, browserPublicKey, authSecret, endpoint, @@ -59,7 +58,7 @@ export class PushService { // nsIObserver methods - observe(subject, topic, data) {} + observe() {} // nsIPushService methods @@ -151,13 +150,13 @@ export class PushService { // nsIPushQuotaManager methods - notificationForOriginShown(origin) {} + notificationForOriginShown() {} - notificationForOriginClosed(origin) {} + notificationForOriginClosed() {} // nsIPushErrorReporter methods - reportDeliveryError(messageId, reason) {} + reportDeliveryError() {} } PushService.prototype.classID = Components.ID( diff --git a/mobile/android/components/geckoview/GeckoViewStartup.sys.mjs b/mobile/android/components/geckoview/GeckoViewStartup.sys.mjs index 734db47887..2a5b0beb4d 100644 --- a/mobile/android/components/geckoview/GeckoViewStartup.sys.mjs +++ b/mobile/android/components/geckoview/GeckoViewStartup.sys.mjs @@ -95,7 +95,7 @@ const JSWINDOWACTORS = { export class GeckoViewStartup { /* ---------- nsIObserver ---------- */ - observe(aSubject, aTopic, aData) { + observe(aSubject, aTopic) { debug`observe: ${aTopic}`; switch (aTopic) { case "content-process-ready-for-script": @@ -284,7 +284,7 @@ export class GeckoViewStartup { } } - onEvent(aEvent, aData, aCallback) { + onEvent(aEvent, aData) { debug`onEvent ${aEvent}`; switch (aEvent) { diff --git a/mobile/android/components/geckoview/LoginStorageDelegate.sys.mjs b/mobile/android/components/geckoview/LoginStorageDelegate.sys.mjs index 28916917ca..3c6d264069 100644 --- a/mobile/android/components/geckoview/LoginStorageDelegate.sys.mjs +++ b/mobile/android/components/geckoview/LoginStorageDelegate.sys.mjs @@ -38,12 +38,7 @@ export class LoginStorageDelegate { }; } - promptToSavePassword( - aBrowser, - aLogin, - dismissed = false, - notifySaved = false - ) { + promptToSavePassword(aBrowser, aLogin, dismissed = false) { const prompt = new lazy.GeckoViewPrompter(aBrowser.ownerGlobal); prompt.asyncShowPrompt( this._createMessage({ dismissed }, [ @@ -75,7 +70,7 @@ export class LoginStorageDelegate { aOldLogin, aNewLogin, dismissed = false, - notifySaved = false, + notifySaved, autoSavedLoginGuid = "" ) { const newLogin = lazy.LoginEntry.fromLoginInfo(aOldLogin || aNewLogin); diff --git a/mobile/android/docs/geckoview/design/priority-hint.rst b/mobile/android/docs/geckoview/design/priority-hint.rst index 4a915bb7ed..d7250e60e8 100644 --- a/mobile/android/docs/geckoview/design/priority-hint.rst +++ b/mobile/android/docs/geckoview/design/priority-hint.rst @@ -47,7 +47,7 @@ Specified and active tabs would be ``PRIORITY_HIGH``. The default would be public void setPriorityHint(final @Priority int priorityHint) -Listeners in ``GeckoViewContent.jsm`` will set +Listeners in ``GeckoViewContent.sys.mjs`` will set ``this.browser.frameLoader.remoteTab.priorityHint`` to the boolean passed in. .. code:: java diff --git a/mobile/android/docs/geckoview/design/save-to-pdf.rst b/mobile/android/docs/geckoview/design/save-to-pdf.rst index fc4edc6310..63473f5ed9 100644 --- a/mobile/android/docs/geckoview/design/save-to-pdf.rst +++ b/mobile/android/docs/geckoview/design/save-to-pdf.rst @@ -40,12 +40,12 @@ What ---- This work will add a method to ``GeckoSession`` called ``savePdf`` for -embedders to use, which will communicate with a new ``GeckoViewPdf.jsm`` to +embedders to use, which will communicate with a new ``GeckoViewPdf.sys.mjs`` to create the PDF file. When the document is available, the ``GeckoViewPdfController`` will notify the ``ContentDelegate.onExternalResponse`` with the downloadable document. -- ``GeckoViewPdf.jsm`` - JavaScript implementation that converts the content to +- ``GeckoViewPdf.sys.mjs`` - JavaScript implementation that converts the content to a PDF and saves the file, also responds to messaging from ``GeckoViewPdfController``. - ``GeckoViewPdfController.java`` - The Controller coordinates between the Java @@ -72,8 +72,8 @@ GeckoSession.java } -GeckoViewPdf.jsm -^^^^^^^^^^^^^^^^ +GeckoViewPdf.sys.mjs +^^^^^^^^^^^^^^^^^^^^ .. code:: java this.registerListener([ @@ -92,7 +92,7 @@ GeckoViewPdf.jsm } async saveToPDF() { - // Reference: https://searchfox.org/mozilla-central/source/remote/cdp/domains/parent/Page.jsm#519 + // Reference: https://searchfox.org/mozilla-central/source/remote/cdp/domains/parent/Page.sys.mjs#519 } @@ -183,7 +183,7 @@ geckoview.js { name: "GeckoViewPdf", onInit: { - resource: "resource://gre/modules/GeckoViewPdf.jsm", + resource: "resource://gre/modules/GeckoViewPdf.sys.mjs", } } @@ -191,7 +191,7 @@ geckoview.js Testing ------- -- Tests for the jsm and java code will be covered by mochitests and junit. +- Tests for the sys.mjs and java code will be covered by mochitests and junit. - Make assertions to check that the text and images are in the finished PDF; the PDF is a non-zero file size. diff --git a/mobile/android/exoplayer2/build.gradle b/mobile/android/exoplayer2/build.gradle index d67995650f..f4106a7591 100644 --- a/mobile/android/exoplayer2/build.gradle +++ b/mobile/android/exoplayer2/build.gradle @@ -34,6 +34,10 @@ android { } } + publishing { + singleVariant("debug") + } + namespace 'org.mozilla.geckoview.thirdparty' } @@ -106,5 +110,7 @@ publishing { } } -sourceCompatibility = JavaVersion.VERSION_1_8 -targetCompatibility = JavaVersion.VERSION_1_8 +java { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 +} 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 Binary files differnew file mode 100644 index 0000000000..90687de26d --- /dev/null +++ b/mobile/android/geckoview/src/androidTest/assets/web_extensions/borderify-mv3/icons/border-48.png 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"); + } +} diff --git a/mobile/android/geckoview_example/src/main/java/org/mozilla/geckoview_example/GeckoViewActivity.java b/mobile/android/geckoview_example/src/main/java/org/mozilla/geckoview_example/GeckoViewActivity.java index 168a238694..30ae778b8b 100644 --- a/mobile/android/geckoview_example/src/main/java/org/mozilla/geckoview_example/GeckoViewActivity.java +++ b/mobile/android/geckoview_example/src/main/java/org/mozilla/geckoview_example/GeckoViewActivity.java @@ -2624,7 +2624,10 @@ public class GeckoViewActivity extends AppCompatActivity private class ExampleNavigationDelegate implements GeckoSession.NavigationDelegate { @Override public void onLocationChange( - GeckoSession session, final String url, final List<ContentPermission> perms) { + GeckoSession session, + final String url, + final List<ContentPermission> perms, + Boolean hasUserGesture) { mToolbarView.getLocationView().setText(url); TabSession tabSession = mTabSessionManager.getSession(session); if (tabSession != null) { diff --git a/mobile/android/gradle/with_gecko_binaries.gradle b/mobile/android/gradle/with_gecko_binaries.gradle index 009a1f586e..0f47e89414 100644 --- a/mobile/android/gradle/with_gecko_binaries.gradle +++ b/mobile/android/gradle/with_gecko_binaries.gradle @@ -46,7 +46,7 @@ ext.configureLibraryVariantWithJNIWrappers = { variant, module -> wrapperTask = task("generateJNIWrappersFor${module}${variant.name.capitalize()}") } else { wrapperTask = task("generateJNIWrappersFor${module}${variant.name.capitalize()}", type: JavaExec) { - classpath annotationProcessorsJarTask.archivePath + classpath annotationProcessorsJarTask.archiveFile // Configure the classpath at evaluation-time, not at // configuration-time: see above comment. @@ -61,7 +61,7 @@ ext.configureLibraryVariantWithJNIWrappers = { variant, module -> workingDir "${topobjdir}/widget/android" inputs.file(bundleJar) - inputs.file(annotationProcessorsJarTask.archivePath) + inputs.file(annotationProcessorsJarTask.archiveFile) inputs.property("module", module) outputs.file("${topobjdir}/widget/android/GeneratedJNINatives.h") diff --git a/mobile/android/installer/package-manifest.in b/mobile/android/installer/package-manifest.in index 08361b8870..1e76051ab6 100644 --- a/mobile/android/installer/package-manifest.in +++ b/mobile/android/installer/package-manifest.in @@ -43,10 +43,8 @@ #endif @BINPATH@/@DLL_PREFIX@lgpllibs@DLL_SUFFIX@ @BINPATH@/@DLL_PREFIX@gkcodecs@DLL_SUFFIX@ -#ifdef MOZ_FFVPX @BINPATH@/@DLL_PREFIX@mozavutil@DLL_SUFFIX@ @BINPATH@/@DLL_PREFIX@mozavcodec@DLL_SUFFIX@ -#endif #ifdef MOZ_OMX_PLUGIN @BINPATH@/@DLL_PREFIX@omxplugin@DLL_SUFFIX@ @BINPATH@/@DLL_PREFIX@omxpluginkk@DLL_SUFFIX@ diff --git a/mobile/android/modules/geckoview/ChildCrashHandler.sys.mjs b/mobile/android/modules/geckoview/ChildCrashHandler.sys.mjs index 52a929511a..5c6418091a 100644 --- a/mobile/android/modules/geckoview/ChildCrashHandler.sys.mjs +++ b/mobile/android/modules/geckoview/ChildCrashHandler.sys.mjs @@ -30,7 +30,7 @@ export var ChildCrashHandler = { // Map a child ID to a remote type. childMap: new Map(), - // The event listener for this is hooked up in GeckoViewStartup.jsm + // The event listener for this is hooked up in GeckoViewStartup.sys.mjs observe(aSubject, aTopic, aData) { const childID = aData; diff --git a/mobile/android/modules/geckoview/GeckoViewContent.sys.mjs b/mobile/android/modules/geckoview/GeckoViewContent.sys.mjs index b593a6f8e4..240aea0cbe 100644 --- a/mobile/android/modules/geckoview/GeckoViewContent.sys.mjs +++ b/mobile/android/modules/geckoview/GeckoViewContent.sys.mjs @@ -345,7 +345,7 @@ export class GeckoViewContent extends GeckoViewModule { } // nsIObserver event handler - observe(aSubject, aTopic, aData) { + observe(aSubject, aTopic) { debug`observe: ${aTopic}`; this._contentCrashed = false; const browser = aSubject.ownerElement; diff --git a/mobile/android/modules/geckoview/GeckoViewMediaControl.sys.mjs b/mobile/android/modules/geckoview/GeckoViewMediaControl.sys.mjs index 1b39125fce..ebe529e313 100644 --- a/mobile/android/modules/geckoview/GeckoViewMediaControl.sys.mjs +++ b/mobile/android/modules/geckoview/GeckoViewMediaControl.sys.mjs @@ -67,7 +67,7 @@ export class GeckoViewMediaControl extends GeckoViewModule { return this.browser.browsingContext.mediaController; } - onEvent(aEvent, aData, aCallback) { + onEvent(aEvent, aData) { debug`onEvent: event=${aEvent}, data=${aData}`; switch (aEvent) { diff --git a/mobile/android/modules/geckoview/GeckoViewModule.sys.mjs b/mobile/android/modules/geckoview/GeckoViewModule.sys.mjs index 87ad35d817..b05244612a 100644 --- a/mobile/android/modules/geckoview/GeckoViewModule.sys.mjs +++ b/mobile/android/modules/geckoview/GeckoViewModule.sys.mjs @@ -132,7 +132,7 @@ class EventProxy { } } - onEvent(aEvent, aData, aCallback) { + onEvent(aEvent, aData) { if (this._enableQueuing) { debug`queue ${aEvent}, data=${aData}`; this._eventQueue.unshift(arguments); @@ -146,7 +146,7 @@ class EventProxy { this._enableQueuing = aEnable; } - _dispatch(aEvent, aData, aCallback) { + _dispatch(aEvent, aData) { debug`dispatch ${aEvent}, data=${aData}`; if (this.listener.onEvent) { this.listener.onEvent(...arguments); diff --git a/mobile/android/modules/geckoview/GeckoViewNavigation.sys.mjs b/mobile/android/modules/geckoview/GeckoViewNavigation.sys.mjs index 287a605dff..bc098f0413 100644 --- a/mobile/android/modules/geckoview/GeckoViewNavigation.sys.mjs +++ b/mobile/android/modules/geckoview/GeckoViewNavigation.sys.mjs @@ -155,7 +155,7 @@ export class GeckoViewNavigation extends GeckoViewModule { } // Bundle event handler. - async onEvent(aEvent, aData, aCallback) { + async onEvent(aEvent, aData) { debug`onEvent: event=${aEvent}, data=${aData}`; switch (aEvent) { @@ -291,7 +291,7 @@ export class GeckoViewNavigation extends GeckoViewModule { return new Promise(resolve => { const handler = { - observe(aSubject, aTopic, aData) { + observe(aSubject, aTopic) { if ( aTopic === "geckoview-window-created" && aSubject.name === aSessionId @@ -371,7 +371,7 @@ export class GeckoViewNavigation extends GeckoViewModule { // Wait indefinitely for app to respond with a browser or null Services.tm.spinEventLoopUntil( - "GeckoViewNavigation.jsm:handleNewSession", + "GeckoViewNavigation.sys.mjs:handleNewSession", () => this.window.closed || browser !== undefined ); return browser || null; @@ -383,8 +383,7 @@ export class GeckoViewNavigation extends GeckoViewModule { aOpenWindowInfo, aWhere, aFlags, - aTriggeringPrincipal, - aCsp + aTriggeringPrincipal ) { debug`createContentWindow: uri=${aUri && aUri.spec} where=${aWhere} flags=${aFlags}`; @@ -585,7 +584,7 @@ export class GeckoViewNavigation extends GeckoViewModule { } // WebProgress event handler. - onLocationChange(aWebProgress, aRequest, aLocationURI, aFlags) { + onLocationChange(aWebProgress, aRequest, aLocationURI) { debug`onLocationChange`; let fixedURI = aLocationURI; @@ -648,6 +647,8 @@ export class GeckoViewNavigation extends GeckoViewModule { canGoForward: this.browser.canGoForward, isTopLevel: aWebProgress.isTopLevel, permissions, + hasUserGesture: + this.window.document.hasValidTransientUserGestureActivation, }; lazy.TranslationsParent.onLocationChange(this.browser); this.eventDispatcher.sendRequest(message); diff --git a/mobile/android/modules/geckoview/GeckoViewProcessHangMonitor.sys.mjs b/mobile/android/modules/geckoview/GeckoViewProcessHangMonitor.sys.mjs index 7f6f14a29e..387fda4421 100644 --- a/mobile/android/modules/geckoview/GeckoViewProcessHangMonitor.sys.mjs +++ b/mobile/android/modules/geckoview/GeckoViewProcessHangMonitor.sys.mjs @@ -65,7 +65,7 @@ export class GeckoViewProcessHangMonitor extends GeckoViewModule { } // Bundle event handler. - onEvent(aEvent, aData, aCallback) { + onEvent(aEvent, aData) { debug`onEvent: event=${aEvent}, data=${aData}`; if (this._reportIndex.has(aData.hangId)) { @@ -84,7 +84,7 @@ export class GeckoViewProcessHangMonitor extends GeckoViewModule { } // nsIObserver event handler - observe(aSubject, aTopic, aData) { + observe(aSubject, aTopic) { debug`observe(aTopic=${aTopic})`; aSubject.QueryInterface(Ci.nsIHangReport); if (!aSubject.isReportForBrowserOrChildren(this.browser.frameLoader)) { diff --git a/mobile/android/modules/geckoview/GeckoViewProgress.sys.mjs b/mobile/android/modules/geckoview/GeckoViewProgress.sys.mjs index 66aceb974c..3cad6e977a 100644 --- a/mobile/android/modules/geckoview/GeckoViewProgress.sys.mjs +++ b/mobile/android/modules/geckoview/GeckoViewProgress.sys.mjs @@ -557,7 +557,7 @@ export class GeckoViewProgress extends GeckoViewModule { } } - onEvent(aEvent, aData, aCallback) { + onEvent(aEvent, aData) { debug`onEvent: event=${aEvent}, data=${aData}`; switch (aEvent) { @@ -608,6 +608,7 @@ export class GeckoViewProgress extends GeckoViewModule { canGoBack: false, canGoForward: false, isTopLevel: true, + hasUserGesture: false, }); this.eventDispatcher.sendRequest({ type: "GeckoView:PageStop", @@ -616,7 +617,7 @@ export class GeckoViewProgress extends GeckoViewModule { } // nsIObserver event handler - observe(aSubject, aTopic, aData) { + observe(aSubject, aTopic) { debug`observe: topic=${aTopic}`; switch (aTopic) { diff --git a/mobile/android/modules/geckoview/GeckoViewPushController.sys.mjs b/mobile/android/modules/geckoview/GeckoViewPushController.sys.mjs index da2d7d04e9..07ad8cd514 100644 --- a/mobile/android/modules/geckoview/GeckoViewPushController.sys.mjs +++ b/mobile/android/modules/geckoview/GeckoViewPushController.sys.mjs @@ -27,7 +27,7 @@ function createScopeAndPrincipal(scopeAndAttrs) { } export const GeckoViewPushController = { - onEvent(aEvent, aData, aCallback) { + onEvent(aEvent, aData) { debug`onEvent ${aEvent} ${aData}`; switch (aEvent) { diff --git a/mobile/android/modules/geckoview/GeckoViewSelectionAction.sys.mjs b/mobile/android/modules/geckoview/GeckoViewSelectionAction.sys.mjs index 07498e4b00..cc3b153716 100644 --- a/mobile/android/modules/geckoview/GeckoViewSelectionAction.sys.mjs +++ b/mobile/android/modules/geckoview/GeckoViewSelectionAction.sys.mjs @@ -20,7 +20,7 @@ export class GeckoViewSelectionAction extends GeckoViewModule { } // Bundle event handler. - onEvent(aEvent, aData, aCallback) { + onEvent(aEvent, aData) { debug`onEvent: ${aEvent}`; switch (aEvent) { diff --git a/mobile/android/modules/geckoview/GeckoViewSessionStore.sys.mjs b/mobile/android/modules/geckoview/GeckoViewSessionStore.sys.mjs index 584429295e..faa5c5f280 100644 --- a/mobile/android/modules/geckoview/GeckoViewSessionStore.sys.mjs +++ b/mobile/android/modules/geckoview/GeckoViewSessionStore.sys.mjs @@ -112,7 +112,7 @@ export var GeckoViewSessionStore = { // For each <browser> element, records the SHistoryListener. _browserSHistoryListener: new WeakMap(), - observe(aSubject, aTopic, aData) { + observe(aSubject, aTopic) { debug`observe ${aTopic}`; switch (aTopic) { diff --git a/mobile/android/modules/geckoview/GeckoViewStorageController.sys.mjs b/mobile/android/modules/geckoview/GeckoViewStorageController.sys.mjs index e69ad3b973..0f4e692ba9 100644 --- a/mobile/android/modules/geckoview/GeckoViewStorageController.sys.mjs +++ b/mobile/android/modules/geckoview/GeckoViewStorageController.sys.mjs @@ -308,7 +308,7 @@ export const GeckoViewStorageController = { new Promise(resolve => { Services.clearData.deleteData(flags, resolve); - }).then(resultFlags => { + }).then(() => { aCallback.onSuccess(); }); }, @@ -321,7 +321,7 @@ export const GeckoViewStorageController = { convertFlags(aFlags), resolve ); - }).then(resultFlags => { + }).then(() => { aCallback.onSuccess(); }); }, @@ -334,7 +334,7 @@ export const GeckoViewStorageController = { convertFlags(aFlags), resolve ); - }).then(resultFlags => { + }).then(() => { aCallback.onSuccess(); }); }, diff --git a/mobile/android/modules/geckoview/GeckoViewTab.sys.mjs b/mobile/android/modules/geckoview/GeckoViewTab.sys.mjs index 53f43f153c..fe984934ec 100644 --- a/mobile/android/modules/geckoview/GeckoViewTab.sys.mjs +++ b/mobile/android/modules/geckoview/GeckoViewTab.sys.mjs @@ -116,7 +116,7 @@ export const GeckoViewTabBridge = { // need to start waiting before we send the message. const windowPromise = new Promise(resolve => { const handler = { - observe(aSubject, aTopic, aData) { + observe(aSubject, aTopic) { if ( aTopic === "geckoview-window-created" && aSubject.name === newSessionId @@ -203,7 +203,7 @@ export class GeckoViewTab extends GeckoViewModule { this.registerListener(["GeckoView:WebExtension:SetTabActive"]); } - onEvent(aEvent, aData, aCallback) { + onEvent(aEvent, aData) { debug`onEvent: event=${aEvent}, data=${aData}`; switch (aEvent) { diff --git a/mobile/android/modules/geckoview/GeckoViewTelemetry.sys.mjs b/mobile/android/modules/geckoview/GeckoViewTelemetry.sys.mjs index bb7074ced8..c5738e672c 100644 --- a/mobile/android/modules/geckoview/GeckoViewTelemetry.sys.mjs +++ b/mobile/android/modules/geckoview/GeckoViewTelemetry.sys.mjs @@ -33,12 +33,16 @@ export class GleanStopwatch { } finish() { - this._metric.stopAndAccumulate(this._timerId); - this._timerId = null; + if (this.isRunning()) { + this._metric.stopAndAccumulate(this._timerId); + this._timerId = null; + } } cancel() { - this._metric.cancel(this._timerId); - this._timerId = null; + if (this.isRunning()) { + this._metric.cancel(this._timerId); + this._timerId = null; + } } } diff --git a/mobile/android/modules/geckoview/GeckoViewTestUtils.sys.mjs b/mobile/android/modules/geckoview/GeckoViewTestUtils.sys.mjs index 6c5113cdc2..a2ca252cdd 100644 --- a/mobile/android/modules/geckoview/GeckoViewTestUtils.sys.mjs +++ b/mobile/android/modules/geckoview/GeckoViewTestUtils.sys.mjs @@ -20,7 +20,7 @@ export const GeckoViewTabUtil = { async createNewTab(url = "about:blank") { let sessionId = ""; const windowPromise = new Promise(resolve => { - const openingObserver = (subject, topic, data) => { + const openingObserver = subject => { if (subject.name === sessionId) { Services.obs.removeObserver( openingObserver, diff --git a/mobile/android/modules/geckoview/GeckoViewTranslations.sys.mjs b/mobile/android/modules/geckoview/GeckoViewTranslations.sys.mjs index 3db694a64a..7e74e7bf30 100644 --- a/mobile/android/modules/geckoview/GeckoViewTranslations.sys.mjs +++ b/mobile/android/modules/geckoview/GeckoViewTranslations.sys.mjs @@ -182,7 +182,7 @@ export const GeckoViewTranslationsSettings = { if (operation === "delete") { if (operationLevel === "all") { lazy.TranslationsParent.deleteAllLanguageFiles().then( - function (value) { + function () { aCallback.onSuccess(); }, function (error) { @@ -201,7 +201,7 @@ export const GeckoViewTranslationsSettings = { return; } lazy.TranslationsParent.deleteLanguageFiles(language).then( - function (value) { + function () { aCallback.onSuccess(); }, function (error) { @@ -216,7 +216,7 @@ export const GeckoViewTranslationsSettings = { if (operation === "download") { if (operationLevel === "all") { lazy.TranslationsParent.downloadAllFiles().then( - function (value) { + function () { aCallback.onSuccess(); }, function (error) { @@ -235,7 +235,7 @@ export const GeckoViewTranslationsSettings = { return; } lazy.TranslationsParent.downloadLanguageFiles(language).then( - function (value) { + function () { aCallback.onSuccess(); }, function (error) { diff --git a/mobile/android/modules/geckoview/GeckoViewUtils.sys.mjs b/mobile/android/modules/geckoview/GeckoViewUtils.sys.mjs index ddfb40c1a1..3fe8309b6b 100644 --- a/mobile/android/modules/geckoview/GeckoViewUtils.sys.mjs +++ b/mobile/android/modules/geckoview/GeckoViewUtils.sys.mjs @@ -25,7 +25,7 @@ class AndroidFormatter extends Log.BasicFormatter { /* * AndroidAppender - * Logs to Android logcat using AndroidLog.jsm + * Logs to Android logcat using AndroidLog.sys.mjs */ class AndroidAppender extends Log.Appender { constructor(aFormatter) { @@ -49,7 +49,7 @@ class AndroidAppender extends Log.Appender { return; } - // AndroidLog.jsm always prepends "Gecko" to the tag, so we strip any + // AndroidLog.sys.mjs always prepends "Gecko" to the tag, so we strip any // leading "Gecko" here. Also strip dots to save space. const tag = aMessage.loggerName.replace(/^Gecko|\./g, ""); const msg = this._formatter.format(aMessage); @@ -257,9 +257,7 @@ export var GeckoViewUtils = { (handlers, observer, args) => { if (!once) { Services.prefs.removeObserver(args[2], observer); - handlers.forEach(handler => - Services.prefs.addObserver(args[2], observer) - ); + handlers.forEach(() => Services.prefs.addObserver(args[2], observer)); } handlers.forEach(handler => handler.observe(...args)); } @@ -386,7 +384,7 @@ export var GeckoViewUtils = { * do_something(bar); // No log. * do_something(debug.foo = bar); // Output "foo = 42" to the log. * - * @param aTag Name of the Log.jsm logger to forward logs to. + * @param aTag Name of the Log.sys.mjs logger to forward logs to. * @param aScope Scope to add the logging functions to. */ initLogging(aTag, aScope) { diff --git a/mobile/android/modules/geckoview/GeckoViewWebExtension.sys.mjs b/mobile/android/modules/geckoview/GeckoViewWebExtension.sys.mjs index ae821a3656..97538fd6bb 100644 --- a/mobile/android/modules/geckoview/GeckoViewWebExtension.sys.mjs +++ b/mobile/android/modules/geckoview/GeckoViewWebExtension.sys.mjs @@ -158,7 +158,7 @@ class EmbedderPort { data: holder.deserialize({}), }); } - onEvent(aEvent, aData, aCallback) { + onEvent(aEvent, aData) { debug`onEvent ${aEvent} ${aData}`; switch (aEvent) { @@ -360,6 +360,23 @@ async function exportExtension(aAddon, aPermissions, aSourceURI) { updateDate = null; } + const normalizePermissions = perms => { + if (perms?.permissions) { + perms = { ...perms }; + perms.permissions = perms.permissions.filter( + perm => !perm.startsWith("internal:") + ); + } + return perms; + }; + + const optionalPermissions = aAddon.optionalPermissions?.permissions ?? []; + const optionalOrigins = aAddon.optionalPermissions?.origins ?? []; + const grantedPermissions = + normalizePermissions(await lazy.ExtensionPermissions.get(id)) ?? []; + const grantedOptionalPermissions = grantedPermissions?.permissions ?? []; + const grantedOptionalOrigins = grantedPermissions?.origins ?? []; + return { webExtensionId: id, locationURI: aSourceURI != null ? aSourceURI.spec : "", @@ -393,6 +410,10 @@ async function exportExtension(aAddon, aPermissions, aSourceURI) { temporary: temporarilyInstalled, updateDate, version, + optionalPermissions, + optionalOrigins, + grantedOptionalPermissions, + grantedOptionalOrigins, }, }; } @@ -528,7 +549,7 @@ class ExtensionPromptObserver { resolve(response.allow); } - observe(aSubject, aTopic, aData) { + observe(aSubject, aTopic) { debug`observe ${aTopic}`; switch (aTopic) { @@ -572,7 +593,7 @@ class AddonInstallObserver { }); } - observe(aSubject, aTopic, aData) { + observe(aSubject, aTopic) { debug`observe ${aTopic}`; switch (aTopic) { case "addon-install-failed": { @@ -758,7 +779,7 @@ class ExtensionProcessListener { ]); } - async onEvent(aEvent, aData, aCallback) { + async onEvent(aEvent, aData) { debug`onEvent ${aEvent} ${aData}`; switch (aEvent) { @@ -872,7 +893,7 @@ async function updatePromptHandler(aInfo) { } export var GeckoViewWebExtension = { - observe(aSubject, aTopic, aData) { + observe(aSubject, aTopic) { debug`observe ${aTopic}`; switch (aTopic) { diff --git a/mobile/android/modules/geckoview/LoadURIDelegate.sys.mjs b/mobile/android/modules/geckoview/LoadURIDelegate.sys.mjs index 5769fcafe8..fa65b8a2e2 100644 --- a/mobile/android/modules/geckoview/LoadURIDelegate.sys.mjs +++ b/mobile/android/modules/geckoview/LoadURIDelegate.sys.mjs @@ -40,7 +40,7 @@ export const LoadURIDelegate = { } ); Services.tm.spinEventLoopUntil( - "LoadURIDelegate.jsm:load", + "LoadURIDelegate.sys.mjs:load", () => aWindow.closed || handled !== undefined ); @@ -75,13 +75,13 @@ export const LoadURIDelegate = { Components.returnCode = Cr.NS_ERROR_ABORT; } }, - e => { + () => { errorPageURI = null; Components.returnCode = Cr.NS_ERROR_ABORT; } ); Services.tm.spinEventLoopUntil( - "LoadURIDelegate.jsm:handleLoadError", + "LoadURIDelegate.sys.mjs:handleLoadError", () => aWindow.closed || errorPageURI !== undefined ); diff --git a/mobile/android/modules/geckoview/Messaging.sys.mjs b/mobile/android/modules/geckoview/Messaging.sys.mjs index e67161fede..fff0b4311c 100644 --- a/mobile/android/modules/geckoview/Messaging.sys.mjs +++ b/mobile/android/modules/geckoview/Messaging.sys.mjs @@ -11,10 +11,10 @@ class ChildActorDispatcher { } // TODO: Bug 1658980 - registerListener(aListener, aEvents) { + registerListener() { throw new Error("Cannot registerListener in child actor"); } - unregisterListener(aListener, aEvents) { + unregisterListener() { throw new Error("Cannot registerListener in child actor"); } diff --git a/mobile/android/modules/geckoview/test/xpcshell/test_ChildCrashHandler.js b/mobile/android/modules/geckoview/test/xpcshell/test_ChildCrashHandler.js index 0e07937ed3..ee03e2ba4a 100644 --- a/mobile/android/modules/geckoview/test/xpcshell/test_ChildCrashHandler.js +++ b/mobile/android/modules/geckoview/test/xpcshell/test_ChildCrashHandler.js @@ -41,7 +41,7 @@ add_task(async function test_remoteType() { let listener; const crashReportPromise = new Promise(resolve => { listener = { - onEvent(aEvent, aData, aCallback) { + onEvent(aEvent, aData) { resolve([aEvent, aData]); }, }; @@ -79,7 +79,7 @@ add_task(async function test_extensions_process_crash() { let listener; const crashReportPromise = new Promise(resolve => { listener = { - onEvent(aEvent, aData, aCallback) { + onEvent(aEvent, aData) { resolve([aEvent, aData]); }, }; diff --git a/mobile/android/test_runner/src/main/java/org/mozilla/geckoview/test_runner/TestRunnerActivity.java b/mobile/android/test_runner/src/main/java/org/mozilla/geckoview/test_runner/TestRunnerActivity.java index 3930ab545c..399f9417c2 100644 --- a/mobile/android/test_runner/src/main/java/org/mozilla/geckoview/test_runner/TestRunnerActivity.java +++ b/mobile/android/test_runner/src/main/java/org/mozilla/geckoview/test_runner/TestRunnerActivity.java @@ -163,7 +163,10 @@ public class TestRunnerActivity extends Activity { new GeckoSession.NavigationDelegate() { @Override public void onLocationChange( - final GeckoSession session, final String url, final List<ContentPermission> perms) { + final GeckoSession session, + final String url, + final List<ContentPermission> perms, + final Boolean hasUserGesture) { getActionBar().setSubtitle(url); } diff --git a/mobile/ios/app.mozbuild b/mobile/ios/app.mozbuild new file mode 100644 index 0000000000..af3e729a4a --- /dev/null +++ b/mobile/ios/app.mozbuild @@ -0,0 +1,10 @@ +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +include("/toolkit/toolkit.mozbuild") + +DIRS += [ + "/mobile/ios", +] diff --git a/mobile/ios/build.mk b/mobile/ios/build.mk new file mode 100644 index 0000000000..1e0afc0a68 --- /dev/null +++ b/mobile/ios/build.mk @@ -0,0 +1,5 @@ +package: + $(MAKE) -C mobile/ios/installer + +upload: + $(MAKE) -C mobile/ios/installer upload diff --git a/mobile/ios/config/mozconfigs/ios-sim/debug b/mobile/ios/config/mozconfigs/ios-sim/debug new file mode 100644 index 0000000000..ea0501d224 --- /dev/null +++ b/mobile/ios/config/mozconfigs/ios-sim/debug @@ -0,0 +1,3 @@ +. $topsrcdir/mobile/ios/config/mozconfigs/ios-sim/opt + +ac_add_options --enable-debug diff --git a/mobile/ios/config/mozconfigs/ios-sim/opt b/mobile/ios/config/mozconfigs/ios-sim/opt new file mode 100644 index 0000000000..aeaf6aa0c3 --- /dev/null +++ b/mobile/ios/config/mozconfigs/ios-sim/opt @@ -0,0 +1,6 @@ +ac_add_options --enable-project=mobile/ios +ac_add_options --target=aarch64-apple-ios-sim +ac_add_options --enable-clang-plugin + +. "$topsrcdir/build/mozconfig.cache" +. "$topsrcdir/build/mozconfig.automation" diff --git a/mobile/ios/config/mozconfigs/ios/debug b/mobile/ios/config/mozconfigs/ios/debug new file mode 100644 index 0000000000..279ebb2053 --- /dev/null +++ b/mobile/ios/config/mozconfigs/ios/debug @@ -0,0 +1,3 @@ +. $topsrcdir/mobile/ios/config/mozconfigs/ios/opt + +ac_add_options --enable-debug diff --git a/mobile/ios/config/mozconfigs/ios/debug-searchfox b/mobile/ios/config/mozconfigs/ios/debug-searchfox new file mode 100644 index 0000000000..a027cd8921 --- /dev/null +++ b/mobile/ios/config/mozconfigs/ios/debug-searchfox @@ -0,0 +1,8 @@ +MOZ_AUTOMATION_BUILD_SYMBOLS=0 +MOZ_AUTOMATION_CHECK=0 + +. $topsrcdir/mobile/ios/config/mozconfigs/ios/opt + +ac_add_options --enable-debug + +ac_add_options --enable-mozsearch-plugin diff --git a/mobile/ios/config/mozconfigs/ios/opt b/mobile/ios/config/mozconfigs/ios/opt new file mode 100644 index 0000000000..4cde731827 --- /dev/null +++ b/mobile/ios/config/mozconfigs/ios/opt @@ -0,0 +1,5 @@ +ac_add_options --enable-project=mobile/ios +ac_add_options --enable-clang-plugin + +. "$topsrcdir/build/mozconfig.cache" +. "$topsrcdir/build/mozconfig.automation" diff --git a/mobile/ios/installer/Makefile.in b/mobile/ios/installer/Makefile.in new file mode 100644 index 0000000000..1d4c4ff321 --- /dev/null +++ b/mobile/ios/installer/Makefile.in @@ -0,0 +1,11 @@ +# 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/. + +STANDALONE_MAKEFILE := 1 + +include $(topsrcdir)/config/rules.mk + +MOZ_PKG_DUPEFLAGS = -f $(srcdir)/allowed-dupes.mn + +include $(topsrcdir)/toolkit/mozapps/installer/packager.mk diff --git a/mobile/ios/installer/allowed-dupes.mn b/mobile/ios/installer/allowed-dupes.mn new file mode 100644 index 0000000000..078bbe4e09 --- /dev/null +++ b/mobile/ios/installer/allowed-dupes.mn @@ -0,0 +1,26 @@ +# Known duplicate files +# This file is ideally removed, but some existing files will be allowed exceptions +# See bug 1303184 +# +# PLEASE DO NOT ADD MORE EXCEPTIONS TO THIS LIST +# + +# Row and column icons are duplicated +res/table-remove-column-active.gif +res/table-remove-row-active.gif +res/table-remove-column-hover.gif +res/table-remove-row-hover.gif +res/table-remove-column.gif +res/table-remove-row.gif + +res/multilocale.txt +update.locale + +# Bug 1833829 - Rolling out new search configuration. +defaults/settings/main/search-config-icons/47da97b5-600f-c450-fd15-a52bb2169c11 +defaults/settings/main/search-config-icons/fed4f021-ff3e-942a-010e-afa43fda2136 +defaults/settings/main/search-config-icons/6a83583a-f0ba-fd39-2fdb-fd2b6990ea3b +defaults/settings/main/search-config-icons/f312610a-ebfb-a106-ea92-fd643c5d3636 + +components/httpd.sys.mjs +chrome/remote/content/server/httpd.sys.mjs diff --git a/mobile/ios/moz.build b/mobile/ios/moz.build new file mode 100644 index 0000000000..2253746e12 --- /dev/null +++ b/mobile/ios/moz.build @@ -0,0 +1,10 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +CONFIGURE_SUBST_FILES += ["installer/Makefile"] + +with Files("**"): + BUG_COMPONENT = ("Core", "General") diff --git a/mobile/ios/moz.configure b/mobile/ios/moz.configure new file mode 100644 index 0000000000..b02ed1347e --- /dev/null +++ b/mobile/ios/moz.configure @@ -0,0 +1,16 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +imply_option("MOZ_PLACES", True) + + +@depends(target) +def check_target(target): + if target.os != "iOS": + die("Cannot build mobile/ios with a target other than an iOS one") + + +include("../../toolkit/moz.configure") |