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

refactor: move PDF viewer to OOPIF #41728

Merged
merged 1 commit into from Apr 9, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
Expand Up @@ -154,7 +154,7 @@ void ElectronManagementAPIDelegate::InstallOrLaunchReplacementWebApp(

void ElectronManagementAPIDelegate::EnableExtension(
content::BrowserContext* context,
const std::string& extension_id) const {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not strictly related - drive by change from CL:5268445

const extensions::ExtensionId& extension_id) const {
// const extensions::Extension* extension =
// extensions::ExtensionRegistry::Get(context)->GetExtensionById(
// extension_id, extensions::ExtensionRegistry::EVERYTHING);
Expand All @@ -171,7 +171,7 @@ void ElectronManagementAPIDelegate::EnableExtension(
void ElectronManagementAPIDelegate::DisableExtension(
content::BrowserContext* context,
const extensions::Extension* source_extension,
const std::string& extension_id,
const extensions::ExtensionId& extension_id,
extensions::disable_reason::DisableReason disable_reason) const {
// TODO(sentialx): we don't have ExtensionService
// extensions::ExtensionSystem::Get(context)
Expand All @@ -182,7 +182,7 @@ void ElectronManagementAPIDelegate::DisableExtension(

bool ElectronManagementAPIDelegate::UninstallExtension(
content::BrowserContext* context,
const std::string& transient_extension_id,
const extensions::ExtensionId& transient_extension_id,
extensions::UninstallReason reason,
std::u16string* error) const {
// TODO(sentialx): we don't have ExtensionService
Expand All @@ -194,7 +194,7 @@ bool ElectronManagementAPIDelegate::UninstallExtension(

void ElectronManagementAPIDelegate::SetLaunchType(
content::BrowserContext* context,
const std::string& extension_id,
const extensions::ExtensionId& extension_id,
extensions::LaunchType launch_type) const {
// TODO(sentialx)
// extensions::SetLaunchType(context, extension_id, launch_type);
Expand Down
Expand Up @@ -10,6 +10,7 @@

#include "base/task/cancelable_task_tracker.h"
#include "extensions/browser/api/management/management_api_delegate.h"
#include "extensions/common/extension_id.h"

class ElectronManagementAPIDelegate : public extensions::ManagementAPIDelegate {
public:
Expand Down Expand Up @@ -51,19 +52,20 @@ class ElectronManagementAPIDelegate : public extensions::ManagementAPIDelegate {
const GURL& web_app_url,
ManagementAPIDelegate::InstallOrLaunchWebAppCallback callback)
const override;
void EnableExtension(content::BrowserContext* context,
const std::string& extension_id) const override;
void EnableExtension(
content::BrowserContext* context,
const extensions::ExtensionId& extension_id) const override;
void DisableExtension(
content::BrowserContext* context,
const extensions::Extension* source_extension,
const std::string& extension_id,
const extensions::ExtensionId& extension_id,
extensions::disable_reason::DisableReason disable_reason) const override;
bool UninstallExtension(content::BrowserContext* context,
const std::string& transient_extension_id,
const extensions::ExtensionId& transient_extension_id,
extensions::UninstallReason reason,
std::u16string* error) const override;
void SetLaunchType(content::BrowserContext* context,
const std::string& extension_id,
const extensions::ExtensionId& extension_id,
extensions::LaunchType launch_type) const override;
GURL GetIconURL(const extensions::Extension* extension,
int icon_size,
Expand Down
Expand Up @@ -6,10 +6,16 @@

#include <string>

#include "base/memory/weak_ptr.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/browser/pdf/pdf_viewer_stream_manager.h"
#include "chrome/common/extensions/api/pdf_viewer_private.h"
#include "chrome/common/pref_names.h"
#include "components/pdf/common/constants.h"
#include "components/prefs/pref_service.h"
#include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h"
#include "shell/browser/electron_browser_context.h"
#include "url/url_constants.h"

Expand All @@ -22,6 +28,11 @@ namespace IsAllowedLocalFileAccess =

namespace SetPdfOcrPref = api::pdf_viewer_private::SetPdfOcrPref;

namespace SetPdfPluginAttributes =
api::pdf_viewer_private::SetPdfPluginAttributes;

namespace SetPdfDocumentTitle = api::pdf_viewer_private::SetPdfDocumentTitle;

// Check if the current URL is allowed based on a list of allowlisted domains.
bool IsUrlAllowedToEmbedLocalFiles(
const GURL& current_url,
Expand All @@ -43,8 +54,46 @@ bool IsUrlAllowedToEmbedLocalFiles(
return false;
}

// Get the `StreamContainer` associated with the `extension_host`.
base::WeakPtr<StreamContainer> GetStreamContainer(
content::RenderFrameHost* extension_host) {
content::RenderFrameHost* embedder_host = extension_host->GetParent();
if (!embedder_host) {
return nullptr;
}

auto* pdf_viewer_stream_manager =
pdf::PdfViewerStreamManager::FromRenderFrameHost(embedder_host);
if (!pdf_viewer_stream_manager) {
return nullptr;
}

return pdf_viewer_stream_manager->GetStreamContainer(embedder_host);
}

} // namespace

PdfViewerPrivateGetStreamInfoFunction::PdfViewerPrivateGetStreamInfoFunction() =
default;

PdfViewerPrivateGetStreamInfoFunction::
~PdfViewerPrivateGetStreamInfoFunction() = default;

ExtensionFunction::ResponseAction PdfViewerPrivateGetStreamInfoFunction::Run() {
base::WeakPtr<StreamContainer> stream =
GetStreamContainer(render_frame_host());
if (!stream) {
return RespondNow(Error("Failed to get StreamContainer"));
}

api::pdf_viewer_private::StreamInfo stream_info;
stream_info.original_url = stream->original_url().spec();
stream_info.stream_url = stream->stream_url().spec();
stream_info.tab_id = stream->tab_id();
stream_info.embedded = stream->embedded();
return RespondNow(WithArguments(stream_info.ToValue()));
}

PdfViewerPrivateIsAllowedLocalFileAccessFunction::
PdfViewerPrivateIsAllowedLocalFileAccessFunction() = default;

Expand All @@ -61,6 +110,37 @@ PdfViewerPrivateIsAllowedLocalFileAccessFunction::Run() {
IsUrlAllowedToEmbedLocalFiles(GURL(params->url), base::Value::List())));
}

PdfViewerPrivateSetPdfDocumentTitleFunction::
PdfViewerPrivateSetPdfDocumentTitleFunction() = default;

PdfViewerPrivateSetPdfDocumentTitleFunction::
~PdfViewerPrivateSetPdfDocumentTitleFunction() = default;

// This function is only called for full-page PDFs.
ExtensionFunction::ResponseAction
PdfViewerPrivateSetPdfDocumentTitleFunction::Run() {
content::WebContents* web_contents = GetSenderWebContents();
if (!web_contents) {
return RespondNow(Error("Could not find a valid web contents."));
}

// Title should only be set for full-page PDFs.
// MIME type associated with sender `WebContents` must be `application/pdf`
// for a full-page PDF.
EXTENSION_FUNCTION_VALIDATE(web_contents->GetContentsMimeType() ==
pdf::kPDFMimeType);

std::optional<SetPdfDocumentTitle::Params> params =
SetPdfDocumentTitle::Params::Create(args());
EXTENSION_FUNCTION_VALIDATE(params);

web_contents->UpdateTitleForEntry(
web_contents->GetController().GetLastCommittedEntry(),
base::UTF8ToUTF16(params->title));

return RespondNow(NoArguments());
}

PdfViewerPrivateIsPdfOcrAlwaysActiveFunction::
PdfViewerPrivateIsPdfOcrAlwaysActiveFunction() = default;

Expand All @@ -87,4 +167,42 @@ ExtensionFunction::ResponseAction PdfViewerPrivateSetPdfOcrPrefFunction::Run() {
return RespondNow(WithArguments(false));
}

PdfViewerPrivateSetPdfPluginAttributesFunction::
PdfViewerPrivateSetPdfPluginAttributesFunction() = default;

PdfViewerPrivateSetPdfPluginAttributesFunction::
~PdfViewerPrivateSetPdfPluginAttributesFunction() = default;

ExtensionFunction::ResponseAction
PdfViewerPrivateSetPdfPluginAttributesFunction::Run() {
std::optional<SetPdfPluginAttributes::Params> params =
SetPdfPluginAttributes::Params::Create(args());
EXTENSION_FUNCTION_VALIDATE(params);

base::WeakPtr<StreamContainer> stream =
GetStreamContainer(render_frame_host());
if (!stream) {
return RespondNow(Error("Failed to get StreamContainer"));
}

const api::pdf_viewer_private::PdfPluginAttributes& attributes =
params->attributes;
// Check the `background_color` is an integer.
double whole = 0.0;
if (std::modf(attributes.background_color, &whole) != 0.0) {
return RespondNow(Error("Background color is not an integer"));
}

// Check the `background_color` is within the range of a uint32_t.
if (!base::IsValueInRangeForNumericType<uint32_t>(
attributes.background_color)) {
return RespondNow(Error("Background color out of bounds"));
}

stream->set_pdf_plugin_attributes(mime_handler::PdfPluginAttributes::New(
/*background_color=*/attributes.background_color,
/*allow_javascript=*/attributes.allow_javascript));
return RespondNow(NoArguments());
}

} // namespace extensions
Expand Up @@ -9,6 +9,24 @@

namespace extensions {

class PdfViewerPrivateGetStreamInfoFunction : public ExtensionFunction {
public:
DECLARE_EXTENSION_FUNCTION("pdfViewerPrivate.getStreamInfo",
PDFVIEWERPRIVATE_GETSTREAMINFO)

PdfViewerPrivateGetStreamInfoFunction();
PdfViewerPrivateGetStreamInfoFunction(
const PdfViewerPrivateGetStreamInfoFunction&) = delete;
PdfViewerPrivateGetStreamInfoFunction& operator=(
const PdfViewerPrivateGetStreamInfoFunction&) = delete;

protected:
~PdfViewerPrivateGetStreamInfoFunction() override;

// Override from ExtensionFunction:
ResponseAction Run() override;
};

class PdfViewerPrivateIsAllowedLocalFileAccessFunction
: public ExtensionFunction {
public:
Expand All @@ -28,6 +46,24 @@ class PdfViewerPrivateIsAllowedLocalFileAccessFunction
ResponseAction Run() override;
};

class PdfViewerPrivateSetPdfDocumentTitleFunction : public ExtensionFunction {
public:
DECLARE_EXTENSION_FUNCTION("pdfViewerPrivate.setPdfDocumentTitle",
PDFVIEWERPRIVATE_SETPDFDOCUMENTTITLE)

PdfViewerPrivateSetPdfDocumentTitleFunction();
PdfViewerPrivateSetPdfDocumentTitleFunction(
const PdfViewerPrivateSetPdfDocumentTitleFunction&) = delete;
PdfViewerPrivateSetPdfDocumentTitleFunction& operator=(
const PdfViewerPrivateSetPdfDocumentTitleFunction&) = delete;

protected:
~PdfViewerPrivateSetPdfDocumentTitleFunction() override;

// Override from ExtensionFunction:
ResponseAction Run() override;
};

class PdfViewerPrivateIsPdfOcrAlwaysActiveFunction : public ExtensionFunction {
public:
DECLARE_EXTENSION_FUNCTION("pdfViewerPrivate.isPdfOcrAlwaysActive",
Expand Down Expand Up @@ -64,6 +100,25 @@ class PdfViewerPrivateSetPdfOcrPrefFunction : public ExtensionFunction {
ResponseAction Run() override;
};

class PdfViewerPrivateSetPdfPluginAttributesFunction
: public ExtensionFunction {
public:
DECLARE_EXTENSION_FUNCTION("pdfViewerPrivate.setPdfPluginAttributes",
PDFVIEWERPRIVATE_SETPDFPLUGINATTRIBUTES)

PdfViewerPrivateSetPdfPluginAttributesFunction();
PdfViewerPrivateSetPdfPluginAttributesFunction(
const PdfViewerPrivateSetPdfPluginAttributesFunction&) = delete;
PdfViewerPrivateSetPdfPluginAttributesFunction& operator=(
const PdfViewerPrivateSetPdfPluginAttributesFunction&) = delete;

protected:
~PdfViewerPrivateSetPdfPluginAttributesFunction() override;

// Override from ExtensionFunction:
ResponseAction Run() override;
};

} // namespace extensions

#endif // ELECTRON_SHELL_BROWSER_EXTENSIONS_API_PDF_VIEWER_PRIVATE_PDF_VIEWER_PRIVATE_API_H_
Expand Up @@ -10,12 +10,20 @@
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
#include "electron/buildflags/buildflags.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/guest_view/mime_handler_view/mime_handler_stream_manager.h"
#include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h"
#include "extensions/common/manifest_handlers/mime_types_handler.h"
#include "shell/browser/api/electron_api_web_contents.h"

#if BUILDFLAG(ENABLE_PDF_VIEWER)
#include "base/feature_list.h"
#include "chrome/browser/pdf/pdf_viewer_stream_manager.h"
#include "extensions/common/constants.h"
#include "pdf/pdf_features.h"
#endif // BUILDFLAG(ENABLE_PDF_VIEWER)

namespace extensions {

void StreamsPrivateAPI::SendExecuteMimeTypeHandlerEvent(
Expand Down Expand Up @@ -51,13 +59,27 @@ void StreamsPrivateAPI::SendExecuteMimeTypeHandlerEvent(
GURL handler_url(
extensions::Extension::GetBaseURLFromExtensionId(extension_id).spec() +
handler->handler_url());

int tab_id = -1;
auto* api_contents = electron::api::WebContents::From(web_contents);
if (api_contents)
tab_id = api_contents->ID();

auto stream_container = std::make_unique<extensions::StreamContainer>(
tab_id, embedded, handler_url, extension_id,
std::move(transferrable_loader), original_url);

#if BUILDFLAG(ENABLE_PDF_VIEWER)
if (base::FeatureList::IsEnabled(chrome_pdf::features::kPdfOopif) &&
extension_id == extension_misc::kPdfExtensionId) {
pdf::PdfViewerStreamManager::Create(web_contents);
pdf::PdfViewerStreamManager::FromWebContents(web_contents)
->AddStreamContainer(frame_tree_node_id, internal_id,
std::move(stream_container));
return;
}
#endif // BUILDFLAG(ENABLE_PDF_VIEWER)

extensions::MimeHandlerStreamManager::Get(browser_context)
->AddStream(stream_id, std::move(stream_container), frame_tree_node_id);
}
Expand Down