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 |