// 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 "public/web/WebFrame.h"

#include <algorithm>
#include "bindings/core/v8/WindowProxyManager.h"
#include "core/dom/IncrementLoadEventDelayCount.h"
#include "core/dom/UserGestureIndicator.h"
#include "core/exported/WebRemoteFrameImpl.h"
#include "core/frame/LocalFrame.h"
#include "core/frame/LocalFrameView.h"
#include "core/frame/OpenedFrameTracker.h"
#include "core/frame/RemoteFrame.h"
#include "core/frame/RemoteFrameOwner.h"
#include "core/frame/WebLocalFrameImpl.h"
#include "core/html/HTMLFrameElementBase.h"
#include "core/html/HTMLFrameOwnerElement.h"
#include "core/html_names.h"
#include "core/page/Page.h"
#include "core/probe/CoreProbes.h"
#include "platform/heap/Handle.h"
#include "platform/instrumentation/tracing/TraceEvent.h"
#include "public/web/WebElement.h"
#include "public/web/WebFrameOwnerProperties.h"
#include "third_party/WebKit/common/sandbox_flags.h"

namespace blink {

bool WebFrame::Swap(WebFrame* frame) {
  using std::swap;
  Frame* old_frame = ToCoreFrame(*this);
  if (!old_frame->IsAttached())
    return false;

  // Unload the current Document in this frame: this calls unload handlers,
  // detaches child frames, etc. Since this runs script, make sure this frame
  // wasn't detached before continuing with the swap.
  // FIXME: There is no unit test for this condition, so one needs to be
  // written.
  if (!old_frame->PrepareForCommit())
    return false;

  // If there is a local parent, it might incorrectly declare itself complete
  // during the detach phase of this swap. Suppress its completion until swap is
  // over, at which point its completion will be correctly dependent on its
  // newly swapped-in child.
  std::unique_ptr<IncrementLoadEventDelayCount> delay_parent_load =
      parent_ && parent_->IsWebLocalFrame()
          ? IncrementLoadEventDelayCount::Create(
                *ToWebLocalFrameImpl(parent_)->GetFrame()->GetDocument())
          : nullptr;

  if (parent_) {
    if (parent_->first_child_ == this)
      parent_->first_child_ = frame;
    if (parent_->last_child_ == this)
      parent_->last_child_ = frame;
    // FIXME: This is due to the fact that the |frame| may be a provisional
    // local frame, because we don't know if the navigation will result in
    // an actual page or something else, like a download. The PlzNavigate
    // project will remove the need for provisional local frames.
    frame->parent_ = parent_;
  }

  if (previous_sibling_) {
    previous_sibling_->next_sibling_ = frame;
    swap(previous_sibling_, frame->previous_sibling_);
  }
  if (next_sibling_) {
    next_sibling_->previous_sibling_ = frame;
    swap(next_sibling_, frame->next_sibling_);
  }

  if (opener_) {
    frame->SetOpener(opener_);
    SetOpener(nullptr);
  }
  opened_frame_tracker_->TransferTo(frame);

  Page* page = old_frame->GetPage();
  AtomicString name = old_frame->Tree().GetName();
  FrameOwner* owner = old_frame->Owner();

  v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
  WindowProxyManager::GlobalProxyVector global_proxies;
  old_frame->GetWindowProxyManager()->ClearForSwap();
  old_frame->GetWindowProxyManager()->ReleaseGlobalProxies(global_proxies);

  // Although the Document in this frame is now unloaded, many resources
  // associated with the frame itself have not yet been freed yet.
  old_frame->Detach(FrameDetachType::kSwap);

  // Clone the state of the current Frame into the one being swapped in.
  // FIXME: This is a bit clunky; this results in pointless decrements and
  // increments of connected subframes.
  if (frame->IsWebLocalFrame()) {
    // TODO(dcheng): in an ideal world, both branches would just use
    // WebFrame's initializeCoreFrame() helper. However, Blink
    // currently requires a 'provisional' local frame to serve as a
    // placeholder for loading state when swapping to a local frame.
    // In this case, the core LocalFrame is already initialized, so just
    // update a bit of state.
    LocalFrame& local_frame = *ToWebLocalFrameImpl(frame)->GetFrame();
    DCHECK_EQ(owner, local_frame.Owner());
    if (owner) {
      owner->SetContentFrame(local_frame);

      if (owner->IsLocal()) {
        ToHTMLFrameOwnerElement(owner)->SetEmbeddedContentView(
            local_frame.View());
      }
    } else {
      local_frame.GetPage()->SetMainFrame(&local_frame);
      // This trace event is needed to detect the main frame of the
      // renderer in telemetry metrics. See crbug.com/692112#c11.
      TRACE_EVENT_INSTANT1("loading", "markAsMainFrame",
                           TRACE_EVENT_SCOPE_THREAD, "frame", &local_frame);
    }
    local_frame.SetIsProvisional(false);
  } else {
    ToWebRemoteFrameImpl(frame)->InitializeCoreFrame(*page, owner, name);
  }

  Frame* new_frame = ToCoreFrame(*frame);

  if (parent_ && old_frame->HasBeenActivated())
    new_frame->UpdateUserActivationInFrameTree();

  new_frame->GetWindowProxyManager()->SetGlobalProxies(global_proxies);

  parent_ = nullptr;

  if (owner && owner->IsLocal()) {
    if (new_frame && new_frame->IsLocalFrame()) {
      probe::frameOwnerContentUpdated(ToLocalFrame(new_frame),
                                      ToHTMLFrameOwnerElement(owner));
    } else if (old_frame && old_frame->IsLocalFrame()) {
      probe::frameOwnerContentUpdated(ToLocalFrame(old_frame),
                                      ToHTMLFrameOwnerElement(owner));
    }
  }

  return true;
}

void WebFrame::Detach() {
  ToCoreFrame(*this)->Detach(FrameDetachType::kRemove);
}

WebSecurityOrigin WebFrame::GetSecurityOrigin() const {
  return WebSecurityOrigin(
      ToCoreFrame(*this)->GetSecurityContext()->GetSecurityOrigin());
}

void WebFrame::SetFrameOwnerPolicy(
    WebSandboxFlags flags,
    const blink::ParsedFeaturePolicy& container_policy) {
  // At the moment, this is only used to replicate sandbox flags and container
  // policy for frames with a remote owner.
  RemoteFrameOwner* owner = ToRemoteFrameOwner(ToCoreFrame(*this)->Owner());
  DCHECK(owner);
  owner->SetSandboxFlags(static_cast<SandboxFlags>(flags));
  owner->SetContainerPolicy(container_policy);
}

WebInsecureRequestPolicy WebFrame::GetInsecureRequestPolicy() const {
  return ToCoreFrame(*this)->GetSecurityContext()->GetInsecureRequestPolicy();
}

std::vector<unsigned> WebFrame::GetInsecureRequestToUpgrade() const {
  SecurityContext::InsecureNavigationsSet* set =
      ToCoreFrame(*this)->GetSecurityContext()->InsecureNavigationsToUpgrade();
  return SecurityContext::SerializeInsecureNavigationSet(*set);
}

void WebFrame::SetFrameOwnerProperties(
    const WebFrameOwnerProperties& properties) {
  // At the moment, this is only used to replicate frame owner properties
  // for frames with a remote owner.
  RemoteFrameOwner* owner = ToRemoteFrameOwner(ToCoreFrame(*this)->Owner());
  DCHECK(owner);

  Frame* frame = ToCoreFrame(*this);
  DCHECK(frame);

  if (frame->IsLocalFrame()) {
    ToLocalFrame(frame)->GetDocument()->WillChangeFrameOwnerProperties(
        properties.margin_width, properties.margin_height,
        static_cast<ScrollbarMode>(properties.scrolling_mode),
        properties.is_display_none);
  }

  owner->SetBrowsingContextContainerName(properties.name);
  owner->SetScrollingMode(properties.scrolling_mode);
  owner->SetMarginWidth(properties.margin_width);
  owner->SetMarginHeight(properties.margin_height);
  owner->SetAllowFullscreen(properties.allow_fullscreen);
  owner->SetAllowPaymentRequest(properties.allow_payment_request);
  owner->SetIsDisplayNone(properties.is_display_none);
  owner->SetCsp(properties.required_csp);
}

void WebFrame::Collapse(bool collapsed) {
  FrameOwner* owner = ToCoreFrame(*this)->Owner();
  DCHECK(owner->IsLocal());
  ToHTMLFrameOwnerElement(owner)->SetCollapsed(collapsed);
}

WebFrame* WebFrame::Opener() const {
  return opener_;
}

void WebFrame::SetOpener(WebFrame* opener) {
  if (opener_)
    opener_->opened_frame_tracker_->Remove(this);
  if (opener)
    opener->opened_frame_tracker_->Add(this);
  opener_ = opener;
}

void WebFrame::ClearOpener() {
  SetOpener(nullptr);
}

void WebFrame::InsertAfter(WebFrame* new_child, WebFrame* previous_sibling) {
  new_child->parent_ = this;

  WebFrame* next;
  if (!previous_sibling) {
    // Insert at the beginning if no previous sibling is specified.
    next = first_child_;
    first_child_ = new_child;
  } else {
    DCHECK_EQ(previous_sibling->parent_, this);
    next = previous_sibling->next_sibling_;
    previous_sibling->next_sibling_ = new_child;
    new_child->previous_sibling_ = previous_sibling;
  }

  if (next) {
    new_child->next_sibling_ = next;
    next->previous_sibling_ = new_child;
  } else {
    last_child_ = new_child;
  }

  ToCoreFrame(*this)->Tree().InvalidateScopedChildCount();
  ToCoreFrame(*this)->GetPage()->IncrementSubframeCount();
}

void WebFrame::AppendChild(WebFrame* child) {
  // TODO(dcheng): Original code asserts that the frames have the same Page.
  // We should add an equivalent check... figure out what.
  InsertAfter(child, last_child_);
}

void WebFrame::RemoveChild(WebFrame* child) {
  child->parent_ = nullptr;

  if (first_child_ == child)
    first_child_ = child->next_sibling_;
  else
    child->previous_sibling_->next_sibling_ = child->next_sibling_;

  if (last_child_ == child)
    last_child_ = child->previous_sibling_;
  else
    child->next_sibling_->previous_sibling_ = child->previous_sibling_;

  child->previous_sibling_ = child->next_sibling_ = nullptr;

  ToCoreFrame(*this)->Tree().InvalidateScopedChildCount();
  ToCoreFrame(*this)->GetPage()->DecrementSubframeCount();
}

void WebFrame::SetParent(WebFrame* parent) {
  parent_ = parent;
}

WebFrame* WebFrame::Parent() const {
  return parent_;
}

WebFrame* WebFrame::Top() const {
  WebFrame* frame = const_cast<WebFrame*>(this);
  for (WebFrame* parent = frame; parent; parent = parent->parent_)
    frame = parent;
  return frame;
}

WebFrame* WebFrame::FirstChild() const {
  return first_child_;
}

WebFrame* WebFrame::NextSibling() const {
  return next_sibling_;
}

WebFrame* WebFrame::TraverseNext() const {
  if (Frame* frame = ToCoreFrame(*this))
    return FromFrame(frame->Tree().TraverseNext());
  return nullptr;
}

WebFrame* WebFrame::FromFrameOwnerElement(const WebNode& web_node) {
  Node* node = web_node;

  if (!node->IsFrameOwnerElement())
    return nullptr;
  return FromFrame(ToHTMLFrameOwnerElement(node)->ContentFrame());
}

bool WebFrame::IsLoading() const {
  if (Frame* frame = ToCoreFrame(*this))
    return frame->IsLoading();
  return false;
}

WebFrame* WebFrame::FromFrame(Frame* frame) {
  if (!frame)
    return nullptr;

  if (frame->IsLocalFrame())
    return WebLocalFrameImpl::FromFrame(ToLocalFrame(*frame));
  return WebRemoteFrameImpl::FromFrame(ToRemoteFrame(*frame));
}

WebFrame::WebFrame(WebTreeScopeType scope)
    : scope_(scope),
      parent_(nullptr),
      previous_sibling_(nullptr),
      next_sibling_(nullptr),
      first_child_(nullptr),
      last_child_(nullptr),
      opener_(nullptr),
      opened_frame_tracker_(new OpenedFrameTracker) {}

WebFrame::~WebFrame() {
  opened_frame_tracker_.reset(nullptr);
}

void WebFrame::TraceFrame(Visitor* visitor, WebFrame* frame) {
  if (!frame)
    return;

  if (frame->IsWebLocalFrame())
    visitor->Trace(ToWebLocalFrameImpl(frame));
  else
    visitor->Trace(ToWebRemoteFrameImpl(frame));
}

void WebFrame::TraceFrames(Visitor* visitor, WebFrame* frame) {
  DCHECK(frame);
  TraceFrame(visitor, frame->parent_);
  for (WebFrame* child = frame->FirstChild(); child;
       child = child->NextSibling())
    TraceFrame(visitor, child);
}

void WebFrame::Close() {
  opened_frame_tracker_->Dispose();
}

void WebFrame::DetachFromParent() {
  // TODO(dcheng): This should really just check if there's a parent, and call
  // RemoveChild() if so. Once provisional frames are removed, this check can be
  // simplified to just check Parent(). See https://crbug.com/578349.
  const blink::Frame* frame = ToCoreFrame(*this);
  if (frame->Owner() && frame->Owner()->ContentFrame() == frame)
    Parent()->RemoveChild(this);
}

Frame* WebFrame::ToCoreFrame(const WebFrame& frame) {
  if (frame.IsWebLocalFrame())
    return ToWebLocalFrameImpl(frame).GetFrame();
  if (frame.IsWebRemoteFrame())
    return ToWebRemoteFrameImpl(frame).GetFrame();
  NOTREACHED();
  return nullptr;
}

}  // namespace blink
