blob: d789278a5d16ac29ae75cc9add04487939b0fe6c [file] [log] [blame]
Lei Zhang72e8b692019-02-05 19:16:52 +00001// 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
Felix Kauselmann5fe85692019-02-11 20:55:52 +00007#include <cstring>
8
Lei Zhangb6992dd2019-02-05 23:30:20 +00009#include "public/fpdfview.h"
10#include "testing/utils/file_util.h"
Lei Zhang72e8b692019-02-05 19:16:52 +000011#include "testing/utils/path_service.h"
Tom Sepezea03a7b2022-02-24 00:30:14 +000012#include "third_party/base/numerics/safe_conversions.h"
Lei Zhang72e8b692019-02-05 19:16:52 +000013#include "v8/include/libplatform/libplatform.h"
14#include "v8/include/v8.h"
15
Tom Sepez30eddfa2021-02-16 19:24:00 +000016#ifdef PDF_ENABLE_XFA
17#include "v8/include/cppgc/platform.h"
18#endif
19
Lei Zhang72e8b692019-02-05 19:16:52 +000020namespace {
21
22#ifdef V8_USE_EXTERNAL_STARTUP_DATA
23// Returns the full path for an external V8 data file based on either
24// the currect exectuable path or an explicit override.
25std::string GetFullPathForSnapshotFile(const std::string& exe_path,
26 const std::string& bin_dir,
27 const std::string& filename) {
28 std::string result;
29 if (!bin_dir.empty()) {
30 result = bin_dir;
31 if (*bin_dir.rbegin() != PATH_SEPARATOR) {
32 result += PATH_SEPARATOR;
33 }
34 } else if (!exe_path.empty()) {
35 size_t last_separator = exe_path.rfind(PATH_SEPARATOR);
36 if (last_separator != std::string::npos) {
37 result = exe_path.substr(0, last_separator + 1);
38 }
39 }
40 result += filename;
41 return result;
42}
43
44bool GetExternalData(const std::string& exe_path,
45 const std::string& bin_dir,
46 const std::string& filename,
47 v8::StartupData* result_data) {
48 std::string full_path =
49 GetFullPathForSnapshotFile(exe_path, bin_dir, filename);
50 size_t data_length = 0;
51 std::unique_ptr<char, pdfium::FreeDeleter> data_buffer =
52 GetFileContents(full_path.c_str(), &data_length);
53 if (!data_buffer)
54 return false;
55
56 result_data->data = data_buffer.release();
Tom Sepezea03a7b2022-02-24 00:30:14 +000057 result_data->raw_size = pdfium::base::checked_cast<int>(data_length);
Lei Zhang72e8b692019-02-05 19:16:52 +000058 return true;
59}
60#endif // V8_USE_EXTERNAL_STARTUP_DATA
61
Tom Sepeze0d3c502020-08-11 23:51:10 +000062std::unique_ptr<v8::Platform> InitializeV8Common(const std::string& exe_path,
63 const std::string& js_flags) {
Lei Zhang72e8b692019-02-05 19:16:52 +000064 v8::V8::InitializeICUDefaultLocation(exe_path.c_str());
65
66 std::unique_ptr<v8::Platform> platform = v8::platform::NewDefaultPlatform();
67 v8::V8::InitializePlatform(platform.get());
Tom Sepez30eddfa2021-02-16 19:24:00 +000068#ifdef PDF_ENABLE_XFA
69 cppgc::InitializeProcess(platform->GetPageAllocator());
70#endif
Lei Zhang72e8b692019-02-05 19:16:52 +000071
72 const char* recommended_v8_flags = FPDF_GetRecommendedV8Flags();
Lei Zhang06d1acb2019-05-04 07:40:40 +000073 v8::V8::SetFlagsFromString(recommended_v8_flags);
Lei Zhang72e8b692019-02-05 19:16:52 +000074
Tom Sepeze0d3c502020-08-11 23:51:10 +000075 if (!js_flags.empty())
76 v8::V8::SetFlagsFromString(js_flags.c_str());
77
Lei Zhang72e8b692019-02-05 19:16:52 +000078 // By enabling predictable mode, V8 won't post any background tasks.
79 // By enabling GC, it makes it easier to chase use-after-free.
80 static const char kAdditionalV8Flags[] = "--predictable --expose-gc";
Lei Zhang06d1acb2019-05-04 07:40:40 +000081 v8::V8::SetFlagsFromString(kAdditionalV8Flags);
Lei Zhang72e8b692019-02-05 19:16:52 +000082
Tom Sepez238933f2022-06-03 21:39:31 +000083#ifdef V8_ENABLE_SANDBOX
Samuel Großd1b54c32022-05-09 20:52:49 +000084 v8::V8::InitializeSandbox();
85#endif
Lei Zhang72e8b692019-02-05 19:16:52 +000086 v8::V8::Initialize();
87 return platform;
88}
89
90} // namespace
91
92#ifdef V8_USE_EXTERNAL_STARTUP_DATA
93std::unique_ptr<v8::Platform> InitializeV8ForPDFiumWithStartupData(
94 const std::string& exe_path,
Tom Sepeze0d3c502020-08-11 23:51:10 +000095 const std::string& js_flags,
Lei Zhang72e8b692019-02-05 19:16:52 +000096 const std::string& bin_dir,
Lei Zhang72e8b692019-02-05 19:16:52 +000097 v8::StartupData* snapshot_blob) {
Tom Sepeze0d3c502020-08-11 23:51:10 +000098 std::unique_ptr<v8::Platform> platform =
99 InitializeV8Common(exe_path, js_flags);
Lei Zhanga8e8baf2019-10-08 17:53:04 +0000100 if (snapshot_blob) {
Lei Zhang72e8b692019-02-05 19:16:52 +0000101 if (!GetExternalData(exe_path, bin_dir, "snapshot_blob.bin", snapshot_blob))
102 return nullptr;
Lei Zhang72e8b692019-02-05 19:16:52 +0000103 v8::V8::SetSnapshotDataBlob(snapshot_blob);
104 }
105 return platform;
106}
107#else // V8_USE_EXTERNAL_STARTUP_DATA
108std::unique_ptr<v8::Platform> InitializeV8ForPDFium(
Tom Sepeze0d3c502020-08-11 23:51:10 +0000109 const std::string& exe_path,
110 const std::string& js_flags) {
111 return InitializeV8Common(exe_path, js_flags);
Lei Zhang72e8b692019-02-05 19:16:52 +0000112}
113#endif // V8_USE_EXTERNAL_STARTUP_DATA
Tom Sepez30eddfa2021-02-16 19:24:00 +0000114
115void ShutdownV8ForPDFium() {
116#ifdef PDF_ENABLE_XFA
117 cppgc::ShutdownProcess();
118#endif
Tom Sepeze506d562022-01-24 20:52:53 +0000119 v8::V8::Dispose();
Alan Screen5e30ae82021-12-01 23:08:27 +0000120 v8::V8::DisposePlatform();
Tom Sepez30eddfa2021-02-16 19:24:00 +0000121}