// 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 "third_party/blink/public/mojom/loader/referrer.mojom-blink.h"
#include "third_party/blink/public/mojom/web_feature/web_feature.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/js_event_handler_for_content_attribute.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/bindings/core/v8/v8_binding_for_core.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_portal_activate_options.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_window_post_message_options.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_dom_window.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/html/html_document.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_activation_delegate.h"
#include "third_party/blink/renderer/core/html/portal/portal_contents.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/core/probe/core_probes.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/instrumentation/use_counter.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h"
#include "third_party/blink/renderer/platform/scheduler/public/scheduling_policy.h"
#include "third_party/blink/renderer/platform/weborigin/referrer.h"
#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
#include "third_party/blink/renderer/platform/weborigin/security_policy.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"

namespace blink {

HTMLPortalElement::HTMLPortalElement(
    Document& document,
    const PortalToken* portal_token,
    mojo::PendingAssociatedRemote<mojom::blink::Portal> remote_portal,
    mojo::PendingAssociatedReceiver<mojom::blink::PortalClient>
        portal_client_receiver)
    : HTMLFrameOwnerElement(html_names::kPortalTag, document),
      feature_handle_for_scheduler_(
          document.GetExecutionContext()->GetScheduler()->RegisterFeature(
              SchedulingPolicy::Feature::kPortal,
              {SchedulingPolicy::DisableBackForwardCache()})) {
  if (remote_portal) {
    DCHECK(portal_token);
    was_just_adopted_ = true;
    DCHECK(CanHaveGuestContents())
        << "<portal> element was created with an existing contents but is not "
           "permitted to have one";
    portal_ = MakeGarbageCollected<PortalContents>(
        *this, *portal_token, std::move(remote_portal),
        std::move(portal_client_receiver));
  }
  UseCounter::Count(document, WebFeature::kHTMLPortalElement);
}

HTMLPortalElement::~HTMLPortalElement() {}

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

void HTMLPortalElement::ConsumePortal() {
  if (portal_)
    portal_->Destroy();

  DCHECK(!portal_);
}

void HTMLPortalElement::ExpireAdoptionLifetime() {
  was_just_adopted_ = false;

  // After dispatching the portalactivate event, we check to see if we need to
  // cleanup the portal hosting the predecessor. If the portal was created,
  // but wasn't inserted or activated, we destroy it.
  if (!CanHaveGuestContents())
    ConsumePortal();
}

void HTMLPortalElement::PortalContentsWillBeDestroyed(PortalContents* portal) {
  DCHECK_EQ(portal_, portal);
  portal_ = nullptr;
}

bool HTMLPortalElement::IsCurrentlyWithinFrameLimit() const {
  auto* frame = GetDocument().GetFrame();
  if (!frame)
    return false;
  auto* page = frame->GetPage();
  if (!page)
    return false;
  return page->SubframeCount() < Page::MaxNumberOfFrames();
}

String HTMLPortalElement::PreActivateChecksCommon() {
  if (!portal_)
    return "The HTMLPortalElement is not associated with a portal context.";

  if (DocumentPortals::From(GetDocument()).IsPortalInDocumentActivating())
    return "Another portal in this document is activating.";

  if (GetDocument().GetPage()->InsidePortal())
    return "Cannot activate a portal that is inside another portal.";

  if (GetDocument().BeforeUnloadStarted()) {
    return "Cannot activate portal while document is in beforeunload or has "
           "started unloading.";
  }

  return String();
}

void HTMLPortalElement::ActivateDefault() {
  ExecutionContext* context = GetExecutionContext();
  if (!CheckPortalsEnabledOrWarn() || !context)
    return;

  String pre_activate_error = PreActivateChecksCommon();
  if (pre_activate_error) {
    context->AddConsoleMessage(mojom::blink::ConsoleMessageSource::kRendering,
                               mojom::blink::ConsoleMessageLevel::kWarning,
                               pre_activate_error);
    return;
  }

  // Quickly encode undefined without actually invoking script.
  BlinkTransferableMessage data;
  data.message = SerializedScriptValue::UndefinedValue();
  data.message->UnregisterMemoryAllocatedWithCurrentScriptContext();
  data.sender_origin =
      GetExecutionContext()->GetSecurityOrigin()->IsolatedCopy();
  if (ThreadDebugger* debugger =
          ThreadDebugger::From(V8PerIsolateData::MainThreadIsolate())) {
    data.sender_stack_trace_id =
        debugger->StoreCurrentStackTrace("activate (implicit)");
  }

  PortalContents* portal = std::exchange(portal_, nullptr);
  portal->Activate(std::move(data),
                   PortalActivationDelegate::ForConsole(context));
}

bool HTMLPortalElement::CheckWithinFrameLimitOrWarn() const {
  if (IsCurrentlyWithinFrameLimit())
    return true;

  Document& document = GetDocument();
  document.AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
      mojom::blink::ConsoleMessageSource::kRendering,
      mojom::blink::ConsoleMessageLevel::kWarning,
      "An operation was prevented due to too many frames and portals present "
      "on the page."));
  return false;
}

bool HTMLPortalElement::CheckPortalsEnabledOrWarn() const {
  ExecutionContext* context = GetExecutionContext();
  if (RuntimeEnabledFeatures::PortalsEnabled(context))
    return true;

  context->AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
      mojom::blink::ConsoleMessageSource::kRendering,
      mojom::blink::ConsoleMessageLevel::kWarning,
      "An operation was prevented because a <portal> was moved to a document "
      "where it is not enabled. See "
      "https://www.chromium.org/blink/origin-trials/portals."));
  return false;
}

bool HTMLPortalElement::CheckPortalsEnabledOrThrow(
    ExceptionState& exception_state) const {
  if (RuntimeEnabledFeatures::PortalsEnabled(GetExecutionContext()))
    return true;

  exception_state.ThrowDOMException(
      DOMExceptionCode::kNotSupportedError,
      "An operation was prevented because a <portal> was moved to a document "
      "where it is not enabled. See "
      "https://www.chromium.org/blink/origin-trials/portals.");
  return false;
}

// https://wicg.github.io/portals/#htmlportalelement-may-have-a-guest-browsing-context
HTMLPortalElement::GuestContentsEligibility
HTMLPortalElement::GetGuestContentsEligibility() const {
  // Non-HTML documents aren't eligible at all.
  if (!IsA<HTMLDocument>(GetDocument()))
    return GuestContentsEligibility::kIneligible;

  LocalFrame* frame = GetDocument().GetFrame();
  const bool is_connected = frame && isConnected();
  if (!is_connected && !was_just_adopted_)
    return GuestContentsEligibility::kIneligible;

  const bool is_top_level = frame && frame->IsMainFrame();
  if (!is_top_level)
    return GuestContentsEligibility::kNotTopLevel;

  // TODO(crbug.com/1051639): We need to find a long term solution to when/how
  // portals should work in sandboxed documents.
  if (frame->DomWindow()->GetSandboxFlags() !=
      network::mojom::blink::WebSandboxFlags::kNone) {
    return GuestContentsEligibility::kSandboxed;
  }

  if (!GetDocument().Url().ProtocolIsInHTTPFamily())
    return GuestContentsEligibility::kNotHTTPFamily;

  return GuestContentsEligibility::kEligible;
}

void HTMLPortalElement::Navigate() {
  if (!CheckPortalsEnabledOrWarn())
    return;

  if (!CheckWithinFrameLimitOrWarn())
    return;

  auto url = GetNonEmptyURLAttribute(html_names::kSrcAttr);

  if (url.PotentiallyDanglingMarkup())
    return;

  if (portal_)
    portal_->Navigate(url, ReferrerPolicyAttribute());
}

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.sender_origin = execution_context->GetSecurityOrigin()->IsolatedCopy();

  // 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,
                                          ExceptionState& exception_state) {
  if (!CheckPortalsEnabledOrThrow(exception_state))
    return ScriptPromise();

  String pre_activate_error = PreActivateChecksCommon();
  if (pre_activate_error) {
    exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
                                      pre_activate_error);
    return ScriptPromise();
  }

  BlinkTransferableMessage data =
      ActivateDataAsMessage(script_state, options, exception_state);
  if (exception_state.HadException())
    return ScriptPromise();

  PortalContents* portal = std::exchange(portal_, nullptr);
  ScriptPromiseResolver* resolver =
      MakeGarbageCollected<ScriptPromiseResolver>(script_state);
  ScriptPromise promise = resolver->Promise();
  portal->Activate(std::move(data), PortalActivationDelegate::ForPromise(
                                        resolver, exception_state));
  return promise;
}

void HTMLPortalElement::postMessage(ScriptState* script_state,
                                    const ScriptValue& message,
                                    const PostMessageOptions* options,
                                    ExceptionState& exception_state) {
  if (!CheckPortalsEnabledOrThrow(exception_state) || !GetExecutionContext())
    return;

  if (!portal_) {
    exception_state.ThrowDOMException(
        DOMExceptionCode::kInvalidStateError,
        "The HTMLPortalElement is not associated with a portal context");
    return;
  }

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

  portal_->PostMessageToGuest(std::move(transferable_message));
}

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);
}

const PortalToken& HTMLPortalElement::GetToken() const {
  DCHECK(portal_ && portal_->IsValid());
  return portal_->GetToken().value();
}

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

  if (!CheckPortalsEnabledOrWarn())
    return result;

  if (!CheckWithinFrameLimitOrWarn())
    return result;

  if (!SubframeLoadingDisabler::CanLoadFrame(*this))
    return result;

  switch (GetGuestContentsEligibility()) {
    case GuestContentsEligibility::kIneligible:
      return result;

    case GuestContentsEligibility::kNotTopLevel:
      GetDocument().AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
          mojom::ConsoleMessageSource::kRendering,
          mojom::ConsoleMessageLevel::kWarning,
          "Cannot use <portal> in a nested browsing context."));
      return result;

    case GuestContentsEligibility::kSandboxed:
      GetDocument().AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
          mojom::ConsoleMessageSource::kRendering,
          mojom::ConsoleMessageLevel::kWarning,
          "Cannot use <portal> in a sandboxed browsing context."));
      return result;

    case GuestContentsEligibility::kNotHTTPFamily:
      GetDocument().AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
          mojom::ConsoleMessageSource::kRendering,
          mojom::ConsoleMessageLevel::kWarning,
          "<portal> use is restricted to the HTTP family."));
      return result;

    case GuestContentsEligibility::kEligible:
      break;
  };

  // When adopting a predecessor, it is possible to insert a portal that's
  // eligible to have a guest contents to a node that's not connected. In this
  // case, do not create the portal frame yet.
  if (!node.isConnected()) {
    return result;
  }

  if (portal_) {
    // The interface is already bound if the HTMLPortalElement is adopting the
    // predecessor.
    GetDocument().GetFrame()->Client()->AdoptPortal(this);
  } else {
    mojo::PendingAssociatedRemote<mojom::blink::Portal> portal;
    mojo::PendingAssociatedReceiver<mojom::blink::Portal> portal_receiver =
        portal.InitWithNewEndpointAndPassReceiver();

    mojo::PendingAssociatedRemote<mojom::blink::PortalClient> client;
    mojo::PendingAssociatedReceiver<mojom::blink::PortalClient>
        client_receiver = client.InitWithNewEndpointAndPassReceiver();

    RemoteFrame* portal_frame;
    PortalToken portal_token;
    std::tie(portal_frame, portal_token) =
        GetDocument().GetFrame()->Client()->CreatePortal(
            this, std::move(portal_receiver), std::move(client));
    DCHECK(portal_frame);

    portal_ = MakeGarbageCollected<PortalContents>(
        *this, portal_token, std::move(portal), std::move(client_receiver));

    Navigate();
  }
  probe::PortalRemoteFrameCreated(&GetDocument(), this);
  return result;
}

void HTMLPortalElement::RemovedFrom(ContainerNode& node) {
  DCHECK(!portal_) << "This element should have previously dissociated in "
                      "DisconnectContentFrame";
  HTMLFrameOwnerElement::RemovedFrom(node);
}

void HTMLPortalElement::DefaultEventHandler(Event& event) {
  // Clicking (or equivalent operations via keyboard and other input modalities)
  // a portal element causes it to activate unless prevented.
  if (event.type() == event_type_names::kDOMActivate) {
    ActivateDefault();
    event.SetDefaultHandled();
  }

  if (HandleKeyboardActivation(event))
    return;
  HTMLFrameOwnerElement::DefaultEventHandler(event);
}

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;
  }

  if (params.name == html_names::kReferrerpolicyAttr) {
    referrer_policy_ = network::mojom::ReferrerPolicy::kDefault;
    if (!params.new_value.IsNull()) {
      SecurityPolicy::ReferrerPolicyFromString(
          params.new_value, kDoNotSupportReferrerPolicyLegacyKeywords,
          &referrer_policy_);
    }
    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,
          JSEventHandlerForContentAttribute::Create(
              GetExecutionContext(), attribute.name, params.new_value));
      return;
    }
  }
}

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

bool HTMLPortalElement::SupportsFocus() const {
  return true;
}

void HTMLPortalElement::DisconnectContentFrame() {
  HTMLFrameOwnerElement::DisconnectContentFrame();
  ConsumePortal();
}

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

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

network::mojom::ReferrerPolicy HTMLPortalElement::ReferrerPolicyAttribute() {
  return referrer_policy_;
}

}  // namespace blink
