From 97011bca14869c509e009397566439359eb727e4 Mon Sep 17 00:00:00 2001 From: Marshall Greenblatt Date: Thu, 23 Jul 2020 15:46:57 -0400 Subject: [PATCH] Fix DCHECK when showing print preview dialog (see issue #2952) --- libcef/browser/browser_info_manager.cc | 19 ++++++++++------- libcef/browser/browser_info_manager.h | 2 +- libcef/browser/content_browser_client.cc | 26 ++++++++++++++++++++++++ libcef/browser/content_browser_client.h | 3 +++ 4 files changed, 42 insertions(+), 8 deletions(-) diff --git a/libcef/browser/browser_info_manager.cc b/libcef/browser/browser_info_manager.cc index 90e4c96f3..68c08241f 100644 --- a/libcef/browser/browser_info_manager.cc +++ b/libcef/browser/browser_info_manager.cc @@ -22,6 +22,7 @@ #include "content/public/browser/render_process_host.h" #include "content/public/browser/web_contents.h" #include "content/public/common/child_process_host.h" +#include "content/public/common/url_constants.h" #include "extensions/common/constants.h" namespace { @@ -122,7 +123,7 @@ bool CefBrowserInfoManager::CanCreateWindow( params.user_gesture = user_gesture; CefRefPtr browser; - if (!MaybeAllowNavigation(opener, params, browser)) { + if (!MaybeAllowNavigation(opener, params, browser) || !browser) { // Cancel the popup. return false; } @@ -366,13 +367,17 @@ bool CefBrowserInfoManager::MaybeAllowNavigation( bool is_guest_view = false; CefRefPtr browser = extensions::GetOwnerBrowserForHost(opener, &is_guest_view); - DCHECK(browser); - if (!browser) - return false; + if (!browser) { + // Print preview uses a modal dialog where we don't own the WebContents. + // Allow that navigation to proceed. + return true; + } - if (is_guest_view && !params.url.SchemeIs(extensions::kExtensionScheme)) { - // The PDF viewer will load an extension in the guest view. All other - // navigations are passed to the owner browser. + if (is_guest_view && !params.url.SchemeIs(extensions::kExtensionScheme) && + !params.url.SchemeIs(content::kChromeUIScheme)) { + // The PDF viewer will load the PDF extension in the guest view, and print + // preview will load chrome://print in the guest view. All other navigations + // are passed to the owner browser. CEF_POST_TASK( CEF_UIT, base::Bind(base::IgnoreResult(&CefBrowserHostImpl::OpenURLFromTab), diff --git a/libcef/browser/browser_info_manager.h b/libcef/browser/browser_info_manager.h index a9afbfb6d..c26405716 100644 --- a/libcef/browser/browser_info_manager.h +++ b/libcef/browser/browser_info_manager.h @@ -141,7 +141,7 @@ class CefBrowserInfoManager : public content::RenderProcessHostObserver { // Returns true if the navigation should be allowed to proceed, or false if // the navigation will instead be sent via OpenURLFromTab. If allowed, - // |browser| will be set to the target browser. + // |browser| will be set to the target browser if any. bool MaybeAllowNavigation(content::RenderFrameHost* opener, const content::OpenURLParams& params, CefRefPtr& browser) const; diff --git a/libcef/browser/content_browser_client.cc b/libcef/browser/content_browser_client.cc index 4b96c7b9d..172bd6503 100644 --- a/libcef/browser/content_browser_client.cc +++ b/libcef/browser/content_browser_client.cc @@ -59,6 +59,7 @@ #include "chrome/browser/profiles/renderer_updater_factory.h" #include "chrome/browser/renderer_host/pepper/chrome_browser_pepper_host_factory.h" #include "chrome/browser/spellchecker/spell_check_host_chrome_impl.h" +#include "chrome/common/chrome_content_client.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/google_url_loader_throttle.h" @@ -1501,6 +1502,31 @@ CefContentBrowserClient::GetPluginMimeTypesWithExternalHandlers( return mime_types; } +bool CefContentBrowserClient::ShouldAllowPluginCreation( + const url::Origin& embedder_origin, + const content::PepperPluginInfo& plugin_info) { + if (plugin_info.name == ChromeContentClient::kPDFInternalPluginName) { + // Allow embedding the internal PDF plugin in the built-in PDF extension. + if (embedder_origin.scheme() == extensions::kExtensionScheme && + embedder_origin.host() == extension_misc::kPdfExtensionId) { + return true; + } + + // Allow embedding the internal PDF plugin in chrome://print. + if (embedder_origin == + url::Origin::Create(GURL(chrome::kChromeUIPrintURL))) { + return true; + } + + // Only allow the PDF plugin in the known, trustworthy origins that are + // allowlisted above. See also https://crbug.com/520422 and + // https://crbug.com/1027173. + return false; + } + + return true; +} + CefRefPtr CefContentBrowserClient::request_context() const { return browser_main_parts_->request_context(); diff --git a/libcef/browser/content_browser_client.h b/libcef/browser/content_browser_client.h index 72c0fe104..036f052d6 100644 --- a/libcef/browser/content_browser_client.h +++ b/libcef/browser/content_browser_client.h @@ -211,6 +211,9 @@ class CefContentBrowserClient : public content::ContentBrowserClient { blink::UserAgentMetadata GetUserAgentMetadata() override; base::flat_set GetPluginMimeTypesWithExternalHandlers( content::BrowserContext* browser_context) override; + bool ShouldAllowPluginCreation( + const url::Origin& embedder_origin, + const content::PepperPluginInfo& plugin_info) override; CefRefPtr request_context() const; CefDevToolsDelegate* devtools_delegate() const;