summaryrefslogtreecommitdiffstats
path: root/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebPushController.java
diff options
context:
space:
mode:
Diffstat (limited to 'mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebPushController.java')
-rw-r--r--mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebPushController.java165
1 files changed, 165 insertions, 0 deletions
diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebPushController.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebPushController.java
new file mode 100644
index 0000000000..f5ea153bfe
--- /dev/null
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/WebPushController.java
@@ -0,0 +1,165 @@
+/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
+ * vim: ts=4 sw=4 expandtab:
+ * 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.geckoview;
+
+import android.util.Log;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.annotation.UiThread;
+import org.mozilla.gecko.EventDispatcher;
+import org.mozilla.gecko.GeckoThread;
+import org.mozilla.gecko.util.BundleEventListener;
+import org.mozilla.gecko.util.EventCallback;
+import org.mozilla.gecko.util.GeckoBundle;
+import org.mozilla.gecko.util.ThreadUtils;
+
+public class WebPushController {
+ private static final String LOGTAG = "WebPushController";
+
+ private WebPushDelegate mDelegate;
+ private BundleEventListener mEventListener;
+
+ /* package */ WebPushController() {
+ mEventListener = new EventListener();
+ EventDispatcher.getInstance()
+ .registerUiThreadListener(
+ mEventListener,
+ "GeckoView:PushSubscribe",
+ "GeckoView:PushUnsubscribe",
+ "GeckoView:PushGetSubscription");
+ }
+
+ /**
+ * Sets the {@link WebPushDelegate} for this instance.
+ *
+ * @param delegate The {@link WebPushDelegate} instance.
+ */
+ @UiThread
+ public void setDelegate(final @Nullable WebPushDelegate delegate) {
+ ThreadUtils.assertOnUiThread();
+ mDelegate = delegate;
+ }
+
+ /**
+ * Gets the {@link WebPushDelegate} for this instance.
+ *
+ * @return delegate The {@link WebPushDelegate} instance.
+ */
+ @UiThread
+ @Nullable
+ public WebPushDelegate getDelegate() {
+ ThreadUtils.assertOnUiThread();
+ return mDelegate;
+ }
+
+ /**
+ * Send a push event for a given subscription.
+ *
+ * @param scope The Service Worker scope associated with this subscription.
+ */
+ @UiThread
+ public void onPushEvent(final @NonNull String scope) {
+ ThreadUtils.assertOnUiThread();
+ onPushEvent(scope, null);
+ }
+
+ /**
+ * Send a push event with a payload for a given subscription.
+ *
+ * @param scope The Service Worker scope associated with this subscription.
+ * @param data The unencrypted payload.
+ */
+ @UiThread
+ public void onPushEvent(final @NonNull String scope, final @Nullable byte[] data) {
+ ThreadUtils.assertOnUiThread();
+
+ GeckoThread.waitForState(GeckoThread.State.JNI_READY)
+ .accept(
+ val -> {
+ final GeckoBundle msg = new GeckoBundle(2);
+ msg.putString("scope", scope);
+ msg.putString("data", Base64Utils.encode(data));
+ EventDispatcher.getInstance().dispatch("GeckoView:PushEvent", msg);
+ },
+ e -> Log.e(LOGTAG, "Unable to deliver Web Push message", e));
+ }
+
+ /**
+ * Notify that a given subscription has changed. This is normally a signal to the content that it
+ * needs to re-subscribe.
+ *
+ * @param scope The Service Worker scope associated with this subscription.
+ */
+ @UiThread
+ public void onSubscriptionChanged(final @NonNull String scope) {
+ ThreadUtils.assertOnUiThread();
+
+ final GeckoBundle msg = new GeckoBundle(1);
+ msg.putString("scope", scope);
+ EventDispatcher.getInstance().dispatch("GeckoView:PushSubscriptionChanged", msg);
+ }
+
+ private class EventListener implements BundleEventListener {
+
+ @Override
+ public void handleMessage(
+ final String event, final GeckoBundle message, final EventCallback callback) {
+ if (mDelegate == null) {
+ callback.sendError("Not allowed");
+ return;
+ }
+
+ switch (event) {
+ case "GeckoView:PushSubscribe":
+ {
+ byte[] appServerKey = null;
+ if (message.containsKey("appServerKey")) {
+ appServerKey = Base64Utils.decode(message.getString("appServerKey"));
+ }
+
+ final GeckoResult<WebPushSubscription> result =
+ mDelegate.onSubscribe(message.getString("scope"), appServerKey);
+
+ if (result == null) {
+ callback.sendSuccess(null);
+ return;
+ }
+
+ result.accept(
+ subscription ->
+ callback.sendSuccess(subscription != null ? subscription.toBundle() : null),
+ error -> callback.sendSuccess(null));
+ break;
+ }
+ case "GeckoView:PushUnsubscribe":
+ {
+ final GeckoResult<Void> result = mDelegate.onUnsubscribe(message.getString("scope"));
+ if (result == null) {
+ callback.sendSuccess(null);
+ return;
+ }
+
+ callback.resolveTo(result.map(val -> null));
+ break;
+ }
+ case "GeckoView:PushGetSubscription":
+ {
+ final GeckoResult<WebPushSubscription> result =
+ mDelegate.onGetSubscription(message.getString("scope"));
+ if (result == null) {
+ callback.sendSuccess(null);
+ return;
+ }
+
+ callback.resolveTo(
+ result.map(subscription -> subscription != null ? subscription.toBundle() : null));
+ break;
+ }
+ }
+ }
+ }
+}