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 |