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

Side by Side Diff: third_party/WebKit/Source/modules/permissions/Permissions.cpp

Issue 2108003002: Merge //content/child/permissions into Blink's permissions module. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixing presubmits. 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
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "modules/permissions/Permissions.h" 5 #include "modules/permissions/Permissions.h"
6 6
7 #include "bindings/core/v8/Dictionary.h" 7 #include "bindings/core/v8/Dictionary.h"
8 #include "bindings/core/v8/Nullable.h" 8 #include "bindings/core/v8/Nullable.h"
9 #include "bindings/core/v8/ScriptPromise.h" 9 #include "bindings/core/v8/ScriptPromise.h"
10 #include "bindings/core/v8/ScriptPromiseResolver.h" 10 #include "bindings/core/v8/ScriptPromiseResolver.h"
11 #include "bindings/modules/v8/V8MidiPermissionDescriptor.h" 11 #include "bindings/modules/v8/V8MidiPermissionDescriptor.h"
12 #include "bindings/modules/v8/V8PermissionDescriptor.h" 12 #include "bindings/modules/v8/V8PermissionDescriptor.h"
13 #include "bindings/modules/v8/V8PushPermissionDescriptor.h" 13 #include "bindings/modules/v8/V8PushPermissionDescriptor.h"
14 #include "core/dom/DOMException.h" 14 #include "core/dom/DOMException.h"
15 #include "core/dom/Document.h" 15 #include "core/dom/Document.h"
16 #include "core/dom/ExceptionCode.h" 16 #include "core/dom/ExceptionCode.h"
17 #include "modules/permissions/PermissionCallback.h" 17 #include "core/frame/LocalFrame.h"
18 #include "modules/permissions/PermissionController.h"
19 #include "modules/permissions/PermissionDescriptor.h" 18 #include "modules/permissions/PermissionDescriptor.h"
20 #include "modules/permissions/PermissionStatus.h" 19 #include "modules/permissions/PermissionStatus.h"
21 #include "modules/permissions/PermissionsCallback.h"
22 #include "platform/Logging.h" 20 #include "platform/Logging.h"
21 #include "platform/UserGestureIndicator.h"
22 #include "platform/mojo/MojoHelper.h"
23 #include "public/platform/Platform.h" 23 #include "public/platform/Platform.h"
24 #include "public/platform/modules/permissions/WebPermissionClient.h" 24 #include "public/platform/ServiceRegistry.h"
25 #include "wtf/Functional.h"
25 #include "wtf/NotFound.h" 26 #include "wtf/NotFound.h"
26 #include "wtf/PtrUtil.h" 27 #include "wtf/PtrUtil.h"
27 #include "wtf/Vector.h" 28 #include "wtf/Vector.h"
28 #include <memory> 29 #include <memory>
29 30
30 namespace blink { 31 namespace blink {
31 32
33 using mojom::blink::PermissionName;
34 using mojom::blink::PermissionService;
35
32 namespace { 36 namespace {
33 37
34 WebPermissionType getPermissionType(ScriptState* scriptState, const Dictionary& rawPermission, const PermissionDescriptor& permission, ExceptionState& exception State) 38 PermissionName getPermissionName(ScriptState* scriptState, const Dictionary& raw Permission, const PermissionDescriptor& permission, ExceptionState& exceptionSta te)
35 { 39 {
36 const String& name = permission.name(); 40 const String& name = permission.name();
37 if (name == "geolocation") 41 if (name == "geolocation")
38 return WebPermissionTypeGeolocation; 42 return PermissionName::GEOLOCATION;
39 if (name == "notifications") 43 if (name == "notifications")
40 return WebPermissionTypeNotifications; 44 return PermissionName::NOTIFICATIONS;
41 if (name == "push") 45 if (name == "push")
42 return WebPermissionTypePushNotifications; 46 return PermissionName::PUSH_NOTIFICATIONS;
43 if (name == "midi") { 47 if (name == "midi") {
44 MidiPermissionDescriptor midiPermission = NativeValueTraits<MidiPermissi onDescriptor>::nativeValue(scriptState->isolate(), rawPermission.v8Value(), exce ptionState); 48 MidiPermissionDescriptor midiPermission = NativeValueTraits<MidiPermissi onDescriptor>::nativeValue(scriptState->isolate(), rawPermission.v8Value(), exce ptionState);
45 return midiPermission.sysex() ? WebPermissionTypeMidiSysEx : WebPermissi onTypeMidi; 49 return midiPermission.sysex() ? PermissionName::MIDI_SYSEX : PermissionN ame::MIDI;
46 } 50 }
47 if (name == "background-sync") 51 if (name == "background-sync")
48 return WebPermissionTypeBackgroundSync; 52 return PermissionName::BACKGROUND_SYNC;
49 53
50 ASSERT_NOT_REACHED(); 54 ASSERT_NOT_REACHED();
51 return WebPermissionTypeGeolocation; 55 return PermissionName::GEOLOCATION;
52 } 56 }
53 57
54 // Parses the raw permission dictionary and returns the PermissionType if 58 // Parses the raw permission dictionary and returns the PermissionType if
55 // parsing was successful. If an exception occurs, it will be stored in 59 // parsing was successful. If an exception occurs, it will be stored in
56 // |exceptionState| and null will be returned. Therefore, the |exceptionState| 60 // |exceptionState| and null will be returned. Therefore, the |exceptionState|
57 // should be checked before attempting to use the returned permission as the 61 // should be checked before attempting to use the returned permission as the
58 // non-null assert will be fired otherwise. 62 // non-null assert will be fired otherwise.
59 Nullable<WebPermissionType> parsePermission(ScriptState* scriptState, const Dict ionary rawPermission, ExceptionState& exceptionState) 63 Nullable<PermissionName> parsePermission(ScriptState* scriptState, const Diction ary rawPermission, ExceptionState& exceptionState)
60 { 64 {
61 PermissionDescriptor permission = NativeValueTraits<PermissionDescriptor>::n ativeValue(scriptState->isolate(), rawPermission.v8Value(), exceptionState); 65 PermissionDescriptor permission = NativeValueTraits<PermissionDescriptor>::n ativeValue(scriptState->isolate(), rawPermission.v8Value(), exceptionState);
62 66
63 if (exceptionState.hadException()) { 67 if (exceptionState.hadException()) {
64 exceptionState.throwTypeError(exceptionState.message()); 68 exceptionState.throwTypeError(exceptionState.message());
65 return Nullable<WebPermissionType>(); 69 return Nullable<PermissionName>();
66 } 70 }
67 71
68 WebPermissionType type = getPermissionType(scriptState, rawPermission, permi ssion, exceptionState); 72 PermissionName name = getPermissionName(scriptState, rawPermission, permissi on, exceptionState);
69 if (exceptionState.hadException()) { 73 if (exceptionState.hadException()) {
70 exceptionState.throwTypeError(exceptionState.message()); 74 exceptionState.throwTypeError(exceptionState.message());
71 return Nullable<WebPermissionType>(); 75 return Nullable<PermissionName>();
72 } 76 }
73 77
74 // Here we reject any permissions which are not yet supported by Blink. 78 // Here we reject any permissions which are not yet supported by Blink.
75 if (type == WebPermissionTypePushNotifications) { 79 if (name == PermissionName::PUSH_NOTIFICATIONS) {
76 PushPermissionDescriptor pushPermission = NativeValueTraits<PushPermissi onDescriptor>::nativeValue(scriptState->isolate(), rawPermission.v8Value(), exce ptionState); 80 PushPermissionDescriptor pushPermission = NativeValueTraits<PushPermissi onDescriptor>::nativeValue(scriptState->isolate(), rawPermission.v8Value(), exce ptionState);
77 if (exceptionState.hadException()) { 81 if (exceptionState.hadException()) {
78 exceptionState.throwTypeError(exceptionState.message()); 82 exceptionState.throwTypeError(exceptionState.message());
79 return Nullable<WebPermissionType>(); 83 return Nullable<PermissionName>();
80 } 84 }
81 85
82 // Only "userVisibleOnly" push is supported for now. 86 // Only "userVisibleOnly" push is supported for now.
83 if (!pushPermission.userVisibleOnly()) { 87 if (!pushPermission.userVisibleOnly()) {
84 exceptionState.throwDOMException(NotSupportedError, "Push Permission without userVisibleOnly:true isn't supported yet."); 88 exceptionState.throwDOMException(NotSupportedError, "Push Permission without userVisibleOnly:true isn't supported yet.");
85 return Nullable<WebPermissionType>(); 89 return Nullable<PermissionName>();
86 } 90 }
87 } 91 }
88 92
89 return Nullable<WebPermissionType>(type); 93 return Nullable<PermissionName>(name);
90 } 94 }
91 95
92 } // anonymous namespace 96 } // anonymous namespace
93 97
94 // static 98 // static
95 WebPermissionClient* Permissions::getClient(ExecutionContext* executionContext) 99 bool Permissions::connectToService(ExecutionContext* executionContext, mojom::bl ink::PermissionServiceRequest request)
96 { 100 {
101 ServiceRegistry* serviceRegistry = nullptr;
97 if (executionContext->isDocument()) { 102 if (executionContext->isDocument()) {
98 Document* document = toDocument(executionContext); 103 Document* document = toDocument(executionContext);
99 if (!document->frame()) 104 if (document->frame())
100 return nullptr; 105 serviceRegistry = document->frame()->serviceRegistry();
101 PermissionController* controller = PermissionController::from(*document- >frame()); 106 } else {
102 return controller ? controller->client() : nullptr; 107 serviceRegistry = Platform::current()->serviceRegistry();
103 } 108 }
104 return Platform::current()->permissionClient(); 109
110 if (serviceRegistry)
111 serviceRegistry->connectToRemoteService(std::move(request));
112 return serviceRegistry;
105 } 113 }
106 114
107 ScriptPromise Permissions::query(ScriptState* scriptState, const Dictionary& raw Permission) 115 ScriptPromise Permissions::query(ScriptState* scriptState, const Dictionary& raw Permission)
108 { 116 {
109 WebPermissionClient* client = getClient(scriptState->getExecutionContext()); 117 PermissionService* service = getService(scriptState->getExecutionContext());
110 if (!client) 118 if (!service)
111 return ScriptPromise::rejectWithDOMException(scriptState, DOMException:: create(InvalidStateError, "In its current state, the global scope can't query pe rmissions.")); 119 return ScriptPromise::rejectWithDOMException(scriptState, DOMException:: create(InvalidStateError, "In its current state, the global scope can't query pe rmissions."));
112 120
113 ExceptionState exceptionState(ExceptionState::GetterContext, "query", "Perm issions", scriptState->context()->Global(), scriptState->isolate()); 121 ExceptionState exceptionState(ExceptionState::GetterContext, "query", "Perm issions", scriptState->context()->Global(), scriptState->isolate());
114 Nullable<WebPermissionType> type = parsePermission(scriptState, rawPermissio n, exceptionState); 122 Nullable<PermissionName> name = parsePermission(scriptState, rawPermission, exceptionState);
115 if (exceptionState.hadException()) 123 if (exceptionState.hadException())
116 return exceptionState.reject(scriptState); 124 return exceptionState.reject(scriptState);
117 125
118 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState) ; 126 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState) ;
119 ScriptPromise promise = resolver->promise(); 127 ScriptPromise promise = resolver->promise();
120 128
121 // If the current origin is a file scheme, it will unlikely return a 129 // If the current origin is a file scheme, it will unlikely return a
122 // meaningful value because most APIs are broken on file scheme and no 130 // meaningful value because most APIs are broken on file scheme and no
123 // permission prompt will be shown even if the returned permission will most 131 // permission prompt will be shown even if the returned permission will most
124 // likely be "prompt". 132 // likely be "prompt".
125 client->queryPermission(type.get(), KURL(KURL(), scriptState->getExecutionCo ntext()->getSecurityOrigin()->toString()), new PermissionCallback(resolver, type .get())); 133 service->HasPermission(name.get(), scriptState->getExecutionContext()->getSe curityOrigin()->toString(), createBaseCallback(bind(&Permissions::taskComplete, wrapPersistent(this), wrapPersistent(resolver), name.get())));
126 return promise; 134 return promise;
127 } 135 }
128 136
129 ScriptPromise Permissions::request(ScriptState* scriptState, const Dictionary& r awPermission) 137 ScriptPromise Permissions::request(ScriptState* scriptState, const Dictionary& r awPermission)
130 { 138 {
131 WebPermissionClient* client = getClient(scriptState->getExecutionContext()); 139 PermissionService* service = getService(scriptState->getExecutionContext());
132 if (!client) 140 if (!service)
133 return ScriptPromise::rejectWithDOMException(scriptState, DOMException:: create(InvalidStateError, "In its current state, the global scope can't request permissions.")); 141 return ScriptPromise::rejectWithDOMException(scriptState, DOMException:: create(InvalidStateError, "In its current state, the global scope can't request permissions."));
134 142
135 ExceptionState exceptionState(ExceptionState::GetterContext, "request", "Pe rmissions", scriptState->context()->Global(), scriptState->isolate()); 143 ExceptionState exceptionState(ExceptionState::GetterContext, "request", "Pe rmissions", scriptState->context()->Global(), scriptState->isolate());
136 Nullable<WebPermissionType> type = parsePermission(scriptState, rawPermissio n, exceptionState); 144 Nullable<PermissionName> name = parsePermission(scriptState, rawPermission, exceptionState);
137 if (exceptionState.hadException()) 145 if (exceptionState.hadException())
138 return exceptionState.reject(scriptState); 146 return exceptionState.reject(scriptState);
139 147
140 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState) ; 148 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState) ;
141 ScriptPromise promise = resolver->promise(); 149 ScriptPromise promise = resolver->promise();
142 150
143 client->requestPermission(type.get(), KURL(KURL(), scriptState->getExecution Context()->getSecurityOrigin()->toString()), new PermissionCallback(resolver, ty pe.get())); 151 service->RequestPermission(name.get(), scriptState->getExecutionContext()->g etSecurityOrigin()->toString(), UserGestureIndicator::processingUserGesture(), c reateBaseCallback(bind(&Permissions::taskComplete, wrapPersistent(this), wrapPer sistent(resolver), name.get())));
144 return promise; 152 return promise;
145 } 153 }
146 154
147 ScriptPromise Permissions::revoke(ScriptState* scriptState, const Dictionary& ra wPermission) 155 ScriptPromise Permissions::revoke(ScriptState* scriptState, const Dictionary& ra wPermission)
148 { 156 {
149 WebPermissionClient* client = getClient(scriptState->getExecutionContext()); 157 PermissionService* service = getService(scriptState->getExecutionContext());
150 if (!client) 158 if (!service)
151 return ScriptPromise::rejectWithDOMException(scriptState, DOMException:: create(InvalidStateError, "In its current state, the global scope can't revoke p ermissions.")); 159 return ScriptPromise::rejectWithDOMException(scriptState, DOMException:: create(InvalidStateError, "In its current state, the global scope can't revoke p ermissions."));
152 160
153 ExceptionState exceptionState(ExceptionState::GetterContext, "revoke", "Per missions", scriptState->context()->Global(), scriptState->isolate()); 161 ExceptionState exceptionState(ExceptionState::GetterContext, "revoke", "Per missions", scriptState->context()->Global(), scriptState->isolate());
154 Nullable<WebPermissionType> type = parsePermission(scriptState, rawPermissio n, exceptionState); 162 Nullable<PermissionName> name = parsePermission(scriptState, rawPermission, exceptionState);
155 if (exceptionState.hadException()) 163 if (exceptionState.hadException())
156 return exceptionState.reject(scriptState); 164 return exceptionState.reject(scriptState);
157 165
158 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState) ; 166 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState) ;
159 ScriptPromise promise = resolver->promise(); 167 ScriptPromise promise = resolver->promise();
160 168
161 client->revokePermission(type.get(), KURL(KURL(), scriptState->getExecutionC ontext()->getSecurityOrigin()->toString()), new PermissionCallback(resolver, typ e.get())); 169 service->RevokePermission(name.get(), scriptState->getExecutionContext()->ge tSecurityOrigin()->toString(), createBaseCallback(bind(&Permissions::taskComplet e, wrapPersistent(this), wrapPersistent(resolver), name.get())));
162 return promise; 170 return promise;
163 } 171 }
164 172
165 ScriptPromise Permissions::requestAll(ScriptState* scriptState, const Vector<Dic tionary>& rawPermissions) 173 ScriptPromise Permissions::requestAll(ScriptState* scriptState, const Vector<Dic tionary>& rawPermissions)
166 { 174 {
167 WebPermissionClient* client = getClient(scriptState->getExecutionContext()); 175 PermissionService* service = getService(scriptState->getExecutionContext());
168 if (!client) 176 if (!service)
169 return ScriptPromise::rejectWithDOMException(scriptState, DOMException:: create(InvalidStateError, "In its current state, the global scope can't request permissions.")); 177 return ScriptPromise::rejectWithDOMException(scriptState, DOMException:: create(InvalidStateError, "In its current state, the global scope can't request permissions."));
170 178
171 ExceptionState exceptionState(ExceptionState::GetterContext, "request", "Pe rmissions", scriptState->context()->Global(), scriptState->isolate()); 179 ExceptionState exceptionState(ExceptionState::GetterContext, "request", "Pe rmissions", scriptState->context()->Global(), scriptState->isolate());
172 std::unique_ptr<Vector<WebPermissionType>> internalPermissions = wrapUnique( new Vector<WebPermissionType>()); 180 Vector<PermissionName> internalPermissions;
173 std::unique_ptr<Vector<int>> callerIndexToInternalIndex = wrapUnique(new Vec tor<int>(rawPermissions.size())); 181 Vector<int> callerIndexToInternalIndex;
182 callerIndexToInternalIndex.resize(rawPermissions.size());
174 for (size_t i = 0; i < rawPermissions.size(); ++i) { 183 for (size_t i = 0; i < rawPermissions.size(); ++i) {
175 const Dictionary& rawPermission = rawPermissions[i]; 184 const Dictionary& rawPermission = rawPermissions[i];
176 185
177 Nullable<WebPermissionType> type = parsePermission(scriptState, rawPermi ssion, exceptionState); 186 Nullable<PermissionName> name = parsePermission(scriptState, rawPermissi on, exceptionState);
178 if (exceptionState.hadException()) 187 if (exceptionState.hadException())
179 return exceptionState.reject(scriptState); 188 return exceptionState.reject(scriptState);
180 189
181 // Only append permissions to the vector that is passed to the client if it is not already 190 // Only append permissions to the vector that is passed to the client if it is not already
182 // in the vector (i.e. do not duplicate permisison types). 191 // in the vector (i.e. do not duplicate permisison types).
183 int internalIndex; 192 int internalIndex;
184 auto it = internalPermissions->find(type.get()); 193 auto it = internalPermissions.find(name.get());
185 if (it == kNotFound) { 194 if (it == kNotFound) {
186 internalIndex = internalPermissions->size(); 195 internalIndex = internalPermissions.size();
187 internalPermissions->append(type.get()); 196 internalPermissions.append(name.get());
188 } else { 197 } else {
189 internalIndex = it; 198 internalIndex = it;
190 } 199 }
191 callerIndexToInternalIndex->operator[](i) = internalIndex; 200 callerIndexToInternalIndex[i] = internalIndex;
192 } 201 }
193 202
194 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState) ; 203 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState) ;
195 ScriptPromise promise = resolver->promise(); 204 ScriptPromise promise = resolver->promise();
196 205
197 WebVector<WebPermissionType> internalWebPermissions = *internalPermissions; 206 Vector<PermissionName> internalPermissionsCopy(internalPermissions);
198 client->requestPermissions(internalWebPermissions, KURL(KURL(), scriptState- >getExecutionContext()->getSecurityOrigin()->toString()), 207 service->RequestPermissions(std::move(internalPermissions), scriptState->get ExecutionContext()->getSecurityOrigin()->toString(), UserGestureIndicator::proce ssingUserGesture(),
199 new PermissionsCallback(resolver, std::move(internalPermissions), std::m ove(callerIndexToInternalIndex))); 208 createBaseCallback(bind(&Permissions::batchTaskComplete, wrapPersistent( this), wrapPersistent(resolver), std::move(internalPermissionsCopy), std::move(c allerIndexToInternalIndex))));
200 return promise; 209 return promise;
201 } 210 }
202 211
212 PermissionService* Permissions::getService(ExecutionContext* executionContext)
213 {
214 if (!m_service) {
215 if (connectToService(executionContext, mojo::GetProxy(&m_service)))
216 m_service.set_connection_error_handler(createBaseCallback(bind(&Perm issions::serviceConnectionError, wrapWeakPersistent(this))));
mlamouri (slow - plz ping) 2016/07/18 10:25:57 See below (in Storage)
Reilly Grant (use Gerrit) 2016/07/19 20:10:28 Done.
217 }
218 return m_service.get();
219 }
220
221 void Permissions::serviceConnectionError()
222 {
223 m_service.reset();
224 }
225
226 void Permissions::taskComplete(ScriptPromiseResolver* resolver, PermissionName n ame, mojom::blink::PermissionStatus result)
227 {
228 if (!resolver->getExecutionContext() || resolver->getExecutionContext()->act iveDOMObjectsAreStopped())
229 return;
230 resolver->resolve(PermissionStatus::take(resolver, result, name));
231 }
232
233 void Permissions::batchTaskComplete(ScriptPromiseResolver* resolver, Vector<Perm issionName> names, Vector<int> callerIndexToInternalIndex, mojo::WTFArray<mojom: :blink::PermissionStatus> results)
234 {
235 if (!resolver->getExecutionContext() || resolver->getExecutionContext()->act iveDOMObjectsAreStopped())
236 return;
237
238 // Create the response vector by finding the status for each index by
239 // using the caller to internal index mapping and looking up the status
240 // using the internal index obtained.
241 HeapVector<Member<PermissionStatus>> result(callerIndexToInternalIndex.size( ));
esprehn 2016/07/19 04:00:05 this is actually calling the default constructor,
Reilly Grant (use Gerrit) 2016/07/19 20:10:28 Done.
242 for (size_t i = 0; i < callerIndexToInternalIndex.size(); ++i) {
243 int internalIndex = callerIndexToInternalIndex[i];
244 result[i] = PermissionStatus::createAndListen(resolver->getExecutionCont ext(), results[internalIndex], names[internalIndex]);
245 }
246 resolver->resolve(result);
247 }
248
203 } // namespace blink 249 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698