[go: nahoru, domu]

Refactors parts of gin:
. Runner no longer extends ContextHolder. It will still have a
  ContextHolder, but not own it. This enables a couple of
  things:
  . Runner no longer need own a v8::Context.
  . Runner can be lazily created after the ContextHolder.
. Runner becomes a (mostly) pure virtual interface. This enables an
  implementation to execute through blink rather than v8 directly.
. What was Runner is now DefaultRunner (and
  DefaultRunnerDelegate). I'm not a fan of these names, if you have
  better ideas let me know. Maybe DirectRunner?

BUG=none
TEST=none
R=abarth@chromium.org

Review URL: https://codereview.chromium.org/179803007

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@253732 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/gin/converter.h b/gin/converter.h
index 1ce459e..e5c95fc 100644
--- a/gin/converter.h
+++ b/gin/converter.h
@@ -176,8 +176,7 @@
 
 // Convenience functions that deduce T.
 template<typename T>
-v8::Handle<v8::Value> ConvertToV8(v8::Isolate* isolate,
-                                  T input) {
+v8::Handle<v8::Value> ConvertToV8(v8::Isolate* isolate, T input) {
   return Converter<T>::ToV8(isolate, input);
 }
 
diff --git a/gin/gin.gyp b/gin/gin.gyp
index 78c8fb1..a827c426b 100644
--- a/gin/gin.gyp
+++ b/gin/gin.gyp
@@ -58,6 +58,8 @@
         'public/wrapper_info.h',
         'runner.cc',
         'runner.h',
+        'shell_runner.cc',
+        'shell_runner.h',
         'try_catch.cc',
         'try_catch.h',
         'wrappable.cc',
@@ -115,9 +117,9 @@
       'sources': [
         'converter_unittest.cc',
         'modules/timer_unittest.cc',
+        'shell_runner_unittest.cc',
         'test/run_all_unittests.cc',
         'test/run_js_tests.cc',
-        'runner_unittest.cc',
         'wrappable_unittest.cc',
       ],
     },
diff --git a/gin/modules/module_registry.cc b/gin/modules/module_registry.cc
index eda3488..0c1a976 100644
--- a/gin/modules/module_registry.cc
+++ b/gin/modules/module_registry.cc
@@ -101,11 +101,13 @@
   modules_.Reset();
 }
 
+// static
 void ModuleRegistry::RegisterGlobals(Isolate* isolate,
                                      v8::Handle<ObjectTemplate> templ) {
   templ->Set(StringToSymbol(isolate, "define"), GetDefineTemplate(isolate));
 }
 
+// static
 ModuleRegistry* ModuleRegistry::From(v8::Handle<Context> context) {
   Isolate* isolate = context->GetIsolate();
   v8::Handle<String> key = GetHiddenValueKey(isolate);
diff --git a/gin/modules/module_runner_delegate.cc b/gin/modules/module_runner_delegate.cc
index 2a9f95c..16b5afd0 100644
--- a/gin/modules/module_runner_delegate.cc
+++ b/gin/modules/module_runner_delegate.cc
@@ -6,6 +6,7 @@
 
 #include "gin/modules/module_registry.h"
 #include "gin/object_template_builder.h"
+#include "gin/public/context_holder.h"
 
 namespace gin {
 
@@ -23,34 +24,35 @@
 }
 
 void ModuleRunnerDelegate::AttemptToLoadMoreModules(Runner* runner) {
-  ModuleRegistry* registry = ModuleRegistry::From(runner->context());
-  registry->AttemptToLoadMoreModules(runner->isolate());
+  ModuleRegistry* registry = ModuleRegistry::From(
+      runner->GetContextHolder()->context());
+  registry->AttemptToLoadMoreModules(runner->GetContextHolder()->isolate());
   module_provider_.AttempToLoadModules(
       runner, registry->unsatisfied_dependencies());
 }
 
 v8::Handle<v8::ObjectTemplate> ModuleRunnerDelegate::GetGlobalTemplate(
-    Runner* runner) {
-  v8::Handle<v8::ObjectTemplate> templ =
-      ObjectTemplateBuilder(runner->isolate()).Build();
-  ModuleRegistry::RegisterGlobals(runner->isolate(), templ);
+    ShellRunner* runner,
+    v8::Isolate* isolate) {
+  v8::Handle<v8::ObjectTemplate> templ = ObjectTemplateBuilder(isolate).Build();
+  ModuleRegistry::RegisterGlobals(isolate, templ);
   return templ;
 }
 
-void ModuleRunnerDelegate::DidCreateContext(Runner* runner) {
-  RunnerDelegate::DidCreateContext(runner);
+void ModuleRunnerDelegate::DidCreateContext(ShellRunner* runner) {
+  ShellRunnerDelegate::DidCreateContext(runner);
 
-  v8::Handle<v8::Context> context = runner->context();
+  v8::Handle<v8::Context> context = runner->GetContextHolder()->context();
   ModuleRegistry* registry = ModuleRegistry::From(context);
 
+  v8::Isolate* isolate = runner->GetContextHolder()->isolate();
   for (BuiltinModuleMap::const_iterator it = builtin_modules_.begin();
        it != builtin_modules_.end(); ++it) {
-    registry->AddBuiltinModule(runner->isolate(), it->first,
-                               it->second(runner->isolate()));
+    registry->AddBuiltinModule(isolate, it->first, it->second(isolate));
   }
 }
 
-void ModuleRunnerDelegate::DidRunScript(Runner* runner) {
+void ModuleRunnerDelegate::DidRunScript(ShellRunner* runner) {
   AttemptToLoadMoreModules(runner);
 }
 
diff --git a/gin/modules/module_runner_delegate.h b/gin/modules/module_runner_delegate.h
index 3ce056f..09d4582 100644
--- a/gin/modules/module_runner_delegate.h
+++ b/gin/modules/module_runner_delegate.h
@@ -10,7 +10,7 @@
 #include "base/compiler_specific.h"
 #include "gin/gin_export.h"
 #include "gin/modules/file_module_provider.h"
-#include "gin/runner.h"
+#include "gin/shell_runner.h"
 
 namespace gin {
 
@@ -19,7 +19,7 @@
 // Emebedders that use AMD modules will probably want to use a RunnerDelegate
 // that inherits from ModuleRunnerDelegate. ModuleRunnerDelegate lets embedders
 // register built-in modules and routes module requests to FileModuleProvider.
-class GIN_EXPORT ModuleRunnerDelegate : public RunnerDelegate {
+class GIN_EXPORT ModuleRunnerDelegate : public ShellRunnerDelegate {
  public:
   explicit ModuleRunnerDelegate(
       const std::vector<base::FilePath>& search_paths);
@@ -33,11 +33,12 @@
  private:
   typedef std::map<std::string, ModuleGetter> BuiltinModuleMap;
 
-  // From RunnerDelegate:
+  // From ShellRunnerDelegate:
   virtual v8::Handle<v8::ObjectTemplate> GetGlobalTemplate(
-      Runner* runner) OVERRIDE;
-  virtual void DidCreateContext(Runner* runner) OVERRIDE;
-  virtual void DidRunScript(Runner* runner) OVERRIDE;
+      ShellRunner* runner,
+      v8::Isolate* isolate) OVERRIDE;
+  virtual void DidCreateContext(ShellRunner* runner) OVERRIDE;
+  virtual void DidRunScript(ShellRunner* runner) OVERRIDE;
 
   BuiltinModuleMap builtin_modules_;
   FileModuleProvider module_provider_;
diff --git a/gin/modules/timer.cc b/gin/modules/timer.cc
index 6d59f56..3196dda 100644
--- a/gin/modules/timer.cc
+++ b/gin/modules/timer.cc
@@ -45,8 +45,8 @@
       timer_(false, repeating),
       runner_(PerContextData::From(
           isolate->GetCurrentContext())->runner()->GetWeakPtr()) {
-  GetWrapper(runner_->isolate())->SetHiddenValue(GetHiddenPropertyName(isolate),
-                                                 function);
+  GetWrapper(runner_->GetContextHolder()->isolate())->SetHiddenValue(
+      GetHiddenPropertyName(isolate), function);
   timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(delay_ms),
                base::Bind(&Timer::OnTimerFired, weak_factory_.GetWeakPtr()));
 }
@@ -63,10 +63,10 @@
   }
 
   Runner::Scope scope(runner_.get());
+  v8::Isolate* isolate = runner_->GetContextHolder()->isolate();
   v8::Handle<v8::Function> function = v8::Handle<v8::Function>::Cast(
-      GetWrapper(runner_->isolate())->GetHiddenValue(
-          GetHiddenPropertyName(runner_->isolate())));
-  runner_->Call(function, v8::Undefined(runner_->isolate()), 0, NULL);
+      GetWrapper(isolate)->GetHiddenValue(GetHiddenPropertyName(isolate)));
+  runner_->Call(function, v8::Undefined(isolate), 0, NULL);
 }
 
 
diff --git a/gin/modules/timer_unittest.cc b/gin/modules/timer_unittest.cc
index 98267475..f7fd8f2 100644
--- a/gin/modules/timer_unittest.cc
+++ b/gin/modules/timer_unittest.cc
@@ -9,7 +9,7 @@
 #include "gin/handle.h"
 #include "gin/object_template_builder.h"
 #include "gin/public/isolate_holder.h"
-#include "gin/runner.h"
+#include "gin/shell_runner.h"
 #include "gin/test/v8_test.h"
 #include "gin/try_catch.h"
 #include "gin/wrappable.h"
@@ -54,7 +54,7 @@
 
 struct TestHelper {
   TestHelper(v8::Isolate* isolate)
-      : runner(new Runner(&delegate, isolate)),
+      : runner(new ShellRunner(&delegate, isolate)),
         scope(runner.get()),
         timer_module(TimerModule::Create(isolate)),
         result(Result::Create(isolate)) {
@@ -70,8 +70,8 @@
                          base::TimeDelta::FromMilliseconds(0));
   }
 
-  RunnerDelegate delegate;
-  scoped_ptr<Runner> runner;
+  ShellRunnerDelegate delegate;
+  scoped_ptr<ShellRunner> runner;
   Runner::Scope scope;
   Handle<TimerModule> timer_module;
   Handle<Result> result;
diff --git a/gin/per_context_data.cc b/gin/per_context_data.cc
index 5183d00..5fedf52 100644
--- a/gin/per_context_data.cc
+++ b/gin/per_context_data.cc
@@ -40,6 +40,7 @@
   }
 }
 
+// static
 PerContextData* PerContextData::From(v8::Handle<v8::Context> context) {
   return static_cast<PerContextData*>(
       context->GetAlignedPointerFromEmbedderData(kEncodedValueIndex));
diff --git a/gin/public/context_holder.h b/gin/public/context_holder.h
index f8f0c47..afbcf23 100644
--- a/gin/public/context_holder.h
+++ b/gin/public/context_holder.h
@@ -25,9 +25,7 @@
 
 class PerContextData;
 
-// ContextHolder is a generic class for holding a v8::Context. Rather than
-// using ContextHolder directly, most code should use a subclass of
-// ContextHolder, such as Runner.
+// ContextHolder is a generic class for holding a v8::Context.
 class GIN_EXPORT ContextHolder {
  public:
   explicit ContextHolder(v8::Isolate* isolate);
diff --git a/gin/runner.cc b/gin/runner.cc
index e8e4089..6f018b1 100644
--- a/gin/runner.cc
+++ b/gin/runner.cc
@@ -4,106 +4,18 @@
 
 #include "gin/runner.h"
 
-#include "gin/converter.h"
-#include "gin/per_context_data.h"
-#include "gin/try_catch.h"
-
-using v8::Context;
-using v8::HandleScope;
-using v8::Isolate;
-using v8::Object;
-using v8::ObjectTemplate;
-using v8::Script;
-
 namespace gin {
 
-RunnerDelegate::RunnerDelegate() {
-}
-
-RunnerDelegate::~RunnerDelegate() {
-}
-
-v8::Handle<ObjectTemplate> RunnerDelegate::GetGlobalTemplate(Runner* runner) {
-  return v8::Handle<ObjectTemplate>();
-}
-
-void RunnerDelegate::DidCreateContext(Runner* runner) {
-}
-
-void RunnerDelegate::WillRunScript(Runner* runner) {
-}
-
-void RunnerDelegate::DidRunScript(Runner* runner) {
-}
-
-void RunnerDelegate::UnhandledException(Runner* runner, TryCatch& try_catch) {
-  CHECK(false) << try_catch.GetStackTrace();
-}
-
-Runner::Runner(RunnerDelegate* delegate, Isolate* isolate)
-    : ContextHolder(isolate),
-      delegate_(delegate),
-      weak_factory_(this) {
-  v8::Isolate::Scope isolate_scope(isolate);
-  HandleScope handle_scope(isolate);
-  v8::Handle<v8::Context> context =
-      Context::New(isolate, NULL, delegate_->GetGlobalTemplate(this));
-
-  SetContext(context);
-  PerContextData::From(context)->set_runner(this);
-
-  v8::Context::Scope scope(context);
-  delegate_->DidCreateContext(this);
+Runner::Runner() : weak_factory_(this) {
 }
 
 Runner::~Runner() {
 }
 
-void Runner::Run(const std::string& source, const std::string& resource_name) {
-  TryCatch try_catch;
-  v8::Handle<Script> script = Script::New(StringToV8(isolate(), source),
-                                          StringToV8(isolate(), resource_name));
-  if (try_catch.HasCaught()) {
-    delegate_->UnhandledException(this, try_catch);
-    return;
-  }
-
-  Run(script);
-}
-
-void Runner::Run(v8::Handle<Script> script) {
-  TryCatch try_catch;
-  delegate_->WillRunScript(this);
-
-  script->Run();
-
-  delegate_->DidRunScript(this);
-  if (try_catch.HasCaught()) {
-    delegate_->UnhandledException(this, try_catch);
-  }
-}
-
-v8::Handle<v8::Value> Runner::Call(v8::Handle<v8::Function> function,
-                                   v8::Handle<v8::Value> receiver,
-                                   int argc,
-                                   v8::Handle<v8::Value> argv[]) {
-  TryCatch try_catch;
-  delegate_->WillRunScript(this);
-
-  v8::Handle<v8::Value> result = function->Call(receiver, argc, argv);
-
-  delegate_->DidRunScript(this);
-  if (try_catch.HasCaught()) {
-    delegate_->UnhandledException(this, try_catch);
-  }
-
-  return result;
-}
-
 Runner::Scope::Scope(Runner* runner)
-    : isolate_scope_(runner->isolate()),
-      handle_scope_(runner->isolate()),
-      scope_(runner->context()) {
+    : isolate_scope_(runner->GetContextHolder()->isolate()),
+      handle_scope_(runner->GetContextHolder()->isolate()),
+      scope_(runner->GetContextHolder()->context()) {
 }
 
 Runner::Scope::~Scope() {
diff --git a/gin/runner.h b/gin/runner.h
index 943bced..36a75d2 100644
--- a/gin/runner.h
+++ b/gin/runner.h
@@ -10,47 +10,28 @@
 #include "base/memory/weak_ptr.h"
 #include "gin/gin_export.h"
 #include "gin/public/context_holder.h"
+#include "v8/include/v8.h"
 
 namespace gin {
 
-class Runner;
-class TryCatch;
-
-// Subclass RunnerDelegate to customize the behavior of |Runner|. Typical
-// embedders will want to subclass one of the specialized RunnerDelegates,
-// such as ModuleRunnerDelegate.
-class GIN_EXPORT RunnerDelegate {
+// Runner is responsible for running code in a v8::Context.
+class GIN_EXPORT Runner {
  public:
-  RunnerDelegate();
-  virtual ~RunnerDelegate();
-
-  // Returns the template for the global object.
-  virtual v8::Handle<v8::ObjectTemplate> GetGlobalTemplate(Runner* runner);
-  virtual void DidCreateContext(Runner* runner);
-  virtual void WillRunScript(Runner* runner);
-  virtual void DidRunScript(Runner* runner);
-  virtual void UnhandledException(Runner* runner, TryCatch& try_catch);
-};
-
-// Runner lets you run code in a v8::Context. Upon construction, Runner will
-// create a v8::Context. Upon destruction, Runner will dispose the context.
-class GIN_EXPORT Runner : public ContextHolder {
- public:
-  Runner(RunnerDelegate* delegate, v8::Isolate* isolate);
-  ~Runner();
+  Runner();
+  virtual ~Runner();
 
   // Before running script in this context, you'll need to enter the runner's
   // context by creating an instance of Runner::Scope on the stack.
-  void Run(const std::string& source, const std::string& resource_name);
-  void Run(v8::Handle<v8::Script> script);
+  virtual void Run(const std::string& source,
+                   const std::string& resource_name) = 0;
+  virtual v8::Handle<v8::Value> Call(v8::Handle<v8::Function> function,
+                                     v8::Handle<v8::Value> receiver,
+                                     int argc,
+                                     v8::Handle<v8::Value> argv[]) = 0;
+  virtual ContextHolder* GetContextHolder() = 0;
 
-  v8::Handle<v8::Value> Call(v8::Handle<v8::Function> function,
-                             v8::Handle<v8::Value> receiver,
-                             int argc,
-                             v8::Handle<v8::Value> argv[]);
-
-  v8::Handle<v8::Object> global() const {
-    return context()->Global();
+  v8::Handle<v8::Object> global() {
+    return GetContextHolder()->context()->Global();
   }
 
   // Useful for running script in this context asynchronously. Rather than
@@ -75,8 +56,6 @@
  private:
   friend class Scope;
 
-  RunnerDelegate* delegate_;
-
   base::WeakPtrFactory<Runner> weak_factory_;
 
   DISALLOW_COPY_AND_ASSIGN(Runner);
diff --git a/gin/shell/gin_main.cc b/gin/shell/gin_main.cc
index 0ff52cc..3b990f0 100644
--- a/gin/shell/gin_main.cc
+++ b/gin/shell/gin_main.cc
@@ -43,7 +43,7 @@
     AddBuiltinModule(Console::kModuleName, Console::GetModule);
   }
 
-  virtual void UnhandledException(Runner* runner,
+  virtual void UnhandledException(ShellRunner* runner,
                                   TryCatch& try_catch) OVERRIDE {
     ModuleRunnerDelegate::UnhandledException(runner, try_catch);
     LOG(ERROR) << try_catch.GetStackTrace();
@@ -66,7 +66,7 @@
   base::MessageLoop message_loop;
 
   gin::ShellRunnerDelegate delegate;
-  gin::Runner runner(&delegate, instance.isolate());
+  gin::ShellRunner runner(&delegate, instance.isolate());
 
   {
     gin::Runner::Scope scope(&runner);
diff --git a/gin/shell_runner.cc b/gin/shell_runner.cc
new file mode 100644
index 0000000..7f05b3ee
--- /dev/null
+++ b/gin/shell_runner.cc
@@ -0,0 +1,112 @@
+// Copyright 2014 The Chromium 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 "gin/shell_runner.h"
+
+#include "gin/converter.h"
+#include "gin/modules/module_registry.h"
+#include "gin/per_context_data.h"
+#include "gin/public/context_holder.h"
+#include "gin/try_catch.h"
+
+using v8::Context;
+using v8::HandleScope;
+using v8::Isolate;
+using v8::Object;
+using v8::ObjectTemplate;
+using v8::Script;
+
+namespace gin {
+
+ShellRunnerDelegate::ShellRunnerDelegate() {
+}
+
+ShellRunnerDelegate::~ShellRunnerDelegate() {
+}
+
+v8::Handle<ObjectTemplate> ShellRunnerDelegate::GetGlobalTemplate(
+    ShellRunner* runner,
+    v8::Isolate* isolate) {
+  return v8::Handle<ObjectTemplate>();
+}
+
+void ShellRunnerDelegate::DidCreateContext(ShellRunner* runner) {
+}
+
+void ShellRunnerDelegate::WillRunScript(ShellRunner* runner) {
+}
+
+void ShellRunnerDelegate::DidRunScript(ShellRunner* runner) {
+}
+
+void ShellRunnerDelegate::UnhandledException(ShellRunner* runner,
+                                               TryCatch& try_catch) {
+  CHECK(false) << try_catch.GetStackTrace();
+}
+
+ShellRunner::ShellRunner(ShellRunnerDelegate* delegate, Isolate* isolate)
+    : delegate_(delegate) {
+  v8::Isolate::Scope isolate_scope(isolate);
+  HandleScope handle_scope(isolate);
+  v8::Handle<v8::Context> context =
+      Context::New(isolate, NULL, delegate_->GetGlobalTemplate(this, isolate));
+
+  context_holder_.reset(new ContextHolder(isolate));
+  context_holder_->SetContext(context);
+  PerContextData::From(context)->set_runner(this);
+
+  v8::Context::Scope scope(context);
+  delegate_->DidCreateContext(this);
+}
+
+ShellRunner::~ShellRunner() {
+}
+
+void ShellRunner::Run(const std::string& source,
+                      const std::string& resource_name) {
+  TryCatch try_catch;
+  v8::Isolate* isolate = GetContextHolder()->isolate();
+  v8::Handle<Script> script = Script::New(StringToV8(isolate, source),
+                                          StringToV8(isolate, resource_name));
+  if (try_catch.HasCaught()) {
+    delegate_->UnhandledException(this, try_catch);
+    return;
+  }
+
+  Run(script);
+}
+
+v8::Handle<v8::Value> ShellRunner::Call(v8::Handle<v8::Function> function,
+                                        v8::Handle<v8::Value> receiver,
+                                        int argc,
+                                        v8::Handle<v8::Value> argv[]) {
+  TryCatch try_catch;
+  delegate_->WillRunScript(this);
+
+  v8::Handle<v8::Value> result = function->Call(receiver, argc, argv);
+
+  delegate_->DidRunScript(this);
+  if (try_catch.HasCaught())
+    delegate_->UnhandledException(this, try_catch);
+
+  return result;
+}
+
+ContextHolder* ShellRunner::GetContextHolder() {
+  return context_holder_.get();
+}
+
+void ShellRunner::Run(v8::Handle<Script> script) {
+  TryCatch try_catch;
+  delegate_->WillRunScript(this);
+
+  script->Run();
+
+  delegate_->DidRunScript(this);
+  if (try_catch.HasCaught()) {
+    delegate_->UnhandledException(this, try_catch);
+  }
+}
+
+}  // namespace gin
diff --git a/gin/shell_runner.h b/gin/shell_runner.h
new file mode 100644
index 0000000..23e495a
--- /dev/null
+++ b/gin/shell_runner.h
@@ -0,0 +1,68 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GIN_DEFAULT_RUNNER_H_
+#define GIN_DEFAULT_RUNNER_H_
+
+#include "gin/runner.h"
+
+namespace gin {
+
+class ContextHolder;
+class ShellRunner;
+class TryCatch;
+
+// Subclass ShellRunnerDelegate to customize the behavior of ShellRunner.
+// Typical embedders will want to subclass one of the specialized
+// ShellRunnerDelegates, such as ModuleRunnerDelegate.
+class GIN_EXPORT ShellRunnerDelegate {
+ public:
+  ShellRunnerDelegate();
+  virtual ~ShellRunnerDelegate();
+
+  // Returns the template for the global object.
+  virtual v8::Handle<v8::ObjectTemplate> GetGlobalTemplate(
+      ShellRunner* runner,
+      v8::Isolate* isolate);
+  virtual void DidCreateContext(ShellRunner* runner);
+  virtual void WillRunScript(ShellRunner* runner);
+  virtual void DidRunScript(ShellRunner* runner);
+  virtual void UnhandledException(ShellRunner* runner, TryCatch& try_catch);
+};
+
+// ShellRunner executes the script/functions directly in a v8::Context.
+// ShellRunner owns a ContextHolder and v8::Context, both of which are destroyed
+// when the ShellRunner is deleted.
+class GIN_EXPORT ShellRunner : public Runner {
+ public:
+  ShellRunner(ShellRunnerDelegate* delegate, v8::Isolate* isolate);
+  virtual ~ShellRunner();
+
+  // Before running script in this context, you'll need to enter the runner's
+  // context by creating an instance of Runner::Scope on the stack.
+
+  // Runner overrides:
+  virtual void Run(const std::string& source,
+                   const std::string& resource_name) OVERRIDE;
+  virtual v8::Handle<v8::Value> Call(v8::Handle<v8::Function> function,
+                                     v8::Handle<v8::Value> receiver,
+                                     int argc,
+                                     v8::Handle<v8::Value> argv[]) OVERRIDE;
+  virtual ContextHolder* GetContextHolder() OVERRIDE;
+
+ private:
+  friend class Scope;
+
+  void Run(v8::Handle<v8::Script> script);
+
+  ShellRunnerDelegate* delegate_;
+
+  scoped_ptr<ContextHolder> context_holder_;
+
+  DISALLOW_COPY_AND_ASSIGN(ShellRunner);
+};
+
+}  // namespace gin
+
+#endif  // GIN_DEFAULT_RUNNER_H_
diff --git a/gin/runner_unittest.cc b/gin/shell_runner_unittest.cc
similarity index 82%
rename from gin/runner_unittest.cc
rename to gin/shell_runner_unittest.cc
index 3723956..93c071f 100644
--- a/gin/runner_unittest.cc
+++ b/gin/shell_runner_unittest.cc
@@ -1,8 +1,8 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
+// Copyright 2014 The Chromium 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 "gin/runner.h"
+#include "gin/shell_runner.h"
 
 #include "base/compiler_specific.h"
 #include "gin/converter.h"
@@ -21,9 +21,9 @@
 
   gin::IsolateHolder instance;
 
-  RunnerDelegate delegate;
+  ShellRunnerDelegate delegate;
   Isolate* isolate = instance.isolate();
-  Runner runner(&delegate, isolate);
+  ShellRunner runner(&delegate, isolate);
   Runner::Scope scope(&runner);
   runner.Run(source, "test_data.js");
 
diff --git a/gin/test/file_runner.cc b/gin/test/file_runner.cc
index 7b91273..86cb2f3 100644
--- a/gin/test/file_runner.cc
+++ b/gin/test/file_runner.cc
@@ -10,6 +10,7 @@
 #include "gin/converter.h"
 #include "gin/modules/console.h"
 #include "gin/modules/module_registry.h"
+#include "gin/public/context_holder.h"
 #include "gin/public/isolate_holder.h"
 #include "gin/test/gtest.h"
 #include "gin/try_catch.h"
@@ -38,7 +39,7 @@
 FileRunnerDelegate::~FileRunnerDelegate() {
 }
 
-void FileRunnerDelegate::UnhandledException(Runner* runner,
+void FileRunnerDelegate::UnhandledException(ShellRunner* runner,
                                             TryCatch& try_catch) {
   ModuleRunnerDelegate::UnhandledException(runner, try_catch);
   FAIL() << try_catch.GetStackTrace();
@@ -53,7 +54,7 @@
   base::MessageLoop message_loop;
 
   gin::IsolateHolder instance;
-  gin::Runner runner(delegate, instance.isolate());
+  gin::ShellRunner runner(delegate, instance.isolate());
   {
     gin::Runner::Scope scope(&runner);
     v8::V8::SetCaptureStackTraceForUncaughtExceptions(true);
@@ -65,8 +66,8 @@
       message_loop.Run();
     }
 
-    v8::Handle<v8::Value> result = runner.context()->Global()->Get(
-        StringToSymbol(runner.isolate(), "result"));
+    v8::Handle<v8::Value> result = runner.global()->Get(
+        StringToSymbol(runner.GetContextHolder()->isolate(), "result"));
     EXPECT_EQ("PASS", V8ToString(result));
   }
 }
diff --git a/gin/test/file_runner.h b/gin/test/file_runner.h
index 267023d..f248fb59 100644
--- a/gin/test/file_runner.h
+++ b/gin/test/file_runner.h
@@ -24,7 +24,8 @@
 
  private:
   // From ModuleRunnerDelegate:
-  virtual void UnhandledException(Runner* runner, TryCatch& try_catch) OVERRIDE;
+  virtual void UnhandledException(ShellRunner* runner,
+                                  TryCatch& try_catch) OVERRIDE;
 
   DISALLOW_COPY_AND_ASSIGN(FileRunnerDelegate);
 };