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

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

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

Powered by Google App Engine
This is Rietveld 408576698