Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(62)

Side by Side Diff: content/child/np_channel_base.cc

Issue 19462016: Move npapi related files from content\child to the new content\child\npapi directory. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « content/child/np_channel_base.h ('k') | content/child/npapi/np_channel_base.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "content/child/np_channel_base.h"
6
7 #include <stack>
8
9 #include "base/auto_reset.h"
10 #include "base/containers/hash_tables.h"
11 #include "base/lazy_instance.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "ipc/ipc_sync_message.h"
14
15 #if defined(OS_POSIX)
16 #include "ipc/ipc_channel_posix.h"
17 #endif
18
19 namespace content {
20
21 typedef base::hash_map<std::string, scoped_refptr<NPChannelBase> > ChannelMap;
22 static base::LazyInstance<ChannelMap>::Leaky
23 g_channels = LAZY_INSTANCE_INITIALIZER;
24
25 typedef std::stack<scoped_refptr<NPChannelBase> > NPChannelRefStack;
26 static base::LazyInstance<NPChannelRefStack>::Leaky
27 g_lazy_channel_stack = LAZY_INSTANCE_INITIALIZER;
28
29 NPChannelBase* NPChannelBase::GetChannel(
30 const IPC::ChannelHandle& channel_handle, IPC::Channel::Mode mode,
31 ChannelFactory factory, base::MessageLoopProxy* ipc_message_loop,
32 bool create_pipe_now, base::WaitableEvent* shutdown_event) {
33 scoped_refptr<NPChannelBase> channel;
34 std::string channel_key = channel_handle.name;
35 ChannelMap::const_iterator iter = g_channels.Get().find(channel_key);
36 if (iter == g_channels.Get().end()) {
37 channel = factory();
38 } else {
39 channel = iter->second;
40 }
41
42 DCHECK(channel.get() != NULL);
43
44 if (!channel->channel_valid()) {
45 channel->channel_handle_ = channel_handle;
46 if (mode & IPC::Channel::MODE_SERVER_FLAG) {
47 channel->channel_handle_.name =
48 IPC::Channel::GenerateVerifiedChannelID(channel_key);
49 }
50 channel->mode_ = mode;
51 if (channel->Init(ipc_message_loop, create_pipe_now, shutdown_event)) {
52 g_channels.Get()[channel_key] = channel;
53 } else {
54 channel = NULL;
55 }
56 }
57
58 return channel.get();
59 }
60
61 void NPChannelBase::Broadcast(IPC::Message* message) {
62 for (ChannelMap::iterator iter = g_channels.Get().begin();
63 iter != g_channels.Get().end();
64 ++iter) {
65 iter->second->Send(new IPC::Message(*message));
66 }
67 delete message;
68 }
69
70 NPChannelBase::NPChannelBase()
71 : mode_(IPC::Channel::MODE_NONE),
72 non_npobject_count_(0),
73 peer_pid_(0),
74 in_remove_route_(false),
75 default_owner_(NULL),
76 channel_valid_(false),
77 in_unblock_dispatch_(0),
78 send_unblocking_only_during_unblock_dispatch_(false) {
79 }
80
81 NPChannelBase::~NPChannelBase() {
82 // TODO(wez): Establish why these would ever be non-empty at teardown.
83 //DCHECK(npobject_listeners_.empty());
84 //DCHECK(proxy_map_.empty());
85 //DCHECK(stub_map_.empty());
86 DCHECK(owner_to_route_.empty());
87 DCHECK(route_to_owner_.empty());
88 }
89
90 NPChannelBase* NPChannelBase::GetCurrentChannel() {
91 return g_lazy_channel_stack.Pointer()->top().get();
92 }
93
94 void NPChannelBase::CleanupChannels() {
95 // Make a copy of the references as we can't iterate the map since items will
96 // be removed from it as we clean them up.
97 std::vector<scoped_refptr<NPChannelBase> > channels;
98 for (ChannelMap::const_iterator iter = g_channels.Get().begin();
99 iter != g_channels.Get().end();
100 ++iter) {
101 channels.push_back(iter->second);
102 }
103
104 for (size_t i = 0; i < channels.size(); ++i)
105 channels[i]->CleanUp();
106
107 // This will clean up channels added to the map for which subsequent
108 // AddRoute wasn't called
109 g_channels.Get().clear();
110 }
111
112 NPObjectBase* NPChannelBase::GetNPObjectListenerForRoute(int route_id) {
113 ListenerMap::iterator iter = npobject_listeners_.find(route_id);
114 if (iter == npobject_listeners_.end()) {
115 DLOG(WARNING) << "Invalid route id passed in:" << route_id;
116 return NULL;
117 }
118 return iter->second;
119 }
120
121 base::WaitableEvent* NPChannelBase::GetModalDialogEvent(int render_view_id) {
122 return NULL;
123 }
124
125 bool NPChannelBase::Init(base::MessageLoopProxy* ipc_message_loop,
126 bool create_pipe_now,
127 base::WaitableEvent* shutdown_event) {
128 #if defined(OS_POSIX)
129 // Attempting to initialize with an invalid channel handle.
130 // See http://crbug.com/97285 for details.
131 if (mode_ == IPC::Channel::MODE_CLIENT && -1 == channel_handle_.socket.fd)
132 return false;
133 #endif
134
135 channel_.reset(new IPC::SyncChannel(
136 channel_handle_, mode_, this, ipc_message_loop, create_pipe_now,
137 shutdown_event));
138
139 #if defined(OS_POSIX)
140 // Check the validity of fd for bug investigation. Remove after fixed.
141 // See crbug.com/97285 for details.
142 if (mode_ == IPC::Channel::MODE_SERVER)
143 CHECK_NE(-1, channel_->GetClientFileDescriptor());
144 #endif
145
146 channel_valid_ = true;
147 return true;
148 }
149
150 bool NPChannelBase::Send(IPC::Message* message) {
151 if (!channel_) {
152 VLOG(1) << "Channel is NULL; dropping message";
153 delete message;
154 return false;
155 }
156
157 if (send_unblocking_only_during_unblock_dispatch_ &&
158 in_unblock_dispatch_ == 0 &&
159 message->is_sync()) {
160 message->set_unblock(false);
161 }
162
163 return channel_->Send(message);
164 }
165
166 int NPChannelBase::Count() {
167 return static_cast<int>(g_channels.Get().size());
168 }
169
170 bool NPChannelBase::OnMessageReceived(const IPC::Message& message) {
171 // This call might cause us to be deleted, so keep an extra reference to
172 // ourself so that we can send the reply and decrement back in_dispatch_.
173 g_lazy_channel_stack.Pointer()->push(
174 scoped_refptr<NPChannelBase>(this));
175
176 bool handled;
177 if (message.should_unblock())
178 in_unblock_dispatch_++;
179 if (message.routing_id() == MSG_ROUTING_CONTROL) {
180 handled = OnControlMessageReceived(message);
181 } else {
182 handled = router_.RouteMessage(message);
183 if (!handled && message.is_sync()) {
184 // The listener has gone away, so we must respond or else the caller will
185 // hang waiting for a reply.
186 IPC::Message* reply = IPC::SyncMessage::GenerateReply(&message);
187 reply->set_reply_error();
188 Send(reply);
189 }
190 }
191 if (message.should_unblock())
192 in_unblock_dispatch_--;
193
194 g_lazy_channel_stack.Pointer()->pop();
195 return handled;
196 }
197
198 void NPChannelBase::OnChannelConnected(int32 peer_pid) {
199 peer_pid_ = peer_pid;
200 }
201
202 void NPChannelBase::AddRoute(int route_id,
203 IPC::Listener* listener,
204 NPObjectBase* npobject) {
205 if (npobject) {
206 npobject_listeners_[route_id] = npobject;
207 } else {
208 non_npobject_count_++;
209 }
210
211 router_.AddRoute(route_id, listener);
212 }
213
214 void NPChannelBase::RemoveRoute(int route_id) {
215 router_.RemoveRoute(route_id);
216
217 ListenerMap::iterator iter = npobject_listeners_.find(route_id);
218 if (iter != npobject_listeners_.end()) {
219 // This was an NPObject proxy or stub, it's not involved in the refcounting.
220
221 // If this RemoveRoute call from the NPObject is a result of us calling
222 // OnChannelError below, don't call erase() here because that'll corrupt
223 // the iterator below.
224 if (in_remove_route_) {
225 iter->second = NULL;
226 } else {
227 npobject_listeners_.erase(iter);
228 }
229
230 return;
231 }
232
233 non_npobject_count_--;
234 DCHECK(non_npobject_count_ >= 0);
235
236 if (!non_npobject_count_) {
237 base::AutoReset<bool> auto_reset_in_remove_route(&in_remove_route_, true);
238 for (ListenerMap::iterator npobj_iter = npobject_listeners_.begin();
239 npobj_iter != npobject_listeners_.end(); ++npobj_iter) {
240 if (npobj_iter->second) {
241 npobj_iter->second->GetChannelListener()->OnChannelError();
242 }
243 }
244
245 for (ChannelMap::iterator iter = g_channels.Get().begin();
246 iter != g_channels.Get().end(); ++iter) {
247 if (iter->second.get() == this) {
248 g_channels.Get().erase(iter);
249 return;
250 }
251 }
252
253 NOTREACHED();
254 }
255 }
256
257 bool NPChannelBase::OnControlMessageReceived(const IPC::Message& msg) {
258 NOTREACHED() <<
259 "should override in subclass if you care about control messages";
260 return false;
261 }
262
263 void NPChannelBase::OnChannelError() {
264 channel_valid_ = false;
265
266 // TODO(shess): http://crbug.com/97285
267 // Once an error is seen on a channel, remap the channel to prevent
268 // it from being vended again. Keep the channel in the map so
269 // RemoveRoute() can clean things up correctly.
270 for (ChannelMap::iterator iter = g_channels.Get().begin();
271 iter != g_channels.Get().end(); ++iter) {
272 if (iter->second.get() == this) {
273 // Insert new element before invalidating |iter|.
274 g_channels.Get()[iter->first + "-error"] = iter->second;
275 g_channels.Get().erase(iter);
276 break;
277 }
278 }
279 }
280
281 void NPChannelBase::AddMappingForNPObjectProxy(int route_id,
282 NPObject* object) {
283 proxy_map_[route_id] = object;
284 }
285
286 void NPChannelBase::RemoveMappingForNPObjectProxy(int route_id) {
287 proxy_map_.erase(route_id);
288 }
289
290 void NPChannelBase::AddMappingForNPObjectStub(int route_id,
291 NPObject* object) {
292 DCHECK(object != NULL);
293 stub_map_[object] = route_id;
294 }
295
296 void NPChannelBase::RemoveMappingForNPObjectStub(int route_id,
297 NPObject* object) {
298 DCHECK(object != NULL);
299 stub_map_.erase(object);
300 }
301
302 void NPChannelBase::AddMappingForNPObjectOwner(int route_id,
303 struct _NPP* owner) {
304 DCHECK(owner != NULL);
305 route_to_owner_[route_id] = owner;
306 owner_to_route_[owner] = route_id;
307 }
308
309 void NPChannelBase::SetDefaultNPObjectOwner(struct _NPP* owner) {
310 DCHECK(owner != NULL);
311 default_owner_ = owner;
312 }
313
314 void NPChannelBase::RemoveMappingForNPObjectOwner(int route_id) {
315 DCHECK(route_to_owner_.find(route_id) != route_to_owner_.end());
316 owner_to_route_.erase(route_to_owner_[route_id]);
317 route_to_owner_.erase(route_id);
318 }
319
320 NPObject* NPChannelBase::GetExistingNPObjectProxy(int route_id) {
321 ProxyMap::iterator iter = proxy_map_.find(route_id);
322 return iter != proxy_map_.end() ? iter->second : NULL;
323 }
324
325 int NPChannelBase::GetExistingRouteForNPObjectStub(NPObject* npobject) {
326 StubMap::iterator iter = stub_map_.find(npobject);
327 return iter != stub_map_.end() ? iter->second : MSG_ROUTING_NONE;
328 }
329
330 NPP NPChannelBase::GetExistingNPObjectOwner(int route_id) {
331 RouteToOwnerMap::iterator iter = route_to_owner_.find(route_id);
332 return iter != route_to_owner_.end() ? iter->second : default_owner_;
333 }
334
335 int NPChannelBase::GetExistingRouteForNPObjectOwner(NPP owner) {
336 OwnerToRouteMap::iterator iter = owner_to_route_.find(owner);
337 return iter != owner_to_route_.end() ? iter->second : MSG_ROUTING_NONE;
338 }
339
340 } // namespace content
OLDNEW
« no previous file with comments | « content/child/np_channel_base.h ('k') | content/child/npapi/np_channel_base.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698