| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/child/npapi/np_channel_base.h" | 5 #include "content/child/npapi/np_channel_base.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include "base/auto_reset.h" | 9 #include "base/auto_reset.h" |
| 10 #include "base/containers/hash_tables.h" | 10 #include "base/containers/hash_tables.h" |
| 11 #include "base/files/scoped_file.h" | 11 #include "base/files/scoped_file.h" |
| 12 #include "base/lazy_instance.h" | 12 #include "base/lazy_instance.h" |
| 13 #include "base/single_thread_task_runner.h" | 13 #include "base/single_thread_task_runner.h" |
| 14 #include "base/strings/string_number_conversions.h" | |
| 15 #include "base/threading/thread_local.h" | 14 #include "base/threading/thread_local.h" |
| 16 #include "build/build_config.h" | 15 #include "build/build_config.h" |
| 17 #include "ipc/ipc_sync_message.h" | 16 #include "ipc/ipc_sync_message.h" |
| 18 | 17 |
| 19 #if defined(OS_POSIX) | 18 #if defined(OS_POSIX) |
| 20 #include "base/files/file_util.h" | 19 #include "base/files/file_util.h" |
| 21 #include "ipc/ipc_channel_posix.h" | 20 #include "ipc/ipc_channel_posix.h" |
| 22 #endif | 21 #endif |
| 23 | 22 |
| 24 namespace content { | 23 namespace content { |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 117 ++iter) { | 116 ++iter) { |
| 118 iter->second->Send(new IPC::Message(*message)); | 117 iter->second->Send(new IPC::Message(*message)); |
| 119 } | 118 } |
| 120 delete message; | 119 delete message; |
| 121 } | 120 } |
| 122 | 121 |
| 123 NPChannelBase::NPChannelBase() | 122 NPChannelBase::NPChannelBase() |
| 124 : mode_(IPC::Channel::MODE_NONE), | 123 : mode_(IPC::Channel::MODE_NONE), |
| 125 non_npobject_count_(0), | 124 non_npobject_count_(0), |
| 126 peer_pid_(0), | 125 peer_pid_(0), |
| 127 in_remove_route_(false), | |
| 128 default_owner_(NULL), | |
| 129 channel_valid_(false), | 126 channel_valid_(false), |
| 130 in_unblock_dispatch_(0), | 127 in_unblock_dispatch_(0), |
| 131 send_unblocking_only_during_unblock_dispatch_(false) { | 128 send_unblocking_only_during_unblock_dispatch_(false) { |
| 132 } | 129 } |
| 133 | 130 |
| 134 NPChannelBase::~NPChannelBase() { | 131 NPChannelBase::~NPChannelBase() { |
| 135 // TODO(wez): Establish why these would ever be non-empty at teardown. | |
| 136 //DCHECK(npobject_listeners_.empty()); | |
| 137 //DCHECK(proxy_map_.empty()); | |
| 138 //DCHECK(stub_map_.empty()); | |
| 139 DCHECK(owner_to_route_.empty()); | |
| 140 DCHECK(route_to_owner_.empty()); | |
| 141 } | 132 } |
| 142 | 133 |
| 143 NPChannelBase* NPChannelBase::GetCurrentChannel() { | 134 NPChannelBase* NPChannelBase::GetCurrentChannel() { |
| 144 return GetChannelGlobals()->current_channel.get(); | 135 return GetChannelGlobals()->current_channel.get(); |
| 145 } | 136 } |
| 146 | 137 |
| 147 void NPChannelBase::CleanupChannels() { | 138 void NPChannelBase::CleanupChannels() { |
| 148 // Make a copy of the references as we can't iterate the map since items will | 139 // Make a copy of the references as we can't iterate the map since items will |
| 149 // be removed from it as we clean them up. | 140 // be removed from it as we clean them up. |
| 150 std::vector<scoped_refptr<NPChannelBase> > channels; | 141 std::vector<scoped_refptr<NPChannelBase> > channels; |
| 151 for (ChannelMap::const_iterator iter = GetChannelMap()->begin(); | 142 for (ChannelMap::const_iterator iter = GetChannelMap()->begin(); |
| 152 iter != GetChannelMap()->end(); | 143 iter != GetChannelMap()->end(); |
| 153 ++iter) { | 144 ++iter) { |
| 154 channels.push_back(iter->second); | 145 channels.push_back(iter->second); |
| 155 } | 146 } |
| 156 | 147 |
| 157 for (size_t i = 0; i < channels.size(); ++i) | 148 for (size_t i = 0; i < channels.size(); ++i) |
| 158 channels[i]->CleanUp(); | 149 channels[i]->CleanUp(); |
| 159 | 150 |
| 160 // This will clean up channels added to the map for which subsequent | 151 // This will clean up channels added to the map for which subsequent |
| 161 // AddRoute wasn't called | 152 // AddRoute wasn't called |
| 162 GetChannelMap()->clear(); | 153 GetChannelMap()->clear(); |
| 163 } | 154 } |
| 164 | 155 |
| 165 NPObjectBase* NPChannelBase::GetNPObjectListenerForRoute(int route_id) { | |
| 166 ListenerMap::iterator iter = npobject_listeners_.find(route_id); | |
| 167 if (iter == npobject_listeners_.end()) { | |
| 168 DLOG(WARNING) << "Invalid route id passed in:" << route_id; | |
| 169 return NULL; | |
| 170 } | |
| 171 return iter->second; | |
| 172 } | |
| 173 | |
| 174 base::WaitableEvent* NPChannelBase::GetModalDialogEvent(int render_view_id) { | 156 base::WaitableEvent* NPChannelBase::GetModalDialogEvent(int render_view_id) { |
| 175 return NULL; | 157 return NULL; |
| 176 } | 158 } |
| 177 | 159 |
| 178 bool NPChannelBase::Init(base::SingleThreadTaskRunner* ipc_task_runner, | 160 bool NPChannelBase::Init(base::SingleThreadTaskRunner* ipc_task_runner, |
| 179 bool create_pipe_now, | 161 bool create_pipe_now, |
| 180 base::WaitableEvent* shutdown_event) { | 162 base::WaitableEvent* shutdown_event) { |
| 181 #if defined(OS_POSIX) | 163 #if defined(OS_POSIX) |
| 182 // Attempting to initialize with an invalid channel handle. | 164 // Attempting to initialize with an invalid channel handle. |
| 183 // See http://crbug.com/97285 for details. | 165 // See http://crbug.com/97285 for details. |
| (...skipping 25 matching lines...) Expand all Loading... |
| 209 | 191 |
| 210 if (send_unblocking_only_during_unblock_dispatch_ && | 192 if (send_unblocking_only_during_unblock_dispatch_ && |
| 211 in_unblock_dispatch_ == 0 && | 193 in_unblock_dispatch_ == 0 && |
| 212 message->is_sync()) { | 194 message->is_sync()) { |
| 213 message->set_unblock(false); | 195 message->set_unblock(false); |
| 214 } | 196 } |
| 215 | 197 |
| 216 return channel_->Send(message); | 198 return channel_->Send(message); |
| 217 } | 199 } |
| 218 | 200 |
| 219 int NPChannelBase::Count() { | |
| 220 return static_cast<int>(GetChannelMap()->size()); | |
| 221 } | |
| 222 | |
| 223 bool NPChannelBase::OnMessageReceived(const IPC::Message& message) { | 201 bool NPChannelBase::OnMessageReceived(const IPC::Message& message) { |
| 224 // Push this channel as the current channel being processed. This also forms | 202 // Push this channel as the current channel being processed. This also forms |
| 225 // a stack of scoped_refptr avoiding ourselves (or any instance higher | 203 // a stack of scoped_refptr avoiding ourselves (or any instance higher |
| 226 // up the callstack) from being deleted while processing a message. | 204 // up the callstack) from being deleted while processing a message. |
| 227 base::AutoReset<scoped_refptr<NPChannelBase> > keep_alive( | 205 base::AutoReset<scoped_refptr<NPChannelBase> > keep_alive( |
| 228 &GetChannelGlobals()->current_channel, this); | 206 &GetChannelGlobals()->current_channel, this); |
| 229 | 207 |
| 230 bool handled; | 208 bool handled; |
| 231 if (message.should_unblock()) | 209 if (message.should_unblock()) |
| 232 in_unblock_dispatch_++; | 210 in_unblock_dispatch_++; |
| (...skipping 12 matching lines...) Expand all Loading... |
| 245 if (message.should_unblock()) | 223 if (message.should_unblock()) |
| 246 in_unblock_dispatch_--; | 224 in_unblock_dispatch_--; |
| 247 | 225 |
| 248 return handled; | 226 return handled; |
| 249 } | 227 } |
| 250 | 228 |
| 251 void NPChannelBase::OnChannelConnected(int32_t peer_pid) { | 229 void NPChannelBase::OnChannelConnected(int32_t peer_pid) { |
| 252 peer_pid_ = peer_pid; | 230 peer_pid_ = peer_pid; |
| 253 } | 231 } |
| 254 | 232 |
| 255 void NPChannelBase::AddRoute(int route_id, | 233 void NPChannelBase::AddRoute(int route_id, IPC::Listener* listener) { |
| 256 IPC::Listener* listener, | 234 non_npobject_count_++; |
| 257 NPObjectBase* npobject) { | |
| 258 if (npobject) { | |
| 259 npobject_listeners_[route_id] = npobject; | |
| 260 } else { | |
| 261 non_npobject_count_++; | |
| 262 } | |
| 263 | |
| 264 router_.AddRoute(route_id, listener); | 235 router_.AddRoute(route_id, listener); |
| 265 } | 236 } |
| 266 | 237 |
| 267 void NPChannelBase::RemoveRoute(int route_id) { | 238 void NPChannelBase::RemoveRoute(int route_id) { |
| 268 router_.RemoveRoute(route_id); | 239 router_.RemoveRoute(route_id); |
| 269 | 240 |
| 270 ListenerMap::iterator iter = npobject_listeners_.find(route_id); | |
| 271 if (iter != npobject_listeners_.end()) { | |
| 272 // This was an NPObject proxy or stub, it's not involved in the refcounting. | |
| 273 | |
| 274 // If this RemoveRoute call from the NPObject is a result of us calling | |
| 275 // OnChannelError below, don't call erase() here because that'll corrupt | |
| 276 // the iterator below. | |
| 277 if (in_remove_route_) { | |
| 278 iter->second = NULL; | |
| 279 } else { | |
| 280 npobject_listeners_.erase(iter); | |
| 281 } | |
| 282 | |
| 283 return; | |
| 284 } | |
| 285 | |
| 286 non_npobject_count_--; | 241 non_npobject_count_--; |
| 287 DCHECK(non_npobject_count_ >= 0); | 242 DCHECK(non_npobject_count_ >= 0); |
| 288 | 243 |
| 289 if (!non_npobject_count_) { | 244 if (!non_npobject_count_) { |
| 290 base::AutoReset<bool> auto_reset_in_remove_route(&in_remove_route_, true); | |
| 291 for (ListenerMap::iterator npobj_iter = npobject_listeners_.begin(); | |
| 292 npobj_iter != npobject_listeners_.end(); ++npobj_iter) { | |
| 293 if (npobj_iter->second) { | |
| 294 npobj_iter->second->GetChannelListener()->OnChannelError(); | |
| 295 } | |
| 296 } | |
| 297 | |
| 298 for (ChannelMap::iterator iter = GetChannelMap()->begin(); | 245 for (ChannelMap::iterator iter = GetChannelMap()->begin(); |
| 299 iter != GetChannelMap()->end(); ++iter) { | 246 iter != GetChannelMap()->end(); ++iter) { |
| 300 if (iter->second.get() == this) { | 247 if (iter->second.get() == this) { |
| 301 GetChannelMap()->erase(iter); | 248 GetChannelMap()->erase(iter); |
| 302 return; | 249 return; |
| 303 } | 250 } |
| 304 } | 251 } |
| 305 | 252 |
| 306 NOTREACHED(); | 253 NOTREACHED(); |
| 307 } | 254 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 324 iter != GetChannelMap()->end(); ++iter) { | 271 iter != GetChannelMap()->end(); ++iter) { |
| 325 if (iter->second.get() == this) { | 272 if (iter->second.get() == this) { |
| 326 // Insert new element before invalidating |iter|. | 273 // Insert new element before invalidating |iter|. |
| 327 (*GetChannelMap())[iter->first + "-error"] = iter->second; | 274 (*GetChannelMap())[iter->first + "-error"] = iter->second; |
| 328 GetChannelMap()->erase(iter); | 275 GetChannelMap()->erase(iter); |
| 329 break; | 276 break; |
| 330 } | 277 } |
| 331 } | 278 } |
| 332 } | 279 } |
| 333 | 280 |
| 334 void NPChannelBase::AddMappingForNPObjectProxy(int route_id, | |
| 335 NPObject* object) { | |
| 336 proxy_map_[route_id] = object; | |
| 337 } | |
| 338 | |
| 339 void NPChannelBase::RemoveMappingForNPObjectProxy(int route_id) { | |
| 340 proxy_map_.erase(route_id); | |
| 341 } | |
| 342 | |
| 343 void NPChannelBase::AddMappingForNPObjectStub(int route_id, | |
| 344 NPObject* object) { | |
| 345 DCHECK(object != NULL); | |
| 346 stub_map_[object] = route_id; | |
| 347 } | |
| 348 | |
| 349 void NPChannelBase::RemoveMappingForNPObjectStub(int route_id, | |
| 350 NPObject* object) { | |
| 351 DCHECK(object != NULL); | |
| 352 stub_map_.erase(object); | |
| 353 } | |
| 354 | |
| 355 void NPChannelBase::AddMappingForNPObjectOwner(int route_id, | |
| 356 struct _NPP* owner) { | |
| 357 DCHECK(owner != NULL); | |
| 358 route_to_owner_[route_id] = owner; | |
| 359 owner_to_route_[owner] = route_id; | |
| 360 } | |
| 361 | |
| 362 void NPChannelBase::SetDefaultNPObjectOwner(struct _NPP* owner) { | |
| 363 DCHECK(owner != NULL); | |
| 364 default_owner_ = owner; | |
| 365 } | |
| 366 | |
| 367 void NPChannelBase::RemoveMappingForNPObjectOwner(int route_id) { | |
| 368 DCHECK(route_to_owner_.find(route_id) != route_to_owner_.end()); | |
| 369 owner_to_route_.erase(route_to_owner_[route_id]); | |
| 370 route_to_owner_.erase(route_id); | |
| 371 } | |
| 372 | |
| 373 NPObject* NPChannelBase::GetExistingNPObjectProxy(int route_id) { | |
| 374 ProxyMap::iterator iter = proxy_map_.find(route_id); | |
| 375 return iter != proxy_map_.end() ? iter->second : NULL; | |
| 376 } | |
| 377 | |
| 378 int NPChannelBase::GetExistingRouteForNPObjectStub(NPObject* npobject) { | |
| 379 StubMap::iterator iter = stub_map_.find(npobject); | |
| 380 return iter != stub_map_.end() ? iter->second : MSG_ROUTING_NONE; | |
| 381 } | |
| 382 | |
| 383 NPP NPChannelBase::GetExistingNPObjectOwner(int route_id) { | |
| 384 RouteToOwnerMap::iterator iter = route_to_owner_.find(route_id); | |
| 385 return iter != route_to_owner_.end() ? iter->second : default_owner_; | |
| 386 } | |
| 387 | |
| 388 int NPChannelBase::GetExistingRouteForNPObjectOwner(NPP owner) { | |
| 389 OwnerToRouteMap::iterator iter = owner_to_route_.find(owner); | |
| 390 return iter != owner_to_route_.end() ? iter->second : MSG_ROUTING_NONE; | |
| 391 } | |
| 392 | |
| 393 } // namespace content | 281 } // namespace content |
| OLD | NEW |