0

[unseasoned-pdf] Merge common plugin initialization logic

Consolidates plugin initialization logic shared between the Pepper and
the unseasoned PDF plugins into PdfViewPluginBase::InitializeBase(). The
duplication here is a perennial source of bugs, including a few that are
blocking unseasoned Print Preview (crbug.com/1253984).

This change also tries to be more consistent about the order of
initialization between the Pepper and the unseasoned plugins.

Bug: 1232152, 1253984
Change-Id: I65e472c808b2a0ea89e884e5c744a9db1ec8a3c7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3212727
Reviewed-by: Daniel Hosseinian <dhoss@chromium.org>
Commit-Queue: K. Moon <kmoon@chromium.org>
Cr-Commit-Position: refs/heads/main@{#929468}
This commit is contained in:
K. Moon
2021-10-07 22:59:46 +00:00
committed by Chromium LUCI CQ
parent 23be872650
commit 32e98087f2
8 changed files with 147 additions and 130 deletions

@@ -334,7 +334,6 @@ if (enable_pdf) {
"//base", "//base",
"//build:chromeos_buildflags", "//build:chromeos_buildflags",
"//net", "//net",
"//pdf:buildflags",
"//ppapi/cpp:objects", "//ppapi/cpp:objects",
"//ppapi/cpp/private:internal_module", "//ppapi/cpp/private:internal_module",
"//skia", "//skia",
@@ -342,6 +341,7 @@ if (enable_pdf) {
"//third_party/blink/public/common:headers", "//third_party/blink/public/common:headers",
"//ui/base", "//ui/base",
"//ui/base/cursor/mojom:cursor_type", "//ui/base/cursor/mojom:cursor_type",
"//url",
] ]
} }

@@ -22,6 +22,7 @@
#include "base/notreached.h" #include "base/notreached.h"
#include "base/numerics/safe_conversions.h" #include "base/numerics/safe_conversions.h"
#include "base/strings/string_number_conversions.h" #include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h" #include "base/strings/string_util.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "base/values.h" #include "base/values.h"
@@ -30,7 +31,6 @@
#include "net/base/escape.h" #include "net/base/escape.h"
#include "pdf/accessibility.h" #include "pdf/accessibility.h"
#include "pdf/accessibility_structs.h" #include "pdf/accessibility_structs.h"
#include "pdf/buildflags.h"
#include "pdf/document_attachment_info.h" #include "pdf/document_attachment_info.h"
#include "pdf/document_metadata.h" #include "pdf/document_metadata.h"
#include "pdf/pdfium/pdfium_engine.h" #include "pdf/pdfium/pdfium_engine.h"
@@ -72,6 +72,7 @@
#include "ui/gfx/geometry/point_f.h" #include "ui/gfx/geometry/point_f.h"
#include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h" #include "ui/gfx/geometry/size.h"
#include "url/gurl.h"
#if defined(OS_LINUX) || defined(OS_CHROMEOS) #if defined(OS_LINUX) || defined(OS_CHROMEOS)
#include "pdf/ppapi_migration/pdfium_font_linux.h" #include "pdf/ppapi_migration/pdfium_font_linux.h"
@@ -441,44 +442,33 @@ bool OutOfProcessInstance::Init(uint32_t argc,
pp::Var document_url_var = pp::URLUtil_Dev::Get()->GetDocumentURL(this); pp::Var document_url_var = pp::URLUtil_Dev::Get()->GetDocumentURL(this);
if (!document_url_var.is_string()) if (!document_url_var.is_string())
return false; return false;
GURL document_url(document_url_var.AsString());
// Check if the PDF is being loaded in the PDF chrome extension. We only allow
// the plugin to be loaded in the extension and print preview to avoid
// exposing sensitive APIs directly to external websites.
//
// This is enforced before launching the plugin process (see
// ChromeContentBrowserClient::ShouldAllowPluginCreation), so below we just do
// a CHECK as a defense-in-depth.
std::string document_url = document_url_var.AsString();
base::StringPiece document_url_piece(document_url);
set_is_print_preview(IsPrintPreviewUrl(document_url_piece));
ValidateDocumentUrl(document_url_piece);
// Allow the plugin to handle find requests. // Allow the plugin to handle find requests.
SetPluginToHandleFindRequests(); SetPluginToHandleFindRequests();
text_input_ = std::make_unique<pp::TextInput_Dev>(this); text_input_ = std::make_unique<pp::TextInput_Dev>(this);
PDFiumFormFiller::ScriptOption script_option =
PDFiumFormFiller::DefaultScriptOption();
bool has_edits = false;
const char* src_url = nullptr; const char* src_url = nullptr;
const char* original_url = nullptr; const char* original_url = nullptr;
const char* top_level_url = nullptr; const char* top_level_url = nullptr;
bool full_frame = false;
SkColor background_color = SK_ColorTRANSPARENT;
PDFiumFormFiller::ScriptOption script_option =
PDFiumFormFiller::DefaultScriptOption();
bool has_edits = false;
for (uint32_t i = 0; i < argc; ++i) { for (uint32_t i = 0; i < argc; ++i) {
if (strcmp(argn[i], "original-url") == 0) { if (strcmp(argn[i], "src") == 0) {
original_url = argv[i];
} else if (strcmp(argn[i], "src") == 0) {
src_url = argv[i]; src_url = argv[i];
} else if (strcmp(argn[i], "original-url") == 0) {
original_url = argv[i];
} else if (strcmp(argn[i], "top-level-url") == 0) { } else if (strcmp(argn[i], "top-level-url") == 0) {
top_level_url = argv[i]; top_level_url = argv[i];
} else if (strcmp(argn[i], "full-frame") == 0) { } else if (strcmp(argn[i], "full-frame") == 0) {
set_full_frame(true); full_frame = true;
} else if (strcmp(argn[i], "background-color") == 0) { } else if (strcmp(argn[i], "background-color") == 0) {
SkColor background_color;
if (!base::StringToUint(argv[i], &background_color)) if (!base::StringToUint(argv[i], &background_color))
return false; return false;
SetBackgroundColor(background_color);
} else if (strcmp(argn[i], "javascript") == 0) { } else if (strcmp(argn[i], "javascript") == 0) {
if (strcmp(argv[i], "allow") != 0) if (strcmp(argv[i], "allow") != 0)
script_option = PDFiumFormFiller::ScriptOption::kNoJavaScript; script_option = PDFiumFormFiller::ScriptOption::kNoJavaScript;
@@ -493,27 +483,14 @@ bool OutOfProcessInstance::Init(uint32_t argc,
if (!original_url) if (!original_url)
original_url = src_url; original_url = src_url;
InitializeEngine(std::make_unique<PDFiumEngine>(this, script_option));
// If we're in print preview mode we don't need to load the document yet.
// A `kJSResetPrintPreviewModeType` message will be sent to the plugin letting
// it know the url to load. By not loading here we avoid loading the same
// document twice.
if (IsPrintPreview())
return true;
LoadUrl(src_url, /*is_print_preview=*/false);
set_url(original_url);
// Not all edits go through the PDF plugin's form filler. The plugin instance
// can be restarted by exiting annotation mode on ChromeOS, which can set the
// document to an edited state.
set_edit_mode(has_edits);
#if !BUILDFLAG(ENABLE_INK)
DCHECK(!edit_mode());
#endif // !BUILDFLAG(ENABLE_INK)
pp::PDF::SetCrashData(this, original_url, top_level_url); pp::PDF::SetCrashData(this, original_url, top_level_url);
InitializeBase(std::make_unique<PDFiumEngine>(this, script_option),
/*embedder_origin=*/document_url.GetOrigin().spec(),
/*src_url=*/src_url,
/*original_url=*/original_url,
/*full_frame=*/full_frame,
/*background_color=*/background_color,
/*has_edits=*/has_edits);
return true; return true;
} }

@@ -85,7 +85,7 @@ constexpr base::TimeDelta kFindResultCooldown = base::Milliseconds(100);
constexpr char kChromePrintHost[] = "chrome://print/"; constexpr char kChromePrintHost[] = "chrome://print/";
constexpr char kChromeExtensionHost[] = constexpr char kChromeExtensionHost[] =
"chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai"; "chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/";
// Same value as printing::COMPLETE_PREVIEW_DOCUMENT_INDEX. // Same value as printing::COMPLETE_PREVIEW_DOCUMENT_INDEX.
constexpr int kCompletePDFIndex = -1; constexpr int kCompletePDFIndex = -1;
@@ -116,6 +116,10 @@ base::Value PrepareReplyMessage(base::StringPiece reply_type,
return reply; return reply;
} }
bool IsPrintPreviewUrl(base::StringPiece url) {
return base::StartsWith(url, kChromePrintHost);
}
int ExtractPrintPreviewPageIndex(base::StringPiece src_url) { int ExtractPrintPreviewPageIndex(base::StringPiece src_url) {
// Sample `src_url` format: chrome://print/id/page_index/print.pdf // Sample `src_url` format: chrome://print/id/page_index/print.pdf
// The page_index is zero-based, but can be negative with special meanings. // The page_index is zero-based, but can be negative with special meanings.
@@ -144,6 +148,48 @@ PdfViewPluginBase::PdfViewPluginBase() = default;
PdfViewPluginBase::~PdfViewPluginBase() = default; PdfViewPluginBase::~PdfViewPluginBase() = default;
void PdfViewPluginBase::InitializeBase(std::unique_ptr<PDFiumEngine> engine,
base::StringPiece embedder_origin,
base::StringPiece src_url,
base::StringPiece original_url,
bool full_frame,
SkColor background_color,
bool has_edits) {
// Check if the PDF is being loaded in the PDF chrome extension. We only allow
// the plugin to be loaded in the extension and print preview to avoid
// exposing sensitive APIs directly to external websites.
//
// This is enforced before launching the plugin process (see
// ChromeContentBrowserClient::ShouldAllowPluginCreation), so below we just do
// a CHECK as a defense-in-depth.
is_print_preview_ = IsPrintPreviewUrl(embedder_origin);
CHECK(IsPrintPreview() || embedder_origin == kChromeExtensionHost);
full_frame_ = full_frame;
background_color_ = background_color;
DCHECK(engine);
engine_ = std::move(engine);
// If we're in print preview mode we don't need to load the document yet.
// A `kJSResetPrintPreviewModeType` message will be sent to the plugin letting
// it know the url to load. By not loading here we avoid loading the same
// document twice.
if (IsPrintPreview())
return;
LoadUrl(src_url, /*is_print_preview=*/false);
url_ = std::string(original_url);
// Not all edits go through the PDF plugin's form filler. The plugin instance
// can be restarted by exiting annotation mode on ChromeOS, which can set the
// document to an edited state.
edit_mode_ = has_edits;
#if !BUILDFLAG(ENABLE_INK)
DCHECK(!edit_mode_);
#endif // !BUILDFLAG(ENABLE_INK)
}
void PdfViewPluginBase::ProposeDocumentLayout(const DocumentLayout& layout) { void PdfViewPluginBase::ProposeDocumentLayout(const DocumentLayout& layout) {
base::Value message(base::Value::Type::DICTIONARY); base::Value message(base::Value::Type::DICTIONARY);
message.SetStringKey("type", "documentDimensions"); message.SetStringKey("type", "documentDimensions");
@@ -693,7 +739,8 @@ bool PdfViewPluginBase::UnsupportedFeatureIsReportedForTesting(
return base::Contains(unsupported_features_reported_, feature); return base::Contains(unsupported_features_reported_, feature);
} }
void PdfViewPluginBase::InitializeEngine(std::unique_ptr<PDFiumEngine> engine) { void PdfViewPluginBase::InitializeEngineForTesting(
std::unique_ptr<PDFiumEngine> engine) {
DCHECK(engine); DCHECK(engine);
engine_ = std::move(engine); engine_ = std::move(engine);
} }
@@ -706,16 +753,11 @@ void PdfViewPluginBase::DestroyPreviewEngine() {
preview_engine_.reset(); preview_engine_.reset();
} }
void PdfViewPluginBase::ValidateDocumentUrl(base::StringPiece document_url) { void PdfViewPluginBase::LoadUrl(base::StringPiece url, bool is_print_preview) {
CHECK(base::StartsWith(document_url, kChromeExtensionHost) ||
IsPrintPreview());
}
void PdfViewPluginBase::LoadUrl(const std::string& url, bool is_print_preview) {
last_progress_sent_ = 0; last_progress_sent_ = 0;
UrlRequest request; UrlRequest request;
request.url = url; request.url = std::string(url);
request.method = "GET"; request.method = "GET";
request.ignore_redirects = true; request.ignore_redirects = true;
@@ -989,11 +1031,6 @@ void PdfViewPluginBase::SetZoom(double scale) {
OnGeometryChanged(old_zoom, device_scale_); OnGeometryChanged(old_zoom, device_scale_);
} }
// static
bool PdfViewPluginBase::IsPrintPreviewUrl(base::StringPiece url) {
return base::StartsWith(url, kChromePrintHost);
}
// static // static
base::Value::DictStorage PdfViewPluginBase::DictFromRect( base::Value::DictStorage PdfViewPluginBase::DictFromRect(
const gfx::Rect& rect) { const gfx::Rect& rect) {
@@ -1109,8 +1146,8 @@ void PdfViewPluginBase::HandleResetPrintPreviewModeMessage(
document_load_state_ = DocumentLoadState::kLoading; document_load_state_ = DocumentLoadState::kLoading;
LoadUrl(GetURL(), /*is_print_preview=*/false); LoadUrl(GetURL(), /*is_print_preview=*/false);
preview_engine_.reset(); preview_engine_.reset();
InitializeEngine(std::make_unique<PDFiumEngine>( engine_ = std::make_unique<PDFiumEngine>(
this, PDFiumFormFiller::ScriptOption::kNoJavaScript)); this, PDFiumFormFiller::ScriptOption::kNoJavaScript);
engine()->SetGrayscale(is_grayscale); engine()->SetGrayscale(is_grayscale);
paint_manager_.InvalidateRect(gfx::Rect(plugin_rect().size())); paint_manager_.InvalidateRect(gfx::Rect(plugin_rect().size()));
@@ -1180,9 +1217,8 @@ void PdfViewPluginBase::HandleSelectAllMessage(const base::Value& /*message*/) {
void PdfViewPluginBase::HandleSetBackgroundColorMessage( void PdfViewPluginBase::HandleSetBackgroundColorMessage(
const base::Value& message) { const base::Value& message) {
const SkColor background_color = background_color_ =
base::checked_cast<SkColor>(message.FindDoubleKey("color").value()); base::checked_cast<SkColor>(message.FindDoubleKey("color").value());
SetBackgroundColor(background_color);
} }
void PdfViewPluginBase::HandleSetReadOnlyMessage(const base::Value& message) { void PdfViewPluginBase::HandleSetReadOnlyMessage(const base::Value& message) {

@@ -17,6 +17,7 @@
#include "base/containers/queue.h" #include "base/containers/queue.h"
#include "base/i18n/rtl.h" #include "base/i18n/rtl.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/strings/string_piece_forward.h"
#include "base/values.h" #include "base/values.h"
#include "pdf/accessibility_structs.h" #include "pdf/accessibility_structs.h"
#include "pdf/paint_manager.h" #include "pdf/paint_manager.h"
@@ -160,10 +161,16 @@ class PdfViewPluginBase : public PDFEngine::Client,
return notified_browser_about_unsupported_feature_; return notified_browser_about_unsupported_feature_;
} }
void InitializeEngineForTesting(std::unique_ptr<PDFiumEngine> engine);
void set_full_frame_for_testing(bool full_frame) { full_frame_ = full_frame; }
DocumentLoadState document_load_state_for_testing() const { DocumentLoadState document_load_state_for_testing() const {
return document_load_state_; return document_load_state_;
} }
bool edit_mode_for_testing() const { return edit_mode_; }
protected: protected:
struct BackgroundPart { struct BackgroundPart {
gfx::Rect location; gfx::Rect location;
@@ -173,9 +180,17 @@ class PdfViewPluginBase : public PDFEngine::Client,
PdfViewPluginBase(); PdfViewPluginBase();
~PdfViewPluginBase() override; ~PdfViewPluginBase() override;
// Initializes the main `PDFiumEngine` with `engine`. Any existing engine will // Performs initialization common to all implementations of this plugin.
// be replaced. `engine` must not be nullptr. // `engine` should be an appropriately-configured PDF engine, and
void InitializeEngine(std::unique_ptr<PDFiumEngine> engine); // `embedder_origin` should be the origin of the plugin's embedder. The other
// parameters come from the corresponding plugin attributes.
void InitializeBase(std::unique_ptr<PDFiumEngine> engine,
base::StringPiece embedder_origin,
base::StringPiece src_url,
base::StringPiece original_url,
bool full_frame,
SkColor background_color,
bool has_edits);
// Destroys the main `PDFiumEngine`. Subclasses should call this method in // Destroys the main `PDFiumEngine`. Subclasses should call this method in
// their destructor to ensure the engine is destroyed first. // their destructor to ensure the engine is destroyed first.
@@ -188,11 +203,9 @@ class PdfViewPluginBase : public PDFEngine::Client,
const PDFiumEngine* engine() const { return engine_.get(); } const PDFiumEngine* engine() const { return engine_.get(); }
PDFiumEngine* engine() { return engine_.get(); } PDFiumEngine* engine() { return engine_.get(); }
void ValidateDocumentUrl(base::StringPiece document_url);
// Starts loading `url`. If `is_print_preview` is `true`, load for print // Starts loading `url`. If `is_print_preview` is `true`, load for print
// preview instead of normal PDF viewing. // preview instead of normal PDF viewing.
void LoadUrl(const std::string& url, bool is_print_preview); void LoadUrl(base::StringPiece url, bool is_print_preview);
// Gets a weak pointer with a lifetime matching the derived class. // Gets a weak pointer with a lifetime matching the derived class.
virtual base::WeakPtr<PdfViewPluginBase> GetWeakPtr() = 0; virtual base::WeakPtr<PdfViewPluginBase> GetWeakPtr() = 0;
@@ -355,8 +368,6 @@ class PdfViewPluginBase : public PDFEngine::Client,
// Records user actions. // Records user actions.
virtual void UserMetricsRecordAction(const std::string& action) = 0; virtual void UserMetricsRecordAction(const std::string& action) = 0;
void set_url(const std::string& url) { url_ = url; }
ui::mojom::CursorType cursor_type() const { return cursor_type_; } ui::mojom::CursorType cursor_type() const { return cursor_type_; }
void set_cursor_type(ui::mojom::CursorType cursor_type) { void set_cursor_type(ui::mojom::CursorType cursor_type) {
cursor_type_ = cursor_type; cursor_type_ = cursor_type;
@@ -365,7 +376,6 @@ class PdfViewPluginBase : public PDFEngine::Client,
const std::string& link_under_cursor() const { return link_under_cursor_; } const std::string& link_under_cursor() const { return link_under_cursor_; }
bool full_frame() const { return full_frame_; } bool full_frame() const { return full_frame_; }
void set_full_frame(bool full_frame) { full_frame_ = full_frame; }
SkBitmap& mutable_image_data() { return image_data_; } SkBitmap& mutable_image_data() { return image_data_; }
@@ -375,10 +385,6 @@ class PdfViewPluginBase : public PDFEngine::Client,
const gfx::Rect& plugin_rect() const { return plugin_rect_; } const gfx::Rect& plugin_rect() const { return plugin_rect_; }
void SetBackgroundColor(SkColor background_color) {
background_color_ = background_color;
}
// Sets the new zoom scale. // Sets the new zoom scale.
void SetZoom(double scale); void SetZoom(double scale);
@@ -390,15 +396,6 @@ class PdfViewPluginBase : public PDFEngine::Client,
return accessibility_state_; return accessibility_state_;
} }
bool edit_mode() const { return edit_mode_; }
void set_edit_mode(bool edit_mode) { edit_mode_ = edit_mode; }
void set_is_print_preview(bool is_print_preview) {
is_print_preview_ = is_print_preview;
}
static bool IsPrintPreviewUrl(base::StringPiece url);
static constexpr bool IsSaveDataSizeValid(size_t size) { static constexpr bool IsSaveDataSizeValid(size_t size) {
return size > 0 && size <= kMaximumSavedFileSize; return size > 0 && size <= kMaximumSavedFileSize;
} }

@@ -136,13 +136,10 @@ class FakePdfViewPluginBase : public PdfViewPluginBase {
public: public:
// Public for testing. // Public for testing.
using PdfViewPluginBase::accessibility_state; using PdfViewPluginBase::accessibility_state;
using PdfViewPluginBase::edit_mode;
using PdfViewPluginBase::engine; using PdfViewPluginBase::engine;
using PdfViewPluginBase::full_frame; using PdfViewPluginBase::full_frame;
using PdfViewPluginBase::HandleMessage; using PdfViewPluginBase::HandleMessage;
using PdfViewPluginBase::InitializeEngine;
using PdfViewPluginBase::LoadUrl; using PdfViewPluginBase::LoadUrl;
using PdfViewPluginBase::set_full_frame;
using PdfViewPluginBase::SetZoom; using PdfViewPluginBase::SetZoom;
using PdfViewPluginBase::UpdateGeometryOnPluginRectChanged; using PdfViewPluginBase::UpdateGeometryOnPluginRectChanged;
using PdfViewPluginBase::UpdateScroll; using PdfViewPluginBase::UpdateScroll;
@@ -383,7 +380,7 @@ class PdfViewPluginBaseWithEngineTest : public PdfViewPluginBaseTest {
void SetUp() override { void SetUp() override {
auto engine = auto engine =
std::make_unique<testing::NiceMock<TestPDFiumEngine>>(&fake_plugin_); std::make_unique<testing::NiceMock<TestPDFiumEngine>>(&fake_plugin_);
fake_plugin_.InitializeEngine(std::move(engine)); fake_plugin_.InitializeEngineForTesting(std::move(engine));
} }
protected: protected:
@@ -417,7 +414,7 @@ class PdfViewPluginBaseWithDocInfoTest
void SetUp() override { void SetUp() override {
std::unique_ptr<TestPDFiumEngineWithDocInfo> engine = std::unique_ptr<TestPDFiumEngineWithDocInfo> engine =
std::make_unique<TestPDFiumEngineWithDocInfo>(&fake_plugin_); std::make_unique<TestPDFiumEngineWithDocInfo>(&fake_plugin_);
fake_plugin_.InitializeEngine(std::move(engine)); fake_plugin_.InitializeEngineForTesting(std::move(engine));
// Initialize some arbitrary document information for the engine. // Initialize some arbitrary document information for the engine.
static_cast<TestPDFiumEngineWithDocInfo*>(fake_plugin_.engine()) static_cast<TestPDFiumEngineWithDocInfo*>(fake_plugin_.engine())
@@ -499,7 +496,7 @@ TEST_F(PdfViewPluginBaseTest, DocumentLoadProgressResetByLoadUrl) {
} }
TEST_F(PdfViewPluginBaseTest, CreateUrlLoaderInFullFrame) { TEST_F(PdfViewPluginBaseTest, CreateUrlLoaderInFullFrame) {
fake_plugin_.set_full_frame(true); fake_plugin_.set_full_frame_for_testing(true);
ASSERT_TRUE(fake_plugin_.full_frame()); ASSERT_TRUE(fake_plugin_.full_frame());
EXPECT_FALSE(fake_plugin_.GetDidCallStartLoadingForTesting()); EXPECT_FALSE(fake_plugin_.GetDidCallStartLoadingForTesting());
@@ -527,7 +524,7 @@ TEST_F(PdfViewPluginBaseTest, CreateUrlLoaderWithoutFullFrame) {
TEST_F(PdfViewPluginBaseWithDocInfoTest, TEST_F(PdfViewPluginBaseWithDocInfoTest,
DocumentLoadCompleteInFullFramePdfViewerWithAccessibilityEnabled) { DocumentLoadCompleteInFullFramePdfViewerWithAccessibilityEnabled) {
// Notify the render frame about document loading. // Notify the render frame about document loading.
fake_plugin_.set_full_frame(true); fake_plugin_.set_full_frame_for_testing(true);
ASSERT_TRUE(fake_plugin_.full_frame()); ASSERT_TRUE(fake_plugin_.full_frame());
fake_plugin_.CreateUrlLoader(); fake_plugin_.CreateUrlLoader();
@@ -570,7 +567,7 @@ TEST_F(PdfViewPluginBaseWithDocInfoTest,
TEST_F(PdfViewPluginBaseWithDocInfoTest, TEST_F(PdfViewPluginBaseWithDocInfoTest,
DocumentLoadCompleteInFullFramePdfViewerWithAccessibilityDisabled) { DocumentLoadCompleteInFullFramePdfViewerWithAccessibilityDisabled) {
// Notify the render frame about document loading. // Notify the render frame about document loading.
fake_plugin_.set_full_frame(true); fake_plugin_.set_full_frame_for_testing(true);
ASSERT_TRUE(fake_plugin_.full_frame()); ASSERT_TRUE(fake_plugin_.full_frame());
fake_plugin_.CreateUrlLoader(); fake_plugin_.CreateUrlLoader();
@@ -663,7 +660,7 @@ TEST_F(PdfViewPluginBaseWithoutDocInfoTest, DocumentLoadCompletePostMessages) {
TEST_F(PdfViewPluginBaseTest, DocumentLoadFailedWithNotifiedRenderFrame) { TEST_F(PdfViewPluginBaseTest, DocumentLoadFailedWithNotifiedRenderFrame) {
// Notify the render frame about document loading. // Notify the render frame about document loading.
fake_plugin_.set_full_frame(true); fake_plugin_.set_full_frame_for_testing(true);
ASSERT_TRUE(fake_plugin_.full_frame()); ASSERT_TRUE(fake_plugin_.full_frame());
fake_plugin_.CreateUrlLoader(); fake_plugin_.CreateUrlLoader();
@@ -697,7 +694,7 @@ TEST_F(PdfViewPluginBaseTest, DocumentLoadFailedWithoutNotifiedRenderFrame) {
} }
TEST_F(PdfViewPluginBaseTest, DocumentHasUnsupportedFeatureInFullFrame) { TEST_F(PdfViewPluginBaseTest, DocumentHasUnsupportedFeatureInFullFrame) {
fake_plugin_.set_full_frame(true); fake_plugin_.set_full_frame_for_testing(true);
ASSERT_TRUE(fake_plugin_.full_frame()); ASSERT_TRUE(fake_plugin_.full_frame());
// Arbitrary feature names and their matching metric names. // Arbitrary feature names and their matching metric names.
@@ -763,7 +760,7 @@ TEST_F(PdfViewPluginBaseTest, EnteredEditMode) {
base::Value expected_response(base::Value::Type::DICTIONARY); base::Value expected_response(base::Value::Type::DICTIONARY);
expected_response.SetStringKey("type", "setIsEditing"); expected_response.SetStringKey("type", "setIsEditing");
EXPECT_TRUE(fake_plugin_.edit_mode()); EXPECT_TRUE(fake_plugin_.edit_mode_for_testing());
ASSERT_EQ(1u, fake_plugin_.sent_messages().size()); ASSERT_EQ(1u, fake_plugin_.sent_messages().size());
EXPECT_EQ(expected_response, fake_plugin_.sent_messages()[0]); EXPECT_EQ(expected_response, fake_plugin_.sent_messages()[0]);
} }
@@ -772,7 +769,7 @@ using PdfViewPluginBaseSaveTest = PdfViewPluginBaseWithEngineTest;
#if BUILDFLAG(ENABLE_INK) #if BUILDFLAG(ENABLE_INK)
TEST_F(PdfViewPluginBaseSaveTest, SaveAnnotationInNonEditMode) { TEST_F(PdfViewPluginBaseSaveTest, SaveAnnotationInNonEditMode) {
ASSERT_FALSE(fake_plugin_.edit_mode()); ASSERT_FALSE(fake_plugin_.edit_mode_for_testing());
static constexpr char kSaveAnnotInNonEditModeToken[] = static constexpr char kSaveAnnotInNonEditModeToken[] =
"save-annot-in-non-edit-mode-token"; "save-annot-in-non-edit-mode-token";
@@ -791,7 +788,7 @@ TEST_F(PdfViewPluginBaseSaveTest, SaveAnnotationInNonEditMode) {
TEST_F(PdfViewPluginBaseSaveTest, SaveAnnotationInEditMode) { TEST_F(PdfViewPluginBaseSaveTest, SaveAnnotationInEditMode) {
fake_plugin_.EnteredEditMode(); fake_plugin_.EnteredEditMode();
ASSERT_TRUE(fake_plugin_.edit_mode()); ASSERT_TRUE(fake_plugin_.edit_mode_for_testing());
static constexpr char kSaveAnnotInEditModeToken[] = static constexpr char kSaveAnnotInEditModeToken[] =
"save-annot-in-edit-mode-token"; "save-annot-in-edit-mode-token";
@@ -810,7 +807,7 @@ TEST_F(PdfViewPluginBaseSaveTest, SaveAnnotationInEditMode) {
#endif // BUILDFLAG(ENABLE_INK) #endif // BUILDFLAG(ENABLE_INK)
TEST_F(PdfViewPluginBaseSaveTest, SaveOriginalInNonEditMode) { TEST_F(PdfViewPluginBaseSaveTest, SaveOriginalInNonEditMode) {
ASSERT_FALSE(fake_plugin_.edit_mode()); ASSERT_FALSE(fake_plugin_.edit_mode_for_testing());
static constexpr char kSaveOriginalInNonEditModeToken[] = static constexpr char kSaveOriginalInNonEditModeToken[] =
"save-original-in-non-edit-mode-token"; "save-original-in-non-edit-mode-token";
@@ -831,7 +828,7 @@ TEST_F(PdfViewPluginBaseSaveTest, SaveOriginalInNonEditMode) {
TEST_F(PdfViewPluginBaseSaveTest, SaveOriginalInEditMode) { TEST_F(PdfViewPluginBaseSaveTest, SaveOriginalInEditMode) {
fake_plugin_.EnteredEditMode(); fake_plugin_.EnteredEditMode();
ASSERT_TRUE(fake_plugin_.edit_mode()); ASSERT_TRUE(fake_plugin_.edit_mode_for_testing());
static constexpr char kSaveOriginalInEditModeToken[] = static constexpr char kSaveOriginalInEditModeToken[] =
"save-original-in-edit-mode-token"; "save-original-in-edit-mode-token";
@@ -853,7 +850,7 @@ TEST_F(PdfViewPluginBaseSaveTest, SaveOriginalInEditMode) {
#if BUILDFLAG(ENABLE_INK) #if BUILDFLAG(ENABLE_INK)
TEST_F(PdfViewPluginBaseSaveTest, SaveEditedInNonEditMode) { TEST_F(PdfViewPluginBaseSaveTest, SaveEditedInNonEditMode) {
ASSERT_FALSE(fake_plugin_.edit_mode()); ASSERT_FALSE(fake_plugin_.edit_mode_for_testing());
static constexpr char kSaveEditedInNonEditModeToken[] = static constexpr char kSaveEditedInNonEditModeToken[] =
"save-edited-in-non-edit-mode"; "save-edited-in-non-edit-mode";
@@ -872,7 +869,7 @@ TEST_F(PdfViewPluginBaseSaveTest, SaveEditedInNonEditMode) {
TEST_F(PdfViewPluginBaseSaveTest, SaveEditedInEditMode) { TEST_F(PdfViewPluginBaseSaveTest, SaveEditedInEditMode) {
fake_plugin_.EnteredEditMode(); fake_plugin_.EnteredEditMode();
ASSERT_TRUE(fake_plugin_.edit_mode()); ASSERT_TRUE(fake_plugin_.edit_mode_for_testing());
static constexpr char kSaveEditedInEditModeToken[] = static constexpr char kSaveEditedInEditModeToken[] =
"save-edited-in-edit-mode-token"; "save-edited-in-edit-mode-token";

@@ -48,6 +48,7 @@
#include "third_party/blink/public/common/metrics/document_update_reason.h" #include "third_party/blink/public/common/metrics/document_update_reason.h"
#include "third_party/blink/public/mojom/input/focus_type.mojom-shared.h" #include "third_party/blink/public/mojom/input/focus_type.mojom-shared.h"
#include "third_party/blink/public/platform/web_input_event_result.h" #include "third_party/blink/public/platform/web_input_event_result.h"
#include "third_party/blink/public/platform/web_security_origin.h"
#include "third_party/blink/public/platform/web_string.h" #include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/platform/web_text_input_type.h" #include "third_party/blink/public/platform/web_text_input_type.h"
#include "third_party/blink/public/platform/web_url.h" #include "third_party/blink/public/platform/web_url.h"
@@ -57,6 +58,7 @@
#include "third_party/blink/public/web/web_associated_url_loader.h" #include "third_party/blink/public/web/web_associated_url_loader.h"
#include "third_party/blink/public/web/web_associated_url_loader_options.h" #include "third_party/blink/public/web/web_associated_url_loader_options.h"
#include "third_party/blink/public/web/web_document.h" #include "third_party/blink/public/web/web_document.h"
#include "third_party/blink/public/web/web_frame.h"
#include "third_party/blink/public/web/web_frame_widget.h" #include "third_party/blink/public/web/web_frame_widget.h"
#include "third_party/blink/public/web/web_local_frame.h" #include "third_party/blink/public/web/web_local_frame.h"
#include "third_party/blink/public/web/web_local_frame_client.h" #include "third_party/blink/public/web/web_local_frame_client.h"
@@ -65,6 +67,7 @@
#include "third_party/blink/public/web/web_print_preset_options.h" #include "third_party/blink/public/web/web_print_preset_options.h"
#include "third_party/blink/public/web/web_view.h" #include "third_party/blink/public/web/web_view.h"
#include "third_party/blink/public/web/web_widget.h" #include "third_party/blink/public/web/web_widget.h"
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkRect.h" #include "third_party/skia/include/core/SkRect.h"
#include "third_party/skia/include/core/SkRefCnt.h" #include "third_party/skia/include/core/SkRefCnt.h"
#include "ui/base/cursor/cursor.h" #include "ui/base/cursor/cursor.h"
@@ -220,6 +223,18 @@ class BlinkContainerWrapper final : public PdfViewWebPlugin::ContainerWrapper {
widget->UpdateSelectionBounds(); widget->UpdateSelectionBounds();
} }
std::string GetEmbedderOriginString() override {
auto* frame = GetFrame();
if (!frame)
return {};
auto* parent_frame = frame->Parent();
if (!parent_frame)
return {};
return GURL(parent_frame->GetSecurityOrigin().ToString().Utf8()).spec();
}
blink::WebLocalFrame* GetFrame() override { blink::WebLocalFrame* GetFrame() override {
return container_->GetDocument().GetFrame(); return container_->GetDocument().GetFrame();
} }
@@ -275,26 +290,15 @@ bool PdfViewWebPlugin::InitializeCommon(
std::unique_ptr<ContainerWrapper> container_wrapper, std::unique_ptr<ContainerWrapper> container_wrapper,
std::unique_ptr<PDFiumEngine> engine) { std::unique_ptr<PDFiumEngine> engine) {
container_wrapper_ = std::move(container_wrapper); container_wrapper_ = std::move(container_wrapper);
post_message_sender_.set_container(Container());
// Check if the PDF is being loaded in the PDF chrome extension. We only allow // Allow the plugin to handle touch events.
// the plugin to be loaded in the extension and print preview to avoid container_wrapper_->RequestTouchEventType(
// exposing sensitive APIs directly to external websites. blink::WebPluginContainer::kTouchEventRequestTypeRaw);
std::string document_url;
auto* container = Container();
if (container) {
GURL maybe_url(container->GetDocument().Url());
if (maybe_url.is_valid())
document_url = maybe_url.possibly_invalid_spec();
}
base::StringPiece document_url_piece(document_url);
set_is_print_preview(IsPrintPreviewUrl(document_url_piece));
// TODO(crbug.com/1123621): Consider calling ValidateDocumentUrl() or
// something like it once the process model has been finalized.
// Allow the plugin to handle find requests. // Allow the plugin to handle find requests.
if (container) if (Container())
container->UsePluginAsFindHandler(); Container()->UsePluginAsFindHandler();
absl::optional<ParsedParams> params = ParseWebPluginParams(initial_params_); absl::optional<ParsedParams> params = ParseWebPluginParams(initial_params_);
@@ -304,21 +308,19 @@ bool PdfViewWebPlugin::InitializeCommon(
if (!params.has_value()) if (!params.has_value())
return false; return false;
set_full_frame(params->full_frame);
if (params->background_color.has_value())
SetBackgroundColor(params->background_color.value());
PerProcessInitializer::GetInstance().Acquire(); PerProcessInitializer::GetInstance().Acquire();
InitializeEngine( // TODO(crbug.com/1257666): Implement "has-edits" support.
InitializeBase(
engine ? std::move(engine) engine ? std::move(engine)
: std::make_unique<PDFiumEngine>(this, params->script_option)); : std::make_unique<PDFiumEngine>(this, params->script_option),
LoadUrl(params->src_url, /*is_print_preview=*/false); /*embedder_origin=*/container_wrapper_->GetEmbedderOriginString(),
set_url(params->original_url); /*src_url=*/params->src_url,
post_message_sender_.set_container(Container()); /*original_url=*/params->original_url,
/*full_frame=*/params->full_frame,
container_wrapper_->RequestTouchEventType( /*background_color=*/
blink::WebPluginContainer::kTouchEventRequestTypeRaw); params->background_color.value_or(SK_ColorTRANSPARENT),
/*has_edits=*/false);
return true; return true;
} }
@@ -329,8 +331,8 @@ void PdfViewWebPlugin::Destroy() {
DestroyPreviewEngine(); DestroyPreviewEngine();
DestroyEngine(); DestroyEngine();
PerProcessInitializer::GetInstance().Release(); PerProcessInitializer::GetInstance().Release();
container_wrapper_.reset();
post_message_sender_.set_container(nullptr); post_message_sender_.set_container(nullptr);
container_wrapper_.reset();
} }
delete this; delete this;

@@ -8,6 +8,7 @@
#include <stdint.h> #include <stdint.h>
#include <memory> #include <memory>
#include <string>
#include <vector> #include <vector>
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
@@ -112,6 +113,9 @@ class PdfViewWebPlugin final : public PdfViewPluginBase,
// Notifies the frame widget about the selection bound change. // Notifies the frame widget about the selection bound change.
virtual void UpdateSelectionBounds() = 0; virtual void UpdateSelectionBounds() = 0;
// Gets the embedder's origin as a serialized string.
virtual std::string GetEmbedderOriginString() = 0;
// Returns the local frame to which the web plugin container belongs. // Returns the local frame to which the web plugin container belongs.
virtual blink::WebLocalFrame* GetFrame() = 0; virtual blink::WebLocalFrame* GetFrame() = 0;

@@ -182,6 +182,10 @@ class FakeContainerWrapper : public PdfViewWebPlugin::ContainerWrapper {
MOCK_METHOD(void, UpdateSelectionBounds, (), (override)); MOCK_METHOD(void, UpdateSelectionBounds, (), (override));
std::string GetEmbedderOriginString() override {
return "chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai/";
}
blink::WebLocalFrame* GetFrame() override { return nullptr; } blink::WebLocalFrame* GetFrame() override { return nullptr; }
blink::WebLocalFrameClient* GetWebLocalFrameClient() override { blink::WebLocalFrameClient* GetWebLocalFrameClient() override {