| 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, SensorType type) |
| 17 { | |
| 18 } | |
| 19 | |
| 20 Sensor::Sensor(ExecutionContext* executionContext, const SensorOptions& sensorOp
tions) | |
| 21 : ActiveScriptWrappable(this) | 21 : ActiveScriptWrappable(this) |
| 22 , ActiveDOMObject(executionContext) | 22 , ContextLifecycleObserver(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 , m_storedData() |
| 28 { |
| 29 } |
| 30 |
| 31 Sensor::~Sensor() = default; |
| 32 |
| 33 void Sensor::start(ScriptState* scriptState, ExceptionState& exceptionState) |
| 34 { |
| 35 if (m_state != Sensor::SensorState::IDLE && m_state != Sensor::SensorState::
ERRORED) { |
| 36 exceptionState.throwDOMException(InvalidStateError, "Cannot start becaus
e SensorState is not idle or errored"); |
| 37 return; |
| 38 } |
| 39 |
| 40 initSensorProxyIfNeeded(); |
| 41 |
| 42 if (!m_sensorProxy) { |
| 43 exceptionState.throwDOMException(InvalidStateError, "The Sensor is no lo
nger associated to a frame."); |
| 44 return; |
| 45 } |
| 46 |
| 47 startListening(); |
| 48 } |
| 49 |
| 50 void Sensor::stop(ScriptState*, ExceptionState& exceptionState) |
| 51 { |
| 52 if (m_state == Sensor::SensorState::IDLE || m_state == Sensor::SensorState::
ERRORED) { |
| 53 exceptionState.throwDOMException(InvalidStateError, "Cannot stop because
SensorState is either idle or errored"); |
| 54 return; |
| 55 } |
| 56 |
| 57 stopListening(); |
| 58 } |
| 59 |
| 60 static String ToString(Sensor::SensorState state) |
| 61 { |
| 62 switch (state) { |
| 63 case Sensor::SensorState::IDLE: |
| 64 return "idle"; |
| 65 case Sensor::SensorState::ACTIVATING: |
| 66 return "activating"; |
| 67 case Sensor::SensorState::ACTIVE: |
| 68 return "active"; |
| 69 case Sensor::SensorState::ERRORED: |
| 70 return "errored"; |
| 71 default: |
| 72 NOTREACHED(); |
| 73 } |
| 74 return "idle"; |
| 28 } | 75 } |
| 29 | 76 |
| 30 // Getters | 77 // Getters |
| 31 String Sensor::state() const | 78 String Sensor::state() const |
| 32 { | 79 { |
| 33 // TODO(riju): Validate the transitions. | 80 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 } | 81 } |
| 47 | 82 |
| 48 SensorReading* Sensor::reading() const | 83 SensorReading* Sensor::reading() const |
| 49 { | 84 { |
| 50 return m_sensorReading.get(); | 85 return m_sensorReading.get(); |
| 51 } | 86 } |
| 52 | 87 |
| 53 void Sensor::start(ScriptState* scriptState, ExceptionState& exceptionState) | 88 DEFINE_TRACE(Sensor) |
| 54 { | 89 { |
| 55 | 90 visitor->trace(m_sensorProxy); |
| 56 if (m_sensorState != SensorState::Idle && m_sensorState != SensorState::Erro
red) { | 91 visitor->trace(m_sensorReading); |
| 57 exceptionState.throwDOMException(InvalidStateError, "Invalid State: Sens
orState is not idle or errored"); | 92 ActiveScriptWrappable::trace(visitor); |
| 58 return; | 93 ContextLifecycleObserver::trace(visitor); |
| 59 } | 94 PageVisibilityObserver::trace(visitor); |
| 60 | 95 EventTargetWithInlineData::trace(visitor); |
| 61 updateState(SensorState::Activating); | 96 } |
| 62 | 97 |
| 63 // TODO(riju) : Add Permissions stuff later. | 98 bool Sensor::hasPendingActivity() const |
| 64 | 99 { |
| 65 m_hasEventListener = true; | 100 if (m_state == Sensor::SensorState::IDLE || m_state == Sensor::SensorState::
ERRORED) |
| 66 | 101 return false; |
| 67 // TODO(riju): verify the correct order of onstatechange(active) and the fir
st onchange(event). | 102 return hasEventListeners(); |
| 68 startUpdating(); | 103 } |
| 69 } | 104 |
| 70 | 105 void Sensor::initSensorProxyIfNeeded() |
| 71 void Sensor::stop(ScriptState* scriptState, ExceptionState& exceptionState) | 106 { |
| 72 { | 107 if (m_sensorProxy) |
| 73 if (m_sensorState == SensorState::Idle || m_sensorState == SensorState::Erro
red) { | 108 return; |
| 74 exceptionState.throwDOMException(InvalidStateError, "Invalid State: Sens
orState is either idle or errored"); | 109 |
| 75 return; | 110 Document* document = toDocument(getExecutionContext()); |
| 76 } | 111 if (!document || !document->frame()) |
| 77 | 112 return; |
| 78 m_hasEventListener = false; | 113 |
| 79 stopUpdating(); | 114 m_sensorProxy = SensorProviderProxy::from(document->frame())->getOrCreateSen
sor(m_type); |
| 80 | 115 } |
| 81 m_sensorReading.clear(); | 116 |
| 82 updateState(SensorState::Idle); | 117 void Sensor::contextDestroyed() |
| 83 } | 118 { |
| 84 | 119 if (m_state == Sensor::SensorState::ACTIVE || m_state == Sensor::SensorState
::ACTIVATING) |
| 85 void Sensor::updateState(SensorState newState) | 120 stopListening(); |
| 86 { | 121 } |
| 87 DCHECK(isMainThread()); | 122 |
| 88 if (m_sensorState == newState) | 123 void Sensor::onSensorInitialized() |
| 89 return; | 124 { |
| 90 | 125 if (m_state != Sensor::SensorState::ACTIVATING) |
| 91 m_sensorState = newState; | 126 return; |
| 92 // Notify context that state changed. | 127 |
| 93 if (getExecutionContext()) | 128 m_configuration = createSensorConfig(m_sensorOptions); |
| 94 getExecutionContext()->postTask(BLINK_FROM_HERE, createSameThreadTask(&S
ensor::notifyStateChange, wrapPersistent(this))); | 129 if (!m_configuration) { |
| 95 } | 130 reportError(); |
| 96 | 131 return; |
| 97 void Sensor::notifyStateChange() | 132 } |
| 98 { | 133 |
| 134 DCHECK(m_sensorProxy); |
| 135 auto startCallback = WTF::bind(&Sensor::onStartRequestCompleted, wrapWeakPer
sistent(this)); |
| 136 m_sensorProxy->addConfiguration(m_configuration->Clone(), std::move(startCal
lback)); |
| 137 } |
| 138 |
| 139 void Sensor::onSensorReadingChanged() |
| 140 { |
| 141 if (m_polling) |
| 142 m_polling->onSensorReadingChanged(); |
| 143 } |
| 144 |
| 145 void Sensor::onSensorError() |
| 146 { |
| 147 reportError(); |
| 148 } |
| 149 |
| 150 void Sensor::onStartRequestCompleted(bool result) |
| 151 { |
| 152 if (m_state != Sensor::SensorState::ACTIVATING) |
| 153 return; |
| 154 |
| 155 if (!result) { |
| 156 reportError(); |
| 157 return; |
| 158 } |
| 159 |
| 160 DCHECK(m_configuration); |
| 161 DCHECK(m_sensorProxy); |
| 162 auto pollCallback = WTF::bind(&Sensor::pollForData, wrapWeakPersistent(this)
); |
| 163 m_polling = SensorPollingStrategy::create(m_configuration->frequency, std::m
ove(pollCallback), m_sensorProxy->reportingMode()); |
| 164 updateState(Sensor::SensorState::ACTIVE); |
| 165 } |
| 166 |
| 167 void Sensor::onStopRequestCompleted(bool result) |
| 168 { |
| 169 if (m_state == Sensor::SensorState::IDLE) |
| 170 return; |
| 171 |
| 172 if (!result) |
| 173 reportError(); |
| 174 |
| 175 DCHECK(m_sensorProxy); |
| 176 m_sensorProxy->removeObserver(this); |
| 177 } |
| 178 |
| 179 void Sensor::pageVisibilityChanged() |
| 180 { |
| 181 updatePollingStatus(); |
| 182 } |
| 183 |
| 184 void Sensor::startListening() |
| 185 { |
| 186 DCHECK(m_sensorProxy); |
| 187 updateState(Sensor::SensorState::ACTIVATING); |
| 188 if (!m_sensorReading) |
| 189 m_sensorReading = createSensorReading(m_sensorProxy); |
| 190 |
| 191 m_sensorProxy->addObserver(this); |
| 192 if (m_sensorProxy->isInitialized()) { |
| 193 auto callback = WTF::bind(&Sensor::onStartRequestCompleted, wrapWeakPers
istent(this)); |
| 194 DCHECK(m_configuration); |
| 195 m_sensorProxy->addConfiguration(m_configuration->Clone(), std::move(call
back)); |
| 196 } else { |
| 197 m_sensorProxy->initialize(); |
| 198 } |
| 199 } |
| 200 |
| 201 void Sensor::stopListening() |
| 202 { |
| 203 DCHECK(m_sensorProxy); |
| 204 m_sensorReading = nullptr; |
| 205 updateState(Sensor::SensorState::IDLE); |
| 206 |
| 207 if (m_sensorProxy->isInitialized()) { |
| 208 auto callback = WTF::bind(&Sensor::onStopRequestCompleted, wrapWeakPersi
stent(this)); |
| 209 DCHECK(m_configuration); |
| 210 m_sensorProxy->removeConfiguration(m_configuration->Clone(), std::move(c
allback)); |
| 211 } else { |
| 212 m_sensorProxy->removeObserver(this); |
| 213 } |
| 214 } |
| 215 |
| 216 void Sensor::pollForData() |
| 217 { |
| 218 if (m_state != Sensor::SensorState::ACTIVE) { |
| 219 DCHECK(m_polling); |
| 220 m_polling->stopPolling(); |
| 221 return; |
| 222 } |
| 223 |
| 224 DCHECK(m_sensorProxy); |
| 225 DCHECK(m_sensorProxy->isInitialized()); |
| 226 m_sensorProxy->updateInternalReading(); |
| 227 |
| 228 DCHECK(m_sensorReading); |
| 229 if (m_sensorReading->isReadingUpdated(m_storedData)) |
| 230 dispatchEvent(SensorReadingEvent::create(EventTypeNames::change, m_senso
rReading)); |
| 231 |
| 232 m_storedData = m_sensorProxy->reading(); |
| 233 } |
| 234 |
| 235 void Sensor::updateState(Sensor::SensorState newState) |
| 236 { |
| 237 if (newState == m_state) |
| 238 return; |
| 239 m_state = newState; |
| 99 dispatchEvent(Event::create(EventTypeNames::statechange)); | 240 dispatchEvent(Event::create(EventTypeNames::statechange)); |
| 100 } | 241 updatePollingStatus(); |
| 101 | 242 } |
| 102 void Sensor::suspend() | 243 |
| 103 { | 244 void Sensor::reportError() |
| 104 m_hasEventListener = false; | 245 { |
| 105 stopUpdating(); | 246 updateState(Sensor::SensorState::ERRORED); |
| 106 } | 247 // TODO(Mikhail) : Dispatch Sensor Error event. |
| 107 | 248 } |
| 108 void Sensor::resume() | 249 |
| 109 { | 250 void Sensor::updatePollingStatus() |
| 110 m_hasEventListener = true; | 251 { |
| 111 startUpdating(); | 252 if (!m_polling) |
| 112 } | 253 return; |
| 113 | 254 |
| 114 void Sensor::stop() | 255 if (m_state != Sensor::SensorState::ACTIVE |
| 115 { | 256 || page()->visibilityState() != PageVisibilityStateVisible) { |
| 116 m_hasEventListener = false; | 257 m_polling->stopPolling(); |
| 117 stopUpdating(); | 258 } else { |
| 118 } | 259 m_polling->startPolling(); |
| 119 | 260 } |
| 120 bool Sensor::hasPendingActivity() const | |
| 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 } | 261 } |
| 134 | 262 |
| 135 } // namespace blink | 263 } // namespace blink |
| OLD | NEW |