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[];