| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/np_channel_base.h" | 5 #include "content/common/np_channel_base.h" |
| 6 | 6 |
| 7 #include <stack> | 7 #include <stack> |
| 8 | 8 |
| 9 #include "base/auto_reset.h" | 9 #include "base/auto_reset.h" |
| 10 #include "base/hash_tables.h" | 10 #include "base/hash_tables.h" |
| 11 #include "base/lazy_instance.h" | 11 #include "base/lazy_instance.h" |
| 12 #include "base/string_number_conversions.h" | 12 #include "base/string_number_conversions.h" |
| 13 #include "ipc/ipc_sync_message.h" | 13 #include "ipc/ipc_sync_message.h" |
| 14 | 14 |
| 15 #if defined(OS_POSIX) | 15 #if defined(OS_POSIX) |
| 16 #include "ipc/ipc_channel_posix.h" | 16 #include "ipc/ipc_channel_posix.h" |
| 17 #endif | 17 #endif |
| 18 | 18 |
| 19 typedef base::hash_map<std::string, scoped_refptr<NPChannelBase> > ChannelMap; | 19 typedef base::hash_map<std::string, scoped_refptr<NPChannelBase> > ChannelMap; |
| 20 static base::LazyInstance<ChannelMap, |
| 21 base::LeakyLazyInstanceTraits<ChannelMap> > |
| 22 g_channels(base::LINKER_INITIALIZED); |
| 20 | 23 |
| 21 static ChannelMap g_channels_; | 24 typedef std::stack<scoped_refptr<NPChannelBase> > NPChannelRefStack; |
| 22 | 25 static base::LazyInstance<NPChannelRefStack, |
| 23 static base::LazyInstance<std::stack<scoped_refptr<NPChannelBase> > > | 26 base::LeakyLazyInstanceTraits<NPChannelRefStack> > |
| 24 lazy_channel_stack_(base::LINKER_INITIALIZED); | 27 g_lazy_channel_stack(base::LINKER_INITIALIZED); |
| 25 | 28 |
| 26 static int next_pipe_id = 0; | 29 static int next_pipe_id = 0; |
| 27 | 30 |
| 28 NPChannelBase* NPChannelBase::GetChannel( | 31 NPChannelBase* NPChannelBase::GetChannel( |
| 29 const IPC::ChannelHandle& channel_handle, IPC::Channel::Mode mode, | 32 const IPC::ChannelHandle& channel_handle, IPC::Channel::Mode mode, |
| 30 ChannelFactory factory, base::MessageLoopProxy* ipc_message_loop, | 33 ChannelFactory factory, base::MessageLoopProxy* ipc_message_loop, |
| 31 bool create_pipe_now, base::WaitableEvent* shutdown_event) { | 34 bool create_pipe_now, base::WaitableEvent* shutdown_event) { |
| 32 scoped_refptr<NPChannelBase> channel; | 35 scoped_refptr<NPChannelBase> channel; |
| 33 std::string channel_key = channel_handle.name; | 36 std::string channel_key = channel_handle.name; |
| 34 ChannelMap::const_iterator iter = g_channels_.find(channel_key); | 37 ChannelMap::const_iterator iter = g_channels.Get().find(channel_key); |
| 35 if (iter == g_channels_.end()) { | 38 if (iter == g_channels.Get().end()) { |
| 36 channel = factory(); | 39 channel = factory(); |
| 37 } else { | 40 } else { |
| 38 channel = iter->second; | 41 channel = iter->second; |
| 39 } | 42 } |
| 40 | 43 |
| 41 DCHECK(channel != NULL); | 44 DCHECK(channel != NULL); |
| 42 | 45 |
| 43 if (!channel->channel_valid()) { | 46 if (!channel->channel_valid()) { |
| 44 channel->channel_handle_ = channel_handle; | 47 channel->channel_handle_ = channel_handle; |
| 45 if (mode & IPC::Channel::MODE_SERVER_FLAG) { | 48 if (mode & IPC::Channel::MODE_SERVER_FLAG) { |
| 46 channel->channel_handle_.name.append("."); | 49 channel->channel_handle_.name.append("."); |
| 47 channel->channel_handle_.name.append(base::IntToString(next_pipe_id++)); | 50 channel->channel_handle_.name.append(base::IntToString(next_pipe_id++)); |
| 48 } | 51 } |
| 49 channel->mode_ = mode; | 52 channel->mode_ = mode; |
| 50 if (channel->Init(ipc_message_loop, create_pipe_now, shutdown_event)) { | 53 if (channel->Init(ipc_message_loop, create_pipe_now, shutdown_event)) { |
| 51 g_channels_[channel_key] = channel; | 54 g_channels.Get()[channel_key] = channel; |
| 52 } else { | 55 } else { |
| 53 channel = NULL; | 56 channel = NULL; |
| 54 } | 57 } |
| 55 } | 58 } |
| 56 | 59 |
| 57 return channel; | 60 return channel; |
| 58 } | 61 } |
| 59 | 62 |
| 60 void NPChannelBase::Broadcast(IPC::Message* message) { | 63 void NPChannelBase::Broadcast(IPC::Message* message) { |
| 61 for (ChannelMap::iterator iter = g_channels_.begin(); | 64 for (ChannelMap::iterator iter = g_channels.Get().begin(); |
| 62 iter != g_channels_.end(); | 65 iter != g_channels.Get().end(); |
| 63 ++iter) { | 66 ++iter) { |
| 64 iter->second->Send(new IPC::Message(*message)); | 67 iter->second->Send(new IPC::Message(*message)); |
| 65 } | 68 } |
| 66 delete message; | 69 delete message; |
| 67 } | 70 } |
| 68 | 71 |
| 69 NPChannelBase::NPChannelBase() | 72 NPChannelBase::NPChannelBase() |
| 70 : mode_(IPC::Channel::MODE_NONE), | 73 : mode_(IPC::Channel::MODE_NONE), |
| 71 non_npobject_count_(0), | 74 non_npobject_count_(0), |
| 72 peer_pid_(0), | 75 peer_pid_(0), |
| 73 in_remove_route_(false), | 76 in_remove_route_(false), |
| 74 channel_valid_(false), | 77 channel_valid_(false), |
| 75 in_unblock_dispatch_(0), | 78 in_unblock_dispatch_(0), |
| 76 send_unblocking_only_during_unblock_dispatch_(false) { | 79 send_unblocking_only_during_unblock_dispatch_(false) { |
| 77 } | 80 } |
| 78 | 81 |
| 79 NPChannelBase::~NPChannelBase() { | 82 NPChannelBase::~NPChannelBase() { |
| 80 } | 83 } |
| 81 | 84 |
| 82 NPChannelBase* NPChannelBase::GetCurrentChannel() { | 85 NPChannelBase* NPChannelBase::GetCurrentChannel() { |
| 83 return lazy_channel_stack_.Pointer()->top(); | 86 return g_lazy_channel_stack.Pointer()->top(); |
| 84 } | 87 } |
| 85 | 88 |
| 86 void NPChannelBase::CleanupChannels() { | 89 void NPChannelBase::CleanupChannels() { |
| 87 // Make a copy of the references as we can't iterate the map since items will | 90 // Make a copy of the references as we can't iterate the map since items will |
| 88 // be removed from it as we clean them up. | 91 // be removed from it as we clean them up. |
| 89 std::vector<scoped_refptr<NPChannelBase> > channels; | 92 std::vector<scoped_refptr<NPChannelBase> > channels; |
| 90 for (ChannelMap::const_iterator iter = g_channels_.begin(); | 93 for (ChannelMap::const_iterator iter = g_channels.Get().begin(); |
| 91 iter != g_channels_.end(); | 94 iter != g_channels.Get().end(); |
| 92 ++iter) { | 95 ++iter) { |
| 93 channels.push_back(iter->second); | 96 channels.push_back(iter->second); |
| 94 } | 97 } |
| 95 | 98 |
| 96 for (size_t i = 0; i < channels.size(); ++i) | 99 for (size_t i = 0; i < channels.size(); ++i) |
| 97 channels[i]->CleanUp(); | 100 channels[i]->CleanUp(); |
| 98 | 101 |
| 99 // This will clean up channels added to the map for which subsequent | 102 // This will clean up channels added to the map for which subsequent |
| 100 // AddRoute wasn't called | 103 // AddRoute wasn't called |
| 101 g_channels_.clear(); | 104 g_channels.Get().clear(); |
| 102 } | 105 } |
| 103 | 106 |
| 104 NPObjectBase* NPChannelBase::GetNPObjectListenerForRoute(int route_id) { | 107 NPObjectBase* NPChannelBase::GetNPObjectListenerForRoute(int route_id) { |
| 105 ListenerMap::iterator iter = npobject_listeners_.find(route_id); | 108 ListenerMap::iterator iter = npobject_listeners_.find(route_id); |
| 106 if (iter == npobject_listeners_.end()) { | 109 if (iter == npobject_listeners_.end()) { |
| 107 DLOG(WARNING) << "Invalid route id passed in:" << route_id; | 110 DLOG(WARNING) << "Invalid route id passed in:" << route_id; |
| 108 return NULL; | 111 return NULL; |
| 109 } | 112 } |
| 110 return iter->second; | 113 return iter->second; |
| 111 } | 114 } |
| (...skipping 22 matching lines...) Expand all Loading... |
| 134 if (send_unblocking_only_during_unblock_dispatch_ && | 137 if (send_unblocking_only_during_unblock_dispatch_ && |
| 135 in_unblock_dispatch_ == 0 && | 138 in_unblock_dispatch_ == 0 && |
| 136 message->is_sync()) { | 139 message->is_sync()) { |
| 137 message->set_unblock(false); | 140 message->set_unblock(false); |
| 138 } | 141 } |
| 139 | 142 |
| 140 return channel_->Send(message); | 143 return channel_->Send(message); |
| 141 } | 144 } |
| 142 | 145 |
| 143 int NPChannelBase::Count() { | 146 int NPChannelBase::Count() { |
| 144 return static_cast<int>(g_channels_.size()); | 147 return static_cast<int>(g_channels.Get().size()); |
| 145 } | 148 } |
| 146 | 149 |
| 147 bool NPChannelBase::OnMessageReceived(const IPC::Message& message) { | 150 bool NPChannelBase::OnMessageReceived(const IPC::Message& message) { |
| 148 // This call might cause us to be deleted, so keep an extra reference to | 151 // This call might cause us to be deleted, so keep an extra reference to |
| 149 // ourself so that we can send the reply and decrement back in_dispatch_. | 152 // ourself so that we can send the reply and decrement back in_dispatch_. |
| 150 lazy_channel_stack_.Pointer()->push( | 153 g_lazy_channel_stack.Pointer()->push( |
| 151 scoped_refptr<NPChannelBase>(this)); | 154 scoped_refptr<NPChannelBase>(this)); |
| 152 | 155 |
| 153 bool handled; | 156 bool handled; |
| 154 if (message.should_unblock()) | 157 if (message.should_unblock()) |
| 155 in_unblock_dispatch_++; | 158 in_unblock_dispatch_++; |
| 156 if (message.routing_id() == MSG_ROUTING_CONTROL) { | 159 if (message.routing_id() == MSG_ROUTING_CONTROL) { |
| 157 handled = OnControlMessageReceived(message); | 160 handled = OnControlMessageReceived(message); |
| 158 } else { | 161 } else { |
| 159 handled = router_.RouteMessage(message); | 162 handled = router_.RouteMessage(message); |
| 160 if (!handled && message.is_sync()) { | 163 if (!handled && message.is_sync()) { |
| 161 // The listener has gone away, so we must respond or else the caller will | 164 // The listener has gone away, so we must respond or else the caller will |
| 162 // hang waiting for a reply. | 165 // hang waiting for a reply. |
| 163 IPC::Message* reply = IPC::SyncMessage::GenerateReply(&message); | 166 IPC::Message* reply = IPC::SyncMessage::GenerateReply(&message); |
| 164 reply->set_reply_error(); | 167 reply->set_reply_error(); |
| 165 Send(reply); | 168 Send(reply); |
| 166 } | 169 } |
| 167 } | 170 } |
| 168 if (message.should_unblock()) | 171 if (message.should_unblock()) |
| 169 in_unblock_dispatch_--; | 172 in_unblock_dispatch_--; |
| 170 | 173 |
| 171 lazy_channel_stack_.Pointer()->pop(); | 174 g_lazy_channel_stack.Pointer()->pop(); |
| 172 return handled; | 175 return handled; |
| 173 } | 176 } |
| 174 | 177 |
| 175 void NPChannelBase::OnChannelConnected(int32 peer_pid) { | 178 void NPChannelBase::OnChannelConnected(int32 peer_pid) { |
| 176 peer_pid_ = peer_pid; | 179 peer_pid_ = peer_pid; |
| 177 } | 180 } |
| 178 | 181 |
| 179 void NPChannelBase::AddRoute(int route_id, | 182 void NPChannelBase::AddRoute(int route_id, |
| 180 IPC::Channel::Listener* listener, | 183 IPC::Channel::Listener* listener, |
| 181 NPObjectBase* npobject) { | 184 NPObjectBase* npobject) { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 215 for (ListenerMap::iterator npobj_iter = npobject_listeners_.begin(); | 218 for (ListenerMap::iterator npobj_iter = npobject_listeners_.begin(); |
| 216 npobj_iter != npobject_listeners_.end(); ++npobj_iter) { | 219 npobj_iter != npobject_listeners_.end(); ++npobj_iter) { |
| 217 if (npobj_iter->second) { | 220 if (npobj_iter->second) { |
| 218 IPC::Channel::Listener* channel_listener = | 221 IPC::Channel::Listener* channel_listener = |
| 219 npobj_iter->second->GetChannelListener(); | 222 npobj_iter->second->GetChannelListener(); |
| 220 DCHECK(channel_listener != NULL); | 223 DCHECK(channel_listener != NULL); |
| 221 channel_listener->OnChannelError(); | 224 channel_listener->OnChannelError(); |
| 222 } | 225 } |
| 223 } | 226 } |
| 224 | 227 |
| 225 for (ChannelMap::iterator iter = g_channels_.begin(); | 228 for (ChannelMap::iterator iter = g_channels.Get().begin(); |
| 226 iter != g_channels_.end(); ++iter) { | 229 iter != g_channels.Get().end(); ++iter) { |
| 227 if (iter->second == this) { | 230 if (iter->second == this) { |
| 228 g_channels_.erase(iter); | 231 g_channels.Get().erase(iter); |
| 229 return; | 232 return; |
| 230 } | 233 } |
| 231 } | 234 } |
| 232 | 235 |
| 233 NOTREACHED(); | 236 NOTREACHED(); |
| 234 } | 237 } |
| 235 } | 238 } |
| 236 | 239 |
| 237 bool NPChannelBase::OnControlMessageReceived(const IPC::Message& msg) { | 240 bool NPChannelBase::OnControlMessageReceived(const IPC::Message& msg) { |
| 238 NOTREACHED() << | 241 NOTREACHED() << |
| (...skipping 28 matching lines...) Expand all Loading... |
| 267 | 270 |
| 268 void NPChannelBase::RemoveMappingForNPObjectStub(int route_id, | 271 void NPChannelBase::RemoveMappingForNPObjectStub(int route_id, |
| 269 NPObject* object) { | 272 NPObject* object) { |
| 270 DCHECK(object != NULL); | 273 DCHECK(object != NULL); |
| 271 stub_map_.erase(object); | 274 stub_map_.erase(object); |
| 272 } | 275 } |
| 273 | 276 |
| 274 void NPChannelBase::RemoveMappingForNPObjectProxy(int route_id) { | 277 void NPChannelBase::RemoveMappingForNPObjectProxy(int route_id) { |
| 275 proxy_map_.erase(route_id); | 278 proxy_map_.erase(route_id); |
| 276 } | 279 } |
| OLD | NEW |