diff --git a/BUILD.gn b/BUILD.gn index c6555da0f..6e0f1904b 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -1061,10 +1061,14 @@ static_library("libcef_static") { deps += [ "//ui/views", ] - } - if (use_aura) { sources += [ + "libcef/browser/chrome/views/browser_platform_delegate_chrome_views.cc", + "libcef/browser/chrome/views/browser_platform_delegate_chrome_views.h", + "libcef/browser/chrome/views/chrome_browser_frame.cc", + "libcef/browser/chrome/views/chrome_browser_frame.h", + "libcef/browser/chrome/views/chrome_browser_view.cc", + "libcef/browser/chrome/views/chrome_browser_view.h", "libcef/browser/native/window_delegate_view.cc", "libcef/browser/native/window_delegate_view.h", "libcef/browser/views/basic_label_button_impl.cc", diff --git a/libcef/browser/alloy/alloy_browser_host_impl.cc b/libcef/browser/alloy/alloy_browser_host_impl.cc index cd119bcce..90ff20f1e 100644 --- a/libcef/browser/alloy/alloy_browser_host_impl.cc +++ b/libcef/browser/alloy/alloy_browser_host_impl.cc @@ -378,7 +378,7 @@ void AlloyBrowserHostImpl::SetFocusInternal(bool focus) { } CefWindowHandle AlloyBrowserHostImpl::GetWindowHandle() { - if (IsViewsHosted() && CEF_CURRENTLY_ON_UIT()) { + if (is_views_hosted_ && CEF_CURRENTLY_ON_UIT()) { // Always return the most up-to-date window handle for a views-hosted // browser since it may change if the view is re-parented. if (platform_delegate_) @@ -391,10 +391,6 @@ CefWindowHandle AlloyBrowserHostImpl::GetOpenerWindowHandle() { return opener_; } -bool AlloyBrowserHostImpl::HasView() { - return IsViewsHosted(); -} - double AlloyBrowserHostImpl::GetZoomLevel() { // Verify that this method is being called on the UI thread. if (!CEF_CURRENTLY_ON_UIT()) { @@ -803,10 +799,6 @@ bool AlloyBrowserHostImpl::IsWindowless() const { return is_windowless_; } -bool AlloyBrowserHostImpl::IsViewsHosted() const { - return is_views_hosted_; -} - bool AlloyBrowserHostImpl::IsPictureInPictureSupported() const { // Not currently supported with OSR. return !IsWindowless(); @@ -870,22 +862,6 @@ void AlloyBrowserHostImpl::DestroyBrowser() { CefBrowserHostBase::DestroyBrowser(); } -#if defined(USE_AURA) -views::Widget* AlloyBrowserHostImpl::GetWindowWidget() const { - CEF_REQUIRE_UIT(); - if (!platform_delegate_) - return nullptr; - return platform_delegate_->GetWindowWidget(); -} - -CefRefPtr AlloyBrowserHostImpl::GetBrowserView() const { - CEF_REQUIRE_UIT(); - if (IsViewsHosted() && platform_delegate_) - return platform_delegate_->GetBrowserView(); - return nullptr; -} -#endif - void AlloyBrowserHostImpl::CancelContextMenu() { CEF_REQUIRE_UIT(); if (menu_manager_) @@ -1684,11 +1660,10 @@ AlloyBrowserHostImpl::AlloyBrowserHostImpl( content::WebContentsObserver(web_contents), opener_(kNullWindowHandle), is_windowless_(platform_delegate_->IsWindowless()), - is_views_hosted_(platform_delegate_->IsViewsHosted()), extension_(extension) { contents_delegate_->ObserveWebContents(web_contents); - if (opener.get() && !platform_delegate_->IsViewsHosted()) { + if (opener.get() && !is_views_hosted_) { // GetOpenerWindowHandle() only returns a value for non-views-hosted // popup browsers. opener_ = opener->GetWindowHandle(); @@ -1707,7 +1682,7 @@ bool AlloyBrowserHostImpl::CreateHostWindow() { bool success = true; if (!IsWindowless()) success = platform_delegate_->CreateHostWindow(); - if (success && !IsViewsHosted()) + if (success && !is_views_hosted_) host_window_handle_ = platform_delegate_->GetHostWindowHandle(); return success; } diff --git a/libcef/browser/alloy/alloy_browser_host_impl.h b/libcef/browser/alloy/alloy_browser_host_impl.h index 5203162ed..45c7e6655 100644 --- a/libcef/browser/alloy/alloy_browser_host_impl.h +++ b/libcef/browser/alloy/alloy_browser_host_impl.h @@ -88,7 +88,6 @@ class AlloyBrowserHostImpl : public CefBrowserHostBase, 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, @@ -161,14 +160,11 @@ class AlloyBrowserHostImpl : public CefBrowserHostBase, // Returns true if windowless rendering is enabled. bool IsWindowless() const; - // Returns true if this browser is views-hosted. - bool IsViewsHosted() const; - // Returns true if this browser supports picture-in-picture. bool IsPictureInPictureSupported() const; // Called when the OS window hosting the browser is destroyed. - void WindowDestroyed(); + void WindowDestroyed() override; // Destroy the browser members. This method should only be called after the // native browser window is not longer processing messages. @@ -177,16 +173,6 @@ class AlloyBrowserHostImpl : public CefBrowserHostBase, // Cancel display of the context menu, if any. void CancelContextMenu(); -#if defined(USE_AURA) - // Returns the Widget owner for the browser window. Only used with windowed - // rendering. - views::Widget* GetWindowWidget() const; - - // Returns the BrowserView associated with this browser. Only used with views- - // based browsers. - CefRefPtr GetBrowserView() const; -#endif - bool MaybeAllowNavigation(content::RenderFrameHost* opener, bool is_guest_view, const content::OpenURLParams& params) override; @@ -374,7 +360,6 @@ class AlloyBrowserHostImpl : public CefBrowserHostBase, CefWindowHandle opener_; const bool is_windowless_; - const bool is_views_hosted_; CefWindowHandle host_window_handle_ = kNullWindowHandle; CefRefPtr extension_; bool is_background_host_ = false; diff --git a/libcef/browser/browser_host_base.cc b/libcef/browser/browser_host_base.cc index 4033dd706..e30a9a21c 100644 --- a/libcef/browser/browser_host_base.cc +++ b/libcef/browser/browser_host_base.cc @@ -163,7 +163,8 @@ CefBrowserHostBase::CefBrowserHostBase( client_(client), platform_delegate_(std::move(platform_delegate)), browser_info_(browser_info), - request_context_(request_context) { + request_context_(request_context), + is_views_hosted_(platform_delegate_->IsViewsHosted()) { CEF_REQUIRE_UIT(); DCHECK(!browser_info_->browser().get()); browser_info_->SetBrowser(this); @@ -205,6 +206,10 @@ CefRefPtr CefBrowserHostBase::GetRequestContext() { return request_context_; } +bool CefBrowserHostBase::HasView() { + return is_views_hosted_; +} + void CefBrowserHostBase::StartDownload(const CefString& url) { if (!CEF_CURRENTLY_ON_UIT()) { CEF_POST_TASK( @@ -790,3 +795,19 @@ content::BrowserContext* CefBrowserHostBase::GetBrowserContext() const { return web_contents->GetBrowserContext(); return nullptr; } + +#if defined(TOOLKIT_VIEWS) +views::Widget* CefBrowserHostBase::GetWindowWidget() const { + CEF_REQUIRE_UIT(); + if (!platform_delegate_) + return nullptr; + return platform_delegate_->GetWindowWidget(); +} + +CefRefPtr CefBrowserHostBase::GetBrowserView() const { + CEF_REQUIRE_UIT(); + if (is_views_hosted_ && platform_delegate_) + return platform_delegate_->GetBrowserView(); + return nullptr; +} +#endif // defined(TOOLKIT_VIEWS) diff --git a/libcef/browser/browser_host_base.h b/libcef/browser/browser_host_base.h index 957d53416..042d8ea0f 100644 --- a/libcef/browser/browser_host_base.h +++ b/libcef/browser/browser_host_base.h @@ -38,6 +38,9 @@ struct CefBrowserCreateParams { settings = that.settings; request_context = that.request_context; extra_info = that.extra_info; +#if defined(TOOLKIT_VIEWS) + browser_view = that.browser_view; +#endif return *this; } @@ -45,10 +48,9 @@ struct CefBrowserCreateParams { // 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 +#if defined(TOOLKIT_VIEWS) + // 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 @@ -100,6 +102,11 @@ class CefBrowserHostBase : public CefBrowserHost, virtual ~Observer() {} }; + // Create a new CefBrowserHost instance of the current runtime type with + // owned WebContents. + static CefRefPtr Create( + CefBrowserCreateParams& create_params); + // Returns the browser associated with the specified RenderViewHost. static CefRefPtr GetBrowserForHost( const content::RenderViewHost* host); @@ -127,6 +134,10 @@ class CefBrowserHostBase : public CefBrowserHost, // Called on the UI thread after the associated WebContents is created. virtual void InitializeBrowser(); + // Called on the UI thread when the OS window hosting the browser is + // destroyed. + virtual void WindowDestroyed() = 0; + // Called on the UI thread after the associated WebContents is destroyed. // Also called from CefBrowserInfoManager::DestroyAllBrowsers if the browser // was not properly shut down. @@ -136,6 +147,7 @@ class CefBrowserHostBase : public CefBrowserHost, CefRefPtr GetBrowser() override; CefRefPtr GetClient() override; CefRefPtr GetRequestContext() override; + bool HasView() override; void StartDownload(const CefString& url) override; void DownloadImage(const CefString& image_url, bool is_favicon, @@ -221,6 +233,7 @@ class CefBrowserHostBase : public CefBrowserHost, CefRefPtr request_context() const { return request_context_; } + bool is_views_hosted() const { return is_views_hosted_; } // Accessors that must be called on the UI thread. content::WebContents* GetWebContents() const; @@ -232,6 +245,16 @@ class CefBrowserHostBase : public CefBrowserHost, return contents_delegate_.get(); } +#if defined(TOOLKIT_VIEWS) + // Returns the Widget owner for the browser window. Only used with windowed + // rendering. + views::Widget* GetWindowWidget() const; + + // Returns the BrowserView associated with this browser. Only used with Views- + // based browsers. + CefRefPtr GetBrowserView() const; +#endif + protected: // Called from LoadMainFrameURL to perform the actual navigation. virtual bool Navigate(const content::OpenURLParams& params); @@ -242,6 +265,7 @@ class CefBrowserHostBase : public CefBrowserHost, std::unique_ptr platform_delegate_; scoped_refptr browser_info_; CefRefPtr request_context_; + const bool is_views_hosted_; // Only accessed on the UI thread. std::unique_ptr contents_delegate_; diff --git a/libcef/browser/browser_host_create.cc b/libcef/browser/browser_host_create.cc index 28b11b476..b47056a6d 100644 --- a/libcef/browser/browser_host_create.cc +++ b/libcef/browser/browser_host_create.cc @@ -134,6 +134,12 @@ CefRefPtr CefBrowserHost::CreateBrowserSync( create_params.extra_info = extra_info; create_params.request_context = request_context; + return CefBrowserHostBase::Create(create_params); +} + +// static +CefRefPtr CefBrowserHostBase::Create( + CefBrowserCreateParams& create_params) { if (cef::IsChromeRuntimeEnabled()) { auto browser = ChromeBrowserHostImpl::Create(create_params); return browser.get(); diff --git a/libcef/browser/browser_platform_delegate.cc b/libcef/browser/browser_platform_delegate.cc index 278e1105a..9f6292633 100644 --- a/libcef/browser/browser_platform_delegate.cc +++ b/libcef/browser/browser_platform_delegate.cc @@ -112,7 +112,7 @@ CefWindowHandle CefBrowserPlatformDelegate::GetHostWindowHandle() const { return kNullWindowHandle; } -#if defined(USE_AURA) +#if defined(TOOLKIT_VIEWS) views::Widget* CefBrowserPlatformDelegate::GetWindowWidget() const { NOTREACHED(); return nullptr; @@ -122,7 +122,7 @@ CefRefPtr CefBrowserPlatformDelegate::GetBrowserView() const { NOTREACHED(); return nullptr; } -#endif +#endif // defined(TOOLKIT_VIEWS) void CefBrowserPlatformDelegate::PopupWebContentsCreated( const CefBrowserSettings& settings, diff --git a/libcef/browser/browser_platform_delegate.h b/libcef/browser/browser_platform_delegate.h index 6e9d34a32..f2b726b72 100644 --- a/libcef/browser/browser_platform_delegate.h +++ b/libcef/browser/browser_platform_delegate.h @@ -168,7 +168,7 @@ class CefBrowserPlatformDelegate { // the client, which may be NULL. May be called on multiple threads. virtual CefWindowHandle GetHostWindowHandle() const; -#if defined(USE_AURA) +#if defined(TOOLKIT_VIEWS) // Returns the Widget owner for the browser window. Only used with windowed // rendering. virtual views::Widget* GetWindowWidget() const; diff --git a/libcef/browser/browser_platform_delegate_create.cc b/libcef/browser/browser_platform_delegate_create.cc index 14af1812e..f91943293 100644 --- a/libcef/browser/browser_platform_delegate_create.cc +++ b/libcef/browser/browser_platform_delegate_create.cc @@ -29,7 +29,8 @@ #error A delegate implementation is not available for your platform. #endif -#if defined(USE_AURA) +#if defined(TOOLKIT_VIEWS) +#include "libcef/browser/chrome/views/browser_platform_delegate_chrome_views.h" #include "libcef/browser/views/browser_platform_delegate_views.h" #endif @@ -82,6 +83,13 @@ std::unique_ptr CefBrowserPlatformDelegate::Create( // CefWindowInfo is not used in this case. std::unique_ptr native_delegate = CreateNativeDelegate(CefWindowInfo(), background_color); +#if defined(TOOLKIT_VIEWS) + if (create_params.browser_view) { + return std::make_unique( + std::move(native_delegate), + static_cast(create_params.browser_view.get())); + } +#endif return std::make_unique( std::move(native_delegate)); } @@ -113,7 +121,7 @@ std::unique_ptr CefBrowserPlatformDelegate::Create( return std::make_unique( std::move(native_delegate)); } -#if defined(USE_AURA) +#if defined(TOOLKIT_VIEWS) else { // CefWindowInfo is not used in this case. std::unique_ptr native_delegate = @@ -122,7 +130,7 @@ std::unique_ptr CefBrowserPlatformDelegate::Create( std::move(native_delegate), static_cast(create_params.browser_view.get())); } -#endif // defined(USE_AURA) +#endif // defined(TOOLKIT_VIEWS) NOTREACHED(); return nullptr; diff --git a/libcef/browser/chrome/browser_platform_delegate_chrome.cc b/libcef/browser/chrome/browser_platform_delegate_chrome.cc index 4df6ed3c5..854914d31 100644 --- a/libcef/browser/chrome/browser_platform_delegate_chrome.cc +++ b/libcef/browser/chrome/browser_platform_delegate_chrome.cc @@ -86,6 +86,11 @@ void CefBrowserPlatformDelegateChrome::ViewText(const std::string& text) { native_delegate_->ViewText(text); } +CefEventHandle CefBrowserPlatformDelegateChrome::GetEventHandle( + const content::NativeWebKeyboardEvent& event) const { + return native_delegate_->GetEventHandle(event); +} + CefWindowHandle CefBrowserPlatformDelegateChrome::GetParentWindowHandle() const { return GetHostWindowHandle(); diff --git a/libcef/browser/chrome/browser_platform_delegate_chrome.h b/libcef/browser/chrome/browser_platform_delegate_chrome.h index 60275f234..ae36d2b55 100644 --- a/libcef/browser/chrome/browser_platform_delegate_chrome.h +++ b/libcef/browser/chrome/browser_platform_delegate_chrome.h @@ -36,6 +36,8 @@ class CefBrowserPlatformDelegateChrome int deltaY) override; gfx::Point GetScreenPoint(const gfx::Point& view) const override; void ViewText(const std::string& text) override; + CefEventHandle GetEventHandle( + const content::NativeWebKeyboardEvent& event) const override; // CefBrowserPlatformDelegateNative::WindowlessHandler methods: CefWindowHandle GetParentWindowHandle() const override; @@ -43,7 +45,7 @@ class CefBrowserPlatformDelegateChrome void set_chrome_browser(Browser* browser); - private: + protected: std::unique_ptr native_delegate_; Browser* chrome_browser_ = nullptr; diff --git a/libcef/browser/chrome/chrome_browser_delegate.cc b/libcef/browser/chrome/chrome_browser_delegate.cc index c3f73e667..25e8a5e9b 100644 --- a/libcef/browser/chrome/chrome_browser_delegate.cc +++ b/libcef/browser/chrome/chrome_browser_delegate.cc @@ -252,6 +252,11 @@ std::unique_ptr BrowserDelegate::Create( cef_params.get()); if (params) { create_params = params->create_params_; + + // Clear these values so they're not persisted to additional Browsers. +#if defined(TOOLKIT_VIEWS) + params->create_params_.browser_view = nullptr; +#endif } return std::make_unique(browser, create_params); diff --git a/libcef/browser/chrome/chrome_browser_host_impl.cc b/libcef/browser/chrome/chrome_browser_host_impl.cc index ca782cd51..e35bae728 100644 --- a/libcef/browser/chrome/chrome_browser_host_impl.cc +++ b/libcef/browser/chrome/chrome_browser_host_impl.cc @@ -7,6 +7,7 @@ #include "libcef/browser/browser_platform_delegate.h" #include "libcef/browser/chrome/browser_platform_delegate_chrome.h" #include "libcef/browser/thread_util.h" +#include "libcef/browser/views/browser_view_impl.h" #include "libcef/features/runtime_checks.h" #include "base/logging.h" @@ -22,6 +23,11 @@ #include "chrome/common/pref_names.h" #include "url/url_constants.h" +#if defined(TOOLKIT_VIEWS) +#include "libcef/browser/chrome/views/chrome_browser_frame.h" +#include "libcef/browser/chrome/views/chrome_browser_view.h" +#endif + // static CefRefPtr ChromeBrowserHostImpl::Create( const CefBrowserCreateParams& params) { @@ -40,11 +46,46 @@ CefRefPtr ChromeBrowserHostImpl::Create( // Pass |params| to cef::BrowserDelegate::Create from the Browser constructor. chrome_params.cef_params = base::MakeRefCounted(params); +#if defined(TOOLKIT_VIEWS) + // Configure Browser creation to use the existing Views-based + // Widget/BrowserFrame (ChromeBrowserFrame) and BrowserView/BrowserWindow + // (ChromeBrowserView). See views/chrome_browser_frame.h for related + // documentation. + ChromeBrowserView* chrome_browser_view = nullptr; + if (params.browser_view) { + // Don't show most controls. + chrome_params.type = Browser::TYPE_POPUP; + // Don't show title bar or address. + chrome_params.trusted_source = true; + + auto view_impl = + static_cast(params.browser_view.get()); + + chrome_browser_view = + static_cast(view_impl->root_view()); + chrome_params.window = chrome_browser_view; + + auto chrome_widget = + static_cast(chrome_browser_view->GetWidget()); + chrome_browser_view->set_frame(chrome_widget); + } +#endif // defined(TOOLKIT_VIEWS) + // 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. + // out of the existing Browser. The returned Browser is owned by the + // associated BrowserView. auto browser = Browser::Create(chrome_params); +#if defined(TOOLKIT_VIEWS) + if (chrome_browser_view) { + // Initialize the BrowserFrame and BrowserView and create the controls that + // require access to the Browser. + chrome_browser_view->InitBrowser(base::WrapUnique(browser), + params.browser_view); + } +#endif + GURL url = params.url; if (url.is_empty()) { // Chrome will navigate to kChromeUINewTabURL by default. We want to keep @@ -148,8 +189,9 @@ void ChromeBrowserHostImpl::CloseBrowser(bool force_close) { } bool ChromeBrowserHostImpl::TryCloseBrowser() { - NOTIMPLEMENTED(); - return false; + // TODO(chrome): Handle the case where the browser may not close immediately. + CloseBrowser(true); + return true; } void ChromeBrowserHostImpl::SetFocus(bool focus) { @@ -168,11 +210,6 @@ CefWindowHandle ChromeBrowserHostImpl::GetOpenerWindowHandle() { return kNullWindowHandle; } -bool ChromeBrowserHostImpl::HasView() { - // TODO(chrome-runtime): Support Views-hosted browsers. - return false; -} - double ChromeBrowserHostImpl::GetZoomLevel() { NOTIMPLEMENTED(); return 0.0; @@ -437,10 +474,10 @@ void ChromeBrowserHostImpl::Attach(Browser* browser, DCHECK(browser); DCHECK(web_contents); + SetBrowser(browser); + platform_delegate_->WebContentsCreated(web_contents, /*own_web_contents=*/false); - - SetBrowser(browser); contents_delegate_->ObserveWebContents(web_contents); InitializeBrowser(); } @@ -467,6 +504,19 @@ void ChromeBrowserHostImpl::InitializeBrowser() { OnAfterCreated(); } +void ChromeBrowserHostImpl::WindowDestroyed() { + CEF_REQUIRE_UIT(); +#if defined(TOOLKIT_VIEWS) + if (browser_ && is_views_hosted_) { + auto chrome_browser_view = + static_cast(browser_->window()); + chrome_browser_view->Destroyed(); + } +#endif + + platform_delegate_->CloseHostWindow(); +} + void ChromeBrowserHostImpl::DestroyBrowser() { CEF_REQUIRE_UIT(); browser_ = nullptr; @@ -486,6 +536,8 @@ void ChromeBrowserHostImpl::DoCloseBrowser(bool force_close) { // Like chrome::CloseTab() but specifying the WebContents. const int tab_index = GetCurrentTabIndex(); if (tab_index != TabStripModel::kNoTab) { + // TODO(chrome): Handle the case where this method returns false, + // indicating that the contents were not closed immediately. browser_->tab_strip_model()->CloseWebContentsAt( tab_index, TabStripModel::CLOSE_CREATE_HISTORICAL_TAB | TabStripModel::CLOSE_USER_GESTURE); diff --git a/libcef/browser/chrome/chrome_browser_host_impl.h b/libcef/browser/chrome/chrome_browser_host_impl.h index daaf83489..bcf32fadc 100644 --- a/libcef/browser/chrome/chrome_browser_host_impl.h +++ b/libcef/browser/chrome/chrome_browser_host_impl.h @@ -66,7 +66,6 @@ class ChromeBrowserHostImpl : public CefBrowserHostBase { 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, @@ -160,6 +159,7 @@ class ChromeBrowserHostImpl : public CefBrowserHostBase { // CefBrowserHostBase methods: void InitializeBrowser() override; + void WindowDestroyed() override; void DestroyBrowser() override; void DoCloseBrowser(bool force_close); diff --git a/libcef/browser/chrome/views/browser_platform_delegate_chrome_views.cc b/libcef/browser/chrome/views/browser_platform_delegate_chrome_views.cc new file mode 100644 index 000000000..f2c01ee17 --- /dev/null +++ b/libcef/browser/chrome/views/browser_platform_delegate_chrome_views.cc @@ -0,0 +1,64 @@ +// Copyright 2021 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/views/browser_platform_delegate_chrome_views.h" + +#include "chrome/browser/ui/browser.h" +#include "ui/views/widget/widget.h" + +CefBrowserPlatformDelegateChromeViews::CefBrowserPlatformDelegateChromeViews( + std::unique_ptr native_delegate, + CefRefPtr browser_view) + : CefBrowserPlatformDelegateChrome(std::move(native_delegate)), + browser_view_(browser_view) {} + +void CefBrowserPlatformDelegateChromeViews::WebContentsCreated( + content::WebContents* web_contents, + bool owned) { + CefBrowserPlatformDelegateChrome::WebContentsCreated(web_contents, owned); + browser_view_->WebContentsCreated(web_contents); +} + +void CefBrowserPlatformDelegateChromeViews::BrowserCreated( + CefBrowserHostBase* browser) { + CefBrowserPlatformDelegateChrome::BrowserCreated(browser); + browser_view_->BrowserCreated(browser, base::RepeatingClosure()); +} + +void CefBrowserPlatformDelegateChromeViews::NotifyBrowserCreated() { + if (browser_view_->delegate()) + browser_view_->delegate()->OnBrowserCreated(browser_view_, browser_); +} + +void CefBrowserPlatformDelegateChromeViews::NotifyBrowserDestroyed() { + if (browser_view_->delegate()) + browser_view_->delegate()->OnBrowserDestroyed(browser_view_, browser_); +} + +void CefBrowserPlatformDelegateChromeViews::BrowserDestroyed( + CefBrowserHostBase* browser) { + CefBrowserPlatformDelegateChrome::BrowserDestroyed(browser); + browser_view_->BrowserDestroyed(browser); +} + +void CefBrowserPlatformDelegateChromeViews::CloseHostWindow() { + views::Widget* widget = GetWindowWidget(); + if (widget && !widget->IsClosed()) + widget->Close(); +} + +views::Widget* CefBrowserPlatformDelegateChromeViews::GetWindowWidget() const { + if (browser_view_->root_view()) + return browser_view_->root_view()->GetWidget(); + return nullptr; +} + +CefRefPtr +CefBrowserPlatformDelegateChromeViews::GetBrowserView() const { + return browser_view_.get(); +} + +bool CefBrowserPlatformDelegateChromeViews::IsViewsHosted() const { + return true; +} diff --git a/libcef/browser/chrome/views/browser_platform_delegate_chrome_views.h b/libcef/browser/chrome/views/browser_platform_delegate_chrome_views.h new file mode 100644 index 000000000..2c66017e0 --- /dev/null +++ b/libcef/browser/chrome/views/browser_platform_delegate_chrome_views.h @@ -0,0 +1,35 @@ +// Copyright 2021 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_VIEWS_BROWSER_PLATFORM_DELEGATE_CHROME_VIEWS_H_ +#define CEF_LIBCEF_BROWSER_CHROME_VIEWS_BROWSER_PLATFORM_DELEGATE_CHROME_VIEWS_H_ + +#include "libcef/browser/chrome/browser_platform_delegate_chrome.h" +#include "libcef/browser/views/browser_view_impl.h" + +// Implementation of Chrome-based browser functionality. +class CefBrowserPlatformDelegateChromeViews + : public CefBrowserPlatformDelegateChrome { + public: + explicit CefBrowserPlatformDelegateChromeViews( + std::unique_ptr native_delegate, + CefRefPtr browser_view); + + // CefBrowserPlatformDelegate overrides. + void WebContentsCreated(content::WebContents* web_contents, + bool owned) override; + void BrowserCreated(CefBrowserHostBase* browser) override; + void NotifyBrowserCreated() override; + void NotifyBrowserDestroyed() override; + void BrowserDestroyed(CefBrowserHostBase* browser) override; + void CloseHostWindow() override; + views::Widget* GetWindowWidget() const override; + CefRefPtr GetBrowserView() const override; + bool IsViewsHosted() const override; + + private: + CefRefPtr browser_view_; +}; + +#endif // CEF_LIBCEF_BROWSER_CHROME_VIEWS_BROWSER_PLATFORM_DELEGATE_CHROME_VIEWS_H_ diff --git a/libcef/browser/chrome/views/chrome_browser_frame.cc b/libcef/browser/chrome/views/chrome_browser_frame.cc new file mode 100644 index 000000000..7a20b31ad --- /dev/null +++ b/libcef/browser/chrome/views/chrome_browser_frame.cc @@ -0,0 +1,35 @@ +// Copyright 2021 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/views/chrome_browser_frame.h" + +#include "chrome/browser/themes/theme_service.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/views/frame/browser_view.h" + +void ChromeBrowserFrame::Init(BrowserView* browser_view, + std::unique_ptr browser) { + DCHECK(browser_view); + + DCHECK(!browser_); + browser_ = browser.get(); + DCHECK(browser_); + + // Initialize BrowserFrame state. + InitBrowserView(browser_view); + + // Initialize BrowserView state. + browser_view->InitBrowser(std::move(browser)); +} + +views::internal::RootView* ChromeBrowserFrame::CreateRootView() { + // Bypass the BrowserFrame implementation. + return views::Widget::CreateRootView(); +} + +std::unique_ptr +ChromeBrowserFrame::CreateNonClientFrameView() { + // Bypass the BrowserFrame implementation. + return views::Widget::CreateNonClientFrameView(); +} diff --git a/libcef/browser/chrome/views/chrome_browser_frame.h b/libcef/browser/chrome/views/chrome_browser_frame.h new file mode 100644 index 000000000..472c1ef9b --- /dev/null +++ b/libcef/browser/chrome/views/chrome_browser_frame.h @@ -0,0 +1,109 @@ +// Copyright 2021 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_VIEWS_CHROME_BROWSER_FRAME_H_ +#define CEF_LIBCEF_BROWSER_CHROME_VIEWS_CHROME_BROWSER_FRAME_H_ +#pragma once + +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/views/frame/browser_frame.h" + +// An overview of the Chrome Browser object model is provided below. Object +// creation normally begins with a call to Browser::Create(CreateParams) which +// then creates the necessary Browser view, window and frame objects. CEF has +// modified the default object creation model are described below to better +// integrate with the existing CEF Views APIs. +// +// OVERVIEW +// +// Browser and BrowserWindow are the primary Chrome objects. Browser provides +// the concrete state and mutation methods while BrowserWindow is an interface +// implemented by the platform-specific "view" of the Browser window. +// +// Browser: +// - Creates a BrowserView (aka BrowserWindow) and BrowserFrame (aka Widget) via +// a call to BrowserWindow::CreateBrowserWindow() in the Browser constructor. +// - An existing BrowserWindow can alternately be specified via the +// Browser::CreateParams::window parameter. +// - Owned by the BrowserView after creation. +// +// The Chrome Views implementation uses BrowserView to represent the browser +// client area and BrowserFrame (plus helpers) to represent the non-client +// window frame. +// +// BrowserView: +// - Extends BrowserWindow, views::ClientView, views::WidgetDelegate. +// - Owns the Browser. +// - References the BrowserFrame. +// - Passed to Widget::Init() via Widget::InitParams::delegate to receive +// WidgetDelegate callbacks. +// - Extended by CEF as ChromeBrowserView. +// BrowserFrame: +// - Extends Widget (aka views::internal::NativeWidgetDelegate). +// - References the BrowserView. +// - Creates/owns a DesktopBrowserFrameAura (aka NativeBrowserFrame) via +// BrowserFrame::InitBrowserFrame(). +// - Extended by CEF as ChromeBrowserFrame. +// +// Chrome custom window/frame handling is implemented using platform-specific +// objects. +// +// DesktopBrowserFrameAura: +// - Extends NativeBrowserFrame, DesktopNativeWidgetAura. +// - Acts as a helper for BrowserFrame. +// - Creates/references a BrowserDesktopWindowTreeHostWin via +// DesktopBrowserFrameAura::InitNativeWidget(). +// BrowserDesktopWindowTreeHostWin (for Windows): +// - Extends DesktopWindowTreeHost. +// - References DesktopBrowserFrameAura, BrowserView, BrowserFrame. +// - Passed to Widget::Init() via Widget::InitParams::desktop_window_tree_host. +// +// CEF MODIFICATIONS +// +// The CEF Views integration uses an alternative approach of creating the +// ChromeBrowserFrame in CefWindowView::CreateWidget() and the +// ChromeBrowserView in CefBrowserViewImpl::CreateRootView(). +// The object associations described above are then configured via +// ChromeBrowserView::AddedToWidget() and ChromeBrowserHostImpl::Create() +// after the BrowserView is added to the Widget. The Chromium code has been +// patched to allow later initialization of the Browser, BrowserFrame and +// BrowserView members to support this model. +// +// CEF does not use Chrome's NativeBrowserFrame (aka DesktopBrowserFrameAura), +// BrowserNonClientFrameView or BrowserRootView objects (all normally created by +// BrowserFrame during Widget initialization). Consequently +// |BrowserFrame::native_browser_frame_| and |BrowserFrame::browser_frame_view_| +// (sometimes retrieved via BrowserFrame::GetFrameView) will be nullptr and the +// Chromium code has been patched to add the necessary null checks. +// +// CEF does not pass ChromeBrowserView as the WidgetDelegate when the Widget is +// initialized in CefWindowView::CreateWidget(). Some of the WidgetDelegate +// callbacks may need to be routed from CefWindowView to ChromeBrowserView in +// the future. +// +// See the chrome_runtime_views.patch file for the complete set of related +// modifications. + +class BrowserView; + +// Widget for a Views-hosted Chrome browser. Created in +// CefWindowView::CreateWidget() when the Chrome runtime is enabled. +class ChromeBrowserFrame : public BrowserFrame { + public: + ChromeBrowserFrame() {} + ChromeBrowserFrame(const ChromeBrowserFrame&) = delete; + ChromeBrowserFrame& operator=(const ChromeBrowserFrame&) = delete; + + void Init(BrowserView* browser_view, std::unique_ptr browser); + + // views::Widget methods: + views::internal::RootView* CreateRootView() override; + std::unique_ptr CreateNonClientFrameView() + override; + + private: + Browser* browser_ = nullptr; +}; + +#endif // CEF_LIBCEF_BROWSER_CHROME_VIEWS_CHROME_BROWSER_FRAME_H_ diff --git a/libcef/browser/chrome/views/chrome_browser_view.cc b/libcef/browser/chrome/views/chrome_browser_view.cc new file mode 100644 index 000000000..bbd58d5af --- /dev/null +++ b/libcef/browser/chrome/views/chrome_browser_view.cc @@ -0,0 +1,70 @@ +// Copyright 2021 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/views/chrome_browser_view.h" + +#include "libcef/browser/chrome/views/chrome_browser_frame.h" +#include "libcef/browser/views/browser_view_impl.h" + +ChromeBrowserView::ChromeBrowserView(CefBrowserViewDelegate* cef_delegate, + Delegate* browser_view_delegate) + : ParentClass(cef_delegate), browser_view_delegate_(browser_view_delegate) { + DCHECK(browser_view_delegate_); +} + +void ChromeBrowserView::InitBrowser(std::unique_ptr browser, + CefRefPtr browser_view) { + DCHECK(!browser_); + DCHECK(!web_view_); + + browser_ = browser.get(); + DCHECK(browser_); + + // Initialize the BrowserFrame and BrowserView. + auto chrome_widget = static_cast(GetWidget()); + chrome_widget->Init(this, std::move(browser)); + + // Retrieve the views::WebView that was created by the above initializations. + auto view_impl = static_cast(browser_view.get()); + web_view_ = view_impl->web_view(); + DCHECK(web_view_); + + ParentClass::AddedToWidget(); +} + +void ChromeBrowserView::Destroyed() { + DCHECK(!destroyed_); + destroyed_ = true; + browser_ = nullptr; + web_view_ = nullptr; +} + +void ChromeBrowserView::ViewHierarchyChanged( + const views::ViewHierarchyChangedDetails& details) { + ParentClass::ViewHierarchyChanged(details); + if (details.is_add && details.child == this) { + gfx::Size size = GetPreferredSize(); + if (size.IsEmpty()) { + // No size was provided for this View. Size it to the parent by default + // or, depending on the Layout, the browser may be initially 0x0 size and + // will not display until the parent is next resized (resulting in a call + // to WebView::OnBoundsChanged). For example, this can happen when adding + // this View to a CefWindow with FillLayout and then calling + // CefWindow::Show() without first resizing the CefWindow. + size = details.parent->GetPreferredSize(); + if (!size.IsEmpty()) + SetSize(size); + } + } +} + +void ChromeBrowserView::AddedToWidget() { + // Results in a call to InitBrowser which calls ParentClass::AddedToWidget. + browser_view_delegate_->OnBrowserViewAdded(); +} + +void ChromeBrowserView::OnBoundsChanged(const gfx::Rect& previous_bounds) { + ParentClass::OnBoundsChanged(previous_bounds); + browser_view_delegate_->OnBoundsChanged(); +} diff --git a/libcef/browser/chrome/views/chrome_browser_view.h b/libcef/browser/chrome/views/chrome_browser_view.h new file mode 100644 index 000000000..d9246eed8 --- /dev/null +++ b/libcef/browser/chrome/views/chrome_browser_view.h @@ -0,0 +1,57 @@ +// Copyright 2021 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_VIEWS_CHROME_BROWSER_VIEW_H_ +#define CEF_LIBCEF_BROWSER_CHROME_VIEWS_CHROME_BROWSER_VIEW_H_ +#pragma once + +#include "include/views/cef_browser_view.h" +#include "include/views/cef_browser_view_delegate.h" +#include "libcef/browser/views/browser_view_view.h" +#include "libcef/browser/views/view_view.h" + +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/views/frame/browser_view.h" + +namespace views { +class WebView; +} // namespace views + +// A variant of CefBrowserViewView that extends BrowserView instead of +// views::WebView. See chrome_browser_frame.h for related documentation. +class ChromeBrowserView + : public CefViewView { + public: + using ParentClass = CefViewView; + using Delegate = CefBrowserViewView::Delegate; + + // |cef_delegate| may be nullptr. + // |browser_view_delegate| must be non-nullptr. + ChromeBrowserView(CefBrowserViewDelegate* cef_delegate, + Delegate* browser_view_delegate); + + // Called by ChromeBrowserHostImpl. + void InitBrowser(std::unique_ptr browser, + CefRefPtr browser_view); + void Destroyed(); + + // View methods: + void ViewHierarchyChanged( + const views::ViewHierarchyChangedDetails& details) override; + void AddedToWidget() override; + void OnBoundsChanged(const gfx::Rect& previous_bounds) override; + + private: + // Not owned by this object. + Delegate* browser_view_delegate_; + + Browser* browser_ = nullptr; + views::WebView* web_view_ = nullptr; + + bool destroyed_ = false; + + DISALLOW_COPY_AND_ASSIGN(ChromeBrowserView); +}; + +#endif // CEF_LIBCEF_BROWSER_CHROME_VIEWS_CHROME_BROWSER_VIEW_H_ diff --git a/libcef/browser/devtools/devtools_frontend.cc b/libcef/browser/devtools/devtools_frontend.cc index a8aca14a6..18bdf59cf 100644 --- a/libcef/browser/devtools/devtools_frontend.cc +++ b/libcef/browser/devtools/devtools_frontend.cc @@ -251,7 +251,7 @@ CefDevToolsFrontend* CefDevToolsFrontend::Show( } CefBrowserCreateParams create_params; - if (!inspected_browser->IsViewsHosted()) + if (!inspected_browser->is_views_hosted()) create_params.window_info.reset(new CefWindowInfo(windowInfo)); create_params.client = client; create_params.settings = new_settings; diff --git a/libcef/browser/extensions/extension_function_details.cc b/libcef/browser/extensions/extension_function_details.cc index 001d2770b..658444f8c 100644 --- a/libcef/browser/extensions/extension_function_details.cc +++ b/libcef/browser/extensions/extension_function_details.cc @@ -388,7 +388,7 @@ base::DictionaryValue* CefExtensionFunctionDetails::OpenTab( return nullptr; } - if (active_browser->IsViewsHosted()) { + if (active_browser->is_views_hosted()) { // The new browser will also be Views hosted. create_params.window_info.reset(); } diff --git a/libcef/browser/views/browser_view_impl.cc b/libcef/browser/views/browser_view_impl.cc index b5d289452..cbf5fa560 100644 --- a/libcef/browser/views/browser_view_impl.cc +++ b/libcef/browser/views/browser_view_impl.cc @@ -4,11 +4,13 @@ #include "libcef/browser/views/browser_view_impl.h" -#include "libcef/browser/alloy/alloy_browser_host_impl.h" +#include "libcef/browser/browser_host_base.h" #include "libcef/browser/browser_util.h" +#include "libcef/browser/chrome/views/chrome_browser_view.h" #include "libcef/browser/context.h" #include "libcef/browser/thread_util.h" #include "libcef/browser/views/window_impl.h" +#include "libcef/features/runtime.h" #include "libcef/features/runtime_checks.h" #include "content/public/browser/native_web_keyboard_event.h" @@ -29,12 +31,11 @@ CefRefPtr CefBrowserView::CreateBrowserView( // static CefRefPtr CefBrowserView::GetForBrowser( CefRefPtr browser) { - REQUIRE_ALLOY_RUNTIME(); CEF_REQUIRE_UIT_RETURN(nullptr); - AlloyBrowserHostImpl* browser_impl = - static_cast(browser.get()); - if (browser_impl && browser_impl->IsViewsHosted()) + CefBrowserHostBase* browser_impl = + static_cast(browser.get()); + if (browser_impl && browser_impl->is_views_hosted()) return browser_impl->GetBrowserView(); return nullptr; } @@ -47,7 +48,6 @@ CefRefPtr CefBrowserViewImpl::Create( CefRefPtr extra_info, CefRefPtr request_context, CefRefPtr delegate) { - REQUIRE_ALLOY_RUNTIME(); CEF_REQUIRE_UIT_RETURN(nullptr); CefRefPtr browser_view = new CefBrowserViewImpl(delegate); @@ -73,8 +73,8 @@ CefRefPtr CefBrowserViewImpl::CreateForPopup( void CefBrowserViewImpl::WebContentsCreated( content::WebContents* web_contents) { - if (root_view()) - root_view()->SetWebContents(web_contents); + if (web_view()) + web_view()->SetWebContents(web_contents); } void CefBrowserViewImpl::BrowserCreated( @@ -88,8 +88,8 @@ void CefBrowserViewImpl::BrowserDestroyed(CefBrowserHostBase* browser) { DCHECK_EQ(browser, browser_); browser_ = nullptr; - if (root_view()) - root_view()->SetWebContents(nullptr); + if (web_view()) + web_view()->SetWebContents(nullptr); } bool CefBrowserViewImpl::HandleKeyboardEvent( @@ -128,8 +128,8 @@ CefRefPtr CefBrowserViewImpl::GetBrowser() { void CefBrowserViewImpl::SetPreferAccelerators(bool prefer_accelerators) { CEF_REQUIRE_VALID_RETURN_VOID(); - if (root_view()) - root_view()->set_allow_accelerators(prefer_accelerators); + if (web_view()) + web_view()->set_allow_accelerators(prefer_accelerators); } void CefBrowserViewImpl::RequestFocus() { @@ -143,8 +143,8 @@ void CefBrowserViewImpl::RequestFocus() { void CefBrowserViewImpl::SetBackgroundColor(cef_color_t color) { CEF_REQUIRE_VALID_RETURN_VOID(); ParentClass::SetBackgroundColor(color); - if (root_view()) - root_view()->SetResizeBackgroundColor(color); + if (web_view()) + web_view()->SetResizeBackgroundColor(color); } void CefBrowserViewImpl::Detach() { @@ -154,12 +154,12 @@ void CefBrowserViewImpl::Detach() { DCHECK(!root_view()); if (browser_) { - // |browser_| will disappear when WindowDestroyed() indirectly calls - // BrowserDestroyed() so keep a reference. + // With the Alloy runtime |browser_| will disappear when WindowDestroyed() + // indirectly calls BrowserDestroyed() so keep a reference. CefRefPtr browser = browser_; // Force the browser to be destroyed. - static_cast(browser.get())->WindowDestroyed(); + browser->WindowDestroyed(); } } @@ -176,7 +176,7 @@ void CefBrowserViewImpl::OnBrowserViewAdded() { // hierarchy. pending_browser_create_params_->browser_view = this; - AlloyBrowserHostImpl::Create(*pending_browser_create_params_); + CefBrowserHostBase::Create(*pending_browser_create_params_); DCHECK(browser_); pending_browser_create_params_.reset(nullptr); @@ -212,12 +212,28 @@ void CefBrowserViewImpl::SetDefaults(const CefBrowserSettings& settings) { CefContext::Get()->GetBackgroundColor(&settings, STATE_DISABLED)); } -CefBrowserViewView* CefBrowserViewImpl::CreateRootView() { +views::View* CefBrowserViewImpl::CreateRootView() { + if (cef::IsChromeRuntimeEnabled()) { + return new ChromeBrowserView(delegate(), this); + } + return new CefBrowserViewView(delegate(), this); } void CefBrowserViewImpl::InitializeRootView() { - static_cast(root_view())->Initialize(); + if (cef::IsChromeRuntimeEnabled()) { + static_cast(root_view())->Initialize(); + } else { + static_cast(root_view())->Initialize(); + } +} + +views::WebView* CefBrowserViewImpl::web_view() const { + if (cef::IsChromeRuntimeEnabled()) { + return static_cast(root_view())->contents_web_view(); + } + + return static_cast(root_view()); } bool CefBrowserViewImpl::HandleAccelerator( diff --git a/libcef/browser/views/browser_view_impl.h b/libcef/browser/views/browser_view_impl.h index 15ae54467..3a9770039 100644 --- a/libcef/browser/views/browser_view_impl.h +++ b/libcef/browser/views/browser_view_impl.h @@ -19,14 +19,11 @@ class CefBrowserHostBase; -class CefBrowserViewImpl : public CefViewImpl, - public CefBrowserViewView::Delegate { +class CefBrowserViewImpl + : public CefViewImpl, + public CefBrowserViewView::Delegate { public: - typedef CefViewImpl + typedef CefViewImpl ParentClass; // Create a new CefBrowserView instance. |delegate| may be nullptr. @@ -73,6 +70,9 @@ class CefBrowserViewImpl : public CefViewImplset_frame(this); ++ browser_view_(nullptr) { + set_is_secondary_widget(false); + // Don't focus anything on creation, selecting a tab will set the focus. + set_focus_on_creation(false); ++ if (browser_view) ++ InitBrowserView(browser_view); ++} ++ ++void BrowserFrame::InitBrowserView(BrowserView* browser_view) { ++ browser_view_ = browser_view; ++ browser_view_->set_frame(this); + } + + BrowserFrame::~BrowserFrame() {} +@@ -133,6 +141,12 @@ gfx::Rect BrowserFrame::GetBoundsForTabStripRegion( + } + + int BrowserFrame::GetTopInset() const { ++ if (!browser_frame_view_) { ++ // With CEF the browser may already be part of a larger Views layout. Zero ++ // out the adjustment in BrowserView::GetTopInsetInBrowserView() so that ++ // the browser isn't shifted to the top of the window. ++ return browser_view_->y(); ++ } + return browser_frame_view_->GetTopInset(false); + } + +@@ -167,15 +181,21 @@ void BrowserFrame::GetWindowPlacement(gfx::Rect* bounds, + + content::KeyboardEventProcessingResult BrowserFrame::PreHandleKeyboardEvent( + const content::NativeWebKeyboardEvent& event) { ++ if (!native_browser_frame_) ++ return content::KeyboardEventProcessingResult::NOT_HANDLED; + return native_browser_frame_->PreHandleKeyboardEvent(event); + } + + bool BrowserFrame::HandleKeyboardEvent( + const content::NativeWebKeyboardEvent& event) { ++ if (!native_browser_frame_) ++ return false; + return native_browser_frame_->HandleKeyboardEvent(event); + } + + void BrowserFrame::OnBrowserViewInitViewsComplete() { ++ if (!browser_frame_view_) ++ return; + browser_frame_view_->OnBrowserViewInitViewsComplete(); + } + +@@ -208,7 +228,8 @@ const ui::ThemeProvider* BrowserFrame::GetThemeProvider() const { + } + + const ui::NativeTheme* BrowserFrame::GetNativeTheme() const { +- if (browser_view_->browser()->profile()->IsIncognitoProfile() && ++ if (browser_view_ && ++ browser_view_->browser()->profile()->IsIncognitoProfile() && + ThemeServiceFactory::GetForProfile(browser_view_->browser()->profile()) + ->UsingDefaultTheme()) { + return ui::NativeTheme::GetInstanceForDarkUI(); +diff --git chrome/browser/ui/views/frame/browser_frame.h chrome/browser/ui/views/frame/browser_frame.h +index 3a1314f21ce4..f9464abc97a7 100644 +--- chrome/browser/ui/views/frame/browser_frame.h ++++ chrome/browser/ui/views/frame/browser_frame.h +@@ -53,7 +53,9 @@ enum class TabDragKind { + // This is a virtual interface that allows system specific browser frames. + class BrowserFrame : public views::Widget, public views::ContextMenuController { + public: ++ BrowserFrame(); + explicit BrowserFrame(BrowserView* browser_view); ++ void InitBrowserView(BrowserView* browser_view); + ~BrowserFrame() override; + + // Initialize the frame (creates the underlying native window). +diff --git chrome/browser/ui/views/frame/browser_view.cc chrome/browser/ui/views/frame/browser_view.cc +index c4d99326bacf..3c7b45b99186 100644 +--- chrome/browser/ui/views/frame/browser_view.cc ++++ chrome/browser/ui/views/frame/browser_view.cc +@@ -545,16 +545,26 @@ class BrowserView::AccessibilityModeObserver : public ui::AXModeObserver { + // static + const char BrowserView::kViewClassName[] = "BrowserView"; + ++BrowserView::BrowserView() : BrowserView(nullptr) {} ++ + BrowserView::BrowserView(std::unique_ptr browser) + : views::ClientView(nullptr, nullptr), +- browser_(std::move(browser)), + accessibility_mode_observer_( + std::make_unique(this)) { ++ if (browser) ++ InitBrowser(std::move(browser)); ++} ++ ++void BrowserView::InitBrowser(std::unique_ptr browser) { ++ DCHECK(!browser_); ++ browser_ = std::move(browser); ++ ++ immersive_mode_controller_ = chrome::CreateImmersiveModeController(); ++ + SetShowIcon(::ShouldShowWindowIcon(browser_.get())); + SetHasWindowSizeControls(!chrome::IsRunningInForcedAppMode()); + + browser_->tab_strip_model()->AddObserver(this); +- immersive_mode_controller_ = chrome::CreateImmersiveModeController(); + + // Top container holds tab strip region and toolbar and lives at the front of + // the view hierarchy. +@@ -1340,6 +1350,8 @@ bool BrowserView::ShouldHideUIForFullscreen() const { + if (immersive_mode_controller_->IsEnabled()) + return false; + ++ if (!frame_->GetFrameView()) ++ return false; + return frame_->GetFrameView()->ShouldHideTopUIForFullscreen(); + } + +@@ -2357,7 +2369,8 @@ BrowserView::GetNativeViewHostsForTopControlsSlide() const { + } + + void BrowserView::ReparentTopContainerForEndOfImmersive() { +- overlay_view_->SetVisible(false); ++ if (overlay_view_) ++ overlay_view_->SetVisible(false); + top_container()->DestroyLayer(); + AddChildViewAt(top_container(), 0); + EnsureFocusOrder(); +@@ -2804,7 +2817,8 @@ void BrowserView::Layout() { + // TODO(jamescook): Why was this in the middle of layout code? + toolbar_->location_bar()->omnibox_view()->SetFocusBehavior( + IsToolbarVisible() ? FocusBehavior::ALWAYS : FocusBehavior::NEVER); +- frame()->GetFrameView()->UpdateMinimumSize(); ++ if (frame()->GetFrameView()) ++ frame()->GetFrameView()->UpdateMinimumSize(); + + // Some of the situations when the BrowserView is laid out are: + // - Enter/exit immersive fullscreen mode. +@@ -2907,7 +2921,8 @@ void BrowserView::AddedToWidget() { + SetToolbarButtonProvider(toolbar_); + + frame_->OnBrowserViewInitViewsComplete(); +- frame_->GetFrameView()->UpdateMinimumSize(); ++ if (frame_->GetFrameView()) ++ frame_->GetFrameView()->UpdateMinimumSize(); + using_native_frame_ = frame_->ShouldUseNativeFrame(); + + MaybeInitializeWebUITabStrip(); +diff --git chrome/browser/ui/views/frame/browser_view.h chrome/browser/ui/views/frame/browser_view.h +index 986798357dbc..2793bf7b184e 100644 +--- chrome/browser/ui/views/frame/browser_view.h ++++ chrome/browser/ui/views/frame/browser_view.h +@@ -117,7 +117,9 @@ class BrowserView : public BrowserWindow, + // The browser view's class name. + static const char kViewClassName[]; + ++ BrowserView(); + explicit BrowserView(std::unique_ptr browser); ++ void InitBrowser(std::unique_ptr browser); + ~BrowserView() override; + + void set_frame(BrowserFrame* frame) { frame_ = frame; } +diff --git chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc +index 824acb2c7c8a..cd81e0e3f4d3 100644 +--- chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc ++++ chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc +@@ -578,37 +578,53 @@ gfx::Range BrowserTabStripController::ListTabsInGroup( + } + + bool BrowserTabStripController::IsFrameCondensed() const { ++ if (!GetFrameView()) ++ return false; + return GetFrameView()->IsFrameCondensed(); + } + + bool BrowserTabStripController::HasVisibleBackgroundTabShapes() const { ++ if (!GetFrameView()) ++ return false; + return GetFrameView()->HasVisibleBackgroundTabShapes( + BrowserFrameActiveState::kUseCurrent); + } + + bool BrowserTabStripController::EverHasVisibleBackgroundTabShapes() const { ++ if (!GetFrameView()) ++ return false; + return GetFrameView()->EverHasVisibleBackgroundTabShapes(); + } + + bool BrowserTabStripController::ShouldPaintAsActiveFrame() const { ++ if (!GetFrameView()) ++ return false; + return GetFrameView()->ShouldPaintAsActive(); + } + + bool BrowserTabStripController::CanDrawStrokes() const { ++ if (!GetFrameView()) ++ return false; + return GetFrameView()->CanDrawStrokes(); + } + + SkColor BrowserTabStripController::GetFrameColor( + BrowserFrameActiveState active_state) const { ++ if (!GetFrameView()) ++ return SK_ColorWHITE; + return GetFrameView()->GetFrameColor(active_state); + } + + SkColor BrowserTabStripController::GetToolbarTopSeparatorColor() const { ++ if (!GetFrameView()) ++ return SK_ColorWHITE; + return GetFrameView()->GetToolbarTopSeparatorColor(); + } + + base::Optional BrowserTabStripController::GetCustomBackgroundId( + BrowserFrameActiveState active_state) const { ++ if (!GetFrameView()) ++ return base::nullopt; + return GetFrameView()->GetCustomBackgroundId(active_state); + } + diff --git a/tests/cefclient/browser/main_context_impl.cc b/tests/cefclient/browser/main_context_impl.cc index ef293bfc0..a85d39ed1 100644 --- a/tests/cefclient/browser/main_context_impl.cc +++ b/tests/cefclient/browser/main_context_impl.cc @@ -93,6 +93,16 @@ MainContextImpl::MainContextImpl(CefRefPtr command_line, #endif } + // Enable experimental Chrome runtime. See issue #2969 for details. + use_chrome_runtime_ = + command_line_->HasSwitch(switches::kEnableChromeRuntime); + + if (use_windowless_rendering_ && use_chrome_runtime_) { + LOG(ERROR) + << "Windowless rendering is not supported with the Chrome runtime."; + use_chrome_runtime_ = false; + } + #if defined(OS_WIN) || defined(OS_LINUX) // Whether the Views framework will be used. use_views_ = command_line_->HasSwitch(switches::kUseViews); @@ -103,6 +113,14 @@ MainContextImpl::MainContextImpl(CefRefPtr command_line, use_views_ = false; } + if (use_chrome_runtime_ && !use_views_) { + // TODO(chrome): Add support for this runtime configuration (e.g. a fully + // styled Chrome window with cefclient menu customizations). In the mean + // time this can be demo'd with "cefsimple --enable-chrome-runtime". + LOG(WARNING) << "Chrome runtime requires the Views framework."; + use_views_ = true; + } + if (use_views_ && command_line->HasSwitch(switches::kHideFrame) && !command_line_->HasSwitch(switches::kUrl)) { // Use the draggable regions test as the default URL for frameless windows. @@ -178,6 +196,9 @@ void MainContextImpl::PopulateSettings(CefSettings* settings) { command_line_->HasSwitch(switches::kExternalMessagePump); } + if (use_chrome_runtime_) + settings->chrome_runtime = true; + CefString(&settings->cache_path) = command_line_->GetSwitchValue(switches::kCachePath); diff --git a/tests/cefclient/browser/main_context_impl.h b/tests/cefclient/browser/main_context_impl.h index 4c267f3ea..008629b5b 100644 --- a/tests/cefclient/browser/main_context_impl.h +++ b/tests/cefclient/browser/main_context_impl.h @@ -70,6 +70,7 @@ class MainContextImpl : public MainContext { cef_color_t browser_background_color_; bool use_windowless_rendering_; int windowless_frame_rate_; + bool use_chrome_runtime_; bool use_views_; bool touch_events_enabled_; diff --git a/tests/cefsimple/simple_app.cc b/tests/cefsimple/simple_app.cc index 1ff857e2d..3294529ec 100644 --- a/tests/cefsimple/simple_app.cc +++ b/tests/cefsimple/simple_app.cc @@ -85,8 +85,6 @@ void SimpleApp::OnContextInitialized() { CefRefPtr command_line = CefCommandLine::GetGlobalCommandLine(); - const bool enable_chrome_runtime = SimpleHandler::IsChromeRuntimeEnabled(); - #if defined(OS_WIN) || defined(OS_LINUX) // Create the browser using the Views framework if "--use-views" is specified // via the command-line. Otherwise, create the browser using the native @@ -111,7 +109,7 @@ void SimpleApp::OnContextInitialized() { if (url.empty()) url = "http://www.google.com"; - if (use_views && !enable_chrome_runtime) { + if (use_views) { // Create the BrowserView. CefRefPtr browser_view = CefBrowserView::CreateBrowserView( handler, url, browser_settings, nullptr, nullptr, diff --git a/tests/cefsimple/simple_handler.cc b/tests/cefsimple/simple_handler.cc index 1a8b1922e..334893377 100644 --- a/tests/cefsimple/simple_handler.cc +++ b/tests/cefsimple/simple_handler.cc @@ -47,10 +47,6 @@ void SimpleHandler::OnTitleChange(CefRefPtr browser, const CefString& title) { CEF_REQUIRE_UI_THREAD(); - // Allow Chrome to handle the title change. - if (IsChromeRuntimeEnabled()) - return; - if (use_views_) { // Set the title of the window using the Views framework. CefRefPtr browser_view = @@ -60,7 +56,7 @@ void SimpleHandler::OnTitleChange(CefRefPtr browser, if (window) window->SetTitle(title); } - } else { + } else if (!IsChromeRuntimeEnabled()) { // Set the title of the window using platform APIs. PlatformTitleChange(browser, title); }