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

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

Issue 2121313002: [sensors] Generic Sensors Framework blink side (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@sensors_mojo_interfaces
Patch Set: Rebased Created 4 years, 3 months 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 "device/generic_sensor/public/interfaces/sensor.mojom-blink.h"
10 #include "core/events/Event.h" 10 #include "modules/sensor/SensorErrorEvent.h"
11 11 #include "modules/sensor/SensorPollingStrategy.h"
12 #include "modules/sensor/SensorProviderProxy.h"
12 #include "modules/sensor/SensorReading.h" 13 #include "modules/sensor/SensorReading.h"
14 #include "modules/sensor/SensorReadingEvent.h"
15
16 using namespace device::mojom::blink;
13 17
14 namespace blink { 18 namespace blink {
15 19
16 Sensor::~Sensor() 20 Sensor::Sensor(ExecutionContext* executionContext, const SensorOptions& sensorOp tions, device::mojom::blink::SensorType type)
17 {
18 }
19
20 Sensor::Sensor(ExecutionContext* executionContext, const SensorOptions& sensorOp tions)
21 : ActiveScriptWrappable(this) 21 : ActiveScriptWrappable(this)
22 , ActiveDOMObject(executionContext) 22 , ActiveDOMObject(executionContext)
23 , PlatformEventController(toDocument(executionContext)->page()) 23 , PageVisibilityObserver(toDocument(executionContext)->page())
24 , m_sensorState(SensorState::Idle)
25 , m_sensorReading(nullptr)
26 , m_sensorOptions(sensorOptions) 24 , m_sensorOptions(sensorOptions)
27 { 25 , m_type(type)
26 , m_state(Sensor::SensorState::IDLE)
27 {
28 DCHECK(executionContext->isDocument());
29 }
30
31 void Sensor::dispose()
32 {
33 stopListening();
34 }
35
36 void Sensor::start(ScriptState* scriptState, ExceptionState& exceptionState)
37 {
38 if (m_state != Sensor::SensorState::IDLE && m_state != Sensor::SensorState:: ERRORED) {
39 exceptionState.throwDOMException(InvalidStateError, "Invalid State: Sens orState is not idle or errored");
timvolodine 2016/08/25 17:52:32 error message not very specific, maybe better some
Mikhail 2016/08/26 16:42:41 This if condition is coming from spec https://w3c.
timvolodine 2016/09/01 19:02:05 yes, that sounds more informative compared to just
40 return;
41 }
42
43 initSensorProxyIfNeeded();
44
45 if (!m_sensorProxy) {
46 exceptionState.throwDOMException(InvalidStateError, "The Sensor is no lo nger associated to a frame.");
timvolodine 2016/08/25 17:52:32 when can this happen? and should this ever happen?
Mikhail 2016/08/26 16:42:41 document might not be always associated with a fra
47 return;
48 }
49
50 updateState(Sensor::SensorState::ACTIVATING);
51
52 startListening();
53 }
54
55 void Sensor::stop(ScriptState*, ExceptionState& exceptionState)
56 {
57 if (m_state == Sensor::SensorState::IDLE || m_state == Sensor::SensorState:: ERRORED) {
58 exceptionState.throwDOMException(InvalidStateError, "Invalid State: Sens orState is either idle or errored");
timvolodine 2016/08/25 17:52:32 same here: maybe something like "Ignoring stop() b
Mikhail 2016/08/26 16:42:41 Done.
59 return;
60 }
61
62 if (!m_sensorProxy) {
timvolodine 2016/08/25 17:52:32 same question
63 exceptionState.throwDOMException(InvalidStateError, "The Sensor is no lo nger associated to a frame.");
64 return;
65 }
66
67 stopListening();
68 }
69
70 static String ToString(Sensor::SensorState state)
71 {
72 switch (state) {
73 case Sensor::SensorState::IDLE:
74 return "idle";
75 case Sensor::SensorState::ACTIVATING:
76 return "activating";
77 case Sensor::SensorState::ACTIVE:
78 return "active";
79 case Sensor::SensorState::ERRORED:
80 return "errored";
81 default:
82 NOTREACHED();
83 }
84 return "idle";
28 } 85 }
29 86
30 // Getters 87 // Getters
31 String Sensor::state() const 88 String Sensor::state() const
32 { 89 {
33 // TODO(riju): Validate the transitions. 90 return ToString(m_state);
34 switch (m_sensorState) {
35 case SensorState::Idle:
36 return "idle";
37 case SensorState::Activating:
38 return "activating";
39 case SensorState::Active:
40 return "active";
41 case SensorState::Errored:
42 return "errored";
43 }
44 NOTREACHED();
45 return "idle";
46 } 91 }
47 92
48 SensorReading* Sensor::reading() const 93 SensorReading* Sensor::reading() const
49 { 94 {
50 return m_sensorReading.get(); 95 return m_sensorReading.get();
51 } 96 }
52 97
53 void Sensor::start(ScriptState* scriptState, ExceptionState& exceptionState) 98 DEFINE_TRACE(Sensor)
54 { 99 {
55 100 visitor->trace(m_polling);
56 if (m_sensorState != SensorState::Idle && m_sensorState != SensorState::Erro red) { 101 visitor->trace(m_sensorProxy);
57 exceptionState.throwDOMException(InvalidStateError, "Invalid State: Sens orState is not idle or errored"); 102 visitor->trace(m_sensorReading);
58 return; 103 ActiveScriptWrappable::trace(visitor);
59 } 104 ActiveDOMObject::trace(visitor);
60 105 PageVisibilityObserver::trace(visitor);
61 updateState(SensorState::Activating); 106 EventTargetWithInlineData::trace(visitor);
62 107 }
63 // TODO(riju) : Add Permissions stuff later. 108
64 109 bool Sensor::hasPendingActivity() const
65 m_hasEventListener = true; 110 {
66 111 if (!getExecutionContext() || getExecutionContext()->activeDOMObjectsAreStop ped())
67 // TODO(riju): verify the correct order of onstatechange(active) and the fir st onchange(event). 112 return false;
68 startUpdating(); 113 return hasEventListeners();
69 } 114 }
70 115
71 void Sensor::stop(ScriptState* scriptState, ExceptionState& exceptionState) 116 void Sensor::initSensorProxyIfNeeded()
72 { 117 {
73 if (m_sensorState == SensorState::Idle || m_sensorState == SensorState::Erro red) { 118 if (m_sensorProxy)
74 exceptionState.throwDOMException(InvalidStateError, "Invalid State: Sens orState is either idle or errored"); 119 return;
75 return; 120
76 } 121 Document* document = toDocument(getExecutionContext());
77 122 if (!document->frame())
78 m_hasEventListener = false; 123 return;
79 stopUpdating(); 124
80 125 m_sensorProxy = SensorProviderProxy::getOrCreateForFrame(document->frame())- >getOrCreateSensor(m_type);
81 m_sensorReading.clear(); 126 }
82 updateState(SensorState::Idle); 127
83 } 128 void Sensor::addedEventListener(const AtomicString& eventType, RegisteredEventLi stener&)
84 129 {
85 void Sensor::updateState(SensorState newState) 130 if (EventTypeNames::change == eventType)
timvolodine 2016/08/25 17:52:32 hmm, don't we have "change" already, would this be
Mikhail 2016/08/26 16:42:41 This method is called on JS call like "sensor.onch
timvolodine 2016/09/01 19:02:05 I was looking at https://cs.chromium.org/chromium/
Mikhail 2016/09/02 08:23:43 This event is local to sensor object (does not bub
86 { 131 updatePollingStatus();
87 DCHECK(isMainThread()); 132 }
88 if (m_sensorState == newState) 133
89 return; 134 void Sensor::removedEventListener(const AtomicString& eventType, const Registere dEventListener&)
90 135 {
91 m_sensorState = newState; 136 if (EventTypeNames::change == eventType)
92 // Notify context that state changed. 137 updatePollingStatus();
93 if (getExecutionContext()) 138 }
94 getExecutionContext()->postTask(BLINK_FROM_HERE, createSameThreadTask(&S ensor::notifyStateChange, wrapPersistent(this))); 139
95 } 140 void Sensor::stop()
96 141 {
97 void Sensor::notifyStateChange() 142 stopListening();
98 { 143 }
144
145 void Sensor::onSensorInitialized()
146 {
147 if (m_state != Sensor::SensorState::ACTIVATING)
148 return;
149
150 if (!m_sensorProxy) {
151 reportError();
152 return;
153 }
154
155 auto startCallback = WTF::bind(&Sensor::onStartRequestCompleted, wrapWeakPer sistent(this));
156 m_sensorProxy->addConfiguration(createSensorOptions(m_sensorOptions), std::m ove(startCallback));
157 }
158
159 void Sensor::onSensorReadingChanged()
160 {
161 if (m_polling)
162 m_polling->onSensorReadingChanged();
163 }
164
165 void Sensor::onSensorError()
166 {
167 reportError();
168 }
169
170 void Sensor::onStartRequestCompleted(bool result)
171 {
172 if (m_state != Sensor::SensorState::ACTIVATING)
173 return;
174
175 if (!result || !m_sensorProxy) {
176 reportError();
177 return;
178 }
179
180 updateState(Sensor::SensorState::ACTIVE);
181
182 double frequency = m_sensorOptions.hasFrequency() ? m_sensorOptions.frequenc y() : 1;
timvolodine 2016/08/25 17:52:32 why is this needed? i.e. if hasFrequency() is fals
Mikhail 2016/08/26 16:42:41 We need to slightly modify the mojo interface to h
timvolodine 2016/09/01 19:02:05 hmm don't see the TODO comment in the latest patch
Mikhail 2016/09/02 08:23:42 The latest patch contains already the solution for
183 auto pollCallback = WTF::bind(&Sensor::pollForData, wrapWeakPersistent(this) );
184 m_polling = SensorPollingStrategy::create(frequency, std::move(pollCallback) , m_sensorProxy->reportingMode());
185 updatePollingStatus();
186 }
187
188 void Sensor::onStopRequestCompleted(bool result)
189 {
190 if (m_state == Sensor::SensorState::IDLE)
191 return;
192
193 if (!result)
194 reportError();
195
196 if (m_sensorProxy)
197 m_sensorProxy->removeObserver(this);
198 }
199
200 void Sensor::pageVisibilityChanged()
201 {
202 updatePollingStatus();
203 }
204
205 void Sensor::startListening()
206 {
207 if (!m_sensorProxy)
208 return;
209
210 if (!m_sensorReading) {
211 m_sensorReading = createSensorReading(getExecutionContext());
212 m_sensorReading->attach(m_sensorProxy);
213 }
214
215 m_sensorProxy->addObserver(this);
216 if (m_sensorProxy->isInitialized()) {
217 auto callback = WTF::bind(&Sensor::onStartRequestCompleted, wrapWeakPers istent(this));
218 m_sensorProxy->addConfiguration(createSensorOptions(m_sensorOptions), st d::move(callback));
timvolodine 2016/08/25 17:52:32 can startListening() be invoked multiple times? if
Mikhail 2016/08/26 16:42:41 It is called only from 'Sensor::start' and only if
219 } else {
220 m_sensorProxy->initialize();
221 }
222 }
223
224 void Sensor::stopListening()
225 {
226 if (m_sensorReading) {
227 m_sensorReading->detach();
228 m_sensorReading = nullptr;
229 }
230
231 updateState(Sensor::SensorState::IDLE);
232
233 if (!m_sensorProxy)
234 return;
235
236 if (m_sensorProxy->isInitialized()) {
237 auto callback = WTF::bind(&Sensor::onStopRequestCompleted, wrapWeakPersi stent(this));
238 m_sensorProxy->removeConfiguration(createSensorOptions(m_sensorOptions), std::move(callback));
239 } else {
240 m_sensorProxy->removeObserver(this);
241 }
242 }
243
244 void Sensor::pollForData()
245 {
246 if (m_state != Sensor::SensorState::ACTIVE) {
timvolodine 2016/08/25 17:52:32 shouldn't this be a DCHECK. i.e. invariant that po
Mikhail 2016/08/26 16:42:41 It can happen if a scheduled task from 'OnChangeSe
247 DCHECK(m_polling);
248 m_polling->stopPolling();
249 return;
250 }
251
252 switch (m_sensorReading->updateInternalData()) {
253 case SensorReading::Updated:
254 dispatchEvent(SensorReadingEvent::create(EventTypeNames::change, m_senso rReading));
255 break;
256 case SensorReading::Error:
257 reportError();
258 break;
259 case SensorReading::Same:
260 break;
261 default:
262 NOTREACHED();
263 }
264 }
265
266 void Sensor::updateState(Sensor::SensorState newState)
267 {
268 if (newState == m_state)
269 return;
270 m_state = newState;
99 dispatchEvent(Event::create(EventTypeNames::statechange)); 271 dispatchEvent(Event::create(EventTypeNames::statechange));
100 } 272 }
101 273
102 void Sensor::suspend() 274 void Sensor::reportError()
103 { 275 {
104 m_hasEventListener = false; 276 updateState(Sensor::SensorState::ERRORED);
105 stopUpdating(); 277 updatePollingStatus();
106 } 278 // TODO(Mikhail) : Dispatch Sensor Error event.
107 279 }
108 void Sensor::resume() 280
109 { 281 void Sensor::updatePollingStatus()
110 m_hasEventListener = true; 282 {
111 startUpdating(); 283 if (!m_polling)
112 } 284 return;
113 285
114 void Sensor::stop() 286 if (m_state != Sensor::SensorState::ACTIVE // Sensor is not active.
115 { 287 || !hasEventListeners(EventTypeNames::change) // Noone is listening to ' onchange' event.
timvolodine 2016/08/25 17:52:32 noone -> "no one" or "nobody" ;) actually the com
Mikhail 2016/08/26 16:42:41 Done.
116 m_hasEventListener = false; 288 || page()->visibilityState() != PageVisibilityStateVisible) { // Page is not visible.
117 stopUpdating(); 289 m_polling->stopPolling();
118 } 290 } else {
119 291 m_polling->startPolling();
120 bool Sensor::hasPendingActivity() const 292 }
121 {
122 // Prevent V8 from garbage collecting the wrapper object if there are
123 // event listeners attached to it.
124 return hasEventListeners();
125 }
126
127 DEFINE_TRACE(Sensor)
128 {
129 ActiveDOMObject::trace(visitor);
130 EventTargetWithInlineData::trace(visitor);
131 PlatformEventController::trace(visitor);
132 visitor->trace(m_sensorReading);
133 } 293 }
134 294
135 } // namespace blink 295 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698