| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/common/mojo/embedded_application_runner.h" | 5 #include "content/common/mojo/embedded_application_runner.h" |
| 6 | 6 |
| 7 #include <vector> | 7 #include <vector> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/macros.h" | 10 #include "base/macros.h" |
| 11 #include "base/memory/ref_counted.h" | 11 #include "base/memory/ref_counted.h" |
| 12 #include "base/single_thread_task_runner.h" | 12 #include "base/single_thread_task_runner.h" |
| 13 #include "base/threading/thread.h" |
| 13 #include "base/threading/thread_checker.h" | 14 #include "base/threading/thread_checker.h" |
| 14 #include "base/threading/thread_task_runner_handle.h" | 15 #include "base/threading/thread_task_runner_handle.h" |
| 15 #include "services/shell/public/cpp/shell_connection.h" | 16 #include "services/shell/public/cpp/shell_connection.h" |
| 16 | 17 |
| 17 namespace content { | 18 namespace content { |
| 18 | 19 |
| 19 class EmbeddedApplicationRunner::Instance | 20 class EmbeddedApplicationRunner::Instance |
| 20 : public base::RefCountedThreadSafe<Instance> { | 21 : public base::RefCountedThreadSafe<Instance> { |
| 21 public: | 22 public: |
| 22 explicit Instance( | 23 Instance(const base::StringPiece& name, |
| 23 const EmbeddedApplicationRunner::FactoryCallback& callback, | 24 const MojoApplicationInfo& info, |
| 24 const base::Closure& quit_closure) | 25 const base::Closure& quit_closure) |
| 25 : factory_callback_(callback), | 26 : name_(name.as_string()), |
| 27 factory_callback_(info.application_factory), |
| 28 use_own_thread_(!info.application_task_runner && info.use_own_thread), |
| 26 quit_closure_(quit_closure), | 29 quit_closure_(quit_closure), |
| 27 quit_task_runner_(base::ThreadTaskRunnerHandle::Get()) { | 30 quit_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
| 28 // This object may be used exclusively from a single thread which may be | 31 application_task_runner_(info.application_task_runner) { |
| 29 // different from the one that created it. | 32 application_thread_checker_.DetachFromThread(); |
| 30 thread_checker_.DetachFromThread(); | 33 |
| 34 if (!use_own_thread_ && !application_task_runner_) |
| 35 application_task_runner_ = base::ThreadTaskRunnerHandle::Get(); |
| 31 } | 36 } |
| 32 | 37 |
| 33 void BindShellClientRequest(shell::mojom::ShellClientRequest request) { | 38 void BindShellClientRequest(shell::mojom::ShellClientRequest request) { |
| 34 DCHECK(thread_checker_.CalledOnValidThread()); | 39 DCHECK(runner_thread_checker_.CalledOnValidThread()); |
| 40 |
| 41 if (use_own_thread_ && !thread_) { |
| 42 // Start a new thread if necessary. |
| 43 thread_.reset(new base::Thread(name_)); |
| 44 thread_->Start(); |
| 45 application_task_runner_ = thread_->task_runner(); |
| 46 } |
| 47 |
| 48 DCHECK(application_task_runner_); |
| 49 application_task_runner_->PostTask( |
| 50 FROM_HERE, |
| 51 base::Bind(&Instance::BindShellClientRequestOnApplicationThread, this, |
| 52 base::Passed(&request))); |
| 53 } |
| 54 |
| 55 void ShutDown() { |
| 56 DCHECK(runner_thread_checker_.CalledOnValidThread()); |
| 57 if (thread_) { |
| 58 application_task_runner_ = nullptr; |
| 59 thread_.reset(); |
| 60 } |
| 61 } |
| 62 |
| 63 private: |
| 64 void BindShellClientRequestOnApplicationThread( |
| 65 shell::mojom::ShellClientRequest request) { |
| 66 DCHECK(application_thread_checker_.CalledOnValidThread()); |
| 35 | 67 |
| 36 if (!shell_client_) { | 68 if (!shell_client_) { |
| 37 shell_client_ = factory_callback_.Run( | 69 shell_client_ = factory_callback_.Run( |
| 38 base::Bind(&Instance::Quit, base::Unretained(this))); | 70 base::Bind(&Instance::Quit, base::Unretained(this))); |
| 39 } | 71 } |
| 40 | 72 |
| 41 shell::ShellConnection* new_connection = | 73 shell::ShellConnection* new_connection = |
| 42 new shell::ShellConnection(shell_client_.get(), std::move(request)); | 74 new shell::ShellConnection(shell_client_.get(), std::move(request)); |
| 43 shell_connections_.push_back(base::WrapUnique(new_connection)); | 75 shell_connections_.push_back(base::WrapUnique(new_connection)); |
| 44 new_connection->SetConnectionLostClosure( | 76 new_connection->SetConnectionLostClosure( |
| 45 base::Bind(&Instance::OnShellConnectionLost, base::Unretained(this), | 77 base::Bind(&Instance::OnShellConnectionLost, base::Unretained(this), |
| 46 new_connection)); | 78 new_connection)); |
| 47 } | 79 } |
| 48 | 80 |
| 49 private: | 81 private: |
| 50 friend class base::RefCountedThreadSafe<Instance>; | 82 friend class base::RefCountedThreadSafe<Instance>; |
| 51 | 83 |
| 52 ~Instance() { DCHECK(thread_checker_.CalledOnValidThread()); } | 84 ~Instance() { |
| 85 // If this instance had its own thread, it MUST be explicitly destroyed by |
| 86 // ShutDown() on the runner's thread by the time this destructor is run. |
| 87 DCHECK(!thread_); |
| 88 } |
| 53 | 89 |
| 54 void OnShellConnectionLost(shell::ShellConnection* connection) { | 90 void OnShellConnectionLost(shell::ShellConnection* connection) { |
| 55 DCHECK(thread_checker_.CalledOnValidThread()); | 91 DCHECK(application_thread_checker_.CalledOnValidThread()); |
| 56 | 92 |
| 57 for (auto it = shell_connections_.begin(); it != shell_connections_.end(); | 93 for (auto it = shell_connections_.begin(); it != shell_connections_.end(); |
| 58 ++it) { | 94 ++it) { |
| 59 if (it->get() == connection) { | 95 if (it->get() == connection) { |
| 60 shell_connections_.erase(it); | 96 shell_connections_.erase(it); |
| 61 break; | 97 break; |
| 62 } | 98 } |
| 63 } | 99 } |
| 64 } | 100 } |
| 65 | 101 |
| 66 void Quit() { | 102 void Quit() { |
| 103 DCHECK(application_thread_checker_.CalledOnValidThread()); |
| 104 |
| 67 shell_connections_.clear(); | 105 shell_connections_.clear(); |
| 68 shell_client_.reset(); | 106 shell_client_.reset(); |
| 69 quit_task_runner_->PostTask(FROM_HERE, quit_closure_); | 107 quit_task_runner_->PostTask( |
| 108 FROM_HERE, base::Bind(&Instance::QuitOnRunnerThread, this)); |
| 70 } | 109 } |
| 71 | 110 |
| 72 base::ThreadChecker thread_checker_; | 111 void QuitOnRunnerThread() { |
| 73 const FactoryCallback factory_callback_; | 112 DCHECK(runner_thread_checker_.CalledOnValidThread()); |
| 113 ShutDown(); |
| 114 quit_closure_.Run(); |
| 115 } |
| 116 |
| 117 const std::string name_; |
| 118 const MojoApplicationInfo::ApplicationFactory factory_callback_; |
| 119 const bool use_own_thread_; |
| 120 const base::Closure quit_closure_; |
| 121 const scoped_refptr<base::SingleThreadTaskRunner> quit_task_runner_; |
| 122 |
| 123 // Thread checker used to ensure certain operations happen only on the |
| 124 // runner's (i.e. our owner's) thread. |
| 125 base::ThreadChecker runner_thread_checker_; |
| 126 |
| 127 // Thread checker used to ensure certain operations happen only on the |
| 128 // application task runner's thread. |
| 129 base::ThreadChecker application_thread_checker_; |
| 130 |
| 131 // These fields must only be accessed from the runner's thread. |
| 132 std::unique_ptr<base::Thread> thread_; |
| 133 scoped_refptr<base::SingleThreadTaskRunner> application_task_runner_; |
| 134 |
| 135 // These fields must only be accessed from the application thread, except in |
| 136 // the destructor which may run on either the runner thread or the application |
| 137 // thread. |
| 74 std::unique_ptr<shell::ShellClient> shell_client_; | 138 std::unique_ptr<shell::ShellClient> shell_client_; |
| 75 std::vector<std::unique_ptr<shell::ShellConnection>> shell_connections_; | 139 std::vector<std::unique_ptr<shell::ShellConnection>> shell_connections_; |
| 76 const base::Closure quit_closure_; | |
| 77 const scoped_refptr<base::SingleThreadTaskRunner> quit_task_runner_; | |
| 78 | 140 |
| 79 DISALLOW_COPY_AND_ASSIGN(Instance); | 141 DISALLOW_COPY_AND_ASSIGN(Instance); |
| 80 }; | 142 }; |
| 81 | 143 |
| 82 EmbeddedApplicationRunner::EmbeddedApplicationRunner( | 144 EmbeddedApplicationRunner::EmbeddedApplicationRunner( |
| 83 const FactoryCallback& callback, | 145 const base::StringPiece& name, |
| 84 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) | 146 const MojoApplicationInfo& info) |
| 85 : application_task_runner_( | 147 : weak_factory_(this) { |
| 86 task_runner ? task_runner : base::ThreadTaskRunnerHandle::Get()), | 148 instance_ = new Instance(name, info, |
| 87 weak_factory_(this) { | |
| 88 instance_ = new Instance(callback, | |
| 89 base::Bind(&EmbeddedApplicationRunner::OnQuit, | 149 base::Bind(&EmbeddedApplicationRunner::OnQuit, |
| 90 weak_factory_.GetWeakPtr())); | 150 weak_factory_.GetWeakPtr())); |
| 91 } | 151 } |
| 92 | 152 |
| 93 EmbeddedApplicationRunner::~EmbeddedApplicationRunner() { | 153 EmbeddedApplicationRunner::~EmbeddedApplicationRunner() { |
| 154 instance_->ShutDown(); |
| 94 } | 155 } |
| 95 | 156 |
| 96 void EmbeddedApplicationRunner::BindShellClientRequest( | 157 void EmbeddedApplicationRunner::BindShellClientRequest( |
| 97 shell::mojom::ShellClientRequest request) { | 158 shell::mojom::ShellClientRequest request) { |
| 98 application_task_runner_->PostTask( | 159 instance_->BindShellClientRequest(std::move(request)); |
| 99 FROM_HERE, | |
| 100 base::Bind(&Instance::BindShellClientRequest, instance_, | |
| 101 base::Passed(&request))); | |
| 102 } | 160 } |
| 103 | 161 |
| 104 void EmbeddedApplicationRunner::SetQuitClosure( | 162 void EmbeddedApplicationRunner::SetQuitClosure( |
| 105 const base::Closure& quit_closure) { | 163 const base::Closure& quit_closure) { |
| 106 quit_closure_ = quit_closure; | 164 quit_closure_ = quit_closure; |
| 107 } | 165 } |
| 108 | 166 |
| 109 void EmbeddedApplicationRunner::OnQuit() { | 167 void EmbeddedApplicationRunner::OnQuit() { |
| 110 quit_closure_.Run(); | 168 if (!quit_closure_.is_null()) |
| 169 quit_closure_.Run(); |
| 111 } | 170 } |
| 112 | 171 |
| 113 } // namespace content | 172 } // namespace content |
| OLD | NEW |