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

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

Issue 2936213002: [Extensions] Don't require() a module for calling a method (Closed)
Patch Set: lazyboy's 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 25 matching lines...) Expand all
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"; 332 // This can legitimately happen when the module hasn't been loaded in the
333 // context (since GetModuleFunction() does not load an unloaded module).
334 // Typically, we won't do this, but we can in the case of, e.g., dispatching
335 // events (where we'll try to dispatch to each context in a process). In
336 // these cases, though, we can know that there are no listeners registered,
337 // since the event module hasn't been loaded.
329 return; 338 return;
330 } 339 }
331 340
332 { 341 {
333 v8::TryCatch try_catch(GetIsolate()); 342 v8::TryCatch try_catch(GetIsolate());
334 try_catch.SetCaptureMessage(true); 343 try_catch.SetCaptureMessage(true);
335 context_->SafeCallFunction(function, argc, argv, callback); 344 context_->SafeCallFunction(function, argc, argv, callback);
336 if (try_catch.HasCaught()) 345 if (try_catch.HasCaught())
337 HandleException(try_catch); 346 HandleException(try_catch);
338 } 347 }
(...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after
594 GetIsolate()->ThrowException( 603 GetIsolate()->ThrowException(
595 ToV8StringUnsafe(GetIsolate(), "Natives disabled")); 604 ToV8StringUnsafe(GetIsolate(), "Natives disabled"));
596 return v8::MaybeLocal<v8::Object>(); 605 return v8::MaybeLocal<v8::Object>();
597 } 606 }
598 Fatal(context_, "Natives disabled for requireNative(" + native_name + ")"); 607 Fatal(context_, "Natives disabled for requireNative(" + native_name + ")");
599 return v8::MaybeLocal<v8::Object>(); 608 return v8::MaybeLocal<v8::Object>();
600 } 609 }
601 610
602 if (overridden_native_handlers_.count(native_name) > 0u) { 611 if (overridden_native_handlers_.count(native_name) > 0u) {
603 v8::Local<v8::Value> value = RequireForJsInner( 612 v8::Local<v8::Value> value = RequireForJsInner(
604 ToV8StringUnsafe(GetIsolate(), native_name.c_str())); 613 ToV8StringUnsafe(GetIsolate(), native_name.c_str()), true /* create */);
605 if (value.IsEmpty() || !value->IsObject()) 614 if (value.IsEmpty() || !value->IsObject())
606 return v8::MaybeLocal<v8::Object>(); 615 return v8::MaybeLocal<v8::Object>();
607 return value.As<v8::Object>(); 616 return value.As<v8::Object>();
608 } 617 }
609 618
610 NativeHandlerMap::iterator i = native_handler_map_.find(native_name); 619 NativeHandlerMap::iterator i = native_handler_map_.find(native_name);
611 if (i == native_handler_map_.end()) { 620 if (i == native_handler_map_.end()) {
612 Fatal(context_, 621 Fatal(context_,
613 "Couldn't find native for requireNative(" + native_name + ")"); 622 "Couldn't find native for requireNative(" + native_name + ")");
614 return v8::MaybeLocal<v8::Object>(); 623 return v8::MaybeLocal<v8::Object>();
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after
851 clobbered_native_handlers_.push_back(std::move(existing_handler->second)); 860 clobbered_native_handlers_.push_back(std::move(existing_handler->second));
852 native_handler_map_.erase(existing_handler); 861 native_handler_map_.erase(existing_handler);
853 } 862 }
854 } 863 }
855 864
856 v8::Local<v8::Function> ModuleSystem::GetModuleFunction( 865 v8::Local<v8::Function> ModuleSystem::GetModuleFunction(
857 const std::string& module_name, 866 const std::string& module_name,
858 const std::string& method_name) { 867 const std::string& method_name) {
859 v8::Local<v8::String> v8_module_name; 868 v8::Local<v8::String> v8_module_name;
860 v8::Local<v8::String> v8_method_name; 869 v8::Local<v8::String> v8_method_name;
861 v8::Local<v8::Function> function;
862 if (!ToV8String(GetIsolate(), module_name.c_str(), &v8_module_name) || 870 if (!ToV8String(GetIsolate(), module_name.c_str(), &v8_module_name) ||
863 !ToV8String(GetIsolate(), method_name.c_str(), &v8_method_name)) { 871 !ToV8String(GetIsolate(), method_name.c_str(), &v8_method_name)) {
864 return function; 872 return v8::Local<v8::Function>();
865 } 873 }
866 874
867 v8::Local<v8::Value> module; 875 v8::Local<v8::Value> module;
868 { 876 // Important: don't create the module if it doesn't exist. Doing so would
869 NativesEnabledScope natives_enabled(this); 877 // force a call into JS, which is something we want to avoid in case it has
870 module = RequireForJsInner(v8_module_name); 878 // been suspended. Additionally, we should only be calling module methods for
871 } 879 // modules that have been instantiated.
880 bool create = false;
881 module = RequireForJsInner(v8_module_name, create);
882
883 // RequireForJsInner() returns Undefined in the case of a module not being
884 // loaded, since we don't create it here.
885 if (!module.IsEmpty() && module->IsUndefined())
886 return v8::Local<v8::Function>();
872 887
873 if (module.IsEmpty() || !module->IsObject()) { 888 if (module.IsEmpty() || !module->IsObject()) {
874 Fatal(context_, 889 Fatal(context_,
875 "Failed to get module " + module_name + " to call " + method_name); 890 "Failed to get module " + module_name + " to call " + method_name);
876 return function; 891 return v8::Local<v8::Function>();
877 } 892 }
878 893
879 v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(module); 894 v8::Local<v8::Object> object = v8::Local<v8::Object>::Cast(module);
880 v8::Local<v8::Value> value; 895 v8::Local<v8::Value> value;
881 if (!GetProperty(context()->v8_context(), object, v8_method_name, &value) || 896 if (!GetProperty(context()->v8_context(), object, v8_method_name, &value) ||
882 !value->IsFunction()) { 897 !value->IsFunction()) {
883 Fatal(context_, module_name + "." + method_name + " is not a function"); 898 Fatal(context_, module_name + "." + method_name + " is not a function");
884 return function; 899 return v8::Local<v8::Function>();
885 } 900 }
886 901
887 function = v8::Local<v8::Function>::Cast(value); 902 return v8::Local<v8::Function>::Cast(value);
888 return function;
889 } 903 }
890 904
891 } // namespace extensions 905 } // 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