blob: ffe51192afe88bc8a178496c8d0e1075150f0d8f [file] [log] [blame]
Tom Sepez96d13342015-01-16 14:59:26 -08001// Copyright (c) 2015 PDFium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "embedder_test.h"
6
7#include <limits.h>
8#include <stdio.h>
9#include <stdlib.h>
10#include <string.h>
11
12#include <list>
13#include <string>
14#include <utility>
15#include <vector>
16
Tom Sepez96d13342015-01-16 14:59:26 -080017#include "../fpdfsdk/include/fpdftext.h"
18#include "../fpdfsdk/include/fpdfview.h"
19#include "../core/include/fxcrt/fx_system.h"
Tom Sepeza310e002015-02-27 13:03:07 -080020#include "testing/gmock/include/gmock/gmock.h"
Tom Sepez96d13342015-01-16 14:59:26 -080021#include "v8/include/v8.h"
22
23#ifdef _WIN32
24#define snprintf _snprintf
25#define PATH_SEPARATOR '\\'
26#else
27#define PATH_SEPARATOR '/'
28#endif
29
30namespace {
31
Tom Sepez1b1bb492015-01-22 17:36:32 -080032const char* g_exe_path_ = nullptr;
33
Tom Sepez96d13342015-01-16 14:59:26 -080034// Reads the entire contents of a file into a newly malloc'd buffer.
35static char* GetFileContents(const char* filename, size_t* retlen) {
36 FILE* file = fopen(filename, "rb");
37 if (!file) {
38 fprintf(stderr, "Failed to open: %s\n", filename);
39 return NULL;
40 }
41 (void) fseek(file, 0, SEEK_END);
42 size_t file_length = ftell(file);
43 if (!file_length) {
44 return NULL;
45 }
46 (void) fseek(file, 0, SEEK_SET);
47 char* buffer = (char*) malloc(file_length);
48 if (!buffer) {
49 return NULL;
50 }
51 size_t bytes_read = fread(buffer, 1, file_length, file);
52 (void) fclose(file);
53 if (bytes_read != file_length) {
54 fprintf(stderr, "Failed to read: %s\n", filename);
55 free(buffer);
56 return NULL;
57 }
58 *retlen = bytes_read;
59 return buffer;
60}
61
62#ifdef V8_USE_EXTERNAL_STARTUP_DATA
63// Returns the full path for an external V8 data file based on either
64// the currect exectuable path or an explicit override.
Tom Sepez1b1bb492015-01-22 17:36:32 -080065static std::string GetFullPathForSnapshotFile(const std::string& exe_path,
Tom Sepez96d13342015-01-16 14:59:26 -080066 const std::string& filename) {
67 std::string result;
Tom Sepez1b1bb492015-01-22 17:36:32 -080068 if (!exe_path.empty()) {
69 size_t last_separator = exe_path.rfind(PATH_SEPARATOR);
Tom Sepez96d13342015-01-16 14:59:26 -080070 if (last_separator != std::string::npos) {
Tom Sepez1b1bb492015-01-22 17:36:32 -080071 result = exe_path.substr(0, last_separator + 1);
Tom Sepez96d13342015-01-16 14:59:26 -080072 }
73 }
74 result += filename;
75 return result;
76}
77
78// Reads an extenal V8 data file from the |options|-indicated location,
79// returing true on success and false on error.
Tom Sepez1b1bb492015-01-22 17:36:32 -080080static bool GetExternalData(const std::string& exe_path,
81 const std::string& filename,
Tom Sepez96d13342015-01-16 14:59:26 -080082 v8::StartupData* result_data) {
Tom Sepez1b1bb492015-01-22 17:36:32 -080083 std::string full_path = GetFullPathForSnapshotFile(exe_path, filename);
Tom Sepez96d13342015-01-16 14:59:26 -080084 size_t data_length = 0;
85 char* data_buffer = GetFileContents(full_path.c_str(), &data_length);
86 if (!data_buffer) {
87 return false;
88 }
89 result_data->data = const_cast<const char*>(data_buffer);
90 result_data->raw_size = data_length;
91 return true;
92}
93#endif // V8_USE_EXTERNAL_STARTUP_DATA
94
95} // namespace
96
Tom Sepez4cb0fa72015-02-25 16:08:18 -080097class EmbedderTestDefaultDelegate : public EmbedderTest::Delegate {
98 public:
99 int Alert(FPDF_WIDESTRING, FPDF_WIDESTRING, int, int) override {
100 printf("Form_Alert called.\n");
101 return 0;
Tom Sepez96d13342015-01-16 14:59:26 -0800102 }
Tom Sepez4cb0fa72015-02-25 16:08:18 -0800103
104 void UnsupportedHandler(int type) {
105 std::string feature = "Unknown";
106 switch (type) {
107 case FPDF_UNSP_DOC_XFAFORM:
108 feature = "XFA";
109 break;
110 case FPDF_UNSP_DOC_PORTABLECOLLECTION:
111 feature = "Portfolios_Packages";
112 break;
113 case FPDF_UNSP_DOC_ATTACHMENT:
114 case FPDF_UNSP_ANNOT_ATTACHMENT:
115 feature = "Attachment";
116 break;
117 case FPDF_UNSP_DOC_SECURITY:
118 feature = "Rights_Management";
119 break;
120 case FPDF_UNSP_DOC_SHAREDREVIEW:
121 feature = "Shared_Review";
122 break;
123 case FPDF_UNSP_DOC_SHAREDFORM_ACROBAT:
124 case FPDF_UNSP_DOC_SHAREDFORM_FILESYSTEM:
125 case FPDF_UNSP_DOC_SHAREDFORM_EMAIL:
126 feature = "Shared_Form";
127 break;
128 case FPDF_UNSP_ANNOT_3DANNOT:
129 feature = "3D";
130 break;
131 case FPDF_UNSP_ANNOT_MOVIE:
132 feature = "Movie";
133 break;
134 case FPDF_UNSP_ANNOT_SOUND:
135 feature = "Sound";
136 break;
137 case FPDF_UNSP_ANNOT_SCREEN_MEDIA:
138 case FPDF_UNSP_ANNOT_SCREEN_RICHMEDIA:
139 feature = "Screen";
140 break;
141 case FPDF_UNSP_ANNOT_SIG:
142 feature = "Digital_Signature";
143 break;
144 }
145 printf("Unsupported feature: %s.\n", feature.c_str());
146 }
147};
Tom Sepez96d13342015-01-16 14:59:26 -0800148
149class TestLoader {
150 public:
151 TestLoader(const char* pBuf, size_t len);
152
153 const char* m_pBuf;
154 size_t m_Len;
155};
156
157TestLoader::TestLoader(const char* pBuf, size_t len)
158 : m_pBuf(pBuf), m_Len(len) {
159}
160
161int Get_Block(void* param, unsigned long pos, unsigned char* pBuf,
162 unsigned long size) {
163 TestLoader* pLoader = (TestLoader*) param;
164 if (pos + size < pos || pos + size > pLoader->m_Len) return 0;
165 memcpy(pBuf, pLoader->m_pBuf + pos, size);
166 return 1;
167}
168
169bool Is_Data_Avail(FX_FILEAVAIL* pThis, size_t offset, size_t size) {
170 return true;
171}
172
173void Add_Segment(FX_DOWNLOADHINTS* pThis, size_t offset, size_t size) {
174}
175
Tom Sepez4cb0fa72015-02-25 16:08:18 -0800176EmbedderTest::EmbedderTest() :
177 document_(nullptr),
178 form_handle_(nullptr),
179 avail_(nullptr),
180 loader_(nullptr),
181 file_length_(0),
182 file_contents_(nullptr) {
183 memset(&hints_, 0, sizeof(hints_));
184 memset(&file_access_, 0, sizeof(file_access_));
185 memset(&file_avail_, 0, sizeof(file_avail_));
186 default_delegate_ = new EmbedderTestDefaultDelegate();
187 delegate_ = default_delegate_;
188}
189
190EmbedderTest::~EmbedderTest() {
191 delete default_delegate_;
192}
193
Tom Sepez96d13342015-01-16 14:59:26 -0800194void EmbedderTest::SetUp() {
195 v8::V8::InitializeICU();
196
197#ifdef V8_USE_EXTERNAL_STARTUP_DATA
Tom Sepez1b1bb492015-01-22 17:36:32 -0800198 ASSERT_TRUE(GetExternalData(g_exe_path_, "natives_blob.bin", &natives_));
199 ASSERT_TRUE(GetExternalData(g_exe_path_, "snapshot_blob.bin", &snapshot_));
200 v8::V8::SetNativesDataBlob(&natives_);
201 v8::V8::SetSnapshotDataBlob(&snapshot_);
Tom Sepez96d13342015-01-16 14:59:26 -0800202#endif // V8_USE_EXTERNAL_STARTUP_DATA
203
204 FPDF_InitLibrary();
205
Tom Sepez4cb0fa72015-02-25 16:08:18 -0800206 UNSUPPORT_INFO* info = static_cast<UNSUPPORT_INFO*>(this);
207 memset(info, 0, sizeof(UNSUPPORT_INFO));
208 info->version = 1;
209 info->FSDK_UnSupport_Handler = UnsupportedHandlerTrampoline;
210 FSDK_SetUnSpObjProcessHandler(info);
Tom Sepez96d13342015-01-16 14:59:26 -0800211 }
212
213void EmbedderTest::TearDown() {
Tom Sepezda8189e2015-01-30 14:41:50 -0800214 if (form_handle_) {
215 FORM_DoDocumentAAction(form_handle_, FPDFDOC_AACTION_WC);
216 FPDFDOC_ExitFormFillEnvironment(form_handle_);
217 }
218 if (document_) {
219 FPDF_CloseDocument(document_);
220 }
Tom Sepez96d13342015-01-16 14:59:26 -0800221 FPDFAvail_Destroy(avail_);
222 FPDF_DestroyLibrary();
223 if (loader_) {
224 delete loader_;
225 }
226 if (file_contents_) {
227 free(file_contents_);
228 }
229}
230
231bool EmbedderTest::OpenDocument(const std::string& filename) {
232 file_contents_ = GetFileContents(filename.c_str(), &file_length_);
233 if (!file_contents_) {
234 return false;
235 }
236
237 loader_ = new TestLoader(file_contents_, file_length_);
238 file_access_.m_FileLen = static_cast<unsigned long>(file_length_);
239 file_access_.m_GetBlock = Get_Block;
240 file_access_.m_Param = loader_;
241
242 file_avail_.version = 1;
243 file_avail_.IsDataAvail = Is_Data_Avail;
244
245 hints_.version = 1;
246 hints_.AddSegment = Add_Segment;
247
248 avail_ = FPDFAvail_Create(&file_avail_, &file_access_);
249 (void) FPDFAvail_IsDocAvail(avail_, &hints_);
250
251 if (!FPDFAvail_IsLinearized(avail_)) {
252 document_ = FPDF_LoadCustomDocument(&file_access_, NULL);
253 } else {
254 document_ = FPDFAvail_GetDocument(avail_, NULL);
255 }
256 if (!document_) {
257 return false;
258 }
259 (void) FPDF_LoadXFA(document_);
260 (void) FPDF_GetDocPermissions(document_);
261 (void) FPDFAvail_IsFormAvail(avail_, &hints_);
Tom Sepez96d13342015-01-16 14:59:26 -0800262
Tom Sepez4cb0fa72015-02-25 16:08:18 -0800263 IPDF_JSPLATFORM* platform = static_cast<IPDF_JSPLATFORM*>(this);
264 memset(platform, 0, sizeof(IPDF_JSPLATFORM));
265 platform->version = 1;
266 platform->app_alert = AlertTrampoline;
Tom Sepez96d13342015-01-16 14:59:26 -0800267
Tom Sepez4cb0fa72015-02-25 16:08:18 -0800268 FPDF_FORMFILLINFO* formfillinfo = static_cast<FPDF_FORMFILLINFO*>(this);
269 memset(formfillinfo, 0, sizeof(FPDF_FORMFILLINFO));
270 formfillinfo->version = 1;
271 formfillinfo->m_pJsPlatform = platform;
Tom Sepez96d13342015-01-16 14:59:26 -0800272
Tom Sepez4cb0fa72015-02-25 16:08:18 -0800273 form_handle_ = FPDFDOC_InitFormFillEnvironment(document_, formfillinfo);
Tom Sepezda8189e2015-01-30 14:41:50 -0800274 FPDF_SetFormFieldHighlightColor(form_handle_, 0, 0xFFE4DD);
275 FPDF_SetFormFieldHighlightAlpha(form_handle_, 100);
276
277 return true;
Tom Sepez96d13342015-01-16 14:59:26 -0800278}
279
Tom Sepezda8189e2015-01-30 14:41:50 -0800280void EmbedderTest::DoOpenActions() {
281 FORM_DoDocumentJSAction(form_handle_);
282 FORM_DoDocumentOpenAction(form_handle_);
Tom Sepez96d13342015-01-16 14:59:26 -0800283}
284
285int EmbedderTest::GetFirstPageNum() {
286 int first_page = FPDFAvail_GetFirstPageNum(document_);
287 (void) FPDFAvail_IsPageAvail(avail_, first_page, &hints_);
288 return first_page;
289}
290
291int EmbedderTest::GetPageCount() {
292 int page_count = FPDF_GetPageCount(document_);
293 for (int i = 0; i < page_count; ++i) {
294 (void) FPDFAvail_IsPageAvail(avail_, i, &hints_);
295 }
296 return page_count;
297}
298
Tom Sepezda8189e2015-01-30 14:41:50 -0800299FPDF_PAGE EmbedderTest::LoadPage(int page_number) {
Tom Sepez96d13342015-01-16 14:59:26 -0800300 FPDF_PAGE page = FPDF_LoadPage(document_, page_number);
301 if (!page) {
302 return nullptr;
303 }
Tom Sepezda8189e2015-01-30 14:41:50 -0800304 FORM_OnAfterLoadPage(page, form_handle_);
305 FORM_DoPageAAction(page, form_handle_, FPDFPAGE_AACTION_OPEN);
Tom Sepez96d13342015-01-16 14:59:26 -0800306 return page;
307}
308
Tom Sepezda8189e2015-01-30 14:41:50 -0800309FPDF_BITMAP EmbedderTest::RenderPage(FPDF_PAGE page) {
Tom Sepez96d13342015-01-16 14:59:26 -0800310 int width = static_cast<int>(FPDF_GetPageWidth(page));
311 int height = static_cast<int>(FPDF_GetPageHeight(page));
312 FPDF_BITMAP bitmap = FPDFBitmap_Create(width, height, 0);
313 FPDFBitmap_FillRect(bitmap, 0, 0, width, height, 0xFFFFFFFF);
314 FPDF_RenderPageBitmap(bitmap, page, 0, 0, width, height, 0, 0);
Tom Sepezda8189e2015-01-30 14:41:50 -0800315 FPDF_FFLDraw(form_handle_, bitmap, page, 0, 0, width, height, 0, 0);
Tom Sepez96d13342015-01-16 14:59:26 -0800316 return bitmap;
317}
318
Tom Sepezda8189e2015-01-30 14:41:50 -0800319void EmbedderTest::UnloadPage(FPDF_PAGE page) {
320 FORM_DoPageAAction(page, form_handle_, FPDFPAGE_AACTION_CLOSE);
321 FORM_OnBeforeClosePage(page, form_handle_);
Tom Sepez96d13342015-01-16 14:59:26 -0800322 FPDF_ClosePage(page);
323}
Tom Sepez1b1bb492015-01-22 17:36:32 -0800324
Tom Sepez4cb0fa72015-02-25 16:08:18 -0800325// static
326void EmbedderTest::UnsupportedHandlerTrampoline(UNSUPPORT_INFO* info,
327 int type) {
328 EmbedderTest* test = static_cast<EmbedderTest*>(info);
329 test->delegate_->UnsupportedHandler(type);
330}
331
332// static
333int EmbedderTest::AlertTrampoline(IPDF_JSPLATFORM* platform,
334 FPDF_WIDESTRING message,
335 FPDF_WIDESTRING title,
336 int type,
337 int icon) {
338 EmbedderTest* test = static_cast<EmbedderTest*>(platform);
339 return test->delegate_->Alert(message, title, type, icon);
340}
341
Tom Sepez1b1bb492015-01-22 17:36:32 -0800342// Can't use gtest-provided main since we need to stash the path to the
343// executable in order to find the external V8 binary data files.
344int main(int argc, char** argv) {
345 g_exe_path_ = argv[0];
346 testing::InitGoogleTest(&argc, argv);
Tom Sepeza310e002015-02-27 13:03:07 -0800347 testing::InitGoogleMock(&argc, argv);
Tom Sepez1b1bb492015-01-22 17:36:32 -0800348 return RUN_ALL_TESTS();
349}