Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/sensor/Sensor.h" | 5 #include "modules/sensor/Sensor.h" |
| 6 | 6 |
| 7 #include "core/dom/Document.h" | 7 #include "core/dom/Document.h" |
| 8 #include "core/dom/ExceptionCode.h" | 8 #include "core/dom/ExceptionCode.h" |
| 9 #include "core/dom/ExecutionContextTask.h" | 9 #include "core/dom/ExecutionContextTask.h" |
| 10 #include "core/inspector/ConsoleMessage.h" | 10 #include "core/inspector/ConsoleMessage.h" |
| 11 #include "device/generic_sensor/public/interfaces/sensor.mojom-blink.h" | 11 #include "device/generic_sensor/public/interfaces/sensor.mojom-blink.h" |
| 12 #include "modules/permissions/PermissionUtils.h" | |
| 12 #include "modules/sensor/SensorErrorEvent.h" | 13 #include "modules/sensor/SensorErrorEvent.h" |
| 13 #include "modules/sensor/SensorPollingStrategy.h" | 14 #include "modules/sensor/SensorPollingStrategy.h" |
| 14 #include "modules/sensor/SensorProviderProxy.h" | 15 #include "modules/sensor/SensorProviderProxy.h" |
| 15 #include "modules/sensor/SensorReading.h" | 16 #include "modules/sensor/SensorReading.h" |
| 16 #include "modules/sensor/SensorReadingEvent.h" | 17 #include "modules/sensor/SensorReadingEvent.h" |
| 18 #include "platform/UserGestureIndicator.h" | |
| 17 | 19 |
| 18 using namespace device::mojom::blink; | 20 using namespace device::mojom::blink; |
| 19 | 21 |
| 20 namespace blink { | 22 namespace blink { |
| 21 | 23 |
| 24 using mojom::blink::PermissionName; | |
| 25 using mojom::blink::PermissionService; | |
| 26 using mojom::blink::PermissionStatus; | |
| 27 | |
| 22 Sensor::Sensor(ScriptState* scriptState, | 28 Sensor::Sensor(ScriptState* scriptState, |
| 23 const SensorOptions& sensorOptions, | 29 const SensorOptions& sensorOptions, |
| 24 ExceptionState& exceptionState, | 30 ExceptionState& exceptionState, |
| 25 SensorType type) | 31 SensorType type) |
| 26 : ActiveScriptWrappable(this), | 32 : ActiveScriptWrappable(this), |
| 27 ContextLifecycleObserver(scriptState->getExecutionContext()), | 33 ContextLifecycleObserver(scriptState->getExecutionContext()), |
| 28 PageVisibilityObserver( | 34 PageVisibilityObserver( |
| 29 toDocument(scriptState->getExecutionContext())->page()), | 35 toDocument(scriptState->getExecutionContext())->page()), |
| 30 m_sensorOptions(sensorOptions), | 36 m_sensorOptions(sensorOptions), |
| 31 m_type(type), | 37 m_type(type), |
| 32 m_state(Sensor::SensorState::IDLE), | 38 m_state(Sensor::SensorState::IDLE), |
| 33 m_storedData() { | 39 m_storedData(), |
| 40 m_sensorPermission(PermissionStatus::ASK) { | |
| 34 // Check secure context. | 41 // Check secure context. |
| 35 String errorMessage; | 42 String errorMessage; |
| 36 if (!scriptState->getExecutionContext()->isSecureContext(errorMessage)) { | 43 if (!scriptState->getExecutionContext()->isSecureContext(errorMessage)) { |
| 37 exceptionState.throwDOMException(SecurityError, errorMessage); | 44 exceptionState.throwDOMException(SecurityError, errorMessage); |
| 38 return; | 45 return; |
| 39 } | 46 } |
| 40 | 47 |
| 41 // Check top-level browsing context. | 48 // Check top-level browsing context. |
| 42 if (!scriptState->domWindow() || !scriptState->domWindow()->frame() || | 49 if (!scriptState->domWindow() || !scriptState->domWindow()->frame() || |
| 43 !scriptState->domWindow()->frame()->isMainFrame()) { | 50 !scriptState->domWindow()->frame()->isMainFrame()) { |
| 44 exceptionState.throwSecurityError( | 51 exceptionState.throwSecurityError( |
| 45 "Must be in a top-level browsing context"); | 52 "Must be in a top-level browsing context"); |
| 46 return; | 53 return; |
| 47 } | 54 } |
| 48 | 55 |
| 56 // Get permission service. | |
| 57 PermissionService* permissionService = | |
| 58 getPermissionService(scriptState->getExecutionContext()); | |
| 59 | |
| 60 if (!permissionService) { | |
| 61 exceptionState.throwDOMException( | |
| 62 InvalidStateError, | |
| 63 "In its current state, the global scope can't request permissions"); | |
| 64 } | |
| 65 | |
| 49 // Check the given frequency value. | 66 // Check the given frequency value. |
| 50 if (m_sensorOptions.hasFrequency()) { | 67 if (m_sensorOptions.hasFrequency()) { |
| 51 double frequency = m_sensorOptions.frequency(); | 68 double frequency = m_sensorOptions.frequency(); |
| 52 if (frequency <= 0.0) { | 69 if (frequency <= 0.0) { |
| 53 exceptionState.throwRangeError("Frequency must be positive."); | 70 exceptionState.throwRangeError("Frequency must be positive."); |
| 54 return; | 71 return; |
| 55 } | 72 } |
| 56 | 73 |
| 57 if (frequency > SensorConfiguration::kMaxAllowedFrequency) { | 74 if (frequency > SensorConfiguration::kMaxAllowedFrequency) { |
| 58 m_sensorOptions.setFrequency(SensorConfiguration::kMaxAllowedFrequency); | 75 m_sensorOptions.setFrequency(SensorConfiguration::kMaxAllowedFrequency); |
| 59 ConsoleMessage* consoleMessage = ConsoleMessage::create( | 76 ConsoleMessage* consoleMessage = ConsoleMessage::create( |
| 60 JSMessageSource, InfoMessageLevel, "Frequency is limited to 60 Hz."); | 77 JSMessageSource, InfoMessageLevel, "Frequency is limited to 60 Hz."); |
| 61 scriptState->getExecutionContext()->addConsoleMessage(consoleMessage); | 78 scriptState->getExecutionContext()->addConsoleMessage(consoleMessage); |
| 62 } | 79 } |
| 63 } | 80 } |
| 64 } | 81 } |
| 65 | 82 |
| 66 Sensor::~Sensor() = default; | 83 Sensor::~Sensor() { |
| 84 m_permissionService.reset(); | |
| 85 } | |
| 86 | |
| 87 void Sensor::permissionServiceConnectionError() { | |
| 88 m_permissionService.reset(); | |
| 89 } | |
| 90 | |
| 91 PermissionService* Sensor::getPermissionService( | |
| 92 ExecutionContext* executionContext) { | |
| 93 if (!m_permissionService && | |
| 94 connectToPermissionService(executionContext, | |
| 95 mojo::GetProxy(&m_permissionService))) { | |
| 96 m_permissionService.set_connection_error_handler(convertToBaseCallback( | |
| 97 WTF::bind(&Sensor::permissionServiceConnectionError, | |
| 98 wrapWeakPersistent(this)))); | |
| 99 } | |
| 100 return m_permissionService.get(); | |
| 101 } | |
| 67 | 102 |
| 68 void Sensor::start(ScriptState* scriptState, ExceptionState& exceptionState) { | 103 void Sensor::start(ScriptState* scriptState, ExceptionState& exceptionState) { |
| 69 if (m_state != Sensor::SensorState::IDLE && | 104 if (m_state != Sensor::SensorState::IDLE && |
| 70 m_state != Sensor::SensorState::ERRORED) { | 105 m_state != Sensor::SensorState::ERRORED) { |
| 71 exceptionState.throwDOMException( | 106 exceptionState.throwDOMException( |
| 72 InvalidStateError, | 107 InvalidStateError, |
| 73 "Cannot start because SensorState is not idle or errored"); | 108 "Cannot start because SensorState is not idle or errored"); |
| 74 return; | 109 return; |
| 75 } | 110 } |
| 76 | 111 |
| 77 initSensorProxyIfNeeded(); | 112 initSensorProxyIfNeeded(); |
| 78 | 113 |
| 79 if (!m_sensorProxy) { | 114 if (!m_sensorProxy) { |
| 80 exceptionState.throwDOMException( | 115 exceptionState.throwDOMException( |
| 81 InvalidStateError, "The Sensor is no longer associated to a frame."); | 116 InvalidStateError, "The Sensor is no longer associated to a frame."); |
| 82 return; | 117 return; |
| 83 } | 118 } |
| 84 | 119 |
| 85 startListening(); | 120 // If the algorithm is not allowed to show a popup, throw SecurityError. |
| 121 if (!UserGestureIndicator::consumeUserGesture()) { | |
| 122 exceptionState.throwDOMException( | |
| 123 SecurityError, | |
| 124 "Must be handling a user gesture to show a permission request."); | |
| 125 return; | |
| 126 } | |
| 127 | |
| 128 // Check permissions. | |
| 129 m_permissionService->HasPermission( | |
|
shalamov
2016/10/27 08:47:25
What happens if you call start(), then permission
| |
| 130 createPermissionDescriptor(PermissionName::SENSORS), | |
| 131 scriptState->getExecutionContext()->getSecurityOrigin(), | |
| 132 convertToBaseCallback( | |
| 133 WTF::bind(&Sensor::onPermissionUpdate, wrapPersistent(this), | |
| 134 wrapPersistent(scriptState->getExecutionContext())))); | |
| 135 | |
| 136 // Keep listening for next change in permission. | |
| 137 // TODO(riju): Re-use same onPermissionUpdate callback for everything? | |
| 138 m_permissionService->GetNextPermissionChange( | |
|
shalamov
2016/10/27 08:47:25
I think logic should be different.
Initially we d
| |
| 139 createPermissionDescriptor(PermissionName::SENSORS), | |
| 140 scriptState->getExecutionContext()->getSecurityOrigin(), | |
| 141 m_sensorPermission, | |
| 142 convertToBaseCallback( | |
| 143 WTF::bind(&Sensor::onPermissionUpdate, wrapPersistent(this), | |
| 144 wrapPersistent(scriptState->getExecutionContext())))); | |
| 145 } | |
| 146 | |
| 147 void Sensor::requestPermission(ExecutionContext* executionContext, | |
| 148 PermissionStatus status) { | |
| 149 m_permissionService->RequestPermission( | |
| 150 createPermissionDescriptor(PermissionName::SENSORS), | |
| 151 executionContext->getSecurityOrigin(), | |
| 152 UserGestureIndicator::processingUserGesture(), | |
| 153 convertToBaseCallback(WTF::bind(&Sensor::onPermissionUpdate, | |
| 154 wrapPersistent(this), | |
| 155 wrapPersistent(executionContext)))); | |
| 156 } | |
| 157 | |
| 158 void Sensor::onPermissionUpdate(ExecutionContext* executionContext, | |
|
shalamov
2016/10/27 08:47:25
I think permission checking should not be bound to
| |
| 159 PermissionStatus status) { | |
| 160 m_sensorPermission = status; | |
| 161 | |
| 162 // m_permissionService.reset(); | |
| 163 | |
| 164 if (m_sensorPermission == PermissionStatus::GRANTED) { | |
| 165 startListening(); | |
|
shalamov
2016/10/27 08:47:25
ditto, what if user called stop() before permissio
| |
| 166 } else if (m_sensorPermission == PermissionStatus::ASK) { | |
| 167 requestPermission(executionContext, status); | |
| 168 } else if (m_sensorPermission == PermissionStatus::DENIED) { | |
| 169 stopListening(); | |
| 170 | |
| 171 ConsoleMessage* consoleMessage = ConsoleMessage::create( | |
| 172 JSMessageSource, InfoMessageLevel, "Permission Rejected."); | |
| 173 executionContext->addConsoleMessage(consoleMessage); | |
| 174 | |
| 175 reportError(PermissionDeniedError, | |
| 176 "start() call has failed as permission was denied."); | |
| 177 } | |
| 86 } | 178 } |
| 87 | 179 |
| 88 void Sensor::stop(ScriptState*, ExceptionState& exceptionState) { | 180 void Sensor::stop(ScriptState*, ExceptionState& exceptionState) { |
| 89 if (m_state == Sensor::SensorState::IDLE || | 181 if (m_state == Sensor::SensorState::IDLE || |
| 90 m_state == Sensor::SensorState::ERRORED) { | 182 m_state == Sensor::SensorState::ERRORED) { |
| 91 exceptionState.throwDOMException( | 183 exceptionState.throwDOMException( |
| 92 InvalidStateError, | 184 InvalidStateError, |
| 93 "Cannot stop because SensorState is either idle or errored"); | 185 "Cannot stop because SensorState is either idle or errored"); |
| 94 return; | 186 return; |
| 95 } | 187 } |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 147 return; | 239 return; |
| 148 | 240 |
| 149 m_sensorProxy = | 241 m_sensorProxy = |
| 150 SensorProviderProxy::from(document->frame())->getOrCreateSensor(m_type); | 242 SensorProviderProxy::from(document->frame())->getOrCreateSensor(m_type); |
| 151 } | 243 } |
| 152 | 244 |
| 153 void Sensor::contextDestroyed() { | 245 void Sensor::contextDestroyed() { |
| 154 if (m_state == Sensor::SensorState::ACTIVE || | 246 if (m_state == Sensor::SensorState::ACTIVE || |
| 155 m_state == Sensor::SensorState::ACTIVATING) | 247 m_state == Sensor::SensorState::ACTIVATING) |
| 156 stopListening(); | 248 stopListening(); |
| 249 m_permissionService.reset(); | |
| 157 } | 250 } |
| 158 | 251 |
| 159 void Sensor::onSensorInitialized() { | 252 void Sensor::onSensorInitialized() { |
| 160 if (m_state != Sensor::SensorState::ACTIVATING) | 253 if (m_state != Sensor::SensorState::ACTIVATING) |
| 161 return; | 254 return; |
| 162 | 255 |
| 163 startListening(); | 256 startListening(); |
| 164 } | 257 } |
| 165 | 258 |
| 166 void Sensor::onSensorReadingChanged() { | 259 void Sensor::onSensorReadingChanged() { |
| (...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 331 void Sensor::notifyStateChanged() { | 424 void Sensor::notifyStateChanged() { |
| 332 dispatchEvent(Event::create(EventTypeNames::statechange)); | 425 dispatchEvent(Event::create(EventTypeNames::statechange)); |
| 333 } | 426 } |
| 334 | 427 |
| 335 void Sensor::notifyError(DOMException* error) { | 428 void Sensor::notifyError(DOMException* error) { |
| 336 dispatchEvent( | 429 dispatchEvent( |
| 337 SensorErrorEvent::create(EventTypeNames::error, std::move(error))); | 430 SensorErrorEvent::create(EventTypeNames::error, std::move(error))); |
| 338 } | 431 } |
| 339 | 432 |
| 340 } // namespace blink | 433 } // namespace blink |
| OLD | NEW |