1 // Copyright 2019 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/v8_initializer.h"
6
7 #include <cstring>
8
9 #include "public/fpdfview.h"
10 #include "testing/utils/file_util.h"
11 #include "testing/utils/path_service.h"
12 #include "v8/include/libplatform/libplatform.h"
13 #include "v8/include/v8.h"
14
15 namespace {
16
17 #ifdef V8_USE_EXTERNAL_STARTUP_DATA
18 // Returns the full path for an external V8 data file based on either
19 // the currect exectuable path or an explicit override.
GetFullPathForSnapshotFile(const std::string & exe_path,const std::string & bin_dir,const std::string & filename)20 std::string GetFullPathForSnapshotFile(const std::string& exe_path,
21 const std::string& bin_dir,
22 const std::string& filename) {
23 std::string result;
24 if (!bin_dir.empty()) {
25 result = bin_dir;
26 if (*bin_dir.rbegin() != PATH_SEPARATOR) {
27 result += PATH_SEPARATOR;
28 }
29 } else if (!exe_path.empty()) {
30 size_t last_separator = exe_path.rfind(PATH_SEPARATOR);
31 if (last_separator != std::string::npos) {
32 result = exe_path.substr(0, last_separator + 1);
33 }
34 }
35 result += filename;
36 return result;
37 }
38
GetExternalData(const std::string & exe_path,const std::string & bin_dir,const std::string & filename,v8::StartupData * result_data)39 bool GetExternalData(const std::string& exe_path,
40 const std::string& bin_dir,
41 const std::string& filename,
42 v8::StartupData* result_data) {
43 std::string full_path =
44 GetFullPathForSnapshotFile(exe_path, bin_dir, filename);
45 size_t data_length = 0;
46 std::unique_ptr<char, pdfium::FreeDeleter> data_buffer =
47 GetFileContents(full_path.c_str(), &data_length);
48 if (!data_buffer)
49 return false;
50
51 result_data->data = data_buffer.release();
52 result_data->raw_size = data_length;
53 return true;
54 }
55 #endif // V8_USE_EXTERNAL_STARTUP_DATA
56
InitializeV8Common(const std::string & exe_path)57 std::unique_ptr<v8::Platform> InitializeV8Common(const std::string& exe_path) {
58 v8::V8::InitializeICUDefaultLocation(exe_path.c_str());
59
60 std::unique_ptr<v8::Platform> platform = v8::platform::NewDefaultPlatform();
61 v8::V8::InitializePlatform(platform.get());
62
63 const char* recommended_v8_flags = FPDF_GetRecommendedV8Flags();
64 v8::V8::SetFlagsFromString(recommended_v8_flags);
65
66 // By enabling predictable mode, V8 won't post any background tasks.
67 // By enabling GC, it makes it easier to chase use-after-free.
68 static const char kAdditionalV8Flags[] = "--predictable --expose-gc";
69 v8::V8::SetFlagsFromString(kAdditionalV8Flags);
70
71 v8::V8::Initialize();
72 return platform;
73 }
74
75 } // namespace
76
77 #ifdef V8_USE_EXTERNAL_STARTUP_DATA
InitializeV8ForPDFiumWithStartupData(const std::string & exe_path,const std::string & bin_dir,v8::StartupData * snapshot_blob)78 std::unique_ptr<v8::Platform> InitializeV8ForPDFiumWithStartupData(
79 const std::string& exe_path,
80 const std::string& bin_dir,
81 v8::StartupData* snapshot_blob) {
82 std::unique_ptr<v8::Platform> platform = InitializeV8Common(exe_path);
83 if (snapshot_blob) {
84 if (!GetExternalData(exe_path, bin_dir, "snapshot_blob.bin", snapshot_blob))
85 return nullptr;
86 v8::V8::SetSnapshotDataBlob(snapshot_blob);
87 }
88 return platform;
89 }
90 #else // V8_USE_EXTERNAL_STARTUP_DATA
InitializeV8ForPDFium(const std::string & exe_path)91 std::unique_ptr<v8::Platform> InitializeV8ForPDFium(
92 const std::string& exe_path) {
93 return InitializeV8Common(exe_path);
94 }
95 #endif // V8_USE_EXTERNAL_STARTUP_DATA
96