Bug 1685614 - Use GeckoResult in EventDispatcher. r=owlish,snorp

This patch adds `queryString`, `queryBoolean`, `queryVoid` and `queryBundle` to
`EventDispatcher` in place of `dispatch(type, message, callback)`.

These `query*` methods returns a `GeckoResult` which can be manipulated using
`GeckoResult.map`.

Differential Revision: https://phabricator.services.mozilla.com/D96951
This commit is contained in:
Agi Sferro 2021-01-07 22:24:46 +00:00
Родитель 88f85b7b64
Коммит ea5931e9fd
8 изменённых файлов: 289 добавлений и 296 удалений

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

@ -1072,7 +1072,7 @@ class WebExtensionTest : BaseSessionTest() {
: WebExtension.SessionTabDelegate {
override fun onCloseTab(source: WebExtension?,
session: GeckoSession): GeckoResult<AllowOrDeny> {
assertEquals(extension, source)
assertEquals(extension.id, source!!.id)
assertEquals(expectedSession, session)
result.complete(null)
return GeckoResult.ALLOW

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

@ -15,6 +15,7 @@ import org.mozilla.gecko.util.EventCallback;
import org.mozilla.gecko.util.GeckoBundle;
import org.mozilla.gecko.util.ThreadUtils;
import org.mozilla.geckoview.BuildConfig;
import org.mozilla.geckoview.GeckoResult;
import android.os.Handler;
import androidx.annotation.AnyThread;
@ -221,6 +222,129 @@ public final class EventDispatcher extends JNIObject {
dispatch(type, message, /* callback */ null);
}
private abstract class CallbackResult<T> extends GeckoResult<T>
implements EventCallback {
@Override
public void sendError(final Object response) {
completeExceptionally(new QueryException(response));
}
}
public class QueryException extends Exception {
public final Object data;
public QueryException(final Object data) {
this.data = data;
}
}
/**
* Query event to any registered Bundle listeners (non-Gecko thread listeners).
*
* The returned GeckoResult completes when the event handler returns.
*
* @param type Event type
*/
public GeckoResult<Void> queryVoid(final String type) {
return queryVoid(type, null);
}
/**
* Query event to any registered Bundle listeners (non-Gecko thread listeners).
*
* The returned GeckoResult completes when the event handler returns.
*
* @param type Event type
* @param message GeckoBundle message
*/
public GeckoResult<Void> queryVoid(final String type, final GeckoBundle message) {
return query(type, message);
}
/**
* Query event to any registered Bundle listeners (non-Gecko thread listeners).
*
* The returned GeckoResult completes with the given boolean value returned by the handler.
*
* @param type Event type
*/
public GeckoResult<Boolean> queryBoolean(final String type) {
return queryBoolean(type, null);
}
/**
* Query event to any registered Bundle listeners (non-Gecko thread listeners).
*
* The returned GeckoResult completes with the given boolean value returned by the handler.
*
* @param type Event type
* @param message GeckoBundle message
*/
public GeckoResult<Boolean> queryBoolean(final String type, final GeckoBundle message) {
return query(type, message);
}
/**
* Query event to any registered Bundle listeners (non-Gecko thread listeners).
*
* The returned GeckoResult completes with the given String value returned by the handler.
*
* @param type Event type
*/
public GeckoResult<String> queryString(final String type) {
return queryString(type, null);
}
/**
* Query event to any registered Bundle listeners (non-Gecko thread listeners).
*
* The returned GeckoResult completes with the given String value returned by the handler.
*
* @param type Event type
* @param message GeckoBundle message
*/
public GeckoResult<String> queryString(final String type, final GeckoBundle message) {
return query(type, message);
}
/**
* Query event to any registered Bundle listeners (non-Gecko thread listeners).
*
* The returned GeckoResult completes with the given {@link GeckoBundle} value
* returned by the handler.
*
* @param type Event type
*/
public GeckoResult<GeckoBundle> queryBundle(final String type) {
return queryBundle(type, null);
}
/**
* Query event to any registered Bundle listeners (non-Gecko thread listeners).
*
* The returned GeckoResult completes with the given {@link GeckoBundle} value
* returned by the handler.
*
* @param type Event type
* @param message GeckoBundle message
*/
public GeckoResult<GeckoBundle> queryBundle(final String type, final GeckoBundle message) {
return query(type, message);
}
private <T> GeckoResult<T> query(final String type, final GeckoBundle message) {
final CallbackResult<T> result = new CallbackResult<T>() {
@Override
@SuppressWarnings("unchecked") // Not a lot we can do about this :(
public void sendSuccess(final Object response) {
complete((T) response);
}
};
dispatch(type, message, result);
return result;
}
/**
* Flushes pending messages of given types.
*
@ -259,8 +383,8 @@ public final class EventDispatcher extends JNIObject {
* @param callback Optional object for callbacks from events.
*/
@AnyThread
public void dispatch(final String type, final GeckoBundle message,
final EventCallback callback) {
private void dispatch(final String type, final GeckoBundle message,
final EventCallback callback) {
final boolean isGeckoReady;
synchronized (this) {
isGeckoReady = isReadyForDispatchingToGecko();

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

@ -132,16 +132,27 @@ public class ContentBlockingController {
*/
@UiThread
public @NonNull GeckoResult<Boolean> checkException(final @NonNull GeckoSession session) {
final CallbackResult<Boolean> result = new CallbackResult<Boolean>() {
@Override
public void sendSuccess(final Object value) {
complete((Boolean) value);
}
};
final GeckoBundle msg = new GeckoBundle(1);
msg.putString("sessionId", session.getId());
EventDispatcher.getInstance().dispatch("ContentBlocking:CheckException", msg, result);
return result;
return EventDispatcher.getInstance()
.queryBoolean("ContentBlocking:CheckException", msg);
}
private List<ContentBlockingException> exceptionListFromBundle(final GeckoBundle value) {
final String[] principals = value.getStringArray("principals");
final String[] uris = value.getStringArray("uris");
if (principals == null || uris == null) {
throw new RuntimeException("Received invalid content blocking exception list");
}
final ArrayList<ContentBlockingException> res = new ArrayList<>(principals.length);
for (int i = 0; i < principals.length; i++) {
res.add(new ContentBlockingException(principals[i], uris[i]));
}
return Collections.unmodifiableList(res);
}
/**
@ -152,28 +163,9 @@ public class ContentBlockingController {
*/
@UiThread
public @NonNull GeckoResult<List<ContentBlockingException>> saveExceptionList() {
final CallbackResult<List<ContentBlockingException>> result = new CallbackResult<List<ContentBlockingException>>() {
@Override
public void sendSuccess(final Object value) {
final String[] principals = ((GeckoBundle) value).getStringArray("principals");
final String[] uris = ((GeckoBundle) value).getStringArray("uris");
if (principals == null || uris == null) {
completeExceptionally(new RuntimeException("Received invalid content blocking exception list"));
return;
}
final ArrayList<ContentBlockingException> res = new ArrayList<ContentBlockingException>(principals.length);
for (int i = 0; i < principals.length; i++) {
res.add(new ContentBlockingException(principals[i], uris[i]));
}
complete(Collections.unmodifiableList(res));
}
};
EventDispatcher.getInstance().dispatch("ContentBlocking:SaveList", null, result);
return result;
return EventDispatcher.getInstance()
.queryBundle("ContentBlocking:SaveList")
.map(this::exceptionListFromBundle);
}
/**
@ -401,6 +393,15 @@ public class ContentBlockingController {
}
}
private List<LogEntry> logFromBundle(final GeckoBundle value) {
final GeckoBundle[] bundles = value.getBundleArray("log");
final ArrayList<LogEntry> logArray = new ArrayList<>(bundles.length);
for (GeckoBundle b : bundles) {
logArray.add(new LogEntry(b));
}
return Collections.unmodifiableList(logArray);
}
/**
* Get a log of all content blocking information for the site currently loaded by the
* supplied {@link GeckoSession}.
@ -411,18 +412,8 @@ public class ContentBlockingController {
*/
@UiThread
public @NonNull GeckoResult<List<LogEntry>> getLog(final @NonNull GeckoSession session) {
final CallbackResult<List<LogEntry>> result = new CallbackResult<List<LogEntry>>() {
@Override
public void sendSuccess(final Object value) {
final GeckoBundle[] bundles = ((GeckoBundle) value).getBundleArray("log");
final ArrayList<LogEntry> logArray = new ArrayList<LogEntry>(bundles.length);
for (GeckoBundle b : bundles) {
logArray.add(new LogEntry(b));
}
complete(Collections.unmodifiableList(logArray));
}
};
session.getEventDispatcher().dispatch("ContentBlocking:RequestLog", null, result);
return result;
return session.getEventDispatcher()
.queryBundle("ContentBlocking:RequestLog")
.map(this::logFromBundle);
}
}

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

@ -953,14 +953,7 @@ public class GeckoSession {
*/
@AnyThread
public @NonNull GeckoResult<String> getUserAgent() {
final CallbackResult<String> result = new CallbackResult<String>() {
@Override
public void sendSuccess(final Object value) {
complete((String) value);
}
};
mEventDispatcher.dispatch("GeckoView:GetUserAgent", null, result);
return result;
return mEventDispatcher.queryString("GeckoView:GetUserAgent");
}
/**

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

@ -85,14 +85,8 @@ public final class SessionFinder {
bundle.putString("searchString", searchString);
addFlagsToBundle(flags, bundle);
final CallbackResult<FinderResult> result = new CallbackResult<FinderResult>() {
@Override
public void sendSuccess(final Object response) {
complete(new FinderResult((GeckoBundle) response));
}
};
mDispatcher.dispatch("GeckoView:FindInPage", bundle, result);
return result;
return mDispatcher.queryBundle("GeckoView:FindInPage", bundle)
.map(response -> new FinderResult(response));
}
/**

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

@ -112,20 +112,11 @@ public final class StorageController {
@AnyThread
public @NonNull GeckoResult<Void> clearData(
final @StorageControllerClearFlags long flags) {
final CallbackResult<Void> result = new CallbackResult<Void>() {
@Override
public void sendSuccess(final Object response) {
complete(null);
}
};
final GeckoBundle bundle = new GeckoBundle(1);
bundle.putLong("flags", flags);
EventDispatcher.getInstance().dispatch(
"GeckoView:ClearData", bundle, result);
return result;
return EventDispatcher.getInstance()
.queryVoid("GeckoView:ClearData", bundle);
}
/**
@ -146,21 +137,12 @@ public final class StorageController {
public @NonNull GeckoResult<Void> clearDataFromHost(
final @NonNull String host,
final @StorageControllerClearFlags long flags) {
final CallbackResult<Void> result = new CallbackResult<Void>() {
@Override
public void sendSuccess(final Object response) {
complete(null);
}
};
final GeckoBundle bundle = new GeckoBundle(2);
bundle.putString("host", host);
bundle.putLong("flags", flags);
EventDispatcher.getInstance().dispatch(
"GeckoView:ClearHostData", bundle, result);
return result;
return EventDispatcher.getInstance()
.queryVoid("GeckoView:ClearHostData", bundle);
}
/**

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

@ -1216,6 +1216,13 @@ public class WebExtension {
}
}
/* package */ static WebExtension fromBundle(final GeckoBundle bundle) {
if (bundle == null) {
return null;
}
return new WebExtension(bundle.getBundle("extension"));
}
/**
* Represents either a Browser Action or a Page Action from the
* WebExtension API.
@ -1604,6 +1611,33 @@ public class WebExtension {
protected ErrorCodes() {}
}
/** These states should match gecko's AddonManager.STATE_* constants. */
private static class StateCodes {
public static final int STATE_POSTPONED = 7;
public static final int STATE_CANCELED = 12;
}
/* package */ static Throwable fromQueryException(final Throwable exception) {
final EventDispatcher.QueryException queryException =
(EventDispatcher.QueryException) exception;
final Object response = queryException.data;
if (response instanceof GeckoBundle
&& ((GeckoBundle) response).containsKey("installError")) {
final GeckoBundle bundle = (GeckoBundle) response;
int errorCode = bundle.getInt("installError");
final int installState = bundle.getInt("state");
if (errorCode == 0 && installState ==
StateCodes.STATE_CANCELED) {
errorCode = ErrorCodes.ERROR_USER_CANCELED;
} else if (errorCode == 0 && installState == StateCodes.STATE_POSTPONED) {
errorCode = ErrorCodes.ERROR_POSTPONED;
}
return new WebExtension.InstallException(errorCode);
} else {
return new Exception(response.toString());
}
}
@Retention(RetentionPolicy.SOURCE)
@IntDef(value = {
ErrorCodes.ERROR_NETWORK_FAILURE,

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

@ -26,9 +26,6 @@ import java.util.Map;
import java.util.Objects;
import java.util.UUID;
import static org.mozilla.geckoview.WebExtension.InstallException.ErrorCodes.ERROR_POSTPONED;
import static org.mozilla.geckoview.WebExtension.InstallException.ErrorCodes.ERROR_USER_CANCELED;
public class WebExtensionController {
private final static String LOGTAG = "WebExtension";
@ -74,23 +71,23 @@ public class WebExtensionController {
public GeckoResult<WebExtension> get(final String id) {
final WebExtension extension = mData.get(id);
if (extension == null) {
final WebExtensionResult result = new WebExtensionResult("extension");
final GeckoBundle bundle = new GeckoBundle(1);
bundle.putString("extensionId", id);
EventDispatcher.getInstance().dispatch("GeckoView:WebExtension:Get",
bundle, result);
return result.then(ext -> {
mData.put(ext.id, ext);
mObserver.onNewExtension(ext);
return GeckoResult.fromValue(ext);
});
if (extension != null) {
return GeckoResult.fromValue(extension);
}
return GeckoResult.fromValue(extension);
final GeckoBundle bundle = new GeckoBundle(1);
bundle.putString("extensionId", id);
final GeckoResult<WebExtension> pending = EventDispatcher.getInstance()
.queryBundle("GeckoView:WebExtension:Get", bundle)
.map(WebExtension::fromBundle)
.map(ext -> {
mData.put(ext.id, ext);
mObserver.onNewExtension(ext);
return ext;
});
return pending;
}
public void setObserver(final Observer observer) {
@ -359,107 +356,21 @@ public class WebExtensionController {
mDebuggerDelegate = delegate;
}
private static class WebExtensionResult extends GeckoResult<WebExtension>
implements EventCallback {
/** These states should match gecko's AddonManager.STATE_* constants. */
private static class StateCodes {
public static final int STATE_POSTPONED = 7;
public static final int STATE_CANCELED = 12;
}
private final String mFieldName;
public WebExtensionResult(final String fieldName) {
mFieldName = fieldName;
}
@Override
public void sendSuccess(final Object response) {
if (response == null) {
complete(null);
return;
}
final GeckoBundle bundle = (GeckoBundle) response;
complete(new WebExtension(bundle.getBundle(mFieldName)));
}
@Override
public void sendError(final Object response) {
if (response instanceof GeckoBundle
&& ((GeckoBundle) response).containsKey("installError")) {
final GeckoBundle bundle = (GeckoBundle) response;
int errorCode = bundle.getInt("installError");
final int installState = bundle.getInt("state");
if (errorCode == 0 && installState == StateCodes.STATE_CANCELED) {
errorCode = ERROR_USER_CANCELED;
} else if (errorCode == 0 && installState == StateCodes.STATE_POSTPONED) {
errorCode = ERROR_POSTPONED;
}
completeExceptionally(new WebExtension.InstallException(errorCode));
} else {
completeExceptionally(new Exception(response.toString()));
}
}
}
private static class WebExtensionInstallResult extends WebExtensionResult {
private static class InstallCanceller implements GeckoResult.CancellationDelegate {
private static class CancelResult extends GeckoResult<Boolean>
implements EventCallback {
@Override
public void sendSuccess(final Object response) {
final boolean result = ((GeckoBundle) response).getBoolean("cancelled");
complete(result);
}
@Override
public void sendError(final Object response) {
completeExceptionally(new Exception(response.toString()));
}
}
private final String mInstallId;
private boolean mCancelled;
public InstallCanceller(@NonNull final String aInstallId) {
mInstallId = aInstallId;
mCancelled = false;
}
@Override
public GeckoResult<Boolean> cancel() {
CancelResult result = new CancelResult();
final GeckoBundle bundle = new GeckoBundle(1);
bundle.putString("installId", mInstallId);
EventDispatcher.getInstance().dispatch("GeckoView:WebExtension:CancelInstall",
bundle, result);
return result.then(wasCancelled -> {
mCancelled = wasCancelled;
return GeckoResult.fromValue(wasCancelled);
});
}
}
/* package */ final @NonNull String installId;
private final InstallCanceller mInstallCanceller;
public WebExtensionInstallResult() {
super("extension");
private static class InstallCanceller implements GeckoResult.CancellationDelegate {
public final String installId;
public InstallCanceller() {
installId = UUID.randomUUID().toString();
mInstallCanceller = new InstallCanceller(installId);
setCancellationDelegate(mInstallCanceller);
}
@Override
public void sendError(final Object response) {
if (!mInstallCanceller.mCancelled) {
super.sendError(response);
}
public GeckoResult<Boolean> cancel() {
final GeckoBundle bundle = new GeckoBundle(1);
bundle.putString("installId", installId);
return EventDispatcher.getInstance()
.queryBundle("GeckoView:WebExtension:CancelInstall", bundle)
.map(response -> response.getBoolean("cancelled"));
}
}
@ -501,16 +412,18 @@ public class WebExtensionController {
@NonNull
@AnyThread
public GeckoResult<WebExtension> install(final @NonNull String uri) {
WebExtensionInstallResult result = new WebExtensionInstallResult();
final InstallCanceller canceller = new InstallCanceller();
final GeckoBundle bundle = new GeckoBundle(2);
bundle.putString("locationUri", uri);
bundle.putString("installId", result.installId);
EventDispatcher.getInstance().dispatch("GeckoView:WebExtension:Install",
bundle, result);
return result.then(extension -> {
registerWebExtension(extension);
return GeckoResult.fromValue(extension);
});
bundle.putString("installId", canceller.installId);
final GeckoResult<WebExtension> result = EventDispatcher.getInstance()
.queryBundle("GeckoView:WebExtension:Install", bundle)
.map(WebExtension::fromBundle,
WebExtension.InstallException::fromQueryException)
.map(this::registerWebExtension);
result.setCancellationDelegate(canceller);
return result;
}
/**
@ -526,20 +439,14 @@ public class WebExtensionController {
public GeckoResult<WebExtension> setAllowedInPrivateBrowsing(
final @NonNull WebExtension extension,
final boolean allowed) {
final WebExtensionController.WebExtensionResult result =
new WebExtensionController.WebExtensionResult("extension");
final GeckoBundle bundle = new GeckoBundle(2);
bundle.putString("extensionId", extension.id);
bundle.putBoolean("allowed", allowed);
EventDispatcher.getInstance().dispatch("GeckoView:WebExtension:SetPBAllowed",
bundle, result);
return result.then(newExtension -> {
registerWebExtension(newExtension);
return GeckoResult.fromValue(newExtension);
});
return EventDispatcher.getInstance()
.queryBundle("GeckoView:WebExtension:SetPBAllowed", bundle)
.map(WebExtension::fromBundle)
.map(this::registerWebExtension);
}
/**
@ -567,15 +474,14 @@ public class WebExtensionController {
@NonNull
@AnyThread
public GeckoResult<WebExtension> installBuiltIn(final @NonNull String uri) {
WebExtensionInstallResult result = new WebExtensionInstallResult();
final GeckoBundle bundle = new GeckoBundle(1);
bundle.putString("locationUri", uri);
EventDispatcher.getInstance().dispatch("GeckoView:WebExtension:InstallBuiltIn",
bundle, result);
return result.then(extension -> {
registerWebExtension(extension);
return GeckoResult.fromValue(extension);
});
return EventDispatcher.getInstance()
.queryBundle("GeckoView:WebExtension:InstallBuiltIn", bundle)
.map(WebExtension::fromBundle,
WebExtension.InstallException::fromQueryException)
.map(this::registerWebExtension);
}
/**
@ -604,16 +510,15 @@ public class WebExtensionController {
@AnyThread
public GeckoResult<WebExtension> ensureBuiltIn(final @NonNull String uri,
final @Nullable String id) {
WebExtensionInstallResult result = new WebExtensionInstallResult();
final GeckoBundle bundle = new GeckoBundle(2);
bundle.putString("locationUri", uri);
bundle.putString("webExtensionId", id);
EventDispatcher.getInstance().dispatch("GeckoView:WebExtension:EnsureBuiltIn",
bundle, result);
return result.then(extension -> {
registerWebExtension(extension);
return GeckoResult.fromValue(extension);
});
return EventDispatcher.getInstance()
.queryBundle("GeckoView:WebExtension:EnsureBuiltIn", bundle)
.map(WebExtension::fromBundle,
WebExtension.InstallException::fromQueryException)
.map(this::registerWebExtension);
}
/**
@ -629,23 +534,12 @@ public class WebExtensionController {
@NonNull
@AnyThread
public GeckoResult<Void> uninstall(final @NonNull WebExtension extension) {
final CallbackResult<Void> result = new CallbackResult<Void>() {
@Override
public void sendSuccess(final Object response) {
complete(null);
}
};
final GeckoBundle bundle = new GeckoBundle(1);
bundle.putString("webExtensionId", extension.id);
EventDispatcher.getInstance().dispatch("GeckoView:WebExtension:Uninstall",
bundle, result);
return result.then(success -> {
unregisterWebExtension(extension);
return GeckoResult.fromValue(success);
});
return EventDispatcher.getInstance()
.queryBundle("GeckoView:WebExtension:Uninstall", bundle)
.accept(result -> unregisterWebExtension(extension));
}
@Retention(RetentionPolicy.SOURCE)
@ -686,19 +580,14 @@ public class WebExtensionController {
@NonNull
public GeckoResult<WebExtension> enable(final @NonNull WebExtension extension,
final @EnableSources int source) {
final WebExtensionResult result = new WebExtensionResult("extension");
final GeckoBundle bundle = new GeckoBundle(2);
bundle.putString("webExtensionId", extension.id);
bundle.putString("source", EnableSource.toString(source));
EventDispatcher.getInstance().dispatch("GeckoView:WebExtension:Enable",
bundle, result);
return result.then(newExtension -> {
registerWebExtension(newExtension);
return GeckoResult.fromValue(newExtension);
});
return EventDispatcher.getInstance()
.queryBundle("GeckoView:WebExtension:Enable", bundle)
.map(WebExtension::fromBundle)
.map(this::registerWebExtension);
}
/**
@ -714,19 +603,26 @@ public class WebExtensionController {
@NonNull
public GeckoResult<WebExtension> disable(final @NonNull WebExtension extension,
final @EnableSources int source) {
final WebExtensionResult result = new WebExtensionResult("extension");
final GeckoBundle bundle = new GeckoBundle(2);
bundle.putString("webExtensionId", extension.id);
bundle.putString("source", EnableSource.toString(source));
EventDispatcher.getInstance().dispatch("GeckoView:WebExtension:Disable",
bundle, result);
return EventDispatcher.getInstance()
.queryBundle("GeckoView:WebExtension:Disable", bundle)
.map(WebExtension::fromBundle)
.map(this::registerWebExtension);
}
return result.then(newExtension -> {
registerWebExtension(newExtension);
return GeckoResult.fromValue(newExtension);
});
private List<WebExtension> listFromBundle(final GeckoBundle response) {
final GeckoBundle[] bundles = response.getBundleArray("extensions");
final List<WebExtension> list = new ArrayList<>(bundles.length);
for (GeckoBundle bundle : bundles) {
final WebExtension extension = new WebExtension(bundle);
list.add(registerWebExtension(extension));
}
return list;
}
/**
@ -740,27 +636,9 @@ public class WebExtensionController {
@AnyThread
@NonNull
public GeckoResult<List<WebExtension>> list() {
final CallbackResult<List<WebExtension>> result = new CallbackResult<List<WebExtension>>() {
@Override
public void sendSuccess(final Object response) {
final GeckoBundle[] bundles = ((GeckoBundle) response)
.getBundleArray("extensions");
final List<WebExtension> list = new ArrayList<>(bundles.length);
for (GeckoBundle bundle : bundles) {
final WebExtension extension = new WebExtension(bundle);
registerWebExtension(extension);
list.add(extension);
}
complete(list);
}
};
EventDispatcher.getInstance().dispatch("GeckoView:WebExtension:List",
null, result);
return result;
return EventDispatcher.getInstance()
.queryBundle("GeckoView:WebExtension:List")
.map(this::listFromBundle);
}
/**
@ -788,20 +666,14 @@ public class WebExtensionController {
@AnyThread
@NonNull
public GeckoResult<WebExtension> update(final @NonNull WebExtension extension) {
final WebExtensionResult result = new WebExtensionResult("extension");
final GeckoBundle bundle = new GeckoBundle(1);
bundle.putString("webExtensionId", extension.id);
EventDispatcher.getInstance().dispatch("GeckoView:WebExtension:Update",
bundle, result);
return result.then(newExtension -> {
if (newExtension != null) {
registerWebExtension(newExtension);
}
return GeckoResult.fromValue(newExtension);
});
return EventDispatcher.getInstance()
.queryBundle("GeckoView:WebExtension:Update", bundle)
.map(WebExtension::fromBundle,
WebExtension.InstallException::fromQueryException)
.map(this::registerWebExtension);
}
/* package */ WebExtensionController(final GeckoRuntime runtime) {
@ -814,9 +686,12 @@ public class WebExtensionController {
mDownloads = new HashMap<>();
}
/* package */ void registerWebExtension(final WebExtension webExtension) {
webExtension.setDelegateController(new DelegateController(webExtension));
mExtensions.update(webExtension.id, webExtension);
/* package */ WebExtension registerWebExtension(final WebExtension webExtension) {
if (webExtension != null) {
webExtension.setDelegateController(new DelegateController(webExtension));
mExtensions.update(webExtension.id, webExtension);
}
return webExtension;
}
/* package */ void handleMessage(final String event, final GeckoBundle bundle,