// 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/renderer/frame_impl.h"

#include "base/compiler_specific.h"

// Enable deprecation warnings on Windows. See http://crbug.com/585142.
#if defined(OS_WIN)
#if defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic error "-Wdeprecated-declarations"
#else
#pragma warning(push)
#pragma warning(default : 4996)
#endif
#endif

#include "libcef/common/cef_messages.h"
#include "libcef/common/content_client.h"
#include "libcef/common/net/http_header_utils.h"
#include "libcef/common/process_message_impl.h"
#include "libcef/common/request_impl.h"
#include "libcef/common/response_manager.h"
#include "libcef/renderer/blink_glue.h"
#include "libcef/renderer/browser_impl.h"
#include "libcef/renderer/dom_document_impl.h"
#include "libcef/renderer/render_frame_util.h"
#include "libcef/renderer/render_urlrequest_impl.h"
#include "libcef/renderer/thread_util.h"
#include "libcef/renderer/v8_impl.h"

#include "base/strings/utf_string_conversions.h"
#include "content/public/renderer/render_view.h"
#include "content/renderer/render_frame_impl.h"
#include "third_party/blink/public/platform/web_data.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/platform/web_url.h"
#include "third_party/blink/public/web/blink.h"
#include "third_party/blink/public/web/web_document.h"
#include "third_party/blink/public/web/web_document_loader.h"
#include "third_party/blink/public/web/web_frame_content_dumper.h"
#include "third_party/blink/public/web/web_local_frame.h"
#include "third_party/blink/public/web/web_navigation_control.h"
#include "third_party/blink/public/web/web_script_source.h"
#include "third_party/blink/public/web/web_view.h"

CefFrameImpl::CefFrameImpl(CefBrowserImpl* browser,
                           blink::WebLocalFrame* frame,
                           int64_t frame_id)
    : browser_(browser),
      frame_(frame),
      frame_id_(frame_id),
      response_manager_(new CefResponseManager) {}

CefFrameImpl::~CefFrameImpl() {}

bool CefFrameImpl::IsValid() {
  CEF_REQUIRE_RT_RETURN(false);

  return (frame_ != nullptr);
}

void CefFrameImpl::Undo() {
  ExecuteCommand("Undo");
}

void CefFrameImpl::Redo() {
  ExecuteCommand("Redo");
}

void CefFrameImpl::Cut() {
  ExecuteCommand("Cut");
}

void CefFrameImpl::Copy() {
  ExecuteCommand("Copy");
}

void CefFrameImpl::Paste() {
  ExecuteCommand("Paste");
}

void CefFrameImpl::Delete() {
  ExecuteCommand("Delete");
}

void CefFrameImpl::SelectAll() {
  ExecuteCommand("SelectAll");
}

void CefFrameImpl::ViewSource() {
  NOTREACHED() << "ViewSource cannot be called from the renderer process";
}

void CefFrameImpl::GetSource(CefRefPtr<CefStringVisitor> visitor) {
  CEF_REQUIRE_RT_RETURN_VOID();
  if (frame_) {
    const CefString& content =
        std::string(blink::WebFrameContentDumper::DumpAsMarkup(frame_).Utf8());
    visitor->Visit(content);
  }
}

void CefFrameImpl::GetText(CefRefPtr<CefStringVisitor> visitor) {
  CEF_REQUIRE_RT_RETURN_VOID();
  if (frame_) {
    const CefString& content = blink_glue::DumpDocumentText(frame_);
    visitor->Visit(content);
  }
}

void CefFrameImpl::LoadRequest(CefRefPtr<CefRequest> request) {
  CEF_REQUIRE_RT_RETURN_VOID();

  if (!frame_)
    return;

  CefMsg_LoadRequest_Params params;
  params.url = GURL(std::string(request->GetURL()));
  params.method = request->GetMethod();
  params.site_for_cookies = net::SiteForCookies::FromUrl(
      GURL(request->GetFirstPartyForCookies().ToString()));

  CefRequest::HeaderMap headerMap;
  request->GetHeaderMap(headerMap);
  if (!headerMap.empty())
    params.headers = HttpHeaderUtils::GenerateHeaders(headerMap);

  CefRefPtr<CefPostData> postData = request->GetPostData();
  if (postData.get()) {
    CefPostDataImpl* impl = static_cast<CefPostDataImpl*>(postData.get());
    params.upload_data = new net::UploadData();
    impl->Get(*params.upload_data.get());
  }

  params.load_flags = request->GetFlags();

  OnLoadRequest(params);
}

void CefFrameImpl::LoadURL(const CefString& url) {
  CEF_REQUIRE_RT_RETURN_VOID();

  if (!frame_)
    return;

  CefMsg_LoadRequest_Params params;
  params.url = GURL(url.ToString());
  params.method = "GET";

  OnLoadRequest(params);
}

void CefFrameImpl::ExecuteJavaScript(const CefString& jsCode,
                                     const CefString& scriptUrl,
                                     int startLine) {
  CEF_REQUIRE_RT_RETURN_VOID();

  if (jsCode.empty())
    return;
  if (startLine < 1)
    startLine = 1;

  if (frame_) {
    GURL gurl = GURL(scriptUrl.ToString());
    frame_->ExecuteScript(blink::WebScriptSource(
        blink::WebString::FromUTF16(jsCode.ToString16()), gurl, startLine));
  }
}

bool CefFrameImpl::IsMain() {
  CEF_REQUIRE_RT_RETURN(false);

  if (frame_)
    return (frame_->Parent() == nullptr);
  return false;
}

bool CefFrameImpl::IsFocused() {
  CEF_REQUIRE_RT_RETURN(false);

  if (frame_ && frame_->View())
    return (frame_->View()->FocusedFrame() == frame_);
  return false;
}

CefString CefFrameImpl::GetName() {
  CefString name;
  CEF_REQUIRE_RT_RETURN(name);

  if (frame_)
    name = render_frame_util::GetName(frame_);
  return name;
}

int64 CefFrameImpl::GetIdentifier() {
  CEF_REQUIRE_RT_RETURN(0);

  return frame_id_;
}

CefRefPtr<CefFrame> CefFrameImpl::GetParent() {
  CEF_REQUIRE_RT_RETURN(nullptr);

  if (frame_) {
    blink::WebFrame* parent = frame_->Parent();
    if (parent && parent->IsWebLocalFrame())
      return browser_->GetWebFrameImpl(parent->ToWebLocalFrame()).get();
  }

  return nullptr;
}

CefString CefFrameImpl::GetURL() {
  CefString url;
  CEF_REQUIRE_RT_RETURN(url);

  if (frame_) {
    GURL gurl = frame_->GetDocument().Url();
    url = gurl.spec();
  }
  return url;
}

CefRefPtr<CefBrowser> CefFrameImpl::GetBrowser() {
  CEF_REQUIRE_RT_RETURN(nullptr);

  return browser_;
}

CefRefPtr<CefV8Context> CefFrameImpl::GetV8Context() {
  CEF_REQUIRE_RT_RETURN(nullptr);

  if (frame_) {
    v8::Isolate* isolate = blink::MainThreadIsolate();
    v8::HandleScope handle_scope(isolate);
    return new CefV8ContextImpl(isolate, frame_->MainWorldScriptContext());
  } else {
    return nullptr;
  }
}

void CefFrameImpl::VisitDOM(CefRefPtr<CefDOMVisitor> visitor) {
  CEF_REQUIRE_RT_RETURN_VOID();

  if (!frame_)
    return;

  // Create a CefDOMDocumentImpl object that is valid only for the scope of this
  // method.
  CefRefPtr<CefDOMDocumentImpl> documentImpl;
  const blink::WebDocument& document = frame_->GetDocument();
  if (!document.IsNull())
    documentImpl = new CefDOMDocumentImpl(browser_, frame_);

  visitor->Visit(documentImpl.get());

  if (documentImpl.get())
    documentImpl->Detach();
}

CefRefPtr<CefURLRequest> CefFrameImpl::CreateURLRequest(
    CefRefPtr<CefRequest> request,
    CefRefPtr<CefURLRequestClient> client) {
  CEF_REQUIRE_RT_RETURN(nullptr);

  if (!request || !client || !frame_)
    return nullptr;

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

void CefFrameImpl::SendProcessMessage(CefProcessId target_process,
                                      CefRefPtr<CefProcessMessage> message) {
  Cef_Request_Params params;
  CefProcessMessageImpl* impl =
      static_cast<CefProcessMessageImpl*>(message.get());
  if (impl->CopyTo(params)) {
    SendProcessMessage(target_process, params.name, &params.arguments, true);
  }
}

blink::WebURLLoaderFactory* CefFrameImpl::GetURLLoaderFactory() {
  CEF_REQUIRE_RT();
  if (!url_loader_factory_ && frame_) {
    auto render_frame = content::RenderFrameImpl::FromWebFrame(frame_);
    if (render_frame) {
      url_loader_factory_ = render_frame->CreateURLLoaderFactory();
    }
  }
  return url_loader_factory_.get();
}

void CefFrameImpl::OnAttached() {
  Send(new CefHostMsg_FrameAttached(MSG_ROUTING_NONE));
}

bool CefFrameImpl::OnMessageReceived(const IPC::Message& message) {
  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP(CefFrameImpl, message)
    IPC_MESSAGE_HANDLER(CefMsg_Request, OnRequest)
    IPC_MESSAGE_HANDLER(CefMsg_Response, OnResponse)
    IPC_MESSAGE_HANDLER(CefMsg_ResponseAck, OnResponseAck)
    IPC_MESSAGE_HANDLER(CefMsg_LoadRequest, OnLoadRequest)
    IPC_MESSAGE_HANDLER(CefMsg_DidStopLoading, OnDidStopLoading)
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()
  return handled;
}

void CefFrameImpl::OnDidFinishLoad() {
  // Ignore notifications from the embedded frame hosting a mime-type plugin.
  // We'll eventually receive a notification from the owner frame.
  if (blink_glue::HasPluginFrameOwner(frame_))
    return;

  blink::WebDocumentLoader* dl = frame_->GetDocumentLoader();
  const int http_status_code = dl->GetResponse().HttpStatusCode();
  Send(new CefHostMsg_DidFinishLoad(MSG_ROUTING_NONE, dl->GetUrl(),
                                    http_status_code));

  CefRefPtr<CefApp> app = CefContentClient::Get()->application();
  if (app) {
    CefRefPtr<CefRenderProcessHandler> handler = app->GetRenderProcessHandler();
    if (handler) {
      CefRefPtr<CefLoadHandler> load_handler = handler->GetLoadHandler();
      if (load_handler) {
        load_handler->OnLoadEnd(browser_, this, http_status_code);
      }
    }
  }
}

void CefFrameImpl::OnDraggableRegionsChanged() {
  blink::WebVector<blink::WebDraggableRegion> webregions =
      frame_->GetDocument().DraggableRegions();
  std::vector<Cef_DraggableRegion_Params> regions;
  for (size_t i = 0; i < webregions.size(); ++i) {
    Cef_DraggableRegion_Params region;
    auto render_frame = content::RenderFrameImpl::FromWebFrame(frame_);
    render_frame->ConvertViewportToWindow(&webregions[i].bounds);
    region.bounds = webregions[i].bounds;
    region.draggable = webregions[i].draggable;
    regions.push_back(region);
  }
  Send(new CefHostMsg_UpdateDraggableRegions(MSG_ROUTING_NONE, regions));
}

void CefFrameImpl::OnDetached() {
  // The browser may hold the last reference to |this|. Take a reference here to
  // keep |this| alive until after this method returns.
  CefRefPtr<CefFrameImpl> self = this;

  browser_->FrameDetached(frame_id_);

  browser_ = nullptr;
  frame_ = nullptr;
  url_loader_factory_.reset();
  response_manager_.reset();
}

void CefFrameImpl::ExecuteCommand(const std::string& command) {
  CEF_REQUIRE_RT_RETURN_VOID();
  if (frame_)
    frame_->ExecuteCommand(blink::WebString::FromUTF8(command));
}

void CefFrameImpl::SendProcessMessage(CefProcessId target_process,
                                      const std::string& name,
                                      base::ListValue* arguments,
                                      bool user_initiated) {
  DCHECK_EQ(PID_BROWSER, target_process);
  DCHECK(!name.empty());

  if (!frame_)
    return;

  Cef_Request_Params params;
  params.name = name;
  if (arguments)
    params.arguments.Swap(arguments);
  params.user_initiated = user_initiated;
  params.request_id = -1;
  params.expect_response = false;

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

void CefFrameImpl::Send(IPC::Message* message) {
  if (!frame_) {
    delete message;
    return;
  }

  auto render_frame = content::RenderFrame::FromWebFrame(frame_);
  message->set_routing_id(render_frame->GetRoutingID());
  render_frame->Send(message);
}

void CefFrameImpl::OnRequest(const Cef_Request_Params& params) {
  DCHECK(browser_);
  DCHECK(frame_);

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

  TRACE_EVENT2("cef", "CefBrowserImpl::OnRequest", "request_id",
               params.request_id, "expect_response",
               params.expect_response ? 1 : 0);

  if (params.user_initiated) {
    // Give the user a chance to handle the request.
    CefRefPtr<CefApp> app = CefContentClient::Get()->application();
    if (app.get()) {
      CefRefPtr<CefRenderProcessHandler> handler =
          app->GetRenderProcessHandler();
      if (handler.get()) {
        CefRefPtr<CefProcessMessageImpl> message(new CefProcessMessageImpl(
            const_cast<Cef_Request_Params*>(&params), false, true));
        success = handler->OnProcessMessageReceived(browser_, this, PID_BROWSER,
                                                    message.get());
        message->Detach(nullptr);
      }
    }
  } else if (params.name == "execute-code") {
    // Execute code.
    DCHECK_EQ(params.arguments.GetSize(), (size_t)4);

    bool is_javascript = false;
    std::string code, script_url;
    int script_start_line = 0;

    params.arguments.GetBoolean(0, &is_javascript);
    params.arguments.GetString(1, &code);
    DCHECK(!code.empty());
    params.arguments.GetString(2, &script_url);
    params.arguments.GetInteger(3, &script_start_line);
    DCHECK_GE(script_start_line, 0);

    if (is_javascript) {
      frame_->ExecuteScript(
          blink::WebScriptSource(blink::WebString::FromUTF8(code),
                                 GURL(script_url), script_start_line));
      success = true;
    } else {
      // TODO(cef): implement support for CSS code.
      NOTIMPLEMENTED();
    }
  } else if (params.name == "execute-command") {
    // Execute command.
    DCHECK_EQ(params.arguments.GetSize(), (size_t)1);

    std::string command;

    params.arguments.GetString(0, &command);
    DCHECK(!command.empty());

    if (base::LowerCaseEqualsASCII(command, "getsource")) {
      response = blink::WebFrameContentDumper::DumpAsMarkup(frame_).Utf8();
      success = true;
    } else if (base::LowerCaseEqualsASCII(command, "gettext")) {
      response = blink_glue::DumpDocumentText(frame_);
      success = true;
    } else if (frame_->ExecuteCommand(blink::WebString::FromUTF8(command))) {
      success = true;
    }
  } else {
    // Invalid request.
    NOTREACHED();
  }

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

    // Send a response to the browser.
    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 CefHostMsg_Response(MSG_ROUTING_NONE, response_params));
  }
}

void CefFrameImpl::OnResponse(const Cef_Response_Params& params) {
  response_manager_->RunHandler(params);
  if (params.expect_response_ack)
    Send(new CefHostMsg_ResponseAck(MSG_ROUTING_NONE, params.request_id));
}

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

void CefFrameImpl::OnDidStopLoading() {
  // We should only receive this notification for the highest-level LocalFrame
  // in this frame's in-process subtree. If there are multiple of these for the
  // same browser then the other occurrences will be discarded in
  // OnLoadingStateChange.
  browser_->OnLoadingStateChange(false);
}

void CefFrameImpl::OnLoadRequest(const CefMsg_LoadRequest_Params& params) {
  DCHECK(frame_);

  blink::WebURLRequest request;
  CefRequestImpl::Get(params, request);

  frame_->StartNavigation(request);
}

// Enable deprecation warnings on Windows. See http://crbug.com/585142.
#if defined(OS_WIN)
#if defined(__clang__)
#pragma GCC diagnostic pop
#else
#pragma warning(pop)
#endif
#endif
