| 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/mojo_shell_connection_impl.h" | 5 #include "content/common/mojo/mojo_shell_connection_impl.h" |
| 6 | 6 |
| 7 #include <queue> | 7 #include <queue> |
| 8 #include <utility> | 8 #include <utility> |
| 9 #include <vector> | 9 #include <vector> |
| 10 | 10 |
| (...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 107 | 107 |
| 108 // Safe to call any time before Start() is called. | 108 // Safe to call any time before Start() is called. |
| 109 void SetDefaultBinderForBrowserConnection( | 109 void SetDefaultBinderForBrowserConnection( |
| 110 const shell::InterfaceRegistry::Binder& binder) { | 110 const shell::InterfaceRegistry::Binder& binder) { |
| 111 DCHECK(!started_); | 111 DCHECK(!started_); |
| 112 default_browser_binder_ = base::Bind( | 112 default_browser_binder_ = base::Bind( |
| 113 &IOThreadContext::CallBinderOnTaskRunner, | 113 &IOThreadContext::CallBinderOnTaskRunner, |
| 114 base::ThreadTaskRunnerHandle::Get(), binder); | 114 base::ThreadTaskRunnerHandle::Get(), binder); |
| 115 } | 115 } |
| 116 | 116 |
| 117 // Safe to call any time after Start() is called. | |
| 118 void GetRemoteInterface(const mojo::String& interface_name, | |
| 119 mojo::ScopedMessagePipeHandle request_handle) { | |
| 120 DCHECK(started_); | |
| 121 io_task_runner_->PostTask( | |
| 122 FROM_HERE, | |
| 123 base::Bind(&IOThreadContext::GetRemoteInterfaceOnIOThread, this, | |
| 124 interface_name, base::Passed(&request_handle))); | |
| 125 } | |
| 126 | |
| 127 private: | 117 private: |
| 128 friend class base::RefCountedThreadSafe<IOThreadContext>; | 118 friend class base::RefCountedThreadSafe<IOThreadContext>; |
| 129 | 119 |
| 130 ~IOThreadContext() override {} | 120 ~IOThreadContext() override {} |
| 131 | 121 |
| 132 void StartOnIOThread() { | 122 void StartOnIOThread() { |
| 133 // Should bind |io_thread_checker_| to the context's thread. | 123 // Should bind |io_thread_checker_| to the context's thread. |
| 134 DCHECK(io_thread_checker_.CalledOnValidThread()); | 124 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 135 service_context_.reset(new shell::ServiceContext( | 125 service_context_.reset(new shell::ServiceContext( |
| 136 this, std::move(pending_service_request_), | 126 this, std::move(pending_service_request_), |
| 137 std::move(io_thread_connector_), | 127 std::move(io_thread_connector_), |
| 138 std::move(pending_connector_request_))); | 128 std::move(pending_connector_request_))); |
| 139 } | 129 } |
| 140 | 130 |
| 141 void ShutDownOnIOThread() { | 131 void ShutDownOnIOThread() { |
| 142 DCHECK(io_thread_checker_.CalledOnValidThread()); | 132 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 143 service_context_.reset(); | 133 service_context_.reset(); |
| 144 factory_bindings_.CloseAllBindings(); | 134 factory_bindings_.CloseAllBindings(); |
| 145 } | 135 } |
| 146 | 136 |
| 147 void GetRemoteInterfaceOnIOThread( | |
| 148 const mojo::String& interface_name, | |
| 149 mojo::ScopedMessagePipeHandle request_handle) { | |
| 150 DCHECK(io_thread_checker_.CalledOnValidThread()); | |
| 151 if (browser_connection_) { | |
| 152 browser_connection_->GetRemoteInterfaces()->GetInterface( | |
| 153 interface_name, std::move(request_handle)); | |
| 154 } else { | |
| 155 pending_remote_interface_requests_.emplace(interface_name, | |
| 156 std::move(request_handle)); | |
| 157 } | |
| 158 } | |
| 159 | |
| 160 void OnBrowserConnectionLost() { | 137 void OnBrowserConnectionLost() { |
| 161 DCHECK(io_thread_checker_.CalledOnValidThread()); | 138 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 162 browser_connection_ = nullptr; | 139 has_browser_connection_ = false; |
| 163 } | 140 } |
| 164 | 141 |
| 165 ///////////////////////////////////////////////////////////////////////////// | 142 ///////////////////////////////////////////////////////////////////////////// |
| 166 // shell::Service implementation | 143 // shell::Service implementation |
| 167 | 144 |
| 168 void OnStart(const shell::Identity& identity) override { | 145 void OnStart(const shell::Identity& identity) override { |
| 169 DCHECK(io_thread_checker_.CalledOnValidThread()); | 146 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 170 DCHECK(!initialize_handler_.is_null()); | 147 DCHECK(!initialize_handler_.is_null()); |
| 171 | 148 |
| 172 InitializeCallback handler = base::ResetAndReturn(&initialize_handler_); | 149 InitializeCallback handler = base::ResetAndReturn(&initialize_handler_); |
| 173 callback_task_runner_->PostTask(FROM_HERE, base::Bind(handler, identity)); | 150 callback_task_runner_->PostTask(FROM_HERE, base::Bind(handler, identity)); |
| 174 } | 151 } |
| 175 | 152 |
| 176 bool OnConnect(shell::Connection* connection) override { | 153 bool OnConnect(const shell::Identity& remote_identity, |
| 154 shell::InterfaceRegistry* registry) override { |
| 177 DCHECK(io_thread_checker_.CalledOnValidThread()); | 155 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 178 std::string remote_app = connection->GetRemoteIdentity().name(); | 156 std::string remote_app = remote_identity.name(); |
| 179 if (remote_app == "mojo:shell") { | 157 if (remote_app == "mojo:shell") { |
| 180 // Only expose the SCF interface to the shell. | 158 // Only expose the SCF interface to the shell. |
| 181 connection->AddInterface<shell::mojom::ServiceFactory>(this); | 159 registry->AddInterface<shell::mojom::ServiceFactory>(this); |
| 182 return true; | 160 return true; |
| 183 } | 161 } |
| 184 | 162 |
| 185 bool accept = false; | 163 bool accept = false; |
| 186 for (auto& filter : connection_filters_) { | 164 for (auto& filter : connection_filters_) { |
| 187 accept = accept || | 165 accept = accept || |
| 188 filter->OnConnect(connection, service_context_->connector()); | 166 filter->OnConnect(remote_identity, registry, |
| 167 service_context_->connector()); |
| 189 } | 168 } |
| 190 | 169 |
| 191 // Capture the browser connection if possible. | 170 if (remote_identity.name() == "exe:content_browser" && |
| 192 if (remote_app == "exe:content_browser" && !browser_connection_) { | 171 !has_browser_connection_) { |
| 193 browser_connection_ = connection; | 172 has_browser_connection_ = true; |
| 194 connection->GetInterfaceRegistry()->set_default_binder( | 173 registry->set_default_binder(default_browser_binder_); |
| 195 default_browser_binder_); | 174 registry->SetConnectionLostClosure( |
| 196 connection->SetConnectionLostClosure( | |
| 197 base::Bind(&IOThreadContext::OnBrowserConnectionLost, this)); | 175 base::Bind(&IOThreadContext::OnBrowserConnectionLost, this)); |
| 198 shell::InterfaceProvider* remote_interfaces = | |
| 199 connection->GetRemoteInterfaces(); | |
| 200 | |
| 201 // Flush any pending outgoing interface requests. | |
| 202 while (!pending_remote_interface_requests_.empty()) { | |
| 203 auto& request = pending_remote_interface_requests_.front(); | |
| 204 remote_interfaces->GetInterface( | |
| 205 request.first, std::move(request.second)); | |
| 206 pending_remote_interface_requests_.pop(); | |
| 207 } | |
| 208 return true; | 176 return true; |
| 209 } | 177 } |
| 210 | 178 |
| 211 // If no filters were interested, reject the connection. | 179 // If no filters were interested, reject the connection. |
| 212 return accept; | 180 return accept; |
| 213 } | 181 } |
| 214 | 182 |
| 215 bool OnStop() override { | 183 bool OnStop() override { |
| 216 callback_task_runner_->PostTask(FROM_HERE, stop_callback_); | 184 callback_task_runner_->PostTask(FROM_HERE, stop_callback_); |
| 217 return true; | 185 return true; |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 262 | 230 |
| 263 // Callback to run once Service::OnStart is invoked. | 231 // Callback to run once Service::OnStart is invoked. |
| 264 InitializeCallback initialize_handler_; | 232 InitializeCallback initialize_handler_; |
| 265 | 233 |
| 266 // Callback to run when a new Service request is received. | 234 // Callback to run when a new Service request is received. |
| 267 ServiceFactoryCallback create_service_callback_; | 235 ServiceFactoryCallback create_service_callback_; |
| 268 | 236 |
| 269 // Callback to run if the service is stopped by the service manager. | 237 // Callback to run if the service is stopped by the service manager. |
| 270 base::Closure stop_callback_; | 238 base::Closure stop_callback_; |
| 271 | 239 |
| 272 // The incoming Connection from the browser process. This is captured the | 240 // Called once a connection has been received from the browser process & the |
| 273 // first time the browser connects to this Service and persists until shutdown | 241 // default binder (below) has been set up. |
| 274 // or a connection error is detected. This connection is used to fulfill | 242 bool has_browser_connection_ = false; |
| 275 // remote interface requests from legacy code which does not use | |
| 276 // shell::Connector. | |
| 277 // | |
| 278 // TODO(rockot): Remove this once all child-to-browser interface connections | |
| 279 // are made via a Connector rather than directly through an InterfaceProvider | |
| 280 // and all interfaces exposed to the browser are exposed via a | |
| 281 // ConnectionFilter. | |
| 282 shell::Connection* browser_connection_ = nullptr; | |
| 283 | |
| 284 // A queue of remote interface requests destined for the browser, which will | |
| 285 // remain pending until an incoming connection is accepted from the browser. | |
| 286 // | |
| 287 // TODO(rockot): Remove this once all child-to-browser interface connections | |
| 288 // are made via a Connector rather than directly through an InterfaceProvider. | |
| 289 std::queue<std::pair<mojo::String, mojo::ScopedMessagePipeHandle>> | |
| 290 pending_remote_interface_requests_; | |
| 291 | 243 |
| 292 // Default binder callback used for the browser connection's | 244 // Default binder callback used for the browser connection's |
| 293 // InterfaceRegistry. | 245 // InterfaceRegistry. |
| 294 // | 246 // |
| 295 // TODO(rockot): Remove this once all interfaces exposed to the browser are | 247 // TODO(rockot): Remove this once all interfaces exposed to the browser are |
| 296 // exposed via a ConnectionFilter. | 248 // exposed via a ConnectionFilter. |
| 297 shell::InterfaceRegistry::Binder default_browser_binder_; | 249 shell::InterfaceRegistry::Binder default_browser_binder_; |
| 298 | 250 |
| 299 std::unique_ptr<shell::ServiceContext> service_context_; | 251 std::unique_ptr<shell::ServiceContext> service_context_; |
| 300 mojo::BindingSet<shell::mojom::ServiceFactory> factory_bindings_; | 252 mojo::BindingSet<shell::mojom::ServiceFactory> factory_bindings_; |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 398 | 350 |
| 399 void MojoShellConnectionImpl::SetupInterfaceRequestProxies( | 351 void MojoShellConnectionImpl::SetupInterfaceRequestProxies( |
| 400 shell::InterfaceRegistry* registry, | 352 shell::InterfaceRegistry* registry, |
| 401 shell::InterfaceProvider* provider) { | 353 shell::InterfaceProvider* provider) { |
| 402 // It's safe to bind |registry| as a raw pointer because the caller must | 354 // It's safe to bind |registry| as a raw pointer because the caller must |
| 403 // guarantee that it outlives |this|, and |this| is bound as a weak ptr here. | 355 // guarantee that it outlives |this|, and |this| is bound as a weak ptr here. |
| 404 context_->SetDefaultBinderForBrowserConnection( | 356 context_->SetDefaultBinderForBrowserConnection( |
| 405 base::Bind(&MojoShellConnectionImpl::GetInterface, | 357 base::Bind(&MojoShellConnectionImpl::GetInterface, |
| 406 weak_factory_.GetWeakPtr(), registry)); | 358 weak_factory_.GetWeakPtr(), registry)); |
| 407 | 359 |
| 408 if (!provider) | 360 // TODO(beng): remove provider parameter. |
| 409 return; | |
| 410 | |
| 411 // Forward all remote interface requests on |provider| to our IO-thread | |
| 412 // context. This will ensure they're forwarded to the provider on the | |
| 413 // incoming browser connection. | |
| 414 provider->Forward(base::Bind(&IOThreadContext::GetRemoteInterface, | |
| 415 context_)); | |
| 416 } | 361 } |
| 417 | 362 |
| 418 void MojoShellConnectionImpl::AddConnectionFilter( | 363 void MojoShellConnectionImpl::AddConnectionFilter( |
| 419 std::unique_ptr<ConnectionFilter> filter) { | 364 std::unique_ptr<ConnectionFilter> filter) { |
| 420 context_->AddConnectionFilter(std::move(filter)); | 365 context_->AddConnectionFilter(std::move(filter)); |
| 421 } | 366 } |
| 422 | 367 |
| 423 std::unique_ptr<ConnectionFilter> | 368 std::unique_ptr<ConnectionFilter> |
| 424 MojoShellConnectionImpl::RemoveConnectionFilter(ConnectionFilter* filter) { | 369 MojoShellConnectionImpl::RemoveConnectionFilter(ConnectionFilter* filter) { |
| 425 return context_->RemoveConnectionFilter(filter); | 370 return context_->RemoveConnectionFilter(filter); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 465 } | 410 } |
| 466 | 411 |
| 467 void MojoShellConnectionImpl::GetInterface( | 412 void MojoShellConnectionImpl::GetInterface( |
| 468 shell::mojom::InterfaceProvider* provider, | 413 shell::mojom::InterfaceProvider* provider, |
| 469 const mojo::String& interface_name, | 414 const mojo::String& interface_name, |
| 470 mojo::ScopedMessagePipeHandle request_handle) { | 415 mojo::ScopedMessagePipeHandle request_handle) { |
| 471 provider->GetInterface(interface_name, std::move(request_handle)); | 416 provider->GetInterface(interface_name, std::move(request_handle)); |
| 472 } | 417 } |
| 473 | 418 |
| 474 } // namespace content | 419 } // namespace content |
| OLD | NEW |