#include "testing/embedder_test.h"
#include <algorithm>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "core/fdrm/fx_crypt.h"
#include "core/fxcrt/check.h"
#include "core/fxcrt/check_op.h"
#include "core/fxcrt/containers/contains.h"
#include "core/fxcrt/fx_memcpy_wrappers.h"
#include "core/fxcrt/numerics/checked_math.h"
#include "core/fxcrt/numerics/safe_conversions.h"
#include "fpdfsdk/cpdfsdk_helpers.h"
#include "public/cpp/fpdf_scopers.h"
#include "public/fpdf_dataavail.h"
#include "public/fpdf_edit.h"
#include "public/fpdf_text.h"
#include "public/fpdfview.h"
#include "testing/embedder_test_environment.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/test_loader.h"
#include "testing/utils/bitmap_saver.h"
#include "testing/utils/file_util.h"
#include "testing/utils/hash.h"
#include "testing/utils/path_service.h"
namespace {
int GetBitmapBytesPerPixel(FPDF_BITMAP bitmap) { … }
#if BUILDFLAG(IS_WIN)
int CALLBACK GetRecordProc(HDC hdc,
HANDLETABLE* handle_table,
const ENHMETARECORD* record,
int objects_count,
LPARAM param) {
auto& records = *reinterpret_cast<std::vector<const ENHMETARECORD*>*>(param);
records.push_back(record);
return 1;
}
#endif
void UnsupportedHandlerTrampoline(UNSUPPORT_INFO* info, int type) { … }
int AlertTrampoline(IPDF_JSPLATFORM* platform,
FPDF_WIDESTRING message,
FPDF_WIDESTRING title,
int type,
int icon) { … }
int SetTimerTrampoline(FPDF_FORMFILLINFO* info, int msecs, TimerCallback fn) { … }
void KillTimerTrampoline(FPDF_FORMFILLINFO* info, int id) { … }
FPDF_PAGE GetPageTrampoline(FPDF_FORMFILLINFO* info,
FPDF_DOCUMENT document,
int page_index) { … }
void DoURIActionTrampoline(FPDF_FORMFILLINFO* info, FPDF_BYTESTRING uri) { … }
void DoGoToActionTrampoline(FPDF_FORMFILLINFO* info,
int page_index,
int zoom_mode,
float* pos_array,
int array_size) { … }
void OnFocusChangeTrampoline(FPDF_FORMFILLINFO* info,
FPDF_ANNOTATION annot,
int page_index) { … }
void DoURIActionWithKeyboardModifierTrampoline(FPDF_FORMFILLINFO* info,
FPDF_BYTESTRING uri,
int modifiers) { … }
void InvalidateStub(FPDF_FORMFILLINFO* pThis,
FPDF_PAGE page,
double left,
double top,
double right,
double bottom) { … }
void OutputSelectedRectStub(FPDF_FORMFILLINFO* pThis,
FPDF_PAGE page,
double left,
double top,
double right,
double bottom) { … }
void SetCursorStub(FPDF_FORMFILLINFO* pThis, int nCursorType) { … }
FPDF_SYSTEMTIME GetLocalTimeStub(FPDF_FORMFILLINFO* pThis) { … }
void OnChangeStub(FPDF_FORMFILLINFO* pThis) { … }
FPDF_PAGE GetCurrentPageStub(FPDF_FORMFILLINFO* pThis, FPDF_DOCUMENT document) { … }
int GetRotationStub(FPDF_FORMFILLINFO* pThis, FPDF_PAGE page) { … }
void ExecuteNamedActionStub(FPDF_FORMFILLINFO* pThis, FPDF_BYTESTRING name) { … }
void SetTextFieldFocusStub(FPDF_FORMFILLINFO* pThis,
FPDF_WIDESTRING value,
FPDF_DWORD valueLen,
FPDF_BOOL is_focus) { … }
#ifdef PDF_ENABLE_XFA
void DisplayCaretStub(FPDF_FORMFILLINFO* pThis,
FPDF_PAGE page,
FPDF_BOOL bVisible,
double left,
double top,
double right,
double bottom) { … }
int GetCurrentPageIndexStub(FPDF_FORMFILLINFO* pThis, FPDF_DOCUMENT document) { … }
void SetCurrentPageStub(FPDF_FORMFILLINFO* pThis,
FPDF_DOCUMENT document,
int iCurPage) { … }
void GotoURLStub(FPDF_FORMFILLINFO* pThis,
FPDF_DOCUMENT document,
FPDF_WIDESTRING wsURL) { … }
void GetPageViewRectStub(FPDF_FORMFILLINFO* pThis,
FPDF_PAGE page,
double* left,
double* top,
double* right,
double* bottom) { … }
void PageEventStub(FPDF_FORMFILLINFO* pThis,
int page_count,
FPDF_DWORD event_type) { … }
FPDF_BOOL PopupMenuStub(FPDF_FORMFILLINFO* pThis,
FPDF_PAGE page,
FPDF_WIDGET hWidget,
int menuFlag,
float x,
float y) { … }
FPDF_FILEHANDLER* OpenFileStub(FPDF_FORMFILLINFO* pThis,
int fileFlag,
FPDF_WIDESTRING wsURL,
const char* mode) { … }
void EmailToStub(FPDF_FORMFILLINFO* pThis,
FPDF_FILEHANDLER* fileHandler,
FPDF_WIDESTRING pTo,
FPDF_WIDESTRING pSubject,
FPDF_WIDESTRING pCC,
FPDF_WIDESTRING pBcc,
FPDF_WIDESTRING pMsg) { … }
void UploadToStub(FPDF_FORMFILLINFO* pThis,
FPDF_FILEHANDLER* fileHandler,
int fileFlag,
FPDF_WIDESTRING uploadTo) { … }
int GetPlatformStub(FPDF_FORMFILLINFO* pThis, void* platform, int length) { … }
int GetLanguageStub(FPDF_FORMFILLINFO* pThis, void* language, int length) { … }
FPDF_FILEHANDLER* DownloadFromURLStub(FPDF_FORMFILLINFO* pThis,
FPDF_WIDESTRING URL) { … }
FPDF_BOOL PostRequestURLStub(FPDF_FORMFILLINFO* pThis,
FPDF_WIDESTRING wsURL,
FPDF_WIDESTRING wsData,
FPDF_WIDESTRING wsContentType,
FPDF_WIDESTRING wsEncode,
FPDF_WIDESTRING wsHeader,
FPDF_BSTR* response) { … }
FPDF_BOOL PutRequestURLStub(FPDF_FORMFILLINFO* pThis,
FPDF_WIDESTRING wsURL,
FPDF_WIDESTRING wsData,
FPDF_WIDESTRING wsEncode) { … }
#endif
}
EmbedderTest::EmbedderTest()
: … { … }
EmbedderTest::~EmbedderTest() = default;
void EmbedderTest::SetUp() { … }
void EmbedderTest::TearDown() { … }
void EmbedderTest::CreateEmptyDocument() { … }
void EmbedderTest::CreateEmptyDocumentWithoutFormFillEnvironment() { … }
bool EmbedderTest::OpenDocument(const std::string& filename) { … }
bool EmbedderTest::OpenDocumentLinearized(const std::string& filename) { … }
bool EmbedderTest::OpenDocumentWithPassword(const std::string& filename,
const char* password) { … }
bool EmbedderTest::OpenDocumentWithoutJavaScript(const std::string& filename) { … }
bool EmbedderTest::OpenDocumentWithOptions(const std::string& filename,
const char* password,
LinearizeOption linearize_option,
JavaScriptOption javascript_option) { … }
bool EmbedderTest::OpenDocumentHelper(const char* password,
LinearizeOption linearize_option,
JavaScriptOption javascript_option,
FakeFileAccess* network_simulator,
ScopedFPDFDocument* document,
ScopedFPDFAvail* avail,
ScopedFPDFFormHandle* form_handle) { … }
void EmbedderTest::CloseDocument() { … }
FPDF_FORMHANDLE EmbedderTest::SetupFormFillEnvironment(
FPDF_DOCUMENT doc,
JavaScriptOption javascript_option) { … }
void EmbedderTest::DoOpenActions() { … }
int EmbedderTest::GetFirstPageNum() { … }
int EmbedderTest::GetPageCount() { … }
EmbedderTest::ScopedEmbedderTestPage EmbedderTest::LoadScopedPage(
int page_index) { … }
FPDF_PAGE EmbedderTest::LoadPage(int page_index) { … }
FPDF_PAGE EmbedderTest::LoadPageNoEvents(int page_index) { … }
FPDF_PAGE EmbedderTest::LoadPageCommon(int page_index, bool do_events) { … }
void EmbedderTest::UnloadPage(FPDF_PAGE page) { … }
void EmbedderTest::UnloadPageNoEvents(FPDF_PAGE page) { … }
void EmbedderTest::UnloadPageCommon(FPDF_PAGE page, bool do_events) { … }
void EmbedderTest::SetInitialFormFieldHighlight(FPDF_FORMHANDLE form) { … }
ScopedFPDFBitmap EmbedderTest::RenderLoadedPage(FPDF_PAGE page) { … }
ScopedFPDFBitmap EmbedderTest::RenderLoadedPageWithFlags(FPDF_PAGE page,
int flags) { … }
ScopedFPDFBitmap EmbedderTest::RenderSavedPage(FPDF_PAGE page) { … }
ScopedFPDFBitmap EmbedderTest::RenderSavedPageWithFlags(FPDF_PAGE page,
int flags) { … }
ScopedFPDFBitmap EmbedderTest::RenderPageWithFlags(FPDF_PAGE page,
FPDF_FORMHANDLE handle,
int flags) { … }
ScopedFPDFBitmap EmbedderTest::RenderPage(FPDF_PAGE page) { … }
#if BUILDFLAG(IS_WIN)
std::vector<uint8_t> EmbedderTest::RenderPageWithFlagsToEmf(FPDF_PAGE page,
int flags) {
HDC dc = CreateEnhMetaFileA(nullptr, nullptr, nullptr, nullptr);
int width = static_cast<int>(FPDF_GetPageWidthF(page));
int height = static_cast<int>(FPDF_GetPageHeightF(page));
HRGN rgn = CreateRectRgn(0, 0, width, height);
SelectClipRgn(dc, rgn);
DeleteObject(rgn);
SelectObject(dc, GetStockObject(NULL_PEN));
SelectObject(dc, GetStockObject(WHITE_BRUSH));
Rectangle(dc, 0, 0, width + 1, height + 1);
FPDF_RenderPage(dc, page, 0, 0, width, height, 0, flags);
HENHMETAFILE emf = CloseEnhMetaFile(dc);
UINT size_in_bytes = GetEnhMetaFileBits(emf, 0, nullptr);
std::vector<uint8_t> buffer(size_in_bytes);
GetEnhMetaFileBits(emf, size_in_bytes, buffer.data());
DeleteEnhMetaFile(emf);
return buffer;
}
std::string EmbedderTest::GetPostScriptFromEmf(
pdfium::span<const uint8_t> emf_data) {
HENHMETAFILE emf = SetEnhMetaFileBits(
pdfium::checked_cast<UINT>(emf_data.size()), emf_data.data());
if (!emf)
return std::string();
std::vector<const ENHMETARECORD*> records;
if (!EnumEnhMetaFile(nullptr, emf, &GetRecordProc, &records, nullptr)) {
DeleteEnhMetaFile(emf);
return std::string();
}
std::string ps_data;
for (const auto* record : records) {
if (record->iType != EMR_GDICOMMENT)
continue;
const auto* comment = reinterpret_cast<const EMRGDICOMMENT*>(record);
const char* data = reinterpret_cast<const char*>(comment->Data);
uint16_t size = *reinterpret_cast<const uint16_t*>(data);
data += 2;
ps_data.append(data, size);
}
DeleteEnhMetaFile(emf);
return ps_data;
}
#endif
FPDF_DOCUMENT EmbedderTest::OpenSavedDocument() { … }
int EmbedderTest::BytesPerPixelForFormat(int format) { … }
FPDF_DOCUMENT EmbedderTest::OpenSavedDocumentWithPassword(
const char* password) { … }
void EmbedderTest::CloseSavedDocument() { … }
FPDF_PAGE EmbedderTest::LoadSavedPage(int page_index) { … }
void EmbedderTest::CloseSavedPage(FPDF_PAGE page) { … }
void EmbedderTest::VerifySavedRendering(FPDF_PAGE page,
int width,
int height,
const char* md5) { … }
void EmbedderTest::VerifySavedDocument(int width, int height, const char* md5) { … }
void EmbedderTest::SetWholeFileAvailable() { … }
void EmbedderTest::SetDocumentFromAvail() { … }
void EmbedderTest::CreateAvail(FX_FILEAVAIL* file_avail,
FPDF_FILEACCESS* file) { … }
FPDF_PAGE EmbedderTest::Delegate::GetPage(FPDF_FORMFILLINFO* info,
FPDF_DOCUMENT document,
int page_index) { … }
std::string EmbedderTest::HashBitmap(FPDF_BITMAP bitmap) { … }
void EmbedderTest::WriteBitmapToPng(FPDF_BITMAP bitmap,
const std::string& filename) { … }
void EmbedderTest::CompareBitmap(FPDF_BITMAP bitmap,
int expected_width,
int expected_height,
const char* expected_md5sum) { … }
int EmbedderTest::WriteBlockCallback(FPDF_FILEWRITE* pFileWrite,
const void* data,
unsigned long size) { … }
int EmbedderTest::GetBlockFromString(void* param,
unsigned long pos,
unsigned char* buf,
unsigned long size) { … }
int EmbedderTest::GetPageNumberForPage(const PageNumberToHandleMap& page_map,
FPDF_PAGE page) { … }
int EmbedderTest::GetPageNumberForLoadedPage(FPDF_PAGE page) const { … }
int EmbedderTest::GetPageNumberForSavedPage(FPDF_PAGE page) const { … }
#ifndef NDEBUG
void EmbedderTest::OpenPDFFileForWrite(const std::string& filename) { … }
void EmbedderTest::ClosePDFFileForWrite() { … }
#endif
EmbedderTest::ScopedEmbedderTestPage::ScopedEmbedderTestPage(EmbedderTest* test,
int page_index)
: … { … }
EmbedderTest::ScopedEmbedderTestPage::~ScopedEmbedderTestPage() { … }