Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
embedder_test.cpp
Go to the documentation of this file.
1// Copyright 2015 The PDFium Authors
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 "testing/embedder_test.h"
6
7#include <algorithm>
8#include <memory>
9#include <string>
10#include <utility>
11#include <vector>
12
13#include "core/fdrm/fx_crypt.h"
14#include "core/fxcrt/check.h"
15#include "core/fxcrt/check_op.h"
16#include "core/fxcrt/containers/contains.h"
17#include "core/fxcrt/fx_memcpy_wrappers.h"
18#include "core/fxcrt/numerics/checked_math.h"
19#include "core/fxcrt/numerics/safe_conversions.h"
20#include "fpdfsdk/cpdfsdk_helpers.h"
21#include "public/cpp/fpdf_scopers.h"
22#include "public/fpdf_dataavail.h"
23#include "public/fpdf_edit.h"
24#include "public/fpdf_text.h"
25#include "public/fpdfview.h"
26#include "testing/embedder_test_environment.h"
27#include "testing/gmock/include/gmock/gmock.h"
28#include "testing/test_loader.h"
29#include "testing/utils/bitmap_saver.h"
30#include "testing/utils/file_util.h"
31#include "testing/utils/hash.h"
32#include "testing/utils/path_service.h"
33
34namespace {
35
36int GetBitmapBytesPerPixel(FPDF_BITMAP bitmap) {
38}
39
40#if BUILDFLAG(IS_WIN)
41int CALLBACK GetRecordProc(HDC hdc,
42 HANDLETABLE* handle_table,
43 const ENHMETARECORD* record,
44 int objects_count,
45 LPARAM param) {
46 auto& records = *reinterpret_cast<std::vector<const ENHMETARECORD*>*>(param);
47 records.push_back(record);
48 return 1;
49}
50#endif // BUILDFLAG(IS_WIN)
51
52// These "jump" into the delegate to do actual testing.
53void UnsupportedHandlerTrampoline(UNSUPPORT_INFO* info, int type) {
54 auto* delegate = static_cast<EmbedderTest*>(info)->GetDelegate();
55 delegate->UnsupportedHandler(type);
56}
57
58int AlertTrampoline(IPDF_JSPLATFORM* platform,
59 FPDF_WIDESTRING message,
60 FPDF_WIDESTRING title,
61 int type,
62 int icon) {
63 auto* delegate = static_cast<EmbedderTest*>(platform)->GetDelegate();
64 return delegate->Alert(message, title, type, icon);
65}
66
67int SetTimerTrampoline(FPDF_FORMFILLINFO* info, int msecs, TimerCallback fn) {
68 auto* delegate = static_cast<EmbedderTest*>(info)->GetDelegate();
69 return delegate->SetTimer(msecs, fn);
70}
71
72void KillTimerTrampoline(FPDF_FORMFILLINFO* info, int id) {
73 auto* delegate = static_cast<EmbedderTest*>(info)->GetDelegate();
74 return delegate->KillTimer(id);
75}
76
77FPDF_PAGE GetPageTrampoline(FPDF_FORMFILLINFO* info,
78 FPDF_DOCUMENT document,
79 int page_index) {
80 auto* delegate = static_cast<EmbedderTest*>(info)->GetDelegate();
81 return delegate->GetPage(info, document, page_index);
82}
83
84void DoURIActionTrampoline(FPDF_FORMFILLINFO* info, FPDF_BYTESTRING uri) {
85 auto* delegate = static_cast<EmbedderTest*>(info)->GetDelegate();
86 return delegate->DoURIAction(uri);
87}
88
89void DoGoToActionTrampoline(FPDF_FORMFILLINFO* info,
90 int page_index,
91 int zoom_mode,
92 float* pos_array,
93 int array_size) {
94 auto* delegate = static_cast<EmbedderTest*>(info)->GetDelegate();
95 return delegate->DoGoToAction(info, page_index, zoom_mode, pos_array,
96 array_size);
97}
98
99void OnFocusChangeTrampoline(FPDF_FORMFILLINFO* info,
100 FPDF_ANNOTATION annot,
101 int page_index) {
102 auto* delegate = static_cast<EmbedderTest*>(info)->GetDelegate();
103 return delegate->OnFocusChange(info, annot, page_index);
104}
105
106void DoURIActionWithKeyboardModifierTrampoline(FPDF_FORMFILLINFO* info,
107 FPDF_BYTESTRING uri,
108 int modifiers) {
109 auto* delegate = static_cast<EmbedderTest*>(info)->GetDelegate();
110 return delegate->DoURIActionWithKeyboardModifier(info, uri, modifiers);
111}
112
113// These do nothing (but must return a reasonable default value).
114void InvalidateStub(FPDF_FORMFILLINFO* pThis,
115 FPDF_PAGE page,
116 double left,
117 double top,
118 double right,
119 double bottom) {}
120
121void OutputSelectedRectStub(FPDF_FORMFILLINFO* pThis,
122 FPDF_PAGE page,
123 double left,
124 double top,
125 double right,
126 double bottom) {}
127
128void SetCursorStub(FPDF_FORMFILLINFO* pThis, int nCursorType) {}
129
130FPDF_SYSTEMTIME GetLocalTimeStub(FPDF_FORMFILLINFO* pThis) {
131 return {122, 11, 6, 28, 12, 59, 59, 500};
132}
133
134void OnChangeStub(FPDF_FORMFILLINFO* pThis) {}
135
136FPDF_PAGE GetCurrentPageStub(FPDF_FORMFILLINFO* pThis, FPDF_DOCUMENT document) {
137 return GetPageTrampoline(pThis, document, 0);
138}
139
140int GetRotationStub(FPDF_FORMFILLINFO* pThis, FPDF_PAGE page) {
141 return 0;
142}
143
144void ExecuteNamedActionStub(FPDF_FORMFILLINFO* pThis, FPDF_BYTESTRING name) {}
145
146void SetTextFieldFocusStub(FPDF_FORMFILLINFO* pThis,
147 FPDF_WIDESTRING value,
148 FPDF_DWORD valueLen,
149 FPDF_BOOL is_focus) {}
150
151#ifdef PDF_ENABLE_XFA
152void DisplayCaretStub(FPDF_FORMFILLINFO* pThis,
153 FPDF_PAGE page,
154 FPDF_BOOL bVisible,
155 double left,
156 double top,
157 double right,
158 double bottom) {}
159
160int GetCurrentPageIndexStub(FPDF_FORMFILLINFO* pThis, FPDF_DOCUMENT document) {
161 return 0;
162}
163
164void SetCurrentPageStub(FPDF_FORMFILLINFO* pThis,
165 FPDF_DOCUMENT document,
166 int iCurPage) {}
167
168void GotoURLStub(FPDF_FORMFILLINFO* pThis,
169 FPDF_DOCUMENT document,
170 FPDF_WIDESTRING wsURL) {}
171
172void GetPageViewRectStub(FPDF_FORMFILLINFO* pThis,
173 FPDF_PAGE page,
174 double* left,
175 double* top,
176 double* right,
177 double* bottom) {
178 *left = 0.0;
179 *top = 0.0;
180 *right = 512.0;
181 *bottom = 512.0;
182}
183
184void PageEventStub(FPDF_FORMFILLINFO* pThis,
185 int page_count,
186 FPDF_DWORD event_type) {}
187
188FPDF_BOOL PopupMenuStub(FPDF_FORMFILLINFO* pThis,
189 FPDF_PAGE page,
190 FPDF_WIDGET hWidget,
191 int menuFlag,
192 float x,
193 float y) {
194 return true;
195}
196
197FPDF_FILEHANDLER* OpenFileStub(FPDF_FORMFILLINFO* pThis,
198 int fileFlag,
199 FPDF_WIDESTRING wsURL,
200 const char* mode) {
201 return nullptr;
202}
203
204void EmailToStub(FPDF_FORMFILLINFO* pThis,
205 FPDF_FILEHANDLER* fileHandler,
206 FPDF_WIDESTRING pTo,
207 FPDF_WIDESTRING pSubject,
208 FPDF_WIDESTRING pCC,
209 FPDF_WIDESTRING pBcc,
210 FPDF_WIDESTRING pMsg) {}
211
212void UploadToStub(FPDF_FORMFILLINFO* pThis,
213 FPDF_FILEHANDLER* fileHandler,
214 int fileFlag,
215 FPDF_WIDESTRING uploadTo) {}
216
217int GetPlatformStub(FPDF_FORMFILLINFO* pThis, void* platform, int length) {
218 return 0;
219}
220
221int GetLanguageStub(FPDF_FORMFILLINFO* pThis, void* language, int length) {
222 return 0;
223}
224
225FPDF_FILEHANDLER* DownloadFromURLStub(FPDF_FORMFILLINFO* pThis,
226 FPDF_WIDESTRING URL) {
227 static const char kString[] = "<body>secrets</body>";
228 static FPDF_FILEHANDLER kFakeFileHandler = {
229 nullptr,
230 [](void*) -> void {},
231 [](void*) -> FPDF_DWORD { return sizeof(kString) - 1; },
232 [](void*, FPDF_DWORD off, void* buffer, FPDF_DWORD size) -> FPDF_RESULT {
233 FXSYS_memcpy(buffer, kString,
234 std::min<size_t>(size, sizeof(kString) - 1));
235 return 0;
236 },
237 [](void*, FPDF_DWORD, const void*, FPDF_DWORD) -> FPDF_RESULT {
238 return -1;
239 },
240 [](void*) -> FPDF_RESULT { return 0; },
241 [](void*, FPDF_DWORD) -> FPDF_RESULT { return 0; }};
242 return &kFakeFileHandler;
243}
244
245FPDF_BOOL PostRequestURLStub(FPDF_FORMFILLINFO* pThis,
246 FPDF_WIDESTRING wsURL,
247 FPDF_WIDESTRING wsData,
248 FPDF_WIDESTRING wsContentType,
249 FPDF_WIDESTRING wsEncode,
250 FPDF_WIDESTRING wsHeader,
251 FPDF_BSTR* response) {
252 const char kString[] = "p\0o\0s\0t\0e\0d\0";
253 FPDF_BStr_Set(response, kString, sizeof(kString) - 1);
254 return true;
255}
256
257FPDF_BOOL PutRequestURLStub(FPDF_FORMFILLINFO* pThis,
258 FPDF_WIDESTRING wsURL,
259 FPDF_WIDESTRING wsData,
260 FPDF_WIDESTRING wsEncode) {
261 return true;
262}
263#endif // PDF_ENABLE_XFA
264
265} // namespace
266
270 FPDF_FILEWRITE::version = 1;
271 FPDF_FILEWRITE::WriteBlock = WriteBlockCallback;
272}
273
274EmbedderTest::~EmbedderTest() = default;
275
277 UNSUPPORT_INFO* info = static_cast<UNSUPPORT_INFO*>(this);
278 FXSYS_memset(info, 0, sizeof(UNSUPPORT_INFO));
279 info->version = 1;
280 info->FSDK_UnSupport_Handler = UnsupportedHandlerTrampoline;
282}
283
285 // Use an EXPECT_EQ() here and continue to let TearDown() finish as cleanly as
286 // possible. This can fail when an DCHECK test fails in a test case.
287 EXPECT_EQ(0U, page_map_.size());
288 EXPECT_EQ(0U, saved_page_map_.size());
289 if (document())
291}
292
295 form_handle_.reset(SetupFormFillEnvironment(
296 document(), JavaScriptOption::kEnableJavaScript));
297}
298
300 document_.reset(FPDF_CreateNewDocument());
301 CHECK(document_);
302}
303
304bool EmbedderTest::OpenDocument(const std::string& filename) {
305 return OpenDocumentWithOptions(filename, nullptr,
308}
309
310bool EmbedderTest::OpenDocumentLinearized(const std::string& filename) {
311 return OpenDocumentWithOptions(filename, nullptr,
314}
315
316bool EmbedderTest::OpenDocumentWithPassword(const std::string& filename,
317 const char* password) {
318 return OpenDocumentWithOptions(filename, password,
321}
322
323bool EmbedderTest::OpenDocumentWithoutJavaScript(const std::string& filename) {
324 return OpenDocumentWithOptions(filename, nullptr,
327}
328
329bool EmbedderTest::OpenDocumentWithOptions(const std::string& filename,
330 const char* password,
331 LinearizeOption linearize_option,
332 JavaScriptOption javascript_option) {
333 std::string file_path = PathService::GetTestFilePath(filename);
334 if (file_path.empty()) {
335 return false;
336 }
337
338 file_contents_ = GetFileContents(file_path.c_str());
339 if (file_contents_.empty()) {
340 return false;
341 }
342
343 EXPECT_TRUE(!loader_);
344 loader_ = std::make_unique<TestLoader>(file_contents_);
345
346 FXSYS_memset(&file_access_, 0, sizeof(file_access_));
347 file_access_.m_FileLen =
348 pdfium::checked_cast<unsigned long>(file_contents_.size());
349 file_access_.m_GetBlock = TestLoader::GetBlock;
350 file_access_.m_Param = loader_.get();
351
352 fake_file_access_ = std::make_unique<FakeFileAccess>(&file_access_);
353 return OpenDocumentHelper(password, linearize_option, javascript_option,
354 fake_file_access_.get(), &document_, &avail_,
355 &form_handle_);
356}
357
358bool EmbedderTest::OpenDocumentHelper(const char* password,
359 LinearizeOption linearize_option,
360 JavaScriptOption javascript_option,
361 FakeFileAccess* network_simulator,
362 ScopedFPDFDocument* document,
363 ScopedFPDFAvail* avail,
364 ScopedFPDFFormHandle* form_handle) {
365 network_simulator->AddSegment(0, 1024);
366 network_simulator->SetRequestedDataAvailable();
367 avail->reset(FPDFAvail_Create(network_simulator->GetFileAvail(),
368 network_simulator->GetFileAccess()));
369 FPDF_AVAIL avail_ptr = avail->get();
370 FPDF_DOCUMENT document_ptr = nullptr;
372 int32_t nRet = PDF_DATA_NOTAVAIL;
373 while (nRet == PDF_DATA_NOTAVAIL) {
374 network_simulator->SetRequestedDataAvailable();
375 nRet = FPDFAvail_IsDocAvail(avail_ptr,
376 network_simulator->GetDownloadHints());
377 }
378 if (nRet == PDF_DATA_ERROR)
379 return false;
380
381 document->reset(FPDFAvail_GetDocument(avail_ptr, password));
382 document_ptr = document->get();
383 if (!document_ptr)
384 return false;
385
386 nRet = PDF_DATA_NOTAVAIL;
387 while (nRet == PDF_DATA_NOTAVAIL) {
388 network_simulator->SetRequestedDataAvailable();
389 nRet = FPDFAvail_IsFormAvail(avail_ptr,
390 network_simulator->GetDownloadHints());
391 }
392 if (nRet == PDF_FORM_ERROR)
393 return false;
394
395 int page_count = FPDF_GetPageCount(document_ptr);
396 for (int i = 0; i < page_count; ++i) {
397 nRet = PDF_DATA_NOTAVAIL;
398 while (nRet == PDF_DATA_NOTAVAIL) {
399 network_simulator->SetRequestedDataAvailable();
400 nRet = FPDFAvail_IsPageAvail(avail_ptr, i,
401 network_simulator->GetDownloadHints());
402 }
403 if (nRet == PDF_DATA_ERROR)
404 return false;
405 }
406 } else {
407 if (linearize_option == LinearizeOption::kMustLinearize)
408 return false;
409 network_simulator->SetWholeFileAvailable();
410 document->reset(
411 FPDF_LoadCustomDocument(network_simulator->GetFileAccess(), password));
412 document_ptr = document->get();
413 if (!document_ptr)
414 return false;
415 }
416 form_handle->reset(SetupFormFillEnvironment(document_ptr, javascript_option));
417
418 int doc_type = FPDF_GetFormType(document_ptr);
419 if (doc_type == FORMTYPE_XFA_FULL || doc_type == FORMTYPE_XFA_FOREGROUND)
420 FPDF_LoadXFA(document_ptr);
421
422 return true;
423}
424
427 form_handle_.reset();
428 document_.reset();
429 avail_.reset();
430 fake_file_access_.reset();
431 FXSYS_memset(&file_access_, 0, sizeof(file_access_));
432 loader_.reset();
433 file_contents_ = {};
434}
435
437 FPDF_DOCUMENT doc,
438 JavaScriptOption javascript_option) {
439 IPDF_JSPLATFORM* platform = static_cast<IPDF_JSPLATFORM*>(this);
440 FXSYS_memset(platform, '\0', sizeof(IPDF_JSPLATFORM));
441 platform->version = 3;
442 platform->app_alert = AlertTrampoline;
443
444 FPDF_FORMFILLINFO* formfillinfo = static_cast<FPDF_FORMFILLINFO*>(this);
445 FXSYS_memset(formfillinfo, 0, sizeof(FPDF_FORMFILLINFO));
446 formfillinfo->version = form_fill_info_version_;
447 formfillinfo->FFI_Invalidate = InvalidateStub;
448 formfillinfo->FFI_OutputSelectedRect = OutputSelectedRectStub;
449 formfillinfo->FFI_SetCursor = SetCursorStub;
450 formfillinfo->FFI_SetTimer = SetTimerTrampoline;
451 formfillinfo->FFI_KillTimer = KillTimerTrampoline;
452 formfillinfo->FFI_GetLocalTime = GetLocalTimeStub;
453 formfillinfo->FFI_OnChange = OnChangeStub;
454 formfillinfo->FFI_GetPage = GetPageTrampoline;
455 formfillinfo->FFI_GetCurrentPage = GetCurrentPageStub;
456 formfillinfo->FFI_GetRotation = GetRotationStub;
457 formfillinfo->FFI_ExecuteNamedAction = ExecuteNamedActionStub;
458 formfillinfo->FFI_SetTextFieldFocus = SetTextFieldFocusStub;
459 formfillinfo->FFI_DoURIAction = DoURIActionTrampoline;
460 formfillinfo->FFI_DoGoToAction = DoGoToActionTrampoline;
461#ifdef PDF_ENABLE_XFA
462 formfillinfo->FFI_DisplayCaret = DisplayCaretStub;
463 formfillinfo->FFI_GetCurrentPageIndex = GetCurrentPageIndexStub;
464 formfillinfo->FFI_SetCurrentPage = SetCurrentPageStub;
465 formfillinfo->FFI_GotoURL = GotoURLStub;
466 formfillinfo->FFI_GetPageViewRect = GetPageViewRectStub;
467 formfillinfo->FFI_PageEvent = PageEventStub;
468 formfillinfo->FFI_PopupMenu = PopupMenuStub;
469 formfillinfo->FFI_OpenFile = OpenFileStub;
470 formfillinfo->FFI_EmailTo = EmailToStub;
471 formfillinfo->FFI_UploadTo = UploadToStub;
472 formfillinfo->FFI_GetPlatform = GetPlatformStub;
473 formfillinfo->FFI_GetLanguage = GetLanguageStub;
474 formfillinfo->FFI_DownloadFromURL = DownloadFromURLStub;
475 formfillinfo->FFI_PostRequestURL = PostRequestURLStub;
476 formfillinfo->FFI_PutRequestURL = PutRequestURLStub;
477#endif // PDF_ENABLE_XFA
478 formfillinfo->FFI_OnFocusChange = OnFocusChangeTrampoline;
480 DoURIActionWithKeyboardModifierTrampoline;
481
482 if (javascript_option == JavaScriptOption::kEnableJavaScript)
483 formfillinfo->m_pJsPlatform = platform;
484
485 FPDF_FORMHANDLE form_handle =
488 return form_handle;
489}
490
496
499 (void)FPDFAvail_IsPageAvail(avail(), first_page,
500 fake_file_access_->GetDownloadHints());
501 return first_page;
502}
503
505 int page_count = FPDF_GetPageCount(document());
506 for (int i = 0; i < page_count; ++i)
507 (void)FPDFAvail_IsPageAvail(avail(), i,
508 fake_file_access_->GetDownloadHints());
509 return page_count;
510}
511
513 int page_index) {
514 return ScopedEmbedderTestPage(this, page_index);
515}
516
517FPDF_PAGE EmbedderTest::LoadPage(int page_index) {
518 return LoadPageCommon(page_index, /*do_events=*/true);
519}
520
521FPDF_PAGE EmbedderTest::LoadPageNoEvents(int page_index) {
522 return LoadPageCommon(page_index, /*do_events=*/false);
523}
524
525FPDF_PAGE EmbedderTest::LoadPageCommon(int page_index, bool do_events) {
527 CHECK_GE(page_index, 0);
528 CHECK(!pdfium::Contains(page_map_, page_index));
529
530 FPDF_PAGE page = FPDF_LoadPage(document(), page_index);
531 if (!page)
532 return nullptr;
533
534 if (do_events) {
537 }
538 page_map_[page_index] = page;
539 return page;
540}
541
542void EmbedderTest::UnloadPage(FPDF_PAGE page) {
543 UnloadPageCommon(page, true);
544}
545
546void EmbedderTest::UnloadPageNoEvents(FPDF_PAGE page) {
547 UnloadPageCommon(page, false);
548}
549
550void EmbedderTest::UnloadPageCommon(FPDF_PAGE page, bool do_events) {
552 int page_index = GetPageNumberForLoadedPage(page);
553 CHECK_GE(page_index, 0);
554
555 if (do_events) {
558 }
560 page_map_.erase(page_index);
561}
562
567
569 return RenderLoadedPageWithFlags(page, 0);
570}
571
573 int flags) {
574 int page_index = GetPageNumberForLoadedPage(page);
575 CHECK_GE(page_index, 0);
576 return RenderPageWithFlags(page, form_handle(), flags);
577}
578
580 return RenderSavedPageWithFlags(page, 0);
581}
582
584 int flags) {
585 int page_index = GetPageNumberForSavedPage(page);
586 CHECK_GE(page_index, 0);
587 return RenderPageWithFlags(page, saved_form_handle(), flags);
588}
589
590// static
591ScopedFPDFBitmap EmbedderTest::RenderPageWithFlags(FPDF_PAGE page,
592 FPDF_FORMHANDLE handle,
593 int flags) {
594 int width = static_cast<int>(FPDF_GetPageWidthF(page));
595 int height = static_cast<int>(FPDF_GetPageHeightF(page));
596 int alpha = FPDFPage_HasTransparency(page) ? 1 : 0;
597 ScopedFPDFBitmap bitmap(FPDFBitmap_Create(width, height, alpha));
598 FPDF_DWORD fill_color = alpha ? 0x00000000 : 0xFFFFFFFF;
599 if (!FPDFBitmap_FillRect(bitmap.get(), 0, 0, width, height, fill_color)) {
600 return nullptr;
601 }
602 FPDF_RenderPageBitmap(bitmap.get(), page, 0, 0, width, height, 0, flags);
603 FPDF_FFLDraw(handle, bitmap.get(), page, 0, 0, width, height, 0, flags);
604 return bitmap;
605}
606
607// static
608ScopedFPDFBitmap EmbedderTest::RenderPage(FPDF_PAGE page) {
609 return RenderPageWithFlags(page, nullptr, 0);
610}
611
612#if BUILDFLAG(IS_WIN)
613// static
614std::vector<uint8_t> EmbedderTest::RenderPageWithFlagsToEmf(FPDF_PAGE page,
615 int flags) {
616 HDC dc = CreateEnhMetaFileA(nullptr, nullptr, nullptr, nullptr);
617
618 int width = static_cast<int>(FPDF_GetPageWidthF(page));
619 int height = static_cast<int>(FPDF_GetPageHeightF(page));
620 HRGN rgn = CreateRectRgn(0, 0, width, height);
621 SelectClipRgn(dc, rgn);
622 DeleteObject(rgn);
623
624 SelectObject(dc, GetStockObject(NULL_PEN));
625 SelectObject(dc, GetStockObject(WHITE_BRUSH));
626 // If a PS_NULL pen is used, the dimensions of the rectangle are 1 pixel less.
627 Rectangle(dc, 0, 0, width + 1, height + 1);
628
629 FPDF_RenderPage(dc, page, 0, 0, width, height, 0, flags);
630
631 HENHMETAFILE emf = CloseEnhMetaFile(dc);
632 UINT size_in_bytes = GetEnhMetaFileBits(emf, 0, nullptr);
633 std::vector<uint8_t> buffer(size_in_bytes);
634 GetEnhMetaFileBits(emf, size_in_bytes, buffer.data());
635 DeleteEnhMetaFile(emf);
636 return buffer;
637}
638
639// static
640std::string EmbedderTest::GetPostScriptFromEmf(
641 pdfium::span<const uint8_t> emf_data) {
642 // This comes from Emf::InitFromData() in Chromium.
643 HENHMETAFILE emf = SetEnhMetaFileBits(
644 pdfium::checked_cast<UINT>(emf_data.size()), emf_data.data());
645 if (!emf)
646 return std::string();
647
648 // This comes from Emf::Enumerator::Enumerator() in Chromium.
649 std::vector<const ENHMETARECORD*> records;
650 if (!EnumEnhMetaFile(nullptr, emf, &GetRecordProc, &records, nullptr)) {
651 DeleteEnhMetaFile(emf);
652 return std::string();
653 }
654
655 // This comes from PostScriptMetaFile::SafePlayback() in Chromium.
656 std::string ps_data;
657 for (const auto* record : records) {
658 if (record->iType != EMR_GDICOMMENT)
659 continue;
660
661 // PostScript data is encapsulated inside EMF comment records.
662 // The first two bytes of the comment indicate the string length. The rest
663 // is the actual string data.
664 const auto* comment = reinterpret_cast<const EMRGDICOMMENT*>(record);
665 const char* data = reinterpret_cast<const char*>(comment->Data);
666 uint16_t size = *reinterpret_cast<const uint16_t*>(data);
667 data += 2;
668 ps_data.append(data, size);
669 }
670 DeleteEnhMetaFile(emf);
671 return ps_data;
672}
673#endif // BUILDFLAG(IS_WIN)
674
677}
678
679// static
683 return GetCompsFromFormat(fx_format);
684}
685
687 const char* password) {
688 FXSYS_memset(&saved_file_access_, 0, sizeof(saved_file_access_));
689 saved_file_access_.m_FileLen =
690 pdfium::checked_cast<unsigned long>(data_string_.size());
691 saved_file_access_.m_GetBlock = GetBlockFromString;
692 // Copy data to prevent clearing it before saved document close.
693 saved_document_file_data_ = data_string_;
694 saved_file_access_.m_Param = &saved_document_file_data_;
695
696 saved_fake_file_access_ =
697 std::make_unique<FakeFileAccess>(&saved_file_access_);
698
699 EXPECT_TRUE(OpenDocumentHelper(
700 password, LinearizeOption::kDefaultLinearize,
701 JavaScriptOption::kEnableJavaScript, saved_fake_file_access_.get(),
702 &saved_document_, &saved_avail_, &saved_form_handle_));
703 return saved_document();
704}
705
708
709 saved_form_handle_.reset();
710 saved_document_.reset();
711 saved_avail_.reset();
712}
713
714FPDF_PAGE EmbedderTest::LoadSavedPage(int page_index) {
716 CHECK_GE(page_index, 0);
717 CHECK(!pdfium::Contains(saved_page_map_, page_index));
718
719 FPDF_PAGE page = FPDF_LoadPage(saved_document(), page_index);
720 if (!page)
721 return nullptr;
722
725 saved_page_map_[page_index] = page;
726 return page;
727}
728
729void EmbedderTest::CloseSavedPage(FPDF_PAGE page) {
731
732 int page_index = GetPageNumberForSavedPage(page);
733 CHECK_GE(page_index, 0);
734
738
739 saved_page_map_.erase(page_index);
740}
741
743 int width,
744 int height,
745 const char* md5) {
747 CHECK(page);
748
749 ScopedFPDFBitmap bitmap = RenderSavedPageWithFlags(page, FPDF_ANNOT);
750 CompareBitmap(bitmap.get(), width, height, md5);
751}
752
753void EmbedderTest::VerifySavedDocument(int width, int height, const char* md5) {
754 ASSERT_TRUE(OpenSavedDocument());
755 FPDF_PAGE page = LoadSavedPage(0);
756 VerifySavedRendering(page, width, height, md5);
759}
760
762 CHECK(fake_file_access_);
763 fake_file_access_->SetWholeFileAvailable();
764}
765
767 document_.reset(FPDFAvail_GetDocument(avail(), nullptr));
768}
769
770void EmbedderTest::CreateAvail(FX_FILEAVAIL* file_avail,
771 FPDF_FILEACCESS* file) {
772 avail_.reset(FPDFAvail_Create(file_avail, file));
773}
774
775FPDF_PAGE EmbedderTest::Delegate::GetPage(FPDF_FORMFILLINFO* info,
776 FPDF_DOCUMENT document,
777 int page_index) {
778 EmbedderTest* test = static_cast<EmbedderTest*>(info);
779 auto it = test->page_map_.find(page_index);
780 return it != test->page_map_.end() ? it->second : nullptr;
781}
782
783// static
784std::string EmbedderTest::HashBitmap(FPDF_BITMAP bitmap) {
785 int stride = FPDFBitmap_GetStride(bitmap);
786 int usable_bytes_per_row =
787 GetBitmapBytesPerPixel(bitmap) * FPDFBitmap_GetWidth(bitmap);
788 int height = FPDFBitmap_GetHeight(bitmap);
789 auto span =
790 pdfium::make_span(static_cast<uint8_t*>(FPDFBitmap_GetBuffer(bitmap)),
791 static_cast<size_t>(stride) * height);
792
794 for (int i = 0; i < height; ++i)
795 CRYPT_MD5Update(&context, span.subspan(i * stride, usable_bytes_per_row));
796 uint8_t digest[16];
797 CRYPT_MD5Finish(&context, digest);
798 return CryptToBase16(digest);
799}
800
801// static
802void EmbedderTest::WriteBitmapToPng(FPDF_BITMAP bitmap,
803 const std::string& filename) {
805}
806
807// static
808void EmbedderTest::CompareBitmap(FPDF_BITMAP bitmap,
809 int expected_width,
810 int expected_height,
811 const char* expected_md5sum) {
812 ASSERT_EQ(expected_width, FPDFBitmap_GetWidth(bitmap));
813 ASSERT_EQ(expected_height, FPDFBitmap_GetHeight(bitmap));
814
815 // The expected stride is calculated using the same formula as in
816 // CFX_DIBitmap::CalculatePitchAndSize(), which sets the bitmap stride.
817 const int expected_stride =
818 (expected_width * GetBitmapBytesPerPixel(bitmap) * 8 + 31) / 32 * 4;
819 ASSERT_EQ(expected_stride, FPDFBitmap_GetStride(bitmap));
820
821 if (!expected_md5sum)
822 return;
823
824 std::string actual_md5sum = HashBitmap(bitmap);
825 EXPECT_EQ(expected_md5sum, actual_md5sum);
827 WriteBitmapToPng(bitmap, actual_md5sum + ".png");
828 }
829}
830
831// static
832int EmbedderTest::WriteBlockCallback(FPDF_FILEWRITE* pFileWrite,
833 const void* data,
834 unsigned long size) {
835 EmbedderTest* pThis = static_cast<EmbedderTest*>(pFileWrite);
836
837 pThis->data_string_.append(static_cast<const char*>(data), size);
838
839 if (pThis->filestream_.is_open())
840 pThis->filestream_.write(static_cast<const char*>(data), size);
841
842 return 1;
843}
844
845// static
847 unsigned long pos,
848 unsigned char* buf,
849 unsigned long size) {
850 std::string* new_file = static_cast<std::string*>(param);
851 CHECK(new_file);
852
853 pdfium::CheckedNumeric<size_t> end = pos;
854 end += size;
855 CHECK_LE(end.ValueOrDie(), new_file->size());
856
857 FXSYS_memcpy(buf, new_file->data() + pos, size);
858 return 1;
859}
860
861// static
862int EmbedderTest::GetPageNumberForPage(const PageNumberToHandleMap& page_map,
863 FPDF_PAGE page) {
864 for (const auto& it : page_map) {
865 if (it.second == page) {
866 int page_index = it.first;
867 CHECK_GE(page_index, 0);
868 return page_index;
869 }
870 }
871 return -1;
872}
873
874int EmbedderTest::GetPageNumberForLoadedPage(FPDF_PAGE page) const {
875 return GetPageNumberForPage(page_map_, page);
876}
877
878int EmbedderTest::GetPageNumberForSavedPage(FPDF_PAGE page) const {
879 return GetPageNumberForPage(saved_page_map_, page);
880}
881
882#ifndef NDEBUG
883void EmbedderTest::OpenPDFFileForWrite(const std::string& filename) {
884 filestream_.open(filename, std::ios_base::binary);
885}
886
888 filestream_.close();
889}
890#endif
891
893 int page_index)
894 : test_(test), page_(test->LoadPage(page_index)) {}
895
897 EmbedderTest::ScopedEmbedderTestPage&& that) noexcept
898 : test_(std::move(that.test_)), page_(std::exchange(that.page_, nullptr)) {}
899
902 EmbedderTest::ScopedEmbedderTestPage&& that) noexcept {
903 test_ = std::move(that.test_);
904 page_ = std::exchange(that.page_, nullptr);
905 return *this;
906}
907
909 if (page_) {
910 test_->UnloadPage(page_);
911 }
912}
#define CHECK_GE(x, y)
Definition check_op.h:15
#define CHECK_LE(x, y)
Definition check_op.h:14
#define CHECK_NE(x, y)
Definition check_op.h:11
static void WriteBitmapToPng(FPDF_BITMAP bitmap, const std::string &filename)
static EmbedderTestEnvironment * GetInstance()
virtual void UnsupportedHandler(int type)
virtual void DoGoToAction(FPDF_FORMFILLINFO *info, int page_index, int zoom_mode, float *pos_arry, int array_size)
virtual int SetTimer(int msecs, TimerCallback fn)
virtual int Alert(FPDF_WIDESTRING message, FPDF_WIDESTRING title, int type, int icon)
virtual void DoURIAction(FPDF_BYTESTRING uri)
virtual FPDF_PAGE GetPage(FPDF_FORMFILLINFO *info, FPDF_DOCUMENT document, int page_index)
virtual void KillTimer(int id)
virtual void OnFocusChange(FPDF_FORMFILLINFO *info, FPDF_ANNOTATION annot, int page_index)
virtual void DoURIActionWithKeyboardModifier(FPDF_FORMFILLINFO *info, FPDF_BYTESTRING uri, int modifiers)
ScopedEmbedderTestPage(EmbedderTest *test, int page_index)
ScopedEmbedderTestPage & operator=(ScopedEmbedderTestPage &&) noexcept
ScopedEmbedderTestPage(ScopedEmbedderTestPage &&) noexcept
ScopedFPDFBitmap RenderLoadedPage(FPDF_PAGE page)
void SetUp() override
ScopedFPDFBitmap RenderLoadedPageWithFlags(FPDF_PAGE page, int flags)
ScopedEmbedderTestPage LoadScopedPage(int page_index)
void SetWholeFileAvailable()
void VerifySavedDocument(int width, int height, const char *md5)
FPDF_DOCUMENT OpenSavedDocumentWithPassword(const char *password)
void VerifySavedRendering(FPDF_PAGE page, int width, int height, const char *md5)
void SetInitialFormFieldHighlight(FPDF_FORMHANDLE form)
FPDF_DOCUMENT saved_document() const
void CloseSavedDocument()
FPDF_DOCUMENT OpenSavedDocument()
ScopedFPDFBitmap RenderSavedPageWithFlags(FPDF_PAGE page, int flags)
FPDF_FORMHANDLE SetupFormFillEnvironment(FPDF_DOCUMENT doc, JavaScriptOption javascript_option)
FPDF_PAGE LoadPageNoEvents(int page_index)
void TearDown() override
FPDF_PAGE LoadPage(int page_index)
FPDF_FORMHANDLE saved_form_handle() const
static void CompareBitmap(FPDF_BITMAP bitmap, int expected_width, int expected_height, const char *expected_md5sum)
void UnloadPage(FPDF_PAGE page)
bool OpenDocumentHelper(const char *password, LinearizeOption linearize_option, JavaScriptOption javascript_option, FakeFileAccess *network_simulator, ScopedFPDFDocument *document, ScopedFPDFAvail *avail, ScopedFPDFFormHandle *form_handle)
void ClosePDFFileForWrite()
static int GetBlockFromString(void *param, unsigned long pos, unsigned char *buf, unsigned long size)
FPDF_DOCUMENT document() const
ScopedFPDFBitmap RenderSavedPage(FPDF_PAGE page)
Delegate * GetDelegate()
void UnloadPageNoEvents(FPDF_PAGE page)
void CreateAvail(FX_FILEAVAIL *file_avail, FPDF_FILEACCESS *file)
void CloseSavedPage(FPDF_PAGE page)
static std::string HashBitmap(FPDF_BITMAP bitmap)
void SetDocumentFromAvail()
~EmbedderTest() override
FPDF_FORMHANDLE form_handle() const
static int BytesPerPixelForFormat(int format)
void CreateEmptyDocument()
FPDF_PAGE LoadSavedPage(int page_index)
void CreateEmptyDocumentWithoutFormFillEnvironment()
FX_DOWNLOADHINTS * GetDownloadHints() const
FX_FILEAVAIL * GetFileAvail() const
FPDF_FILEACCESS * GetFileAccess() const
static int GetBlock(void *param, unsigned long pos, unsigned char *pBuf, unsigned long size)
FXDIB_Format FXDIBFormatFromFPDFFormat(int format)
#define PDF_DATA_NOTAVAIL
#define PDF_DATA_ERROR
FPDF_EXPORT int FPDF_CALLCONV FPDFAvail_IsFormAvail(FPDF_AVAIL avail, FX_DOWNLOADHINTS *hints)
#define PDF_LINEARIZED
#define PDF_FORM_ERROR
FPDF_EXPORT int FPDF_CALLCONV FPDFAvail_IsPageAvail(FPDF_AVAIL avail, int page_index, FX_DOWNLOADHINTS *hints)
FPDF_EXPORT FPDF_DOCUMENT FPDF_CALLCONV FPDFAvail_GetDocument(FPDF_AVAIL avail, FPDF_BYTESTRING password)
FPDF_EXPORT int FPDF_CALLCONV FPDFAvail_IsDocAvail(FPDF_AVAIL avail, FX_DOWNLOADHINTS *hints)
FPDF_EXPORT int FPDF_CALLCONV FPDFAvail_GetFirstPageNum(FPDF_DOCUMENT doc)
FPDF_EXPORT int FPDF_CALLCONV FPDFAvail_IsLinearized(FPDF_AVAIL avail)
FPDF_EXPORT FPDF_AVAIL FPDF_CALLCONV FPDFAvail_Create(FX_FILEAVAIL *file_avail, FPDF_FILEACCESS *file)
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPage_HasTransparency(FPDF_PAGE page)
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FSDK_SetUnSpObjProcessHandler(UNSUPPORT_INFO *unsp_info)
Definition fpdf_ext.cpp:67
#define FPDFDOC_AACTION_WC
FPDF_EXPORT void FPDF_CALLCONV FORM_OnAfterLoadPage(FPDF_PAGE page, FPDF_FORMHANDLE hHandle)
FPDF_EXPORT void FPDF_CALLCONV FPDF_SetFormFieldHighlightAlpha(FPDF_FORMHANDLE hHandle, unsigned char alpha)
FPDF_EXPORT void FPDF_CALLCONV FORM_OnBeforeClosePage(FPDF_PAGE page, FPDF_FORMHANDLE hHandle)
#define FORMTYPE_XFA_FOREGROUND
void(* TimerCallback)(int idEvent)
#define FPDFPAGE_AACTION_CLOSE
FPDF_EXPORT void FPDF_CALLCONV FORM_DoPageAAction(FPDF_PAGE page, FPDF_FORMHANDLE hHandle, int aaType)
#define FPDF_FORMFIELD_UNKNOWN
FPDF_EXPORT void FPDF_CALLCONV FORM_DoDocumentJSAction(FPDF_FORMHANDLE hHandle)
#define FORMTYPE_XFA_FULL
FPDF_EXPORT void FPDF_CALLCONV FORM_DoDocumentOpenAction(FPDF_FORMHANDLE hHandle)
FPDF_EXPORT void FPDF_CALLCONV FORM_DoDocumentAAction(FPDF_FORMHANDLE hHandle, int aaType)
FPDF_EXPORT void FPDF_CALLCONV FPDF_SetFormFieldHighlightColor(FPDF_FORMHANDLE hHandle, int fieldType, unsigned long color)
FPDF_EXPORT FPDF_FORMHANDLE FPDF_CALLCONV FPDFDOC_InitFormFillEnvironment(FPDF_DOCUMENT document, FPDF_FORMFILLINFO *formInfo)
#define FPDFPAGE_AACTION_OPEN
FPDF_EXPORT int FPDF_CALLCONV FPDF_GetFormType(FPDF_DOCUMENT document)
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_LoadXFA(FPDF_DOCUMENT document)
FPDF_EXPORT FPDF_PAGE FPDF_CALLCONV FPDF_LoadPage(FPDF_DOCUMENT document, int page_index)
FPDF_EXPORT int FPDF_CALLCONV FPDF_GetPageCount(FPDF_DOCUMENT document)
FPDF_EXPORT FPDF_DOCUMENT FPDF_CALLCONV FPDF_LoadCustomDocument(FPDF_FILEACCESS *pFileAccess, FPDF_BYTESTRING password)
FPDF_EXPORT int FPDF_CALLCONV FPDFBitmap_GetHeight(FPDF_BITMAP bitmap)
FPDF_EXPORT float FPDF_CALLCONV FPDF_GetPageHeightF(FPDF_PAGE page)
FPDF_EXPORT FPDF_BITMAP FPDF_CALLCONV FPDFBitmap_Create(int width, int height, int alpha)
FPDF_EXPORT int FPDF_CALLCONV FPDFBitmap_GetStride(FPDF_BITMAP bitmap)
FPDF_EXPORT int FPDF_CALLCONV FPDFBitmap_GetFormat(FPDF_BITMAP bitmap)
FPDF_EXPORT void *FPDF_CALLCONV FPDFBitmap_GetBuffer(FPDF_BITMAP bitmap)
FPDF_EXPORT int FPDF_CALLCONV FPDFBitmap_GetWidth(FPDF_BITMAP bitmap)
FPDF_EXPORT float FPDF_CALLCONV FPDF_GetPageWidthF(FPDF_PAGE page)
FPDF_EXPORT void FPDF_CALLCONV FPDF_ClosePage(FPDF_PAGE page)
#define FPDF_ANNOT
Definition fpdfview.h:790
CRYPT_md5_context CRYPT_MD5Start()
Definition fx_crypt.cpp:164
int GetCompsFromFormat(FXDIB_Format format)
Definition fx_dib.h:165
FXDIB_Format
Definition fx_dib.h:21
UNSAFE_BUFFER_USAGE void * FXSYS_memset(void *ptr1, int val, size_t len)
#define CHECK(cvref)
int(* WriteBlock)(struct FPDF_FILEWRITE_ *pThis, const void *pData, unsigned long size)
Definition fpdf_save.h:39
int(* FFI_SetTimer)(struct _FPDF_FORMFILLINFO *pThis, int uElapse, TimerCallback lpTimerFunc)
void(* FFI_Invalidate)(struct _FPDF_FORMFILLINFO *pThis, FPDF_PAGE page, double left, double top, double right, double bottom)
void(* FFI_KillTimer)(struct _FPDF_FORMFILLINFO *pThis, int nTimerID)
void(* FFI_SetCursor)(struct _FPDF_FORMFILLINFO *pThis, int nCursorType)
void(* FFI_DoGoToAction)(struct _FPDF_FORMFILLINFO *pThis, int nPageIndex, int zoomMode, float *fPosArray, int sizeofArray)
void(* FFI_DoURIAction)(struct _FPDF_FORMFILLINFO *pThis, FPDF_BYTESTRING bsURI)
void(* FFI_OnFocusChange)(struct _FPDF_FORMFILLINFO *param, FPDF_ANNOTATION annot, int page_index)
IPDF_JSPLATFORM * m_pJsPlatform
void(* FFI_SetTextFieldFocus)(struct _FPDF_FORMFILLINFO *pThis, FPDF_WIDESTRING value, FPDF_DWORD valueLen, FPDF_BOOL is_focus)
void(* FFI_OutputSelectedRect)(struct _FPDF_FORMFILLINFO *pThis, FPDF_PAGE page, double left, double top, double right, double bottom)
int(* FFI_GetRotation)(struct _FPDF_FORMFILLINFO *pThis, FPDF_PAGE page)
void(* FFI_DoURIActionWithKeyboardModifier)(struct _FPDF_FORMFILLINFO *param, FPDF_BYTESTRING uri, int modifiers)
void(* FFI_ExecuteNamedAction)(struct _FPDF_FORMFILLINFO *pThis, FPDF_BYTESTRING namedAction)
void(* FFI_OnChange)(struct _FPDF_FORMFILLINFO *pThis)
int(* app_alert)(struct _IPDF_JsPlatform *pThis, FPDF_WIDESTRING Msg, FPDF_WIDESTRING Title, int Type, int Icon)
void(* FSDK_UnSupport_Handler)(struct _UNSUPPORT_INFO *pThis, int nType)
Definition fpdf_ext.h:61