| Index: third_party/WebKit/Source/modules/sensor/Sensor.cpp
|
| diff --git a/third_party/WebKit/Source/modules/sensor/Sensor.cpp b/third_party/WebKit/Source/modules/sensor/Sensor.cpp
|
| index 9d716ca5e02e56ebec1fc95b3088d3d2ec82e2a2..070b3b88aa3107e7257ddbff65b4110899b8bd19 100644
|
| --- a/third_party/WebKit/Source/modules/sensor/Sensor.cpp
|
| +++ b/third_party/WebKit/Source/modules/sensor/Sensor.cpp
|
| @@ -6,130 +6,258 @@
|
|
|
| #include "core/dom/Document.h"
|
| #include "core/dom/ExceptionCode.h"
|
| -#include "core/dom/ExecutionContextTask.h"
|
| -#include "core/events/Event.h"
|
| -
|
| +#include "device/generic_sensor/public/interfaces/sensor.mojom-blink.h"
|
| +#include "modules/sensor/SensorErrorEvent.h"
|
| +#include "modules/sensor/SensorPollingStrategy.h"
|
| +#include "modules/sensor/SensorProviderProxy.h"
|
| #include "modules/sensor/SensorReading.h"
|
| +#include "modules/sensor/SensorReadingEvent.h"
|
| +
|
| +using namespace device::mojom::blink;
|
|
|
| namespace blink {
|
|
|
| -Sensor::~Sensor()
|
| +Sensor::Sensor(ExecutionContext* executionContext, const SensorOptions& sensorOptions, SensorType type)
|
| + : ActiveScriptWrappable(this)
|
| + , ContextLifecycleObserver(executionContext)
|
| + , PageVisibilityObserver(toDocument(executionContext)->page())
|
| + , m_sensorOptions(sensorOptions)
|
| + , m_type(type)
|
| + , m_state(Sensor::SensorState::IDLE)
|
| + , m_storedData()
|
| {
|
| }
|
|
|
| -Sensor::Sensor(ExecutionContext* executionContext, const SensorOptions& sensorOptions)
|
| - : ActiveScriptWrappable(this)
|
| - , ActiveDOMObject(executionContext)
|
| - , PlatformEventController(toDocument(executionContext)->page())
|
| - , m_sensorState(SensorState::Idle)
|
| - , m_sensorReading(nullptr)
|
| - , m_sensorOptions(sensorOptions)
|
| +Sensor::~Sensor() = default;
|
| +
|
| +void Sensor::start(ScriptState* scriptState, ExceptionState& exceptionState)
|
| {
|
| + if (m_state != Sensor::SensorState::IDLE && m_state != Sensor::SensorState::ERRORED) {
|
| + exceptionState.throwDOMException(InvalidStateError, "Cannot start because SensorState is not idle or errored");
|
| + return;
|
| + }
|
| +
|
| + initSensorProxyIfNeeded();
|
| +
|
| + if (!m_sensorProxy) {
|
| + exceptionState.throwDOMException(InvalidStateError, "The Sensor is no longer associated to a frame.");
|
| + return;
|
| + }
|
| +
|
| + startListening();
|
| }
|
|
|
| -// Getters
|
| -String Sensor::state() const
|
| +void Sensor::stop(ScriptState*, ExceptionState& exceptionState)
|
| +{
|
| + if (m_state == Sensor::SensorState::IDLE || m_state == Sensor::SensorState::ERRORED) {
|
| + exceptionState.throwDOMException(InvalidStateError, "Cannot stop because SensorState is either idle or errored");
|
| + return;
|
| + }
|
| +
|
| + stopListening();
|
| +}
|
| +
|
| +static String ToString(Sensor::SensorState state)
|
| {
|
| - // TODO(riju): Validate the transitions.
|
| - switch (m_sensorState) {
|
| - case SensorState::Idle:
|
| + switch (state) {
|
| + case Sensor::SensorState::IDLE:
|
| return "idle";
|
| - case SensorState::Activating:
|
| + case Sensor::SensorState::ACTIVATING:
|
| return "activating";
|
| - case SensorState::Active:
|
| + case Sensor::SensorState::ACTIVE:
|
| return "active";
|
| - case SensorState::Errored:
|
| + case Sensor::SensorState::ERRORED:
|
| return "errored";
|
| + default:
|
| + NOTREACHED();
|
| }
|
| - NOTREACHED();
|
| return "idle";
|
| }
|
|
|
| +// Getters
|
| +String Sensor::state() const
|
| +{
|
| + return ToString(m_state);
|
| +}
|
| +
|
| SensorReading* Sensor::reading() const
|
| {
|
| return m_sensorReading.get();
|
| }
|
|
|
| -void Sensor::start(ScriptState* scriptState, ExceptionState& exceptionState)
|
| +DEFINE_TRACE(Sensor)
|
| {
|
| + visitor->trace(m_sensorProxy);
|
| + visitor->trace(m_sensorReading);
|
| + ActiveScriptWrappable::trace(visitor);
|
| + ContextLifecycleObserver::trace(visitor);
|
| + PageVisibilityObserver::trace(visitor);
|
| + EventTargetWithInlineData::trace(visitor);
|
| +}
|
|
|
| - if (m_sensorState != SensorState::Idle && m_sensorState != SensorState::Errored) {
|
| - exceptionState.throwDOMException(InvalidStateError, "Invalid State: SensorState is not idle or errored");
|
| - return;
|
| - }
|
| +bool Sensor::hasPendingActivity() const
|
| +{
|
| + if (m_state == Sensor::SensorState::IDLE || m_state == Sensor::SensorState::ERRORED)
|
| + return false;
|
| + return hasEventListeners();
|
| +}
|
|
|
| - updateState(SensorState::Activating);
|
| +void Sensor::initSensorProxyIfNeeded()
|
| +{
|
| + if (m_sensorProxy)
|
| + return;
|
|
|
| - // TODO(riju) : Add Permissions stuff later.
|
| + Document* document = toDocument(getExecutionContext());
|
| + if (!document || !document->frame())
|
| + return;
|
|
|
| - m_hasEventListener = true;
|
| + m_sensorProxy = SensorProviderProxy::from(document->frame())->getOrCreateSensor(m_type);
|
| +}
|
|
|
| - // TODO(riju): verify the correct order of onstatechange(active) and the first onchange(event).
|
| - startUpdating();
|
| +void Sensor::contextDestroyed()
|
| +{
|
| + if (m_state == Sensor::SensorState::ACTIVE || m_state == Sensor::SensorState::ACTIVATING)
|
| + stopListening();
|
| }
|
|
|
| -void Sensor::stop(ScriptState* scriptState, ExceptionState& exceptionState)
|
| +void Sensor::onSensorInitialized()
|
| {
|
| - if (m_sensorState == SensorState::Idle || m_sensorState == SensorState::Errored) {
|
| - exceptionState.throwDOMException(InvalidStateError, "Invalid State: SensorState is either idle or errored");
|
| + if (m_state != Sensor::SensorState::ACTIVATING)
|
| + return;
|
| +
|
| + m_configuration = createSensorConfig(m_sensorOptions);
|
| + if (!m_configuration) {
|
| + reportError();
|
| return;
|
| }
|
|
|
| - m_hasEventListener = false;
|
| - stopUpdating();
|
| + DCHECK(m_sensorProxy);
|
| + auto startCallback = WTF::bind(&Sensor::onStartRequestCompleted, wrapWeakPersistent(this));
|
| + m_sensorProxy->addConfiguration(m_configuration->Clone(), std::move(startCallback));
|
| +}
|
|
|
| - m_sensorReading.clear();
|
| - updateState(SensorState::Idle);
|
| +void Sensor::onSensorReadingChanged()
|
| +{
|
| + if (m_polling)
|
| + m_polling->onSensorReadingChanged();
|
| }
|
|
|
| -void Sensor::updateState(SensorState newState)
|
| +void Sensor::onSensorError()
|
| {
|
| - DCHECK(isMainThread());
|
| - if (m_sensorState == newState)
|
| + reportError();
|
| +}
|
| +
|
| +void Sensor::onStartRequestCompleted(bool result)
|
| +{
|
| + if (m_state != Sensor::SensorState::ACTIVATING)
|
| return;
|
|
|
| - m_sensorState = newState;
|
| - // Notify context that state changed.
|
| - if (getExecutionContext())
|
| - getExecutionContext()->postTask(BLINK_FROM_HERE, createSameThreadTask(&Sensor::notifyStateChange, wrapPersistent(this)));
|
| + if (!result) {
|
| + reportError();
|
| + return;
|
| + }
|
| +
|
| + DCHECK(m_configuration);
|
| + DCHECK(m_sensorProxy);
|
| + auto pollCallback = WTF::bind(&Sensor::pollForData, wrapWeakPersistent(this));
|
| + m_polling = SensorPollingStrategy::create(m_configuration->frequency, std::move(pollCallback), m_sensorProxy->reportingMode());
|
| + updateState(Sensor::SensorState::ACTIVE);
|
| }
|
|
|
| -void Sensor::notifyStateChange()
|
| +void Sensor::onStopRequestCompleted(bool result)
|
| {
|
| - dispatchEvent(Event::create(EventTypeNames::statechange));
|
| + if (m_state == Sensor::SensorState::IDLE)
|
| + return;
|
| +
|
| + if (!result)
|
| + reportError();
|
| +
|
| + DCHECK(m_sensorProxy);
|
| + m_sensorProxy->removeObserver(this);
|
| }
|
|
|
| -void Sensor::suspend()
|
| +void Sensor::pageVisibilityChanged()
|
| {
|
| - m_hasEventListener = false;
|
| - stopUpdating();
|
| + updatePollingStatus();
|
| }
|
|
|
| -void Sensor::resume()
|
| +void Sensor::startListening()
|
| {
|
| - m_hasEventListener = true;
|
| - startUpdating();
|
| + DCHECK(m_sensorProxy);
|
| + updateState(Sensor::SensorState::ACTIVATING);
|
| + if (!m_sensorReading)
|
| + m_sensorReading = createSensorReading(m_sensorProxy);
|
| +
|
| + m_sensorProxy->addObserver(this);
|
| + if (m_sensorProxy->isInitialized()) {
|
| + auto callback = WTF::bind(&Sensor::onStartRequestCompleted, wrapWeakPersistent(this));
|
| + DCHECK(m_configuration);
|
| + m_sensorProxy->addConfiguration(m_configuration->Clone(), std::move(callback));
|
| + } else {
|
| + m_sensorProxy->initialize();
|
| + }
|
| }
|
|
|
| -void Sensor::stop()
|
| +void Sensor::stopListening()
|
| {
|
| - m_hasEventListener = false;
|
| - stopUpdating();
|
| + DCHECK(m_sensorProxy);
|
| + m_sensorReading = nullptr;
|
| + updateState(Sensor::SensorState::IDLE);
|
| +
|
| + if (m_sensorProxy->isInitialized()) {
|
| + auto callback = WTF::bind(&Sensor::onStopRequestCompleted, wrapWeakPersistent(this));
|
| + DCHECK(m_configuration);
|
| + m_sensorProxy->removeConfiguration(m_configuration->Clone(), std::move(callback));
|
| + } else {
|
| + m_sensorProxy->removeObserver(this);
|
| + }
|
| }
|
|
|
| -bool Sensor::hasPendingActivity() const
|
| +void Sensor::pollForData()
|
| {
|
| - // Prevent V8 from garbage collecting the wrapper object if there are
|
| - // event listeners attached to it.
|
| - return hasEventListeners();
|
| + if (m_state != Sensor::SensorState::ACTIVE) {
|
| + DCHECK(m_polling);
|
| + m_polling->stopPolling();
|
| + return;
|
| + }
|
| +
|
| + DCHECK(m_sensorProxy);
|
| + DCHECK(m_sensorProxy->isInitialized());
|
| + m_sensorProxy->updateInternalReading();
|
| +
|
| + DCHECK(m_sensorReading);
|
| + if (m_sensorReading->isReadingUpdated(m_storedData))
|
| + dispatchEvent(SensorReadingEvent::create(EventTypeNames::change, m_sensorReading));
|
| +
|
| + m_storedData = m_sensorProxy->reading();
|
| }
|
|
|
| -DEFINE_TRACE(Sensor)
|
| +void Sensor::updateState(Sensor::SensorState newState)
|
| {
|
| - ActiveDOMObject::trace(visitor);
|
| - EventTargetWithInlineData::trace(visitor);
|
| - PlatformEventController::trace(visitor);
|
| - visitor->trace(m_sensorReading);
|
| + if (newState == m_state)
|
| + return;
|
| + m_state = newState;
|
| + dispatchEvent(Event::create(EventTypeNames::statechange));
|
| + updatePollingStatus();
|
| +}
|
| +
|
| +void Sensor::reportError()
|
| +{
|
| + updateState(Sensor::SensorState::ERRORED);
|
| + // TODO(Mikhail) : Dispatch Sensor Error event.
|
| +}
|
| +
|
| +void Sensor::updatePollingStatus()
|
| +{
|
| + if (!m_polling)
|
| + return;
|
| +
|
| + if (m_state != Sensor::SensorState::ACTIVE
|
| + || page()->visibilityState() != PageVisibilityStateVisible) {
|
| + m_polling->stopPolling();
|
| + } else {
|
| + m_polling->startPolling();
|
| + }
|
| }
|
|
|
| } // namespace blink
|
|
|