Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(131)

Side by Side Diff: extensions/renderer/module_system.cc

Issue 2936213002: [Extensions] Don't require() a module for calling a method (Closed)
Patch Set: . Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « extensions/renderer/module_system.h ('k') | extensions/renderer/utils_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "extensions/renderer/module_system.h" 5 #include "extensions/renderer/module_system.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/command_line.h" 8 #include "base/command_line.h"
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/macros.h" 10 #include "base/macros.h"
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
232 void ModuleSystem::HandleException(const v8::TryCatch& try_catch) { 232 void ModuleSystem::HandleException(const v8::TryCatch& try_catch) {
233 exception_handler_->HandleUncaughtException(try_catch); 233 exception_handler_->HandleUncaughtException(try_catch);
234 } 234 }
235 235
236 v8::MaybeLocal<v8::Object> ModuleSystem::Require( 236 v8::MaybeLocal<v8::Object> ModuleSystem::Require(
237 const std::string& module_name) { 237 const std::string& module_name) {
238 v8::Local<v8::String> v8_module_name; 238 v8::Local<v8::String> v8_module_name;
239 if (!ToV8String(GetIsolate(), module_name, &v8_module_name)) 239 if (!ToV8String(GetIsolate(), module_name, &v8_module_name))
240 return v8::MaybeLocal<v8::Object>(); 240 return v8::MaybeLocal<v8::Object>();
241 v8::EscapableHandleScope handle_scope(GetIsolate()); 241 v8::EscapableHandleScope handle_scope(GetIsolate());
242 v8::Local<v8::Value> value = RequireForJsInner( 242 v8::Local<v8::Value> value =
243 v8_module_name); 243 RequireForJsInner(v8_module_name, true /* create */);
244 if (value.IsEmpty() || !value->IsObject()) 244 if (value.IsEmpty() || !value->IsObject())
245 return v8::MaybeLocal<v8::Object>(); 245 return v8::MaybeLocal<v8::Object>();
246 return handle_scope.Escape(value.As<v8::Object>()); 246 return handle_scope.Escape(value.As<v8::Object>());
247 } 247 }
248 248
249 void ModuleSystem::RequireForJs( 249 void ModuleSystem::RequireForJs(
250 const v8::FunctionCallbackInfo<v8::Value>& args) { 250 const v8::FunctionCallbackInfo<v8::Value>& args) {
251 if (!args[0]->IsString()) { 251 if (!args[0]->IsString()) {
252 NOTREACHED() << "require() called with a non-string argument"; 252 NOTREACHED() << "require() called with a non-string argument";
253 return; 253 return;
254 } 254 }
255 v8::Local<v8::String> module_name = args[0].As<v8::String>(); 255 v8::Local<v8::String> module_name = args[0].As<v8::String>();
256 args.GetReturnValue().Set(RequireForJsInner(module_name)); 256 args.GetReturnValue().Set(RequireForJsInner(module_name, true /* create */));
257 } 257 }
258 258
259 v8::Local<v8::Value> ModuleSystem::RequireForJsInner( 259 v8::Local<v8::Value> ModuleSystem::RequireForJsInner(
260 v8::Local<v8::String> module_name) { 260 v8::Local<v8::String> module_name,
261 bool create) {
261 v8::EscapableHandleScope handle_scope(GetIsolate()); 262 v8::EscapableHandleScope handle_scope(GetIsolate());
262 v8::Local<v8::Context> v8_context = context()->v8_context(); 263 v8::Local<v8::Context> v8_context = context()->v8_context();
263 v8::Context::Scope context_scope(v8_context); 264 v8::Context::Scope context_scope(v8_context);
264 265
265 v8::Local<v8::Object> global(context()->v8_context()->Global()); 266 v8::Local<v8::Object> global(context()->v8_context()->Global());
266 267
267 // The module system might have been deleted. This can happen if a different 268 // The module system might have been deleted. This can happen if a different
268 // context keeps a reference to us, but our frame is destroyed (e.g. 269 // context keeps a reference to us, but our frame is destroyed (e.g.
269 // background page keeps reference to chrome object in a closed popup). 270 // background page keeps reference to chrome object in a closed popup).
270 v8::Local<v8::Value> modules_value; 271 v8::Local<v8::Value> modules_value;
271 if (!GetPrivate(global, kModulesField, &modules_value) || 272 if (!GetPrivate(global, kModulesField, &modules_value) ||
272 modules_value->IsUndefined()) { 273 modules_value->IsUndefined()) {
273 Warn(GetIsolate(), "Extension view no longer exists"); 274 Warn(GetIsolate(), "Extension view no longer exists");
274 return v8::Undefined(GetIsolate()); 275 return v8::Undefined(GetIsolate());
275 } 276 }
276 277
277 v8::Local<v8::Object> modules(v8::Local<v8::Object>::Cast(modules_value)); 278 v8::Local<v8::Object> modules(v8::Local<v8::Object>::Cast(modules_value));
278 v8::Local<v8::Value> exports; 279 v8::Local<v8::Value> exports;
279 if (!GetPrivateProperty(v8_context, modules, module_name, &exports) || 280 if (!GetPrivateProperty(v8_context, modules, module_name, &exports) ||
280 !exports->IsUndefined()) 281 !exports->IsUndefined())
281 return handle_scope.Escape(exports); 282 return handle_scope.Escape(exports);
282 283
284 if (!create)
285 return v8::Undefined(GetIsolate());
286
283 exports = LoadModule(*v8::String::Utf8Value(module_name)); 287 exports = LoadModule(*v8::String::Utf8Value(module_name));
284 SetPrivateProperty(v8_context, modules, module_name, exports); 288 SetPrivateProperty(v8_context, modules, module_name, exports);
285 return handle_scope.Escape(exports); 289 return handle_scope.Escape(exports);
286 } 290 }
287 291
288 void ModuleSystem::CallModuleMethodSafe(const std::string& module_name, 292 void ModuleSystem::CallModuleMethodSafe(const std::string& module_name,
289 const std::string& method_name) { 293 const std::string& method_name) {
290 v8::HandleScope handle_scope(GetIsolate()); 294 v8::HandleScope handle_scope(GetIsolate());
291 v8::Local<v8::Value> no_args; 295 v8::Local<v8::Value> no_args;
292 CallModuleMethodSafe(module_name, method_name, 0, &no_args, 296 CallModuleMethodSafe(module_name, method_name, 0, &no_args,
(...skipping 24 matching lines...) Expand all
317 const ScriptInjectionCallback::CompleteCallback& callback) { 321 const ScriptInjectionCallback::CompleteCallback& callback) {
318 TRACE_EVENT2("v8", "v8.callModuleMethodSafe", "module_name", module_name, 322 TRACE_EVENT2("v8", "v8.callModuleMethodSafe", "module_name", module_name,
319 "method_name", method_name); 323 "method_name", method_name);
320 324
321 v8::HandleScope handle_scope(GetIsolate()); 325 v8::HandleScope handle_scope(GetIsolate());
322 v8::Local<v8::Context> v8_context = context()->v8_context(); 326 v8::Local<v8::Context> v8_context = context()->v8_context();
323 v8::Context::Scope context_scope(v8_context); 327 v8::Context::Scope context_scope(v8_context);
324 328
325 v8::Local<v8::Function> function = 329 v8::Local<v8::Function> function =
326 GetModuleFunction(module_name, method_name); 330 GetModuleFunction(module_name, method_name);
327 if (function.IsEmpty()) { 331 if (function.IsEmpty())
328 NOTREACHED() << "GetModuleFunction() returns empty function handle";
329 return; 332 return;
Devlin 2017/06/16 14:53:16 Note: I'll add a comment explaining when this can
lazyboy 2017/06/23 21:28:13 OK, I'd be interested to know.
Devlin 2017/06/24 02:04:21 Done.
330 }
331 333
332 { 334 {
333 v8::TryCatch try_catch(GetIsolate()); 335 v8::TryCatch try_catch(GetIsolate());
334 try_catch.SetCaptureMessage(true); 336 try_catch.SetCaptureMessage(true);
335 context_->SafeCallFunction(function, argc, argv, callback); 337 context_->SafeCallFunction(function, argc, argv, callback);
336 if (try_catch.HasCaught()) 338 if (try_catch.HasCaught())
337 HandleException(try_catch); 339 HandleException(try_catch);
338 } 340 }
339 } 341 }
340 342
(...skipping 253 matching lines...) Expand 10 before | Expand all | Expand 10 after
594 GetIsolate()->ThrowException( 596 GetIsolate()->ThrowException(
595 ToV8StringUnsafe(GetIsolate(), "Natives disabled")); 597 ToV8StringUnsafe(GetIsolate(), "Natives disabled"));
596 return v8::MaybeLocal<v8::Object>(); 598 return v8::MaybeLocal<v8::Object>();
597 } 599 }
598 Fatal(context_, "Natives disabled for requireNative(" + native_name + ")"); 600 Fatal(context_, "Natives disabled for requireNative(" + native_name + ")");
599 return v8::MaybeLocal<v8::Object>(); 601 return v8::MaybeLocal<v8::Object>();
600 } 602 }
601 603
602 if (overridden_native_handlers_.count(native_name) > 0u) { 604 if (overridden_native_handlers_.count(native_name) > 0u) {
603 v8::Local<v8::Value> value = RequireForJsInner( 605 v8::Local<v8::Value> value = RequireForJsInner(
604 ToV8StringUnsafe(GetIsolate(), native_name.c_str())); 606 ToV8StringUnsafe(GetIsolate(), native_name.c_str()), true /* create */);
605 if (value.IsEmpty() || !value->IsObject()) 607 if (value.IsEmpty() || !value->IsObject())
606 return v8::MaybeLocal<v8::Object>(); 608 return v8::MaybeLocal<v8::Object>();
607 return value.As<v8::Object>(); 609 return value.As<v8::Object>();
608 } 610 }
609 611
610 NativeHandlerMap::iterator i = native_handler_map_.find(native_name); 612 NativeHandlerMap::iterator i = native_handler_map_.find(native_name);
611 if (i == native_handler_map_.end()) { 613 if (i == native_handler_map_.end()) {
612 Fatal(context_, 614 Fatal(context_,
613 "Couldn't find native for requireNative(" + native_name + ")"); 615 "Couldn't find native for requireNative(" + native_name + ")");
614 return v8::MaybeLocal<v8::Object>(); 616 return v8::MaybeLocal<v8::Object>();
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after
858 const std::string& method_name) { 860 const std::string& method_name) {
859 v8::Local<v8::String> v8_module_name; 861 v8::Local<v8::String> v8_module_name;
860 v8::Local<v8::String> v8_method_name; 862 v8::Local<v8::String> v8_method_name;
861 v8::Local<v8::Function> function; 863 v8::Local<v8::Function> function;
862 if (!ToV8String(GetIsolate(), module_name.c_str(), &v8_module_name) || 864 if (!ToV8String(GetIsolate(), module_name.c_str(), &v8_module_name) ||
863 !ToV8String(GetIsolate(), method_name.c_str(), &v8_method_name)) { 865 !ToV8String(GetIsolate(), method_name.c_str(), &v8_method_name)) {
864 return function; 866 return function;
865 } 867 }
866 868
867 v8::Local<v8::Value> module; 869 v8::Local<v8::Value> module;
868 { 870 // Important: don't create the module if it doesn't exist. Doing so would
869 NativesEnabledScope natives_enabled(this); 871 // force a call into JS, which is something we want to avoid in case it has
870 module = RequireForJsInner(v8_module_name); 872 // been suspended. Additionally, we should only be calling module methods for
871 } 873 // modules that have been instantiated.
874 bool create = false;
875 module = RequireForJsInner(v8_module_name, create);
876
877 if (!module.IsEmpty() && module->IsUndefined())
lazyboy 2017/06/23 21:28:13 Add a note what this (!IsEmpty but IsUndefined = t
Devlin 2017/06/24 02:04:21 Done.
878 return function;
lazyboy 2017/06/23 21:28:13 nit: do you think it makes it more readable to "re
Devlin 2017/06/24 02:04:21 Sure, that's reasonable. It means we lose RVO, bu
872 879
873 if (module.IsEmpty() || !module->IsObject()) { 880 if (module.IsEmpty() || !module->IsObject()) {
874 Fatal(context_, 881 Fatal(context_,
875 "Failed to get module " + module_name + " to call " + method_name); 882 "Failed to get module " + module_name + " to call " + method_name);
876 return function; 883 return function;
877 } 884 }
878 885
879 v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(module); 886 v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(module);
880 v8::Local<v8::Value> value; 887 v8::Local<v8::Value> value;
881 if (!GetProperty(context()->v8_context(), object, v8_method_name, &value) || 888 if (!GetProperty(context()->v8_context(), object, v8_method_name, &value) ||
882 !value->IsFunction()) { 889 !value->IsFunction()) {
883 Fatal(context_, module_name + "." + method_name + " is not a function"); 890 Fatal(context_, module_name + "." + method_name + " is not a function");
884 return function; 891 return function;
885 } 892 }
886 893
887 function = v8::Local<v8::Function>::Cast(value); 894 function = v8::Local<v8::Function>::Cast(value);
888 return function; 895 return function;
889 } 896 }
890 897
891 } // namespace extensions 898 } // namespace extensions
OLDNEW
« no previous file with comments | « extensions/renderer/module_system.h ('k') | extensions/renderer/utils_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698