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 "bindings/core/v8/ScriptPromise.h" |
| 8 #include "bindings/core/v8/ScriptPromiseResolver.h" |
7 #include "core/dom/Document.h" | 9 #include "core/dom/Document.h" |
8 #include "core/dom/ExceptionCode.h" | 10 #include "core/dom/ExceptionCode.h" |
9 #include "core/dom/ExecutionContextTask.h" | 11 #include "modules/sensor/SensorErrorEvent.h" |
10 #include "core/events/Event.h" | 12 #include "modules/sensor/SensorPollingStrategy.h" |
11 | |
12 #include "modules/sensor/SensorReading.h" | 13 #include "modules/sensor/SensorReading.h" |
| 14 #include "modules/sensor/SensorReadingEvent.h" |
13 | 15 |
14 namespace blink { | 16 namespace blink { |
15 | 17 |
16 Sensor::~Sensor() | 18 Sensor::Sensor(ExecutionContext* executionContext, const SensorOptions& sensorOp
tions, device::sensors::blink::SensorType type) |
17 { | |
18 } | |
19 | |
20 Sensor::Sensor(ExecutionContext* executionContext, const SensorOptions& sensorOp
tions) | |
21 : ActiveScriptWrappable(this) | 19 : ActiveScriptWrappable(this) |
22 , ActiveDOMObject(executionContext) | 20 , ActiveDOMObject(executionContext) |
23 , PlatformEventController(toDocument(executionContext)->page()) | |
24 , m_sensorState(SensorState::Idle) | |
25 , m_sensorReading(nullptr) | |
26 , m_sensorOptions(sensorOptions) | 21 , m_sensorOptions(sensorOptions) |
27 { | 22 , m_type(type) |
| 23 , m_state(Sensor::SensorState::IDLE) |
| 24 { |
| 25 } |
| 26 |
| 27 void Sensor::start(ScriptState* scriptState, ExceptionState& exceptionState) |
| 28 { |
| 29 // 1. Check if sensor_instance’s state is neither "idle" nor "errored" |
| 30 if (m_state != Sensor::SensorState::IDLE && m_state != Sensor::SensorState::
ERRORED) { |
| 31 exceptionState.throwDOMException(InvalidStateError, "Invalid State: Sens
orState is not idle or errored"); |
| 32 return; |
| 33 } |
| 34 |
| 35 InitControllerIfNeeded(); |
| 36 |
| 37 if (!m_controller) { |
| 38 exceptionState.throwDOMException(InvalidStateError, "The Sensor is no lo
nger associated to a frame."); |
| 39 return; |
| 40 } |
| 41 |
| 42 // 2. Invoke the update state algorithm passing sensor_instance and "activat
ing" as the arguments. |
| 43 updateState(Sensor::SensorState::ACTIVATING); |
| 44 |
| 45 m_sensorReading = createSensorReading(); |
| 46 |
| 47 m_controller->addObserver(this); |
| 48 if (m_controller->isInitialized()) { |
| 49 auto callback = bind<bool>(&Sensor::onStartRequestCompleted, WeakPersist
entThisPointer<Sensor>(this)); |
| 50 m_controller->startConfiguration(createSensorOptions(), std::move(callba
ck)); |
| 51 } else { |
| 52 m_controller->initialize(); |
| 53 } |
| 54 } |
| 55 |
| 56 void Sensor::stop(ScriptState*, ExceptionState& exceptionState) |
| 57 { |
| 58 if (m_state == Sensor::SensorState::IDLE || m_state == Sensor::SensorState::
ERRORED) { |
| 59 exceptionState.throwDOMException(InvalidStateError, "Invalid State: Sens
orState is either idle or errored"); |
| 60 return; |
| 61 } |
| 62 |
| 63 if (!m_controller) { |
| 64 exceptionState.throwDOMException(InvalidStateError, "The Sensor is no lo
nger associated to a frame."); |
| 65 return; |
| 66 } |
| 67 m_sensorReading = nullptr; |
| 68 |
| 69 updateState(Sensor::SensorState::IDLE); |
| 70 |
| 71 if (m_controller->isInitialized()) { |
| 72 auto callback = bind<bool>(&Sensor::onStopRequestCompleted, WeakPersiste
ntThisPointer<Sensor>(this)); |
| 73 m_controller->stopConfiguration(createSensorOptions(), std::move(callbac
k)); |
| 74 } else { |
| 75 m_controller->removeObserver(this); |
| 76 } |
| 77 } |
| 78 |
| 79 static String ToString(Sensor::SensorState state) { |
| 80 switch (state) { |
| 81 case Sensor::SensorState::IDLE: |
| 82 return "idle"; |
| 83 case Sensor::SensorState::ACTIVATING: |
| 84 return "activating"; |
| 85 case Sensor::SensorState::ACTIVE: |
| 86 return "active"; |
| 87 case Sensor::SensorState::ERRORED: |
| 88 return "errored"; |
| 89 default: |
| 90 ASSERT_NOT_REACHED(); |
| 91 } |
| 92 return "idle"; |
28 } | 93 } |
29 | 94 |
30 // Getters | 95 // Getters |
31 String Sensor::state() const | 96 String Sensor::state() const |
32 { | 97 { |
33 // TODO(riju): Validate the transitions. | 98 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 } | 99 } |
47 | 100 |
48 SensorReading* Sensor::reading() const | 101 SensorReading* Sensor::reading() const |
49 { | 102 { |
50 return m_sensorReading.get(); | 103 return m_sensorReading.get(); |
51 } | 104 } |
52 | 105 |
53 void Sensor::start(ScriptState* scriptState, ExceptionState& exceptionState) | |
54 { | |
55 | |
56 if (m_sensorState != SensorState::Idle && m_sensorState != SensorState::Erro
red) { | |
57 exceptionState.throwDOMException(InvalidStateError, "Invalid State: Sens
orState is not idle or errored"); | |
58 return; | |
59 } | |
60 | |
61 updateState(SensorState::Activating); | |
62 | |
63 // TODO(riju) : Add Permissions stuff later. | |
64 | |
65 m_hasEventListener = true; | |
66 | |
67 // TODO(riju): verify the correct order of onstatechange(active) and the fir
st onchange(event). | |
68 startUpdating(); | |
69 } | |
70 | |
71 void Sensor::stop(ScriptState* scriptState, ExceptionState& exceptionState) | |
72 { | |
73 if (m_sensorState == SensorState::Idle || m_sensorState == SensorState::Erro
red) { | |
74 exceptionState.throwDOMException(InvalidStateError, "Invalid State: Sens
orState is either idle or errored"); | |
75 return; | |
76 } | |
77 | |
78 m_hasEventListener = false; | |
79 stopUpdating(); | |
80 | |
81 m_sensorReading.clear(); | |
82 updateState(SensorState::Idle); | |
83 } | |
84 | |
85 void Sensor::updateState(SensorState newState) | |
86 { | |
87 DCHECK(isMainThread()); | |
88 if (m_sensorState == newState) | |
89 return; | |
90 | |
91 m_sensorState = newState; | |
92 // Notify context that state changed. | |
93 if (getExecutionContext()) | |
94 getExecutionContext()->postTask(BLINK_FROM_HERE, createSameThreadTask(&S
ensor::notifyStateChange, this)); | |
95 } | |
96 | |
97 void Sensor::notifyStateChange() | |
98 { | |
99 dispatchEvent(Event::create(EventTypeNames::statechange)); | |
100 } | |
101 | |
102 void Sensor::suspend() | |
103 { | |
104 m_hasEventListener = false; | |
105 stopUpdating(); | |
106 } | |
107 | |
108 void Sensor::resume() | |
109 { | |
110 m_hasEventListener = true; | |
111 startUpdating(); | |
112 } | |
113 | |
114 void Sensor::stop() | |
115 { | |
116 m_hasEventListener = false; | |
117 stopUpdating(); | |
118 } | |
119 | |
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) | 106 DEFINE_TRACE(Sensor) |
128 { | 107 { |
| 108 visitor->trace(m_polling); |
| 109 visitor->trace(m_controller); |
| 110 visitor->trace(m_sensorReading); |
129 ActiveDOMObject::trace(visitor); | 111 ActiveDOMObject::trace(visitor); |
130 EventTargetWithInlineData::trace(visitor); | 112 EventTargetWithInlineData::trace(visitor); |
131 PlatformEventController::trace(visitor); | 113 } |
132 visitor->trace(m_sensorReading); | 114 |
| 115 void Sensor::InitControllerIfNeeded() |
| 116 { |
| 117 if (m_controller) |
| 118 return; |
| 119 |
| 120 ExecutionContext* executionContext = getExecutionContext(); |
| 121 ASSERT(executionContext && executionContext->isDocument()); |
| 122 |
| 123 Document* document = toDocument(executionContext); |
| 124 if (!document->frame()) |
| 125 return; |
| 126 |
| 127 m_controller = SensorProvider::getOrCreateForFrame(*document->frame())->getO
rCreateSensor(m_type); |
| 128 } |
| 129 |
| 130 void Sensor::addedEventListener(const AtomicString& eventType, RegisteredEventLi
stener&) |
| 131 { |
| 132 if (EventTypeNames::change == eventType) |
| 133 updatePollingStatus(); |
| 134 } |
| 135 |
| 136 void Sensor::removedEventListener(const AtomicString& eventType, const Registere
dEventListener&) |
| 137 { |
| 138 if (EventTypeNames::change == eventType) |
| 139 updatePollingStatus(); |
| 140 } |
| 141 |
| 142 void Sensor::onSensorInitialized() |
| 143 { |
| 144 if (m_state != Sensor::SensorState::ACTIVATING) |
| 145 return; |
| 146 |
| 147 if (!m_controller) |
| 148 { |
| 149 reportError(); |
| 150 return; |
| 151 } |
| 152 |
| 153 auto startCallback = bind<bool>(&Sensor::onStartRequestCompleted, WeakPersis
tentThisPointer<Sensor>(this)); |
| 154 m_controller->startConfiguration(createSensorOptions(), std::move(startCallb
ack)); |
| 155 } |
| 156 |
| 157 void Sensor::onSensorReadingChanged() |
| 158 { |
| 159 if (m_polling) |
| 160 m_polling->onSensorReadingChanged(); |
| 161 } |
| 162 |
| 163 void Sensor::onSensorError() |
| 164 { |
| 165 reportError(); |
| 166 } |
| 167 |
| 168 bool Sensor::hasPendingActivity() const { |
| 169 if (!getExecutionContext() || getExecutionContext()->activeDOMObjectsAreStop
ped()) |
| 170 return false; |
| 171 return hasEventListeners(); |
| 172 } |
| 173 |
| 174 void Sensor::onStartRequestCompleted(bool success) |
| 175 { |
| 176 if (m_state != Sensor::SensorState::ACTIVATING) |
| 177 return; |
| 178 |
| 179 if (!success || !m_controller) { |
| 180 reportError(); |
| 181 return; |
| 182 } |
| 183 |
| 184 updateState(Sensor::SensorState::ACTIVE); |
| 185 |
| 186 double frequency = options().hasFrequency() ? options().frequency() : 1; |
| 187 auto pollCallback = bind(&Sensor::pollForData, WeakPersistentThisPointer<Sen
sor>(this)); |
| 188 m_polling = SensorPollingStrategy::create(frequency, std::move(pollCallback)
, m_controller->reportingMode()); |
| 189 updatePollingStatus(); |
| 190 } |
| 191 |
| 192 void Sensor::onStopRequestCompleted(bool success) |
| 193 { |
| 194 if (m_state == Sensor::SensorState::IDLE) |
| 195 return; |
| 196 |
| 197 if (!success) |
| 198 reportError(); |
| 199 |
| 200 if (m_controller) |
| 201 m_controller->removeObserver(this); |
| 202 } |
| 203 |
| 204 void Sensor::pollForData() |
| 205 { |
| 206 if (m_state != Sensor::SensorState::ACTIVE) |
| 207 { |
| 208 ASSERT(m_polling); |
| 209 m_polling->stopPolling(); |
| 210 return; |
| 211 } |
| 212 |
| 213 switch (m_sensorReading->updateInternalData()) |
| 214 { |
| 215 case SensorReading::Updated: |
| 216 dispatchEvent(SensorReadingEvent::create(EventTypeNames::change, *m_sens
orReading)); |
| 217 break; |
| 218 case SensorReading::Error: |
| 219 reportError(); |
| 220 break; |
| 221 case SensorReading::Same: |
| 222 break; |
| 223 default: |
| 224 ASSERT_NOT_REACHED(); |
| 225 } |
| 226 } |
| 227 |
| 228 void Sensor::updateState(Sensor::SensorState newState) { |
| 229 if (newState == m_state) |
| 230 return; |
| 231 m_state = newState; |
| 232 dispatchEvent(Event::create(EventTypeNames::statechange)); |
| 233 } |
| 234 |
| 235 void Sensor::reportError() |
| 236 { |
| 237 updateState(Sensor::SensorState::ERRORED); |
| 238 dispatchEvent(SensorErrorEvent::create(EventTypeNames::error)); |
| 239 } |
| 240 |
| 241 void Sensor::updatePollingStatus() |
| 242 { |
| 243 if (!m_polling) |
| 244 return; |
| 245 |
| 246 if (m_state != Sensor::SensorState::ACTIVE || !hasEventListeners(EventTypeNa
mes::change)) { |
| 247 // Do not poll if noone is listening 'onchange' event. |
| 248 m_polling->stopPolling(); |
| 249 } else { |
| 250 m_polling->startPolling(); |
| 251 } |
133 } | 252 } |
134 | 253 |
135 } // namespace blink | 254 } // namespace blink |
OLD | NEW |