Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(336)

Side by Side Diff: content/common/mojo/mojo_shell_connection_impl.cc

Issue 2111353002: Move content's shell connections to the IO thread (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: . Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/mojo_shell_connection_impl.h" 5 #include "content/common/mojo/mojo_shell_connection_impl.h"
6 6
7 #include <utility>
8 #include <vector>
9
7 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/callback_helpers.h"
8 #include "base/lazy_instance.h" 12 #include "base/lazy_instance.h"
13 #include "base/macros.h"
9 #include "base/memory/ptr_util.h" 14 #include "base/memory/ptr_util.h"
10 #include "base/threading/thread_local.h" 15 #include "base/threading/thread_checker.h"
11 #include "content/common/mojo/embedded_application_runner.h" 16 #include "content/common/mojo/embedded_application_runner.h"
17 #include "mojo/public/cpp/bindings/binding_set.h"
18 #include "mojo/public/cpp/system/message_pipe.h"
12 #include "services/shell/public/cpp/shell_client.h" 19 #include "services/shell/public/cpp/shell_client.h"
13 #include "services/shell/public/cpp/shell_connection.h" 20 #include "services/shell/public/cpp/shell_connection.h"
21 #include "services/shell/public/interfaces/shell_client_factory.mojom.h"
14 #include "services/shell/runner/common/client_util.h" 22 #include "services/shell/runner/common/client_util.h"
15 23
16 namespace content { 24 namespace content {
17 namespace { 25 namespace {
18 26
19 using MojoShellConnectionPtr = 27 base::LazyInstance<std::unique_ptr<MojoShellConnection>>::Leaky
20 base::ThreadLocalPointer<MojoShellConnection>; 28 g_connection_for_process = LAZY_INSTANCE_INITIALIZER;
21
22 // Env is thread local so that aura may be used on multiple threads.
23 base::LazyInstance<MojoShellConnectionPtr>::Leaky lazy_tls_ptr =
24 LAZY_INSTANCE_INITIALIZER;
25 29
26 MojoShellConnection::Factory* mojo_shell_connection_factory = nullptr; 30 MojoShellConnection::Factory* mojo_shell_connection_factory = nullptr;
27 31
28 } // namespace 32 } // namespace
29 33
34 // A ref-counted object which owns the IO thread state of a
35 // MojoShellConnectionImpl. This includes ShellClient and ShellClientFactory
36 // bindings.
37 class MojoShellConnectionImpl::IOThreadContext
38 : public base::RefCountedThreadSafe<IOThreadContext>,
39 public shell::ShellClient,
40 public shell::InterfaceFactory<shell::mojom::ShellClientFactory>,
41 public shell::mojom::ShellClientFactory {
42 public:
43 using ShellClientFactoryCallback =
44 base::Callback<void(shell::mojom::ShellClientRequest,
45 const mojo::String&)>;
46
47 IOThreadContext() {}
48
49 // The following methods are safe to call from any thread.
50
51 void Initialize(shell::mojom::ShellClientRequest request,
52 scoped_refptr<base::SequencedTaskRunner> io_task_runner,
53 std::unique_ptr<shell::Connector> io_thread_connector,
54 shell::mojom::ConnectorRequest connector_request,
55 const base::Closure& initialize_callback,
56 const ShellClientFactoryCallback& create_shell_client) {
57 DCHECK(!io_task_runner_);
58 io_thread_checker_.DetachFromThread();
59
60 io_task_runner_ = io_task_runner;
61 initialize_handler_ = base::Bind(
62 &IOThreadContext::CallInitializeOnTaskRunner,
63 base::ThreadTaskRunnerHandle::Get(), initialize_callback);
64
65 create_shell_client_ = base::Bind(
66 &IOThreadContext::CallShellClientFactoryOnTaskRunner,
67 base::ThreadTaskRunnerHandle::Get(), create_shell_client);
68
69 io_task_runner_->PostTask(
70 FROM_HERE,
71 base::Bind(&IOThreadContext::InitializeOnIOThread, this,
72 base::Passed(&request), base::Passed(&io_thread_connector),
73 base::Passed(&connector_request)));
74 }
75
76 void ShutDown() {
77 bool posted = io_task_runner_->PostTask(
78 FROM_HERE, base::Bind(&IOThreadContext::ShutdownOnIOThread, this));
79
80 // This must be called before IO thread shutdown.
81 DCHECK(posted);
82 }
83
84 void AddConnectionFilter(
85 const MojoShellConnection::ConnectionFilter& filter) {
86 base::AutoLock lock(lock_);
87 connection_filters_.push_back(filter);
88 }
89
90 shell::Identity GetIdentity() {
91 base::AutoLock lock(lock_);
92 if (!shell_connection_)
93 return shell::Identity();
94
95 return shell_connection_->identity();
96 }
97
98 private:
99 friend class base::RefCountedThreadSafe<IOThreadContext>;
100
101 ~IOThreadContext() override {}
102
103 void InitializeOnIOThread(shell::mojom::ShellClientRequest request,
104 std::unique_ptr<shell::Connector> connector,
105 shell::mojom::ConnectorRequest connector_request) {
106 // Should bind |io_thread_checker_| to the context's thread.
107 DCHECK(io_thread_checker_.CalledOnValidThread());
108 shell_connection_.reset(new shell::ShellConnection(
109 this, std::move(request), std::move(connector),
110 std::move(connector_request)));
111 }
112
113 void ShutdownOnIOThread() {
114 DCHECK(io_thread_checker_.CalledOnValidThread());
115 shell_connection_.reset();
116 factory_bindings_.CloseAllBindings();
117 }
118
119 /////////////////////////////////////////////////////////////////////////////
120 // shell::ShellClient implementation
121
122 void Initialize(shell::Connector* connector,
123 const shell::Identity& identity,
124 uint32_t id) override {
125 DCHECK(io_thread_checker_.CalledOnValidThread());
126 DCHECK(!initialize_handler_.is_null());
127 base::ResetAndReturn(&initialize_handler_).Run();
128 }
129
130 bool AcceptConnection(shell::Connection* connection) override {
131 DCHECK(io_thread_checker_.CalledOnValidThread());
132 std::string remote_app = connection->GetRemoteIdentity().name();
133 if (remote_app == "mojo:shell") {
134 // Only expose the SCF interface to the shell.
135 connection->AddInterface<shell::mojom::ShellClientFactory>(this);
136 return true;
137 }
138
139 bool accept = false;
140 base::AutoLock lock(lock_);
141 for (auto& filter : connection_filters_)
142 accept = accept || filter.Run(connection, shell_connection_->connector());
143
144 // Reject all other connections to this application.
145 return accept;
146 }
147
148 /////////////////////////////////////////////////////////////////////////////
149 // shell::InterfaceFactory<shell::mojom::ShellClientFactory> implementation
150
151 void Create(shell::Connection* connection,
152 shell::mojom::ShellClientFactoryRequest request) override {
153 DCHECK(io_thread_checker_.CalledOnValidThread());
154 factory_bindings_.AddBinding(this, std::move(request));
155 }
156
157 /////////////////////////////////////////////////////////////////////////////
158 // shell::mojom::ShellClientFactory implementation
159
160 void CreateShellClient(shell::mojom::ShellClientRequest request,
161 const mojo::String& name) override {
162 DCHECK(io_thread_checker_.CalledOnValidThread());
163 create_shell_client_.Run(std::move(request), name);
164 }
165
166 static void CallInitializeOnTaskRunner(
167 scoped_refptr<base::SequencedTaskRunner> task_runner,
168 const base::Closure& callback) {
169 task_runner->PostTask(FROM_HERE, callback);
170 }
171
172 static void CallShellClientFactoryOnTaskRunner(
173 scoped_refptr<base::SequencedTaskRunner> task_runner,
174 const ShellClientFactoryCallback& callback,
175 shell::mojom::ShellClientRequest request,
176 const mojo::String& name) {
177 task_runner->PostTask(
178 FROM_HERE, base::Bind(callback, base::Passed(&request), name));
179 }
180
181 base::ThreadChecker io_thread_checker_;
182
183 scoped_refptr<base::SequencedTaskRunner> io_task_runner_;
184
185 base::Closure initialize_handler_;
186 ShellClientFactoryCallback create_shell_client_;
187
188 // Guards fields below for thread-safe access.
189 base::Lock lock_;
190
191 std::unique_ptr<shell::ShellConnection> shell_connection_;
192 mojo::BindingSet<shell::mojom::ShellClientFactory> factory_bindings_;
193 std::vector<MojoShellConnection::ConnectionFilter> connection_filters_;
194
195 DISALLOW_COPY_AND_ASSIGN(IOThreadContext);
196 };
197
30 //////////////////////////////////////////////////////////////////////////////// 198 ////////////////////////////////////////////////////////////////////////////////
31 // MojoShellConnection, public: 199 // MojoShellConnection, public:
32 200
33 // static 201 // static
34 void MojoShellConnection::SetForProcess( 202 void MojoShellConnection::SetForProcess(
35 std::unique_ptr<MojoShellConnection> connection) { 203 std::unique_ptr<MojoShellConnection> connection) {
36 DCHECK(!lazy_tls_ptr.Pointer()->Get()); 204 DCHECK(!g_connection_for_process.Get());
37 lazy_tls_ptr.Pointer()->Set(connection.release()); 205 g_connection_for_process.Get() = std::move(connection);
38 } 206 }
39 207
40 // static 208 // static
41 MojoShellConnection* MojoShellConnection::GetForProcess() { 209 MojoShellConnection* MojoShellConnection::GetForProcess() {
42 return lazy_tls_ptr.Pointer()->Get(); 210 return g_connection_for_process.Get().get();
43 } 211 }
44 212
45 // static 213 // static
46 void MojoShellConnection::DestroyForProcess() { 214 void MojoShellConnection::DestroyForProcess() {
47 // This joins the shell controller thread. 215 // This joins the shell controller thread.
48 delete GetForProcess(); 216 g_connection_for_process.Get().reset();
49 lazy_tls_ptr.Pointer()->Set(nullptr);
50 } 217 }
51 218
52 // static 219 // static
53 void MojoShellConnection::SetFactoryForTest(Factory* factory) { 220 void MojoShellConnection::SetFactoryForTest(Factory* factory) {
54 DCHECK(!lazy_tls_ptr.Pointer()->Get()); 221 DCHECK(!g_connection_for_process.Get());
55 mojo_shell_connection_factory = factory; 222 mojo_shell_connection_factory = factory;
56 } 223 }
57 224
58 // static 225 // static
59 std::unique_ptr<MojoShellConnection> MojoShellConnection::Create( 226 std::unique_ptr<MojoShellConnection> MojoShellConnection::Create(
60 shell::mojom::ShellClientRequest request) { 227 shell::mojom::ShellClientRequest request,
228 scoped_refptr<base::SequencedTaskRunner> io_task_runner) {
61 if (mojo_shell_connection_factory) 229 if (mojo_shell_connection_factory)
62 return mojo_shell_connection_factory->Run(); 230 return mojo_shell_connection_factory->Run();
63 return base::WrapUnique(new MojoShellConnectionImpl(std::move(request))); 231 return base::MakeUnique<MojoShellConnectionImpl>(
232 std::move(request), io_task_runner);
64 } 233 }
65 234
66 MojoShellConnection::~MojoShellConnection() {} 235 MojoShellConnection::~MojoShellConnection() {}
67 236
68 //////////////////////////////////////////////////////////////////////////////// 237 ////////////////////////////////////////////////////////////////////////////////
69 // MojoShellConnectionImpl, public: 238 // MojoShellConnectionImpl, public:
70 239
71 MojoShellConnectionImpl::MojoShellConnectionImpl( 240 MojoShellConnectionImpl::MojoShellConnectionImpl(
72 shell::mojom::ShellClientRequest request) 241 shell::mojom::ShellClientRequest request,
73 : shell_connection_(new shell::ShellConnection(this, std::move(request))) {} 242 scoped_refptr<base::SequencedTaskRunner> io_task_runner)
243 : context_(new IOThreadContext), weak_factory_(this) {
244 shell::mojom::ConnectorRequest connector_request;
245 connector_ = shell::Connector::Create(&connector_request);
74 246
75 MojoShellConnectionImpl::~MojoShellConnectionImpl() {} 247 std::unique_ptr<shell::Connector> io_thread_connector = connector_->Clone();
76 248 context_->Initialize(
77 //////////////////////////////////////////////////////////////////////////////// 249 std::move(request), io_task_runner, std::move(io_thread_connector),
78 // MojoShellConnectionImpl, shell::ShellClient implementation: 250 std::move(connector_request),
79 251 base::Bind(&MojoShellConnectionImpl::OnContextInitialized,
80 void MojoShellConnectionImpl::Initialize(shell::Connector* connector, 252 weak_factory_.GetWeakPtr()),
81 const shell::Identity& identity, 253 base::Bind(&MojoShellConnectionImpl::CreateShellClient,
82 uint32_t id) { 254 weak_factory_.GetWeakPtr()));
83 for (auto& client : embedded_shell_clients_)
84 client->Initialize(connector, identity, id);
85 } 255 }
86 256
87 bool MojoShellConnectionImpl::AcceptConnection(shell::Connection* connection) { 257 MojoShellConnectionImpl::~MojoShellConnectionImpl() {
88 std::string remote_app = connection->GetRemoteIdentity().name(); 258 context_->ShutDown();
89 if (remote_app == "mojo:shell") {
90 // Only expose the SCF interface to the shell.
91 connection->AddInterface<shell::mojom::ShellClientFactory>(this);
92 return true;
93 }
94
95 bool accept = false;
96 for (auto& client : embedded_shell_clients_)
97 accept |= client->AcceptConnection(connection);
98
99 // Reject all other connections to this application.
100 return accept;
101 }
102
103 shell::InterfaceRegistry*
104 MojoShellConnectionImpl::GetInterfaceRegistryForConnection() {
105 // TODO(beng): This is really horrible since obviously subject to issues
106 // of ordering, but is no more horrible than this API is in general.
107 shell::InterfaceRegistry* registry = nullptr;
108 for (auto& client : embedded_shell_clients_) {
109 registry = client->GetInterfaceRegistryForConnection();
110 if (registry)
111 return registry;
112 }
113 return nullptr;
114 }
115
116 shell::InterfaceProvider*
117 MojoShellConnectionImpl::GetInterfaceProviderForConnection() {
118 // TODO(beng): This is really horrible since obviously subject to issues
119 // of ordering, but is no more horrible than this API is in general.
120 shell::InterfaceProvider* provider = nullptr;
121 for (auto& client : embedded_shell_clients_) {
122 provider = client->GetInterfaceProviderForConnection();
123 if (provider)
124 return provider;
125 }
126 return nullptr;
127 }
128
129 ////////////////////////////////////////////////////////////////////////////////
130 // MojoShellConnectionImpl,
131 // shell::InterfaceFactory<shell::mojom::ShellClientFactory> implementation:
132
133 void MojoShellConnectionImpl::Create(
134 shell::Connection* connection,
135 shell::mojom::ShellClientFactoryRequest request) {
136 factory_bindings_.AddBinding(this, std::move(request));
137 }
138
139 ////////////////////////////////////////////////////////////////////////////////
140 // MojoShellConnectionImpl, shell::mojom::ShellClientFactory implementation:
141
142 void MojoShellConnectionImpl::CreateShellClient(
143 shell::mojom::ShellClientRequest request,
144 const mojo::String& name) {
145 auto it = request_handlers_.find(name);
146 if (it != request_handlers_.end())
147 it->second.Run(std::move(request));
148 } 259 }
149 260
150 //////////////////////////////////////////////////////////////////////////////// 261 ////////////////////////////////////////////////////////////////////////////////
151 // MojoShellConnectionImpl, MojoShellConnection implementation: 262 // MojoShellConnectionImpl, MojoShellConnection implementation:
152 263
153 shell::ShellConnection* MojoShellConnectionImpl::GetShellConnection() { 264 void MojoShellConnectionImpl::SetInitializeHandler(
154 return shell_connection_.get(); 265 const base::Closure& handler) {
266 DCHECK(initialize_handler_.is_null());
267 initialize_handler_ = handler;
155 } 268 }
156 269
157 shell::Connector* MojoShellConnectionImpl::GetConnector() { 270 shell::Connector* MojoShellConnectionImpl::GetConnector() {
158 DCHECK(shell_connection_); 271 return connector_.get();
159 return shell_connection_->connector();
160 } 272 }
161 273
162 const shell::Identity& MojoShellConnectionImpl::GetIdentity() const { 274 const shell::Identity& MojoShellConnectionImpl::GetIdentity() const {
163 DCHECK(shell_connection_); 275 return identity_;
164 return shell_connection_->identity();
165 } 276 }
166 277
167 void MojoShellConnectionImpl::SetConnectionLostClosure( 278 void MojoShellConnectionImpl::SetConnectionLostClosure(
168 const base::Closure& closure) { 279 const base::Closure& closure) {
169 shell_connection_->SetConnectionLostClosure(closure); 280 connection_lost_handler_ = closure;
170 } 281 }
171 282
172 void MojoShellConnectionImpl::AddEmbeddedShellClient( 283 void MojoShellConnectionImpl::AddConnectionFilter(
173 std::unique_ptr<shell::ShellClient> shell_client) { 284 const ConnectionFilter& filter) {
Ben Goodger (Google) 2016/07/03 03:29:27 did you mean to leave this implementation empty?
174 embedded_shell_clients_.push_back(shell_client.get());
175 owned_shell_clients_.push_back(std::move(shell_client));
176 }
177
178 void MojoShellConnectionImpl::AddEmbeddedShellClient(
179 shell::ShellClient* shell_client) {
180 embedded_shell_clients_.push_back(shell_client);
181 } 285 }
182 286
183 void MojoShellConnectionImpl::AddEmbeddedService( 287 void MojoShellConnectionImpl::AddEmbeddedService(
184 const std::string& name, 288 const std::string& name,
185 const MojoApplicationInfo& info) { 289 const MojoApplicationInfo& info) {
186 std::unique_ptr<EmbeddedApplicationRunner> app( 290 std::unique_ptr<EmbeddedApplicationRunner> app(
187 new EmbeddedApplicationRunner(name, info)); 291 new EmbeddedApplicationRunner(name, info));
188 AddShellClientRequestHandler( 292 AddShellClientRequestHandler(
189 name, base::Bind(&EmbeddedApplicationRunner::BindShellClientRequest, 293 name, base::Bind(&EmbeddedApplicationRunner::BindShellClientRequest,
190 base::Unretained(app.get()))); 294 base::Unretained(app.get())));
191 auto result = embedded_apps_.insert(std::make_pair(name, std::move(app))); 295 auto result = embedded_apps_.insert(std::make_pair(name, std::move(app)));
192 DCHECK(result.second); 296 DCHECK(result.second);
193 } 297 }
194 298
195 void MojoShellConnectionImpl::AddShellClientRequestHandler( 299 void MojoShellConnectionImpl::AddShellClientRequestHandler(
196 const std::string& name, 300 const std::string& name,
197 const ShellClientRequestHandler& handler) { 301 const ShellClientRequestHandler& handler) {
198 auto result = request_handlers_.insert(std::make_pair(name, handler)); 302 auto result = request_handlers_.insert(std::make_pair(name, handler));
199 DCHECK(result.second); 303 DCHECK(result.second);
200 } 304 }
201 305
306 void MojoShellConnectionImpl::CreateShellClient(
307 shell::mojom::ShellClientRequest request,
308 const mojo::String& name) {
309 auto it = request_handlers_.find(name);
310 if (it != request_handlers_.end())
311 it->second.Run(std::move(request));
312 }
313
314 void MojoShellConnectionImpl::OnContextInitialized() {
315 identity_ = context_->GetIdentity();
316 if (!initialize_handler_.is_null())
317 base::ResetAndReturn(&initialize_handler_).Run();
318 }
319
320 void MojoShellConnectionImpl::OnConnectionLost() {
321 if (!connection_lost_handler_.is_null())
322 connection_lost_handler_.Run();
323 }
324
202 } // namespace content 325 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698