Make sure that Content Handled application can be connected multiple times.

This CL updates ApplicationManager so that it always reconnect to an
application that is already launched.

To obtain this results, the following changes habe also been made:

1) The Loader interface has been simplified:
  - The pipe to the shell if given during the Load request, so that loader do
    not need to called RegisterLoadedApplication
2) PngViewer and PdfViewer allows multiple embedder to embed those.
3) For the second connection forward, Sky issue network request to get the
   content of the page to display.

R=aa@chromium.org

Review URL: https://codereview.chromium.org/741453002
diff --git a/mojo/application_manager/application_loader.cc b/mojo/application_manager/application_loader.cc
index 60dec66..ac98b63 100644
--- a/mojo/application_manager/application_loader.cc
+++ b/mojo/application_manager/application_loader.cc
@@ -4,27 +4,23 @@
 
 #include "mojo/application_manager/application_loader.h"
 
+#include "base/bind.h"
 #include "base/logging.h"
 
 namespace mojo {
 
-ApplicationLoader::SimpleLoadCallbacks::SimpleLoadCallbacks(
-    ScopedMessagePipeHandle shell_handle)
-    : shell_handle_(shell_handle.Pass()) {
-}
+namespace {
 
-ApplicationLoader::SimpleLoadCallbacks::~SimpleLoadCallbacks() {
-}
-
-ScopedMessagePipeHandle
-ApplicationLoader::SimpleLoadCallbacks::RegisterApplication() {
-  return shell_handle_.Pass();
-}
-
-void ApplicationLoader::SimpleLoadCallbacks::LoadWithContentHandler(
-    const GURL& content_handle_url,
-    URLResponsePtr url_response) {
+void NotReached(const GURL& url,
+                ScopedMessagePipeHandle shell_handle,
+                URLResponsePtr response) {
   NOTREACHED();
 }
 
+}  // namespace
+
+ApplicationLoader::LoadCallback ApplicationLoader::SimpleLoadCallback() {
+  return base::Bind(&NotReached);
+}
+
 }  // namespace mojo
diff --git a/mojo/application_manager/application_loader.h b/mojo/application_manager/application_loader.h
index f6e4e40..d1267cc 100644
--- a/mojo/application_manager/application_loader.h
+++ b/mojo/application_manager/application_loader.h
@@ -5,7 +5,7 @@
 #ifndef MOJO_APPLICATION_MANAGER_APPLICATION_LOADER_H_
 #define MOJO_APPLICATION_MANAGER_APPLICATION_LOADER_H_
 
-#include "base/memory/ref_counted.h"
+#include "base/callback.h"
 #include "mojo/application_manager/application_manager_export.h"
 #include "mojo/public/cpp/system/core.h"
 #include "mojo/services/public/interfaces/network/url_loader.mojom.h"
@@ -24,56 +24,26 @@
 // apps and services.
 class MOJO_APPLICATION_MANAGER_EXPORT ApplicationLoader {
  public:
-  class MOJO_APPLICATION_MANAGER_EXPORT LoadCallbacks
-      : public base::RefCounted<LoadCallbacks> {
-   public:
-    // Register the requested application with ApplicationManager. If the
-    // returned handle is valid, it should be used to implement the
-    // mojo::Application interface.
-    virtual ScopedMessagePipeHandle RegisterApplication() = 0;
-
-    // Load the requested application with a content handler.
-    virtual void LoadWithContentHandler(const GURL& content_handler_url,
-                                        URLResponsePtr url_response) = 0;
-
-   protected:
-    friend base::RefCounted<LoadCallbacks>;
-    virtual ~LoadCallbacks() {}
-  };
-
-  // Implements RegisterApplication() by returning a handle that was specified
-  // at construction time. LoadWithContentHandler() is not supported.
-  class MOJO_APPLICATION_MANAGER_EXPORT SimpleLoadCallbacks
-      : public LoadCallbacks {
-   public:
-    SimpleLoadCallbacks(ScopedMessagePipeHandle shell_handle);
-    ScopedMessagePipeHandle RegisterApplication() override;
-    void LoadWithContentHandler(const GURL& content_handler_url,
-                                URLResponsePtr response) override;
-
-   private:
-    ScopedMessagePipeHandle shell_handle_;
-    ~SimpleLoadCallbacks() override;
-  };
-
+  typedef base::Callback<
+      void(const GURL&, ScopedMessagePipeHandle, URLResponsePtr)> LoadCallback;
   virtual ~ApplicationLoader() {}
 
+  // Returns a callback that will should never be called.
+  static LoadCallback SimpleLoadCallback();
+
   // Load the application named |url|. Applications can be loaded two ways:
   //
-  // 1. |url| can refer directly to a Mojo application. In this case, call
-  //    callbacks->RegisterApplication(). The returned handle should be used to
-  //    implement the mojo.Application interface. Note that the returned handle
-  //    can be invalid in the case where the application has already been
-  //    loaded.
+  // 1. |url| can refer directly to a Mojo application. In this case,
+  //    shell_handle should be used to implement the mojo.Application interface.
   //
   // 2. |url| can refer to some content that can be handled by some other Mojo
-  //    application. In this case, call callbacks->LoadWithContentHandler() and
-  //    specify the URL of the application that should handle the content.
-  //    The specified application must implement the mojo.ContentHandler
-  //    interface.
+  //    application. In this case, call callbacks and specify the URL of the
+  //    application that should handle the content.  The specified application
+  //    must implement the mojo.ContentHandler interface.
   virtual void Load(ApplicationManager* application_manager,
                     const GURL& url,
-                    scoped_refptr<LoadCallbacks> callbacks) = 0;
+                    ScopedMessagePipeHandle shell_handle,
+                    LoadCallback callback) = 0;
 
   // Called when the Application exits.
   virtual void OnApplicationError(ApplicationManager* manager,
diff --git a/mojo/application_manager/application_manager.cc b/mojo/application_manager/application_manager.cc
index e99c627..1be7853 100644
--- a/mojo/application_manager/application_manager.cc
+++ b/mojo/application_manager/application_manager.cc
@@ -50,55 +50,6 @@
 }
 
 
-class ApplicationManager::LoadCallbacksImpl
-    : public ApplicationLoader::LoadCallbacks {
- public:
-  LoadCallbacksImpl(base::WeakPtr<ApplicationManager> manager,
-                    const GURL& requested_url,
-                    const GURL& resolved_url,
-                    const GURL& requestor_url,
-                    ServiceProviderPtr service_provider)
-      : manager_(manager),
-        requested_url_(requested_url),
-        resolved_url_(resolved_url),
-        requestor_url_(requestor_url),
-        service_provider_(service_provider.Pass()) {}
-
- private:
-  ~LoadCallbacksImpl() override {}
-
-  // LoadCallbacks implementation
-  ScopedMessagePipeHandle RegisterApplication() override {
-    ScopedMessagePipeHandle shell_handle;
-    if (manager_) {
-      manager_->RegisterLoadedApplication(requested_url_,
-                                          resolved_url_,
-                                          requestor_url_,
-                                          service_provider_.Pass(),
-                                          &shell_handle);
-    }
-    return shell_handle.Pass();
-  }
-
-  void LoadWithContentHandler(const GURL& content_handler_url,
-                              URLResponsePtr url_response) override {
-    if (manager_) {
-      manager_->LoadWithContentHandler(requested_url_,
-                                       resolved_url_,
-                                       requestor_url_,
-                                       content_handler_url,
-                                       url_response.Pass(),
-                                       service_provider_.Pass());
-    }
-  }
-
-  base::WeakPtr<ApplicationManager> manager_;
-  GURL requested_url_;
-  GURL resolved_url_;
-  GURL requestor_url_;
-  ServiceProviderPtr service_provider_;
-};
-
 class ApplicationManager::ShellImpl : public Shell, public ErrorHandler {
  public:
   ShellImpl(ScopedMessagePipeHandle handle,
@@ -222,7 +173,6 @@
 
 void ApplicationManager::TerminateShellConnections() {
   STLDeleteValues(&url_to_shell_impl_);
-  STLDeleteElements(&content_shell_impls_);
 }
 
 void ApplicationManager::ConnectToApplication(
@@ -250,24 +200,28 @@
 }
 
 void ApplicationManager::ConnectToApplicationImpl(
-    const GURL& requested_url, const GURL& resolved_url,
-    const GURL& requestor_url, ServiceProviderPtr service_provider,
+    const GURL& requested_url,
+    const GURL& resolved_url,
+    const GURL& requestor_url,
+    ServiceProviderPtr service_provider,
     ApplicationLoader* loader) {
+  ShellImpl* shell = nullptr;
   URLToShellImplMap::const_iterator shell_it =
       url_to_shell_impl_.find(resolved_url);
   if (shell_it != url_to_shell_impl_.end()) {
-    ConnectToClient(shell_it->second, resolved_url, requestor_url,
-                    service_provider.Pass());
-    return;
-  }
+    shell = shell_it->second;
+  } else {
+    MessagePipe pipe;
+    shell =
+        new ShellImpl(pipe.handle0.Pass(), this, requested_url, resolved_url);
+    url_to_shell_impl_[resolved_url] = shell;
+    shell->client()->Initialize(GetArgsForURL(requested_url));
 
-  scoped_refptr<LoadCallbacksImpl> callbacks(
-      new LoadCallbacksImpl(weak_ptr_factory_.GetWeakPtr(),
-                            requested_url,
-                            resolved_url,
-                            requestor_url,
-                            service_provider.Pass()));
-  loader->Load(this, resolved_url, callbacks);
+    loader->Load(this, resolved_url, pipe.handle1.Pass(),
+                 base::Bind(&ApplicationManager::LoadWithContentHandler,
+                            weak_ptr_factory_.GetWeakPtr()));
+  }
+  ConnectToClient(shell, resolved_url, requestor_url, service_provider.Pass());
 }
 
 void ApplicationManager::ConnectToClient(ShellImpl* shell_impl,
@@ -296,39 +250,10 @@
   shell_impl->client()->Initialize(args.Pass());
 }
 
-void ApplicationManager::RegisterLoadedApplication(
-    const GURL& requested_url,
-    const GURL& resolved_url,
-    const GURL& requestor_url,
-    ServiceProviderPtr service_provider,
-    ScopedMessagePipeHandle* shell_handle) {
-  ShellImpl* shell_impl = NULL;
-  URLToShellImplMap::iterator iter = url_to_shell_impl_.find(resolved_url);
-  if (iter != url_to_shell_impl_.end()) {
-    // This can happen because services are loaded asynchronously. So if we get
-    // two requests for the same service close to each other, we might get here
-    // and find that we already have it.
-    shell_impl = iter->second;
-  } else {
-    MessagePipe pipe;
-    shell_impl =
-        new ShellImpl(pipe.handle1.Pass(), this, requested_url, resolved_url);
-    url_to_shell_impl_[resolved_url] = shell_impl;
-    *shell_handle = pipe.handle0.Pass();
-    shell_impl->client()->Initialize(GetArgsForURL(requested_url));
-  }
-
-  ConnectToClient(shell_impl, resolved_url, requestor_url,
-                  service_provider.Pass());
-}
-
 void ApplicationManager::LoadWithContentHandler(
-    const GURL& requested_url,
-    const GURL& resolved_url,
-    const GURL& requestor_url,
     const GURL& content_handler_url,
-    URLResponsePtr url_response,
-    ServiceProviderPtr service_provider) {
+    ScopedMessagePipeHandle shell_handle,
+    URLResponsePtr url_response) {
   ContentHandlerConnection* connection = NULL;
   URLToContentHandlerMap::iterator iter =
       url_to_content_handler_.find(content_handler_url);
@@ -339,16 +264,8 @@
     url_to_content_handler_[content_handler_url] = connection;
   }
 
-  ShellPtr shell_proxy;
-  ShellImpl* shell_impl =
-      new ShellImpl(&shell_proxy, this, requested_url, resolved_url);
-  content_shell_impls_.insert(shell_impl);
-  shell_impl->client()->Initialize(GetArgsForURL(requested_url));
-
-  connection->content_handler()->StartApplication(shell_proxy.Pass(),
-                                                  url_response.Pass());
-  ConnectToClient(
-      shell_impl, resolved_url, requestor_url, service_provider.Pass());
+  connection->content_handler()->StartApplication(
+      MakeProxy<Shell>(shell_handle.Pass()), url_response.Pass());
 }
 
 void ApplicationManager::SetLoaderForURL(scoped_ptr<ApplicationLoader> loader,
@@ -392,12 +309,6 @@
 
 void ApplicationManager::OnShellImplError(ShellImpl* shell_impl) {
   // Called from ~ShellImpl, so we do not need to call Destroy here.
-  auto content_shell_it = content_shell_impls_.find(shell_impl);
-  if (content_shell_it != content_shell_impls_.end()) {
-    delete (*content_shell_it);
-    content_shell_impls_.erase(content_shell_it);
-    return;
-  }
   const GURL url = shell_impl->url();
   const GURL requested_url = shell_impl->requested_url();
   // Remove the shell.
diff --git a/mojo/application_manager/application_manager.h b/mojo/application_manager/application_manager.h
index 84ad9c4..212aeea 100644
--- a/mojo/application_manager/application_manager.h
+++ b/mojo/application_manager/application_manager.h
@@ -109,7 +109,6 @@
   };
 
   class ContentHandlerConnection;
-  class LoadCallbacksImpl;
   class ShellImpl;
 
   typedef std::map<std::string, ApplicationLoader*> SchemeToLoaderMap;
@@ -129,18 +128,9 @@
                        const GURL& requestor_url,
                        ServiceProviderPtr service_provider);
 
-  void RegisterLoadedApplication(const GURL& requested_url,
-                                 const GURL& resolved_url,
-                                 const GURL& requestor_url,
-                                 ServiceProviderPtr service_provider,
-                                 ScopedMessagePipeHandle* shell_handle);
-
-  void LoadWithContentHandler(const GURL& requested_url,
-                              const GURL& resolved_url,
-                              const GURL& requestor_url,
-                              const GURL& content_handler_url,
-                              URLResponsePtr url_response,
-                              ServiceProviderPtr service_provider);
+  void LoadWithContentHandler(const GURL& content_handler_url,
+                              ScopedMessagePipeHandle shell_handle,
+                              URLResponsePtr url_response);
 
   // Return the appropriate loader for |url|. This can return NULL if there is
   // no default loader configured.
@@ -166,7 +156,6 @@
   URLToShellImplMap url_to_shell_impl_;
   URLToContentHandlerMap url_to_content_handler_;
   URLToArgsMap url_to_args_;
-  std::set<ShellImpl*> content_shell_impls_;
 
   base::WeakPtrFactory<ApplicationManager> weak_ptr_factory_;
 
diff --git a/mojo/application_manager/application_manager_unittest.cc b/mojo/application_manager/application_manager_unittest.cc
index 4db9706..53fcec1 100644
--- a/mojo/application_manager/application_manager_unittest.cc
+++ b/mojo/application_manager/application_manager_unittest.cc
@@ -115,10 +115,10 @@
   // ApplicationLoader implementation.
   void Load(ApplicationManager* manager,
             const GURL& url,
-            scoped_refptr<LoadCallbacks> callbacks) override {
+            ScopedMessagePipeHandle shell_handle,
+            LoadCallback callback) override {
     ++num_loads_;
-    test_app_.reset(
-        new ApplicationImpl(this, callbacks->RegisterApplication().Pass()));
+    test_app_.reset(new ApplicationImpl(this, shell_handle.Pass()));
   }
 
   void OnApplicationError(ApplicationManager* manager,
@@ -326,9 +326,9 @@
  private:
   void Load(ApplicationManager* manager,
             const GURL& url,
-            scoped_refptr<LoadCallbacks> callbacks) override {
-    app_.reset(
-        new ApplicationImpl(this, callbacks->RegisterApplication().Pass()));
+            ScopedMessagePipeHandle shell_handle,
+            LoadCallback callback) override {
+    app_.reset(new ApplicationImpl(this, shell_handle.Pass()));
   }
 
   void OnApplicationError(ApplicationManager* manager,
diff --git a/mojo/application_manager/background_shell_application_loader.cc b/mojo/application_manager/background_shell_application_loader.cc
index e6664db..a89e36a 100644
--- a/mojo/application_manager/background_shell_application_loader.cc
+++ b/mojo/application_manager/background_shell_application_loader.cc
@@ -10,29 +10,6 @@
 
 namespace mojo {
 
-class BackgroundShellApplicationLoader::BackgroundLoader {
- public:
-  explicit BackgroundLoader(ApplicationLoader* loader) : loader_(loader) {}
-  ~BackgroundLoader() {}
-
-  void Load(ApplicationManager* manager,
-            const GURL& url,
-            ScopedMessagePipeHandle shell_handle) {
-    scoped_refptr<LoadCallbacks> callbacks(
-        new ApplicationLoader::SimpleLoadCallbacks(shell_handle.Pass()));
-    loader_->Load(manager, url, callbacks);
-  }
-
-  void OnApplicationError(ApplicationManager* manager, const GURL& url) {
-    loader_->OnApplicationError(manager, url);
-  }
-
- private:
-  ApplicationLoader* loader_;  // Owned by BackgroundShellApplicationLoader
-
-  DISALLOW_COPY_AND_ASSIGN(BackgroundLoader);
-};
-
 BackgroundShellApplicationLoader::BackgroundShellApplicationLoader(
     scoped_ptr<ApplicationLoader> real_loader,
     const std::string& thread_name,
@@ -40,8 +17,7 @@
     : loader_(real_loader.Pass()),
       message_loop_type_(message_loop_type),
       thread_name_(thread_name),
-      message_loop_created_(true, false),
-      background_loader_(NULL) {
+      message_loop_created_(true, false) {
 }
 
 BackgroundShellApplicationLoader::~BackgroundShellApplicationLoader() {
@@ -52,11 +28,9 @@
 void BackgroundShellApplicationLoader::Load(
     ApplicationManager* manager,
     const GURL& url,
-    scoped_refptr<LoadCallbacks> callbacks) {
-  ScopedMessagePipeHandle shell_handle = callbacks->RegisterApplication();
-  if (!shell_handle.is_valid())
-    return;
-
+    ScopedMessagePipeHandle shell_handle,
+    LoadCallback callback) {
+  DCHECK(shell_handle.is_valid());
   if (!thread_) {
     // TODO(tim): It'd be nice if we could just have each Load call
     // result in a new thread like DynamicService{Loader, Runner}. But some
@@ -72,12 +46,9 @@
 
   task_runner_->PostTask(
       FROM_HERE,
-      base::Bind(
-          &BackgroundShellApplicationLoader::LoadOnBackgroundThread,
-          base::Unretained(this),
-          manager,
-          url,
-          base::Owned(new ScopedMessagePipeHandle(shell_handle.Pass()))));
+      base::Bind(&BackgroundShellApplicationLoader::LoadOnBackgroundThread,
+                 base::Unretained(this), manager, url,
+                 base::Passed(&shell_handle)));
 }
 
 void BackgroundShellApplicationLoader::OnApplicationError(
@@ -99,8 +70,6 @@
   message_loop_created_.Signal();
   loop.Run();
 
-  delete background_loader_;
-  background_loader_ = NULL;
   // Destroy |loader_| on the thread it's actually used on.
   loader_.reset();
 }
@@ -108,20 +77,16 @@
 void BackgroundShellApplicationLoader::LoadOnBackgroundThread(
     ApplicationManager* manager,
     const GURL& url,
-    ScopedMessagePipeHandle* shell_handle) {
+    ScopedMessagePipeHandle shell_handle) {
   DCHECK(task_runner_->RunsTasksOnCurrentThread());
-  if (!background_loader_)
-    background_loader_ = new BackgroundLoader(loader_.get());
-  background_loader_->Load(manager, url, shell_handle->Pass());
+  loader_->Load(manager, url, shell_handle.Pass(), SimpleLoadCallback());
 }
 
 void BackgroundShellApplicationLoader::OnApplicationErrorOnBackgroundThread(
     ApplicationManager* manager,
     const GURL& url) {
   DCHECK(task_runner_->RunsTasksOnCurrentThread());
-  if (!background_loader_)
-    background_loader_ = new BackgroundLoader(loader_.get());
-  background_loader_->OnApplicationError(manager, url);
+  loader_->OnApplicationError(manager, url);
 }
 
 }  // namespace mojo
diff --git a/mojo/application_manager/background_shell_application_loader.h b/mojo/application_manager/background_shell_application_loader.h
index 399df43..a1d8ef3 100644
--- a/mojo/application_manager/background_shell_application_loader.h
+++ b/mojo/application_manager/background_shell_application_loader.h
@@ -29,13 +29,12 @@
   // ApplicationLoader overrides:
   void Load(ApplicationManager* manager,
             const GURL& url,
-            scoped_refptr<LoadCallbacks> callbacks) override;
+            ScopedMessagePipeHandle shell_handle,
+            LoadCallback callback) override;
   void OnApplicationError(ApplicationManager* manager,
                           const GURL& url) override;
 
  private:
-  class BackgroundLoader;
-
   // |base::DelegateSimpleThread::Delegate| method:
   void Run() override;
 
@@ -45,7 +44,7 @@
   // isn't thread safe).
   void LoadOnBackgroundThread(ApplicationManager* manager,
                               const GURL& url,
-                              ScopedMessagePipeHandle* shell_handle);
+                              ScopedMessagePipeHandle shell_handle);
   void OnApplicationErrorOnBackgroundThread(ApplicationManager* manager,
                                             const GURL& url);
   bool quit_on_shutdown_;
@@ -66,9 +65,6 @@
 
   scoped_ptr<base::DelegateSimpleThread> thread_;
 
-  // Lives on |thread_|. Trivial interface that calls through to |loader_|.
-  BackgroundLoader* background_loader_;
-
   DISALLOW_COPY_AND_ASSIGN(BackgroundShellApplicationLoader);
 };
 
diff --git a/mojo/application_manager/background_shell_application_loader_unittest.cc b/mojo/application_manager/background_shell_application_loader_unittest.cc
index ae9eae9..b783a72 100644
--- a/mojo/application_manager/background_shell_application_loader_unittest.cc
+++ b/mojo/application_manager/background_shell_application_loader_unittest.cc
@@ -18,7 +18,8 @@
   // ApplicationLoader overrides:
   void Load(ApplicationManager* manager,
             const GURL& url,
-            scoped_refptr<LoadCallbacks> callbacks) override {
+            ScopedMessagePipeHandle shell_handle,
+            LoadCallback callback) override {
     if (simulate_app_quit_)
       base::MessageLoop::current()->Quit();
   }
@@ -48,9 +49,8 @@
   BackgroundShellApplicationLoader loader(
       real_loader.Pass(), "test", base::MessageLoop::TYPE_DEFAULT);
   MessagePipe dummy;
-  scoped_refptr<ApplicationLoader::SimpleLoadCallbacks> callbacks(
-      new ApplicationLoader::SimpleLoadCallbacks(dummy.handle0.Pass()));
-  loader.Load(NULL, GURL(), callbacks);
+  loader.Load(NULL, GURL(), dummy.handle0.Pass(),
+              ApplicationLoader::SimpleLoadCallback());
 }
 
 }  // namespace mojo
diff --git a/mojo/services/public/cpp/view_manager/tests/view_manager_unittest.cc b/mojo/services/public/cpp/view_manager/tests/view_manager_unittest.cc
index 15ad527..540b145 100644
--- a/mojo/services/public/cpp/view_manager/tests/view_manager_unittest.cc
+++ b/mojo/services/public/cpp/view_manager/tests/view_manager_unittest.cc
@@ -63,12 +63,11 @@
   // Overridden from ApplicationLoader:
   void Load(ApplicationManager* manager,
             const GURL& url,
-            scoped_refptr<LoadCallbacks> callbacks) override {
-    ScopedMessagePipeHandle shell_handle = callbacks->RegisterApplication();
-    if (!shell_handle.is_valid())
-      return;
-    scoped_ptr<ApplicationImpl> app(new ApplicationImpl(this,
-                                                        shell_handle.Pass()));
+            ScopedMessagePipeHandle shell_handle,
+            LoadCallback callback) override {
+    ASSERT_TRUE(shell_handle.is_valid());
+    scoped_ptr<ApplicationImpl> app(
+        new ApplicationImpl(this, shell_handle.Pass()));
     apps_.push_back(app.release());
   }
 
diff --git a/mojo/services/view_manager/view_manager_unittest.cc b/mojo/services/view_manager/view_manager_unittest.cc
index 6f64ad8..c573cf1 100644
--- a/mojo/services/view_manager/view_manager_unittest.cc
+++ b/mojo/services/view_manager/view_manager_unittest.cc
@@ -422,12 +422,11 @@
   // ApplicationLoader implementation:
   void Load(ApplicationManager* manager,
             const GURL& url,
-            scoped_refptr<LoadCallbacks> callbacks) override {
-    ScopedMessagePipeHandle shell_handle = callbacks->RegisterApplication();
-    if (!shell_handle.is_valid())
-      return;
-    scoped_ptr<ApplicationImpl> app(new ApplicationImpl(this,
-                                                        shell_handle.Pass()));
+            ScopedMessagePipeHandle shell_handle,
+            LoadCallback callback) override {
+    ASSERT_TRUE(shell_handle.is_valid());
+    scoped_ptr<ApplicationImpl> app(
+        new ApplicationImpl(this, shell_handle.Pass()));
     apps_.push_back(app.release());
   }
   void OnApplicationError(ApplicationManager* manager,
@@ -517,10 +516,9 @@
   // ApplicationLoader implementation:
   virtual void Load(ApplicationManager* manager,
                     const GURL& url,
-                    scoped_refptr<LoadCallbacks> callbacks) override {
-    ScopedMessagePipeHandle shell_handle = callbacks->RegisterApplication();
-    if (!shell_handle.is_valid())
-      return;
+                    ScopedMessagePipeHandle shell_handle,
+                    LoadCallback callback) override {
+    ASSERT_TRUE(shell_handle.is_valid());
     scoped_ptr<ApplicationImpl> app(
         new ApplicationImpl(this, shell_handle.Pass()));
     apps_.push_back(app.release());
diff --git a/mojo/services/window_manager/window_manager_api_unittest.cc b/mojo/services/window_manager/window_manager_api_unittest.cc
index 683be56..30ce038 100644
--- a/mojo/services/window_manager/window_manager_api_unittest.cc
+++ b/mojo/services/window_manager/window_manager_api_unittest.cc
@@ -78,10 +78,9 @@
   // Overridden from ApplicationLoader:
   void Load(ApplicationManager* application_manager,
             const GURL& url,
-            scoped_refptr<LoadCallbacks> callbacks) override {
-    ScopedMessagePipeHandle shell_handle = callbacks->RegisterApplication();
-    if (!shell_handle.is_valid())
-      return;
+            ScopedMessagePipeHandle shell_handle,
+            LoadCallback callback) override {
+    ASSERT_TRUE(shell_handle.is_valid());
     scoped_ptr<ApplicationImpl> app(
         new ApplicationImpl(this, shell_handle.Pass()));
     apps_.push_back(app.release());
diff --git a/mojo/shell/context.cc b/mojo/shell/context.cc
index fab5a6a..90b296c 100644
--- a/mojo/shell/context.cc
+++ b/mojo/shell/context.cc
@@ -134,10 +134,10 @@
   // ApplicationLoader implementation.
   virtual void Load(ApplicationManager* manager,
                     const GURL& url,
-                    scoped_refptr<LoadCallbacks> callbacks) override {
-    ScopedMessagePipeHandle shell_handle = callbacks->RegisterApplication();
-    if (shell_handle.is_valid())
-      app_.reset(new ApplicationImpl(this, shell_handle.Pass()));
+                    ScopedMessagePipeHandle shell_handle,
+                    LoadCallback callback) override {
+    DCHECK(shell_handle.is_valid());
+    app_.reset(new ApplicationImpl(this, shell_handle.Pass()));
   }
 
   virtual void OnApplicationError(ApplicationManager* manager,
diff --git a/mojo/shell/dynamic_application_loader.cc b/mojo/shell/dynamic_application_loader.cc
index 7c57871..35578d1 100644
--- a/mojo/shell/dynamic_application_loader.cc
+++ b/mojo/shell/dynamic_application_loader.cc
@@ -53,9 +53,11 @@
   Loader(MimeTypeToURLMap* mime_type_to_url,
          Context* context,
          DynamicServiceRunnerFactory* runner_factory,
-         scoped_refptr<ApplicationLoader::LoadCallbacks> load_callbacks,
+         ScopedMessagePipeHandle shell_handle,
+         ApplicationLoader::LoadCallback load_callback,
          const LoaderCompleteCallback& loader_complete_callback)
-      : load_callbacks_(load_callbacks),
+      : shell_handle_(shell_handle.Pass()),
+        load_callback_(load_callback),
         loader_complete_callback_(loader_complete_callback),
         context_(context),
         mime_type_to_url_(mime_type_to_url),
@@ -83,16 +85,17 @@
     GURL url;
     std::string shebang;
     if (PeekContentHandler(&shebang, &url)) {
-      load_callbacks_->LoadWithContentHandler(
-          url, AsURLResponse(context_->task_runners()->blocking_pool(),
-                             static_cast<int>(shebang.size())));
+      load_callback_.Run(
+          url, shell_handle_.Pass(),
+          AsURLResponse(context_->task_runners()->blocking_pool(),
+                        static_cast<int>(shebang.size())));
       return;
     }
 
     MimeTypeToURLMap::iterator iter = mime_type_to_url_->find(MimeType());
     if (iter != mime_type_to_url_->end()) {
-      load_callbacks_->LoadWithContentHandler(
-          iter->second,
+      load_callback_.Run(
+          iter->second, shell_handle_.Pass(),
           AsURLResponse(context_->task_runners()->blocking_pool(), 0));
       return;
     }
@@ -124,12 +127,7 @@
   }
 
   void RunLibrary(const base::FilePath& path, bool path_exists) {
-    ScopedMessagePipeHandle shell_handle =
-        load_callbacks_->RegisterApplication();
-    if (!shell_handle.is_valid()) {
-      ReportComplete();
-      return;
-    }
+    DCHECK(shell_handle_.is_valid());
 
     if (!path_exists) {
       LOG(ERROR) << "Library not started because library path '" << path.value()
@@ -140,11 +138,12 @@
 
     runner_ = runner_factory_->Create(context_);
     runner_->Start(
-        path, shell_handle.Pass(),
+        path, shell_handle_.Pass(),
         base::Bind(&Loader::ReportComplete, weak_ptr_factory_.GetWeakPtr()));
   }
 
-  scoped_refptr<ApplicationLoader::LoadCallbacks> load_callbacks_;
+  ScopedMessagePipeHandle shell_handle_;
+  ApplicationLoader::LoadCallback load_callback_;
   LoaderCompleteCallback loader_complete_callback_;
   Context* context_;
   MimeTypeToURLMap* mime_type_to_url_;
@@ -160,12 +159,14 @@
               MimeTypeToURLMap* mime_type_to_url,
               Context* context,
               DynamicServiceRunnerFactory* runner_factory,
-              scoped_refptr<ApplicationLoader::LoadCallbacks> load_callbacks,
+              ScopedMessagePipeHandle shell_handle,
+              ApplicationLoader::LoadCallback load_callback,
               const LoaderCompleteCallback& loader_complete_callback)
       : Loader(mime_type_to_url,
                context,
                runner_factory,
-               load_callbacks,
+               shell_handle.Pass(),
+               load_callback,
                loader_complete_callback),
         url_(url),
         path_(UrlToFile(url)) {
@@ -246,12 +247,14 @@
                 MimeTypeToURLMap* mime_type_to_url,
                 Context* context,
                 DynamicServiceRunnerFactory* runner_factory,
-                scoped_refptr<ApplicationLoader::LoadCallbacks> load_callbacks,
+                ScopedMessagePipeHandle shell_handle,
+                ApplicationLoader::LoadCallback load_callback,
                 const LoaderCompleteCallback& loader_complete_callback)
       : Loader(mime_type_to_url,
                context,
                runner_factory,
-               load_callbacks,
+               shell_handle.Pass(),
+               load_callback,
                loader_complete_callback),
         weak_ptr_factory_(this) {
     StartNetworkRequest(url, network_service);
@@ -365,14 +368,14 @@
   mime_type_to_url_[mime_type] = content_handler_url;
 }
 
-void DynamicApplicationLoader::Load(
-    ApplicationManager* manager,
-    const GURL& url,
-    scoped_refptr<LoadCallbacks> load_callbacks) {
+void DynamicApplicationLoader::Load(ApplicationManager* manager,
+                                    const GURL& url,
+                                    ScopedMessagePipeHandle shell_handle,
+                                    LoadCallback load_callback) {
   if (url.SchemeIsFile()) {
-    loaders_.push_back(new LocalLoader(url, &mime_type_to_url_, context_,
-                                       runner_factory_.get(), load_callbacks,
-                                       loader_complete_callback_));
+    loaders_.push_back(new LocalLoader(
+        url, &mime_type_to_url_, context_, runner_factory_.get(),
+        shell_handle.Pass(), load_callback, loader_complete_callback_));
     return;
   }
 
@@ -381,9 +384,10 @@
         GURL("mojo:network_service"), &network_service_);
   }
 
-  loaders_.push_back(new NetworkLoader(
-      url, network_service_.get(), &mime_type_to_url_, context_,
-      runner_factory_.get(), load_callbacks, loader_complete_callback_));
+  loaders_.push_back(
+      new NetworkLoader(url, network_service_.get(), &mime_type_to_url_,
+                        context_, runner_factory_.get(), shell_handle.Pass(),
+                        load_callback, loader_complete_callback_));
 }
 
 void DynamicApplicationLoader::OnApplicationError(ApplicationManager* manager,
diff --git a/mojo/shell/dynamic_application_loader.h b/mojo/shell/dynamic_application_loader.h
index 5644100..7a7b41b 100644
--- a/mojo/shell/dynamic_application_loader.h
+++ b/mojo/shell/dynamic_application_loader.h
@@ -40,7 +40,8 @@
   // ApplicationLoader methods:
   void Load(ApplicationManager* manager,
             const GURL& url,
-            scoped_refptr<LoadCallbacks> callbacks) override;
+            ScopedMessagePipeHandle shell_handle,
+            LoadCallback callback) override;
   void OnApplicationError(ApplicationManager* manager,
                           const GURL& url) override;
 
diff --git a/mojo/shell/dynamic_application_loader_unittest.cc b/mojo/shell/dynamic_application_loader_unittest.cc
index 7c04e4c..07fb614 100644
--- a/mojo/shell/dynamic_application_loader_unittest.cc
+++ b/mojo/shell/dynamic_application_loader_unittest.cc
@@ -83,9 +83,8 @@
   base::FilePath nonexistent_file(FILE_PATH_LITERAL("nonexistent.txt"));
   GURL url(FilePathToFileURL(temp_dir.path().Append(nonexistent_file)));
   MessagePipe pipe;
-  scoped_refptr<ApplicationLoader::SimpleLoadCallbacks> callbacks(
-      new ApplicationLoader::SimpleLoadCallbacks(pipe.handle0.Pass()));
-  loader_->Load(context_.application_manager(), url, callbacks);
+  loader_->Load(context_.application_manager(), url, pipe.handle0.Pass(),
+                ApplicationLoader::SimpleLoadCallback());
   EXPECT_FALSE(state_.runner_was_created);
   EXPECT_FALSE(state_.runner_was_started);
   EXPECT_FALSE(state_.runner_was_destroyed);
diff --git a/mojo/shell/external_application_listener_unittest.cc b/mojo/shell/external_application_listener_unittest.cc
index 9433312..c694065 100644
--- a/mojo/shell/external_application_listener_unittest.cc
+++ b/mojo/shell/external_application_listener_unittest.cc
@@ -33,7 +33,8 @@
 
   void Load(ApplicationManager* application_manager,
             const GURL& url,
-            scoped_refptr<LoadCallbacks> callbacks) override {
+            ScopedMessagePipeHandle shell_handle,
+            LoadCallback callback) override {
     NOTREACHED();
   }
 
diff --git a/mojo/shell/network_application_loader.cc b/mojo/shell/network_application_loader.cc
index dbe70b7..6a2c519 100644
--- a/mojo/shell/network_application_loader.cc
+++ b/mojo/shell/network_application_loader.cc
@@ -31,11 +31,9 @@
 
 void NetworkApplicationLoader::Load(ApplicationManager* manager,
                                     const GURL& url,
-                                    scoped_refptr<LoadCallbacks> callbacks) {
-  ScopedMessagePipeHandle shell_handle = callbacks->RegisterApplication();
-  if (!shell_handle.is_valid())
-    return;
-
+                                    ScopedMessagePipeHandle shell_handle,
+                                    LoadCallback callback) {
+  DCHECK(shell_handle.is_valid());
   uintptr_t key = reinterpret_cast<uintptr_t>(manager);
   if (apps_.find(key) == apps_.end()) {
     scoped_ptr<ApplicationImpl> app(
diff --git a/mojo/shell/network_application_loader.h b/mojo/shell/network_application_loader.h
index 0f426b0..e06d250 100644
--- a/mojo/shell/network_application_loader.h
+++ b/mojo/shell/network_application_loader.h
@@ -32,7 +32,8 @@
   // ApplicationLoader overrides:
   virtual void Load(ApplicationManager* manager,
                     const GURL& url,
-                    scoped_refptr<LoadCallbacks> callbacks) override;
+                    ScopedMessagePipeHandle shell_handle,
+                    LoadCallback callback) override;
   virtual void OnApplicationError(ApplicationManager* manager,
                                   const GURL& url) override;
 
diff --git a/mojo/shell/ui_application_loader_android.cc b/mojo/shell/ui_application_loader_android.cc
index 1e4e5aa..b871707 100644
--- a/mojo/shell/ui_application_loader_android.cc
+++ b/mojo/shell/ui_application_loader_android.cc
@@ -10,29 +10,6 @@
 
 namespace mojo {
 
-class UIApplicationLoader::UILoader {
- public:
-  explicit UILoader(ApplicationLoader* loader) : loader_(loader) {}
-  ~UILoader() {}
-
-  void Load(ApplicationManager* manager,
-            const GURL& url,
-            ScopedMessagePipeHandle shell_handle) {
-    scoped_refptr<LoadCallbacks> callbacks(
-        new ApplicationLoader::SimpleLoadCallbacks(shell_handle.Pass()));
-    loader_->Load(manager, url, callbacks);
-  }
-
-  void OnApplicationError(ApplicationManager* manager, const GURL& url) {
-    loader_->OnApplicationError(manager, url);
-  }
-
- private:
-  ApplicationLoader* loader_;  // Owned by UIApplicationLoader
-
-  DISALLOW_COPY_AND_ASSIGN(UILoader);
-};
-
 UIApplicationLoader::UIApplicationLoader(
     scoped_ptr<ApplicationLoader> real_loader,
     shell::Context* context)
@@ -48,18 +25,13 @@
 
 void UIApplicationLoader::Load(ApplicationManager* manager,
                                const GURL& url,
-                               scoped_refptr<LoadCallbacks> callbacks) {
-  ScopedMessagePipeHandle shell_handle = callbacks->RegisterApplication();
-  if (!shell_handle.is_valid())
-    return;
+                               ScopedMessagePipeHandle shell_handle,
+                               LoadCallback callback) {
+  DCHECK(shell_handle.is_valid());
   context_->ui_loop()->PostTask(
       FROM_HERE,
-      base::Bind(
-          &UIApplicationLoader::LoadOnUIThread,
-          base::Unretained(this),
-          manager,
-          url,
-          base::Owned(new ScopedMessagePipeHandle(shell_handle.Pass()))));
+      base::Bind(&UIApplicationLoader::LoadOnUIThread, base::Unretained(this),
+                 manager, url, base::Passed(&shell_handle)));
 }
 
 void UIApplicationLoader::OnApplicationError(ApplicationManager* manager,
@@ -72,25 +44,19 @@
                  url));
 }
 
-void UIApplicationLoader::LoadOnUIThread(
-    ApplicationManager* manager,
-    const GURL& url,
-    ScopedMessagePipeHandle* shell_handle) {
-  if (!ui_loader_)
-    ui_loader_ = new UILoader(loader_.get());
-  ui_loader_->Load(manager, url, shell_handle->Pass());
+void UIApplicationLoader::LoadOnUIThread(ApplicationManager* manager,
+                                         const GURL& url,
+                                         ScopedMessagePipeHandle shell_handle) {
+  loader_->Load(manager, url, shell_handle.Pass(), SimpleLoadCallback());
 }
 
 void UIApplicationLoader::OnApplicationErrorOnUIThread(
     ApplicationManager* manager,
     const GURL& url) {
-  if (!ui_loader_)
-    ui_loader_ = new UILoader(loader_.get());
-  ui_loader_->OnApplicationError(manager, url);
+  loader_->OnApplicationError(manager, url);
 }
 
 void UIApplicationLoader::ShutdownOnUIThread() {
-  delete ui_loader_;
   // Destroy |loader_| on the thread it's actually used on.
   loader_.reset();
 }
diff --git a/mojo/shell/ui_application_loader_android.h b/mojo/shell/ui_application_loader_android.h
index 9b88410..91d346f 100644
--- a/mojo/shell/ui_application_loader_android.h
+++ b/mojo/shell/ui_application_loader_android.h
@@ -29,7 +29,8 @@
   // ApplicationLoader overrides:
   void Load(ApplicationManager* manager,
             const GURL& url,
-            scoped_refptr<LoadCallbacks> callbacks) override;
+            ScopedMessagePipeHandle shell_handle,
+            LoadCallback callback) override;
   void OnApplicationError(ApplicationManager* manager,
                           const GURL& url) override;
 
@@ -42,7 +43,7 @@
   // isn't thread safe).
   void LoadOnUIThread(ApplicationManager* manager,
                       const GURL& url,
-                      ScopedMessagePipeHandle* shell_handle);
+                      ScopedMessagePipeHandle shell_handle);
   void OnApplicationErrorOnUIThread(ApplicationManager* manager,
                                     const GURL& url);
   void ShutdownOnUIThread();
@@ -50,9 +51,6 @@
   scoped_ptr<ApplicationLoader> loader_;
   shell::Context* context_;
 
-  // Lives on the UI thread. Trivial interface that calls through to |loader_|.
-  UILoader* ui_loader_;
-
   DISALLOW_COPY_AND_ASSIGN(UIApplicationLoader);
 };
 
diff --git a/mojo/shell/view_manager_loader.cc b/mojo/shell/view_manager_loader.cc
index 9128084..3df15d1 100644
--- a/mojo/shell/view_manager_loader.cc
+++ b/mojo/shell/view_manager_loader.cc
@@ -22,7 +22,7 @@
 
 void ViewManagerLoader::Load(ApplicationManager* manager,
                              const GURL& url,
-                             scoped_refptr<LoadCallbacks> callbacks) {
+                             LoadCallback callback) {
   ScopedMessagePipeHandle shell_handle = callbacks->RegisterApplication();
   if (!shell_handle.is_valid())
     return;
diff --git a/mojo/shell/view_manager_loader.h b/mojo/shell/view_manager_loader.h
index 83c5f31..77e066d 100644
--- a/mojo/shell/view_manager_loader.h
+++ b/mojo/shell/view_manager_loader.h
@@ -32,7 +32,7 @@
   // ApplicationLoader overrides:
   virtual void Load(ApplicationManager* manager,
                     const GURL& url,
-                    scoped_refptr<LoadCallbacks> callbacks) override;
+                    LoadCallback callback) override;
   virtual void OnApplicationError(ApplicationManager* manager,
                                   const GURL& url) override;
 
diff --git a/sky/viewer/content_handler_impl.cc b/sky/viewer/content_handler_impl.cc
index 6a2d103..58df7be 100644
--- a/sky/viewer/content_handler_impl.cc
+++ b/sky/viewer/content_handler_impl.cc
@@ -4,10 +4,81 @@
 
 #include "sky/viewer/content_handler_impl.h"
 
+#include "base/bind.h"
+#include "mojo/public/cpp/application/connect.h"
+#include "mojo/services/public/interfaces/network/network_service.mojom.h"
 #include "sky/viewer/document_view.h"
 
 namespace sky {
 
+class SkyApplication : public mojo::Application {
+ public:
+  SkyApplication(scoped_refptr<base::MessageLoopProxy> compositor_thread,
+                 mojo::ShellPtr shell,
+                 mojo::URLResponsePtr response)
+      : compositor_thread_(compositor_thread),
+        url_(response->url),
+        shell_(shell.Pass()),
+        initial_response_(response.Pass()),
+        view_count_(0) {
+    shell_.set_client(this);
+    mojo::ServiceProviderPtr service_provider;
+    shell_->ConnectToApplication("mojo:network_service",
+                                 mojo::GetProxy(&service_provider));
+    mojo::ConnectToService(service_provider.get(), &network_service_);
+  }
+
+  void Initialize(mojo::Array<mojo::String> args) override {}
+
+  void AcceptConnection(const mojo::String& requestor_url,
+                        mojo::ServiceProviderPtr provider) override {
+    ++view_count_;
+    if (initial_response_) {
+      OnResponseReceived(mojo::URLLoaderPtr(), provider.Pass(),
+                         initial_response_.Pass());
+    } else {
+      mojo::URLLoaderPtr loader;
+      network_service_->CreateURLLoader(mojo::GetProxy(&loader));
+      mojo::URLRequestPtr request(mojo::URLRequest::New());
+      request->url = url_;
+      request->auto_follow_redirects = true;
+
+      // |loader| will be pass to the OnResponseReceived method through a
+      // callback. Because order of evaluation is undefined, a reference to the
+      // raw pointer is needed.
+      mojo::URLLoader* raw_loader = loader.get();
+      raw_loader->Start(
+          request.Pass(),
+          base::Bind(&SkyApplication::OnResponseReceived,
+                     base::Unretained(this), base::Passed(&loader),
+                     base::Passed(&provider)));
+    }
+  }
+
+ private:
+  void OnViewDestroyed() {
+    --view_count_;
+    if (view_count_ == 0) {
+      delete this;
+    }
+  }
+
+  void OnResponseReceived(mojo::URLLoaderPtr loader,
+                          mojo::ServiceProviderPtr provider,
+                          mojo::URLResponsePtr response) {
+    new DocumentView(
+        base::Bind(&SkyApplication::OnViewDestroyed, base::Unretained(this)),
+        provider.Pass(), response.Pass(), shell_.get(), compositor_thread_);
+  }
+
+  scoped_refptr<base::MessageLoopProxy> compositor_thread_;
+  mojo::String url_;
+  mojo::ShellPtr shell_;
+  mojo::NetworkServicePtr network_service_;
+  mojo::URLResponsePtr initial_response_;
+  uint32_t view_count_;
+};
+
 ContentHandlerImpl::ContentHandlerImpl(
     scoped_refptr<base::MessageLoopProxy> compositor_thread)
     : compositor_thread_(compositor_thread) {
@@ -18,7 +89,7 @@
 
 void ContentHandlerImpl::StartApplication(mojo::ShellPtr shell,
                                           mojo::URLResponsePtr response) {
-  new DocumentView(response.Pass(), shell.Pass(), compositor_thread_);
+  new SkyApplication(compositor_thread_, shell.Pass(), response.Pass());
 }
 
 }  // namespace sky
diff --git a/sky/viewer/document_view.cc b/sky/viewer/document_view.cc
index a8be823..9b74033 100644
--- a/sky/viewer/document_view.cc
+++ b/sky/viewer/document_view.cc
@@ -72,19 +72,23 @@
 static int s_next_debugger_id = 1;
 
 DocumentView::DocumentView(
+    const base::Closure& destruction_callback,
+    mojo::ServiceProviderPtr provider,
     mojo::URLResponsePtr response,
-    mojo::ShellPtr shell,
+    mojo::Shell* shell,
     scoped_refptr<base::MessageLoopProxy> compositor_thread)
-    : response_(response.Pass()),
-      shell_(shell.Pass()),
+    : destruction_callback_(destruction_callback),
+      response_(response.Pass()),
+      shell_(shell),
       web_view_(NULL),
       root_(NULL),
-      view_manager_client_factory_(shell_.get(), this),
+      view_manager_client_factory_(shell_, this),
       inspector_service_factory_(this),
       compositor_thread_(compositor_thread),
       debugger_id_(s_next_debugger_id++),
       weak_factory_(this) {
-  shell_.set_client(this);
+  exported_services_.AddService(&view_manager_client_factory_);
+  mojo::WeakBindToPipe(&exported_services_, provider.PassMessagePipe());
 }
 
 DocumentView::~DocumentView() {
@@ -92,21 +96,13 @@
     web_view_->close();
   if (root_)
     root_->RemoveObserver(this);
+  destruction_callback_.Run();
 }
 
 base::WeakPtr<DocumentView> DocumentView::GetWeakPtr() {
   return weak_factory_.GetWeakPtr();
 }
 
-void DocumentView::AcceptConnection(const mojo::String& requestor_url,
-                                    mojo::ServiceProviderPtr provider) {
-  exported_services_.AddService(&view_manager_client_factory_);
-  mojo::WeakBindToPipe(&exported_services_, provider.PassMessagePipe());
-}
-
-void DocumentView::Initialize(mojo::Array<mojo::String> args) {
-}
-
 void DocumentView::OnEmbed(
     mojo::ViewManager* view_manager,
     mojo::View* root,
@@ -267,7 +263,7 @@
 }
 
 mojo::Shell* DocumentView::Shell() {
-  return shell_.get();
+  return shell_;
 }
 
 void DocumentView::OnViewBoundsChanged(mojo::View* view,
@@ -324,7 +320,7 @@
 
 void DocumentView::StartDebuggerInspectorBackend() {
   if (!inspector_backend_) {
-    inspector_host_.reset(new InspectorHostImpl(web_view_, shell_.get()));
+    inspector_host_.reset(new InspectorHostImpl(web_view_, shell_));
     inspector_backend_.reset(
         new inspector::InspectorBackendMojo(inspector_host_.get()));
   }
diff --git a/sky/viewer/document_view.h b/sky/viewer/document_view.h
index 4bb7de9..ff72208 100644
--- a/sky/viewer/document_view.h
+++ b/sky/viewer/document_view.h
@@ -5,6 +5,7 @@
 #ifndef SKY_VIEWER_DOCUMENT_VIEW_H_
 #define SKY_VIEWER_DOCUMENT_VIEW_H_
 
+#include "base/callback.h"
 #include "base/memory/weak_ptr.h"
 #include "mojo/public/cpp/application/lazy_interface_ptr.h"
 #include "mojo/public/cpp/application/service_provider_impl.h"
@@ -46,8 +47,7 @@
 class LayerHost;
 class WebLayerTreeViewImpl;
 
-class DocumentView : public mojo::InterfaceImpl<mojo::Application>,
-                     public blink::ServiceProvider,
+class DocumentView : public blink::ServiceProvider,
                      public blink::WebViewClient,
                      public blink::WebFrameClient,
 #if ENABLE_SKY_COMPOSITOR
@@ -57,8 +57,10 @@
                      public mojo::ViewManagerDelegate,
                      public mojo::ViewObserver {
  public:
-  DocumentView(mojo::URLResponsePtr response,
-               mojo::ShellPtr shell,
+  DocumentView(const base::Closure& destruction_callback,
+               mojo::ServiceProviderPtr provider,
+               mojo::URLResponsePtr response,
+               mojo::Shell* shell,
                scoped_refptr<base::MessageLoopProxy> compositor_thread);
   virtual ~DocumentView();
 
@@ -69,7 +71,7 @@
     return imported_services_.get();
   }
 
-  mojo::Shell* shell() const { return shell_.get(); }
+  mojo::Shell* shell() const { return shell_; }
 
 #if ENABLE_SKY_COMPOSITOR
   // sky::LayerHostClient
@@ -83,11 +85,6 @@
   void StartDebuggerInspectorBackend();
 
  private:
-  // Application methods:
-  void AcceptConnection(const mojo::String& requestor_url,
-                        mojo::ServiceProviderPtr provider) override;
-  void Initialize(mojo::Array<mojo::String> args) override;
-
   // WebWidgetClient methods:
   blink::WebLayerTreeView* initializeLayerTreeView() override;
   void scheduleAnimation() override;
@@ -134,10 +131,11 @@
 
   void Load(mojo::URLResponsePtr response);
 
+  base::Closure destruction_callback_;
   mojo::URLResponsePtr response_;
   mojo::ServiceProviderImpl exported_services_;
   scoped_ptr<mojo::ServiceProvider> imported_services_;
-  mojo::ShellPtr shell_;
+  mojo::Shell* shell_;
   mojo::LazyInterfacePtr<mojo::NavigatorHost> navigator_host_;
   blink::WebView* web_view_;
   mojo::View* root_;