Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : #include "mozilla/dom/Permissions.h"
8 :
9 : #include "mozilla/dom/ContentChild.h"
10 : #include "mozilla/dom/PermissionsBinding.h"
11 : #include "mozilla/dom/Promise.h"
12 : #include "mozilla/Services.h"
13 : #include "nsIPermissionManager.h"
14 : #include "PermissionUtils.h"
15 :
16 : namespace mozilla {
17 : namespace dom {
18 :
19 0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Permissions)
20 0 : NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
21 0 : NS_INTERFACE_MAP_ENTRY(nsISupports)
22 0 : NS_INTERFACE_MAP_END
23 :
24 0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(Permissions)
25 0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(Permissions)
26 :
27 0 : NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Permissions, mWindow)
28 :
29 0 : Permissions::Permissions(nsPIDOMWindowInner* aWindow)
30 0 : : mWindow(aWindow)
31 : {
32 0 : }
33 :
34 0 : Permissions::~Permissions()
35 : {
36 0 : }
37 :
38 : JSObject*
39 0 : Permissions::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
40 : {
41 0 : return PermissionsBinding::Wrap(aCx, this, aGivenProto);
42 : }
43 :
44 : namespace {
45 :
46 : already_AddRefed<PermissionStatus>
47 0 : CreatePermissionStatus(JSContext* aCx,
48 : JS::Handle<JSObject*> aPermission,
49 : nsPIDOMWindowInner* aWindow,
50 : ErrorResult& aRv)
51 : {
52 0 : PermissionDescriptor permission;
53 0 : JS::Rooted<JS::Value> value(aCx, JS::ObjectOrNullValue(aPermission));
54 0 : if (NS_WARN_IF(!permission.Init(aCx, value))) {
55 0 : aRv.NoteJSContextException(aCx);
56 0 : return nullptr;
57 : }
58 :
59 0 : switch (permission.mName) {
60 : case PermissionName::Geolocation:
61 : case PermissionName::Notifications:
62 : case PermissionName::Push:
63 : case PermissionName::Persistent_storage:
64 0 : return PermissionStatus::Create(aWindow, permission.mName, aRv);
65 :
66 : default:
67 0 : MOZ_ASSERT_UNREACHABLE("Unhandled type");
68 : aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
69 : return nullptr;
70 : }
71 : }
72 :
73 : } // namespace
74 :
75 : already_AddRefed<Promise>
76 0 : Permissions::Query(JSContext* aCx,
77 : JS::Handle<JSObject*> aPermission,
78 : ErrorResult& aRv)
79 : {
80 0 : nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(mWindow);
81 0 : if (!global) {
82 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
83 0 : return nullptr;
84 : }
85 :
86 : RefPtr<PermissionStatus> status =
87 0 : CreatePermissionStatus(aCx, aPermission, mWindow, aRv);
88 0 : if (NS_WARN_IF(aRv.Failed())) {
89 0 : MOZ_ASSERT(!status);
90 0 : return nullptr;
91 : }
92 :
93 0 : MOZ_ASSERT(status);
94 0 : RefPtr<Promise> promise = Promise::Create(global, aRv);
95 0 : if (NS_WARN_IF(aRv.Failed())) {
96 0 : return nullptr;
97 : }
98 :
99 0 : promise->MaybeResolve(status);
100 0 : return promise.forget();
101 : }
102 :
103 : /* static */ nsresult
104 0 : Permissions::RemovePermission(nsIPrincipal* aPrincipal, const char* aPermissionType)
105 : {
106 0 : MOZ_ASSERT(XRE_IsParentProcess());
107 :
108 0 : nsCOMPtr<nsIPermissionManager> permMgr = services::GetPermissionManager();
109 0 : if (NS_WARN_IF(!permMgr)) {
110 0 : return NS_ERROR_FAILURE;
111 : }
112 :
113 0 : return permMgr->RemoveFromPrincipal(aPrincipal, aPermissionType);
114 : }
115 :
116 : already_AddRefed<Promise>
117 0 : Permissions::Revoke(JSContext* aCx,
118 : JS::Handle<JSObject*> aPermission,
119 : ErrorResult& aRv)
120 : {
121 0 : nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(mWindow);
122 0 : if (!global) {
123 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
124 0 : return nullptr;
125 : }
126 :
127 0 : PermissionDescriptor permission;
128 0 : JS::Rooted<JS::Value> value(aCx, JS::ObjectOrNullValue(aPermission));
129 0 : if (NS_WARN_IF(!permission.Init(aCx, value))) {
130 0 : aRv.NoteJSContextException(aCx);
131 0 : return nullptr;
132 : }
133 :
134 0 : RefPtr<Promise> promise = Promise::Create(global, aRv);
135 0 : if (NS_WARN_IF(aRv.Failed())) {
136 0 : return nullptr;
137 : }
138 :
139 0 : nsCOMPtr<nsIDocument> document = mWindow->GetExtantDoc();
140 0 : if (!document) {
141 0 : promise->MaybeReject(NS_ERROR_UNEXPECTED);
142 0 : return promise.forget();
143 : }
144 :
145 0 : nsCOMPtr<nsIPermissionManager> permMgr = services::GetPermissionManager();
146 0 : if (NS_WARN_IF(!permMgr)) {
147 0 : promise->MaybeReject(NS_ERROR_FAILURE);
148 0 : return promise.forget();
149 : }
150 :
151 0 : const char* permissionType = PermissionNameToType(permission.mName);
152 :
153 : nsresult rv;
154 0 : if (XRE_IsParentProcess()) {
155 0 : rv = RemovePermission(document->NodePrincipal(), permissionType);
156 : } else {
157 : // Permissions can't be removed from the content process. Send a message
158 : // to the parent; `ContentParent::RecvRemovePermission` will call
159 : // `RemovePermission`.
160 0 : ContentChild::GetSingleton()->SendRemovePermission(
161 0 : IPC::Principal(document->NodePrincipal()), nsDependentCString(permissionType), &rv);
162 : }
163 :
164 0 : if (NS_WARN_IF(NS_FAILED(rv))) {
165 0 : promise->MaybeReject(rv);
166 0 : return promise.forget();
167 : }
168 :
169 : RefPtr<PermissionStatus> status =
170 0 : CreatePermissionStatus(aCx, aPermission, mWindow, aRv);
171 0 : if (NS_WARN_IF(aRv.Failed())) {
172 0 : MOZ_ASSERT(!status);
173 0 : return nullptr;
174 : }
175 :
176 0 : MOZ_ASSERT(status);
177 0 : promise->MaybeResolve(status);
178 0 : return promise.forget();
179 : }
180 :
181 : } // namespace dom
182 : } // namespace mozilla
|