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

Side by Side Diff: chrome/common/ipc_channel_proxy.cc

Issue 155905: Separates ipc code from common (http://crbug.com/16829) (Closed)
Patch Set: Fixes reference to 'common_message_traits' it's actually 'common_param_traits' Created 11 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
« no previous file with comments | « chrome/common/ipc_channel_proxy.h ('k') | chrome/common/ipc_channel_win.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 (c) 2006-2008 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 "base/message_loop.h"
6 #include "base/thread.h"
7 #include "chrome/common/ipc_channel_proxy.h"
8 #include "chrome/common/ipc_logging.h"
9 #include "chrome/common/ipc_message_utils.h"
10
11 namespace IPC {
12
13 //-----------------------------------------------------------------------------
14
15 ChannelProxy::Context::Context(Channel::Listener* listener,
16 MessageFilter* filter,
17 MessageLoop* ipc_message_loop)
18 : listener_message_loop_(MessageLoop::current()),
19 listener_(listener),
20 ipc_message_loop_(ipc_message_loop),
21 channel_(NULL),
22 peer_pid_(0),
23 channel_connected_called_(false) {
24 if (filter)
25 filters_.push_back(filter);
26 }
27
28 void ChannelProxy::Context::CreateChannel(const std::string& id,
29 const Channel::Mode& mode) {
30 DCHECK(channel_ == NULL);
31 channel_id_ = id;
32 channel_ = new Channel(id, mode, this);
33 }
34
35 bool ChannelProxy::Context::TryFilters(const Message& message) {
36 #ifdef IPC_MESSAGE_LOG_ENABLED
37 Logging* logger = Logging::current();
38 if (logger->Enabled())
39 logger->OnPreDispatchMessage(message);
40 #endif
41
42 for (size_t i = 0; i < filters_.size(); ++i) {
43 if (filters_[i]->OnMessageReceived(message)) {
44 #ifdef IPC_MESSAGE_LOG_ENABLED
45 if (logger->Enabled())
46 logger->OnPostDispatchMessage(message, channel_id_);
47 #endif
48 return true;
49 }
50 }
51 return false;
52 }
53
54 // Called on the IPC::Channel thread
55 void ChannelProxy::Context::OnMessageReceived(const Message& message) {
56 // First give a chance to the filters to process this message.
57 if (!TryFilters(message))
58 OnMessageReceivedNoFilter(message);
59 }
60
61 // Called on the IPC::Channel thread
62 void ChannelProxy::Context::OnMessageReceivedNoFilter(const Message& message) {
63 // NOTE: This code relies on the listener's message loop not going away while
64 // this thread is active. That should be a reasonable assumption, but it
65 // feels risky. We may want to invent some more indirect way of referring to
66 // a MessageLoop if this becomes a problem.
67 listener_message_loop_->PostTask(FROM_HERE, NewRunnableMethod(
68 this, &Context::OnDispatchMessage, message));
69 }
70
71 // Called on the IPC::Channel thread
72 void ChannelProxy::Context::OnChannelConnected(int32 peer_pid) {
73 peer_pid_ = peer_pid;
74 for (size_t i = 0; i < filters_.size(); ++i)
75 filters_[i]->OnChannelConnected(peer_pid);
76
77 // See above comment about using listener_message_loop_ here.
78 listener_message_loop_->PostTask(FROM_HERE, NewRunnableMethod(
79 this, &Context::OnDispatchConnected));
80 }
81
82 // Called on the IPC::Channel thread
83 void ChannelProxy::Context::OnChannelError() {
84 for (size_t i = 0; i < filters_.size(); ++i)
85 filters_[i]->OnChannelError();
86
87 // See above comment about using listener_message_loop_ here.
88 listener_message_loop_->PostTask(FROM_HERE, NewRunnableMethod(
89 this, &Context::OnDispatchError));
90 }
91
92 // Called on the IPC::Channel thread
93 void ChannelProxy::Context::OnChannelOpened() {
94 DCHECK(channel_ != NULL);
95
96 // Assume a reference to ourselves on behalf of this thread. This reference
97 // will be released when we are closed.
98 AddRef();
99
100 if (!channel_->Connect()) {
101 OnChannelError();
102 return;
103 }
104
105 for (size_t i = 0; i < filters_.size(); ++i)
106 filters_[i]->OnFilterAdded(channel_);
107 }
108
109 // Called on the IPC::Channel thread
110 void ChannelProxy::Context::OnChannelClosed() {
111 // It's okay for IPC::ChannelProxy::Close to be called more than once, which
112 // would result in this branch being taken.
113 if (!channel_)
114 return;
115
116 for (size_t i = 0; i < filters_.size(); ++i) {
117 filters_[i]->OnChannelClosing();
118 filters_[i]->OnFilterRemoved();
119 }
120
121 // We don't need the filters anymore.
122 filters_.clear();
123
124 delete channel_;
125 channel_ = NULL;
126
127 // Balance with the reference taken during startup. This may result in
128 // self-destruction.
129 Release();
130 }
131
132 // Called on the IPC::Channel thread
133 void ChannelProxy::Context::OnSendMessage(Message* message) {
134 if (!channel_->Send(message))
135 OnChannelError();
136 }
137
138 // Called on the IPC::Channel thread
139 void ChannelProxy::Context::OnAddFilter(MessageFilter* filter) {
140 filters_.push_back(filter);
141
142 // If the channel has already been created, then we need to send this message
143 // so that the filter gets access to the Channel.
144 if (channel_)
145 filter->OnFilterAdded(channel_);
146
147 // Balances the AddRef in ChannelProxy::AddFilter.
148 filter->Release();
149 }
150
151 // Called on the IPC::Channel thread
152 void ChannelProxy::Context::OnRemoveFilter(MessageFilter* filter) {
153 for (size_t i = 0; i < filters_.size(); ++i) {
154 if (filters_[i].get() == filter) {
155 filter->OnFilterRemoved();
156 filters_.erase(filters_.begin() + i);
157 return;
158 }
159 }
160
161 NOTREACHED() << "filter to be removed not found";
162 }
163
164 // Called on the listener's thread
165 void ChannelProxy::Context::OnDispatchMessage(const Message& message) {
166 if (!listener_)
167 return;
168
169 OnDispatchConnected();
170
171 #ifdef IPC_MESSAGE_LOG_ENABLED
172 Logging* logger = Logging::current();
173 if (message.type() == IPC_LOGGING_ID) {
174 logger->OnReceivedLoggingMessage(message);
175 return;
176 }
177
178 if (logger->Enabled())
179 logger->OnPreDispatchMessage(message);
180 #endif
181
182 listener_->OnMessageReceived(message);
183
184 #ifdef IPC_MESSAGE_LOG_ENABLED
185 if (logger->Enabled())
186 logger->OnPostDispatchMessage(message, channel_id_);
187 #endif
188 }
189
190 // Called on the listener's thread
191 void ChannelProxy::Context::OnDispatchConnected() {
192 if (channel_connected_called_)
193 return;
194
195 channel_connected_called_ = true;
196 if (listener_)
197 listener_->OnChannelConnected(peer_pid_);
198 }
199
200 // Called on the listener's thread
201 void ChannelProxy::Context::OnDispatchError() {
202 if (listener_)
203 listener_->OnChannelError();
204 }
205
206 //-----------------------------------------------------------------------------
207
208 ChannelProxy::ChannelProxy(const std::string& channel_id, Channel::Mode mode,
209 Channel::Listener* listener, MessageFilter* filter,
210 MessageLoop* ipc_thread)
211 : context_(new Context(listener, filter, ipc_thread)) {
212 Init(channel_id, mode, ipc_thread, true);
213 }
214
215 ChannelProxy::ChannelProxy(const std::string& channel_id, Channel::Mode mode,
216 MessageLoop* ipc_thread, Context* context,
217 bool create_pipe_now)
218 : context_(context) {
219 Init(channel_id, mode, ipc_thread, create_pipe_now);
220 }
221
222 void ChannelProxy::Init(const std::string& channel_id, Channel::Mode mode,
223 MessageLoop* ipc_thread_loop, bool create_pipe_now) {
224 if (create_pipe_now) {
225 // Create the channel immediately. This effectively sets up the
226 // low-level pipe so that the client can connect. Without creating
227 // the pipe immediately, it is possible for a listener to attempt
228 // to connect and get an error since the pipe doesn't exist yet.
229 context_->CreateChannel(channel_id, mode);
230 } else {
231 context_->ipc_message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
232 context_.get(), &Context::CreateChannel, channel_id, mode));
233 }
234
235 // complete initialization on the background thread
236 context_->ipc_message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
237 context_.get(), &Context::OnChannelOpened));
238 }
239
240 void ChannelProxy::Close() {
241 // Clear the backpointer to the listener so that any pending calls to
242 // Context::OnDispatchMessage or OnDispatchError will be ignored. It is
243 // possible that the channel could be closed while it is receiving messages!
244 context_->Clear();
245
246 if (context_->ipc_message_loop()) {
247 context_->ipc_message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
248 context_.get(), &Context::OnChannelClosed));
249 }
250 }
251
252 bool ChannelProxy::Send(Message* message) {
253 #ifdef IPC_MESSAGE_LOG_ENABLED
254 Logging::current()->OnSendMessage(message, context_->channel_id());
255 #endif
256
257 context_->ipc_message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
258 context_.get(), &Context::OnSendMessage, message));
259 return true;
260 }
261
262 void ChannelProxy::AddFilter(MessageFilter* filter) {
263 // We want to addref the filter to prevent it from
264 // being destroyed before the OnAddFilter call is invoked.
265 filter->AddRef();
266 context_->ipc_message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
267 context_.get(), &Context::OnAddFilter, filter));
268 }
269
270 void ChannelProxy::RemoveFilter(MessageFilter* filter) {
271 context_->ipc_message_loop()->PostTask(FROM_HERE, NewRunnableMethod(
272 context_.get(), &Context::OnRemoveFilter, filter));
273 }
274
275 #if defined(OS_POSIX)
276 // See the TODO regarding lazy initialization of the channel in
277 // ChannelProxy::Init().
278 // We assume that IPC::Channel::GetClientFileDescriptorMapping() is thread-safe.
279 int ChannelProxy::GetClientFileDescriptor() const {
280 Channel *channel = context_.get()->channel_;
281 DCHECK(channel); // Channel must have been created first.
282 return channel->GetClientFileDescriptor();
283 }
284 #endif
285
286 //-----------------------------------------------------------------------------
287
288 } // namespace IPC
OLDNEW
« no previous file with comments | « chrome/common/ipc_channel_proxy.h ('k') | chrome/common/ipc_channel_win.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698