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.