blob: 034291c629768026db87bea3ff8e16863265e5a7 [file] [log] [blame]
[email protected]f55c90ee62014-04-12 00:50:031// Copyright 2014 The Chromium Authors. All rights reserved.
[email protected]58e10452012-02-22 03:34:452// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]f55c90ee62014-04-12 00:50:035#include "extensions/renderer/module_system.h"
[email protected]58e10452012-02-22 03:34:456
7#include "base/bind.h"
[email protected]ad6aa8f92013-06-22 15:34:168#include "base/command_line.h"
kalmanb0c1c502015-04-15 00:25:069#include "base/logging.h"
avi2d124c02015-12-23 06:36:4210#include "base/macros.h"
rdevlin.cronin95cbe922016-06-29 22:40:5211#include "base/metrics/histogram_macros.h"
[email protected]a19a16d82013-06-11 17:45:1212#include "base/strings/string_util.h"
13#include "base/strings/stringprintf.h"
rdevlin.cronin95cbe922016-06-29 22:40:5214#include "base/timer/elapsed_timer.h"
primiano7182d7b2015-01-30 18:02:0315#include "base/trace_event/trace_event.h"
sammcfb8875c2014-10-28 11:51:0416#include "content/public/renderer/render_frame.h"
[email protected]4f1633f2013-03-09 14:26:2417#include "content/public/renderer/render_view.h"
thestigb012bc3d2014-09-18 22:57:1318#include "extensions/common/extension.h"
[email protected]f55c90ee62014-04-12 00:50:0319#include "extensions/common/extensions_client.h"
20#include "extensions/renderer/console.h"
21#include "extensions/renderer/safe_builtins.h"
22#include "extensions/renderer/script_context.h"
rdevlin.croninb2cec912015-06-24 20:36:0123#include "extensions/renderer/script_context_set.h"
rdevlin.cronin1ed2e892016-12-06 21:35:4324#include "extensions/renderer/source_map.h"
bashi6a4854f2015-06-19 00:51:5125#include "extensions/renderer/v8_helpers.h"
[email protected]d9f51dad2014-07-09 05:39:3826#include "gin/modules/module_registry.h"
[email protected]2255a9332013-06-17 05:12:3127#include "third_party/WebKit/public/web/WebFrame.h"
[email protected]58e10452012-02-22 03:34:4528
[email protected]95ee77da2013-03-19 21:11:1129namespace extensions {
30
bashi6a4854f2015-06-19 00:51:5131using namespace v8_helpers;
32
[email protected]58e10452012-02-22 03:34:4533namespace {
34
thestig041f756e2016-10-14 18:26:1835const char kModuleSystem[] = "module_system";
36const char kModuleName[] = "module_name";
37const char kModuleField[] = "module_field";
38const char kModulesField[] = "modules";
[email protected]cc0457712012-03-21 03:56:3839
kalmanec0e3aa2015-04-28 21:50:3240// Logs an error for the calling context in preparation for potentially
41// crashing the renderer, with some added metadata about the context:
[email protected]662c48b2013-07-12 03:50:5242// - Its type (blessed, unblessed, etc).
43// - Whether it's valid.
44// - The extension ID, if one exists.
kalmanec0e3aa2015-04-28 21:50:3245// Crashing won't happen in stable/beta releases, but is encouraged to happen
46// in the less stable released to catch errors early.
[email protected]f55c90ee62014-04-12 00:50:0347void Fatal(ScriptContext* context, const std::string& message) {
[email protected]662c48b2013-07-12 03:50:5248 // Prepend some context metadata.
49 std::string full_message = "(";
50 if (!context->is_valid())
51 full_message += "Invalid ";
52 full_message += context->GetContextTypeDescription();
53 full_message += " context";
54 if (context->extension()) {
55 full_message += " for ";
56 full_message += context->extension()->id();
57 }
58 full_message += ") ";
59 full_message += message;
60
kalman309f98b2015-04-30 00:12:0061 ExtensionsClient* client = ExtensionsClient::Get();
62 if (client->ShouldSuppressFatalErrors()) {
rdevlin.croninb2cec912015-06-24 20:36:0163 console::Error(context->GetRenderFrame(), full_message);
kalman309f98b2015-04-30 00:12:0064 client->RecordDidSuppressFatalError();
65 } else {
rdevlin.croninb2cec912015-06-24 20:36:0166 console::Fatal(context->GetRenderFrame(), full_message);
kalman309f98b2015-04-30 00:12:0067 }
[email protected]ad6aa8f92013-06-22 15:34:1668}
69
[email protected]95c6b3012013-12-02 14:30:3170void Warn(v8::Isolate* isolate, const std::string& message) {
rdevlin.croninb2cec912015-06-24 20:36:0171 ScriptContext* script_context =
jochen520e6222015-10-29 16:21:2472 ScriptContextSet::GetContextByV8Context(isolate->GetCurrentContext());
rdevlin.croninb2cec912015-06-24 20:36:0173 console::Warn(script_context ? script_context->GetRenderFrame() : nullptr,
74 message);
[email protected]ad6aa8f92013-06-22 15:34:1675}
76
[email protected]68e63ea12013-06-05 05:00:5477// Default exception handler which logs the exception.
78class DefaultExceptionHandler : public ModuleSystem::ExceptionHandler {
79 public:
[email protected]f55c90ee62014-04-12 00:50:0380 explicit DefaultExceptionHandler(ScriptContext* context)
bashi6a4854f2015-06-19 00:51:5181 : ModuleSystem::ExceptionHandler(context) {}
[email protected]ad6aa8f92013-06-22 15:34:1682
[email protected]68e63ea12013-06-05 05:00:5483 // Fatally dumps the debug info from |try_catch| to the console.
84 // Make sure this is never used for exceptions that originate in external
85 // code!
dcheng9168b2f2014-10-21 12:38:2486 void HandleUncaughtException(const v8::TryCatch& try_catch) override {
[email protected]dc3d06e2013-09-06 12:21:0387 v8::HandleScope handle_scope(context_->isolate());
[email protected]68e63ea12013-06-05 05:00:5488 std::string stack_trace = "<stack trace unavailable>";
bashi6a4854f2015-06-19 00:51:5189 v8::Local<v8::Value> v8_stack_trace;
90 if (try_catch.StackTrace(context_->v8_context()).ToLocal(&v8_stack_trace)) {
91 v8::String::Utf8Value stack_value(v8_stack_trace);
[email protected]68e63ea12013-06-05 05:00:5492 if (*stack_value)
93 stack_trace.assign(*stack_value, stack_value.length());
94 else
95 stack_trace = "<could not convert stack trace to string>";
96 }
[email protected]662c48b2013-07-12 03:50:5297 Fatal(context_, CreateExceptionString(try_catch) + "{" + stack_trace + "}");
[email protected]68e63ea12013-06-05 05:00:5498 }
99};
100
rdevlin.cronin83a4b3a2015-10-28 21:43:58101// Sets a property on the "exports" object for bindings. Called by JS with
102// exports.$set(<key>, <value>).
103void SetExportsProperty(
104 const v8::FunctionCallbackInfo<v8::Value>& args) {
105 v8::Local<v8::Object> obj = args.This();
rdevlin.cronin415b73b2015-11-13 01:14:47106 CHECK_EQ(2, args.Length());
107 CHECK(args[0]->IsString());
rdevlin.cronin83a4b3a2015-10-28 21:43:58108 v8::Maybe<bool> result =
109 obj->DefineOwnProperty(args.GetIsolate()->GetCurrentContext(),
110 args[0]->ToString(), args[1], v8::ReadOnly);
111 if (!result.FromMaybe(false))
112 LOG(ERROR) << "Failed to set private property on the export.";
113}
114
sammc9152fe902016-10-13 22:34:16115bool ContextNeedsMojoBindings(ScriptContext* context) {
116 // Mojo is only used from JS by some APIs so a context only needs the mojo
117 // bindings if at least one is available.
118 //
119 // Prefer to use Mojo from C++ if possible rather than adding to this list.
120 static const char* const kApisRequiringMojo[] = {
121 "mimeHandlerPrivate", "mojoPrivate",
122 };
123
124 for (const auto* api : kApisRequiringMojo) {
125 if (context->GetAvailability(api).is_available())
126 return true;
127 }
128 return false;
129}
130
[email protected]f55c90ee62014-04-12 00:50:03131} // namespace
[email protected]68e63ea12013-06-05 05:00:54132
133std::string ModuleSystem::ExceptionHandler::CreateExceptionString(
134 const v8::TryCatch& try_catch) {
tfarinaf85316f2015-04-29 17:03:40135 v8::Local<v8::Message> message(try_catch.Message());
[email protected]95ee77da2013-03-19 21:11:11136 if (message.IsEmpty()) {
137 return "try_catch has no message";
138 }
[email protected]58e10452012-02-22 03:34:45139
[email protected]95ee77da2013-03-19 21:11:11140 std::string resource_name = "<unknown resource>";
[email protected]bce20ba2014-06-27 18:18:45141 if (!message->GetScriptOrigin().ResourceName().IsEmpty()) {
[email protected]95ee77da2013-03-19 21:11:11142 v8::String::Utf8Value resource_name_v8(
dcarneya261b772014-11-20 17:55:07143 message->GetScriptOrigin().ResourceName());
[email protected]95ee77da2013-03-19 21:11:11144 resource_name.assign(*resource_name_v8, resource_name_v8.length());
145 }
146
147 std::string error_message = "<no error message>";
148 if (!message->Get().IsEmpty()) {
149 v8::String::Utf8Value error_message_v8(message->Get());
150 error_message.assign(*error_message_v8, error_message_v8.length());
151 }
152
rdevlin.cronin96902d82016-04-14 20:35:07153 int line_number = 0;
154 if (context_) { // |context_| can be null in unittests.
155 auto maybe = message->GetLineNumber(context_->v8_context());
156 line_number = maybe.IsJust() ? maybe.FromJust() : 0;
157 }
[email protected]95ee77da2013-03-19 21:11:11158 return base::StringPrintf("%s:%d: %s",
159 resource_name.c_str(),
bashi6a4854f2015-06-19 00:51:51160 line_number,
[email protected]95ee77da2013-03-19 21:11:11161 error_message.c_str());
162}
163
lazyboyce333962016-04-12 18:22:04164ModuleSystem::ModuleSystem(ScriptContext* context, const SourceMap* source_map)
[email protected]4f1633f2013-03-09 14:26:24165 : ObjectBackedNativeHandler(context),
[email protected]68e63ea12013-06-05 05:00:54166 context_(context),
[email protected]bad9a5f2012-04-13 19:16:54167 source_map_(source_map),
[email protected]68e63ea12013-06-05 05:00:54168 natives_enabled_(0),
[email protected]d9f51dad2014-07-09 05:39:38169 exception_handler_(new DefaultExceptionHandler(context)),
170 weak_factory_(this) {
[email protected]f55c90ee62014-04-12 00:50:03171 RouteFunction(
172 "require",
[email protected]ecde1912012-03-16 06:25:31173 base::Bind(&ModuleSystem::RequireForJs, base::Unretained(this)));
[email protected]f55c90ee62014-04-12 00:50:03174 RouteFunction(
175 "requireNative",
[email protected]4f1633f2013-03-09 14:26:24176 base::Bind(&ModuleSystem::RequireNative, base::Unretained(this)));
[email protected]d9f51dad2014-07-09 05:39:38177 RouteFunction(
178 "requireAsync",
179 base::Bind(&ModuleSystem::RequireAsync, base::Unretained(this)));
[email protected]ca557292013-12-11 08:44:27180 RouteFunction("privates",
[email protected]f55c90ee62014-04-12 00:50:03181 base::Bind(&ModuleSystem::Private, base::Unretained(this)));
[email protected]ecde1912012-03-16 06:25:31182
tfarinaf85316f2015-04-29 17:03:40183 v8::Local<v8::Object> global(context->v8_context()->Global());
[email protected]505ffde2013-12-19 15:47:13184 v8::Isolate* isolate = context->isolate();
jochen300abe232015-11-06 21:17:53185 SetPrivate(global, kModulesField, v8::Object::New(isolate));
186 SetPrivate(global, kModuleSystem, v8::External::New(isolate, this));
[email protected]d9f51dad2014-07-09 05:39:38187
188 gin::ModuleRegistry::From(context->v8_context())->AddObserver(this);
rdevlin.cronin3cf02f522016-08-15 23:12:31189 if (context_->GetRenderFrame() &&
sammc9152fe902016-10-13 22:34:16190 context_->context_type() == Feature::BLESSED_EXTENSION_CONTEXT &&
191 ContextNeedsMojoBindings(context_)) {
sammcfb8875c2014-10-28 11:51:04192 context_->GetRenderFrame()->EnsureMojoBuiltinsAreAvailable(
193 context->isolate(), context->v8_context());
194 }
[email protected]58e10452012-02-22 03:34:45195}
196
kalmanb0c1c502015-04-15 00:25:06197ModuleSystem::~ModuleSystem() {
198}
[email protected]4f1633f2013-03-09 14:26:24199
200void ModuleSystem::Invalidate() {
[email protected]079532242013-03-12 06:01:10201 // Clear the module system properties from the global context. It's polite,
202 // and we use this as a signal in lazy handlers that we no longer exist.
203 {
[email protected]dc3d06e2013-09-06 12:21:03204 v8::HandleScope scope(GetIsolate());
tfarinaf85316f2015-04-29 17:03:40205 v8::Local<v8::Object> global = context()->v8_context()->Global();
jochen300abe232015-11-06 21:17:53206 DeletePrivate(global, kModulesField);
207 DeletePrivate(global, kModuleSystem);
[email protected]079532242013-03-12 06:01:10208 }
209
kalmanb0c1c502015-04-15 00:25:06210 // Invalidate all active and clobbered NativeHandlers we own.
211 for (const auto& handler : native_handler_map_)
212 handler.second->Invalidate();
213 for (const auto& clobbered_handler : clobbered_native_handlers_)
214 clobbered_handler->Invalidate();
[email protected]079532242013-03-12 06:01:10215
[email protected]4f1633f2013-03-09 14:26:24216 ObjectBackedNativeHandler::Invalidate();
[email protected]58e10452012-02-22 03:34:45217}
218
[email protected]b6aad81c2012-03-27 08:45:15219ModuleSystem::NativesEnabledScope::NativesEnabledScope(
220 ModuleSystem* module_system)
221 : module_system_(module_system) {
222 module_system_->natives_enabled_++;
223}
224
225ModuleSystem::NativesEnabledScope::~NativesEnabledScope() {
226 module_system_->natives_enabled_--;
227 CHECK_GE(module_system_->natives_enabled_, 0);
228}
229
[email protected]144114942012-12-04 07:23:23230void ModuleSystem::HandleException(const v8::TryCatch& try_catch) {
[email protected]68e63ea12013-06-05 05:00:54231 exception_handler_->HandleUncaughtException(try_catch);
[email protected]1c6189f2012-05-18 06:45:52232}
233
bashi61ca3c72015-06-26 00:40:10234v8::MaybeLocal<v8::Object> ModuleSystem::Require(
235 const std::string& module_name) {
236 v8::Local<v8::String> v8_module_name;
237 if (!ToV8String(GetIsolate(), module_name, &v8_module_name))
238 return v8::MaybeLocal<v8::Object>();
[email protected]95c6b3012013-12-02 14:30:31239 v8::EscapableHandleScope handle_scope(GetIsolate());
bashi61ca3c72015-06-26 00:40:10240 v8::Local<v8::Value> value = RequireForJsInner(
241 v8_module_name);
242 if (value.IsEmpty() || !value->IsObject())
243 return v8::MaybeLocal<v8::Object>();
244 return handle_scope.Escape(value.As<v8::Object>());
[email protected]ecde1912012-03-16 06:25:31245}
246
[email protected]d8c5fbb2013-06-14 11:35:25247void ModuleSystem::RequireForJs(
[email protected]f55c90ee62014-04-12 00:50:03248 const v8::FunctionCallbackInfo<v8::Value>& args) {
bashi6a4854f2015-06-19 00:51:51249 if (!args[0]->IsString()) {
250 NOTREACHED() << "require() called with a non-string argument";
251 return;
252 }
253 v8::Local<v8::String> module_name = args[0].As<v8::String>();
[email protected]d8c5fbb2013-06-14 11:35:25254 args.GetReturnValue().Set(RequireForJsInner(module_name));
[email protected]ecde1912012-03-16 06:25:31255}
256
[email protected]95c6b3012013-12-02 14:30:31257v8::Local<v8::Value> ModuleSystem::RequireForJsInner(
tfarinaf85316f2015-04-29 17:03:40258 v8::Local<v8::String> module_name) {
[email protected]95c6b3012013-12-02 14:30:31259 v8::EscapableHandleScope handle_scope(GetIsolate());
bashi6a4854f2015-06-19 00:51:51260 v8::Local<v8::Context> v8_context = context()->v8_context();
261 v8::Context::Scope context_scope(v8_context);
[email protected]95ee77da2013-03-19 21:11:11262
tfarinaf85316f2015-04-29 17:03:40263 v8::Local<v8::Object> global(context()->v8_context()->Global());
[email protected]079532242013-03-12 06:01:10264
265 // The module system might have been deleted. This can happen if a different
266 // context keeps a reference to us, but our frame is destroyed (e.g.
267 // background page keeps reference to chrome object in a closed popup).
jochen300abe232015-11-06 21:17:53268 v8::Local<v8::Value> modules_value;
269 if (!GetPrivate(global, kModulesField, &modules_value) ||
270 modules_value->IsUndefined()) {
[email protected]95c6b3012013-12-02 14:30:31271 Warn(GetIsolate(), "Extension view no longer exists");
272 return v8::Undefined(GetIsolate());
[email protected]d2663612013-03-17 09:25:56273 }
[email protected]079532242013-03-12 06:01:10274
tfarinaf85316f2015-04-29 17:03:40275 v8::Local<v8::Object> modules(v8::Local<v8::Object>::Cast(modules_value));
bashi6a4854f2015-06-19 00:51:51276 v8::Local<v8::Value> exports;
rdevlin.cronin75b803b2016-03-02 00:13:47277 if (!GetPrivateProperty(v8_context, modules, module_name, &exports) ||
bashi6a4854f2015-06-19 00:51:51278 !exports->IsUndefined())
[email protected]95c6b3012013-12-02 14:30:31279 return handle_scope.Escape(exports);
[email protected]7c95c1a82012-04-17 02:11:33280
[email protected]d9f51dad2014-07-09 05:39:38281 exports = LoadModule(*v8::String::Utf8Value(module_name));
rdevlin.cronin75b803b2016-03-02 00:13:47282 SetPrivateProperty(v8_context, modules, module_name, exports);
[email protected]95c6b3012013-12-02 14:30:31283 return handle_scope.Escape(exports);
[email protected]58e10452012-02-22 03:34:45284}
285
[email protected]4f1633f2013-03-09 14:26:24286v8::Local<v8::Value> ModuleSystem::CallModuleMethod(
287 const std::string& module_name,
288 const std::string& method_name) {
[email protected]f80685c32014-07-26 19:48:04289 v8::EscapableHandleScope handle_scope(GetIsolate());
tfarinaf85316f2015-04-29 17:03:40290 v8::Local<v8::Value> no_args;
[email protected]f80685c32014-07-26 19:48:04291 return handle_scope.Escape(
292 CallModuleMethod(module_name, method_name, 0, &no_args));
[email protected]a714e462013-01-26 06:33:10293}
294
295v8::Local<v8::Value> ModuleSystem::CallModuleMethod(
296 const std::string& module_name,
297 const std::string& method_name,
[email protected]68e63ea12013-06-05 05:00:54298 int argc,
tfarinaf85316f2015-04-29 17:03:40299 v8::Local<v8::Value> argv[]) {
[email protected]f55c90ee62014-04-12 00:50:03300 TRACE_EVENT2("v8",
301 "v8.callModuleMethod",
302 "module_name",
303 module_name,
304 "method_name",
305 method_name);
[email protected]68e63ea12013-06-05 05:00:54306
[email protected]95c6b3012013-12-02 14:30:31307 v8::EscapableHandleScope handle_scope(GetIsolate());
bashi6a4854f2015-06-19 00:51:51308 v8::Local<v8::Context> v8_context = context()->v8_context();
309 v8::Context::Scope context_scope(v8_context);
310
rdevlin.croninaac306632016-10-18 21:27:46311 v8::Local<v8::Function> function =
312 GetModuleFunction(module_name, method_name);
kozyatinskiydedd4892016-12-01 23:06:53313 if (function.IsEmpty()) {
314 NOTREACHED() << "GetModuleFunction() returns empty function handle";
315 return handle_scope.Escape(v8::Undefined(GetIsolate()));
316 }
[email protected]68e63ea12013-06-05 05:00:54317
[email protected]a714e462013-01-26 06:33:10318 v8::Local<v8::Value> result;
[email protected]2bcbf712012-09-05 06:58:49319 {
bashi6a4854f2015-06-19 00:51:51320 v8::TryCatch try_catch(GetIsolate());
[email protected]2bcbf712012-09-05 06:58:49321 try_catch.SetCaptureMessage(true);
rdevlin.croninaac306632016-10-18 21:27:46322 result = context_->CallFunction(function, argc, argv);
bashi6a4854f2015-06-19 00:51:51323 if (try_catch.HasCaught()) {
[email protected]144114942012-12-04 07:23:23324 HandleException(try_catch);
bashi6a4854f2015-06-19 00:51:51325 result = v8::Undefined(GetIsolate());
326 }
[email protected]2bcbf712012-09-05 06:58:49327 }
[email protected]95c6b3012013-12-02 14:30:31328 return handle_scope.Escape(result);
[email protected]2bcbf712012-09-05 06:58:49329}
330
rdevlin.croninaac306632016-10-18 21:27:46331void ModuleSystem::CallModuleMethodSafe(const std::string& module_name,
332 const std::string& method_name) {
333 v8::HandleScope handle_scope(GetIsolate());
334 v8::Local<v8::Value> no_args;
335 CallModuleMethodSafe(module_name, method_name, 0, &no_args);
336}
337
338void ModuleSystem::CallModuleMethodSafe(
339 const std::string& module_name,
340 const std::string& method_name,
341 std::vector<v8::Local<v8::Value>>* args) {
342 CallModuleMethodSafe(module_name, method_name, args->size(), args->data());
343}
344
345void ModuleSystem::CallModuleMethodSafe(const std::string& module_name,
346 const std::string& method_name,
347 int argc,
348 v8::Local<v8::Value> argv[]) {
349 TRACE_EVENT2("v8", "v8.callModuleMethodSafe", "module_name", module_name,
350 "method_name", method_name);
351
352 v8::HandleScope handle_scope(GetIsolate());
353 v8::Local<v8::Context> v8_context = context()->v8_context();
354 v8::Context::Scope context_scope(v8_context);
355
356 v8::Local<v8::Function> function =
357 GetModuleFunction(module_name, method_name);
kozyatinskiydedd4892016-12-01 23:06:53358 if (function.IsEmpty()) {
359 NOTREACHED() << "GetModuleFunction() returns empty function handle";
360 return;
361 }
rdevlin.croninaac306632016-10-18 21:27:46362
363 {
364 v8::TryCatch try_catch(GetIsolate());
365 try_catch.SetCaptureMessage(true);
366 context_->SafeCallFunction(function, argc, argv);
367 if (try_catch.HasCaught())
368 HandleException(try_catch);
369 }
370}
371
[email protected]f55c90ee62014-04-12 00:50:03372void ModuleSystem::RegisterNativeHandler(
373 const std::string& name,
dchengf6f80662016-04-20 20:26:04374 std::unique_ptr<NativeHandler> native_handler) {
kalmanb0c1c502015-04-15 00:25:06375 ClobberExistingNativeHandler(name);
tzik8f7af2922015-11-25 03:16:48376 native_handler_map_[name] = std::move(native_handler);
[email protected]58e10452012-02-22 03:34:45377}
378
[email protected]95ee77da2013-03-19 21:11:11379void ModuleSystem::OverrideNativeHandlerForTest(const std::string& name) {
kalmanb0c1c502015-04-15 00:25:06380 ClobberExistingNativeHandler(name);
[email protected]11844fa2012-05-10 00:35:59381 overridden_native_handlers_.insert(name);
382}
383
[email protected]ecde1912012-03-16 06:25:31384void ModuleSystem::RunString(const std::string& code, const std::string& name) {
[email protected]dc3d06e2013-09-06 12:21:03385 v8::HandleScope handle_scope(GetIsolate());
bashi6a4854f2015-06-19 00:51:51386 v8::Local<v8::String> v8_code;
387 v8::Local<v8::String> v8_name;
388 if (!ToV8String(GetIsolate(), code.c_str(), &v8_code) ||
389 !ToV8String(GetIsolate(), name.c_str(), &v8_name)) {
390 Warn(GetIsolate(), "Too long code or name.");
391 return;
392 }
393 RunString(v8_code, v8_name);
[email protected]58e10452012-02-22 03:34:45394}
395
[email protected]cc0457712012-03-21 03:56:38396// static
[email protected]4e008e172013-06-13 20:15:48397void ModuleSystem::NativeLazyFieldGetter(
bashi6a4854f2015-06-19 00:51:51398 v8::Local<v8::Name> property,
[email protected]4e008e172013-06-13 20:15:48399 const v8::PropertyCallbackInfo<v8::Value>& info) {
bashi6a4854f2015-06-19 00:51:51400 LazyFieldGetterInner(property.As<v8::String>(), info,
401 &ModuleSystem::RequireNativeFromString);
[email protected]4e008e172013-06-13 20:15:48402}
403
404// static
405void ModuleSystem::LazyFieldGetter(
bashi6a4854f2015-06-19 00:51:51406 v8::Local<v8::Name> property,
[email protected]4e008e172013-06-13 20:15:48407 const v8::PropertyCallbackInfo<v8::Value>& info) {
bashi6a4854f2015-06-19 00:51:51408 LazyFieldGetterInner(property.As<v8::String>(), info, &ModuleSystem::Require);
[email protected]4e008e172013-06-13 20:15:48409}
410
411// static
412void ModuleSystem::LazyFieldGetterInner(
413 v8::Local<v8::String> property,
414 const v8::PropertyCallbackInfo<v8::Value>& info,
[email protected]4f1633f2013-03-09 14:26:24415 RequireFunction require_function) {
rdevlin.cronin95cbe922016-06-29 22:40:52416 base::ElapsedTimer timer;
[email protected]561ddce2012-03-22 01:18:55417 CHECK(!info.Data().IsEmpty());
418 CHECK(info.Data()->IsObject());
jochen300abe232015-11-06 21:17:53419 v8::Isolate* isolate = info.GetIsolate();
420 v8::HandleScope handle_scope(isolate);
tfarinaf85316f2015-04-29 17:03:40421 v8::Local<v8::Object> parameters = v8::Local<v8::Object>::Cast(info.Data());
[email protected]9a598442013-06-04 16:39:12422 // This context should be the same as context()->v8_context().
tfarinaf85316f2015-04-29 17:03:40423 v8::Local<v8::Context> context = parameters->CreationContext();
424 v8::Local<v8::Object> global(context->Global());
jochen300abe232015-11-06 21:17:53425 v8::Local<v8::Value> module_system_value;
426 if (!GetPrivate(context, global, kModuleSystem, &module_system_value) ||
427 !module_system_value->IsExternal()) {
[email protected]bad9a5f2012-04-13 19:16:54428 // ModuleSystem has been deleted.
[email protected]95ee77da2013-03-19 21:11:11429 // TODO(kalman): See comment in header file.
jochen300abe232015-11-06 21:17:53430 Warn(isolate,
[email protected]95c6b3012013-12-02 14:30:31431 "Module system has been deleted, does extension view exist?");
[email protected]4e008e172013-06-13 20:15:48432 return;
[email protected]bad9a5f2012-04-13 19:16:54433 }
[email protected]95ee77da2013-03-19 21:11:11434
[email protected]561ddce2012-03-22 01:18:55435 ModuleSystem* module_system = static_cast<ModuleSystem*>(
tfarinaf85316f2015-04-29 17:03:40436 v8::Local<v8::External>::Cast(module_system_value)->Value());
[email protected]cc0457712012-03-21 03:56:38437
bashi6a4854f2015-06-19 00:51:51438 v8::Local<v8::Value> v8_module_name;
rdevlin.cronin163beed2016-03-04 18:19:09439 if (!GetPrivateProperty(context, parameters, kModuleName, &v8_module_name)) {
jochen300abe232015-11-06 21:17:53440 Warn(isolate, "Cannot find module.");
bashi6a4854f2015-06-19 00:51:51441 return;
442 }
443 std::string name = *v8::String::Utf8Value(v8_module_name);
[email protected]4f1633f2013-03-09 14:26:24444
445 // Switch to our v8 context because we need functions created while running
446 // the require()d module to belong to our context, not the current one.
447 v8::Context::Scope context_scope(context);
448 NativesEnabledScope natives_enabled_scope(module_system);
449
jochen300abe232015-11-06 21:17:53450 v8::TryCatch try_catch(isolate);
bashi61ca3c72015-06-26 00:40:10451 v8::Local<v8::Value> module_value;
452 if (!(module_system->*require_function)(name).ToLocal(&module_value)) {
[email protected]4f1633f2013-03-09 14:26:24453 module_system->HandleException(try_catch);
[email protected]4e008e172013-06-13 20:15:48454 return;
[email protected]95ee77da2013-03-19 21:11:11455 }
[email protected]4f1633f2013-03-09 14:26:24456
tfarinaf85316f2015-04-29 17:03:40457 v8::Local<v8::Object> module = v8::Local<v8::Object>::Cast(module_value);
bashi6a4854f2015-06-19 00:51:51458 v8::Local<v8::Value> field_value;
rdevlin.cronin163beed2016-03-04 18:19:09459 if (!GetPrivateProperty(context, parameters, kModuleField, &field_value)) {
bashi6a4854f2015-06-19 00:51:51460 module_system->HandleException(try_catch);
461 return;
462 }
463 v8::Local<v8::String> field;
464 if (!field_value->ToString(context).ToLocal(&field)) {
465 module_system->HandleException(try_catch);
466 return;
467 }
[email protected]561ddce2012-03-22 01:18:55468
bashi6a4854f2015-06-19 00:51:51469 if (!IsTrue(module->Has(context, field))) {
[email protected]d7cd1b02013-09-10 00:22:16470 std::string field_str = *v8::String::Utf8Value(field);
[email protected]662c48b2013-07-12 03:50:52471 Fatal(module_system->context_,
472 "Lazy require of " + name + "." + field_str + " did not set the " +
473 field_str + " field");
[email protected]4e008e172013-06-13 20:15:48474 return;
[email protected]95ee77da2013-03-19 21:11:11475 }
[email protected]4f1633f2013-03-09 14:26:24476
bashi6a4854f2015-06-19 00:51:51477 v8::Local<v8::Value> new_field;
478 if (!GetProperty(context, module, field, &new_field)) {
[email protected]95ee77da2013-03-19 21:11:11479 module_system->HandleException(try_catch);
[email protected]4e008e172013-06-13 20:15:48480 return;
[email protected]95ee77da2013-03-19 21:11:11481 }
482
483 // Ok for it to be undefined, among other things it's how bindings signify
484 // that the extension doesn't have permission to use them.
485 CHECK(!new_field.IsEmpty());
486
[email protected]4f1633f2013-03-09 14:26:24487 // Delete the getter and set this field to |new_field| so the same object is
488 // returned every time a certain API is accessed.
tfarinaf85316f2015-04-29 17:03:40489 v8::Local<v8::Value> val = info.This();
[email protected]80b0c8c2014-04-22 15:00:43490 if (val->IsObject()) {
tfarinaf85316f2015-04-29 17:03:40491 v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(val);
bashi6a4854f2015-06-19 00:51:51492 object->Delete(context, property);
493 SetProperty(context, object, property, new_field);
[email protected]80b0c8c2014-04-22 15:00:43494 } else {
495 NOTREACHED();
496 }
[email protected]4e008e172013-06-13 20:15:48497 info.GetReturnValue().Set(new_field);
rdevlin.cronin95cbe922016-06-29 22:40:52498
499 UMA_HISTOGRAM_TIMES("Extensions.ApiBindingGenerationTime", timer.Elapsed());
[email protected]561ddce2012-03-22 01:18:55500}
501
tfarinaf85316f2015-04-29 17:03:40502void ModuleSystem::SetLazyField(v8::Local<v8::Object> object,
[email protected]561ddce2012-03-22 01:18:55503 const std::string& field,
504 const std::string& module_name,
505 const std::string& module_field) {
[email protected]f55c90ee62014-04-12 00:50:03506 SetLazyField(
507 object, field, module_name, module_field, &ModuleSystem::LazyFieldGetter);
[email protected]4f1633f2013-03-09 14:26:24508}
509
tfarinaf85316f2015-04-29 17:03:40510void ModuleSystem::SetLazyField(v8::Local<v8::Object> object,
[email protected]4f1633f2013-03-09 14:26:24511 const std::string& field,
512 const std::string& module_name,
513 const std::string& module_field,
bashi6a4854f2015-06-19 00:51:51514 v8::AccessorNameGetterCallback getter) {
515 CHECK(field.size() < v8::String::kMaxLength);
516 CHECK(module_name.size() < v8::String::kMaxLength);
517 CHECK(module_field.size() < v8::String::kMaxLength);
[email protected]dc3d06e2013-09-06 12:21:03518 v8::HandleScope handle_scope(GetIsolate());
tfarinaf85316f2015-04-29 17:03:40519 v8::Local<v8::Object> parameters = v8::Object::New(GetIsolate());
bashi6a4854f2015-06-19 00:51:51520 v8::Local<v8::Context> context = context_->v8_context();
rdevlin.cronin163beed2016-03-04 18:19:09521 SetPrivateProperty(context, parameters, kModuleName,
bashi6a4854f2015-06-19 00:51:51522 ToV8StringUnsafe(GetIsolate(), module_name.c_str()));
rdevlin.cronin163beed2016-03-04 18:19:09523 SetPrivateProperty(context, parameters, kModuleField,
bashi6a4854f2015-06-19 00:51:51524 ToV8StringUnsafe(GetIsolate(), module_field.c_str()));
525 auto maybe = object->SetAccessor(
526 context, ToV8StringUnsafe(GetIsolate(), field.c_str()), getter, NULL,
527 parameters);
528 CHECK(IsTrue(maybe));
[email protected]cc0457712012-03-21 03:56:38529}
[email protected]ecde1912012-03-16 06:25:31530
tfarinaf85316f2015-04-29 17:03:40531void ModuleSystem::SetNativeLazyField(v8::Local<v8::Object> object,
[email protected]4f1633f2013-03-09 14:26:24532 const std::string& field,
533 const std::string& module_name,
534 const std::string& module_field) {
[email protected]f55c90ee62014-04-12 00:50:03535 SetLazyField(object,
536 field,
537 module_name,
538 module_field,
539 &ModuleSystem::NativeLazyFieldGetter);
[email protected]4f1633f2013-03-09 14:26:24540}
541
tfarinaf85316f2015-04-29 17:03:40542v8::Local<v8::Value> ModuleSystem::RunString(v8::Local<v8::String> code,
543 v8::Local<v8::String> name) {
annekao533482222015-08-21 23:23:53544 return context_->RunScript(
545 name, code, base::Bind(&ExceptionHandler::HandleUncaughtException,
546 base::Unretained(exception_handler_.get())));
[email protected]9e03ce22012-03-13 08:50:05547}
548
[email protected]d8c5fbb2013-06-14 11:35:25549void ModuleSystem::RequireNative(
550 const v8::FunctionCallbackInfo<v8::Value>& args) {
[email protected]58e10452012-02-22 03:34:45551 CHECK_EQ(1, args.Length());
dcarneya261b772014-11-20 17:55:07552 std::string native_name = *v8::String::Utf8Value(args[0]);
bashi61ca3c72015-06-26 00:40:10553 v8::Local<v8::Object> object;
554 if (RequireNativeFromString(native_name).ToLocal(&object))
555 args.GetReturnValue().Set(object);
[email protected]4f1633f2013-03-09 14:26:24556}
557
bashi61ca3c72015-06-26 00:40:10558v8::MaybeLocal<v8::Object> ModuleSystem::RequireNativeFromString(
[email protected]4f1633f2013-03-09 14:26:24559 const std::string& native_name) {
[email protected]95ee77da2013-03-19 21:11:11560 if (natives_enabled_ == 0) {
561 // HACK: if in test throw exception so that we can test the natives-disabled
562 // logic; however, under normal circumstances, this is programmer error so
563 // we could crash.
[email protected]9c47471e2013-11-28 14:41:21564 if (exception_handler_) {
bashi61ca3c72015-06-26 00:40:10565 GetIsolate()->ThrowException(
bashi6a4854f2015-06-19 00:51:51566 ToV8StringUnsafe(GetIsolate(), "Natives disabled"));
bashi61ca3c72015-06-26 00:40:10567 return v8::MaybeLocal<v8::Object>();
[email protected]9c47471e2013-11-28 14:41:21568 }
[email protected]662c48b2013-07-12 03:50:52569 Fatal(context_, "Natives disabled for requireNative(" + native_name + ")");
bashi61ca3c72015-06-26 00:40:10570 return v8::MaybeLocal<v8::Object>();
[email protected]95ee77da2013-03-19 21:11:11571 }
572
[email protected]9c47471e2013-11-28 14:41:21573 if (overridden_native_handlers_.count(native_name) > 0u) {
bashi61ca3c72015-06-26 00:40:10574 v8::Local<v8::Value> value = RequireForJsInner(
bashi6a4854f2015-06-19 00:51:51575 ToV8StringUnsafe(GetIsolate(), native_name.c_str()));
bashi61ca3c72015-06-26 00:40:10576 if (value.IsEmpty() || !value->IsObject())
577 return v8::MaybeLocal<v8::Object>();
578 return value.As<v8::Object>();
[email protected]9c47471e2013-11-28 14:41:21579 }
[email protected]95ee77da2013-03-19 21:11:11580
[email protected]58e10452012-02-22 03:34:45581 NativeHandlerMap::iterator i = native_handler_map_.find(native_name);
[email protected]95ee77da2013-03-19 21:11:11582 if (i == native_handler_map_.end()) {
[email protected]662c48b2013-07-12 03:50:52583 Fatal(context_,
[email protected]ad6aa8f92013-06-22 15:34:16584 "Couldn't find native for requireNative(" + native_name + ")");
bashi61ca3c72015-06-26 00:40:10585 return v8::MaybeLocal<v8::Object>();
[email protected]95ee77da2013-03-19 21:11:11586 }
[email protected]58e10452012-02-22 03:34:45587 return i->second->NewInstance();
588}
[email protected]ecde1912012-03-16 06:25:31589
[email protected]d9f51dad2014-07-09 05:39:38590void ModuleSystem::RequireAsync(
591 const v8::FunctionCallbackInfo<v8::Value>& args) {
592 CHECK_EQ(1, args.Length());
dcarneya261b772014-11-20 17:55:07593 std::string module_name = *v8::String::Utf8Value(args[0]);
bashi6a4854f2015-06-19 00:51:51594 v8::Local<v8::Context> v8_context = context_->v8_context();
tfarinaf85316f2015-04-29 17:03:40595 v8::Local<v8::Promise::Resolver> resolver(
bashi6a4854f2015-06-19 00:51:51596 v8::Promise::Resolver::New(v8_context).ToLocalChecked());
[email protected]d9f51dad2014-07-09 05:39:38597 args.GetReturnValue().Set(resolver->GetPromise());
dchengf6f80662016-04-20 20:26:04598 std::unique_ptr<v8::Global<v8::Promise::Resolver>> global_resolver(
kalman83292b82015-03-12 16:40:25599 new v8::Global<v8::Promise::Resolver>(GetIsolate(), resolver));
[email protected]d9f51dad2014-07-09 05:39:38600 gin::ModuleRegistry* module_registry =
bashi6a4854f2015-06-19 00:51:51601 gin::ModuleRegistry::From(v8_context);
[email protected]d9f51dad2014-07-09 05:39:38602 if (!module_registry) {
603 Warn(GetIsolate(), "Extension view no longer exists");
bashi6a4854f2015-06-19 00:51:51604 resolver->Reject(v8_context, v8::Exception::Error(ToV8StringUnsafe(
[email protected]d9f51dad2014-07-09 05:39:38605 GetIsolate(), "Extension view no longer exists")));
606 return;
607 }
kalman83292b82015-03-12 16:40:25608 module_registry->LoadModule(
609 GetIsolate(), module_name,
610 base::Bind(&ModuleSystem::OnModuleLoaded, weak_factory_.GetWeakPtr(),
611 base::Passed(&global_resolver)));
[email protected]d9f51dad2014-07-09 05:39:38612 if (module_registry->available_modules().count(module_name) == 0)
613 LoadModule(module_name);
614}
615
tfarinaf85316f2015-04-29 17:03:40616v8::Local<v8::String> ModuleSystem::WrapSource(v8::Local<v8::String> source) {
[email protected]95c6b3012013-12-02 14:30:31617 v8::EscapableHandleScope handle_scope(GetIsolate());
[email protected]295890bd2013-06-15 10:52:45618 // Keep in order with the arguments in RequireForJsInner.
bashi6a4854f2015-06-19 00:51:51619 v8::Local<v8::String> left = ToV8StringUnsafe(
[email protected]2a356872014-02-21 23:18:52620 GetIsolate(),
[email protected]d9f51dad2014-07-09 05:39:38621 "(function(define, require, requireNative, requireAsync, exports, "
[email protected]2a356872014-02-21 23:18:52622 "console, privates,"
[email protected]0d775c72014-08-22 13:06:26623 "$Array, $Function, $JSON, $Object, $RegExp, $String, $Error) {"
[email protected]2a356872014-02-21 23:18:52624 "'use strict';");
bashi6a4854f2015-06-19 00:51:51625 v8::Local<v8::String> right = ToV8StringUnsafe(GetIsolate(), "\n})");
[email protected]95c6b3012013-12-02 14:30:31626 return handle_scope.Escape(v8::Local<v8::String>(
627 v8::String::Concat(left, v8::String::Concat(source, right))));
[email protected]ecde1912012-03-16 06:25:31628}
629
[email protected]ca557292013-12-11 08:44:27630void ModuleSystem::Private(const v8::FunctionCallbackInfo<v8::Value>& args) {
631 CHECK_EQ(1, args.Length());
rob5c641ed2014-12-09 00:24:57632 if (!args[0]->IsObject() || args[0]->IsNull()) {
633 GetIsolate()->ThrowException(
bashi6a4854f2015-06-19 00:51:51634 v8::Exception::TypeError(ToV8StringUnsafe(GetIsolate(),
rob5c641ed2014-12-09 00:24:57635 args[0]->IsUndefined()
636 ? "Method called without a valid receiver (this). "
637 "Did you forget to call .bind()?"
638 : "Invalid invocation: receiver is not an object!")));
639 return;
640 }
[email protected]ca557292013-12-11 08:44:27641 v8::Local<v8::Object> obj = args[0].As<v8::Object>();
jochen300abe232015-11-06 21:17:53642 v8::Local<v8::Value> privates;
643 if (!GetPrivate(obj, "privates", &privates) || !privates->IsObject()) {
[email protected]505ffde2013-12-19 15:47:13644 privates = v8::Object::New(args.GetIsolate());
kalmanad8ddd02014-10-15 00:20:06645 if (privates.IsEmpty()) {
646 GetIsolate()->ThrowException(
bashi6a4854f2015-06-19 00:51:51647 ToV8StringUnsafe(GetIsolate(), "Failed to create privates"));
kalmanad8ddd02014-10-15 00:20:06648 return;
649 }
rob77e0fbe2016-04-22 23:16:54650 v8::Maybe<bool> maybe =
651 privates.As<v8::Object>()->SetPrototype(context()->v8_context(),
652 v8::Null(args.GetIsolate()));
653 CHECK(maybe.IsJust() && maybe.FromJust());
jochen300abe232015-11-06 21:17:53654 SetPrivate(obj, "privates", privates);
[email protected]ca557292013-12-11 08:44:27655 }
656 args.GetReturnValue().Set(privates);
657}
658
tfarinaf85316f2015-04-29 17:03:40659v8::Local<v8::Value> ModuleSystem::LoadModule(const std::string& module_name) {
[email protected]d9f51dad2014-07-09 05:39:38660 v8::EscapableHandleScope handle_scope(GetIsolate());
bashi6a4854f2015-06-19 00:51:51661 v8::Local<v8::Context> v8_context = context()->v8_context();
662 v8::Context::Scope context_scope(v8_context);
[email protected]d9f51dad2014-07-09 05:39:38663
rdevlin.cronin1ed2e892016-12-06 21:35:43664 v8::Local<v8::String> source =
665 source_map_->GetSource(GetIsolate(), module_name);
666 if (source.IsEmpty()) {
[email protected]d9f51dad2014-07-09 05:39:38667 Fatal(context_, "No source for require(" + module_name + ")");
668 return v8::Undefined(GetIsolate());
669 }
rdevlin.cronin1ed2e892016-12-06 21:35:43670 v8::Local<v8::String> wrapped_source(WrapSource(source));
bashi6a4854f2015-06-19 00:51:51671 v8::Local<v8::String> v8_module_name;
672 if (!ToV8String(GetIsolate(), module_name.c_str(), &v8_module_name)) {
673 NOTREACHED() << "module_name is too long";
674 return v8::Undefined(GetIsolate());
675 }
[email protected]d9f51dad2014-07-09 05:39:38676 // Modules are wrapped in (function(){...}) so they always return functions.
tfarinaf85316f2015-04-29 17:03:40677 v8::Local<v8::Value> func_as_value =
bashi6a4854f2015-06-19 00:51:51678 RunString(wrapped_source, v8_module_name);
[email protected]d9f51dad2014-07-09 05:39:38679 if (func_as_value.IsEmpty() || func_as_value->IsUndefined()) {
680 Fatal(context_, "Bad source for require(" + module_name + ")");
681 return v8::Undefined(GetIsolate());
682 }
683
tfarinaf85316f2015-04-29 17:03:40684 v8::Local<v8::Function> func = v8::Local<v8::Function>::Cast(func_as_value);
[email protected]d9f51dad2014-07-09 05:39:38685
tfarinaf85316f2015-04-29 17:03:40686 v8::Local<v8::Object> define_object = v8::Object::New(GetIsolate());
[email protected]d9f51dad2014-07-09 05:39:38687 gin::ModuleRegistry::InstallGlobals(GetIsolate(), define_object);
688
rdevlin.cronin83a4b3a2015-10-28 21:43:58689 v8::Local<v8::Object> exports = v8::Object::New(GetIsolate());
690
691 v8::Local<v8::FunctionTemplate> tmpl = v8::FunctionTemplate::New(
692 GetIsolate(),
693 &SetExportsProperty);
jochen596fd5e2016-07-06 12:29:50694 tmpl->RemovePrototype();
rdevlin.cronin83a4b3a2015-10-28 21:43:58695 v8::Local<v8::String> v8_key;
696 if (!v8_helpers::ToV8String(GetIsolate(), "$set", &v8_key)) {
697 NOTREACHED();
698 return v8::Undefined(GetIsolate());
699 }
700
701 v8::Local<v8::Function> function;
702 if (!tmpl->GetFunction(v8_context).ToLocal(&function)) {
703 NOTREACHED();
704 return v8::Undefined(GetIsolate());
705 }
706
jochen37ec8f42015-12-11 10:29:49707 exports->DefineOwnProperty(v8_context, v8_key, function, v8::ReadOnly)
708 .FromJust();
rdevlin.cronin83a4b3a2015-10-28 21:43:58709
tfarinaf85316f2015-04-29 17:03:40710 v8::Local<v8::Object> natives(NewInstance());
bashi6a4854f2015-06-19 00:51:51711 CHECK(!natives.IsEmpty()); // this can fail if v8 has issues
[email protected]d9f51dad2014-07-09 05:39:38712
713 // These must match the argument order in WrapSource.
tfarinaf85316f2015-04-29 17:03:40714 v8::Local<v8::Value> args[] = {
[email protected]d9f51dad2014-07-09 05:39:38715 // AMD.
bashi6a4854f2015-06-19 00:51:51716 GetPropertyUnsafe(v8_context, define_object, "define"),
[email protected]d9f51dad2014-07-09 05:39:38717 // CommonJS.
bashi6a4854f2015-06-19 00:51:51718 GetPropertyUnsafe(v8_context, natives, "require",
719 v8::NewStringType::kInternalized),
720 GetPropertyUnsafe(v8_context, natives, "requireNative",
721 v8::NewStringType::kInternalized),
722 GetPropertyUnsafe(v8_context, natives, "requireAsync",
723 v8::NewStringType::kInternalized),
[email protected]d9f51dad2014-07-09 05:39:38724 exports,
725 // Libraries that we magically expose to every module.
kalmanfb6f10ac2014-11-06 23:55:35726 console::AsV8Object(GetIsolate()),
bashi6a4854f2015-06-19 00:51:51727 GetPropertyUnsafe(v8_context, natives, "privates",
728 v8::NewStringType::kInternalized),
[email protected]d9f51dad2014-07-09 05:39:38729 // Each safe builtin. Keep in order with the arguments in WrapSource.
730 context_->safe_builtins()->GetArray(),
731 context_->safe_builtins()->GetFunction(),
732 context_->safe_builtins()->GetJSON(),
733 context_->safe_builtins()->GetObjekt(),
734 context_->safe_builtins()->GetRegExp(),
735 context_->safe_builtins()->GetString(),
[email protected]0d775c72014-08-22 13:06:26736 context_->safe_builtins()->GetError(),
[email protected]d9f51dad2014-07-09 05:39:38737 };
738 {
bashi6a4854f2015-06-19 00:51:51739 v8::TryCatch try_catch(GetIsolate());
[email protected]d9f51dad2014-07-09 05:39:38740 try_catch.SetCaptureMessage(true);
rdevlin.cronina9bc8cc2016-10-06 15:51:17741 context_->SafeCallFunction(func, arraysize(args), args);
[email protected]d9f51dad2014-07-09 05:39:38742 if (try_catch.HasCaught()) {
743 HandleException(try_catch);
744 return v8::Undefined(GetIsolate());
745 }
746 }
747 return handle_scope.Escape(exports);
748}
749
750void ModuleSystem::OnDidAddPendingModule(
751 const std::string& id,
752 const std::vector<std::string>& dependencies) {
sammc2cc226562015-01-14 01:25:06753 bool module_system_managed = source_map_->Contains(id);
[email protected]d9f51dad2014-07-09 05:39:38754
755 gin::ModuleRegistry* registry =
756 gin::ModuleRegistry::From(context_->v8_context());
757 DCHECK(registry);
sammc2cc226562015-01-14 01:25:06758 for (const auto& dependency : dependencies) {
759 // If a dependency is not available, and either the module or this
760 // dependency is managed by ModuleSystem, attempt to load it. Other
761 // gin::ModuleRegistry users (WebUI and users of the mojoPrivate API) are
762 // responsible for loading their module dependencies when required.
763 if (registry->available_modules().count(dependency) == 0 &&
764 (module_system_managed || source_map_->Contains(dependency))) {
765 LoadModule(dependency);
766 }
[email protected]d9f51dad2014-07-09 05:39:38767 }
768 registry->AttemptToLoadMoreModules(GetIsolate());
769}
770
771void ModuleSystem::OnModuleLoaded(
dchengf6f80662016-04-20 20:26:04772 std::unique_ptr<v8::Global<v8::Promise::Resolver>> resolver,
tfarinaf85316f2015-04-29 17:03:40773 v8::Local<v8::Value> value) {
[email protected]d9f51dad2014-07-09 05:39:38774 if (!is_valid())
775 return;
776 v8::HandleScope handle_scope(GetIsolate());
tfarinaf85316f2015-04-29 17:03:40777 v8::Local<v8::Promise::Resolver> resolver_local(
[email protected]d9f51dad2014-07-09 05:39:38778 v8::Local<v8::Promise::Resolver>::New(GetIsolate(), *resolver));
bashi6a4854f2015-06-19 00:51:51779 resolver_local->Resolve(context()->v8_context(), value);
[email protected]d9f51dad2014-07-09 05:39:38780}
781
kalmanb0c1c502015-04-15 00:25:06782void ModuleSystem::ClobberExistingNativeHandler(const std::string& name) {
783 NativeHandlerMap::iterator existing_handler = native_handler_map_.find(name);
784 if (existing_handler != native_handler_map_.end()) {
tzik8f7af2922015-11-25 03:16:48785 clobbered_native_handlers_.push_back(std::move(existing_handler->second));
kalmanb0c1c502015-04-15 00:25:06786 native_handler_map_.erase(existing_handler);
787 }
788}
789
rdevlin.croninaac306632016-10-18 21:27:46790v8::Local<v8::Function> ModuleSystem::GetModuleFunction(
791 const std::string& module_name,
792 const std::string& method_name) {
793 v8::Local<v8::String> v8_module_name;
794 v8::Local<v8::String> v8_method_name;
795 v8::Local<v8::Function> function;
796 if (!ToV8String(GetIsolate(), module_name.c_str(), &v8_module_name) ||
797 !ToV8String(GetIsolate(), method_name.c_str(), &v8_method_name)) {
798 return function;
799 }
800
801 v8::Local<v8::Value> module;
802 {
803 NativesEnabledScope natives_enabled(this);
804 module = RequireForJsInner(v8_module_name);
805 }
806
807 if (module.IsEmpty() || !module->IsObject()) {
808 Fatal(context_,
809 "Failed to get module " + module_name + " to call " + method_name);
810 return function;
811 }
812
813 v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(module);
814 v8::Local<v8::Value> value;
815 if (!GetProperty(context()->v8_context(), object, v8_method_name, &value) ||
816 !value->IsFunction()) {
817 Fatal(context_, module_name + "." + method_name + " is not a function");
818 return function;
819 }
820
821 function = v8::Local<v8::Function>::Cast(value);
822 return function;
823}
824
[email protected]4e008e172013-06-13 20:15:48825} // namespace extensions