| Index: extensions/renderer/module_system.cc | 
| diff --git a/extensions/renderer/module_system.cc b/extensions/renderer/module_system.cc | 
| index 4a685e34caaa25dfa358c56727c4511a64632b63..ab265fade68c92cba7f902d96365371fe22f1c42 100644 | 
| --- a/extensions/renderer/module_system.cc | 
| +++ b/extensions/renderer/module_system.cc | 
| @@ -16,6 +16,7 @@ | 
| #include "extensions/renderer/console.h" | 
| #include "extensions/renderer/safe_builtins.h" | 
| #include "extensions/renderer/script_context.h" | 
| +#include "gin/modules/module_registry.h" | 
| #include "third_party/WebKit/public/web/WebFrame.h" | 
| #include "third_party/WebKit/public/web/WebScopedMicrotaskSuppression.h" | 
|  | 
| @@ -121,13 +122,17 @@ ModuleSystem::ModuleSystem(ScriptContext* context, SourceMap* source_map) | 
| context_(context), | 
| source_map_(source_map), | 
| natives_enabled_(0), | 
| -      exception_handler_(new DefaultExceptionHandler(context)) { | 
| +      exception_handler_(new DefaultExceptionHandler(context)), | 
| +      weak_factory_(this) { | 
| RouteFunction( | 
| "require", | 
| base::Bind(&ModuleSystem::RequireForJs, base::Unretained(this))); | 
| RouteFunction( | 
| "requireNative", | 
| base::Bind(&ModuleSystem::RequireNative, base::Unretained(this))); | 
| +  RouteFunction( | 
| +      "requireAsync", | 
| +      base::Bind(&ModuleSystem::RequireAsync, base::Unretained(this))); | 
| RouteFunction("privates", | 
| base::Bind(&ModuleSystem::Private, base::Unretained(this))); | 
|  | 
| @@ -137,6 +142,8 @@ ModuleSystem::ModuleSystem(ScriptContext* context, SourceMap* source_map) | 
| v8::Object::New(isolate)); | 
| global->SetHiddenValue(v8::String::NewFromUtf8(isolate, kModuleSystem), | 
| v8::External::New(isolate, this)); | 
| + | 
| +  gin::ModuleRegistry::From(context->v8_context())->AddObserver(this); | 
| } | 
|  | 
| ModuleSystem::~ModuleSystem() { Invalidate(); } | 
| @@ -215,55 +222,7 @@ v8::Local<v8::Value> ModuleSystem::RequireForJsInner( | 
| if (!exports->IsUndefined()) | 
| return handle_scope.Escape(exports); | 
|  | 
| -  std::string module_name_str = *v8::String::Utf8Value(module_name); | 
| -  v8::Handle<v8::Value> source(GetSource(module_name_str)); | 
| -  if (source.IsEmpty() || source->IsUndefined()) { | 
| -    Fatal(context_, "No source for require(" + module_name_str + ")"); | 
| -    return v8::Undefined(GetIsolate()); | 
| -  } | 
| -  v8::Handle<v8::String> wrapped_source( | 
| -      WrapSource(v8::Handle<v8::String>::Cast(source))); | 
| -  // Modules are wrapped in (function(){...}) so they always return functions. | 
| -  v8::Handle<v8::Value> func_as_value = RunString(wrapped_source, module_name); | 
| -  if (func_as_value.IsEmpty() || func_as_value->IsUndefined()) { | 
| -    Fatal(context_, "Bad source for require(" + module_name_str + ")"); | 
| -    return v8::Undefined(GetIsolate()); | 
| -  } | 
| - | 
| -  v8::Handle<v8::Function> func = v8::Handle<v8::Function>::Cast(func_as_value); | 
| - | 
| -  exports = v8::Object::New(GetIsolate()); | 
| -  v8::Handle<v8::Object> natives(NewInstance()); | 
| -  CHECK(!natives.IsEmpty());  // this can happen if v8 has issues | 
| - | 
| -  // These must match the argument order in WrapSource. | 
| -  v8::Handle<v8::Value> args[] = { | 
| -      // CommonJS. | 
| -      natives->Get(v8::String::NewFromUtf8( | 
| -          GetIsolate(), "require", v8::String::kInternalizedString)), | 
| -      natives->Get(v8::String::NewFromUtf8( | 
| -          GetIsolate(), "requireNative", v8::String::kInternalizedString)), | 
| -      exports, | 
| -      // Libraries that we magically expose to every module. | 
| -      console::AsV8Object(), | 
| -      natives->Get(v8::String::NewFromUtf8( | 
| -          GetIsolate(), "privates", v8::String::kInternalizedString)), | 
| -      // Each safe builtin. Keep in order with the arguments in WrapSource. | 
| -      context_->safe_builtins()->GetArray(), | 
| -      context_->safe_builtins()->GetFunction(), | 
| -      context_->safe_builtins()->GetJSON(), | 
| -      context_->safe_builtins()->GetObjekt(), | 
| -      context_->safe_builtins()->GetRegExp(), | 
| -      context_->safe_builtins()->GetString(), }; | 
| -  { | 
| -    v8::TryCatch try_catch; | 
| -    try_catch.SetCaptureMessage(true); | 
| -    context_->CallFunction(func, arraysize(args), args); | 
| -    if (try_catch.HasCaught()) { | 
| -      HandleException(try_catch); | 
| -      return v8::Undefined(GetIsolate()); | 
| -    } | 
| -  } | 
| +  exports = LoadModule(*v8::String::Utf8Value(module_name)); | 
| modules->Set(module_name, exports); | 
| return handle_scope.Escape(exports); | 
| } | 
| @@ -558,12 +517,38 @@ v8::Handle<v8::Value> ModuleSystem::RequireNativeFromString( | 
| return i->second->NewInstance(); | 
| } | 
|  | 
| +void ModuleSystem::RequireAsync( | 
| +    const v8::FunctionCallbackInfo<v8::Value>& args) { | 
| +  CHECK_EQ(1, args.Length()); | 
| +  std::string module_name = *v8::String::Utf8Value(args[0]->ToString()); | 
| +  v8::Handle<v8::Promise::Resolver> resolver( | 
| +      v8::Promise::Resolver::New(GetIsolate())); | 
| +  args.GetReturnValue().Set(resolver->GetPromise()); | 
| +  scoped_ptr<v8::UniquePersistent<v8::Promise::Resolver> > persistent_resolver( | 
| +      new v8::UniquePersistent<v8::Promise::Resolver>(GetIsolate(), resolver)); | 
| +  gin::ModuleRegistry* module_registry = | 
| +      gin::ModuleRegistry::From(context_->v8_context()); | 
| +  if (!module_registry) { | 
| +    Warn(GetIsolate(), "Extension view no longer exists"); | 
| +    resolver->Reject(v8::Exception::Error(v8::String::NewFromUtf8( | 
| +        GetIsolate(), "Extension view no longer exists"))); | 
| +    return; | 
| +  } | 
| +  module_registry->LoadModule(GetIsolate(), | 
| +                              module_name, | 
| +                              base::Bind(&ModuleSystem::OnModuleLoaded, | 
| +                                         weak_factory_.GetWeakPtr(), | 
| +                                         base::Passed(&persistent_resolver))); | 
| +  if (module_registry->available_modules().count(module_name) == 0) | 
| +    LoadModule(module_name); | 
| +} | 
| + | 
| v8::Handle<v8::String> ModuleSystem::WrapSource(v8::Handle<v8::String> source) { | 
| v8::EscapableHandleScope handle_scope(GetIsolate()); | 
| // Keep in order with the arguments in RequireForJsInner. | 
| v8::Handle<v8::String> left = v8::String::NewFromUtf8( | 
| GetIsolate(), | 
| -      "(function(require, requireNative, exports, " | 
| +      "(function(define, require, requireNative, requireAsync, exports, " | 
| "console, privates," | 
| "$Array, $Function, $JSON, $Object, $RegExp, $String) {" | 
| "'use strict';"); | 
| @@ -586,4 +571,98 @@ void ModuleSystem::Private(const v8::FunctionCallbackInfo<v8::Value>& args) { | 
| args.GetReturnValue().Set(privates); | 
| } | 
|  | 
| +v8::Handle<v8::Value> ModuleSystem::LoadModule(const std::string& module_name) { | 
| +  v8::EscapableHandleScope handle_scope(GetIsolate()); | 
| +  v8::Context::Scope context_scope(context()->v8_context()); | 
| + | 
| +  v8::Handle<v8::Value> source(GetSource(module_name)); | 
| +  if (source.IsEmpty() || source->IsUndefined()) { | 
| +    Fatal(context_, "No source for require(" + module_name + ")"); | 
| +    return v8::Undefined(GetIsolate()); | 
| +  } | 
| +  v8::Handle<v8::String> wrapped_source( | 
| +      WrapSource(v8::Handle<v8::String>::Cast(source))); | 
| +  // Modules are wrapped in (function(){...}) so they always return functions. | 
| +  v8::Handle<v8::Value> func_as_value = | 
| +      RunString(wrapped_source, | 
| +                v8::String::NewFromUtf8(GetIsolate(), module_name.c_str())); | 
| +  if (func_as_value.IsEmpty() || func_as_value->IsUndefined()) { | 
| +    Fatal(context_, "Bad source for require(" + module_name + ")"); | 
| +    return v8::Undefined(GetIsolate()); | 
| +  } | 
| + | 
| +  v8::Handle<v8::Function> func = v8::Handle<v8::Function>::Cast(func_as_value); | 
| + | 
| +  v8::Handle<v8::Object> define_object = v8::Object::New(GetIsolate()); | 
| +  gin::ModuleRegistry::InstallGlobals(GetIsolate(), define_object); | 
| + | 
| +  v8::Local<v8::Value> exports = v8::Object::New(GetIsolate()); | 
| +  v8::Handle<v8::Object> natives(NewInstance()); | 
| +  CHECK(!natives.IsEmpty());  // this can happen if v8 has issues | 
| + | 
| +  // These must match the argument order in WrapSource. | 
| +  v8::Handle<v8::Value> args[] = { | 
| +      // AMD. | 
| +      define_object->Get(v8::String::NewFromUtf8(GetIsolate(), "define")), | 
| +      // CommonJS. | 
| +      natives->Get(v8::String::NewFromUtf8( | 
| +          GetIsolate(), "require", v8::String::kInternalizedString)), | 
| +      natives->Get(v8::String::NewFromUtf8( | 
| +          GetIsolate(), "requireNative", v8::String::kInternalizedString)), | 
| +      natives->Get(v8::String::NewFromUtf8( | 
| +          GetIsolate(), "requireAsync", v8::String::kInternalizedString)), | 
| +      exports, | 
| +      // Libraries that we magically expose to every module. | 
| +      console::AsV8Object(), | 
| +      natives->Get(v8::String::NewFromUtf8( | 
| +          GetIsolate(), "privates", v8::String::kInternalizedString)), | 
| +      // Each safe builtin. Keep in order with the arguments in WrapSource. | 
| +      context_->safe_builtins()->GetArray(), | 
| +      context_->safe_builtins()->GetFunction(), | 
| +      context_->safe_builtins()->GetJSON(), | 
| +      context_->safe_builtins()->GetObjekt(), | 
| +      context_->safe_builtins()->GetRegExp(), | 
| +      context_->safe_builtins()->GetString(), | 
| +  }; | 
| +  { | 
| +    v8::TryCatch try_catch; | 
| +    try_catch.SetCaptureMessage(true); | 
| +    context_->CallFunction(func, arraysize(args), args); | 
| +    if (try_catch.HasCaught()) { | 
| +      HandleException(try_catch); | 
| +      return v8::Undefined(GetIsolate()); | 
| +    } | 
| +  } | 
| +  return handle_scope.Escape(exports); | 
| +} | 
| + | 
| +void ModuleSystem::OnDidAddPendingModule( | 
| +    const std::string& id, | 
| +    const std::vector<std::string>& dependencies) { | 
| +  if (!source_map_->Contains(id)) | 
| +    return; | 
| + | 
| +  gin::ModuleRegistry* registry = | 
| +      gin::ModuleRegistry::From(context_->v8_context()); | 
| +  DCHECK(registry); | 
| +  for (std::vector<std::string>::const_iterator it = dependencies.begin(); | 
| +       it != dependencies.end(); | 
| +       ++it) { | 
| +    if (registry->available_modules().count(*it) == 0) | 
| +      LoadModule(*it); | 
| +  } | 
| +  registry->AttemptToLoadMoreModules(GetIsolate()); | 
| +} | 
| + | 
| +void ModuleSystem::OnModuleLoaded( | 
| +    scoped_ptr<v8::UniquePersistent<v8::Promise::Resolver> > resolver, | 
| +    v8::Handle<v8::Value> value) { | 
| +  if (!is_valid()) | 
| +    return; | 
| +  v8::HandleScope handle_scope(GetIsolate()); | 
| +  v8::Handle<v8::Promise::Resolver> resolver_local( | 
| +      v8::Local<v8::Promise::Resolver>::New(GetIsolate(), *resolver)); | 
| +  resolver_local->Resolve(value); | 
| +} | 
| + | 
| }  // namespace extensions | 
|  |