Chromium Code Reviews| 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 "config.h" | 5 #include "config.h" |
| 6 #include "modules/permissions/Permissions.h" | 6 #include "modules/permissions/Permissions.h" |
| 7 | 7 |
| 8 #include "bindings/core/v8/Dictionary.h" | 8 #include "bindings/core/v8/Dictionary.h" |
| 9 #include "bindings/core/v8/Nullable.h" | |
| 9 #include "bindings/core/v8/ScriptPromise.h" | 10 #include "bindings/core/v8/ScriptPromise.h" |
| 10 #include "bindings/core/v8/ScriptPromiseResolver.h" | 11 #include "bindings/core/v8/ScriptPromiseResolver.h" |
| 11 #include "bindings/modules/v8/V8MidiPermissionDescriptor.h" | 12 #include "bindings/modules/v8/V8MidiPermissionDescriptor.h" |
| 12 #include "bindings/modules/v8/V8PermissionDescriptor.h" | 13 #include "bindings/modules/v8/V8PermissionDescriptor.h" |
| 13 #include "bindings/modules/v8/V8PushPermissionDescriptor.h" | 14 #include "bindings/modules/v8/V8PushPermissionDescriptor.h" |
| 14 #include "core/dom/DOMException.h" | 15 #include "core/dom/DOMException.h" |
| 15 #include "core/dom/Document.h" | 16 #include "core/dom/Document.h" |
| 16 #include "core/dom/ExceptionCode.h" | 17 #include "core/dom/ExceptionCode.h" |
| 17 #include "modules/permissions/PermissionCallback.h" | 18 #include "modules/permissions/PermissionCallback.h" |
| 18 #include "modules/permissions/PermissionController.h" | 19 #include "modules/permissions/PermissionController.h" |
| 19 #include "modules/permissions/PermissionDescriptor.h" | 20 #include "modules/permissions/PermissionDescriptor.h" |
| 20 #include "modules/permissions/PermissionStatus.h" | 21 #include "modules/permissions/PermissionStatus.h" |
| 21 #include "modules/permissions/PermissionsCallback.h" | 22 #include "modules/permissions/PermissionsCallback.h" |
| 22 #include "platform/Logging.h" | 23 #include "platform/Logging.h" |
| 23 #include "public/platform/Platform.h" | 24 #include "public/platform/Platform.h" |
| 24 #include "public/platform/modules/permissions/WebPermissionClient.h" | 25 #include "public/platform/modules/permissions/WebPermissionClient.h" |
| 25 | 26 |
| 26 namespace blink { | 27 namespace blink { |
| 27 | 28 |
| 28 namespace { | 29 namespace { |
| 29 | 30 |
| 30 // Here we eagerly reject any permissions that we do not support. | 31 WebPermissionType getPermissionType(ScriptState* scriptState, const Dictionary& rawPermission, const PermissionDescriptor& permission, ExceptionState& exception State) |
| 31 // If the permission is handled here, it will not be propogated up to the conten t layer. | |
| 32 // The return value indicates if the permissions has been handled by the funcito n. | |
| 33 bool handleNotSupportedPermission( | |
| 34 ScriptState* scriptState, const Dictionary& rawPermission, ScriptPromiseReso lver* resolver, WebPermissionType type, TrackExceptionState& exceptionState) | |
| 35 { | |
| 36 if (type == WebPermissionTypePushNotifications) { | |
| 37 PushPermissionDescriptor pushPermission = NativeValueTraits<PushPermissi onDescriptor>::nativeValue(scriptState->isolate(), rawPermission.v8Value(), exce ptionState); | |
| 38 // Only "userVisibleOnly" push is supported for now. | |
| 39 if (!pushPermission.userVisibleOnly()) { | |
| 40 resolver->reject(DOMException::create(NotSupportedError, "Push Permi ssion without userVisibleOnly:true isn't supported yet.")); | |
| 41 return true; | |
| 42 } | |
| 43 } | |
| 44 return false; | |
| 45 } | |
| 46 | |
| 47 WebPermissionType getPermissionType(ScriptState* scriptState, const Dictionary& rawPermission, const PermissionDescriptor& permission, TrackExceptionState& exce ptionState) | |
| 48 { | 32 { |
| 49 const String& name = permission.name(); | 33 const String& name = permission.name(); |
| 50 if (name == "geolocation") | 34 if (name == "geolocation") |
| 51 return WebPermissionTypeGeolocation; | 35 return WebPermissionTypeGeolocation; |
| 52 if (name == "notifications") | 36 if (name == "notifications") |
| 53 return WebPermissionTypeNotifications; | 37 return WebPermissionTypeNotifications; |
| 54 if (name == "push") | 38 if (name == "push") |
| 55 return WebPermissionTypePushNotifications; | 39 return WebPermissionTypePushNotifications; |
| 56 if (name == "midi") { | 40 if (name == "midi") { |
| 57 MidiPermissionDescriptor midiPermission = NativeValueTraits<MidiPermissi onDescriptor>::nativeValue(scriptState->isolate(), rawPermission.v8Value(), exce ptionState); | 41 MidiPermissionDescriptor midiPermission = NativeValueTraits<MidiPermissi onDescriptor>::nativeValue(scriptState->isolate(), rawPermission.v8Value(), exce ptionState); |
| 58 return midiPermission.sysex() ? WebPermissionTypeMidiSysEx : WebPermissi onTypeMidi; | 42 return midiPermission.sysex() ? WebPermissionTypeMidiSysEx : WebPermissi onTypeMidi; |
| 59 } | 43 } |
| 60 | 44 |
| 61 ASSERT_NOT_REACHED(); | 45 ASSERT_NOT_REACHED(); |
| 62 return WebPermissionTypeGeolocation; | 46 return WebPermissionTypeGeolocation; |
| 63 } | 47 } |
| 64 | 48 |
| 49 Nullable<WebPermissionType> parsePermission(ScriptState* scriptState, const Dict ionary rawPermission, ExceptionState& exceptionState) | |
|
mlamouri (slow - plz ping)
2015/09/28 10:48:43
This need some documentation :)
Lalit Maganti
2015/09/28 12:23:09
Done.
| |
| 50 { | |
| 51 PermissionDescriptor permission = NativeValueTraits<PermissionDescriptor>::n ativeValue(scriptState->isolate(), rawPermission.v8Value(), exceptionState); | |
| 52 | |
| 53 if (exceptionState.hadException()) { | |
| 54 exceptionState.throwTypeError(exceptionState.message()); | |
| 55 return Nullable<WebPermissionType>(); | |
| 56 } | |
| 57 | |
| 58 WebPermissionType type = getPermissionType(scriptState, rawPermission, permi ssion, exceptionState); | |
| 59 if (exceptionState.hadException()) { | |
| 60 exceptionState.throwTypeError(exceptionState.message()); | |
| 61 return Nullable<WebPermissionType>(); | |
| 62 } | |
| 63 | |
| 64 // Here we reject any permissions which are not yet supported by Blink. | |
| 65 if (type == WebPermissionTypePushNotifications) { | |
| 66 PushPermissionDescriptor pushPermission = NativeValueTraits<PushPermissi onDescriptor>::nativeValue(scriptState->isolate(), rawPermission.v8Value(), exce ptionState); | |
| 67 if (exceptionState.hadException()) { | |
| 68 exceptionState.throwTypeError(exceptionState.message()); | |
| 69 return Nullable<WebPermissionType>(); | |
| 70 } | |
| 71 | |
| 72 // Only "userVisibleOnly" push is supported for now. | |
| 73 if (!pushPermission.userVisibleOnly()) { | |
| 74 exceptionState.throwDOMException(NotSupportedError, "Push Permission without userVisibleOnly:true isn't supported yet."); | |
| 75 return Nullable<WebPermissionType>(); | |
| 76 } | |
| 77 } | |
| 78 | |
| 79 return Nullable<WebPermissionType>(type); | |
| 80 } | |
| 81 | |
| 65 } // anonymous namespace | 82 } // anonymous namespace |
| 66 | 83 |
| 67 // static | 84 // static |
| 68 WebPermissionClient* Permissions::getClient(ExecutionContext* executionContext) | 85 WebPermissionClient* Permissions::getClient(ExecutionContext* executionContext) |
| 69 { | 86 { |
| 70 if (executionContext->isDocument()) { | 87 if (executionContext->isDocument()) { |
| 71 Document* document = toDocument(executionContext); | 88 Document* document = toDocument(executionContext); |
| 72 if (!document->frame()) | 89 if (!document->frame()) |
| 73 return nullptr; | 90 return nullptr; |
| 74 PermissionController* controller = PermissionController::from(*document- >frame()); | 91 PermissionController* controller = PermissionController::from(*document- >frame()); |
| 75 return controller ? controller->client() : nullptr; | 92 return controller ? controller->client() : nullptr; |
| 76 } | 93 } |
| 77 return Platform::current()->permissionClient(); | 94 return Platform::current()->permissionClient(); |
| 78 } | 95 } |
| 79 | 96 |
| 80 ScriptPromise Permissions::query(ScriptState* scriptState, const Dictionary& raw Permission) | 97 ScriptPromise Permissions::query(ScriptState* scriptState, const Dictionary& raw Permission) |
| 81 { | 98 { |
| 82 WebPermissionClient* client = getClient(scriptState->executionContext()); | 99 WebPermissionClient* client = getClient(scriptState->executionContext()); |
| 83 if (!client) | 100 if (!client) |
| 84 return ScriptPromise::rejectWithDOMException(scriptState, DOMException:: create(InvalidStateError, "In its current state, the global scope can't query pe rmissions.")); | 101 return ScriptPromise::rejectWithDOMException(scriptState, DOMException:: create(InvalidStateError, "In its current state, the global scope can't query pe rmissions.")); |
| 85 | 102 |
| 86 TrackExceptionState exceptionState; | 103 ExceptionState exceptionState(ExceptionState::UnknownContext, nullptr, nullp tr, scriptState->context()->Global(), scriptState->isolate()); |
|
mlamouri (slow - plz ping)
2015/09/28 10:48:43
Why not passing: |ExceptionState::GetterContext, "
Lalit Maganti
2015/09/28 12:23:09
Makes a lot of sense. I scoured code search to fig
| |
| 87 PermissionDescriptor permission = NativeValueTraits<PermissionDescriptor>::n ativeValue(scriptState->isolate(), rawPermission.v8Value(), exceptionState); | 104 Nullable<WebPermissionType> type = parsePermission(scriptState, rawPermissio n, exceptionState); |
| 88 | |
| 89 if (exceptionState.hadException()) | 105 if (exceptionState.hadException()) |
| 90 return ScriptPromise::reject(scriptState, v8::Exception::TypeError(v8Str ing(scriptState->isolate(), exceptionState.message()))); | 106 return exceptionState.reject(scriptState); |
| 91 | 107 |
| 92 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState) ; | 108 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState) ; |
| 93 ScriptPromise promise = resolver->promise(); | 109 ScriptPromise promise = resolver->promise(); |
| 94 | 110 |
| 95 WebPermissionType type = getPermissionType(scriptState, rawPermission, permi ssion, exceptionState); | |
| 96 if (handleNotSupportedPermission(scriptState, rawPermission, resolver, type, exceptionState)) | |
| 97 return promise; | |
| 98 | |
| 99 // If the current origin is a file scheme, it will unlikely return a | 111 // If the current origin is a file scheme, it will unlikely return a |
| 100 // meaningful value because most APIs are broken on file scheme and no | 112 // meaningful value because most APIs are broken on file scheme and no |
| 101 // permission prompt will be shown even if the returned permission will most | 113 // permission prompt will be shown even if the returned permission will most |
| 102 // likely be "prompt". | 114 // likely be "prompt". |
| 103 client->queryPermission(type, KURL(KURL(), scriptState->executionContext()-> securityOrigin()->toString()), new PermissionCallback(resolver, type)); | 115 client->queryPermission(type.get(), KURL(KURL(), scriptState->executionConte xt()->securityOrigin()->toString()), new PermissionCallback(resolver, type.get() )); |
| 104 return promise; | 116 return promise; |
| 105 } | 117 } |
| 106 | 118 |
| 107 ScriptPromise Permissions::request(ScriptState* scriptState, const Dictionary& r awPermission) | 119 ScriptPromise Permissions::request(ScriptState* scriptState, const Dictionary& r awPermission) |
| 108 { | 120 { |
| 109 WebPermissionClient* client = getClient(scriptState->executionContext()); | 121 WebPermissionClient* client = getClient(scriptState->executionContext()); |
| 110 if (!client) | 122 if (!client) |
| 111 return ScriptPromise::rejectWithDOMException(scriptState, DOMException:: create(InvalidStateError, "In its current state, the global scope can't request permissions.")); | 123 return ScriptPromise::rejectWithDOMException(scriptState, DOMException:: create(InvalidStateError, "In its current state, the global scope can't request permissions.")); |
| 112 | 124 |
| 113 TrackExceptionState exceptionState; | 125 ExceptionState exceptionState(ExceptionState::UnknownContext, nullptr, nullp tr, scriptState->context()->Global(), scriptState->isolate()); |
|
mlamouri (slow - plz ping)
2015/09/28 10:48:43
ditto with "request"
Lalit Maganti
2015/09/28 12:23:09
Done.
| |
| 114 PermissionDescriptor permission = NativeValueTraits<PermissionDescriptor>::n ativeValue(scriptState->isolate(), rawPermission.v8Value(), exceptionState); | 126 Nullable<WebPermissionType> type = parsePermission(scriptState, rawPermissio n, exceptionState); |
|
mlamouri (slow - plz ping)
2015/09/28 10:48:43
So here you use |Nullable<>| but you don't actuall
Lalit Maganti
2015/09/28 12:23:09
Done.
| |
| 115 | |
| 116 if (exceptionState.hadException()) | 127 if (exceptionState.hadException()) |
| 117 return ScriptPromise::reject(scriptState, v8::Exception::TypeError(v8Str ing(scriptState->isolate(), exceptionState.message()))); | 128 return exceptionState.reject(scriptState); |
| 118 | 129 |
| 119 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState) ; | 130 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState) ; |
| 120 ScriptPromise promise = resolver->promise(); | 131 ScriptPromise promise = resolver->promise(); |
| 121 | 132 |
| 122 WebPermissionType type = getPermissionType(scriptState, rawPermission, permi ssion, exceptionState); | 133 client->requestPermission(type.get(), KURL(KURL(), scriptState->executionCon text()->securityOrigin()->toString()), new PermissionCallback(resolver, type.get ())); |
| 123 if (handleNotSupportedPermission(scriptState, rawPermission, resolver, type, exceptionState)) | |
| 124 return promise; | |
| 125 | |
| 126 client->requestPermission(type, KURL(KURL(), scriptState->executionContext() ->securityOrigin()->toString()), new PermissionCallback(resolver, type)); | |
| 127 return promise; | 134 return promise; |
| 128 } | 135 } |
| 129 | 136 |
| 130 ScriptPromise Permissions::request(ScriptState* scriptState, const Vector<Dictio nary>& rawPermissions) | 137 ScriptPromise Permissions::request(ScriptState* scriptState, const Vector<Dictio nary>& rawPermissions) |
| 131 { | 138 { |
| 132 WebPermissionClient* client = getClient(scriptState->executionContext()); | 139 WebPermissionClient* client = getClient(scriptState->executionContext()); |
| 133 if (!client) | 140 if (!client) |
| 134 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.")); |
| 135 | 142 |
| 136 TrackExceptionState exceptionState; | 143 ExceptionState exceptionState(ExceptionState::UnknownContext, nullptr, nullp tr, scriptState->context()->Global(), scriptState->isolate()); |
|
mlamouri (slow - plz ping)
2015/09/28 10:48:43
ditto with "request"
Lalit Maganti
2015/09/28 12:23:09
Done.
| |
| 137 OwnPtr<WebVector<WebPermissionType>> permissions = adoptPtr(new WebVector<We bPermissionType>(rawPermissions.size())); | 144 OwnPtr<WebVector<WebPermissionType>> permissions = adoptPtr(new WebVector<We bPermissionType>(rawPermissions.size())); |
| 138 | |
| 139 for (size_t i = 0; i < rawPermissions.size(); ++i) { | 145 for (size_t i = 0; i < rawPermissions.size(); ++i) { |
| 140 const Dictionary& rawPermission = rawPermissions[i]; | 146 const Dictionary& rawPermission = rawPermissions[i]; |
| 141 PermissionDescriptor permission = NativeValueTraits<PermissionDescriptor >::nativeValue(scriptState->isolate(), rawPermission.v8Value(), exceptionState); | |
| 142 | 147 |
| 148 Nullable<WebPermissionType> type = parsePermission(scriptState, rawPermi ssion, exceptionState); | |
| 143 if (exceptionState.hadException()) | 149 if (exceptionState.hadException()) |
| 144 return ScriptPromise::reject(scriptState, v8::Exception::TypeError(v 8String(scriptState->isolate(), exceptionState.message()))); | 150 return exceptionState.reject(scriptState); |
| 145 | 151 |
| 146 permissions->operator[](i) = getPermissionType(scriptState, rawPermissio n, permission, exceptionState); | 152 permissions->operator[](i) = type.get(); |
| 147 } | 153 } |
| 148 | 154 |
| 149 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState) ; | 155 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState) ; |
| 150 ScriptPromise promise = resolver->promise(); | 156 ScriptPromise promise = resolver->promise(); |
| 151 | 157 |
| 152 // We need to do this is a separate loop because we can't create the Resolve r and Promise untile we are clear of all parsing/type errors. | |
| 153 for (size_t i = 0; i < rawPermissions.size(); ++i) { | |
| 154 if (handleNotSupportedPermission(scriptState, rawPermissions[i], resolve r, (*permissions)[i], exceptionState)) | |
| 155 return promise; | |
| 156 } | |
| 157 | |
| 158 client->requestPermissions(*permissions, KURL(KURL(), scriptState->execution Context()->securityOrigin()->toString()), new PermissionsCallback(resolver, perm issions.release())); | 158 client->requestPermissions(*permissions, KURL(KURL(), scriptState->execution Context()->securityOrigin()->toString()), new PermissionsCallback(resolver, perm issions.release())); |
| 159 return promise; | 159 return promise; |
| 160 } | 160 } |
| 161 | 161 |
| 162 ScriptPromise Permissions::revoke(ScriptState* scriptState, const Dictionary& ra wPermission) | 162 ScriptPromise Permissions::revoke(ScriptState* scriptState, const Dictionary& ra wPermission) |
| 163 { | 163 { |
| 164 WebPermissionClient* client = getClient(scriptState->executionContext()); | 164 WebPermissionClient* client = getClient(scriptState->executionContext()); |
| 165 if (!client) | 165 if (!client) |
| 166 return ScriptPromise::rejectWithDOMException(scriptState, DOMException:: create(InvalidStateError, "In its current state, the global scope can't revoke p ermissions.")); | 166 return ScriptPromise::rejectWithDOMException(scriptState, DOMException:: create(InvalidStateError, "In its current state, the global scope can't revoke p ermissions.")); |
| 167 | 167 |
| 168 TrackExceptionState exceptionState; | 168 ExceptionState exceptionState(ExceptionState::UnknownContext, nullptr, nullp tr, scriptState->context()->Global(), scriptState->isolate()); |
|
mlamouri (slow - plz ping)
2015/09/28 10:48:43
ditto with "revoke"
Lalit Maganti
2015/09/28 12:23:09
Done.
| |
| 169 PermissionDescriptor permission = NativeValueTraits<PermissionDescriptor>::n ativeValue(scriptState->isolate(), rawPermission.v8Value(), exceptionState); | 169 Nullable<WebPermissionType> type = parsePermission(scriptState, rawPermissio n, exceptionState); |
| 170 | |
| 171 if (exceptionState.hadException()) | 170 if (exceptionState.hadException()) |
| 172 return ScriptPromise::reject(scriptState, v8::Exception::TypeError(v8Str ing(scriptState->isolate(), exceptionState.message()))); | 171 return exceptionState.reject(scriptState); |
| 173 | 172 |
| 174 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState) ; | 173 ScriptPromiseResolver* resolver = ScriptPromiseResolver::create(scriptState) ; |
| 175 ScriptPromise promise = resolver->promise(); | 174 ScriptPromise promise = resolver->promise(); |
| 176 | 175 |
| 177 WebPermissionType type = getPermissionType(scriptState, rawPermission, permi ssion, exceptionState); | 176 client->revokePermission(type.get(), KURL(KURL(), scriptState->executionCont ext()->securityOrigin()->toString()), new PermissionCallback(resolver, type.get( ))); |
| 178 if (handleNotSupportedPermission(scriptState, rawPermission, resolver, type, exceptionState)) | |
| 179 return promise; | |
| 180 | |
| 181 client->revokePermission(type, KURL(KURL(), scriptState->executionContext()- >securityOrigin()->toString()), new PermissionCallback(resolver, type)); | |
| 182 return promise; | 177 return promise; |
| 183 } | 178 } |
| 184 | 179 |
| 185 } // namespace blink | 180 } // namespace blink |
| OLD | NEW |