OLD | NEW |
(Empty) | |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "content/public/common/static_mojo_application_loader.h" |
| 6 |
| 7 #include "base/bind.h" |
| 8 #include "base/lazy_instance.h" |
| 9 #include "base/macros.h" |
| 10 #include "base/memory/ref_counted.h" |
| 11 #include "base/message_loop/message_loop.h" |
| 12 #include "base/task_runner.h" |
| 13 #include "base/thread_task_runner_handle.h" |
| 14 #include "base/threading/thread.h" |
| 15 #include "base/threading/thread_local.h" |
| 16 #include "mojo/application/public/cpp/application_delegate.h" |
| 17 #include "mojo/application/public/cpp/application_impl.h" |
| 18 #include "mojo/application/public/interfaces/application.mojom.h" |
| 19 #include "mojo/common/message_pump_mojo.h" |
| 20 #include "third_party/mojo/src/mojo/public/cpp/bindings/interface_request.h" |
| 21 |
| 22 namespace content { |
| 23 |
| 24 namespace { |
| 25 |
| 26 class Runner; |
| 27 |
| 28 // Tracks each application's Runner on its main thread. |
| 29 base::LazyInstance<base::ThreadLocalPointer<Runner>> g_runner; |
| 30 |
| 31 void TerminateCurrentApp(); |
| 32 |
| 33 // Container for a single instance of the loaded application. This lives and |
| 34 // dies on the app instance's own thread and kills itself either when the thread |
| 35 // message loop is destroyed or the app terminates itself. |
| 36 class Runner : public base::MessageLoop::DestructionObserver { |
| 37 public: |
| 38 Runner(mojo::InterfaceRequest<mojo::Application> request, |
| 39 scoped_refptr<base::TaskRunner> exit_task_runner, |
| 40 const base::Closure& exit_callback, |
| 41 scoped_ptr<mojo::ApplicationDelegate> delegate) |
| 42 : exit_task_runner_(exit_task_runner), |
| 43 exit_callback_(exit_callback), |
| 44 delegate_(delegate.Pass()) { |
| 45 DCHECK(base::MessageLoop::current()); |
| 46 DCHECK(!g_runner.Get().Get()); |
| 47 g_runner.Get().Set(this); |
| 48 base::MessageLoop::current()->AddDestructionObserver(this); |
| 49 application_.reset( |
| 50 new mojo::ApplicationImpl(delegate_.get(), request.Pass(), |
| 51 base::Bind(&TerminateCurrentApp))); |
| 52 } |
| 53 |
| 54 private: |
| 55 friend void TerminateCurrentApp(); |
| 56 |
| 57 ~Runner() override { |
| 58 g_runner.Get().Set(nullptr); |
| 59 base::MessageLoop::current()->RemoveDestructionObserver(this); |
| 60 exit_task_runner_->PostTask(FROM_HERE, exit_callback_); |
| 61 } |
| 62 |
| 63 // base::MessageLoop::DestructionObserver: |
| 64 void WillDestroyCurrentMessageLoop() override { |
| 65 DCHECK(base::MessageLoop::current()); |
| 66 delete this; |
| 67 } |
| 68 |
| 69 scoped_refptr<base::TaskRunner> exit_task_runner_; |
| 70 base::Closure exit_callback_; |
| 71 scoped_ptr<mojo::ApplicationDelegate> delegate_; |
| 72 scoped_ptr<mojo::ApplicationImpl> application_; |
| 73 |
| 74 DISALLOW_COPY_AND_ASSIGN(Runner); |
| 75 }; |
| 76 |
| 77 void RunAppOnOwnThread( |
| 78 mojo::InterfaceRequest<mojo::Application> request, |
| 79 scoped_refptr<base::TaskRunner> exit_task_runner, |
| 80 const base::Closure& exit_callback, |
| 81 const StaticMojoApplicationLoader::ApplicationFactory& factory) { |
| 82 // This object either destroys itself when the current MessageLoop is |
| 83 // destroyed, or it is destroyed by TerminateCurrentApp (see below). |
| 84 new Runner(request.Pass(), exit_task_runner, exit_callback, factory.Run()); |
| 85 } |
| 86 |
| 87 // This is run on an app's own thread when its ApplicationImpl::Terminate() |
| 88 // method is called. |
| 89 void TerminateCurrentApp() { |
| 90 Runner* runner = g_runner.Get().Get(); |
| 91 DCHECK(runner); |
| 92 delete runner; |
| 93 } |
| 94 |
| 95 } // namespace |
| 96 |
| 97 StaticMojoApplicationLoader::StaticMojoApplicationLoader( |
| 98 const ApplicationFactory& factory) |
| 99 : StaticMojoApplicationLoader(factory, base::Closure()) { |
| 100 } |
| 101 |
| 102 StaticMojoApplicationLoader::StaticMojoApplicationLoader( |
| 103 const ApplicationFactory& factory, |
| 104 const base::Closure& quit_callback) |
| 105 : factory_(factory), |
| 106 quit_callback_(quit_callback), |
| 107 weak_factory_(this) { |
| 108 } |
| 109 |
| 110 StaticMojoApplicationLoader::~StaticMojoApplicationLoader() { |
| 111 } |
| 112 |
| 113 void StaticMojoApplicationLoader::Load( |
| 114 const GURL& url, |
| 115 mojo::InterfaceRequest<mojo::Application> request) { |
| 116 threads_.insert(threads_.begin(), make_scoped_ptr(new base::Thread( |
| 117 "Mojo Application: " + url.spec()))); |
| 118 base::Thread::Options options; |
| 119 options.message_pump_factory = |
| 120 base::Bind(&mojo::common::MessagePumpMojo::Create); |
| 121 threads_.front()->StartWithOptions(options); |
| 122 |
| 123 // If the application's thread quits on its own before this loader dies, we |
| 124 // evict the Thread object from |threads_| and destroy it. |
| 125 auto exit_callback = base::Bind( |
| 126 &StaticMojoApplicationLoader::CleanUpAppThread, |
| 127 weak_factory_.GetWeakPtr(), threads_.begin()); |
| 128 threads_.front()->task_runner()->PostTask( |
| 129 FROM_HERE, |
| 130 base::Bind(&RunAppOnOwnThread, base::Passed(&request), |
| 131 base::ThreadTaskRunnerHandle::Get(), exit_callback, factory_)); |
| 132 } |
| 133 |
| 134 void StaticMojoApplicationLoader::CleanUpAppThread( |
| 135 typename ThreadList::iterator iter) { |
| 136 threads_.erase(iter); |
| 137 if (!quit_callback_.is_null()) |
| 138 quit_callback_.Run(); |
| 139 } |
| 140 |
| 141 } // namespace content |
OLD | NEW |