diff options
author | Tom Sepez <tsepez@chromium.org> | 2014-12-17 16:24:01 -0800 |
---|---|---|
committer | Tom Sepez <tsepez@chromium.org> | 2014-12-17 16:24:01 -0800 |
commit | 5ee12d778eb90ad865085680d49cd9f0391f3edd (patch) | |
tree | 000d3c154cfdf74f54d425ad7a37bf8315881a99 | |
parent | 1a6785b2dd574e61ee3d666fb7fff3f09599776d (diff) | |
download | pdfium-5ee12d778eb90ad865085680d49cd9f0391f3edd.tar.xz |
Initialize V8 external data (XFA version).
This is a quick patch to fix the segv which occurs in pdfium_test when
the v8 external data is not provided. Fixing the full-up initialization
is left as a follow-on exercise.
Path manipulations remain a nuisance since we don't want to depend on a
particular /base library.
BUG=439793
R=thestig@chromium.org
Review URL: https://codereview.chromium.org/810793004
-rw-r--r-- | samples/pdfium_test.cc | 210 |
1 files changed, 157 insertions, 53 deletions
diff --git a/samples/pdfium_test.cc b/samples/pdfium_test.cc index 19e8b7ee57..61732d52b2 100644 --- a/samples/pdfium_test.cc +++ b/samples/pdfium_test.cc @@ -11,6 +11,7 @@ #include <list> #include <string> #include <utility> +#include <vector> #include "../fpdfsdk/include/fpdf_dataavail.h" #include "../fpdfsdk/include/fpdf_ext.h" @@ -21,7 +22,10 @@ #include "v8/include/v8.h" #ifdef _WIN32 - #define snprintf _snprintf +#define snprintf _snprintf +#define PATH_SEPARATOR '\\' +#else +#define PATH_SEPARATOR '/' #endif enum OutputFormat { @@ -33,6 +37,80 @@ enum OutputFormat { #endif }; +struct Options { + Options() : output_format(OUTPUT_NONE) { } + + OutputFormat output_format; + std::string exe_path; + std::string bin_directory; +}; + +// 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 + static void WritePpm(const char* pdf_name, int num, const void* buffer_void, int stride, int width, int height) { const char* buffer = reinterpret_cast<const char*>(buffer_void); @@ -198,34 +276,57 @@ void Unsupported_Handler(UNSUPPORT_INFO*, int type) { printf("Unsupported feature: %s.\n", feature.c_str()); } -bool ParseCommandLine(int argc, const char* argv[], OutputFormat* output_format, - std::list<const char*>* files) { - *output_format = OUTPUT_NONE; - files->clear(); - - int cur_arg = 1; - for (; cur_arg < argc; ++cur_arg) { - if (strcmp(argv[cur_arg], "--ppm") == 0) - *output_format = OUTPUT_PPM; +bool ParseCommandLine(const std::vector<std::string>& args, + Options* options, std::list<std::string>* files) { + if (args.empty()) { + return false; + } + options->exe_path = args[0]; + int cur_idx = 1; + for (; cur_idx < args.size(); ++cur_idx) { + const std::string& cur_arg = args[cur_idx]; + if (cur_arg == "--ppm") { + if (options->output_format != OUTPUT_NONE) { + fprintf(stderr, "Duplicate or conflicting --ppm argument\n"); + return false; + } + options->output_format = OUTPUT_PPM; + } #ifdef _WIN32 - else if (strcmp(argv[cur_arg], "--emf") == 0) - *output_format = OUTPUT_EMF; - else if (strcmp(argv[cur_arg], "--bmp") == 0) - *output_format = OUTPUT_BMP; -#endif + else if (cur_arg == "--emf") { + if (options->output_format != OUTPUT_NONE) { + fprintf(stderr, "Duplicate or conflicting --emf argument\n"); + return false; + } + options->output_format = OUTPUT_EMF; + } + else if (cur_arg == "--bmp") { + if (options->output_format != OUTPUT_NONE) { + fprintf(stderr, "Duplicate or conflicting --bmp argument\n"); + return false; + } + options->output_format = OUTPUT_BMP; + } +#endif // _WIN32 +#ifdef V8_USE_EXTERNAL_STARTUP_DATA + else if (cur_arg.size() > 10 && cur_arg.compare(0, 10, "--bin-dir=") == 0) { + if (!options->bin_directory.empty()) { + fprintf(stderr, "Duplicate --bin-dir argument\n"); + return false; + } + options->bin_directory = cur_arg.substr(10); + } +#endif // V8_USE_EXTERNAL_STARTUP_DATA else break; } - - if (cur_arg > 2) // Multiple options. + if (cur_idx >= args.size()) { + fprintf(stderr, "No input files.\n"); return false; - - if (cur_arg >= argc) // No input files. - return false; - - for (int i = cur_arg; i < argc; i++) - files->push_back(argv[i]); - + } + for (int i = cur_idx; i < args.size(); i++) { + files->push_back(args[i]); + } return true; } @@ -256,9 +357,9 @@ bool Is_Data_Avail(FX_FILEAVAIL* pThis, size_t offset, size_t size) { void Add_Segment(FX_DOWNLOADHINTS* pThis, size_t offset, size_t size) { } -void RenderPdf(const char* name, const char* pBuf, size_t len, +void RenderPdf(const std::string& name, const char* pBuf, size_t len, OutputFormat format) { - printf("Rendering PDF file %s.\n", name); + printf("Rendering PDF file %s.\n", name.c_str()); IPDF_JSPLATFORM platform_callbacks; memset(&platform_callbacks, '\0', sizeof(platform_callbacks)); @@ -350,15 +451,15 @@ void RenderPdf(const char* name, const char* pBuf, size_t len, switch (format) { #ifdef _WIN32 case OUTPUT_BMP: - WriteBmp(name, i, buffer, stride, width, height); + WriteBmp(name.c_str(), i, buffer, stride, width, height); break; case OUTPUT_EMF: - WriteEmf(page, name, i); + WriteEmf(page.c_str(), name, i); break; #endif case OUTPUT_PPM: - WritePpm(name, i, buffer, stride, width, height); + WritePpm(name.c_str(), i, buffer, stride, width, height); break; default: break; @@ -382,19 +483,33 @@ void RenderPdf(const char* name, const char* pBuf, size_t len, } int main(int argc, const char* argv[]) { - v8::V8::InitializeICU(); - OutputFormat format = OUTPUT_NONE; - std::list<const char*> files; - if (!ParseCommandLine(argc, argv, &format, &files)) { + std::vector<std::string> args(argv, argv + argc); + Options options; + std::list<std::string> files; + if (!ParseCommandLine(args, &options, &files)) { printf("Usage: pdfium_test [OPTION] [FILE]...\n"); - printf("--ppm write page images <pdf-name>.<page-number>.ppm\n"); + printf("--bin-dir=<path> - override path to v8 external data\n"); + printf("--ppm - write page images <pdf-name>.<page-number>.ppm\n"); #ifdef _WIN32 - printf("--bmp write page images <pdf-name>.<page-number>.bmp\n"); - printf("--emf write page meta files <pdf-name>.<page-number>.emf\n"); + printf("--bmp - write page images <pdf-name>.<page-number>.bmp\n"); + printf("--emf - write page meta files <pdf-name>.<page-number>.emf\n"); #endif return 1; } + v8::V8::InitializeICU(); + +#ifdef V8_USE_EXTERNAL_STARTUP_DATA + v8::StartupData natives; + v8::StartupData snapshot; + if (!GetExternalData(options, "natives_blob.bin", &natives) || + !GetExternalData(options, "snapshot_blob.bin", &snapshot)) { + return 1; + } + v8::V8::SetNativesDataBlob(&natives); + v8::V8::SetSnapshotDataBlob(&snapshot); +#endif // V8_USE_EXTERNAL_STARTUP_DATA + FPDF_InitLibrary(); UNSUPPORT_INFO unsuppored_info; @@ -405,25 +520,14 @@ int main(int argc, const char* argv[]) { FSDK_SetUnSpObjProcessHandler(&unsuppored_info); while (!files.empty()) { - const char* filename = files.front(); + std::string filename = files.front(); files.pop_front(); - FILE* file = fopen(filename, "rb"); - if (!file) { - fprintf(stderr, "Failed to open: %s\n", filename); + size_t file_length = 0; + char* file_contents = GetFileContents(filename.c_str(), &file_length); + if (!file_contents) continue; - } - (void) fseek(file, 0, SEEK_END); - size_t len = ftell(file); - (void) fseek(file, 0, SEEK_SET); - char* pBuf = (char*) malloc(len); - size_t ret = fread(pBuf, 1, len, file); - (void) fclose(file); - if (ret != len) { - fprintf(stderr, "Failed to read: %s\n", filename); - } else { - RenderPdf(filename, pBuf, len, format); - } - free(pBuf); + RenderPdf(filename, file_contents, file_length, options.output_format); + free(file_contents); } FPDF_DestroyLibrary(); |