зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1614295 - Provide a way for apps to know when an extension is installed. r=snorp,ochameau,esawin
This patch adds a `onExtensionListUpdated` method to `DebuggerDelegate` which is called whenever devtools install a new extension. This method provides an opportunity for apps to refresh the list of installed extensions and sets appropriate delegates so that the new extension is correctly recognized. Differential Revision: https://phabricator.services.mozilla.com/D62333 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
6360b24e80
Коммит
b1c5704faa
|
@ -8,6 +8,7 @@ const { AddonManager } = require("resource://gre/modules/AddonManager.jsm");
|
|||
const protocol = require("devtools/shared/protocol");
|
||||
const { FileUtils } = require("resource://gre/modules/FileUtils.jsm");
|
||||
const { addonsSpec } = require("devtools/shared/specs/addon/addons");
|
||||
const { Services } = require("resource://gre/modules/Services.jsm");
|
||||
|
||||
// This actor is not used by DevTools, but is relied on externally by
|
||||
// webext-run and the Firefox VS-Code plugin. see bug #1578108
|
||||
|
@ -26,6 +27,8 @@ const AddonsActor = protocol.ActorClassWithSpec(addonsSpec, {
|
|||
throw new Error(`Could not install add-on at '${addonPath}': ${error}`);
|
||||
}
|
||||
|
||||
Services.obs.notifyObservers(null, "devtools-installed-addon", addon.id);
|
||||
|
||||
// TODO: once the add-on actor has been refactored to use
|
||||
// protocol.js, we could return it directly.
|
||||
// return new AddonTargetActor(this.conn, addon);
|
||||
|
|
|
@ -1598,6 +1598,7 @@ package org.mozilla.geckoview {
|
|||
method @UiThread @Nullable public WebExtensionController.TabDelegate getTabDelegate();
|
||||
method @NonNull @AnyThread public GeckoResult<WebExtension> install(@NonNull String);
|
||||
method @AnyThread @NonNull public GeckoResult<List<WebExtension>> list();
|
||||
method @UiThread public void setDebuggerDelegate(@NonNull WebExtensionController.DebuggerDelegate);
|
||||
method @UiThread public void setPromptDelegate(@Nullable WebExtensionController.PromptDelegate);
|
||||
method @AnyThread public void setTabActive(@NonNull GeckoSession, boolean);
|
||||
method @UiThread public void setTabDelegate(@Nullable WebExtensionController.TabDelegate);
|
||||
|
@ -1605,6 +1606,10 @@ package org.mozilla.geckoview {
|
|||
method @AnyThread @NonNull public GeckoResult<WebExtension> update(@NonNull WebExtension);
|
||||
}
|
||||
|
||||
public static interface WebExtensionController.DebuggerDelegate {
|
||||
method @UiThread default public void onExtensionListUpdated();
|
||||
}
|
||||
|
||||
public static class WebExtensionController.EnableSource {
|
||||
ctor public EnableSource();
|
||||
field public static final int APP = 2;
|
||||
|
|
|
@ -27,6 +27,7 @@ import static org.mozilla.geckoview.WebExtension.InstallException.ErrorCodes.ERR
|
|||
public class WebExtensionController {
|
||||
private final static String LOGTAG = "WebExtension";
|
||||
|
||||
private DebuggerDelegate mDebuggerDelegate;
|
||||
private PromptDelegate mPromptDelegate;
|
||||
private final WebExtension.Listener mListener;
|
||||
|
||||
|
@ -291,6 +292,23 @@ public class WebExtensionController {
|
|||
} */
|
||||
}
|
||||
|
||||
public interface DebuggerDelegate {
|
||||
/**
|
||||
* Called whenever the list of installed extensions has been modified using the debugger
|
||||
* with tools like web-ext.
|
||||
*
|
||||
* This is intended as an opportunity to refresh the list of installed extensions using
|
||||
* {@link WebExtensionController#list} and to set delegates on the new {@link WebExtension}
|
||||
* objects, e.g. using {@link WebExtension#setActionDelegate} and
|
||||
* {@link WebExtension#setMessageDelegate}.
|
||||
*
|
||||
* @see <a href="https://extensionworkshop.com/documentation/develop/getting-started-with-web-ext">
|
||||
* Getting started with web-ext</a>
|
||||
*/
|
||||
@UiThread
|
||||
default void onExtensionListUpdated() {}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the current {@link PromptDelegate} instance.
|
||||
* @see PromptDelegate
|
||||
|
@ -328,6 +346,29 @@ public class WebExtensionController {
|
|||
mPromptDelegate = delegate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link DebuggerDelegate} for this instance. This delegate will receive updates
|
||||
* about extension changes using developer tools.
|
||||
*
|
||||
* @param delegate the Delegate instance
|
||||
*/
|
||||
@UiThread
|
||||
public void setDebuggerDelegate(final @NonNull DebuggerDelegate delegate) {
|
||||
if (delegate == null && mDebuggerDelegate != null) {
|
||||
EventDispatcher.getInstance().unregisterUiThreadListener(
|
||||
mInternals,
|
||||
"GeckoView:WebExtension:DebuggerListUpdated"
|
||||
);
|
||||
} else if (delegate != null && mDebuggerDelegate == null) {
|
||||
EventDispatcher.getInstance().registerUiThreadListener(
|
||||
mInternals,
|
||||
"GeckoView:WebExtension:DebuggerListUpdated"
|
||||
);
|
||||
}
|
||||
|
||||
mDebuggerDelegate = delegate;
|
||||
}
|
||||
|
||||
private static class WebExtensionResult extends GeckoResult<WebExtension>
|
||||
implements EventCallback {
|
||||
/** These states should match gecko's AddonManager.STATE_* constants. */
|
||||
|
@ -663,6 +704,11 @@ public class WebExtensionController {
|
|||
} else if ("GeckoView:WebExtension:UpdatePrompt".equals(event)) {
|
||||
updatePrompt(bundle, callback);
|
||||
return;
|
||||
} else if ("GeckoView:WebExtension:DebuggerListUpdated".equals(event)) {
|
||||
if (mDebuggerDelegate != null) {
|
||||
mDebuggerDelegate.onExtensionListUpdated();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
final String nativeApp = bundle.getString("nativeApp");
|
||||
|
|
|
@ -20,8 +20,12 @@ exclude: true
|
|||
- ⚠️ Move [`GeckoSessionSettings.Builder#useMultiprocess`] to
|
||||
[`GeckoRuntimeSettings.Builder#useMultiprocess`][75.1]. Multiprocess state is
|
||||
no longer determined per session.
|
||||
- Added [`DebuggerDelegate#onExtensionListUpdated`][75.2] to notify that a temporary
|
||||
extension has been installed by the debugger.
|
||||
([bug 1614295]({{bugzilla}}1614295))
|
||||
|
||||
[75.1]: {{javadoc_uri}}/GeckoRuntimeSettings.Builder.html#useMultiprocess-boolean-
|
||||
[75.2]: {{javadoc_uri}}/WebExtensionController.DebuggerDelegate.html#onExtensionListUpdated--
|
||||
|
||||
## v74
|
||||
- Added [`WebExtensionController.enable`][74.1] and [`disable`][74.2] to
|
||||
|
|
|
@ -94,12 +94,14 @@ interface BrowserActionDelegate {
|
|||
|
||||
class WebExtensionManager implements WebExtension.ActionDelegate,
|
||||
WebExtensionController.PromptDelegate,
|
||||
WebExtensionController.DebuggerDelegate,
|
||||
TabSessionManager.TabObserver {
|
||||
public WebExtension extension;
|
||||
|
||||
private LruCache<WebExtension.Icon, Bitmap> mBitmapCache = new LruCache<>(5);
|
||||
private GeckoRuntime mRuntime;
|
||||
private WebExtension.Action mDefaultAction;
|
||||
private TabSessionManager mTabManager;
|
||||
|
||||
private WeakReference<BrowserActionDelegate> mActionDelegate;
|
||||
|
||||
|
@ -109,6 +111,11 @@ class WebExtensionManager implements WebExtension.ActionDelegate,
|
|||
return GeckoResult.fromValue(AllowOrDeny.ALLOW);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onExtensionListUpdated() {
|
||||
refreshExtensionList();
|
||||
}
|
||||
|
||||
// We only support either one browserAction or one pageAction
|
||||
private void onAction(final WebExtension extension, final GeckoSession session,
|
||||
final WebExtension.Action action) {
|
||||
|
@ -244,12 +251,12 @@ class WebExtensionManager implements WebExtension.ActionDelegate,
|
|||
}
|
||||
}
|
||||
|
||||
public GeckoResult<Void> unregisterExtension(TabSessionManager tabManager) {
|
||||
public GeckoResult<Void> unregisterExtension() {
|
||||
if (extension == null) {
|
||||
return GeckoResult.fromValue(null);
|
||||
}
|
||||
|
||||
tabManager.unregisterWebExtension();
|
||||
mTabManager.unregisterWebExtension();
|
||||
|
||||
return mRuntime.getWebExtensionController().uninstall(extension).accept((unused) -> {
|
||||
extension = null;
|
||||
|
@ -258,22 +265,24 @@ class WebExtensionManager implements WebExtension.ActionDelegate,
|
|||
});
|
||||
}
|
||||
|
||||
public void registerExtension(WebExtension extension,
|
||||
TabSessionManager tabManager) {
|
||||
public void registerExtension(WebExtension extension) {
|
||||
extension.setActionDelegate(this);
|
||||
tabManager.setWebExtensionActionDelegate(extension, this);
|
||||
mTabManager.setWebExtensionActionDelegate(extension, this);
|
||||
this.extension = extension;
|
||||
}
|
||||
|
||||
private void refreshExtensionList() {
|
||||
mRuntime.getWebExtensionController()
|
||||
.list().accept(extensions -> {
|
||||
for (final WebExtension extension : extensions) {
|
||||
registerExtension(extension);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public WebExtensionManager(GeckoRuntime runtime,
|
||||
TabSessionManager tabManager) {
|
||||
runtime.getWebExtensionController()
|
||||
.list().accept(extensions -> {
|
||||
for (final WebExtension extension : extensions) {
|
||||
registerExtension(extension, tabManager);
|
||||
}
|
||||
});
|
||||
|
||||
mTabManager = tabManager;
|
||||
mRuntime = runtime;
|
||||
}
|
||||
}
|
||||
|
@ -415,6 +424,8 @@ public class GeckoViewActivity
|
|||
sExtensionManager = new WebExtensionManager(sGeckoRuntime, mTabSessionManager);
|
||||
mTabSessionManager.setTabObserver(sExtensionManager);
|
||||
|
||||
sGeckoRuntime.getWebExtensionController().setDebuggerDelegate(sExtensionManager);
|
||||
|
||||
// `getSystemService` call requires API level 23
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.M) {
|
||||
sGeckoRuntime.setWebNotificationDelegate(new WebNotificationDelegate() {
|
||||
|
@ -797,12 +808,12 @@ public class GeckoViewActivity
|
|||
setPopupVisibility(false);
|
||||
mPopupView = null;
|
||||
mPopupSession = null;
|
||||
sExtensionManager.unregisterExtension(mTabSessionManager).then(unused -> {
|
||||
sExtensionManager.unregisterExtension().then(unused -> {
|
||||
final WebExtensionController controller = sGeckoRuntime.getWebExtensionController();
|
||||
controller.setPromptDelegate(sExtensionManager);
|
||||
return controller.install(uri);
|
||||
}).accept(extension ->
|
||||
sExtensionManager.registerExtension(extension, mTabSessionManager));
|
||||
sExtensionManager.registerExtension(extension));
|
||||
});
|
||||
builder.setNegativeButton(R.string.cancel, (dialog, which) -> {
|
||||
// Nothing to do
|
||||
|
|
|
@ -438,6 +438,19 @@ async function updatePromptHandler(aInfo) {
|
|||
}
|
||||
|
||||
var GeckoViewWebExtension = {
|
||||
observe(aSubject, aTopic, aData) {
|
||||
debug`observe ${aTopic}`;
|
||||
|
||||
switch (aTopic) {
|
||||
case "devtools-installed-addon": {
|
||||
EventDispatcher.instance.sendRequest({
|
||||
type: "GeckoView:WebExtension:DebuggerListUpdated",
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
async registerWebExtension(aId, aUri, allowContentMessaging, aCallback) {
|
||||
const params = {
|
||||
id: aId,
|
||||
|
@ -836,3 +849,4 @@ GeckoViewWebExtension.extensionScopes = new Map();
|
|||
GeckoViewWebExtension.browserActions = new WeakMap();
|
||||
// WeakMap[Extension -> PageAction]
|
||||
GeckoViewWebExtension.pageActions = new WeakMap();
|
||||
Services.obs.addObserver(GeckoViewWebExtension, "devtools-installed-addon");
|
||||
|
|
Загрузка…
Ссылка в новой задаче