summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Sepez <tsepez@chromium.org>2015-06-02 16:51:07 -0700
committerTom Sepez <tsepez@chromium.org>2015-06-02 16:51:07 -0700
commita76f557650dfc95cae5f535d4a1b627a84d2b5f0 (patch)
tree40de9a298f1e02774dcb6cfb303d629bc97a7ec4
parentb29338d126125d96d63817af1d80a64ea929ffae (diff)
downloadpdfium-a76f557650dfc95cae5f535d4a1b627a84d2b5f0.tar.xz
Automated test case for 487928.
Reproducing this bug requires the embedder to fire timers, something the single-pass pdfium-test binary doesn't do properly at the present. So we modify the embedder test delegate to allow the immediate triggering of the same. Perform some cleanup along the way by removing EmbedderTestDefaultDelegate -- it buys us nothing over the the no-op one. And, of course, v8 initialization is busted again, and we need v8 here. R=thestig@chromium.org Review URL: https://codereview.chromium.org/1153213004
-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