Moves BackgroundShellApplicationLoader to shell/android

As this is the only place that uses it. Also renamed to
BackgroundApplicationLoader.

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

Review URL: https://codereview.chromium.org/788243007
diff --git a/shell/android/background_application_loader.cc b/shell/android/background_application_loader.cc
new file mode 100644
index 0000000..8e6d0f4
--- /dev/null
+++ b/shell/android/background_application_loader.cc
@@ -0,0 +1,90 @@
+// 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 "shell/android/background_application_loader.h"
+
+#include "base/bind.h"
+#include "base/run_loop.h"
+#include "mojo/application_manager/application_manager.h"
+
+namespace mojo {
+
+BackgroundApplicationLoader::BackgroundApplicationLoader(
+    scoped_ptr<ApplicationLoader> real_loader,
+    const std::string& thread_name,
+    base::MessageLoop::Type message_loop_type)
+    : loader_(real_loader.Pass()),
+      message_loop_type_(message_loop_type),
+      thread_name_(thread_name),
+      message_loop_created_(true, false) {
+}
+
+BackgroundApplicationLoader::~BackgroundApplicationLoader() {
+  if (thread_)
+    thread_->Join();
+}
+
+void BackgroundApplicationLoader::Load(ApplicationManager* manager,
+                                       const GURL& url,
+                                       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
+    // loaders are creating multiple ApplicationImpls (NetworkApplicationLoader)
+    // sharing a delegate (etc). So we have to keep it single threaded, wait
+    // for the thread to initialize, and post to the TaskRunner for subsequent
+    // Load calls for now.
+    thread_.reset(new base::DelegateSimpleThread(this, thread_name_));
+    thread_->Start();
+    message_loop_created_.Wait();
+    DCHECK(task_runner_.get());
+  }
+
+  task_runner_->PostTask(
+      FROM_HERE,
+      base::Bind(&BackgroundApplicationLoader::LoadOnBackgroundThread,
+                 base::Unretained(this), manager, url,
+                 base::Passed(&shell_handle)));
+}
+
+void BackgroundApplicationLoader::OnApplicationError(
+    ApplicationManager* manager,
+    const GURL& url) {
+  task_runner_->PostTask(
+      FROM_HERE,
+      base::Bind(
+          &BackgroundApplicationLoader::OnApplicationErrorOnBackgroundThread,
+          base::Unretained(this), manager, url));
+}
+
+void BackgroundApplicationLoader::Run() {
+  base::MessageLoop message_loop(message_loop_type_);
+  base::RunLoop loop;
+  task_runner_ = message_loop.task_runner();
+  quit_closure_ = loop.QuitClosure();
+  message_loop_created_.Signal();
+  loop.Run();
+
+  // Destroy |loader_| on the thread it's actually used on.
+  loader_.reset();
+}
+
+void BackgroundApplicationLoader::LoadOnBackgroundThread(
+    ApplicationManager* manager,
+    const GURL& url,
+    ScopedMessagePipeHandle shell_handle) {
+  DCHECK(task_runner_->RunsTasksOnCurrentThread());
+  loader_->Load(manager, url, shell_handle.Pass(), SimpleLoadCallback());
+}
+
+void BackgroundApplicationLoader::OnApplicationErrorOnBackgroundThread(
+    ApplicationManager* manager,
+    const GURL& url) {
+  DCHECK(task_runner_->RunsTasksOnCurrentThread());
+  loader_->OnApplicationError(manager, url);
+}
+
+}  // namespace mojo
diff --git a/shell/android/background_application_loader.h b/shell/android/background_application_loader.h
new file mode 100644
index 0000000..5321d97
--- /dev/null
+++ b/shell/android/background_application_loader.h
@@ -0,0 +1,70 @@
+// 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 SHELL_ANDROID_BACKGROUND_APPLICATION_LOADER_H_
+#define SHELL_ANDROID_BACKGROUND_APPLICATION_LOADER_H_
+
+#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop/message_loop.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/threading/simple_thread.h"
+#include "mojo/application_manager/application_loader.h"
+
+namespace mojo {
+
+class MOJO_APPLICATION_MANAGER_EXPORT BackgroundApplicationLoader
+    : public ApplicationLoader,
+      public base::DelegateSimpleThread::Delegate {
+ public:
+  BackgroundApplicationLoader(scoped_ptr<ApplicationLoader> real_loader,
+                              const std::string& thread_name,
+                              base::MessageLoop::Type message_loop_type);
+  ~BackgroundApplicationLoader() override;
+
+  // ApplicationLoader overrides:
+  void Load(ApplicationManager* manager,
+            const GURL& url,
+            ScopedMessagePipeHandle shell_handle,
+            LoadCallback callback) override;
+  void OnApplicationError(ApplicationManager* manager,
+                          const GURL& url) override;
+
+ private:
+  // |base::DelegateSimpleThread::Delegate| method:
+  void Run() override;
+
+  // These functions are exected on the background thread. They call through
+  // to |background_loader_| to do the actual loading.
+  // TODO: having this code take a |manager| is fragile (as ApplicationManager
+  // isn't thread safe).
+  void LoadOnBackgroundThread(ApplicationManager* manager,
+                              const GURL& url,
+                              ScopedMessagePipeHandle shell_handle);
+  void OnApplicationErrorOnBackgroundThread(ApplicationManager* manager,
+                                            const GURL& url);
+  bool quit_on_shutdown_;
+  scoped_ptr<ApplicationLoader> loader_;
+
+  const base::MessageLoop::Type message_loop_type_;
+  const std::string thread_name_;
+
+  // Created on |thread_| during construction of |this|. Protected against
+  // uninitialized use by |message_loop_created_|, and protected against
+  // use-after-free by holding a reference to the thread-safe object. Note
+  // that holding a reference won't hold |thread_| from exiting.
+  scoped_refptr<base::TaskRunner> task_runner_;
+  base::WaitableEvent message_loop_created_;
+
+  // Lives on |thread_|.
+  base::Closure quit_closure_;
+
+  scoped_ptr<base::DelegateSimpleThread> thread_;
+
+  DISALLOW_COPY_AND_ASSIGN(BackgroundApplicationLoader);
+};
+
+}  // namespace mojo
+
+#endif  // SHELL_ANDROID_BACKGROUND_APPLICATION_LOADER_H_
diff --git a/shell/android/background_application_loader_unittest.cc b/shell/android/background_application_loader_unittest.cc
new file mode 100644
index 0000000..09bc2c8
--- /dev/null
+++ b/shell/android/background_application_loader_unittest.cc
@@ -0,0 +1,56 @@
+// 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 "shell/android/background_application_loader.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace mojo {
+
+namespace {
+
+class DummyLoader : public ApplicationLoader {
+ public:
+  DummyLoader() : simulate_app_quit_(true) {}
+  ~DummyLoader() override {}
+
+  // ApplicationLoader overrides:
+  void Load(ApplicationManager* manager,
+            const GURL& url,
+            ScopedMessagePipeHandle shell_handle,
+            LoadCallback callback) override {
+    if (simulate_app_quit_)
+      base::MessageLoop::current()->Quit();
+  }
+
+  void OnApplicationError(ApplicationManager* manager,
+                          const GURL& url) override {}
+
+  void DontSimulateAppQuit() { simulate_app_quit_ = false; }
+
+ private:
+  bool simulate_app_quit_;
+};
+
+}  // namespace
+
+// Tests that the loader can start and stop gracefully.
+TEST(BackgroundApplicationLoaderTest, StartStop) {
+  scoped_ptr<ApplicationLoader> real_loader(new DummyLoader());
+  BackgroundApplicationLoader loader(real_loader.Pass(), "test",
+                                     base::MessageLoop::TYPE_DEFAULT);
+}
+
+// Tests that the loader can load a service that is well behaved (quits
+// itself).
+TEST(BackgroundApplicationLoaderTest, Load) {
+  scoped_ptr<ApplicationLoader> real_loader(new DummyLoader());
+  BackgroundApplicationLoader loader(real_loader.Pass(), "test",
+                                     base::MessageLoop::TYPE_DEFAULT);
+  MessagePipe dummy;
+  loader.Load(NULL, GURL(), dummy.handle0.Pass(),
+              ApplicationLoader::SimpleLoadCallback());
+}
+
+}  // namespace mojo
diff --git a/shell/android/mojo_main.cc b/shell/android/mojo_main.cc
index d19e3db..086d29f 100644
--- a/shell/android/mojo_main.cc
+++ b/shell/android/mojo_main.cc
@@ -18,8 +18,8 @@
 #include "base/message_loop/message_loop.h"
 #include "jni/MojoMain_jni.h"
 #include "mojo/application_manager/application_loader.h"
-#include "mojo/application_manager/background_shell_application_loader.h"
 #include "shell/android/android_handler_loader.h"
+#include "shell/android/background_application_loader.h"
 #include "shell/android/native_viewport_application_loader.h"
 #include "shell/android/ui_application_loader_android.h"
 #include "shell/context.h"
@@ -52,7 +52,7 @@
   // MojoShell application as the JNI bridge to bootstrap execution of other
   // Android Mojo apps that need JNI.
   context->application_manager()->SetLoaderForURL(
-      make_scoped_ptr(new BackgroundShellApplicationLoader(
+      make_scoped_ptr(new BackgroundApplicationLoader(
           make_scoped_ptr(new AndroidHandlerLoader()), "android_handler",
           base::MessageLoop::TYPE_DEFAULT)),
       GURL("mojo:android_handler"));