mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-01-27 09:41:17 +01:00
alloy: Add support for the new non-PPAPI PDF viewer (see issue #3047)
Enable by passing `--enable-features=PdfUnseasoned` on the command line.
This commit is contained in:
parent
d6d316e304
commit
c75ebbccec
2
BUILD.gn
2
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",
|
||||
|
@ -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),
|
||||
|
@ -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<AlloyBrowserContext*>(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<AlloyBrowserContext*>(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<std::unique_ptr<content::NavigationThrottle>>
|
||||
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<ChromePdfStreamDelegate>());
|
||||
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<std::unique_ptr<content::URLLoaderRequestInterceptor>>
|
||||
AlloyContentBrowserClient::WillCreateURLLoaderRequestInterceptors(
|
||||
content::NavigationUIData* navigation_ui_data,
|
||||
int frame_tree_node_id,
|
||||
const scoped_refptr<network::SharedURLLoaderFactory>&
|
||||
network_loader_factory) {
|
||||
std::vector<std::unique_ptr<content::URLLoaderRequestInterceptor>>
|
||||
interceptors;
|
||||
|
||||
if (extensions::ExtensionsEnabled()) {
|
||||
auto pdf_interceptor =
|
||||
pdf::PdfURLLoaderRequestInterceptor::MaybeCreateInterceptor(
|
||||
frame_tree_node_id, std::make_unique<ChromePdfStreamDelegate>());
|
||||
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<CefRequestContextImpl> AlloyContentBrowserClient::request_context()
|
||||
const {
|
||||
return browser_main_parts_->request_context();
|
||||
|
@ -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<content::WebContents*()>& wc_getter,
|
||||
content::NavigationUIData* navigation_ui_data,
|
||||
int frame_tree_node_id) override;
|
||||
std::vector<std::unique_ptr<content::URLLoaderRequestInterceptor>>
|
||||
WillCreateURLLoaderRequestInterceptors(
|
||||
content::NavigationUIData* navigation_ui_data,
|
||||
int frame_tree_node_id,
|
||||
const scoped_refptr<network::SharedURLLoaderFactory>&
|
||||
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<CefRequestContextImpl> request_context() const;
|
||||
CefDevToolsDelegate* devtools_delegate() const;
|
||||
|
@ -8,7 +8,6 @@
|
||||
#include <string>
|
||||
|
||||
#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.
|
||||
|
@ -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[] = "<NAME>";
|
||||
|
||||
} // 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
|
@ -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 <string>
|
||||
|
||||
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_
|
@ -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<CefBrowserHostBase> 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<content::NavigationThrottle> throttle =
|
||||
std::make_unique<navigation_interception::InterceptNavigationThrottle>(
|
||||
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));
|
||||
}
|
||||
|
@ -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<content::PepperPluginInfo>* 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<content::PepperPluginInfo>* plugins) {
|
||||
|
||||
} // namespace
|
||||
|
||||
const char AlloyContentClient::kPDFPluginPath[] = "internal-pdf-viewer";
|
||||
|
||||
AlloyContentClient::AlloyContentClient() = default;
|
||||
AlloyContentClient::~AlloyContentClient() = default;
|
||||
|
||||
|
@ -13,8 +13,6 @@
|
||||
|
||||
class AlloyContentClient : public content::ContentClient {
|
||||
public:
|
||||
static const char kPDFPluginPath[];
|
||||
|
||||
AlloyContentClient();
|
||||
~AlloyContentClient() override;
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user