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

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

Issue 1851093005: Remove content/child/npapi (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@remove_combined_01_02
Patch Set: rebase Created 4 years, 8 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
« no previous file with comments | « content/child/npapi/np_channel_base.h ('k') | content/child/npapi/plugin_host.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/npapi/np_channel_base.h"
6
7 #include <stddef.h>
8
9 #include "base/auto_reset.h"
10 #include "base/containers/hash_tables.h"
11 #include "base/files/scoped_file.h"
12 #include "base/lazy_instance.h"
13 #include "base/single_thread_task_runner.h"
14 #include "base/threading/thread_local.h"
15 #include "build/build_config.h"
16 #include "ipc/ipc_sync_message.h"
17
18 #if defined(OS_POSIX)
19 #include "base/files/file_util.h"
20 #include "ipc/ipc_channel_posix.h"
21 #endif
22
23 namespace content {
24
25 namespace {
26
27 typedef base::hash_map<std::string, scoped_refptr<NPChannelBase> > ChannelMap;
28
29 struct ChannelGlobals {
30 ChannelMap channel_map;
31 scoped_refptr<NPChannelBase> current_channel;
32 };
33
34 #if defined(OS_ANDROID)
35 // Workaround for http://crbug.com/298179 - NPChannelBase is only intended
36 // for use on one thread per process. Using TLS to store the globals removes the
37 // worst thread hostility in this class, especially needed for webview which
38 // runs in single-process mode. TODO(joth): Make a complete fix, most likely
39 // as part of addressing http://crbug.com/258510.
40 base::LazyInstance<base::ThreadLocalPointer<ChannelGlobals> >::Leaky
41 g_channels_tls_ptr = LAZY_INSTANCE_INITIALIZER;
42
43 ChannelGlobals* GetChannelGlobals() {
44 ChannelGlobals* globals = g_channels_tls_ptr.Get().Get();
45 if (!globals) {
46 globals = new ChannelGlobals;
47 g_channels_tls_ptr.Get().Set(globals);
48 }
49 return globals;
50 }
51
52 #else
53
54 base::LazyInstance<ChannelGlobals>::Leaky g_channels_globals =
55 LAZY_INSTANCE_INITIALIZER;
56
57 ChannelGlobals* GetChannelGlobals() { return g_channels_globals.Pointer(); }
58
59 #endif // OS_ANDROID
60
61 ChannelMap* GetChannelMap() {
62 return &GetChannelGlobals()->channel_map;
63 }
64
65 } // namespace
66
67 NPChannelBase* NPChannelBase::GetChannel(
68 const IPC::ChannelHandle& channel_handle,
69 IPC::Channel::Mode mode,
70 ChannelFactory factory,
71 base::SingleThreadTaskRunner* ipc_task_runner,
72 bool create_pipe_now,
73 base::WaitableEvent* shutdown_event) {
74 #if defined(OS_POSIX)
75 // On POSIX the channel_handle conveys an FD (socket) which is duped by the
76 // kernel during the IPC message exchange (via the SCM_RIGHTS mechanism).
77 // Ensure we do not leak this FD.
78 base::ScopedFD fd(channel_handle.socket.auto_close ?
79 channel_handle.socket.fd : -1);
80 #endif
81
82 scoped_refptr<NPChannelBase> channel;
83 std::string channel_key = channel_handle.name;
84 ChannelMap::const_iterator iter = GetChannelMap()->find(channel_key);
85 if (iter == GetChannelMap()->end()) {
86 channel = factory();
87 } else {
88 channel = iter->second;
89 }
90
91 DCHECK(channel.get() != NULL);
92
93 if (!channel->channel_valid()) {
94 channel->channel_handle_ = channel_handle;
95 #if defined(OS_POSIX)
96 ignore_result(fd.release());
97 #endif
98 if (mode & IPC::Channel::MODE_SERVER_FLAG) {
99 channel->channel_handle_.name =
100 IPC::Channel::GenerateVerifiedChannelID(channel_key);
101 }
102 channel->mode_ = mode;
103 if (channel->Init(ipc_task_runner, create_pipe_now, shutdown_event)) {
104 (*GetChannelMap())[channel_key] = channel;
105 } else {
106 channel = NULL;
107 }
108 }
109
110 return channel.get();
111 }
112
113 void NPChannelBase::Broadcast(IPC::Message* message) {
114 for (ChannelMap::iterator iter = GetChannelMap()->begin();
115 iter != GetChannelMap()->end();
116 ++iter) {
117 iter->second->Send(new IPC::Message(*message));
118 }
119 delete message;
120 }
121
122 NPChannelBase::NPChannelBase()
123 : mode_(IPC::Channel::MODE_NONE),
124 non_npobject_count_(0),
125 peer_pid_(0),
126 channel_valid_(false),
127 in_unblock_dispatch_(0),
128 send_unblocking_only_during_unblock_dispatch_(false) {
129 }
130
131 NPChannelBase::~NPChannelBase() {
132 }
133
134 NPChannelBase* NPChannelBase::GetCurrentChannel() {
135 return GetChannelGlobals()->current_channel.get();
136 }
137
138 void NPChannelBase::CleanupChannels() {
139 // Make a copy of the references as we can't iterate the map since items will
140 // be removed from it as we clean them up.
141 std::vector<scoped_refptr<NPChannelBase> > channels;
142 for (ChannelMap::const_iterator iter = GetChannelMap()->begin();
143 iter != GetChannelMap()->end();
144 ++iter) {
145 channels.push_back(iter->second);
146 }
147
148 for (size_t i = 0; i < channels.size(); ++i)
149 channels[i]->CleanUp();
150
151 // This will clean up channels added to the map for which subsequent
152 // AddRoute wasn't called
153 GetChannelMap()->clear();
154 }
155
156 base::WaitableEvent* NPChannelBase::GetModalDialogEvent(int render_view_id) {
157 return NULL;
158 }
159
160 bool NPChannelBase::Init(base::SingleThreadTaskRunner* ipc_task_runner,
161 bool create_pipe_now,
162 base::WaitableEvent* shutdown_event) {
163 #if defined(OS_POSIX)
164 // Attempting to initialize with an invalid channel handle.
165 // See http://crbug.com/97285 for details.
166 if (mode_ == IPC::Channel::MODE_CLIENT && -1 == channel_handle_.socket.fd)
167 return false;
168 #endif
169
170 channel_ =
171 IPC::SyncChannel::Create(channel_handle_, mode_, this, ipc_task_runner,
172 create_pipe_now, shutdown_event);
173
174 #if defined(OS_POSIX)
175 // Check the validity of fd for bug investigation. Remove after fixed.
176 // See crbug.com/97285 for details.
177 if (mode_ == IPC::Channel::MODE_SERVER)
178 CHECK_NE(-1, channel_->GetClientFileDescriptor());
179 #endif
180
181 channel_valid_ = true;
182 return true;
183 }
184
185 bool NPChannelBase::Send(IPC::Message* message) {
186 if (!channel_) {
187 VLOG(1) << "Channel is NULL; dropping message";
188 delete message;
189 return false;
190 }
191
192 if (send_unblocking_only_during_unblock_dispatch_ &&
193 in_unblock_dispatch_ == 0 &&
194 message->is_sync()) {
195 message->set_unblock(false);
196 }
197
198 return channel_->Send(message);
199 }
200
201 bool NPChannelBase::OnMessageReceived(const IPC::Message& message) {
202 // Push this channel as the current channel being processed. This also forms
203 // a stack of scoped_refptr avoiding ourselves (or any instance higher
204 // up the callstack) from being deleted while processing a message.
205 base::AutoReset<scoped_refptr<NPChannelBase> > keep_alive(
206 &GetChannelGlobals()->current_channel, this);
207
208 bool handled;
209 if (message.should_unblock())
210 in_unblock_dispatch_++;
211 if (message.routing_id() == MSG_ROUTING_CONTROL) {
212 handled = OnControlMessageReceived(message);
213 } else {
214 handled = router_.RouteMessage(message);
215 if (!handled && message.is_sync()) {
216 // The listener has gone away, so we must respond or else the caller will
217 // hang waiting for a reply.
218 IPC::Message* reply = IPC::SyncMessage::GenerateReply(&message);
219 reply->set_reply_error();
220 Send(reply);
221 }
222 }
223 if (message.should_unblock())
224 in_unblock_dispatch_--;
225
226 return handled;
227 }
228
229 void NPChannelBase::OnChannelConnected(int32_t peer_pid) {
230 peer_pid_ = peer_pid;
231 }
232
233 void NPChannelBase::AddRoute(int route_id, IPC::Listener* listener) {
234 non_npobject_count_++;
235 router_.AddRoute(route_id, listener);
236 }
237
238 void NPChannelBase::RemoveRoute(int route_id) {
239 router_.RemoveRoute(route_id);
240
241 non_npobject_count_--;
242 DCHECK(non_npobject_count_ >= 0);
243
244 if (!non_npobject_count_) {
245 for (ChannelMap::iterator iter = GetChannelMap()->begin();
246 iter != GetChannelMap()->end(); ++iter) {
247 if (iter->second.get() == this) {
248 GetChannelMap()->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 = GetChannelMap()->begin();
271 iter != GetChannelMap()->end(); ++iter) {
272 if (iter->second.get() == this) {
273 // Insert new element before invalidating |iter|.
274 (*GetChannelMap())[iter->first + "-error"] = iter->second;
275 GetChannelMap()->erase(iter);
276 break;
277 }
278 }
279 }
280
281 } // namespace content
OLDNEW
« no previous file with comments | « content/child/npapi/np_channel_base.h ('k') | content/child/npapi/plugin_host.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698