1*3ac0a46fSAndroid Build Coastguard Worker // Copyright 2019 The PDFium Authors
2*3ac0a46fSAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*3ac0a46fSAndroid Build Coastguard Worker // found in the LICENSE file.
4*3ac0a46fSAndroid Build Coastguard Worker
5*3ac0a46fSAndroid Build Coastguard Worker #include "testing/v8_initializer.h"
6*3ac0a46fSAndroid Build Coastguard Worker
7*3ac0a46fSAndroid Build Coastguard Worker #include <cstring>
8*3ac0a46fSAndroid Build Coastguard Worker
9*3ac0a46fSAndroid Build Coastguard Worker #include "public/fpdfview.h"
10*3ac0a46fSAndroid Build Coastguard Worker #include "testing/utils/file_util.h"
11*3ac0a46fSAndroid Build Coastguard Worker #include "testing/utils/path_service.h"
12*3ac0a46fSAndroid Build Coastguard Worker #include "third_party/base/numerics/safe_conversions.h"
13*3ac0a46fSAndroid Build Coastguard Worker #include "v8/include/libplatform/libplatform.h"
14*3ac0a46fSAndroid Build Coastguard Worker #include "v8/include/v8-initialization.h"
15*3ac0a46fSAndroid Build Coastguard Worker #include "v8/include/v8-snapshot.h"
16*3ac0a46fSAndroid Build Coastguard Worker
17*3ac0a46fSAndroid Build Coastguard Worker #ifdef PDF_ENABLE_XFA
18*3ac0a46fSAndroid Build Coastguard Worker #include "v8/include/cppgc/platform.h"
19*3ac0a46fSAndroid Build Coastguard Worker #endif
20*3ac0a46fSAndroid Build Coastguard Worker
21*3ac0a46fSAndroid Build Coastguard Worker namespace {
22*3ac0a46fSAndroid Build Coastguard Worker
23*3ac0a46fSAndroid Build Coastguard Worker #ifdef V8_USE_EXTERNAL_STARTUP_DATA
24*3ac0a46fSAndroid Build Coastguard Worker // Returns the full path for an external V8 data file based on either
25*3ac0a46fSAndroid Build Coastguard Worker // the currect exectuable path or an explicit override.
GetFullPathForSnapshotFile(const std::string & exe_path,const std::string & bin_dir,const std::string & filename)26*3ac0a46fSAndroid Build Coastguard Worker std::string GetFullPathForSnapshotFile(const std::string& exe_path,
27*3ac0a46fSAndroid Build Coastguard Worker const std::string& bin_dir,
28*3ac0a46fSAndroid Build Coastguard Worker const std::string& filename) {
29*3ac0a46fSAndroid Build Coastguard Worker std::string result;
30*3ac0a46fSAndroid Build Coastguard Worker if (!bin_dir.empty()) {
31*3ac0a46fSAndroid Build Coastguard Worker result = bin_dir;
32*3ac0a46fSAndroid Build Coastguard Worker if (*bin_dir.rbegin() != PATH_SEPARATOR) {
33*3ac0a46fSAndroid Build Coastguard Worker result += PATH_SEPARATOR;
34*3ac0a46fSAndroid Build Coastguard Worker }
35*3ac0a46fSAndroid Build Coastguard Worker } else if (!exe_path.empty()) {
36*3ac0a46fSAndroid Build Coastguard Worker size_t last_separator = exe_path.rfind(PATH_SEPARATOR);
37*3ac0a46fSAndroid Build Coastguard Worker if (last_separator != std::string::npos) {
38*3ac0a46fSAndroid Build Coastguard Worker result = exe_path.substr(0, last_separator + 1);
39*3ac0a46fSAndroid Build Coastguard Worker }
40*3ac0a46fSAndroid Build Coastguard Worker }
41*3ac0a46fSAndroid Build Coastguard Worker result += filename;
42*3ac0a46fSAndroid Build Coastguard Worker return result;
43*3ac0a46fSAndroid Build Coastguard Worker }
44*3ac0a46fSAndroid Build Coastguard Worker
GetExternalData(const std::string & exe_path,const std::string & bin_dir,const std::string & filename,v8::StartupData * result_data)45*3ac0a46fSAndroid Build Coastguard Worker bool GetExternalData(const std::string& exe_path,
46*3ac0a46fSAndroid Build Coastguard Worker const std::string& bin_dir,
47*3ac0a46fSAndroid Build Coastguard Worker const std::string& filename,
48*3ac0a46fSAndroid Build Coastguard Worker v8::StartupData* result_data) {
49*3ac0a46fSAndroid Build Coastguard Worker std::string full_path =
50*3ac0a46fSAndroid Build Coastguard Worker GetFullPathForSnapshotFile(exe_path, bin_dir, filename);
51*3ac0a46fSAndroid Build Coastguard Worker size_t data_length = 0;
52*3ac0a46fSAndroid Build Coastguard Worker std::unique_ptr<char, pdfium::FreeDeleter> data_buffer =
53*3ac0a46fSAndroid Build Coastguard Worker GetFileContents(full_path.c_str(), &data_length);
54*3ac0a46fSAndroid Build Coastguard Worker if (!data_buffer)
55*3ac0a46fSAndroid Build Coastguard Worker return false;
56*3ac0a46fSAndroid Build Coastguard Worker
57*3ac0a46fSAndroid Build Coastguard Worker result_data->data = data_buffer.release();
58*3ac0a46fSAndroid Build Coastguard Worker result_data->raw_size = pdfium::base::checked_cast<int>(data_length);
59*3ac0a46fSAndroid Build Coastguard Worker return true;
60*3ac0a46fSAndroid Build Coastguard Worker }
61*3ac0a46fSAndroid Build Coastguard Worker #endif // V8_USE_EXTERNAL_STARTUP_DATA
62*3ac0a46fSAndroid Build Coastguard Worker
InitializeV8Common(const std::string & exe_path,const std::string & js_flags)63*3ac0a46fSAndroid Build Coastguard Worker std::unique_ptr<v8::Platform> InitializeV8Common(const std::string& exe_path,
64*3ac0a46fSAndroid Build Coastguard Worker const std::string& js_flags) {
65*3ac0a46fSAndroid Build Coastguard Worker v8::V8::InitializeICUDefaultLocation(exe_path.c_str());
66*3ac0a46fSAndroid Build Coastguard Worker
67*3ac0a46fSAndroid Build Coastguard Worker std::unique_ptr<v8::Platform> platform = v8::platform::NewDefaultPlatform();
68*3ac0a46fSAndroid Build Coastguard Worker v8::V8::InitializePlatform(platform.get());
69*3ac0a46fSAndroid Build Coastguard Worker #ifdef PDF_ENABLE_XFA
70*3ac0a46fSAndroid Build Coastguard Worker cppgc::InitializeProcess(platform->GetPageAllocator());
71*3ac0a46fSAndroid Build Coastguard Worker #endif
72*3ac0a46fSAndroid Build Coastguard Worker
73*3ac0a46fSAndroid Build Coastguard Worker const char* recommended_v8_flags = FPDF_GetRecommendedV8Flags();
74*3ac0a46fSAndroid Build Coastguard Worker v8::V8::SetFlagsFromString(recommended_v8_flags);
75*3ac0a46fSAndroid Build Coastguard Worker
76*3ac0a46fSAndroid Build Coastguard Worker if (!js_flags.empty())
77*3ac0a46fSAndroid Build Coastguard Worker v8::V8::SetFlagsFromString(js_flags.c_str());
78*3ac0a46fSAndroid Build Coastguard Worker
79*3ac0a46fSAndroid Build Coastguard Worker // By enabling predictable mode, V8 won't post any background tasks.
80*3ac0a46fSAndroid Build Coastguard Worker // By enabling GC, it makes it easier to chase use-after-free.
81*3ac0a46fSAndroid Build Coastguard Worker static const char kAdditionalV8Flags[] = "--predictable --expose-gc";
82*3ac0a46fSAndroid Build Coastguard Worker v8::V8::SetFlagsFromString(kAdditionalV8Flags);
83*3ac0a46fSAndroid Build Coastguard Worker
84*3ac0a46fSAndroid Build Coastguard Worker v8::V8::Initialize();
85*3ac0a46fSAndroid Build Coastguard Worker return platform;
86*3ac0a46fSAndroid Build Coastguard Worker }
87*3ac0a46fSAndroid Build Coastguard Worker
88*3ac0a46fSAndroid Build Coastguard Worker } // namespace
89*3ac0a46fSAndroid Build Coastguard Worker
90*3ac0a46fSAndroid Build Coastguard Worker #ifdef V8_USE_EXTERNAL_STARTUP_DATA
InitializeV8ForPDFiumWithStartupData(const std::string & exe_path,const std::string & js_flags,const std::string & bin_dir,v8::StartupData * snapshot_blob)91*3ac0a46fSAndroid Build Coastguard Worker std::unique_ptr<v8::Platform> InitializeV8ForPDFiumWithStartupData(
92*3ac0a46fSAndroid Build Coastguard Worker const std::string& exe_path,
93*3ac0a46fSAndroid Build Coastguard Worker const std::string& js_flags,
94*3ac0a46fSAndroid Build Coastguard Worker const std::string& bin_dir,
95*3ac0a46fSAndroid Build Coastguard Worker v8::StartupData* snapshot_blob) {
96*3ac0a46fSAndroid Build Coastguard Worker std::unique_ptr<v8::Platform> platform =
97*3ac0a46fSAndroid Build Coastguard Worker InitializeV8Common(exe_path, js_flags);
98*3ac0a46fSAndroid Build Coastguard Worker if (snapshot_blob) {
99*3ac0a46fSAndroid Build Coastguard Worker if (!GetExternalData(exe_path, bin_dir, "snapshot_blob.bin", snapshot_blob))
100*3ac0a46fSAndroid Build Coastguard Worker return nullptr;
101*3ac0a46fSAndroid Build Coastguard Worker v8::V8::SetSnapshotDataBlob(snapshot_blob);
102*3ac0a46fSAndroid Build Coastguard Worker }
103*3ac0a46fSAndroid Build Coastguard Worker return platform;
104*3ac0a46fSAndroid Build Coastguard Worker }
105*3ac0a46fSAndroid Build Coastguard Worker #else // V8_USE_EXTERNAL_STARTUP_DATA
InitializeV8ForPDFium(const std::string & exe_path,const std::string & js_flags)106*3ac0a46fSAndroid Build Coastguard Worker std::unique_ptr<v8::Platform> InitializeV8ForPDFium(
107*3ac0a46fSAndroid Build Coastguard Worker const std::string& exe_path,
108*3ac0a46fSAndroid Build Coastguard Worker const std::string& js_flags) {
109*3ac0a46fSAndroid Build Coastguard Worker return InitializeV8Common(exe_path, js_flags);
110*3ac0a46fSAndroid Build Coastguard Worker }
111*3ac0a46fSAndroid Build Coastguard Worker #endif // V8_USE_EXTERNAL_STARTUP_DATA
112*3ac0a46fSAndroid Build Coastguard Worker
ShutdownV8ForPDFium()113*3ac0a46fSAndroid Build Coastguard Worker void ShutdownV8ForPDFium() {
114*3ac0a46fSAndroid Build Coastguard Worker #ifdef PDF_ENABLE_XFA
115*3ac0a46fSAndroid Build Coastguard Worker cppgc::ShutdownProcess();
116*3ac0a46fSAndroid Build Coastguard Worker #endif
117*3ac0a46fSAndroid Build Coastguard Worker v8::V8::Dispose();
118*3ac0a46fSAndroid Build Coastguard Worker v8::V8::DisposePlatform();
119*3ac0a46fSAndroid Build Coastguard Worker }
120