mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-01-20 21:44:06 +01:00
b3a8da9b25
This is the first pass in removing direct dependencies on the Alloy runtime from code that can potentially be shared between runtimes. CefBrowserHost and CefRequestContext APIs (including CefCookieManager, CefURLRequest, etc.) are not yet implemented for the Chrome runtime. Assert early if these API methods are called while the Chrome runtime is enabled.
402 lines
12 KiB
C++
402 lines
12 KiB
C++
// 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/app_manager.h"
|
|
#include "libcef/common/cef_messages.h"
|
|
#include "libcef/renderer/alloy/alloy_content_renderer_client.h"
|
|
#include "libcef/renderer/blink_glue.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 AlloyContentRendererClient::Get()->GetBrowserForView(view);
|
|
}
|
|
|
|
// static
|
|
CefRefPtr<CefBrowserImpl> CefBrowserImpl::GetBrowserForMainFrame(
|
|
blink::WebFrame* frame) {
|
|
return AlloyContentRendererClient::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 = CefAppManager::Get()->GetApplication();
|
|
if (app.get()) {
|
|
CefRefPtr<CefRenderProcessHandler> handler = app->GetRenderProcessHandler();
|
|
if (handler.get())
|
|
handler->OnBrowserDestroyed(this);
|
|
}
|
|
|
|
AlloyContentRendererClient::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 = CefAppManager::Get()->GetApplication();
|
|
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));
|
|
}
|
|
}
|
|
}
|
|
}
|