зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1619766 - [1.2] Add WebExtension openOptionsPage support. r=agi,geckoview-reviewers,robwu
Differential Revision: https://phabricator.services.mozilla.com/D77901
This commit is contained in:
Родитель
d02396bd67
Коммит
60b2d3d9e9
|
@ -1,5 +1,17 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
"use strict";
|
||||
|
||||
const { XPCOMUtils } = ChromeUtils.import(
|
||||
"resource://gre/modules/XPCOMUtils.jsm"
|
||||
);
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetters(this, {
|
||||
mobileWindowTracker: "resource://gre/modules/GeckoViewWebExtension.jsm",
|
||||
});
|
||||
|
||||
// This function is pretty tightly tied to Extension.jsm.
|
||||
// Its job is to fill in the |tab| property of the sender.
|
||||
const getSender = (extension, target, sender) => {
|
||||
|
@ -37,9 +49,35 @@ extensions.on("page-shutdown", (type, context) => {
|
|||
});
|
||||
/* eslint-enable mozilla/balanced-listeners */
|
||||
|
||||
global.openOptionsPage = extension => {
|
||||
// TODO: Bug 1619766
|
||||
return Promise.reject({ message: "Not implemented yet." });
|
||||
global.openOptionsPage = async extension => {
|
||||
const { options_ui } = extension.manifest;
|
||||
const extensionId = extension.id;
|
||||
|
||||
if (options_ui.open_in_tab) {
|
||||
// Delegate new tab creation and open the options page in the new tab.
|
||||
const tab = await GeckoViewTabBridge.createNewTab({
|
||||
extensionId,
|
||||
createProperties: {
|
||||
url: options_ui.page,
|
||||
active: true,
|
||||
},
|
||||
});
|
||||
|
||||
const { browser } = tab;
|
||||
const flags = Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
|
||||
|
||||
browser.loadURI(options_ui.page, {
|
||||
flags,
|
||||
triggeringPrincipal: extension.principal,
|
||||
});
|
||||
|
||||
const newWindow = browser.ownerGlobal;
|
||||
mobileWindowTracker.setTabActive(newWindow, true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Delegate option page handling to the app.
|
||||
return GeckoViewTabBridge.openOptionsPage(extensionId);
|
||||
};
|
||||
|
||||
extensions.registerModules({
|
||||
|
|
|
@ -1635,6 +1635,7 @@ package org.mozilla.geckoview {
|
|||
|
||||
public static interface WebExtension.TabDelegate {
|
||||
method @UiThread @Nullable default public GeckoResult<GeckoSession> onNewTab(@NonNull WebExtension, @NonNull WebExtension.CreateTabDetails);
|
||||
method @UiThread default public void onOpenOptionsPage(@NonNull WebExtension);
|
||||
}
|
||||
|
||||
public static class WebExtension.UpdateTabDetails {
|
||||
|
|
|
@ -630,6 +630,18 @@ public class WebExtension {
|
|||
@NonNull CreateTabDetails createDetails) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when runtime.openOptionsPage is invoked with
|
||||
* options_ui.open_in_tab = false.
|
||||
* In this case, GeckoView delegates options page handling to the app.
|
||||
* With options_ui.open_in_tab = true, {@link #onNewTab} is called
|
||||
* instead.
|
||||
*
|
||||
* @param source An instance of {@link WebExtension}.
|
||||
*/
|
||||
@UiThread
|
||||
default void onOpenOptionsPage(@NonNull WebExtension source) {}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -842,7 +854,8 @@ public class WebExtension {
|
|||
this,
|
||||
"GeckoView:WebExtension:NewTab",
|
||||
"GeckoView:WebExtension:UpdateTab",
|
||||
"GeckoView:WebExtension:CloseTab"
|
||||
"GeckoView:WebExtension:CloseTab",
|
||||
"GeckoView:WebExtension:OpenOptionsPage"
|
||||
);
|
||||
mTabDelegateRegistered = true;
|
||||
}
|
||||
|
@ -874,7 +887,8 @@ public class WebExtension {
|
|||
this,
|
||||
"GeckoView:WebExtension:NewTab",
|
||||
"GeckoView:WebExtension:UpdateTab",
|
||||
"GeckoView:WebExtension:CloseTab"
|
||||
"GeckoView:WebExtension:CloseTab",
|
||||
"GeckoView:WebExtension:OpenOptionsPage"
|
||||
);
|
||||
mTabDelegateRegistered = true;
|
||||
}
|
||||
|
@ -901,7 +915,8 @@ public class WebExtension {
|
|||
this,
|
||||
"GeckoView:WebExtension:NewTab",
|
||||
"GeckoView:WebExtension:UpdateTab",
|
||||
"GeckoView:WebExtension:CloseTab"
|
||||
"GeckoView:WebExtension:CloseTab",
|
||||
"GeckoView:WebExtension:OpenOptionsPage"
|
||||
);
|
||||
mTabDelegateRegistered = true;
|
||||
}
|
||||
|
|
|
@ -832,6 +832,8 @@ public class WebExtensionController {
|
|||
final EventCallback callback, final GeckoSession session) {
|
||||
final Message message = new Message(event, bundle, callback, session);
|
||||
|
||||
Log.d(LOGTAG, "handleMessage " + event);
|
||||
|
||||
if ("GeckoView:WebExtension:Disconnect".equals(event)) {
|
||||
disconnect(bundle.getLong("portId", -1), callback);
|
||||
return;
|
||||
|
@ -881,6 +883,9 @@ public class WebExtensionController {
|
|||
} else if ("GeckoView:PageAction:OpenPopup".equals(event)) {
|
||||
openPopup(message, extension, WebExtension.Action.TYPE_PAGE_ACTION);
|
||||
return;
|
||||
} else if ("GeckoView:WebExtension:OpenOptionsPage".equals(event)) {
|
||||
openOptionsPage(message, extension);
|
||||
return;
|
||||
}
|
||||
|
||||
final String nativeApp = bundle.getString("nativeApp");
|
||||
|
@ -986,6 +991,22 @@ public class WebExtensionController {
|
|||
});
|
||||
}
|
||||
|
||||
/* package */ void openOptionsPage(
|
||||
final Message message,
|
||||
final WebExtension extension) {
|
||||
final GeckoBundle bundle = message.bundle;
|
||||
final WebExtension.TabDelegate delegate =
|
||||
mListener.getTabDelegate(extension);
|
||||
|
||||
if (delegate != null) {
|
||||
delegate.onOpenOptionsPage(extension);
|
||||
} else {
|
||||
// TODO: Save as pending?
|
||||
}
|
||||
|
||||
message.callback.sendSuccess(null);
|
||||
}
|
||||
|
||||
/* package */ void newTab(final Message message, final WebExtension extension) {
|
||||
newTab(message, null, extension);
|
||||
}
|
||||
|
|
|
@ -13,6 +13,13 @@ exclude: true
|
|||
|
||||
⚠️ breaking change and deprecation notices
|
||||
|
||||
## v79
|
||||
- Added `runtime.openOptionsPage` support. For `options_ui.open_in_new_tab` ==
|
||||
`false`, [`TabDelegate.onOpenOptionsPage`][79.1] is called.
|
||||
([bug 1618058]({{bugzilla}}1619766))
|
||||
|
||||
[79.1]: {{javadoc_uri}}/WebExtension.TabDelegate.html#onOpenOptionsPage-org.mozilla.geckoview.WebExtension-
|
||||
|
||||
## v78
|
||||
- Added [`WebExtensionController.installBuiltIn`][78.1] that allows installing an
|
||||
extension that is bundled with the APK. This method is meant as a replacement
|
||||
|
@ -712,4 +719,4 @@ exclude: true
|
|||
[65.24]: {{javadoc_uri}}/CrashReporter.html#sendCrashReport-android.content.Context-android.os.Bundle-java.lang.String-
|
||||
[65.25]: {{javadoc_uri}}/GeckoResult.html
|
||||
|
||||
[api-version]: f334c3c72b512156da2d96b2d2e7bbf4392c0b0e
|
||||
[api-version]: c75d02b7653f49b0d301d95a50f6d559dca1c48c
|
||||
|
|
|
@ -45,7 +45,7 @@ const GeckoViewTabBridge = {
|
|||
/**
|
||||
* Converts windowId to tabId as in GeckoView every browser window has exactly one tab.
|
||||
*
|
||||
* @param {windowId} number outerWindowId
|
||||
* @param {number} windowId outerWindowId
|
||||
*
|
||||
* @returns {number} tabId
|
||||
*/
|
||||
|
@ -56,7 +56,7 @@ const GeckoViewTabBridge = {
|
|||
/**
|
||||
* Converts tabId to windowId.
|
||||
*
|
||||
* @param {windowId} number
|
||||
* @param {number} tabId
|
||||
*
|
||||
* @returns {number}
|
||||
* outerWindowId of browser window to which the tab belongs.
|
||||
|
@ -65,14 +65,32 @@ const GeckoViewTabBridge = {
|
|||
return tabId - TAB_ID_BASE;
|
||||
},
|
||||
|
||||
/**
|
||||
* Delegates openOptionsPage handling to the app.
|
||||
*
|
||||
* @param {number} extensionId
|
||||
* The ID of the extension requesting the options menu.
|
||||
*
|
||||
* @returns {Promise<Void>}
|
||||
* A promise resolved after successful handling.
|
||||
*/
|
||||
async openOptionsPage(extensionId) {
|
||||
debug`openOptionsPage for extensionId ${extensionId}`;
|
||||
|
||||
return EventDispatcher.instance.sendRequestForResult({
|
||||
type: "GeckoView:WebExtension:OpenOptionsPage",
|
||||
extensionId,
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Request the GeckoView App to create a new tab (GeckoSession).
|
||||
*
|
||||
* @param {object} options
|
||||
* @param {string} options.url The url to load in the newly created tab
|
||||
* @param {nsIPrincipal} options.triggeringPrincipal
|
||||
* @param {boolean} [options.disallowInheritPrincipal]
|
||||
* @param {string} options.extensionId
|
||||
* The ID of the extension that requested a new tab.
|
||||
* @param {object} options.createProperties
|
||||
* The properties for the new tab, see tabs.create reference for details.
|
||||
*
|
||||
* @returns {Promise<Tab>}
|
||||
* A promise resolved to the newly created tab.
|
||||
|
@ -80,6 +98,8 @@ const GeckoViewTabBridge = {
|
|||
* Throws an error if the GeckoView app doesn't support tabs.create or fails to handle the request.
|
||||
*/
|
||||
async createNewTab({ extensionId, createProperties } = {}) {
|
||||
debug`createNewTab`;
|
||||
|
||||
const sessionId = await EventDispatcher.instance.sendRequestForResult({
|
||||
type: "GeckoView:WebExtension:NewTab",
|
||||
extensionId,
|
||||
|
|
Загрузка…
Ссылка в новой задаче