// Copyright (c) 2012 The Chromium Embedded Framework 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 "libcef/browser/frame_host_impl.h"

#include "include/cef_request.h"
#include "include/cef_stream.h"
#include "include/cef_v8.h"
#include "include/test/cef_test_helpers.h"
#include "libcef/browser/browser_host_impl.h"
#include "libcef/browser/navigate_params.h"
#include "libcef/browser/net_service/browser_urlrequest_impl.h"
#include "libcef/common/cef_messages.h"
#include "libcef/common/frame_util.h"
#include "libcef/common/process_message_impl.h"
#include "libcef/common/request_impl.h"
#include "libcef/common/task_runner_impl.h"

#include "content/browser/frame_host/frame_tree_node.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"

namespace {

// Implementation of CommandResponseHandler for calling a CefStringVisitor.
class StringVisitHandler : public CefResponseManager::Handler {
 public:
  explicit StringVisitHandler(CefRefPtr<CefStringVisitor> visitor)
      : visitor_(visitor) {}
  void OnResponse(const Cef_Response_Params& params) override {
    visitor_->Visit(params.response);
  }

 private:
  CefRefPtr<CefStringVisitor> visitor_;

  IMPLEMENT_REFCOUNTING(StringVisitHandler);
};

// Implementation of CommandResponseHandler for calling ViewText().
class ViewTextHandler : public CefResponseManager::Handler {
 public:
  explicit ViewTextHandler(CefRefPtr<CefFrameHostImpl> frame) : frame_(frame) {}
  void OnResponse(const Cef_Response_Params& params) override {
    CefRefPtr<CefBrowser> browser = frame_->GetBrowser();
    if (browser.get()) {
      static_cast<CefBrowserHostImpl*>(browser.get())
          ->ViewText(params.response);
    }
  }

 private:
  CefRefPtr<CefFrameHostImpl> frame_;

  IMPLEMENT_REFCOUNTING(ViewTextHandler);
};

}  // namespace

CefFrameHostImpl::CefFrameHostImpl(scoped_refptr<CefBrowserInfo> browser_info,
                                   bool is_main_frame,
                                   int64_t parent_frame_id)
    : is_main_frame_(is_main_frame),
      frame_id_(kInvalidFrameId),
      browser_info_(browser_info),
      is_focused_(is_main_frame_),  // The main frame always starts focused.
      parent_frame_id_(parent_frame_id) {
#if DCHECK_IS_ON()
  DCHECK(browser_info_);
  if (is_main_frame_) {
    DCHECK_EQ(parent_frame_id_, kInvalidFrameId);
  } else {
    DCHECK_GT(parent_frame_id_, 0);
  }
#endif
}

CefFrameHostImpl::CefFrameHostImpl(scoped_refptr<CefBrowserInfo> browser_info,
                                   content::RenderFrameHost* render_frame_host)
    : is_main_frame_(render_frame_host->GetParent() == nullptr),
      frame_id_(MakeFrameId(render_frame_host)),
      browser_info_(browser_info),
      is_focused_(is_main_frame_),  // The main frame always starts focused.
      url_(render_frame_host->GetLastCommittedURL().spec()),
      name_(render_frame_host->GetFrameName()),
      parent_frame_id_(is_main_frame_
                           ? kInvalidFrameId
                           : MakeFrameId(render_frame_host->GetParent())),
      render_frame_host_(render_frame_host),
      response_manager_(new CefResponseManager) {
  DCHECK(browser_info_);
}

CefFrameHostImpl::~CefFrameHostImpl() {}

void CefFrameHostImpl::SetRenderFrameHost(content::RenderFrameHost* host) {
  CEF_REQUIRE_UIT();

  base::AutoLock lock_scope(state_lock_);

  // We should not be detached.
  CHECK(browser_info_);
  // We should be the main frame.
  CHECK(is_main_frame_);

  render_frame_host_ = host;
  frame_id_ = MakeFrameId(host);
  url_ = host->GetLastCommittedURL().spec();
  name_ = host->GetFrameName();

  // Cancel any existing messages.
  response_manager_.reset(new CefResponseManager);
}

bool CefFrameHostImpl::IsValid() {
  return !!GetBrowserHostImpl();
}

void CefFrameHostImpl::Undo() {
  SendCommand("Undo", nullptr);
}

void CefFrameHostImpl::Redo() {
  SendCommand("Redo", nullptr);
}

void CefFrameHostImpl::Cut() {
  SendCommand("Cut", nullptr);
}

void CefFrameHostImpl::Copy() {
  SendCommand("Copy", nullptr);
}

void CefFrameHostImpl::Paste() {
  SendCommand("Paste", nullptr);
}

void CefFrameHostImpl::Delete() {
  SendCommand("Delete", nullptr);
}

void CefFrameHostImpl::SelectAll() {
  SendCommand("SelectAll", nullptr);
}

void CefFrameHostImpl::ViewSource() {
  SendCommand("GetSource", new ViewTextHandler(this));
}

void CefFrameHostImpl::GetSource(CefRefPtr<CefStringVisitor> visitor) {
  SendCommand("GetSource", new StringVisitHandler(visitor));
}

void CefFrameHostImpl::GetText(CefRefPtr<CefStringVisitor> visitor) {
  SendCommand("GetText", new StringVisitHandler(visitor));
}

void CefFrameHostImpl::LoadRequest(CefRefPtr<CefRequest> request) {
  CefNavigateParams params(GURL(), kPageTransitionExplicit);
  static_cast<CefRequestImpl*>(request.get())->Get(params);
  Navigate(params);
}

void CefFrameHostImpl::LoadURL(const CefString& url) {
  LoadURLWithExtras(url, content::Referrer(), kPageTransitionExplicit,
                    std::string());
}

void CefFrameHostImpl::ExecuteJavaScript(const CefString& jsCode,
                                         const CefString& scriptUrl,
                                         int startLine) {
  SendJavaScript(jsCode, scriptUrl, startLine);
}

bool CefFrameHostImpl::IsMain() {
  return is_main_frame_;
}

bool CefFrameHostImpl::IsFocused() {
  base::AutoLock lock_scope(state_lock_);
  return is_focused_;
}

CefString CefFrameHostImpl::GetName() {
  base::AutoLock lock_scope(state_lock_);
  return name_;
}

int64 CefFrameHostImpl::GetIdentifier() {
  base::AutoLock lock_scope(state_lock_);
  return frame_id_;
}

CefRefPtr<CefFrame> CefFrameHostImpl::GetParent() {
  int64 parent_frame_id;

  {
    base::AutoLock lock_scope(state_lock_);
    if (is_main_frame_ || parent_frame_id_ == kInvalidFrameId)
      return nullptr;
    parent_frame_id = parent_frame_id_;
  }

  auto browser = GetBrowserHostImpl();
  if (browser)
    return browser->GetFrame(parent_frame_id);

  return nullptr;
}

CefString CefFrameHostImpl::GetURL() {
  base::AutoLock lock_scope(state_lock_);
  return url_;
}

CefRefPtr<CefBrowser> CefFrameHostImpl::GetBrowser() {
  return GetBrowserHostImpl().get();
}

CefRefPtr<CefV8Context> CefFrameHostImpl::GetV8Context() {
  NOTREACHED() << "GetV8Context cannot be called from the browser process";
  return nullptr;
}

void CefFrameHostImpl::VisitDOM(CefRefPtr<CefDOMVisitor> visitor) {
  NOTREACHED() << "VisitDOM cannot be called from the browser process";
}

CefRefPtr<CefURLRequest> CefFrameHostImpl::CreateURLRequest(
    CefRefPtr<CefRequest> request,
    CefRefPtr<CefURLRequestClient> client) {
  if (!request || !client)
    return nullptr;

  if (!CefTaskRunnerImpl::GetCurrentTaskRunner()) {
    NOTREACHED() << "called on invalid thread";
    return nullptr;
  }

  auto browser = GetBrowserHostImpl();
  if (!browser)
    return nullptr;

  auto request_context = browser->request_context();

  CefRefPtr<CefBrowserURLRequest> impl =
      new CefBrowserURLRequest(this, request, client, request_context);
  if (impl->Start())
    return impl.get();
  return nullptr;
}

void CefFrameHostImpl::SendProcessMessage(
    CefProcessId target_process,
    CefRefPtr<CefProcessMessage> message) {
  DCHECK_EQ(PID_RENDERER, target_process);
  DCHECK(message.get());

  Cef_Request_Params params;
  CefProcessMessageImpl* impl =
      static_cast<CefProcessMessageImpl*>(message.get());
  if (!impl->CopyTo(params))
    return;

  DCHECK(!params.name.empty());

  params.user_initiated = true;
  params.request_id = -1;
  params.expect_response = false;

  Send(new CefMsg_Request(MSG_ROUTING_NONE, params));
}

void CefFrameHostImpl::SetFocused(bool focused) {
  base::AutoLock lock_scope(state_lock_);
  is_focused_ = focused;
}

void CefFrameHostImpl::RefreshAttributes() {
  CEF_REQUIRE_UIT();

  base::AutoLock lock_scope(state_lock_);
  if (!render_frame_host_)
    return;
  url_ = render_frame_host_->GetLastCommittedURL().spec();

  // Use the assigned name if it is non-empty. This represents the name property
  // on the frame DOM element. If the assigned name is empty, revert to the
  // internal unique name. This matches the logic in render_frame_util::GetName.
  name_ = render_frame_host_->GetFrameName();
  if (name_.empty()) {
    const auto node = content::FrameTreeNode::GloballyFindByID(
        render_frame_host_->GetFrameTreeNodeId());
    if (node) {
      name_ = node->unique_name();
    }
  }

  if (!is_main_frame_)
    parent_frame_id_ = MakeFrameId(render_frame_host_->GetParent());
}

void CefFrameHostImpl::Navigate(const CefNavigateParams& params) {
  CefMsg_LoadRequest_Params request;
  request.url = params.url;
  if (!request.url.is_valid()) {
    LOG(ERROR) << "Invalid URL passed to CefFrameHostImpl::Navigate: "
               << params.url;
    return;
  }

  request.method = params.method;
  request.referrer = params.referrer.url;
  request.referrer_policy =
      CefRequestImpl::BlinkReferrerPolicyToNetReferrerPolicy(
          params.referrer.policy);
  request.site_for_cookies = params.site_for_cookies;
  request.headers = params.headers;
  request.load_flags = params.load_flags;
  request.upload_data = params.upload_data;

  Send(new CefMsg_LoadRequest(MSG_ROUTING_NONE, request));

  auto browser = GetBrowserHostImpl();
  if (browser)
    browser->OnSetFocus(FOCUS_SOURCE_NAVIGATION);
}

void CefFrameHostImpl::LoadURLWithExtras(const std::string& url,
                                         const content::Referrer& referrer,
                                         ui::PageTransition transition,
                                         const std::string& extra_headers) {
  // Only known frame ids or kMainFrameId are supported.
  const auto frame_id = GetFrameId();
  if (frame_id < CefFrameHostImpl::kMainFrameId)
    return;

  if (frame_id == CefFrameHostImpl::kMainFrameId) {
    // Load via the browser using NavigationController.
    auto browser = GetBrowserHostImpl();
    if (browser) {
      browser->LoadMainFrameURL(url, referrer, transition, extra_headers);
    }
  } else {
    CefNavigateParams params(GURL(url), transition);
    params.referrer = referrer;
    params.headers = extra_headers;
    Navigate(params);
  }
}

void CefFrameHostImpl::SendCommand(
    const std::string& command,
    CefRefPtr<CefResponseManager::Handler> responseHandler) {
  DCHECK(!command.empty());

  if (!CEF_CURRENTLY_ON_UIT()) {
    CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefFrameHostImpl::SendCommand, this,
                                          command, responseHandler));
    return;
  }

  // Only known frame ids or kMainFrameId are supported.
  const auto frame_id = GetFrameId();
  if (frame_id < CefFrameHostImpl::kMainFrameId)
    return;

  if (!render_frame_host_ || !response_manager_) {
    // detached frame has no response_manager_
    return;
  }

  TRACE_EVENT2("cef", "CefFrameHostImpl::SendCommand", "frame_id", frame_id,
               "needsResponse", responseHandler.get() ? 1 : 0);
  Cef_Request_Params params;
  params.name = "execute-command";
  params.user_initiated = false;

  if (responseHandler.get()) {
    params.request_id = response_manager_->RegisterHandler(responseHandler);
    params.expect_response = true;
  } else {
    params.request_id = -1;
    params.expect_response = false;
  }

  params.arguments.AppendString(command);

  Send(new CefMsg_Request(MSG_ROUTING_NONE, params));
}

void CefFrameHostImpl::SendCode(
    bool is_javascript,
    const std::string& code,
    const std::string& script_url,
    int script_start_line,
    CefRefPtr<CefResponseManager::Handler> responseHandler) {
  DCHECK(!code.empty());
  DCHECK_GE(script_start_line, 0);

  if (!CEF_CURRENTLY_ON_UIT()) {
    CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefFrameHostImpl::SendCode, this,
                                          is_javascript, code, script_url,
                                          script_start_line, responseHandler));
    return;
  }

  // Only known frame ids or kMainFrameId are supported.
  auto frame_id = GetFrameId();
  if (frame_id < CefFrameHostImpl::kMainFrameId)
    return;

  if (!render_frame_host_ || !response_manager_) {
    // detached frame has no response_manager_
    return;
  }

  TRACE_EVENT2("cef", "CefFrameHostImpl::SendCommand", "frame_id", frame_id,
               "needsResponse", responseHandler.get() ? 1 : 0);
  Cef_Request_Params params;
  params.name = "execute-code";
  params.user_initiated = false;

  if (responseHandler.get()) {
    params.request_id = response_manager_->RegisterHandler(responseHandler);
    params.expect_response = true;
  } else {
    params.request_id = -1;
    params.expect_response = false;
  }

  params.arguments.AppendBoolean(is_javascript);
  params.arguments.AppendString(code);
  params.arguments.AppendString(script_url);
  params.arguments.AppendInteger(script_start_line);

  Send(new CefMsg_Request(MSG_ROUTING_NONE, params));
}

void CefFrameHostImpl::SendJavaScript(const std::string& jsCode,
                                      const std::string& scriptUrl,
                                      int startLine) {
  if (jsCode.empty())
    return;
  if (startLine <= 0) {
    // A value of 0 is v8::Message::kNoLineNumberInfo in V8. There is code in
    // V8 that will assert on that value (e.g. V8StackTraceImpl::Frame::Frame
    // if a JS exception is thrown) so make sure |startLine| > 0.
    startLine = 1;
  }

  SendCode(true, jsCode, scriptUrl, startLine, nullptr);
}

void CefFrameHostImpl::MaybeSendDidStopLoading() {
  auto rfh = GetRenderFrameHost();
  if (!rfh)
    return;

  // We only want to notify for the highest-level LocalFrame in this frame's
  // renderer process subtree. If this frame has a parent in the same process
  // then the notification will be sent via the parent instead.
  auto rfh_parent = rfh->GetParent();
  if (rfh_parent && rfh_parent->GetProcess() == rfh->GetProcess()) {
    return;
  }

  Send(new CefMsg_DidStopLoading(MSG_ROUTING_NONE));
}

bool CefFrameHostImpl::OnMessageReceived(const IPC::Message& message) {
  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP(CefFrameHostImpl, message)
    IPC_MESSAGE_HANDLER(CefHostMsg_FrameAttached, OnAttached)
    IPC_MESSAGE_HANDLER(CefHostMsg_DidFinishLoad, OnDidFinishLoad)
    IPC_MESSAGE_HANDLER(CefHostMsg_UpdateDraggableRegions,
                        OnUpdateDraggableRegions)
    IPC_MESSAGE_HANDLER(CefHostMsg_Request, OnRequest)
    IPC_MESSAGE_HANDLER(CefHostMsg_Response, OnResponse)
    IPC_MESSAGE_HANDLER(CefHostMsg_ResponseAck, OnResponseAck)
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()
  return handled;
}

void CefFrameHostImpl::ExecuteJavaScriptWithUserGestureForTests(
    const CefString& javascript) {
  if (!CEF_CURRENTLY_ON_UIT()) {
    CEF_POST_TASK(
        CEF_UIT,
        base::BindOnce(
            &CefFrameHostImpl::ExecuteJavaScriptWithUserGestureForTests, this,
            javascript));
    return;
  }

  content::RenderFrameHost* rfh = GetRenderFrameHost();
  if (rfh)
    rfh->ExecuteJavaScriptWithUserGestureForTests(javascript);
}

content::RenderFrameHost* CefFrameHostImpl::GetRenderFrameHost() const {
  CEF_REQUIRE_UIT();
  return render_frame_host_;
}

void CefFrameHostImpl::Detach() {
  CEF_REQUIRE_UIT();

  {
    base::AutoLock lock_scope(state_lock_);
    browser_info_ = nullptr;
  }

  // In case we never attached, clean up.
  while (!queued_messages_.empty()) {
    queued_messages_.pop();
  }

  response_manager_.reset();
  render_frame_host_ = nullptr;
}

// static
int64_t CefFrameHostImpl::MakeFrameId(const content::RenderFrameHost* host) {
  CEF_REQUIRE_UIT();
  auto host_nonconst = const_cast<content::RenderFrameHost*>(host);
  return MakeFrameId(host_nonconst->GetProcess()->GetID(),
                     host_nonconst->GetRoutingID());
}

// static
int64_t CefFrameHostImpl::MakeFrameId(int32_t render_process_id,
                                      int32_t render_routing_id) {
  return frame_util::MakeFrameId(render_process_id, render_routing_id);
}

// kMainFrameId must be -1 to align with renderer expectations.
const int64_t CefFrameHostImpl::kMainFrameId = -1;
const int64_t CefFrameHostImpl::kFocusedFrameId = -2;
const int64_t CefFrameHostImpl::kUnspecifiedFrameId = -3;
const int64_t CefFrameHostImpl::kInvalidFrameId = -4;

// This equates to (TT_EXPLICIT | TT_DIRECT_LOAD_FLAG).
const ui::PageTransition CefFrameHostImpl::kPageTransitionExplicit =
    static_cast<ui::PageTransition>(ui::PAGE_TRANSITION_TYPED |
                                    ui::PAGE_TRANSITION_FROM_ADDRESS_BAR);

int64 CefFrameHostImpl::GetFrameId() const {
  base::AutoLock lock_scope(state_lock_);
  return is_main_frame_ ? kMainFrameId : frame_id_;
}

CefRefPtr<CefBrowserHostImpl> CefFrameHostImpl::GetBrowserHostImpl() const {
  base::AutoLock lock_scope(state_lock_);
  if (browser_info_)
    return browser_info_->browser();
  return nullptr;
}

void CefFrameHostImpl::OnAttached() {
  if (!is_attached_) {
    is_attached_ = true;
    while (!queued_messages_.empty()) {
      Send(queued_messages_.front().release());
      queued_messages_.pop();
    }
  }
}

void CefFrameHostImpl::OnDidFinishLoad(const GURL& validated_url,
                                       int http_status_code) {
  auto browser = GetBrowserHostImpl();
  if (browser)
    browser->OnDidFinishLoad(this, validated_url, http_status_code);
}

void CefFrameHostImpl::OnUpdateDraggableRegions(
    const std::vector<Cef_DraggableRegion_Params>& regions) {
  auto browser = GetBrowserHostImpl();
  if (!browser)
    return;

  CefRefPtr<CefDragHandler> handler;
  auto client = browser->GetClient();
  if (client)
    handler = client->GetDragHandler();
  if (!handler)
    return;

  std::vector<CefDraggableRegion> draggable_regions;
  draggable_regions.reserve(regions.size());

  std::vector<Cef_DraggableRegion_Params>::const_iterator it = regions.begin();
  for (; it != regions.end(); ++it) {
    const gfx::Rect& rect(it->bounds);
    const CefRect bounds(rect.x(), rect.y(), rect.width(), rect.height());
    draggable_regions.push_back(CefDraggableRegion(bounds, it->draggable));
  }

  handler->OnDraggableRegionsChanged(browser.get(), this, draggable_regions);
}

void CefFrameHostImpl::OnRequest(const Cef_Request_Params& params) {
  CEF_REQUIRE_UIT();

  bool success = false;
  std::string response;
  bool expect_response_ack = false;

  if (params.user_initiated) {
    auto browser = GetBrowserHostImpl();
    if (browser && browser->client()) {
      // Give the user a chance to handle the request.
      CefRefPtr<CefProcessMessageImpl> message(new CefProcessMessageImpl(
          const_cast<Cef_Request_Params*>(&params), false, true));
      success = browser->client()->OnProcessMessageReceived(
          browser.get(), this, PID_RENDERER, message.get());
      message->Detach(nullptr);
    }
  } else {
    // Invalid request.
    NOTREACHED();
  }

  if (params.expect_response) {
    DCHECK_GE(params.request_id, 0);

    // Send a response to the renderer.
    Cef_Response_Params response_params;
    response_params.request_id = params.request_id;
    response_params.success = success;
    response_params.response = response;
    response_params.expect_response_ack = expect_response_ack;
    Send(new CefMsg_Response(MSG_ROUTING_NONE, response_params));
  }
}

void CefFrameHostImpl::OnResponse(const Cef_Response_Params& params) {
  CEF_REQUIRE_UIT();

  response_manager_->RunHandler(params);
  if (params.expect_response_ack)
    Send(new CefMsg_ResponseAck(MSG_ROUTING_NONE, params.request_id));
}

void CefFrameHostImpl::OnResponseAck(int request_id) {
  response_manager_->RunAckHandler(request_id);
}

void CefFrameHostImpl::Send(IPC::Message* message) {
  if (!CEF_CURRENTLY_ON_UIT()) {
    CEF_POST_TASK(CEF_UIT,
                  base::BindOnce(base::IgnoreResult(&CefFrameHostImpl::Send),
                                 this, message));
    return;
  }

  if (!render_frame_host_) {
    // Either we're a placeholder frame without a renderer representation, or
    // we've been detached.
    delete message;
    return;
  }

  if (!is_attached_) {
    // Queue messages until we're notified by the renderer that it's ready to
    // handle them.
    queued_messages_.push(base::WrapUnique(message));
    return;
  }

  message->set_routing_id(render_frame_host_->GetRoutingID());
  render_frame_host_->Send(message);
}

void CefExecuteJavaScriptWithUserGestureForTests(CefRefPtr<CefFrame> frame,
                                                 const CefString& javascript) {
  CefFrameHostImpl* impl = static_cast<CefFrameHostImpl*>(frame.get());
  if (impl)
    impl->ExecuteJavaScriptWithUserGestureForTests(javascript);
}
