From 38d8acfa186c5663e03e0ea58b4848c5d2635a21 Mon Sep 17 00:00:00 2001 From: Marshall Greenblatt Date: Thu, 17 Sep 2020 18:24:08 -0400 Subject: [PATCH] Create a ChromeBrowserHostImpl for every Chrome tab (see issue #2969) The Browser object represents the top-level Chrome browser window. One or more tabs (WebContents) are then owned by the Browser object via TabStripModel. A new Browser object can be created programmatically using "new Browser" or Browser::Create, or as a result of user action such as dragging a tab out of an existing window. New or existing tabs can also be added to an already existing Browser object. The Browser object acts as the WebContentsDelegate for all attached tabs. CEF integration requires WebContentsDelegate callbacks and notification of tab attach/detach. To support this integration we add a cef::BrowserDelegate (ChromeBrowserDelegate) member that is created in the Browser constructor and receives delegation for the Browser callbacks. ChromeBrowserDelegate creates a new ChromeBrowserHostImpl when a tab is added to a Browser for the first time, and that ChromeBrowserHostImpl continues to exist until the tab's WebContents is destroyed. The associated WebContents object does not change, but the Browser object will change when the tab is dragged between windows. CEF callback logic is shared between the chrome and alloy runtimes where possible. This shared logic has been extracted from CefBrowserHostImpl to create new CefBrowserHostBase and CefBrowserContentsDelegate classes. The CefBrowserHostImpl class is now only used with the alloy runtime and will be renamed to AlloyBrowserHostImpl in a future commit. --- BUILD.gn | 12 +- .../capi/cef_browser_process_handler_capi.h | 13 +- include/cef_api_hash.h | 8 +- include/cef_browser_process_handler.h | 11 + libcef/browser/alloy/alloy_browser_context.cc | 8 +- libcef/browser/alloy/alloy_browser_context.h | 5 +- .../alloy/alloy_content_browser_client.cc | 3 +- .../alloy/browser_platform_delegate_alloy.cc | 2 +- .../alloy/browser_platform_delegate_alloy.h | 2 +- libcef/browser/browser_contents_delegate.cc | 450 +++++++ libcef/browser/browser_contents_delegate.h | 164 +++ libcef/browser/browser_context.cc | 2 - libcef/browser/browser_context.h | 4 - libcef/browser/browser_host_base.cc | 623 +++++++++ libcef/browser/browser_host_base.h | 240 ++++ libcef/browser/browser_host_create.cc | 144 ++ libcef/browser/browser_host_impl.cc | 1192 ++--------------- libcef/browser/browser_host_impl.h | 206 +-- libcef/browser/browser_info.cc | 35 +- libcef/browser/browser_info.h | 49 +- libcef/browser/browser_info_manager.cc | 13 +- libcef/browser/browser_info_manager.h | 11 +- libcef/browser/browser_platform_delegate.h | 4 +- .../browser_platform_delegate_create.cc | 7 +- libcef/browser/chrome/browser_delegate.h | 45 + .../browser_platform_delegate_chrome.cc | 138 -- .../chrome/browser_platform_delegate_chrome.h | 55 - .../browser/chrome/chrome_browser_delegate.cc | 158 +++ .../browser/chrome/chrome_browser_delegate.h | 80 ++ .../chrome/chrome_browser_host_impl.cc | 508 +++++++ .../browser/chrome/chrome_browser_host_impl.h | 179 +++ libcef/browser/devtools/devtools_frontend.cc | 2 +- libcef/browser/download_manager_delegate.cc | 3 +- libcef/browser/download_manager_delegate.h | 10 +- .../extensions/browser_extensions_util.cc | 29 +- .../extensions/browser_extensions_util.h | 16 +- .../extensions/extension_function_details.cc | 2 +- .../extensions/extensions_browser_client.cc | 2 +- libcef/browser/frame_host_impl.cc | 28 +- libcef/browser/frame_host_impl.h | 8 +- .../resource_request_handler_wrapper.cc | 22 +- libcef/browser/prefs/renderer_prefs.cc | 7 +- libcef/browser/printing/print_dialog_linux.cc | 5 +- libcef/browser/printing/print_dialog_linux.h | 4 +- libcef/browser/views/browser_view_impl.cc | 2 +- libcef/browser/views/browser_view_impl.h | 2 +- libcef/features/runtime_checks.h | 2 +- .../cpptoc/browser_process_handler_cpptoc.cc | 20 +- .../ctocpp/browser_process_handler_ctocpp.cc | 18 +- .../ctocpp/browser_process_handler_ctocpp.h | 3 +- patch/patch.cfg | 5 + patch/patches/chrome_browser_browser.patch | 180 +++ 52 files changed, 3138 insertions(+), 1603 deletions(-) create mode 100644 libcef/browser/browser_contents_delegate.cc create mode 100644 libcef/browser/browser_contents_delegate.h create mode 100644 libcef/browser/browser_host_base.cc create mode 100644 libcef/browser/browser_host_base.h create mode 100644 libcef/browser/browser_host_create.cc create mode 100644 libcef/browser/chrome/browser_delegate.h delete mode 100644 libcef/browser/chrome/browser_platform_delegate_chrome.cc delete mode 100644 libcef/browser/chrome/browser_platform_delegate_chrome.h create mode 100644 libcef/browser/chrome/chrome_browser_delegate.cc create mode 100644 libcef/browser/chrome/chrome_browser_delegate.h create mode 100644 libcef/browser/chrome/chrome_browser_host_impl.cc create mode 100644 libcef/browser/chrome/chrome_browser_host_impl.h create mode 100644 patch/patches/chrome_browser_browser.patch diff --git a/BUILD.gn b/BUILD.gn index e902b904b..143ea6a23 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -423,10 +423,15 @@ static_library("libcef_static") { "libcef/browser/alloy/alloy_content_browser_client.h", "libcef/browser/audio_capturer.cc", "libcef/browser/audio_capturer.h", + "libcef/browser/browser_contents_delegate.cc", + "libcef/browser/browser_contents_delegate.h", "libcef/browser/browser_context.cc", "libcef/browser/browser_context.h", "libcef/browser/browser_context_keyed_service_factories.cc", "libcef/browser/browser_context_keyed_service_factories.h", + "libcef/browser/browser_host_base.cc", + "libcef/browser/browser_host_base.h", + "libcef/browser/browser_host_create.cc", "libcef/browser/browser_host_impl.cc", "libcef/browser/browser_host_impl.h", "libcef/browser/browser_info.cc", @@ -442,10 +447,13 @@ static_library("libcef_static") { "libcef/browser/browser_platform_delegate_create.cc", "libcef/browser/browser_util.cc", "libcef/browser/browser_util.h", - "libcef/browser/chrome/browser_platform_delegate_chrome.cc", - "libcef/browser/chrome/browser_platform_delegate_chrome.h", + "libcef/browser/chrome/browser_delegate.h", "libcef/browser/chrome/chrome_browser_context.cc", "libcef/browser/chrome/chrome_browser_context.h", + "libcef/browser/chrome/chrome_browser_delegate.cc", + "libcef/browser/chrome/chrome_browser_delegate.h", + "libcef/browser/chrome/chrome_browser_host_impl.cc", + "libcef/browser/chrome/chrome_browser_host_impl.h", "libcef/browser/chrome/chrome_browser_main_extra_parts_cef.cc", "libcef/browser/chrome/chrome_browser_main_extra_parts_cef.h", "libcef/browser/chrome/chrome_content_browser_client_cef.cc", diff --git a/include/capi/cef_browser_process_handler_capi.h b/include/capi/cef_browser_process_handler_capi.h index c3195a51b..e546a564a 100644 --- a/include/capi/cef_browser_process_handler_capi.h +++ b/include/capi/cef_browser_process_handler_capi.h @@ -33,7 +33,7 @@ // by hand. See the translator.README.txt file in the tools directory for // more information. // -// $hash=306236316b35037523ca566068d133755bce48fd$ +// $hash=17e60bfb954ddf6c40b90b9a117d90a0fe3f08d6$ // #ifndef CEF_INCLUDE_CAPI_CEF_BROWSER_PROCESS_HANDLER_CAPI_H_ @@ -41,6 +41,7 @@ #pragma once #include "include/capi/cef_base_capi.h" +#include "include/capi/cef_client_capi.h" #include "include/capi/cef_command_line_capi.h" #include "include/capi/cef_print_handler_capi.h" #include "include/capi/cef_values_capi.h" @@ -101,6 +102,16 @@ typedef struct _cef_browser_process_handler_t { void(CEF_CALLBACK* on_schedule_message_pump_work)( struct _cef_browser_process_handler_t* self, int64 delay_ms); + + /// + // Return the default client for use with a newly created browser window. If + // null is returned the browser will be unmanaged (no callbacks will be + // executed for that browser) and application shutdown will be blocked until + // the browser window is closed manually. This function is currently only used + // with the chrome runtime. + /// + struct _cef_client_t*(CEF_CALLBACK* get_default_client)( + struct _cef_browser_process_handler_t* self); } cef_browser_process_handler_t; #ifdef __cplusplus diff --git a/include/cef_api_hash.h b/include/cef_api_hash.h index 3c5a20089..841de18a2 100644 --- a/include/cef_api_hash.h +++ b/include/cef_api_hash.h @@ -42,13 +42,13 @@ // way that may cause binary incompatibility with other builds. The universal // hash value will change if any platform is affected whereas the platform hash // values will change only if that particular platform is affected. -#define CEF_API_HASH_UNIVERSAL "09d3d4f08869644fe3baa7a751de537f3446525b" +#define CEF_API_HASH_UNIVERSAL "c148b1a4fd1d29c2e14b1ab8ce1c04f29013de73" #if defined(OS_WIN) -#define CEF_API_HASH_PLATFORM "3022db6736af26cc38158d38e22f74a51312a5c9" +#define CEF_API_HASH_PLATFORM "1f380ef6bde94cd7331d090b7aee0a08f2515541" #elif defined(OS_MAC) -#define CEF_API_HASH_PLATFORM "13e2e2451c2320f0d16b35ba53b3295409888dd8" +#define CEF_API_HASH_PLATFORM "c42f0866e58d3f96183e1f8931a4d01a7900b0b4" #elif defined(OS_LINUX) -#define CEF_API_HASH_PLATFORM "d781b815150795b0bce95d72ce967b508c9a04d5" +#define CEF_API_HASH_PLATFORM "92824ced77603246263f1f2ecf95ff4fad73885d" #endif #ifdef __cplusplus diff --git a/include/cef_browser_process_handler.h b/include/cef_browser_process_handler.h index 102dcb1eb..b6906c09a 100644 --- a/include/cef_browser_process_handler.h +++ b/include/cef_browser_process_handler.h @@ -39,6 +39,7 @@ #pragma once #include "include/cef_base.h" +#include "include/cef_client.h" #include "include/cef_command_line.h" #include "include/cef_print_handler.h" #include "include/cef_values.h" @@ -90,6 +91,16 @@ class CefBrowserProcessHandler : public virtual CefBaseRefCounted { /// /*--cef()--*/ virtual void OnScheduleMessagePumpWork(int64 delay_ms) {} + + /// + // Return the default client for use with a newly created browser window. If + // null is returned the browser will be unmanaged (no callbacks will be + // executed for that browser) and application shutdown will be blocked until + // the browser window is closed manually. This method is currently only used + // with the chrome runtime. + /// + /*--cef()--*/ + virtual CefRefPtr GetDefaultClient() { return nullptr; } }; #endif // CEF_INCLUDE_CEF_BROWSER_PROCESS_HANDLER_H_ diff --git a/libcef/browser/alloy/alloy_browser_context.cc b/libcef/browser/alloy/alloy_browser_context.cc index 51ebda2ad..427271147 100644 --- a/libcef/browser/alloy/alloy_browser_context.cc +++ b/libcef/browser/alloy/alloy_browser_context.cc @@ -285,10 +285,6 @@ bool AlloyBrowserContext::IsPrintPreviewSupported() const { return !GetPrefs()->GetBoolean(prefs::kPrintPreviewDisabled); } -void AlloyBrowserContext::AddVisitedURLs(const std::vector& urls) { - visitedlink_master_->AddURLs(urls); -} - content::ResourceContext* AlloyBrowserContext::GetResourceContext() { if (!resource_context_) { resource_context_ = std::make_unique(); @@ -454,3 +450,7 @@ DownloadPrefs* AlloyBrowserContext::GetDownloadPrefs() { } return download_prefs_.get(); } + +void AlloyBrowserContext::AddVisitedURLs(const std::vector& urls) { + visitedlink_master_->AddURLs(urls); +} diff --git a/libcef/browser/alloy/alloy_browser_context.h b/libcef/browser/alloy/alloy_browser_context.h index 945808d62..b647b1ced 100644 --- a/libcef/browser/alloy/alloy_browser_context.h +++ b/libcef/browser/alloy/alloy_browser_context.h @@ -53,7 +53,6 @@ class AlloyBrowserContext : public ChromeProfileAlloy, CefRefPtr GetExtension(const CefString& extension_id) override; bool UnloadExtension(const CefString& extension_id) override; bool IsPrintPreviewSupported() const override; - void AddVisitedURLs(const std::vector& urls) override; // content::BrowserContext overrides. content::ResourceContext* GetResourceContext() override; @@ -116,6 +115,10 @@ class AlloyBrowserContext : public ChromeProfileAlloy, return extension_system_; } + // Called from CefBrowserHostImpl::DidFinishNavigation to update the table of + // visited links. + void AddVisitedURLs(const std::vector& urls); + // Called from DownloadPrefs::FromBrowserContext. DownloadPrefs* GetDownloadPrefs(); diff --git a/libcef/browser/alloy/alloy_content_browser_client.cc b/libcef/browser/alloy/alloy_content_browser_client.cc index 9054fa01e..413ef5331 100644 --- a/libcef/browser/alloy/alloy_content_browser_client.cc +++ b/libcef/browser/alloy/alloy_content_browser_client.cc @@ -495,8 +495,7 @@ bool NavigationOnUIThread( // Initiating a new navigation in OnBeforeBrowse will delete the // InterceptNavigationThrottle that currently owns this callback, // resulting in a crash. Use the lock to prevent that. - std::unique_ptr navigation_lock = - browser->CreateNavigationLock(); + auto navigation_lock = browser->browser_info()->CreateNavigationLock(); ignore_navigation = handler->OnBeforeBrowse( browser.get(), frame, request.get(), params.has_user_gesture(), params.is_redirect()); diff --git a/libcef/browser/alloy/browser_platform_delegate_alloy.cc b/libcef/browser/alloy/browser_platform_delegate_alloy.cc index 466ee4617..5c7fca508 100644 --- a/libcef/browser/alloy/browser_platform_delegate_alloy.cc +++ b/libcef/browser/alloy/browser_platform_delegate_alloy.cc @@ -28,7 +28,7 @@ CefBrowserPlatformDelegateAlloy::CefBrowserPlatformDelegateAlloy() : weak_ptr_factory_(this) {} content::WebContents* CefBrowserPlatformDelegateAlloy::CreateWebContents( - CefBrowserHostImpl::CreateParams& create_params, + CefBrowserHostBase::CreateParams& create_params, bool& own_web_contents) { // Get or create the request context and browser context. CefRefPtr request_context_impl = diff --git a/libcef/browser/alloy/browser_platform_delegate_alloy.h b/libcef/browser/alloy/browser_platform_delegate_alloy.h index f1e6ba0f3..b9cc84ae8 100644 --- a/libcef/browser/alloy/browser_platform_delegate_alloy.h +++ b/libcef/browser/alloy/browser_platform_delegate_alloy.h @@ -15,7 +15,7 @@ class CefBrowserPlatformDelegateAlloy : public CefBrowserPlatformDelegate { public: content::WebContents* CreateWebContents( - CefBrowserHostImpl::CreateParams& create_params, + CefBrowserHostBase::CreateParams& create_params, bool& own_web_contents) override; void WebContentsCreated(content::WebContents* web_contents, bool owned) override; diff --git a/libcef/browser/browser_contents_delegate.cc b/libcef/browser/browser_contents_delegate.cc new file mode 100644 index 000000000..406ed4543 --- /dev/null +++ b/libcef/browser/browser_contents_delegate.cc @@ -0,0 +1,450 @@ +// Copyright 2020 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/browser_contents_delegate.h" + +#include "libcef/browser/browser_host_base.h" + +#include "content/public/browser/navigation_entry.h" +#include "content/public/browser/navigation_handle.h" +#include "content/public/browser/render_view_host.h" + +CefBrowserContentsDelegate::CefBrowserContentsDelegate( + scoped_refptr browser_info) + : browser_info_(browser_info) { + DCHECK(browser_info_->browser()); +} + +void CefBrowserContentsDelegate::ObserveWebContents( + content::WebContents* new_contents) { + Observe(new_contents); + + if (new_contents) { + // Create the frame representation before OnAfterCreated is called for a new + // browser. Additionally, RenderFrameCreated is otherwise not called at all + // for new popup browsers. + RenderFrameCreated(new_contents->GetMainFrame()); + } +} + +void CefBrowserContentsDelegate::AddObserver(Observer* observer) { + observers_.AddObserver(observer); +} + +void CefBrowserContentsDelegate::RemoveObserver(Observer* observer) { + observers_.RemoveObserver(observer); +} + +void CefBrowserContentsDelegate::LoadingStateChanged( + content::WebContents* source, + bool to_different_document) { + const int current_index = + source->GetController().GetLastCommittedEntryIndex(); + const int max_index = source->GetController().GetEntryCount() - 1; + + const bool is_loading = source->IsLoading(); + const bool can_go_back = (current_index > 0); + const bool can_go_forward = (current_index < max_index); + + // This method may be called multiple times in a row with |is_loading| + // true as a result of https://crrev.com/5e750ad0. Ignore the 2nd+ times. + if (is_loading_ == is_loading && can_go_back_ == can_go_back && + can_go_forward_ == can_go_forward) { + return; + } + + is_loading_ = is_loading; + can_go_back_ = can_go_back; + can_go_forward_ = can_go_forward; + OnStateChanged(State::kNavigation); + + if (auto c = client()) { + if (auto handler = c->GetLoadHandler()) { + handler->OnLoadingStateChange(browser(), is_loading, can_go_back, + can_go_forward); + } + } +} + +void CefBrowserContentsDelegate::UpdateTargetURL(content::WebContents* source, + const GURL& url) { + if (auto c = client()) { + if (auto handler = c->GetDisplayHandler()) { + handler->OnStatusMessage(browser(), url.spec()); + } + } +} + +bool CefBrowserContentsDelegate::DidAddMessageToConsole( + content::WebContents* source, + blink::mojom::ConsoleMessageLevel log_level, + const base::string16& message, + int32_t line_no, + const base::string16& source_id) { + if (auto c = client()) { + if (auto handler = c->GetDisplayHandler()) { + // Use LOGSEVERITY_DEBUG for unrecognized |level| values. + cef_log_severity_t cef_level = LOGSEVERITY_DEBUG; + switch (log_level) { + case blink::mojom::ConsoleMessageLevel::kVerbose: + cef_level = LOGSEVERITY_DEBUG; + break; + case blink::mojom::ConsoleMessageLevel::kInfo: + cef_level = LOGSEVERITY_INFO; + break; + case blink::mojom::ConsoleMessageLevel::kWarning: + cef_level = LOGSEVERITY_WARNING; + break; + case blink::mojom::ConsoleMessageLevel::kError: + cef_level = LOGSEVERITY_ERROR; + break; + } + + return handler->OnConsoleMessage(browser(), cef_level, message, source_id, + line_no); + } + } + + return false; +} + +void CefBrowserContentsDelegate::DidNavigateMainFramePostCommit( + content::WebContents* web_contents) { + has_document_ = false; + OnStateChanged(State::kDocument); +} + +void CefBrowserContentsDelegate::EnterFullscreenModeForTab( + content::RenderFrameHost* requesting_frame, + const blink::mojom::FullscreenOptions& options) { + OnFullscreenModeChange(/*fullscreen=*/true); +} + +void CefBrowserContentsDelegate::ExitFullscreenModeForTab( + content::WebContents* web_contents) { + OnFullscreenModeChange(/*fullscreen=*/false); +} + +void CefBrowserContentsDelegate::RenderFrameCreated( + content::RenderFrameHost* render_frame_host) { + browser_info_->MaybeCreateFrame(render_frame_host, false /* is_guest_view */); +} + +void CefBrowserContentsDelegate::RenderFrameHostChanged( + content::RenderFrameHost* old_host, + content::RenderFrameHost* new_host) { + // Just in case RenderFrameCreated wasn't called for some reason. + RenderFrameCreated(new_host); +} + +void CefBrowserContentsDelegate::RenderFrameDeleted( + content::RenderFrameHost* render_frame_host) { + const auto frame_id = CefFrameHostImpl::MakeFrameId(render_frame_host); + browser_info_->RemoveFrame(render_frame_host); + + if (focused_frame_ && focused_frame_->GetIdentifier() == frame_id) { + focused_frame_ = nullptr; + OnStateChanged(State::kFocusedFrame); + } +} + +void CefBrowserContentsDelegate::RenderViewReady() { + if (auto c = client()) { + if (auto handler = c->GetRequestHandler()) { + handler->OnRenderViewReady(browser()); + } + } +} + +void CefBrowserContentsDelegate::RenderProcessGone( + base::TerminationStatus status) { + cef_termination_status_t ts = TS_ABNORMAL_TERMINATION; + if (status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED) + ts = TS_PROCESS_WAS_KILLED; + else if (status == base::TERMINATION_STATUS_PROCESS_CRASHED) + ts = TS_PROCESS_CRASHED; + else if (status == base::TERMINATION_STATUS_OOM) + ts = TS_PROCESS_OOM; + else if (status != base::TERMINATION_STATUS_ABNORMAL_TERMINATION) + return; + + if (auto c = client()) { + if (auto handler = c->GetRequestHandler()) { + auto navigation_lock = browser_info_->CreateNavigationLock(); + handler->OnRenderProcessTerminated(browser(), ts); + } + } +} + +void CefBrowserContentsDelegate::OnFrameFocused( + content::RenderFrameHost* render_frame_host) { + CefRefPtr frame = static_cast( + browser_info_->GetFrameForHost(render_frame_host).get()); + if (!frame || frame->IsFocused()) + return; + + CefRefPtr previous_frame = focused_frame_; + if (frame->IsMain()) + focused_frame_ = nullptr; + else + focused_frame_ = frame; + + if (!previous_frame) { + // The main frame is focused by default. + previous_frame = browser_info_->GetMainFrame(); + } + + if (previous_frame->GetIdentifier() != frame->GetIdentifier()) { + previous_frame->SetFocused(false); + frame->SetFocused(true); + } + + OnStateChanged(State::kFocusedFrame); +} + +void CefBrowserContentsDelegate::DocumentAvailableInMainFrame() { + has_document_ = true; + OnStateChanged(State::kDocument); + + if (auto c = client()) { + if (auto handler = c->GetRequestHandler()) { + handler->OnDocumentAvailableInMainFrame(browser()); + } + } +} + +void CefBrowserContentsDelegate::LoadProgressChanged(double progress) { + if (auto c = client()) { + if (auto handler = c->GetDisplayHandler()) { + handler->OnLoadingProgressChange(browser(), progress); + } + } +} + +void CefBrowserContentsDelegate::DidStopLoading() { + // Notify all renderers that loading has stopped. We used to use + // RenderFrameObserver::DidStopLoading in the renderer process but that was + // removed in https://crrev.com/3e37dd0ead. However, that callback wasn't + // necessarily accurate because it wasn't called in all of the cases where + // RenderFrameImpl sends the FrameHostMsg_DidStopLoading message. This adds + // an additional round trip but should provide the same or improved + // functionality. + for (const auto& frame : browser_info_->GetAllFrames()) { + frame->MaybeSendDidStopLoading(); + } +} + +void CefBrowserContentsDelegate::DidFinishNavigation( + content::NavigationHandle* navigation_handle) { + const net::Error error_code = navigation_handle->GetNetErrorCode(); + + // Skip calls where the navigation has not yet committed and there is no + // error code. For example, when creating a browser without loading a URL. + if (!navigation_handle->HasCommitted() && error_code == net::OK) + return; + + const bool is_main_frame = navigation_handle->IsInMainFrame(); + const GURL& url = + (error_code == net::OK ? navigation_handle->GetURL() : GURL()); + + auto browser_info = browser_info_; + + // May return NULL when starting a new navigation if the previous navigation + // caused the renderer process to crash during load. + CefRefPtr frame = browser_info->GetFrameForFrameTreeNode( + navigation_handle->GetFrameTreeNodeId()); + if (!frame) { + if (is_main_frame) { + frame = browser_info->GetMainFrame(); + } else { + frame = + browser_info->CreateTempSubFrame(CefFrameHostImpl::kInvalidFrameId); + } + } + frame->RefreshAttributes(); + + if (error_code == net::OK) { + // The navigation has been committed and there is no error. + DCHECK(navigation_handle->HasCommitted()); + + // Don't call OnLoadStart for same page navigations (fragments, + // history state). + if (!navigation_handle->IsSameDocument()) { + OnLoadStart(frame.get(), navigation_handle->GetPageTransition()); + } + + if (is_main_frame) { + OnAddressChange(url); + } + } else { + // The navigation failed with an error. This may happen before commit + // (e.g. network error) or after commit (e.g. response filter error). + // If the error happened before commit then this call will originate from + // RenderFrameHostImpl::OnDidFailProvisionalLoadWithError. + // OnLoadStart/OnLoadEnd will not be called. + OnLoadError(frame.get(), navigation_handle->GetURL(), error_code); + } +} + +void CefBrowserContentsDelegate::DidFailLoad( + content::RenderFrameHost* render_frame_host, + const GURL& validated_url, + int error_code) { + // The navigation failed after commit. OnLoadStart was called so we also + // call OnLoadEnd. + auto frame = browser_info_->GetFrameForHost(render_frame_host); + frame->RefreshAttributes(); + OnLoadError(frame, validated_url, error_code); + OnLoadEnd(frame, validated_url, error_code); +} + +bool CefBrowserContentsDelegate::OnMessageReceived( + const IPC::Message& message, + content::RenderFrameHost* render_frame_host) { + // Messages may arrive after a frame is detached. Ignore those messages. + auto frame = browser_info_->GetFrameForHost(render_frame_host); + if (frame) { + return static_cast(frame.get()) + ->OnMessageReceived(message); + } + return false; +} + +void CefBrowserContentsDelegate::TitleWasSet(content::NavigationEntry* entry) { + // |entry| may be NULL if a popup is created via window.open and never + // navigated. + if (entry) + OnTitleChange(entry->GetTitle()); + else if (web_contents()) + OnTitleChange(web_contents()->GetTitle()); +} + +void CefBrowserContentsDelegate::PluginCrashed( + const base::FilePath& plugin_path, + base::ProcessId plugin_pid) { + if (auto c = client()) { + if (auto handler = c->GetRequestHandler()) { + handler->OnPluginCrashed(browser(), plugin_path.value()); + } + } +} + +void CefBrowserContentsDelegate::DidUpdateFaviconURL( + content::RenderFrameHost* render_frame_host, + const std::vector& candidates) { + if (auto c = client()) { + if (auto handler = c->GetDisplayHandler()) { + std::vector icon_urls; + for (const auto& icon : candidates) { + if (icon->icon_type == blink::mojom::FaviconIconType::kFavicon) { + icon_urls.push_back(icon->icon_url.spec()); + } + } + if (!icon_urls.empty()) { + handler->OnFaviconURLChange(browser(), icon_urls); + } + } + } +} + +void CefBrowserContentsDelegate::OnWebContentsFocused( + content::RenderWidgetHost* render_widget_host) { + if (auto c = client()) { + if (auto handler = c->GetFocusHandler()) { + handler->OnGotFocus(browser()); + } + } +} + +void CefBrowserContentsDelegate::WebContentsDestroyed() { + ObserveWebContents(nullptr); + for (auto& observer : observers_) { + observer.OnWebContentsDestroyed(); + } +} + +void CefBrowserContentsDelegate::OnAddressChange(const GURL& url) { + if (auto c = client()) { + if (auto handler = c->GetDisplayHandler()) { + // On the handler of an address change. + handler->OnAddressChange(browser(), browser_info_->GetMainFrame(), + url.spec()); + } + } +} + +void CefBrowserContentsDelegate::OnLoadStart( + CefRefPtr frame, + ui::PageTransition transition_type) { + if (auto c = client()) { + if (auto handler = c->GetLoadHandler()) { + // On the handler that loading has started. + handler->OnLoadStart(browser(), frame, + static_cast(transition_type)); + } + } +} + +void CefBrowserContentsDelegate::OnLoadError(CefRefPtr frame, + const GURL& url, + int error_code) { + if (auto c = client()) { + if (auto handler = c->GetLoadHandler()) { + auto navigation_lock = browser_info_->CreateNavigationLock(); + // On the handler that loading has failed. + handler->OnLoadError(browser(), frame, + static_cast(error_code), + net::ErrorToShortString(error_code), url.spec()); + } + } +} + +void CefBrowserContentsDelegate::OnLoadEnd(CefRefPtr frame, + const GURL& url, + int http_status_code) { + if (auto c = client()) { + if (auto handler = c->GetLoadHandler()) { + handler->OnLoadEnd(browser(), frame, http_status_code); + } + } +} + +void CefBrowserContentsDelegate::OnTitleChange(const base::string16& title) { + if (auto c = client()) { + if (auto handler = c->GetDisplayHandler()) { + handler->OnTitleChange(browser(), title); + } + } +} + +CefRefPtr CefBrowserContentsDelegate::client() const { + if (auto b = browser()) { + return b->GetHost()->GetClient(); + } + return nullptr; +} + +CefRefPtr CefBrowserContentsDelegate::browser() const { + return browser_info_->browser(); +} + +void CefBrowserContentsDelegate::OnFullscreenModeChange(bool fullscreen) { + if (fullscreen == is_fullscreen_) + return; + + is_fullscreen_ = fullscreen; + OnStateChanged(State::kFullscreen); + + if (auto c = client()) { + if (auto handler = c->GetDisplayHandler()) { + handler->OnFullscreenModeChange(browser(), fullscreen); + } + } +} + +void CefBrowserContentsDelegate::OnStateChanged(State state_changed) { + for (auto& observer : observers_) { + observer.OnStateChanged(state_changed); + } +} diff --git a/libcef/browser/browser_contents_delegate.h b/libcef/browser/browser_contents_delegate.h new file mode 100644 index 000000000..31ec6cad6 --- /dev/null +++ b/libcef/browser/browser_contents_delegate.h @@ -0,0 +1,164 @@ +// Copyright 2020 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. + +#ifndef CEF_LIBCEF_BROWSER_BROWSER_CONTENTS_DELEGATE_H_ +#define CEF_LIBCEF_BROWSER_BROWSER_CONTENTS_DELEGATE_H_ +#pragma once + +#include + +#include "libcef/browser/frame_host_impl.h" + +#include "base/observer_list.h" +#include "content/public/browser/web_contents_delegate.h" +#include "content/public/browser/web_contents_observer.h" + +class CefBrowser; +class CefBrowserInfo; +class CefClient; + +// Flags that represent which states have changed. +enum class CefBrowserContentsState : uint8_t { + kNone = 0, + kNavigation = (1 << 0), + kDocument = (1 << 1), + kFullscreen = (1 << 2), + kFocusedFrame = (1 << 3), +}; + +constexpr inline CefBrowserContentsState operator&( + CefBrowserContentsState lhs, + CefBrowserContentsState rhs) { + return static_cast(static_cast(lhs) & + static_cast(rhs)); +} + +constexpr inline CefBrowserContentsState operator|( + CefBrowserContentsState lhs, + CefBrowserContentsState rhs) { + return static_cast(static_cast(lhs) | + static_cast(rhs)); +} + +// Tracks state and executes client callbacks based on WebContents callbacks. +// Includes functionality that is shared by the alloy and chrome runtimes. +// Only accessed on the UI thread. +class CefBrowserContentsDelegate : public content::WebContentsDelegate, + public content::WebContentsObserver { + public: + using State = CefBrowserContentsState; + + // Interface to implement for observers that wish to be informed of changes + // to the delegate. All methods will be called on the UI thread. + class Observer : public base::CheckedObserver { + public: + // Called after state has changed and before the associated CefClient + // callback is executed. + virtual void OnStateChanged(State state_changed) = 0; + + // Called when the associated WebContents is destroyed. + virtual void OnWebContentsDestroyed() = 0; + + protected: + ~Observer() override {} + }; + + explicit CefBrowserContentsDelegate( + scoped_refptr browser_info); + + void ObserveWebContents(content::WebContents* new_contents); + + // Manage observer objects. The observer must either outlive this object or + // be removed before destruction. + void AddObserver(Observer* observer); + void RemoveObserver(Observer* observer); + + // WebContentsDelegate methods: + void LoadingStateChanged(content::WebContents* source, + bool to_different_document) override; + void UpdateTargetURL(content::WebContents* source, const GURL& url) override; + bool DidAddMessageToConsole(content::WebContents* source, + blink::mojom::ConsoleMessageLevel log_level, + const base::string16& message, + int32_t line_no, + const base::string16& source_id) override; + void DidNavigateMainFramePostCommit( + content::WebContents* web_contents) override; + void EnterFullscreenModeForTab( + content::RenderFrameHost* requesting_frame, + const blink::mojom::FullscreenOptions& options) override; + void ExitFullscreenModeForTab(content::WebContents* web_contents) override; + + // WebContentsObserver methods: + void RenderFrameCreated(content::RenderFrameHost* render_frame_host) override; + void RenderFrameHostChanged(content::RenderFrameHost* old_host, + content::RenderFrameHost* new_host) override; + void RenderFrameDeleted(content::RenderFrameHost* render_frame_host) override; + void RenderViewReady() override; + void RenderProcessGone(base::TerminationStatus status) override; + void OnFrameFocused(content::RenderFrameHost* render_frame_host) override; + void DocumentAvailableInMainFrame() override; + void LoadProgressChanged(double progress) override; + void DidStopLoading() override; + void DidFinishNavigation( + content::NavigationHandle* navigation_handle) override; + void DidFailLoad(content::RenderFrameHost* render_frame_host, + const GURL& validated_url, + int error_code) override; + bool OnMessageReceived(const IPC::Message& message, + content::RenderFrameHost* render_frame_host) override; + void TitleWasSet(content::NavigationEntry* entry) override; + void PluginCrashed(const base::FilePath& plugin_path, + base::ProcessId plugin_pid) override; + void DidUpdateFaviconURL( + content::RenderFrameHost* render_frame_host, + const std::vector& candidates) override; + void OnWebContentsFocused( + content::RenderWidgetHost* render_widget_host) override; + void WebContentsDestroyed() override; + + // Accessors for state information. Changes will be signaled to + // Observer::OnStateChanged. + bool is_loading() const { return is_loading_; } + bool can_go_back() const { return can_go_back_; } + bool can_go_forward() const { return can_go_forward_; } + bool has_document() const { return has_document_; } + bool is_fullscreen() const { return is_fullscreen_; } + CefRefPtr focused_frame() const { return focused_frame_; } + + // Helpers for executing client callbacks. + void OnAddressChange(const GURL& url); + void OnLoadStart(CefRefPtr frame, + ui::PageTransition transition_type); + void OnLoadError(CefRefPtr frame, const GURL& url, int error_code); + void OnLoadEnd(CefRefPtr frame, + const GURL& url, + int http_status_code); + void OnTitleChange(const base::string16& title); + + private: + CefRefPtr client() const; + CefRefPtr browser() const; + + void OnFullscreenModeChange(bool fullscreen); + void OnStateChanged(State state_changed); + + scoped_refptr browser_info_; + + bool is_loading_ = false; + bool can_go_back_ = false; + bool can_go_forward_ = false; + bool has_document_ = false; + bool is_fullscreen_ = false; + + // The currently focused frame, or nullptr if the main frame is focused. + CefRefPtr focused_frame_; + + // Observers that want to be notified of changes to this object. + base::ObserverList observers_; + + DISALLOW_COPY_AND_ASSIGN(CefBrowserContentsDelegate); +}; + +#endif // CEF_LIBCEF_BROWSER_BROWSER_CONTENTS_DELEGATE_H_ diff --git a/libcef/browser/browser_context.cc b/libcef/browser/browser_context.cc index e1bcff08b..934767794 100644 --- a/libcef/browser/browser_context.cc +++ b/libcef/browser/browser_context.cc @@ -456,8 +456,6 @@ bool CefBrowserContext::IsPrintPreviewSupported() const { return true; } -void CefBrowserContext::AddVisitedURLs(const std::vector& urls) {} - network::mojom::NetworkContext* CefBrowserContext::GetNetworkContext() { CEF_REQUIRE_UIT(); auto browser_context = AsBrowserContext(); diff --git a/libcef/browser/browser_context.h b/libcef/browser/browser_context.h index 6aad857dc..cbe9b2f89 100644 --- a/libcef/browser/browser_context.h +++ b/libcef/browser/browser_context.h @@ -188,10 +188,6 @@ class CefBrowserContext { // Returns true if this context supports print preview. virtual bool IsPrintPreviewSupported() const; - // Called from CefBrowserHostImpl::DidNavigateAnyFrame to update the table of - // visited links. - virtual void AddVisitedURLs(const std::vector& urls); - network::mojom::NetworkContext* GetNetworkContext(); CefMediaRouterManager* GetMediaRouterManager(); diff --git a/libcef/browser/browser_host_base.cc b/libcef/browser/browser_host_base.cc new file mode 100644 index 000000000..8f35ecf1b --- /dev/null +++ b/libcef/browser/browser_host_base.cc @@ -0,0 +1,623 @@ +// Copyright 2020 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/browser_host_base.h" + +#include "libcef/browser/browser_info_manager.h" +#include "libcef/browser/image_impl.h" +#include "libcef/browser/navigation_entry_impl.h" +#include "libcef/browser/net/scheme_handler.h" +#include "libcef/browser/thread_util.h" + +#include "base/logging.h" +#include "chrome/browser/spellchecker/spellcheck_factory.h" +#include "chrome/browser/spellchecker/spellcheck_service.h" +#include "components/favicon/core/favicon_url.h" +#include "components/spellcheck/common/spellcheck_features.h" +#include "content/public/browser/browser_context.h" +#include "content/public/browser/download_manager.h" +#include "content/public/browser/download_request_utils.h" +#include "content/public/browser/navigation_entry.h" +#include "ui/gfx/image/image_skia.h" + +#if defined(OS_MAC) +#include "components/spellcheck/browser/spellcheck_platform.h" +#endif + +namespace { + +// Associates a CefBrowserHostBase instance with a WebContents. This object will +// be deleted automatically when the WebContents is destroyed. +class WebContentsUserDataAdapter : public base::SupportsUserData::Data { + public: + static void Register(CefRefPtr browser) { + new WebContentsUserDataAdapter(browser); + } + + static CefRefPtr Get( + const content::WebContents* web_contents) { + WebContentsUserDataAdapter* adapter = + static_cast( + web_contents->GetUserData(UserDataKey())); + if (adapter) + return adapter->browser_; + return nullptr; + } + + private: + WebContentsUserDataAdapter(CefRefPtr browser) + : browser_(browser) { + auto web_contents = browser->GetWebContents(); + DCHECK(web_contents); + web_contents->SetUserData(UserDataKey(), base::WrapUnique(this)); + } + + static void* UserDataKey() { + // We just need a unique constant. Use the address of a static that + // COMDAT folding won't touch in an optimizing linker. + static int data_key = 0; + return reinterpret_cast(&data_key); + } + + CefRefPtr browser_; +}; + +} // namespace + +// static +CefRefPtr CefBrowserHostBase::GetBrowserForHost( + const content::RenderViewHost* host) { + DCHECK(host); + CEF_REQUIRE_UIT(); + content::WebContents* web_contents = content::WebContents::FromRenderViewHost( + const_cast(host)); + if (web_contents) + return GetBrowserForContents(web_contents); + return nullptr; +} + +// static +CefRefPtr CefBrowserHostBase::GetBrowserForHost( + const content::RenderFrameHost* host) { + DCHECK(host); + CEF_REQUIRE_UIT(); + content::WebContents* web_contents = + content::WebContents::FromRenderFrameHost( + const_cast(host)); + if (web_contents) + return GetBrowserForContents(web_contents); + return nullptr; +} + +// static +CefRefPtr CefBrowserHostBase::GetBrowserForContents( + const content::WebContents* contents) { + DCHECK(contents); + CEF_REQUIRE_UIT(); + return WebContentsUserDataAdapter::Get(contents); +} + +// static +CefRefPtr CefBrowserHostBase::GetBrowserForFrameTreeNode( + int frame_tree_node_id) { + // Use the thread-safe approach. + auto info = + CefBrowserInfoManager::GetInstance()->GetBrowserInfoForFrameTreeNode( + frame_tree_node_id); + if (info) { + auto browser = info->browser(); + if (!browser) { + LOG(WARNING) << "Found browser id " << info->browser_id() + << " but no browser object matching frame tree node id " + << frame_tree_node_id; + } + return browser; + } + + return nullptr; +} + +// static +CefRefPtr CefBrowserHostBase::GetBrowserForFrameRoute( + int render_process_id, + int render_routing_id) { + if (render_process_id == -1 || render_routing_id == MSG_ROUTING_NONE) + return nullptr; + + if (CEF_CURRENTLY_ON_UIT()) { + // Use the non-thread-safe but potentially faster approach. + content::RenderFrameHost* render_frame_host = + content::RenderFrameHost::FromID(render_process_id, render_routing_id); + if (!render_frame_host) + return nullptr; + return GetBrowserForHost(render_frame_host); + } else { + // Use the thread-safe approach. + bool is_guest_view = false; + auto info = + CefBrowserInfoManager::GetInstance()->GetBrowserInfoForFrameRoute( + render_process_id, render_routing_id, &is_guest_view); + if (info && !is_guest_view) { + auto browser = info->browser(); + if (!browser) { + LOG(WARNING) << "Found browser id " << info->browser_id() + << " but no browser object matching frame process id " + << render_process_id << " and routing id " + << render_routing_id; + } + return browser; + } + return nullptr; + } +} + +CefBrowserHostBase::CefBrowserHostBase( + const CefBrowserSettings& settings, + CefRefPtr client, + scoped_refptr browser_info, + CefRefPtr request_context) + : settings_(settings), + client_(client), + browser_info_(browser_info), + request_context_(request_context) { + CEF_REQUIRE_UIT(); + DCHECK(!browser_info_->browser().get()); + browser_info_->SetBrowser(this); + + contents_delegate_ = + std::make_unique(browser_info_); + contents_delegate_->AddObserver(this); +} + +void CefBrowserHostBase::InitializeBrowser() { + CEF_REQUIRE_UIT(); + + // Associate the WebContents with this browser object. + DCHECK(GetWebContents()); + WebContentsUserDataAdapter::Register(this); +} + +void CefBrowserHostBase::DestroyBrowser() { + CEF_REQUIRE_UIT(); + + contents_delegate_->RemoveObserver(this); + contents_delegate_->ObserveWebContents(nullptr); + + CefBrowserInfoManager::GetInstance()->RemoveBrowserInfo(browser_info_); + browser_info_->SetBrowser(nullptr); +} + +CefRefPtr CefBrowserHostBase::GetBrowser() { + return this; +} + +CefRefPtr CefBrowserHostBase::GetClient() { + return client_; +} + +CefRefPtr CefBrowserHostBase::GetRequestContext() { + return request_context_; +} + +void CefBrowserHostBase::StartDownload(const CefString& url) { + if (!CEF_CURRENTLY_ON_UIT()) { + CEF_POST_TASK( + CEF_UIT, base::BindOnce(&CefBrowserHostBase::StartDownload, this, url)); + return; + } + + GURL gurl = GURL(url.ToString()); + if (gurl.is_empty() || !gurl.is_valid()) + return; + + auto web_contents = GetWebContents(); + if (!web_contents) + return; + + auto browser_context = web_contents->GetBrowserContext(); + if (!browser_context) + return; + + content::DownloadManager* manager = + content::BrowserContext::GetDownloadManager(browser_context); + if (!manager) + return; + + std::unique_ptr params( + content::DownloadRequestUtils::CreateDownloadForWebContentsMainFrame( + web_contents, gurl, MISSING_TRAFFIC_ANNOTATION)); + manager->DownloadUrl(std::move(params)); +} + +void CefBrowserHostBase::DownloadImage( + const CefString& image_url, + bool is_favicon, + uint32 max_image_size, + bool bypass_cache, + CefRefPtr callback) { + if (!CEF_CURRENTLY_ON_UIT()) { + CEF_POST_TASK( + CEF_UIT, + base::BindOnce(&CefBrowserHostBase::DownloadImage, this, image_url, + is_favicon, max_image_size, bypass_cache, callback)); + return; + } + + if (!callback) + return; + + GURL gurl = GURL(image_url.ToString()); + if (gurl.is_empty() || !gurl.is_valid()) + return; + + auto web_contents = GetWebContents(); + if (!web_contents) + return; + + web_contents->DownloadImage( + gurl, is_favicon, max_image_size, + max_image_size * gfx::ImageSkia::GetMaxSupportedScale(), bypass_cache, + base::BindOnce( + [](uint32 max_image_size, + CefRefPtr callback, int id, + int http_status_code, const GURL& image_url, + const std::vector& bitmaps, + const std::vector& sizes) { + CEF_REQUIRE_UIT(); + + CefRefPtr image_impl; + + if (!bitmaps.empty()) { + image_impl = new CefImageImpl(); + image_impl->AddBitmaps(max_image_size, bitmaps); + } + + callback->OnDownloadImageFinished( + image_url.spec(), http_status_code, image_impl.get()); + }, + max_image_size, callback)); +} + +void CefBrowserHostBase::GetNavigationEntries( + CefRefPtr visitor, + bool current_only) { + DCHECK(visitor.get()); + if (!visitor.get()) + return; + + if (!CEF_CURRENTLY_ON_UIT()) { + CEF_POST_TASK( + CEF_UIT, base::BindOnce(&CefBrowserHostBase::GetNavigationEntries, this, + visitor, current_only)); + return; + } + + auto web_contents = GetWebContents(); + if (!web_contents) + return; + + content::NavigationController& controller = web_contents->GetController(); + const int total = controller.GetEntryCount(); + const int current = controller.GetCurrentEntryIndex(); + + if (current_only) { + // Visit only the current entry. + CefRefPtr entry = + new CefNavigationEntryImpl(controller.GetEntryAtIndex(current)); + visitor->Visit(entry.get(), true, current, total); + entry->Detach(nullptr); + } else { + // Visit all entries. + bool cont = true; + for (int i = 0; i < total && cont; ++i) { + CefRefPtr entry = + new CefNavigationEntryImpl(controller.GetEntryAtIndex(i)); + cont = visitor->Visit(entry.get(), (i == current), i, total); + entry->Detach(nullptr); + } + } +} + +CefRefPtr CefBrowserHostBase::GetVisibleNavigationEntry() { + if (!CEF_CURRENTLY_ON_UIT()) { + NOTREACHED() << "called on invalid thread"; + return nullptr; + } + + content::NavigationEntry* entry = nullptr; + auto web_contents = GetWebContents(); + if (web_contents) + entry = web_contents->GetController().GetVisibleEntry(); + + if (!entry) + return nullptr; + + return new CefNavigationEntryImpl(entry); +} + +void CefBrowserHostBase::ReplaceMisspelling(const CefString& word) { + if (!CEF_CURRENTLY_ON_UIT()) { + CEF_POST_TASK( + CEF_UIT, + base::BindOnce(&CefBrowserHostBase::ReplaceMisspelling, this, word)); + return; + } + + auto web_contents = GetWebContents(); + if (web_contents) + web_contents->ReplaceMisspelling(word); +} + +void CefBrowserHostBase::AddWordToDictionary(const CefString& word) { + if (!CEF_CURRENTLY_ON_UIT()) { + CEF_POST_TASK( + CEF_UIT, + base::BindOnce(&CefBrowserHostBase::AddWordToDictionary, this, word)); + return; + } + + auto web_contents = GetWebContents(); + if (!web_contents) + return; + + SpellcheckService* spellcheck = nullptr; + content::BrowserContext* browser_context = web_contents->GetBrowserContext(); + if (browser_context) { + spellcheck = SpellcheckServiceFactory::GetForContext(browser_context); + if (spellcheck) + spellcheck->GetCustomDictionary()->AddWord(word); + } +#if defined(OS_MAC) + if (spellcheck && spellcheck::UseBrowserSpellChecker()) { + spellcheck_platform::AddWord(spellcheck->platform_spell_checker(), word); + } +#endif +} + +CefRefPtr CefBrowserHostBase::GetHost() { + return this; +} + +bool CefBrowserHostBase::CanGoBack() { + base::AutoLock lock_scope(state_lock_); + return can_go_back_; +} + +bool CefBrowserHostBase::CanGoForward() { + base::AutoLock lock_scope(state_lock_); + return can_go_forward_; +} + +bool CefBrowserHostBase::IsLoading() { + base::AutoLock lock_scope(state_lock_); + return is_loading_; +} + +int CefBrowserHostBase::GetIdentifier() { + return browser_id(); +} + +bool CefBrowserHostBase::IsSame(CefRefPtr that) { + auto impl = static_cast(that.get()); + return (impl == this); +} + +bool CefBrowserHostBase::HasDocument() { + base::AutoLock lock_scope(state_lock_); + return has_document_; +} + +bool CefBrowserHostBase::IsPopup() { + return browser_info_->is_popup(); +} + +CefRefPtr CefBrowserHostBase::GetMainFrame() { + return GetFrame(CefFrameHostImpl::kMainFrameId); +} + +CefRefPtr CefBrowserHostBase::GetFocusedFrame() { + return GetFrame(CefFrameHostImpl::kFocusedFrameId); +} + +CefRefPtr CefBrowserHostBase::GetFrame(int64 identifier) { + if (identifier == CefFrameHostImpl::kInvalidFrameId) { + return nullptr; + } else if (identifier == CefFrameHostImpl::kMainFrameId) { + return browser_info_->GetMainFrame(); + } else if (identifier == CefFrameHostImpl::kFocusedFrameId) { + base::AutoLock lock_scope(state_lock_); + if (!focused_frame_) { + // The main frame is focused by default. + return browser_info_->GetMainFrame(); + } + return focused_frame_; + } + + return browser_info_->GetFrameForId(identifier); +} + +CefRefPtr CefBrowserHostBase::GetFrame(const CefString& name) { + for (const auto& frame : browser_info_->GetAllFrames()) { + if (frame->GetName() == name) + return frame; + } + return nullptr; +} + +size_t CefBrowserHostBase::GetFrameCount() { + return browser_info_->GetAllFrames().size(); +} + +void CefBrowserHostBase::GetFrameIdentifiers(std::vector& identifiers) { + if (identifiers.size() > 0) + identifiers.clear(); + + const auto frames = browser_info_->GetAllFrames(); + if (frames.empty()) + return; + + identifiers.reserve(frames.size()); + for (const auto& frame : frames) { + identifiers.push_back(frame->GetIdentifier()); + } +} + +void CefBrowserHostBase::GetFrameNames(std::vector& names) { + if (names.size() > 0) + names.clear(); + + const auto frames = browser_info_->GetAllFrames(); + if (frames.empty()) + return; + + names.reserve(frames.size()); + for (const auto& frame : frames) { + names.push_back(frame->GetName()); + } +} + +void CefBrowserHostBase::OnStateChanged(CefBrowserContentsState state_changed) { + // Make sure that CefBrowser state is consistent before the associated + // CefClient callback is executed. + base::AutoLock lock_scope(state_lock_); + if ((state_changed & CefBrowserContentsState::kNavigation) == + CefBrowserContentsState::kNavigation) { + is_loading_ = contents_delegate_->is_loading(); + can_go_back_ = contents_delegate_->can_go_back(); + can_go_forward_ = contents_delegate_->can_go_forward(); + } + if ((state_changed & CefBrowserContentsState::kDocument) == + CefBrowserContentsState::kDocument) { + has_document_ = contents_delegate_->has_document(); + } + if ((state_changed & CefBrowserContentsState::kFullscreen) == + CefBrowserContentsState::kFullscreen) { + is_fullscreen_ = contents_delegate_->is_fullscreen(); + } + if ((state_changed & CefBrowserContentsState::kFocusedFrame) == + CefBrowserContentsState::kFocusedFrame) { + focused_frame_ = contents_delegate_->focused_frame(); + } +} + +void CefBrowserHostBase::OnWebContentsDestroyed() {} + +CefRefPtr CefBrowserHostBase::GetFrameForHost( + const content::RenderFrameHost* host) { + CEF_REQUIRE_UIT(); + if (!host) + return nullptr; + + return browser_info_->GetFrameForHost(host); +} + +CefRefPtr CefBrowserHostBase::GetFrameForFrameTreeNode( + int frame_tree_node_id) { + return browser_info_->GetFrameForFrameTreeNode(frame_tree_node_id, nullptr); +} + +void CefBrowserHostBase::AddObserver(Observer* observer) { + CEF_REQUIRE_UIT(); + observers_.AddObserver(observer); +} + +void CefBrowserHostBase::RemoveObserver(Observer* observer) { + CEF_REQUIRE_UIT(); + observers_.RemoveObserver(observer); +} + +bool CefBrowserHostBase::HasObserver(Observer* observer) const { + CEF_REQUIRE_UIT(); + return observers_.HasObserver(observer); +} + +void CefBrowserHostBase::LoadMainFrameURL(const std::string& url, + const content::Referrer& referrer, + ui::PageTransition transition, + const std::string& extra_headers) { + auto callback = base::BindOnce(&CefBrowserHostBase::LoadMainFrameURL, this, + url, referrer, transition, extra_headers); + if (!CEF_CURRENTLY_ON_UIT()) { + CEF_POST_TASK(CEF_UIT, std::move(callback)); + return; + } + + if (browser_info_->IsNavigationLocked(std::move(callback))) { + return; + } + + auto web_contents = GetWebContents(); + if (web_contents) { + GURL gurl = GURL(url); + + if (!gurl.is_valid() && !gurl.has_scheme()) { + // Try to add "http://" at the beginning + std::string new_url = std::string("http://") + url; + gurl = GURL(new_url); + } + + if (!gurl.is_valid()) { + LOG(ERROR) + << "Invalid URL passed to CefBrowserHostImpl::LoadMainFrameURL: " + << url; + return; + } + + web_contents->GetController().LoadURL(gurl, referrer, transition, + extra_headers); + OnSetFocus(FOCUS_SOURCE_NAVIGATION); + } +} + +void CefBrowserHostBase::OnDidFinishLoad(CefRefPtr frame, + const GURL& validated_url, + int http_status_code) { + frame->RefreshAttributes(); + + // Give internal scheme handlers an opportunity to update content. + scheme::DidFinishLoad(frame, validated_url); + + contents_delegate_->OnLoadEnd(frame, validated_url, http_status_code); +} + +void CefBrowserHostBase::OnAfterCreated() { + CEF_REQUIRE_UIT(); + if (client_) { + if (auto handler = client_->GetLifeSpanHandler()) { + handler->OnAfterCreated(this); + } + } +} + +void CefBrowserHostBase::OnBeforeClose() { + CEF_REQUIRE_UIT(); + if (client_) { + if (auto handler = client_->GetLifeSpanHandler()) { + handler->OnBeforeClose(this); + } + } +} + +void CefBrowserHostBase::OnBrowserDestroyed() { + CEF_REQUIRE_UIT(); + for (auto& observer : observers_) + observer.OnBrowserDestroyed(this); +} + +int CefBrowserHostBase::browser_id() const { + return browser_info_->browser_id(); +} + +content::WebContents* CefBrowserHostBase::GetWebContents() const { + CEF_REQUIRE_UIT(); + return contents_delegate_->web_contents(); +} + +content::BrowserContext* CefBrowserHostBase::GetBrowserContext() const { + CEF_REQUIRE_UIT(); + auto web_contents = GetWebContents(); + if (web_contents) + return web_contents->GetBrowserContext(); + return nullptr; +} diff --git a/libcef/browser/browser_host_base.h b/libcef/browser/browser_host_base.h new file mode 100644 index 000000000..a26844bae --- /dev/null +++ b/libcef/browser/browser_host_base.h @@ -0,0 +1,240 @@ +// Copyright 2020 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. + +#ifndef CEF_LIBCEF_BROWSER_BROWSER_HOST_BASE_H_ +#define CEF_LIBCEF_BROWSER_BROWSER_HOST_BASE_H_ +#pragma once + +#include "include/cef_browser.h" +#include "include/cef_client.h" +#include "include/views/cef_browser_view.h" +#include "libcef/browser/browser_contents_delegate.h" +#include "libcef/browser/browser_info.h" +#include "libcef/browser/frame_host_impl.h" +#include "libcef/browser/request_context_impl.h" + +#include "base/observer_list.h" +#include "base/synchronization/lock.h" +#include "extensions/common/view_type.h" + +namespace extensions { +class Extension; +} + +// Base class for CefBrowserHost implementations. Includes functionality that is +// shared by the alloy and chrome runtimes. All methods are thread-safe unless +// otherwise indicated. +class CefBrowserHostBase : public CefBrowserHost, + public CefBrowser, + public CefBrowserContentsDelegate::Observer { + public: + // Parameters that are passed to the runtime-specific Create methods. + struct CreateParams { + CreateParams() {} + + // Copy constructor used with the chrome runtime only. + CreateParams(const CreateParams& that) { operator=(that); } + CreateParams& operator=(const CreateParams& that) { + // Not all parameters can be copied. + client = that.client; + url = that.url; + settings = that.settings; + request_context = that.request_context; + extra_info = that.extra_info; + return *this; + } + + // Platform-specific window creation info. Will be nullptr when creating a + // views-hosted browser. Currently used with the alloy runtime only. + std::unique_ptr window_info; + +#if defined(USE_AURA) + // The BrowserView that will own a views-hosted browser. Will be nullptr for + // popup browsers (the BrowserView will be created later in that case). + // Currently used with the alloy runtime only. + CefRefPtr browser_view; +#endif + + // Client implementation. May be nullptr. + CefRefPtr client; + + // Initial URL to load. May be empty. If this is a valid extension URL then + // the browser will be created as an app view extension host. + GURL url; + + // Browser settings. + CefBrowserSettings settings; + + // Other browser that opened this DevTools browser. Will be nullptr for non- + // DevTools browsers. Currently used with the alloy runtime only. + CefRefPtr devtools_opener; + + // Request context to use when creating the browser. If nullptr the global + // request context will be used. + CefRefPtr request_context; + + // Extra information that will be passed to + // CefRenderProcessHandler::OnBrowserCreated. + CefRefPtr extra_info; + + // Used when explicitly creating the browser as an extension host via + // ProcessManager::CreateBackgroundHost. Currently used with the alloy + // runtime only. + const extensions::Extension* extension = nullptr; + extensions::ViewType extension_host_type = extensions::VIEW_TYPE_INVALID; + }; + + // Interface to implement for observers that wish to be informed of changes + // to the CefBrowserHostBase. All methods will be called on the UI thread. + class Observer : public base::CheckedObserver { + public: + // Called before |browser| is destroyed. Any references to |browser| should + // be cleared when this method is called. + virtual void OnBrowserDestroyed(CefBrowserHostBase* browser) = 0; + + protected: + virtual ~Observer() {} + }; + + // Returns the browser associated with the specified RenderViewHost. + static CefRefPtr GetBrowserForHost( + const content::RenderViewHost* host); + // Returns the browser associated with the specified RenderFrameHost. + static CefRefPtr GetBrowserForHost( + const content::RenderFrameHost* host); + // Returns the browser associated with the specified WebContents. + static CefRefPtr GetBrowserForContents( + const content::WebContents* contents); + // Returns the browser associated with the specified FrameTreeNode ID. + static CefRefPtr GetBrowserForFrameTreeNode( + int frame_tree_node_id); + // Returns the browser associated with the specified frame routing IDs. + static CefRefPtr GetBrowserForFrameRoute( + int render_process_id, + int render_routing_id); + + CefBrowserHostBase(const CefBrowserSettings& settings, + CefRefPtr client, + scoped_refptr browser_info, + CefRefPtr request_context); + + // Called on the UI thread after the associated WebContents is created. + virtual void InitializeBrowser(); + + // Called on the UI thread after the associated WebContents is destroyed. + // Also called from CefBrowserInfoManager::DestroyAllBrowsers if the browser + // was not properly shut down. + virtual void DestroyBrowser(); + + // CefBrowserHost methods: + CefRefPtr GetBrowser() override; + CefRefPtr GetClient() override; + CefRefPtr GetRequestContext() override; + void StartDownload(const CefString& url) override; + void DownloadImage(const CefString& image_url, + bool is_favicon, + uint32 max_image_size, + bool bypass_cache, + CefRefPtr callback) override; + void ReplaceMisspelling(const CefString& word) override; + void AddWordToDictionary(const CefString& word) override; + void GetNavigationEntries(CefRefPtr visitor, + bool current_only) override; + CefRefPtr GetVisibleNavigationEntry() override; + + // CefBrowser methods: + CefRefPtr GetHost() override; + bool CanGoBack() override; + bool CanGoForward() override; + bool IsLoading() override; + int GetIdentifier() override; + bool IsSame(CefRefPtr that) override; + bool HasDocument() override; + bool IsPopup() override; + CefRefPtr GetMainFrame() override; + CefRefPtr GetFocusedFrame() override; + CefRefPtr GetFrame(int64 identifier) override; + CefRefPtr GetFrame(const CefString& name) override; + size_t GetFrameCount() override; + void GetFrameIdentifiers(std::vector& identifiers) override; + void GetFrameNames(std::vector& names) override; + + // CefBrowserContentsDelegate::Observer methods: + void OnStateChanged(CefBrowserContentsState state_changed) override; + void OnWebContentsDestroyed() override; + + // Returns the frame associated with the specified RenderFrameHost. + CefRefPtr GetFrameForHost(const content::RenderFrameHost* host); + + // Returns the frame associated with the specified FrameTreeNode ID. + CefRefPtr GetFrameForFrameTreeNode(int frame_tree_node_id); + + // Manage observer objects. The observer must either outlive this object or + // be removed before destruction. Must be called on the UI thread. + void AddObserver(Observer* observer); + void RemoveObserver(Observer* observer); + bool HasObserver(Observer* observer) const; + + // Methods called from CefFrameHostImpl. + void LoadMainFrameURL(const std::string& url, + const content::Referrer& referrer, + ui::PageTransition transition, + const std::string& extra_headers); + void OnDidFinishLoad(CefRefPtr frame, + const GURL& validated_url, + int http_status_code); + virtual void OnSetFocus(cef_focus_source_t source) = 0; + virtual void ViewText(const std::string& text) = 0; + + // Helpers for executing client callbacks. Must be called on the UI thread. + void OnAfterCreated(); + void OnBeforeClose(); + void OnBrowserDestroyed(); + + // Thread-safe accessors. + const CefBrowserSettings& settings() const { return settings_; } + CefRefPtr client() const { return client_; } + scoped_refptr browser_info() const { return browser_info_; } + int browser_id() const; + CefRefPtr request_context() const { + return request_context_; + } + + // Accessors that must be called on the UI thread. + content::WebContents* GetWebContents() const; + content::BrowserContext* GetBrowserContext() const; + CefBrowserContentsDelegate* contents_delegate() const { + return contents_delegate_.get(); + } + + protected: + // Thread-safe members. + CefBrowserSettings settings_; + CefRefPtr client_; + scoped_refptr browser_info_; + CefRefPtr request_context_; + + // Only accessed on the UI thread. + std::unique_ptr contents_delegate_; + + // Observers that want to be notified of changes to this object. + // Only accessed on the UI thread. + base::ObserverList observers_; + + // Volatile state accessed from multiple threads. All access must be protected + // by |state_lock_|. + base::Lock state_lock_; + bool is_loading_ = false; + bool can_go_back_ = false; + bool can_go_forward_ = false; + bool has_document_ = false; + bool is_fullscreen_ = false; + CefRefPtr focused_frame_; + + private: + IMPLEMENT_REFCOUNTING(CefBrowserHostBase); + DISALLOW_COPY_AND_ASSIGN(CefBrowserHostBase); +}; + +#endif // CEF_LIBCEF_BROWSER_BROWSER_HOST_BASE_H_ diff --git a/libcef/browser/browser_host_create.cc b/libcef/browser/browser_host_create.cc new file mode 100644 index 000000000..980aa149c --- /dev/null +++ b/libcef/browser/browser_host_create.cc @@ -0,0 +1,144 @@ +// 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 "include/cef_browser.h" +#include "libcef/browser/browser_host_impl.h" +#include "libcef/browser/chrome/chrome_browser_host_impl.h" +#include "libcef/browser/context.h" +#include "libcef/browser/thread_util.h" +#include "libcef/features/runtime.h" + +namespace { + +class CreateBrowserHelper { + public: + CreateBrowserHelper(const CefWindowInfo& windowInfo, + CefRefPtr client, + const CefString& url, + const CefBrowserSettings& settings, + CefRefPtr extra_info, + CefRefPtr request_context) + : window_info_(windowInfo), + client_(client), + url_(url), + settings_(settings), + extra_info_(extra_info), + request_context_(request_context) {} + + CefWindowInfo window_info_; + CefRefPtr client_; + CefString url_; + CefBrowserSettings settings_; + CefRefPtr extra_info_; + CefRefPtr request_context_; +}; + +} // namespace + +// static +bool CefBrowserHost::CreateBrowser( + const CefWindowInfo& windowInfo, + CefRefPtr client, + const CefString& url, + const CefBrowserSettings& settings, + CefRefPtr extra_info, + CefRefPtr request_context) { + // Verify that the context is in a valid state. + if (!CONTEXT_STATE_VALID()) { + NOTREACHED() << "context not valid"; + return false; + } + + // Verify that the settings structure is a valid size. + if (settings.size != sizeof(cef_browser_settings_t)) { + NOTREACHED() << "invalid CefBrowserSettings structure size"; + return false; + } + + // Verify windowless rendering requirements. + if (windowInfo.windowless_rendering_enabled && + !client->GetRenderHandler().get()) { + NOTREACHED() << "CefRenderHandler implementation is required"; + return false; + } + + if (windowInfo.windowless_rendering_enabled && + !CefContext::Get()->settings().windowless_rendering_enabled) { + LOG(ERROR) << "Creating a windowless browser without setting " + "CefSettings.windowless_rendering_enabled may result in " + "reduced performance or runtime errors."; + } + + // Create the browser on the UI thread. + CreateBrowserHelper* helper = new CreateBrowserHelper( + windowInfo, client, url, settings, extra_info, request_context); + CEF_POST_TASK(CEF_UIT, base::BindOnce( + [](CreateBrowserHelper* helper) { + CefBrowserHost::CreateBrowserSync( + helper->window_info_, helper->client_, + helper->url_, helper->settings_, + helper->extra_info_, + helper->request_context_); + delete helper; + }, + helper)); + + return true; +} + +// static +CefRefPtr CefBrowserHost::CreateBrowserSync( + const CefWindowInfo& windowInfo, + CefRefPtr client, + const CefString& url, + const CefBrowserSettings& settings, + CefRefPtr extra_info, + CefRefPtr request_context) { + // Verify that the context is in a valid state. + if (!CONTEXT_STATE_VALID()) { + NOTREACHED() << "context not valid"; + return nullptr; + } + + // Verify that the settings structure is a valid size. + if (settings.size != sizeof(cef_browser_settings_t)) { + NOTREACHED() << "invalid CefBrowserSettings structure size"; + return nullptr; + } + + // Verify that this method is being called on the UI thread. + if (!CEF_CURRENTLY_ON_UIT()) { + NOTREACHED() << "called on invalid thread"; + return nullptr; + } + + // Verify windowless rendering requirements. + if (windowInfo.windowless_rendering_enabled && + !client->GetRenderHandler().get()) { + NOTREACHED() << "CefRenderHandler implementation is required"; + return nullptr; + } + + CefBrowserHostBase::CreateParams create_params; + create_params.window_info.reset(new CefWindowInfo(windowInfo)); + create_params.client = client; + create_params.url = GURL(url.ToString()); + if (!url.empty() && !create_params.url.is_valid() && + !create_params.url.has_scheme()) { + std::string new_url = std::string("http://") + url.ToString(); + create_params.url = GURL(new_url); + } + create_params.settings = settings; + create_params.extra_info = extra_info; + create_params.request_context = request_context; + + if (cef::IsChromeRuntimeEnabled()) { + auto browser = ChromeBrowserHostImpl::Create(create_params); + return browser.get(); + } + + auto browser = CefBrowserHostImpl::Create(create_params); + return browser.get(); +} diff --git a/libcef/browser/browser_host_impl.cc b/libcef/browser/browser_host_impl.cc index de92afa46..6db0dc6d5 100644 --- a/libcef/browser/browser_host_impl.cc +++ b/libcef/browser/browser_host_impl.cc @@ -8,6 +8,7 @@ #include #include +#include "libcef/browser/alloy/alloy_browser_context.h" #include "libcef/browser/audio_capturer.h" #include "libcef/browser/browser_context.h" #include "libcef/browser/browser_info.h" @@ -16,10 +17,7 @@ #include "libcef/browser/browser_util.h" #include "libcef/browser/context.h" #include "libcef/browser/devtools/devtools_manager.h" -#include "libcef/browser/image_impl.h" #include "libcef/browser/media_capture_devices_dispatcher.h" -#include "libcef/browser/navigation_entry_impl.h" -#include "libcef/browser/net/scheme_handler.h" #include "libcef/browser/osr/osr_util.h" #include "libcef/browser/request_context_impl.h" #include "libcef/browser/thread_util.h" @@ -28,27 +26,21 @@ #include "libcef/common/drag_data_impl.h" #include "libcef/common/request_impl.h" #include "libcef/common/values_impl.h" +#include "libcef/features/runtime_checks.h" #include "base/bind.h" #include "base/bind_helpers.h" #include "base/command_line.h" #include "chrome/browser/picture_in_picture/picture_in_picture_window_manager.h" -#include "chrome/browser/spellchecker/spellcheck_factory.h" -#include "chrome/browser/spellchecker/spellcheck_service.h" -#include "components/favicon/core/favicon_url.h" -#include "components/spellcheck/common/spellcheck_features.h" #include "content/browser/gpu/compositor_util.h" #include "content/browser/renderer_host/render_widget_host_impl.h" #include "content/common/widget_messages.h" #include "content/public/browser/desktop_media_id.h" -#include "content/public/browser/download_manager.h" -#include "content/public/browser/download_request_utils.h" #include "content/public/browser/file_select_listener.h" #include "content/public/browser/host_zoom_map.h" #include "content/public/browser/keyboard_event_processing_result.h" #include "content/public/browser/native_web_keyboard_event.h" #include "content/public/browser/navigation_controller.h" -#include "content/public/browser/navigation_entry.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/notification_details.h" #include "content/public/browser/notification_source.h" @@ -63,78 +55,11 @@ #include "net/base/net_errors.h" #include "third_party/blink/public/mojom/page/widget.mojom-test-utils.h" #include "ui/events/base_event_utils.h" -#include "ui/gfx/image/image_skia.h" - -#if defined(OS_MAC) -#include "components/spellcheck/browser/spellcheck_platform.h" -#endif using content::KeyboardEventProcessingResult; namespace { -// Associates a CefBrowserHostImpl instance with a WebContents. This object will -// be deleted automatically when the WebContents is destroyed. -class WebContentsUserDataAdapter : public base::SupportsUserData::Data { - public: - static void Register(CefBrowserHostImpl* browser) { - new WebContentsUserDataAdapter(browser); - } - - static CefBrowserHostImpl* Get(const content::WebContents* web_contents) { - WebContentsUserDataAdapter* adapter = - static_cast( - web_contents->GetUserData(UserDataKey())); - if (adapter) - return adapter->browser_; - return nullptr; - } - - private: - WebContentsUserDataAdapter(CefBrowserHostImpl* browser) : browser_(browser) { - browser->web_contents()->SetUserData(UserDataKey(), base::WrapUnique(this)); - } - - static void* UserDataKey() { - // We just need a unique constant. Use the address of a static that - // COMDAT folding won't touch in an optimizing linker. - static int data_key = 0; - return reinterpret_cast(&data_key); - } - - CefBrowserHostImpl* browser_; // Not owned. -}; - -class CreateBrowserHelper { - public: - CreateBrowserHelper(const CefWindowInfo& windowInfo, - CefRefPtr client, - const CefString& url, - const CefBrowserSettings& settings, - CefRefPtr extra_info, - CefRefPtr request_context) - : window_info_(windowInfo), - client_(client), - url_(url), - settings_(settings), - extra_info_(extra_info), - request_context_(request_context) {} - - CefWindowInfo window_info_; - CefRefPtr client_; - CefString url_; - CefBrowserSettings settings_; - CefRefPtr extra_info_; - CefRefPtr request_context_; -}; - -void CreateBrowserWithHelper(CreateBrowserHelper* helper) { - CefBrowserHost::CreateBrowserSync( - helper->window_info_, helper->client_, helper->url_, helper->settings_, - helper->extra_info_, helper->request_context_); - delete helper; -} - class ShowDevToolsHelper { public: ShowDevToolsHelper(CefRefPtr browser, @@ -162,27 +87,6 @@ void ShowDevToolsWithHelper(ShowDevToolsHelper* helper) { delete helper; } -// Callback from CefBrowserHostImpl::DownloadImage. -void OnDownloadImage(uint32 max_image_size, - CefRefPtr callback, - int id, - int http_status_code, - const GURL& image_url, - const std::vector& bitmaps, - const std::vector& sizes) { - CEF_REQUIRE_UIT(); - - CefRefPtr image_impl; - - if (!bitmaps.empty()) { - image_impl = new CefImageImpl(); - image_impl->AddBitmaps(max_image_size, bitmaps); - } - - callback->OnDownloadImageFinished(image_url.spec(), http_status_code, - image_impl.get()); -} - class CefWidgetHostInterceptor : public blink::mojom::WidgetHostInterceptorForTesting, public content::RenderWidgetHostObserver { @@ -228,102 +132,6 @@ static constexpr base::TimeDelta kRecentlyAudibleTimeout = } // namespace -// CefBrowserHost static methods. -// ----------------------------------------------------------------------------- - -// static -bool CefBrowserHost::CreateBrowser( - const CefWindowInfo& windowInfo, - CefRefPtr client, - const CefString& url, - const CefBrowserSettings& settings, - CefRefPtr extra_info, - CefRefPtr request_context) { - // Verify that the context is in a valid state. - if (!CONTEXT_STATE_VALID()) { - NOTREACHED() << "context not valid"; - return false; - } - - // Verify that the settings structure is a valid size. - if (settings.size != sizeof(cef_browser_settings_t)) { - NOTREACHED() << "invalid CefBrowserSettings structure size"; - return false; - } - - // Verify windowless rendering requirements. - if (windowInfo.windowless_rendering_enabled && - !client->GetRenderHandler().get()) { - NOTREACHED() << "CefRenderHandler implementation is required"; - return false; - } - - if (windowInfo.windowless_rendering_enabled && - !CefContext::Get()->settings().windowless_rendering_enabled) { - LOG(ERROR) << "Creating a windowless browser without setting " - "CefSettings.windowless_rendering_enabled may result in " - "reduced performance or runtime errors."; - } - - // Create the browser on the UI thread. - CreateBrowserHelper* helper = new CreateBrowserHelper( - windowInfo, client, url, settings, extra_info, request_context); - CEF_POST_TASK(CEF_UIT, base::BindOnce(CreateBrowserWithHelper, helper)); - - return true; -} - -// static -CefRefPtr CefBrowserHost::CreateBrowserSync( - const CefWindowInfo& windowInfo, - CefRefPtr client, - const CefString& url, - const CefBrowserSettings& settings, - CefRefPtr extra_info, - CefRefPtr request_context) { - // Verify that the context is in a valid state. - if (!CONTEXT_STATE_VALID()) { - NOTREACHED() << "context not valid"; - return nullptr; - } - - // Verify that the settings structure is a valid size. - if (settings.size != sizeof(cef_browser_settings_t)) { - NOTREACHED() << "invalid CefBrowserSettings structure size"; - return nullptr; - } - - // Verify that this method is being called on the UI thread. - if (!CEF_CURRENTLY_ON_UIT()) { - NOTREACHED() << "called on invalid thread"; - return nullptr; - } - - // Verify windowless rendering requirements. - if (windowInfo.windowless_rendering_enabled && - !client->GetRenderHandler().get()) { - NOTREACHED() << "CefRenderHandler implementation is required"; - return nullptr; - } - - CefBrowserHostImpl::CreateParams create_params; - create_params.window_info.reset(new CefWindowInfo(windowInfo)); - create_params.client = client; - create_params.url = GURL(url.ToString()); - if (!url.empty() && !create_params.url.is_valid() && - !create_params.url.has_scheme()) { - std::string new_url = std::string("http://") + url.ToString(); - create_params.url = GURL(new_url); - } - create_params.settings = settings; - create_params.extra_info = extra_info; - create_params.request_context = request_context; - - CefRefPtr browser = - CefBrowserHostImpl::Create(create_params); - return browser.get(); -} - // CefBrowserHostImpl static methods. // ----------------------------------------------------------------------------- @@ -362,8 +170,10 @@ CefRefPtr CefBrowserHostImpl::Create( CefRefPtr browser = CreateInternal( create_params.settings, create_params.client, web_contents, - own_web_contents, info, create_params.devtools_opener, is_devtools_popup, - request_context_impl, std::move(platform_delegate), cef_extension); + own_web_contents, info, + static_cast(create_params.devtools_opener.get()), + is_devtools_popup, request_context_impl, std::move(platform_delegate), + cef_extension); if (!browser) return nullptr; @@ -422,6 +232,8 @@ CefRefPtr CefBrowserHostImpl::CreateInternal( CefRefPtr browser = new CefBrowserHostImpl( settings, client, web_contents, browser_info, opener, request_context, std::move(platform_delegate), extension); + browser->InitializeBrowser(); + if (!browser->CreateHostWindow()) return nullptr; @@ -430,11 +242,7 @@ CefRefPtr CefBrowserHostImpl::CreateInternal( // 1. Notify the browser's LifeSpanHandler. This must always be the first // notification for the browser. - if (client.get()) { - CefRefPtr handler = client->GetLifeSpanHandler(); - if (handler.get()) - handler->OnAfterCreated(browser.get()); - } + browser->OnAfterCreated(); // 2. Notify the platform delegate. With Views this will result in a call to // CefBrowserViewDelegate::OnBrowserCreated(). @@ -453,88 +261,44 @@ CefRefPtr CefBrowserHostImpl::CreateInternal( // static CefRefPtr CefBrowserHostImpl::GetBrowserForHost( const content::RenderViewHost* host) { - DCHECK(host); - CEF_REQUIRE_UIT(); - content::WebContents* web_contents = content::WebContents::FromRenderViewHost( - const_cast(host)); - if (web_contents) - return GetBrowserForContents(web_contents); - return nullptr; + REQUIRE_ALLOY_RUNTIME(); + auto browser = CefBrowserHostBase::GetBrowserForHost(host); + return static_cast(browser.get()); } // static CefRefPtr CefBrowserHostImpl::GetBrowserForHost( const content::RenderFrameHost* host) { - DCHECK(host); - CEF_REQUIRE_UIT(); - content::WebContents* web_contents = - content::WebContents::FromRenderFrameHost( - const_cast(host)); - if (web_contents) - return GetBrowserForContents(web_contents); - return nullptr; + REQUIRE_ALLOY_RUNTIME(); + auto browser = CefBrowserHostBase::GetBrowserForHost(host); + return static_cast(browser.get()); } // static CefRefPtr CefBrowserHostImpl::GetBrowserForContents( const content::WebContents* contents) { - DCHECK(contents); - CEF_REQUIRE_UIT(); - return WebContentsUserDataAdapter::Get(contents); + REQUIRE_ALLOY_RUNTIME(); + auto browser = CefBrowserHostBase::GetBrowserForContents(contents); + return static_cast(browser.get()); } // static CefRefPtr CefBrowserHostImpl::GetBrowserForFrameTreeNode( int frame_tree_node_id) { - // Use the thread-safe approach. - scoped_refptr info = - CefBrowserInfoManager::GetInstance()->GetBrowserInfoForFrameTreeNode( - frame_tree_node_id); - if (info.get()) { - CefRefPtr browser = info->browser(); - if (!browser.get()) { - LOG(WARNING) << "Found browser id " << info->browser_id() - << " but no browser object matching frame tree node id " - << frame_tree_node_id; - } - return browser; - } - - return nullptr; + REQUIRE_ALLOY_RUNTIME(); + auto browser = + CefBrowserHostBase::GetBrowserForFrameTreeNode(frame_tree_node_id); + return static_cast(browser.get()); } // static CefRefPtr CefBrowserHostImpl::GetBrowserForFrameRoute( int render_process_id, int render_routing_id) { - if (render_process_id == -1 || render_routing_id == MSG_ROUTING_NONE) - return nullptr; - - if (CEF_CURRENTLY_ON_UIT()) { - // Use the non-thread-safe but potentially faster approach. - content::RenderFrameHost* render_frame_host = - content::RenderFrameHost::FromID(render_process_id, render_routing_id); - if (!render_frame_host) - return nullptr; - return GetBrowserForHost(render_frame_host); - } else { - // Use the thread-safe approach. - bool is_guest_view = false; - scoped_refptr info = - CefBrowserInfoManager::GetInstance()->GetBrowserInfoForFrameRoute( - render_process_id, render_routing_id, &is_guest_view); - if (info.get() && !is_guest_view) { - CefRefPtr browser = info->browser(); - if (!browser.get()) { - LOG(WARNING) << "Found browser id " << info->browser_id() - << " but no browser object matching frame process id " - << render_process_id << " and routing id " - << render_routing_id; - } - return browser; - } - return nullptr; - } + REQUIRE_ALLOY_RUNTIME(); + auto browser = CefBrowserHostBase::GetBrowserForFrameRoute(render_process_id, + render_routing_id); + return static_cast(browser.get()); } // CefBrowserHostImpl methods. @@ -542,10 +306,6 @@ CefRefPtr CefBrowserHostImpl::GetBrowserForFrameRoute( CefBrowserHostImpl::~CefBrowserHostImpl() {} -CefRefPtr CefBrowserHostImpl::GetBrowser() { - return this; -} - void CefBrowserHostImpl::CloseBrowser(bool force_close) { if (CEF_CURRENTLY_ON_UIT()) { // Exit early if a close attempt is already pending and this method is @@ -630,14 +390,6 @@ bool CefBrowserHostImpl::HasView() { return IsViewsHosted(); } -CefRefPtr CefBrowserHostImpl::GetClient() { - return client_; -} - -CefRefPtr CefBrowserHostImpl::GetRequestContext() { - return request_context_; -} - double CefBrowserHostImpl::GetZoomLevel() { // Verify that this method is being called on the UI thread. if (!CEF_CURRENTLY_ON_UIT()) { @@ -682,65 +434,6 @@ void CefBrowserHostImpl::RunFileDialog( callback); } -void CefBrowserHostImpl::StartDownload(const CefString& url) { - if (!CEF_CURRENTLY_ON_UIT()) { - CEF_POST_TASK( - CEF_UIT, base::BindOnce(&CefBrowserHostImpl::StartDownload, this, url)); - return; - } - - GURL gurl = GURL(url.ToString()); - if (gurl.is_empty() || !gurl.is_valid()) - return; - - if (!web_contents()) - return; - - auto browser_context = web_contents()->GetBrowserContext(); - if (!browser_context) - return; - - content::DownloadManager* manager = - content::BrowserContext::GetDownloadManager(browser_context); - if (!manager) - return; - - std::unique_ptr params( - content::DownloadRequestUtils::CreateDownloadForWebContentsMainFrame( - web_contents(), gurl, MISSING_TRAFFIC_ANNOTATION)); - manager->DownloadUrl(std::move(params)); -} - -void CefBrowserHostImpl::DownloadImage( - const CefString& image_url, - bool is_favicon, - uint32 max_image_size, - bool bypass_cache, - CefRefPtr callback) { - if (!CEF_CURRENTLY_ON_UIT()) { - CEF_POST_TASK( - CEF_UIT, - base::BindOnce(&CefBrowserHostImpl::DownloadImage, this, image_url, - is_favicon, max_image_size, bypass_cache, callback)); - return; - } - - if (!callback) - return; - - GURL gurl = GURL(image_url.ToString()); - if (gurl.is_empty() || !gurl.is_valid()) - return; - - if (!web_contents()) - return; - - web_contents()->DownloadImage( - gurl, is_favicon, max_image_size, - max_image_size * gfx::ImageSkia::GetMaxSupportedScale(), bypass_cache, - base::BindOnce(OnDownloadImage, max_image_size, callback)); -} - void CefBrowserHostImpl::Print() { if (!CEF_CURRENTLY_ON_UIT()) { CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefBrowserHostImpl::Print, this)); @@ -909,61 +602,6 @@ void CefBrowserHostImpl::InitializeDevToolsRegistrationOnUIThread( devtools_manager_->InitializeRegistrationOnUIThread(registration); } -void CefBrowserHostImpl::GetNavigationEntries( - CefRefPtr visitor, - bool current_only) { - DCHECK(visitor.get()); - if (!visitor.get()) - return; - - if (!CEF_CURRENTLY_ON_UIT()) { - CEF_POST_TASK( - CEF_UIT, base::BindOnce(&CefBrowserHostImpl::GetNavigationEntries, this, - visitor, current_only)); - return; - } - - if (!web_contents()) - return; - - content::NavigationController& controller = web_contents()->GetController(); - const int total = controller.GetEntryCount(); - const int current = controller.GetCurrentEntryIndex(); - - if (current_only) { - // Visit only the current entry. - CefRefPtr entry = - new CefNavigationEntryImpl(controller.GetEntryAtIndex(current)); - visitor->Visit(entry.get(), true, current, total); - entry->Detach(nullptr); - } else { - // Visit all entries. - bool cont = true; - for (int i = 0; i < total && cont; ++i) { - CefRefPtr entry = - new CefNavigationEntryImpl(controller.GetEntryAtIndex(i)); - cont = visitor->Visit(entry.get(), (i == current), i, total); - entry->Detach(nullptr); - } - } -} - -CefRefPtr CefBrowserHostImpl::GetVisibleNavigationEntry() { - if (!CEF_CURRENTLY_ON_UIT()) { - NOTREACHED() << "called on invalid thread"; - return nullptr; - } - - content::NavigationEntry* entry = nullptr; - if (web_contents()) - entry = web_contents()->GetController().GetVisibleEntry(); - - if (!entry) - return nullptr; - - return new CefNavigationEntryImpl(entry); -} - void CefBrowserHostImpl::SetAccessibilityState( cef_state_t accessibility_state) { if (!CEF_CURRENTLY_ON_UIT()) { @@ -1017,44 +655,6 @@ bool CefBrowserHostImpl::IsWindowRenderingDisabled() { return IsWindowless(); } -void CefBrowserHostImpl::ReplaceMisspelling(const CefString& word) { - if (!CEF_CURRENTLY_ON_UIT()) { - CEF_POST_TASK( - CEF_UIT, - base::BindOnce(&CefBrowserHostImpl::ReplaceMisspelling, this, word)); - return; - } - - if (web_contents()) - web_contents()->ReplaceMisspelling(word); -} - -void CefBrowserHostImpl::AddWordToDictionary(const CefString& word) { - if (!CEF_CURRENTLY_ON_UIT()) { - CEF_POST_TASK( - CEF_UIT, - base::BindOnce(&CefBrowserHostImpl::AddWordToDictionary, this, word)); - return; - } - - if (!web_contents()) - return; - - SpellcheckService* spellcheck = nullptr; - content::BrowserContext* browser_context = - web_contents()->GetBrowserContext(); - if (browser_context) { - spellcheck = SpellcheckServiceFactory::GetForContext(browser_context); - if (spellcheck) - spellcheck->GetCustomDictionary()->AddWord(word); - } -#if defined(OS_MAC) - if (spellcheck && spellcheck::UseBrowserSpellChecker()) { - spellcheck_platform::AddWord(spellcheck->platform_spell_checker(), word); - } -#endif -} - void CefBrowserHostImpl::WasResized() { if (!CEF_CURRENTLY_ON_UIT()) { CEF_POST_TASK(CEF_UIT, @@ -1265,189 +865,83 @@ void CefBrowserHostImpl::SetWindowlessFrameRate(int frame_rate) { // CefBrowser methods. // ----------------------------------------------------------------------------- -CefRefPtr CefBrowserHostImpl::GetHost() { - return this; -} - -bool CefBrowserHostImpl::CanGoBack() { - base::AutoLock lock_scope(state_lock_); - return can_go_back_; -} - void CefBrowserHostImpl::GoBack() { - if (CEF_CURRENTLY_ON_UIT()) { - if (navigation_locked()) { - // Try again after the lock has been released. - set_pending_navigation_action( - base::BindOnce(&CefBrowserHostImpl::GoBack, this)); - return; - } - - if (web_contents() && web_contents()->GetController().CanGoBack()) - web_contents()->GetController().GoBack(); - } else { - CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefBrowserHostImpl::GoBack, this)); + auto callback = base::BindOnce(&CefBrowserHostImpl::GoBack, this); + if (!CEF_CURRENTLY_ON_UIT()) { + CEF_POST_TASK(CEF_UIT, std::move(callback)); } -} -bool CefBrowserHostImpl::CanGoForward() { - base::AutoLock lock_scope(state_lock_); - return can_go_forward_; + if (browser_info_->IsNavigationLocked(std::move(callback))) { + return; + } + + auto wc = web_contents(); + if (wc && wc->GetController().CanGoBack()) { + wc->GetController().GoBack(); + } } void CefBrowserHostImpl::GoForward() { - if (CEF_CURRENTLY_ON_UIT()) { - if (navigation_locked()) { - // Try again after the lock has been released. - set_pending_navigation_action( - base::BindOnce(&CefBrowserHostImpl::GoForward, this)); - return; - } + auto callback = base::BindOnce(&CefBrowserHostImpl::GoForward, this); + if (!CEF_CURRENTLY_ON_UIT()) { + CEF_POST_TASK(CEF_UIT, std::move(callback)); + } - if (web_contents() && web_contents()->GetController().CanGoForward()) - web_contents()->GetController().GoForward(); - } else { - CEF_POST_TASK(CEF_UIT, - base::BindOnce(&CefBrowserHostImpl::GoForward, this)); + if (browser_info_->IsNavigationLocked(std::move(callback))) { + return; + } + + auto wc = web_contents(); + if (wc && wc->GetController().CanGoForward()) { + wc->GetController().GoForward(); } } -bool CefBrowserHostImpl::IsLoading() { - base::AutoLock lock_scope(state_lock_); - return is_loading_; -} - void CefBrowserHostImpl::Reload() { - if (CEF_CURRENTLY_ON_UIT()) { - if (navigation_locked()) { - // Try again after the lock has been released. - set_pending_navigation_action( - base::BindOnce(&CefBrowserHostImpl::Reload, this)); - return; - } + auto callback = base::BindOnce(&CefBrowserHostImpl::Reload, this); + if (!CEF_CURRENTLY_ON_UIT()) { + CEF_POST_TASK(CEF_UIT, std::move(callback)); + } - if (web_contents()) - web_contents()->GetController().Reload(content::ReloadType::NORMAL, true); - } else { - CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefBrowserHostImpl::Reload, this)); + if (browser_info_->IsNavigationLocked(std::move(callback))) { + return; + } + + auto wc = web_contents(); + if (wc) { + wc->GetController().Reload(content::ReloadType::NORMAL, true); } } void CefBrowserHostImpl::ReloadIgnoreCache() { - if (CEF_CURRENTLY_ON_UIT()) { - if (navigation_locked()) { - // Try again after the lock has been released. - set_pending_navigation_action( - base::BindOnce(&CefBrowserHostImpl::ReloadIgnoreCache, this)); - return; - } + auto callback = base::BindOnce(&CefBrowserHostImpl::ReloadIgnoreCache, this); + if (!CEF_CURRENTLY_ON_UIT()) { + CEF_POST_TASK(CEF_UIT, std::move(callback)); + } - if (web_contents()) { - web_contents()->GetController().Reload( - content::ReloadType::BYPASSING_CACHE, true); - } - } else { - CEF_POST_TASK(CEF_UIT, - base::BindOnce(&CefBrowserHostImpl::ReloadIgnoreCache, this)); + if (browser_info_->IsNavigationLocked(std::move(callback))) { + return; + } + + auto wc = web_contents(); + if (wc) { + wc->GetController().Reload(content::ReloadType::BYPASSING_CACHE, true); } } void CefBrowserHostImpl::StopLoad() { - if (CEF_CURRENTLY_ON_UIT()) { - if (navigation_locked()) { - // Try again after the lock has been released. - set_pending_navigation_action( - base::BindOnce(&CefBrowserHostImpl::StopLoad, this)); - return; - } - - if (web_contents()) - web_contents()->Stop(); - } else { - CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefBrowserHostImpl::StopLoad, this)); - } -} - -int CefBrowserHostImpl::GetIdentifier() { - return browser_id(); -} - -bool CefBrowserHostImpl::IsSame(CefRefPtr that) { - CefBrowserHostImpl* impl = static_cast(that.get()); - return (impl == this); -} - -bool CefBrowserHostImpl::IsPopup() { - return browser_info_->is_popup(); -} - -bool CefBrowserHostImpl::HasDocument() { - base::AutoLock lock_scope(state_lock_); - return has_document_; -} - -CefRefPtr CefBrowserHostImpl::GetMainFrame() { - return GetFrame(CefFrameHostImpl::kMainFrameId); -} - -CefRefPtr CefBrowserHostImpl::GetFocusedFrame() { - return GetFrame(CefFrameHostImpl::kFocusedFrameId); -} - -CefRefPtr CefBrowserHostImpl::GetFrame(int64 identifier) { - if (identifier == CefFrameHostImpl::kInvalidFrameId) { - return nullptr; - } else if (identifier == CefFrameHostImpl::kMainFrameId) { - return browser_info_->GetMainFrame(); - } else if (identifier == CefFrameHostImpl::kFocusedFrameId) { - base::AutoLock lock_scope(state_lock_); - if (!focused_frame_) { - // The main frame is focused by default. - return browser_info_->GetMainFrame(); - } - return focused_frame_; + auto callback = base::BindOnce(&CefBrowserHostImpl::StopLoad, this); + if (!CEF_CURRENTLY_ON_UIT()) { + CEF_POST_TASK(CEF_UIT, std::move(callback)); } - return browser_info_->GetFrameForId(identifier); -} - -CefRefPtr CefBrowserHostImpl::GetFrame(const CefString& name) { - for (const auto& frame : browser_info_->GetAllFrames()) { - if (frame->GetName() == name) - return frame; - } - return nullptr; -} - -size_t CefBrowserHostImpl::GetFrameCount() { - return browser_info_->GetAllFrames().size(); -} - -void CefBrowserHostImpl::GetFrameIdentifiers(std::vector& identifiers) { - if (identifiers.size() > 0) - identifiers.clear(); - - const auto frames = browser_info_->GetAllFrames(); - if (frames.empty()) + if (browser_info_->IsNavigationLocked(std::move(callback))) { return; - - identifiers.reserve(frames.size()); - for (const auto& frame : frames) { - identifiers.push_back(frame->GetIdentifier()); } -} -void CefBrowserHostImpl::GetFrameNames(std::vector& names) { - if (names.size() > 0) - names.clear(); - - const auto frames = browser_info_->GetAllFrames(); - if (frames.empty()) - return; - - names.reserve(frames.size()); - for (const auto& frame : frames) { - names.push_back(frame->GetName()); + auto wc = web_contents(); + if (wc) { + wc->Stop(); } } @@ -1488,13 +982,7 @@ void CefBrowserHostImpl::DestroyBrowser() { // 2. Notify the browser's LifeSpanHandler. This must always be the last // notification for this browser. - if (client_.get()) { - CefRefPtr handler = client_->GetLifeSpanHandler(); - if (handler.get()) { - // Notify the handler that the window is about to be closed. - handler->OnBeforeClose(this); - } - } + OnBeforeClose(); // Destroy any platform constructs first. if (file_dialog_manager_.get()) @@ -1505,8 +993,7 @@ void CefBrowserHostImpl::DestroyBrowser() { menu_manager_->Destroy(); // Notify any observers that may have state associated with this browser. - for (auto& observer : observers_) - observer.OnBrowserDestroyed(this); + OnBrowserDestroyed(); // If the WebContents still exists at this point, signal destruction before // browser destruction. @@ -1534,8 +1021,7 @@ void CefBrowserHostImpl::DestroyBrowser() { // Delete the platform delegate. platform_delegate_.reset(nullptr); - CefBrowserInfoManager::GetInstance()->RemoveBrowserInfo(browser_info_); - browser_info_->SetBrowser(nullptr); + CefBrowserHostBase::DestroyBrowser(); } #if defined(USE_AURA) @@ -1560,73 +1046,6 @@ void CefBrowserHostImpl::CancelContextMenu() { menu_manager_->CancelContextMenu(); } -CefRefPtr CefBrowserHostImpl::GetFrameForHost( - const content::RenderFrameHost* host) { - CEF_REQUIRE_UIT(); - if (!host) - return nullptr; - - return browser_info_->GetFrameForHost(host); -} - -CefRefPtr CefBrowserHostImpl::GetFrameForFrameTreeNode( - int frame_tree_node_id) { - return browser_info_->GetFrameForFrameTreeNode(frame_tree_node_id, nullptr); -} - -void CefBrowserHostImpl::LoadMainFrameURL(const std::string& url, - const content::Referrer& referrer, - ui::PageTransition transition, - const std::string& extra_headers) { - if (!CEF_CURRENTLY_ON_UIT()) { - CEF_POST_TASK(CEF_UIT, - base::BindOnce(&CefBrowserHostImpl::LoadMainFrameURL, this, - url, referrer, transition, extra_headers)); - return; - } - - // Go through the navigation controller. - if (navigation_locked()) { - // Try again after the lock has been released. - set_pending_navigation_action( - base::BindOnce(&CefBrowserHostImpl::LoadMainFrameURL, this, url, - referrer, transition, extra_headers)); - return; - } - - if (web_contents()) { - GURL gurl = GURL(url); - - if (!gurl.is_valid() && !gurl.has_scheme()) { - // Try to add "http://" at the beginning - std::string new_url = std::string("http://") + url; - gurl = GURL(new_url); - } - - if (!gurl.is_valid()) { - LOG(ERROR) - << "Invalid URL passed to CefBrowserHostImpl::LoadMainFrameURL: " - << url; - return; - } - - web_contents()->GetController().LoadURL(gurl, referrer, transition, - extra_headers); - OnSetFocus(FOCUS_SOURCE_NAVIGATION); - } -} - -void CefBrowserHostImpl::OnDidFinishLoad(CefRefPtr frame, - const GURL& validated_url, - int http_status_code) { - frame->RefreshAttributes(); - - // Give internal scheme handlers an opportunity to update content. - scheme::DidFinishLoad(frame, validated_url); - - OnLoadEnd(frame, validated_url, http_status_code); -} - void CefBrowserHostImpl::ViewText(const std::string& text) { if (!CEF_CURRENTLY_ON_UIT()) { CEF_POST_TASK(CEF_UIT, @@ -1644,17 +1063,6 @@ SkColor CefBrowserHostImpl::GetBackgroundColor() const { &settings_, is_windowless_ ? STATE_ENABLED : STATE_DISABLED); } -int CefBrowserHostImpl::browser_id() const { - return browser_info_->browser_id(); -} - -content::BrowserContext* CefBrowserHostImpl::GetBrowserContext() const { - CEF_REQUIRE_UIT(); - if (web_contents()) - return web_contents()->GetBrowserContext(); - return nullptr; -} - extensions::ExtensionHost* CefBrowserHostImpl::GetExtensionHost() const { CEF_REQUIRE_UIT(); DCHECK(platform_delegate_); @@ -1703,12 +1111,14 @@ bool CefBrowserHostImpl::EmbedsFullscreenWidget() { void CefBrowserHostImpl::EnterFullscreenModeForTab( content::RenderFrameHost* requesting_frame, const blink::mojom::FullscreenOptions& options) { - OnFullscreenModeChange(true); + contents_delegate_->EnterFullscreenModeForTab(requesting_frame, options); + WasResized(); } void CefBrowserHostImpl::ExitFullscreenModeForTab( content::WebContents* web_contents) { - OnFullscreenModeChange(false); + contents_delegate_->ExitFullscreenModeForTab(web_contents); + WasResized(); } bool CefBrowserHostImpl::IsFullscreenForTabOrPending( @@ -2007,45 +1417,7 @@ void CefBrowserHostImpl::AddNewContents( void CefBrowserHostImpl::LoadingStateChanged(content::WebContents* source, bool to_different_document) { - const int current_index = - source->GetController().GetLastCommittedEntryIndex(); - const int max_index = source->GetController().GetEntryCount() - 1; - - const bool is_loading = source->IsLoading(); - const bool can_go_back = (current_index > 0); - const bool can_go_forward = (current_index < max_index); - - { - base::AutoLock lock_scope(state_lock_); - - // This method may be called multiple times in a row with |is_loading| - // true as a result of https://crrev.com/5e750ad0. Ignore the 2nd+ times. - if (is_loading_ == is_loading && can_go_back_ == can_go_back && - can_go_forward_ == can_go_forward) { - return; - } - - is_loading_ = is_loading; - can_go_back_ = can_go_back; - can_go_forward_ = can_go_forward; - } - - if (client_.get()) { - CefRefPtr handler = client_->GetLoadHandler(); - if (handler.get()) { - handler->OnLoadingStateChange(this, is_loading, can_go_back, - can_go_forward); - } - } -} - -void CefBrowserHostImpl::LoadProgressChanged(double progress) { - if (client_.get()) { - CefRefPtr handler = client_->GetDisplayHandler(); - if (handler.get()) { - handler->OnLoadingProgressChange(this, progress); - } - } + contents_delegate_->LoadingStateChanged(source, to_different_document); } void CefBrowserHostImpl::CloseContents(content::WebContents* source) { @@ -2090,11 +1462,7 @@ void CefBrowserHostImpl::CloseContents(content::WebContents* source) { void CefBrowserHostImpl::UpdateTargetURL(content::WebContents* source, const GURL& url) { - if (client_.get()) { - CefRefPtr handler = client_->GetDisplayHandler(); - if (handler.get()) - handler->OnStatusMessage(this, url.spec()); - } + contents_delegate_->UpdateTargetURL(source, url); } bool CefBrowserHostImpl::DidAddMessageToConsole( @@ -2103,32 +1471,8 @@ bool CefBrowserHostImpl::DidAddMessageToConsole( const base::string16& message, int32_t line_no, const base::string16& source_id) { - if (client_.get()) { - CefRefPtr handler = client_->GetDisplayHandler(); - if (handler.get()) { - // Use LOGSEVERITY_DEBUG for unrecognized |level| values. - cef_log_severity_t log_level = LOGSEVERITY_DEBUG; - switch (level) { - case blink::mojom::ConsoleMessageLevel::kVerbose: - log_level = LOGSEVERITY_DEBUG; - break; - case blink::mojom::ConsoleMessageLevel::kInfo: - log_level = LOGSEVERITY_INFO; - break; - case blink::mojom::ConsoleMessageLevel::kWarning: - log_level = LOGSEVERITY_WARNING; - break; - case blink::mojom::ConsoleMessageLevel::kError: - log_level = LOGSEVERITY_ERROR; - break; - } - - return handler->OnConsoleMessage(this, log_level, message, source_id, - line_no); - } - } - - return false; + return contents_delegate_->DidAddMessageToConsole(source, level, message, + line_no, source_id); } void CefBrowserHostImpl::BeforeUnloadFired(content::WebContents* source, @@ -2286,8 +1630,7 @@ void CefBrowserHostImpl::WebContentsCreated( void CefBrowserHostImpl::DidNavigateMainFramePostCommit( content::WebContents* web_contents) { - base::AutoLock lock_scope(state_lock_); - has_document_ = false; + contents_delegate_->DidNavigateMainFramePostCommit(web_contents); } content::JavaScriptDialogManager* @@ -2435,30 +1778,6 @@ void CefBrowserHostImpl::ExitPictureInPicture() { // content::WebContentsObserver methods. // ----------------------------------------------------------------------------- -void CefBrowserHostImpl::RenderFrameCreated( - content::RenderFrameHost* render_frame_host) { - browser_info_->MaybeCreateFrame(render_frame_host, false /* is_guest_view */); -} - -void CefBrowserHostImpl::RenderFrameHostChanged( - content::RenderFrameHost* old_host, - content::RenderFrameHost* new_host) { - // Just in case RenderFrameCreated wasn't called for some reason. - RenderFrameCreated(new_host); -} - -void CefBrowserHostImpl::RenderFrameDeleted( - content::RenderFrameHost* render_frame_host) { - const auto frame_id = CefFrameHostImpl::MakeFrameId(render_frame_host); - browser_info_->RemoveFrame(render_frame_host); - - base::AutoLock lock_scope(state_lock_); - - if (focused_frame_ && focused_frame_->GetIdentifier() == frame_id) { - focused_frame_ = nullptr; - } -} - void CefBrowserHostImpl::RenderViewCreated( content::RenderViewHost* render_view_host) { // May be already registered if the renderer crashed previously. @@ -2469,9 +1788,6 @@ void CefBrowserHostImpl::RenderViewCreated( content::Source(render_view_host)); } - // RenderFrameCreated is otherwise not called for new popup browsers. - RenderFrameCreated(render_view_host->GetMainFrame()); - new CefWidgetHostInterceptor(this, render_view_host); platform_delegate_->RenderViewCreated(render_view_host); @@ -2490,84 +1806,13 @@ void CefBrowserHostImpl::RenderViewDeleted( void CefBrowserHostImpl::RenderViewReady() { platform_delegate_->RenderViewReady(); - - if (client_.get()) { - CefRefPtr handler = client_->GetRequestHandler(); - if (handler.get()) - handler->OnRenderViewReady(this); - } -} - -void CefBrowserHostImpl::RenderProcessGone(base::TerminationStatus status) { - cef_termination_status_t ts = TS_ABNORMAL_TERMINATION; - if (status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED) - ts = TS_PROCESS_WAS_KILLED; - else if (status == base::TERMINATION_STATUS_PROCESS_CRASHED) - ts = TS_PROCESS_CRASHED; - else if (status == base::TERMINATION_STATUS_OOM) - ts = TS_PROCESS_OOM; - else if (status != base::TERMINATION_STATUS_ABNORMAL_TERMINATION) - return; - - if (client_.get()) { - CefRefPtr handler = client_->GetRequestHandler(); - if (handler.get()) { - std::unique_ptr navigation_lock = CreateNavigationLock(); - handler->OnRenderProcessTerminated(this, ts); - } - } } void CefBrowserHostImpl::DidFinishNavigation( content::NavigationHandle* navigation_handle) { - const net::Error error_code = navigation_handle->GetNetErrorCode(); - - // Skip calls where the navigation has not yet committed and there is no - // error code. For example, when creating a browser without loading a URL. - if (!navigation_handle->HasCommitted() && error_code == net::OK) - return; - - const bool is_main_frame = navigation_handle->IsInMainFrame(); - const GURL& url = - (error_code == net::OK ? navigation_handle->GetURL() : GURL()); - - // May return NULL when starting a new navigation if the previous navigation - // caused the renderer process to crash during load. - CefRefPtr frame = browser_info_->GetFrameForFrameTreeNode( - navigation_handle->GetFrameTreeNodeId()); - if (!frame) { - if (is_main_frame) { - frame = browser_info_->GetMainFrame(); - } else { - frame = - browser_info_->CreateTempSubFrame(CefFrameHostImpl::kInvalidFrameId); - } - } - frame->RefreshAttributes(); - - if (error_code == net::OK) { - // The navigation has been committed and there is no error. - DCHECK(navigation_handle->HasCommitted()); - - // Don't call OnLoadStart for same page navigations (fragments, - // history state). - if (!navigation_handle->IsSameDocument()) - OnLoadStart(frame.get(), navigation_handle->GetPageTransition()); - - if (is_main_frame) - OnAddressChange(url); - } else { - // The navigation failed with an error. This may happen before commit - // (e.g. network error) or after commit (e.g. response filter error). - // If the error happened before commit then this call will originate from - // RenderFrameHostImpl::OnDidFailProvisionalLoadWithError. - // OnLoadStart/OnLoadEnd will not be called. - OnLoadError(frame.get(), navigation_handle->GetURL(), error_code); - } - if (web_contents()) { - auto cef_browser_context = CefBrowserContext::FromBrowserContext( - web_contents()->GetBrowserContext()); + auto cef_browser_context = + static_cast(web_contents()->GetBrowserContext()); if (cef_browser_context) { cef_browser_context->AddVisitedURLs( navigation_handle->GetRedirectChain()); @@ -2575,79 +1820,6 @@ void CefBrowserHostImpl::DidFinishNavigation( } } -void CefBrowserHostImpl::DidStopLoading() { - // Notify all renderers that loading has stopped. We used to use - // RenderFrameObserver::DidStopLoading which was removed in - // https://crrev.com/3e37dd0ead. However, that callback wasn't necessarily - // accurate because it wasn't called in all of the cases where - // RenderFrameImpl sends the FrameHostMsg_DidStopLoading message. This adds - // an additional round trip but should provide the same or improved - // functionality. - for (const auto& frame : browser_info_->GetAllFrames()) { - frame->MaybeSendDidStopLoading(); - } -} - -void CefBrowserHostImpl::DocumentAvailableInMainFrame() { - { - base::AutoLock lock_scope(state_lock_); - has_document_ = true; - } - - if (client_) { - CefRefPtr handler = client_->GetRequestHandler(); - if (handler) - handler->OnDocumentAvailableInMainFrame(this); - } -} - -void CefBrowserHostImpl::DidFailLoad( - content::RenderFrameHost* render_frame_host, - const GURL& validated_url, - int error_code) { - // The navigation failed after commit. OnLoadStart was called so we also - // call OnLoadEnd. - auto frame = browser_info_->GetFrameForHost(render_frame_host); - frame->RefreshAttributes(); - OnLoadError(frame, validated_url, error_code); - OnLoadEnd(frame, validated_url, error_code); -} - -void CefBrowserHostImpl::TitleWasSet(content::NavigationEntry* entry) { - // |entry| may be NULL if a popup is created via window.open and never - // navigated. - if (entry) - OnTitleChange(entry->GetTitle()); - else if (web_contents()) - OnTitleChange(web_contents()->GetTitle()); -} - -void CefBrowserHostImpl::PluginCrashed(const base::FilePath& plugin_path, - base::ProcessId plugin_pid) { - if (client_.get()) { - CefRefPtr handler = client_->GetRequestHandler(); - if (handler.get()) - handler->OnPluginCrashed(this, plugin_path.value()); - } -} - -void CefBrowserHostImpl::DidUpdateFaviconURL( - content::RenderFrameHost* render_frame_host, - const std::vector& candidates) { - if (client_.get()) { - CefRefPtr handler = client_->GetDisplayHandler(); - if (handler.get()) { - std::vector icon_urls; - for (const auto& icon : candidates) { - if (icon->icon_type == blink::mojom::FaviconIconType::kFavicon) - icon_urls.push_back(icon->icon_url.spec()); - } - if (!icon_urls.empty()) - handler->OnFaviconURLChange(this, icon_urls); - } - } -} - void CefBrowserHostImpl::OnAudioStateChanged(bool audible) { if (audible) { recently_audible_timer_.Stop(); @@ -2667,46 +1839,6 @@ void CefBrowserHostImpl::OnRecentlyAudibleTimerFired() { audio_capturer_.reset(); } -bool CefBrowserHostImpl::OnMessageReceived( - const IPC::Message& message, - content::RenderFrameHost* render_frame_host) { - // Messages may arrive after a frame is detached. Ignore those messages. - auto frame = GetFrameForHost(render_frame_host); - if (frame) { - return static_cast(frame.get()) - ->OnMessageReceived(message); - } - return false; -} - -void CefBrowserHostImpl::OnFrameFocused( - content::RenderFrameHost* render_frame_host) { - CefRefPtr frame = - static_cast(GetFrameForHost(render_frame_host).get()); - if (!frame || frame->IsFocused()) - return; - - CefRefPtr previous_frame; - { - base::AutoLock lock_scope(state_lock_); - previous_frame = focused_frame_; - if (frame->IsMain()) - focused_frame_ = nullptr; - else - focused_frame_ = frame; - } - - if (!previous_frame) { - // The main frame is focused by default. - previous_frame = browser_info_->GetMainFrame(); - } - - if (previous_frame->GetIdentifier() != frame->GetIdentifier()) { - previous_frame->SetFocused(false); - frame->SetFocused(true); - } -} - void CefBrowserHostImpl::AccessibilityEventReceived( const content::AXEventNotificationDetails& content_event_bundle) { // Only needed in windowless mode. @@ -2729,15 +1861,6 @@ void CefBrowserHostImpl::AccessibilityLocationChangesReceived( } } -void CefBrowserHostImpl::OnWebContentsFocused( - content::RenderWidgetHost* render_widget_host) { - if (client_.get()) { - CefRefPtr handler = client_->GetFocusHandler(); - if (handler.get()) - handler->OnGotFocus(this); - } -} - void CefBrowserHostImpl::WebContentsDestroyed() { auto wc = web_contents(); content::WebContentsObserver::Observe(nullptr); @@ -2745,21 +1868,6 @@ void CefBrowserHostImpl::WebContentsDestroyed() { platform_delegate_->WebContentsDestroyed(wc); } -void CefBrowserHostImpl::AddObserver(Observer* observer) { - CEF_REQUIRE_UIT(); - observers_.AddObserver(observer); -} - -void CefBrowserHostImpl::RemoveObserver(Observer* observer) { - CEF_REQUIRE_UIT(); - observers_.RemoveObserver(observer); -} - -bool CefBrowserHostImpl::HasObserver(Observer* observer) const { - CEF_REQUIRE_UIT(); - return observers_.HasObserver(observer); -} - void CefBrowserHostImpl::StartAudioCapturer() { if (!client_.get() || audio_capturer_) return; @@ -2779,38 +1887,6 @@ void CefBrowserHostImpl::StartAudioCapturer() { audio_capturer_.reset(new CefAudioCapturer(params, this, audio_handler)); } -CefBrowserHostImpl::NavigationLock::NavigationLock( - CefRefPtr browser) - : browser_(browser) { - CEF_REQUIRE_UIT(); - browser_->navigation_lock_count_++; -} - -CefBrowserHostImpl::NavigationLock::~NavigationLock() { - CEF_REQUIRE_UIT(); - if (--browser_->navigation_lock_count_ == 0) { - if (!browser_->pending_navigation_action_.is_null()) { - CEF_POST_TASK(CEF_UIT, std::move(browser_->pending_navigation_action_)); - } - } -} - -std::unique_ptr -CefBrowserHostImpl::CreateNavigationLock() { - return base::WrapUnique(new NavigationLock(this)); -} - -bool CefBrowserHostImpl::navigation_locked() const { - CEF_REQUIRE_UIT(); - return navigation_lock_count_ > 0; -} - -void CefBrowserHostImpl::set_pending_navigation_action( - base::OnceClosure action) { - CEF_REQUIRE_UIT(); - pending_navigation_action_ = std::move(action); -} - // content::NotificationObserver methods. // ----------------------------------------------------------------------------- @@ -2823,7 +1899,7 @@ void CefBrowserHostImpl::Observe(int type, if (type == content::NOTIFICATION_LOAD_STOP) { content::NavigationController* controller = content::Source(source).ptr(); - OnTitleChange(controller->GetWebContents()->GetTitle()); + contents_delegate_->OnTitleChange(controller->GetWebContents()->GetTitle()); } else if (type == content::NOTIFICATION_FOCUS_CHANGED_IN_PAGE) { focus_on_editable_field_ = *content::Details(details).ptr(); } @@ -2841,28 +1917,21 @@ CefBrowserHostImpl::CefBrowserHostImpl( CefRefPtr request_context, std::unique_ptr platform_delegate, CefRefPtr extension) - : content::WebContentsObserver(web_contents), - settings_(settings), - client_(client), - browser_info_(browser_info), + : CefBrowserHostBase(settings, client, browser_info, request_context), + content::WebContentsObserver(web_contents), opener_(kNullWindowHandle), - request_context_(request_context), platform_delegate_(std::move(platform_delegate)), is_windowless_(platform_delegate_->IsWindowless()), is_views_hosted_(platform_delegate_->IsViewsHosted()), extension_(extension) { + contents_delegate_->ObserveWebContents(web_contents); + if (opener.get() && !platform_delegate_->IsViewsHosted()) { // GetOpenerWindowHandle() only returns a value for non-views-hosted // popup browsers. opener_ = opener->GetWindowHandle(); } - DCHECK(!browser_info_->browser().get()); - browser_info_->SetBrowser(this); - - // Associate the WebContents with this browser object. - WebContentsUserDataAdapter::Register(this); - registrar_.reset(new content::NotificationRegistrar); // When navigating through the history, the restored NavigationEntry's title @@ -2917,75 +1986,6 @@ void CefBrowserHostImpl::UpdateDragCursor(blink::WebDragOperation operation) { platform_delegate_->UpdateDragCursor(operation); } -void CefBrowserHostImpl::OnAddressChange(const GURL& url) { - if (client_.get()) { - CefRefPtr handler = client_->GetDisplayHandler(); - if (handler.get()) { - // Notify the handler of an address change. - handler->OnAddressChange(this, GetMainFrame(), url.spec()); - } - } -} - -void CefBrowserHostImpl::OnLoadStart(CefRefPtr frame, - ui::PageTransition transition_type) { - if (client_.get()) { - CefRefPtr handler = client_->GetLoadHandler(); - if (handler.get()) { - // Notify the handler that loading has started. - handler->OnLoadStart(this, frame, - static_cast(transition_type)); - } - } -} - -void CefBrowserHostImpl::OnLoadError(CefRefPtr frame, - const GURL& url, - int error_code) { - if (client_.get()) { - CefRefPtr handler = client_->GetLoadHandler(); - if (handler.get()) { - std::unique_ptr navigation_lock = CreateNavigationLock(); - // Notify the handler that loading has failed. - handler->OnLoadError(this, frame, - static_cast(error_code), - net::ErrorToShortString(error_code), url.spec()); - } - } -} - -void CefBrowserHostImpl::OnLoadEnd(CefRefPtr frame, - const GURL& url, - int http_status_code) { - if (client_.get()) { - CefRefPtr handler = client_->GetLoadHandler(); - if (handler.get()) - handler->OnLoadEnd(this, frame, http_status_code); - } -} - -void CefBrowserHostImpl::OnFullscreenModeChange(bool fullscreen) { - if (is_fullscreen_ == fullscreen) - return; - - is_fullscreen_ = fullscreen; - WasResized(); - - if (client_.get()) { - CefRefPtr handler = client_->GetDisplayHandler(); - if (handler.get()) - handler->OnFullscreenModeChange(this, fullscreen); - } -} - -void CefBrowserHostImpl::OnTitleChange(const base::string16& title) { - if (client_.get()) { - CefRefPtr handler = client_->GetDisplayHandler(); - if (handler.get()) - handler->OnTitleChange(this, title); - } -} - void CefBrowserHostImpl::EnsureFileDialogManager() { CEF_REQUIRE_UIT(); if (!file_dialog_manager_.get() && platform_delegate_) { diff --git a/libcef/browser/browser_host_impl.h b/libcef/browser/browser_host_impl.h index 63d940e85..1fa8a1e00 100644 --- a/libcef/browser/browser_host_impl.h +++ b/libcef/browser/browser_host_impl.h @@ -14,7 +14,7 @@ #include "include/cef_browser.h" #include "include/cef_client.h" #include "include/cef_frame.h" -#include "include/views/cef_browser_view.h" +#include "libcef/browser/browser_host_base.h" #include "libcef/browser/browser_info.h" #include "libcef/browser/file_dialog_manager.h" #include "libcef/browser/frame_host_impl.h" @@ -22,7 +22,6 @@ #include "libcef/browser/menu_manager.h" #include "libcef/browser/request_context_impl.h" -#include "base/observer_list.h" #include "base/strings/string16.h" #include "base/synchronization/lock.h" #include "content/public/browser/notification_observer.h" @@ -58,7 +57,9 @@ class CefBrowserPlatformDelegate; class CefDevToolsManager; class SiteInstance; -// Implementation of CefBrowser. +// CefBrowser implementation for the alloy runtime. Method calls are delegated +// to the CefPlatformDelegate or the WebContents as appropriate. All methods are +// thread-safe unless otherwise indicated. // // WebContentsDelegate: Interface for handling WebContents delegations. There is // a one-to-one relationship between CefBrowserHostImpl and WebContents @@ -73,8 +74,7 @@ class SiteInstance; // WebContentsObserver::routing_id() when sending IPC messages. // // NotificationObserver: Interface for observing post-processed notifications. -class CefBrowserHostImpl : public CefBrowserHost, - public CefBrowser, +class CefBrowserHostImpl : public CefBrowserHostBase, public content::WebContentsDelegate, public content::WebContentsObserver, public content::NotificationObserver { @@ -85,58 +85,9 @@ class CefBrowserHostImpl : public CefBrowserHost, virtual void OnResponse(const std::string& response) = 0; }; - // Interface to implement for observers that wish to be informed of changes - // to the CefBrowserHostImpl. All methods will be called on the UI thread. - class Observer { - public: - // Called before |browser| is destroyed. Any references to |browser| should - // be cleared when this method is called. - virtual void OnBrowserDestroyed(CefBrowserHostImpl* browser) = 0; - - protected: - virtual ~Observer() {} - }; - ~CefBrowserHostImpl() override; - struct CreateParams { - // Platform-specific window creation info. Will be nullptr when creating a - // views-hosted browser. - std::unique_ptr window_info; - -#if defined(USE_AURA) - // The BrowserView that will own a views-hosted browser. Will be nullptr for - // popup browsers (the BrowserView will be created later in that case). - CefRefPtr browser_view; -#endif - - // Client implementation. May be nullptr. - CefRefPtr client; - - // Initial URL to load. May be empty. If this is a valid extension URL then - // the browser will be created as an app view extension host. - GURL url; - - // Browser settings. - CefBrowserSettings settings; - - // Other browser that opened this DevTools browser. Will be nullptr for non- - // DevTools browsers. - CefRefPtr devtools_opener; - - // Request context to use when creating the browser. If nullptr the global - // request context will be used. - CefRefPtr request_context; - - CefRefPtr extra_info; - - // Used when explicitly creating the browser as an extension host via - // ProcessManager::CreateBackgroundHost. - const extensions::Extension* extension = nullptr; - extensions::ViewType extension_host_type = extensions::VIEW_TYPE_INVALID; - }; - - // Create a new CefBrowserHostImpl instance. + // Create a new CefBrowserHostImpl instance with owned WebContents. static CefRefPtr Create(CreateParams& create_params); // Returns the browser associated with the specified RenderViewHost. @@ -157,15 +108,12 @@ class CefBrowserHostImpl : public CefBrowserHost, int render_routing_id); // CefBrowserHost methods. - CefRefPtr GetBrowser() override; void CloseBrowser(bool force_close) override; bool TryCloseBrowser() override; void SetFocus(bool focus) override; CefWindowHandle GetWindowHandle() override; CefWindowHandle GetOpenerWindowHandle() override; bool HasView() override; - CefRefPtr GetClient() override; - CefRefPtr GetRequestContext() override; double GetZoomLevel() override; void SetZoomLevel(double zoomLevel) override; void RunFileDialog(FileDialogMode mode, @@ -174,12 +122,6 @@ class CefBrowserHostImpl : public CefBrowserHost, const std::vector& accept_filters, int selected_accept_filter, CefRefPtr callback) override; - void StartDownload(const CefString& url) override; - void DownloadImage(const CefString& image_url, - bool is_favicon, - uint32 max_image_size, - bool bypass_cache, - CefRefPtr callback) override; void Print() override; void PrintToPDF(const CefString& path, const CefPdfPrintSettings& settings, @@ -202,13 +144,9 @@ class CefBrowserHostImpl : public CefBrowserHost, CefRefPtr params) override; CefRefPtr AddDevToolsMessageObserver( CefRefPtr observer) override; - void GetNavigationEntries(CefRefPtr visitor, - bool current_only) override; void SetMouseCursorChangeDisabled(bool disabled) override; bool IsMouseCursorChangeDisabled() override; bool IsWindowRenderingDisabled() override; - void ReplaceMisspelling(const CefString& word) override; - void AddWordToDictionary(const CefString& word) override; void WasResized() override; void WasHidden(bool hidden) override; void NotifyScreenInfoChanged() override; @@ -249,7 +187,6 @@ class CefBrowserHostImpl : public CefBrowserHost, void DragSourceEndedAt(int x, int y, DragOperationsMask op) override; void SetAudioMuted(bool mute) override; bool IsAudioMuted() override; - CefRefPtr GetVisibleNavigationEntry() override; void SetAccessibilityState(cef_state_t accessibility_state) override; void SetAutoResizeEnabled(bool enabled, const CefSize& min_size, @@ -258,26 +195,11 @@ class CefBrowserHostImpl : public CefBrowserHost, bool IsBackgroundHost() override; // CefBrowser methods. - CefRefPtr GetHost() override; - bool CanGoBack() override; void GoBack() override; - bool CanGoForward() override; void GoForward() override; - bool IsLoading() override; void Reload() override; void ReloadIgnoreCache() override; void StopLoad() override; - int GetIdentifier() override; - bool IsSame(CefRefPtr that) override; - bool IsPopup() override; - bool HasDocument() override; - CefRefPtr GetMainFrame() override; - CefRefPtr GetFocusedFrame() override; - CefRefPtr GetFrame(int64 identifier) override; - CefRefPtr GetFrame(const CefString& name) override; - size_t GetFrameCount() override; - void GetFrameIdentifiers(std::vector& identifiers) override; - void GetFrameNames(std::vector& names) override; // Returns true if windowless rendering is enabled. bool IsWindowless() const; @@ -293,7 +215,7 @@ class CefBrowserHostImpl : public CefBrowserHost, // Destroy the browser members. This method should only be called after the // native browser window is not longer processing messages. - void DestroyBrowser(); + void DestroyBrowser() override; // Cancel display of the context menu, if any. void CancelContextMenu(); @@ -308,25 +230,8 @@ class CefBrowserHostImpl : public CefBrowserHost, CefRefPtr GetBrowserView() const; #endif - // Returns the frame associated with the specified RenderFrameHost. - CefRefPtr GetFrameForHost(const content::RenderFrameHost* host); - - // Returns the frame associated with the specified FrameTreeNode ID. - CefRefPtr GetFrameForFrameTreeNode(int frame_tree_node_id); - - // Load the specified URL in the main frame. - void LoadMainFrameURL(const std::string& url, - const content::Referrer& referrer, - ui::PageTransition transition, - const std::string& extra_headers); - - // Called from CefFrameHostImpl. - void OnDidFinishLoad(CefRefPtr frame, - const GURL& validated_url, - int http_status_code); - // Open the specified text in the default text editor. - void ViewText(const std::string& text); + void ViewText(const std::string& text) override; // Convert from view coordinates to screen coordinates. Potential display // scaling will be applied to the result. @@ -341,20 +246,12 @@ class CefBrowserHostImpl : public CefBrowserHost, void UpdateDragCursor(blink::WebDragOperation operation); // Thread safe accessors. - const CefBrowserSettings& settings() const { return settings_; } SkColor GetBackgroundColor() const; - CefRefPtr client() const { return client_; } - scoped_refptr browser_info() const { return browser_info_; } - int browser_id() const; - CefRefPtr request_context() const { - return request_context_; - } // Accessors that must be called on the UI thread. - content::BrowserContext* GetBrowserContext() const; extensions::ExtensionHost* GetExtensionHost() const; - void OnSetFocus(cef_focus_source_t source); + void OnSetFocus(cef_focus_source_t source) override; // Run the file chooser dialog specified by |params|. Only a single dialog may // be pending at any given time. |callback| will be executed asynchronously @@ -387,7 +284,6 @@ class CefBrowserHostImpl : public CefBrowserHost, bool* was_blocked) override; void LoadingStateChanged(content::WebContents* source, bool to_different_document) override; - void LoadProgressChanged(double progress) override; void CloseContents(content::WebContents* source) override; void UpdateTargetURL(content::WebContents* source, const GURL& url) override; bool DidAddMessageToConsole(content::WebContents* source, @@ -467,61 +363,19 @@ class CefBrowserHostImpl : public CefBrowserHost, // content::WebContentsObserver methods. using content::WebContentsObserver::BeforeUnloadFired; - void RenderFrameCreated(content::RenderFrameHost* render_frame_host) override; - void RenderFrameHostChanged(content::RenderFrameHost* old_host, - content::RenderFrameHost* new_host) override; - void RenderFrameDeleted(content::RenderFrameHost* render_frame_host) override; void RenderViewCreated(content::RenderViewHost* render_view_host) override; void RenderViewDeleted(content::RenderViewHost* render_view_host) override; void RenderViewReady() override; - void RenderProcessGone(base::TerminationStatus status) override; void DidFinishNavigation( content::NavigationHandle* navigation_handle) override; - void DidStopLoading() override; - void DocumentAvailableInMainFrame() override; - void DidFailLoad(content::RenderFrameHost* render_frame_host, - const GURL& validated_url, - int error_code) override; - void TitleWasSet(content::NavigationEntry* entry) override; - void PluginCrashed(const base::FilePath& plugin_path, - base::ProcessId plugin_pid) override; - void DidUpdateFaviconURL( - content::RenderFrameHost* render_frame_host, - const std::vector& candidates) override; void OnAudioStateChanged(bool audible) override; - bool OnMessageReceived(const IPC::Message& message, - content::RenderFrameHost* render_frame_host) override; - void OnFrameFocused(content::RenderFrameHost* render_frame_host) override; void AccessibilityEventReceived( const content::AXEventNotificationDetails& content_event_bundle) override; void AccessibilityLocationChangesReceived( const std::vector& locData) override; - void OnWebContentsFocused( - content::RenderWidgetHost* render_widget_host) override; void WebContentsDestroyed() override; - // Manage observer objects. The observer must either outlive this object or - // remove itself before destruction. These methods can only be called on the - // UI thread. - void AddObserver(Observer* observer); - void RemoveObserver(Observer* observer); - bool HasObserver(Observer* observer) const; - - class NavigationLock final { - private: - friend class CefBrowserHostImpl; - friend std::unique_ptr::deleter_type; - - explicit NavigationLock(CefRefPtr browser); - ~NavigationLock(); - - CefRefPtr browser_; - }; - - // Block navigation-related events on NavigationLock life span. - std::unique_ptr CreateNavigationLock(); - private: friend class CefBrowserPlatformDelegateAlloy; @@ -555,21 +409,6 @@ class CefBrowserHostImpl : public CefBrowserHost, // Give the platform delegate an opportunity to create the host window. bool CreateHostWindow(); - // Returns true if navigation actions are currently locked. - bool navigation_locked() const; - // Action to be executed once the navigation lock is released. - void set_pending_navigation_action(base::OnceClosure action); - - void OnAddressChange(const GURL& url); - void OnLoadStart(CefRefPtr frame, - ui::PageTransition transition_type); - void OnLoadError(CefRefPtr frame, const GURL& url, int error_code); - void OnLoadEnd(CefRefPtr frame, - const GURL& url, - int http_status_code); - void OnFullscreenModeChange(bool fullscreen); - void OnTitleChange(const base::string16& title); - // Create the CefFileDialogManager if it doesn't already exist. void EnsureFileDialogManager(); @@ -580,11 +419,7 @@ class CefBrowserHostImpl : public CefBrowserHost, void InitializeDevToolsRegistrationOnUIThread( CefRefPtr registration); - CefBrowserSettings settings_; - CefRefPtr client_; - scoped_refptr browser_info_; CefWindowHandle opener_; - CefRefPtr request_context_; std::unique_ptr platform_delegate_; const bool is_windowless_; const bool is_views_hosted_; @@ -592,27 +427,10 @@ class CefBrowserHostImpl : public CefBrowserHost, CefRefPtr extension_; bool is_background_host_ = false; - // Volatile state information. All access must be protected by the state lock. - base::Lock state_lock_; - bool is_loading_ = false; - bool can_go_back_ = false; - bool can_go_forward_ = false; - bool has_document_ = false; - bool is_fullscreen_ = false; - - // The currently focused frame, or nullptr if the main frame is focused. - CefRefPtr focused_frame_; - // Represents the current browser destruction state. Only accessed on the UI // thread. DestructionState destruction_state_ = DESTRUCTION_STATE_NONE; - // Navigation will not occur while |navigation_lock_count_| > 0. - // |pending_navigation_action_| will be executed when the lock is released. - // Only accessed on the UI thread. - int navigation_lock_count_ = 0; - base::OnceClosure pending_navigation_action_; - // True if the OS window hosting the browser has been destroyed. Only accessed // on the UI thread. bool window_destroyed_ = false; @@ -643,9 +461,6 @@ class CefBrowserHostImpl : public CefBrowserHost, // Used for creating and managing DevTools instances. std::unique_ptr devtools_manager_; - // Observers that want to be notified of changes to this object. - base::ObserverList::Unchecked observers_; - // Used for capturing audio for CefAudioHandler. std::unique_ptr audio_capturer_; @@ -653,9 +468,6 @@ class CefBrowserHostImpl : public CefBrowserHost, // starts running when a tab stops being audible, and is canceled if it starts // being audible again before it fires. base::OneShotTimer recently_audible_timer_; - - IMPLEMENT_REFCOUNTING(CefBrowserHostImpl); - DISALLOW_COPY_AND_ASSIGN(CefBrowserHostImpl); }; #endif // CEF_LIBCEF_BROWSER_BROWSER_HOST_IMPL_H_ diff --git a/libcef/browser/browser_info.cc b/libcef/browser/browser_info.cc index 851e7d53c..8b27d608a 100644 --- a/libcef/browser/browser_info.cc +++ b/libcef/browser/browser_info.cc @@ -34,12 +34,12 @@ CefBrowserInfo::CefBrowserInfo(int browser_id, CefBrowserInfo::~CefBrowserInfo() {} -CefRefPtr CefBrowserInfo::browser() const { +CefRefPtr CefBrowserInfo::browser() const { base::AutoLock lock_scope(lock_); return browser_; } -void CefBrowserInfo::SetBrowser(CefRefPtr browser) { +void CefBrowserInfo::SetBrowser(CefRefPtr browser) { base::AutoLock lock_scope(lock_); browser_ = browser; @@ -297,6 +297,37 @@ CefBrowserInfo::FrameHostList CefBrowserInfo::GetAllFrames() const { return frames; } +CefBrowserInfo::NavigationLock::NavigationLock() : weak_ptr_factory_(this) {} + +CefBrowserInfo::NavigationLock::~NavigationLock() { + CEF_REQUIRE_UIT(); + if (pending_action_) { + CEF_POST_TASK(CEF_UIT, std::move(pending_action_)); + } +} + +scoped_refptr +CefBrowserInfo::CreateNavigationLock() { + CEF_REQUIRE_UIT(); + scoped_refptr lock; + if (!navigation_lock_) { + lock = new NavigationLock(); + navigation_lock_ = lock->weak_ptr_factory_.GetWeakPtr(); + } else { + lock = navigation_lock_.get(); + } + return lock; +} + +bool CefBrowserInfo::IsNavigationLocked(base::OnceClosure pending_action) { + CEF_REQUIRE_UIT(); + if (navigation_lock_) { + navigation_lock_->pending_action_ = std::move(pending_action); + return true; + } + return false; +} + void CefBrowserInfo::MaybeUpdateFrameTreeNodeIdMap(FrameInfo* info) { lock_.AssertAcquired(); diff --git a/libcef/browser/browser_info.h b/libcef/browser/browser_info.h index c48328ff7..a4c825abe 100644 --- a/libcef/browser/browser_info.h +++ b/libcef/browser/browser_info.h @@ -12,8 +12,10 @@ #include "include/internal/cef_ptr.h" #include "libcef/common/values_impl.h" +#include "base/callback.h" #include "base/containers/unique_ptr_adapters.h" #include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" #include "base/synchronization/lock.h" #include "base/values.h" @@ -21,12 +23,12 @@ namespace content { class RenderFrameHost; } -class CefBrowserHostImpl; +class CefBrowserHostBase; class CefFrameHostImpl; // CefBrowserInfo is used to associate a browser ID and render view/process -// IDs with a particular CefBrowserHostImpl. Render view/process IDs may change -// during the lifetime of a single CefBrowserHostImpl. +// IDs with a particular CefBrowserHostBase. Render view/process IDs may change +// during the lifetime of a single CefBrowserHostBase. // // CefBrowserInfo objects are managed by CefBrowserInfoManager and should not be // created directly. @@ -44,23 +46,24 @@ class CefBrowserInfo : public base::RefCountedThreadSafe { // May return NULL if the browser has not yet been created or if the browser // has been destroyed. - CefRefPtr browser() const; + CefRefPtr browser() const; - // Set or clear the browser. Called from the CefBrowserHostImpl constructor + // Set or clear the browser. Called from CefBrowserHostBase InitializeBrowser // (to set) and DestroyBrowser (to clear). - void SetBrowser(CefRefPtr browser); + void SetBrowser(CefRefPtr browser); // Ensure that a frame record exists for |host|. Called for the main frame // when the RenderView is created, or for a sub-frame when the associated // RenderFrame is created in the renderer process. - // Called from CefBrowserHostImpl::RenderFrameCreated (is_guest_view = false) - // or CefMimeHandlerViewGuestDelegate::OnGuestAttached (is_guest_view = true). + // Called from CefBrowserContentsDelegate::RenderFrameCreated (is_guest_view = + // false) or CefMimeHandlerViewGuestDelegate::OnGuestAttached (is_guest_view = + // true). void MaybeCreateFrame(content::RenderFrameHost* host, bool is_guest_view); // Remove the frame record for |host|. Called for the main frame when the // RenderView is destroyed, or for a sub-frame when the associated RenderFrame // is destroyed in the renderer process. - // Called from CefBrowserHostImpl::FrameDeleted or + // Called from CefBrowserContentsDelegate::RenderFrameDeleted or // CefMimeHandlerViewGuestDelegate::OnGuestDetached. void RemoveFrame(content::RenderFrameHost* host); @@ -121,6 +124,28 @@ class CefBrowserInfo : public base::RefCountedThreadSafe { typedef std::set> FrameHostList; FrameHostList GetAllFrames() const; + class NavigationLock final : public base::RefCounted { + private: + friend class CefBrowserInfo; + friend class base::RefCounted; + + NavigationLock(); + ~NavigationLock(); + + base::OnceClosure pending_action_; + base::WeakPtrFactory weak_ptr_factory_; + }; + + // Block navigation actions on NavigationLock life span. Must be called on the + // UI thread. + scoped_refptr CreateNavigationLock(); + + // Returns true if navigation actions are currently blocked. If this method + // returns true the most recent |pending_action| will be executed on the UI + // thread once the navigation lock is released. Must be called on the UI + // thread. + bool IsNavigationLocked(base::OnceClosure pending_action); + private: friend class base::RefCountedThreadSafe; @@ -151,11 +176,15 @@ class CefBrowserInfo : public base::RefCountedThreadSafe { bool is_windowless_; CefRefPtr extra_info_; + // Navigation will be blocked while |navigation_lock_| exists. + // Only accessed on the UI thread. + base::WeakPtr navigation_lock_; + mutable base::Lock lock_; // The below members must be protected by |lock_|. - CefRefPtr browser_; + CefRefPtr browser_; // Owner of FrameInfo structs. typedef std::set, base::UniquePtrComparator> diff --git a/libcef/browser/browser_info_manager.cc b/libcef/browser/browser_info_manager.cc index d67b9b551..9f3635fc4 100644 --- a/libcef/browser/browser_info_manager.cc +++ b/libcef/browser/browser_info_manager.cc @@ -14,6 +14,7 @@ #include "libcef/common/cef_switches.h" #include "libcef/common/extensions/extensions_util.h" #include "libcef/common/values_impl.h" +#include "libcef/features/runtime_checks.h" #include "base/command_line.h" #include "base/logging.h" @@ -116,6 +117,7 @@ bool CefBrowserInfoManager::CanCreateWindow( bool opener_suppressed, bool* no_javascript_access) { CEF_REQUIRE_UIT(); + REQUIRE_ALLOY_RUNTIME(); content::OpenURLParams params(target_url, referrer, disposition, ui::PAGE_TRANSITION_LINK, @@ -180,7 +182,7 @@ bool CefBrowserInfoManager::CanCreateWindow( } if (allow) { - CefBrowserHostImpl::CreateParams create_params; + CefBrowserHostBase::CreateParams create_params; if (!browser->IsViewsHosted()) create_params.window_info = std::move(window_info); @@ -213,6 +215,7 @@ void CefBrowserInfoManager::GetCustomWebContentsView( content::WebContentsView** view, content::RenderViewHostDelegateView** delegate_view) { CEF_REQUIRE_UIT(); + REQUIRE_ALLOY_RUNTIME(); std::unique_ptr pending_popup = PopPendingPopup(CefBrowserInfoManager::PendingPopup::CAN_CREATE_WINDOW, @@ -240,6 +243,7 @@ void CefBrowserInfoManager::WebContentsCreated( std::unique_ptr& platform_delegate, CefRefPtr& extra_info) { CEF_REQUIRE_UIT(); + REQUIRE_ALLOY_RUNTIME(); std::unique_ptr pending_popup = PopPendingPopup( @@ -332,7 +336,7 @@ void CefBrowserInfoManager::DestroyAllBrowsers() { if (!list.empty()) { BrowserInfoList::iterator it = list.begin(); for (; it != list.end(); ++it) { - CefRefPtr browser = (*it)->browser(); + CefRefPtr browser = (*it)->browser(); DCHECK(browser.get()); if (browser.get()) { // DestroyBrowser will call RemoveBrowserInfo. @@ -363,10 +367,11 @@ bool CefBrowserInfoManager::MaybeAllowNavigation( const content::OpenURLParams& params, CefRefPtr& browser_out) const { CEF_REQUIRE_UIT(); + REQUIRE_ALLOY_RUNTIME(); bool is_guest_view = false; - CefRefPtr browser = - extensions::GetOwnerBrowserForHost(opener, &is_guest_view); + CefRefPtr browser = static_cast( + extensions::GetOwnerBrowserForHost(opener, &is_guest_view).get()); if (!browser) { // Print preview uses a modal dialog where we don't own the WebContents. // Allow that navigation to proceed. diff --git a/libcef/browser/browser_info_manager.h b/libcef/browser/browser_info_manager.h index 55236b3aa..5c1ebf970 100644 --- a/libcef/browser/browser_info_manager.h +++ b/libcef/browser/browser_info_manager.h @@ -37,6 +37,8 @@ namespace IPC { class Message; } +class CefBrowserHostBase; +class CefBrowserHostImpl; class CefBrowserPlatformDelegate; // Singleton object for managing BrowserInfo instances. @@ -48,7 +50,8 @@ class CefBrowserInfoManager : public content::RenderProcessHostObserver { // Returns this singleton instance of this class. static CefBrowserInfoManager* GetInstance(); - // Called from CefBrowserHostImpl::Create when a new browser is being created + // Called from CefBrowserHostImpl::Create or + // ChromeBrowserDelegate::SetAsDelegate when a new browser is being created // directly. In this case |is_popup| will be true only for DevTools browsers. scoped_refptr CreateBrowserInfo( bool is_popup, @@ -107,7 +110,7 @@ class CefBrowserInfoManager : public content::RenderProcessHostObserver { int render_routing_id, IPC::Message* reply_msg); - // Called from CefBrowserHostImpl::DestroyBrowser() when a browser is + // Called from CefBrowserHostBase::DestroyBrowser() when a browser is // destroyed. void RemoveBrowserInfo(scoped_refptr browser_info); @@ -116,7 +119,7 @@ class CefBrowserInfoManager : public content::RenderProcessHostObserver { // Returns the CefBrowserInfo matching the specified IDs or nullptr if no // match is found. It is allowed to add new callers of this method but - // consider using CefBrowserHostImpl::GetBrowserForFrameRoute() or + // consider using CefBrowserHostBase::GetBrowserForFrameRoute() or // extensions::GetOwnerBrowserForFrameRoute() instead. If |is_guest_view| is // non-nullptr it will be set to true if the IDs match a guest view associated // with the returned browser info instead of the browser itself. @@ -127,7 +130,7 @@ class CefBrowserInfoManager : public content::RenderProcessHostObserver { // Returns the CefBrowserInfo matching the specified ID or nullptr if no match // is found. It is allowed to add new callers of this method but consider - // using CefBrowserHostImpl::GetBrowserForFrameTreeNode() instead. If + // using CefBrowserHostBase::GetBrowserForFrameTreeNode() instead. If // |is_guest_view| is non-nullptr it will be set to true if the IDs match a // guest view associated with the returned browser info instead of the browser // itself. diff --git a/libcef/browser/browser_platform_delegate.h b/libcef/browser/browser_platform_delegate.h index b5f2741c8..801422219 100644 --- a/libcef/browser/browser_platform_delegate.h +++ b/libcef/browser/browser_platform_delegate.h @@ -54,13 +54,13 @@ class CefBrowserPlatformDelegate { // Create a new CefBrowserPlatformDelegate instance. May be called on multiple // threads. static std::unique_ptr Create( - CefBrowserHostImpl::CreateParams& create_params); + CefBrowserHostBase::CreateParams& create_params); // Called from CefBrowserHostImpl::Create. // Wait for the call to WebContentsCreated(owned=true) before taking ownership // of the resulting WebContents object. virtual content::WebContents* CreateWebContents( - CefBrowserHostImpl::CreateParams& create_params, + CefBrowserHostBase::CreateParams& create_params, bool& own_web_contents) = 0; // Called to create the view objects for a new WebContents. Will only be diff --git a/libcef/browser/browser_platform_delegate_create.cc b/libcef/browser/browser_platform_delegate_create.cc index b3fcf6120..d6f6fc05d 100644 --- a/libcef/browser/browser_platform_delegate_create.cc +++ b/libcef/browser/browser_platform_delegate_create.cc @@ -11,7 +11,6 @@ #include "base/memory/ptr_util.h" #include "build/build_config.h" -#include "libcef/browser/chrome/browser_platform_delegate_chrome.h" #include "libcef/browser/extensions/browser_platform_delegate_background.h" #include "libcef/features/runtime_checks.h" @@ -69,7 +68,7 @@ std::unique_ptr CreateOSRDelegate( // static std::unique_ptr CefBrowserPlatformDelegate::Create( - CefBrowserHostImpl::CreateParams& create_params) { + CefBrowserHostBase::CreateParams& create_params) { const bool is_windowless = create_params.window_info && create_params.window_info->windowless_rendering_enabled && @@ -77,10 +76,6 @@ std::unique_ptr CefBrowserPlatformDelegate::Create( const SkColor background_color = CefContext::Get()->GetBackgroundColor( &create_params.settings, is_windowless ? STATE_ENABLED : STATE_DISABLED); - if (cef::IsChromeRuntimeEnabled()) { - return std::make_unique(background_color); - } - if (create_params.window_info) { std::unique_ptr native_delegate = CreateNativeDelegate(*create_params.window_info.get(), diff --git a/libcef/browser/chrome/browser_delegate.h b/libcef/browser/chrome/browser_delegate.h new file mode 100644 index 000000000..9e01825df --- /dev/null +++ b/libcef/browser/chrome/browser_delegate.h @@ -0,0 +1,45 @@ +// Copyright 2020 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. + +#ifndef CEF_LIBCEF_BROWSER_CHROME_BROWSER_DELEGATE_H_ +#define CEF_LIBCEF_BROWSER_CHROME_BROWSER_DELEGATE_H_ +#pragma once + +#include + +#include "base/memory/scoped_refptr.h" +#include "content/public/browser/web_contents_delegate.h" + +class Browser; + +namespace cef { + +// Delegate for the chrome Browser object. Lifespan is controlled by the Browser +// object. See the ChromeBrowserDelegate documentation for additional details. +// Only accessed on the UI thread. +class BrowserDelegate : public content::WebContentsDelegate { + public: + // Opaque ref-counted base class for CEF-specific parameters passed via + // Browser::CreateParams::cef_params and possibly shared by multiple Browser + // instances. + class CreateParams : public base::RefCounted { + public: + virtual ~CreateParams() {} + }; + + // Called from the Browser constructor to create a new delegate. + static std::unique_ptr Create( + Browser* browser, + scoped_refptr cef_params); + + ~BrowserDelegate() override {} + + // Add or remove ownership of the WebContents. + virtual void SetAsDelegate(content::WebContents* web_contents, + bool set_delegate) = 0; +}; + +} // namespace cef + +#endif // CEF_LIBCEF_BROWSER_CHROME_BROWSER_DELEGATE_H_ diff --git a/libcef/browser/chrome/browser_platform_delegate_chrome.cc b/libcef/browser/chrome/browser_platform_delegate_chrome.cc deleted file mode 100644 index a8bd9a249..000000000 --- a/libcef/browser/chrome/browser_platform_delegate_chrome.cc +++ /dev/null @@ -1,138 +0,0 @@ -// Copyright 2020 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/chrome/browser_platform_delegate_chrome.h" - -#include "base/logging.h" -#include "chrome/browser/ui/browser.h" -#include "chrome/browser/ui/browser_tabstrip.h" -#include "chrome/browser/ui/browser_window.h" -#include "chrome/browser/ui/tabs/tab_strip_model.h" - -CefBrowserPlatformDelegateChrome::CefBrowserPlatformDelegateChrome( - SkColor background_color) - : background_color_(background_color) {} - -content::WebContents* CefBrowserPlatformDelegateChrome::CreateWebContents( - CefBrowserHostImpl::CreateParams& create_params, - bool& own_web_contents) { - // Get or create the request context and profile. - CefRefPtr request_context_impl = - CefRequestContextImpl::GetOrCreateForRequestContext( - create_params.request_context); - CHECK(request_context_impl); - auto cef_browser_context = request_context_impl->GetBrowserContext(); - CHECK(cef_browser_context); - auto profile = cef_browser_context->AsProfile(); - - if (!create_params.request_context) { - // Using the global request context. - create_params.request_context = request_context_impl.get(); - } - - // Create a Browser. - Browser::CreateParams params = - Browser::CreateParams(profile, /*user_gesture=*/false); - chrome_browser_ = new Browser(params); - - chrome::AddTabAt(chrome_browser_, create_params.url, /*idx=*/-1, - /*foreground=*/true); - - auto web_contents = - chrome_browser_->tab_strip_model()->GetActiveWebContents(); - CHECK(web_contents); - - own_web_contents = false; - return web_contents; -} - -void CefBrowserPlatformDelegateChrome::WebContentsDestroyed( - content::WebContents* web_contents) { - CefBrowserPlatformDelegate::WebContentsDestroyed(web_contents); - - // TODO(chrome-runtime): Find a better way to be notified of Browser - // destruction. - browser_->WindowDestroyed(); -} - -void CefBrowserPlatformDelegateChrome::BrowserDestroyed( - CefBrowserHostImpl* browser) { - CefBrowserPlatformDelegate::BrowserDestroyed(browser); - - // Release the reference added in CreateHostWindow. - browser->Release(); -} - -bool CefBrowserPlatformDelegateChrome::CreateHostWindow() { - // Keep a reference to the CEF browser. - browser_->AddRef(); - - chrome_browser_->window()->Show(); - return true; -} - -void CefBrowserPlatformDelegateChrome::CloseHostWindow() {} - -CefWindowHandle CefBrowserPlatformDelegateChrome::GetHostWindowHandle() const { - return kNullWindowHandle; -} - -SkColor CefBrowserPlatformDelegateChrome::GetBackgroundColor() const { - return background_color_; -} - -void CefBrowserPlatformDelegateChrome::WasResized() {} - -void CefBrowserPlatformDelegateChrome::SendKeyEvent(const CefKeyEvent& event) {} - -void CefBrowserPlatformDelegateChrome::SendMouseClickEvent( - const CefMouseEvent& event, - CefBrowserHost::MouseButtonType type, - bool mouseUp, - int clickCount) {} - -void CefBrowserPlatformDelegateChrome::SendMouseMoveEvent( - const CefMouseEvent& event, - bool mouseLeave) {} - -void CefBrowserPlatformDelegateChrome::SendMouseWheelEvent( - const CefMouseEvent& event, - int deltaX, - int deltaY) {} - -void CefBrowserPlatformDelegateChrome::SendTouchEvent( - const CefTouchEvent& event) {} - -void CefBrowserPlatformDelegateChrome::SendFocusEvent(bool setFocus) {} - -gfx::Point CefBrowserPlatformDelegateChrome::GetScreenPoint( - const gfx::Point& view) const { - return view; -} - -void CefBrowserPlatformDelegateChrome::ViewText(const std::string& text) {} - -bool CefBrowserPlatformDelegateChrome::HandleKeyboardEvent( - const content::NativeWebKeyboardEvent& event) { - return false; -} - -CefEventHandle CefBrowserPlatformDelegateChrome::GetEventHandle( - const content::NativeWebKeyboardEvent& event) const { - return kNullEventHandle; -} - -std::unique_ptr -CefBrowserPlatformDelegateChrome::CreateMenuRunner() { - NOTIMPLEMENTED(); - return nullptr; -} - -bool CefBrowserPlatformDelegateChrome::IsWindowless() const { - return false; -} - -bool CefBrowserPlatformDelegateChrome::IsViewsHosted() const { - return false; -} diff --git a/libcef/browser/chrome/browser_platform_delegate_chrome.h b/libcef/browser/chrome/browser_platform_delegate_chrome.h deleted file mode 100644 index a19855b97..000000000 --- a/libcef/browser/chrome/browser_platform_delegate_chrome.h +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright 2020 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. - -#ifndef CEF_LIBCEF_BROWSER_CHROME_BROWSER_PLATFORM_DELEGATE_CHROME_H_ -#define CEF_LIBCEF_BROWSER_CHROME_BROWSER_PLATFORM_DELEGATE_CHROME_H_ - -#include "libcef/browser/browser_platform_delegate.h" - -class Browser; - -// Implementation of Chrome-based browser functionality. -class CefBrowserPlatformDelegateChrome : public CefBrowserPlatformDelegate { - public: - explicit CefBrowserPlatformDelegateChrome(SkColor background_color); - - // CefBrowserPlatformDelegate overrides. - content::WebContents* CreateWebContents( - CefBrowserHostImpl::CreateParams& create_params, - bool& own_web_contents) override; - void WebContentsDestroyed(content::WebContents* web_contents) override; - void BrowserDestroyed(CefBrowserHostImpl* browser) override; - bool CreateHostWindow() override; - void CloseHostWindow() override; - CefWindowHandle GetHostWindowHandle() const override; - SkColor GetBackgroundColor() const override; - void WasResized() override; - void SendKeyEvent(const CefKeyEvent& event) override; - void SendMouseClickEvent(const CefMouseEvent& event, - CefBrowserHost::MouseButtonType type, - bool mouseUp, - int clickCount) override; - void SendMouseMoveEvent(const CefMouseEvent& event, bool mouseLeave) override; - void SendMouseWheelEvent(const CefMouseEvent& event, - int deltaX, - int deltaY) override; - void SendTouchEvent(const CefTouchEvent& event) override; - void SendFocusEvent(bool setFocus) override; - gfx::Point GetScreenPoint(const gfx::Point& view) const override; - void ViewText(const std::string& text) override; - bool HandleKeyboardEvent( - const content::NativeWebKeyboardEvent& event) override; - CefEventHandle GetEventHandle( - const content::NativeWebKeyboardEvent& event) const override; - std::unique_ptr CreateMenuRunner() override; - bool IsWindowless() const override; - bool IsViewsHosted() const override; - - private: - const SkColor background_color_; - - Browser* chrome_browser_; -}; - -#endif // CEF_LIBCEF_BROWSER_CHROME_BROWSER_PLATFORM_DELEGATE_CHROME_H_ diff --git a/libcef/browser/chrome/chrome_browser_delegate.cc b/libcef/browser/chrome/chrome_browser_delegate.cc new file mode 100644 index 000000000..5d781c20b --- /dev/null +++ b/libcef/browser/chrome/chrome_browser_delegate.cc @@ -0,0 +1,158 @@ +// Copyright 2020 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 + +#include "libcef/browser/chrome/chrome_browser_delegate.h" + +#include "libcef/browser/browser_contents_delegate.h" +#include "libcef/browser/browser_host_base.h" +#include "libcef/browser/browser_info_manager.h" +#include "libcef/browser/chrome/chrome_browser_host_impl.h" +#include "libcef/browser/request_context_impl.h" +#include "libcef/common/app_manager.h" + +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/browser.h" + +ChromeBrowserDelegate::ChromeBrowserDelegate( + Browser* browser, + const CefBrowserHostBase::CreateParams& create_params) + : browser_(browser), create_params_(create_params) { + DCHECK(browser_); +} + +ChromeBrowserDelegate::~ChromeBrowserDelegate() = default; + +void ChromeBrowserDelegate::SetAsDelegate(content::WebContents* web_contents, + bool set_delegate) { + DCHECK(web_contents); + auto browser_host = + ChromeBrowserHostImpl::GetBrowserForContents(web_contents); + + // |set_delegate=false| only makes sense if we already have a browser host. + DCHECK(browser_host || set_delegate); + + if (browser_host) { + // We already have a browser host, so just change the associated Browser. + browser_host->SetBrowser(set_delegate ? browser_ : nullptr); + return; + } + + auto request_context_impl = + CefRequestContextImpl::GetOrCreateForRequestContext( + create_params_.request_context); + + // Check if chrome and CEF are using the same browser context. + // TODO(chrome-runtime): Verify if/when this might occur. + auto chrome_browser_context = + CefBrowserContext::FromBrowserContext(browser_->create_params().profile); + if (chrome_browser_context != request_context_impl->GetBrowserContext()) { + LOG(WARNING) << "Creating a chrome browser with mismatched context"; + } + + CefRefPtr client = create_params_.client; + if (!client) { + if (auto app = CefAppManager::Get()->GetApplication()) { + if (auto bph = app->GetBrowserProcessHandler()) { + client = bph->GetDefaultClient(); + } + } + } + + if (!client) { + LOG(WARNING) << "Creating a chrome browser without a client"; + } + + auto browser_info = CefBrowserInfoManager::GetInstance()->CreateBrowserInfo( + /*is_popup=*/false, /*is_windowless=*/false, create_params_.extra_info); + + browser_host = new ChromeBrowserHostImpl(create_params_.settings, client, + browser_info, request_context_impl); + browser_host->Attach(browser_, web_contents); +} + +void ChromeBrowserDelegate::LoadingStateChanged(content::WebContents* source, + bool to_different_document) { + if (auto delegate = GetDelegateForWebContents(source)) { + delegate->LoadingStateChanged(source, to_different_document); + } +} + +void ChromeBrowserDelegate::UpdateTargetURL(content::WebContents* source, + const GURL& url) { + if (auto delegate = GetDelegateForWebContents(source)) { + delegate->UpdateTargetURL(source, url); + } +} + +bool ChromeBrowserDelegate::DidAddMessageToConsole( + content::WebContents* source, + blink::mojom::ConsoleMessageLevel log_level, + const base::string16& message, + int32_t line_no, + const base::string16& source_id) { + if (auto delegate = GetDelegateForWebContents(source)) { + return delegate->DidAddMessageToConsole(source, log_level, message, line_no, + source_id); + } + return false; +} + +void ChromeBrowserDelegate::DidNavigateMainFramePostCommit( + content::WebContents* web_contents) { + if (auto delegate = GetDelegateForWebContents(web_contents)) { + delegate->DidNavigateMainFramePostCommit(web_contents); + } +} + +void ChromeBrowserDelegate::EnterFullscreenModeForTab( + content::RenderFrameHost* requesting_frame, + const blink::mojom::FullscreenOptions& options) { + auto web_contents = + content::WebContents::FromRenderFrameHost(requesting_frame); + if (!web_contents) + return; + + if (auto delegate = GetDelegateForWebContents(web_contents)) { + delegate->EnterFullscreenModeForTab(requesting_frame, options); + } +} + +void ChromeBrowserDelegate::ExitFullscreenModeForTab( + content::WebContents* web_contents) { + if (auto delegate = GetDelegateForWebContents(web_contents)) { + delegate->ExitFullscreenModeForTab(web_contents); + } +} + +CefBrowserContentsDelegate* ChromeBrowserDelegate::GetDelegateForWebContents( + content::WebContents* web_contents) { + auto browser_host = + ChromeBrowserHostImpl::GetBrowserForContents(web_contents); + if (browser_host) + return browser_host->contents_delegate(); + return nullptr; +} + +namespace cef { + +// static +std::unique_ptr BrowserDelegate::Create( + Browser* browser, + scoped_refptr cef_params) { + CefBrowserHostBase::CreateParams create_params; + + // Parameters from ChromeBrowserHostImpl::Create, or nullptr if the Browser + // was created from somewhere else. + auto params = static_cast( + cef_params.get()); + if (params) { + create_params = params->create_params_; + } + + return std::make_unique(browser, create_params); +} + +} // namespace cef diff --git a/libcef/browser/chrome/chrome_browser_delegate.h b/libcef/browser/chrome/chrome_browser_delegate.h new file mode 100644 index 000000000..485e44a29 --- /dev/null +++ b/libcef/browser/chrome/chrome_browser_delegate.h @@ -0,0 +1,80 @@ +// Copyright 2020 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. + +#ifndef CEF_LIBCEF_BROWSER_CHROME_CHROME_BROWSER_DELEGATE_H_ +#define CEF_LIBCEF_BROWSER_CHROME_CHROME_BROWSER_DELEGATE_H_ +#pragma once + +#include + +#include "libcef/browser/browser_host_base.h" +#include "libcef/browser/browser_info.h" +#include "libcef/browser/chrome/browser_delegate.h" + +#include "base/optional.h" + +class CefBrowserContentsDelegate; +class CefRequestContextImpl; +class ChromeBrowserHostImpl; + +// Implementation of the cef::BrowserDelegate interface. Lifespan is controlled +// by the Browser object. Only accessed on the UI thread. +// +// The Browser object represents the top-level Chrome browser window. One or +// more tabs (WebContents) are then owned by the Browser object via +// TabStripModel. A new Browser object can be created programmatically using +// "new Browser" or Browser::Create, or as a result of user action such as +// dragging a tab out of an existing window. New or existing tabs can also be +// added to an already existing Browser object. +// +// The Browser object acts as the WebContentsDelegate for all attached tabs. CEF +// integration requires WebContentsDelegate callbacks and notification of tab +// attach/detach. To support this integration a cef::BrowserDelegate +// (ChromeBrowserDelegate) member is created in the Browser constructor and +// receives delegation for the Browser callbacks. ChromeBrowserDelegate creates +// a new ChromeBrowserHostImpl when a tab is added to a Browser for the first +// time, and that ChromeBrowserHostImpl continues to exist until the tab's +// WebContents is destroyed. The associated WebContents object does not change, +// but the Browser object will change when the tab is dragged between windows. +class ChromeBrowserDelegate : public cef::BrowserDelegate { + public: + ChromeBrowserDelegate(Browser* browser, + const CefBrowserHostBase::CreateParams& create_params); + ~ChromeBrowserDelegate() override; + + // cef::BrowserDelegate methods: + void SetAsDelegate(content::WebContents* web_contents, + bool set_delegate) override; + + // WebContentsDelegate methods: + void LoadingStateChanged(content::WebContents* source, + bool to_different_document) override; + void UpdateTargetURL(content::WebContents* source, const GURL& url) override; + bool DidAddMessageToConsole(content::WebContents* source, + blink::mojom::ConsoleMessageLevel log_level, + const base::string16& message, + int32_t line_no, + const base::string16& source_id) override; + void DidNavigateMainFramePostCommit( + content::WebContents* web_contents) override; + void EnterFullscreenModeForTab( + content::RenderFrameHost* requesting_frame, + const blink::mojom::FullscreenOptions& options) override; + void ExitFullscreenModeForTab(content::WebContents* web_contents) override; + + Browser* browser() const { return browser_; } + + private: + CefBrowserContentsDelegate* GetDelegateForWebContents( + content::WebContents* web_contents); + + Browser* const browser_; + + // Used when creating a new browser host. + const CefBrowserHostBase::CreateParams create_params_; + + DISALLOW_COPY_AND_ASSIGN(ChromeBrowserDelegate); +}; + +#endif // CEF_LIBCEF_BROWSER_CHROME_CHROME_BROWSER_DELEGATE_H_ diff --git a/libcef/browser/chrome/chrome_browser_host_impl.cc b/libcef/browser/chrome/chrome_browser_host_impl.cc new file mode 100644 index 000000000..80cbabf3e --- /dev/null +++ b/libcef/browser/chrome/chrome_browser_host_impl.cc @@ -0,0 +1,508 @@ +// Copyright 2020 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/chrome/chrome_browser_host_impl.h" + +#include "libcef/browser/thread_util.h" +#include "libcef/features/runtime_checks.h" + +#include "base/logging.h" +#include "base/notreached.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_commands.h" +#include "chrome/browser/ui/browser_tabstrip.h" +#include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/tabs/tab_strip_model.h" + +namespace { + +const auto kDefaultWindowDisposition = WindowOpenDisposition::CURRENT_TAB; + +} // namespace + +// static +CefRefPtr ChromeBrowserHostImpl::Create( + const CreateParams& params) { + // Get or create the request context and profile. + CefRefPtr request_context_impl = + CefRequestContextImpl::GetOrCreateForRequestContext( + params.request_context); + CHECK(request_context_impl); + auto cef_browser_context = request_context_impl->GetBrowserContext(); + CHECK(cef_browser_context); + auto profile = cef_browser_context->AsProfile(); + + Browser::CreateParams chrome_params = + Browser::CreateParams(profile, /*user_gesture=*/false); + + // Pass |params| to cef::BrowserDelegate::Create from the Browser constructor. + chrome_params.cef_params = base::MakeRefCounted(params); + + // Create the Browser. This will indirectly create the ChomeBrowserDelegate. + // The same params will be used to create a new Browser if the tab is dragged + // out of the existing Browser. + auto browser = new Browser(chrome_params); + + // Add a new tab. This will indirectly create a new tab WebContents and + // call ChromeBrowserDelegate::SetAsDelegate to create the associated + // ChromeBrowserHostImpl. + chrome::AddTabAt(browser, params.url, /*idx=*/-1, /*foreground=*/true); + + browser->window()->Show(); + + // The new tab WebContents. + auto web_contents = browser->tab_strip_model()->GetActiveWebContents(); + DCHECK(web_contents); + + // The associated ChromeBrowserHostImpl. + auto browser_host = + ChromeBrowserHostImpl::GetBrowserForContents(web_contents); + DCHECK(browser_host); + return browser_host; +} + +// static +CefRefPtr ChromeBrowserHostImpl::GetBrowserForHost( + const content::RenderViewHost* host) { + REQUIRE_CHROME_RUNTIME(); + auto browser = CefBrowserHostBase::GetBrowserForHost(host); + return static_cast(browser.get()); +} + +// static +CefRefPtr ChromeBrowserHostImpl::GetBrowserForHost( + const content::RenderFrameHost* host) { + REQUIRE_CHROME_RUNTIME(); + auto browser = CefBrowserHostBase::GetBrowserForHost(host); + return static_cast(browser.get()); +} + +// static +CefRefPtr ChromeBrowserHostImpl::GetBrowserForContents( + const content::WebContents* contents) { + REQUIRE_CHROME_RUNTIME(); + auto browser = CefBrowserHostBase::GetBrowserForContents(contents); + return static_cast(browser.get()); +} + +// static +CefRefPtr +ChromeBrowserHostImpl::GetBrowserForFrameTreeNode(int frame_tree_node_id) { + REQUIRE_CHROME_RUNTIME(); + auto browser = + CefBrowserHostBase::GetBrowserForFrameTreeNode(frame_tree_node_id); + return static_cast(browser.get()); +} + +// static +CefRefPtr ChromeBrowserHostImpl::GetBrowserForFrameRoute( + int render_process_id, + int render_routing_id) { + REQUIRE_CHROME_RUNTIME(); + auto browser = CefBrowserHostBase::GetBrowserForFrameRoute(render_process_id, + render_routing_id); + return static_cast(browser.get()); +} + +ChromeBrowserHostImpl::~ChromeBrowserHostImpl() = default; + +void ChromeBrowserHostImpl::OnWebContentsDestroyed() { + DestroyBrowser(); +} + +void ChromeBrowserHostImpl::OnSetFocus(cef_focus_source_t source) { + NOTIMPLEMENTED(); +} + +void ChromeBrowserHostImpl::ViewText(const std::string& text) { + NOTIMPLEMENTED(); +} + +void ChromeBrowserHostImpl::CloseBrowser(bool force_close) { + NOTIMPLEMENTED(); +} + +bool ChromeBrowserHostImpl::TryCloseBrowser() { + NOTIMPLEMENTED(); + return false; +} + +void ChromeBrowserHostImpl::SetFocus(bool focus) { + NOTIMPLEMENTED(); +} + +CefWindowHandle ChromeBrowserHostImpl::GetWindowHandle() { + NOTIMPLEMENTED(); + return kNullWindowHandle; +} + +CefWindowHandle ChromeBrowserHostImpl::GetOpenerWindowHandle() { + NOTIMPLEMENTED(); + return kNullWindowHandle; +} + +bool ChromeBrowserHostImpl::HasView() { + NOTIMPLEMENTED(); + return false; +} + +double ChromeBrowserHostImpl::GetZoomLevel() { + NOTIMPLEMENTED(); + return 0.0; +} + +void ChromeBrowserHostImpl::SetZoomLevel(double zoomLevel) { + NOTIMPLEMENTED(); +} + +void ChromeBrowserHostImpl::RunFileDialog( + FileDialogMode mode, + const CefString& title, + const CefString& default_file_path, + const std::vector& accept_filters, + int selected_accept_filter, + CefRefPtr callback) { + NOTIMPLEMENTED(); + callback->OnFileDialogDismissed(0, {}); +} + +void ChromeBrowserHostImpl::Print() { + if (!CEF_CURRENTLY_ON_UIT()) { + CEF_POST_TASK(CEF_UIT, base::BindOnce(&ChromeBrowserHostImpl::Print, this)); + return; + } + + if (browser_) { + chrome::Print(browser_); + } +} + +void ChromeBrowserHostImpl::PrintToPDF( + const CefString& path, + const CefPdfPrintSettings& settings, + CefRefPtr callback) { + NOTIMPLEMENTED(); + callback->OnPdfPrintFinished(CefString(), false); +} + +void ChromeBrowserHostImpl::Find(int identifier, + const CefString& searchText, + bool forward, + bool matchCase, + bool findNext) { + NOTIMPLEMENTED(); +} + +void ChromeBrowserHostImpl::StopFinding(bool clearSelection) { + NOTIMPLEMENTED(); +} + +void ChromeBrowserHostImpl::ShowDevTools(const CefWindowInfo& windowInfo, + CefRefPtr client, + const CefBrowserSettings& settings, + const CefPoint& inspect_element_at) { + NOTIMPLEMENTED(); +} + +void ChromeBrowserHostImpl::CloseDevTools() { + NOTIMPLEMENTED(); +} + +bool ChromeBrowserHostImpl::HasDevTools() { + NOTIMPLEMENTED(); + return false; +} + +bool ChromeBrowserHostImpl::SendDevToolsMessage(const void* message, + size_t message_size) { + NOTIMPLEMENTED(); + return false; +} + +int ChromeBrowserHostImpl::ExecuteDevToolsMethod( + int message_id, + const CefString& method, + CefRefPtr params) { + NOTIMPLEMENTED(); + return 0; +} + +CefRefPtr ChromeBrowserHostImpl::AddDevToolsMessageObserver( + CefRefPtr observer) { + NOTIMPLEMENTED(); + return nullptr; +} + +void ChromeBrowserHostImpl::SetMouseCursorChangeDisabled(bool disabled) { + NOTIMPLEMENTED(); +} + +bool ChromeBrowserHostImpl::IsMouseCursorChangeDisabled() { + NOTIMPLEMENTED(); + return false; +} + +bool ChromeBrowserHostImpl::IsWindowRenderingDisabled() { + return false; +} + +void ChromeBrowserHostImpl::WasResized() { + NOTIMPLEMENTED(); +} + +void ChromeBrowserHostImpl::WasHidden(bool hidden) { + NOTIMPLEMENTED(); +} + +void ChromeBrowserHostImpl::NotifyScreenInfoChanged() { + NOTIMPLEMENTED(); +} + +void ChromeBrowserHostImpl::Invalidate(PaintElementType type) { + NOTIMPLEMENTED(); +} + +void ChromeBrowserHostImpl::SendExternalBeginFrame() { + NOTIMPLEMENTED(); +} + +void ChromeBrowserHostImpl::SendKeyEvent(const CefKeyEvent& event) { + NOTIMPLEMENTED(); +} + +void ChromeBrowserHostImpl::SendMouseClickEvent(const CefMouseEvent& event, + MouseButtonType type, + bool mouseUp, + int clickCount) { + NOTIMPLEMENTED(); +} + +void ChromeBrowserHostImpl::SendMouseMoveEvent(const CefMouseEvent& event, + bool mouseLeave) { + NOTIMPLEMENTED(); +} + +void ChromeBrowserHostImpl::SendMouseWheelEvent(const CefMouseEvent& event, + int deltaX, + int deltaY) { + NOTIMPLEMENTED(); +} + +void ChromeBrowserHostImpl::SendTouchEvent(const CefTouchEvent& event) { + NOTIMPLEMENTED(); +} + +void ChromeBrowserHostImpl::SendFocusEvent(bool setFocus) { + NOTIMPLEMENTED(); +} + +void ChromeBrowserHostImpl::SendCaptureLostEvent() { + NOTIMPLEMENTED(); +} + +void ChromeBrowserHostImpl::NotifyMoveOrResizeStarted() { + NOTIMPLEMENTED(); +} + +int ChromeBrowserHostImpl::GetWindowlessFrameRate() { + return 0; +} + +void ChromeBrowserHostImpl::SetWindowlessFrameRate(int frame_rate) {} + +void ChromeBrowserHostImpl::ImeSetComposition( + const CefString& text, + const std::vector& underlines, + const CefRange& replacement_range, + const CefRange& selection_range) { + NOTIMPLEMENTED(); +} + +void ChromeBrowserHostImpl::ImeCommitText(const CefString& text, + const CefRange& replacement_range, + int relative_cursor_pos) { + NOTIMPLEMENTED(); +} +void ChromeBrowserHostImpl::ImeFinishComposingText(bool keep_selection) { + NOTIMPLEMENTED(); +} + +void ChromeBrowserHostImpl::ImeCancelComposition() { + NOTIMPLEMENTED(); +} + +void ChromeBrowserHostImpl::DragTargetDragEnter( + CefRefPtr drag_data, + const CefMouseEvent& event, + DragOperationsMask allowed_ops) { + NOTIMPLEMENTED(); +} + +void ChromeBrowserHostImpl::DragTargetDragOver(const CefMouseEvent& event, + DragOperationsMask allowed_ops) { + NOTIMPLEMENTED(); +} + +void ChromeBrowserHostImpl::DragTargetDragLeave() { + NOTIMPLEMENTED(); +} + +void ChromeBrowserHostImpl::DragTargetDrop(const CefMouseEvent& event) { + NOTIMPLEMENTED(); +} + +void ChromeBrowserHostImpl::DragSourceSystemDragEnded() { + NOTIMPLEMENTED(); +} + +void ChromeBrowserHostImpl::DragSourceEndedAt(int x, + int y, + DragOperationsMask op) { + NOTIMPLEMENTED(); +} + +void ChromeBrowserHostImpl::SetAudioMuted(bool mute) { + NOTIMPLEMENTED(); +} + +bool ChromeBrowserHostImpl::IsAudioMuted() { + NOTIMPLEMENTED(); + return false; +} + +void ChromeBrowserHostImpl::SetAccessibilityState( + cef_state_t accessibility_state) { + NOTIMPLEMENTED(); +} + +void ChromeBrowserHostImpl::SetAutoResizeEnabled(bool enabled, + const CefSize& min_size, + const CefSize& max_size) { + NOTIMPLEMENTED(); +} + +CefRefPtr ChromeBrowserHostImpl::GetExtension() { + return nullptr; +} + +bool ChromeBrowserHostImpl::IsBackgroundHost() { + return false; +} + +void ChromeBrowserHostImpl::GoBack() { + auto callback = base::BindOnce(&ChromeBrowserHostImpl::GoBack, this); + if (!CEF_CURRENTLY_ON_UIT()) { + CEF_POST_TASK(CEF_UIT, std::move(callback)); + } + + if (browser_info_->IsNavigationLocked(std::move(callback))) { + return; + } + + if (browser_ && chrome::CanGoBack(browser_)) { + chrome::GoBack(browser_, kDefaultWindowDisposition); + } +} + +void ChromeBrowserHostImpl::GoForward() { + auto callback = base::BindOnce(&ChromeBrowserHostImpl::GoForward, this); + if (!CEF_CURRENTLY_ON_UIT()) { + CEF_POST_TASK(CEF_UIT, std::move(callback)); + } + + if (browser_info_->IsNavigationLocked(std::move(callback))) { + return; + } + + if (browser_ && chrome::CanGoForward(browser_)) { + chrome::GoForward(browser_, kDefaultWindowDisposition); + } +} + +void ChromeBrowserHostImpl::Reload() { + auto callback = base::BindOnce(&ChromeBrowserHostImpl::Reload, this); + if (!CEF_CURRENTLY_ON_UIT()) { + CEF_POST_TASK(CEF_UIT, std::move(callback)); + } + + if (browser_info_->IsNavigationLocked(std::move(callback))) { + return; + } + + if (browser_) { + chrome::Reload(browser_, kDefaultWindowDisposition); + } +} + +void ChromeBrowserHostImpl::ReloadIgnoreCache() { + auto callback = + base::BindOnce(&ChromeBrowserHostImpl::ReloadIgnoreCache, this); + if (!CEF_CURRENTLY_ON_UIT()) { + CEF_POST_TASK(CEF_UIT, std::move(callback)); + } + + if (browser_info_->IsNavigationLocked(std::move(callback))) { + return; + } + + if (browser_) { + chrome::ReloadBypassingCache(browser_, kDefaultWindowDisposition); + } +} + +void ChromeBrowserHostImpl::StopLoad() { + auto callback = base::BindOnce(&ChromeBrowserHostImpl::StopLoad, this); + if (!CEF_CURRENTLY_ON_UIT()) { + CEF_POST_TASK(CEF_UIT, std::move(callback)); + } + + if (browser_info_->IsNavigationLocked(std::move(callback))) { + return; + } + + if (browser_) { + chrome::Stop(browser_); + } +} + +ChromeBrowserHostImpl::ChromeBrowserHostImpl( + const CefBrowserSettings& settings, + CefRefPtr client, + scoped_refptr browser_info, + CefRefPtr request_context) + : CefBrowserHostBase(settings, client, browser_info, request_context) {} + +void ChromeBrowserHostImpl::Attach(Browser* browser, + content::WebContents* web_contents) { + DCHECK(browser); + DCHECK(web_contents); + + SetBrowser(browser); + contents_delegate_->ObserveWebContents(web_contents); + InitializeBrowser(); +} + +void ChromeBrowserHostImpl::SetBrowser(Browser* browser) { + CEF_REQUIRE_UIT(); + browser_ = browser; +} + +void ChromeBrowserHostImpl::InitializeBrowser() { + CEF_REQUIRE_UIT(); + DCHECK(browser_); + + CefBrowserHostBase::InitializeBrowser(); + + OnAfterCreated(); +} + +void ChromeBrowserHostImpl::DestroyBrowser() { + CEF_REQUIRE_UIT(); + browser_ = nullptr; + + OnBeforeClose(); + OnBrowserDestroyed(); + + CefBrowserHostBase::DestroyBrowser(); +} diff --git a/libcef/browser/chrome/chrome_browser_host_impl.h b/libcef/browser/chrome/chrome_browser_host_impl.h new file mode 100644 index 000000000..511151c8c --- /dev/null +++ b/libcef/browser/chrome/chrome_browser_host_impl.h @@ -0,0 +1,179 @@ +// Copyright 2020 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. + +#ifndef CEF_LIBCEF_BROWSER_CHROME_CHROME_BROWSER_HOST_IMPL_H_ +#define CEF_LIBCEF_BROWSER_CHROME_CHROME_BROWSER_HOST_IMPL_H_ +#pragma once + +#include "libcef/browser/browser_host_base.h" +#include "libcef/browser/chrome/browser_delegate.h" + +class Browser; +class ChromeBrowserDelegate; + +// CefBrowser implementation for the chrome runtime. Method calls are delegated +// to the chrome Browser object or the WebContents as appropriate. See the +// ChromeBrowserDelegate documentation for additional details. All methods are +// thread-safe unless otherwise indicated. +class ChromeBrowserHostImpl : public CefBrowserHostBase { + public: + // CEF-specific parameters passed via Browser::CreateParams::cef_params and + // possibly shared by multiple Browser instances. + class DelegateCreateParams : public cef::BrowserDelegate::CreateParams { + public: + DelegateCreateParams(const CefBrowserHostBase::CreateParams& create_params) + : create_params_(create_params) {} + + CefBrowserHostBase::CreateParams create_params_; + }; + + // Create a new Browser with a single tab (WebContents) and associated + // ChromeBrowserHostImpl instance. + static CefRefPtr Create(const CreateParams& params); + + // Returns the browser associated with the specified RenderViewHost. + static CefRefPtr GetBrowserForHost( + const content::RenderViewHost* host); + // Returns the browser associated with the specified RenderFrameHost. + static CefRefPtr GetBrowserForHost( + const content::RenderFrameHost* host); + // Returns the browser associated with the specified WebContents. + static CefRefPtr GetBrowserForContents( + const content::WebContents* contents); + // Returns the browser associated with the specified FrameTreeNode ID. + static CefRefPtr GetBrowserForFrameTreeNode( + int frame_tree_node_id); + // Returns the browser associated with the specified frame routing IDs. + static CefRefPtr GetBrowserForFrameRoute( + int render_process_id, + int render_routing_id); + + ~ChromeBrowserHostImpl() override; + + // CefBrowserContentsDelegate::Observer methods: + void OnWebContentsDestroyed() override; + + // CefBrowserHostBase methods called from CefFrameHostImpl: + void OnSetFocus(cef_focus_source_t source) override; + void ViewText(const std::string& text) override; + + // CefBrowserHost methods: + void CloseBrowser(bool force_close) override; + bool TryCloseBrowser() override; + void SetFocus(bool focus) override; + CefWindowHandle GetWindowHandle() override; + CefWindowHandle GetOpenerWindowHandle() override; + bool HasView() override; + double GetZoomLevel() override; + void SetZoomLevel(double zoomLevel) override; + void RunFileDialog(FileDialogMode mode, + const CefString& title, + const CefString& default_file_path, + const std::vector& accept_filters, + int selected_accept_filter, + CefRefPtr callback) override; + void Print() override; + void PrintToPDF(const CefString& path, + const CefPdfPrintSettings& settings, + CefRefPtr callback) override; + void Find(int identifier, + const CefString& searchText, + bool forward, + bool matchCase, + bool findNext) override; + void StopFinding(bool clearSelection) override; + void ShowDevTools(const CefWindowInfo& windowInfo, + CefRefPtr client, + const CefBrowserSettings& settings, + const CefPoint& inspect_element_at) override; + void CloseDevTools() override; + bool HasDevTools() override; + bool SendDevToolsMessage(const void* message, size_t message_size) override; + int ExecuteDevToolsMethod(int message_id, + const CefString& method, + CefRefPtr params) override; + CefRefPtr AddDevToolsMessageObserver( + CefRefPtr observer) override; + void SetMouseCursorChangeDisabled(bool disabled) override; + bool IsMouseCursorChangeDisabled() override; + bool IsWindowRenderingDisabled() override; + void WasResized() override; + void WasHidden(bool hidden) override; + void NotifyScreenInfoChanged() override; + void Invalidate(PaintElementType type) override; + void SendExternalBeginFrame() override; + void SendKeyEvent(const CefKeyEvent& event) override; + void SendMouseClickEvent(const CefMouseEvent& event, + MouseButtonType type, + bool mouseUp, + int clickCount) override; + void SendMouseMoveEvent(const CefMouseEvent& event, bool mouseLeave) override; + void SendMouseWheelEvent(const CefMouseEvent& event, + int deltaX, + int deltaY) override; + void SendTouchEvent(const CefTouchEvent& event) override; + void SendFocusEvent(bool setFocus) override; + void SendCaptureLostEvent() override; + void NotifyMoveOrResizeStarted() override; + int GetWindowlessFrameRate() override; + void SetWindowlessFrameRate(int frame_rate) override; + void ImeSetComposition(const CefString& text, + const std::vector& underlines, + const CefRange& replacement_range, + const CefRange& selection_range) override; + void ImeCommitText(const CefString& text, + const CefRange& replacement_range, + int relative_cursor_pos) override; + void ImeFinishComposingText(bool keep_selection) override; + void ImeCancelComposition() override; + void DragTargetDragEnter(CefRefPtr drag_data, + const CefMouseEvent& event, + DragOperationsMask allowed_ops) override; + void DragTargetDragOver(const CefMouseEvent& event, + DragOperationsMask allowed_ops) override; + void DragTargetDragLeave() override; + void DragTargetDrop(const CefMouseEvent& event) override; + void DragSourceSystemDragEnded() override; + void DragSourceEndedAt(int x, int y, DragOperationsMask op) override; + void SetAudioMuted(bool mute) override; + bool IsAudioMuted() override; + void SetAccessibilityState(cef_state_t accessibility_state) override; + void SetAutoResizeEnabled(bool enabled, + const CefSize& min_size, + const CefSize& max_size) override; + CefRefPtr GetExtension() override; + bool IsBackgroundHost() override; + + // CefBrowser methods: + void GoBack() override; + void GoForward() override; + void Reload() override; + void ReloadIgnoreCache() override; + void StopLoad() override; + + private: + friend class ChromeBrowserDelegate; + + ChromeBrowserHostImpl(const CefBrowserSettings& settings, + CefRefPtr client, + scoped_refptr browser_info, + CefRefPtr request_context); + + // Called from ChromeBrowserDelegate::SetAsDelegate when this object is first + // created. Must be called on the UI thread. + void Attach(Browser* browser, content::WebContents* web_contents); + + // Called from ChromeBrowserDelegate::SetAsDelegate when this object changes + // Browser ownership (e.g. dragging between windows). The old Browser will be + // cleared before the new Browser is added. Must be called on the UI thread. + void SetBrowser(Browser* browser); + + // CefBrowserHostBase methods: + void InitializeBrowser() override; + void DestroyBrowser() override; + + Browser* browser_ = nullptr; +}; + +#endif // CEF_LIBCEF_BROWSER_CHROME_CHROME_BROWSER_HOST_IMPL_H_ diff --git a/libcef/browser/devtools/devtools_frontend.cc b/libcef/browser/devtools/devtools_frontend.cc index 540ab7435..3398368b8 100644 --- a/libcef/browser/devtools/devtools_frontend.cc +++ b/libcef/browser/devtools/devtools_frontend.cc @@ -249,7 +249,7 @@ CefDevToolsFrontend* CefDevToolsFrontend::Show( new_settings.background_color = SK_ColorWHITE; } - CefBrowserHostImpl::CreateParams create_params; + CefBrowserHostBase::CreateParams create_params; if (!inspected_browser->IsViewsHosted()) create_params.window_info.reset(new CefWindowInfo(windowInfo)); create_params.client = client; diff --git a/libcef/browser/download_manager_delegate.cc b/libcef/browser/download_manager_delegate.cc index 9a949cd21..dc04c05c1 100644 --- a/libcef/browser/download_manager_delegate.cc +++ b/libcef/browser/download_manager_delegate.cc @@ -5,6 +5,7 @@ #include "libcef/browser/download_manager_delegate.h" #include "include/cef_download_handler.h" +#include "libcef/browser/browser_host_impl.h" #include "libcef/browser/context.h" #include "libcef/browser/download_item_impl.h" #include "libcef/browser/thread_util.h" @@ -405,7 +406,7 @@ std::string CefDownloadManagerDelegate::ApplicationClientIdForFileScanning() { } void CefDownloadManagerDelegate::OnBrowserDestroyed( - CefBrowserHostImpl* browser) { + CefBrowserHostBase* browser) { ItemBrowserMap::iterator it = item_browser_map_.begin(); for (; it != item_browser_map_.end(); ++it) { if (it->second == browser) { diff --git a/libcef/browser/download_manager_delegate.h b/libcef/browser/download_manager_delegate.h index 86a54ba5a..4f5b3fe93 100644 --- a/libcef/browser/download_manager_delegate.h +++ b/libcef/browser/download_manager_delegate.h @@ -8,7 +8,7 @@ #include -#include "libcef/browser/browser_host_impl.h" +#include "libcef/browser/browser_host_base.h" #include "base/compiler_specific.h" #include "base/memory/weak_ptr.h" @@ -16,10 +16,12 @@ #include "content/public/browser/download_manager.h" #include "content/public/browser/download_manager_delegate.h" +class CefBrowserHostImpl; + class CefDownloadManagerDelegate : public download::DownloadItem::Observer, public content::DownloadManager::Observer, public content::DownloadManagerDelegate, - public CefBrowserHostImpl::Observer { + public CefBrowserHostBase::Observer { public: explicit CefDownloadManagerDelegate(content::DownloadManager* manager); ~CefDownloadManagerDelegate() override; @@ -41,8 +43,8 @@ class CefDownloadManagerDelegate : public download::DownloadItem::Observer, void GetNextId(content::DownloadIdCallback callback) override; std::string ApplicationClientIdForFileScanning() override; - // CefBrowserHostImpl::Observer methods. - void OnBrowserDestroyed(CefBrowserHostImpl* browser) override; + // CefBrowserHostBase::Observer methods. + void OnBrowserDestroyed(CefBrowserHostBase* browser) override; CefBrowserHostImpl* GetOrAssociateBrowser(download::DownloadItem* item); CefBrowserHostImpl* GetBrowser(download::DownloadItem* item); diff --git a/libcef/browser/extensions/browser_extensions_util.cc b/libcef/browser/extensions/browser_extensions_util.cc index 4c797668d..02e8c7f6e 100644 --- a/libcef/browser/extensions/browser_extensions_util.cc +++ b/libcef/browser/extensions/browser_extensions_util.cc @@ -5,9 +5,12 @@ #include "libcef/browser/extensions/browser_extensions_util.h" #include "libcef/browser/browser_context.h" +#include "libcef/browser/browser_host_base.h" +#include "libcef/browser/browser_host_impl.h" #include "libcef/browser/browser_info_manager.h" #include "libcef/browser/thread_util.h" #include "libcef/common/extensions/extensions_util.h" +#include "libcef/features/runtime_checks.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/printing/print_preview_dialog_controller.h" @@ -16,6 +19,8 @@ #include "content/browser/web_contents/web_contents_impl.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_plugin_guest_manager.h" +#include "content/public/browser/render_frame_host.h" +#include "content/public/browser/render_view_host.h" #include "extensions/browser/extension_registry.h" namespace extensions { @@ -69,7 +74,7 @@ content::WebContents* GetOwnerForGuestContents(content::WebContents* guest) { return print_preview_controller->GetInitiator(guest); } -CefRefPtr GetOwnerBrowserForFrameRoute( +CefRefPtr GetOwnerBrowserForFrameRoute( int render_process_id, int render_routing_id, bool* is_guest_view) { @@ -86,7 +91,7 @@ CefRefPtr GetOwnerBrowserForFrameRoute( CefBrowserInfoManager::GetInstance()->GetBrowserInfoForFrameRoute( render_process_id, render_routing_id, is_guest_view); if (info.get()) { - CefRefPtr browser = info->browser(); + CefRefPtr browser = info->browser(); if (!browser.get()) { LOG(WARNING) << "Found browser id " << info->browser_id() << " but no browser object matching view process id " @@ -99,20 +104,20 @@ CefRefPtr GetOwnerBrowserForFrameRoute( } } -CefRefPtr GetOwnerBrowserForHost( +CefRefPtr GetOwnerBrowserForHost( content::RenderViewHost* host, bool* is_guest_view) { if (is_guest_view) *is_guest_view = false; - CefRefPtr browser = - CefBrowserHostImpl::GetBrowserForHost(host); + CefRefPtr browser = + CefBrowserHostBase::GetBrowserForHost(host); if (!browser.get() && ExtensionsEnabled()) { // Retrieve the owner browser, if any. content::WebContents* owner = GetOwnerForGuestContents( content::WebContents::FromRenderViewHost(host)); if (owner) { - browser = CefBrowserHostImpl::GetBrowserForContents(owner); + browser = CefBrowserHostBase::GetBrowserForContents(owner); if (browser.get() && is_guest_view) *is_guest_view = true; } @@ -120,20 +125,20 @@ CefRefPtr GetOwnerBrowserForHost( return browser; } -CefRefPtr GetOwnerBrowserForHost( +CefRefPtr GetOwnerBrowserForHost( content::RenderFrameHost* host, bool* is_guest_view) { if (is_guest_view) *is_guest_view = false; - CefRefPtr browser = - CefBrowserHostImpl::GetBrowserForHost(host); + CefRefPtr browser = + CefBrowserHostBase::GetBrowserForHost(host); if (!browser.get() && ExtensionsEnabled()) { // Retrieve the owner browser, if any. content::WebContents* owner = GetOwnerForGuestContents( content::WebContents::FromRenderFrameHost(host)); if (owner) { - browser = CefBrowserHostImpl::GetBrowserForContents(owner); + browser = CefBrowserHostBase::GetBrowserForContents(owner); if (browser.get() && is_guest_view) *is_guest_view = true; } @@ -144,6 +149,7 @@ CefRefPtr GetOwnerBrowserForHost( CefRefPtr GetBrowserForTabId( int tab_id, content::BrowserContext* browser_context) { + REQUIRE_ALLOY_RUNTIME(); CEF_REQUIRE_UIT(); DCHECK(browser_context); if (tab_id < 0 || !browser_context) @@ -154,7 +160,8 @@ CefRefPtr GetBrowserForTabId( for (const auto& browser_info : CefBrowserInfoManager::GetInstance()->GetBrowserInfoList()) { - CefRefPtr current_browser = browser_info->browser(); + CefRefPtr current_browser = + static_cast(browser_info->browser().get()); if (current_browser && current_browser->GetIdentifier() == tab_id) { // Make sure we're operating in the same CefBrowserContext. if (CefBrowserContext::FromBrowserContext( diff --git a/libcef/browser/extensions/browser_extensions_util.h b/libcef/browser/extensions/browser_extensions_util.h index 9e98431f7..d62dbb669 100644 --- a/libcef/browser/extensions/browser_extensions_util.h +++ b/libcef/browser/extensions/browser_extensions_util.h @@ -7,16 +7,20 @@ #include -#include "libcef/browser/browser_host_impl.h" +#include "include/internal/cef_ptr.h" #include "url/gurl.h" namespace content { class BrowserContext; +class RenderFrameHost; class RenderViewHost; class WebContents; } // namespace content +class CefBrowserHostBase; +class CefBrowserHostImpl; + namespace extensions { class Extension; @@ -32,24 +36,24 @@ void GetAllGuestsForOwnerContents(content::WebContents* owner, // Returns the WebContents that owns the specified |guest|, if any. content::WebContents* GetOwnerForGuestContents(content::WebContents* guest); -// Returns the CefBrowserHostImpl that owns the host identified by the specified +// Returns the CefBrowserHostBase that owns the host identified by the specified // routing IDs, if any. |is_guest_view| will be set to true if the IDs // match a guest view associated with the returned browser instead of the // browser itself. -CefRefPtr GetOwnerBrowserForFrameRoute( +CefRefPtr GetOwnerBrowserForFrameRoute( int render_process_id, int render_routing_id, bool* is_guest_view); -// Returns the CefBrowserHostImpl that owns the specified |host|, if any. +// Returns the CefBrowserHostBase that owns the specified |host|, if any. // |is_guest_view| will be set to true if the host matches a guest view // associated with the returned browser instead of the browser itself. // TODO(cef): Delete the RVH variant once the remaining use case // (via AlloyContentBrowserClient::OverrideWebkitPrefs) has been removed. -CefRefPtr GetOwnerBrowserForHost( +CefRefPtr GetOwnerBrowserForHost( content::RenderViewHost* host, bool* is_guest_view); -CefRefPtr GetOwnerBrowserForHost( +CefRefPtr GetOwnerBrowserForHost( content::RenderFrameHost* host, bool* is_guest_view); diff --git a/libcef/browser/extensions/extension_function_details.cc b/libcef/browser/extensions/extension_function_details.cc index e199ac493..b1824a1ef 100644 --- a/libcef/browser/extensions/extension_function_details.cc +++ b/libcef/browser/extensions/extension_function_details.cc @@ -365,7 +365,7 @@ base::DictionaryValue* CefExtensionFunctionDetails::OpenTab( if (!request_context) return nullptr; - CefBrowserHostImpl::CreateParams create_params; + CefBrowserHostBase::CreateParams create_params; create_params.url = url; create_params.request_context = request_context; create_params.window_info.reset(new CefWindowInfo); diff --git a/libcef/browser/extensions/extensions_browser_client.cc b/libcef/browser/extensions/extensions_browser_client.cc index 3751ce70c..9212ce7d0 100644 --- a/libcef/browser/extensions/extensions_browser_client.cc +++ b/libcef/browser/extensions/extensions_browser_client.cc @@ -250,7 +250,7 @@ bool CefExtensionsBrowserClient::CreateBackgroundExtensionHost( return true; } - CefBrowserHostImpl::CreateParams create_params; + CefBrowserHostBase::CreateParams create_params; create_params.url = url; create_params.request_context = request_context; diff --git a/libcef/browser/frame_host_impl.cc b/libcef/browser/frame_host_impl.cc index 7b2f6056f..589803d92 100644 --- a/libcef/browser/frame_host_impl.cc +++ b/libcef/browser/frame_host_impl.cc @@ -8,7 +8,7 @@ #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/browser_host_base.h" #include "libcef/browser/navigate_params.h" #include "libcef/browser/net_service/browser_urlrequest_impl.h" #include "libcef/common/cef_messages.h" @@ -45,7 +45,7 @@ class ViewTextHandler : public CefResponseManager::Handler { void OnResponse(const Cef_Response_Params& params) override { CefRefPtr browser = frame_->GetBrowser(); if (browser.get()) { - static_cast(browser.get()) + static_cast(browser.get()) ->ViewText(params.response); } } @@ -114,7 +114,7 @@ void CefFrameHostImpl::SetRenderFrameHost(content::RenderFrameHost* host) { } bool CefFrameHostImpl::IsValid() { - return !!GetBrowserHostImpl(); + return !!GetBrowserHostBase(); } void CefFrameHostImpl::Undo() { @@ -203,7 +203,7 @@ CefRefPtr CefFrameHostImpl::GetParent() { parent_frame_id = parent_frame_id_; } - auto browser = GetBrowserHostImpl(); + auto browser = GetBrowserHostBase(); if (browser) return browser->GetFrame(parent_frame_id); @@ -216,7 +216,7 @@ CefString CefFrameHostImpl::GetURL() { } CefRefPtr CefFrameHostImpl::GetBrowser() { - return GetBrowserHostImpl().get(); + return GetBrowserHostBase().get(); } CefRefPtr CefFrameHostImpl::GetV8Context() { @@ -239,7 +239,7 @@ CefRefPtr CefFrameHostImpl::CreateURLRequest( return nullptr; } - auto browser = GetBrowserHostImpl(); + auto browser = GetBrowserHostBase(); if (!browser) return nullptr; @@ -323,7 +323,7 @@ void CefFrameHostImpl::Navigate(const CefNavigateParams& params) { Send(new CefMsg_LoadRequest(MSG_ROUTING_NONE, request)); - auto browser = GetBrowserHostImpl(); + auto browser = GetBrowserHostBase(); if (browser) browser->OnSetFocus(FOCUS_SOURCE_NAVIGATION); } @@ -339,7 +339,7 @@ void CefFrameHostImpl::LoadURLWithExtras(const std::string& url, if (frame_id == CefFrameHostImpl::kMainFrameId) { // Load via the browser using NavigationController. - auto browser = GetBrowserHostImpl(); + auto browser = GetBrowserHostBase(); if (browser) { browser->LoadMainFrameURL(url, referrer, transition, extra_headers); } @@ -553,7 +553,7 @@ int64 CefFrameHostImpl::GetFrameId() const { return is_main_frame_ ? kMainFrameId : frame_id_; } -CefRefPtr CefFrameHostImpl::GetBrowserHostImpl() const { +CefRefPtr CefFrameHostImpl::GetBrowserHostBase() const { base::AutoLock lock_scope(state_lock_); if (browser_info_) return browser_info_->browser(); @@ -572,14 +572,14 @@ void CefFrameHostImpl::OnAttached() { void CefFrameHostImpl::OnDidFinishLoad(const GURL& validated_url, int http_status_code) { - auto browser = GetBrowserHostImpl(); + auto browser = GetBrowserHostBase(); if (browser) browser->OnDidFinishLoad(this, validated_url, http_status_code); } void CefFrameHostImpl::OnUpdateDraggableRegions( const std::vector& regions) { - auto browser = GetBrowserHostImpl(); + auto browser = GetBrowserHostBase(); if (!browser) return; @@ -611,12 +611,12 @@ void CefFrameHostImpl::OnRequest(const Cef_Request_Params& params) { bool expect_response_ack = false; if (params.user_initiated) { - auto browser = GetBrowserHostImpl(); - if (browser && browser->client()) { + auto browser = GetBrowserHostBase(); + if (browser && browser->GetClient()) { // Give the user a chance to handle the request. CefRefPtr message(new CefProcessMessageImpl( const_cast(¶ms), false, true)); - success = browser->client()->OnProcessMessageReceived( + success = browser->GetClient()->OnProcessMessageReceived( browser.get(), this, PID_RENDERER, message.get()); message->Detach(nullptr); } diff --git a/libcef/browser/frame_host_impl.h b/libcef/browser/frame_host_impl.h index 4342502ed..a7411c529 100644 --- a/libcef/browser/frame_host_impl.h +++ b/libcef/browser/frame_host_impl.h @@ -31,7 +31,7 @@ struct Cef_DraggableRegion_Params; struct Cef_Request_Params; struct Cef_Response_Params; class CefBrowserInfo; -class CefBrowserHostImpl; +class CefBrowserHostBase; struct CefNavigateParams; // Implementation of CefFrame. CefFrameHostImpl objects should always be created @@ -112,10 +112,10 @@ class CefFrameHostImpl : public CefFrame { const std::string& scriptUrl, int startLine); - // Called from CefBrowserHostImpl::DidStopLoading. + // Called from CefBrowserHostBase::DidStopLoading. void MaybeSendDidStopLoading(); - // Called from CefBrowserHostImpl::OnMessageReceived. + // Called from CefBrowserHostBase::OnMessageReceived. bool OnMessageReceived(const IPC::Message& message); void ExecuteJavaScriptWithUserGestureForTests(const CefString& javascript); @@ -145,7 +145,7 @@ class CefFrameHostImpl : public CefFrame { private: int64 GetFrameId() const; - CefRefPtr GetBrowserHostImpl() const; + CefRefPtr GetBrowserHostBase() const; // OnMessageReceived message handlers. void OnAttached(); diff --git a/libcef/browser/net_service/resource_request_handler_wrapper.cc b/libcef/browser/net_service/resource_request_handler_wrapper.cc index 828232da2..2631b0850 100644 --- a/libcef/browser/net_service/resource_request_handler_wrapper.cc +++ b/libcef/browser/net_service/resource_request_handler_wrapper.cc @@ -4,7 +4,7 @@ #include "libcef/browser/net_service/resource_request_handler_wrapper.h" -#include "libcef/browser/browser_host_impl.h" +#include "libcef/browser/browser_host_base.h" #include "libcef/browser/browser_platform_delegate.h" #include "libcef/browser/context.h" #include "libcef/browser/iothread_state.h" @@ -80,7 +80,7 @@ class RequestCallbackWrapper : public CefRequestCallback { }; std::string GetAcceptLanguageList(content::BrowserContext* browser_context, - CefRefPtr browser) { + CefRefPtr browser) { if (browser) { const CefBrowserSettings& browser_settings = browser->settings(); if (browser_settings.accept_language_list.length > 0) { @@ -163,10 +163,10 @@ class InterceptedRequestHandlerWrapper : public InterceptedRequestHandler { // Observer to receive notification of CEF context or associated browser // destruction. Only one of the *Destroyed() methods will be called. - class DestructionObserver : public CefBrowserHostImpl::Observer, + class DestructionObserver : public CefBrowserHostBase::Observer, public CefContext::Observer { public: - explicit DestructionObserver(CefBrowserHostImpl* browser) { + explicit DestructionObserver(CefBrowserHostBase* browser) { if (browser) { browser_info_ = browser->browser_info(); browser->AddObserver(this); @@ -198,7 +198,7 @@ class InterceptedRequestHandlerWrapper : public InterceptedRequestHandler { wrapper_ = wrapper; } - void OnBrowserDestroyed(CefBrowserHostImpl* browser) override { + void OnBrowserDestroyed(CefBrowserHostBase* browser) override { CEF_REQUIRE_UIT(); browser->RemoveObserver(this); registered_ = false; @@ -249,7 +249,7 @@ class InterceptedRequestHandlerWrapper : public InterceptedRequestHandler { } void Initialize(content::BrowserContext* browser_context, - CefRefPtr browser, + CefRefPtr browser, CefRefPtr frame, int render_process_id, int render_frame_id, @@ -310,7 +310,7 @@ class InterceptedRequestHandlerWrapper : public InterceptedRequestHandler { bool initialized_ = false; - CefRefPtr browser_; + CefRefPtr browser_; CefRefPtr frame_; CefIOThreadState* iothread_state_ = nullptr; CefBrowserContext::CookieableSchemes cookieable_schemes_; @@ -1239,13 +1239,13 @@ void InitOnUIThread( } } - CefRefPtr browserPtr; + CefRefPtr browserPtr; CefRefPtr framePtr; // |frame| may be null for service worker requests. if (frame) { // May return nullptr for requests originating from guest views. - browserPtr = CefBrowserHostImpl::GetBrowserForHost(frame); + browserPtr = CefBrowserHostBase::GetBrowserForHost(frame); if (browserPtr) { framePtr = browserPtr->GetFrameForHost(frame); if (frame_tree_node_id < 0) @@ -1282,7 +1282,7 @@ std::unique_ptr CreateInterceptedRequestHandler( bool is_download, const url::Origin& request_initiator) { CEF_REQUIRE_UIT(); - CefRefPtr browserPtr; + CefRefPtr browserPtr; CefRefPtr framePtr; int render_frame_id = -1; int frame_tree_node_id = -1; @@ -1293,7 +1293,7 @@ std::unique_ptr CreateInterceptedRequestHandler( frame_tree_node_id = frame->GetFrameTreeNodeId(); // May return nullptr for requests originating from guest views. - browserPtr = CefBrowserHostImpl::GetBrowserForHost(frame); + browserPtr = CefBrowserHostBase::GetBrowserForHost(frame); if (browserPtr) { framePtr = browserPtr->GetFrameForHost(frame); DCHECK(framePtr); diff --git a/libcef/browser/prefs/renderer_prefs.cc b/libcef/browser/prefs/renderer_prefs.cc index 6e3175761..b0af2034a 100644 --- a/libcef/browser/prefs/renderer_prefs.cc +++ b/libcef/browser/prefs/renderer_prefs.cc @@ -6,10 +6,12 @@ #include +#include "libcef/browser/browser_host_impl.h" #include "libcef/browser/context.h" #include "libcef/browser/extensions/browser_extensions_util.h" #include "libcef/common/cef_switches.h" #include "libcef/common/extensions/extensions_util.h" +#include "libcef/features/runtime_checks.h" #include "base/command_line.h" #include "base/i18n/character_encoding.h" @@ -349,8 +351,9 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry, void PopulateWebPreferences(content::RenderViewHost* rvh, content::WebPreferences& web) { - CefRefPtr browser = - extensions::GetOwnerBrowserForHost(rvh, nullptr); + REQUIRE_ALLOY_RUNTIME(); + CefRefPtr browser = static_cast( + extensions::GetOwnerBrowserForHost(rvh, nullptr).get()); // Set defaults for preferences that are not handled by PrefService. SetDefaultPrefs(web); diff --git a/libcef/browser/printing/print_dialog_linux.cc b/libcef/browser/printing/print_dialog_linux.cc index c2f3796cd..c10d733eb 100644 --- a/libcef/browser/printing/print_dialog_linux.cc +++ b/libcef/browser/printing/print_dialog_linux.cc @@ -149,9 +149,8 @@ void CefPrintDialogLinux::OnPrintStart(int render_process_id, if (!handler.get()) return; - CefRefPtr browser = - extensions::GetOwnerBrowserForFrameRoute(render_process_id, - render_routing_id, nullptr); + auto browser = extensions::GetOwnerBrowserForFrameRoute( + render_process_id, render_routing_id, nullptr); if (browser.get()) handler->OnPrintStart(browser.get()); } diff --git a/libcef/browser/printing/print_dialog_linux.h b/libcef/browser/printing/print_dialog_linux.h index 7f01e09e8..4209ab408 100644 --- a/libcef/browser/printing/print_dialog_linux.h +++ b/libcef/browser/printing/print_dialog_linux.h @@ -7,7 +7,7 @@ #define LIBCEF_BROWSER_PRINTING_PRINT_DIALOG_LINUX_H_ #include "include/cef_print_handler.h" -#include "libcef/browser/browser_host_impl.h" +#include "libcef/browser/browser_host_base.h" #include "base/compiler_specific.h" #include "base/files/file_path.h" @@ -87,7 +87,7 @@ class CefPrintDialogLinux : public printing::PrintDialogGtkInterface, // Printing dialog callback. PrintingContextLinux::PrintSettingsCallback callback_; PrintingContextLinux* context_; - CefRefPtr browser_; + CefRefPtr browser_; base::FilePath path_to_pdf_; diff --git a/libcef/browser/views/browser_view_impl.cc b/libcef/browser/views/browser_view_impl.cc index 64fd7821b..84ccf77ad 100644 --- a/libcef/browser/views/browser_view_impl.cc +++ b/libcef/browser/views/browser_view_impl.cc @@ -188,7 +188,7 @@ void CefBrowserViewImpl::SetPendingBrowserCreateParams( CefRefPtr extra_info, CefRefPtr request_context) { DCHECK(!pending_browser_create_params_); - pending_browser_create_params_.reset(new CefBrowserHostImpl::CreateParams()); + pending_browser_create_params_.reset(new CefBrowserHostBase::CreateParams()); pending_browser_create_params_->client = client; pending_browser_create_params_->url = GURL(url.ToString()); pending_browser_create_params_->settings = settings; diff --git a/libcef/browser/views/browser_view_impl.h b/libcef/browser/views/browser_view_impl.h index f35e647af..4b2484867 100644 --- a/libcef/browser/views/browser_view_impl.h +++ b/libcef/browser/views/browser_view_impl.h @@ -95,7 +95,7 @@ class CefBrowserViewImpl : public CefViewImpl + std::unique_ptr pending_browser_create_params_; CefRefPtr browser_; diff --git a/libcef/features/runtime_checks.h b/libcef/features/runtime_checks.h index be7327ac7..23f5c5e45 100644 --- a/libcef/features/runtime_checks.h +++ b/libcef/features/runtime_checks.h @@ -13,6 +13,6 @@ CHECK(cef::IsAlloyRuntimeEnabled()) << "Alloy runtime is required" #define REQUIRE_CHROME_RUNTIME() \ - CHECK(cef::IsChrimeRuntimeEnabled()) << "Chrome runtime is required" + CHECK(cef::IsChromeRuntimeEnabled()) << "Chrome runtime is required" #endif // CEF_LIBCEF_FEATURES_RUNTIME_CHECKS_H_ diff --git a/libcef_dll/cpptoc/browser_process_handler_cpptoc.cc b/libcef_dll/cpptoc/browser_process_handler_cpptoc.cc index de89eddbb..ceb5b402a 100644 --- a/libcef_dll/cpptoc/browser_process_handler_cpptoc.cc +++ b/libcef_dll/cpptoc/browser_process_handler_cpptoc.cc @@ -9,10 +9,11 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=7f01f5096df081ae224560eefba57b45fb9c758b$ +// $hash=94217ee1df26d037136df93adda612261606c569$ // #include "libcef_dll/cpptoc/browser_process_handler_cpptoc.h" +#include "libcef_dll/cpptoc/client_cpptoc.h" #include "libcef_dll/cpptoc/print_handler_cpptoc.h" #include "libcef_dll/ctocpp/command_line_ctocpp.h" @@ -81,6 +82,22 @@ void CEF_CALLBACK browser_process_handler_on_schedule_message_pump_work( delay_ms); } +struct _cef_client_t* CEF_CALLBACK browser_process_handler_get_default_client( + struct _cef_browser_process_handler_t* self) { + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) + return NULL; + + // Execute + CefRefPtr _retval = + CefBrowserProcessHandlerCppToC::Get(self)->GetDefaultClient(); + + // Return type: refptr_same + return CefClientCppToC::Wrap(_retval); +} + } // namespace // CONSTRUCTOR - Do not edit by hand. @@ -93,6 +110,7 @@ CefBrowserProcessHandlerCppToC::CefBrowserProcessHandlerCppToC() { GetStruct()->get_print_handler = browser_process_handler_get_print_handler; GetStruct()->on_schedule_message_pump_work = browser_process_handler_on_schedule_message_pump_work; + GetStruct()->get_default_client = browser_process_handler_get_default_client; } // DESTRUCTOR - Do not edit by hand. diff --git a/libcef_dll/ctocpp/browser_process_handler_ctocpp.cc b/libcef_dll/ctocpp/browser_process_handler_ctocpp.cc index a470ab5e1..d3e015502 100644 --- a/libcef_dll/ctocpp/browser_process_handler_ctocpp.cc +++ b/libcef_dll/ctocpp/browser_process_handler_ctocpp.cc @@ -9,11 +9,12 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=394c9b4009a90393aa15be216b5e44f1bafccdfb$ +// $hash=9e8f283905d68b7b97c13a568040dc12c2859ad3$ // #include "libcef_dll/ctocpp/browser_process_handler_ctocpp.h" #include "libcef_dll/cpptoc/command_line_cpptoc.h" +#include "libcef_dll/ctocpp/client_ctocpp.h" #include "libcef_dll/ctocpp/print_handler_ctocpp.h" // VIRTUAL METHODS - Body may be edited by hand. @@ -76,6 +77,21 @@ void CefBrowserProcessHandlerCToCpp::OnScheduleMessagePumpWork(int64 delay_ms) { _struct->on_schedule_message_pump_work(_struct, delay_ms); } +NO_SANITIZE("cfi-icall") +CefRefPtr CefBrowserProcessHandlerCToCpp::GetDefaultClient() { + cef_browser_process_handler_t* _struct = GetStruct(); + if (CEF_MEMBER_MISSING(_struct, get_default_client)) + return nullptr; + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Execute + cef_client_t* _retval = _struct->get_default_client(_struct); + + // Return type: refptr_same + return CefClientCToCpp::Wrap(_retval); +} + // CONSTRUCTOR - Do not edit by hand. CefBrowserProcessHandlerCToCpp::CefBrowserProcessHandlerCToCpp() {} diff --git a/libcef_dll/ctocpp/browser_process_handler_ctocpp.h b/libcef_dll/ctocpp/browser_process_handler_ctocpp.h index 121bec5b2..cc6c1b456 100644 --- a/libcef_dll/ctocpp/browser_process_handler_ctocpp.h +++ b/libcef_dll/ctocpp/browser_process_handler_ctocpp.h @@ -9,7 +9,7 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=79e6f729e377f1dca76c076d7c694f07b8e171e6$ +// $hash=857a8ad51f8b7ca9e62b9ce35d0cf510d84fb8b1$ // #ifndef CEF_LIBCEF_DLL_CTOCPP_BROWSER_PROCESS_HANDLER_CTOCPP_H_ @@ -40,6 +40,7 @@ class CefBrowserProcessHandlerCToCpp CefRefPtr command_line) override; CefRefPtr GetPrintHandler() override; void OnScheduleMessagePumpWork(int64 delay_ms) override; + CefRefPtr GetDefaultClient() override; }; #endif // CEF_LIBCEF_DLL_CTOCPP_BROWSER_PROCESS_HANDLER_CTOCPP_H_ diff --git a/patch/patch.cfg b/patch/patch.cfg index 27fc94d29..61b876bd9 100644 --- a/patch/patch.cfg +++ b/patch/patch.cfg @@ -217,6 +217,11 @@ patches = [ # https://bitbucket.org/chromiumembedded/cef/issues/2969 'name': 'chrome_runtime', }, + { + # Changes to support the Chrome runtime in CEF. + # https://bitbucket.org/chromiumembedded/cef/issues/2969 + 'name': 'chrome_browser_browser', + }, { # Don't initialize ExtensionSystemFactory when extensions are disabled. # https://bitbucket.org/chromiumembedded/cef/issues/2359 diff --git a/patch/patches/chrome_browser_browser.patch b/patch/patches/chrome_browser_browser.patch new file mode 100644 index 000000000..8a514f1a9 --- /dev/null +++ b/patch/patches/chrome_browser_browser.patch @@ -0,0 +1,180 @@ +diff --git chrome/browser/ui/browser.cc chrome/browser/ui/browser.cc +index 71ec3bbbf1b6..8b99a3ac7de2 100644 +--- chrome/browser/ui/browser.cc ++++ chrome/browser/ui/browser.cc +@@ -257,6 +257,20 @@ + #include "components/captive_portal/content/captive_portal_tab_helper.h" + #endif + ++#if BUILDFLAG(ENABLE_CEF) ++#define CALL_CEF_DELEGATE(name, ...) \ ++ if (cef_browser_delegate_) { \ ++ cef_browser_delegate_->name(__VA_ARGS__); \ ++ } ++#define CALL_CEF_DELEGATE_RETURN(name, ...) \ ++ if (cef_browser_delegate_) { \ ++ return cef_browser_delegate_->name(__VA_ARGS__); \ ++ } ++#else // !BUILDFLAG(ENABLE_CEF) ++#define CALL_CEF_DELEGATE(name, ...) ++#define CALL_CEF_DELEGATE_RETURN(name, ...) ++#endif ++ + #if BUILDFLAG(ENABLE_EXTENSIONS) + #include "chrome/browser/extensions/extension_browser_window_helper.h" + #endif +@@ -470,6 +484,13 @@ Browser::Browser(const CreateParams& params) + + CHECK(CanCreateBrowserForProfile(profile_)); + ++#if BUILDFLAG(ENABLE_CEF) ++ if (cef::IsChromeRuntimeEnabled()) { ++ cef_browser_delegate_ = ++ cef::BrowserDelegate::Create(this, params.cef_params); ++ } ++#endif ++ + tab_strip_model_->AddObserver(this); + + location_bar_model_ = std::make_unique( +@@ -1713,6 +1734,8 @@ void Browser::LoadingStateChanged(WebContents* source, + bool to_different_document) { + ScheduleUIUpdate(source, content::INVALIDATE_TYPE_LOAD); + UpdateWindowForLoadingStateChanged(source, to_different_document); ++ ++ CALL_CEF_DELEGATE(LoadingStateChanged, source, to_different_document); + } + + void Browser::CloseContents(WebContents* source) { +@@ -1740,6 +1763,8 @@ void Browser::SetContentsBounds(WebContents* source, const gfx::Rect& bounds) { + } + + void Browser::UpdateTargetURL(WebContents* source, const GURL& url) { ++ CALL_CEF_DELEGATE(UpdateTargetURL, source, url); ++ + if (!GetStatusBubble()) + return; + +@@ -1747,6 +1772,17 @@ void Browser::UpdateTargetURL(WebContents* source, const GURL& url) { + GetStatusBubble()->SetURL(url); + } + ++bool Browser::DidAddMessageToConsole( ++ content::WebContents* source, ++ blink::mojom::ConsoleMessageLevel log_level, ++ const base::string16& message, ++ int32_t line_no, ++ const base::string16& source_id) { ++ CALL_CEF_DELEGATE_RETURN(DidAddMessageToConsole, source, log_level, message, ++ line_no, source_id); ++ return false; ++} ++ + void Browser::ContentsMouseEvent(WebContents* source, + bool motion, + bool exited) { +@@ -1899,6 +1935,8 @@ void Browser::RendererResponsive( + void Browser::DidNavigateMainFramePostCommit(WebContents* web_contents) { + if (web_contents == tab_strip_model_->GetActiveWebContents()) + UpdateBookmarkBarState(BOOKMARK_BAR_STATE_CHANGE_TAB_STATE); ++ ++ CALL_CEF_DELEGATE(DidNavigateMainFramePostCommit, web_contents); + } + + content::JavaScriptDialogManager* Browser::GetJavaScriptDialogManager( +@@ -1949,11 +1987,15 @@ void Browser::EnterFullscreenModeForTab( + const blink::mojom::FullscreenOptions& options) { + exclusive_access_manager_->fullscreen_controller()->EnterFullscreenModeForTab( + requesting_frame, options.display_id); ++ ++ CALL_CEF_DELEGATE(EnterFullscreenModeForTab, requesting_frame, options); + } + + void Browser::ExitFullscreenModeForTab(WebContents* web_contents) { + exclusive_access_manager_->fullscreen_controller()->ExitFullscreenModeForTab( + web_contents); ++ ++ CALL_CEF_DELEGATE(ExitFullscreenModeForTab, web_contents); + } + + bool Browser::IsFullscreenForTabOrPending(const WebContents* web_contents) { +@@ -2814,6 +2856,8 @@ void Browser::SetAsDelegate(WebContents* web_contents, bool set_delegate) { + content_translate_driver->RemoveObserver(this); + BookmarkTabHelper::FromWebContents(web_contents)->RemoveObserver(this); + } ++ ++ CALL_CEF_DELEGATE(SetAsDelegate, web_contents, set_delegate); + } + + void Browser::CloseFrame() { +diff --git chrome/browser/ui/browser.h chrome/browser/ui/browser.h +index ab2a03e6e878..aef94abf4fd8 100644 +--- chrome/browser/ui/browser.h ++++ chrome/browser/ui/browser.h +@@ -21,6 +21,7 @@ + #include "base/strings/string16.h" + #include "base/timer/elapsed_timer.h" + #include "build/build_config.h" ++#include "cef/libcef/features/runtime.h" + #include "chrome/browser/devtools/devtools_toggle_action.h" + #include "chrome/browser/ui/bookmarks/bookmark_bar.h" + #include "chrome/browser/ui/bookmarks/bookmark_tab_helper_observer.h" +@@ -56,6 +57,10 @@ + #include "ui/gfx/geometry/rect.h" + #include "ui/shell_dialogs/select_file_dialog.h" + ++#if BUILDFLAG(ENABLE_CEF) ++#include "cef/libcef/browser/chrome/browser_delegate.h" ++#endif ++ + #if defined(OS_ANDROID) + #error This file should only be included on desktop. + #endif +@@ -241,6 +246,11 @@ class Browser : public TabStripModelObserver, + // default. Intended for testing. + BrowserWindow* window = nullptr; + ++#if BUILDFLAG(ENABLE_CEF) ++ // Opaque CEF-specific configuration. Will be propagated to new Browsers. ++ scoped_refptr cef_params; ++#endif ++ + private: + friend class Browser; + friend class WindowSizerChromeOSTest; +@@ -358,6 +368,12 @@ class Browser : public TabStripModelObserver, + return &signin_view_controller_; + } + ++#if BUILDFLAG(ENABLE_CEF) ++ cef::BrowserDelegate* cef_delegate() const { ++ return cef_browser_delegate_.get(); ++ } ++#endif ++ + // Get the FindBarController for this browser, creating it if it does not + // yet exist. + FindBarController* GetFindBarController(); +@@ -742,6 +758,11 @@ class Browser : public TabStripModelObserver, + void SetContentsBounds(content::WebContents* source, + const gfx::Rect& bounds) override; + void UpdateTargetURL(content::WebContents* source, const GURL& url) override; ++ bool DidAddMessageToConsole(content::WebContents* source, ++ blink::mojom::ConsoleMessageLevel log_level, ++ const base::string16& message, ++ int32_t line_no, ++ const base::string16& source_id) override; + void ContentsMouseEvent(content::WebContents* source, + bool motion, + bool exited) override; +@@ -1206,6 +1227,10 @@ class Browser : public TabStripModelObserver, + extension_browser_window_helper_; + #endif + ++#if BUILDFLAG(ENABLE_CEF) ++ std::unique_ptr cef_browser_delegate_; ++#endif ++ + const base::ElapsedTimer creation_timer_; + + // Stores the list of browser windows showing via a menu.