// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "modules/sensor/Sensor.h"

#include "core/dom/Document.h"
#include "core/dom/ExceptionCode.h"
#include "core/inspector/ConsoleMessage.h"
#include "core/timing/DOMWindowPerformance.h"
#include "core/timing/Performance.h"
#include "modules/sensor/SensorErrorEvent.h"
#include "modules/sensor/SensorProviderProxy.h"
#include "platform/LayoutTestSupport.h"
#include "platform/feature_policy/FeaturePolicy.h"
#include "public/platform/TaskType.h"
#include "services/device/public/cpp/generic_sensor/sensor_traits.h"
#include "services/device/public/interfaces/sensor.mojom-blink.h"

namespace blink {

namespace {
const double kWaitingIntervalThreshold = 0.01;

bool AreFeaturesEnabled(LocalFrame* frame,
                        const Vector<FeaturePolicyFeature>& features) {
  return std::all_of(features.begin(), features.end(),
                     [frame](FeaturePolicyFeature feature) {
                       return frame->IsFeatureEnabled(feature);
                     });
}

}  // namespace

Sensor::Sensor(ExecutionContext* execution_context,
               const SensorOptions& sensor_options,
               ExceptionState& exception_state,
               device::mojom::blink::SensorType type,
               const Vector<FeaturePolicyFeature>& features)
    : ContextLifecycleObserver(execution_context),
      frequency_(0.0),
      type_(type),
      state_(SensorState::kIdle),
      last_reported_timestamp_(0.0) {
  // [SecureContext] in idl.
  DCHECK(execution_context->IsSecureContext());
  DCHECK(!features.IsEmpty());
  LocalFrame* frame = ToDocument(execution_context)->GetFrame();

  if (!frame || !AreFeaturesEnabled(frame, features)) {
    exception_state.ThrowSecurityError(
        "Access to sensor features is disallowed by feature policy");
    return;
  }

  // Check the given frequency value.
  if (sensor_options.hasFrequency()) {
    frequency_ = sensor_options.frequency();
    const double max_allowed_frequency =
        device::GetSensorMaxAllowedFrequency(type_);
    if (frequency_ > max_allowed_frequency) {
      frequency_ = max_allowed_frequency;
      String message = String::Format(
          "Maximum allowed frequency value for this sensor type is %.0f Hz.",
          max_allowed_frequency);
      ConsoleMessage* console_message = ConsoleMessage::Create(
          kJSMessageSource, kInfoMessageLevel, std::move(message));
      execution_context->AddConsoleMessage(console_message);
    }
  }
}

Sensor::Sensor(ExecutionContext* execution_context,
               const SpatialSensorOptions& options,
               ExceptionState& exception_state,
               device::mojom::blink::SensorType sensor_type,
               const Vector<FeaturePolicyFeature>& features)
    : Sensor(execution_context,
             static_cast<const SensorOptions&>(options),
             exception_state,
             sensor_type,
             features) {
  use_screen_coords_ = (options.referenceFrame() == "screen");
}

Sensor::~Sensor() = default;

void Sensor::start() {
  if (state_ != SensorState::kIdle)
    return;
  state_ = SensorState::kActivating;
  Activate();
}

void Sensor::stop() {
  if (state_ == SensorState::kIdle)
    return;
  Deactivate();
  state_ = SensorState::kIdle;
}

// Getters
bool Sensor::activated() const {
  return state_ == SensorState::kActivated;
}

bool Sensor::hasReading() const {
  if (!IsActivated())
    return false;
  DCHECK(sensor_proxy_);
  return sensor_proxy_->GetReading().timestamp() != 0.0;
}

DOMHighResTimeStamp Sensor::timestamp(ScriptState* script_state,
                                      bool& is_null) const {
  if (!hasReading()) {
    is_null = true;
    return 0.0;
  }

  LocalDOMWindow* window = LocalDOMWindow::From(script_state);
  if (!window) {
    is_null = true;
    return 0.0;
  }

  Performance* performance = DOMWindowPerformance::performance(*window);
  DCHECK(performance);
  DCHECK(sensor_proxy_);
  is_null = false;

  if (LayoutTestSupport::IsRunningLayoutTest()) {
    // In layout tests Performance.now() * 0.001 is passed to the shared buffer.
    return sensor_proxy_->GetReading().timestamp() * 1000;
  }

  return performance->MonotonicTimeToDOMHighResTimeStamp(
      TimeTicksFromSeconds(sensor_proxy_->GetReading().timestamp()));
}

void Sensor::Trace(blink::Visitor* visitor) {
  visitor->Trace(sensor_proxy_);
  ActiveScriptWrappable::Trace(visitor);
  ContextLifecycleObserver::Trace(visitor);
  EventTargetWithInlineData::Trace(visitor);
}

bool Sensor::HasPendingActivity() const {
  if (state_ == SensorState::kIdle)
    return false;
  return GetExecutionContext() && HasEventListeners();
}

auto Sensor::CreateSensorConfig() -> SensorConfigurationPtr {
  auto result = SensorConfiguration::New();

  double default_frequency = sensor_proxy_->DefaultConfig()->frequency;
  double minimum_frequency = sensor_proxy_->FrequencyLimits().first;
  double maximum_frequency = sensor_proxy_->FrequencyLimits().second;

  if (frequency_ == 0.0)  // i.e. was never set.
    frequency_ = default_frequency;
  if (frequency_ > maximum_frequency)
    frequency_ = maximum_frequency;
  if (frequency_ < minimum_frequency)
    frequency_ = minimum_frequency;

  result->frequency = frequency_;
  return result;
}

void Sensor::InitSensorProxyIfNeeded() {
  if (sensor_proxy_)
    return;

  Document* document = ToDocument(GetExecutionContext());
  if (!document || !document->GetFrame())
    return;

  auto provider = SensorProviderProxy::From(document->GetFrame());
  sensor_proxy_ = provider->GetSensorProxy(type_);

  if (!sensor_proxy_)
    sensor_proxy_ = provider->CreateSensorProxy(type_, document->GetPage());
}

void Sensor::ContextDestroyed(ExecutionContext*) {
  if (!IsIdleOrErrored())
    Deactivate();
}

void Sensor::OnSensorInitialized() {
  if (state_ != SensorState::kActivating)
    return;

  RequestAddConfiguration();
}

void Sensor::OnSensorReadingChanged() {
  if (state_ != SensorState::kActivated)
    return;

  // Return if reading update is already scheduled or the cached
  // reading is up-to-date.
  if (pending_reading_notification_.IsActive())
    return;

  double elapsedTime =
      sensor_proxy_->GetReading().timestamp() - last_reported_timestamp_;
  DCHECK_GT(elapsedTime, 0.0);

  DCHECK_GT(configuration_->frequency, 0.0);
  double waitingTime = 1 / configuration_->frequency - elapsedTime;

  // Negative or zero 'waitingTime' means that polling period has elapsed.
  // We also avoid scheduling if the elapsed time is slightly behind the
  // polling period.
  auto sensor_reading_changed =
      WTF::Bind(&Sensor::NotifyReading, WrapWeakPersistent(this));
  if (waitingTime < kWaitingIntervalThreshold) {
    // Invoke JS callbacks in a different callchain to obviate
    // possible modifications of SensorProxy::observers_ container
    // while it is being iterated through.
    pending_reading_notification_ = PostCancellableTask(
        *GetExecutionContext()->GetTaskRunner(TaskType::kSensor), FROM_HERE,
        std::move(sensor_reading_changed));
  } else {
    pending_reading_notification_ = PostDelayedCancellableTask(
        *GetExecutionContext()->GetTaskRunner(TaskType::kSensor), FROM_HERE,
        std::move(sensor_reading_changed),
        WTF::TimeDelta::FromSecondsD(waitingTime));
  }
}

void Sensor::OnSensorError(ExceptionCode code,
                           const String& sanitized_message,
                           const String& unsanitized_message) {
  HandleError(code, sanitized_message, unsanitized_message);
}

void Sensor::OnAddConfigurationRequestCompleted(bool result) {
  if (state_ != SensorState::kActivating)
    return;

  if (!result) {
    HandleError(kNotReadableError, "start() call has failed.");
    return;
  }

  if (!GetExecutionContext())
    return;

  pending_activated_notification_ = PostCancellableTask(
      *GetExecutionContext()->GetTaskRunner(TaskType::kSensor), FROM_HERE,
      WTF::Bind(&Sensor::NotifyActivated, WrapWeakPersistent(this)));
}

void Sensor::Activate() {
  DCHECK_EQ(state_, SensorState::kActivating);

  InitSensorProxyIfNeeded();
  if (!sensor_proxy_) {
    HandleError(kInvalidStateError,
                "The Sensor is no longer associated to a frame.");
    return;
  }

  if (sensor_proxy_->IsInitialized())
    RequestAddConfiguration();
  else
    sensor_proxy_->Initialize();

  sensor_proxy_->AddObserver(this);
}

void Sensor::Deactivate() {
  DCHECK_NE(state_, SensorState::kIdle);
  // state_ is not set to kIdle here as on error it should
  // transition to the kIdle state in the same call chain
  // the error event is dispatched, i.e. inside NotifyError().
  pending_reading_notification_.Cancel();
  pending_activated_notification_.Cancel();
  pending_error_notification_.Cancel();

  if (!sensor_proxy_)
    return;

  if (sensor_proxy_->IsInitialized()) {
    DCHECK(configuration_);
    sensor_proxy_->RemoveConfiguration(configuration_->Clone());
    last_reported_timestamp_ = 0.0;
  }

  sensor_proxy_->RemoveObserver(this);
}

void Sensor::RequestAddConfiguration() {
  if (!configuration_) {
    configuration_ = CreateSensorConfig();
    DCHECK(configuration_);
    DCHECK_GE(configuration_->frequency,
              sensor_proxy_->FrequencyLimits().first);
    DCHECK_LE(configuration_->frequency,
              sensor_proxy_->FrequencyLimits().second);
  }

  DCHECK(sensor_proxy_);
  sensor_proxy_->AddConfiguration(
      configuration_->Clone(),
      WTF::Bind(&Sensor::OnAddConfigurationRequestCompleted,
                WrapWeakPersistent(this)));
}

void Sensor::HandleError(ExceptionCode code,
                         const String& sanitized_message,
                         const String& unsanitized_message) {
  if (!GetExecutionContext()) {
    // Deactivate() is already called from Sensor::ContextDestroyed().
    return;
  }

  if (IsIdleOrErrored())
    return;

  Deactivate();

  auto error =
      DOMException::Create(code, sanitized_message, unsanitized_message);
  pending_error_notification_ = PostCancellableTask(
      *GetExecutionContext()->GetTaskRunner(TaskType::kSensor), FROM_HERE,
      WTF::Bind(&Sensor::NotifyError, WrapWeakPersistent(this),
                WrapPersistent(error)));
}

void Sensor::NotifyReading() {
  DCHECK_EQ(state_, SensorState::kActivated);
  last_reported_timestamp_ = sensor_proxy_->GetReading().timestamp();
  DispatchEvent(Event::Create(EventTypeNames::reading));
}

void Sensor::NotifyActivated() {
  DCHECK_EQ(state_, SensorState::kActivating);
  state_ = SensorState::kActivated;

  if (hasReading()) {
    // If reading has already arrived, send initial 'reading' notification
    // right away.
    DCHECK(!pending_reading_notification_.IsActive());
    pending_reading_notification_ = PostCancellableTask(
        *GetExecutionContext()->GetTaskRunner(TaskType::kSensor), FROM_HERE,
        WTF::Bind(&Sensor::NotifyReading, WrapWeakPersistent(this)));
  }

  DispatchEvent(Event::Create(EventTypeNames::activate));
}

void Sensor::NotifyError(DOMException* error) {
  DCHECK_NE(state_, SensorState::kIdle);
  state_ = SensorState::kIdle;
  DispatchEvent(SensorErrorEvent::Create(EventTypeNames::error, error));
}

bool Sensor::IsIdleOrErrored() const {
  return (state_ == SensorState::kIdle) ||
         pending_error_notification_.IsActive();
}

const device::SensorReading& Sensor::GetReading() const {
  DCHECK(sensor_proxy_);
  return sensor_proxy_->GetReading(use_screen_coords_);
}

}  // namespace blink
