0

Add foundations of enabling PDFium XFA at runtime.

Replace a boolean enabling javascript with a tri-state enum and
plumb through to the appropriate code.

No functional change yet introduced. Building with PDF_ENABLE_XFA
will still result in a chromium with XFA support fully enabled. We
do not yet ship chrome built with this option.

Bug: chromium:62400
Change-Id: Idbbc8de6033cf3ed90d3eb3ecbb9a2ef0a32b623
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2417091
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
Cr-Commit-Position: refs/heads/master@{#808446}
This commit is contained in:
Tom Sepez
2020-09-18 19:13:23 +00:00
committed by Commit Bot
parent 0e660dfe2c
commit cc750ee302
9 changed files with 67 additions and 48 deletions

@ -455,6 +455,14 @@ bool IsSaveDataSizeValid(size_t size) {
return size > 0 && size <= kMaximumSavedFileSize;
}
PDFiumFormFiller::ScriptOption DefaultScriptOption() {
#if defined(PDF_ENABLE_XFA)
return PDFiumFormFiller::ScriptOption::kJavaScriptAndXFA;
#else // defined(PDF_ENABLE_XFA)
return PDFiumFormFiller::ScriptOption::kJavaScript;
#endif // defined(PDF_ENABLE_XFA)
}
} // namespace
OutOfProcessInstance::OutOfProcessInstance(PP_Instance instance)
@ -512,7 +520,7 @@ bool OutOfProcessInstance::Init(uint32_t argc,
text_input_ = std::make_unique<pp::TextInput_Dev>(this);
bool enable_javascript = true;
PDFiumFormFiller::ScriptOption script_option = DefaultScriptOption();
bool has_edits = false;
const char* stream_url = nullptr;
const char* original_url = nullptr;
@ -534,8 +542,10 @@ bool OutOfProcessInstance::Init(uint32_t argc,
success =
base::StringToInt(argv[i], &top_toolbar_height_in_viewport_coords_);
} else if (strcmp(argn[i], "javascript") == 0) {
if (base::FeatureList::IsEnabled(features::kPdfHonorJsContentSettings))
enable_javascript = (strcmp(argv[i], "allow") == 0);
if (base::FeatureList::IsEnabled(features::kPdfHonorJsContentSettings)) {
if (strcmp(argv[i], "allow") != 0)
script_option = PDFiumFormFiller::ScriptOption::kNoJavaScript;
}
} else if (strcmp(argn[i], "has-edits") == 0) {
has_edits = true;
}
@ -549,7 +559,7 @@ bool OutOfProcessInstance::Init(uint32_t argc,
if (!stream_url)
stream_url = original_url;
InitializeEngine(enable_javascript);
InitializeEngine(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
@ -1092,9 +1102,8 @@ void OutOfProcessInstance::DidOpenPreview(std::unique_ptr<UrlLoader> loader,
int32_t result) {
if (result == PP_OK) {
preview_client_ = std::make_unique<PreviewModeClient>(this);
preview_engine_ =
std::make_unique<PDFiumEngine>(preview_client_.get(),
/*enable_javascript=*/false);
preview_engine_ = std::make_unique<PDFiumEngine>(
preview_client_.get(), PDFiumFormFiller::ScriptOption::kNoJavaScript);
preview_engine_->HandleDocumentLoad(std::move(loader));
} else {
NOTREACHED();
@ -1718,7 +1727,7 @@ void OutOfProcessInstance::HandleResetPrintPreviewModeMessage(
document_load_state_ = LOAD_STATE_LOADING;
LoadUrl(url_, /*is_print_preview=*/false);
preview_engine_.reset();
InitializeEngine(/*enable_javascript=*/false);
InitializeEngine(PDFiumFormFiller::ScriptOption::kNoJavaScript);
engine()->SetGrayscale(dict.Get(pp::Var(kJSPrintPreviewGrayscale)).AsBool());
engine()->New(url_.c_str(), /*headers=*/nullptr);

@ -20,8 +20,9 @@ PdfViewPluginBase::PdfViewPluginBase() = default;
PdfViewPluginBase::~PdfViewPluginBase() = default;
void PdfViewPluginBase::InitializeEngine(bool enable_javascript) {
engine_ = std::make_unique<PDFiumEngine>(this, enable_javascript);
void PdfViewPluginBase::InitializeEngine(
PDFiumFormFiller::ScriptOption script_option) {
engine_ = std::make_unique<PDFiumEngine>(this, script_option);
}
void PdfViewPluginBase::DestroyEngine() {

@ -13,6 +13,7 @@
#include <string>
#include "base/memory/weak_ptr.h"
#include "pdf/pdfium/pdfium_form_filler.h"
namespace chrome_pdf {
@ -30,11 +31,8 @@ class PdfViewPluginBase : public PDFEngine::Client {
PdfViewPluginBase();
~PdfViewPluginBase() override;
// Initializes the main `PDFiumEngine`. If `enable_javascript` is true, the
// engine will support executing JavaScript.
//
// Any existing engine will be replaced.
void InitializeEngine(bool enable_javascript);
// Initializes the main `PDFiumEngine`. Any existing engine will be replaced.
void InitializeEngine(PDFiumFormFiller::ScriptOption script_option);
// Destroys the main `PDFiumEngine`. Subclasses should call this method in
// their destructor to ensure the engine is destroyed first.

@ -109,7 +109,7 @@ bool PdfViewWebPlugin::Initialize(blink::WebPluginContainer* container) {
initial_params_ = {};
PerProcessInitializer::GetInstance().Acquire();
InitializeEngine(/*enable_javascript=*/false);
InitializeEngine(PDFiumFormFiller::ScriptOption::kNoJavaScript);
LoadUrl(stream_url, /*is_print_preview=*/false);
return true;
}

@ -458,14 +458,15 @@ PDFEngine::AccessibilityTextFieldInfo::AccessibilityTextFieldInfo(
PDFEngine::AccessibilityTextFieldInfo::~AccessibilityTextFieldInfo() = default;
PDFiumEngine::PDFiumEngine(PDFEngine::Client* client, bool enable_javascript)
PDFiumEngine::PDFiumEngine(PDFEngine::Client* client,
PDFiumFormFiller::ScriptOption script_option)
: client_(client),
form_filler_(this, enable_javascript),
form_filler_(this, script_option),
mouse_down_state_(PDFiumPage::NONSELECTABLE_AREA,
PDFiumPage::LinkTarget()),
print_(this) {
#if defined(PDF_ENABLE_V8)
if (enable_javascript)
if (script_option != PDFiumFormFiller::ScriptOption::kNoJavaScript)
DCHECK(IsV8Initialized());
#endif // defined(PDF_ENABLE_V8)
@ -2837,10 +2838,11 @@ void PDFiumEngine::LoadForm() {
ScopedUnsupportedFeature scoped_unsupported_feature(this);
document_->InitializeForm(&form_filler_);
}
#if defined(PDF_ENABLE_XFA)
FPDF_LoadXFA(doc());
#endif
if (form_filler_.script_option() ==
PDFiumFormFiller::ScriptOption::kJavaScriptAndXFA) {
FPDF_LoadXFA(doc());
}
FPDF_SetFormFieldHighlightColor(form(), FPDF_FORMFIELD_UNKNOWN,
kFormHighlightColor);
FPDF_SetFormFieldHighlightAlpha(form(), kFormHighlightAlpha);

@ -62,8 +62,9 @@ class PDFiumEngine : public PDFEngine,
// Exposed for testing.
enum class FocusElementType { kNone, kDocument, kPage };
// NOTE: |enable_javascript| is ignored when PDF_ENABLE_V8 is not defined.
PDFiumEngine(PDFEngine::Client* client, bool enable_javascript);
// NOTE: |script_option| is ignored when PDF_ENABLE_V8 is not defined.
PDFiumEngine(PDFEngine::Client* client,
PDFiumFormFiller::ScriptOption script_option);
PDFiumEngine(const PDFiumEngine&) = delete;
PDFiumEngine& operator=(const PDFiumEngine&) = delete;
~PDFiumEngine() override;

@ -28,8 +28,9 @@ std::string WideStringToString(FPDF_WIDESTRING wide_string) {
} // namespace
PDFiumFormFiller::PDFiumFormFiller(PDFiumEngine* engine, bool enable_javascript)
: engine_(engine) {
PDFiumFormFiller::PDFiumFormFiller(PDFiumEngine* engine,
ScriptOption script_option)
: engine_(engine), script_option_(script_option) {
// Initialize FPDF_FORMFILLINFO member variables. Deriving from this struct
// allows the static callbacks to be able to cast the FPDF_FORMFILLINFO in
// callbacks to ourself instead of maintaining a map of them to
@ -72,7 +73,7 @@ PDFiumFormFiller::PDFiumFormFiller(PDFiumEngine* engine, bool enable_javascript)
FPDF_FORMFILLINFO::m_pJsPlatform = nullptr;
#if defined(PDF_ENABLE_V8)
if (enable_javascript) {
if (script_option != ScriptOption::kNoJavaScript) {
FPDF_FORMFILLINFO::m_pJsPlatform = this;
IPDF_JSPLATFORM::version = 3;
IPDF_JSPLATFORM::app_alert = Form_Alert;
@ -86,22 +87,24 @@ PDFiumFormFiller::PDFiumFormFiller(PDFiumEngine* engine, bool enable_javascript)
IPDF_JSPLATFORM::Field_browse = nullptr;
}
#if defined(PDF_ENABLE_XFA)
FPDF_FORMFILLINFO::xfa_disabled = false;
FPDF_FORMFILLINFO::FFI_EmailTo = Form_EmailTo;
FPDF_FORMFILLINFO::FFI_DisplayCaret = Form_DisplayCaret;
FPDF_FORMFILLINFO::FFI_SetCurrentPage = Form_SetCurrentPage;
FPDF_FORMFILLINFO::FFI_GetCurrentPageIndex = Form_GetCurrentPageIndex;
FPDF_FORMFILLINFO::FFI_GetPageViewRect = Form_GetPageViewRect;
FPDF_FORMFILLINFO::FFI_GetPlatform = Form_GetPlatform;
FPDF_FORMFILLINFO::FFI_PageEvent = Form_PageEvent;
FPDF_FORMFILLINFO::FFI_PopupMenu = Form_PopupMenu;
FPDF_FORMFILLINFO::FFI_PostRequestURL = Form_PostRequestURL;
FPDF_FORMFILLINFO::FFI_PutRequestURL = Form_PutRequestURL;
FPDF_FORMFILLINFO::FFI_UploadTo = Form_UploadTo;
FPDF_FORMFILLINFO::FFI_DownloadFromURL = Form_DownloadFromURL;
FPDF_FORMFILLINFO::FFI_OpenFile = Form_OpenFile;
FPDF_FORMFILLINFO::FFI_GotoURL = Form_GotoURL;
FPDF_FORMFILLINFO::FFI_GetLanguage = Form_GetLanguage;
if (script_option == ScriptOption::kJavaScriptAndXFA) {
FPDF_FORMFILLINFO::xfa_disabled = false;
FPDF_FORMFILLINFO::FFI_EmailTo = Form_EmailTo;
FPDF_FORMFILLINFO::FFI_DisplayCaret = Form_DisplayCaret;
FPDF_FORMFILLINFO::FFI_SetCurrentPage = Form_SetCurrentPage;
FPDF_FORMFILLINFO::FFI_GetCurrentPageIndex = Form_GetCurrentPageIndex;
FPDF_FORMFILLINFO::FFI_GetPageViewRect = Form_GetPageViewRect;
FPDF_FORMFILLINFO::FFI_GetPlatform = Form_GetPlatform;
FPDF_FORMFILLINFO::FFI_PageEvent = Form_PageEvent;
FPDF_FORMFILLINFO::FFI_PopupMenu = Form_PopupMenu;
FPDF_FORMFILLINFO::FFI_PostRequestURL = Form_PostRequestURL;
FPDF_FORMFILLINFO::FFI_PutRequestURL = Form_PutRequestURL;
FPDF_FORMFILLINFO::FFI_UploadTo = Form_UploadTo;
FPDF_FORMFILLINFO::FFI_DownloadFromURL = Form_DownloadFromURL;
FPDF_FORMFILLINFO::FFI_OpenFile = Form_OpenFile;
FPDF_FORMFILLINFO::FFI_GotoURL = Form_GotoURL;
FPDF_FORMFILLINFO::FFI_GetLanguage = Form_GetLanguage;
}
#endif // defined(PDF_ENABLE_XFA)
#endif // defined(PDF_ENABLE_V8)
}

@ -19,12 +19,16 @@ class PDFiumEngine;
class PDFiumFormFiller : public FPDF_FORMFILLINFO, public IPDF_JSPLATFORM {
public:
// NOTE: |enable_javascript| is ignored when PDF_ENABLE_V8 is not defined.
PDFiumFormFiller(PDFiumEngine* engine, bool enable_javascript);
enum class ScriptOption { kNoJavaScript, kJavaScript, kJavaScriptAndXFA };
// NOTE: |script_option| is ignored when PDF_ENABLE_V8 is not defined.
PDFiumFormFiller(PDFiumEngine* engine, ScriptOption script_option);
PDFiumFormFiller(const PDFiumFormFiller&) = delete;
PDFiumFormFiller& operator=(const PDFiumFormFiller&) = delete;
~PDFiumFormFiller();
ScriptOption script_option() const { return script_option_; }
private:
friend class FormFillerTest;
@ -191,7 +195,7 @@ class PDFiumFormFiller : public FPDF_FORMFILLINFO, public IPDF_JSPLATFORM {
void KillTimer(int timer_id);
PDFiumEngine* const engine_;
const ScriptOption script_option_;
std::map<int, std::unique_ptr<base::RepeatingTimer>> timers_;
};

@ -12,6 +12,7 @@
#include "base/memory/scoped_refptr.h"
#include "build/build_config.h"
#include "pdf/pdfium/pdfium_engine.h"
#include "pdf/pdfium/pdfium_form_filler.h"
#include "pdf/ppapi_migration/url_loader.h"
#include "pdf/test/test_client.h"
#include "pdf/test/test_document_loader.h"
@ -85,8 +86,8 @@ PDFiumTestBase::InitializeEngineWithoutLoading(
const base::FilePath::CharType* pdf_name) {
InitializeEngineResult result;
result.engine =
std::make_unique<PDFiumEngine>(client, /*enable_javascript=*/false);
result.engine = std::make_unique<PDFiumEngine>(
client, PDFiumFormFiller::ScriptOption::kNoJavaScript);
client->set_engine(result.engine.get());
auto test_loader =