// Copyright (c) 2012 The Chromium Embedded Framework Authors.
// Portions copyright (c) 2011 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 "libcef/renderer/browser_impl.h"

#include <string>
#include <vector>

#include "libcef/common/cef_messages.h"
#include "libcef/common/content_client.h"
#include "libcef/renderer/blink_glue.h"
#include "libcef/renderer/content_renderer_client.h"
#include "libcef/renderer/render_frame_util.h"
#include "libcef/renderer/thread_util.h"

#include "base/strings/string16.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "content/public/renderer/document_state.h"
#include "content/public/renderer/render_frame.h"
#include "content/public/renderer/render_view.h"
#include "content/renderer/navigation_state.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/platform/web_url_error.h"
#include "third_party/blink/public/platform/web_url_response.h"
#include "third_party/blink/public/web/web_document.h"
#include "third_party/blink/public/web/web_frame.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_security_policy.h"
#include "third_party/blink/public/web/web_view.h"

// CefBrowserImpl static methods.
// -----------------------------------------------------------------------------

// static
CefRefPtr<CefBrowserImpl> CefBrowserImpl::GetBrowserForView(
    content::RenderView* view) {
  return CefContentRendererClient::Get()->GetBrowserForView(view);
}

// static
CefRefPtr<CefBrowserImpl> CefBrowserImpl::GetBrowserForMainFrame(
    blink::WebFrame* frame) {
  return CefContentRendererClient::Get()->GetBrowserForMainFrame(frame);
}

// CefBrowser methods.
// -----------------------------------------------------------------------------

CefRefPtr<CefBrowserHost> CefBrowserImpl::GetHost() {
  NOTREACHED() << "GetHost cannot be called from the render process";
  return nullptr;
}

bool CefBrowserImpl::CanGoBack() {
  CEF_REQUIRE_RT_RETURN(false);

  return blink_glue::CanGoBack(render_view()->GetWebView());
}

void CefBrowserImpl::GoBack() {
  CEF_REQUIRE_RT_RETURN_VOID();

  blink_glue::GoBack(render_view()->GetWebView());
}

bool CefBrowserImpl::CanGoForward() {
  CEF_REQUIRE_RT_RETURN(false);

  return blink_glue::CanGoForward(render_view()->GetWebView());
}

void CefBrowserImpl::GoForward() {
  CEF_REQUIRE_RT_RETURN_VOID();

  blink_glue::GoForward(render_view()->GetWebView());
}

bool CefBrowserImpl::IsLoading() {
  CEF_REQUIRE_RT_RETURN(false);

  if (render_view()->GetWebView()) {
    blink::WebFrame* main_frame = render_view()->GetWebView()->MainFrame();
    if (main_frame)
      return main_frame->ToWebLocalFrame()->IsLoading();
  }
  return false;
}

void CefBrowserImpl::Reload() {
  CEF_REQUIRE_RT_RETURN_VOID();

  if (render_view()->GetWebView()) {
    blink::WebFrame* main_frame = render_view()->GetWebView()->MainFrame();
    if (main_frame && main_frame->IsWebLocalFrame()) {
      main_frame->ToWebLocalFrame()->StartReload(
          blink::WebFrameLoadType::kReload);
    }
  }
}

void CefBrowserImpl::ReloadIgnoreCache() {
  CEF_REQUIRE_RT_RETURN_VOID();

  if (render_view()->GetWebView()) {
    blink::WebFrame* main_frame = render_view()->GetWebView()->MainFrame();
    if (main_frame && main_frame->IsWebLocalFrame()) {
      main_frame->ToWebLocalFrame()->StartReload(
          blink::WebFrameLoadType::kReloadBypassingCache);
    }
  }
}

void CefBrowserImpl::StopLoad() {
  CEF_REQUIRE_RT_RETURN_VOID();

  if (render_view()->GetWebView()) {
    blink::WebFrame* main_frame = render_view()->GetWebView()->MainFrame();
    if (main_frame && main_frame->IsWebLocalFrame()) {
      main_frame->ToWebLocalFrame()->StopLoading();
    }
  }
}

int CefBrowserImpl::GetIdentifier() {
  CEF_REQUIRE_RT_RETURN(0);

  return browser_id();
}

bool CefBrowserImpl::IsSame(CefRefPtr<CefBrowser> that) {
  CEF_REQUIRE_RT_RETURN(false);

  CefBrowserImpl* impl = static_cast<CefBrowserImpl*>(that.get());
  return (impl == this);
}

bool CefBrowserImpl::IsPopup() {
  CEF_REQUIRE_RT_RETURN(false);

  return is_popup();
}

bool CefBrowserImpl::HasDocument() {
  CEF_REQUIRE_RT_RETURN(false);

  if (render_view()->GetWebView()) {
    blink::WebFrame* main_frame = render_view()->GetWebView()->MainFrame();
    if (main_frame && main_frame->IsWebLocalFrame()) {
      return !main_frame->ToWebLocalFrame()->GetDocument().IsNull();
    }
  }
  return false;
}

CefRefPtr<CefFrame> CefBrowserImpl::GetMainFrame() {
  CEF_REQUIRE_RT_RETURN(nullptr);

  if (render_view()->GetWebView()) {
    blink::WebFrame* main_frame = render_view()->GetWebView()->MainFrame();
    if (main_frame && main_frame->IsWebLocalFrame()) {
      return GetWebFrameImpl(main_frame->ToWebLocalFrame()).get();
    }
  }
  return nullptr;
}

CefRefPtr<CefFrame> CefBrowserImpl::GetFocusedFrame() {
  CEF_REQUIRE_RT_RETURN(nullptr);

  if (render_view()->GetWebView() &&
      render_view()->GetWebView()->FocusedFrame()) {
    return GetWebFrameImpl(render_view()->GetWebView()->FocusedFrame()).get();
  }
  return nullptr;
}

CefRefPtr<CefFrame> CefBrowserImpl::GetFrame(int64 identifier) {
  CEF_REQUIRE_RT_RETURN(nullptr);

  return GetWebFrameImpl(identifier).get();
}

CefRefPtr<CefFrame> CefBrowserImpl::GetFrame(const CefString& name) {
  CEF_REQUIRE_RT_RETURN(nullptr);

  blink::WebView* web_view = render_view()->GetWebView();
  if (web_view) {
    const blink::WebString& frame_name =
        blink::WebString::FromUTF16(name.ToString16());
    // Search by assigned frame name (Frame::name).
    blink::WebFrame* frame = web_view->MainFrame();
    if (frame && frame->IsWebLocalFrame())
      frame = frame->ToWebLocalFrame()->FindFrameByName(frame_name);
    if (!frame) {
      // Search by unique frame name (Frame::uniqueName).
      const std::string& searchname = name;
      for (blink::WebFrame* cur_frame = web_view->MainFrame(); cur_frame;
           cur_frame = cur_frame->TraverseNext()) {
        if (cur_frame->IsWebLocalFrame() &&
            render_frame_util::GetName(cur_frame->ToWebLocalFrame()) ==
                searchname) {
          frame = cur_frame;
          break;
        }
      }
    }
    if (frame && frame->IsWebLocalFrame())
      return GetWebFrameImpl(frame->ToWebLocalFrame()).get();
  }

  return nullptr;
}

size_t CefBrowserImpl::GetFrameCount() {
  CEF_REQUIRE_RT_RETURN(0);

  int count = 0;

  if (render_view()->GetWebView()) {
    for (blink::WebFrame* frame = render_view()->GetWebView()->MainFrame();
         frame; frame = frame->TraverseNext()) {
      count++;
    }
  }

  return count;
}

void CefBrowserImpl::GetFrameIdentifiers(std::vector<int64>& identifiers) {
  CEF_REQUIRE_RT_RETURN_VOID();

  if (identifiers.size() > 0)
    identifiers.clear();

  if (render_view()->GetWebView()) {
    for (blink::WebFrame* frame = render_view()->GetWebView()->MainFrame();
         frame; frame = frame->TraverseNext()) {
      if (frame->IsWebLocalFrame())
        identifiers.push_back(
            render_frame_util::GetIdentifier(frame->ToWebLocalFrame()));
    }
  }
}

void CefBrowserImpl::GetFrameNames(std::vector<CefString>& names) {
  CEF_REQUIRE_RT_RETURN_VOID();

  if (names.size() > 0)
    names.clear();

  if (render_view()->GetWebView()) {
    for (blink::WebFrame* frame = render_view()->GetWebView()->MainFrame();
         frame; frame = frame->TraverseNext()) {
      if (frame->IsWebLocalFrame())
        names.push_back(render_frame_util::GetName(frame->ToWebLocalFrame()));
    }
  }
}

// CefBrowserImpl public methods.
// -----------------------------------------------------------------------------

CefBrowserImpl::CefBrowserImpl(content::RenderView* render_view,
                               int browser_id,
                               bool is_popup,
                               bool is_windowless)
    : content::RenderViewObserver(render_view),
      browser_id_(browser_id),
      is_popup_(is_popup),
      is_windowless_(is_windowless) {}

CefBrowserImpl::~CefBrowserImpl() {}

CefRefPtr<CefFrameImpl> CefBrowserImpl::GetWebFrameImpl(
    blink::WebLocalFrame* frame) {
  DCHECK(frame);
  int64_t frame_id = render_frame_util::GetIdentifier(frame);

  // Frames are re-used between page loads. Only add the frame to the map once.
  FrameMap::const_iterator it = frames_.find(frame_id);
  if (it != frames_.end())
    return it->second;

  CefRefPtr<CefFrameImpl> framePtr(new CefFrameImpl(this, frame, frame_id));
  frames_.insert(std::make_pair(frame_id, framePtr));

  return framePtr;
}

CefRefPtr<CefFrameImpl> CefBrowserImpl::GetWebFrameImpl(int64_t frame_id) {
  if (frame_id == blink_glue::kInvalidFrameId) {
    if (render_view()->GetWebView()) {
      blink::WebFrame* main_frame = render_view()->GetWebView()->MainFrame();
      if (main_frame && main_frame->IsWebLocalFrame()) {
        return GetWebFrameImpl(main_frame->ToWebLocalFrame());
      }
    }
    return nullptr;
  }

  // Check if we already know about the frame.
  FrameMap::const_iterator it = frames_.find(frame_id);
  if (it != frames_.end())
    return it->second;

  if (render_view()->GetWebView()) {
    // Check if the frame exists but we don't know about it yet.
    for (blink::WebFrame* frame = render_view()->GetWebView()->MainFrame();
         frame; frame = frame->TraverseNext()) {
      if (frame->IsWebLocalFrame() &&
          render_frame_util::GetIdentifier(frame->ToWebLocalFrame()) ==
              frame_id) {
        return GetWebFrameImpl(frame->ToWebLocalFrame());
      }
    }
  }

  return nullptr;
}

void CefBrowserImpl::AddFrameObject(int64_t frame_id,
                                    CefTrackNode* tracked_object) {
  CefRefPtr<CefTrackManager> manager;

  if (!frame_objects_.empty()) {
    FrameObjectMap::const_iterator it = frame_objects_.find(frame_id);
    if (it != frame_objects_.end())
      manager = it->second;
  }

  if (!manager.get()) {
    manager = new CefTrackManager();
    frame_objects_.insert(std::make_pair(frame_id, manager));
  }

  manager->Add(tracked_object);
}

// RenderViewObserver methods.
// -----------------------------------------------------------------------------

void CefBrowserImpl::OnDestruct() {
  // Notify that the browser window has been destroyed.
  CefRefPtr<CefApp> app = CefContentClient::Get()->application();
  if (app.get()) {
    CefRefPtr<CefRenderProcessHandler> handler = app->GetRenderProcessHandler();
    if (handler.get())
      handler->OnBrowserDestroyed(this);
  }

  CefContentRendererClient::Get()->OnBrowserDestroyed(this);
}

void CefBrowserImpl::FrameDetached(int64_t frame_id) {
  if (!frames_.empty()) {
    // Remove the frame from the map.
    FrameMap::iterator it = frames_.find(frame_id);
    if (it != frames_.end()) {
      frames_.erase(it);
    }
  }

  if (!frame_objects_.empty()) {
    // Remove any tracked objects associated with the frame.
    FrameObjectMap::iterator it = frame_objects_.find(frame_id);
    if (it != frame_objects_.end())
      frame_objects_.erase(it);
  }
}

void CefBrowserImpl::OnLoadingStateChange(bool isLoading) {
  CefRefPtr<CefApp> app = CefContentClient::Get()->application();
  if (app.get()) {
    CefRefPtr<CefRenderProcessHandler> handler = app->GetRenderProcessHandler();
    if (handler.get()) {
      CefRefPtr<CefLoadHandler> load_handler = handler->GetLoadHandler();
      if (load_handler.get()) {
        blink::WebView* web_view = render_view()->GetWebView();
        const bool canGoBack = blink_glue::CanGoBack(web_view);
        const bool canGoForward = blink_glue::CanGoForward(web_view);

        // Don't call OnLoadingStateChange multiple times with the same status.
        // This can occur in cases where there are multiple highest-level
        // LocalFrames in-process for the same browser.
        if (last_loading_state_ &&
            last_loading_state_->IsMatch(isLoading, canGoBack, canGoForward)) {
          return;
        }

        load_handler->OnLoadingStateChange(this, isLoading, canGoBack,
                                           canGoForward);
        last_loading_state_.reset(
            new LoadingState(isLoading, canGoBack, canGoForward));
      }
    }
  }
}
