Index: content/public/common/static_mojo_application_loader.cc |
diff --git a/content/public/common/static_mojo_application_loader.cc b/content/public/common/static_mojo_application_loader.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..b875c961e622f5ad0e328a04f75048595ca23313 |
--- /dev/null |
+++ b/content/public/common/static_mojo_application_loader.cc |
@@ -0,0 +1,116 @@ |
+// Copyright 2015 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 "content/public/common/static_mojo_application_loader.h" |
+ |
+#include "base/bind.h" |
+#include "base/callback.h" |
+#include "base/macros.h" |
+#include "base/message_loop/message_loop.h" |
+#include "base/task_runner.h" |
+#include "base/thread_task_runner_handle.h" |
+#include "base/threading/thread.h" |
+#include "mojo/common/message_pump_mojo.h" |
+#include "third_party/mojo/src/mojo/public/cpp/application/application_delegate.h" |
+#include "third_party/mojo/src/mojo/public/cpp/application/application_impl.h" |
+#include "third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h" |
+#include "third_party/mojo/src/mojo/public/interfaces/application/application.mojom.h" |
+ |
+namespace mojo { |
+ |
+// This is required since we depend on the |
+// third_party/mojo/src/mojo/public/cpp/application target and instantiate |
+// a mojo::ApplicationImpl. This exists only to support loading of static |
+// applications. |
+void ApplicationImpl::Terminate() { |
+ base::MessageLoop::current()->Quit(); |
+} |
+ |
+} // namespace mojo |
+ |
+namespace content { |
+ |
+namespace { |
+ |
+// Container for a single instance of the loaded application. This lives and |
+// dies on the app instance's thread and kills itself when the thread's message |
+// loop is destroyed. |
+class Runner : public base::MessageLoop::DestructionObserver { |
+ public: |
+ Runner(mojo::InterfaceRequest<mojo::Application> request, |
+ scoped_refptr<base::TaskRunner> exit_task_runner, |
+ const base::Closure& exit_callback, |
+ scoped_ptr<mojo::ApplicationDelegate> delegate) |
+ : exit_task_runner_(exit_task_runner), |
+ exit_callback_(exit_callback), |
+ delegate_(delegate.Pass()) { |
+ DCHECK(base::MessageLoop::current()); |
+ base::MessageLoop::current()->AddDestructionObserver(this); |
+ application_.reset( |
+ new mojo::ApplicationImpl(delegate_.get(), request.Pass())); |
+ } |
+ |
+ private: |
+ ~Runner() override { exit_task_runner_->PostTask(FROM_HERE, exit_callback_); } |
+ |
+ // base::MessageLoop::DestructionObserver: |
+ void WillDestroyCurrentMessageLoop() override { |
+ DCHECK(base::MessageLoop::current()); |
+ base::MessageLoop::current()->RemoveDestructionObserver(this); |
+ delete this; |
+ } |
+ |
+ scoped_refptr<base::TaskRunner> exit_task_runner_; |
+ base::Closure exit_callback_; |
+ scoped_ptr<mojo::ApplicationDelegate> delegate_; |
+ scoped_ptr<mojo::ApplicationImpl> application_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(Runner); |
+}; |
+ |
+void RunAppOnOwnThread( |
+ mojo::InterfaceRequest<mojo::Application> request, |
+ scoped_refptr<base::TaskRunner> exit_task_runner, |
+ const base::Closure& exit_callback, |
+ const StaticMojoApplicationLoader::ApplicationFactory& factory) { |
+ // This object destroys itself when the current MessageLoop is destroyed. |
+ new Runner(request.Pass(), exit_task_runner, exit_callback, factory.Run()); |
+} |
+ |
+} // namespace |
+ |
+StaticMojoApplicationLoader::StaticMojoApplicationLoader( |
+ const std::string& name, |
+ const ApplicationFactory& factory) |
+ : name_(name), factory_(factory), weak_factory_(this) { |
+} |
+ |
+StaticMojoApplicationLoader::~StaticMojoApplicationLoader() { |
+} |
+ |
+void StaticMojoApplicationLoader::Load( |
+ const GURL& url, |
+ mojo::InterfaceRequest<mojo::Application> request) { |
+ threads_.insert(threads_.begin(), make_scoped_ptr(new base::Thread(name_))); |
+ base::Thread::Options options; |
+ options.message_pump_factory = |
+ base::Bind(&mojo::common::MessagePumpMojo::Create); |
+ threads_.front()->StartWithOptions(options); |
+ |
+ // If the application's thread quits on its own before this loader dies, we |
+ // evict the Thread object from |threads_| and destroy it. |
+ auto exit_callback = base::Bind(&StaticMojoApplicationLoader::ClearThread, |
+ weak_factory_.GetWeakPtr(), threads_.begin()); |
+ threads_.front()->task_runner()->PostTask( |
+ FROM_HERE, |
+ base::Bind(&RunAppOnOwnThread, base::Passed(&request), |
+ base::ThreadTaskRunnerHandle::Get(), exit_callback, factory_)); |
+} |
+ |
+void StaticMojoApplicationLoader::ClearThread( |
+ typename ThreadList::iterator iter) { |
+ threads_.erase(iter); |
+} |
+ |
+} // namespace content |