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

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: better cleanup in case of errors 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 30 matching lines...) Expand all
71 void MessagePortService::Create(int route_id, 88 void MessagePortService::Create(int route_id,
72 MessagePortMessageFilter* filter, 89 MessagePortMessageFilter* filter,
73 int* message_port_id) { 90 int* message_port_id) {
74 *message_port_id = ++next_message_port_id_; 91 *message_port_id = ++next_message_port_id_;
75 92
76 MessagePort port; 93 MessagePort port;
77 port.filter = filter; 94 port.filter = filter;
78 port.route_id = route_id; 95 port.route_id = route_id;
79 port.message_port_id = *message_port_id; 96 port.message_port_id = *message_port_id;
80 port.entangled_message_port_id = MSG_ROUTING_NONE; 97 port.entangled_message_port_id = MSG_ROUTING_NONE;
81 port.queue_messages = false; 98 port.queue_for_inflight_messages = false;
99 port.hold_messages_for_destination = false;
100 port.should_be_destroyed = false;
82 message_ports_[*message_port_id] = port; 101 message_ports_[*message_port_id] = port;
83 } 102 }
84 103
85 void MessagePortService::Destroy(int message_port_id) { 104 void MessagePortService::Destroy(int message_port_id) {
86 if (!message_ports_.count(message_port_id)) { 105 if (!message_ports_.count(message_port_id)) {
87 NOTREACHED(); 106 NOTREACHED();
88 return; 107 return;
89 } 108 }
90 109
91 DCHECK(message_ports_[message_port_id].queued_messages.empty()); 110 DCHECK(message_ports_[message_port_id].queued_messages.empty());
111
92 Erase(message_port_id); 112 Erase(message_port_id);
93 } 113 }
94 114
95 void MessagePortService::Entangle(int local_message_port_id, 115 void MessagePortService::Entangle(int local_message_port_id,
96 int remote_message_port_id) { 116 int remote_message_port_id) {
97 if (!message_ports_.count(local_message_port_id) || 117 if (!message_ports_.count(local_message_port_id) ||
98 !message_ports_.count(remote_message_port_id)) { 118 !message_ports_.count(remote_message_port_id)) {
99 NOTREACHED(); 119 NOTREACHED();
100 return; 120 return;
101 } 121 }
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
142 return; 162 return;
143 } 163 }
144 } 164 }
145 165
146 MessagePort& entangled_port = message_ports_[message_port_id]; 166 MessagePort& entangled_port = message_ports_[message_port_id];
147 167
148 std::vector<MessagePort*> sent_ports(sent_message_port_ids.size()); 168 std::vector<MessagePort*> sent_ports(sent_message_port_ids.size());
149 for (size_t i = 0; i < sent_message_port_ids.size(); ++i) 169 for (size_t i = 0; i < sent_message_port_ids.size(); ++i)
150 sent_ports[i] = &message_ports_[sent_message_port_ids[i]]; 170 sent_ports[i] = &message_ports_[sent_message_port_ids[i]];
151 171
152 if (entangled_port.queue_messages) { 172 if (entangled_port.queue_messages()) {
173 // If the target port is currently holding messages because the destination
174 // renderer isn't available yet, all message ports being sent should also be
175 // put in this state.
176 if (entangled_port.hold_messages_for_destination) {
177 for (int sent_message_port_id : sent_message_port_ids)
178 HoldMessages(sent_message_port_id);
179 }
153 entangled_port.queued_messages.push_back( 180 entangled_port.queued_messages.push_back(
154 std::make_pair(message, sent_message_port_ids)); 181 std::make_pair(message, sent_message_port_ids));
155 return; 182 return;
156 } 183 }
157 184
158 if (!entangled_port.filter) { 185 if (!entangled_port.filter) {
159 NOTREACHED(); 186 NOTREACHED();
160 return; 187 return;
161 } 188 }
162 189
(...skipping 17 matching lines...) Expand all
180 207
181 void MessagePortService::QueueMessages(int message_port_id) { 208 void MessagePortService::QueueMessages(int message_port_id) {
182 if (!message_ports_.count(message_port_id)) { 209 if (!message_ports_.count(message_port_id)) {
183 NOTREACHED(); 210 NOTREACHED();
184 return; 211 return;
185 } 212 }
186 213
187 MessagePort& port = message_ports_[message_port_id]; 214 MessagePort& port = message_ports_[message_port_id];
188 if (port.filter) { 215 if (port.filter) {
189 port.filter->Send(new MessagePortMsg_MessagesQueued(port.route_id)); 216 port.filter->Send(new MessagePortMsg_MessagesQueued(port.route_id));
190 port.queue_messages = true; 217 port.queue_for_inflight_messages = true;
191 port.filter = NULL; 218 port.filter = NULL;
192 } 219 }
193 } 220 }
194 221
195 void MessagePortService::SendQueuedMessages( 222 void MessagePortService::SendQueuedMessages(
196 int message_port_id, 223 int message_port_id,
197 const QueuedMessages& queued_messages) { 224 const QueuedMessages& queued_messages) {
198 if (!message_ports_.count(message_port_id)) { 225 if (!message_ports_.count(message_port_id)) {
199 NOTREACHED(); 226 NOTREACHED();
200 return; 227 return;
201 } 228 }
202 229
203 // Send the queued messages to the port again. This time they'll reach the 230 // Send the queued messages to the port again. This time they'll reach the
204 // new location. 231 // new location.
205 MessagePort& port = message_ports_[message_port_id]; 232 MessagePort& port = message_ports_[message_port_id];
206 port.queue_messages = false; 233 port.queue_for_inflight_messages = false;
234
235 // If the port is currently holding messages waiting for the target renderer,
236 // all ports in messages being sent to the port should also be put on hold.
237 if (port.hold_messages_for_destination) {
238 for (const auto& message : queued_messages)
239 for (int sent_message_port_id : message.second)
240 HoldMessages(sent_message_port_id);
241 }
242
207 port.queued_messages.insert(port.queued_messages.begin(), 243 port.queued_messages.insert(port.queued_messages.begin(),
208 queued_messages.begin(), 244 queued_messages.begin(),
209 queued_messages.end()); 245 queued_messages.end());
210 SendQueuedMessagesIfPossible(message_port_id); 246
247 if (port.should_be_destroyed)
248 ClosePort(message_port_id);
249 else
250 SendQueuedMessagesIfPossible(message_port_id);
211 } 251 }
212 252
213 void MessagePortService::SendQueuedMessagesIfPossible(int message_port_id) { 253 void MessagePortService::SendQueuedMessagesIfPossible(int message_port_id) {
214 if (!message_ports_.count(message_port_id)) { 254 if (!message_ports_.count(message_port_id)) {
215 NOTREACHED(); 255 NOTREACHED();
216 return; 256 return;
217 } 257 }
218 258
219 MessagePort& port = message_ports_[message_port_id]; 259 MessagePort& port = message_ports_[message_port_id];
220 if (port.queue_messages || !port.filter) 260 if (port.queue_messages() || !port.filter)
221 return; 261 return;
222 262
223 for (QueuedMessages::iterator iter = port.queued_messages.begin(); 263 for (QueuedMessages::iterator iter = port.queued_messages.begin();
224 iter != port.queued_messages.end(); ++iter) { 264 iter != port.queued_messages.end(); ++iter) {
225 PostMessageTo(message_port_id, iter->first, iter->second); 265 PostMessageTo(message_port_id, iter->first, iter->second);
226 } 266 }
227 port.queued_messages.clear(); 267 port.queued_messages.clear();
228 } 268 }
229 269
270 void MessagePortService::HoldMessages(int message_port_id) {
271 if (!message_ports_.count(message_port_id)) {
272 NOTREACHED();
273 return;
274 }
275
276 // Any ports in messages currently in the queue should also be put on hold.
277 for (const auto& message : message_ports_[message_port_id].queued_messages)
278 for (int sent_message_port_id : message.second)
279 HoldMessages(sent_message_port_id);
280
281 message_ports_[message_port_id].hold_messages_for_destination = true;
282 }
283
284 void MessagePortService::ClosePort(int message_port_id)
285 {
286 if (!message_ports_.count(message_port_id)) {
287 NOTREACHED();
288 return;
289 }
290
291 if (message_ports_[message_port_id].queue_for_inflight_messages) {
292 message_ports_[message_port_id].should_be_destroyed = true;
293 return;
294 }
295
296 // First close any message ports in the queue for this message port.
297 for (const auto& message : message_ports_[message_port_id].queued_messages)
298 for (int sent_message_port_id : message.second)
299 ClosePort(sent_message_port_id);
300
301 Erase(message_port_id);
302 }
303
304 void MessagePortService::ReleaseMessages(int message_port_id) {
305 if (!message_ports_.count(message_port_id)) {
306 NOTREACHED();
307 return;
308 }
309
310 message_ports_[message_port_id].hold_messages_for_destination = false;
311 SendQueuedMessagesIfPossible(message_port_id);
312 }
313
230 void MessagePortService::Erase(int message_port_id) { 314 void MessagePortService::Erase(int message_port_id) {
231 MessagePorts::iterator erase_item = message_ports_.find(message_port_id); 315 MessagePorts::iterator erase_item = message_ports_.find(message_port_id);
232 DCHECK(erase_item != message_ports_.end()); 316 DCHECK(erase_item != message_ports_.end());
233 317
234 int entangled_id = erase_item->second.entangled_message_port_id; 318 int entangled_id = erase_item->second.entangled_message_port_id;
235 if (entangled_id != MSG_ROUTING_NONE) { 319 if (entangled_id != MSG_ROUTING_NONE) {
236 // Do the disentanglement (and be paranoid about the other side existing 320 // Do the disentanglement (and be paranoid about the other side existing
237 // just in case something unusual happened during entanglement). 321 // just in case something unusual happened during entanglement).
238 if (message_ports_.count(entangled_id)) { 322 if (message_ports_.count(entangled_id)) {
239 message_ports_[entangled_id].entangled_message_port_id = MSG_ROUTING_NONE; 323 message_ports_[entangled_id].entangled_message_port_id = MSG_ROUTING_NONE;
240 } 324 }
241 } 325 }
242 message_ports_.erase(erase_item); 326 message_ports_.erase(erase_item);
243 } 327 }
244 328
245 } // namespace content 329 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698