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 "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 |
OLD | NEW |