From e349b447de931b7d17a566031298a3717cea81c8 Mon Sep 17 00:00:00 2001 From: Emily Toop Date: Mon, 11 Mar 2019 15:35:42 +0000 Subject: [PATCH] Bug 1527716 - Update GVE and Documentation to reflect proper handling of Notification permissions. r=geckoview-reviewers,snorp Differential Revision: https://phabricator.services.mozilla.com/D21947 --HG-- extra : moz-landing-system : lando --- .../org/mozilla/geckoview/GeckoSession.java | 9 ++++-- .../BasicGeckoViewPrompt.java | 13 ++++---- .../geckoview_example/GeckoViewActivity.java | 30 ++++++++++++++++++- 3 files changed, 42 insertions(+), 10 deletions(-) diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java index 891e9abe1fa8..635330ddd07e 100644 --- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java +++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java @@ -3812,6 +3812,11 @@ public class GeckoSession implements Parcelable { * and another request for the content permission (e.g. through * requestContentPermission), which is typically handled by an app-specific * permission dialog. + * + * + * When denying an Android app permission, the response is not stored by GeckoView. + * It is the responsibility of the consumer to store the response state and therefore prevent + * further requests from being presented to the user. **/ public interface PermissionDelegate { @Retention(RetentionPolicy.SOURCE) @@ -3822,13 +3827,13 @@ public class GeckoSession implements Parcelable { * Permission for using the geolocation API. * See: https://developer.mozilla.org/en-US/docs/Web/API/Geolocation */ - public static final int PERMISSION_GEOLOCATION = 0; + int PERMISSION_GEOLOCATION = 0; /** * Permission for using the notifications API. * See: https://developer.mozilla.org/en-US/docs/Web/API/notification */ - public static final int PERMISSION_DESKTOP_NOTIFICATION = 1; + int PERMISSION_DESKTOP_NOTIFICATION = 1; /** * Callback interface for notifying the result of a permission request. diff --git a/mobile/android/geckoview_example/src/main/java/org/mozilla/geckoview_example/BasicGeckoViewPrompt.java b/mobile/android/geckoview_example/src/main/java/org/mozilla/geckoview_example/BasicGeckoViewPrompt.java index 4f92a0b315be..0de427911300 100644 --- a/mobile/android/geckoview_example/src/main/java/org/mozilla/geckoview_example/BasicGeckoViewPrompt.java +++ b/mobile/android/geckoview_example/src/main/java/org/mozilla/geckoview_example/BasicGeckoViewPrompt.java @@ -809,7 +809,12 @@ final class BasicGeckoViewPrompt implements GeckoSession.PromptDelegate { } final AlertDialog.Builder builder = new AlertDialog.Builder(activity); builder.setTitle(title) - .setNegativeButton(android.R.string.cancel, /* onClickListener */ null) + .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { + @Override + public void onClick(final DialogInterface dialog, final int which) { + callback.reject(); + } + }) .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { @Override public void onClick(final DialogInterface dialog, final int which) { @@ -818,12 +823,6 @@ final class BasicGeckoViewPrompt implements GeckoSession.PromptDelegate { }); final AlertDialog dialog = builder.create(); - dialog.setOnDismissListener(new DialogInterface.OnDismissListener() { - @Override - public void onDismiss(final DialogInterface dialog) { - callback.reject(); - } - }); dialog.show(); } diff --git a/mobile/android/geckoview_example/src/main/java/org/mozilla/geckoview_example/GeckoViewActivity.java b/mobile/android/geckoview_example/src/main/java/org/mozilla/geckoview_example/GeckoViewActivity.java index 597995816082..b3e97ab30c1f 100644 --- a/mobile/android/geckoview_example/src/main/java/org/mozilla/geckoview_example/GeckoViewActivity.java +++ b/mobile/android/geckoview_example/src/main/java/org/mozilla/geckoview_example/GeckoViewActivity.java @@ -68,6 +68,8 @@ public class GeckoViewActivity extends AppCompatActivity { private boolean mEnableRemoteDebugging; private boolean mKillProcessOnDestroy; + private boolean mShowNotificationsRejected; + private LocationView mLocationView; private String mCurrentUri; private boolean mCanGoBack; @@ -580,6 +582,25 @@ public class GeckoViewActivity extends AppCompatActivity { public int androidPermissionRequestCode = 1; private Callback mCallback; + class ExampleNotificationCallback implements GeckoSession.PermissionDelegate.Callback { + private final GeckoSession.PermissionDelegate.Callback mCallback; + ExampleNotificationCallback(final GeckoSession.PermissionDelegate.Callback callback) { + mCallback = callback; + } + + @Override + public void reject() { + mShowNotificationsRejected = true; + mCallback.reject(); + } + + @Override + public void grant() { + mShowNotificationsRejected = false; + mCallback.grant(); + } + } + public void onRequestPermissionsResult(final String[] permissions, final int[] grantResults) { if (mCallback == null) { @@ -614,10 +635,17 @@ public class GeckoViewActivity extends AppCompatActivity { public void onContentPermissionRequest(final GeckoSession session, final String uri, final int type, final Callback callback) { final int resId; + Callback contentPermissionCallback = callback; if (PERMISSION_GEOLOCATION == type) { resId = R.string.request_geolocation; } else if (PERMISSION_DESKTOP_NOTIFICATION == type) { + if (mShowNotificationsRejected) { + Log.w(LOGTAG, "Desktop notifications already denied by user."); + callback.reject(); + return; + } resId = R.string.request_notification; + contentPermissionCallback = new ExampleNotificationCallback(callback); } else { Log.w(LOGTAG, "Unknown permission: " + type); callback.reject(); @@ -627,7 +655,7 @@ public class GeckoViewActivity extends AppCompatActivity { final String title = getString(resId, Uri.parse(uri).getAuthority()); final BasicGeckoViewPrompt prompt = (BasicGeckoViewPrompt) mGeckoSession.getPromptDelegate(); - prompt.onPermissionPrompt(session, title, callback); + prompt.onPermissionPrompt(session, title, contentPermissionCallback); } private String[] normalizeMediaName(final MediaSource[] sources) {