Bug 1600742 - Move event listeners from WebExtension to WebExtensionController. r=snorp,esawin

Differential Revision: https://phabricator.services.mozilla.com/D57035

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Agi Sferro 2019-12-17 23:23:52 +00:00
Родитель 6c81d2a85b
Коммит f8d68e46e1
2 изменённых файлов: 98 добавлений и 107 удалений

Просмотреть файл

@ -68,29 +68,15 @@ public class WebExtension {
/* package */ interface DelegateController {
void onMessageDelegate(final String nativeApp, final MessageDelegate delegate);
void onActionDelegate(final ActionDelegate delegate);
ActionDelegate getActionDelegate();
}
private WeakReference<DelegateController> mDelegateController = new WeakReference<>(null);
private DelegateController mDelegateController = null;
/* package */ void setDelegateController(final DelegateController observer) {
mDelegateController = new WeakReference<>(observer);
if (observer != null) {
// Notify observers of already attached delegates
for (final Map.Entry<String, MessageDelegate> entry : messageDelegates.entrySet()) {
observer.onMessageDelegate(entry.getKey(), entry.getValue());
}
observer.onActionDelegate(actionDelegate);
}
/* package */ void setDelegateController(final DelegateController delegate) {
mDelegateController = delegate;
}
/**
* Delegates that handle messaging between this WebExtension and the app.
*/
/* package */ final @NonNull Map<String, MessageDelegate> messageDelegates;
/* package */ @NonNull ActionDelegate actionDelegate;
@Override
public String toString() {
return "WebExtension {" +
@ -128,7 +114,6 @@ public class WebExtension {
flags = bundle.getInt("webExtensionFlags", 0);
isBuiltIn = bundle.getBoolean("isBuiltIn", false);
isEnabled = bundle.getBoolean("isEnabled", false);
messageDelegates = new HashMap<>();
if (bundle.containsKey("metaData")) {
metaData = new MetaData(bundle.getBundle("metaData"));
} else {
@ -164,10 +149,10 @@ public class WebExtension {
public WebExtension(final @NonNull String location, final @NonNull String id,
final @WebExtensionFlags long flags,
final @NonNull WebExtensionController controller) {
setDelegateController(controller.delegateFor(this));
this.location = location;
this.id = id;
this.flags = flags;
this.messageDelegates = new HashMap<>();
// TODO:
this.isEnabled = false;
@ -244,15 +229,9 @@ public class WebExtension {
@UiThread
public void setMessageDelegate(final @Nullable MessageDelegate messageDelegate,
final @NonNull String nativeApp) {
final DelegateController observer = mDelegateController.get();
if (observer != null) {
observer.onMessageDelegate(nativeApp, messageDelegate);
if (mDelegateController != null) {
mDelegateController.onMessageDelegate(nativeApp, messageDelegate);
}
if (messageDelegate == null) {
messageDelegates.remove(nativeApp);
return;
}
messageDelegates.put(nativeApp, messageDelegate);
}
/**
@ -468,6 +447,8 @@ public class WebExtension {
/* package */ final static class Listener implements BundleEventListener {
final private HashMap<Sender, WebExtension.MessageDelegate> mMessageDelegates;
final private HashMap<String, WebExtension.ActionDelegate> mActionDelegates;
private WebExtensionController.TabDelegate mTabDelegate = null;
final private GeckoSession mSession;
final private EventDispatcher mEventDispatcher;
@ -498,6 +479,28 @@ public class WebExtension {
this.runtime = runtime;
}
public void setTabDelegate(final WebExtensionController.TabDelegate delegate) {
if (delegate != null && mTabDelegate == null) {
mEventDispatcher.registerUiThreadListener(
this,
"GeckoView:WebExtension:NewTab",
"GeckoView:WebExtension:CloseTab"
);
} else if (delegate == null && mTabDelegate != null) {
mEventDispatcher.unregisterUiThreadListener(
this,
"GeckoView:WebExtension:NewTab",
"GeckoView:WebExtension:CloseTab"
);
}
mTabDelegate = delegate;
}
public WebExtensionController.TabDelegate getTabDelegate() {
return mTabDelegate;
}
public void setActionDelegate(final WebExtension webExtension,
final WebExtension.ActionDelegate delegate) {
if (!mActionDelegateRegistered && delegate != null) {
@ -555,10 +558,30 @@ public class WebExtension {
|| "GeckoView:BrowserAction:OpenPopup".equals(event)) {
controller.handleMessage(event, message, callback, mSession);
return;
} else if ("GeckoView:WebExtension:CloseTab".equals(event)) {
controller.closeTab(message, callback, mSession);
}
// If a tab delegate is not defined on the session, try the runtime
//
// TODO: The tab delegate is special because it's only set on the
// controller and not on the session, all other delegates are set
// on both, we should unify this and have a tab delegate for each
// session too.
WebExtensionController.TabDelegate delegate = mTabDelegate;
if (delegate == null && mSession != null) {
delegate = runtime.getWebExtensionController().getTabDelegate();
}
if (delegate == null) {
callback.sendError("No delegate registered.");
return;
}
if ("GeckoView:WebExtension:CloseTab".equals(event)) {
controller.closeTab(message, callback, delegate, mSession);
return;
} else if ("GeckoView:WebExtension:NewTab".equals(event)) {
controller.newTab(message, callback, delegate);
}
}
}
@ -941,12 +964,12 @@ public class WebExtension {
@UiThread
public void click() {
if (mPopupUri != null && !mPopupUri.isEmpty()) {
if (mExtension.actionDelegate == null) {
final ActionDelegate delegate = mExtension.mDelegateController.getActionDelegate();
if (delegate == null) {
return;
}
GeckoResult<GeckoSession> popup =
mExtension.actionDelegate.onTogglePopup(mExtension, this);
GeckoResult<GeckoSession> popup = delegate.onTogglePopup(mExtension, this);
openPopup(popup);
// When popupUri is specified, the extension doesn't get a callback
@ -1143,13 +1166,10 @@ public class WebExtension {
*/
@AnyThread
public void setActionDelegate(final @Nullable ActionDelegate delegate) {
final DelegateController observer = mDelegateController.get();
if (observer != null) {
observer.onActionDelegate(delegate);
if (mDelegateController != null) {
mDelegateController.onActionDelegate(delegate);
}
actionDelegate = delegate;
final GeckoBundle bundle = new GeckoBundle(1);
bundle.putString("extensionId", id);

Просмотреть файл

@ -21,10 +21,8 @@ import java.util.Map;
public class WebExtensionController {
private final static String LOGTAG = "WebExtension";
private GeckoRuntime mRuntime;
private TabDelegate mTabDelegate;
private PromptDelegate mPromptDelegate;
private final WebExtension.Listener mListener;
private static class ExtensionStore {
final private Map<String, WebExtension> mData = new HashMap<>();
@ -66,11 +64,7 @@ public class WebExtensionController {
// Avoids exposing listeners to the API
private class Internals implements BundleEventListener,
WebExtension.Port.DisconnectDelegate,
WebExtension.DelegateController {
private boolean mMessageListenersAttached = false;
private boolean mActionListenersAttached = false;
WebExtension.Port.DisconnectDelegate {
@Override
// BundleEventListener
public void handleMessage(final String event, final GeckoBundle message,
@ -85,35 +79,35 @@ public class WebExtensionController {
// we just need to remove it from our list of ports.
mPorts.remove(port.id);
}
}
private class DelegateController implements WebExtension.DelegateController {
private WebExtension mExtension;
public DelegateController(final WebExtension extension) {
mExtension = extension;
}
@Override
// WebExtension.DelegateController
public void onMessageDelegate(final String nativeApp,
final WebExtension.MessageDelegate delegate) {
if (delegate != null && !mMessageListenersAttached) {
EventDispatcher.getInstance().registerUiThreadListener(
this,
"GeckoView:WebExtension:Message",
"GeckoView:WebExtension:PortMessage",
"GeckoView:WebExtension:Connect",
"GeckoView:WebExtension:Disconnect");
mMessageListenersAttached = true;
}
mListener.setMessageDelegate(mExtension, delegate, nativeApp);
}
@Override
// WebExtension.DelegateController
public void onActionDelegate(final WebExtension.ActionDelegate delegate) {
if (delegate != null && !mActionListenersAttached) {
EventDispatcher.getInstance().registerUiThreadListener(
this,
"GeckoView:BrowserAction:Update",
"GeckoView:BrowserAction:OpenPopup",
"GeckoView:PageAction:Update",
"GeckoView:PageAction:OpenPopup");
mActionListenersAttached = true;
}
mListener.setActionDelegate(mExtension, delegate);
}
@Override
public WebExtension.ActionDelegate getActionDelegate() {
return mListener.getActionDelegate(mExtension);
}
}
// TODO: remove once we remove GeckoRuntime#registerWebExtension
/* package */ DelegateController delegateFor(final WebExtension extension) {
return new DelegateController(extension);
}
public interface TabDelegate {
@ -155,27 +149,12 @@ public class WebExtensionController {
@UiThread
public @Nullable TabDelegate getTabDelegate() {
return mTabDelegate;
return mListener.getTabDelegate();
}
@UiThread
public void setTabDelegate(final @Nullable TabDelegate delegate) {
if (delegate == null) {
if (mTabDelegate != null) {
EventDispatcher.getInstance().unregisterUiThreadListener(
mInternals,
"GeckoView:WebExtension:NewTab"
);
}
} else {
if (mTabDelegate == null) {
EventDispatcher.getInstance().registerUiThreadListener(
mInternals,
"GeckoView:WebExtension:NewTab"
);
}
}
mTabDelegate = delegate;
mListener.setTabDelegate(delegate);
}
/**
@ -454,20 +433,17 @@ public class WebExtensionController {
}
/* package */ WebExtensionController(final GeckoRuntime runtime) {
mRuntime = runtime;
mListener = new WebExtension.Listener(runtime);
}
/* package */ void registerWebExtension(final WebExtension webExtension) {
webExtension.setDelegateController(mInternals);
webExtension.setDelegateController(new DelegateController(webExtension));
mExtensions.put(webExtension.id, webExtension);
}
/* package */ void handleMessage(final String event, final GeckoBundle message,
final EventCallback callback, final GeckoSession session) {
if ("GeckoView:WebExtension:NewTab".equals(event)) {
newTab(message, callback);
return;
} else if ("GeckoView:WebExtension:Disconnect".equals(event)) {
if ("GeckoView:WebExtension:Disconnect".equals(event)) {
disconnect(message.getLong("portId", -1), callback);
return;
} else if ("GeckoView:WebExtension:PortMessage".equals(event)) {
@ -532,6 +508,7 @@ public class WebExtensionController {
}
final WebExtension extension = new WebExtension(extensionBundle);
extension.setDelegateController(new DelegateController(extension));
if (mPromptDelegate == null) {
Log.e(LOGTAG, "Tried to install extension " + extension.id +
@ -555,14 +532,10 @@ public class WebExtensionController {
});
}
private void newTab(final GeckoBundle message, final EventCallback callback) {
if (mTabDelegate == null) {
callback.sendSuccess(null);
return;
}
/* package */ void newTab(final GeckoBundle message, final EventCallback callback,
final TabDelegate delegate) {
mExtensions.get(message.getString("extensionId")).then(extension ->
mTabDelegate.onNewTab(extension, message.getString("uri"))
delegate.onNewTab(extension, message.getString("uri"))
).accept(session -> {
if (session == null) {
callback.sendSuccess(null);
@ -573,24 +546,22 @@ public class WebExtensionController {
throw new IllegalArgumentException("Must use an unopened GeckoSession instance");
}
session.open(mRuntime);
session.open(mListener.runtime);
callback.sendSuccess(session.getId());
});
}
/* package */ void closeTab(final GeckoBundle message, final EventCallback callback, final GeckoSession session) {
if (mTabDelegate == null) {
callback.sendError(null);
return;
}
/* package */ void closeTab(final GeckoBundle message,
final EventCallback callback,
final TabDelegate delegate,
final GeckoSession session) {
mExtensions.get(message.getString("extensionId")).then(
extension -> mTabDelegate.onCloseTab(extension, session),
extension -> delegate.onCloseTab(extension, session),
// On uninstall, we close all extension pages, in that case
// the extension object may be gone already so we can't
// send it to the delegate
exception -> mTabDelegate.onCloseTab(null, session)
exception -> delegate.onCloseTab(null, session)
).accept(value -> {
if (value == AllowOrDeny.ALLOW) {
callback.sendSuccess(null);
@ -701,7 +672,7 @@ public class WebExtensionController {
if (sender.session != null) {
delegate = sender.session.getMessageDelegate(sender.webExtension, nativeApp);
} else if (sender.environmentType == WebExtension.MessageSender.ENV_TYPE_EXTENSION) {
delegate = sender.webExtension.messageDelegates.get(nativeApp);
delegate = mListener.getMessageDelegate(sender.webExtension, nativeApp);
}
if (delegate == null) {
@ -805,7 +776,7 @@ public class WebExtensionController {
private WebExtension.ActionDelegate actionDelegateFor(final WebExtension extension,
final GeckoSession session) {
if (session == null) {
return extension.actionDelegate;
return mListener.getActionDelegate(extension);
}
return session.getWebExtensionActionDelegate(extension);