summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--BUILD.gn8
-rw-r--r--fpdfsdk/src/fpdfformfill_embeddertest.cpp15
-rw-r--r--pdfium.gyp5
-rw-r--r--testing/embedder_test.cpp82
-rw-r--r--testing/embedder_test.h11
-rw-r--r--testing/embedder_test_mock_delegate.h2
-rw-r--r--testing/embedder_test_timer_handling_delegate.h54
-rw-r--r--testing/resources/bug_487928.in122
-rw-r--r--testing/resources/bug_487928.pdf180
9 files changed, 421 insertions, 58 deletions
diff --git a/BUILD.gn b/BUILD.gn
index 4074c75b8e..bab57b906b 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -886,15 +886,21 @@ test("pdfium_embeddertests") {
"testing/embedder_test.cpp",
"testing/embedder_test.h",
"testing/embedder_test_mock_delegate.h",
+ "testing/embedder_test_timer_handling_delegate.h",
"testing/fx_string_testhelpers.cpp",
"testing/fx_string_testhelpers.h",
]
deps = [
"//testing/gmock",
"//testing/gtest",
+ "//v8:v8_libplatform",
":pdfium",
]
- include_dirs = [ "." ]
+ include_dirs = [
+ "//v8",
+ "//v8/include",
+ "."
+ ]
configs -= [ "//build/config/compiler:chromium_code" ]
configs += [
":pdfium_config",
diff --git a/fpdfsdk/src/fpdfformfill_embeddertest.cpp b/fpdfsdk/src/fpdfformfill_embeddertest.cpp
index b4cc111a00..615ada99f9 100644
--- a/fpdfsdk/src/fpdfformfill_embeddertest.cpp
+++ b/fpdfsdk/src/fpdfformfill_embeddertest.cpp
@@ -6,6 +6,7 @@
#include "../../public/fpdf_formfill.h"
#include "../../testing/embedder_test.h"
#include "../../testing/embedder_test_mock_delegate.h"
+#include "../../testing/embedder_test_timer_handling_delegate.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -19,6 +20,8 @@ TEST_F(FPDFFormFillEmbeddertest, FirstTest) {
EmbedderTestMockDelegate mock;
EXPECT_CALL(mock, Alert(_, _, _, _)).Times(0);
EXPECT_CALL(mock, UnsupportedHandler(_)).Times(0);
+ EXPECT_CALL(mock, SetTimer(_, _)).Times(0);
+ EXPECT_CALL(mock, KillTimer(_)).Times(0);
SetDelegate(&mock);
EXPECT_TRUE(OpenDocument("testing/resources/hello_world.pdf"));
@@ -26,3 +29,15 @@ TEST_F(FPDFFormFillEmbeddertest, FirstTest) {
EXPECT_NE(nullptr, page);
UnloadPage(page);
}
+
+TEST_F(FPDFFormFillEmbeddertest, BUG_487928) {
+ EmbedderTestTimerHandlingDelegate delegate;
+ SetDelegate(&delegate);
+
+ EXPECT_TRUE(OpenDocument("testing/resources/bug_487928.pdf"));
+ FPDF_PAGE page = LoadPage(0);
+ EXPECT_NE(nullptr, page);
+ DoOpenActions();
+ delegate.AdvanceTime(5000);
+ UnloadPage(page);
+}
diff --git a/pdfium.gyp b/pdfium.gyp
index 7f1d908b1c..c8215e7034 100644
--- a/pdfium.gyp
+++ b/pdfium.gyp
@@ -852,10 +852,12 @@
'dependencies': [
'<(DEPTH)/testing/gmock.gyp:gmock',
'<(DEPTH)/testing/gtest.gyp:gtest',
+ '<(DEPTH)/v8/tools/gyp/v8.gyp:v8_libplatform',
'pdfium',
],
'include_dirs': [
- '<(DEPTH)'
+ '<(DEPTH)',
+ '<(DEPTH)/v8',
],
'sources': [
'core/src/fpdfapi/fpdf_parser/fpdf_parser_decode_embeddertest.cpp',
@@ -870,6 +872,7 @@
'testing/embedder_test.cpp',
'testing/embedder_test.h',
'testing/embedder_test_mock_delegate.h',
+ 'testing/embedder_test_timer_handling_delegate.h',
'testing/fx_string_testhelpers.cpp',
'testing/fx_string_testhelpers.h',
],
diff --git a/testing/embedder_test.cpp b/testing/embedder_test.cpp
index 70c32af8c7..8457a79460 100644
--- a/testing/embedder_test.cpp
+++ b/testing/embedder_test.cpp
@@ -18,6 +18,7 @@
#include "../public/fpdf_text.h"
#include "../public/fpdfview.h"
#include "testing/gmock/include/gmock/gmock.h"
+#include "v8/include/libplatform/libplatform.h"
#include "v8/include/v8.h"
#ifdef _WIN32
@@ -94,58 +95,6 @@ static bool GetExternalData(const std::string& exe_path,
} // namespace
-class EmbedderTestDefaultDelegate : public EmbedderTest::Delegate {
- public:
- int Alert(FPDF_WIDESTRING, FPDF_WIDESTRING, int, int) override {
- printf("Form_Alert called.\n");
- return 0;
- }
-
- void UnsupportedHandler(int type) {
- std::string feature = "Unknown";
- switch (type) {
- case FPDF_UNSP_DOC_XFAFORM:
- feature = "XFA";
- break;
- case FPDF_UNSP_DOC_PORTABLECOLLECTION:
- feature = "Portfolios_Packages";
- break;
- case FPDF_UNSP_DOC_ATTACHMENT:
- case FPDF_UNSP_ANNOT_ATTACHMENT:
- feature = "Attachment";
- break;
- case FPDF_UNSP_DOC_SECURITY:
- feature = "Rights_Management";
- break;
- case FPDF_UNSP_DOC_SHAREDREVIEW:
- feature = "Shared_Review";
- break;
- case FPDF_UNSP_DOC_SHAREDFORM_ACROBAT:
- case FPDF_UNSP_DOC_SHAREDFORM_FILESYSTEM:
- case FPDF_UNSP_DOC_SHAREDFORM_EMAIL:
- feature = "Shared_Form";
- break;
- case FPDF_UNSP_ANNOT_3DANNOT:
- feature = "3D";
- break;
- case FPDF_UNSP_ANNOT_MOVIE:
- feature = "Movie";
- break;
- case FPDF_UNSP_ANNOT_SOUND:
- feature = "Sound";
- break;
- case FPDF_UNSP_ANNOT_SCREEN_MEDIA:
- case FPDF_UNSP_ANNOT_SCREEN_RICHMEDIA:
- feature = "Screen";
- break;
- case FPDF_UNSP_ANNOT_SIG:
- feature = "Digital_Signature";
- break;
- }
- printf("Unsupported feature: %s.\n", feature.c_str());
- }
-};
-
class TestLoader {
public:
TestLoader(const char* pBuf, size_t len);
@@ -183,7 +132,7 @@ EmbedderTest::EmbedderTest() :
memset(&hints_, 0, sizeof(hints_));
memset(&file_access_, 0, sizeof(file_access_));
memset(&file_avail_, 0, sizeof(file_avail_));
- default_delegate_ = new EmbedderTestDefaultDelegate();
+ default_delegate_ = new EmbedderTest::Delegate();
delegate_ = default_delegate_;
}
@@ -193,9 +142,15 @@ EmbedderTest::~EmbedderTest() {
void EmbedderTest::SetUp() {
v8::V8::InitializeICU();
- // By enabling predicatble mode, V8 won't post any background tasks.
+
+ platform_ = v8::platform::CreateDefaultPlatform();
+ v8::V8::InitializePlatform(platform_);
+ v8::V8::Initialize();
+
+ // By enabling predictable mode, V8 won't post any background tasks.
const char predictable_flag[] = "--predictable";
- v8::V8::SetFlagsFromString(predictable_flag, strlen(predictable_flag));
+ v8::V8::SetFlagsFromString(predictable_flag,
+ static_cast<int>(strlen(predictable_flag)));
#ifdef V8_USE_EXTERNAL_STARTUP_DATA
ASSERT_TRUE(GetExternalData(g_exe_path_, "natives_blob.bin", &natives_));
@@ -221,6 +176,8 @@ void EmbedderTest::TearDown() {
}
FPDFAvail_Destroy(avail_);
FPDF_DestroyLibrary();
+ v8::V8::ShutdownPlatform();
+ delete platform_;
delete loader_;
free(file_contents_);
}
@@ -262,6 +219,8 @@ bool EmbedderTest::OpenDocument(const std::string& filename) {
FPDF_FORMFILLINFO* formfillinfo = static_cast<FPDF_FORMFILLINFO*>(this);
memset(formfillinfo, 0, sizeof(FPDF_FORMFILLINFO));
formfillinfo->version = 1;
+ formfillinfo->FFI_SetTimer = SetTimerTrampoline;
+ formfillinfo->FFI_KillTimer = KillTimerTrampoline;
formfillinfo->m_pJsPlatform = platform;
form_handle_ = FPDFDOC_InitFormFillEnvironment(document_, formfillinfo);
@@ -333,6 +292,19 @@ int EmbedderTest::AlertTrampoline(IPDF_JSPLATFORM* platform,
return test->delegate_->Alert(message, title, type, icon);
}
+// static
+int EmbedderTest::SetTimerTrampoline(FPDF_FORMFILLINFO* info,
+ int msecs, TimerCallback fn) {
+ EmbedderTest* test = static_cast<EmbedderTest*>(info);
+ return test->delegate_->SetTimer(msecs, fn);
+}
+
+// static
+void EmbedderTest::KillTimerTrampoline(FPDF_FORMFILLINFO* info, int id) {
+ EmbedderTest* test = static_cast<EmbedderTest*>(info);
+ return test->delegate_->KillTimer(id);
+}
+
// Can't use gtest-provided main since we need to stash the path to the
// executable in order to find the external V8 binary data files.
int main(int argc, char** argv) {
diff --git a/testing/embedder_test.h b/testing/embedder_test.h
index 5cede6c6b4..b0834ddecd 100644
--- a/testing/embedder_test.h
+++ b/testing/embedder_test.h
@@ -36,6 +36,12 @@ class EmbedderTest : public ::testing::Test,
int type, int icon) {
return 0;
}
+
+ // Equivalent to FPDF_FORMFILLINFO::FFI_SetTimer().
+ virtual int SetTimer(int msecs, TimerCallback fn) { return 0; }
+
+ // Equivalent to FPDF_FORMFILLINFO::FFI_KillTimer().
+ virtual void KillTimer(int id) { }
};
EmbedderTest();
@@ -81,6 +87,7 @@ class EmbedderTest : public ::testing::Test,
FX_DOWNLOADHINTS hints_;
FPDF_FILEACCESS file_access_;
FX_FILEAVAIL file_avail_;
+ v8::Platform* platform_;
v8::StartupData natives_;
v8::StartupData snapshot_;
TestLoader* loader_;
@@ -91,7 +98,9 @@ class EmbedderTest : public ::testing::Test,
static void UnsupportedHandlerTrampoline(UNSUPPORT_INFO*, int type);
static int AlertTrampoline(IPDF_JSPLATFORM* plaform, FPDF_WIDESTRING message,
FPDF_WIDESTRING title, int type, int icon);
+ static int SetTimerTrampoline(FPDF_FORMFILLINFO* info, int msecs,
+ TimerCallback fn);
+ static void KillTimerTrampoline(FPDF_FORMFILLINFO* info, int id);
};
#endif // TESTING_EMBEDDER_TEST_H_
-
diff --git a/testing/embedder_test_mock_delegate.h b/testing/embedder_test_mock_delegate.h
index 526e11774e..1e4e99513d 100644
--- a/testing/embedder_test_mock_delegate.h
+++ b/testing/embedder_test_mock_delegate.h
@@ -13,6 +13,8 @@ class EmbedderTestMockDelegate : public EmbedderTest::Delegate {
MOCK_METHOD1(UnsupportedHandler, void(int type));
MOCK_METHOD4(Alert, int(FPDF_WIDESTRING message, FPDF_WIDESTRING title,
int type, int icon));
+ MOCK_METHOD2(SetTimer, int(int msecs, TimerCallback fn));
+ MOCK_METHOD1(KillTimer, void(int msecs));
};
#endif // TESTING_EMBEDDER_TEST_MOCK_DELEGATE_H_
diff --git a/testing/embedder_test_timer_handling_delegate.h b/testing/embedder_test_timer_handling_delegate.h
new file mode 100644
index 0000000000..d05a134b4e
--- /dev/null
+++ b/testing/embedder_test_timer_handling_delegate.h
@@ -0,0 +1,54 @@
+// Copyright 2015 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TESTING_EMBEDDER_TEST_TIMER_HANDLING_DELEGATE_H_
+#define TESTING_EMBEDDER_TEST_TIMER_HANDLING_DELEGATE_H_
+
+#include <map>
+#include <utility>
+
+#include "embedder_test.h"
+
+class EmbedderTestTimerHandlingDelegate : public EmbedderTest::Delegate {
+public:
+ int SetTimer(int msecs, TimerCallback fn) override {
+ expiry_to_timer_map_.insert(std::pair<int, Timer>(
+ msecs + imaginary_elapsed_msecs_, Timer(++next_timer_id_, fn)));
+ return next_timer_id_;
+ }
+
+ void KillTimer(int id) override {
+ for (auto iter = expiry_to_timer_map_.begin();
+ iter != expiry_to_timer_map_.end(); ++iter) {
+ if (iter->second.first == id) {
+ expiry_to_timer_map_.erase(iter);
+ break;
+ }
+ }
+ }
+
+ void AdvanceTime(int increment_msecs) {
+ imaginary_elapsed_msecs_ += increment_msecs;
+ while (1) {
+ auto iter = expiry_to_timer_map_.begin();
+ if (iter == expiry_to_timer_map_.end()) {
+ break;
+ }
+ Timer t = iter->second;
+ if (t.first > imaginary_elapsed_msecs_) {
+ break;
+ }
+ expiry_to_timer_map_.erase(iter);
+ t.second(t.first); // Fire timer.
+ }
+ }
+
+protected:
+ using Timer = std::pair<int, TimerCallback>; // ID, callback pair.
+ std::multimap<int, Timer> expiry_to_timer_map_; // Keyed by timeout.
+ int next_timer_id_ = 0;
+ int imaginary_elapsed_msecs_ = 0;
+};
+
+#endif // TESTING_EMBEDDER_TEST_TIMER_HANDLING_DELEGATE_H_
diff --git a/testing/resources/bug_487928.in b/testing/resources/bug_487928.in
new file mode 100644
index 0000000000..9f6d7f2bd1
--- /dev/null
+++ b/testing/resources/bug_487928.in
@@ -0,0 +1,122 @@
+{{header}}
+{{object 1 0}} <<
+ /Type /Catalog
+ /Pages 2 0 R
+ /AcroForm 6 0 R
+ /Names <</JavaScript 13 0 R>>
+>>
+endobj
+{{object 2 0}} <<
+ /Type /Pages
+ /Count 1
+ /Kids [4 0 R]
+>>
+endobj
+{{object 4 0}} <<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /CropBox [0 0 612 792]
+ /Resources <<>>
+ /Annots [5 0 R]
+>>
+endobj
+{{object 5 0}} <<
+ /FT /Tx
+ /Ff 29360128
+ /T (txtName)
+ /Type /Annot
+ /Subtype /Widget
+ /F 4
+ /M (D:20150514070426+05'30')
+ /Rect [180.279 715.6 256.186 744.072]
+ /BS <<
+ /W 1
+ /S /S
+ >>
+ /DA (/Helv 0 Tf 0 0 0 rg)
+ /AP <</N 8 0 R>>
+ /V ()
+ /AA 19 0 R
+>>
+endobj
+{{object 6 0}} <<
+ /DR <<
+ /Font <</Helv 7 0 R>>
+ >>
+ /DA (/Helv 0 Tf 0 g)
+ /Fields [5 0 R]
+>>
+endobj
+{{object 7 0}} <<
+ /Type /Font
+ /Subtype /Type1
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+>>
+endobj
+{{object 8 0}} <<
+ /Type /XObject
+ /Subtype /Form
+ /FormType 1
+ /Matrix [1 0 0 1 0 0]
+ /BBox [0 0 75.907 28.472]
+ /Resources <<
+ /Font <</FXF0 7 0 R>>
+ >>
+>>
+stream
+q
+Q
+
+
+endstream
+endobj
+{{object 11 0}} <<
+ /Type /Action
+ /S /JavaScript
+ /JS 50 0 R
+>>
+endobj
+{{object 13 0}} <<
+ /Names [(startDelay) 11 0 R]
+>>
+endobj
+{{object 19 0}} <<
+ /V 53 0 R
+>>
+endobj
+{{object 50 0}} <<
+>>
+stream
+function startDelay()
+{
+ f = this.getField("txtName");
+ f.delay = true;
+ f.value = 'test';
+ f.delay = false;
+}
+app.setTimeOut("startDelay()", 3000);
+endstream
+endobj
+{{object 53 0}} <<
+ /Type /Action
+ /S /JavaScript
+ /JS 54 0 R
+>>
+endobj
+{{object 54 0}} <<
+>>
+stream
+f1 = this.getField("txtName");
+f1.delay = true;
+f1.value = 'test new';
+f1.delay = false;
+endstream
+endobj
+{{xref}}
+trailer <<
+ /Root 1 0 R
+>>
+{{startxref}}
+%%EOF
diff --git a/testing/resources/bug_487928.pdf b/testing/resources/bug_487928.pdf
new file mode 100644
index 0000000000..dcfdebc1b0
--- /dev/null
+++ b/testing/resources/bug_487928.pdf
@@ -0,0 +1,180 @@
+%PDF-1.7
+% ò¤ô
+1 0 obj <<
+ /Type /Catalog
+ /Pages 2 0 R
+ /AcroForm 6 0 R
+ /Names <</JavaScript 13 0 R>>
+>>
+endobj
+2 0 obj <<
+ /Type /Pages
+ /Count 1
+ /Kids [4 0 R]
+>>
+endobj
+4 0 obj <<
+ /Type /Page
+ /Parent 2 0 R
+ /MediaBox [0 0 612 792]
+ /CropBox [0 0 612 792]
+ /Resources <<>>
+ /Annots [5 0 R]
+>>
+endobj
+5 0 obj <<
+ /FT /Tx
+ /Ff 29360128
+ /T (txtName)
+ /Type /Annot
+ /Subtype /Widget
+ /F 4
+ /M (D:20150514070426+05'30')
+ /Rect [180.279 715.6 256.186 744.072]
+ /BS <<
+ /W 1
+ /S /S
+ >>
+ /DA (/Helv 0 Tf 0 0 0 rg)
+ /AP <</N 8 0 R>>
+ /V ()
+ /AA 19 0 R
+>>
+endobj
+6 0 obj <<
+ /DR <<
+ /Font <</Helv 7 0 R>>
+ >>
+ /DA (/Helv 0 Tf 0 g)
+ /Fields [5 0 R]
+>>
+endobj
+7 0 obj <<
+ /Type /Font
+ /Subtype /Type1
+ /BaseFont /Helvetica
+ /Encoding /WinAnsiEncoding
+>>
+endobj
+8 0 obj <<
+ /Type /XObject
+ /Subtype /Form
+ /FormType 1
+ /Matrix [1 0 0 1 0 0]
+ /BBox [0 0 75.907 28.472]
+ /Resources <<
+ /Font <</FXF0 7 0 R>>
+ >>
+>>
+stream
+q
+Q
+
+
+endstream
+endobj
+11 0 obj <<
+ /Type /Action
+ /S /JavaScript
+ /JS 50 0 R
+>>
+endobj
+13 0 obj <<
+ /Names [(startDelay) 11 0 R]
+>>
+endobj
+19 0 obj <<
+ /V 53 0 R
+>>
+endobj
+50 0 obj <<
+>>
+stream
+function startDelay()
+{
+ f = this.getField("txtName");
+ f.delay = true;
+ f.value = 'test';
+ f.delay = false;
+}
+app.setTimeOut("startDelay()", 3000);
+endstream
+endobj
+53 0 obj <<
+ /Type /Action
+ /S /JavaScript
+ /JS 54 0 R
+>>
+endobj
+54 0 obj <<
+>>
+stream
+f1 = this.getField("txtName");
+f1.delay = true;
+f1.value = 'test new';
+f1.delay = false;
+endstream
+endobj
+xref
+0 55
+0000000000 65535 f
+0000000015 00000 n
+0000000118 00000 n
+0000000000 65535 f
+0000000181 00000 n
+0000000320 00000 n
+0000000595 00000 n
+0000000697 00000 n
+0000000802 00000 n
+0000000000 65535 f
+0000000000 65535 f
+0000000994 00000 n
+0000000000 65535 f
+0000001062 00000 n
+0000000000 65535 f
+0000000000 65535 f
+0000000000 65535 f
+0000000000 65535 f
+0000000000 65535 f
+0000001115 00000 n
+0000000000 65535 f
+0000000000 65535 f
+0000000000 65535 f
+0000000000 65535 f
+0000000000 65535 f
+0000000000 65535 f
+0000000000 65535 f
+0000000000 65535 f
+0000000000 65535 f
+0000000000 65535 f
+0000000000 65535 f
+0000000000 65535 f
+0000000000 65535 f
+0000000000 65535 f
+0000000000 65535 f
+0000000000 65535 f
+0000000000 65535 f
+0000000000 65535 f
+0000000000 65535 f
+0000000000 65535 f
+0000000000 65535 f
+0000000000 65535 f
+0000000000 65535 f
+0000000000 65535 f
+0000000000 65535 f
+0000000000 65535 f
+0000000000 65535 f
+0000000000 65535 f
+0000000000 65535 f
+0000000000 65535 f
+0000001149 00000 n
+0000000000 65535 f
+0000000000 65535 f
+0000001341 00000 n
+0000001409 00000 n
+trailer <<
+ /Root 1 0 R
+>>
+startxref
+1537
+%%EOF