[unseasoned-pdf] Enter embedder's V8 isolate in PDFium callbacks
Chromium, which is PDFium's embedder, provides callbacks to the latter. It is possible for PDFium to enter its own isolate before calling one of these callbacks, further creating the possibility of Chromium calling v8::Isolate::GetCurrent() and getting PDFium's isolate. Capture Chromium's isolate prior to passing the callbacks to PDFium, and enter it within each of the callbacks. Fixed: 1252212 Change-Id: I1f5036ca1e52a2ae67745795501828cf8659f758 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3183825 Auto-Submit: Daniel Hosseinian <dhoss@chromium.org> Reviewed-by: Adam Klein <adamk@chromium.org> Reviewed-by: John Abd-El-Malek <jam@chromium.org> Reviewed-by: Lei Zhang <thestig@chromium.org> Commit-Queue: John Abd-El-Malek <jam@chromium.org> Cr-Commit-Position: refs/heads/main@{#928423}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
a75539bb07
commit
c1b0f7a47a
@ -175,6 +175,7 @@ if (enable_pdf) {
|
||||
public_deps = [
|
||||
"//printing/mojom",
|
||||
"//skia",
|
||||
"//v8",
|
||||
]
|
||||
|
||||
deps = [
|
||||
@ -507,6 +508,7 @@ if (enable_pdf) {
|
||||
"//ui/gfx:test_support",
|
||||
"//ui/gfx/geometry",
|
||||
"//ui/gfx/range",
|
||||
"//v8",
|
||||
]
|
||||
|
||||
if (v8_use_external_startup_data) {
|
||||
|
2
pdf/DEPS
2
pdf/DEPS
@ -14,7 +14,7 @@ include_rules = [
|
||||
"+ui/display",
|
||||
"+ui/events",
|
||||
"+ui/gfx",
|
||||
"+v8/include/v8.h"
|
||||
"+v8/include",
|
||||
]
|
||||
|
||||
specific_include_rules = {
|
||||
|
@ -2,5 +2,4 @@ include_rules = [
|
||||
"+components/services/font/public/cpp",
|
||||
"+third_party/pdfium/public",
|
||||
"+ui/gfx/codec",
|
||||
"+v8/include/cppgc/platform.h",
|
||||
]
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "pdf/pdfium/pdfium_form_filler.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
@ -18,8 +19,10 @@
|
||||
#include "pdf/pdf_features.h"
|
||||
#include "pdf/pdfium/pdfium_engine.h"
|
||||
#include "third_party/blink/public/common/input/web_input_event.h"
|
||||
#include "third_party/blink/public/web/blink.h"
|
||||
#include "third_party/pdfium/public/fpdf_annot.h"
|
||||
#include "ui/gfx/geometry/rect.h"
|
||||
#include "v8/include/v8-isolate.h"
|
||||
|
||||
namespace chrome_pdf {
|
||||
|
||||
@ -44,7 +47,7 @@ PDFiumFormFiller::ScriptOption PDFiumFormFiller::DefaultScriptOption() {
|
||||
|
||||
PDFiumFormFiller::PDFiumFormFiller(PDFiumEngine* engine,
|
||||
ScriptOption script_option)
|
||||
: engine_(engine), script_option_(script_option) {
|
||||
: engine_in_isolate_scope_factory_(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
|
||||
@ -132,7 +135,8 @@ void PDFiumFormFiller::Form_Invalidate(FPDF_FORMFILLINFO* param,
|
||||
double top,
|
||||
double right,
|
||||
double bottom) {
|
||||
PDFiumEngine* engine = GetEngine(param);
|
||||
EngineInIsolateScope engine_scope = GetEngineInIsolateScope(param);
|
||||
PDFiumEngine* engine = engine_scope.engine();
|
||||
int page_index = engine->GetVisiblePageIndex(page);
|
||||
if (page_index == -1) {
|
||||
// This can sometime happen when the page is closed because it went off
|
||||
@ -153,7 +157,8 @@ void PDFiumFormFiller::Form_OutputSelectedRect(FPDF_FORMFILLINFO* param,
|
||||
double top,
|
||||
double right,
|
||||
double bottom) {
|
||||
PDFiumEngine* engine = GetEngine(param);
|
||||
EngineInIsolateScope engine_scope = GetEngineInIsolateScope(param);
|
||||
PDFiumEngine* engine = engine_scope.engine();
|
||||
int page_index = engine->GetVisiblePageIndex(page);
|
||||
if (page_index == -1)
|
||||
return;
|
||||
@ -208,7 +213,8 @@ FPDF_SYSTEMTIME PDFiumFormFiller::Form_GetLocalTime(FPDF_FORMFILLINFO* param) {
|
||||
|
||||
// static
|
||||
void PDFiumFormFiller::Form_OnChange(FPDF_FORMFILLINFO* param) {
|
||||
PDFiumEngine* engine = GetEngine(param);
|
||||
EngineInIsolateScope engine_scope = GetEngineInIsolateScope(param);
|
||||
PDFiumEngine* engine = engine_scope.engine();
|
||||
engine->EnteredEditMode();
|
||||
}
|
||||
|
||||
@ -216,7 +222,8 @@ void PDFiumFormFiller::Form_OnChange(FPDF_FORMFILLINFO* param) {
|
||||
FPDF_PAGE PDFiumFormFiller::Form_GetPage(FPDF_FORMFILLINFO* param,
|
||||
FPDF_DOCUMENT document,
|
||||
int page_index) {
|
||||
PDFiumEngine* engine = GetEngine(param);
|
||||
EngineInIsolateScope engine_scope = GetEngineInIsolateScope(param);
|
||||
PDFiumEngine* engine = engine_scope.engine();
|
||||
if (!engine->PageIndexInBounds(page_index))
|
||||
return nullptr;
|
||||
return engine->pages_[page_index]->GetPage();
|
||||
@ -225,7 +232,8 @@ FPDF_PAGE PDFiumFormFiller::Form_GetPage(FPDF_FORMFILLINFO* param,
|
||||
// static
|
||||
FPDF_PAGE PDFiumFormFiller::Form_GetCurrentPage(FPDF_FORMFILLINFO* param,
|
||||
FPDF_DOCUMENT document) {
|
||||
PDFiumEngine* engine = GetEngine(param);
|
||||
EngineInIsolateScope engine_scope = GetEngineInIsolateScope(param);
|
||||
PDFiumEngine* engine = engine_scope.engine();
|
||||
int index = engine->last_focused_page_;
|
||||
if (index == -1) {
|
||||
index = engine->GetMostVisiblePage();
|
||||
@ -246,7 +254,8 @@ int PDFiumFormFiller::Form_GetRotation(FPDF_FORMFILLINFO* param,
|
||||
// static
|
||||
void PDFiumFormFiller::Form_ExecuteNamedAction(FPDF_FORMFILLINFO* param,
|
||||
FPDF_BYTESTRING named_action) {
|
||||
PDFiumEngine* engine = GetEngine(param);
|
||||
EngineInIsolateScope engine_scope = GetEngineInIsolateScope(param);
|
||||
PDFiumEngine* engine = engine_scope.engine();
|
||||
std::string action(named_action);
|
||||
if (action == "Print") {
|
||||
engine->client_->Print();
|
||||
@ -293,7 +302,8 @@ void PDFiumFormFiller::Form_SetTextFieldFocus(FPDF_FORMFILLINFO* param,
|
||||
void PDFiumFormFiller::Form_OnFocusChange(FPDF_FORMFILLINFO* param,
|
||||
FPDF_ANNOTATION annot,
|
||||
int page_index) {
|
||||
PDFiumEngine* engine = GetEngine(param);
|
||||
EngineInIsolateScope engine_scope = GetEngineInIsolateScope(param);
|
||||
PDFiumEngine* engine = engine_scope.engine();
|
||||
if (!engine->PageIndexInBounds(page_index))
|
||||
return;
|
||||
|
||||
@ -308,7 +318,8 @@ void PDFiumFormFiller::Form_OnFocusChange(FPDF_FORMFILLINFO* param,
|
||||
// static
|
||||
void PDFiumFormFiller::Form_DoURIAction(FPDF_FORMFILLINFO* param,
|
||||
FPDF_BYTESTRING uri) {
|
||||
PDFiumEngine* engine = GetEngine(param);
|
||||
EngineInIsolateScope engine_scope = GetEngineInIsolateScope(param);
|
||||
PDFiumEngine* engine = engine_scope.engine();
|
||||
engine->client_->NavigateTo(std::string(uri),
|
||||
WindowOpenDisposition::CURRENT_TAB);
|
||||
}
|
||||
@ -319,7 +330,8 @@ void PDFiumFormFiller::Form_DoGoToAction(FPDF_FORMFILLINFO* param,
|
||||
int zoom_mode,
|
||||
float* position_array,
|
||||
int size_of_array) {
|
||||
PDFiumEngine* engine = GetEngine(param);
|
||||
EngineInIsolateScope engine_scope = GetEngineInIsolateScope(param);
|
||||
PDFiumEngine* engine = engine_scope.engine();
|
||||
engine->ScrollToPage(page_index);
|
||||
}
|
||||
|
||||
@ -328,7 +340,8 @@ void PDFiumFormFiller::Form_DoURIActionWithKeyboardModifier(
|
||||
FPDF_FORMFILLINFO* param,
|
||||
FPDF_BYTESTRING uri,
|
||||
int modifiers) {
|
||||
PDFiumEngine* engine = GetEngine(param);
|
||||
EngineInIsolateScope engine_scope = GetEngineInIsolateScope(param);
|
||||
PDFiumEngine* engine = engine_scope.engine();
|
||||
bool middle_button =
|
||||
!!(modifiers & blink::WebInputEvent::Modifiers::kMiddleButtonDown);
|
||||
bool alt_key = !!(modifiers & blink::WebInputEvent::Modifiers::kAltKey);
|
||||
@ -359,7 +372,8 @@ void PDFiumFormFiller::Form_EmailTo(FPDF_FORMFILLINFO* param,
|
||||
std::string bcc_str = WideStringToString(bcc);
|
||||
std::string message_str = WideStringToString(message);
|
||||
|
||||
PDFiumEngine* engine = GetEngine(param);
|
||||
EngineInIsolateScope engine_scope = GetEngineInIsolateScope(param);
|
||||
PDFiumEngine* engine = engine_scope.engine();
|
||||
engine->client_->Email(to_str, cc_str, bcc_str, subject_str, message_str);
|
||||
}
|
||||
|
||||
@ -376,14 +390,16 @@ void PDFiumFormFiller::Form_DisplayCaret(FPDF_FORMFILLINFO* param,
|
||||
void PDFiumFormFiller::Form_SetCurrentPage(FPDF_FORMFILLINFO* param,
|
||||
FPDF_DOCUMENT document,
|
||||
int page) {
|
||||
PDFiumEngine* engine = GetEngine(param);
|
||||
EngineInIsolateScope engine_scope = GetEngineInIsolateScope(param);
|
||||
PDFiumEngine* engine = engine_scope.engine();
|
||||
engine->ScrollToPage(page);
|
||||
}
|
||||
|
||||
// static
|
||||
int PDFiumFormFiller::Form_GetCurrentPageIndex(FPDF_FORMFILLINFO* param,
|
||||
FPDF_DOCUMENT document) {
|
||||
PDFiumEngine* engine = GetEngine(param);
|
||||
EngineInIsolateScope engine_scope = GetEngineInIsolateScope(param);
|
||||
PDFiumEngine* engine = engine_scope.engine();
|
||||
return engine->GetMostVisiblePage();
|
||||
}
|
||||
|
||||
@ -394,7 +410,8 @@ void PDFiumFormFiller::Form_GetPageViewRect(FPDF_FORMFILLINFO* param,
|
||||
double* top,
|
||||
double* right,
|
||||
double* bottom) {
|
||||
PDFiumEngine* engine = GetEngine(param);
|
||||
EngineInIsolateScope engine_scope = GetEngineInIsolateScope(param);
|
||||
PDFiumEngine* engine = engine_scope.engine();
|
||||
int page_index = engine->GetVisiblePageIndex(page);
|
||||
if (!engine->PageIndexInBounds(page_index)) {
|
||||
*left = 0;
|
||||
@ -473,7 +490,8 @@ void PDFiumFormFiller::Form_PageEvent(FPDF_FORMFILLINFO* param,
|
||||
DCHECK(event_type == FXFA_PAGEVIEWEVENT_POSTADDED ||
|
||||
event_type == FXFA_PAGEVIEWEVENT_POSTREMOVED);
|
||||
|
||||
PDFiumEngine* engine = GetEngine(param);
|
||||
EngineInIsolateScope engine_scope = GetEngineInIsolateScope(param);
|
||||
PDFiumEngine* engine = engine_scope.engine();
|
||||
engine->UpdatePageCount();
|
||||
}
|
||||
|
||||
@ -578,7 +596,8 @@ int PDFiumFormFiller::Form_Alert(IPDF_JSPLATFORM* param,
|
||||
ALERT_RESULT_YES
|
||||
};
|
||||
|
||||
PDFiumEngine* engine = GetEngine(param);
|
||||
EngineInIsolateScope engine_scope = GetEngineInIsolateScope(param);
|
||||
PDFiumEngine* engine = engine_scope.engine();
|
||||
std::string message_str = WideStringToString(message);
|
||||
if (type == ALERT_TYPE_OK) {
|
||||
engine->client_->Alert(message_str);
|
||||
@ -593,7 +612,8 @@ int PDFiumFormFiller::Form_Alert(IPDF_JSPLATFORM* param,
|
||||
|
||||
// static
|
||||
void PDFiumFormFiller::Form_Beep(IPDF_JSPLATFORM* param, int type) {
|
||||
PDFiumEngine* engine = GetEngine(param);
|
||||
EngineInIsolateScope engine_scope = GetEngineInIsolateScope(param);
|
||||
PDFiumEngine* engine = engine_scope.engine();
|
||||
engine->client_->Beep();
|
||||
}
|
||||
|
||||
@ -609,7 +629,8 @@ int PDFiumFormFiller::Form_Response(IPDF_JSPLATFORM* param,
|
||||
std::string question_str = WideStringToString(question);
|
||||
std::string default_str = WideStringToString(default_response);
|
||||
|
||||
PDFiumEngine* engine = GetEngine(param);
|
||||
EngineInIsolateScope engine_scope = GetEngineInIsolateScope(param);
|
||||
PDFiumEngine* engine = engine_scope.engine();
|
||||
std::string rv = engine->client_->Prompt(question_str, default_str);
|
||||
std::u16string rv_16 = base::UTF8ToUTF16(rv);
|
||||
int rv_bytes = rv_16.size() * sizeof(char16_t);
|
||||
@ -624,7 +645,8 @@ int PDFiumFormFiller::Form_Response(IPDF_JSPLATFORM* param,
|
||||
int PDFiumFormFiller::Form_GetFilePath(IPDF_JSPLATFORM* param,
|
||||
void* file_path,
|
||||
int length) {
|
||||
PDFiumEngine* engine = GetEngine(param);
|
||||
EngineInIsolateScope engine_scope = GetEngineInIsolateScope(param);
|
||||
PDFiumEngine* engine = engine_scope.engine();
|
||||
std::string rv = engine->client_->GetURL();
|
||||
if (file_path && rv.size() <= static_cast<size_t>(length))
|
||||
memcpy(file_path, rv.c_str(), rv.size());
|
||||
@ -649,7 +671,8 @@ void PDFiumFormFiller::Form_Mail(IPDF_JSPLATFORM* param,
|
||||
std::string subject_str = WideStringToString(subject);
|
||||
std::string message_str = WideStringToString(message);
|
||||
|
||||
PDFiumEngine* engine = GetEngine(param);
|
||||
EngineInIsolateScope engine_scope = GetEngineInIsolateScope(param);
|
||||
PDFiumEngine* engine = engine_scope.engine();
|
||||
engine->client_->Email(to_str, cc_str, bcc_str, subject_str, message_str);
|
||||
}
|
||||
|
||||
@ -665,7 +688,8 @@ void PDFiumFormFiller::Form_Print(IPDF_JSPLATFORM* param,
|
||||
FPDF_BOOL annotations) {
|
||||
// No way to pass the extra information to the print dialog using JavaScript.
|
||||
// Just opening it is fine for now.
|
||||
PDFiumEngine* engine = GetEngine(param);
|
||||
EngineInIsolateScope engine_scope = GetEngineInIsolateScope(param);
|
||||
PDFiumEngine* engine = engine_scope.engine();
|
||||
engine->client_->Print();
|
||||
}
|
||||
|
||||
@ -675,28 +699,67 @@ void PDFiumFormFiller::Form_SubmitForm(IPDF_JSPLATFORM* param,
|
||||
int length,
|
||||
FPDF_WIDESTRING url) {
|
||||
std::string url_str = WideStringToString(url);
|
||||
PDFiumEngine* engine = GetEngine(param);
|
||||
EngineInIsolateScope engine_scope = GetEngineInIsolateScope(param);
|
||||
PDFiumEngine* engine = engine_scope.engine();
|
||||
engine->client_->SubmitForm(url_str, form_data, length);
|
||||
}
|
||||
|
||||
// static
|
||||
void PDFiumFormFiller::Form_GotoPage(IPDF_JSPLATFORM* param, int page_number) {
|
||||
PDFiumEngine* engine = GetEngine(param);
|
||||
EngineInIsolateScope engine_scope = GetEngineInIsolateScope(param);
|
||||
PDFiumEngine* engine = engine_scope.engine();
|
||||
engine->ScrollToPage(page_number);
|
||||
}
|
||||
|
||||
#endif // defined(PDF_ENABLE_V8)
|
||||
|
||||
// static
|
||||
PDFiumEngine* PDFiumFormFiller::GetEngine(FPDF_FORMFILLINFO* info) {
|
||||
auto* form_filler = static_cast<PDFiumFormFiller*>(info);
|
||||
return form_filler->engine_;
|
||||
PDFiumFormFiller::EngineInIsolateScope::EngineInIsolateScope(
|
||||
PDFiumEngine* engine,
|
||||
v8::Isolate* isolate)
|
||||
: isolate_scope_(isolate ? std::make_unique<v8::Isolate::Scope>(isolate)
|
||||
: nullptr),
|
||||
engine_(engine) {
|
||||
DCHECK(engine_);
|
||||
}
|
||||
|
||||
PDFiumFormFiller::EngineInIsolateScope::EngineInIsolateScope(
|
||||
EngineInIsolateScope&&) = default;
|
||||
|
||||
PDFiumFormFiller::EngineInIsolateScope&
|
||||
PDFiumFormFiller::EngineInIsolateScope::operator=(EngineInIsolateScope&&) =
|
||||
default;
|
||||
|
||||
PDFiumFormFiller::EngineInIsolateScope::~EngineInIsolateScope() = default;
|
||||
|
||||
PDFiumFormFiller::EngineInIsolateScopeFactory::EngineInIsolateScopeFactory(
|
||||
PDFiumEngine* engine)
|
||||
: engine_(engine), callback_isolate_(v8::Isolate::TryGetCurrent()) {
|
||||
if (callback_isolate_)
|
||||
CHECK_EQ(blink::MainThreadIsolate(), callback_isolate_);
|
||||
}
|
||||
|
||||
PDFiumFormFiller::EngineInIsolateScopeFactory::~EngineInIsolateScopeFactory() =
|
||||
default;
|
||||
|
||||
PDFiumFormFiller::EngineInIsolateScope
|
||||
PDFiumFormFiller::EngineInIsolateScopeFactory::GetEngineInIsolateScope() const {
|
||||
return EngineInIsolateScope(engine_, callback_isolate_);
|
||||
}
|
||||
|
||||
// static
|
||||
PDFiumEngine* PDFiumFormFiller::GetEngine(IPDF_JSPLATFORM* platform) {
|
||||
PDFiumFormFiller::EngineInIsolateScope
|
||||
PDFiumFormFiller::GetEngineInIsolateScope(FPDF_FORMFILLINFO* info) {
|
||||
auto* form_filler = static_cast<PDFiumFormFiller*>(info);
|
||||
return form_filler->engine_in_isolate_scope_factory_
|
||||
.GetEngineInIsolateScope();
|
||||
}
|
||||
|
||||
// static
|
||||
PDFiumFormFiller::EngineInIsolateScope
|
||||
PDFiumFormFiller::GetEngineInIsolateScope(IPDF_JSPLATFORM* platform) {
|
||||
auto* form_filler = static_cast<PDFiumFormFiller*>(platform);
|
||||
return form_filler->engine_;
|
||||
return form_filler->engine_in_isolate_scope_factory_
|
||||
.GetEngineInIsolateScope();
|
||||
}
|
||||
|
||||
int PDFiumFormFiller::SetTimer(const base::TimeDelta& delay,
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "base/timer/timer.h"
|
||||
#include "third_party/pdfium/public/fpdf_formfill.h"
|
||||
#include "third_party/pdfium/public/fpdfview.h"
|
||||
#include "v8/include/v8-isolate.h"
|
||||
|
||||
namespace chrome_pdf {
|
||||
|
||||
@ -189,13 +190,53 @@ class PDFiumFormFiller : public FPDF_FORMFILLINFO, public IPDF_JSPLATFORM {
|
||||
static void Form_GotoPage(IPDF_JSPLATFORM* param, int page_number);
|
||||
#endif // defined(PDF_ENABLE_V8)
|
||||
|
||||
static PDFiumEngine* GetEngine(FPDF_FORMFILLINFO* info);
|
||||
static PDFiumEngine* GetEngine(IPDF_JSPLATFORM* platform);
|
||||
// A utility class that helps in enforcing accesses of `PDFiumEngine` within a
|
||||
// given `v8::Isolate`. The entries of the isolates are scoped to the
|
||||
// lifetimes of its instances. This class is tolerant of null isolates.
|
||||
class EngineInIsolateScope {
|
||||
public:
|
||||
EngineInIsolateScope(PDFiumEngine* engine, v8::Isolate* isolate);
|
||||
EngineInIsolateScope(EngineInIsolateScope&&);
|
||||
EngineInIsolateScope& operator=(EngineInIsolateScope&&);
|
||||
~EngineInIsolateScope();
|
||||
|
||||
PDFiumEngine* engine() { return engine_; }
|
||||
|
||||
private:
|
||||
std::unique_ptr<v8::Isolate::Scope> isolate_scope_;
|
||||
PDFiumEngine* engine_;
|
||||
};
|
||||
|
||||
class EngineInIsolateScopeFactory {
|
||||
public:
|
||||
explicit EngineInIsolateScopeFactory(PDFiumEngine* engine);
|
||||
EngineInIsolateScopeFactory(const EngineInIsolateScope&) = delete;
|
||||
EngineInIsolateScopeFactory& operator=(
|
||||
const EngineInIsolateScopeFactory&&) = delete;
|
||||
~EngineInIsolateScopeFactory();
|
||||
|
||||
// Retrieves `engine_` while attempting to enter `callback_isolate_`.
|
||||
EngineInIsolateScope GetEngineInIsolateScope() const;
|
||||
|
||||
private:
|
||||
PDFiumEngine* const engine_;
|
||||
|
||||
// The V8 isolate to enter inside callbacks from PDFium. Can be `nullptr`
|
||||
// because indirect callers of `PDFiumFormFiller` might not be embedding V8
|
||||
// separately. This can happen in utility processes (through callers of
|
||||
// //pdf/pdf.h) and in Pepper plugin processes.
|
||||
v8::Isolate* const callback_isolate_;
|
||||
};
|
||||
|
||||
// Gets an `EngineInIsolateScope` using `engine_in_isolate_scope_factory_`.
|
||||
static EngineInIsolateScope GetEngineInIsolateScope(FPDF_FORMFILLINFO* info);
|
||||
static EngineInIsolateScope GetEngineInIsolateScope(
|
||||
IPDF_JSPLATFORM* platform);
|
||||
|
||||
int SetTimer(const base::TimeDelta& delay, TimerCallback timer_func);
|
||||
void KillTimer(int timer_id);
|
||||
|
||||
PDFiumEngine* const engine_;
|
||||
const EngineInIsolateScopeFactory engine_in_isolate_scope_factory_;
|
||||
const ScriptOption script_option_;
|
||||
std::map<int, std::unique_ptr<base::RepeatingTimer>> timers_;
|
||||
};
|
||||
|
@ -2,22 +2,29 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "pdf/pdfium/pdfium_form_filler.h"
|
||||
|
||||
#include "base/threading/thread_task_runner_handle.h"
|
||||
#include "build/build_config.h"
|
||||
#include "gin/public/isolate_holder.h"
|
||||
#include "pdf/pdfium/pdfium_engine.h"
|
||||
#include "pdf/pdfium/pdfium_test_base.h"
|
||||
#include "pdf/test/test_client.h"
|
||||
#include "testing/gmock/include/gmock/gmock.h"
|
||||
#include "third_party/blink/public/common/input/web_input_event.h"
|
||||
#include "third_party/blink/public/web/blink.h"
|
||||
#include "third_party/pdfium/public/fpdf_annot.h"
|
||||
#include "third_party/pdfium/public/fpdf_formfill.h"
|
||||
#include "ui/gfx/geometry/point.h"
|
||||
#include "ui/gfx/geometry/size.h"
|
||||
|
||||
using testing::InSequence;
|
||||
#include "v8/include/v8-isolate.h"
|
||||
|
||||
namespace chrome_pdf {
|
||||
|
||||
namespace {
|
||||
|
||||
using ::testing::InSequence;
|
||||
|
||||
class FormFillerTestClient : public TestClient {
|
||||
public:
|
||||
FormFillerTestClient() = default;
|
||||
@ -26,6 +33,7 @@ class FormFillerTestClient : public TestClient {
|
||||
FormFillerTestClient& operator=(const FormFillerTestClient&) = delete;
|
||||
|
||||
// Mock PDFEngine::Client methods.
|
||||
MOCK_METHOD(void, Beep, (), (override));
|
||||
MOCK_METHOD(void, ScrollToX, (int), (override));
|
||||
MOCK_METHOD(void, ScrollToY, (int), (override));
|
||||
MOCK_METHOD(void,
|
||||
@ -58,6 +66,12 @@ class FormFillerTest : public PDFiumTestBase {
|
||||
engine->form_filler_.Form_DoURIActionWithKeyboardModifier(
|
||||
&engine->form_filler_, uri, modifiers);
|
||||
}
|
||||
|
||||
void TriggerBeep(PDFiumEngine* engine) {
|
||||
ASSERT_TRUE(engine);
|
||||
engine->form_filler_.Form_Beep(&engine->form_filler_,
|
||||
JSPLATFORM_BEEP_DEFAULT);
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(FormFillerTest, DoURIActionWithKeyboardModifier) {
|
||||
@ -161,4 +175,40 @@ TEST_F(FormFillerTest, FormOnFocusChange) {
|
||||
}
|
||||
}
|
||||
|
||||
class FormFillerIsolateTest : public FormFillerTest {
|
||||
public:
|
||||
FormFillerIsolateTest() {
|
||||
// Needed for setting up V8.
|
||||
InitializeSDK(/*enable_v8=*/true, FontMappingMode::kNoMapping);
|
||||
}
|
||||
|
||||
~FormFillerIsolateTest() override { ShutdownSDK(); }
|
||||
};
|
||||
|
||||
TEST_F(FormFillerIsolateTest, IsolateScoping) {
|
||||
// Enter the embedder's isolate so it can be captured when the
|
||||
// `PDFiumFormFiller` is created.
|
||||
v8::Isolate* embedder_isolate = blink::MainThreadIsolate();
|
||||
v8::Isolate::Scope embedder_isolate_scope(embedder_isolate);
|
||||
|
||||
FormFillerTestClient client;
|
||||
PDFiumEngine engine(&client, PDFiumFormFiller::ScriptOption::kJavaScript);
|
||||
|
||||
gin::IsolateHolder pdfium_test_isolate_holder(
|
||||
base::ThreadTaskRunnerHandle::Get(),
|
||||
gin::IsolateHolder::IsolateType::kTest);
|
||||
v8::Isolate* pdfium_test_isolate = pdfium_test_isolate_holder.isolate();
|
||||
|
||||
// Enter PDFium's isolate and then trigger a beep callback. The embedder's
|
||||
// isolate should be entered during the callback's execution.
|
||||
v8::Isolate::Scope pdfium_test_isolate_scope(pdfium_test_isolate);
|
||||
EXPECT_CALL(client, Beep).WillOnce([&embedder_isolate]() {
|
||||
EXPECT_EQ(v8::Isolate::TryGetCurrent(), embedder_isolate);
|
||||
});
|
||||
TriggerBeep(&engine);
|
||||
|
||||
// PDFium's isolate should be entered again after the callback completes.
|
||||
EXPECT_EQ(v8::Isolate::TryGetCurrent(), pdfium_test_isolate);
|
||||
}
|
||||
|
||||
} // namespace chrome_pdf
|
||||
|
Reference in New Issue
Block a user