// Copyright 2018 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/core/html/portal/html_portal_element.h"

#include <utility>
#include "services/service_manager/public/cpp/interface_provider.h"
#include "third_party/blink/renderer/bindings/core/v8/script_event_listener.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/post_message_helper.h"
#include "third_party/blink/renderer/bindings/core/v8/serialization/serialized_script_value.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/node.h"
#include "third_party/blink/renderer/core/event_type_names.h"
#include "third_party/blink/renderer/core/events/message_event.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/local_frame_client.h"
#include "third_party/blink/renderer/core/frame/remote_frame.h"
#include "third_party/blink/renderer/core/frame/window_post_message_options.h"
#include "third_party/blink/renderer/core/html/html_unknown_element.h"
#include "third_party/blink/renderer/core/html/parser/html_parser_idioms.h"
#include "third_party/blink/renderer/core/html/portal/document_portals.h"
#include "third_party/blink/renderer/core/html/portal/portal_activate_options.h"
#include "third_party/blink/renderer/core/html/portal/portal_post_message_helper.h"
#include "third_party/blink/renderer/core/html_names.h"
#include "third_party/blink/renderer/core/inspector/console_message.h"
#include "third_party/blink/renderer/core/inspector/thread_debugger.h"
#include "third_party/blink/renderer/core/layout/layout_iframe.h"
#include "third_party/blink/renderer/core/messaging/message_port.h"
#include "third_party/blink/renderer/core/page/page.h"
#include "third_party/blink/renderer/platform/bindings/script_state.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"

namespace blink {

HTMLPortalElement::HTMLPortalElement(
    Document& document,
    const base::UnguessableToken& portal_token,
    mojom::blink::PortalAssociatedPtr portal_ptr,
    mojom::blink::PortalClientAssociatedRequest portal_client_request)
    : HTMLFrameOwnerElement(html_names::kPortalTag, document),
      portal_token_(portal_token),
      portal_ptr_(std::move(portal_ptr)),
      portal_client_binding_(this, std::move(portal_client_request)) {}

HTMLPortalElement::~HTMLPortalElement() {}

void HTMLPortalElement::Trace(Visitor* visitor) {
  HTMLFrameOwnerElement::Trace(visitor);
  visitor->Trace(portal_frame_);
}

void HTMLPortalElement::Navigate() {
  KURL url = GetNonEmptyURLAttribute(html_names::kSrcAttr);
  if (!url.IsEmpty() && portal_ptr_) {
    portal_ptr_->Navigate(url);
  }
}

void HTMLPortalElement::ConsumePortal() {
  if (portal_token_) {
    DocumentPortals::From(GetDocument()).OnPortalRemoved(this);
    portal_token_ = base::UnguessableToken();
  }
  portal_ptr_.reset();
  portal_client_binding_.Close();
}

namespace {

BlinkTransferableMessage ActivateDataAsMessage(
    ScriptState* script_state,
    PortalActivateOptions* options,
    ExceptionState& exception_state) {
  v8::Isolate* isolate = script_state->GetIsolate();
  Transferables transferables;
  if (options->hasTransfer()) {
    if (!SerializedScriptValue::ExtractTransferables(
            script_state->GetIsolate(), options->transfer(), transferables,
            exception_state))
      return {};
  }

  SerializedScriptValue::SerializeOptions serialize_options;
  serialize_options.transferables = &transferables;
  v8::Local<v8::Value> data = options->hasData()
                                  ? options->data().V8Value()
                                  : v8::Null(isolate).As<v8::Value>();

  BlinkTransferableMessage msg;
  msg.message = SerializedScriptValue::Serialize(
      isolate, data, serialize_options, exception_state);
  if (!msg.message)
    return {};

  msg.message->UnregisterMemoryAllocatedWithCurrentScriptContext();

  auto* execution_context = ExecutionContext::From(script_state);
  msg.ports = MessagePort::DisentanglePorts(
      execution_context, transferables.message_ports, exception_state);
  if (exception_state.HadException())
    return {};

  // msg.user_activation is left out; we will probably handle user activation
  // explicitly for activate data.
  // TODO(crbug.com/936184): Answer this for good.

  if (ThreadDebugger* debugger = ThreadDebugger::From(isolate))
    msg.sender_stack_trace_id = debugger->StoreCurrentStackTrace("activate");

  if (msg.message->IsLockedToAgentCluster()) {
    exception_state.ThrowDOMException(
        DOMExceptionCode::kDataCloneError,
        "Cannot send agent cluster-locked data (e.g. SharedArrayBuffer) "
        "through portal activation.");
    return {};
  }

  return msg;
}

}  // namespace

ScriptPromise HTMLPortalElement::activate(ScriptState* script_state,
                                          PortalActivateOptions* options) {
  auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
  ScriptPromise promise = resolver->Promise();

  ExceptionState exception_state(script_state->GetIsolate(),
                                 ExceptionState::kExecutionContext,
                                 "HTMLPortalElement", "activate");

  if (!portal_ptr_) {
    exception_state.ThrowDOMException(
        DOMExceptionCode::kInvalidStateError,
        "The HTMLPortalElement is not associated with a portal context.");
    resolver->Reject(exception_state);
    return promise;
  }
  if (is_activating_) {
    exception_state.ThrowDOMException(
        DOMExceptionCode::kInvalidStateError,
        "activate() has already been called on this HTMLPortalElement.");
    resolver->Reject(exception_state);
    return promise;
  }
  if (DocumentPortals::From(GetDocument()).IsPortalInDocumentActivating()) {
    exception_state.ThrowDOMException(
        DOMExceptionCode::kInvalidStateError,
        "activate() has already been called on another "
        "HTMLPortalElement in this document.");
    resolver->Reject(exception_state);
    return promise;
  }
  if (GetDocument().GetPage()->InsidePortal()) {
    exception_state.ThrowDOMException(
        DOMExceptionCode::kInvalidStateError,
        "Cannot activate a portal that is inside another portal.");
    resolver->Reject(exception_state);
    return promise;
  }

  BlinkTransferableMessage data =
      ActivateDataAsMessage(script_state, options, exception_state);
  if (exception_state.HadException()) {
    resolver->Reject(exception_state);
    return promise;
  }

  // The HTMLPortalElement is bound as a persistent so that it won't get
  // garbage collected while there is a pending callback.
  // We also pass the ownership of the PortalPtr, which guarantees that the
  // PortalPtr stays alive until the callback is called.
  is_activating_ = true;
  auto* raw_portal_ptr = portal_ptr_.get();
  raw_portal_ptr->Activate(
      std::move(data),
      WTF::Bind(
          [](HTMLPortalElement* portal,
             mojom::blink::PortalAssociatedPtr portal_ptr,
             ScriptPromiseResolver* resolver, bool was_adopted) {
            if (was_adopted)
              portal->GetDocument().GetPage()->SetInsidePortal(true);
            resolver->Resolve();
            portal->is_activating_ = false;
            portal->ConsumePortal();
          },
          WrapPersistent(this), std::move(portal_ptr_),
          WrapPersistent(resolver)));
  return promise;
}

void HTMLPortalElement::postMessage(ScriptState* script_state,
                                    const ScriptValue& message,
                                    const String& target_origin,
                                    const Vector<ScriptValue>& transfer,
                                    ExceptionState& exception_state) {
  WindowPostMessageOptions* options = WindowPostMessageOptions::Create();
  options->setTargetOrigin(target_origin);
  if (!transfer.IsEmpty())
    options->setTransfer(transfer);
  postMessage(script_state, message, options, exception_state);
}

void HTMLPortalElement::postMessage(ScriptState* script_state,
                                    const ScriptValue& message,
                                    const WindowPostMessageOptions* options,
                                    ExceptionState& exception_state) {
  if (!portal_ptr_ || is_activating_) {
    exception_state.ThrowDOMException(
        DOMExceptionCode::kInvalidStateError,
        "The HTMLPortalElement is not associated with a portal context");
    return;
  }

  scoped_refptr<const SecurityOrigin> target_origin =
      PostMessageHelper::GetTargetOrigin(options, GetDocument(),
                                         exception_state);
  if (exception_state.HadException())
    return;

  BlinkTransferableMessage transferable_message =
      PortalPostMessageHelper::CreateMessage(script_state, message, options,
                                             exception_state);
  if (exception_state.HadException())
    return;

  portal_ptr_->PostMessageToGuest(std::move(transferable_message),
                                  target_origin);
}

EventListener* HTMLPortalElement::onmessage() {
  return GetAttributeEventListener(event_type_names::kMessage);
}

void HTMLPortalElement::setOnmessage(EventListener* listener) {
  SetAttributeEventListener(event_type_names::kMessage, listener);
}

EventListener* HTMLPortalElement::onmessageerror() {
  return GetAttributeEventListener(event_type_names::kMessageerror);
}

void HTMLPortalElement::setOnmessageerror(EventListener* listener) {
  SetAttributeEventListener(event_type_names::kMessageerror, listener);
}

void HTMLPortalElement::ForwardMessageFromGuest(
    BlinkTransferableMessage message,
    const scoped_refptr<const SecurityOrigin>& source_origin,
    const scoped_refptr<const SecurityOrigin>& target_origin) {
  if (!portal_ptr_)
    return;

  PortalPostMessageHelper::CreateAndDispatchMessageEvent(
      this, std::move(message), source_origin, target_origin);
}

void HTMLPortalElement::DispatchLoadEvent() {
  if (!portal_ptr_)
    return;

  DispatchLoad();
  GetDocument().CheckCompleted();
}

HTMLPortalElement::InsertionNotificationRequest HTMLPortalElement::InsertedInto(
    ContainerNode& node) {
  auto result = HTMLFrameOwnerElement::InsertedInto(node);

  if (!node.IsInDocumentTree() || !GetDocument().IsHTMLDocument() ||
      !GetDocument().GetFrame())
    return result;

  // We don't support embedding portals in nested browsing contexts.
  if (!GetDocument().GetFrame()->IsMainFrame()) {
    GetDocument().AddConsoleMessage(ConsoleMessage::Create(
        mojom::ConsoleMessageSource::kRendering,
        mojom::ConsoleMessageLevel::kWarning,
        "Cannot use <portal> in a nested browsing context."));
    return result;
  }

  if (portal_ptr_) {
    // The interface is already bound if the HTMLPortalElement is adopting the
    // predecessor.
    portal_frame_ = GetDocument().GetFrame()->Client()->AdoptPortal(this);
    portal_ptr_.set_connection_error_handler(
        WTF::Bind(&HTMLPortalElement::ConsumePortal, WrapWeakPersistent(this)));
    DocumentPortals::From(GetDocument()).OnPortalInserted(this);
  } else {
    mojom::blink::PortalClientAssociatedPtr client;
    portal_client_binding_.Bind(mojo::MakeRequest(&client));
    std::tie(portal_frame_, portal_token_) =
        GetDocument().GetFrame()->Client()->CreatePortal(
            this, mojo::MakeRequest(&portal_ptr_), client.PassInterface());
    portal_ptr_.set_connection_error_handler(
        WTF::Bind(&HTMLPortalElement::ConsumePortal, WrapWeakPersistent(this)));
    DocumentPortals::From(GetDocument()).OnPortalInserted(this);
    Navigate();
  }

  return result;
}

void HTMLPortalElement::RemovedFrom(ContainerNode& node) {
  HTMLFrameOwnerElement::RemovedFrom(node);

  Document& document = GetDocument();

  if (node.IsInDocumentTree() && document.IsHTMLDocument()) {
    ConsumePortal();
  }
}

bool HTMLPortalElement::IsURLAttribute(const Attribute& attribute) const {
  return attribute.GetName() == html_names::kSrcAttr ||
         HTMLFrameOwnerElement::IsURLAttribute(attribute);
}

void HTMLPortalElement::ParseAttribute(
    const AttributeModificationParams& params) {
  HTMLFrameOwnerElement::ParseAttribute(params);

  if (params.name == html_names::kSrcAttr) {
    Navigate();
    return;
  }

  struct {
    const QualifiedName& name;
    const AtomicString& event_name;
  } event_handler_attributes[] = {
      {html_names::kOnmessageAttr, event_type_names::kMessage},
      {html_names::kOnmessageerrorAttr, event_type_names::kMessageerror},
  };
  for (const auto& attribute : event_handler_attributes) {
    if (params.name == attribute.name) {
      SetAttributeEventListener(
          attribute.event_name,
          CreateAttributeEventListener(this, attribute.name, params.new_value));
      return;
    }
  }
}

LayoutObject* HTMLPortalElement::CreateLayoutObject(const ComputedStyle& style,
                                                    LegacyLayout) {
  return new LayoutIFrame(this);
}

void HTMLPortalElement::AttachLayoutTree(AttachContext& context) {
  HTMLFrameOwnerElement::AttachLayoutTree(context);

  if (GetLayoutEmbeddedContent() && ContentFrame())
    SetEmbeddedContentView(ContentFrame()->View());
}

}  // namespace blink
