Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(758)

Side by Side Diff: content/child/permissions/permission_dispatcher.cc

Issue 2108003002: Merge //content/child/permissions into Blink's permissions module. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebased. Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/child/permissions/permission_dispatcher.h"
6
7 #include <stddef.h>
8 #include <utility>
9
10 #include "base/bind.h"
11 #include "base/callback.h"
12 #include "content/public/child/worker_thread.h"
13 #include "services/shell/public/cpp/interface_provider.h"
14 #include "third_party/WebKit/public/platform/WebURL.h"
15 #include "third_party/WebKit/public/platform/modules/permissions/WebPermissionOb server.h"
16 #include "third_party/WebKit/public/web/WebUserGestureIndicator.h"
17
18 using blink::WebPermissionObserver;
19 using blink::mojom::PermissionName;
20 using blink::mojom::PermissionStatus;
21
22 namespace content {
23
24 namespace {
25
26 PermissionName GetPermissionName(blink::WebPermissionType type) {
27 switch (type) {
28 case blink::WebPermissionTypeGeolocation:
29 return PermissionName::GEOLOCATION;
30 case blink::WebPermissionTypeNotifications:
31 return PermissionName::NOTIFICATIONS;
32 case blink::WebPermissionTypePushNotifications:
33 return PermissionName::PUSH_NOTIFICATIONS;
34 case blink::WebPermissionTypeMidiSysEx:
35 return PermissionName::MIDI_SYSEX;
36 case blink::WebPermissionTypeDurableStorage:
37 return PermissionName::DURABLE_STORAGE;
38 case blink::WebPermissionTypeMidi:
39 return PermissionName::MIDI;
40 case blink::WebPermissionTypeBackgroundSync:
41 return PermissionName::BACKGROUND_SYNC;
42 default:
43 // The default statement is only there to prevent compilation failures if
44 // WebPermissionType enum gets extended.
45 NOTREACHED();
46 return PermissionName::GEOLOCATION;
47 }
48 }
49
50 PermissionStatus GetPermissionStatus(blink::WebPermissionStatus status) {
51 switch (status) {
52 case blink::WebPermissionStatusGranted:
53 return PermissionStatus::GRANTED;
54 case blink::WebPermissionStatusDenied:
55 return PermissionStatus::DENIED;
56 case blink::WebPermissionStatusPrompt:
57 return PermissionStatus::ASK;
58 }
59
60 NOTREACHED();
61 return PermissionStatus::DENIED;
62 }
63
64 blink::WebPermissionStatus GetWebPermissionStatus(PermissionStatus status) {
65 switch (status) {
66 case PermissionStatus::GRANTED:
67 return blink::WebPermissionStatusGranted;
68 case PermissionStatus::DENIED:
69 return blink::WebPermissionStatusDenied;
70 case PermissionStatus::ASK:
71 return blink::WebPermissionStatusPrompt;
72 }
73
74 NOTREACHED();
75 return blink::WebPermissionStatusDenied;
76 }
77
78 const int kNoWorkerThread = 0;
79
80 } // anonymous namespace
81
82 // static
83 bool PermissionDispatcher::IsObservable(blink::WebPermissionType type) {
84 return type == blink::WebPermissionTypeGeolocation ||
85 type == blink::WebPermissionTypeNotifications ||
86 type == blink::WebPermissionTypePushNotifications ||
87 type == blink::WebPermissionTypeMidiSysEx ||
88 type == blink::WebPermissionTypeMidi ||
89 type == blink::WebPermissionTypeBackgroundSync;
90 }
91
92 PermissionDispatcher::PermissionDispatcher(
93 shell::InterfaceProvider* remote_interfaces)
94 : remote_interfaces_(remote_interfaces) {
95 }
96
97 PermissionDispatcher::~PermissionDispatcher() {
98 }
99
100 void PermissionDispatcher::queryPermission(
101 blink::WebPermissionType type,
102 const blink::WebURL& origin,
103 blink::WebPermissionCallback* callback) {
104 QueryPermissionInternal(
105 type, origin.string().utf8(), callback, kNoWorkerThread);
106 }
107
108 void PermissionDispatcher::requestPermission(
109 blink::WebPermissionType type,
110 const blink::WebURL& origin,
111 blink::WebPermissionCallback* callback) {
112 RequestPermissionInternal(
113 type, origin.string().utf8(), callback, kNoWorkerThread);
114 }
115
116 void PermissionDispatcher::requestPermissions(
117 const blink::WebVector<blink::WebPermissionType>& types,
118 const blink::WebURL& origin,
119 blink::WebPermissionsCallback* callback) {
120 RequestPermissionsInternal(
121 types, origin.string().utf8(), callback, kNoWorkerThread);
122 }
123
124 void PermissionDispatcher::revokePermission(
125 blink::WebPermissionType type,
126 const blink::WebURL& origin,
127 blink::WebPermissionCallback* callback) {
128 RevokePermissionInternal(
129 type, origin.string().utf8(), callback, kNoWorkerThread);
130 }
131
132 void PermissionDispatcher::startListening(
133 blink::WebPermissionType type,
134 const blink::WebURL& origin,
135 WebPermissionObserver* observer) {
136 if (!IsObservable(type))
137 return;
138
139 RegisterObserver(observer);
140
141 GetNextPermissionChange(type, origin.string().utf8(), observer,
142 // We initialize with an arbitrary value because the
143 // mojo service wants a value. Worst case, the
144 // observer will get notified about a non-change which
145 // should be a no-op. After the first notification,
146 // GetNextPermissionChange will be called with the
147 // latest known value.
148 PermissionStatus::ASK);
149 }
150
151 void PermissionDispatcher::stopListening(WebPermissionObserver* observer) {
152 UnregisterObserver(observer);
153 }
154
155 void PermissionDispatcher::QueryPermissionForWorker(
156 blink::WebPermissionType type,
157 const std::string& origin,
158 blink::WebPermissionCallback* callback,
159 int worker_thread_id) {
160 QueryPermissionInternal(type, origin, callback, worker_thread_id);
161 }
162
163 void PermissionDispatcher::RequestPermissionForWorker(
164 blink::WebPermissionType type,
165 const std::string& origin,
166 blink::WebPermissionCallback* callback,
167 int worker_thread_id) {
168 RequestPermissionInternal(type, origin, callback, worker_thread_id);
169 }
170
171 void PermissionDispatcher::RequestPermissionsForWorker(
172 const blink::WebVector<blink::WebPermissionType>& types,
173 const std::string& origin,
174 blink::WebPermissionsCallback* callback,
175 int worker_thread_id) {
176 RequestPermissionsInternal(types, origin, callback, worker_thread_id);
177 }
178
179 void PermissionDispatcher::RevokePermissionForWorker(
180 blink::WebPermissionType type,
181 const std::string& origin,
182 blink::WebPermissionCallback* callback,
183 int worker_thread_id) {
184 RevokePermissionInternal(type, origin, callback, worker_thread_id);
185 }
186
187 void PermissionDispatcher::StartListeningForWorker(
188 blink::WebPermissionType type,
189 const std::string& origin,
190 int worker_thread_id,
191 const base::Callback<void(blink::WebPermissionStatus)>& callback) {
192 GetPermissionServicePtr()->GetNextPermissionChange(
193 GetPermissionName(type), origin,
194 // We initialize with an arbitrary value because the mojo service wants a
195 // value. Worst case, the observer will get notified about a non-change
196 // which should be a no-op. After the first notification,
197 // GetNextPermissionChange will be called with the latest known value.
198 PermissionStatus::ASK,
199 base::Bind(&PermissionDispatcher::OnPermissionChangedForWorker,
200 base::Unretained(this), worker_thread_id, callback));
201 }
202
203 void PermissionDispatcher::GetNextPermissionChangeForWorker(
204 blink::WebPermissionType type,
205 const std::string& origin,
206 blink::WebPermissionStatus status,
207 int worker_thread_id,
208 const base::Callback<void(blink::WebPermissionStatus)>& callback) {
209 GetPermissionServicePtr()->GetNextPermissionChange(
210 GetPermissionName(type),
211 origin,
212 GetPermissionStatus(status),
213 base::Bind(&PermissionDispatcher::OnPermissionChangedForWorker,
214 base::Unretained(this),
215 worker_thread_id,
216 callback));
217 }
218
219 // static
220 void PermissionDispatcher::RunPermissionCallbackOnWorkerThread(
221 std::unique_ptr<blink::WebPermissionCallback> callback,
222 blink::WebPermissionStatus status) {
223 callback->onSuccess(status);
224 }
225
226 void PermissionDispatcher::RunPermissionsCallbackOnWorkerThread(
227 std::unique_ptr<blink::WebPermissionsCallback> callback,
228 std::unique_ptr<blink::WebVector<blink::WebPermissionStatus>> statuses) {
229 callback->onSuccess(std::move(statuses));
230 }
231
232 blink::mojom::PermissionService*
233 PermissionDispatcher::GetPermissionServicePtr() {
234 if (!permission_service_.get()) {
235 remote_interfaces_->GetInterface(mojo::GetProxy(&permission_service_));
236 }
237 return permission_service_.get();
238 }
239
240 void PermissionDispatcher::QueryPermissionInternal(
241 blink::WebPermissionType type,
242 const std::string& origin,
243 blink::WebPermissionCallback* callback,
244 int worker_thread_id) {
245 // We need to save the |callback| in an ScopedPtrHashMap so if |this| gets
246 // deleted, the callback will not leak. In the case of |this| gets deleted,
247 // the |permission_service_| pipe will be destroyed too so OnQueryPermission
248 // will not be called.
249 uintptr_t callback_key = reinterpret_cast<uintptr_t>(callback);
250 permission_callbacks_.add(
251 callback_key, std::unique_ptr<blink::WebPermissionCallback>(callback));
252
253 GetPermissionServicePtr()->HasPermission(
254 GetPermissionName(type),
255 origin,
256 base::Bind(&PermissionDispatcher::OnPermissionResponse,
257 base::Unretained(this),
258 worker_thread_id,
259 callback_key));
260 }
261
262 void PermissionDispatcher::RequestPermissionInternal(
263 blink::WebPermissionType type,
264 const std::string& origin,
265 blink::WebPermissionCallback* callback,
266 int worker_thread_id) {
267 // We need to save the |callback| in an ScopedPtrHashMap so if |this| gets
268 // deleted, the callback will not leak. In the case of |this| gets deleted,
269 // the |permission_service_| pipe will be destroyed too so OnQueryPermission
270 // will not be called.
271 uintptr_t callback_key = reinterpret_cast<uintptr_t>(callback);
272 permission_callbacks_.add(
273 callback_key, std::unique_ptr<blink::WebPermissionCallback>(callback));
274
275 GetPermissionServicePtr()->RequestPermission(
276 GetPermissionName(type),
277 origin,
278 blink::WebUserGestureIndicator::isProcessingUserGesture(),
279 base::Bind(&PermissionDispatcher::OnPermissionResponse,
280 base::Unretained(this),
281 worker_thread_id,
282 callback_key));
283 }
284
285 void PermissionDispatcher::RequestPermissionsInternal(
286 const blink::WebVector<blink::WebPermissionType>& types,
287 const std::string& origin,
288 blink::WebPermissionsCallback* callback,
289 int worker_thread_id) {
290 // We need to save the |callback| in an ScopedVector so if |this| gets
291 // deleted, the callback will not leak. In the case of |this| gets deleted,
292 // the |permission_service_| pipe will be destroyed too so OnQueryPermission
293 // will not be called.
294 uintptr_t callback_key = reinterpret_cast<uintptr_t>(callback);
295 permissions_callbacks_.add(
296 callback_key, std::unique_ptr<blink::WebPermissionsCallback>(callback));
297
298 mojo::Array<PermissionName> names(types.size());
299 for (size_t i = 0; i < types.size(); ++i)
300 names[i] = GetPermissionName(types[i]);
301
302 GetPermissionServicePtr()->RequestPermissions(
303 std::move(names), origin,
304 blink::WebUserGestureIndicator::isProcessingUserGesture(),
305 base::Bind(&PermissionDispatcher::OnRequestPermissionsResponse,
306 base::Unretained(this), worker_thread_id, callback_key));
307 }
308
309 void PermissionDispatcher::RevokePermissionInternal(
310 blink::WebPermissionType type,
311 const std::string& origin,
312 blink::WebPermissionCallback* callback,
313 int worker_thread_id) {
314 // We need to save the |callback| in an ScopedPtrHashMap so if |this| gets
315 // deleted, the callback will not leak. In the case of |this| gets deleted,
316 // the |permission_service_| pipe will be destroyed too so OnQueryPermission
317 // will not be called.
318 uintptr_t callback_key = reinterpret_cast<uintptr_t>(callback);
319 permission_callbacks_.add(
320 callback_key, std::unique_ptr<blink::WebPermissionCallback>(callback));
321
322 GetPermissionServicePtr()->RevokePermission(
323 GetPermissionName(type),
324 origin,
325 base::Bind(&PermissionDispatcher::OnPermissionResponse,
326 base::Unretained(this),
327 worker_thread_id,
328 callback_key));
329 }
330
331 void PermissionDispatcher::OnPermissionResponse(int worker_thread_id,
332 uintptr_t callback_key,
333 PermissionStatus result) {
334 std::unique_ptr<blink::WebPermissionCallback> callback =
335 permission_callbacks_.take_and_erase(callback_key);
336 blink::WebPermissionStatus status = GetWebPermissionStatus(result);
337
338 if (worker_thread_id != kNoWorkerThread) {
339 // If the worker is no longer running, ::PostTask() will return false and
340 // gracefully fail, destroying the callback too.
341 WorkerThread::PostTask(
342 worker_thread_id,
343 base::Bind(&PermissionDispatcher::RunPermissionCallbackOnWorkerThread,
344 base::Passed(&callback), status));
345 return;
346 }
347
348 callback->onSuccess(status);
349 }
350
351 void PermissionDispatcher::OnRequestPermissionsResponse(
352 int worker_thread_id,
353 uintptr_t callback_key,
354 mojo::Array<PermissionStatus> result) {
355 std::unique_ptr<blink::WebPermissionsCallback> callback =
356 permissions_callbacks_.take_and_erase(callback_key);
357 std::unique_ptr<blink::WebVector<blink::WebPermissionStatus>> statuses(
358 new blink::WebVector<blink::WebPermissionStatus>(result.size()));
359
360 for (size_t i = 0; i < result.size(); i++)
361 statuses->operator[](i) = GetWebPermissionStatus(result[i]);
362
363 if (worker_thread_id != kNoWorkerThread) {
364 // If the worker is no longer running, ::PostTask() will return false and
365 // gracefully fail, destroying the callback too.
366 WorkerThread::PostTask(
367 worker_thread_id,
368 base::Bind(&PermissionDispatcher::RunPermissionsCallbackOnWorkerThread,
369 base::Passed(&callback), base::Passed(&statuses)));
370 return;
371 }
372
373 callback->onSuccess(std::move(statuses));
374 }
375
376 void PermissionDispatcher::OnPermissionChanged(blink::WebPermissionType type,
377 const std::string& origin,
378 WebPermissionObserver* observer,
379 PermissionStatus status) {
380 if (!IsObserverRegistered(observer))
381 return;
382
383 observer->permissionChanged(type, GetWebPermissionStatus(status));
384
385 GetNextPermissionChange(type, origin, observer, status);
386 }
387
388 void PermissionDispatcher::OnPermissionChangedForWorker(
389 int worker_thread_id,
390 const base::Callback<void(blink::WebPermissionStatus)>& callback,
391 PermissionStatus status) {
392 DCHECK(worker_thread_id != kNoWorkerThread);
393
394 WorkerThread::PostTask(worker_thread_id,
395 base::Bind(callback, GetWebPermissionStatus(status)));
396 }
397
398 void PermissionDispatcher::GetNextPermissionChange(
399 blink::WebPermissionType type,
400 const std::string& origin,
401 WebPermissionObserver* observer,
402 PermissionStatus current_status) {
403 GetPermissionServicePtr()->GetNextPermissionChange(
404 GetPermissionName(type),
405 origin,
406 current_status,
407 base::Bind(&PermissionDispatcher::OnPermissionChanged,
408 base::Unretained(this),
409 type,
410 origin,
411 base::Unretained(observer)));
412 }
413
414 } // namespace content
OLDNEW
« no previous file with comments | « content/child/permissions/permission_dispatcher.h ('k') | content/child/permissions/permission_dispatcher_thread_proxy.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698