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

Side by Side Diff: content/browser/message_port_service.cc

Issue 737833002: Properly queue messages sent to message ports that are transferred to a service worker. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@cross_process_messaging_with_terminate
Patch Set: improve comment Created 6 years, 1 month 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
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/message_port_service.h" 5 #include "content/browser/message_port_service.h"
6 6
7 #include "content/browser/message_port_message_filter.h" 7 #include "content/browser/message_port_message_filter.h"
8 #include "content/common/message_port_messages.h" 8 #include "content/common/message_port_messages.h"
9 9
10 namespace content { 10 namespace content {
11 11
12 struct MessagePortService::MessagePort { 12 struct MessagePortService::MessagePort {
13 // |filter| and |route_id| are what we need to send messages to the port. 13 // |filter| and |route_id| are what we need to send messages to the port.
14 // |filter| is just a weak pointer since we get notified when its process has 14 // |filter| is just a weak pointer since we get notified when its process has
15 // gone away and remove it. 15 // gone away and remove it.
16 MessagePortMessageFilter* filter; 16 MessagePortMessageFilter* filter;
17 int route_id; 17 int route_id;
18 // A globally unique id for this message port. 18 // A globally unique id for this message port.
19 int message_port_id; 19 int message_port_id;
20 // The globally unique id of the entangled message port. 20 // The globally unique id of the entangled message port.
21 int entangled_message_port_id; 21 int entangled_message_port_id;
22 // If true, all messages to this message port are queued and not delivered. 22 // If true, all messages to this message port are queued and not delivered.
23 // This is needed so that when a message port is sent between processes all 23 // This is needed so that when a message port is sent between processes all
24 // pending message get transferred. There are two possibilities for pending 24 // pending message get transferred. There are two possibilities for pending
25 // messages: either they are already received by the child process, or they're 25 // messages: either they are already received by the child process, or they're
26 // in-flight. This flag ensures that the latter type get flushed through the 26 // in-flight. This flag ensures that the latter type get flushed through the
27 // system. 27 // system.
28 // This flag should only be set to true in response to 28 // This flag should only be set to true in response to
29 // MessagePortHostMsg_QueueMessages. 29 // MessagePortHostMsg_QueueMessages.
30 bool queue_messages; 30 bool queue_for_inflight_messages;
31 // If true, all messages to this message port are queued and not delivered.
32 // This is needed so that when a message port is sent to a new process all
33 // messages are held in the browser process until the destination process is
34 // ready to receive messages. This flag is set true when a message port is
35 // transferred to a different process but there isn't immediately a
36 // MessagePortMessageFilter available for that new process. Once the
37 // destination process is ready to receive messages it sends
38 // MessagePortHostMsg_ReleaseMessages to set this flag to false.
39 bool hold_messages_for_destination;
40 // Returns true if messages should be queued for either reason.
41 bool queue_messages() const {
42 return queue_for_inflight_messages || hold_messages_for_destination;
43 }
44 // If true, the message port should be destroyed but was currently still
45 // waiting for a SendQueuedMessages message from a renderer. As soon as that
46 // message is received the port will actually be destroyed.
47 bool should_be_destroyed;
31 QueuedMessages queued_messages; 48 QueuedMessages queued_messages;
32 }; 49 };
33 50
34 MessagePortService* MessagePortService::GetInstance() { 51 MessagePortService* MessagePortService::GetInstance() {
35 return Singleton<MessagePortService>::get(); 52 return Singleton<MessagePortService>::get();
36 } 53 }
37 54
38 MessagePortService::MessagePortService() 55 MessagePortService::MessagePortService()
39 : next_message_port_id_(0) { 56 : next_message_port_id_(0) {
40 } 57 }
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
72 MessagePortMessageFilter* filter, 89 MessagePortMessageFilter* filter,
73 int* message_port_id) { 90 int* message_port_id) {
74 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 91 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
75 *message_port_id = ++next_message_port_id_; 92 *message_port_id = ++next_message_port_id_;
76 93
77 MessagePort port; 94 MessagePort port;
78 port.filter = filter; 95 port.filter = filter;
79 port.route_id = route_id; 96 port.route_id = route_id;
80 port.message_port_id = *message_port_id; 97 port.message_port_id = *message_port_id;
81 port.entangled_message_port_id = MSG_ROUTING_NONE; 98 port.entangled_message_port_id = MSG_ROUTING_NONE;
82 port.queue_messages = false; 99 port.queue_for_inflight_messages = false;
100 port.hold_messages_for_destination = false;
101 port.should_be_destroyed = false;
83 message_ports_[*message_port_id] = port; 102 message_ports_[*message_port_id] = port;
84 } 103 }
85 104
86 void MessagePortService::Destroy(int message_port_id) { 105 void MessagePortService::Destroy(int message_port_id) {
87 if (!message_ports_.count(message_port_id)) { 106 if (!message_ports_.count(message_port_id)) {
88 NOTREACHED(); 107 NOTREACHED();
89 return; 108 return;
90 } 109 }
91 110
92 DCHECK(message_ports_[message_port_id].queued_messages.empty()); 111 DCHECK(message_ports_[message_port_id].queued_messages.empty());
112
93 Erase(message_port_id); 113 Erase(message_port_id);
94 } 114 }
95 115
96 void MessagePortService::Entangle(int local_message_port_id, 116 void MessagePortService::Entangle(int local_message_port_id,
97 int remote_message_port_id) { 117 int remote_message_port_id) {
98 if (!message_ports_.count(local_message_port_id) || 118 if (!message_ports_.count(local_message_port_id) ||
99 !message_ports_.count(remote_message_port_id)) { 119 !message_ports_.count(remote_message_port_id)) {
100 NOTREACHED(); 120 NOTREACHED();
101 return; 121 return;
102 } 122 }
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
143 return; 163 return;
144 } 164 }
145 } 165 }
146 166
147 MessagePort& entangled_port = message_ports_[message_port_id]; 167 MessagePort& entangled_port = message_ports_[message_port_id];
148 168
149 std::vector<MessagePort*> sent_ports(sent_message_port_ids.size()); 169 std::vector<MessagePort*> sent_ports(sent_message_port_ids.size());
150 for (size_t i = 0; i < sent_message_port_ids.size(); ++i) 170 for (size_t i = 0; i < sent_message_port_ids.size(); ++i)
151 sent_ports[i] = &message_ports_[sent_message_port_ids[i]]; 171 sent_ports[i] = &message_ports_[sent_message_port_ids[i]];
152 172
153 if (entangled_port.queue_messages) { 173 if (entangled_port.queue_messages()) {
174 // If the target port is currently holding messages because the destination
175 // renderer isn't available yet, all message ports being sent should also be
176 // put in this state.
177 if (entangled_port.hold_messages_for_destination) {
178 for (int sent_message_port_id : sent_message_port_ids)
179 HoldMessages(sent_message_port_id);
180 }
154 entangled_port.queued_messages.push_back( 181 entangled_port.queued_messages.push_back(
155 std::make_pair(message, sent_message_port_ids)); 182 std::make_pair(message, sent_message_port_ids));
156 return; 183 return;
157 } 184 }
158 185
159 if (!entangled_port.filter) { 186 if (!entangled_port.filter) {
160 NOTREACHED(); 187 NOTREACHED();
161 return; 188 return;
162 } 189 }
163 190
(...skipping 17 matching lines...) Expand all
181 208
182 void MessagePortService::QueueMessages(int message_port_id) { 209 void MessagePortService::QueueMessages(int message_port_id) {
183 if (!message_ports_.count(message_port_id)) { 210 if (!message_ports_.count(message_port_id)) {
184 NOTREACHED(); 211 NOTREACHED();
185 return; 212 return;
186 } 213 }
187 214
188 MessagePort& port = message_ports_[message_port_id]; 215 MessagePort& port = message_ports_[message_port_id];
189 if (port.filter) { 216 if (port.filter) {
190 port.filter->Send(new MessagePortMsg_MessagesQueued(port.route_id)); 217 port.filter->Send(new MessagePortMsg_MessagesQueued(port.route_id));
191 port.queue_messages = true; 218 port.queue_for_inflight_messages = true;
192 port.filter = NULL; 219 port.filter = NULL;
193 } 220 }
194 } 221 }
195 222
196 void MessagePortService::SendQueuedMessages( 223 void MessagePortService::SendQueuedMessages(
197 int message_port_id, 224 int message_port_id,
198 const QueuedMessages& queued_messages) { 225 const QueuedMessages& queued_messages) {
199 if (!message_ports_.count(message_port_id)) { 226 if (!message_ports_.count(message_port_id)) {
200 NOTREACHED(); 227 NOTREACHED();
201 return; 228 return;
202 } 229 }
203 230
204 // Send the queued messages to the port again. This time they'll reach the 231 // Send the queued messages to the port again. This time they'll reach the
205 // new location. 232 // new location.
206 MessagePort& port = message_ports_[message_port_id]; 233 MessagePort& port = message_ports_[message_port_id];
207 port.queue_messages = false; 234 port.queue_for_inflight_messages = false;
235
236 // If the port is currently holding messages waiting for the target renderer,
237 // all ports in messages being sent to the port should also be put on hold.
238 if (port.hold_messages_for_destination) {
239 for (const auto& message : queued_messages)
240 for (int sent_message_port_id : message.second)
241 HoldMessages(sent_message_port_id);
242 }
243
208 port.queued_messages.insert(port.queued_messages.begin(), 244 port.queued_messages.insert(port.queued_messages.begin(),
209 queued_messages.begin(), 245 queued_messages.begin(),
210 queued_messages.end()); 246 queued_messages.end());
211 SendQueuedMessagesIfPossible(message_port_id); 247
248 if (port.should_be_destroyed)
249 ClosePort(message_port_id);
250 else
251 SendQueuedMessagesIfPossible(message_port_id);
212 } 252 }
213 253
214 void MessagePortService::SendQueuedMessagesIfPossible(int message_port_id) { 254 void MessagePortService::SendQueuedMessagesIfPossible(int message_port_id) {
215 if (!message_ports_.count(message_port_id)) { 255 if (!message_ports_.count(message_port_id)) {
216 NOTREACHED(); 256 NOTREACHED();
217 return; 257 return;
218 } 258 }
219 259
220 MessagePort& port = message_ports_[message_port_id]; 260 MessagePort& port = message_ports_[message_port_id];
221 if (port.queue_messages || !port.filter) 261 if (port.queue_messages() || !port.filter)
222 return; 262 return;
223 263
224 for (QueuedMessages::iterator iter = port.queued_messages.begin(); 264 for (QueuedMessages::iterator iter = port.queued_messages.begin();
225 iter != port.queued_messages.end(); ++iter) { 265 iter != port.queued_messages.end(); ++iter) {
226 PostMessageTo(message_port_id, iter->first, iter->second); 266 PostMessageTo(message_port_id, iter->first, iter->second);
227 } 267 }
228 port.queued_messages.clear(); 268 port.queued_messages.clear();
229 } 269 }
230 270
271 void MessagePortService::HoldMessages(int message_port_id) {
272 if (!message_ports_.count(message_port_id)) {
273 NOTREACHED();
274 return;
275 }
276
277 // Any ports in messages currently in the queue should also be put on hold.
278 for (const auto& message : message_ports_[message_port_id].queued_messages)
279 for (int sent_message_port_id : message.second)
280 HoldMessages(sent_message_port_id);
281
282 message_ports_[message_port_id].hold_messages_for_destination = true;
283 }
284
285 void MessagePortService::ClosePort(int message_port_id)
286 {
jam 2014/11/20 22:36:47 nit: wrong line
Marijn Kruisselbrink 2014/11/20 23:15:27 Done.
287 if (!message_ports_.count(message_port_id)) {
288 NOTREACHED();
289 return;
290 }
291
292 if (message_ports_[message_port_id].queue_for_inflight_messages) {
293 message_ports_[message_port_id].should_be_destroyed = true;
294 return;
295 }
296
297 // First close any message ports in the queue for this message port.
298 for (const auto& message : message_ports_[message_port_id].queued_messages)
299 for (int sent_message_port_id : message.second)
300 ClosePort(sent_message_port_id);
301
302 Erase(message_port_id);
303 }
304
305 void MessagePortService::ReleaseMessages(int message_port_id) {
306 if (!message_ports_.count(message_port_id)) {
307 NOTREACHED();
308 return;
309 }
310
311 message_ports_[message_port_id].hold_messages_for_destination = false;
312 SendQueuedMessagesIfPossible(message_port_id);
313 }
314
231 void MessagePortService::Erase(int message_port_id) { 315 void MessagePortService::Erase(int message_port_id) {
232 MessagePorts::iterator erase_item = message_ports_.find(message_port_id); 316 MessagePorts::iterator erase_item = message_ports_.find(message_port_id);
233 DCHECK(erase_item != message_ports_.end()); 317 DCHECK(erase_item != message_ports_.end());
234 318
235 int entangled_id = erase_item->second.entangled_message_port_id; 319 int entangled_id = erase_item->second.entangled_message_port_id;
236 if (entangled_id != MSG_ROUTING_NONE) { 320 if (entangled_id != MSG_ROUTING_NONE) {
237 // Do the disentanglement (and be paranoid about the other side existing 321 // Do the disentanglement (and be paranoid about the other side existing
238 // just in case something unusual happened during entanglement). 322 // just in case something unusual happened during entanglement).
239 if (message_ports_.count(entangled_id)) { 323 if (message_ports_.count(entangled_id)) {
240 message_ports_[entangled_id].entangled_message_port_id = MSG_ROUTING_NONE; 324 message_ports_[entangled_id].entangled_message_port_id = MSG_ROUTING_NONE;
241 } 325 }
242 } 326 }
243 message_ports_.erase(erase_item); 327 message_ports_.erase(erase_item);
244 } 328 }
245 329
246 } // namespace content 330 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/message_port_service.h ('k') | content/browser/service_worker/service_worker_version.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698