OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "base/bind.h" | 5 #include "base/bind.h" |
6 #include "base/compiler_specific.h" | 6 #include "base/compiler_specific.h" |
7 #include "base/debug/trace_event.h" | 7 #include "base/debug/trace_event.h" |
8 #include "base/location.h" | 8 #include "base/location.h" |
9 #include "base/memory/ref_counted.h" | 9 #include "base/memory/ref_counted.h" |
10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
149 | 149 |
150 ChannelProxy::Context::~Context() { | 150 ChannelProxy::Context::~Context() { |
151 } | 151 } |
152 | 152 |
153 void ChannelProxy::Context::ClearIPCTaskRunner() { | 153 void ChannelProxy::Context::ClearIPCTaskRunner() { |
154 ipc_task_runner_ = NULL; | 154 ipc_task_runner_ = NULL; |
155 } | 155 } |
156 | 156 |
157 void ChannelProxy::Context::CreateChannel(const IPC::ChannelHandle& handle, | 157 void ChannelProxy::Context::CreateChannel(const IPC::ChannelHandle& handle, |
158 const Channel::Mode& mode) { | 158 const Channel::Mode& mode) { |
159 DCHECK(channel_.get() == NULL); | 159 DCHECK(!channel_); |
160 channel_id_ = handle.name; | 160 channel_id_ = handle.name; |
161 channel_.reset(new Channel(handle, mode, this)); | 161 channel_.reset(new Channel(handle, mode, this)); |
162 } | 162 } |
163 | 163 |
164 bool ChannelProxy::Context::TryFilters(const Message& message) { | 164 bool ChannelProxy::Context::TryFilters(const Message& message) { |
165 DCHECK(message_filter_router_); | 165 DCHECK(message_filter_router_); |
166 #ifdef IPC_MESSAGE_LOG_ENABLED | 166 #ifdef IPC_MESSAGE_LOG_ENABLED |
167 Logging* logger = Logging::GetInstance(); | 167 Logging* logger = Logging::GetInstance(); |
168 if (logger->Enabled()) | 168 if (logger->Enabled()) |
169 logger->OnPreDispatchMessage(message); | 169 logger->OnPreDispatchMessage(message); |
(...skipping 19 matching lines...) Expand all Loading... |
189 | 189 |
190 // Called on the IPC::Channel thread | 190 // Called on the IPC::Channel thread |
191 bool ChannelProxy::Context::OnMessageReceivedNoFilter(const Message& message) { | 191 bool ChannelProxy::Context::OnMessageReceivedNoFilter(const Message& message) { |
192 listener_task_runner_->PostTask( | 192 listener_task_runner_->PostTask( |
193 FROM_HERE, base::Bind(&Context::OnDispatchMessage, this, message)); | 193 FROM_HERE, base::Bind(&Context::OnDispatchMessage, this, message)); |
194 return true; | 194 return true; |
195 } | 195 } |
196 | 196 |
197 // Called on the IPC::Channel thread | 197 // Called on the IPC::Channel thread |
198 void ChannelProxy::Context::OnChannelConnected(int32 peer_pid) { | 198 void ChannelProxy::Context::OnChannelConnected(int32 peer_pid) { |
| 199 // We cache off the peer_pid so it can be safely accessed from both threads. |
| 200 peer_pid_ = channel_->peer_pid(); |
| 201 |
199 // Add any pending filters. This avoids a race condition where someone | 202 // Add any pending filters. This avoids a race condition where someone |
200 // creates a ChannelProxy, calls AddFilter, and then right after starts the | 203 // creates a ChannelProxy, calls AddFilter, and then right after starts the |
201 // peer process. The IO thread could receive a message before the task to add | 204 // peer process. The IO thread could receive a message before the task to add |
202 // the filter is run on the IO thread. | 205 // the filter is run on the IO thread. |
203 OnAddFilter(); | 206 OnAddFilter(); |
204 | 207 |
205 // We cache off the peer_pid so it can be safely accessed from both threads. | |
206 peer_pid_ = channel_->peer_pid(); | |
207 for (size_t i = 0; i < filters_.size(); ++i) | |
208 filters_[i]->OnChannelConnected(peer_pid); | |
209 | |
210 // See above comment about using listener_task_runner_ here. | 208 // See above comment about using listener_task_runner_ here. |
211 listener_task_runner_->PostTask( | 209 listener_task_runner_->PostTask( |
212 FROM_HERE, base::Bind(&Context::OnDispatchConnected, this)); | 210 FROM_HERE, base::Bind(&Context::OnDispatchConnected, this)); |
213 } | 211 } |
214 | 212 |
215 // Called on the IPC::Channel thread | 213 // Called on the IPC::Channel thread |
216 void ChannelProxy::Context::OnChannelError() { | 214 void ChannelProxy::Context::OnChannelError() { |
217 for (size_t i = 0; i < filters_.size(); ++i) | 215 for (size_t i = 0; i < filters_.size(); ++i) |
218 filters_[i]->OnChannelError(); | 216 filters_[i]->OnChannelError(); |
219 | 217 |
(...skipping 16 matching lines...) Expand all Loading... |
236 } | 234 } |
237 | 235 |
238 for (size_t i = 0; i < filters_.size(); ++i) | 236 for (size_t i = 0; i < filters_.size(); ++i) |
239 filters_[i]->OnFilterAdded(channel_.get()); | 237 filters_[i]->OnFilterAdded(channel_.get()); |
240 } | 238 } |
241 | 239 |
242 // Called on the IPC::Channel thread | 240 // Called on the IPC::Channel thread |
243 void ChannelProxy::Context::OnChannelClosed() { | 241 void ChannelProxy::Context::OnChannelClosed() { |
244 // It's okay for IPC::ChannelProxy::Close to be called more than once, which | 242 // It's okay for IPC::ChannelProxy::Close to be called more than once, which |
245 // would result in this branch being taken. | 243 // would result in this branch being taken. |
246 if (!channel_.get()) | 244 if (!channel_) |
247 return; | 245 return; |
248 | 246 |
249 for (size_t i = 0; i < filters_.size(); ++i) { | 247 for (size_t i = 0; i < filters_.size(); ++i) { |
250 filters_[i]->OnChannelClosing(); | 248 filters_[i]->OnChannelClosing(); |
251 filters_[i]->OnFilterRemoved(); | 249 filters_[i]->OnFilterRemoved(); |
252 } | 250 } |
253 | 251 |
254 // We don't need the filters anymore. | 252 // We don't need the filters anymore. |
255 message_filter_router_->Clear(); | 253 message_filter_router_->Clear(); |
256 filters_.clear(); | 254 filters_.clear(); |
| 255 // We don't need the lock, because at this point, the listener thread can't |
| 256 // access it any more. |
| 257 pending_filters_.clear(); |
257 | 258 |
258 channel_.reset(); | 259 channel_.reset(); |
259 | 260 |
260 // Balance with the reference taken during startup. This may result in | 261 // Balance with the reference taken during startup. This may result in |
261 // self-destruction. | 262 // self-destruction. |
262 Release(); | 263 Release(); |
263 } | 264 } |
264 | 265 |
265 void ChannelProxy::Context::Clear() { | 266 void ChannelProxy::Context::Clear() { |
266 listener_ = NULL; | 267 listener_ = NULL; |
267 } | 268 } |
268 | 269 |
269 // Called on the IPC::Channel thread | 270 // Called on the IPC::Channel thread |
270 void ChannelProxy::Context::OnSendMessage(scoped_ptr<Message> message) { | 271 void ChannelProxy::Context::OnSendMessage(scoped_ptr<Message> message) { |
271 if (!channel_.get()) { | 272 if (!channel_) { |
272 OnChannelClosed(); | 273 OnChannelClosed(); |
273 return; | 274 return; |
274 } | 275 } |
| 276 |
275 if (!channel_->Send(message.release())) | 277 if (!channel_->Send(message.release())) |
276 OnChannelError(); | 278 OnChannelError(); |
277 } | 279 } |
278 | 280 |
279 // Called on the IPC::Channel thread | 281 // Called on the IPC::Channel thread |
280 void ChannelProxy::Context::OnAddFilter() { | 282 void ChannelProxy::Context::OnAddFilter() { |
| 283 // Our OnChannelConnected method has not yet been called, so we can't be |
| 284 // sure that channel_ is valid yet. When OnChannelConnected *is* called, |
| 285 // it invokes OnAddFilter, so any pending filter(s) will be added at that |
| 286 // time. |
| 287 if (peer_pid_ == base::kNullProcessId) |
| 288 return; |
| 289 |
281 std::vector<scoped_refptr<MessageFilter> > new_filters; | 290 std::vector<scoped_refptr<MessageFilter> > new_filters; |
282 { | 291 { |
283 base::AutoLock auto_lock(pending_filters_lock_); | 292 base::AutoLock auto_lock(pending_filters_lock_); |
284 new_filters.swap(pending_filters_); | 293 new_filters.swap(pending_filters_); |
285 } | 294 } |
286 | 295 |
287 for (size_t i = 0; i < new_filters.size(); ++i) { | 296 for (size_t i = 0; i < new_filters.size(); ++i) { |
288 filters_.push_back(new_filters[i]); | 297 filters_.push_back(new_filters[i]); |
289 | 298 |
290 message_filter_router_->AddFilter(new_filters[i].get()); | 299 message_filter_router_->AddFilter(new_filters[i].get()); |
291 | 300 |
292 // If the channel has already been created, then we need to send this | 301 // The channel has already been created and connected, so we need to |
293 // message so that the filter gets access to the Channel. | 302 // inform the filters right now. |
294 if (channel_.get()) | 303 new_filters[i]->OnFilterAdded(channel_.get()); |
295 new_filters[i]->OnFilterAdded(channel_.get()); | 304 new_filters[i]->OnChannelConnected(peer_pid_); |
296 // Ditto for if the channel has been connected. | |
297 if (peer_pid_) | |
298 new_filters[i]->OnChannelConnected(peer_pid_); | |
299 } | 305 } |
300 } | 306 } |
301 | 307 |
302 // Called on the IPC::Channel thread | 308 // Called on the IPC::Channel thread |
303 void ChannelProxy::Context::OnRemoveFilter(MessageFilter* filter) { | 309 void ChannelProxy::Context::OnRemoveFilter(MessageFilter* filter) { |
304 if (!channel_.get()) | 310 if (peer_pid_ == base::kNullProcessId) { |
| 311 // The channel is not yet connected, so any filters are still pending. |
| 312 base::AutoLock auto_lock(pending_filters_lock_); |
| 313 for (size_t i = 0; i < pending_filters_.size(); ++i) { |
| 314 if (pending_filters_[i].get() == filter) { |
| 315 filter->OnFilterRemoved(); |
| 316 pending_filters_.erase(pending_filters_.begin() + i); |
| 317 return; |
| 318 } |
| 319 } |
| 320 return; |
| 321 } |
| 322 if (!channel_) |
305 return; // The filters have already been deleted. | 323 return; // The filters have already been deleted. |
306 | 324 |
307 message_filter_router_->RemoveFilter(filter); | 325 message_filter_router_->RemoveFilter(filter); |
308 | 326 |
309 for (size_t i = 0; i < filters_.size(); ++i) { | 327 for (size_t i = 0; i < filters_.size(); ++i) { |
310 if (filters_[i].get() == filter) { | 328 if (filters_[i].get() == filter) { |
311 filter->OnFilterRemoved(); | 329 filter->OnFilterRemoved(); |
312 filters_.erase(filters_.begin() + i); | 330 filters_.erase(filters_.begin() + i); |
313 return; | 331 return; |
314 } | 332 } |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
512 Channel* channel = context_.get()->channel_.get(); | 530 Channel* channel = context_.get()->channel_.get(); |
513 // Channel must have been created first. | 531 // Channel must have been created first. |
514 DCHECK(channel) << context_.get()->channel_id_; | 532 DCHECK(channel) << context_.get()->channel_id_; |
515 return channel->GetPeerEuid(peer_euid); | 533 return channel->GetPeerEuid(peer_euid); |
516 } | 534 } |
517 #endif | 535 #endif |
518 | 536 |
519 //----------------------------------------------------------------------------- | 537 //----------------------------------------------------------------------------- |
520 | 538 |
521 } // namespace IPC | 539 } // namespace IPC |
OLD | NEW |