From 4ef1c21f3e3ba9a523527017ac2f65ec8c3d914c Mon Sep 17 00:00:00 2001 From: Birunthan Mohanathas Date: Tue, 28 Jul 2015 06:33:46 -0700 Subject: [PATCH] Bug 1105827 - Part 3: Implement Permissions.query. r=baku --- dom/permission/Permissions.cpp | 106 +++++++++++++++++++++++++++++++-- dom/permission/Permissions.h | 8 ++- dom/webidl/Permissions.webidl | 7 ++- 3 files changed, 114 insertions(+), 7 deletions(-) diff --git a/dom/permission/Permissions.cpp b/dom/permission/Permissions.cpp index 4012aee0d3e..c7518f9983f 100644 --- a/dom/permission/Permissions.cpp +++ b/dom/permission/Permissions.cpp @@ -8,6 +8,7 @@ #include "mozilla/dom/PermissionsBinding.h" #include "mozilla/dom/Promise.h" +#include "mozilla/Services.h" #include "nsIPermissionManager.h" @@ -39,22 +40,119 @@ Permissions::WrapObject(JSContext* aCx, JS::Handle aGivenProto) return PermissionsBinding::Wrap(aCx, this, aGivenProto); } +namespace { + +PermissionState +ActionToPermissionState(uint32_t aAction) +{ + switch (aAction) { + case nsIPermissionManager::ALLOW_ACTION: + return PermissionState::Granted; + + case nsIPermissionManager::DENY_ACTION: + return PermissionState::Denied; + + default: + case nsIPermissionManager::PROMPT_ACTION: + return PermissionState::Prompt; + } +} + +nsresult +CheckPermission(const char* aName, + nsPIDOMWindow* aWindow, + PermissionState& aResult) +{ + MOZ_ASSERT(aName); + MOZ_ASSERT(aWindow); + + nsCOMPtr permMgr = services::GetPermissionManager(); + if (NS_WARN_IF(!permMgr)) { + return NS_ERROR_FAILURE; + } + + uint32_t action = nsIPermissionManager::DENY_ACTION; + nsresult rv = permMgr->TestPermissionFromWindow(aWindow, aName, &action); + if (NS_WARN_IF(NS_FAILED(rv))) { + return NS_ERROR_FAILURE; + } + + aResult = ActionToPermissionState(action); + return NS_OK; +} + +nsresult +CheckPushPermission(JSContext* aCx, + JS::Handle aPermission, + nsPIDOMWindow* aWindow, + PermissionState& aResult) +{ + PushPermissionDescriptor permission; + JS::Rooted value(aCx, JS::ObjectOrNullValue(aPermission)); + if (NS_WARN_IF(!permission.Init(aCx, value))) { + return NS_ERROR_UNEXPECTED; + } + + if (permission.mUserVisible) { + return NS_ERROR_NOT_IMPLEMENTED; + } + + return CheckPermission("push", aWindow, aResult); +} + +nsresult +CheckPermission(JSContext* aCx, + JS::Handle aPermission, + nsPIDOMWindow* aWindow, + PermissionState& aResult) +{ + PermissionDescriptor permission; + JS::Rooted value(aCx, JS::ObjectOrNullValue(aPermission)); + if (NS_WARN_IF(!permission.Init(aCx, value))) { + return NS_ERROR_UNEXPECTED; + } + + switch (permission.mName) { + case PermissionName::Geolocation: + return CheckPermission("geo", aWindow, aResult); + + case PermissionName::Notifications: + return CheckPermission("desktop-notification", aWindow, aResult); + + case PermissionName::Push: + return CheckPushPermission(aCx, aPermission, aWindow, aResult); + + case PermissionName::Midi: + default: + return NS_ERROR_NOT_IMPLEMENTED; + } +} + +} // namespace + already_AddRefed -Permissions::Query(const PermissionDescriptor& aPermission) +Permissions::Query(JSContext* aCx, + JS::Handle aPermission, + ErrorResult& aRv) { nsCOMPtr global = do_QueryInterface(mWindow); if (!global) { + aRv.Throw(NS_ERROR_UNEXPECTED); return nullptr; } - ErrorResult aRv; nsRefPtr promise = Promise::Create(global, aRv); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } - promise->MaybeReject(NS_ERROR_NOT_IMPLEMENTED); - + PermissionState state = PermissionState::Denied; + nsresult rv = CheckPermission(aCx, aPermission, mWindow, state); + if (NS_WARN_IF(NS_FAILED(rv))) { + promise->MaybeReject(rv); + } else { + promise->MaybeResolve(new PermissionStatus(mWindow, state)); + } return promise.forget(); } diff --git a/dom/permission/Permissions.h b/dom/permission/Permissions.h index 2659ec3d7e7..e57c236d72c 100644 --- a/dom/permission/Permissions.h +++ b/dom/permission/Permissions.h @@ -12,9 +12,11 @@ #include "nsWrapperCache.h" namespace mozilla { + +class ErrorResult; + namespace dom { -struct PermissionDescriptor; class Promise; class Permissions final @@ -32,7 +34,9 @@ public: JSObject* WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; - already_AddRefed Query(const PermissionDescriptor& aPermission); + already_AddRefed Query(JSContext* aCx, + JS::Handle aPermission, + ErrorResult& aRv); private: ~Permissions(); diff --git a/dom/webidl/Permissions.webidl b/dom/webidl/Permissions.webidl index a79f6867798..fa1f6d874a3 100644 --- a/dom/webidl/Permissions.webidl +++ b/dom/webidl/Permissions.webidl @@ -18,8 +18,13 @@ dictionary PermissionDescriptor { required PermissionName name; }; +dictionary PushPermissionDescriptor : PermissionDescriptor { + boolean userVisible = false; +}; + [Exposed=(Window), Pref="dom.permissions.enabled"] interface Permissions { - Promise query(PermissionDescriptor permission); + [Throws] + Promise query(object permission); };