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 |