diff options
author | Tom Sepez <tsepez@chromium.org> | 2015-01-16 14:59:26 -0800 |
---|---|---|
committer | Tom Sepez <tsepez@chromium.org> | 2015-01-16 14:59:26 -0800 |
commit | 96d1334cb605aab143d3135da4d4550920735e91 (patch) | |
tree | 0a4371ef00759ce63cbb1324ef018b0311bcf84d | |
parent | a7f7a284393dbadeb1aaa861677570b61b9658ae (diff) | |
download | pdfium-96d1334cb605aab143d3135da4d4550920735e91.tar.xz |
Merge to XFA: PDFium embeddertests.
This consists of two origin/master CLs:
Review URL: https://codereview.chromium.org/857483005
Review URL: https://codereview.chromium.org/827733006
It also fixes a couple of segv's in XFA when the library is initialized and destroyed multiple times in the same process.
R=jam@chromium.org
TBR=jam@chromium.org
Review URL: https://codereview.chromium.org/856623004
-rw-r--r-- | fpdfsdk/src/fpdfview_embeddertest.cpp | 42 | ||||
-rw-r--r-- | pdfium.gyp | 19 | ||||
-rw-r--r-- | testing/embedder_test.cpp | 309 | ||||
-rw-r--r-- | testing/embedder_test.h | 82 | ||||
-rw-r--r-- | testing/resources/about_blank.pdf | bin | 0 -> 735 bytes | |||
-rw-r--r-- | xfa/src/fwl/src/core/fwl_appimp.cpp | 2 | ||||
-rw-r--r-- | xfa/src/fwl/src/core/fwl_noteimp.cpp | 19 | ||||
-rw-r--r-- | xfa/src/fwl/src/core/include/fwl_noteimp.h | 9 | ||||
-rw-r--r-- | xfa/src/fxjse/src/runtime.cpp | 10 |
9 files changed, 480 insertions, 12 deletions
diff --git a/fpdfsdk/src/fpdfview_embeddertest.cpp b/fpdfsdk/src/fpdfview_embeddertest.cpp new file mode 100644 index 0000000000..94a51094a8 --- /dev/null +++ b/fpdfsdk/src/fpdfview_embeddertest.cpp @@ -0,0 +1,42 @@ +// 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. + +#include "../../testing/embedder_test.h" +#include "testing/gtest/include/gtest/gtest.h" + +class FPDFViewEmbeddertest : public EmbedderTest { +}; + +TEST_F(FPDFViewEmbeddertest, Document) { + EXPECT_TRUE(OpenDocument("testing/resources/about_blank.pdf")); + EXPECT_EQ(1, GetPageCount()); + EXPECT_EQ(0, GetFirstPageNum()); + + int version; + EXPECT_TRUE(FPDF_GetFileVersion(document(), &version)); + EXPECT_EQ(14, version); + + EXPECT_EQ(0xFFFFFFFF, FPDF_GetDocPermissions(document())); + EXPECT_EQ(-1, FPDF_GetSecurityHandlerRevision(document())); +} + +TEST_F(FPDFViewEmbeddertest, Page) { + EXPECT_TRUE(OpenDocument("testing/resources/about_blank.pdf")); + FPDF_FORMHANDLE form_handle = SetFormFillEnvironment(); + FPDF_PAGE page = LoadPage(0, form_handle); + EXPECT_NE(nullptr, page); + EXPECT_EQ(612.0, FPDF_GetPageWidth(page)); + EXPECT_EQ(792.0, FPDF_GetPageHeight(page)); + UnloadPage(page, form_handle); + EXPECT_EQ(nullptr, LoadPage(1, form_handle)); + ClearFormFillEnvironment(form_handle); +} + +TEST_F(FPDFViewEmbeddertest, ViewerRef) { + EXPECT_TRUE(OpenDocument("testing/resources/about_blank.pdf")); + EXPECT_TRUE(FPDF_VIEWERREF_GetPrintScaling(document())); + EXPECT_EQ(1, FPDF_VIEWERREF_GetNumCopies(document())); + EXPECT_EQ(DuplexUndefined, FPDF_VIEWERREF_GetDuplex(document())); +} + diff --git a/pdfium.gyp b/pdfium.gyp index f52fd2dc64..6b8214e18c 100644 --- a/pdfium.gyp +++ b/pdfium.gyp @@ -908,5 +908,24 @@ 'xfa/src/fxbarcode/pdf417/BC_PDF417HighLevelEncoder_unittest.cpp', ], }, + { + 'target_name': 'pdfium_embeddertests', + 'type': 'executable', + 'dependencies': [ + '<(DEPTH)/testing/gtest.gyp:gtest_main', + '<(DEPTH)/testing/gtest.gyp:gtest', + 'pdfium', + ], + 'include_dirs': [ + '<(DEPTH)' + ], + 'sources': [ + 'fpdfsdk/src/fpdfview_embeddertest.cpp', + 'testing/embedder_test.cpp', + 'testing/embedder_test.h', + 'testing/fx_string_testhelpers.cpp', + 'testing/fx_string_testhelpers.h', + ], + }, ], } diff --git a/testing/embedder_test.cpp b/testing/embedder_test.cpp new file mode 100644 index 0000000000..539f48cff5 --- /dev/null +++ b/testing/embedder_test.cpp @@ -0,0 +1,309 @@ +// Copyright (c) 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. + +#include "embedder_test.h" + +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <list> +#include <string> +#include <utility> +#include <vector> + +#include "../fpdfsdk/include/fpdf_ext.h" +#include "../fpdfsdk/include/fpdftext.h" +#include "../fpdfsdk/include/fpdfview.h" +#include "../core/include/fxcrt/fx_system.h" +#include "v8/include/v8.h" + +#ifdef _WIN32 +#define snprintf _snprintf +#define PATH_SEPARATOR '\\' +#else +#define PATH_SEPARATOR '/' +#endif + +namespace { + +// Reads the entire contents of a file into a newly malloc'd buffer. +static char* GetFileContents(const char* filename, size_t* retlen) { + FILE* file = fopen(filename, "rb"); + if (!file) { + fprintf(stderr, "Failed to open: %s\n", filename); + return NULL; + } + (void) fseek(file, 0, SEEK_END); + size_t file_length = ftell(file); + if (!file_length) { + return NULL; + } + (void) fseek(file, 0, SEEK_SET); + char* buffer = (char*) malloc(file_length); + if (!buffer) { + return NULL; + } + size_t bytes_read = fread(buffer, 1, file_length, file); + (void) fclose(file); + if (bytes_read != file_length) { + fprintf(stderr, "Failed to read: %s\n", filename); + free(buffer); + return NULL; + } + *retlen = bytes_read; + return buffer; +} + +#ifdef V8_USE_EXTERNAL_STARTUP_DATA +// Returns the full path for an external V8 data file based on either +// the currect exectuable path or an explicit override. +static std::string GetFullPathForSnapshotFile(const Options& options, + const std::string& filename) { + std::string result; + if (!options.bin_directory.empty()) { + result = options.bin_directory; + if (*options.bin_directory.rbegin() != PATH_SEPARATOR) { + result += PATH_SEPARATOR; + } + } else if (!options.exe_path.empty()) { + size_t last_separator = options.exe_path.rfind(PATH_SEPARATOR); + if (last_separator != std::string::npos) { + result = options.exe_path.substr(0, last_separator + 1); + } + } + result += filename; + return result; +} + +// Reads an extenal V8 data file from the |options|-indicated location, +// returing true on success and false on error. +static bool GetExternalData(const Options& options, + const std::string& bin_filename, + v8::StartupData* result_data) { + std::string full_path = GetFullPathForSnapshotFile(options, bin_filename); + size_t data_length = 0; + char* data_buffer = GetFileContents(full_path.c_str(), &data_length); + if (!data_buffer) { + return false; + } + result_data->data = const_cast<const char*>(data_buffer); + result_data->raw_size = data_length; + return true; +} +#endif // V8_USE_EXTERNAL_STARTUP_DATA + +} // namespace + +int Form_Alert(IPDF_JSPLATFORM*, FPDF_WIDESTRING, FPDF_WIDESTRING, int, int) { + printf("Form_Alert called.\n"); + return 0; +} + +void Unsupported_Handler(UNSUPPORT_INFO*, 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); + + const char* m_pBuf; + size_t m_Len; +}; + +TestLoader::TestLoader(const char* pBuf, size_t len) + : m_pBuf(pBuf), m_Len(len) { +} + +int Get_Block(void* param, unsigned long pos, unsigned char* pBuf, + unsigned long size) { + TestLoader* pLoader = (TestLoader*) param; + if (pos + size < pos || pos + size > pLoader->m_Len) return 0; + memcpy(pBuf, pLoader->m_pBuf + pos, size); + return 1; +} + +bool Is_Data_Avail(FX_FILEAVAIL* pThis, size_t offset, size_t size) { + return true; +} + +void Add_Segment(FX_DOWNLOADHINTS* pThis, size_t offset, size_t size) { +} + +void EmbedderTest::SetUp() { + v8::V8::InitializeICU(); + +#ifdef V8_USE_EXTERNAL_STARTUP_DATA + ASSERT_TRUE(GetExternalData(options, "natives_blob.bin", &natives_)); + ASSERT_TRUE(GetExternalData(options, "snapshot_blob.bin", &snapshot_)); + v8::V8::SetNativesDataBlob(&natives); + v8::V8::SetSnapshotDataBlob(&snapshot); +#endif // V8_USE_EXTERNAL_STARTUP_DATA + + FPDF_InitLibrary(); + + UNSUPPORT_INFO unsuppored_info; + memset(&unsuppored_info, '\0', sizeof(unsuppored_info)); + unsuppored_info.version = 1; + unsuppored_info.FSDK_UnSupport_Handler = Unsupported_Handler; + FSDK_SetUnSpObjProcessHandler(&unsuppored_info); + } + +void EmbedderTest::TearDown() { + FPDF_CloseDocument(document_); + FPDFAvail_Destroy(avail_); + FPDF_DestroyLibrary(); + if (loader_) { + delete loader_; + } + if (file_contents_) { + free(file_contents_); + } +} + +bool EmbedderTest::OpenDocument(const std::string& filename) { + file_contents_ = GetFileContents(filename.c_str(), &file_length_); + if (!file_contents_) { + return false; + } + + loader_ = new TestLoader(file_contents_, file_length_); + file_access_.m_FileLen = static_cast<unsigned long>(file_length_); + file_access_.m_GetBlock = Get_Block; + file_access_.m_Param = loader_; + + file_avail_.version = 1; + file_avail_.IsDataAvail = Is_Data_Avail; + + hints_.version = 1; + hints_.AddSegment = Add_Segment; + + avail_ = FPDFAvail_Create(&file_avail_, &file_access_); + (void) FPDFAvail_IsDocAvail(avail_, &hints_); + + if (!FPDFAvail_IsLinearized(avail_)) { + document_ = FPDF_LoadCustomDocument(&file_access_, NULL); + } else { + document_ = FPDFAvail_GetDocument(avail_, NULL); + } + if (!document_) { + return false; + } + (void) FPDF_LoadXFA(document_); + (void) FPDF_GetDocPermissions(document_); + (void) FPDFAvail_IsFormAvail(avail_, &hints_); + return true; +} + +FPDF_FORMHANDLE EmbedderTest::SetFormFillEnvironment() { + IPDF_JSPLATFORM platform_callbacks; + memset(&platform_callbacks, '\0', sizeof(platform_callbacks)); + platform_callbacks.version = 1; + platform_callbacks.app_alert = Form_Alert; + + FPDF_FORMFILLINFO form_callbacks; + memset(&form_callbacks, '\0', sizeof(form_callbacks)); + form_callbacks.version = 1; + form_callbacks.m_pJsPlatform = &platform_callbacks; + + FPDF_FORMHANDLE form = FPDFDOC_InitFormFillEnvironment(document_, + &form_callbacks); + FPDF_SetFormFieldHighlightColor(form, 0, 0xFFE4DD); + FPDF_SetFormFieldHighlightAlpha(form, 100); + return form; +} + +void EmbedderTest::ClearFormFillEnvironment(FPDF_FORMHANDLE form) { + FORM_DoDocumentAAction(form, FPDFDOC_AACTION_WC); + FPDFDOC_ExitFormFillEnvironment(form); +} + +void EmbedderTest::DoOpenActions(FPDF_FORMHANDLE form) { + FORM_DoDocumentJSAction(form); + FORM_DoDocumentOpenAction(form); +} + +int EmbedderTest::GetFirstPageNum() { + int first_page = FPDFAvail_GetFirstPageNum(document_); + (void) FPDFAvail_IsPageAvail(avail_, first_page, &hints_); + return first_page; +} + +int EmbedderTest::GetPageCount() { + int page_count = FPDF_GetPageCount(document_); + for (int i = 0; i < page_count; ++i) { + (void) FPDFAvail_IsPageAvail(avail_, i, &hints_); + } + return page_count; +} + +FPDF_PAGE EmbedderTest::LoadPage(int page_number, + FPDF_FORMHANDLE form) { + FPDF_PAGE page = FPDF_LoadPage(document_, page_number); + if (!page) { + return nullptr; + } + FORM_OnAfterLoadPage(page, form); + FORM_DoPageAAction(page, form, FPDFPAGE_AACTION_OPEN); + return page; +} + +FPDF_BITMAP EmbedderTest::RenderPage(FPDF_PAGE page, + FPDF_FORMHANDLE form) { + int width = static_cast<int>(FPDF_GetPageWidth(page)); + int height = static_cast<int>(FPDF_GetPageHeight(page)); + FPDF_BITMAP bitmap = FPDFBitmap_Create(width, height, 0); + FPDFBitmap_FillRect(bitmap, 0, 0, width, height, 0xFFFFFFFF); + FPDF_RenderPageBitmap(bitmap, page, 0, 0, width, height, 0, 0); + FPDF_FFLDraw(form, bitmap, page, 0, 0, width, height, 0, 0); + return bitmap; +} + +void EmbedderTest::UnloadPage(FPDF_PAGE page, FPDF_FORMHANDLE form) { + FORM_DoPageAAction(page, form, FPDFPAGE_AACTION_CLOSE); + FORM_OnBeforeClosePage(page, form); + FPDF_ClosePage(page); +} diff --git a/testing/embedder_test.h b/testing/embedder_test.h new file mode 100644 index 0000000000..48ea415e19 --- /dev/null +++ b/testing/embedder_test.h @@ -0,0 +1,82 @@ +// Copyright (c) 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_H_ +#define TESTING_EMBEDDER_TEST_H_ + +#include <string> + +#include "../core/include/fxcrt/fx_system.h" +#include "../fpdfsdk/include/fpdf_dataavail.h" +#include "../fpdfsdk/include/fpdfformfill.h" +#include "../fpdfsdk/include/fpdfview.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "v8/include/v8.h" + +class TestLoader; + +// This class is used to load a PDF document, and then run programatic +// API tests against it. +class EmbedderTest : public ::testing::Test { + public: + EmbedderTest() : + document_(nullptr), + avail_(nullptr), + loader_(nullptr), + file_length_(0), + file_contents_(nullptr) { + memset(&hints_, 0, sizeof(hints_)); + memset(&file_access_, 0, sizeof(file_access_)); + memset(&file_avail_, 0, sizeof(file_avail_)); + } + + virtual ~EmbedderTest() { } + + void SetUp() override; + void TearDown() override; + + FPDF_DOCUMENT document() { return document_; } + + // Open the document specified by |filename|, or return false on failure. + virtual bool OpenDocument(const std::string& filename); + + // Create and return a handle to the form fill module for use with the + // FORM_ family of functions from fpdfformfill.h, or return NULL on failure. + virtual FPDF_FORMHANDLE SetFormFillEnvironment(); + + // Release the resources obtained from SetFormFillEnvironment(). + virtual void ClearFormFillEnvironment(FPDF_FORMHANDLE form); + + // Perform JavaScript actions that are to run at document open time. + virtual void DoOpenActions(FPDF_FORMHANDLE form); + + // Determine the page numbers present in the document. + virtual int GetFirstPageNum(); + virtual int GetPageCount(); + + // Load a specific page of the open document. + virtual FPDF_PAGE LoadPage(int page_number, FPDF_FORMHANDLE form); + + // Convert a loaded page into a bitmap. + virtual FPDF_BITMAP RenderPage(FPDF_PAGE page, FPDF_FORMHANDLE form); + + // Relese the resources obtained from LoadPage(). Further use of |page| + // is prohibited after this call is made. + virtual void UnloadPage(FPDF_PAGE page, FPDF_FORMHANDLE form); + + private: + FPDF_DOCUMENT document_; + FPDF_AVAIL avail_; + FX_DOWNLOADHINTS hints_; + FPDF_FILEACCESS file_access_; + FX_FILEAVAIL file_avail_; + v8::StartupData natives_; + v8::StartupData snapshot_; + TestLoader* loader_; + size_t file_length_; + char* file_contents_; +}; + +#endif // TESTING_EMBEDDER_TEST_H_ + diff --git a/testing/resources/about_blank.pdf b/testing/resources/about_blank.pdf Binary files differnew file mode 100644 index 0000000000..d640582d6a --- /dev/null +++ b/testing/resources/about_blank.pdf diff --git a/xfa/src/fwl/src/core/fwl_appimp.cpp b/xfa/src/fwl/src/core/fwl_appimp.cpp index 70e46e6a41..e70d3f6a09 100644 --- a/xfa/src/fwl/src/core/fwl_appimp.cpp +++ b/xfa/src/fwl/src/core/fwl_appimp.cpp @@ -28,7 +28,7 @@ CFWL_AppImp::CFWL_AppImp(IFWL_AdapterNative *pAdapter) }
CFWL_AppImp::~CFWL_AppImp()
{
- delete CFWL_ToolTipContainer::getInstance();
+ CFWL_ToolTipContainer::DeleteInstance();
if (m_bFuelAdapter) {
FWL_ReleaseFuelAdapterNative(m_pAdapterNative);
m_pAdapterNative = NULL;
diff --git a/xfa/src/fwl/src/core/fwl_noteimp.cpp b/xfa/src/fwl/src/core/fwl_noteimp.cpp index 40f0c1137d..417020ac0f 100644 --- a/xfa/src/fwl/src/core/fwl_noteimp.cpp +++ b/xfa/src/fwl/src/core/fwl_noteimp.cpp @@ -938,6 +938,9 @@ FX_BOOL CFWL_EventTarget::IsFilterEvent(CFWL_Event *pEvent, FX_DWORD dwFilter) }
return bRet;
}
+
+CFWL_ToolTipContainer* CFWL_ToolTipContainer::s_pInstance = NULL;
+
CFWL_ToolTipContainer::CFWL_ToolTipContainer()
: pCurTarget(NULL)
, m_pToolTipImp(NULL)
@@ -959,13 +962,21 @@ CFWL_ToolTipContainer::~CFWL_ToolTipContainer() m_ToolTipDp = NULL;
}
}
+// static
CFWL_ToolTipContainer* CFWL_ToolTipContainer::getInstance()
{
- static CFWL_ToolTipContainer * _toolTipContainer = NULL;
- if (!_toolTipContainer) {
- _toolTipContainer = FX_NEW CFWL_ToolTipContainer;
+ if (!s_pInstance) {
+ s_pInstance = FX_NEW CFWL_ToolTipContainer;
+ }
+ return s_pInstance;
+}
+// static
+void CFWL_ToolTipContainer::DeleteInstance()
+{
+ if (s_pInstance) {
+ delete s_pInstance;
+ s_pInstance = NULL;
}
- return _toolTipContainer;
}
FX_ERR CFWL_ToolTipContainer::AddToolTipTarget(IFWL_ToolTipTarget *pTarget)
{
diff --git a/xfa/src/fwl/src/core/include/fwl_noteimp.h b/xfa/src/fwl/src/core/include/fwl_noteimp.h index 1e7239289b..aeed0b3955 100644 --- a/xfa/src/fwl/src/core/include/fwl_noteimp.h +++ b/xfa/src/fwl/src/core/include/fwl_noteimp.h @@ -127,8 +127,8 @@ protected: class CFWL_ToolTipContainer: public CFX_Object
{
public:
- virtual ~CFWL_ToolTipContainer();
static CFWL_ToolTipContainer* getInstance();
+ static void DeleteInstance();
FX_ERR AddToolTipTarget(IFWL_ToolTipTarget *pTarget);
FX_ERR RemoveToolTipTarget(IFWL_ToolTipTarget *pTarget);
@@ -140,13 +140,18 @@ public: FX_BOOL ProcessLeave(CFWL_EvtMouse *pEvt);
FX_ERR SetToolTipInitialDelay(FX_INT32 iDelayTime);
- FX_ERR SetToolTipAutoPopDelay(FX_INT32 iDelayTime);
+ FX_ERR SetToolTipAutoPopDelay(FX_INT32 iDelayTime);
+
protected:
CFWL_ToolTipContainer();
+ virtual ~CFWL_ToolTipContainer();
IFWL_ToolTipTarget *pCurTarget;
CFWL_ToolTipImp *m_pToolTipImp;
CFWL_CoreToopTipDP *m_ToolTipDp;
CFX_PtrArray m_arrWidget;
+
+private:
+ static CFWL_ToolTipContainer* s_pInstance;
};
#endif
diff --git a/xfa/src/fxjse/src/runtime.cpp b/xfa/src/fxjse/src/runtime.cpp index e406f6a233..0a1b0db78b 100644 --- a/xfa/src/fxjse/src/runtime.cpp +++ b/xfa/src/fxjse/src/runtime.cpp @@ -14,6 +14,9 @@ static void FXJSE_KillV8() }
void FXJSE_Initialize()
{
+ if(!CFXJSE_RuntimeData::g_RuntimeList) {
+ CFXJSE_RuntimeData::g_RuntimeList = FX_NEW CFXJSE_RuntimeList;
+ }
static FX_BOOL bV8Initialized = FALSE;
if (bV8Initialized) {
return;
@@ -26,12 +29,9 @@ void FXJSE_Initialize() ;
v8::V8::SetFlagsFromString(szCmdFlags, FXSYS_strlen(szCmdFlags));
v8::V8::InitializeICU();
- v8::Platform* platform = v8::platform::CreateDefaultPlatform();
- v8::V8::InitializePlatform(platform);
+ v8::Platform* platform = v8::platform::CreateDefaultPlatform();
+ v8::V8::InitializePlatform(platform);
v8::V8::Initialize();
- if(!CFXJSE_RuntimeData::g_RuntimeList) {
- CFXJSE_RuntimeData::g_RuntimeList = FX_NEW CFXJSE_RuntimeList;
- }
}
static void FXJSE_Runtime_DisposeCallback(v8::Isolate* pIsolate)
{
|