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

Side by Side Diff: third_party/WebKit/Source/modules/sensor/Sensor.cpp

Issue 2458453002: [sensors] Add Permission guard to the generic sensor apis.
Patch Set: Created 4 years, 1 month 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 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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698