1 // Copyright 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 "testing/test_support.h" 6 7 #include <stdio.h> 8 #include <string.h> 9 10 #include "testing/utils/path_service.h" 11 12 #ifdef PDF_ENABLE_V8 13 #include "v8/include/libplatform/libplatform.h" 14 #endif 15 16 namespace { 17 18 #ifdef PDF_ENABLE_V8 19 #ifdef V8_USE_EXTERNAL_STARTUP_DATA 20 // Returns the full path for an external V8 data file based on either 21 // the currect exectuable path or an explicit override. 22 std::string GetFullPathForSnapshotFile(const std::string& exe_path, 23 const std::string& bin_dir, 24 const std::string& filename) { 25 std::string result; 26 if (!bin_dir.empty()) { 27 result = bin_dir; 28 if (*bin_dir.rbegin() != PATH_SEPARATOR) { 29 result += PATH_SEPARATOR; 30 } 31 } else if (!exe_path.empty()) { 32 size_t last_separator = exe_path.rfind(PATH_SEPARATOR); 33 if (last_separator != std::string::npos) { 34 result = exe_path.substr(0, last_separator + 1); 35 } 36 } 37 result += filename; 38 return result; 39 } 40 41 bool GetExternalData(const std::string& exe_path, 42 const std::string& bin_dir, 43 const std::string& filename, 44 v8::StartupData* result_data) { 45 std::string full_path = 46 GetFullPathForSnapshotFile(exe_path, bin_dir, filename); 47 size_t data_length = 0; 48 std::unique_ptr<char, pdfium::FreeDeleter> data_buffer = 49 GetFileContents(full_path.c_str(), &data_length); 50 if (!data_buffer) 51 return false; 52 53 result_data->data = data_buffer.release(); 54 result_data->raw_size = data_length; 55 return true; 56 } 57 #endif // V8_USE_EXTERNAL_STARTUP_DATA 58 59 void InitializeV8Common(v8::Platform** platform) { 60 v8::V8::InitializeICU(); 61 62 *platform = v8::platform::CreateDefaultPlatform(); 63 v8::V8::InitializePlatform(*platform); 64 v8::V8::Initialize(); 65 66 // By enabling predictable mode, V8 won't post any background tasks. 67 const char predictable_flag[] = "--predictable"; 68 v8::V8::SetFlagsFromString(predictable_flag, 69 static_cast<int>(strlen(predictable_flag))); 70 } 71 #endif // PDF_ENABLE_V8 72 73 } // namespace 74 75 std::unique_ptr<char, pdfium::FreeDeleter> GetFileContents(const char* filename, 76 size_t* retlen) { 77 FILE* file = fopen(filename, "rb"); 78 if (!file) { 79 fprintf(stderr, "Failed to open: %s\n", filename); 80 return nullptr; 81 } 82 (void)fseek(file, 0, SEEK_END); 83 size_t file_length = ftell(file); 84 if (!file_length) { 85 return nullptr; 86 } 87 (void)fseek(file, 0, SEEK_SET); 88 std::unique_ptr<char, pdfium::FreeDeleter> buffer( 89 static_cast<char*>(malloc(file_length))); 90 if (!buffer) { 91 return nullptr; 92 } 93 size_t bytes_read = fread(buffer.get(), 1, file_length, file); 94 (void)fclose(file); 95 if (bytes_read != file_length) { 96 fprintf(stderr, "Failed to read: %s\n", filename); 97 return nullptr; 98 } 99 *retlen = bytes_read; 100 return buffer; 101 } 102 103 std::wstring GetPlatformWString(FPDF_WIDESTRING wstr) { 104 if (!wstr) 105 return nullptr; 106 107 size_t characters = 0; 108 while (wstr[characters]) 109 ++characters; 110 111 std::wstring platform_string(characters, L'\0'); 112 for (size_t i = 0; i < characters + 1; ++i) { 113 const unsigned char* ptr = reinterpret_cast<const unsigned char*>(&wstr[i]); 114 platform_string[i] = ptr[0] + 256 * ptr[1]; 115 } 116 return platform_string; 117 } 118 119 std::unique_ptr<unsigned short, pdfium::FreeDeleter> GetFPDFWideString( 120 const std::wstring& wstr) { 121 size_t length = sizeof(uint16_t) * (wstr.length() + 1); 122 std::unique_ptr<unsigned short, pdfium::FreeDeleter> result( 123 static_cast<unsigned short*>(malloc(length))); 124 char* ptr = reinterpret_cast<char*>(result.get()); 125 size_t i = 0; 126 for (wchar_t w : wstr) { 127 ptr[i++] = w & 0xff; 128 ptr[i++] = (w >> 8) & 0xff; 129 } 130 ptr[i++] = 0; 131 ptr[i] = 0; 132 return result; 133 } 134 135 #ifdef PDF_ENABLE_V8 136 #ifdef V8_USE_EXTERNAL_STARTUP_DATA 137 bool InitializeV8ForPDFium(const std::string& exe_path, 138 const std::string& bin_dir, 139 v8::StartupData* natives_blob, 140 v8::StartupData* snapshot_blob, 141 v8::Platform** platform) { 142 InitializeV8Common(platform); 143 if (!GetExternalData(exe_path, bin_dir, "natives_blob.bin", natives_blob)) 144 return false; 145 if (!GetExternalData(exe_path, bin_dir, "snapshot_blob.bin", snapshot_blob)) 146 return false; 147 v8::V8::SetNativesDataBlob(natives_blob); 148 v8::V8::SetSnapshotDataBlob(snapshot_blob); 149 return true; 150 } 151 #else // V8_USE_EXTERNAL_STARTUP_DATA 152 bool InitializeV8ForPDFium(v8::Platform** platform) { 153 InitializeV8Common(platform); 154 return true; 155 } 156 #endif // V8_USE_EXTERNAL_STARTUP_DATA 157 #endif // PDF_ENABLE_V8 158 159 TestLoader::TestLoader(const char* pBuf, size_t len) 160 : m_pBuf(pBuf), m_Len(len) { 161 } 162 163 // static 164 int TestLoader::GetBlock(void* param, 165 unsigned long pos, 166 unsigned char* pBuf, 167 unsigned long size) { 168 TestLoader* pLoader = static_cast<TestLoader*>(param); 169 if (pos + size < pos || pos + size > pLoader->m_Len) 170 return 0; 171 172 memcpy(pBuf, pLoader->m_pBuf + pos, size); 173 return 1; 174 } 175 176 TestSaver::TestSaver() { 177 FPDF_FILEWRITE::version = 1; 178 FPDF_FILEWRITE::WriteBlock = WriteBlockCallback; 179 } 180 181 void TestSaver::ClearString() { 182 m_String.clear(); 183 } 184 185 // static 186 int TestSaver::WriteBlockCallback(FPDF_FILEWRITE* pFileWrite, 187 const void* data, 188 unsigned long size) { 189 TestSaver* pThis = static_cast<TestSaver*>(pFileWrite); 190 pThis->m_String.append(static_cast<const char*>(data), size); 191 return 1; 192 } 193