Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: backport unseasoned pdf support to 18.x #33664

Merged
merged 6 commits into from Apr 12, 2022
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions BUILD.gn
Expand Up @@ -363,6 +363,10 @@ source_set("electron_lib") {
"//components/network_session_configurator/common",
"//components/omnibox/browser:buildflags",
"//components/os_crypt",
"//components/pdf/browser",
"//components/pdf/browser:interceptors",
"//components/pdf/common",
"//components/pdf/renderer",
"//components/pref_registry",
"//components/prefs",
"//components/security_state/content",
Expand Down
4 changes: 4 additions & 0 deletions chromium_src/BUILD.gn
Expand Up @@ -298,12 +298,16 @@ 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/renderer/pepper/chrome_pdf_print_client.cc",
"//chrome/renderer/pepper/chrome_pdf_print_client.h",
"//chrome/browser/plugins/pdf_iframe_navigation_throttle.cc",
"//chrome/browser/plugins/pdf_iframe_navigation_throttle.h",
]
}
}
Expand Down
40 changes: 40 additions & 0 deletions shell/browser/electron_browser_client.cc
Expand Up @@ -26,11 +26,16 @@
#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/pdf/chrome_pdf_stream_delegate.h"
#include "chrome/browser/plugins/pdf_iframe_navigation_throttle.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/chrome_version.h"
#include "components/net_log/chrome_net_log.h"
#include "components/network_hints/common/network_hints.mojom.h"
#include "components/pdf/browser/pdf_navigation_throttle.h"
#include "components/pdf/browser/pdf_url_loader_request_interceptor.h"
#include "components/pdf/common/internal_plugin_helpers.h"
#include "content/browser/keyboard_lock/keyboard_lock_service_impl.h" // nogncheck
#include "content/browser/site_instance_impl.h" // nogncheck
#include "content/public/browser/browser_main_runner.h"
Expand Down Expand Up @@ -1048,6 +1053,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 +1469,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 +1762,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
75 changes: 73 additions & 2 deletions shell/renderer/renderer_client_base.cc
Expand Up @@ -12,7 +12,10 @@
#include "base/command_line.h"
#include "base/strings/string_split.h"
#include "base/strings/stringprintf.h"
#include "chrome/common/pdf_util.h"
#include "components/network_hints/renderer/web_prescient_networking_impl.h"
#include "components/pdf/renderer/internal_plugin_renderer_helpers.h"
#include "components/pdf/renderer/pdf_internal_plugin_delegate.h"
#include "content/common/buildflags.h"
#include "content/public/common/content_constants.h"
#include "content/public/common/content_switches.h"
Expand Down Expand Up @@ -311,14 +314,46 @@ void RendererClientBase::DidClearWindowObject(
render_frame->GetWebFrame()->ExecuteScript(blink::WebScriptSource("void 0"));
}

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;
}
};

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() == kPdfPluginMimeType) {
content::WebPluginInfo info;
info.type = content::WebPluginInfo::PLUGIN_TYPE_PEPPER_OUT_OF_PROCESS;
const char16_t kPDFExtensionPluginName[] = u"Chromium PDF Viewer";
info.name = kPDFExtensionPluginName;
info.path = base::FilePath::FromUTF8Unsafe("internal-pdf-viewer");
info.background_color = content::WebPluginInfo::kDefaultBackgroundColor;
info.mime_types.emplace_back("application/x-google-chrome-pdf", "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 ||
params.mime_type.Utf8() == kPdfPluginMimeType ||
render_frame->GetBlinkPreferences().enable_plugins)
return false;

Expand Down Expand Up @@ -355,6 +390,27 @@ bool RendererClientBase::IsPluginHandledExternally(
#if BUILDFLAG(ENABLE_PDF_VIEWER)
DCHECK(plugin_element.HasHTMLTagName("object") ||
plugin_element.HasHTMLTagName("embed"));
if (mime_type == "application/x-google-chrome-pdf") {
if (IsPdfInternalPluginAllowedOrigin(
render_frame->GetWebFrame()->GetSecurityOrigin())) {
return true;
}

content::WebPluginInfo info;
info.type = content::WebPluginInfo::PLUGIN_TYPE_PEPPER_OUT_OF_PROCESS;
const char16_t kPDFExtensionPluginName[] = u"Chromium PDF Viewer";
info.name = kPDFExtensionPluginName;
info.path = base::FilePath::FromUTF8Unsafe("internal-pdf-viewer");
info.background_color = content::WebPluginInfo::kDefaultBackgroundColor;
info.mime_types.emplace_back("application/x-google-chrome-pdf", "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;
Expand All @@ -381,6 +437,21 @@ bool RendererClientBase::IsOriginIsolatedPepperPlugin(
return true;
}

v8::Local<v8::Object> RendererClientBase::GetScriptableObject(
const blink::WebElement& plugin_element,
v8::Isolate* isolate) {
// 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);
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