diff --git a/dom/base/DOMException.cpp b/dom/base/DOMException.cpp index 8c7b480805fb..d9af6d6034c0 100644 --- a/dom/base/DOMException.cpp +++ b/dom/base/DOMException.cpp @@ -87,6 +87,9 @@ enum DOM4ErrorTypeCodeMap { BtAuthFailureError = 0, BtRmtDevDownError = 0, BtAuthRejectedError = 0, + + /* Push API errors */ + PermissionDeniedError = 0, }; #define DOM4_MSG_DEF(name, message, nsresult) {(nsresult), name, #name, message}, diff --git a/dom/base/domerr.msg b/dom/base/domerr.msg index bf6e5b03793e..5c8a63d87ae3 100644 --- a/dom/base/domerr.msg +++ b/dom/base/domerr.msg @@ -151,5 +151,11 @@ DOM4_MSG_DEF(InvalidStateError, "A mutation operation was attempted on a file st DOM4_MSG_DEF(AbortError, "A request was aborted, for example through a call to FileHandle.abort.", NS_ERROR_DOM_FILEHANDLE_ABORT_ERR) DOM4_MSG_DEF(QuotaExceededError, "The current file handle exceeded its quota limitations.", NS_ERROR_DOM_FILEHANDLE_QUOTA_ERR) +/* Push API errors. */ +DOM4_MSG_DEF(InvalidStateError, "Invalid service worker registration.", NS_ERROR_DOM_PUSH_INVALID_REGISTRATION_ERR) +DOM4_MSG_DEF(PermissionDeniedError, "User denied permission to use the Push API.", NS_ERROR_DOM_PUSH_DENIED_ERR) +DOM4_MSG_DEF(AbortError, "Error retrieving push subscription.", NS_ERROR_DOM_PUSH_ABORT_ERR) +DOM4_MSG_DEF(NetworkError, "Push service unreachable.", NS_ERROR_DOM_PUSH_SERVICE_UNREACHABLE) + DOM_MSG_DEF(NS_ERROR_DOM_JS_EXCEPTION, "A callback threw an exception") DOM_MSG_DEF(NS_ERROR_DOM_DOMEXCEPTION, "A DOMException was thrown") diff --git a/dom/push/Push.js b/dom/push/Push.js index d1e1f3e5a0df..d85611e1805b 100644 --- a/dom/push/Push.js +++ b/dom/push/Push.js @@ -68,9 +68,12 @@ Push.prototype = { debug("askPermission"); return this.createPromise((resolve, reject) => { - function permissionDenied() { - reject("PermissionDeniedError"); - } + let permissionDenied = () => { + reject(new this._window.DOMException( + "User denied permission to use the Push API", + "PermissionDeniedError" + )); + }; let permission = Ci.nsIPermissionManager.UNKNOWN_ACTION; try { @@ -190,7 +193,10 @@ PushEndpointCallback.prototype = { onPushEndpoint: function(ok, endpoint, keyLen, key) { let {pushManager} = this; if (!Components.isSuccessCode(ok)) { - this.reject("AbortError"); + this.reject(new pushManager._window.DOMException( + "Error retrieving push subscription", + "AbortError" + )); return; } diff --git a/dom/push/PushManager.cpp b/dom/push/PushManager.cpp index 5fdbc3707af9..5a4044b0cdf7 100644 --- a/dom/push/PushManager.cpp +++ b/dom/push/PushManager.cpp @@ -426,12 +426,13 @@ public: do_CreateInstance("@mozilla.org/push/PushClient;1"); if (!client) { callback->OnUnsubscribe(NS_ERROR_FAILURE, false); + return NS_OK; } nsCOMPtr principal = mProxy->GetWorkerPrivate()->GetPrincipal(); if (NS_WARN_IF(NS_FAILED(client->Unsubscribe(mScope, principal, callback)))) { callback->OnUnsubscribe(NS_ERROR_FAILURE, false); - return NS_ERROR_FAILURE; + return NS_OK; } return NS_OK; } @@ -521,7 +522,7 @@ public: promise->MaybeResolve(sub); } } else { - promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR); + promise->MaybeReject(NS_ERROR_DOM_PUSH_ABORT_ERR); } mProxy->CleanUp(aCx); @@ -647,7 +648,7 @@ public: if (NS_WARN_IF(NS_FAILED(rv))) { callback->OnPushEndpoint(NS_ERROR_FAILURE, EmptyString(), 0, nullptr); - return rv; + return NS_OK; } return NS_OK; @@ -677,7 +678,7 @@ WorkerPushManager::PerformSubscriptionAction(SubscriptionAction aAction, ErrorRe RefPtr proxy = PromiseWorkerProxy::Create(worker, p); if (!proxy) { - p->MaybeReject(NS_ERROR_DOM_ABORT_ERR); + p->MaybeReject(NS_ERROR_DOM_PUSH_ABORT_ERR); return p.forget(); } diff --git a/dom/push/test/test_permissions.html b/dom/push/test/test_permissions.html index 9ae76f55e396..508978f69c9d 100644 --- a/dom/push/test/test_permissions.html +++ b/dom/push/test/test_permissions.html @@ -49,7 +49,8 @@ http://creativecommons.org/licenses/publicdomain/ yield registration.pushManager.subscribe(); ok(false, "subscribe() should fail because no permission for push"); } catch (error) { - ok(true, "subscribe() could not register for push notification"); + ok(error instanceof DOMException, "Wrong exception type"); + is(error.name, "PermissionDeniedError", "Wrong exception name"); } }); diff --git a/xpcom/base/ErrorList.h b/xpcom/base/ErrorList.h index a46c06ddfd66..9ae973fde0ab 100644 --- a/xpcom/base/ErrorList.h +++ b/xpcom/base/ErrorList.h @@ -926,6 +926,16 @@ ERROR(NS_ERROR_DOM_ANIM_NO_TARGET_ERR, FAILURE(2)), #undef MODULE + /* ======================================================================= */ + /* 40: NS_ERROR_MODULE_DOM_PUSH */ + /* ======================================================================= */ +#define MODULE NS_ERROR_MODULE_DOM_PUSH + ERROR(NS_ERROR_DOM_PUSH_INVALID_REGISTRATION_ERR, FAILURE(1)), + ERROR(NS_ERROR_DOM_PUSH_DENIED_ERR, FAILURE(2)), + ERROR(NS_ERROR_DOM_PUSH_ABORT_ERR, FAILURE(3)), + ERROR(NS_ERROR_DOM_PUSH_SERVICE_UNREACHABLE, FAILURE(4)), +#undef MODULE + /* ======================================================================= */ /* 51: NS_ERROR_MODULE_GENERAL */ /* ======================================================================= */ diff --git a/xpcom/base/nsError.h b/xpcom/base/nsError.h index 7fccef1f8d8b..cc8f47d0b832 100644 --- a/xpcom/base/nsError.h +++ b/xpcom/base/nsError.h @@ -77,6 +77,7 @@ #define NS_ERROR_MODULE_DOM_BLUETOOTH 37 #define NS_ERROR_MODULE_SIGNED_APP 38 #define NS_ERROR_MODULE_DOM_ANIM 39 +#define NS_ERROR_MODULE_DOM_PUSH 40 /* NS_ERROR_MODULE_GENERAL should be used by modules that do not * care if return code values overlap. Callers of methods that