OLD | NEW |
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" |
(...skipping 13 matching lines...) Expand all Loading... |
24 #include "public/platform/modules/permissions/WebPermissionClient.h" | 24 #include "public/platform/modules/permissions/WebPermissionClient.h" |
25 #include "wtf/NotFound.h" | 25 #include "wtf/NotFound.h" |
26 #include "wtf/PtrUtil.h" | 26 #include "wtf/PtrUtil.h" |
27 #include "wtf/Vector.h" | 27 #include "wtf/Vector.h" |
28 #include <memory> | 28 #include <memory> |
29 | 29 |
30 namespace blink { | 30 namespace blink { |
31 | 31 |
32 namespace { | 32 namespace { |
33 | 33 |
| 34 // Websites will be able to run code when `name()` is called, changing the |
| 35 // current context. The caller should make sure that no assumption is made |
| 36 // after this has been called. |
34 WebPermissionType getPermissionType(ScriptState* scriptState, const Dictionary&
rawPermission, const PermissionDescriptor& permission, ExceptionState& exception
State) | 37 WebPermissionType getPermissionType(ScriptState* scriptState, const Dictionary&
rawPermission, const PermissionDescriptor& permission, ExceptionState& exception
State) |
35 { | 38 { |
36 const String& name = permission.name(); | 39 const String& name = permission.name(); |
37 if (name == "geolocation") | 40 if (name == "geolocation") |
38 return WebPermissionTypeGeolocation; | 41 return WebPermissionTypeGeolocation; |
39 if (name == "notifications") | 42 if (name == "notifications") |
40 return WebPermissionTypeNotifications; | 43 return WebPermissionTypeNotifications; |
41 if (name == "push") | 44 if (name == "push") |
42 return WebPermissionTypePushNotifications; | 45 return WebPermissionTypePushNotifications; |
43 if (name == "midi") { | 46 if (name == "midi") { |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
99 if (!document->frame()) | 102 if (!document->frame()) |
100 return nullptr; | 103 return nullptr; |
101 PermissionController* controller = PermissionController::from(*document-
>frame()); | 104 PermissionController* controller = PermissionController::from(*document-
>frame()); |
102 return controller ? controller->client() : nullptr; | 105 return controller ? controller->client() : nullptr; |
103 } | 106 } |
104 return Platform::current()->permissionClient(); | 107 return Platform::current()->permissionClient(); |
105 } | 108 } |
106 | 109 |
107 ScriptPromise Permissions::query(ScriptState* scriptState, const Dictionary& raw
Permission) | 110 ScriptPromise Permissions::query(ScriptState* scriptState, const Dictionary& raw
Permission) |
108 { | 111 { |
109 WebPermissionClient* client = getClient(scriptState->getExecutionContext()); | |
110 if (!client) | |
111 return ScriptPromise::rejectWithDOMException(scriptState, DOMException::
create(InvalidStateError, "In its current state, the global scope can't query pe
rmissions.")); | |
112 | |
113 ExceptionState exceptionState(ExceptionState::GetterContext, "query", "Perm
issions", scriptState->context()->Global(), scriptState->isolate()); | 112 ExceptionState exceptionState(ExceptionState::GetterContext, "query", "Perm
issions", scriptState->context()->Global(), scriptState->isolate()); |
114 Nullable<WebPermissionType> type = parsePermission(scriptState, rawPermissio
n, exceptionState); | 113 Nullable<WebPermissionType> type = parsePermission(scriptState, rawPermissio
n, exceptionState); |
115 if (exceptionState.hadException()) | 114 if (exceptionState.hadException()) |
116 return exceptionState.reject(scriptState); | 115 return exceptionState.reject(scriptState); |
117 | 116 |
| 117 // This must be called after `parsePermission` because the website might |
| 118 // be able to run code. |
| 119 WebPermissionClient* client = getClient(scriptState->getExecutionContext()); |
| 120 if (!client) |
| 121 return ScriptPromise::rejectWithDOMException(scriptState, DOMException::
create(InvalidStateError, "In its current state, the global scope can't query pe
rmissions.")); |
| 122 |
118 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; | 123 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; |
119 ScriptPromise promise = resolver->promise(); | 124 ScriptPromise promise = resolver->promise(); |
120 | 125 |
121 // If the current origin is a file scheme, it will unlikely return a | 126 // 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 | 127 // 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 | 128 // permission prompt will be shown even if the returned permission will most |
124 // likely be "prompt". | 129 // likely be "prompt". |
125 client->queryPermission(type.get(), KURL(KURL(), scriptState->getExecutionCo
ntext()->getSecurityOrigin()->toString()), new PermissionCallback(resolver, type
.get())); | 130 client->queryPermission(type.get(), KURL(KURL(), scriptState->getExecutionCo
ntext()->getSecurityOrigin()->toString()), new PermissionCallback(resolver, type
.get())); |
126 return promise; | 131 return promise; |
127 } | 132 } |
128 | 133 |
129 ScriptPromise Permissions::request(ScriptState* scriptState, const Dictionary& r
awPermission) | 134 ScriptPromise Permissions::request(ScriptState* scriptState, const Dictionary& r
awPermission) |
130 { | 135 { |
131 WebPermissionClient* client = getClient(scriptState->getExecutionContext()); | |
132 if (!client) | |
133 return ScriptPromise::rejectWithDOMException(scriptState, DOMException::
create(InvalidStateError, "In its current state, the global scope can't request
permissions.")); | |
134 | |
135 ExceptionState exceptionState(ExceptionState::GetterContext, "request", "Pe
rmissions", scriptState->context()->Global(), scriptState->isolate()); | 136 ExceptionState exceptionState(ExceptionState::GetterContext, "request", "Pe
rmissions", scriptState->context()->Global(), scriptState->isolate()); |
136 Nullable<WebPermissionType> type = parsePermission(scriptState, rawPermissio
n, exceptionState); | 137 Nullable<WebPermissionType> type = parsePermission(scriptState, rawPermissio
n, exceptionState); |
137 if (exceptionState.hadException()) | 138 if (exceptionState.hadException()) |
138 return exceptionState.reject(scriptState); | 139 return exceptionState.reject(scriptState); |
139 | 140 |
| 141 // This must be called after `parsePermission` because the website might |
| 142 // be able to run code. |
| 143 WebPermissionClient* client = getClient(scriptState->getExecutionContext()); |
| 144 if (!client) |
| 145 return ScriptPromise::rejectWithDOMException(scriptState, DOMException::
create(InvalidStateError, "In its current state, the global scope can't request
permissions.")); |
| 146 |
140 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; | 147 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; |
141 ScriptPromise promise = resolver->promise(); | 148 ScriptPromise promise = resolver->promise(); |
142 | 149 |
143 client->requestPermission(type.get(), KURL(KURL(), scriptState->getExecution
Context()->getSecurityOrigin()->toString()), new PermissionCallback(resolver, ty
pe.get())); | 150 client->requestPermission(type.get(), KURL(KURL(), scriptState->getExecution
Context()->getSecurityOrigin()->toString()), new PermissionCallback(resolver, ty
pe.get())); |
144 return promise; | 151 return promise; |
145 } | 152 } |
146 | 153 |
147 ScriptPromise Permissions::revoke(ScriptState* scriptState, const Dictionary& ra
wPermission) | 154 ScriptPromise Permissions::revoke(ScriptState* scriptState, const Dictionary& ra
wPermission) |
148 { | 155 { |
149 WebPermissionClient* client = getClient(scriptState->getExecutionContext()); | |
150 if (!client) | |
151 return ScriptPromise::rejectWithDOMException(scriptState, DOMException::
create(InvalidStateError, "In its current state, the global scope can't revoke p
ermissions.")); | |
152 | |
153 ExceptionState exceptionState(ExceptionState::GetterContext, "revoke", "Per
missions", scriptState->context()->Global(), scriptState->isolate()); | 156 ExceptionState exceptionState(ExceptionState::GetterContext, "revoke", "Per
missions", scriptState->context()->Global(), scriptState->isolate()); |
154 Nullable<WebPermissionType> type = parsePermission(scriptState, rawPermissio
n, exceptionState); | 157 Nullable<WebPermissionType> type = parsePermission(scriptState, rawPermissio
n, exceptionState); |
155 if (exceptionState.hadException()) | 158 if (exceptionState.hadException()) |
156 return exceptionState.reject(scriptState); | 159 return exceptionState.reject(scriptState); |
157 | 160 |
| 161 // This must be called after `parsePermission` because the website might |
| 162 // be able to run code. |
| 163 WebPermissionClient* client = getClient(scriptState->getExecutionContext()); |
| 164 if (!client) |
| 165 return ScriptPromise::rejectWithDOMException(scriptState, DOMException::
create(InvalidStateError, "In its current state, the global scope can't revoke p
ermissions.")); |
| 166 |
158 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; | 167 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; |
159 ScriptPromise promise = resolver->promise(); | 168 ScriptPromise promise = resolver->promise(); |
160 | 169 |
161 client->revokePermission(type.get(), KURL(KURL(), scriptState->getExecutionC
ontext()->getSecurityOrigin()->toString()), new PermissionCallback(resolver, typ
e.get())); | 170 client->revokePermission(type.get(), KURL(KURL(), scriptState->getExecutionC
ontext()->getSecurityOrigin()->toString()), new PermissionCallback(resolver, typ
e.get())); |
162 return promise; | 171 return promise; |
163 } | 172 } |
164 | 173 |
165 ScriptPromise Permissions::requestAll(ScriptState* scriptState, const Vector<Dic
tionary>& rawPermissions) | 174 ScriptPromise Permissions::requestAll(ScriptState* scriptState, const Vector<Dic
tionary>& rawPermissions) |
166 { | 175 { |
167 WebPermissionClient* client = getClient(scriptState->getExecutionContext()); | |
168 if (!client) | |
169 return ScriptPromise::rejectWithDOMException(scriptState, DOMException::
create(InvalidStateError, "In its current state, the global scope can't request
permissions.")); | |
170 | |
171 ExceptionState exceptionState(ExceptionState::GetterContext, "request", "Pe
rmissions", scriptState->context()->Global(), scriptState->isolate()); | 176 ExceptionState exceptionState(ExceptionState::GetterContext, "request", "Pe
rmissions", scriptState->context()->Global(), scriptState->isolate()); |
172 std::unique_ptr<Vector<WebPermissionType>> internalPermissions = wrapUnique(
new Vector<WebPermissionType>()); | 177 std::unique_ptr<Vector<WebPermissionType>> internalPermissions = wrapUnique(
new Vector<WebPermissionType>()); |
173 std::unique_ptr<Vector<int>> callerIndexToInternalIndex = wrapUnique(new Vec
tor<int>(rawPermissions.size())); | 178 std::unique_ptr<Vector<int>> callerIndexToInternalIndex = wrapUnique(new Vec
tor<int>(rawPermissions.size())); |
174 for (size_t i = 0; i < rawPermissions.size(); ++i) { | 179 for (size_t i = 0; i < rawPermissions.size(); ++i) { |
175 const Dictionary& rawPermission = rawPermissions[i]; | 180 const Dictionary& rawPermission = rawPermissions[i]; |
176 | 181 |
177 Nullable<WebPermissionType> type = parsePermission(scriptState, rawPermi
ssion, exceptionState); | 182 Nullable<WebPermissionType> type = parsePermission(scriptState, rawPermi
ssion, exceptionState); |
178 if (exceptionState.hadException()) | 183 if (exceptionState.hadException()) |
179 return exceptionState.reject(scriptState); | 184 return exceptionState.reject(scriptState); |
180 | 185 |
181 // Only append permissions to the vector that is passed to the client if
it is not already | 186 // 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). | 187 // in the vector (i.e. do not duplicate permisison types). |
183 int internalIndex; | 188 int internalIndex; |
184 auto it = internalPermissions->find(type.get()); | 189 auto it = internalPermissions->find(type.get()); |
185 if (it == kNotFound) { | 190 if (it == kNotFound) { |
186 internalIndex = internalPermissions->size(); | 191 internalIndex = internalPermissions->size(); |
187 internalPermissions->append(type.get()); | 192 internalPermissions->append(type.get()); |
188 } else { | 193 } else { |
189 internalIndex = it; | 194 internalIndex = it; |
190 } | 195 } |
191 callerIndexToInternalIndex->operator[](i) = internalIndex; | 196 callerIndexToInternalIndex->operator[](i) = internalIndex; |
192 } | 197 } |
193 | 198 |
| 199 // This must be called after `parsePermission` because the website might |
| 200 // be able to run code. |
| 201 WebPermissionClient* client = getClient(scriptState->getExecutionContext()); |
| 202 if (!client) |
| 203 return ScriptPromise::rejectWithDOMException(scriptState, DOMException::
create(InvalidStateError, "In its current state, the global scope can't request
permissions.")); |
| 204 |
194 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; | 205 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState)
; |
195 ScriptPromise promise = resolver->promise(); | 206 ScriptPromise promise = resolver->promise(); |
196 | 207 |
197 WebVector<WebPermissionType> internalWebPermissions = *internalPermissions; | 208 WebVector<WebPermissionType> internalWebPermissions = *internalPermissions; |
198 client->requestPermissions(internalWebPermissions, KURL(KURL(), scriptState-
>getExecutionContext()->getSecurityOrigin()->toString()), | 209 client->requestPermissions(internalWebPermissions, KURL(KURL(), scriptState-
>getExecutionContext()->getSecurityOrigin()->toString()), |
199 new PermissionsCallback(resolver, std::move(internalPermissions), std::m
ove(callerIndexToInternalIndex))); | 210 new PermissionsCallback(resolver, std::move(internalPermissions), std::m
ove(callerIndexToInternalIndex))); |
200 return promise; | 211 return promise; |
201 } | 212 } |
202 | 213 |
203 } // namespace blink | 214 } // namespace blink |
OLD | NEW |