| 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 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 83 | 83 |
| 84 bool posted = io_task_runner_->PostTask( | 84 bool posted = io_task_runner_->PostTask( |
| 85 FROM_HERE, base::Bind(&IOThreadContext::ShutDownOnIOThread, this)); | 85 FROM_HERE, base::Bind(&IOThreadContext::ShutDownOnIOThread, this)); |
| 86 DCHECK(posted); | 86 DCHECK(posted); |
| 87 } | 87 } |
| 88 | 88 |
| 89 // Safe to call any time before a message is received from a process. | 89 // Safe to call any time before a message is received from a process. |
| 90 // i.e. can be called when starting the process but not afterwards. | 90 // i.e. can be called when starting the process but not afterwards. |
| 91 int AddConnectionFilter(std::unique_ptr<ConnectionFilter> filter) { | 91 int AddConnectionFilter(std::unique_ptr<ConnectionFilter> filter) { |
| 92 base::AutoLock lock(lock_); | 92 base::AutoLock lock(lock_); |
| 93 |
| 93 int id = ++next_filter_id_; | 94 int id = ++next_filter_id_; |
| 95 |
| 96 // We should never hit this in practice, but let's crash just in case. |
| 97 CHECK_NE(id, kInvalidConnectionFilterId); |
| 98 |
| 94 connection_filters_[id] = std::move(filter); | 99 connection_filters_[id] = std::move(filter); |
| 95 return id; | 100 return id; |
| 96 } | 101 } |
| 97 | 102 |
| 98 void RemoveConnectionFilter(int filter_id) { | 103 void RemoveConnectionFilter(int filter_id) { |
| 99 io_task_runner_->PostTask( | 104 io_task_runner_->PostTask( |
| 100 FROM_HERE, | 105 FROM_HERE, |
| 101 base::Bind(&IOThreadContext::RemoveConnectionFilterOnIOThread, this, | 106 base::Bind(&IOThreadContext::RemoveConnectionFilterOnIOThread, this, |
| 102 filter_id)); | 107 filter_id)); |
| 103 } | 108 } |
| 104 | 109 |
| 105 // Safe to call any time before Start() is called. | 110 // Safe to call any time before Start() is called. |
| 106 void SetDefaultBinderForBrowserConnection( | 111 void SetDefaultBinderForBrowserConnection( |
| 107 const shell::InterfaceRegistry::Binder& binder) { | 112 const shell::InterfaceRegistry::Binder& binder) { |
| 108 DCHECK(!started_); | 113 DCHECK(!started_); |
| 109 default_browser_binder_ = base::Bind( | 114 default_browser_binder_ = base::Bind( |
| 110 &IOThreadContext::CallBinderOnTaskRunner, | 115 &IOThreadContext::CallBinderOnTaskRunner, |
| 111 base::ThreadTaskRunnerHandle::Get(), binder); | 116 base::ThreadTaskRunnerHandle::Get(), binder); |
| 112 } | 117 } |
| 113 | 118 |
| 114 private: | 119 private: |
| 115 friend class base::RefCountedThreadSafe<IOThreadContext>; | 120 friend class base::RefCountedThreadSafe<IOThreadContext>; |
| 116 | 121 |
| 117 class Obs : public base::MessageLoop::DestructionObserver { | 122 class MessageLoopObserver : public base::MessageLoop::DestructionObserver { |
| 118 public: | 123 public: |
| 119 explicit Obs(base::WeakPtr<IOThreadContext> context) : context_(context) { | 124 explicit MessageLoopObserver(base::WeakPtr<IOThreadContext> context) |
| 125 : context_(context) { |
| 120 base::MessageLoop::current()->AddDestructionObserver(this); | 126 base::MessageLoop::current()->AddDestructionObserver(this); |
| 121 } | 127 } |
| 122 ~Obs() override { | 128 |
| 129 ~MessageLoopObserver() override { |
| 123 base::MessageLoop::current()->RemoveDestructionObserver(this); | 130 base::MessageLoop::current()->RemoveDestructionObserver(this); |
| 124 } | 131 } |
| 125 | 132 |
| 133 void ShutDown() { |
| 134 if (!is_active_) |
| 135 return; |
| 136 |
| 137 // The call into |context_| below may reenter ShutDown(), hence we set |
| 138 // |is_active_| to false here. |
| 139 is_active_ = false; |
| 140 if (context_) |
| 141 context_->ShutDownOnIOThread(); |
| 142 |
| 143 delete this; |
| 144 } |
| 145 |
| 126 private: | 146 private: |
| 127 void WillDestroyCurrentMessageLoop() override { | 147 void WillDestroyCurrentMessageLoop() override { |
| 128 if (context_) | 148 DCHECK(is_active_); |
| 129 context_->ShutDownOnIOThread(); | 149 ShutDown(); |
| 130 delete this; | |
| 131 } | 150 } |
| 132 | 151 |
| 152 bool is_active_ = true; |
| 133 base::WeakPtr<IOThreadContext> context_; | 153 base::WeakPtr<IOThreadContext> context_; |
| 134 | 154 |
| 135 DISALLOW_COPY_AND_ASSIGN(Obs); | 155 DISALLOW_COPY_AND_ASSIGN(MessageLoopObserver); |
| 136 }; | 156 }; |
| 137 | 157 |
| 138 ~IOThreadContext() override {} | 158 ~IOThreadContext() override {} |
| 139 | 159 |
| 140 void StartOnIOThread() { | 160 void StartOnIOThread() { |
| 141 // Should bind |io_thread_checker_| to the context's thread. | 161 // Should bind |io_thread_checker_| to the context's thread. |
| 142 DCHECK(io_thread_checker_.CalledOnValidThread()); | 162 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 143 service_context_.reset(new shell::ServiceContext( | 163 service_context_.reset(new shell::ServiceContext( |
| 144 this, std::move(pending_service_request_), | 164 this, std::move(pending_service_request_), |
| 145 std::move(io_thread_connector_), | 165 std::move(io_thread_connector_), |
| 146 std::move(pending_connector_request_))); | 166 std::move(pending_connector_request_))); |
| 147 new Obs(weak_factory_.GetWeakPtr()); | 167 |
| 168 // MessageLoopObserver owns itself. |
| 169 message_loop_observer_ = |
| 170 new MessageLoopObserver(weak_factory_.GetWeakPtr()); |
| 148 } | 171 } |
| 149 | 172 |
| 150 void ShutDownOnIOThread() { | 173 void ShutDownOnIOThread() { |
| 151 DCHECK(io_thread_checker_.CalledOnValidThread()); | 174 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 175 |
| 152 weak_factory_.InvalidateWeakPtrs(); | 176 weak_factory_.InvalidateWeakPtrs(); |
| 177 |
| 178 // Note that this method may be invoked by MessageLoopObserver observing |
| 179 // MessageLoop destruction. In that case, this call to ShutDown is |
| 180 // effectively a no-op. In any case it's safe. |
| 181 message_loop_observer_->ShutDown(); |
| 182 message_loop_observer_ = nullptr; |
| 183 |
| 184 // Resetting the ServiceContext below may otherwise release the last |
| 185 // reference to this IOThreadContext. We keep it alive until the stack |
| 186 // unwinds. |
| 187 scoped_refptr<IOThreadContext> keepalive(this); |
| 188 |
| 153 factory_bindings_.CloseAllBindings(); | 189 factory_bindings_.CloseAllBindings(); |
| 190 service_context_.reset(); |
| 191 |
| 192 base::AutoLock lock(lock_); |
| 154 connection_filters_.clear(); | 193 connection_filters_.clear(); |
| 155 service_context_.reset(); | |
| 156 } | 194 } |
| 157 | 195 |
| 158 void RemoveConnectionFilterOnIOThread(int filter_id) { | 196 void RemoveConnectionFilterOnIOThread(int filter_id) { |
| 197 base::AutoLock lock(lock_); |
| 159 auto it = connection_filters_.find(filter_id); | 198 auto it = connection_filters_.find(filter_id); |
| 160 DCHECK(it != connection_filters_.end()); | 199 DCHECK(it != connection_filters_.end()); |
| 161 connection_filters_.erase(it); | 200 connection_filters_.erase(it); |
| 162 } | 201 } |
| 163 | 202 |
| 164 void OnBrowserConnectionLost() { | 203 void OnBrowserConnectionLost() { |
| 165 DCHECK(io_thread_checker_.CalledOnValidThread()); | 204 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 166 has_browser_connection_ = false; | 205 has_browser_connection_ = false; |
| 167 } | 206 } |
| 168 | 207 |
| (...skipping 13 matching lines...) Expand all Loading... |
| 182 shell::InterfaceRegistry* registry) override { | 221 shell::InterfaceRegistry* registry) override { |
| 183 DCHECK(io_thread_checker_.CalledOnValidThread()); | 222 DCHECK(io_thread_checker_.CalledOnValidThread()); |
| 184 std::string remote_app = remote_identity.name(); | 223 std::string remote_app = remote_identity.name(); |
| 185 if (remote_app == "mojo:shell") { | 224 if (remote_app == "mojo:shell") { |
| 186 // Only expose the SCF interface to the shell. | 225 // Only expose the SCF interface to the shell. |
| 187 registry->AddInterface<shell::mojom::ServiceFactory>(this); | 226 registry->AddInterface<shell::mojom::ServiceFactory>(this); |
| 188 return true; | 227 return true; |
| 189 } | 228 } |
| 190 | 229 |
| 191 bool accept = false; | 230 bool accept = false; |
| 192 for (auto& entry : connection_filters_) { | 231 { |
| 193 accept |= entry.second->OnConnect(remote_identity, registry, | 232 base::AutoLock lock(lock_); |
| 194 service_context_->connector()); | 233 for (auto& entry : connection_filters_) { |
| 234 accept |= entry.second->OnConnect(remote_identity, registry, |
| 235 service_context_->connector()); |
| 236 } |
| 195 } | 237 } |
| 196 | 238 |
| 197 if (remote_identity.name() == "exe:content_browser" && | 239 if (remote_identity.name() == "exe:content_browser" && |
| 198 !has_browser_connection_) { | 240 !has_browser_connection_) { |
| 199 has_browser_connection_ = true; | 241 has_browser_connection_ = true; |
| 200 registry->set_default_binder(default_browser_binder_); | 242 registry->set_default_binder(default_browser_binder_); |
| 201 registry->SetConnectionLostClosure( | 243 registry->SetConnectionLostClosure( |
| 202 base::Bind(&IOThreadContext::OnBrowserConnectionLost, this)); | 244 base::Bind(&IOThreadContext::OnBrowserConnectionLost, this)); |
| 203 return true; | 245 return true; |
| 204 } | 246 } |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 272 | 314 |
| 273 // Default binder callback used for the browser connection's | 315 // Default binder callback used for the browser connection's |
| 274 // InterfaceRegistry. | 316 // InterfaceRegistry. |
| 275 // | 317 // |
| 276 // TODO(rockot): Remove this once all interfaces exposed to the browser are | 318 // TODO(rockot): Remove this once all interfaces exposed to the browser are |
| 277 // exposed via a ConnectionFilter. | 319 // exposed via a ConnectionFilter. |
| 278 shell::InterfaceRegistry::Binder default_browser_binder_; | 320 shell::InterfaceRegistry::Binder default_browser_binder_; |
| 279 | 321 |
| 280 std::unique_ptr<shell::ServiceContext> service_context_; | 322 std::unique_ptr<shell::ServiceContext> service_context_; |
| 281 mojo::BindingSet<shell::mojom::ServiceFactory> factory_bindings_; | 323 mojo::BindingSet<shell::mojom::ServiceFactory> factory_bindings_; |
| 282 std::map<int, std::unique_ptr<ConnectionFilter>> connection_filters_; | |
| 283 int next_filter_id_ = kInvalidConnectionFilterId; | 324 int next_filter_id_ = kInvalidConnectionFilterId; |
| 284 | 325 |
| 326 // Not owned. |
| 327 MessageLoopObserver* message_loop_observer_ = nullptr; |
| 328 |
| 329 // Guards |connection_filters_|. |
| 285 base::Lock lock_; | 330 base::Lock lock_; |
| 331 std::map<int, std::unique_ptr<ConnectionFilter>> connection_filters_; |
| 286 | 332 |
| 287 base::WeakPtrFactory<IOThreadContext> weak_factory_; | 333 base::WeakPtrFactory<IOThreadContext> weak_factory_; |
| 288 | 334 |
| 289 DISALLOW_COPY_AND_ASSIGN(IOThreadContext); | 335 DISALLOW_COPY_AND_ASSIGN(IOThreadContext); |
| 290 }; | 336 }; |
| 291 | 337 |
| 292 //////////////////////////////////////////////////////////////////////////////// | 338 //////////////////////////////////////////////////////////////////////////////// |
| 293 // MojoShellConnection, public: | 339 // MojoShellConnection, public: |
| 294 | 340 |
| 295 // static | 341 // static |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 442 | 488 |
| 443 void MojoShellConnectionImpl::GetInterface( | 489 void MojoShellConnectionImpl::GetInterface( |
| 444 shell::mojom::InterfaceProvider* provider, | 490 shell::mojom::InterfaceProvider* provider, |
| 445 const std::string& interface_name, | 491 const std::string& interface_name, |
| 446 mojo::ScopedMessagePipeHandle request_handle) { | 492 mojo::ScopedMessagePipeHandle request_handle) { |
| 447 provider->GetInterface(interface_name, std::move(request_handle)); | 493 provider->GetInterface(interface_name, std::move(request_handle)); |
| 448 } | 494 } |
| 449 | 495 |
| 450 } // namespace content | 496 } // namespace content |
| 451 | 497 |
| OLD | NEW |