Skip to content

Commit

Permalink
fix: backport unseasoned pdf support to 18.x (#33664)
Browse files Browse the repository at this point in the history
  • Loading branch information
nornagon committed Apr 12, 2022
1 parent 4905848 commit 541504c
Show file tree
Hide file tree
Showing 11 changed files with 153 additions and 26 deletions.
2 changes: 2 additions & 0 deletions BUILD.gn
Expand Up @@ -694,6 +694,8 @@ source_set("electron_lib") {
deps += [
"//chrome/browser/resources/pdf:resources",
"//components/pdf/browser",
"//components/pdf/browser:interceptors",
"//components/pdf/common",
"//components/pdf/renderer",
"//pdf:pdf_ppapi",
]
Expand Down
24 changes: 12 additions & 12 deletions chromium_src/BUILD.gn
Expand Up @@ -298,13 +298,21 @@ static_library("chrome") {

if (enable_pdf_viewer) {
sources += [
"//chrome/browser/pdf/chrome_pdf_stream_delegate.cc",
"//chrome/browser/pdf/chrome_pdf_stream_delegate.h",
"//chrome/browser/pdf/pdf_extension_util.cc",
"//chrome/browser/pdf/pdf_extension_util.h",
"//chrome/browser/pdf/pdf_frame_util.cc",
"//chrome/browser/pdf/pdf_frame_util.h",
"//chrome/browser/plugins/pdf_iframe_navigation_throttle.cc",
"//chrome/browser/plugins/pdf_iframe_navigation_throttle.h",
"//chrome/renderer/pepper/chrome_pdf_print_client.cc",
"//chrome/renderer/pepper/chrome_pdf_print_client.h",
]
deps += [
"//components/pdf/browser",
"//components/pdf/renderer",
]
}
}

Expand Down Expand Up @@ -332,15 +340,6 @@ source_set("plugins") {
"//chrome/browser/renderer_host/pepper/pepper_isolated_file_system_message_filter.cc",
"//chrome/browser/renderer_host/pepper/pepper_isolated_file_system_message_filter.h",
]
deps += [
"//media:media_buildflags",
"//ppapi/buildflags",
"//ppapi/proxy:ipc",
"//services/device/public/mojom",
]
if (enable_pdf_viewer) {
deps += [ "//components/pdf/browser" ]
}

# renderer side
sources += [
Expand All @@ -351,17 +350,18 @@ source_set("plugins") {
"//chrome/renderer/pepper/pepper_shared_memory_message_filter.cc",
"//chrome/renderer/pepper/pepper_shared_memory_message_filter.h",
]
if (enable_pdf_viewer) {
deps += [ "//components/pdf/renderer" ]
}

deps += [
"//components/strings",
"//media:media_buildflags",
"//ppapi/buildflags",
"//ppapi/host",
"//ppapi/proxy",
"//ppapi/proxy:ipc",
"//ppapi/shared_impl",
"//services/device/public/mojom",
"//skia",
"//storage/browser",
]
}

Expand Down
11 changes: 6 additions & 5 deletions shell/app/electron_content_client.cc
Expand Up @@ -34,6 +34,8 @@
#endif // defined(WIDEVINE_CDM_AVAILABLE)

#if BUILDFLAG(ENABLE_PDF_VIEWER)
#include "chrome/common/pdf_util.h"
#include "components/pdf/common/internal_plugin_helpers.h"
#include "pdf/pdf.h" // nogncheck
#include "pdf/pdf_ppapi.h" // nogncheck
#include "shell/common/electron_constants.h"
Expand Down Expand Up @@ -107,11 +109,11 @@ 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 = "Chromium PDF Viewer";
pdf_info.name = kPDFInternalPluginName;
pdf_info.description = "Portable Document Format";
// This isn't a real file path; it's just used as a unique identifier.
pdf_info.path = base::FilePath(kPdfPluginPath);
content::WebPluginMimeType pdf_mime_type(kPdfPluginMimeType, "pdf",
content::WebPluginMimeType pdf_mime_type(pdf::kInternalPluginMimeType, "pdf",
"Portable Document Format");
pdf_info.mime_types.push_back(pdf_mime_type);
pdf_info.internal_entry_points.get_interface = chrome_pdf::PPP_GetInterface;
Expand All @@ -128,12 +130,11 @@ void ComputeBuiltInPlugins(std::vector<content::PepperPluginInfo>* plugins) {
// here.
content::WebPluginInfo info;
info.type = content::WebPluginInfo::PLUGIN_TYPE_BROWSER_PLUGIN;
info.name = u"Chromium PDF Viewer";
info.name = base::ASCIIToUTF16(kPDFExtensionPluginName);
// This isn't a real file path; it's just used as a unique identifier.
info.path = base::FilePath::FromUTF8Unsafe(extension_misc::kPdfExtensionId);
info.background_color = content::WebPluginInfo::kDefaultBackgroundColor;
info.mime_types.emplace_back("application/pdf", "pdf",
"Portable Document Format");
info.mime_types.emplace_back(kPDFMimeType, "pdf", "Portable Document Format");
content::PluginService::GetInstance()->RefreshPlugins();
content::PluginService::GetInstance()->RegisterInternalPlugin(info, true);
#endif // BUILDFLAG(ENABLE_PDF_VIEWER)
Expand Down
1 change: 1 addition & 0 deletions shell/browser/electron_api_ipc_handler_impl.h
Expand Up @@ -11,6 +11,7 @@
#include "base/memory/weak_ptr.h"
#include "content/public/browser/web_contents_observer.h"
#include "electron/shell/common/api/api.mojom.h"
#include "mojo/public/cpp/bindings/associated_receiver.h"
#include "shell/browser/api/electron_api_web_contents.h"

namespace content {
Expand Down
41 changes: 41 additions & 0 deletions shell/browser/electron_browser_client.cc
Expand Up @@ -46,6 +46,7 @@
#include "content/public/browser/site_instance.h"
#include "content/public/browser/tts_controller.h"
#include "content/public/browser/tts_platform.h"
#include "content/public/browser/url_loader_request_interceptor.h"
#include "content/public/common/content_descriptors.h"
#include "content/public/common/content_paths.h"
#include "content/public/common/content_switches.h"
Expand Down Expand Up @@ -204,7 +205,12 @@
#endif

#if BUILDFLAG(ENABLE_PDF_VIEWER)
#include "chrome/browser/pdf/chrome_pdf_stream_delegate.h"
#include "chrome/browser/plugins/pdf_iframe_navigation_throttle.h" // nogncheck
#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" // nogncheck
#include "components/pdf/common/internal_plugin_helpers.h"
#endif

using content::BrowserThread;
Expand Down Expand Up @@ -1048,6 +1054,18 @@ ElectronBrowserClient::CreateThrottlesForNavigation(
std::make_unique<extensions::ExtensionNavigationThrottle>(handle));
#endif

#if BUILDFLAG(ENABLE_PDF_VIEWER)
std::unique_ptr<content::NavigationThrottle> pdf_iframe_throttle =
PDFIFrameNavigationThrottle::MaybeCreateThrottleFor(handle);
if (pdf_iframe_throttle)
throttles.push_back(std::move(pdf_iframe_throttle));
std::unique_ptr<content::NavigationThrottle> pdf_throttle =
pdf::PdfNavigationThrottle::MaybeCreateThrottleFor(
handle, std::make_unique<ChromePdfStreamDelegate>());
if (pdf_throttle)
throttles.push_back(std::move(pdf_throttle));
#endif

return throttles;
}

Expand Down Expand Up @@ -1452,6 +1470,26 @@ bool ElectronBrowserClient::WillCreateURLLoaderFactory(
return true;
}

std::vector<std::unique_ptr<content::URLLoaderRequestInterceptor>>
ElectronBrowserClient::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 BUILDFLAG(ENABLE_PDF_VIEWER)
{
std::unique_ptr<content::URLLoaderRequestInterceptor> pdf_interceptor =
pdf::PdfURLLoaderRequestInterceptor::MaybeCreateInterceptor(
frame_tree_node_id, std::make_unique<ChromePdfStreamDelegate>());
if (pdf_interceptor)
interceptors.push_back(std::move(pdf_interceptor));
}
#endif
return interceptors;
}

void ElectronBrowserClient::OverrideURLLoaderFactoryParams(
content::BrowserContext* browser_context,
const url::Origin& origin,
Expand Down Expand Up @@ -1725,6 +1763,9 @@ ElectronBrowserClient::GetPluginMimeTypesWithExternalHandlers(
auto map = PluginUtils::GetMimeTypeToExtensionIdMap(browser_context);
for (const auto& pair : map)
mime_types.insert(pair.first);
#endif
#if BUILDFLAG(ENABLE_PDF_VIEWER)
mime_types.insert(pdf::kInternalPluginMimeType);
#endif
return mime_types;
}
Expand Down
6 changes: 6 additions & 0 deletions shell/browser/electron_browser_client.h
Expand Up @@ -227,6 +227,12 @@ class ElectronBrowserClient : public content::ContentBrowserClient,
bool* bypass_redirect_checks,
bool* disable_secure_dns,
network::mojom::URLLoaderFactoryOverridePtr* factory_override) 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;
bool ShouldTreatURLSchemeAsFirstPartyWhenTopLevel(
base::StringPiece scheme,
bool is_embedded_origin_secure) override;
Expand Down
1 change: 1 addition & 0 deletions shell/browser/electron_web_contents_utility_handler_impl.h
Expand Up @@ -11,6 +11,7 @@
#include "base/memory/weak_ptr.h"
#include "content/public/browser/web_contents_observer.h"
#include "electron/shell/common/api/api.mojom.h"
#include "mojo/public/cpp/bindings/associated_receiver.h"
#include "shell/browser/api/electron_api_web_contents.h"

namespace content {
Expand Down
3 changes: 2 additions & 1 deletion shell/common/electron_constants.cc
Expand Up @@ -30,7 +30,8 @@ const char kRunAsNode[] = "ELECTRON_RUN_AS_NODE";
#endif

#if BUILDFLAG(ENABLE_PDF_VIEWER)
const char kPdfPluginMimeType[] = "application/x-google-chrome-pdf";
const char kPDFExtensionPluginName[] = "Chromium PDF Viewer";
const char kPDFInternalPluginName[] = "Chromium PDF Plugin";
const base::FilePath::CharType kPdfPluginPath[] =
FILE_PATH_LITERAL("internal-pdf-viewer");
#endif // BUILDFLAG(ENABLE_PDF_VIEWER)
Expand Down
4 changes: 2 additions & 2 deletions shell/common/electron_constants.h
Expand Up @@ -30,8 +30,8 @@ extern const char kRunAsNode[];
#endif

#if BUILDFLAG(ENABLE_PDF_VIEWER)
// The MIME type used for the PDF plugin.
extern const char kPdfPluginMimeType[];
extern const char kPDFExtensionPluginName[];
extern const char kPDFInternalPluginName[];
extern const base::FilePath::CharType kPdfPluginPath[];
#endif // BUILDFLAG(ENABLE_PDF_VIEWER)

Expand Down
83 changes: 77 additions & 6 deletions shell/renderer/renderer_client_base.cc
Expand Up @@ -62,6 +62,10 @@
#endif

#if BUILDFLAG(ENABLE_PDF_VIEWER)
#include "chrome/common/pdf_util.h"
#include "components/pdf/common/internal_plugin_helpers.h"
#include "components/pdf/renderer/internal_plugin_renderer_helpers.h"
#include "components/pdf/renderer/pdf_internal_plugin_delegate.h"
#include "shell/common/electron_constants.h"
#endif // BUILDFLAG(ENABLE_PDF_VIEWER)

Expand Down Expand Up @@ -105,6 +109,25 @@ std::vector<std::string> ParseSchemesCLISwitch(base::CommandLine* command_line,
base::SPLIT_WANT_NONEMPTY);
}

#if BUILDFLAG(ENABLE_PDF_VIEWER)
class ChromePdfInternalPluginDelegate final
: public pdf::PdfInternalPluginDelegate {
public:
ChromePdfInternalPluginDelegate() = default;
ChromePdfInternalPluginDelegate(const ChromePdfInternalPluginDelegate&) =
delete;
ChromePdfInternalPluginDelegate& operator=(
const ChromePdfInternalPluginDelegate&) = delete;
~ChromePdfInternalPluginDelegate() override = default;

// `pdf::PdfInternalPluginDelegate`:
bool IsAllowedOrigin(const url::Origin& origin) const override {
return origin.scheme() == extensions::kExtensionScheme &&
origin.host() == extension_misc::kPdfExtensionId;
}
};
#endif // BUILDFLAG(ENABLE_PDF_VIEWER)

// static
RendererClientBase* g_renderer_client_base = nullptr;

Expand Down Expand Up @@ -315,10 +338,23 @@ bool RendererClientBase::OverrideCreatePlugin(
content::RenderFrame* render_frame,
const blink::WebPluginParams& params,
blink::WebPlugin** plugin) {
if (params.mime_type.Utf8() == content::kBrowserPluginMimeType ||
#if BUILDFLAG(ENABLE_PDF_VIEWER)
params.mime_type.Utf8() == kPdfPluginMimeType ||
if (params.mime_type.Utf8() == pdf::kInternalPluginMimeType) {
content::WebPluginInfo info;
info.type = content::WebPluginInfo::PLUGIN_TYPE_PEPPER_OUT_OF_PROCESS;
info.name = base::ASCIIToUTF16(kPDFInternalPluginName);
info.path = base::FilePath(kPdfPluginPath);
info.background_color = content::WebPluginInfo::kDefaultBackgroundColor;
info.mime_types.emplace_back(pdf::kInternalPluginMimeType, "pdf",
"Portable Document Format");
*plugin = pdf::CreateInternalPlugin(
info, std::move(params), render_frame,
std::make_unique<ChromePdfInternalPluginDelegate>());
return true;
}
#endif // BUILDFLAG(ENABLE_PDF_VIEWER)

if (params.mime_type.Utf8() == content::kBrowserPluginMimeType ||
render_frame->GetBlinkPreferences().enable_plugins)
return false;

Expand Down Expand Up @@ -355,16 +391,34 @@ bool RendererClientBase::IsPluginHandledExternally(
#if BUILDFLAG(ENABLE_PDF_VIEWER)
DCHECK(plugin_element.HasHTMLTagName("object") ||
plugin_element.HasHTMLTagName("embed"));
if (mime_type == pdf::kInternalPluginMimeType) {
if (IsPdfInternalPluginAllowedOrigin(
render_frame->GetWebFrame()->GetSecurityOrigin())) {
return true;
}

content::WebPluginInfo info;
info.type = content::WebPluginInfo::PLUGIN_TYPE_PEPPER_OUT_OF_PROCESS;
info.name = base::ASCIIToUTF16(kPDFInternalPluginName);
info.path = base::FilePath(kPdfPluginPath);
info.background_color = content::WebPluginInfo::kDefaultBackgroundColor;
info.mime_types.emplace_back(pdf::kInternalPluginMimeType, "pdf",
"Portable Document Format");
return extensions::MimeHandlerViewContainerManager::Get(
content::RenderFrame::FromWebFrame(
plugin_element.GetDocument().GetFrame()),
true /* create_if_does_not_exist */)
->CreateFrameContainer(plugin_element, original_url, mime_type, info);
}

// TODO(nornagon): this info should be shared with the data in
// electron_content_client.cc / ComputeBuiltInPlugins.
content::WebPluginInfo info;
info.type = content::WebPluginInfo::PLUGIN_TYPE_BROWSER_PLUGIN;
const char16_t kPDFExtensionPluginName[] = u"Chromium PDF Viewer";
info.name = kPDFExtensionPluginName;
info.name = base::ASCIIToUTF16(kPDFExtensionPluginName);
info.path = base::FilePath::FromUTF8Unsafe(extension_misc::kPdfExtensionId);
info.background_color = content::WebPluginInfo::kDefaultBackgroundColor;
info.mime_types.emplace_back("application/pdf", "pdf",
"Portable Document Format");
info.mime_types.emplace_back(kPDFMimeType, "pdf", "Portable Document Format");
return extensions::MimeHandlerViewContainerManager::Get(
content::RenderFrame::FromWebFrame(
plugin_element.GetDocument().GetFrame()),
Expand All @@ -381,6 +435,23 @@ bool RendererClientBase::IsOriginIsolatedPepperPlugin(
return true;
}

v8::Local<v8::Object> RendererClientBase::GetScriptableObject(
const blink::WebElement& plugin_element,
v8::Isolate* isolate) {
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
// If there is a MimeHandlerView that can provide the scriptable object then
// MaybeCreateMimeHandlerView must have been called before and a container
// manager should exist.
auto* container_manager = extensions::MimeHandlerViewContainerManager::Get(
content::RenderFrame::FromWebFrame(
plugin_element.GetDocument().GetFrame()),
false /* create_if_does_not_exist */);
if (container_manager)
return container_manager->GetScriptableObject(plugin_element, isolate);
#endif
return v8::Local<v8::Object>();
}

std::unique_ptr<blink::WebPrescientNetworking>
RendererClientBase::CreatePrescientNetworking(
content::RenderFrame* render_frame) {
Expand Down
3 changes: 3 additions & 0 deletions shell/renderer/renderer_client_base.h
Expand Up @@ -112,6 +112,9 @@ class RendererClientBase : public content::ContentRendererClient
const GURL& original_url,
const std::string& mime_type) override;
bool IsOriginIsolatedPepperPlugin(const base::FilePath& plugin_path) override;
v8::Local<v8::Object> GetScriptableObject(
const blink::WebElement& plugin_element,
v8::Isolate* isolate) override;

void RunScriptsAtDocumentStart(content::RenderFrame* render_frame) override;
void RunScriptsAtDocumentEnd(content::RenderFrame* render_frame) override;
Expand Down

0 comments on commit 541504c

Please sign in to comment.