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

Side by Side Diff: chrome/browser/worker_host/worker_process_host.cc

Issue 390017: Added lifecycle management and sharing support for SharedWorkers. SharedWorkers (Closed)
Patch Set: Changed WebWorkerBase not not call a virtual function from the destructor Created 11 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 (c) 2009 The Chromium Authors. All rights reserved. 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 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 "chrome/browser/worker_host/worker_process_host.h" 5 #include "chrome/browser/worker_host/worker_process_host.h"
6 6
7 #include <set> 7 #include <set>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/command_line.h" 10 #include "base/command_line.h"
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after
143 ChildProcessSecurityPolicy::GetInstance()->GrantRequestURL( 143 ChildProcessSecurityPolicy::GetInstance()->GrantRequestURL(
144 id(), instance.url); 144 id(), instance.url);
145 145
146 instances_.push_back(instance); 146 instances_.push_back(instance);
147 Send(new WorkerProcessMsg_CreateWorker(instance.url, 147 Send(new WorkerProcessMsg_CreateWorker(instance.url,
148 instance.is_shared, 148 instance.is_shared,
149 instance.name, 149 instance.name,
150 instance.worker_route_id)); 150 instance.worker_route_id));
151 151
152 UpdateTitle(); 152 UpdateTitle();
153 instances_.back().sender->Send( 153 DCHECK(instance.senders.size() == 1);
154 new ViewMsg_WorkerCreated(instance.sender_route_id)); 154 WorkerInstance::SenderInfo info = *(instances_.back().senders.begin());
155 info.first->Send(new ViewMsg_WorkerCreated(info.second));
155 } 156 }
156 157
157 bool WorkerProcessHost::FilterMessage(const IPC::Message& message, 158 bool WorkerProcessHost::FilterMessage(const IPC::Message& message,
158 int sender_pid) { 159 IPC::Message::Sender* sender) {
159 for (Instances::iterator i = instances_.begin(); i != instances_.end(); ++i) { 160 for (Instances::iterator i = instances_.begin(); i != instances_.end(); ++i) {
160 if (i->sender_id == sender_pid && 161 if (!i->closed && i->HasSender(sender, message.routing_id())) {
161 i->sender_route_id == message.routing_id()) {
162 RelayMessage( 162 RelayMessage(
163 message, this, i->worker_route_id, next_route_id_callback_.get()); 163 message, this, i->worker_route_id, next_route_id_callback_.get());
164 return true; 164 return true;
165 } 165 }
166 } 166 }
167 167
168 return false; 168 return false;
169 } 169 }
170 170
171 URLRequestContext* WorkerProcessHost::GetRequestContext( 171 URLRequestContext* WorkerProcessHost::GetRequestContext(
172 uint32 request_id, 172 uint32 request_id,
173 const ViewHostMsg_Resource_Request& request_data) { 173 const ViewHostMsg_Resource_Request& request_data) {
174 return NULL; 174 return NULL;
175 } 175 }
176 176
177 // Sent to notify the browser process when a worker context invokes close(), so
178 // no new connections are sent to shared workers.
179 void WorkerProcessHost::OnWorkerContextClosed(int worker_route_id) {
180 for (Instances::iterator i = instances_.begin(); i != instances_.end(); ++i) {
181 if (i->worker_route_id == worker_route_id) {
182 // Set the closed flag - this will stop any further connections from
183 // being sent to the shared worker (ignored for dedicated workers).
jam 2009/11/12 20:11:23 nit: the comment says it's ignored for dedicated w
184 i->closed = true;
185 break;
186 }
187 }
188 }
189
177 void WorkerProcessHost::OnMessageReceived(const IPC::Message& message) { 190 void WorkerProcessHost::OnMessageReceived(const IPC::Message& message) {
178 bool msg_is_ok = true; 191 bool msg_is_ok = true;
179 bool handled = MessagePortDispatcher::GetInstance()->OnMessageReceived( 192 bool handled = MessagePortDispatcher::GetInstance()->OnMessageReceived(
180 message, this, next_route_id_callback_.get(), &msg_is_ok); 193 message, this, next_route_id_callback_.get(), &msg_is_ok);
181 194
182 if (!handled) { 195 if (!handled) {
183 handled = true; 196 handled = true;
184 IPC_BEGIN_MESSAGE_MAP_EX(WorkerProcessHost, message, msg_is_ok) 197 IPC_BEGIN_MESSAGE_MAP_EX(WorkerProcessHost, message, msg_is_ok)
185 IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWorker, OnCreateWorker) 198 IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWorker, OnCreateWorker)
186 IPC_MESSAGE_HANDLER(ViewHostMsg_CancelCreateDedicatedWorker, 199 IPC_MESSAGE_HANDLER(ViewHostMsg_CancelCreateDedicatedWorker,
187 OnCancelCreateDedicatedWorker) 200 OnCancelCreateDedicatedWorker)
201 IPC_MESSAGE_HANDLER(WorkerHostMsg_WorkerContextClosed,
202 OnWorkerContextClosed);
188 IPC_MESSAGE_HANDLER(ViewHostMsg_ForwardToWorker, 203 IPC_MESSAGE_HANDLER(ViewHostMsg_ForwardToWorker,
189 OnForwardToWorker) 204 OnForwardToWorker)
jam 2009/11/12 20:11:23 can you add the new messages that you receive in R
190 IPC_MESSAGE_UNHANDLED(handled = false) 205 IPC_MESSAGE_UNHANDLED(handled = false)
191 IPC_END_MESSAGE_MAP_EX() 206 IPC_END_MESSAGE_MAP_EX()
192 } 207 }
193 208
194 if (!msg_is_ok) { 209 if (!msg_is_ok) {
195 NOTREACHED(); 210 NOTREACHED();
196 base::KillProcess(handle(), ResultCodes::KILLED_BAD_MESSAGE, false); 211 base::KillProcess(handle(), ResultCodes::KILLED_BAD_MESSAGE, false);
197 } 212 }
198 213
199 if (handled) 214 if (handled)
200 return; 215 return;
201 216
202 for (Instances::iterator i = instances_.begin(); i != instances_.end(); ++i) { 217 for (Instances::iterator i = instances_.begin(); i != instances_.end(); ++i) {
203 if (i->worker_route_id == message.routing_id()) { 218 if (i->worker_route_id == message.routing_id()) {
204 CallbackWithReturnValue<int>::Type* next_route_id = 219 if (!i->is_shared) {
205 GetNextRouteIdCallback(i->sender); 220 // Don't relay messages from shared workers (all communication is via
206 RelayMessage(message, i->sender, i->sender_route_id, next_route_id); 221 // the message port).
222 DCHECK(i->senders.size() == 1);
223 WorkerInstance::SenderInfo info = *(i->senders.begin());
224 CallbackWithReturnValue<int>::Type* next_route_id =
225 GetNextRouteIdCallback(info.first);
226 RelayMessage(message, info.first, info.second, next_route_id);
227 }
207 228
208 if (message.type() == WorkerHostMsg_WorkerContextDestroyed::ID) { 229 if (message.type() == WorkerHostMsg_WorkerContextDestroyed::ID) {
209 instances_.erase(i); 230 instances_.erase(i);
210 UpdateTitle(); 231 UpdateTitle();
211 } 232 }
212 break; 233 break;
213 } 234 }
214 } 235 }
215 } 236 }
216 237
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
286 } else { 307 } else {
287 IPC::Message* new_message = new IPC::Message(message); 308 IPC::Message* new_message = new IPC::Message(message);
288 new_message->set_routing_id(route_id); 309 new_message->set_routing_id(route_id);
289 sender->Send(new_message); 310 sender->Send(new_message);
290 return; 311 return;
291 } 312 }
292 } 313 }
293 314
294 void WorkerProcessHost::SenderShutdown(IPC::Message::Sender* sender) { 315 void WorkerProcessHost::SenderShutdown(IPC::Message::Sender* sender) {
295 for (Instances::iterator i = instances_.begin(); i != instances_.end();) { 316 for (Instances::iterator i = instances_.begin(); i != instances_.end();) {
296 if (i->sender == sender) { 317 bool shutdown = false;
318 i->RemoveSenders(sender);
319 if (i->is_shared) {
320 i->RemoveAllAssociatedDocuments(sender);
321 if (i->document_set.empty())
322 shutdown = true;
323 } else if (i->senders.empty()) {
324 shutdown = true;
325 }
326 if (shutdown) {
297 Send(new WorkerMsg_TerminateWorkerContext(i->worker_route_id)); 327 Send(new WorkerMsg_TerminateWorkerContext(i->worker_route_id));
298 i = instances_.erase(i); 328 i = instances_.erase(i);
299 } else { 329 } else {
300 ++i; 330 ++i;
301 } 331 }
302 } 332 }
303 } 333 }
304 334
305 void WorkerProcessHost::UpdateTitle() { 335 void WorkerProcessHost::UpdateTitle() {
306 std::set<std::string> titles; 336 std::set<std::string> titles;
(...skipping 22 matching lines...) Expand all
329 359
330 void WorkerProcessHost::OnCreateWorker(const GURL& url, 360 void WorkerProcessHost::OnCreateWorker(const GURL& url,
331 bool is_shared, 361 bool is_shared,
332 const string16& name, 362 const string16& name,
333 int render_view_route_id, 363 int render_view_route_id,
334 int* route_id) { 364 int* route_id) {
335 DCHECK(instances_.size() == 1); // Only called when one process per worker. 365 DCHECK(instances_.size() == 1); // Only called when one process per worker.
336 *route_id = WorkerService::GetInstance()->next_worker_route_id(); 366 *route_id = WorkerService::GetInstance()->next_worker_route_id();
337 WorkerService::GetInstance()->CreateWorker( 367 WorkerService::GetInstance()->CreateWorker(
338 url, is_shared, name, instances_.front().renderer_id, 368 url, is_shared, name, instances_.front().renderer_id,
339 instances_.front().render_view_route_id, this, id(), *route_id); 369 instances_.front().render_view_route_id, this, *route_id);
340 } 370 }
341 371
342 void WorkerProcessHost::OnCancelCreateDedicatedWorker(int route_id) { 372 void WorkerProcessHost::OnCancelCreateDedicatedWorker(int route_id) {
343 WorkerService::GetInstance()->CancelCreateDedicatedWorker(id(), route_id); 373 WorkerService::GetInstance()->CancelCreateDedicatedWorker(this, route_id);
344 } 374 }
345 375
346 void WorkerProcessHost::OnForwardToWorker(const IPC::Message& message) { 376 void WorkerProcessHost::OnForwardToWorker(const IPC::Message& message) {
347 WorkerService::GetInstance()->ForwardMessage(message, id()); 377 WorkerService::GetInstance()->ForwardMessage(message, this);
348 } 378 }
379
380 void WorkerProcessHost::DocumentDetached(IPC::Message::Sender* parent,
381 unsigned long long document_id)
382 {
383 // Walk all instances and remove the document from their document set
jam 2009/11/12 20:11:23 very nitty nit: period at end of comment
384 for (Instances::iterator i = instances_.begin(); i != instances_.end();) {
385 if (!i->is_shared) {
386 ++i;
387 } else {
388 i->RemoveFromDocumentSet(parent, document_id);
389 if (i->document_set.empty()) {
390 // This worker has no more associated documents - shut it down.
391 Send(new WorkerMsg_TerminateWorkerContext(i->worker_route_id));
392 i = instances_.erase(i);
393 } else {
394 ++i;
395 }
396 }
397 }
398 }
399
400 // Compares an instance based on the algorithm in the WebWorkers spec - an
401 // instance matches if the origins of the URLs match, and:
402 // a) the names are non-empty and equal
403 // -or-
404 // b) the names are both empty, and the urls are equal
405 bool WorkerProcessHost::WorkerInstance::Matches(
406 const GURL& match_url, const string16& match_name) const {
407 // Only match open shared workers.
408 if (!is_shared || closed)
409 return false;
410
411 if (url.GetOrigin() != match_url.GetOrigin())
412 return false;
413
414 if (name.empty() && match_name.empty())
415 return url == match_url;
416
417 return name == match_name;
418 }
419
420 void WorkerProcessHost::WorkerInstance::AddToDocumentSet(
421 IPC::Message::Sender* parent, unsigned long long document_id) {
422 DocumentInfo info(parent, document_id);
423 document_set.insert(info);
424 }
425
426 bool WorkerProcessHost::WorkerInstance::IsInDocumentSet(
427 IPC::Message::Sender* parent, unsigned long long document_id) const {
428 DocumentInfo info(parent, document_id);
429 return document_set.find(info) != document_set.end();
430 }
431
432 void WorkerProcessHost::WorkerInstance::RemoveFromDocumentSet(
433 IPC::Message::Sender* parent, unsigned long long document_id) {
434 DocumentInfo info(parent, document_id);
435 document_set.erase(info);
436 }
437
438 void WorkerProcessHost::WorkerInstance::RemoveAllAssociatedDocuments(
439 IPC::Message::Sender* parent) {
440 for (DocumentSet::iterator i = document_set.begin();
441 i != document_set.end();
442 ++i) {
443 if (i->first == parent)
444 document_set.erase(i);
jam 2009/11/12 20:11:23 this isn't safe, need to increment i only if you d
445 }
446 }
447
448 void WorkerProcessHost::WorkerInstance::AddSender(IPC::Message::Sender* sender,
449 int sender_route_id) {
450 SenderInfo info(sender, sender_route_id);
451 senders.insert(info);
452 // Only shared workers can have more than one associated sender.
453 DCHECK(is_shared || senders.size() == 1);
454 }
455
456 void WorkerProcessHost::WorkerInstance::RemoveSender(
457 IPC::Message::Sender* sender, int sender_route_id) {
458 SenderInfo info(sender, sender_route_id);
459 senders.erase(info);
460 }
461
462 void WorkerProcessHost::WorkerInstance::RemoveSenders(
463 IPC::Message::Sender* sender) {
464 for (SenderList::iterator i = senders.begin(); i != senders.end(); ++i) {
465 if (i->first == sender)
466 senders.erase(i);
467 }
468 }
469
470 bool WorkerProcessHost::WorkerInstance::HasSender(
471 IPC::Message::Sender* sender, int sender_route_id) const {
472 SenderInfo info(sender, sender_route_id);
473 return senders.find(info) != senders.end();
474 }
475
476
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698