From c75ebbccec456ab51a798dedfab3e2303f2fc2e7 Mon Sep 17 00:00:00 2001 From: Marshall Greenblatt Date: Tue, 23 Nov 2021 15:28:12 -0500 Subject: [PATCH] alloy: Add support for the new non-PPAPI PDF viewer (see issue #3047) Enable by passing `--enable-features=PdfUnseasoned` on the command line. --- BUILD.gn | 2 - .../browser/alloy/alloy_browser_host_impl.cc | 9 +- .../alloy/alloy_content_browser_client.cc | 226 ++++++++++++------ .../alloy/alloy_content_browser_client.h | 19 +- libcef/browser/extensions/extension_system.cc | 34 ++- .../browser/extensions/pdf_extension_util.cc | 46 ---- .../browser/extensions/pdf_extension_util.h | 27 --- libcef/browser/net/throttle_handler.cc | 7 +- libcef/common/alloy/alloy_content_client.cc | 13 +- libcef/common/alloy/alloy_content_client.h | 2 - .../alloy/alloy_content_renderer_client.cc | 32 ++- 11 files changed, 244 insertions(+), 173 deletions(-) delete mode 100644 libcef/browser/extensions/pdf_extension_util.cc delete mode 100644 libcef/browser/extensions/pdf_extension_util.h diff --git a/BUILD.gn b/BUILD.gn index 0bcda114a..44c0577c1 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -524,8 +524,6 @@ static_library("libcef_static") { "libcef/browser/extensions/extension_web_contents_observer.h", "libcef/browser/extensions/mime_handler_view_guest_delegate.cc", "libcef/browser/extensions/mime_handler_view_guest_delegate.h", - "libcef/browser/extensions/pdf_extension_util.cc", - "libcef/browser/extensions/pdf_extension_util.h", "libcef/browser/extensions/pdf_web_contents_helper_client.cc", "libcef/browser/extensions/pdf_web_contents_helper_client.h", "libcef/browser/extensions/value_store/cef_value_store.cc", diff --git a/libcef/browser/alloy/alloy_browser_host_impl.cc b/libcef/browser/alloy/alloy_browser_host_impl.cc index fdde30b09..2847e7c74 100644 --- a/libcef/browser/alloy/alloy_browser_host_impl.cc +++ b/libcef/browser/alloy/alloy_browser_host_impl.cc @@ -780,11 +780,14 @@ bool AlloyBrowserHostImpl::MaybeAllowNavigation( content::RenderFrameHost* opener, bool is_guest_view, const content::OpenURLParams& params) { - if (is_guest_view && !params.url.SchemeIs(extensions::kExtensionScheme) && + if (is_guest_view && !params.is_pdf && + !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. + // preview will load chrome://print in the guest view. The PDF renderer + // used with PdfUnseasoned will set |params.is_pdf| when loading the PDF + // stream (see PdfNavigationThrottle::WillStartRequest). All other + // navigations are passed to the owner browser. CEF_POST_TASK(CEF_UIT, base::BindOnce( base::IgnoreResult(&AlloyBrowserHostImpl::OpenURLFromTab), diff --git a/libcef/browser/alloy/alloy_content_browser_client.cc b/libcef/browser/alloy/alloy_content_browser_client.cc index caedfd73e..fad83b986 100644 --- a/libcef/browser/alloy/alloy_content_browser_client.cc +++ b/libcef/browser/alloy/alloy_content_browser_client.cc @@ -53,9 +53,12 @@ #include "cef/grit/cef_resources.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/content_settings/cookie_settings_factory.h" +#include "chrome/browser/extensions/chrome_content_browser_client_extensions_part.h" #include "chrome/browser/net/profile_network_context_service.h" #include "chrome/browser/net/profile_network_context_service_factory.h" #include "chrome/browser/net/system_network_context_manager.h" +#include "chrome/browser/pdf/chrome_pdf_stream_delegate.h" +#include "chrome/browser/plugins/pdf_iframe_navigation_throttle.h" #include "chrome/browser/plugins/plugin_info_host_impl.h" #include "chrome/browser/plugins/plugin_response_interceptor_url_loader_throttle.h" #include "chrome/browser/plugins/plugin_utils.h" @@ -68,6 +71,7 @@ #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/google_url_loader_throttle.h" +#include "chrome/common/pdf_util.h" #include "chrome/common/pref_names.h" #include "chrome/common/webui_url_constants.h" #include "chrome/grit/browser_resources.h" @@ -76,7 +80,10 @@ #include "components/content_settings/core/browser/cookie_settings.h" #include "components/embedder_support/switches.h" #include "components/embedder_support/user_agent_utils.h" +#include "components/pdf/browser/pdf_navigation_throttle.h" +#include "components/pdf/browser/pdf_url_loader_request_interceptor.h" #include "components/pdf/browser/pdf_web_contents_helper.h" +#include "components/pdf/common/internal_plugin_helpers.h" #include "components/spellcheck/common/spellcheck.mojom.h" #include "components/version_info/version_info.h" #include "content/browser/plugin_service_impl.h" @@ -118,6 +125,7 @@ #include "net/base/auth.h" #include "net/ssl/ssl_cert_request_info.h" #include "net/ssl/ssl_private_key.h" +#include "pdf/pdf_features.h" #include "ppapi/host/ppapi_host.h" #include "sandbox/policy/switches.h" #include "services/network/public/cpp/network_switches.h" @@ -466,6 +474,19 @@ base::FilePath GetRootCachePath() { CefString(&CefContext::Get()->settings().root_cache_path)); } +const extensions::Extension* GetEnabledExtensionFromSiteURL( + content::BrowserContext* context, + const GURL& site_url) { + if (!site_url.SchemeIs(extensions::kExtensionScheme)) + return nullptr; + + auto registry = extensions::ExtensionRegistry::Get(context); + if (!registry) + return nullptr; + + return registry->enabled_extensions().GetByID(site_url.host()); +} + } // namespace AlloyContentBrowserClient::AlloyContentBrowserClient() = default; @@ -504,45 +525,79 @@ void AlloyContentBrowserClient::RenderProcessWillLaunch( bool AlloyContentBrowserClient::ShouldUseProcessPerSite( content::BrowserContext* browser_context, - const GURL& effective_url) { - if (!extensions::ExtensionsEnabled()) - return false; + const GURL& site_url) { + if (extensions::ExtensionsEnabled()) { + if (auto profile = Profile::FromBrowserContext(browser_context)) { + return extensions::ChromeContentBrowserClientExtensionsPart:: + ShouldUseProcessPerSite(profile, site_url); + } + } - if (!effective_url.SchemeIs(extensions::kExtensionScheme)) - return false; - - extensions::ExtensionRegistry* registry = - extensions::ExtensionRegistry::Get(browser_context); - if (!registry) - return false; - - const extensions::Extension* extension = - registry->enabled_extensions().GetByID(effective_url.host()); - if (!extension) - return false; - - // TODO(extensions): Extra checks required if type is TYPE_HOSTED_APP. - - // Hosted apps that have script access to their background page must use - // process per site, since all instances can make synchronous calls to the - // background window. Other extensions should use process per site as well. - return true; + return content::ContentBrowserClient::ShouldUseProcessPerSite(browser_context, + site_url); +} + +bool AlloyContentBrowserClient::ShouldUseSpareRenderProcessHost( + content::BrowserContext* browser_context, + const GURL& site_url) { + if (extensions::ExtensionsEnabled()) { + if (auto profile = Profile::FromBrowserContext(browser_context)) { + return extensions::ChromeContentBrowserClientExtensionsPart:: + ShouldUseSpareRenderProcessHost(profile, site_url); + } + } + + return content::ContentBrowserClient::ShouldUseSpareRenderProcessHost( + browser_context, site_url); } -// Based on -// ChromeContentBrowserClientExtensionsPart::DoesSiteRequireDedicatedProcess. bool AlloyContentBrowserClient::DoesSiteRequireDedicatedProcess( content::BrowserContext* browser_context, const GURL& effective_site_url) { - if (!extensions::ExtensionsEnabled()) - return false; + if (extensions::ExtensionsEnabled()) { + return extensions::ChromeContentBrowserClientExtensionsPart:: + DoesSiteRequireDedicatedProcess(browser_context, effective_site_url); + } - const extensions::Extension* extension = - extensions::ExtensionRegistry::Get(browser_context) - ->enabled_extensions() - .GetExtensionOrAppByURL(effective_site_url); - // Isolate all extensions. - return extension != nullptr; + return content::ContentBrowserClient::DoesSiteRequireDedicatedProcess( + browser_context, effective_site_url); +} + +bool AlloyContentBrowserClient::ShouldLockProcessToSite( + content::BrowserContext* browser_context, + const GURL& effective_site_url) { + if (extensions::ExtensionsEnabled()) { + return extensions::ChromeContentBrowserClientExtensionsPart:: + ShouldLockProcessToSite(browser_context, effective_site_url); + } + + return content::ContentBrowserClient::ShouldLockProcessToSite( + browser_context, effective_site_url); +} + +bool AlloyContentBrowserClient::ShouldTreatURLSchemeAsFirstPartyWhenTopLevel( + base::StringPiece scheme, + bool is_embedded_origin_secure) { + // This is needed to bypass the normal SameSite rules for any chrome:// page + // embedding a secure origin, regardless of the registrable domains of any + // intervening frames. For example, this is needed for browser UI to interact + // with SameSite cookies on accounts.google.com, which are used for logging + // into Cloud Print from chrome://print, for displaying a list of available + // accounts on the NTP (chrome://new-tab-page), etc. + if (is_embedded_origin_secure && scheme == content::kChromeUIScheme) + return true; + + if (extensions::ExtensionsEnabled()) + return scheme == extensions::kExtensionScheme; + + return false; +} + +bool AlloyContentBrowserClient:: + ShouldIgnoreSameSiteCookieRestrictionsWhenTopLevel( + base::StringPiece scheme, + bool is_embedded_origin_secure) { + return is_embedded_origin_secure && scheme == content::kChromeUIScheme; } void AlloyContentBrowserClient::OverrideURLLoaderFactoryParams( @@ -600,17 +655,24 @@ void AlloyContentBrowserClient::SiteInstanceGotProcess( if (!extensions::ExtensionsEnabled()) return; - // If this isn't an extension renderer there's nothing to do. - const extensions::Extension* extension = GetExtension(site_instance); + CHECK(site_instance->HasProcess()); + + auto context = site_instance->GetBrowserContext(); + + // Only add the process to the map if the SiteInstance's site URL is already + // a chrome-extension:// URL. This includes hosted apps, except in rare cases + // that a URL in the hosted app's extent is not treated as a hosted app (e.g., + // for isolated origins or cross-site iframes). For that case, don't look up + // the hosted app's Extension from the site URL using GetExtensionOrAppByURL, + // since it isn't treated as a hosted app. + const auto extension = + GetEnabledExtensionFromSiteURL(context, site_instance->GetSiteURL()); if (!extension) return; - auto browser_context = - static_cast(site_instance->GetBrowserContext()); - - extensions::ProcessMap::Get(browser_context) - ->Insert(extension->id(), site_instance->GetProcess()->GetID(), - site_instance->GetId()); + extensions::ProcessMap::Get(context)->Insert( + extension->id(), site_instance->GetProcess()->GetID(), + site_instance->GetId()); } void AlloyContentBrowserClient::SiteInstanceDeleting( @@ -618,25 +680,22 @@ void AlloyContentBrowserClient::SiteInstanceDeleting( if (!extensions::ExtensionsEnabled()) return; - // May be NULL during shutdown. - if (!extensions::ExtensionsBrowserClient::Get()) - return; - - // May be NULL during shutdown. if (!site_instance->HasProcess()) return; - // If this isn't an extension renderer there's nothing to do. - const extensions::Extension* extension = GetExtension(site_instance); + auto context = site_instance->GetBrowserContext(); + auto registry = extensions::ExtensionRegistry::Get(context); + if (!registry) + return; + + auto extension = registry->enabled_extensions().GetExtensionOrAppByURL( + site_instance->GetSiteURL()); if (!extension) return; - auto browser_context = - static_cast(site_instance->GetBrowserContext()); - - extensions::ProcessMap::Get(browser_context) - ->Remove(extension->id(), site_instance->GetProcess()->GetID(), - site_instance->GetId()); + extensions::ProcessMap::Get(context)->Remove( + extension->id(), site_instance->GetProcess()->GetID(), + site_instance->GetId()); } void AlloyContentBrowserClient::BindHostReceiverForRenderer( @@ -1008,7 +1067,21 @@ std::vector> AlloyContentBrowserClient::CreateThrottlesForNavigation( content::NavigationHandle* navigation_handle) { throttle::NavigationThrottleList throttles; + + if (extensions::ExtensionsEnabled()) { + auto pdf_iframe_throttle = + PDFIFrameNavigationThrottle::MaybeCreateThrottleFor(navigation_handle); + if (pdf_iframe_throttle) + throttles.push_back(std::move(pdf_iframe_throttle)); + + auto pdf_throttle = pdf::PdfNavigationThrottle::MaybeCreateThrottleFor( + navigation_handle, std::make_unique()); + if (pdf_throttle) + throttles.push_back(std::move(pdf_throttle)); + } + throttle::CreateThrottlesForNavigation(navigation_handle, throttles); + return throttles; } @@ -1037,6 +1110,26 @@ AlloyContentBrowserClient::CreateURLLoaderThrottles( return result; } +std::vector> +AlloyContentBrowserClient::WillCreateURLLoaderRequestInterceptors( + content::NavigationUIData* navigation_ui_data, + int frame_tree_node_id, + const scoped_refptr& + network_loader_factory) { + std::vector> + interceptors; + + if (extensions::ExtensionsEnabled()) { + auto pdf_interceptor = + pdf::PdfURLLoaderRequestInterceptor::MaybeCreateInterceptor( + frame_tree_node_id, std::make_unique()); + if (pdf_interceptor) + interceptors.push_back(std::move(pdf_interceptor)); + } + + return interceptors; +} + #if defined(OS_LINUX) void AlloyContentBrowserClient::GetAdditionalMappedFilesForChildProcess( const base::CommandLine& command_line, @@ -1383,6 +1476,8 @@ AlloyContentBrowserClient::GetPluginMimeTypesWithExternalHandlers( auto map = PluginUtils::GetMimeTypeToExtensionIdMap(browser_context); for (const auto& pair : map) mime_types.insert(pair.first); + if (pdf::IsInternalPluginExternallyHandled()) + mime_types.insert(pdf::kInternalPluginMimeType); return mime_types; } @@ -1401,27 +1496,20 @@ bool AlloyContentBrowserClient::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 IsPdfInternalPluginAllowedOrigin(embedder_origin); } return true; } +bool AlloyContentBrowserClient::IsFindInPageDisabledForOrigin( + const url::Origin& origin) { + // For PDF viewing with the PPAPI-free PDF Viewer, find-in-page should only + // display results from the PDF content, and not from the UI. + return base::FeatureList::IsEnabled(chrome_pdf::features::kPdfUnseasoned) && + IsPdfExtensionOrigin(origin); +} + CefRefPtr AlloyContentBrowserClient::request_context() const { return browser_main_parts_->request_context(); diff --git a/libcef/browser/alloy/alloy_content_browser_client.h b/libcef/browser/alloy/alloy_content_browser_client.h index c81813405..319ce3597 100644 --- a/libcef/browser/alloy/alloy_content_browser_client.h +++ b/libcef/browser/alloy/alloy_content_browser_client.h @@ -39,9 +39,19 @@ class AlloyContentBrowserClient : public content::ContentBrowserClient { const content::MainFunctionParams& parameters) override; void RenderProcessWillLaunch(content::RenderProcessHost* host) override; bool ShouldUseProcessPerSite(content::BrowserContext* browser_context, - const GURL& effective_url) override; + const GURL& site_url) override; + bool ShouldUseSpareRenderProcessHost(content::BrowserContext* browser_context, + const GURL& site_url) override; bool DoesSiteRequireDedicatedProcess(content::BrowserContext* browser_context, const GURL& effective_site_url) override; + bool ShouldLockProcessToSite(content::BrowserContext* browser_context, + const GURL& effective_site_url) override; + bool ShouldTreatURLSchemeAsFirstPartyWhenTopLevel( + base::StringPiece scheme, + bool is_embedded_origin_secure) override; + bool ShouldIgnoreSameSiteCookieRestrictionsWhenTopLevel( + base::StringPiece scheme, + bool is_embedded_origin_secure) override; void OverrideURLLoaderFactoryParams( content::BrowserContext* browser_context, const url::Origin& origin, @@ -124,6 +134,12 @@ class AlloyContentBrowserClient : public content::ContentBrowserClient { const base::RepeatingCallback& wc_getter, content::NavigationUIData* navigation_ui_data, int frame_tree_node_id) override; + std::vector> + WillCreateURLLoaderRequestInterceptors( + content::NavigationUIData* navigation_ui_data, + int frame_tree_node_id, + const scoped_refptr& + network_loader_factory) override; #if defined(OS_LINUX) void GetAdditionalMappedFilesForChildProcess( @@ -221,6 +237,7 @@ class AlloyContentBrowserClient : public content::ContentBrowserClient { bool ShouldAllowPluginCreation( const url::Origin& embedder_origin, const content::PepperPluginInfo& plugin_info) override; + bool IsFindInPageDisabledForOrigin(const url::Origin& origin) override; CefRefPtr request_context() const; CefDevToolsDelegate* devtools_delegate() const; diff --git a/libcef/browser/extensions/extension_system.cc b/libcef/browser/extensions/extension_system.cc index 9fce20e15..eded393ef 100644 --- a/libcef/browser/extensions/extension_system.cc +++ b/libcef/browser/extensions/extension_system.cc @@ -8,7 +8,6 @@ #include #include "libcef/browser/extension_impl.h" -#include "libcef/browser/extensions/pdf_extension_util.h" #include "libcef/browser/extensions/value_store/cef_value_store_factory.h" #include "libcef/browser/thread_util.h" #include "libcef/common/extensions/extensions_util.h" @@ -22,6 +21,7 @@ #include "base/strings/string_tokenizer.h" #include "base/strings/utf_string_conversions.h" #include "base/threading/thread_restrictions.h" +#include "chrome/browser/pdf/pdf_extension_util.h" #include "chrome/browser/profiles/profile.h" #include "chrome/common/chrome_paths.h" #include "components/crx_file/id_util.h" @@ -179,8 +179,8 @@ void CefExtensionSystem::Init() { ready_.Signal(); // Add the internal PDF extension. PDF loading works as follows: - // 1. The PDF PPAPI plugin is registered in libcef/common/content_client.cc - // ComputeBuiltInPlugins to handle the kPDFPluginOutOfProcessMimeType. + // 1. The PDF plugin is registered in libcef/common/content_client.cc + // ComputeBuiltInPlugins to handle the pdf::kInternalPluginMimeType. // 2. The PDF extension is registered by the below call to AddExtension and // associated with the "application/pdf" mime type. // 3. Web content running in the owner CefBrowser requests to load a PDF file @@ -230,24 +230,34 @@ void CefExtensionSystem::Init() { // CefExtensionsBrowserClient::LoadResourceFromResourceBundle // and CefComponentExtensionResourceManager. Access to chrome://resources // is granted via CefExtensionWebContentsObserver::RenderViewCreated. - // 15.The PDF extension calls chrome.mimeHandlerPrivate.getStreamInfo - // (chrome/browser/resources/pdf/browser_api.js) to retrieve the PDF - // resource stream. This API is implemented using Mojo as described in - // libcef/common/extensions/api/README.txt. - // 16.The PDF extension requests the PDF PPAPI plugin to handle - // kPDFPluginOutOfProcessMimeType. Approval arrives in the guest renderer + // 15.The PDF extension requests the PDF plugin to handle + // pdf::kInternalPluginMimeType. Approval arrives in the guest renderer // process via ExtensionFrameHelper::OnExtensionResponse which calls // NativeExtensionBindingsSystem::HandleResponse. This triggers creation of // an HTMLPlugInElement via native V8 bindings to host the PDF plugin. + // 16.- With the old PPAPI plugin: + // The PDF extension calls chrome.mimeHandlerPrivate.getStreamInfo + // (chrome/browser/resources/pdf/browser_api.js) to retrieve the PDF + // resource stream. This API is implemented using Mojo as described in + // libcef/common/extensions/api/README.txt. + // - With the new PdfUnseasoned plugin: + // The PDF resource navigation is redirected by PdfNavigationThrottle and + // the stream contents are replaced by PdfURLLoaderRequestInterceptor. // 17.HTMLPlugInElement::RequestObject is called in the guest renderer process - // and determines that the PDF PPAPI plugin should be handled internally + // and determines that the PDF plugin should be handled internally // (handled_externally=false). A PluginDocument is created and // AlloyContentRendererClient::OverrideCreatePlugin is called to create a // WebPlugin. - // 18.The PDF extension and PDF plugin are now loaded. Print commands, if + // 18.- With the old PPAPI plugin: + // The PDF plugin is loaded by ChromeContentRendererClient::CreatePlugin + // calling RenderFrameImpl::CreatePlugin. + // - With the new PdfUnseasoned plugin: + // The PDF plugin is loaded by ChromeContentRendererClient::CreatePlugin + // calling pdf::CreateInternalPlugin. + // 19.The PDF extension and PDF plugin are now loaded. Print commands, if // any, are handled in the guest renderer process by ChromePDFPrintClient // and CefPrintRenderFrameHelperDelegate. - // 19.When navigating away from the PDF file or closing the owner CefBrowser + // 20.When navigating away from the PDF file or closing the owner CefBrowser // the guest WebContents will be destroyed. This triggers a call to // CefMimeHandlerViewGuestDelegate::OnGuestDetached which removes the // routing ID association with the owner CefBrowser. diff --git a/libcef/browser/extensions/pdf_extension_util.cc b/libcef/browser/extensions/pdf_extension_util.cc deleted file mode 100644 index 9e3de9e9b..000000000 --- a/libcef/browser/extensions/pdf_extension_util.cc +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2015 The Chromium 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/extensions/pdf_extension_util.h" - -#include "base/strings/string_util.h" -#include "chrome/grit/browser_resources.h" -#include "ui/base/resource/resource_bundle.h" - -namespace extensions { -namespace pdf_extension_util { - -namespace { - -// Tags in the manifest to be replaced. -const char kNameTag[] = ""; - -} // namespace - -// These should match the keys for the Chrome and Chromium PDF Viewer entries in -// chrome/browser/resources/plugin_metadata/plugins_*.json. -#if defined(GOOGLE_CHROME_BUILD) -const char kPdfResourceIdentifier[] = "google-chrome-pdf"; -#else -const char kPdfResourceIdentifier[] = "chromium-pdf"; -#endif - -// Match the GOOGLE_CHROME_BUILD value from ChromeContentClient::kPDFPluginName -// to avoid breaking Websites that specifically look for this string in the -// plugin list. -const char kPdfPluginName[] = "Chrome PDF Viewer"; - -std::string GetManifest() { - std::string manifest_contents = - ui::ResourceBundle::GetSharedInstance().LoadDataResourceString( - IDR_PDF_MANIFEST); - DCHECK(manifest_contents.find(kNameTag) != std::string::npos); - base::ReplaceFirstSubstringAfterOffset(&manifest_contents, 0, kNameTag, - kPdfPluginName); - - return manifest_contents; -} - -} // namespace pdf_extension_util -} // namespace extensions diff --git a/libcef/browser/extensions/pdf_extension_util.h b/libcef/browser/extensions/pdf_extension_util.h deleted file mode 100644 index 7293af2a7..000000000 --- a/libcef/browser/extensions/pdf_extension_util.h +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2015 The Chromium 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_EXTENSIONS_PDF_EXTENSION_UTIL_H_ -#define CEF_LIBCEF_BROWSER_EXTENSIONS_PDF_EXTENSION_UTIL_H_ - -#include - -namespace extensions { -namespace pdf_extension_util { - -// The ResourceIdentifier for the PDF Viewer plugin. -extern const char kPdfResourceIdentifier[]; - -// The name of the PDF Viewer plugin. -extern const char kPdfPluginName[]; - -// Return the extensions manifest for PDF. The manifest is loaded from -// browser_resources.grd and certain fields are replaced based on what chrome -// flags are enabled. -std::string GetManifest(); - -} // namespace pdf_extension_util -} // namespace extensions - -#endif // CEF_LIBCEF_BROWSER_EXTENSIONS_PDF_EXTENSION_UTIL_H_ diff --git a/libcef/browser/net/throttle_handler.cc b/libcef/browser/net/throttle_handler.cc index a3d159db8..bd235f62c 100644 --- a/libcef/browser/net/throttle_handler.cc +++ b/libcef/browser/net/throttle_handler.cc @@ -26,6 +26,7 @@ namespace { // |is_main_frame| argument once this problem is fixed. bool NavigationOnUIThread( bool is_main_frame, + bool is_pdf, const content::GlobalRenderFrameHostId& global_id, const content::GlobalRenderFrameHostId& parent_global_id, content::WebContents* source, @@ -37,6 +38,7 @@ bool NavigationOnUIThread( params.transition_type(), params.is_renderer_initiated()); open_params.user_gesture = params.has_user_gesture(); open_params.initiator_origin = params.initiator_origin(); + open_params.is_pdf = is_pdf; CefRefPtr browser; if (!CefBrowserInfoManager::GetInstance()->MaybeAllowNavigation( @@ -87,6 +89,7 @@ void CreateThrottlesForNavigation(content::NavigationHandle* navigation_handle, CEF_REQUIRE_UIT(); const bool is_main_frame = navigation_handle->IsInMainFrame(); + const bool is_pdf = navigation_handle->IsPdf(); const auto global_id = frame_util::GetGlobalId(navigation_handle); // Identify the RenderFrameHost that originated the navigation. @@ -99,8 +102,8 @@ void CreateThrottlesForNavigation(content::NavigationHandle* navigation_handle, std::unique_ptr throttle = std::make_unique( navigation_handle, - base::BindRepeating(&NavigationOnUIThread, is_main_frame, global_id, - parent_global_id), + base::BindRepeating(&NavigationOnUIThread, is_main_frame, is_pdf, + global_id, parent_global_id), navigation_interception::SynchronyMode::kSync); throttles.push_back(std::move(throttle)); } diff --git a/libcef/common/alloy/alloy_content_client.cc b/libcef/common/alloy/alloy_content_client.cc index a264747ed..fe1f5fa84 100644 --- a/libcef/common/alloy/alloy_content_client.cc +++ b/libcef/common/alloy/alloy_content_client.cc @@ -9,7 +9,6 @@ #include "include/cef_stream.h" #include "include/cef_version.h" -#include "libcef/browser/extensions/pdf_extension_util.h" #include "libcef/common/app_manager.h" #include "libcef/common/cef_switches.h" #include "libcef/common/extensions/extensions_util.h" @@ -25,9 +24,11 @@ #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "chrome/common/chrome_constants.h" +#include "chrome/common/chrome_content_client.h" #include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/media/cdm_registration.h" +#include "components/pdf/common/internal_plugin_helpers.h" #include "content/public/common/cdm_info.h" #include "content/public/common/content_constants.h" #include "content/public/common/content_switches.h" @@ -48,7 +49,6 @@ namespace { const char kPDFPluginExtension[] = "pdf"; const char kPDFPluginDescription[] = "Portable Document Format"; -const char kPDFPluginOutOfProcessMimeType[] = "application/x-google-chrome-pdf"; const uint32_t kPDFPluginPermissions = ppapi::PERMISSION_PDF | ppapi::PERMISSION_DEV; @@ -66,11 +66,10 @@ void ComputeBuiltInPlugins(std::vector* plugins) { content::PepperPluginInfo pdf_info; pdf_info.is_internal = true; pdf_info.is_out_of_process = true; - pdf_info.name = extensions::pdf_extension_util::kPdfPluginName; + pdf_info.name = ChromeContentClient::kPDFInternalPluginName; pdf_info.description = kPDFPluginDescription; - pdf_info.path = - base::FilePath::FromUTF8Unsafe(AlloyContentClient::kPDFPluginPath); - content::WebPluginMimeType pdf_mime_type(kPDFPluginOutOfProcessMimeType, + pdf_info.path = base::FilePath(ChromeContentClient::kPDFPluginPath); + content::WebPluginMimeType pdf_mime_type(pdf::kInternalPluginMimeType, kPDFPluginExtension, kPDFPluginDescription); pdf_info.mime_types.push_back(pdf_mime_type); @@ -84,8 +83,6 @@ void ComputeBuiltInPlugins(std::vector* plugins) { } // namespace -const char AlloyContentClient::kPDFPluginPath[] = "internal-pdf-viewer"; - AlloyContentClient::AlloyContentClient() = default; AlloyContentClient::~AlloyContentClient() = default; diff --git a/libcef/common/alloy/alloy_content_client.h b/libcef/common/alloy/alloy_content_client.h index 5897d831d..160bfe855 100644 --- a/libcef/common/alloy/alloy_content_client.h +++ b/libcef/common/alloy/alloy_content_client.h @@ -13,8 +13,6 @@ class AlloyContentClient : public content::ContentClient { public: - static const char kPDFPluginPath[]; - AlloyContentClient(); ~AlloyContentClient() override; diff --git a/libcef/renderer/alloy/alloy_content_renderer_client.cc b/libcef/renderer/alloy/alloy_content_renderer_client.cc index 0286c4845..6dce1b4a6 100644 --- a/libcef/renderer/alloy/alloy_content_renderer_client.cc +++ b/libcef/renderer/alloy/alloy_content_renderer_client.cc @@ -48,6 +48,7 @@ #include "base/task/post_task.h" #include "build/build_config.h" #include "chrome/common/chrome_switches.h" +#include "chrome/common/pdf_util.h" #include "chrome/common/url_constants.h" #include "chrome/renderer/browser_exposed_renderer_interfaces.h" #include "chrome/renderer/chrome_content_renderer_client.h" @@ -58,6 +59,9 @@ #include "chrome/renderer/plugins/chrome_plugin_placeholder.h" #include "components/content_settings/core/common/content_settings_types.h" #include "components/nacl/common/nacl_constants.h" +#include "components/pdf/common/internal_plugin_helpers.h" +#include "components/pdf/renderer/internal_plugin_renderer_helpers.h" +#include "components/pdf/renderer/pdf_find_in_page.h" #include "components/printing/renderer/print_render_frame_helper.h" #include "components/spellcheck/renderer/spellcheck.h" #include "components/spellcheck/renderer/spellcheck_provider.h" @@ -80,6 +84,7 @@ #include "media/base/media.h" #include "mojo/public/cpp/bindings/binder_map.h" #include "mojo/public/cpp/bindings/generic_pending_receiver.h" +#include "pdf/pdf_features.h" #include "printing/print_settings.h" #include "services/network/public/cpp/is_potentially_trustworthy.h" #include "services/service_manager/public/cpp/connector.h" @@ -195,11 +200,20 @@ void AlloyContentRendererClient::RenderThreadStarted() { content::RenderThread* thread = content::RenderThread::Get(); + const bool is_extension = IsStandaloneExtensionProcess(); + thread->SetRendererProcessType( - IsStandaloneExtensionProcess() + is_extension ? blink::scheduler::WebRendererProcessType::kExtensionRenderer : blink::scheduler::WebRendererProcessType::kRenderer); + if (is_extension) { + // The process name was set to "Renderer" in RendererMain(). Update it to + // "Extension Renderer" to highlight that it's hosting an extension. + base::trace_event::TraceLog::GetInstance()->set_process_name( + "Extension Renderer"); + } + thread->AddObserver(observer_.get()); if (!command_line->HasSwitch(switches::kDisableSpellChecking)) { @@ -305,6 +319,12 @@ void AlloyContentRendererClient::RenderFrameCreated( base::WrapUnique( new extensions::CefPrintRenderFrameHelperDelegate(*is_windowless))); } + + if (base::FeatureList::IsEnabled(chrome_pdf::features::kPdfUnseasoned)) { + render_frame_observer->associated_interfaces()->AddInterface( + base::BindRepeating(&pdf::PdfFindInPageFactory::BindReceiver, + render_frame->GetRoutingID())); + } } void AlloyContentRendererClient::WebViewCreated(blink::WebView* web_view) { @@ -351,6 +371,16 @@ bool AlloyContentRendererClient::IsPluginHandledExternally( plugin_element); return false; } + if (plugin_info->actual_mime_type == pdf::kInternalPluginMimeType && + pdf::IsInternalPluginExternallyHandled()) { + // Only actually treat the internal PDF plugin as externally handled if + // used within an origin allowed to create the internal PDF plugin; + // otherwise, let Blink try to create the in-process PDF plugin. + if (IsPdfInternalPluginAllowedOrigin( + render_frame->GetWebFrame()->GetSecurityOrigin())) { + return true; + } + } return ChromeExtensionsRendererClient::MaybeCreateMimeHandlerView( plugin_element, original_url, plugin_info->actual_mime_type, plugin_info->plugin);