From ff68c01543237f96694a5ddbe4fc7b9e0e1dc919 Mon Sep 17 00:00:00 2001 From: Marshall Greenblatt Date: Thu, 9 Feb 2023 13:15:15 -0500 Subject: [PATCH] chrome: Use default Browser creation for picture-in-picture popups (see issue #3448) Note: In current master (based on M111), document PiP partially works when run with the `--enable-features=DocumentPictureInPictureAPI` command-line flag. However, the document PiP implementation at this Chromium version is missing fixes that have already been cherry-picked to the 5563 release branch. Those fixes will only be available in master after the next Chromium update (to M112). --- include/views/cef_browser_view_delegate.h | 2 +- .../browser/alloy/alloy_browser_host_impl.cc | 2 +- libcef/browser/browser_info_manager.cc | 100 ++++++++++++++---- libcef/browser/browser_info_manager.h | 26 ++++- libcef/browser/chrome/browser_delegate.h | 11 +- .../browser/chrome/chrome_browser_delegate.cc | 42 ++++---- .../browser/chrome/chrome_browser_delegate.h | 9 +- .../views/browser_view_delegate_cpptoc.cc | 8 +- .../views/browser_view_delegate_ctocpp.cc | 8 +- patch/patches/chrome_browser_browser.patch | 55 +++++----- tests/cefclient/browser/client_handler.cc | 6 ++ 11 files changed, 176 insertions(+), 93 deletions(-) diff --git a/include/views/cef_browser_view_delegate.h b/include/views/cef_browser_view_delegate.h index 0d1b36b45..262c14521 100644 --- a/include/views/cef_browser_view_delegate.h +++ b/include/views/cef_browser_view_delegate.h @@ -81,7 +81,7 @@ class CefBrowserViewDelegate : public CefViewDelegate { /// popup will be a DevTools browser. Return the delegate that will be used /// for the new popup BrowserView. /// - /*--cef()--*/ + /*--cef(optional_param=client)--*/ virtual CefRefPtr GetDelegateForPopupBrowserView( CefRefPtr browser_view, const CefBrowserSettings& settings, diff --git a/libcef/browser/alloy/alloy_browser_host_impl.cc b/libcef/browser/alloy/alloy_browser_host_impl.cc index c11055fba..a6720dee8 100644 --- a/libcef/browser/alloy/alloy_browser_host_impl.cc +++ b/libcef/browser/alloy/alloy_browser_host_impl.cc @@ -1227,7 +1227,7 @@ void AlloyBrowserHostImpl::WebContentsCreated( target_url, frame_util::MakeGlobalId(opener_render_process_id, opener_render_frame_id), - settings, client, platform_delegate, extra_info); + settings, client, platform_delegate, extra_info, new_contents); scoped_refptr info = CefBrowserInfoManager::GetInstance()->CreatePopupBrowserInfo( diff --git a/libcef/browser/browser_info_manager.cc b/libcef/browser/browser_info_manager.cc index 2c794f903..c832288c0 100644 --- a/libcef/browser/browser_info_manager.cc +++ b/libcef/browser/browser_info_manager.cc @@ -125,6 +125,7 @@ bool CefBrowserInfoManager::CanCreateWindow( CefRefPtr client = browser->GetClient(); bool allow = true; + bool handled = false; CefWindowInfo window_info; @@ -133,7 +134,7 @@ bool CefBrowserInfoManager::CanCreateWindow( #endif auto pending_popup = std::make_unique(); - pending_popup->step = CefBrowserInfoManager::PendingPopup::CAN_CREATE_WINDOW; + pending_popup->step = PendingPopup::CAN_CREATE_WINDOW; pending_popup->opener_global_id = opener->GetGlobalId(); pending_popup->target_url = target_url; pending_popup->target_frame_name = frame_name; @@ -142,6 +143,11 @@ bool CefBrowserInfoManager::CanCreateWindow( pending_popup->client = client; pending_popup->settings = browser->settings(); + // With the Chrome runtime, we want to use default popup Browser creation + // for document picture-in-picture. + pending_popup->use_default_browser_creation = + disposition == WindowOpenDisposition::NEW_PICTURE_IN_PICTURE; + if (client.get()) { CefRefPtr handler = client->GetLifeSpanHandler(); if (handler.get()) { @@ -172,6 +178,7 @@ bool CefBrowserInfoManager::CanCreateWindow( cef_features, window_info, pending_popup->client, pending_popup->settings, pending_popup->extra_info, no_javascript_access); + handled = true; } } @@ -179,14 +186,21 @@ bool CefBrowserInfoManager::CanCreateWindow( CefBrowserCreateParams create_params; create_params.MaybeSetWindowInfo(window_info); + if (!handled) { + // Use default Browser creation if OnBeforePopup was unhandled. + // TODO(chrome): Expose a mechanism for the client to choose default + // creation. + pending_popup->use_default_browser_creation = true; + } + // In most cases, Views-hosted browsers should create Views-hosted popups - // and native browsers should use default popup handling. The one exception - // is with the Chrome runtime where a Views-hosted browser may have an - // external parent. In that case we want to use default popup handling even - // though the parent is (technically) Views-hosted. + // and native browsers should use default popup handling. With the Chrome + // runtime, we should additionally use default handling (a) when using an + // external parent and (b) when using default Browser creation. create_params.popup_with_views_hosted_opener = browser->HasView() && - !browser->platform_delegate()->HasExternalParent(); + !browser->platform_delegate()->HasExternalParent() && + !pending_popup->use_default_browser_creation; create_params.settings = pending_popup->settings; create_params.client = pending_popup->client; @@ -217,9 +231,8 @@ void CefBrowserInfoManager::GetCustomWebContentsView( CEF_REQUIRE_UIT(); REQUIRE_ALLOY_RUNTIME(); - std::unique_ptr pending_popup = - PopPendingPopup(CefBrowserInfoManager::PendingPopup::CAN_CREATE_WINDOW, - opener_global_id, target_url); + auto pending_popup = PopPendingPopup(PendingPopup::CAN_CREATE_WINDOW, + opener_global_id, target_url); DCHECK(pending_popup.get()); DCHECK(pending_popup->platform_delegate.get()); @@ -228,8 +241,7 @@ void CefBrowserInfoManager::GetCustomWebContentsView( delegate_view); } - pending_popup->step = - CefBrowserInfoManager::PendingPopup::GET_CUSTOM_WEB_CONTENTS_VIEW; + pending_popup->step = PendingPopup::GET_CUSTOM_WEB_CONTENTS_VIEW; PushPendingPopup(std::move(pending_popup)); } @@ -239,16 +251,16 @@ void CefBrowserInfoManager::WebContentsCreated( CefBrowserSettings& settings, CefRefPtr& client, std::unique_ptr& platform_delegate, - CefRefPtr& extra_info) { + CefRefPtr& extra_info, + content::WebContents* new_contents) { CEF_REQUIRE_UIT(); // GET_CUSTOM_WEB_CONTENTS_VIEW is only used with the alloy runtime. - const auto previous_step = - cef::IsAlloyRuntimeEnabled() - ? CefBrowserInfoManager::PendingPopup::GET_CUSTOM_WEB_CONTENTS_VIEW - : CefBrowserInfoManager::PendingPopup::CAN_CREATE_WINDOW; + const auto previous_step = cef::IsAlloyRuntimeEnabled() + ? PendingPopup::GET_CUSTOM_WEB_CONTENTS_VIEW + : PendingPopup::CAN_CREATE_WINDOW; - std::unique_ptr pending_popup = + auto pending_popup = PopPendingPopup(previous_step, opener_global_id, target_url); DCHECK(pending_popup.get()); DCHECK(pending_popup->platform_delegate.get()); @@ -257,6 +269,30 @@ void CefBrowserInfoManager::WebContentsCreated( client = pending_popup->client; platform_delegate = std::move(pending_popup->platform_delegate); extra_info = pending_popup->extra_info; + + // AddWebContents (the next step) is only used with the Chrome runtime. + if (cef::IsChromeRuntimeEnabled()) { + pending_popup->step = PendingPopup::WEB_CONTENTS_CREATED; + pending_popup->new_contents = new_contents; + PushPendingPopup(std::move(pending_popup)); + } +} + +bool CefBrowserInfoManager::AddWebContents(content::WebContents* new_contents) { + CEF_REQUIRE_UIT(); + DCHECK(cef::IsChromeRuntimeEnabled()); + + // Pending popup information may be missing in cases where + // chrome::AddWebContents is called directly from the Chrome UI (profile + // settings, etc). + auto pending_popup = + PopPendingPopup(PendingPopup::WEB_CONTENTS_CREATED, new_contents); + if (pending_popup) { + return !pending_popup->use_default_browser_creation; + } + + // Proceed with default handling. + return false; } void CefBrowserInfoManager::OnGetNewBrowserInfo( @@ -297,7 +333,9 @@ void CefBrowserInfoManager::OnGetNewBrowserInfo( std::make_pair(global_id, std::move(pending))); // Register a timeout for the pending response so that the renderer process - // doesn't hang forever. + // doesn't hang forever. With the Chrome runtime, timeouts may occur in cases + // where chrome::AddWebContents or WebContents::Create are called directly + // from the Chrome UI (profile settings, etc). if (!base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kDisableNewBrowserInfoTimeout)) { CEF_POST_DELAYED_TASK( @@ -438,16 +476,18 @@ void CefBrowserInfoManager::PushPendingPopup( std::unique_ptr CefBrowserInfoManager::PopPendingPopup( - PendingPopup::Step step, + PendingPopup::Step previous_step, const content::GlobalRenderFrameHostId& opener_global_id, const GURL& target_url) { CEF_REQUIRE_UIT(); DCHECK(frame_util::IsValidGlobalId(opener_global_id)); + DCHECK_LE(previous_step, PendingPopup::GET_CUSTOM_WEB_CONTENTS_VIEW); PendingPopupList::iterator it = pending_popup_list_.begin(); for (; it != pending_popup_list_.end(); ++it) { PendingPopup* popup = it->get(); - if (popup->step == step && popup->opener_global_id == opener_global_id && + if (popup->step == previous_step && + popup->opener_global_id == opener_global_id && popup->target_url == target_url) { // Transfer ownership of the pointer. it->release(); @@ -459,6 +499,26 @@ CefBrowserInfoManager::PopPendingPopup( return nullptr; } +std::unique_ptr +CefBrowserInfoManager::PopPendingPopup(PendingPopup::Step previous_step, + content::WebContents* new_contents) { + CEF_REQUIRE_UIT(); + DCHECK_GE(previous_step, PendingPopup::WEB_CONTENTS_CREATED); + + PendingPopupList::iterator it = pending_popup_list_.begin(); + for (; it != pending_popup_list_.end(); ++it) { + PendingPopup* popup = it->get(); + if (popup->step == previous_step && popup->new_contents == new_contents) { + // Transfer ownership of the pointer. + it->release(); + pending_popup_list_.erase(it); + return base::WrapUnique(popup); + } + } + + return nullptr; +} + scoped_refptr CefBrowserInfoManager::GetBrowserInfoInternal( const content::GlobalRenderFrameHostId& global_id, bool* is_guest_view) { diff --git a/libcef/browser/browser_info_manager.h b/libcef/browser/browser_info_manager.h index b8cb281d4..bbe1f6a57 100644 --- a/libcef/browser/browser_info_manager.h +++ b/libcef/browser/browser_info_manager.h @@ -97,7 +97,12 @@ class CefBrowserInfoManager : public content::RenderProcessHostObserver { CefBrowserSettings& settings, CefRefPtr& client, std::unique_ptr& platform_delegate, - CefRefPtr& extra_info); + CefRefPtr& extra_info, + content::WebContents* new_contents); + + // Called from ChromeBrowserDelegate::AddWebContents. See comments on + // PendingPopup for more information. Returns true for custom handling. + bool AddWebContents(content::WebContents* source_contents); // Called from CefBrowserManager::GetNewBrowserInfo for delivering // browser info to the renderer process. If the browser info already exists @@ -154,6 +159,8 @@ class CefBrowserInfoManager : public content::RenderProcessHostObserver { // Creates the OSR views for windowless popups. // - WebContentsCreated (UIT): // Creates the CefBrowserHost representation for the popup. + // - AddWebContents (UIT) (chrome runtime only): + // Creates the Browser or tab representation for the popup. // - CefBrowserManager::GetNewBrowserInfo (IOT) // Passes information about the popup to the renderer process. struct PendingPopup { @@ -163,6 +170,7 @@ class CefBrowserInfoManager : public content::RenderProcessHostObserver { enum Step { CAN_CREATE_WINDOW, GET_CUSTOM_WEB_CONTENTS_VIEW, + WEB_CONTENTS_CREATED, } step; // Initial state from ViewHostMsg_CreateWindow. @@ -179,15 +187,29 @@ class CefBrowserInfoManager : public content::RenderProcessHostObserver { // Platform delegate specific to the new popup. std::unique_ptr platform_delegate; + + // True if default Browser or tab creation should proceed from + // AddWebContents (chrome runtime only). + bool use_default_browser_creation = false; + + // The newly created WebContents (set in WebContentsCreated). + content::WebContents* new_contents = nullptr; }; // Manage pending popups. Only called on the UI thread. void PushPendingPopup(std::unique_ptr popup); + + // Used after CanCreateWindow is called. std::unique_ptr PopPendingPopup( - PendingPopup::Step step, + PendingPopup::Step previous_step, const content::GlobalRenderFrameHostId& opener_global_id, const GURL& target_url); + // Used after WebContentsCreated is called. + std::unique_ptr PopPendingPopup( + PendingPopup::Step previous_step, + content::WebContents* new_contents); + // Retrieves the BrowserInfo matching the specified ID. scoped_refptr GetBrowserInfoInternal( const content::GlobalRenderFrameHostId& global_id, diff --git a/libcef/browser/chrome/browser_delegate.h b/libcef/browser/chrome/browser_delegate.h index 258cbb30e..0a1df4582 100644 --- a/libcef/browser/chrome/browser_delegate.h +++ b/libcef/browser/chrome/browser_delegate.h @@ -36,7 +36,16 @@ class BrowserDelegate : public content::WebContentsDelegate { ~BrowserDelegate() override {} - // Called immediately after |new_contents| is created. + // Optionally override chrome::AddWebContents behavior. This is most often + // called via Browser::AddNewContents for new popup browsers and provides an + // opportunity for CEF to create a new Browser instead of proceeding with + // default Browser or tab creation. + virtual std::unique_ptr AddWebContents( + std::unique_ptr new_contents) = 0; + + // Called immediately after |new_contents| is created via chrome::Navigate. + // This is most often called for navigations targeting a new tab without a + // pre-existing WebContents. virtual void OnWebContentsCreated(content::WebContents* new_contents) = 0; // Add or remove ownership of the WebContents. diff --git a/libcef/browser/chrome/chrome_browser_delegate.cc b/libcef/browser/chrome/chrome_browser_delegate.cc index 761c2a734..a1f6a97e7 100644 --- a/libcef/browser/chrome/chrome_browser_delegate.cc +++ b/libcef/browser/chrome/chrome_browser_delegate.cc @@ -34,6 +34,25 @@ ChromeBrowserDelegate::ChromeBrowserDelegate( ChromeBrowserDelegate::~ChromeBrowserDelegate() = default; +std::unique_ptr ChromeBrowserDelegate::AddWebContents( + std::unique_ptr new_contents) { + if (CefBrowserInfoManager::GetInstance()->AddWebContents( + new_contents.get())) { + // The browser host should have been created in WebContentsCreated(). + auto new_browser = + ChromeBrowserHostImpl::GetBrowserForContents(new_contents.get()); + if (new_browser) { + // Create a new Browser and give it ownership of the new WebContents. + new_browser->AddNewContents(std::move(new_contents)); + } else { + LOG(ERROR) << "No host found for chrome popup browser"; + } + } + + // Proceed with default chrome::AddWebContents behavior. + return new_contents; +} + void ChromeBrowserDelegate::OnWebContentsCreated( content::WebContents* new_contents) { // Necessary to receive LoadingStateChanged calls during initial navigation. @@ -132,7 +151,7 @@ void ChromeBrowserDelegate::WebContentsCreated( target_url, frame_util::MakeGlobalId(opener_render_process_id, opener_render_frame_id), - settings, client, platform_delegate, extra_info); + settings, client, platform_delegate, extra_info, new_contents); auto opener = ChromeBrowserHostImpl::GetBrowserForContents(source_contents); if (!opener) { @@ -155,27 +174,6 @@ void ChromeBrowserDelegate::WebContentsCreated( browser_info, opener, request_context_impl); } -void ChromeBrowserDelegate::AddNewContents( - content::WebContents* source_contents, - std::unique_ptr new_contents, - const GURL& target_url, - WindowOpenDisposition disposition, - const blink::mojom::WindowFeatures& window_features, - bool user_gesture, - bool* was_blocked) { - auto new_browser = - ChromeBrowserHostImpl::GetBrowserForContents(new_contents.get()); - if (new_browser) { - // Create a new Browser and give it ownership of the WebContents. - new_browser->AddNewContents(std::move(new_contents)); - return; - } - - // Fall back to default behavior from Browser::AddNewContents. - chrome::AddWebContents(browser_, source_contents, std::move(new_contents), - target_url, disposition, window_features); -} - content::WebContents* ChromeBrowserDelegate::OpenURLFromTab( content::WebContents* source, const content::OpenURLParams& params) { diff --git a/libcef/browser/chrome/chrome_browser_delegate.h b/libcef/browser/chrome/chrome_browser_delegate.h index 06a99186e..3f7a8a1be 100644 --- a/libcef/browser/chrome/chrome_browser_delegate.h +++ b/libcef/browser/chrome/chrome_browser_delegate.h @@ -48,6 +48,8 @@ class ChromeBrowserDelegate : public cef::BrowserDelegate { ~ChromeBrowserDelegate() override; // cef::BrowserDelegate methods: + std::unique_ptr AddWebContents( + std::unique_ptr new_contents) override; void OnWebContentsCreated(content::WebContents* new_contents) override; void SetAsDelegate(content::WebContents* web_contents, bool set_delegate) override; @@ -66,13 +68,6 @@ class ChromeBrowserDelegate : public cef::BrowserDelegate { const std::string& frame_name, const GURL& target_url, content::WebContents* new_contents) override; - void AddNewContents(content::WebContents* source_contents, - std::unique_ptr new_contents, - const GURL& target_url, - WindowOpenDisposition disposition, - const blink::mojom::WindowFeatures& window_features, - bool user_gesture, - bool* was_blocked) override; content::WebContents* OpenURLFromTab( content::WebContents* source, const content::OpenURLParams& params) override; diff --git a/libcef_dll/cpptoc/views/browser_view_delegate_cpptoc.cc b/libcef_dll/cpptoc/views/browser_view_delegate_cpptoc.cc index 744b03bc3..8e7d9cb1b 100644 --- a/libcef_dll/cpptoc/views/browser_view_delegate_cpptoc.cc +++ b/libcef_dll/cpptoc/views/browser_view_delegate_cpptoc.cc @@ -9,7 +9,7 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=499cb70269cbe05c9bba4b0672a26116f7436f76$ +// $hash=8b92c198857b0ca5c3ddc9b2c8a82febe7ed8cde$ // #include "libcef_dll/cpptoc/views/browser_view_delegate_cpptoc.h" @@ -111,11 +111,7 @@ browser_view_delegate_get_delegate_for_popup_browser_view( NOTREACHED() << "invalid settings->[base.]size"; return NULL; } - // Verify param: client; type: refptr_same - DCHECK(client); - if (!client) { - return NULL; - } + // Unverified params: client // Translate param: settings; type: struct_byref_const CefBrowserSettings settingsObj; diff --git a/libcef_dll/ctocpp/views/browser_view_delegate_ctocpp.cc b/libcef_dll/ctocpp/views/browser_view_delegate_ctocpp.cc index f9399dd0d..a98dc7e9c 100644 --- a/libcef_dll/ctocpp/views/browser_view_delegate_ctocpp.cc +++ b/libcef_dll/ctocpp/views/browser_view_delegate_ctocpp.cc @@ -9,7 +9,7 @@ // implementations. See the translator.README.txt file in the tools directory // for more information. // -// $hash=4f26a1968e558512fa9894106f0bc9f6b9d8a10f$ +// $hash=7301ce9c063a7ff4ab88b6382f6441ba314b20c0$ // #include "libcef_dll/ctocpp/views/browser_view_delegate_ctocpp.h" @@ -101,11 +101,7 @@ CefBrowserViewDelegateCToCpp::GetDelegateForPopupBrowserView( if (!browser_view.get()) { return nullptr; } - // Verify param: client; type: refptr_same - DCHECK(client.get()); - if (!client.get()) { - return nullptr; - } + // Unverified params: client // Execute cef_browser_view_delegate_t* _retval = diff --git a/patch/patches/chrome_browser_browser.patch b/patch/patches/chrome_browser_browser.patch index e5b97d953..15568b7d7 100644 --- a/patch/patches/chrome_browser_browser.patch +++ b/patch/patches/chrome_browser_browser.patch @@ -70,7 +70,7 @@ index 03a6d3a2ee5e8..a19224279243c 100644 ] } diff --git chrome/browser/ui/browser.cc chrome/browser/ui/browser.cc -index 08ac5f0afd874..480986df48aa6 100644 +index 08ac5f0afd874..9248d822a3745 100644 --- chrome/browser/ui/browser.cc +++ chrome/browser/ui/browser.cc @@ -264,6 +264,25 @@ @@ -177,23 +177,7 @@ index 08ac5f0afd874..480986df48aa6 100644 NavigateParams nav_params(this, params.url, params.transition); nav_params.FillNavigateParamsFromOpenURLParams(params); nav_params.source_contents = source; -@@ -1712,6 +1770,15 @@ void Browser::AddNewContents( - return; - } - -+#if BUILDFLAG(ENABLE_CEF) -+ if (cef_browser_delegate_) { -+ cef_browser_delegate_->AddNewContents( -+ source, std::move(new_contents), target_url, disposition, -+ window_features, user_gesture, was_blocked); -+ return; -+ } -+#endif -+ - chrome::AddWebContents(this, source, std::move(new_contents), target_url, - disposition, window_features, window_action); - } -@@ -1730,6 +1797,8 @@ void Browser::LoadingStateChanged(WebContents* source, +@@ -1730,6 +1788,8 @@ void Browser::LoadingStateChanged(WebContents* source, bool should_show_loading_ui) { ScheduleUIUpdate(source, content::INVALIDATE_TYPE_LOAD); UpdateWindowForLoadingStateChanged(source, should_show_loading_ui); @@ -202,7 +186,7 @@ index 08ac5f0afd874..480986df48aa6 100644 } void Browser::CloseContents(WebContents* source) { -@@ -1757,6 +1826,8 @@ void Browser::SetContentsBounds(WebContents* source, const gfx::Rect& bounds) { +@@ -1757,6 +1817,8 @@ void Browser::SetContentsBounds(WebContents* source, const gfx::Rect& bounds) { } void Browser::UpdateTargetURL(WebContents* source, const GURL& url) { @@ -211,7 +195,7 @@ index 08ac5f0afd874..480986df48aa6 100644 if (!GetStatusBubble()) return; -@@ -1764,6 +1835,17 @@ void Browser::UpdateTargetURL(WebContents* source, const GURL& url) { +@@ -1764,6 +1826,17 @@ void Browser::UpdateTargetURL(WebContents* source, const GURL& url) { GetStatusBubble()->SetURL(url); } @@ -229,7 +213,7 @@ index 08ac5f0afd874..480986df48aa6 100644 void Browser::ContentsMouseEvent(WebContents* source, bool motion, bool exited) { -@@ -1788,6 +1870,19 @@ bool Browser::TakeFocus(content::WebContents* source, bool reverse) { +@@ -1788,6 +1861,19 @@ bool Browser::TakeFocus(content::WebContents* source, bool reverse) { return false; } @@ -249,7 +233,7 @@ index 08ac5f0afd874..480986df48aa6 100644 void Browser::BeforeUnloadFired(WebContents* web_contents, bool proceed, bool* proceed_to_fire_unload) { -@@ -1880,6 +1975,10 @@ void Browser::WebContentsCreated(WebContents* source_contents, +@@ -1880,6 +1966,10 @@ void Browser::WebContentsCreated(WebContents* source_contents, // Make the tab show up in the task manager. task_manager::WebContentsTags::CreateForTabContents(new_contents); @@ -260,7 +244,7 @@ index 08ac5f0afd874..480986df48aa6 100644 } void Browser::PortalWebContentsCreated(WebContents* portal_web_contents) { -@@ -1991,11 +2090,15 @@ void Browser::EnterFullscreenModeForTab( +@@ -1991,11 +2081,15 @@ void Browser::EnterFullscreenModeForTab( const blink::mojom::FullscreenOptions& options) { exclusive_access_manager_->fullscreen_controller()->EnterFullscreenModeForTab( requesting_frame, options.display_id); @@ -276,7 +260,7 @@ index 08ac5f0afd874..480986df48aa6 100644 } bool Browser::IsFullscreenForTabOrPending(const WebContents* web_contents) { -@@ -2189,6 +2292,15 @@ void Browser::RequestMediaAccessPermission( +@@ -2189,6 +2283,15 @@ void Browser::RequestMediaAccessPermission( content::WebContents* web_contents, const content::MediaStreamRequest& request, content::MediaResponseCallback callback) { @@ -292,7 +276,7 @@ index 08ac5f0afd874..480986df48aa6 100644 const extensions::Extension* extension = GetExtensionForOrigin(profile_, request.security_origin); MediaCaptureDevicesDispatcher::GetInstance()->ProcessMediaAccessRequest( -@@ -2725,13 +2837,20 @@ void Browser::RemoveScheduledUpdatesFor(WebContents* contents) { +@@ -2725,13 +2828,20 @@ void Browser::RemoveScheduledUpdatesFor(WebContents* contents) { // Browser, Getters for UI (private): StatusBubble* Browser::GetStatusBubble() { @@ -314,7 +298,7 @@ index 08ac5f0afd874..480986df48aa6 100644 return window_ ? window_->GetStatusBubble() : nullptr; } -@@ -2863,6 +2982,8 @@ void Browser::SetAsDelegate(WebContents* web_contents, bool set_delegate) { +@@ -2863,6 +2973,8 @@ void Browser::SetAsDelegate(WebContents* web_contents, bool set_delegate) { BookmarkTabHelper::FromWebContents(web_contents)->RemoveObserver(this); web_contents_collection_.StopObserving(web_contents); } @@ -444,7 +428,7 @@ index f6df2d49dc719..01e5e7a42fa96 100644 // tab helpers, so the entire set of tab helpers needs to be set up // immediately. diff --git chrome/browser/ui/browser_tabstrip.cc chrome/browser/ui/browser_tabstrip.cc -index a3dbf97b6f943..6d8e521e9f189 100644 +index a3dbf97b6f943..799a64e17fca5 100644 --- chrome/browser/ui/browser_tabstrip.cc +++ chrome/browser/ui/browser_tabstrip.cc @@ -33,9 +33,13 @@ void AddTabAt(Browser* browser, @@ -462,3 +446,20 @@ index a3dbf97b6f943..6d8e521e9f189 100644 params.disposition = foreground ? WindowOpenDisposition::NEW_FOREGROUND_TAB : WindowOpenDisposition::NEW_BACKGROUND_TAB; params.tabstrip_index = idx; +@@ -71,6 +75,16 @@ void AddWebContents(Browser* browser, + // Can't create a new contents for the current tab - invalid case. + DCHECK(disposition != WindowOpenDisposition::CURRENT_TAB); + ++#if BUILDFLAG(ENABLE_CEF) ++ if (browser && browser->cef_delegate() && new_contents) { ++ new_contents = browser->cef_delegate()->AddWebContents( ++ std::move(new_contents)); ++ if (!new_contents) { ++ return; ++ } ++ } ++#endif ++ + NavigateParams params(browser, std::move(new_contents)); + params.source_contents = source_contents; + params.url = target_url; diff --git a/tests/cefclient/browser/client_handler.cc b/tests/cefclient/browser/client_handler.cc index 8a0ede2a0..bfebba640 100644 --- a/tests/cefclient/browser/client_handler.cc +++ b/tests/cefclient/browser/client_handler.cc @@ -767,6 +767,12 @@ bool ClientHandler::OnBeforePopup( bool* no_javascript_access) { CEF_REQUIRE_UI_THREAD(); + if (target_disposition == WOD_NEW_PICTURE_IN_PICTURE) { + // Use default handling for document picture-in-picture popups. + client = nullptr; + return false; + } + // Return true to cancel the popup window. return !CreatePopupWindow(browser, false, popupFeatures, windowInfo, client, settings);