From ef6ae3071d065455aa21105a9449dd333878aa8d Mon Sep 17 00:00:00 2001 From: Marshall Greenblatt Date: Thu, 7 Sep 2023 13:28:27 -0400 Subject: [PATCH] chrome: Support frameless document PiP window with draggable regions (fixes #3566) --- .../views/cef_browser_view_delegate_capi.h | 14 +- include/cef_api_hash.h | 8 +- include/views/cef_browser_view_delegate.h | 16 +- libcef/browser/chrome/browser_delegate.h | 25 +- .../browser/chrome/chrome_browser_delegate.cc | 74 +++++- .../browser/chrome/chrome_browser_delegate.h | 12 +- .../chrome/chrome_browser_host_impl.cc | 20 +- .../browser/chrome/chrome_browser_host_impl.h | 14 ++ .../chrome/views/chrome_browser_view.cc | 35 +-- .../chrome/views/chrome_browser_view.h | 20 +- libcef/browser/views/browser_view_impl.cc | 13 +- libcef/browser/views/browser_view_impl.h | 4 + .../views/browser_view_delegate_cpptoc.cc | 42 +++- .../views/browser_view_delegate_ctocpp.cc | 41 +++- .../views/browser_view_delegate_ctocpp.h | 7 +- patch/patches/chrome_browser_browser.patch | 117 +++++---- patch/patches/chrome_runtime_views.patch | 230 ++++++++++++++++-- tests/cefclient/browser/views_window.cc | 9 +- tests/cefclient/browser/views_window.h | 6 +- tests/shared/common/client_switches.cc | 1 + tests/shared/common/client_switches.h | 1 + 21 files changed, 581 insertions(+), 128 deletions(-) diff --git a/include/capi/views/cef_browser_view_delegate_capi.h b/include/capi/views/cef_browser_view_delegate_capi.h index 105c21f99..5c24e3e7c 100644 --- a/include/capi/views/cef_browser_view_delegate_capi.h +++ b/include/capi/views/cef_browser_view_delegate_capi.h @@ -33,7 +33,7 @@ // by hand. See the translator.README.txt file in the tools directory for // more information. // -// $hash=d49d6b19e52e8a0496c69ec5cbd00750f7ac4740$ +// $hash=9e8dd2187d592f7556cbee0db3ceab851f9aae13$ // #ifndef CEF_INCLUDE_CAPI_VIEWS_CEF_BROWSER_VIEW_DELEGATE_CAPI_H_ @@ -119,7 +119,17 @@ typedef struct _cef_browser_view_delegate_t { /// documentation. /// cef_chrome_toolbar_type_t(CEF_CALLBACK* get_chrome_toolbar_type)( - struct _cef_browser_view_delegate_t* self); + struct _cef_browser_view_delegate_t* self, + struct _cef_browser_view_t* browser_view); + + /// + /// Return true (1) to create frameless windows for Document picture-in- + /// picture popups. Content in frameless windows should specify draggable + /// regions using "-webkit-app-region: drag" CSS. + /// + int(CEF_CALLBACK* use_frameless_window_for_picture_in_picture)( + struct _cef_browser_view_delegate_t* self, + struct _cef_browser_view_t* browser_view); /// /// Called when |browser_view| receives a gesture command. Return true (1) to diff --git a/include/cef_api_hash.h b/include/cef_api_hash.h index d8eca0177..ccc0d98d1 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 "a86f6076488c08805e6d0038c8935604fd32507c" +#define CEF_API_HASH_UNIVERSAL "89e632adda7aecabf0c25c8c05de63900f9cc695" #if defined(OS_WIN) -#define CEF_API_HASH_PLATFORM "bf9b8fe7fee80a5ec3b46427e8b3a4b29afca1ce" +#define CEF_API_HASH_PLATFORM "36384f3e3dc2ac64bdad2db177725caebaebf02e" #elif defined(OS_MAC) -#define CEF_API_HASH_PLATFORM "e57a71ffed7a2ef3b8b5725dec90799057a017e9" +#define CEF_API_HASH_PLATFORM "21d5e3fa7563f5238f813e442ae836c0a97073a3" #elif defined(OS_LINUX) -#define CEF_API_HASH_PLATFORM "bb78503cd459091d26ac7876599c975e8f718705" +#define CEF_API_HASH_PLATFORM "1e0de44d5bf97c07a35c4cf3986d784283e0c454" #endif #ifdef __cplusplus diff --git a/include/views/cef_browser_view_delegate.h b/include/views/cef_browser_view_delegate.h index fcfb01f83..e87a1f005 100644 --- a/include/views/cef_browser_view_delegate.h +++ b/include/views/cef_browser_view_delegate.h @@ -113,7 +113,21 @@ class CefBrowserViewDelegate : public CefViewDelegate { /// documentation. /// /*--cef(default_retval=CEF_CTT_NONE)--*/ - virtual ChromeToolbarType GetChromeToolbarType() { return CEF_CTT_NONE; } + virtual ChromeToolbarType GetChromeToolbarType( + CefRefPtr browser_view) { + return CEF_CTT_NONE; + } + + /// + /// Return true to create frameless windows for Document picture-in-picture + /// popups. Content in frameless windows should specify draggable regions + /// using "-webkit-app-region: drag" CSS. + /// + /*--cef()--*/ + virtual bool UseFramelessWindowForPictureInPicture( + CefRefPtr browser_view) { + return false; + } /// /// Called when |browser_view| receives a gesture command. Return true to diff --git a/libcef/browser/chrome/browser_delegate.h b/libcef/browser/chrome/browser_delegate.h index 3ecd82dee..8f56cc487 100644 --- a/libcef/browser/chrome/browser_delegate.h +++ b/libcef/browser/chrome/browser_delegate.h @@ -11,6 +11,8 @@ #include "base/memory/scoped_refptr.h" #include "chrome/browser/ui/page_action/page_action_icon_type.h" #include "content/public/browser/web_contents_delegate.h" +#include "third_party/abseil-cpp/absl/types/optional.h" +#include "third_party/skia/include/core/SkRegion.h" #include "ui/base/window_open_disposition.h" class Browser; @@ -33,7 +35,8 @@ class BrowserDelegate : public content::WebContentsDelegate { // Called from the Browser constructor to create a new delegate. static std::unique_ptr Create( Browser* browser, - scoped_refptr cef_params); + scoped_refptr cef_params, + const Browser* opener); ~BrowserDelegate() override {} @@ -103,6 +106,26 @@ class BrowserDelegate : public content::WebContentsDelegate { content::MediaResponseCallback callback) { return callback; } + + // Optionally override support for the specified window feature of type + // Browser::WindowFeature. + virtual absl::optional SupportsWindowFeature(int feature) const { + return absl::nullopt; + } + + // Returns true if draggable regions are supported. + virtual bool SupportsDraggableRegion() const { return false; } + + // Returns the draggable region, if any, relative to the web contents. + // Called from PictureInPictureBrowserFrameView::NonClientHitTest and + // BrowserView::ShouldDescendIntoChildForEventHandling. + virtual const absl::optional GetDraggableRegion() const { + return absl::nullopt; + } + + // Set the draggable region relative to web contents. + // Called from DraggableRegionsHostImpl::UpdateDraggableRegions. + virtual void UpdateDraggableRegion(const SkRegion& region) {} }; } // namespace cef diff --git a/libcef/browser/chrome/chrome_browser_delegate.cc b/libcef/browser/chrome/chrome_browser_delegate.cc index 4bbdfa5db..b94774ca0 100644 --- a/libcef/browser/chrome/chrome_browser_delegate.cc +++ b/libcef/browser/chrome/chrome_browser_delegate.cc @@ -11,8 +11,10 @@ #include "libcef/browser/browser_info_manager.h" #include "libcef/browser/browser_platform_delegate.h" #include "libcef/browser/chrome/chrome_browser_host_impl.h" +#include "libcef/browser/chrome/views/chrome_browser_view.h" #include "libcef/browser/media_access_query.h" #include "libcef/browser/request_context_impl.h" +#include "libcef/browser/views/browser_view_impl.h" #include "libcef/common/app_manager.h" #include "libcef/common/frame_util.h" @@ -27,9 +29,19 @@ using content::KeyboardEventProcessingResult; ChromeBrowserDelegate::ChromeBrowserDelegate( Browser* browser, - const CefBrowserCreateParams& create_params) + const CefBrowserCreateParams& create_params, + const Browser* opener) : browser_(browser), create_params_(create_params) { DCHECK(browser_); + + if (opener) { + DCHECK(browser->is_type_picture_in_picture()); + auto opener_host = ChromeBrowserHostImpl::GetBrowserForBrowser(opener); + DCHECK(opener_host); + if (opener_host) { + opener_host_ = opener_host->GetWeakPtr(); + } + } } ChromeBrowserDelegate::~ChromeBrowserDelegate() = default; @@ -195,6 +207,56 @@ ChromeBrowserDelegate::RequestMediaAccessPermissionEx( return callback; } +bool ChromeBrowserDelegate::SupportsFramelessPictureInPicture() const { + if (!browser_->is_type_picture_in_picture()) { + return false; + } + + if (frameless_pip_.has_value()) { + return *frameless_pip_; + } + + frameless_pip_ = false; + + if (opener_host_) { + if (auto chrome_browser_view = opener_host_->chrome_browser_view()) { + if (auto cef_delegate = chrome_browser_view->cef_delegate()) { + frameless_pip_ = cef_delegate->UseFramelessWindowForPictureInPicture( + chrome_browser_view->cef_browser_view()); + } + } + } + + return *frameless_pip_; +} + +absl::optional ChromeBrowserDelegate::SupportsWindowFeature( + int feature) const { + // Override the default value from + // Browser::PictureInPictureBrowserSupportsWindowFeature. + if (feature == Browser::FEATURE_TITLEBAR && + browser_->is_type_picture_in_picture()) { + // Return false to hide titlebar and enable draggable regions. + return !SupportsFramelessPictureInPicture(); + } + return absl::nullopt; +} + +bool ChromeBrowserDelegate::SupportsDraggableRegion() const { + return SupportsFramelessPictureInPicture(); +} + +const absl::optional ChromeBrowserDelegate::GetDraggableRegion() + const { + DCHECK(SupportsDraggableRegion()); + return draggable_region_; +} + +void ChromeBrowserDelegate::UpdateDraggableRegion(const SkRegion& region) { + DCHECK(SupportsDraggableRegion()); + draggable_region_ = region; +} + void ChromeBrowserDelegate::WebContentsCreated( content::WebContents* source_contents, int opener_render_process_id, @@ -397,7 +459,12 @@ namespace cef { // static std::unique_ptr BrowserDelegate::Create( Browser* browser, - scoped_refptr cef_params) { + scoped_refptr cef_params, + const Browser* opener) { + if (!cef::IsChromeRuntimeEnabled()) { + return nullptr; + } + CefBrowserCreateParams create_params; // Parameters from ChromeBrowserHostImpl::Create, or nullptr if the Browser @@ -412,7 +479,8 @@ std::unique_ptr BrowserDelegate::Create( params->create_params_.browser_view = nullptr; } - return std::make_unique(browser, create_params); + return std::make_unique(browser, create_params, + opener); } } // namespace cef diff --git a/libcef/browser/chrome/chrome_browser_delegate.h b/libcef/browser/chrome/chrome_browser_delegate.h index cb8b19e16..460c1a444 100644 --- a/libcef/browser/chrome/chrome_browser_delegate.h +++ b/libcef/browser/chrome/chrome_browser_delegate.h @@ -40,7 +40,8 @@ class ChromeBrowserHostImpl; class ChromeBrowserDelegate : public cef::BrowserDelegate { public: ChromeBrowserDelegate(Browser* browser, - const CefBrowserCreateParams& create_params); + const CefBrowserCreateParams& create_params, + const Browser* opener); ChromeBrowserDelegate(const ChromeBrowserDelegate&) = delete; ChromeBrowserDelegate& operator=(const ChromeBrowserDelegate&) = delete; @@ -65,6 +66,10 @@ class ChromeBrowserDelegate : public cef::BrowserDelegate { content::WebContents* web_contents, const content::MediaStreamRequest& request, content::MediaResponseCallback callback) override; + absl::optional SupportsWindowFeature(int feature) const override; + bool SupportsDraggableRegion() const override; + const absl::optional GetDraggableRegion() const override; + void UpdateDraggableRegion(const SkRegion& region) override; // WebContentsDelegate methods: void WebContentsCreated(content::WebContents* source_contents, @@ -113,12 +118,17 @@ class ChromeBrowserDelegate : public cef::BrowserDelegate { CefBrowserContentsDelegate* GetDelegateForWebContents( content::WebContents* web_contents); + bool SupportsFramelessPictureInPicture() const; + Browser* const browser_; + base::WeakPtr opener_host_; // Used when creating a new browser host. const CefBrowserCreateParams create_params_; absl::optional show_status_bubble_; + absl::optional draggable_region_; + mutable absl::optional frameless_pip_; }; #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 index c62776bf5..8d6f95105 100644 --- a/libcef/browser/chrome/chrome_browser_host_impl.cc +++ b/libcef/browser/chrome/chrome_browser_host_impl.cc @@ -332,6 +332,13 @@ bool ChromeBrowserHostImpl::IsBackgroundHost() { return false; } +ChromeBrowserView* ChromeBrowserHostImpl::chrome_browser_view() const { + if (browser_ && is_views_hosted_) { + return static_cast(browser_->window()); + } + return nullptr; +} + bool ChromeBrowserHostImpl::Navigate(const content::OpenURLParams& params) { CEF_REQUIRE_UIT(); if (GetCurrentTabIndex() == TabStripModel::kNoTab) { @@ -413,8 +420,7 @@ Browser* ChromeBrowserHostImpl::CreateBrowser( auto view_impl = static_cast(params.browser_view.get()); - chrome_browser_view = - static_cast(view_impl->root_view()); + chrome_browser_view = view_impl->chrome_browser_view(); chrome_params.window = chrome_browser_view; auto chrome_widget = @@ -433,8 +439,7 @@ Browser* ChromeBrowserHostImpl::CreateBrowser( 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); + chrome_browser_view->InitBrowser(base::WrapUnique(browser)); // Don't set theme colors in ContentsWebView::UpdateBackgroundColor. chrome_browser_view->contents_web_view()->SetBackgroundVisible(false); @@ -514,10 +519,8 @@ void ChromeBrowserHostImpl::SetBrowser(Browser* browser) { void ChromeBrowserHostImpl::WindowDestroyed() { CEF_REQUIRE_UIT(); - if (browser_ && is_views_hosted_) { - auto chrome_browser_view = - static_cast(browser_->window()); - chrome_browser_view->Destroyed(); + if (auto view = chrome_browser_view()) { + view->Destroyed(); } platform_delegate_->CloseHostWindow(); @@ -532,6 +535,7 @@ bool ChromeBrowserHostImpl::WillBeDestroyed() const { void ChromeBrowserHostImpl::DestroyBrowser() { CEF_REQUIRE_UIT(); browser_ = nullptr; + weak_ptr_factory_.InvalidateWeakPtrs(); OnBeforeClose(); OnBrowserDestroyed(); diff --git a/libcef/browser/chrome/chrome_browser_host_impl.h b/libcef/browser/chrome/chrome_browser_host_impl.h index effb5205f..1d7d0bbb0 100644 --- a/libcef/browser/chrome/chrome_browser_host_impl.h +++ b/libcef/browser/chrome/chrome_browser_host_impl.h @@ -11,8 +11,11 @@ #include "libcef/browser/browser_host_base.h" #include "libcef/browser/chrome/browser_delegate.h" +#include "base/memory/weak_ptr.h" + class Browser; class ChromeBrowserDelegate; +class ChromeBrowserView; // CefBrowser implementation for the chrome runtime. Method calls are delegated // to the chrome Browser object or the WebContents as appropriate. See the @@ -114,6 +117,15 @@ class ChromeBrowserHostImpl : public CefBrowserHostBase { CefRefPtr GetExtension() override; bool IsBackgroundHost() override; + Browser* browser() const { return browser_; } + + // Return the CEF specialization of BrowserView. + ChromeBrowserView* chrome_browser_view() const; + + base::WeakPtr GetWeakPtr() { + return weak_ptr_factory_.GetWeakPtr(); + } + protected: bool Navigate(const content::OpenURLParams& params) override; @@ -157,6 +169,8 @@ class ChromeBrowserHostImpl : public CefBrowserHostBase { Browser* browser_ = nullptr; CefWindowHandle host_window_handle_ = kNullWindowHandle; + + base::WeakPtrFactory weak_ptr_factory_{this}; }; #endif // CEF_LIBCEF_BROWSER_CHROME_CHROME_BROWSER_HOST_IMPL_H_ diff --git a/libcef/browser/chrome/views/chrome_browser_view.cc b/libcef/browser/chrome/views/chrome_browser_view.cc index 41a549012..59f7c0f54 100644 --- a/libcef/browser/chrome/views/chrome_browser_view.cc +++ b/libcef/browser/chrome/views/chrome_browser_view.cc @@ -7,27 +7,19 @@ #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_); -} +ChromeBrowserView::ChromeBrowserView(CefBrowserViewImpl* cef_browser_view) + : ParentClass(cef_browser_view->delegate()), + cef_browser_view_(cef_browser_view) {} -void ChromeBrowserView::InitBrowser(std::unique_ptr browser, - CefRefPtr browser_view) { - DCHECK(!browser_); +void ChromeBrowserView::InitBrowser(std::unique_ptr 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(); + web_view_ = cef_browser_view_->web_view(); DCHECK(web_view_); ParentClass::AddedToWidget(); @@ -36,7 +28,6 @@ void ChromeBrowserView::InitBrowser(std::unique_ptr browser, void ChromeBrowserView::Destroyed() { DCHECK(!destroyed_); destroyed_ = true; - browser_ = nullptr; web_view_ = nullptr; } @@ -62,26 +53,24 @@ void ChromeBrowserView::ViewHierarchyChanged( void ChromeBrowserView::AddedToWidget() { // Results in a call to InitBrowser which calls ParentClass::AddedToWidget. - browser_view_delegate_->OnBrowserViewAdded(); + cef_browser_view_->OnBrowserViewAdded(); } void ChromeBrowserView::OnBoundsChanged(const gfx::Rect& previous_bounds) { ParentClass::OnBoundsChanged(previous_bounds); - browser_view_delegate_->OnBoundsChanged(); + cef_browser_view_->OnBoundsChanged(); } void ChromeBrowserView::OnGestureEvent(ui::GestureEvent* event) { - if (browser_view_delegate_->OnGestureEvent(event)) { + if (cef_browser_view_->OnGestureEvent(event)) { return; } ParentClass::OnGestureEvent(event); } -ToolbarView* ChromeBrowserView::OverrideCreateToolbar( - Browser* browser, - BrowserView* browser_view) { +ToolbarView* ChromeBrowserView::OverrideCreateToolbar() { if (cef_delegate()) { - auto toolbar_type = cef_delegate()->GetChromeToolbarType(); + auto toolbar_type = cef_delegate()->GetChromeToolbarType(cef_browser_view_); absl::optional display_mode; switch (toolbar_type) { case CEF_CTT_NORMAL: @@ -94,8 +83,8 @@ ToolbarView* ChromeBrowserView::OverrideCreateToolbar( break; } if (display_mode) { - cef_toolbar_ = CefToolbarViewImpl::Create(nullptr, browser, browser_view, - display_mode); + cef_toolbar_ = + CefToolbarViewImpl::Create(nullptr, browser(), this, display_mode); // Ownership will be taken by BrowserView. view_util::PassOwnership(cef_toolbar_).release(); return cef_toolbar_->root_view(); diff --git a/libcef/browser/chrome/views/chrome_browser_view.h b/libcef/browser/chrome/views/chrome_browser_view.h index f0ebc174f..c7ae94afd 100644 --- a/libcef/browser/chrome/views/chrome_browser_view.h +++ b/libcef/browser/chrome/views/chrome_browser_view.h @@ -19,25 +19,23 @@ namespace views { class WebView; } // namespace views +class CefBrowserViewImpl; + // 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); + // |cef_browser_view| is non-nullptr and will outlive this object. + explicit ChromeBrowserView(CefBrowserViewImpl* cef_browser_view); ChromeBrowserView(const ChromeBrowserView&) = delete; ChromeBrowserView& operator=(const ChromeBrowserView&) = delete; // Called by ChromeBrowserHostImpl. - void InitBrowser(std::unique_ptr browser, - CefRefPtr browser_view); + void InitBrowser(std::unique_ptr browser); void Destroyed(); // View methods: @@ -48,16 +46,14 @@ class ChromeBrowserView void OnGestureEvent(ui::GestureEvent* event) override; // BrowserView methods: - ToolbarView* OverrideCreateToolbar(Browser* browser, - BrowserView* browser_view) override; + ToolbarView* OverrideCreateToolbar() override; CefRefPtr cef_toolbar() const { return cef_toolbar_; } + CefBrowserViewImpl* cef_browser_view() const { return cef_browser_view_; } private: - // Not owned by this object. - Delegate* browser_view_delegate_; + CefBrowserViewImpl* const cef_browser_view_; - Browser* browser_ = nullptr; views::WebView* web_view_ = nullptr; bool destroyed_ = false; diff --git a/libcef/browser/views/browser_view_impl.cc b/libcef/browser/views/browser_view_impl.cc index 046f3b037..847bb77a2 100644 --- a/libcef/browser/views/browser_view_impl.cc +++ b/libcef/browser/views/browser_view_impl.cc @@ -165,7 +165,7 @@ CefRefPtr CefBrowserViewImpl::GetBrowser() { CefRefPtr CefBrowserViewImpl::GetChromeToolbar() { CEF_REQUIRE_VALID_RETURN(nullptr); if (cef::IsChromeRuntimeEnabled()) { - return static_cast(root_view())->cef_toolbar(); + return chrome_browser_view()->cef_toolbar(); } return nullptr; @@ -288,7 +288,7 @@ void CefBrowserViewImpl::SetDefaults(const CefBrowserSettings& settings) { views::View* CefBrowserViewImpl::CreateRootView() { if (cef::IsChromeRuntimeEnabled()) { - return new ChromeBrowserView(delegate(), this); + return new ChromeBrowserView(this); } return new CefBrowserViewView(delegate(), this); @@ -296,7 +296,7 @@ views::View* CefBrowserViewImpl::CreateRootView() { void CefBrowserViewImpl::InitializeRootView() { if (cef::IsChromeRuntimeEnabled()) { - static_cast(root_view())->Initialize(); + chrome_browser_view()->Initialize(); } else { static_cast(root_view())->Initialize(); } @@ -308,12 +308,17 @@ views::WebView* CefBrowserViewImpl::web_view() const { } if (cef::IsChromeRuntimeEnabled()) { - return static_cast(root_view())->contents_web_view(); + return chrome_browser_view()->contents_web_view(); } return static_cast(root_view()); } +ChromeBrowserView* CefBrowserViewImpl::chrome_browser_view() const { + CHECK(cef::IsChromeRuntimeEnabled()); + return static_cast(root_view()); +} + bool CefBrowserViewImpl::HandleAccelerator( const content::NativeWebKeyboardEvent& event, views::FocusManager* focus_manager) { diff --git a/libcef/browser/views/browser_view_impl.h b/libcef/browser/views/browser_view_impl.h index b0d1338e4..588d10ea3 100644 --- a/libcef/browser/views/browser_view_impl.h +++ b/libcef/browser/views/browser_view_impl.h @@ -18,6 +18,7 @@ #include "ui/views/controls/webview/unhandled_keyboard_event_handler.h" class CefBrowserHostBase; +class ChromeBrowserView; class CefBrowserViewImpl : public CefViewImpl, @@ -79,6 +80,9 @@ class CefBrowserViewImpl // Return the WebView representation of this object. views::WebView* web_view() const; + // Return the CEF specialization of BrowserView. + ChromeBrowserView* chrome_browser_view() const; + private: // Create a new implementation object. // Always call Initialize() after creation. diff --git a/libcef_dll/cpptoc/views/browser_view_delegate_cpptoc.cc b/libcef_dll/cpptoc/views/browser_view_delegate_cpptoc.cc index 03df391ab..6967bea19 100644 --- a/libcef_dll/cpptoc/views/browser_view_delegate_cpptoc.cc +++ b/libcef_dll/cpptoc/views/browser_view_delegate_cpptoc.cc @@ -9,7 +9,7 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=4bffd98075025b4d02063698dbec87e9b9a31597$ +// $hash=f82440b30a75049733b4dd200494ab06d52c68b3$ // #include "libcef_dll/cpptoc/views/browser_view_delegate_cpptoc.h" @@ -166,7 +166,8 @@ int CEF_CALLBACK browser_view_delegate_on_popup_browser_view_created( cef_chrome_toolbar_type_t CEF_CALLBACK browser_view_delegate_get_chrome_toolbar_type( - struct _cef_browser_view_delegate_t* self) { + struct _cef_browser_view_delegate_t* self, + cef_browser_view_t* browser_view) { shutdown_checker::AssertNotShutdown(); // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING @@ -175,15 +176,48 @@ browser_view_delegate_get_chrome_toolbar_type( if (!self) { return CEF_CTT_NONE; } + // Verify param: browser_view; type: refptr_diff + DCHECK(browser_view); + if (!browser_view) { + return CEF_CTT_NONE; + } // Execute cef_chrome_toolbar_type_t _retval = - CefBrowserViewDelegateCppToC::Get(self)->GetChromeToolbarType(); + CefBrowserViewDelegateCppToC::Get(self)->GetChromeToolbarType( + CefBrowserViewCToCpp::Wrap(browser_view)); // Return type: simple return _retval; } +int CEF_CALLBACK +browser_view_delegate_use_frameless_window_for_picture_in_picture( + struct _cef_browser_view_delegate_t* self, + cef_browser_view_t* browser_view) { + shutdown_checker::AssertNotShutdown(); + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + DCHECK(self); + if (!self) { + return 0; + } + // Verify param: browser_view; type: refptr_diff + DCHECK(browser_view); + if (!browser_view) { + return 0; + } + + // Execute + bool _retval = CefBrowserViewDelegateCppToC::Get(self) + ->UseFramelessWindowForPictureInPicture( + CefBrowserViewCToCpp::Wrap(browser_view)); + + // Return type: bool + return _retval; +} + int CEF_CALLBACK browser_view_delegate_on_gesture_command( struct _cef_browser_view_delegate_t* self, cef_browser_view_t* browser_view, @@ -493,6 +527,8 @@ CefBrowserViewDelegateCppToC::CefBrowserViewDelegateCppToC() { browser_view_delegate_on_popup_browser_view_created; GetStruct()->get_chrome_toolbar_type = browser_view_delegate_get_chrome_toolbar_type; + GetStruct()->use_frameless_window_for_picture_in_picture = + browser_view_delegate_use_frameless_window_for_picture_in_picture; GetStruct()->on_gesture_command = browser_view_delegate_on_gesture_command; GetStruct()->base.get_preferred_size = browser_view_delegate_get_preferred_size; diff --git a/libcef_dll/ctocpp/views/browser_view_delegate_ctocpp.cc b/libcef_dll/ctocpp/views/browser_view_delegate_ctocpp.cc index 9d10dc134..92c9ab22b 100644 --- a/libcef_dll/ctocpp/views/browser_view_delegate_ctocpp.cc +++ b/libcef_dll/ctocpp/views/browser_view_delegate_ctocpp.cc @@ -9,7 +9,7 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=bff0bff161e504deec6aef910ebf5d8962bd7c85$ +// $hash=a3ab5cba4139ac15763ef0df69988b1bfc00b2bf$ // #include "libcef_dll/ctocpp/views/browser_view_delegate_ctocpp.h" @@ -149,7 +149,8 @@ bool CefBrowserViewDelegateCToCpp::OnPopupBrowserViewCreated( NO_SANITIZE("cfi-icall") CefBrowserViewDelegate::ChromeToolbarType -CefBrowserViewDelegateCToCpp::GetChromeToolbarType() { +CefBrowserViewDelegateCToCpp::GetChromeToolbarType( + CefRefPtr browser_view) { shutdown_checker::AssertNotShutdown(); cef_browser_view_delegate_t* _struct = GetStruct(); @@ -159,13 +160,47 @@ CefBrowserViewDelegateCToCpp::GetChromeToolbarType() { // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + // Verify param: browser_view; type: refptr_diff + DCHECK(browser_view.get()); + if (!browser_view.get()) { + return CEF_CTT_NONE; + } + // Execute - cef_chrome_toolbar_type_t _retval = _struct->get_chrome_toolbar_type(_struct); + cef_chrome_toolbar_type_t _retval = _struct->get_chrome_toolbar_type( + _struct, CefBrowserViewCppToC::Wrap(browser_view)); // Return type: simple return _retval; } +NO_SANITIZE("cfi-icall") +bool CefBrowserViewDelegateCToCpp::UseFramelessWindowForPictureInPicture( + CefRefPtr browser_view) { + shutdown_checker::AssertNotShutdown(); + + cef_browser_view_delegate_t* _struct = GetStruct(); + if (CEF_MEMBER_MISSING(_struct, + use_frameless_window_for_picture_in_picture)) { + return false; + } + + // AUTO-GENERATED CONTENT - DELETE THIS COMMENT BEFORE MODIFYING + + // Verify param: browser_view; type: refptr_diff + DCHECK(browser_view.get()); + if (!browser_view.get()) { + return false; + } + + // Execute + int _retval = _struct->use_frameless_window_for_picture_in_picture( + _struct, CefBrowserViewCppToC::Wrap(browser_view)); + + // Return type: bool + return _retval ? true : false; +} + NO_SANITIZE("cfi-icall") bool CefBrowserViewDelegateCToCpp::OnGestureCommand( CefRefPtr browser_view, diff --git a/libcef_dll/ctocpp/views/browser_view_delegate_ctocpp.h b/libcef_dll/ctocpp/views/browser_view_delegate_ctocpp.h index b92183201..0f0f9a136 100644 --- a/libcef_dll/ctocpp/views/browser_view_delegate_ctocpp.h +++ b/libcef_dll/ctocpp/views/browser_view_delegate_ctocpp.h @@ -9,7 +9,7 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=15c0d7230887344fa77279c76ff377b3f2d9ee1d$ +// $hash=2157bfb760455bcd97d4e30eba9db474c7b3cabd$ // #ifndef CEF_LIBCEF_DLL_CTOCPP_VIEWS_BROWSER_VIEW_DELEGATE_CTOCPP_H_ @@ -51,7 +51,10 @@ class CefBrowserViewDelegateCToCpp bool OnPopupBrowserViewCreated(CefRefPtr browser_view, CefRefPtr popup_browser_view, bool is_devtools) override; - ChromeToolbarType GetChromeToolbarType() override; + ChromeToolbarType GetChromeToolbarType( + CefRefPtr browser_view) override; + bool UseFramelessWindowForPictureInPicture( + CefRefPtr browser_view) override; bool OnGestureCommand(CefRefPtr browser_view, cef_gesture_command_t gesture_command) override; diff --git a/patch/patches/chrome_browser_browser.patch b/patch/patches/chrome_browser_browser.patch index af875655a..6b7a4b214 100644 --- a/patch/patches/chrome_browser_browser.patch +++ b/patch/patches/chrome_browser_browser.patch @@ -70,7 +70,7 @@ index cc4fbda7ddfa8..c7278ef3d7ff7 100644 ] } diff --git chrome/browser/ui/browser.cc chrome/browser/ui/browser.cc -index 501783a57a06e..5a90cf466eed1 100644 +index 501783a57a06e..3c0dd26c58465 100644 --- chrome/browser/ui/browser.cc +++ chrome/browser/ui/browser.cc @@ -263,6 +263,25 @@ @@ -99,21 +99,18 @@ index 501783a57a06e..5a90cf466eed1 100644 #if BUILDFLAG(ENABLE_EXTENSIONS) #include "chrome/browser/extensions/extension_browser_window_helper.h" #endif -@@ -505,6 +524,13 @@ Browser::Browser(const CreateParams& params) - - tab_strip_model_->AddObserver(this); - +@@ -454,6 +473,10 @@ Browser::Browser(const CreateParams& params) + type_(params.type), + profile_(params.profile), + window_(nullptr), +#if BUILDFLAG(ENABLE_CEF) -+ if (cef::IsChromeRuntimeEnabled()) { -+ cef_browser_delegate_ = -+ cef::BrowserDelegate::Create(this, params.cef_params); -+ } ++ cef_browser_delegate_( ++ cef::BrowserDelegate::Create(this, params.cef_params, params.opener)), +#endif -+ - location_bar_model_ = std::make_unique( - location_bar_model_delegate_.get(), content::kMaxURLDisplayChars); - -@@ -645,6 +671,12 @@ Browser::~Browser() { + tab_strip_model_delegate_( + std::make_unique(this)), + tab_strip_model_(std::make_unique( +@@ -645,6 +668,12 @@ Browser::~Browser() { // away so they don't try and call back to us. if (select_file_dialog_.get()) select_file_dialog_->ListenerDestroyed(); @@ -126,7 +123,7 @@ index 501783a57a06e..5a90cf466eed1 100644 } /////////////////////////////////////////////////////////////////////////////// -@@ -1380,6 +1412,14 @@ content::KeyboardEventProcessingResult Browser::PreHandleKeyboardEvent( +@@ -1380,6 +1409,14 @@ content::KeyboardEventProcessingResult Browser::PreHandleKeyboardEvent( if (exclusive_access_manager_->HandleUserKeyEvent(event)) return content::KeyboardEventProcessingResult::HANDLED; @@ -141,7 +138,7 @@ index 501783a57a06e..5a90cf466eed1 100644 return window()->PreHandleKeyboardEvent(event); } -@@ -1387,8 +1427,18 @@ bool Browser::HandleKeyboardEvent(content::WebContents* source, +@@ -1387,8 +1424,18 @@ bool Browser::HandleKeyboardEvent(content::WebContents* source, const NativeWebKeyboardEvent& event) { DevToolsWindow* devtools_window = DevToolsWindow::GetInstanceForInspectedWebContents(source); @@ -162,7 +159,7 @@ index 501783a57a06e..5a90cf466eed1 100644 } bool Browser::TabsNeedBeforeUnloadFired() { -@@ -1592,6 +1642,14 @@ WebContents* Browser::OpenURLFromTab(WebContents* source, +@@ -1592,6 +1639,14 @@ WebContents* Browser::OpenURLFromTab(WebContents* source, return window->OpenURLFromTab(source, params); } @@ -177,7 +174,7 @@ index 501783a57a06e..5a90cf466eed1 100644 NavigateParams nav_params(this, params.url, params.transition); nav_params.FillNavigateParamsFromOpenURLParams(params); nav_params.source_contents = source; -@@ -1749,6 +1807,8 @@ void Browser::LoadingStateChanged(WebContents* source, +@@ -1749,6 +1804,8 @@ void Browser::LoadingStateChanged(WebContents* source, bool should_show_loading_ui) { ScheduleUIUpdate(source, content::INVALIDATE_TYPE_LOAD); UpdateWindowForLoadingStateChanged(source, should_show_loading_ui); @@ -186,7 +183,7 @@ index 501783a57a06e..5a90cf466eed1 100644 } void Browser::CloseContents(WebContents* source) { -@@ -1777,6 +1837,8 @@ void Browser::SetContentsBounds(WebContents* source, const gfx::Rect& bounds) { +@@ -1777,6 +1834,8 @@ void Browser::SetContentsBounds(WebContents* source, const gfx::Rect& bounds) { } void Browser::UpdateTargetURL(WebContents* source, const GURL& url) { @@ -195,7 +192,7 @@ index 501783a57a06e..5a90cf466eed1 100644 if (!GetStatusBubble()) return; -@@ -1784,6 +1846,17 @@ void Browser::UpdateTargetURL(WebContents* source, const GURL& url) { +@@ -1784,6 +1843,17 @@ void Browser::UpdateTargetURL(WebContents* source, const GURL& url) { GetStatusBubble()->SetURL(url); } @@ -213,7 +210,7 @@ index 501783a57a06e..5a90cf466eed1 100644 void Browser::ContentsMouseEvent(WebContents* source, bool motion, bool exited) { -@@ -1808,6 +1881,19 @@ bool Browser::TakeFocus(content::WebContents* source, bool reverse) { +@@ -1808,6 +1878,19 @@ bool Browser::TakeFocus(content::WebContents* source, bool reverse) { return false; } @@ -233,7 +230,7 @@ index 501783a57a06e..5a90cf466eed1 100644 void Browser::BeforeUnloadFired(WebContents* web_contents, bool proceed, bool* proceed_to_fire_unload) { -@@ -1900,6 +1986,10 @@ void Browser::WebContentsCreated(WebContents* source_contents, +@@ -1900,6 +1983,10 @@ void Browser::WebContentsCreated(WebContents* source_contents, // Make the tab show up in the task manager. task_manager::WebContentsTags::CreateForTabContents(new_contents); @@ -244,7 +241,7 @@ index 501783a57a06e..5a90cf466eed1 100644 } void Browser::PortalWebContentsCreated(WebContents* portal_web_contents) { -@@ -2017,11 +2107,15 @@ void Browser::EnterFullscreenModeForTab( +@@ -2017,11 +2104,15 @@ void Browser::EnterFullscreenModeForTab( const blink::mojom::FullscreenOptions& options) { exclusive_access_manager_->fullscreen_controller()->EnterFullscreenModeForTab( requesting_frame, options.display_id); @@ -260,7 +257,7 @@ index 501783a57a06e..5a90cf466eed1 100644 } bool Browser::IsFullscreenForTabOrPending(const WebContents* web_contents) { -@@ -2211,6 +2305,15 @@ void Browser::RequestMediaAccessPermission( +@@ -2211,6 +2302,15 @@ void Browser::RequestMediaAccessPermission( content::WebContents* web_contents, const content::MediaStreamRequest& request, content::MediaResponseCallback callback) { @@ -276,7 +273,7 @@ index 501783a57a06e..5a90cf466eed1 100644 const extensions::Extension* extension = GetExtensionForOrigin(profile_, request.security_origin); MediaCaptureDevicesDispatcher::GetInstance()->ProcessMediaAccessRequest( -@@ -2762,13 +2865,20 @@ void Browser::RemoveScheduledUpdatesFor(WebContents* contents) { +@@ -2762,13 +2862,20 @@ void Browser::RemoveScheduledUpdatesFor(WebContents* contents) { // Browser, Getters for UI (private): StatusBubble* Browser::GetStatusBubble() { @@ -298,7 +295,7 @@ index 501783a57a06e..5a90cf466eed1 100644 return window_ ? window_->GetStatusBubble() : nullptr; } -@@ -2902,6 +3012,8 @@ void Browser::SetAsDelegate(WebContents* web_contents, bool set_delegate) { +@@ -2902,6 +3009,8 @@ void Browser::SetAsDelegate(WebContents* web_contents, bool set_delegate) { BookmarkTabHelper::FromWebContents(web_contents)->RemoveObserver(this); web_contents_collection_.StopObserving(web_contents); } @@ -307,8 +304,23 @@ index 501783a57a06e..5a90cf466eed1 100644 } void Browser::TabDetachedAtImpl(content::WebContents* contents, +@@ -3056,6 +3165,14 @@ bool Browser::PictureInPictureBrowserSupportsWindowFeature( + + bool Browser::SupportsWindowFeatureImpl(WindowFeature feature, + bool check_can_support) const { ++#if BUILDFLAG(ENABLE_CEF) ++ if (cef_delegate()) { ++ if (auto value = cef_delegate()->SupportsWindowFeature(feature)) { ++ return *value; ++ } ++ } ++#endif ++ + switch (type_) { + case TYPE_NORMAL: + return NormalBrowserSupportsWindowFeature(feature, check_can_support); diff --git chrome/browser/ui/browser.h chrome/browser/ui/browser.h -index 9fceed57deff5..bc0058f0b1db2 100644 +index 9fceed57deff5..a1a962cf014fa 100644 --- chrome/browser/ui/browser.h +++ chrome/browser/ui/browser.h @@ -22,6 +22,7 @@ @@ -330,19 +342,23 @@ index 9fceed57deff5..bc0058f0b1db2 100644 #if BUILDFLAG(IS_ANDROID) #error This file should only be included on desktop. #endif -@@ -322,6 +327,11 @@ class Browser : public TabStripModelObserver, +@@ -322,6 +327,15 @@ class Browser : public TabStripModelObserver, // Document Picture in Picture options, specific to TYPE_PICTURE_IN_PICTURE. absl::optional pip_options; +#if BUILDFLAG(ENABLE_CEF) + // Opaque CEF-specific configuration. Will be propagated to new Browsers. + scoped_refptr cef_params; ++ ++ // Specify the Browser that is opening this popup. ++ // Currently only used with TYPE_PICTURE_IN_PICTURE. ++ raw_ptr opener = nullptr; +#endif + private: friend class Browser; friend class WindowSizerChromeOSTest; -@@ -403,6 +413,13 @@ class Browser : public TabStripModelObserver, +@@ -403,6 +417,13 @@ class Browser : public TabStripModelObserver, update_ui_immediately_for_testing_ = true; } @@ -356,7 +372,7 @@ index 9fceed57deff5..bc0058f0b1db2 100644 // Accessors //////////////////////////////////////////////////////////////// const CreateParams& create_params() const { return create_params_; } -@@ -476,6 +493,12 @@ class Browser : public TabStripModelObserver, +@@ -476,6 +497,12 @@ class Browser : public TabStripModelObserver, base::WeakPtr AsWeakPtr(); @@ -369,7 +385,7 @@ index 9fceed57deff5..bc0058f0b1db2 100644 // Get the FindBarController for this browser, creating it if it does not // yet exist. FindBarController* GetFindBarController(); -@@ -869,11 +892,19 @@ class Browser : public TabStripModelObserver, +@@ -869,11 +896,19 @@ class Browser : public TabStripModelObserver, void SetContentsBounds(content::WebContents* source, const gfx::Rect& bounds) override; void UpdateTargetURL(content::WebContents* source, const GURL& url) override; @@ -389,7 +405,18 @@ index 9fceed57deff5..bc0058f0b1db2 100644 void BeforeUnloadFired(content::WebContents* source, bool proceed, bool* proceed_to_fire_unload) override; -@@ -1281,6 +1312,8 @@ class Browser : public TabStripModelObserver, +@@ -1212,6 +1247,10 @@ class Browser : public TabStripModelObserver, + // This Browser's window. + raw_ptr window_; + ++#if BUILDFLAG(ENABLE_CEF) ++ std::unique_ptr cef_browser_delegate_; ++#endif ++ + std::unique_ptr const tab_strip_model_delegate_; + std::unique_ptr const tab_strip_model_; + +@@ -1281,6 +1320,8 @@ class Browser : public TabStripModelObserver, const std::string initial_workspace_; bool initial_visible_on_all_workspaces_state_; @@ -398,22 +425,22 @@ index 9fceed57deff5..bc0058f0b1db2 100644 CreationSource creation_source_ = CreationSource::kUnknown; UnloadController unload_controller_; -@@ -1348,6 +1381,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_; - - // The opener browser of the document picture-in-picture browser. Null if the diff --git chrome/browser/ui/browser_navigator.cc chrome/browser/ui/browser_navigator.cc -index 88edd87bcb2d0..26f9d74bd4ed9 100644 +index 88edd87bcb2d0..03fc4f4ccd95f 100644 --- chrome/browser/ui/browser_navigator.cc +++ chrome/browser/ui/browser_navigator.cc -@@ -556,6 +556,13 @@ std::unique_ptr CreateTargetContents( +@@ -293,6 +293,10 @@ std::pair GetBrowserAndTabForDisposition( + : 1.0; + browser_params.pip_options = pip_options; + ++#if BUILDFLAG(ENABLE_CEF) ++ browser_params.opener = params.browser; ++#endif ++ + const BrowserWindow* const browser_window = params.browser->window(); + const gfx::NativeWindow native_window = + browser_window ? browser_window->GetNativeWindow() +@@ -556,6 +560,13 @@ std::unique_ptr CreateTargetContents( std::unique_ptr target_contents = WebContents::Create(create_params); diff --git a/patch/patches/chrome_runtime_views.patch b/patch/patches/chrome_runtime_views.patch index 92f0e5d70..3087a70e7 100644 --- a/patch/patches/chrome_runtime_views.patch +++ b/patch/patches/chrome_runtime_views.patch @@ -355,7 +355,7 @@ index 77ca1dbf118f9..c60711991d093 100644 BrowserFrame(const BrowserFrame&) = delete; BrowserFrame& operator=(const BrowserFrame&) = delete; diff --git chrome/browser/ui/views/frame/browser_view.cc chrome/browser/ui/views/frame/browser_view.cc -index 261dfb8562dbd..650a2847fb6c8 100644 +index 261dfb8562dbd..64bb1900483c8 100644 --- chrome/browser/ui/views/frame/browser_view.cc +++ chrome/browser/ui/views/frame/browser_view.cc @@ -336,11 +336,10 @@ using content::NativeWebKeyboardEvent; @@ -411,7 +411,7 @@ index 261dfb8562dbd..650a2847fb6c8 100644 - toolbar_ = top_container_->AddChildView( - std::make_unique(browser_.get(), this)); -+ toolbar_ = OverrideCreateToolbar(browser_.get(), this); ++ toolbar_ = OverrideCreateToolbar(); + if (!toolbar_) { + toolbar_ = new ToolbarView(browser_.get(), this, absl::nullopt); + } else { @@ -469,7 +469,57 @@ index 261dfb8562dbd..650a2847fb6c8 100644 top_container()->DestroyLayer(); AddChildViewAt(top_container(), 0); EnsureFocusOrder(); -@@ -3994,8 +4016,10 @@ void BrowserView::Layout() { +@@ -3873,11 +3895,38 @@ void BrowserView::GetAccessiblePanes(std::vector* panes) { + bool BrowserView::ShouldDescendIntoChildForEventHandling( + gfx::NativeView child, + const gfx::Point& location) { ++#if BUILDFLAG(ENABLE_CEF) ++ const bool frameless_pip = ++ GetIsPictureInPictureType() && ++ !browser_->SupportsWindowFeature(Browser::FEATURE_TITLEBAR); ++ if (frameless_pip) { ++ if (auto frame_view = frame()->GetFrameView()) { ++ int result = frame_view->NonClientHitTest(location); ++ if (result == HTTOP || result == HTTOPLEFT || result == HTTOPRIGHT) { ++ // Allow resize from the top of a frameless window. ++ return false; ++ } ++ } ++ } ++#endif ++ ++ absl::optional draggable_region; ++ + // Window for PWAs with window-controls-overlay display override should claim + // mouse events that fall within the draggable region. + web_app::AppBrowserController* controller = browser()->app_controller(); +- if (AreDraggableRegionsEnabled() && controller && +- controller->draggable_region().has_value()) { ++ if (AreDraggableRegionsEnabled() && controller) { ++ draggable_region = controller->draggable_region(); ++ } ++ ++#if BUILDFLAG(ENABLE_CEF) ++ // Match logic in PictureInPictureBrowserFrameView::NonClientHitTest. ++ if (!draggable_region.has_value() && frameless_pip) { ++ draggable_region = browser_->cef_delegate()->GetDraggableRegion(); ++ } ++#endif ++ ++ if (draggable_region.has_value()) { + // Draggable regions are defined relative to the web contents. + gfx::Point point_in_contents_web_view_coords(location); + views::View::ConvertPointToTarget(GetWidget()->GetRootView(), +@@ -3886,7 +3935,7 @@ bool BrowserView::ShouldDescendIntoChildForEventHandling( + + // Draggable regions should be ignored for clicks into any browser view's + // owned widgets, for example alerts, permission prompts or find bar. +- return !controller->draggable_region()->contains( ++ return !draggable_region->contains( + point_in_contents_web_view_coords.x(), + point_in_contents_web_view_coords.y()) || + WidgetOwnedByAnchorContainsPoint(point_in_contents_web_view_coords); +@@ -3994,8 +4043,10 @@ void BrowserView::Layout() { // TODO(jamescook): Why was this in the middle of layout code? toolbar_->location_bar()->omnibox_view()->SetFocusBehavior( @@ -482,7 +532,7 @@ index 261dfb8562dbd..650a2847fb6c8 100644 #if BUILDFLAG(IS_CHROMEOS_ASH) // In chromeOS ash we round the bottom two corners of the browser frame by -@@ -4073,6 +4097,11 @@ void BrowserView::AddedToWidget() { +@@ -4073,6 +4124,11 @@ void BrowserView::AddedToWidget() { SetThemeProfileForWindow(GetNativeWindow(), browser_->profile()); #endif @@ -494,7 +544,7 @@ index 261dfb8562dbd..650a2847fb6c8 100644 toolbar_->Init(); // TODO(pbos): Investigate whether the side panels should be creatable when -@@ -4120,13 +4149,9 @@ void BrowserView::AddedToWidget() { +@@ -4120,13 +4176,9 @@ void BrowserView::AddedToWidget() { EnsureFocusOrder(); @@ -510,7 +560,7 @@ index 261dfb8562dbd..650a2847fb6c8 100644 using_native_frame_ = frame_->ShouldUseNativeFrame(); MaybeInitializeWebUITabStrip(); -@@ -4544,7 +4569,8 @@ void BrowserView::ProcessFullscreen(bool fullscreen, +@@ -4544,7 +4596,8 @@ void BrowserView::ProcessFullscreen(bool fullscreen, // Undo our anti-jankiness hacks and force a re-layout. in_process_fullscreen_ = false; ToolbarSizeChanged(false); @@ -520,7 +570,7 @@ index 261dfb8562dbd..650a2847fb6c8 100644 } bool BrowserView::ShouldUseImmersiveFullscreenForUrl(const GURL& url) const { -@@ -4915,6 +4941,8 @@ Profile* BrowserView::GetProfile() { +@@ -4915,6 +4968,8 @@ Profile* BrowserView::GetProfile() { } void BrowserView::UpdateUIForTabFullscreen() { @@ -529,7 +579,7 @@ index 261dfb8562dbd..650a2847fb6c8 100644 frame()->GetFrameView()->UpdateFullscreenTopUI(); } -@@ -4937,6 +4965,8 @@ void BrowserView::HideDownloadShelf() { +@@ -4937,6 +4992,8 @@ void BrowserView::HideDownloadShelf() { } bool BrowserView::CanUserExitFullscreen() const { @@ -539,7 +589,7 @@ index 261dfb8562dbd..650a2847fb6c8 100644 } diff --git chrome/browser/ui/views/frame/browser_view.h chrome/browser/ui/views/frame/browser_view.h -index 58f128d2217a0..c8dd2a4a5a940 100644 +index 58f128d2217a0..2d5115f2a568e 100644 --- chrome/browser/ui/views/frame/browser_view.h +++ chrome/browser/ui/views/frame/browser_view.h @@ -136,11 +136,16 @@ class BrowserView : public BrowserWindow, @@ -559,15 +609,12 @@ index 58f128d2217a0..c8dd2a4a5a940 100644 void set_frame(BrowserFrame* frame) { frame_ = frame; paint_as_active_subscription_ = -@@ -810,6 +815,12 @@ class BrowserView : public BrowserWindow, +@@ -810,6 +815,9 @@ class BrowserView : public BrowserWindow, return web_app_frame_toolbar(); } + protected: -+ virtual ToolbarView* OverrideCreateToolbar(Browser* browser, -+ BrowserView* browser_view) { -+ return nullptr; -+ } ++ virtual ToolbarView* OverrideCreateToolbar() { return nullptr; } + private: // Do not friend BrowserViewLayout. Use the BrowserViewLayoutDelegate @@ -617,6 +664,100 @@ index 8267a265a8e10..ee08f18e96a34 100644 } ContentsWebView::~ContentsWebView() { +diff --git chrome/browser/ui/views/frame/picture_in_picture_browser_frame_view.cc chrome/browser/ui/views/frame/picture_in_picture_browser_frame_view.cc +index deb2cbe415610..b19dba22d8cc2 100644 +--- chrome/browser/ui/views/frame/picture_in_picture_browser_frame_view.cc ++++ chrome/browser/ui/views/frame/picture_in_picture_browser_frame_view.cc +@@ -404,6 +404,11 @@ PictureInPictureBrowserFrameView::PictureInPictureBrowserFrameView( + frame->GetNativeWindow()->SetEventTargeter( + std::make_unique()); + #endif ++ ++ if (!browser_view->browser()->SupportsWindowFeature( ++ Browser::FEATURE_TITLEBAR)) { ++ top_bar_container_view_->SetVisible(false); ++ } + } + + PictureInPictureBrowserFrameView::~PictureInPictureBrowserFrameView() { +@@ -503,17 +508,20 @@ gfx::Rect PictureInPictureBrowserFrameView::GetWindowBoundsForClientBounds( + + int PictureInPictureBrowserFrameView::NonClientHitTest( + const gfx::Point& point) { +- // Allow interacting with the buttons. +- if (GetLocationIconViewBounds().Contains(point) || +- GetBackToTabControlsBounds().Contains(point) || +- GetCloseControlsBounds().Contains(point)) { +- return HTCLIENT; +- } +- +- for (size_t i = 0; i < content_setting_views_.size(); i++) { +- if (GetContentSettingViewBounds(i).Contains(point)) { ++ const bool frameless = !top_bar_container_view_->GetVisible(); ++ if (!frameless) { ++ // Allow interacting with the buttons. ++ if (GetLocationIconViewBounds().Contains(point) || ++ GetBackToTabControlsBounds().Contains(point) || ++ GetCloseControlsBounds().Contains(point)) { + return HTCLIENT; + } ++ ++ for (size_t i = 0; i < content_setting_views_.size(); i++) { ++ if (GetContentSettingViewBounds(i).Contains(point)) { ++ return HTCLIENT; ++ } ++ } + } + + // Allow dragging and resizing the window. +@@ -523,6 +531,27 @@ int PictureInPictureBrowserFrameView::NonClientHitTest( + if (window_component != HTNOWHERE) + return window_component; + ++#if BUILDFLAG(ENABLE_CEF) ++ if (frameless) { ++ // Match logic in BrowserView::ShouldDescendIntoChildForEventHandling. ++ const auto draggable_region = ++ browser_view()->browser()->cef_delegate()->GetDraggableRegion(); ++ if (draggable_region.has_value()) { ++ // Draggable regions are defined relative to the web contents. ++ gfx::Point point_in_contents_web_view_coords(point); ++ views::View::ConvertPointToTarget(GetWidget()->GetRootView(), ++ browser_view()->contents_web_view(), ++ &point_in_contents_web_view_coords); ++ ++ if (draggable_region->contains( ++ point_in_contents_web_view_coords.x(), ++ point_in_contents_web_view_coords.y())) { ++ return HTCAPTION; ++ } ++ } ++ } ++#endif // BUILDFLAG(ENABLE_CEF) ++ + // Allow interacting with the web contents. + int frame_component = frame()->client_view()->NonClientHitTest(point); + if (frame_component != HTNOWHERE) +@@ -581,7 +610,8 @@ void PictureInPictureBrowserFrameView::Layout() { + gfx::Rect content_area = GetLocalBounds(); + content_area.Inset(FrameBorderInsets()); + gfx::Rect top_bar = content_area; +- top_bar.set_height(kTopControlsHeight); ++ top_bar.set_height( ++ top_bar_container_view_->GetVisible() ? kTopControlsHeight : 0); + top_bar_container_view_->SetBoundsRect(top_bar); + #if !BUILDFLAG(IS_ANDROID) + if (auto_pip_setting_overlay_) { +@@ -982,7 +1012,8 @@ gfx::Insets PictureInPictureBrowserFrameView::ResizeBorderInsets() const { + } + + int PictureInPictureBrowserFrameView::GetTopAreaHeight() const { +- return FrameBorderInsets().top() + kTopControlsHeight; ++ return FrameBorderInsets().top() + ++ (top_bar_container_view_->GetVisible() ? kTopControlsHeight : 0); + } + + gfx::Size PictureInPictureBrowserFrameView::GetNonClientViewAreaSize() const { diff --git chrome/browser/ui/views/page_action/page_action_icon_controller.cc chrome/browser/ui/views/page_action/page_action_icon_controller.cc index 723a2840bd988..975152c988917 100644 --- chrome/browser/ui/views/page_action/page_action_icon_controller.cc @@ -790,3 +931,64 @@ index be3bd96444563..96669547e3ccf 100644 ToolbarView(const ToolbarView&) = delete; ToolbarView& operator=(const ToolbarView&) = delete; ~ToolbarView() override; +diff --git chrome/browser/ui/web_applications/draggable_region_host_impl.cc chrome/browser/ui/web_applications/draggable_region_host_impl.cc +index 460a2b08f964b..cb1b67d8b1213 100644 +--- chrome/browser/ui/web_applications/draggable_region_host_impl.cc ++++ chrome/browser/ui/web_applications/draggable_region_host_impl.cc +@@ -11,6 +11,24 @@ + #include "chrome/common/chrome_features.h" + #include "mojo/public/cpp/bindings/self_owned_receiver.h" + ++namespace { ++ ++bool IsSupported(Browser* browser) { ++ if (web_app::AppBrowserController::IsWebApp(browser)) ++ return true; ++ ++#if BUILDFLAG(ENABLE_CEF) ++ if (browser->cef_delegate() && ++ browser->cef_delegate()->SupportsDraggableRegion()) { ++ return true; ++ } ++#endif ++ ++ return false; ++} ++ ++} // namespace ++ + DraggableRegionsHostImpl::DraggableRegionsHostImpl( + content::RenderFrameHost& render_frame_host, + mojo::PendingReceiver receiver) +@@ -28,7 +46,7 @@ void DraggableRegionsHostImpl::CreateIfAllowed( + auto* browser = chrome::FindBrowserWithWebContents(web_contents); + + // We only want to bind the receiver for PWAs. +- if (!web_app::AppBrowserController::IsWebApp(browser)) ++ if (!IsSupported(browser)) + return; + + // The object is bound to the lifetime of |render_frame_host| and the mojo +@@ -43,7 +61,7 @@ void DraggableRegionsHostImpl::UpdateDraggableRegions( + auto* browser = chrome::FindBrowserWithWebContents(web_contents); + // When a WebApp browser's WebContents is reparented to a tabbed browser, a + // draggable regions update may race with the reparenting logic. +- if (!web_app::AppBrowserController::IsWebApp(browser)) ++ if (!IsSupported(browser)) + return; + + SkRegion sk_region; +@@ -56,5 +74,12 @@ void DraggableRegionsHostImpl::UpdateDraggableRegions( + } + + auto* app_browser_controller = browser->app_controller(); +- app_browser_controller->UpdateDraggableRegion(sk_region); ++ if (app_browser_controller) { ++ app_browser_controller->UpdateDraggableRegion(sk_region); ++ } ++#if BUILDFLAG(ENABLE_CEF) ++ else { ++ browser->cef_delegate()->UpdateDraggableRegion(sk_region); ++ } ++#endif + } diff --git a/tests/cefclient/browser/views_window.cc b/tests/cefclient/browser/views_window.cc index 76731ddcb..d81e95cab 100644 --- a/tests/cefclient/browser/views_window.cc +++ b/tests/cefclient/browser/views_window.cc @@ -485,10 +485,16 @@ bool ViewsWindow::OnPopupBrowserViewCreated( return true; } -CefBrowserViewDelegate::ChromeToolbarType ViewsWindow::GetChromeToolbarType() { +CefBrowserViewDelegate::ChromeToolbarType ViewsWindow::GetChromeToolbarType( + CefRefPtr browser_view) { return chrome_toolbar_type_; } +bool ViewsWindow::UseFramelessWindowForPictureInPicture( + CefRefPtr browser_view) { + return hide_pip_frame_; +} + void ViewsWindow::OnButtonPressed(CefRefPtr button) { CEF_REQUIRE_UI_THREAD(); DCHECK(with_controls_); @@ -1038,6 +1044,7 @@ ViewsWindow::ViewsWindow(WindowType type, use_window_modal_dialog_ = command_line->HasSwitch(switches::kUseWindowModalDialog); + hide_pip_frame_ = command_line->HasSwitch(switches::kHidePipFrame); } void ViewsWindow::SetBrowserView(CefRefPtr browser_view) { diff --git a/tests/cefclient/browser/views_window.h b/tests/cefclient/browser/views_window.h index 317012bc1..3b791c376 100644 --- a/tests/cefclient/browser/views_window.h +++ b/tests/cefclient/browser/views_window.h @@ -140,7 +140,10 @@ class ViewsWindow : public CefBrowserViewDelegate, bool OnPopupBrowserViewCreated(CefRefPtr browser_view, CefRefPtr popup_browser_view, bool is_devtools) override; - ChromeToolbarType GetChromeToolbarType() override; + ChromeToolbarType GetChromeToolbarType( + CefRefPtr browser_view) override; + bool UseFramelessWindowForPictureInPicture( + CefRefPtr browser_view) override; // CefButtonDelegate methods: void OnButtonPressed(CefRefPtr button) override; @@ -254,6 +257,7 @@ class ViewsWindow : public CefBrowserViewDelegate, ChromeToolbarType chrome_toolbar_type_; bool use_window_modal_dialog_; bool use_bottom_controls_; + bool hide_pip_frame_; CefRefPtr window_; CefRefPtr button_menu_model_; diff --git a/tests/shared/common/client_switches.cc b/tests/shared/common/client_switches.cc index b07506a3d..0cb37debe 100644 --- a/tests/shared/common/client_switches.cc +++ b/tests/shared/common/client_switches.cc @@ -56,6 +56,7 @@ const char kUseTestHttpServer[] = "use-test-http-server"; const char kShowWindowButtons[] = "show-window-buttons"; const char kUseWindowModalDialog[] = "use-window-modal-dialog"; const char kUseBottomControls[] = "use-bottom-controls"; +const char kHidePipFrame[] = "hide-pip-frame"; } // namespace switches } // namespace client diff --git a/tests/shared/common/client_switches.h b/tests/shared/common/client_switches.h index a6d43c051..84af2e15c 100644 --- a/tests/shared/common/client_switches.h +++ b/tests/shared/common/client_switches.h @@ -50,6 +50,7 @@ extern const char kUseTestHttpServer[]; extern const char kShowWindowButtons[]; extern const char kUseWindowModalDialog[]; extern const char kUseBottomControls[]; +extern const char kHidePipFrame[]; } // namespace switches } // namespace client