// Copyright 2014 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/presentation/PresentationConnection.h"

#include <memory>
#include "bindings/core/v8/ScriptPromiseResolver.h"
#include "core/dom/Document.h"
#include "core/dom/ExceptionCode.h"
#include "core/dom/events/Event.h"
#include "core/events/MessageEvent.h"
#include "core/fileapi/FileReaderLoader.h"
#include "core/fileapi/FileReaderLoaderClient.h"
#include "core/frame/Deprecation.h"
#include "core/frame/LocalFrame.h"
#include "core/frame/UseCounter.h"
#include "core/typed_arrays/DOMArrayBuffer.h"
#include "core/typed_arrays/DOMArrayBufferView.h"
#include "modules/EventTargetModules.h"
#include "modules/presentation/Presentation.h"
#include "modules/presentation/PresentationConnectionAvailableEvent.h"
#include "modules/presentation/PresentationConnectionCloseEvent.h"
#include "modules/presentation/PresentationController.h"
#include "modules/presentation/PresentationReceiver.h"
#include "modules/presentation/PresentationRequest.h"
#include "platform/wtf/Assertions.h"
#include "platform/wtf/text/AtomicString.h"
#include "public/platform/TaskType.h"

namespace blink {

namespace {

mojom::blink::PresentationConnectionMessagePtr MakeBinaryMessage(
    const DOMArrayBuffer* buffer) {
  // Mutating the data field on the message instead of passing in an already
  // populated Vector into message constructor is more efficient since the
  // latter does not support moves.
  auto message = mojom::blink::PresentationConnectionMessage::NewData(
      WTF::Vector<uint8_t>());
  WTF::Vector<uint8_t>& data = message->get_data();
  data.Append(static_cast<const uint8_t*>(buffer->Data()),
              buffer->ByteLength());
  return message;
}

mojom::blink::PresentationConnectionMessagePtr MakeTextMessage(
    const String& text) {
  return mojom::blink::PresentationConnectionMessage::NewMessage(text);
}

const AtomicString& ConnectionStateToString(
    mojom::blink::PresentationConnectionState state) {
  DEFINE_STATIC_LOCAL(const AtomicString, connecting_value, ("connecting"));
  DEFINE_STATIC_LOCAL(const AtomicString, connected_value, ("connected"));
  DEFINE_STATIC_LOCAL(const AtomicString, closed_value, ("closed"));
  DEFINE_STATIC_LOCAL(const AtomicString, terminated_value, ("terminated"));

  switch (state) {
    case mojom::blink::PresentationConnectionState::CONNECTING:
      return connecting_value;
    case mojom::blink::PresentationConnectionState::CONNECTED:
      return connected_value;
    case mojom::blink::PresentationConnectionState::CLOSED:
      return closed_value;
    case mojom::blink::PresentationConnectionState::TERMINATED:
      return terminated_value;
  }

  NOTREACHED();
  return terminated_value;
}

const AtomicString& ConnectionCloseReasonToString(
    mojom::blink::PresentationConnectionCloseReason reason) {
  DEFINE_STATIC_LOCAL(const AtomicString, error_value, ("error"));
  DEFINE_STATIC_LOCAL(const AtomicString, closed_value, ("closed"));
  DEFINE_STATIC_LOCAL(const AtomicString, went_away_value, ("wentaway"));

  switch (reason) {
    case mojom::blink::PresentationConnectionCloseReason::CONNECTION_ERROR:
      return error_value;
    case mojom::blink::PresentationConnectionCloseReason::CLOSED:
      return closed_value;
    case mojom::blink::PresentationConnectionCloseReason::WENT_AWAY:
      return went_away_value;
  }

  NOTREACHED();
  return error_value;
}

void ThrowPresentationDisconnectedError(ExceptionState& exception_state) {
  exception_state.ThrowDOMException(kInvalidStateError,
                                    "Presentation connection is disconnected.");
}

}  // namespace

class PresentationConnection::Message final
    : public GarbageCollectedFinalized<PresentationConnection::Message> {
 public:
  Message(const String& text) : type(kMessageTypeText), text(text) {}

  Message(DOMArrayBuffer* array_buffer)
      : type(kMessageTypeArrayBuffer), array_buffer(array_buffer) {}

  Message(scoped_refptr<BlobDataHandle> blob_data_handle)
      : type(kMessageTypeBlob), blob_data_handle(std::move(blob_data_handle)) {}

  void Trace(blink::Visitor* visitor) { visitor->Trace(array_buffer); }

  MessageType type;
  String text;
  Member<DOMArrayBuffer> array_buffer;
  scoped_refptr<BlobDataHandle> blob_data_handle;
};

class PresentationConnection::BlobLoader final
    : public GarbageCollectedFinalized<PresentationConnection::BlobLoader>,
      public FileReaderLoaderClient {
 public:
  BlobLoader(scoped_refptr<BlobDataHandle> blob_data_handle,
             PresentationConnection* presentation_connection)
      : presentation_connection_(presentation_connection),
        loader_(FileReaderLoader::Create(FileReaderLoader::kReadAsArrayBuffer,
                                         this)) {
    loader_->Start(presentation_connection_->GetExecutionContext(),
                   std::move(blob_data_handle));
  }
  ~BlobLoader() override = default;

  // FileReaderLoaderClient functions.
  void DidStartLoading() override {}
  void DidReceiveData() override {}
  void DidFinishLoading() override {
    presentation_connection_->DidFinishLoadingBlob(
        loader_->ArrayBufferResult());
  }
  void DidFail(FileError::ErrorCode error_code) override {
    presentation_connection_->DidFailLoadingBlob(error_code);
  }

  void Cancel() { loader_->Cancel(); }

  void Trace(blink::Visitor* visitor) {
    visitor->Trace(presentation_connection_);
  }

 private:
  Member<PresentationConnection> presentation_connection_;
  std::unique_ptr<FileReaderLoader> loader_;
};

PresentationConnection::PresentationConnection(LocalFrame& frame,
                                               const String& id,
                                               const KURL& url)
    : ContextLifecycleObserver(frame.GetDocument()),
      id_(id),
      url_(url),
      state_(mojom::blink::PresentationConnectionState::CONNECTING),
      connection_binding_(this),
      binary_type_(kBinaryTypeArrayBuffer) {}

PresentationConnection::~PresentationConnection() {
  DCHECK(!blob_loader_);
}

void PresentationConnection::OnMessage(
    mojom::blink::PresentationConnectionMessagePtr message,
    OnMessageCallback callback) {
  DCHECK(!callback.is_null());
  if (message->is_data()) {
    const auto& data = message->get_data();
    DidReceiveBinaryMessage(&data.front(), data.size());
  } else {
    DidReceiveTextMessage(message->get_message());
  }

  std::move(callback).Run(true);
}

void PresentationConnection::DidChangeState(
    mojom::blink::PresentationConnectionState state) {
  if (state_ == state)
    return;

  if (state == mojom::blink::PresentationConnectionState::CLOSED) {
    DidClose();
    return;
  }

  state_ = state;

  switch (state_) {
    case mojom::blink::PresentationConnectionState::CONNECTING:
      return;
    case mojom::blink::PresentationConnectionState::CONNECTED:
      DispatchStateChangeEvent(Event::Create(EventTypeNames::connect));
      return;
    // Closed state is handled in |DidClose()|.
    case mojom::blink::PresentationConnectionState::CLOSED:
      return;
    case mojom::blink::PresentationConnectionState::TERMINATED:
      DispatchStateChangeEvent(Event::Create(EventTypeNames::terminate));
      return;
  }
  NOTREACHED();
}

void PresentationConnection::RequestClose() {
  DidChangeState(mojom::blink::PresentationConnectionState::CLOSED);

  // TODO(crbug.com/749327): Instead of calling DidChangeState, consider
  // supplying a callback to RequestClose() and invoking it here.
  if (target_connection_) {
    target_connection_->DidChangeState(
        mojom::blink::PresentationConnectionState::CLOSED);
  }
}

// static
ControllerPresentationConnection* ControllerPresentationConnection::Take(
    ScriptPromiseResolver* resolver,
    const mojom::blink::PresentationInfo& presentation_info,
    PresentationRequest* request) {
  DCHECK(resolver);
  DCHECK(request);
  DCHECK(resolver->GetExecutionContext()->IsDocument());

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

  PresentationController* controller =
      PresentationController::From(*document->GetFrame());
  if (!controller)
    return nullptr;

  return Take(controller, presentation_info, request);
}

// static
ControllerPresentationConnection* ControllerPresentationConnection::Take(
    PresentationController* controller,
    const mojom::blink::PresentationInfo& presentation_info,
    PresentationRequest* request) {
  DCHECK(controller);
  DCHECK(request);

  auto* connection = new ControllerPresentationConnection(
      *controller->GetFrame(), controller, presentation_info.id,
      presentation_info.url);
  controller->RegisterConnection(connection);

  // Fire onconnectionavailable event asynchronously.
  auto* event = PresentationConnectionAvailableEvent::Create(
      EventTypeNames::connectionavailable, connection);
  request->GetExecutionContext()
      ->GetTaskRunner(TaskType::kPresentation)
      ->PostTask(FROM_HERE,
                 WTF::Bind(&PresentationConnection::DispatchEventAsync,
                           WrapPersistent(request), WrapPersistent(event)));

  return connection;
}

ControllerPresentationConnection::ControllerPresentationConnection(
    LocalFrame& frame,
    PresentationController* controller,
    const String& id,
    const KURL& url)
    : PresentationConnection(frame, id, url), controller_(controller) {}

ControllerPresentationConnection::~ControllerPresentationConnection() = default;

void ControllerPresentationConnection::Trace(blink::Visitor* visitor) {
  visitor->Trace(controller_);
  PresentationConnection::Trace(visitor);
}

void ControllerPresentationConnection::Init() {
  // Note that it is possible for the binding to be already bound here, because
  // the ControllerPresentationConnection object could be reused when
  // reconnecting in the same frame. In this case the existing connections are
  // discarded.
  if (connection_binding_.is_bound()) {
    connection_binding_.Close();
    target_connection_.reset();
  }

  mojom::blink::PresentationConnectionPtr controller_connection_ptr;
  connection_binding_.Bind(mojo::MakeRequest(&controller_connection_ptr));

  auto& service = controller_->GetPresentationService();
  if (service) {
    service->SetPresentationConnection(
        mojom::blink::PresentationInfo::New(url_, id_),
        std::move(controller_connection_ptr),
        mojo::MakeRequest(&target_connection_));
  }
}

void ControllerPresentationConnection::DoClose() {
  auto& service = controller_->GetPresentationService();
  if (service)
    service->CloseConnection(url_, id_);
}

void ControllerPresentationConnection::DoTerminate() {
  auto& service = controller_->GetPresentationService();
  if (service)
    service->Terminate(url_, id_);
}

// static
ReceiverPresentationConnection* ReceiverPresentationConnection::Take(
    PresentationReceiver* receiver,
    const mojom::blink::PresentationInfo& presentation_info,
    mojom::blink::PresentationConnectionPtr controller_connection,
    mojom::blink::PresentationConnectionRequest receiver_connection_request) {
  DCHECK(receiver);

  ReceiverPresentationConnection* connection =
      new ReceiverPresentationConnection(*receiver->GetFrame(), receiver,
                                         presentation_info.id,
                                         presentation_info.url);
  connection->Init(std::move(controller_connection),
                   std::move(receiver_connection_request));

  receiver->RegisterConnection(connection);

  return connection;
}

ReceiverPresentationConnection::ReceiverPresentationConnection(
    LocalFrame& frame,
    PresentationReceiver* receiver,
    const String& id,
    const KURL& url)
    : PresentationConnection(frame, id, url), receiver_(receiver) {}

ReceiverPresentationConnection::~ReceiverPresentationConnection() = default;

void ReceiverPresentationConnection::Init(
    mojom::blink::PresentationConnectionPtr controller_connection_ptr,
    mojom::blink::PresentationConnectionRequest receiver_connection_request) {
  target_connection_ = std::move(controller_connection_ptr);
  connection_binding_.Bind(std::move(receiver_connection_request));

  target_connection_->DidChangeState(
      mojom::blink::PresentationConnectionState::CONNECTED);
  DidChangeState(mojom::blink::PresentationConnectionState::CONNECTED);
}

void ReceiverPresentationConnection::DidChangeState(
    mojom::blink::PresentationConnectionState state) {
  PresentationConnection::DidChangeState(state);
  if (state == mojom::blink::PresentationConnectionState::CLOSED)
    receiver_->RemoveConnection(this);
}

void ReceiverPresentationConnection::OnReceiverTerminated() {
  // We don't invoke PresentationConnection::DidChangeState here because we do
  // not want to dispatch an event, as the page might be closing.
  state_ = mojom::blink::PresentationConnectionState::TERMINATED;
  if (target_connection_)
    target_connection_->DidChangeState(state_);
}

void ReceiverPresentationConnection::DoClose() {
  // No-op
}

void ReceiverPresentationConnection::DoTerminate() {
  // This will close the receiver window. At some point later
  // OnReceiverTerminated() will be invoked.
  receiver_->Terminate();
}

void ReceiverPresentationConnection::Trace(blink::Visitor* visitor) {
  visitor->Trace(receiver_);
  PresentationConnection::Trace(visitor);
}

const AtomicString& PresentationConnection::InterfaceName() const {
  return EventTargetNames::PresentationConnection;
}

ExecutionContext* PresentationConnection::GetExecutionContext() const {
  if (!GetFrame())
    return nullptr;
  return GetFrame()->GetDocument();
}

void PresentationConnection::AddedEventListener(
    const AtomicString& event_type,
    RegisteredEventListener& registered_listener) {
  EventTargetWithInlineData::AddedEventListener(event_type,
                                                registered_listener);
  if (event_type == EventTypeNames::connect) {
    UseCounter::Count(GetExecutionContext(),
                      WebFeature::kPresentationConnectionConnectEventListener);
  } else if (event_type == EventTypeNames::close) {
    UseCounter::Count(GetExecutionContext(),
                      WebFeature::kPresentationConnectionCloseEventListener);
  } else if (event_type == EventTypeNames::terminate) {
    UseCounter::Count(
        GetExecutionContext(),
        WebFeature::kPresentationConnectionTerminateEventListener);
  } else if (event_type == EventTypeNames::message) {
    UseCounter::Count(GetExecutionContext(),
                      WebFeature::kPresentationConnectionMessageEventListener);
  }
}

void PresentationConnection::ContextDestroyed(ExecutionContext*) {
  connection_binding_.Close();
}

void PresentationConnection::Trace(blink::Visitor* visitor) {
  visitor->Trace(blob_loader_);
  visitor->Trace(messages_);
  EventTargetWithInlineData::Trace(visitor);
  ContextLifecycleObserver::Trace(visitor);
}

const AtomicString& PresentationConnection::state() const {
  return ConnectionStateToString(state_);
}

void PresentationConnection::send(const String& message,
                                  ExceptionState& exception_state) {
  if (!CanSendMessage(exception_state))
    return;

  messages_.push_back(new Message(message));
  HandleMessageQueue();
}

void PresentationConnection::send(DOMArrayBuffer* array_buffer,
                                  ExceptionState& exception_state) {
  DCHECK(array_buffer);
  DCHECK(array_buffer->Buffer());
  if (!CanSendMessage(exception_state))
    return;

  messages_.push_back(new Message(array_buffer));
  HandleMessageQueue();
}

void PresentationConnection::send(
    NotShared<DOMArrayBufferView> array_buffer_view,
    ExceptionState& exception_state) {
  DCHECK(array_buffer_view);
  if (!CanSendMessage(exception_state))
    return;

  messages_.push_back(new Message(array_buffer_view.View()->buffer()));
  HandleMessageQueue();
}

void PresentationConnection::send(Blob* data, ExceptionState& exception_state) {
  DCHECK(data);
  if (!CanSendMessage(exception_state))
    return;

  messages_.push_back(new Message(data->GetBlobDataHandle()));
  HandleMessageQueue();
}

bool PresentationConnection::CanSendMessage(ExceptionState& exception_state) {
  if (state_ != mojom::blink::PresentationConnectionState::CONNECTED) {
    ThrowPresentationDisconnectedError(exception_state);
    return false;
  }

  return !!target_connection_;
}

void PresentationConnection::HandleMessageQueue() {
  if (!target_connection_)
    return;

  while (!messages_.IsEmpty() && !blob_loader_) {
    Message* message = messages_.front().Get();
    switch (message->type) {
      case kMessageTypeText:
        SendMessageToTargetConnection(MakeTextMessage(message->text));
        messages_.pop_front();
        break;
      case kMessageTypeArrayBuffer:
        SendMessageToTargetConnection(MakeBinaryMessage(message->array_buffer));
        messages_.pop_front();
        break;
      case kMessageTypeBlob:
        DCHECK(!blob_loader_);
        blob_loader_ = new BlobLoader(message->blob_data_handle, this);
        break;
    }
  }
}

String PresentationConnection::binaryType() const {
  switch (binary_type_) {
    case kBinaryTypeBlob:
      return "blob";
    case kBinaryTypeArrayBuffer:
      return "arraybuffer";
  }
  NOTREACHED();
  return String();
}

void PresentationConnection::setBinaryType(const String& binary_type) {
  if (binary_type == "blob") {
    binary_type_ = kBinaryTypeBlob;
    return;
  }
  if (binary_type == "arraybuffer") {
    binary_type_ = kBinaryTypeArrayBuffer;
    return;
  }
  NOTREACHED();
}

void PresentationConnection::SendMessageToTargetConnection(
    mojom::blink::PresentationConnectionMessagePtr message) {
  if (target_connection_) {
    target_connection_->OnMessage(std::move(message),
                                  base::OnceCallback<void(bool)>());
  }
}

void PresentationConnection::DidReceiveTextMessage(const WebString& message) {
  if (state_ != mojom::blink::PresentationConnectionState::CONNECTED)
    return;

  DispatchEvent(MessageEvent::Create(message));
}

void PresentationConnection::DidReceiveBinaryMessage(const uint8_t* data,
                                                     size_t length) {
  if (state_ != mojom::blink::PresentationConnectionState::CONNECTED)
    return;

  switch (binary_type_) {
    case kBinaryTypeBlob: {
      std::unique_ptr<BlobData> blob_data = BlobData::Create();
      blob_data->AppendBytes(data, length);
      Blob* blob =
          Blob::Create(BlobDataHandle::Create(std::move(blob_data), length));
      DispatchEvent(MessageEvent::Create(blob));
      return;
    }
    case kBinaryTypeArrayBuffer:
      DOMArrayBuffer* buffer = DOMArrayBuffer::Create(data, length);
      DispatchEvent(MessageEvent::Create(buffer));
      return;
  }
  NOTREACHED();
}

mojom::blink::PresentationConnectionState PresentationConnection::GetState()
    const {
  return state_;
}

void PresentationConnection::close() {
  if (state_ != mojom::blink::PresentationConnectionState::CONNECTING &&
      state_ != mojom::blink::PresentationConnectionState::CONNECTED) {
    return;
  }

  if (target_connection_)
    target_connection_->RequestClose();

  DoClose();
  TearDown();
}

void PresentationConnection::terminate() {
  if (state_ != mojom::blink::PresentationConnectionState::CONNECTED)
    return;

  DoTerminate();
  TearDown();
}

bool PresentationConnection::Matches(const String& id, const KURL& url) const {
  return url_ == url && id_ == id;
}

void PresentationConnection::DidClose(
    mojom::blink::PresentationConnectionCloseReason reason,
    const String& message) {
  if (state_ == mojom::blink::PresentationConnectionState::CLOSED ||
      state_ == mojom::blink::PresentationConnectionState::TERMINATED) {
    return;
  }

  state_ = mojom::blink::PresentationConnectionState::CLOSED;
  DispatchStateChangeEvent(PresentationConnectionCloseEvent::Create(
      EventTypeNames::close, ConnectionCloseReasonToString(reason), message));
}

void PresentationConnection::DidClose() {
  DidClose(mojom::blink::PresentationConnectionCloseReason::CLOSED, "");
}

void PresentationConnection::DidFinishLoadingBlob(DOMArrayBuffer* buffer) {
  DCHECK(!messages_.IsEmpty());
  DCHECK_EQ(messages_.front()->type, kMessageTypeBlob);
  DCHECK(buffer);
  DCHECK(buffer->Buffer());

  // Send the loaded blob immediately here and continue processing the queue.
  SendMessageToTargetConnection(MakeBinaryMessage(buffer));

  messages_.pop_front();
  blob_loader_.Clear();
  HandleMessageQueue();
}

void PresentationConnection::DidFailLoadingBlob(
    FileError::ErrorCode error_code) {
  DCHECK(!messages_.IsEmpty());
  DCHECK_EQ(messages_.front()->type, kMessageTypeBlob);
  // FIXME: generate error message?
  // Ignore the current failed blob item and continue with next items.
  messages_.pop_front();
  blob_loader_.Clear();
  HandleMessageQueue();
}

void PresentationConnection::DispatchStateChangeEvent(Event* event) {
  GetExecutionContext()
      ->GetTaskRunner(TaskType::kPresentation)
      ->PostTask(FROM_HERE,
                 WTF::Bind(&PresentationConnection::DispatchEventAsync,
                           WrapPersistent(this), WrapPersistent(event)));
}

// static
void PresentationConnection::DispatchEventAsync(EventTarget* target,
                                                Event* event) {
  DCHECK(target);
  DCHECK(event);
  target->DispatchEvent(event);
}

void PresentationConnection::TearDown() {
  // Cancel current Blob loading if any.
  if (blob_loader_) {
    blob_loader_->Cancel();
    blob_loader_.Clear();
  }
  messages_.clear();
}

}  // namespace blink
