Split V8 initialization code into testing/v8_initializer.h.
Change-Id: Icb63d0e50717261667aa657deab38927f96495f0
Reviewed-on: https://pdfium-review.googlesource.com/c/49892
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
diff --git a/testing/v8_initializer.cpp b/testing/v8_initializer.cpp
new file mode 100644
index 0000000..548be03
--- /dev/null
+++ b/testing/v8_initializer.cpp
@@ -0,0 +1,98 @@
+// Copyright 2019 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "testing/v8_initializer.h"
+
+#include "testing/test_support.h"
+#include "testing/utils/path_service.h"
+#include "v8/include/libplatform/libplatform.h"
+#include "v8/include/v8.h"
+
+namespace {
+
+#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.
+std::string GetFullPathForSnapshotFile(const std::string& exe_path,
+ const std::string& bin_dir,
+ const std::string& filename) {
+ std::string result;
+ if (!bin_dir.empty()) {
+ result = bin_dir;
+ if (*bin_dir.rbegin() != PATH_SEPARATOR) {
+ result += PATH_SEPARATOR;
+ }
+ } else if (!exe_path.empty()) {
+ size_t last_separator = exe_path.rfind(PATH_SEPARATOR);
+ if (last_separator != std::string::npos) {
+ result = exe_path.substr(0, last_separator + 1);
+ }
+ }
+ result += filename;
+ return result;
+}
+
+bool GetExternalData(const std::string& exe_path,
+ const std::string& bin_dir,
+ const std::string& filename,
+ v8::StartupData* result_data) {
+ std::string full_path =
+ GetFullPathForSnapshotFile(exe_path, bin_dir, filename);
+ size_t data_length = 0;
+ std::unique_ptr<char, pdfium::FreeDeleter> data_buffer =
+ GetFileContents(full_path.c_str(), &data_length);
+ if (!data_buffer)
+ return false;
+
+ result_data->data = data_buffer.release();
+ result_data->raw_size = data_length;
+ return true;
+}
+#endif // V8_USE_EXTERNAL_STARTUP_DATA
+
+std::unique_ptr<v8::Platform> InitializeV8Common(const std::string& exe_path) {
+ v8::V8::InitializeICUDefaultLocation(exe_path.c_str());
+
+ std::unique_ptr<v8::Platform> platform = v8::platform::NewDefaultPlatform();
+ v8::V8::InitializePlatform(platform.get());
+
+ const char* recommended_v8_flags = FPDF_GetRecommendedV8Flags();
+ v8::V8::SetFlagsFromString(recommended_v8_flags,
+ static_cast<int>(strlen(recommended_v8_flags)));
+
+ // By enabling predictable mode, V8 won't post any background tasks.
+ // By enabling GC, it makes it easier to chase use-after-free.
+ static const char kAdditionalV8Flags[] = "--predictable --expose-gc";
+ v8::V8::SetFlagsFromString(kAdditionalV8Flags,
+ static_cast<int>(strlen(kAdditionalV8Flags)));
+
+ v8::V8::Initialize();
+ return platform;
+}
+
+} // namespace
+
+#ifdef V8_USE_EXTERNAL_STARTUP_DATA
+std::unique_ptr<v8::Platform> InitializeV8ForPDFiumWithStartupData(
+ const std::string& exe_path,
+ const std::string& bin_dir,
+ v8::StartupData* natives_blob,
+ v8::StartupData* snapshot_blob) {
+ std::unique_ptr<v8::Platform> platform = InitializeV8Common(exe_path);
+ if (natives_blob && snapshot_blob) {
+ if (!GetExternalData(exe_path, bin_dir, "natives_blob.bin", natives_blob))
+ return nullptr;
+ if (!GetExternalData(exe_path, bin_dir, "snapshot_blob.bin", snapshot_blob))
+ return nullptr;
+ v8::V8::SetNativesDataBlob(natives_blob);
+ v8::V8::SetSnapshotDataBlob(snapshot_blob);
+ }
+ return platform;
+}
+#else // V8_USE_EXTERNAL_STARTUP_DATA
+std::unique_ptr<v8::Platform> InitializeV8ForPDFium(
+ const std::string& exe_path) {
+ return InitializeV8Common(exe_path);
+}
+#endif // V8_USE_EXTERNAL_STARTUP_DATA