From 3000bc8748d818fa554b25d59c9ea09e47db6b9d Mon Sep 17 00:00:00 2001 From: Marshall Greenblatt Date: Fri, 8 Apr 2022 16:48:56 -0400 Subject: [PATCH] chrome: win/linux: Add support for browser with native parent (see issue #3294) This change adds Chrome runtime support on Windows and Linux for creating a browser parented to a native window supplied by the client application. Expected API usage and window behavior is similar to what already exists with the Alloy runtime. The parent window handle should be specified by using CefWindowInfo::SetAsChild in combination with the CefBrowserHost::CreateBrowser and CefLifeSpanHandler::OnBeforePopup callbacks. The previously existing behavior of creating a fully-featured Chrome browser window when empty CefWindowInfo is used with CreateBrowser remains unchanged and Views is still the preferred API for creating top-level Chrome windows with custom styling (e.g. title bar only, frameless, etc). The cefclient Popup Window test with a native parent window continues to crash on Linux with both the Alloy and Chrome runtimes (see issue #3165). Also adds Chrome runtime support for CefDisplayHandler::OnCursorChange. To test: - Run `cefclient --enable-chrome-runtime [--use-views]` for the default (and previously existing) Views-based behavior. - Run `cefclient --enable-chrome-runtime --use-native` for the new native parent window behavior. - Run `cefclient --enable-chrome-runtime --use-native --no-activate` and the window will not be activated (take input focus) on launch (Windows only). - Run `cefclient --enable-chrome-runtime [--use-views|--use-native] --mouse-cursor-change-disabled` and the mouse cursor will not change on mouseover of DOM elements. --- BUILD.gn | 4 + include/internal/cef_linux.h | 3 + include/internal/cef_mac.h | 3 + include/internal/cef_win.h | 3 + .../browser/alloy/alloy_browser_host_impl.cc | 107 +--------- .../browser/alloy/alloy_browser_host_impl.h | 6 - .../alloy/browser_platform_delegate_alloy.cc | 15 +- libcef/browser/browser_contents_delegate.cc | 55 +++++ libcef/browser/browser_host_base.cc | 28 +++ libcef/browser/browser_host_base.h | 13 +- libcef/browser/browser_host_create.cc | 20 +- libcef/browser/browser_info_manager.cc | 23 +- libcef/browser/browser_platform_delegate.cc | 4 +- .../browser_platform_delegate_create.cc | 80 ++++--- .../chrome/browser_platform_delegate_chrome.h | 4 + .../browser/chrome/chrome_browser_delegate.cc | 1 + .../chrome/chrome_browser_host_impl.cc | 44 ++-- .../browser/chrome/chrome_browser_host_impl.h | 2 - ...r_platform_delegate_chrome_child_window.cc | 38 ++++ ...er_platform_delegate_chrome_child_window.h | 28 +++ .../browser_platform_delegate_chrome_views.cc | 5 + .../browser_platform_delegate_chrome_views.h | 3 + .../chrome/views/chrome_child_window.cc | 199 ++++++++++++++++++ .../chrome/views/chrome_child_window.h | 24 +++ libcef/browser/devtools/devtools_frontend.cc | 5 +- .../extensions/extension_function_details.cc | 1 + .../browser_platform_delegate_native_linux.cc | 4 +- .../browser_platform_delegate_native_win.cc | 13 +- .../browser_platform_delegate_native_win.h | 3 + libcef/browser/native/cursor_util.cc | 4 +- libcef/browser/native/cursor_util.h | 6 +- libcef/browser/views/browser_view_impl.cc | 14 +- libcef/browser/views/browser_view_impl.h | 3 + libcef/browser/views/window_impl.cc | 11 +- libcef/browser/views/window_impl.h | 8 +- libcef/browser/views/window_view.cc | 100 ++++++--- libcef/browser/views/window_view.h | 2 +- patch/patch.cfg | 5 + patch/patches/chrome_runtime_views.patch | 17 +- patch/patches/win_shell_dialogs_3294.patch | 29 +++ tests/cefclient/browser/main_context_impl.cc | 8 + tests/shared/common/client_switches.cc | 1 + tests/shared/common/client_switches.h | 1 + 43 files changed, 702 insertions(+), 245 deletions(-) create mode 100644 libcef/browser/chrome/views/browser_platform_delegate_chrome_child_window.cc create mode 100644 libcef/browser/chrome/views/browser_platform_delegate_chrome_child_window.h create mode 100644 libcef/browser/chrome/views/chrome_child_window.cc create mode 100644 libcef/browser/chrome/views/chrome_child_window.h create mode 100644 patch/patches/win_shell_dialogs_3294.patch diff --git a/BUILD.gn b/BUILD.gn index 3b4fd4134..99b76354f 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -1029,12 +1029,16 @@ static_library("libcef_static") { if (toolkit_views) { sources += [ + "libcef/browser/chrome/views/browser_platform_delegate_chrome_child_window.cc", + "libcef/browser/chrome/views/browser_platform_delegate_chrome_child_window.h", "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/chrome/views/chrome_child_window.cc", + "libcef/browser/chrome/views/chrome_child_window.h", "libcef/browser/chrome/views/chrome_views_util.cc", "libcef/browser/chrome/views/chrome_views_util.h", "libcef/browser/chrome/views/toolbar_view_impl.cc", diff --git a/include/internal/cef_linux.h b/include/internal/cef_linux.h index 004df6f60..14e410761 100644 --- a/include/internal/cef_linux.h +++ b/include/internal/cef_linux.h @@ -99,6 +99,9 @@ class CefWindowInfo : public CefStructBase { explicit CefWindowInfo(const cef_window_info_t& r) : parent(r) {} explicit CefWindowInfo(const CefWindowInfo& r) : parent(r) {} + CefWindowInfo& operator=(const CefWindowInfo&) = default; + CefWindowInfo& operator=(CefWindowInfo&&) = default; + /// // Create the browser as a child window. /// diff --git a/include/internal/cef_mac.h b/include/internal/cef_mac.h index 77d5b4eb0..bf947ffe2 100644 --- a/include/internal/cef_mac.h +++ b/include/internal/cef_mac.h @@ -100,6 +100,9 @@ class CefWindowInfo : public CefStructBase { explicit CefWindowInfo(const cef_window_info_t& r) : parent(r) {} explicit CefWindowInfo(const CefWindowInfo& r) : parent(r) {} + CefWindowInfo& operator=(const CefWindowInfo&) = default; + CefWindowInfo& operator=(CefWindowInfo&&) = default; + /// // Create the browser as a child view. /// diff --git a/include/internal/cef_win.h b/include/internal/cef_win.h index 5fc666485..358f98b99 100644 --- a/include/internal/cef_win.h +++ b/include/internal/cef_win.h @@ -102,6 +102,9 @@ class CefWindowInfo : public CefStructBase { explicit CefWindowInfo(const cef_window_info_t& r) : parent(r) {} explicit CefWindowInfo(const CefWindowInfo& r) : parent(r) {} + CefWindowInfo& operator=(const CefWindowInfo&) = default; + CefWindowInfo& operator=(CefWindowInfo&&) = default; + /// // Create the browser as a child window. /// diff --git a/libcef/browser/alloy/alloy_browser_host_impl.cc b/libcef/browser/alloy/alloy_browser_host_impl.cc index c1de34737..8c306191c 100644 --- a/libcef/browser/alloy/alloy_browser_host_impl.cc +++ b/libcef/browser/alloy/alloy_browser_host_impl.cc @@ -18,7 +18,6 @@ #include "libcef/browser/context.h" #include "libcef/browser/devtools/devtools_manager.h" #include "libcef/browser/media_capture_devices_dispatcher.h" -#include "libcef/browser/native/cursor_util.h" #include "libcef/browser/osr/osr_util.h" #include "libcef/browser/request_context_impl.h" #include "libcef/browser/thread_util.h" @@ -35,7 +34,6 @@ #include "base/command_line.h" #include "chrome/browser/picture_in_picture/picture_in_picture_window_manager.h" #include "content/browser/gpu/compositor_util.h" -#include "content/browser/renderer_host/render_widget_host_impl.h" #include "content/public/browser/desktop_media_id.h" #include "content/public/browser/file_select_listener.h" #include "content/public/browser/host_zoom_map.h" @@ -47,12 +45,11 @@ #include "content/public/browser/render_process_host.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/render_widget_host.h" -#include "content/public/browser/render_widget_host_observer.h" #include "content/public/browser/web_contents.h" +#include "content/public/common/url_constants.h" #include "extensions/common/constants.h" #include "extensions/common/extension.h" #include "net/base/net_errors.h" -#include "third_party/blink/public/mojom/widget/platform_widget.mojom-test-utils.h" #include "ui/events/base_event_utils.h" using content::KeyboardEventProcessingResult; @@ -86,48 +83,6 @@ void ShowDevToolsWithHelper(ShowDevToolsHelper* helper) { delete helper; } -class CefWidgetHostInterceptor - : public blink::mojom::WidgetHostInterceptorForTesting, - public content::RenderWidgetHostObserver { - public: - CefWidgetHostInterceptor(AlloyBrowserHostImpl* browser, - content::RenderViewHost* render_view_host) - : browser_(browser), - render_widget_host_( - content::RenderWidgetHostImpl::From(render_view_host->GetWidget())), - impl_(render_widget_host_->widget_host_receiver_for_testing() - .SwapImplForTesting(this)) { - render_widget_host_->AddObserver(this); - } - - CefWidgetHostInterceptor(const CefWidgetHostInterceptor&) = delete; - CefWidgetHostInterceptor& operator=(const CefWidgetHostInterceptor&) = delete; - - blink::mojom::WidgetHost* GetForwardingInterface() override { return impl_; } - - // WidgetHostInterceptorForTesting method: - void SetCursor(const ui::Cursor& cursor) override { - if (cursor_util::OnCursorChange(browser_, cursor)) { - // Don't change the cursor. - return; - } - - GetForwardingInterface()->SetCursor(cursor); - } - - // RenderWidgetHostObserver method: - void RenderWidgetHostDestroyed( - content::RenderWidgetHost* widget_host) override { - widget_host->RemoveObserver(this); - delete this; - } - - private: - AlloyBrowserHostImpl* const browser_; - content::RenderWidgetHostImpl* const render_widget_host_; - blink::mojom::WidgetHost* const impl_; -}; - static constexpr base::TimeDelta kRecentlyAudibleTimeout = base::Seconds(2); } // namespace @@ -243,7 +198,15 @@ CefRefPtr AlloyBrowserHostImpl::CreateInternal( // Notify that the browser has been created. These must be delivered in the // expected order. - // 1. Notify the browser's LifeSpanHandler. This must always be the first + if (opener && opener->platform_delegate_) { + // 1. Notify the opener browser's platform delegate. With Views this will + // result in a call to CefBrowserViewDelegate::OnPopupBrowserViewCreated(). + // Do this first for consistency with the Chrome runtime. + opener->platform_delegate_->PopupBrowserCreated(browser.get(), + is_devtools_popup); + } + + // 2. Notify the browser's LifeSpanHandler. This must always be the first // notification for the browser. Block navigation to avoid issues with focus // changes being sent to an unbound interface. { @@ -251,17 +214,10 @@ CefRefPtr AlloyBrowserHostImpl::CreateInternal( browser->OnAfterCreated(); } - // 2. Notify the platform delegate. With Views this will result in a call to + // 3. Notify the platform delegate. With Views this will result in a call to // CefBrowserViewDelegate::OnBrowserCreated(). browser->platform_delegate_->NotifyBrowserCreated(); - if (opener && opener->platform_delegate_) { - // 3. Notify the opener browser's platform delegate. With Views this will - // result in a call to CefBrowserViewDelegate::OnPopupBrowserViewCreated(). - opener->platform_delegate_->PopupBrowserCreated(browser.get(), - is_devtools_popup); - } - return browser; } @@ -355,20 +311,6 @@ bool AlloyBrowserHostImpl::TryCloseBrowser() { return true; } -void AlloyBrowserHostImpl::SetFocus(bool focus) { - // Always execute asynchronously to work around issue #3040. - CEF_POST_TASK(CEF_UIT, base::BindOnce(&AlloyBrowserHostImpl::SetFocusInternal, - this, focus)); -} - -void AlloyBrowserHostImpl::SetFocusInternal(bool focus) { - CEF_REQUIRE_UIT(); - if (focus) - OnSetFocus(FOCUS_SOURCE_SYSTEM); - else if (platform_delegate_) - platform_delegate_->SetFocus(false); -} - CefWindowHandle AlloyBrowserHostImpl::GetWindowHandle() { if (is_views_hosted_ && CEF_CURRENTLY_ON_UIT()) { // Always return the most up-to-date window handle for a views-hosted @@ -664,20 +606,6 @@ void AlloyBrowserHostImpl::SendCaptureLostEvent() { platform_delegate_->SendCaptureLostEvent(); } -void AlloyBrowserHostImpl::NotifyMoveOrResizeStarted() { -#if BUILDFLAG(IS_WIN) || (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC)) - if (!CEF_CURRENTLY_ON_UIT()) { - CEF_POST_TASK( - CEF_UIT, - base::BindOnce(&AlloyBrowserHostImpl::NotifyMoveOrResizeStarted, this)); - return; - } - - if (platform_delegate_) - platform_delegate_->NotifyMoveOrResizeStarted(); -#endif -} - int AlloyBrowserHostImpl::GetWindowlessFrameRate() { // Verify that this method is being called on the UI thread. if (!CEF_CURRENTLY_ON_UIT()) { @@ -1490,19 +1418,6 @@ bool AlloyBrowserHostImpl::IsPrerender2Supported( // content::WebContentsObserver methods. // ----------------------------------------------------------------------------- -void AlloyBrowserHostImpl::RenderFrameCreated( - content::RenderFrameHost* render_frame_host) { - if (render_frame_host->GetParent() == nullptr) { - auto render_view_host = render_frame_host->GetRenderViewHost(); - new CefWidgetHostInterceptor(this, render_view_host); - platform_delegate_->RenderViewCreated(render_view_host); - } -} - -void AlloyBrowserHostImpl::RenderViewReady() { - platform_delegate_->RenderViewReady(); -} - void AlloyBrowserHostImpl::DidFinishNavigation( content::NavigationHandle* navigation_handle) { if (web_contents()) { diff --git a/libcef/browser/alloy/alloy_browser_host_impl.h b/libcef/browser/alloy/alloy_browser_host_impl.h index dcc0d14a7..d7ff49954 100644 --- a/libcef/browser/alloy/alloy_browser_host_impl.h +++ b/libcef/browser/alloy/alloy_browser_host_impl.h @@ -79,7 +79,6 @@ class AlloyBrowserHostImpl : public CefBrowserHostBase, // CefBrowserHost methods. void CloseBrowser(bool force_close) override; bool TryCloseBrowser() override; - void SetFocus(bool focus) override; CefWindowHandle GetWindowHandle() override; CefWindowHandle GetOpenerWindowHandle() override; double GetZoomLevel() override; @@ -113,7 +112,6 @@ class AlloyBrowserHostImpl : public CefBrowserHostBase, void SendExternalBeginFrame() override; void SendTouchEvent(const CefTouchEvent& event) override; void SendCaptureLostEvent() override; - void NotifyMoveOrResizeStarted() override; int GetWindowlessFrameRate() override; void SetWindowlessFrameRate(int frame_rate) override; void ImeSetComposition(const CefString& text, @@ -293,8 +291,6 @@ class AlloyBrowserHostImpl : public CefBrowserHostBase, // content::WebContentsObserver methods. using content::WebContentsObserver::BeforeUnloadFired; - void RenderFrameCreated(content::RenderFrameHost* render_frame_host) override; - void RenderViewReady() override; void DidFinishNavigation( content::NavigationHandle* navigation_handle) override; void OnAudioStateChanged(bool audible) override; @@ -339,8 +335,6 @@ class AlloyBrowserHostImpl : public CefBrowserHostBase, void StartAudioCapturer(); void OnRecentlyAudibleTimerFired(); - void SetFocusInternal(bool focus); - CefWindowHandle opener_; const bool is_windowless_; CefWindowHandle host_window_handle_ = kNullWindowHandle; diff --git a/libcef/browser/alloy/browser_platform_delegate_alloy.cc b/libcef/browser/alloy/browser_platform_delegate_alloy.cc index adbee9154..7d1ac0231 100644 --- a/libcef/browser/alloy/browser_platform_delegate_alloy.cc +++ b/libcef/browser/alloy/browser_platform_delegate_alloy.cc @@ -112,10 +112,15 @@ void CefBrowserPlatformDelegateAlloy::WebContentsCreated( content::WebContents* web_contents, bool owned) { CefBrowserPlatformDelegate::WebContentsCreated(web_contents, owned); - find_in_page::FindTabHelper::CreateForWebContents(web_contents); - if (owned) { - SetOwnedWebContents(web_contents); + if (primary_) { + find_in_page::FindTabHelper::CreateForWebContents(web_contents); + + if (owned) { + SetOwnedWebContents(web_contents); + } + } else { + DCHECK(!owned); } } @@ -159,8 +164,8 @@ bool CefBrowserPlatformDelegateAlloy:: void CefBrowserPlatformDelegateAlloy::RenderViewCreated( content::RenderViewHost* render_view_host) { - // Indicate that the view has an external parent (namely us). This changes the - // default view behavior in some cases (e.g. focus handling on Linux). + // Indicate that the view has an external parent (namely us). This setting is + // required for proper focus handling on Windows and Linux. if (!IsViewsHosted() && render_view_host->GetWidget()->GetView()) render_view_host->GetWidget()->GetView()->SetHasExternalParent(true); } diff --git a/libcef/browser/browser_contents_delegate.cc b/libcef/browser/browser_contents_delegate.cc index aa362c672..05a50817d 100644 --- a/libcef/browser/browser_contents_delegate.cc +++ b/libcef/browser/browser_contents_delegate.cc @@ -7,8 +7,10 @@ #include "libcef/browser/browser_host_base.h" #include "libcef/browser/browser_platform_delegate.h" #include "libcef/browser/browser_util.h" +#include "libcef/browser/native/cursor_util.h" #include "libcef/common/frame_util.h" +#include "content/browser/renderer_host/render_widget_host_impl.h" #include "content/public/browser/focused_node_details.h" #include "content/public/browser/keyboard_event_processing_result.h" #include "content/public/browser/native_web_keyboard_event.h" @@ -19,12 +21,60 @@ #include "content/public/browser/notification_types.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/render_widget_host.h" +#include "content/public/browser/render_widget_host_observer.h" #include "content/public/browser/render_widget_host_view.h" #include "third_party/blink/public/mojom/favicon/favicon_url.mojom.h" #include "third_party/blink/public/mojom/input/focus_type.mojom-blink.h" +#include "third_party/blink/public/mojom/widget/platform_widget.mojom-test-utils.h" using content::KeyboardEventProcessingResult; +namespace { + +class CefWidgetHostInterceptor + : public blink::mojom::WidgetHostInterceptorForTesting, + public content::RenderWidgetHostObserver { + public: + CefWidgetHostInterceptor(CefRefPtr browser, + content::RenderViewHost* render_view_host) + : browser_(browser), + render_widget_host_( + content::RenderWidgetHostImpl::From(render_view_host->GetWidget())), + impl_(render_widget_host_->widget_host_receiver_for_testing() + .SwapImplForTesting(this)) { + render_widget_host_->AddObserver(this); + } + + CefWidgetHostInterceptor(const CefWidgetHostInterceptor&) = delete; + CefWidgetHostInterceptor& operator=(const CefWidgetHostInterceptor&) = delete; + + blink::mojom::WidgetHost* GetForwardingInterface() override { return impl_; } + + // WidgetHostInterceptorForTesting method: + void SetCursor(const ui::Cursor& cursor) override { + if (cursor_util::OnCursorChange(browser_, cursor)) { + // Don't change the cursor. + return; + } + + GetForwardingInterface()->SetCursor(cursor); + } + + // RenderWidgetHostObserver method: + void RenderWidgetHostDestroyed( + content::RenderWidgetHost* widget_host) override { + widget_host->RemoveObserver(this); + delete this; + } + + private: + CefRefPtr const browser_; + content::RenderWidgetHostImpl* const render_widget_host_; + blink::mojom::WidgetHost* const impl_; +}; + +} // namespace + CefBrowserContentsDelegate::CefBrowserContentsDelegate( scoped_refptr browser_info) : browser_info_(browser_info) { @@ -265,6 +315,9 @@ void CefBrowserContentsDelegate::RenderFrameCreated( } render_view_host->GetWidget()->GetView()->SetBackgroundColor( base_background_color); + + new CefWidgetHostInterceptor(browser(), render_view_host); + platform_delegate()->RenderViewCreated(render_view_host); } } @@ -295,6 +348,8 @@ void CefBrowserContentsDelegate::RenderFrameDeleted( } void CefBrowserContentsDelegate::RenderViewReady() { + platform_delegate()->RenderViewReady(); + if (auto c = client()) { if (auto handler = c->GetRequestHandler()) { handler->OnRenderViewReady(browser()); diff --git a/libcef/browser/browser_host_base.cc b/libcef/browser/browser_host_base.cc index 177e3b355..7f88714bf 100644 --- a/libcef/browser/browser_host_base.cc +++ b/libcef/browser/browser_host_base.cc @@ -194,6 +194,20 @@ bool CefBrowserHostBase::HasView() { return is_views_hosted_; } +void CefBrowserHostBase::SetFocus(bool focus) { + // Always execute asynchronously to work around issue #3040. + CEF_POST_TASK(CEF_UIT, base::BindOnce(&CefBrowserHostBase::SetFocusInternal, + this, focus)); +} + +void CefBrowserHostBase::SetFocusInternal(bool focus) { + CEF_REQUIRE_UIT(); + if (focus) + OnSetFocus(FOCUS_SOURCE_SYSTEM); + else if (platform_delegate_) + platform_delegate_->SetFocus(false); +} + void CefBrowserHostBase::StartDownload(const CefString& url) { if (!CEF_CURRENTLY_ON_UIT()) { CEF_POST_TASK( @@ -377,6 +391,20 @@ CefRefPtr CefBrowserHostBase::GetVisibleNavigationEntry() { return new CefNavigationEntryImpl(entry); } +void CefBrowserHostBase::NotifyMoveOrResizeStarted() { +#if BUILDFLAG(IS_WIN) || (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC)) + if (!CEF_CURRENTLY_ON_UIT()) { + CEF_POST_TASK( + CEF_UIT, + base::BindOnce(&CefBrowserHostBase::NotifyMoveOrResizeStarted, this)); + return; + } + + if (platform_delegate_) + platform_delegate_->NotifyMoveOrResizeStarted(); +#endif +} + void CefBrowserHostBase::ReplaceMisspelling(const CefString& word) { if (!CEF_CURRENTLY_ON_UIT()) { CEF_POST_TASK( diff --git a/libcef/browser/browser_host_base.h b/libcef/browser/browser_host_base.h index 2359eb72b..8dc2bbd40 100644 --- a/libcef/browser/browser_host_base.h +++ b/libcef/browser/browser_host_base.h @@ -39,14 +39,19 @@ struct CefBrowserCreateParams { settings = that.settings; request_context = that.request_context; extra_info = that.extra_info; + if (that.window_info) + MaybeSetWindowInfo(*that.window_info); #if defined(TOOLKIT_VIEWS) browser_view = that.browser_view; #endif return *this; } - // Platform-specific window creation info. Will be nullptr when creating a - // views-hosted browser. Currently used with the alloy runtime only. + // Set |window_info| if appropriate (see below). + void MaybeSetWindowInfo(const CefWindowInfo& window_info); + + // Platform-specific window creation info. Will be nullptr for Views-hosted + // browsers except when using the Chrome runtime with a native parent handle. std::unique_ptr window_info; #if defined(TOOLKIT_VIEWS) @@ -154,6 +159,7 @@ class CefBrowserHostBase : public CefBrowserHost, CefRefPtr GetClient() override; CefRefPtr GetRequestContext() override; bool HasView() override; + void SetFocus(bool focus) override; void StartDownload(const CefString& url) override; void DownloadImage(const CefString& image_url, bool is_favicon, @@ -180,6 +186,7 @@ class CefBrowserHostBase : public CefBrowserHost, void GetNavigationEntries(CefRefPtr visitor, bool current_only) override; CefRefPtr GetVisibleNavigationEntry() override; + void NotifyMoveOrResizeStarted() override; // CefBrowser methods: bool IsValid() override; @@ -283,6 +290,8 @@ class CefBrowserHostBase : public CefBrowserHost, // Called from LoadMainFrameURL to perform the actual navigation. virtual bool Navigate(const content::OpenURLParams& params); + void SetFocusInternal(bool focus); + // Thread-safe members. CefBrowserSettings settings_; CefRefPtr client_; diff --git a/libcef/browser/browser_host_create.cc b/libcef/browser/browser_host_create.cc index 10a3a4e25..8563dfd3f 100644 --- a/libcef/browser/browser_host_create.cc +++ b/libcef/browser/browser_host_create.cc @@ -10,6 +10,10 @@ #include "libcef/browser/thread_util.h" #include "libcef/features/runtime.h" +#if defined(TOOLKIT_VIEWS) +#include "libcef/browser/chrome/views/chrome_child_window.h" +#endif + namespace { class CreateBrowserHelper { @@ -138,7 +142,7 @@ CefRefPtr CefBrowserHost::CreateBrowserSync( } CefBrowserCreateParams create_params; - create_params.window_info.reset(new CefWindowInfo(windowInfo)); + create_params.MaybeSetWindowInfo(windowInfo); create_params.client = client; create_params.url = url; create_params.settings = settings; @@ -148,10 +152,24 @@ CefRefPtr CefBrowserHost::CreateBrowserSync( return CefBrowserHostBase::Create(create_params); } +void CefBrowserCreateParams::MaybeSetWindowInfo( + const CefWindowInfo& new_window_info) { + if (!cef::IsChromeRuntimeEnabled() || + chrome_child_window::HasParentHandle(new_window_info)) { + window_info = std::make_unique(new_window_info); + } +} + // static CefRefPtr CefBrowserHostBase::Create( CefBrowserCreateParams& create_params) { if (cef::IsChromeRuntimeEnabled()) { +#if defined(TOOLKIT_VIEWS) + if (auto browser = + chrome_child_window::MaybeCreateChildBrowser(create_params)) { + return browser.get(); + } +#endif auto browser = ChromeBrowserHostImpl::Create(create_params); return browser.get(); } diff --git a/libcef/browser/browser_info_manager.cc b/libcef/browser/browser_info_manager.cc index 1ab9eeda8..71fa03319 100644 --- a/libcef/browser/browser_info_manager.cc +++ b/libcef/browser/browser_info_manager.cc @@ -129,10 +129,10 @@ bool CefBrowserInfoManager::CanCreateWindow( CefRefPtr client = browser->GetClient(); bool allow = true; - std::unique_ptr window_info(new CefWindowInfo); + CefWindowInfo window_info; #if BUILDFLAG(IS_WIN) - window_info->SetAsPopup(nullptr, CefString()); + window_info.SetAsPopup(nullptr, CefString()); #endif auto pending_popup = std::make_unique(); @@ -157,20 +157,20 @@ bool CefBrowserInfoManager::CanCreateWindow( #if (BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)) // Default to the size from the popup features. if (cef_features.xSet) - window_info->bounds.x = cef_features.x; + window_info.bounds.x = cef_features.x; if (cef_features.ySet) - window_info->bounds.y = cef_features.y; + window_info.bounds.y = cef_features.y; if (cef_features.widthSet) - window_info->bounds.width = cef_features.width; + window_info.bounds.width = cef_features.width; if (cef_features.heightSet) - window_info->bounds.height = cef_features.height; + window_info.bounds.height = cef_features.height; #endif allow = !handler->OnBeforePopup( browser.get(), opener_frame, pending_popup->target_url.spec(), pending_popup->target_frame_name, static_cast(disposition), user_gesture, - cef_features, *window_info, pending_popup->client, + cef_features, window_info, pending_popup->client, pending_popup->settings, pending_popup->extra_info, no_javascript_access); } @@ -178,13 +178,8 @@ bool CefBrowserInfoManager::CanCreateWindow( if (allow) { CefBrowserCreateParams create_params; - - if (browser->HasView()) { - create_params.popup_with_views_hosted_opener = true; - } else { - create_params.window_info = std::move(window_info); - } - + create_params.MaybeSetWindowInfo(window_info); + create_params.popup_with_views_hosted_opener = browser->HasView(); create_params.settings = pending_popup->settings; create_params.client = pending_popup->client; create_params.extra_info = pending_popup->extra_info; diff --git a/libcef/browser/browser_platform_delegate.cc b/libcef/browser/browser_platform_delegate.cc index f6698a05c..b996e4aff 100644 --- a/libcef/browser/browser_platform_delegate.cc +++ b/libcef/browser/browser_platform_delegate.cc @@ -172,9 +172,7 @@ void CefBrowserPlatformDelegate::SendTouchEvent(const CefTouchEvent& event) { NOTIMPLEMENTED(); } -void CefBrowserPlatformDelegate::SetFocus(bool setFocus) { - NOTIMPLEMENTED(); -} +void CefBrowserPlatformDelegate::SetFocus(bool setFocus) {} void CefBrowserPlatformDelegate::SendCaptureLostEvent() { NOTIMPLEMENTED(); diff --git a/libcef/browser/browser_platform_delegate_create.cc b/libcef/browser/browser_platform_delegate_create.cc index daaf69157..94fd61e84 100644 --- a/libcef/browser/browser_platform_delegate_create.cc +++ b/libcef/browser/browser_platform_delegate_create.cc @@ -30,7 +30,9 @@ #endif #if defined(TOOLKIT_VIEWS) +#include "libcef/browser/chrome/views/browser_platform_delegate_chrome_child_window.h" #include "libcef/browser/chrome/views/browser_platform_delegate_chrome_views.h" +#include "libcef/browser/chrome/views/chrome_child_window.h" #include "libcef/browser/views/browser_platform_delegate_views.h" #endif @@ -80,50 +82,37 @@ std::unique_ptr CefBrowserPlatformDelegate::Create( &create_params.settings, is_windowless ? STATE_ENABLED : STATE_DISABLED); if (cef::IsChromeRuntimeEnabled()) { - // CefWindowInfo is not used in this case. + CefWindowInfo window_info; + if (create_params.window_info) { + window_info = *create_params.window_info; + } + std::unique_ptr native_delegate = - CreateNativeDelegate(CefWindowInfo(), background_color); + CreateNativeDelegate(window_info, background_color); + #if defined(TOOLKIT_VIEWS) - if (create_params.browser_view || - create_params.popup_with_views_hosted_opener) { + if (create_params.window_info) { + // CefWindowInfo should only be set if a parent handle was specified. + DCHECK(chrome_child_window::HasParentHandle(window_info)); + return std::make_unique( + std::move(native_delegate), + static_cast(create_params.browser_view.get())); + } else if (create_params.browser_view || + create_params.popup_with_views_hosted_opener) { + // CefWindowInfo is not used in this case. return std::make_unique( std::move(native_delegate), static_cast(create_params.browser_view.get())); } -#endif +#endif // defined(TOOLKIT_VIEWS) + return std::make_unique( std::move(native_delegate)); } - if (create_params.window_info) { - std::unique_ptr native_delegate = - CreateNativeDelegate(*create_params.window_info.get(), - background_color); - if (is_windowless) { - REQUIRE_ALLOY_RUNTIME(); - - const bool use_shared_texture = - create_params.window_info && - create_params.window_info->shared_texture_enabled; - - const bool use_external_begin_frame = - create_params.window_info && - create_params.window_info->external_begin_frame_enabled; - - return CreateOSRDelegate(std::move(native_delegate), use_shared_texture, - use_external_begin_frame); - } - return std::move(native_delegate); - } else if (create_params.extension_host_type == - extensions::mojom::ViewType::kExtensionBackgroundPage) { - // Creating a background extension host without a window. - std::unique_ptr native_delegate = - CreateNativeDelegate(CefWindowInfo(), background_color); - return std::make_unique( - std::move(native_delegate)); - } #if defined(TOOLKIT_VIEWS) - else { + if (create_params.browser_view || + create_params.popup_with_views_hosted_opener) { // CefWindowInfo is not used in this case. std::unique_ptr native_delegate = CreateNativeDelegate(CefWindowInfo(), background_color); @@ -133,6 +122,31 @@ std::unique_ptr CefBrowserPlatformDelegate::Create( } #endif // defined(TOOLKIT_VIEWS) + if (create_params.extension_host_type == + extensions::mojom::ViewType::kExtensionBackgroundPage) { + // Creating a background extension host without a window. + std::unique_ptr native_delegate = + CreateNativeDelegate(CefWindowInfo(), background_color); + return std::make_unique( + std::move(native_delegate)); + } else if (create_params.window_info) { + std::unique_ptr native_delegate = + CreateNativeDelegate(*create_params.window_info, background_color); + if (is_windowless) { + REQUIRE_ALLOY_RUNTIME(); + + const bool use_shared_texture = + create_params.window_info->shared_texture_enabled; + + const bool use_external_begin_frame = + create_params.window_info->external_begin_frame_enabled; + + return CreateOSRDelegate(std::move(native_delegate), use_shared_texture, + use_external_begin_frame); + } + return std::move(native_delegate); + } + NOTREACHED(); return nullptr; } diff --git a/libcef/browser/chrome/browser_platform_delegate_chrome.h b/libcef/browser/chrome/browser_platform_delegate_chrome.h index ae36d2b55..1eefeb25b 100644 --- a/libcef/browser/chrome/browser_platform_delegate_chrome.h +++ b/libcef/browser/chrome/browser_platform_delegate_chrome.h @@ -45,6 +45,10 @@ class CefBrowserPlatformDelegateChrome void set_chrome_browser(Browser* browser); + CefBrowserPlatformDelegateNative* native_delegate() const { + return native_delegate_.get(); + } + protected: std::unique_ptr native_delegate_; diff --git a/libcef/browser/chrome/chrome_browser_delegate.cc b/libcef/browser/chrome/chrome_browser_delegate.cc index 87a99e4ef..8c92ae7fd 100644 --- a/libcef/browser/chrome/chrome_browser_delegate.cc +++ b/libcef/browser/chrome/chrome_browser_delegate.cc @@ -341,6 +341,7 @@ std::unique_ptr BrowserDelegate::Create( create_params = params->create_params_; // Clear these values so they're not persisted to additional Browsers. + params->create_params_.window_info.reset(); #if defined(TOOLKIT_VIEWS) params->create_params_.browser_view = nullptr; #endif diff --git a/libcef/browser/chrome/chrome_browser_host_impl.cc b/libcef/browser/chrome/chrome_browser_host_impl.cc index de89cdab3..0e2791d28 100644 --- a/libcef/browser/chrome/chrome_browser_host_impl.cc +++ b/libcef/browser/chrome/chrome_browser_host_impl.cc @@ -143,6 +143,9 @@ void ChromeBrowserHostImpl::OnSetFocus(cef_focus_source_t source) { if (contents_delegate_->OnSetFocus(source)) return; + if (platform_delegate_) + platform_delegate_->SetFocus(true); + if (browser_) { const int tab_index = GetCurrentTabIndex(); if (tab_index != TabStripModel::kNoTab) { @@ -163,13 +166,13 @@ bool ChromeBrowserHostImpl::TryCloseBrowser() { return true; } -void ChromeBrowserHostImpl::SetFocus(bool focus) { - if (focus) { - OnSetFocus(FOCUS_SOURCE_SYSTEM); - } -} - CefWindowHandle ChromeBrowserHostImpl::GetWindowHandle() { + if (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_) + return platform_delegate_->GetHostWindowHandle(); + } NOTIMPLEMENTED(); return kNullWindowHandle; } @@ -282,10 +285,6 @@ void ChromeBrowserHostImpl::SendCaptureLostEvent() { NOTIMPLEMENTED(); } -void ChromeBrowserHostImpl::NotifyMoveOrResizeStarted() { - NOTIMPLEMENTED(); -} - int ChromeBrowserHostImpl::GetWindowlessFrameRate() { return 0; } @@ -513,7 +512,20 @@ void ChromeBrowserHostImpl::Attach(content::WebContents* web_contents, // Notify that the browser has been created. These must be delivered in the // expected order. - // 1. Notify the browser's LifeSpanHandler. This must always be the first + if (opener && opener->platform_delegate_) { + // 1. Notify the opener browser's platform delegate. With Views this will + // result in a call to CefBrowserViewDelegate::OnPopupBrowserViewCreated(). + // We want to call this method first because the implementation will often + // create the Widget for the new popup browser. Without that Widget + // CefBrowserHost::GetWindowHandle() will return kNullWindowHandle in + // OnAfterCreated(), which breaks client expectations (e.g. clients expect + // everything about the browser to be valid at that time). + opener->platform_delegate_->PopupBrowserCreated( + this, + /*is_devtools_popup=*/false); + } + + // 2. Notify the browser's LifeSpanHandler. This must always be the first // notification for the browser. { // The WebContents won't be added to the Browser's TabStripModel until later @@ -522,17 +534,9 @@ void ChromeBrowserHostImpl::Attach(content::WebContents* web_contents, OnAfterCreated(); } - // 2. Notify the platform delegate. With Views this will result in a call to + // 3. Notify the platform delegate. With Views this will result in a call to // CefBrowserViewDelegate::OnBrowserCreated(). platform_delegate_->NotifyBrowserCreated(); - - if (opener && opener->platform_delegate_) { - // 3. Notify the opener browser's platform delegate. With Views this will - // result in a call to CefBrowserViewDelegate::OnPopupBrowserViewCreated(). - opener->platform_delegate_->PopupBrowserCreated( - this, - /*is_devtools_popup=*/false); - } } void ChromeBrowserHostImpl::SetBrowser(Browser* browser) { diff --git a/libcef/browser/chrome/chrome_browser_host_impl.h b/libcef/browser/chrome/chrome_browser_host_impl.h index a8c39834d..00c1576af 100644 --- a/libcef/browser/chrome/chrome_browser_host_impl.h +++ b/libcef/browser/chrome/chrome_browser_host_impl.h @@ -62,7 +62,6 @@ class ChromeBrowserHostImpl : public CefBrowserHostBase { // CefBrowserHost methods: void CloseBrowser(bool force_close) override; bool TryCloseBrowser() override; - void SetFocus(bool focus) override; CefWindowHandle GetWindowHandle() override; CefWindowHandle GetOpenerWindowHandle() override; double GetZoomLevel() override; @@ -96,7 +95,6 @@ class ChromeBrowserHostImpl : public CefBrowserHostBase { void SendExternalBeginFrame() override; void SendTouchEvent(const CefTouchEvent& event) override; void SendCaptureLostEvent() override; - void NotifyMoveOrResizeStarted() override; int GetWindowlessFrameRate() override; void SetWindowlessFrameRate(int frame_rate) override; void ImeSetComposition(const CefString& text, diff --git a/libcef/browser/chrome/views/browser_platform_delegate_chrome_child_window.cc b/libcef/browser/chrome/views/browser_platform_delegate_chrome_child_window.cc new file mode 100644 index 000000000..5abf6a29f --- /dev/null +++ b/libcef/browser/chrome/views/browser_platform_delegate_chrome_child_window.cc @@ -0,0 +1,38 @@ +// Copyright 2022 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_child_window.h" + +#include "include/views/cef_browser_view.h" +#include "libcef/browser/chrome/views/chrome_child_window.h" + +CefBrowserPlatformDelegateChromeChildWindow:: + CefBrowserPlatformDelegateChromeChildWindow( + std::unique_ptr native_delegate, + CefRefPtr browser_view) + : CefBrowserPlatformDelegateChromeViews(std::move(native_delegate), + browser_view) {} + +void CefBrowserPlatformDelegateChromeChildWindow::RenderViewCreated( + content::RenderViewHost* render_view_host) { + CefBrowserPlatformDelegateChromeViews::RenderViewCreated(render_view_host); + + // Calls SetHasExternalParent(true). This setting is required for proper + // focus handling on Windows and Linux. + native_delegate_->RenderViewCreated(render_view_host); +} + +void CefBrowserPlatformDelegateChromeChildWindow::CloseHostWindow() { + native_delegate_->CloseHostWindow(); +} + +void CefBrowserPlatformDelegateChromeChildWindow::SetFocus(bool focus) { + native_delegate_->SetFocus(focus); +} + +#if BUILDFLAG(IS_WIN) || (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC)) +void CefBrowserPlatformDelegateChromeChildWindow::NotifyMoveOrResizeStarted() { + native_delegate_->NotifyMoveOrResizeStarted(); +} +#endif diff --git a/libcef/browser/chrome/views/browser_platform_delegate_chrome_child_window.h b/libcef/browser/chrome/views/browser_platform_delegate_chrome_child_window.h new file mode 100644 index 000000000..4f5d81a7a --- /dev/null +++ b/libcef/browser/chrome/views/browser_platform_delegate_chrome_child_window.h @@ -0,0 +1,28 @@ +// Copyright 2022 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_CHILD_WINDOW_H_ +#define CEF_LIBCEF_BROWSER_CHROME_VIEWS_BROWSER_PLATFORM_DELEGATE_CHROME_CHILD_WINDOW_H_ + +#include "libcef/browser/chrome/views/browser_platform_delegate_chrome_views.h" + +// Implementation of Chrome-based browser functionality. +class CefBrowserPlatformDelegateChromeChildWindow + : public CefBrowserPlatformDelegateChromeViews { + public: + CefBrowserPlatformDelegateChromeChildWindow( + std::unique_ptr native_delegate, + CefRefPtr browser_view); + + // CefBrowserPlatformDelegate overrides. + void RenderViewCreated(content::RenderViewHost* render_view_host) override; + void CloseHostWindow() override; + void SetFocus(bool focus) override; + +#if BUILDFLAG(IS_WIN) || (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC)) + void NotifyMoveOrResizeStarted() override; +#endif +}; + +#endif // CEF_LIBCEF_BROWSER_CHROME_VIEWS_BROWSER_PLATFORM_DELEGATE_CHROME_CHILD_WINDOW_H_ diff --git a/libcef/browser/chrome/views/browser_platform_delegate_chrome_views.cc b/libcef/browser/chrome/views/browser_platform_delegate_chrome_views.cc index 455037c03..2b63e397c 100644 --- a/libcef/browser/chrome/views/browser_platform_delegate_chrome_views.cc +++ b/libcef/browser/chrome/views/browser_platform_delegate_chrome_views.cc @@ -95,6 +95,11 @@ void CefBrowserPlatformDelegateChromeViews::CloseHostWindow() { widget->Close(); } +CefWindowHandle CefBrowserPlatformDelegateChromeViews::GetHostWindowHandle() + const { + return view_util::GetWindowHandle(GetWindowWidget()); +} + views::Widget* CefBrowserPlatformDelegateChromeViews::GetWindowWidget() const { if (browser_view_->root_view()) return browser_view_->root_view()->GetWidget(); diff --git a/libcef/browser/chrome/views/browser_platform_delegate_chrome_views.h b/libcef/browser/chrome/views/browser_platform_delegate_chrome_views.h index 2b8400aec..4b41b411a 100644 --- a/libcef/browser/chrome/views/browser_platform_delegate_chrome_views.h +++ b/libcef/browser/chrome/views/browser_platform_delegate_chrome_views.h @@ -24,6 +24,7 @@ class CefBrowserPlatformDelegateChromeViews void NotifyBrowserDestroyed() override; void BrowserDestroyed(CefBrowserHostBase* browser) override; void CloseHostWindow() override; + CefWindowHandle GetHostWindowHandle() const override; views::Widget* GetWindowWidget() const override; CefRefPtr GetBrowserView() const override; void PopupWebContentsCreated( @@ -36,6 +37,8 @@ class CefBrowserPlatformDelegateChromeViews bool is_devtools) override; bool IsViewsHosted() const override; + CefRefPtr browser_view() const { return browser_view_; } + private: void SetBrowserView(CefRefPtr browser_view); diff --git a/libcef/browser/chrome/views/chrome_child_window.cc b/libcef/browser/chrome/views/chrome_child_window.cc new file mode 100644 index 000000000..d072eaacf --- /dev/null +++ b/libcef/browser/chrome/views/chrome_child_window.cc @@ -0,0 +1,199 @@ +// Copyright 2022 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_child_window.h" + +#include "libcef/browser/chrome/views/browser_platform_delegate_chrome_views.h" +#include "libcef/browser/views/browser_view_impl.h" +#include "libcef/browser/views/window_impl.h" + +#if BUILDFLAG(IS_WIN) +#include "libcef/browser/native/browser_platform_delegate_native_win.h" +#include "ui/views/win/hwnd_util.h" +#endif + +namespace { + +class ChildWindowDelegate : public CefWindowDelegate { + public: + ChildWindowDelegate(const ChildWindowDelegate&) = delete; + ChildWindowDelegate& operator=(const ChildWindowDelegate&) = delete; + + static void Create(CefRefPtr browser_view, + const CefWindowInfo& window_info, + gfx::AcceleratedWidget parent_handle) { + DCHECK(parent_handle != gfx::kNullAcceleratedWidget); + + // Create the Window. It will show itself after creation. + CefWindowImpl::Create(new ChildWindowDelegate(browser_view, window_info), + parent_handle); + } + + void OnWindowCreated(CefRefPtr window) override { + DCHECK(!window_); + window_ = window; + + // Add the browser view. It will now have an associated Widget. + window_->AddChildView(browser_view_); + + ShowWindow(); + } + + void OnWindowDestroyed(CefRefPtr window) override { + browser_view_ = nullptr; + window_ = nullptr; + } + + CefRect GetInitialBounds(CefRefPtr window) override { + CefRect initial_bounds(window_info_.bounds); + if (initial_bounds.IsEmpty()) + return CefRect(0, 0, 800, 600); + return initial_bounds; + } + + void ShowWindow() { +#if BUILDFLAG(IS_WIN) + auto widget = static_cast(window_.get())->widget(); + DCHECK(widget); + const HWND widget_hwnd = HWNDForWidget(widget); + DCHECK(widget_hwnd); + + // The native delegate needs state to perform some actions. + auto browser = + static_cast(browser_view_->GetBrowser().get()); + auto platform_delegate = browser->platform_delegate(); + DCHECK(platform_delegate->IsViewsHosted()); + auto chrome_delegate = + static_cast(platform_delegate); + auto native_delegate = static_cast( + chrome_delegate->native_delegate()); + native_delegate->set_widget(widget, widget_hwnd); + + if (window_info_.ex_style & WS_EX_NOACTIVATE) { + const DWORD widget_ex_styles = GetWindowLongPtr(widget_hwnd, GWL_EXSTYLE); + + // Add the WS_EX_NOACTIVATE style on the DesktopWindowTreeHostWin HWND + // so that HWNDMessageHandler::Show() called via Widget::Show() does not + // activate the window. + SetWindowLongPtr(widget_hwnd, GWL_EXSTYLE, + widget_ex_styles | WS_EX_NOACTIVATE); + + window_->Show(); + + // Remove the WS_EX_NOACTIVATE style so that future mouse clicks inside + // the browser correctly activate and focus the window. + SetWindowLongPtr(widget_hwnd, GWL_EXSTYLE, widget_ex_styles); + return; + } +#endif // BUILDFLAG(IS_WIN) + + window_->Show(); + + // Give keyboard focus to the browser view. + browser_view_->RequestFocus(); + } + + private: + ChildWindowDelegate(CefRefPtr browser_view, + const CefWindowInfo& window_info) + : browser_view_(browser_view), window_info_(window_info) {} + + CefRefPtr browser_view_; + const CefWindowInfo window_info_; + + CefRefPtr window_; + + IMPLEMENT_REFCOUNTING(ChildWindowDelegate); +}; + +class ChildBrowserViewDelegate : public CefBrowserViewDelegate { + public: + ChildBrowserViewDelegate() = default; + + ChildBrowserViewDelegate(const ChildBrowserViewDelegate&) = delete; + ChildBrowserViewDelegate& operator=(const ChildBrowserViewDelegate&) = delete; + + CefRefPtr GetDelegateForPopupBrowserView( + CefRefPtr browser_view, + const CefBrowserSettings& settings, + CefRefPtr client, + bool is_devtools) override { + return new ChildBrowserViewDelegate(); + } + + bool OnPopupBrowserViewCreated(CefRefPtr browser_view, + CefRefPtr popup_browser_view, + bool is_devtools) override { + DCHECK(!is_devtools); + + auto new_browser = static_cast( + popup_browser_view->GetBrowser().get()); + auto new_platform_delegate = new_browser->platform_delegate(); + DCHECK(new_platform_delegate->IsViewsHosted()); + auto new_platform_delegate_impl = + static_cast( + new_platform_delegate); + + const auto& window_info = + new_platform_delegate_impl->native_delegate()->window_info(); + const auto parent_handle = + chrome_child_window::GetParentHandle(window_info); + if (parent_handle != gfx::kNullAcceleratedWidget) { + ChildWindowDelegate::Create(popup_browser_view, window_info, + parent_handle); + return true; + } + + // Use the default implementation that creates a new Views-hosted top-level + // window. + return false; + } + + private: + IMPLEMENT_REFCOUNTING(ChildBrowserViewDelegate); +}; + +} // namespace + +namespace chrome_child_window { + +bool HasParentHandle(const CefWindowInfo& window_info) { + return GetParentHandle(window_info) != gfx::kNullAcceleratedWidget; +} + +gfx::AcceleratedWidget GetParentHandle(const CefWindowInfo& window_info) { +#if !BUILDFLAG(IS_MAC) + return window_info.parent_window; +#else + return gfx::kNullAcceleratedWidget; +#endif +} + +CefRefPtr MaybeCreateChildBrowser( + const CefBrowserCreateParams& create_params) { + // If the BrowserView already exists it means that we're dealing with a popup + // and we'll instead create the Window in OnPopupBrowserViewCreated. + if (create_params.browser_view) + return nullptr; + + if (!create_params.window_info) + return nullptr; + + const auto parent_handle = GetParentHandle(*create_params.window_info); + if (parent_handle == gfx::kNullAcceleratedWidget) + return nullptr; + + // Create the BrowserView. + auto browser_view = CefBrowserViewImpl::Create( + *create_params.window_info, create_params.client, create_params.url, + create_params.settings, create_params.extra_info, + create_params.request_context, new ChildBrowserViewDelegate()); + + ChildWindowDelegate::Create(browser_view, *create_params.window_info, + parent_handle); + + return static_cast(browser_view->GetBrowser().get()); +} + +} // namespace chrome_child_window diff --git a/libcef/browser/chrome/views/chrome_child_window.h b/libcef/browser/chrome/views/chrome_child_window.h new file mode 100644 index 000000000..ac77481d7 --- /dev/null +++ b/libcef/browser/chrome/views/chrome_child_window.h @@ -0,0 +1,24 @@ +// Copyright 2022 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_CHILD_WINDOW_H_ +#define CEF_LIBCEF_BROWSER_CHROME_VIEWS_CHROME_CHILD_WINDOW_H_ +#pragma once + +#include "libcef/browser/browser_host_base.h" + +#include "ui/gfx/native_widget_types.h" + +namespace chrome_child_window { + +bool HasParentHandle(const CefWindowInfo& window_info); +gfx::AcceleratedWidget GetParentHandle(const CefWindowInfo& window_info); + +// Called from CefBrowserHostBase::Create. +CefRefPtr MaybeCreateChildBrowser( + const CefBrowserCreateParams& create_params); + +} // namespace chrome_child_window + +#endif // CEF_LIBCEF_BROWSER_CHROME_VIEWS_CHROME_CHILD_WINDOW_H_ diff --git a/libcef/browser/devtools/devtools_frontend.cc b/libcef/browser/devtools/devtools_frontend.cc index 6fea93e5f..9d9d6a04c 100644 --- a/libcef/browser/devtools/devtools_frontend.cc +++ b/libcef/browser/devtools/devtools_frontend.cc @@ -251,8 +251,11 @@ CefDevToolsFrontend* CefDevToolsFrontend::Show( } CefBrowserCreateParams create_params; - if (!inspected_browser->is_views_hosted()) + if (inspected_browser->is_views_hosted()) { + create_params.popup_with_views_hosted_opener = true; + } else { create_params.window_info.reset(new CefWindowInfo(windowInfo)); + } create_params.client = client; create_params.settings = new_settings; create_params.devtools_opener = inspected_browser; diff --git a/libcef/browser/extensions/extension_function_details.cc b/libcef/browser/extensions/extension_function_details.cc index ca57de415..a74a252f6 100644 --- a/libcef/browser/extensions/extension_function_details.cc +++ b/libcef/browser/extensions/extension_function_details.cc @@ -381,6 +381,7 @@ base::DictionaryValue* CefExtensionFunctionDetails::OpenTab( if (active_browser->is_views_hosted()) { // The new browser will also be Views hosted. + create_params.popup_with_views_hosted_opener = true; create_params.window_info.reset(); } diff --git a/libcef/browser/native/browser_platform_delegate_native_linux.cc b/libcef/browser/native/browser_platform_delegate_native_linux.cc index 4d67bb273..3716d9d18 100644 --- a/libcef/browser/native/browser_platform_delegate_native_linux.cc +++ b/libcef/browser/native/browser_platform_delegate_native_linux.cc @@ -37,7 +37,7 @@ CefBrowserPlatformDelegateNativeLinux::CefBrowserPlatformDelegateNativeLinux( void CefBrowserPlatformDelegateNativeLinux::BrowserDestroyed( CefBrowserHostBase* browser) { - CefBrowserPlatformDelegateNative::BrowserDestroyed(browser); + CefBrowserPlatformDelegateNativeAura::BrowserDestroyed(browser); if (host_window_created_) { // Release the reference added in CreateHostWindow(). @@ -155,7 +155,7 @@ void CefBrowserPlatformDelegateNativeLinux::SetFocus(bool setFocus) { void CefBrowserPlatformDelegateNativeLinux::NotifyMoveOrResizeStarted() { // Call the parent method to dismiss any existing popups. - CefBrowserPlatformDelegateNative::NotifyMoveOrResizeStarted(); + CefBrowserPlatformDelegateNativeAura::NotifyMoveOrResizeStarted(); if (!web_contents_) return; diff --git a/libcef/browser/native/browser_platform_delegate_native_win.cc b/libcef/browser/native/browser_platform_delegate_native_win.cc index 1ea9eeb43..7aa418155 100644 --- a/libcef/browser/native/browser_platform_delegate_native_win.cc +++ b/libcef/browser/native/browser_platform_delegate_native_win.cc @@ -156,9 +156,18 @@ CefBrowserPlatformDelegateNativeWin::CefBrowserPlatformDelegateNativeWin( SkColor background_color) : CefBrowserPlatformDelegateNativeAura(window_info, background_color) {} +void CefBrowserPlatformDelegateNativeWin::set_widget( + views::Widget* widget, + CefWindowHandle widget_handle) { + DCHECK(!window_widget_); + window_widget_ = widget; + DCHECK(!window_info_.window); + window_info_.window = widget_handle; +} + void CefBrowserPlatformDelegateNativeWin::BrowserDestroyed( CefBrowserHostBase* browser) { - CefBrowserPlatformDelegateNative::BrowserDestroyed(browser); + CefBrowserPlatformDelegateNativeAura::BrowserDestroyed(browser); if (host_window_created_) { // Release the reference added in CreateHostWindow(). @@ -315,7 +324,7 @@ void CefBrowserPlatformDelegateNativeWin::SetFocus(bool setFocus) { void CefBrowserPlatformDelegateNativeWin::NotifyMoveOrResizeStarted() { // Call the parent method to dismiss any existing popups. - CefBrowserPlatformDelegateNative::NotifyMoveOrResizeStarted(); + CefBrowserPlatformDelegateNativeAura::NotifyMoveOrResizeStarted(); if (!window_widget_) return; diff --git a/libcef/browser/native/browser_platform_delegate_native_win.h b/libcef/browser/native/browser_platform_delegate_native_win.h index 9879f6c03..58689a04c 100644 --- a/libcef/browser/native/browser_platform_delegate_native_win.h +++ b/libcef/browser/native/browser_platform_delegate_native_win.h @@ -16,6 +16,9 @@ class CefBrowserPlatformDelegateNativeWin CefBrowserPlatformDelegateNativeWin(const CefWindowInfo& window_info, SkColor background_color); + // Called from chrome_child_window.cc after |widget| is created. + void set_widget(views::Widget* widget, CefWindowHandle widget_handle); + // CefBrowserPlatformDelegate methods: void BrowserDestroyed(CefBrowserHostBase* browser) override; bool CreateHostWindow() override; diff --git a/libcef/browser/native/cursor_util.cc b/libcef/browser/native/cursor_util.cc index 9b4d07293..1789f64bd 100644 --- a/libcef/browser/native/cursor_util.cc +++ b/libcef/browser/native/cursor_util.cc @@ -12,8 +12,8 @@ namespace cursor_util { -bool OnCursorChange(CefBrowserHostBase* browser, const ui::Cursor& ui_cursor) { - auto client = browser->GetClient(); +bool OnCursorChange(CefRefPtr browser, const ui::Cursor& ui_cursor) { + auto client = browser->GetHost()->GetClient(); if (!client) return false; auto handler = client->GetDisplayHandler(); diff --git a/libcef/browser/native/cursor_util.h b/libcef/browser/native/cursor_util.h index 9e677ef6f..5830cf176 100644 --- a/libcef/browser/native/cursor_util.h +++ b/libcef/browser/native/cursor_util.h @@ -5,7 +5,7 @@ #ifndef CEF_LIBCEF_BROWSER_NATIVE_CURSOR_UTIL_H_ #define CEF_LIBCEF_BROWSER_NATIVE_CURSOR_UTIL_H_ -#include "include/internal/cef_types.h" +#include "include/cef_browser.h" #include "ui/base/cursor/cursor.h" #include "ui/base/cursor/mojom/cursor_type.mojom-forward.h" @@ -14,8 +14,6 @@ #include "ui/base/cursor/platform_cursor.h" #endif -class CefBrowserHostBase; - namespace cursor_util { #if defined(USE_AURA) @@ -24,7 +22,7 @@ cef_cursor_handle_t ToCursorHandle(scoped_refptr cursor); #endif // defined(USE_AURA) // Returns true if the client handled the cursor change. -bool OnCursorChange(CefBrowserHostBase* browser, const ui::Cursor& ui_cursor); +bool OnCursorChange(CefRefPtr browser, const ui::Cursor& ui_cursor); } // namespace cursor_util diff --git a/libcef/browser/views/browser_view_impl.cc b/libcef/browser/views/browser_view_impl.cc index 139dff2ad..57e53450b 100644 --- a/libcef/browser/views/browser_view_impl.cc +++ b/libcef/browser/views/browser_view_impl.cc @@ -23,8 +23,8 @@ CefRefPtr CefBrowserView::CreateBrowserView( CefRefPtr extra_info, CefRefPtr request_context, CefRefPtr delegate) { - return CefBrowserViewImpl::Create(client, url, settings, extra_info, - request_context, delegate); + return CefBrowserViewImpl::Create(CefWindowInfo(), client, url, settings, + extra_info, request_context, delegate); } // static @@ -41,6 +41,7 @@ CefRefPtr CefBrowserView::GetForBrowser( // static CefRefPtr CefBrowserViewImpl::Create( + const CefWindowInfo& window_info, CefRefPtr client, const CefString& url, const CefBrowserSettings& settings, @@ -62,8 +63,8 @@ CefRefPtr CefBrowserViewImpl::Create( } CefRefPtr browser_view = new CefBrowserViewImpl(delegate); - browser_view->SetPendingBrowserCreateParams(client, url, settings, extra_info, - request_context); + browser_view->SetPendingBrowserCreateParams( + window_info, client, url, settings, extra_info, request_context); browser_view->Initialize(); browser_view->SetDefaults(settings); return browser_view; @@ -212,6 +213,7 @@ CefBrowserViewImpl::CefBrowserViewImpl( : ParentClass(delegate), weak_ptr_factory_(this) {} void CefBrowserViewImpl::SetPendingBrowserCreateParams( + const CefWindowInfo& window_info, CefRefPtr client, const CefString& url, const CefBrowserSettings& settings, @@ -219,6 +221,7 @@ void CefBrowserViewImpl::SetPendingBrowserCreateParams( CefRefPtr request_context) { DCHECK(!pending_browser_create_params_); pending_browser_create_params_.reset(new CefBrowserCreateParams()); + pending_browser_create_params_->MaybeSetWindowInfo(window_info); pending_browser_create_params_->client = client; pending_browser_create_params_->url = url; pending_browser_create_params_->settings = settings; @@ -248,6 +251,9 @@ void CefBrowserViewImpl::InitializeRootView() { } views::WebView* CefBrowserViewImpl::web_view() const { + if (!root_view()) + return nullptr; + if (cef::IsChromeRuntimeEnabled()) { return static_cast(root_view())->contents_web_view(); } diff --git a/libcef/browser/views/browser_view_impl.h b/libcef/browser/views/browser_view_impl.h index 98c071bce..c1b738748 100644 --- a/libcef/browser/views/browser_view_impl.h +++ b/libcef/browser/views/browser_view_impl.h @@ -30,7 +30,9 @@ class CefBrowserViewImpl CefBrowserViewImpl& operator=(const CefBrowserViewImpl&) = delete; // Create a new CefBrowserView instance. |delegate| may be nullptr. + // |window_info| will only be used when creating a Chrome child window. static CefRefPtr Create( + const CefWindowInfo& window_info, CefRefPtr client, const CefString& url, const CefBrowserSettings& settings, @@ -84,6 +86,7 @@ class CefBrowserViewImpl explicit CefBrowserViewImpl(CefRefPtr delegate); void SetPendingBrowserCreateParams( + const CefWindowInfo& window_info, CefRefPtr client, const CefString& url, const CefBrowserSettings& settings, diff --git a/libcef/browser/views/window_impl.cc b/libcef/browser/views/window_impl.cc index 713f19a00..b256822d4 100644 --- a/libcef/browser/views/window_impl.cc +++ b/libcef/browser/views/window_impl.cc @@ -125,16 +125,17 @@ class CefUnhandledKeyEventHandler : public ui::EventHandler { // static CefRefPtr CefWindow::CreateTopLevelWindow( CefRefPtr delegate) { - return CefWindowImpl::Create(delegate); + return CefWindowImpl::Create(delegate, gfx::kNullAcceleratedWidget); } // static CefRefPtr CefWindowImpl::Create( - CefRefPtr delegate) { + CefRefPtr delegate, + gfx::AcceleratedWidget parent_widget) { CEF_REQUIRE_UIT_RETURN(nullptr); CefRefPtr window = new CefWindowImpl(delegate); window->Initialize(); - window->CreateWidget(); + window->CreateWidget(parent_widget); if (delegate) delegate->OnWindowCreated(window.get()); return window; @@ -656,10 +657,10 @@ void CefWindowImpl::InitializeRootView() { static_cast(root_view())->Initialize(); } -void CefWindowImpl::CreateWidget() { +void CefWindowImpl::CreateWidget(gfx::AcceleratedWidget parent_widget) { DCHECK(!widget_); - root_view()->CreateWidget(); + root_view()->CreateWidget(parent_widget); widget_ = root_view()->GetWidget(); DCHECK(widget_); diff --git a/libcef/browser/views/window_impl.h b/libcef/browser/views/window_impl.h index 092fa6204..f9557d415 100644 --- a/libcef/browser/views/window_impl.h +++ b/libcef/browser/views/window_impl.h @@ -33,8 +33,10 @@ class CefWindowImpl CefWindowImpl(const CefWindowImpl&) = delete; CefWindowImpl& operator=(const CefWindowImpl&) = delete; - // Create a new CefWindow instance. |delegate| may be nullptr. - static CefRefPtr Create(CefRefPtr delegate); + // Create a new CefWindow instance. |delegate| may be nullptr. |parent_widget| + // will be used when creating a Chrome child window. + static CefRefPtr Create(CefRefPtr delegate, + gfx::AcceleratedWidget parent_widget); // CefWindow methods: void Show() override; @@ -141,7 +143,7 @@ class CefWindowImpl void InitializeRootView() override; // Initialize the Widget. - void CreateWidget(); + void CreateWidget(gfx::AcceleratedWidget parent_widget); views::Widget* widget_; diff --git a/libcef/browser/views/window_view.cc b/libcef/browser/views/window_view.cc index f1784a5a8..2964c1352 100644 --- a/libcef/browser/views/window_view.cc +++ b/libcef/browser/views/window_view.cc @@ -254,7 +254,7 @@ CefWindowView::CefWindowView(CefWindowDelegate* cef_delegate, DCHECK(window_delegate_); } -void CefWindowView::CreateWidget() { +void CefWindowView::CreateWidget(gfx::AcceleratedWidget parent_widget) { DCHECK(!GetWidget()); // |widget| is owned by the NativeWidget and will be destroyed in response to @@ -264,8 +264,29 @@ void CefWindowView::CreateWidget() { views::Widget::InitParams params; params.delegate = this; - params.type = views::Widget::InitParams::TYPE_WINDOW; + bool can_activate = true; + bool can_resize = true; + + const bool has_native_parent = parent_widget != gfx::kNullAcceleratedWidget; + if (has_native_parent) { + params.parent_widget = parent_widget; + + // Remove the window frame. + is_frameless_ = true; + + // See CalculateWindowStylesFromInitParams in + // ui/views/widget/widget_hwnd_utils.cc for the conversion of |params| to + // Windows style flags. + // - Set the WS_CHILD flag. + params.child = true; + // - Set the WS_VISIBLE flag. + params.type = views::Widget::InitParams::TYPE_CONTROL; + // - Don't set the WS_EX_COMPOSITED flag. + params.opacity = views::Widget::InitParams::WindowOpacity::kOpaque; + } else { + params.type = views::Widget::InitParams::TYPE_WINDOW; + } // WidgetDelegate::DeleteDelegate() will delete |this| after executing the // registered callback. @@ -275,47 +296,49 @@ void CefWindowView::CreateWidget() { if (cef_delegate()) { CefRefPtr cef_window = GetCefWindow(); - is_frameless_ = cef_delegate()->IsFrameless(cef_window); auto bounds = cef_delegate()->GetInitialBounds(cef_window); params.bounds = gfx::Rect(bounds.x, bounds.y, bounds.width, bounds.height); - SetCanResize(cef_delegate()->CanResize(cef_window)); + if (has_native_parent) { + DCHECK(!params.bounds.IsEmpty()); + } else { + is_frameless_ = cef_delegate()->IsFrameless(cef_window); + can_resize = cef_delegate()->CanResize(cef_window); - const auto show_state = cef_delegate()->GetInitialShowState(cef_window); - switch (show_state) { - case CEF_SHOW_STATE_NORMAL: - params.show_state = ui::SHOW_STATE_NORMAL; - break; - case CEF_SHOW_STATE_MINIMIZED: - params.show_state = ui::SHOW_STATE_MINIMIZED; - break; - case CEF_SHOW_STATE_MAXIMIZED: - params.show_state = ui::SHOW_STATE_MAXIMIZED; - break; - case CEF_SHOW_STATE_FULLSCREEN: - params.show_state = ui::SHOW_STATE_FULLSCREEN; - break; - } + const auto show_state = cef_delegate()->GetInitialShowState(cef_window); + switch (show_state) { + case CEF_SHOW_STATE_NORMAL: + params.show_state = ui::SHOW_STATE_NORMAL; + break; + case CEF_SHOW_STATE_MINIMIZED: + params.show_state = ui::SHOW_STATE_MINIMIZED; + break; + case CEF_SHOW_STATE_MAXIMIZED: + params.show_state = ui::SHOW_STATE_MAXIMIZED; + break; + case CEF_SHOW_STATE_FULLSCREEN: + params.show_state = ui::SHOW_STATE_FULLSCREEN; + break; + } - bool is_menu = false; - bool can_activate_menu = true; - CefRefPtr parent_window = cef_delegate()->GetParentWindow( - cef_window, &is_menu, &can_activate_menu); - if (parent_window && !parent_window->IsSame(cef_window)) { - CefWindowImpl* parent_window_impl = - static_cast(parent_window.get()); - params.parent = view_util::GetNativeView(parent_window_impl->widget()); - if (is_menu) { - // Don't clip the window to parent bounds. - params.type = views::Widget::InitParams::TYPE_MENU; + bool is_menu = false; + bool can_activate_menu = true; + CefRefPtr parent_window = cef_delegate()->GetParentWindow( + cef_window, &is_menu, &can_activate_menu); + if (parent_window && !parent_window->IsSame(cef_window)) { + CefWindowImpl* parent_window_impl = + static_cast(parent_window.get()); + params.parent = view_util::GetNativeView(parent_window_impl->widget()); + if (is_menu) { + // Don't clip the window to parent bounds. + params.type = views::Widget::InitParams::TYPE_MENU; - // Don't set "always on top" for the window. - params.z_order = ui::ZOrderLevel::kNormal; + // Don't set "always on top" for the window. + params.z_order = ui::ZOrderLevel::kNormal; - can_activate = can_activate_menu; - if (can_activate_menu) - params.activatable = views::Widget::InitParams::Activatable::kYes; + can_activate = can_activate_menu; + } } } } @@ -325,6 +348,13 @@ void CefWindowView::CreateWidget() { params.bounds = gfx::Rect(CalculatePreferredSize()); } + if (can_activate) { + // Cause WidgetDelegate::CanActivate to return true. + params.activatable = views::Widget::InitParams::Activatable::kYes; + } + + SetCanResize(can_resize); + #if BUILDFLAG(IS_WIN) if (is_frameless_) { // Don't show the native window caption. Setting this value on Linux will diff --git a/libcef/browser/views/window_view.h b/libcef/browser/views/window_view.h index cbaaab6cc..7a26d18d5 100644 --- a/libcef/browser/views/window_view.h +++ b/libcef/browser/views/window_view.h @@ -51,7 +51,7 @@ class CefWindowView CefWindowView& operator=(const CefWindowView&) = delete; // Create the Widget. - void CreateWidget(); + void CreateWidget(gfx::AcceleratedWidget parent_widget); // Returns the CefWindow associated with this view. See comments on // CefViewView::GetCefView. diff --git a/patch/patch.cfg b/patch/patch.cfg index d36783159..2916333e2 100644 --- a/patch/patch.cfg +++ b/patch/patch.cfg @@ -539,5 +539,10 @@ patches = [ # Remove DCHECK that triggers while loading DevTools resources. # https://bugs.chromium.org/p/chromium/issues/detail?id=1289230 'name': 'blink_security_policy_1289230', + }, + { + # Windows: Always use the root window as the owner for shell dialogs. + # https://bitbucket.org/chromiumembedded/cef/issues/3294 + 'name': 'win_shell_dialogs_3294', } ] diff --git a/patch/patches/chrome_runtime_views.patch b/patch/patches/chrome_runtime_views.patch index f50e1cf03..abe6e1f51 100644 --- a/patch/patches/chrome_runtime_views.patch +++ b/patch/patches/chrome_runtime_views.patch @@ -45,7 +45,7 @@ index f9d291e52bc70..288d8ea2b3d72 100644 bool BrowserCommandController::IsWebAppOrCustomTab() const { diff --git chrome/browser/ui/views/frame/browser_frame.cc chrome/browser/ui/views/frame/browser_frame.cc -index 42ce84a750319..a0e5ead15263b 100644 +index 42ce84a750319..28b8702260434 100644 --- chrome/browser/ui/views/frame/browser_frame.cc +++ chrome/browser/ui/views/frame/browser_frame.cc @@ -74,15 +74,23 @@ bool IsUsingGtkTheme(Profile* profile) { @@ -127,7 +127,16 @@ index 42ce84a750319..a0e5ead15263b 100644 Browser* browser = browser_view_->browser(); // If this is an incognito profile, there should never be a custom theme. if (browser->profile()->IsIncognitoProfile()) -@@ -352,6 +378,8 @@ void BrowserFrame::SetTabDragKind(TabDragKind tab_drag_kind) { +@@ -263,6 +289,8 @@ BrowserFrame::GetCustomTheme() const { + } + + void BrowserFrame::OnNativeWidgetWorkspaceChanged() { ++ if (!browser_view_) ++ return; + chrome::SaveWindowWorkspace(browser_view_->browser(), GetWorkspace()); + chrome::SaveWindowVisibleOnAllWorkspaces(browser_view_->browser(), + IsVisibleOnAllWorkspaces()); +@@ -352,6 +380,8 @@ void BrowserFrame::SetTabDragKind(TabDragKind tab_drag_kind) { ui::ColorProviderManager::Key BrowserFrame::GetColorProviderKey() const { auto key = Widget::GetColorProviderKey(); @@ -136,7 +145,7 @@ index 42ce84a750319..a0e5ead15263b 100644 auto* app_controller = browser_view_->browser()->app_controller(); key.app_controller = app_controller ? app_controller->get_weak_ref() : nullptr; -@@ -382,7 +410,8 @@ void BrowserFrame::SelectNativeTheme() { +@@ -382,7 +412,8 @@ void BrowserFrame::SelectNativeTheme() { // Select between regular, dark and GTK theme. ui::NativeTheme* native_theme = ui::NativeTheme::GetInstanceForNativeUi(); @@ -146,7 +155,7 @@ index 42ce84a750319..a0e5ead15263b 100644 // No matter if we are using the default theme or not we always use the dark // ui instance. SetNativeTheme(ui::NativeTheme::GetInstanceForDarkUI()); -@@ -395,7 +424,8 @@ void BrowserFrame::SelectNativeTheme() { +@@ -395,7 +426,8 @@ void BrowserFrame::SelectNativeTheme() { // display_override so the web contents can blend with the overlay by using // the developer-provided theme color for a better experience. Context: // https://crbug.com/1219073. diff --git a/patch/patches/win_shell_dialogs_3294.patch b/patch/patches/win_shell_dialogs_3294.patch new file mode 100644 index 000000000..567006c96 --- /dev/null +++ b/patch/patches/win_shell_dialogs_3294.patch @@ -0,0 +1,29 @@ +diff --git ui/shell_dialogs/base_shell_dialog_win.cc ui/shell_dialogs/base_shell_dialog_win.cc +index 46fd116c02dad..499bf49cff882 100644 +--- ui/shell_dialogs/base_shell_dialog_win.cc ++++ ui/shell_dialogs/base_shell_dialog_win.cc +@@ -59,11 +59,15 @@ BaseShellDialogImpl::Owners& BaseShellDialogImpl::GetOwners() { + + // static + void BaseShellDialogImpl::DisableOwner(HWND owner) { ++ if (owner) ++ owner = GetAncestor(owner, GA_ROOT); + SetOwnerEnabled(owner, false); + } + + std::unique_ptr BaseShellDialogImpl::BeginRun( + HWND owner) { ++ if (owner) ++ owner = GetAncestor(owner, GA_ROOT); + // Cannot run a modal shell dialog if one is already running for this owner. + DCHECK(!IsRunningDialogForOwner(owner)); + // The owner must be a top level window, otherwise we could end up with two +@@ -89,6 +93,8 @@ void BaseShellDialogImpl::EndRun(std::unique_ptr run_state) { + } + + bool BaseShellDialogImpl::IsRunningDialogForOwner(HWND owner) const { ++ if (owner) ++ owner = GetAncestor(owner, GA_ROOT); + return (owner && GetOwners().find(owner) != GetOwners().end()); + } + diff --git a/tests/cefclient/browser/main_context_impl.cc b/tests/cefclient/browser/main_context_impl.cc index 095f99f87..68d56275f 100644 --- a/tests/cefclient/browser/main_context_impl.cc +++ b/tests/cefclient/browser/main_context_impl.cc @@ -108,6 +108,13 @@ MainContextImpl::MainContextImpl(CefRefPtr command_line, use_views_ = false; } +#if defined(OS_WIN) || defined(OS_LINUX) + if (use_chrome_runtime_ && !use_views_ && + !command_line->HasSwitch(switches::kUseNative)) { + LOG(WARNING) << "Chrome runtime defaults to the Views framework."; + use_views_ = true; + } +#else // !(defined(OS_WIN) || defined(OS_LINUX)) 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 @@ -115,6 +122,7 @@ MainContextImpl::MainContextImpl(CefRefPtr command_line, LOG(WARNING) << "Chrome runtime requires the Views framework."; use_views_ = true; } +#endif // !(defined(OS_WIN) || defined(OS_LINUX)) if (use_views_ && command_line->HasSwitch(switches::kHideFrame) && !command_line_->HasSwitch(switches::kUrl)) { diff --git a/tests/shared/common/client_switches.cc b/tests/shared/common/client_switches.cc index 34e647580..679e8d2a8 100644 --- a/tests/shared/common/client_switches.cc +++ b/tests/shared/common/client_switches.cc @@ -35,6 +35,7 @@ const char kBackgroundColor[] = "background-color"; const char kEnableGPU[] = "enable-gpu"; const char kFilterURL[] = "filter-url"; const char kUseViews[] = "use-views"; +const char kUseNative[] = "use-native"; const char kHideFrame[] = "hide-frame"; const char kHideControls[] = "hide-controls"; const char kHideOverlays[] = "hide-overlays"; diff --git a/tests/shared/common/client_switches.h b/tests/shared/common/client_switches.h index e3fc13e88..4c8eabf89 100644 --- a/tests/shared/common/client_switches.h +++ b/tests/shared/common/client_switches.h @@ -29,6 +29,7 @@ extern const char kBackgroundColor[]; extern const char kEnableGPU[]; extern const char kFilterURL[]; extern const char kUseViews[]; +extern const char kUseNative[]; extern const char kHideFrame[]; extern const char kHideControls[]; extern const char kHideOverlays[];