// 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 "third_party/blink/renderer/modules/remoteplayback/remote_playback.h"

#include "third_party/blink/public/platform/task_type.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/bindings/modules/v8/v8_remote_playback_availability_callback.h"
#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
#include "third_party/blink/renderer/core/html/media/html_media_element.h"
#include "third_party/blink/renderer/core/html/media/html_video_element.h"
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"
#include "third_party/blink/renderer/modules/event_target_modules.h"
#include "third_party/blink/renderer/modules/presentation/presentation_availability_state.h"
#include "third_party/blink/renderer/modules/presentation/presentation_controller.h"
#include "third_party/blink/renderer/modules/remoteplayback/availability_callback_wrapper.h"
#include "third_party/blink/renderer/platform/memory_coordinator.h"
#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
#include "third_party/blink/renderer/platform/wtf/text/base64.h"

namespace blink {

namespace {

const AtomicString& RemotePlaybackStateToString(WebRemotePlaybackState state) {
  DEFINE_STATIC_LOCAL(const AtomicString, connecting_value, ("connecting"));
  DEFINE_STATIC_LOCAL(const AtomicString, connected_value, ("connected"));
  DEFINE_STATIC_LOCAL(const AtomicString, disconnected_value, ("disconnected"));

  switch (state) {
    case WebRemotePlaybackState::kConnecting:
      return connecting_value;
    case WebRemotePlaybackState::kConnected:
      return connected_value;
    case WebRemotePlaybackState::kDisconnected:
      return disconnected_value;
  }

  NOTREACHED();
  return disconnected_value;
}

void RunRemotePlaybackTask(ExecutionContext* context,
                           base::OnceClosure task,
                           std::unique_ptr<int> task_id) {
  probe::AsyncTask async_task(context, task_id.get());
  std::move(task).Run();
}

KURL GetAvailabilityUrl(const WebURL& source, bool is_source_supported) {
  if (source.IsEmpty() || !source.IsValid() || !is_source_supported)
    return KURL();

  // The URL for each media element's source looks like the following:
  // remote-playback://<encoded-data> where |encoded-data| is base64 URL
  // encoded string representation of the source URL.
  std::string source_string = source.GetString().Utf8();
  String encoded_source = WTF::Base64URLEncode(
      source_string.data(), SafeCast<unsigned>(source_string.length()));

  return KURL("remote-playback://" + encoded_source);
}

bool IsBackgroundAvailabilityMonitoringDisabled() {
  return MemoryCoordinator::IsLowEndDevice();
}

}  // anonymous namespace

// static
RemotePlayback* RemotePlayback::Create(HTMLMediaElement& element) {
  return MakeGarbageCollected<RemotePlayback>(element);
}

RemotePlayback::RemotePlayback(HTMLMediaElement& element)
    : ContextLifecycleObserver(element.GetExecutionContext()),
      state_(element.IsPlayingRemotely()
                 ? WebRemotePlaybackState::kConnected
                 : WebRemotePlaybackState::kDisconnected),
      availability_(WebRemotePlaybackAvailability::kUnknown),
      media_element_(&element),
      is_listening_(false),
      presentation_connection_binding_(this) {}

const AtomicString& RemotePlayback::InterfaceName() const {
  return event_target_names::kRemotePlayback;
}

ExecutionContext* RemotePlayback::GetExecutionContext() const {
  return &media_element_->GetDocument();
}

ScriptPromise RemotePlayback::watchAvailability(
    ScriptState* script_state,
    V8RemotePlaybackAvailabilityCallback* callback) {
  ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
  ScriptPromise promise = resolver->Promise();

  if (media_element_->FastHasAttribute(
          html_names::kDisableremoteplaybackAttr)) {
    resolver->Reject(
        DOMException::Create(DOMExceptionCode::kInvalidStateError,
                             "disableRemotePlayback attribute is present."));
    return promise;
  }

  int id = WatchAvailabilityInternal(new AvailabilityCallbackWrapper(callback));
  if (id == kWatchAvailabilityNotSupported) {
    resolver->Reject(DOMException::Create(
        DOMExceptionCode::kNotSupportedError,
        "Availability monitoring is not supported on this device."));
    return promise;
  }

  // TODO(avayvod): Currently the availability is tracked for each media element
  // as soon as it's created, we probably want to limit that to when the
  // page/element is visible (see https://crbug.com/597281) and has default
  // controls. If there are no default controls, we should also start tracking
  // availability on demand meaning the Promise returned by watchAvailability()
  // will be resolved asynchronously.
  resolver->Resolve(id);
  return promise;
}

ScriptPromise RemotePlayback::cancelWatchAvailability(ScriptState* script_state,
                                                      int id) {
  ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
  ScriptPromise promise = resolver->Promise();

  if (media_element_->FastHasAttribute(
          html_names::kDisableremoteplaybackAttr)) {
    resolver->Reject(
        DOMException::Create(DOMExceptionCode::kInvalidStateError,
                             "disableRemotePlayback attribute is present."));
    return promise;
  }

  if (!CancelWatchAvailabilityInternal(id)) {
    resolver->Reject(
        DOMException::Create(DOMExceptionCode::kNotFoundError,
                             "A callback with the given id is not found."));
    return promise;
  }

  resolver->Resolve();
  return promise;
}

ScriptPromise RemotePlayback::cancelWatchAvailability(
    ScriptState* script_state) {
  ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
  ScriptPromise promise = resolver->Promise();

  if (media_element_->FastHasAttribute(
          html_names::kDisableremoteplaybackAttr)) {
    resolver->Reject(
        DOMException::Create(DOMExceptionCode::kInvalidStateError,
                             "disableRemotePlayback attribute is present."));
    return promise;
  }

  availability_callbacks_.clear();
  StopListeningForAvailability();

  resolver->Resolve();
  return promise;
}

ScriptPromise RemotePlayback::prompt(ScriptState* script_state) {
  ScriptPromiseResolver* resolver = ScriptPromiseResolver::Create(script_state);
  ScriptPromise promise = resolver->Promise();

  if (media_element_->FastHasAttribute(
          html_names::kDisableremoteplaybackAttr)) {
    resolver->Reject(
        DOMException::Create(DOMExceptionCode::kInvalidStateError,
                             "disableRemotePlayback attribute is present."));
    return promise;
  }

  if (prompt_promise_resolver_) {
    resolver->Reject(DOMException::Create(
        DOMExceptionCode::kOperationError,
        "A prompt is already being shown for this media element."));
    return promise;
  }

  if (!LocalFrame::HasTransientUserActivation(media_element_->GetFrame())) {
    resolver->Reject(DOMException::Create(
        DOMExceptionCode::kInvalidAccessError,
        "RemotePlayback::prompt() requires user gesture."));
    return promise;
  }

  if (!RuntimeEnabledFeatures::RemotePlaybackBackendEnabled()) {
    resolver->Reject(DOMException::Create(
        DOMExceptionCode::kNotSupportedError,
        "The RemotePlayback API is disabled on this platform."));
    return promise;
  }

  if (availability_ == WebRemotePlaybackAvailability::kDeviceNotAvailable) {
    resolver->Reject(DOMException::Create(DOMExceptionCode::kNotFoundError,
                                          "No remote playback devices found."));
    return promise;
  }

  if (availability_ == WebRemotePlaybackAvailability::kSourceNotCompatible) {
    resolver->Reject(DOMException::Create(
        DOMExceptionCode::kNotSupportedError,
        "The currentSrc is not compatible with remote playback"));
    return promise;
  }

  prompt_promise_resolver_ = resolver;
  PromptInternal();

  return promise;
}

String RemotePlayback::state() const {
  return RemotePlaybackStateToString(state_);
}

bool RemotePlayback::HasPendingActivity() const {
  return HasEventListeners() || !availability_callbacks_.IsEmpty() ||
         prompt_promise_resolver_;
}

void RemotePlayback::ContextDestroyed(ExecutionContext*) {
  CleanupConnections();
}

void RemotePlayback::PromptInternal() {
  DCHECK(RuntimeEnabledFeatures::RemotePlaybackBackendEnabled());

  if (RuntimeEnabledFeatures::NewRemotePlaybackPipelineEnabled()) {
    PresentationController* controller =
        PresentationController::FromContext(GetExecutionContext());
    if (controller && !availability_urls_.IsEmpty()) {
      controller->GetPresentationService()->StartPresentation(
          availability_urls_,
          WTF::Bind(&RemotePlayback::HandlePresentationResponse,
                    WrapPersistent(this)));
    } else {
      // TODO(yuryu): Wrapping PromptCancelled with base::OnceClosure as
      // InspectorInstrumentation requires a globally unique pointer to track
      // tasks. We can remove the wrapper if InspectorInstrumentation returns a
      // task id.
      base::OnceClosure task =
          WTF::Bind(&RemotePlayback::PromptCancelled, WrapPersistent(this));
      std::unique_ptr<int> task_id = std::make_unique<int>(0);
      probe::AsyncTaskScheduled(GetExecutionContext(), "promptCancelled",
                                task_id.get());
      GetExecutionContext()
          ->GetTaskRunner(TaskType::kMediaElementEvent)
          ->PostTask(FROM_HERE, WTF::Bind(RunRemotePlaybackTask,
                                          WrapPersistent(GetExecutionContext()),
                                          WTF::Passed(std::move(task)),
                                          WTF::Passed(std::move(task_id))));
    }
    return;
  }

  if (state_ == WebRemotePlaybackState::kDisconnected)
    media_element_->RequestRemotePlayback();
  else
    media_element_->RequestRemotePlaybackControl();
}

int RemotePlayback::WatchAvailabilityInternal(
    AvailabilityCallbackWrapper* callback) {
  if (RuntimeEnabledFeatures::RemotePlaybackBackendEnabled() &&
      IsBackgroundAvailabilityMonitoringDisabled()) {
    return kWatchAvailabilityNotSupported;
  }

  int id;
  do {
    id = GetExecutionContext()->CircularSequentialID();
  } while (!availability_callbacks_.insert(id, callback).is_new_entry);

  // Report the current availability via the callback.
  // TODO(yuryu): Wrapping notifyInitialAvailability with base::OnceClosure as
  // InspectorInstrumentation requires a globally unique pointer to track tasks.
  // We can remove the wrapper if InspectorInstrumentation returns a task id.
  base::OnceClosure task = WTF::Bind(&RemotePlayback::NotifyInitialAvailability,
                                     WrapPersistent(this), id);
  std::unique_ptr<int> task_id = std::make_unique<int>(0);
  probe::AsyncTaskScheduled(GetExecutionContext(), "watchAvailabilityCallback",
                            task_id.get());
  GetExecutionContext()
      ->GetTaskRunner(TaskType::kMediaElementEvent)
      ->PostTask(FROM_HERE, WTF::Bind(RunRemotePlaybackTask,
                                      WrapPersistent(GetExecutionContext()),
                                      WTF::Passed(std::move(task)),
                                      WTF::Passed(std::move(task_id))));

  MaybeStartListeningForAvailability();
  return id;
}

bool RemotePlayback::CancelWatchAvailabilityInternal(int id) {
  if (id <= 0)  // HashMap doesn't support the cases of key = 0 or key = -1.
    return false;
  auto iter = availability_callbacks_.find(id);
  if (iter == availability_callbacks_.end())
    return false;
  availability_callbacks_.erase(iter);
  if (availability_callbacks_.IsEmpty())
    StopListeningForAvailability();

  return true;
}

void RemotePlayback::NotifyInitialAvailability(int callback_id) {
  // May not find the callback if the website cancels it fast enough.
  auto iter = availability_callbacks_.find(callback_id);
  if (iter == availability_callbacks_.end())
    return;

  iter->value->Run(this, RemotePlaybackAvailable());
}

void RemotePlayback::StateChanged(WebRemotePlaybackState state) {
  if (prompt_promise_resolver_) {
    // Changing state to "disconnected" from "disconnected" or "connecting"
    // means that establishing connection with remote playback device failed.
    // Changing state to anything else means the state change intended by
    // prompt() succeeded.
    if (state_ != WebRemotePlaybackState::kConnected &&
        state == WebRemotePlaybackState::kDisconnected) {
      prompt_promise_resolver_->Reject(
          DOMException::Create(DOMExceptionCode::kAbortError,
                               "Failed to connect to the remote device."));
    } else {
      DCHECK((state_ == WebRemotePlaybackState::kDisconnected &&
              state == WebRemotePlaybackState::kConnecting) ||
             (state_ == WebRemotePlaybackState::kConnected &&
              state == WebRemotePlaybackState::kDisconnected));
      prompt_promise_resolver_->Resolve();
    }
    prompt_promise_resolver_ = nullptr;
  }

  if (state_ == state)
    return;

  state_ = state;
  switch (state_) {
    case WebRemotePlaybackState::kConnecting:
      DispatchEvent(*Event::Create(event_type_names::kConnecting));
      if (RuntimeEnabledFeatures::NewRemotePlaybackPipelineEnabled()) {
        if (media_element_->IsHTMLVideoElement()) {
          // TODO(xjz): Pass the remote device name.
          ToHTMLVideoElement(media_element_)->MediaRemotingStarted(WebString());
        }
        media_element_->FlingingStarted();
      }
      break;
    case WebRemotePlaybackState::kConnected:
      DispatchEvent(*Event::Create(event_type_names::kConnect));
      break;
    case WebRemotePlaybackState::kDisconnected:
      DispatchEvent(*Event::Create(event_type_names::kDisconnect));
      if (RuntimeEnabledFeatures::NewRemotePlaybackPipelineEnabled()) {
        if (media_element_->IsHTMLVideoElement()) {
          ToHTMLVideoElement(media_element_)
              ->MediaRemotingStopped(
                  WebLocalizedString::kMediaRemotingStopNoText);
        }
        CleanupConnections();
        presentation_id_ = "";
        presentation_url_ = KURL();
        media_element_->FlingingStopped();
      }
      break;
  }
}

void RemotePlayback::AvailabilityChanged(
    WebRemotePlaybackAvailability availability) {
  if (availability_ == availability)
    return;

  bool old_availability = RemotePlaybackAvailable();
  availability_ = availability;
  bool new_availability = RemotePlaybackAvailable();
  if (new_availability == old_availability)
    return;

  for (auto& callback : availability_callbacks_.Values())
    callback->Run(this, new_availability);
}

void RemotePlayback::PromptCancelled() {
  if (!prompt_promise_resolver_)
    return;

  prompt_promise_resolver_->Reject(DOMException::Create(
      DOMExceptionCode::kNotAllowedError, "The prompt was dismissed."));
  prompt_promise_resolver_ = nullptr;
}

void RemotePlayback::SourceChanged(const WebURL& source,
                                   bool is_source_supported) {
  DCHECK(RuntimeEnabledFeatures::NewRemotePlaybackPipelineEnabled());

  if (IsBackgroundAvailabilityMonitoringDisabled())
    return;

  KURL current_url =
      availability_urls_.IsEmpty() ? KURL() : availability_urls_[0];
  KURL new_url = GetAvailabilityUrl(source, is_source_supported);

  if (new_url == current_url)
    return;

  // Tell PresentationController to stop listening for availability before the
  // URLs vector is updated.
  StopListeningForAvailability();

  availability_urls_.clear();
  if (!new_url.IsEmpty())
    availability_urls_.push_back(new_url);

  MaybeStartListeningForAvailability();
}

WebString RemotePlayback::GetPresentationId() {
  return presentation_id_;
}

bool RemotePlayback::RemotePlaybackAvailable() const {
  if (IsBackgroundAvailabilityMonitoringDisabled() &&
      RuntimeEnabledFeatures::RemotePlaybackBackendEnabled() &&
      !media_element_->currentSrc().IsEmpty()) {
    return true;
  }

  return availability_ == WebRemotePlaybackAvailability::kDeviceAvailable;
}

void RemotePlayback::RemotePlaybackDisabled() {
  if (prompt_promise_resolver_) {
    prompt_promise_resolver_->Reject(
        DOMException::Create(DOMExceptionCode::kInvalidStateError,
                             "disableRemotePlayback attribute is present."));
    prompt_promise_resolver_ = nullptr;
  }

  availability_callbacks_.clear();
  StopListeningForAvailability();

  if (state_ == WebRemotePlaybackState::kDisconnected)
    return;

  if (RuntimeEnabledFeatures::NewRemotePlaybackPipelineEnabled()) {
    auto* controller =
        PresentationController::FromContext(GetExecutionContext());
    if (controller) {
      controller->GetPresentationService()->CloseConnection(presentation_url_,
                                                            presentation_id_);
    }
  } else {
    media_element_->RequestRemotePlaybackStop();
  }
}

void RemotePlayback::CleanupConnections() {
  target_presentation_connection_.reset();
  presentation_connection_binding_.Close();
}

void RemotePlayback::AvailabilityChanged(
    mojom::blink::ScreenAvailability availability) {
  DCHECK(RuntimeEnabledFeatures::NewRemotePlaybackPipelineEnabled());
  DCHECK(is_listening_);

  // TODO(avayvod): Use mojom::ScreenAvailability directly once
  // WebRemotePlaybackAvailability is gone with the old pipeline.
  WebRemotePlaybackAvailability remote_playback_availability =
      WebRemotePlaybackAvailability::kUnknown;
  switch (availability) {
    case mojom::ScreenAvailability::UNKNOWN:
    case mojom::ScreenAvailability::DISABLED:
      NOTREACHED();
      remote_playback_availability = WebRemotePlaybackAvailability::kUnknown;
      break;
    case mojom::ScreenAvailability::UNAVAILABLE:
      remote_playback_availability =
          WebRemotePlaybackAvailability::kDeviceNotAvailable;
      break;
    case mojom::ScreenAvailability::SOURCE_NOT_SUPPORTED:
      remote_playback_availability =
          WebRemotePlaybackAvailability::kSourceNotCompatible;
      break;
    case mojom::ScreenAvailability::AVAILABLE:
      remote_playback_availability =
          WebRemotePlaybackAvailability::kDeviceAvailable;
      break;
  }
  AvailabilityChanged(remote_playback_availability);
}

const Vector<KURL>& RemotePlayback::Urls() const {
  DCHECK(RuntimeEnabledFeatures::NewRemotePlaybackPipelineEnabled());
  // TODO(avayvod): update the URL format and add frame url, mime type and
  // response headers when available.
  return availability_urls_;
}

void RemotePlayback::OnConnectionSuccess(
    mojom::blink::PresentationConnectionResultPtr result) {
  DCHECK(RuntimeEnabledFeatures::NewRemotePlaybackPipelineEnabled());
  presentation_id_ = std::move(result->presentation_info->id);
  presentation_url_ = std::move(result->presentation_info->url);

  StateChanged(WebRemotePlaybackState::kConnecting);

  DCHECK(!presentation_connection_binding_.is_bound());
  auto* presentation_controller =
      PresentationController::FromContext(GetExecutionContext());
  if (!presentation_controller)
    return;

  // Note: Messages on |connection_request| are ignored.
  target_presentation_connection_.Bind(std::move(result->connection_ptr));
  presentation_connection_binding_.Bind(std::move(result->connection_request));
}

void RemotePlayback::OnConnectionError(
    const mojom::blink::PresentationError& error) {
  DCHECK(RuntimeEnabledFeatures::NewRemotePlaybackPipelineEnabled());
  presentation_id_ = "";
  presentation_url_ = KURL();
  if (error.error_type ==
      mojom::blink::PresentationErrorType::PRESENTATION_REQUEST_CANCELLED) {
    PromptCancelled();
    return;
  }

  StateChanged(WebRemotePlaybackState::kDisconnected);
}

void RemotePlayback::HandlePresentationResponse(
    mojom::blink::PresentationConnectionResultPtr result,
    mojom::blink::PresentationErrorPtr error) {
  if (result) {
    OnConnectionSuccess(std::move(result));
  } else {
    OnConnectionError(*error);
  }
}

void RemotePlayback::OnMessage(
    mojom::blink::PresentationConnectionMessagePtr message) {
  // Messages are ignored.
}

void RemotePlayback::DidChangeState(
    mojom::blink::PresentationConnectionState state) {
  WebRemotePlaybackState remote_playback_state =
      WebRemotePlaybackState::kDisconnected;
  if (state == mojom::blink::PresentationConnectionState::CONNECTING)
    remote_playback_state = WebRemotePlaybackState::kConnecting;
  else if (state == mojom::blink::PresentationConnectionState::CONNECTED)
    remote_playback_state = WebRemotePlaybackState::kConnected;

  StateChanged(remote_playback_state);
}

void RemotePlayback::DidClose(
    mojom::blink::PresentationConnectionCloseReason reason) {
  StateChanged(WebRemotePlaybackState::kDisconnected);
}

void RemotePlayback::StopListeningForAvailability() {
  if (!RuntimeEnabledFeatures::RemotePlaybackBackendEnabled())
    return;

  if (!is_listening_)
    return;

  availability_ = WebRemotePlaybackAvailability::kUnknown;
  PresentationController* controller =
      PresentationController::FromContext(GetExecutionContext());
  if (!controller)
    return;

  controller->RemoveAvailabilityObserver(this);
  is_listening_ = false;
}

void RemotePlayback::MaybeStartListeningForAvailability() {
  if (IsBackgroundAvailabilityMonitoringDisabled())
    return;

  if (!RuntimeEnabledFeatures::RemotePlaybackBackendEnabled())
    return;

  if (is_listening_)
    return;

  if (availability_urls_.IsEmpty() || availability_callbacks_.IsEmpty())
    return;

  PresentationController* controller =
      PresentationController::FromContext(GetExecutionContext());
  if (!controller)
    return;

  controller->AddAvailabilityObserver(this);
  is_listening_ = true;
}

void RemotePlayback::Trace(blink::Visitor* visitor) {
  visitor->Trace(availability_callbacks_);
  visitor->Trace(prompt_promise_resolver_);
  visitor->Trace(media_element_);
  EventTargetWithInlineData::Trace(visitor);
  ContextLifecycleObserver::Trace(visitor);
}

}  // namespace blink
