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

Side by Side Diff: content/common/webmessageportchannel_impl.cc

Issue 16328003: Move a bunch of child-only code from content/common to content/child (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: . Created 7 years, 6 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/common/webmessageportchannel_impl.h ('k') | content/content_child.gypi » ('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) 2011 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/common/webmessageportchannel_impl.h"
6
7 #include "base/bind.h"
8 #include "content/common/child_process.h"
9 #include "content/common/child_thread.h"
10 #include "content/common/worker_messages.h"
11 #include "third_party/WebKit/public/platform/WebMessagePortChannelClient.h"
12 #include "third_party/WebKit/public/platform/WebString.h"
13
14 using WebKit::WebMessagePortChannel;
15 using WebKit::WebMessagePortChannelArray;
16 using WebKit::WebMessagePortChannelClient;
17 using WebKit::WebString;
18
19 namespace content {
20
21 WebMessagePortChannelImpl::WebMessagePortChannelImpl()
22 : client_(NULL),
23 route_id_(MSG_ROUTING_NONE),
24 message_port_id_(MSG_ROUTING_NONE) {
25 AddRef();
26 Init();
27 }
28
29 WebMessagePortChannelImpl::WebMessagePortChannelImpl(
30 int route_id,
31 int message_port_id)
32 : client_(NULL),
33 route_id_(route_id),
34 message_port_id_(message_port_id) {
35 AddRef();
36 Init();
37 }
38
39 WebMessagePortChannelImpl::~WebMessagePortChannelImpl() {
40 // If we have any queued messages with attached ports, manually destroy them.
41 while (!message_queue_.empty()) {
42 const std::vector<WebMessagePortChannelImpl*>& channel_array =
43 message_queue_.front().ports;
44 for (size_t i = 0; i < channel_array.size(); i++) {
45 channel_array[i]->destroy();
46 }
47 message_queue_.pop();
48 }
49
50 if (message_port_id_ != MSG_ROUTING_NONE)
51 Send(new WorkerProcessHostMsg_DestroyMessagePort(message_port_id_));
52
53 if (route_id_ != MSG_ROUTING_NONE)
54 ChildThread::current()->RemoveRoute(route_id_);
55 }
56
57 void WebMessagePortChannelImpl::setClient(WebMessagePortChannelClient* client) {
58 // Must lock here since client_ is called on the main thread.
59 base::AutoLock auto_lock(lock_);
60 client_ = client;
61 }
62
63 void WebMessagePortChannelImpl::destroy() {
64 setClient(NULL);
65
66 // Release the object on the main thread, since the destructor might want to
67 // send an IPC, and that has to happen on the main thread.
68 ChildThread::current()->message_loop()->ReleaseSoon(FROM_HERE, this);
69 }
70
71 void WebMessagePortChannelImpl::entangle(WebMessagePortChannel* channel) {
72 // The message port ids might not be set up yet, if this channel wasn't
73 // created on the main thread. So need to wait until we're on the main thread
74 // before getting the other message port id.
75 scoped_refptr<WebMessagePortChannelImpl> webchannel(
76 static_cast<WebMessagePortChannelImpl*>(channel));
77 Entangle(webchannel);
78 }
79
80 void WebMessagePortChannelImpl::postMessage(
81 const WebString& message,
82 WebMessagePortChannelArray* channels) {
83 if (base::MessageLoop::current() != ChildThread::current()->message_loop()) {
84 ChildThread::current()->message_loop()->PostTask(
85 FROM_HERE,
86 base::Bind(
87 &WebMessagePortChannelImpl::postMessage, this, message, channels));
88 return;
89 }
90
91 std::vector<int> message_port_ids(channels ? channels->size() : 0);
92 if (channels) {
93 // Extract the port IDs from the source array, then free it.
94 for (size_t i = 0; i < channels->size(); ++i) {
95 WebMessagePortChannelImpl* webchannel =
96 static_cast<WebMessagePortChannelImpl*>((*channels)[i]);
97 message_port_ids[i] = webchannel->message_port_id();
98 webchannel->QueueMessages();
99 DCHECK(message_port_ids[i] != MSG_ROUTING_NONE);
100 }
101 delete channels;
102 }
103
104 IPC::Message* msg = new WorkerProcessHostMsg_PostMessage(
105 message_port_id_, message, message_port_ids);
106 Send(msg);
107 }
108
109 bool WebMessagePortChannelImpl::tryGetMessage(
110 WebString* message,
111 WebMessagePortChannelArray& channels) {
112 base::AutoLock auto_lock(lock_);
113 if (message_queue_.empty())
114 return false;
115
116 *message = message_queue_.front().message;
117 const std::vector<WebMessagePortChannelImpl*>& channel_array =
118 message_queue_.front().ports;
119 WebMessagePortChannelArray result_ports(channel_array.size());
120 for (size_t i = 0; i < channel_array.size(); i++) {
121 result_ports[i] = channel_array[i];
122 }
123
124 channels.swap(result_ports);
125 message_queue_.pop();
126 return true;
127 }
128
129 void WebMessagePortChannelImpl::Init() {
130 if (base::MessageLoop::current() != ChildThread::current()->message_loop()) {
131 ChildThread::current()->message_loop()->PostTask(
132 FROM_HERE, base::Bind(&WebMessagePortChannelImpl::Init, this));
133 return;
134 }
135
136 if (route_id_ == MSG_ROUTING_NONE) {
137 DCHECK(message_port_id_ == MSG_ROUTING_NONE);
138 Send(new WorkerProcessHostMsg_CreateMessagePort(
139 &route_id_, &message_port_id_));
140 }
141
142 ChildThread::current()->AddRoute(route_id_, this);
143 }
144
145 void WebMessagePortChannelImpl::Entangle(
146 scoped_refptr<WebMessagePortChannelImpl> channel) {
147 if (base::MessageLoop::current() != ChildThread::current()->message_loop()) {
148 ChildThread::current()->message_loop()->PostTask(
149 FROM_HERE,
150 base::Bind(&WebMessagePortChannelImpl::Entangle, this, channel));
151 return;
152 }
153
154 Send(new WorkerProcessHostMsg_Entangle(
155 message_port_id_, channel->message_port_id()));
156 }
157
158 void WebMessagePortChannelImpl::QueueMessages() {
159 if (base::MessageLoop::current() != ChildThread::current()->message_loop()) {
160 ChildThread::current()->message_loop()->PostTask(
161 FROM_HERE, base::Bind(&WebMessagePortChannelImpl::QueueMessages, this));
162 return;
163 }
164 // This message port is being sent elsewhere (perhaps to another process).
165 // The new endpoint needs to receive the queued messages, including ones that
166 // could still be in-flight. So we tell the browser to queue messages, and it
167 // sends us an ack, whose receipt we know means that no more messages are
168 // in-flight. We then send the queued messages to the browser, which prepends
169 // them to the ones it queued and it sends them to the new endpoint.
170 Send(new WorkerProcessHostMsg_QueueMessages(message_port_id_));
171
172 // The process could potentially go away while we're still waiting for
173 // in-flight messages. Ensure it stays alive.
174 ChildProcess::current()->AddRefProcess();
175 }
176
177 void WebMessagePortChannelImpl::Send(IPC::Message* message) {
178 if (base::MessageLoop::current() != ChildThread::current()->message_loop()) {
179 DCHECK(!message->is_sync());
180 ChildThread::current()->message_loop()->PostTask(
181 FROM_HERE,
182 base::Bind(&WebMessagePortChannelImpl::Send, this, message));
183 return;
184 }
185
186 ChildThread::current()->Send(message);
187 }
188
189 bool WebMessagePortChannelImpl::OnMessageReceived(const IPC::Message& message) {
190 bool handled = true;
191 IPC_BEGIN_MESSAGE_MAP(WebMessagePortChannelImpl, message)
192 IPC_MESSAGE_HANDLER(WorkerProcessMsg_Message, OnMessage)
193 IPC_MESSAGE_HANDLER(WorkerProcessMsg_MessagesQueued, OnMessagedQueued)
194 IPC_MESSAGE_UNHANDLED(handled = false)
195 IPC_END_MESSAGE_MAP()
196 return handled;
197 }
198
199 void WebMessagePortChannelImpl::OnMessage(
200 const string16& message,
201 const std::vector<int>& sent_message_port_ids,
202 const std::vector<int>& new_routing_ids) {
203 base::AutoLock auto_lock(lock_);
204 Message msg;
205 msg.message = message;
206 if (!sent_message_port_ids.empty()) {
207 msg.ports.resize(sent_message_port_ids.size());
208 for (size_t i = 0; i < sent_message_port_ids.size(); ++i) {
209 msg.ports[i] = new WebMessagePortChannelImpl(
210 new_routing_ids[i], sent_message_port_ids[i]);
211 }
212 }
213
214 bool was_empty = message_queue_.empty();
215 message_queue_.push(msg);
216 if (client_ && was_empty)
217 client_->messageAvailable();
218 }
219
220 void WebMessagePortChannelImpl::OnMessagedQueued() {
221 std::vector<QueuedMessage> queued_messages;
222
223 {
224 base::AutoLock auto_lock(lock_);
225 queued_messages.reserve(message_queue_.size());
226 while (!message_queue_.empty()) {
227 string16 message = message_queue_.front().message;
228 const std::vector<WebMessagePortChannelImpl*>& channel_array =
229 message_queue_.front().ports;
230 std::vector<int> port_ids(channel_array.size());
231 for (size_t i = 0; i < channel_array.size(); ++i) {
232 port_ids[i] = channel_array[i]->message_port_id();
233 }
234 queued_messages.push_back(std::make_pair(message, port_ids));
235 message_queue_.pop();
236 }
237 }
238
239 Send(new WorkerProcessHostMsg_SendQueuedMessages(
240 message_port_id_, queued_messages));
241
242 message_port_id_ = MSG_ROUTING_NONE;
243
244 Release();
245 ChildProcess::current()->ReleaseProcess();
246 }
247
248 WebMessagePortChannelImpl::Message::Message() {}
249
250 WebMessagePortChannelImpl::Message::~Message() {}
251
252 } // namespace content
OLDNEW
« no previous file with comments | « content/common/webmessageportchannel_impl.h ('k') | content/content_child.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698