Bug 1259148 - Notify content when the notification permission pop-up is dismissed by the user. f?past,MattN
MozReview-Commit-ID: 8CcgQcJDeie
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -2630,16 +2630,26 @@ ContentPermissionPrompt.prototype = {
callback: function() {},
},
];
}
var options = {
learnMoreURL:
Services.urlFormatter.formatURLPref("app.support.baseURL") + "push",
+ eventCallback(type) {
+ if (type == "dismissed") {
+ // Hide the doorhanger. Unlike other permission doorhangers, the
+ // user can't click the icon in the address bar to restore the
+ // doorhanger. Instead, the site must request permission again.
+ // See bug 1259148 for context.
+ this.remove();
+ aRequest.cancel();
+ }
+ },
};
this._showPrompt(aRequest, message, "desktop-notification", actions,
"web-notifications",
"web-notifications-notification-icon", options);
},
_promptPointerLock: function CPP_promtPointerLock(aRequest, autoAllow) {
--- a/dom/notification/Notification.cpp
+++ b/dom/notification/Notification.cpp
@@ -609,17 +609,21 @@ NotificationPermissionRequest::GetElemen
NS_ENSURE_ARG_POINTER(aElement);
*aElement = nullptr;
return NS_OK;
}
NS_IMETHODIMP
NotificationPermissionRequest::Cancel()
{
- mPermission = NotificationPermission::Denied;
+ // `Cancel` is called if the user denied permission or dismissed the
+ // permission request. To distinguish between the two, we set the
+ // permission to "default" and query the permission manager on the
+ // main thread.
+ mPermission = NotificationPermission::Default;
return DispatchResolvePromise();
}
NS_IMETHODIMP
NotificationPermissionRequest::Allow(JS::HandleValue aChoices)
{
MOZ_ASSERT(aChoices.isUndefined());
@@ -644,16 +648,21 @@ NotificationPermissionRequest::DispatchR
&NotificationPermissionRequest::ResolvePromise);
return NS_DispatchToMainThread(resolveRunnable);
}
nsresult
NotificationPermissionRequest::ResolvePromise()
{
nsresult rv = NS_OK;
+ if (mPermission == NotificationPermission::Default) {
+ // This will still be "default" if the user dismissed the doorhanger,
+ // or "denied" otherwise.
+ mPermission = Notification::TestPermission(mPrincipal);
+ }
if (mCallback) {
ErrorResult error;
mCallback->Call(mPermission, error);
rv = error.StealNSResult();
}
Telemetry::Accumulate(
Telemetry::WEB_NOTIFICATION_REQUEST_PERMISSION_CALLBACK, !!mCallback);
mPromise->MaybeResolve(mPermission);
@@ -1942,20 +1951,31 @@ Notification::GetPermissionInternal(nsIP
if (Preferences::GetBool("notification.prompt.testing", false)) {
if (Preferences::GetBool("notification.prompt.testing.allow", true)) {
return NotificationPermission::Granted;
} else {
return NotificationPermission::Denied;
}
}
+ return TestPermission(aPrincipal);
+}
+
+/* static */ NotificationPermission
+Notification::TestPermission(nsIPrincipal* aPrincipal)
+{
+ AssertIsOnMainThread();
+
uint32_t permission = nsIPermissionManager::UNKNOWN_ACTION;
nsCOMPtr<nsIPermissionManager> permissionManager =
services::GetPermissionManager();
+ if (!permissionManager) {
+ return NotificationPermission::Default;
+ }
permissionManager->TestExactPermissionFromPrincipal(aPrincipal,
"desktop-notification",
&permission);
// Convert the result to one of the enum types.
switch (permission) {
case nsIPermissionManager::ALLOW_ACTION:
--- a/dom/notification/Notification.h
+++ b/dom/notification/Notification.h
@@ -312,16 +312,18 @@ public:
void ReleaseObject();
static NotificationPermission GetPermission(nsIGlobalObject* aGlobal,
ErrorResult& aRv);
static NotificationPermission GetPermissionInternal(nsIPrincipal* aPrincipal,
ErrorResult& rv);
+ static NotificationPermission TestPermission(nsIPrincipal* aPrincipal);
+
bool DispatchClickEvent();
bool DispatchNotificationClickEvent();
static nsresult RemovePermission(nsIPrincipal* aPrincipal);
static nsresult OpenSettings(nsIPrincipal* aPrincipal);
protected:
Notification(nsIGlobalObject* aGlobal, const nsAString& aID,
const nsAString& aTitle, const nsAString& aBody,
--- a/dom/push/Push.js
+++ b/dom/push/Push.js
@@ -156,18 +156,21 @@ Push.prototype = {
types: typeArray,
principal: this._principal,
QueryInterface: XPCOMUtils.generateQI([Ci.nsIContentPermissionRequest]),
allow: function() {
let histogram = Services.telemetry.getHistogramById("PUSH_API_PERMISSION_GRANTED");
histogram.add();
allowCallback();
},
- cancel: function() {
- let histogram = Services.telemetry.getHistogramById("PUSH_API_PERMISSION_DENIED");
+ cancel: () => {
+ let histogramName =
+ this._testPermission() == Ci.nsIPermissionManager.DENY_ACTION ?
+ "PUSH_API_PERMISSION_DENIED" : "PUSH_API_PERMISSION_DISMISSED";
+ let histogram = Services.telemetry.getHistogramById(histogramName);
histogram.add();
cancelCallback();
},
window: this._window,
};
let histogram = Services.telemetry.getHistogramById("PUSH_API_PERMISSION_REQUESTED");
histogram.add(1);
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -10088,16 +10088,22 @@
"description": "Count of number of times the PermissionManager explicitly prompted user for Push Notifications permission"
},
"PUSH_API_PERMISSION_DENIED": {
"alert_emails": ["push@mozilla.com"],
"expires_in_version": "55",
"kind": "count",
"description": "User explicitly denied Push Notifications permission"
},
+ "PUSH_API_PERMISSION_DISMISSED": {
+ "alert_emails": ["push@mozilla.com"],
+ "expires_in_version": "55",
+ "kind": "count",
+ "description": "User dismissed request for Push Notifications permission"
+ },
"PUSH_API_PERMISSION_GRANTED": {
"alert_emails": ["push@mozilla.com"],
"expires_in_version": "55",
"kind": "count",
"description": "User explicitly granted Push Notifications permission"
},
"PUSH_API_SUBSCRIBE_ATTEMPT": {
"alert_emails": ["push@mozilla.com"],
--- a/toolkit/components/telemetry/histogram-whitelists.json
+++ b/toolkit/components/telemetry/histogram-whitelists.json
@@ -2163,16 +2163,17 @@
"PREDICTOR_WAIT_TIME",
"PROCESS_CRASH_SUBMIT_ATTEMPT",
"PROCESS_CRASH_SUBMIT_SUCCESS",
"PUSH_API_NOTIFICATION_RECEIVED",
"PUSH_API_NOTIFICATION_RECEIVED_BUT_DID_NOT_NOTIFY",
"PUSH_API_NOTIFY",
"PUSH_API_NOTIFY_REGISTRATION_LOST",
"PUSH_API_PERMISSION_DENIED",
+ "PUSH_API_PERMISSION_DISMISSED",
"PUSH_API_PERMISSION_GRANTED",
"PUSH_API_PERMISSION_REQUESTED",
"PUSH_API_QUOTA_EXPIRATION_TIME",
"PUSH_API_QUOTA_RESET_TO",
"PUSH_API_SUBSCRIBE_ATTEMPT",
"PUSH_API_SUBSCRIBE_FAILED",
"PUSH_API_SUBSCRIBE_HTTP2_TIME",
"PUSH_API_SUBSCRIBE_SUCCEEDED",