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

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

Issue 411283002: Remove disable-embedded-shared-worker flag and shared worker process related codes. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: rebase Created 6 years, 5 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
OLDNEW
(Empty)
1 // Copyright (c) 2012 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/browser/worker_host/worker_process_host.h"
6
7 #include <set>
8 #include <string>
9 #include <vector>
10
11 #include "base/base_switches.h"
12 #include "base/bind.h"
13 #include "base/bind_helpers.h"
14 #include "base/callback.h"
15 #include "base/command_line.h"
16 #include "base/message_loop/message_loop.h"
17 #include "base/strings/string_util.h"
18 #include "base/strings/utf_string_conversions.h"
19 #include "content/browser/appcache/appcache_dispatcher_host.h"
20 #include "content/browser/appcache/chrome_appcache_service.h"
21 #include "content/browser/browser_child_process_host_impl.h"
22 #include "content/browser/child_process_security_policy_impl.h"
23 #include "content/browser/devtools/worker_devtools_manager.h"
24 #include "content/browser/devtools/worker_devtools_message_filter.h"
25 #include "content/browser/fileapi/fileapi_message_filter.h"
26 #include "content/browser/frame_host/render_frame_host_delegate.h"
27 #include "content/browser/frame_host/render_frame_host_impl.h"
28 #include "content/browser/indexed_db/indexed_db_dispatcher_host.h"
29 #include "content/browser/loader/resource_message_filter.h"
30 #include "content/browser/message_port_message_filter.h"
31 #include "content/browser/message_port_service.h"
32 #include "content/browser/mime_registry_message_filter.h"
33 #include "content/browser/quota_dispatcher_host.h"
34 #include "content/browser/renderer_host/database_message_filter.h"
35 #include "content/browser/renderer_host/file_utilities_message_filter.h"
36 #include "content/browser/renderer_host/render_view_host_delegate.h"
37 #include "content/browser/renderer_host/render_view_host_impl.h"
38 #include "content/browser/renderer_host/socket_stream_dispatcher_host.h"
39 #include "content/browser/renderer_host/websocket_dispatcher_host.h"
40 #include "content/browser/resource_context_impl.h"
41 #include "content/browser/worker_host/worker_message_filter.h"
42 #include "content/browser/worker_host/worker_service_impl.h"
43 #include "content/common/child_process_host_impl.h"
44 #include "content/common/view_messages.h"
45 #include "content/common/worker_messages.h"
46 #include "content/public/browser/browser_thread.h"
47 #include "content/public/browser/content_browser_client.h"
48 #include "content/public/browser/user_metrics.h"
49 #include "content/public/common/content_switches.h"
50 #include "content/public/common/resource_type.h"
51 #include "content/public/common/result_codes.h"
52 #include "content/public/common/sandboxed_process_launcher_delegate.h"
53 #include "ipc/ipc_switches.h"
54 #include "net/base/mime_util.h"
55 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
56 #include "net/url_request/url_request_context_getter.h"
57 #include "ui/base/ui_base_switches.h"
58 #include "webkit/browser/fileapi/file_system_context.h"
59 #include "webkit/browser/fileapi/sandbox_file_system_backend.h"
60
61 #if defined(OS_WIN)
62 #include "content/common/sandbox_win.h"
63 #endif
64
65 namespace content {
66 namespace {
67
68 // NOTE: changes to this class need to be reviewed by the security team.
69 class WorkerSandboxedProcessLauncherDelegate
70 : public content::SandboxedProcessLauncherDelegate {
71 public:
72 WorkerSandboxedProcessLauncherDelegate(ChildProcessHost* host,
73 bool debugging_child)
74 #if defined(OS_POSIX)
75 : ipc_fd_(host->TakeClientFileDescriptor()),
76 debugging_child_(debugging_child)
77 #endif // OS_POSIX
78 {}
79
80 virtual ~WorkerSandboxedProcessLauncherDelegate() {}
81
82 #if defined(OS_WIN)
83 virtual void PreSpawnTarget(sandbox::TargetPolicy* policy,
84 bool* success) {
85 AddBaseHandleClosePolicy(policy);
86 }
87 #elif defined(OS_POSIX)
88 virtual bool ShouldUseZygote() OVERRIDE {
89 return !debugging_child_;
90 }
91 virtual int GetIpcFd() OVERRIDE {
92 return ipc_fd_;
93 }
94 #endif // OS_WIN
95
96 private:
97 #if defined(OS_POSIX)
98 int ipc_fd_;
99 bool debugging_child_;
100 #endif // OS_POSIX
101 };
102
103 // Notifies RenderViewHost that one or more worker objects crashed.
104 void WorkerCrashCallback(int render_process_unique_id, int render_frame_id) {
105 RenderFrameHostImpl* host =
106 RenderFrameHostImpl::FromID(render_process_unique_id, render_frame_id);
107 if (host)
108 host->delegate()->WorkerCrashed(host);
109 }
110
111 void WorkerCreatedCallback(int render_process_id,
112 int render_frame_id,
113 int worker_process_id) {
114 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
115 RenderFrameHost* render_frame_host =
116 RenderFrameHost::FromID(render_process_id, render_frame_id);
117 if (!render_frame_host)
118 return;
119 SiteInstance* site_instance = render_frame_host->GetSiteInstance();
120 GetContentClient()->browser()->WorkerProcessCreated(site_instance,
121 worker_process_id);
122 }
123
124 void WorkerTerminatedCallback(int render_process_id,
125 int render_frame_id,
126 int worker_process_id) {
127 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
128 RenderFrameHost* render_frame_host =
129 RenderFrameHost::FromID(render_process_id, render_frame_id);
130 if (!render_frame_host)
131 return;
132 SiteInstance* site_instance = render_frame_host->GetSiteInstance();
133 GetContentClient()->browser()->WorkerProcessTerminated(site_instance,
134 worker_process_id);
135 }
136
137 } // namespace
138
139 WorkerProcessHost::WorkerProcessHost(
140 ResourceContext* resource_context,
141 const WorkerStoragePartition& partition)
142 : resource_context_(resource_context),
143 partition_(partition),
144 process_launched_(false),
145 weak_factory_(this) {
146 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
147 DCHECK(resource_context_);
148 process_.reset(
149 new BrowserChildProcessHostImpl(PROCESS_TYPE_WORKER, this));
150 }
151
152 WorkerProcessHost::~WorkerProcessHost() {
153 // If we crashed, tell the RenderViewHosts.
154 for (Instances::iterator i = instances_.begin(); i != instances_.end(); ++i) {
155 if (!i->load_failed()) {
156 const WorkerDocumentSet::DocumentInfoSet& parents =
157 i->worker_document_set()->documents();
158 for (WorkerDocumentSet::DocumentInfoSet::const_iterator parent_iter =
159 parents.begin(); parent_iter != parents.end(); ++parent_iter) {
160 BrowserThread::PostTask(
161 BrowserThread::UI, FROM_HERE,
162 base::Bind(&WorkerCrashCallback, parent_iter->render_process_id(),
163 parent_iter->render_frame_id()));
164 }
165 }
166 WorkerServiceImpl::GetInstance()->NotifyWorkerDestroyed(
167 this, i->worker_route_id());
168 }
169
170 ChildProcessSecurityPolicyImpl::GetInstance()->Remove(
171 process_->GetData().id);
172 }
173
174 bool WorkerProcessHost::Send(IPC::Message* message) {
175 return process_->Send(message);
176 }
177
178 bool WorkerProcessHost::Init(int render_process_id, int render_frame_id) {
179 std::string channel_id = process_->GetHost()->CreateChannel();
180 if (channel_id.empty())
181 return false;
182
183 #if defined(OS_LINUX)
184 int flags = ChildProcessHost::CHILD_ALLOW_SELF;
185 #else
186 int flags = ChildProcessHost::CHILD_NORMAL;
187 #endif
188
189 base::FilePath exe_path = ChildProcessHost::GetChildPath(flags);
190 if (exe_path.empty())
191 return false;
192
193 CommandLine* cmd_line = new CommandLine(exe_path);
194 cmd_line->AppendSwitchASCII(switches::kProcessType, switches::kWorkerProcess);
195 cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id);
196 std::string locale = GetContentClient()->browser()->GetApplicationLocale();
197 cmd_line->AppendSwitchASCII(switches::kLang, locale);
198
199 static const char* const kSwitchNames[] = {
200 switches::kDisableApplicationCache,
201 switches::kDisableDatabases,
202 #if defined(OS_WIN)
203 switches::kDisableDesktopNotifications,
204 #endif
205 switches::kDisableFileSystem,
206 switches::kDisableSeccompFilterSandbox,
207 switches::kEnableExperimentalWebPlatformFeatures,
208 switches::kEnablePreciseMemoryInfo,
209 #if defined(OS_MACOSX)
210 switches::kEnableSandboxLogging,
211 #endif
212 switches::kJavaScriptFlags,
213 switches::kNoSandbox
214 };
215 cmd_line->CopySwitchesFrom(*CommandLine::ForCurrentProcess(), kSwitchNames,
216 arraysize(kSwitchNames));
217
218 bool debugging_child = false;
219 #if defined(OS_POSIX)
220 if (CommandLine::ForCurrentProcess()->HasSwitch(
221 switches::kWaitForDebuggerChildren)) {
222 // Look to pass-on the kWaitForDebugger flag.
223 std::string value = CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
224 switches::kWaitForDebuggerChildren);
225 if (value.empty() || value == switches::kWorkerProcess) {
226 cmd_line->AppendSwitch(switches::kWaitForDebugger);
227 debugging_child = true;
228 }
229 }
230 #endif
231
232 process_->Launch(
233 new WorkerSandboxedProcessLauncherDelegate(process_->GetHost(),
234 debugging_child),
235 cmd_line);
236
237 ChildProcessSecurityPolicyImpl::GetInstance()->AddWorker(
238 process_->GetData().id, render_process_id);
239 CreateMessageFilters(render_process_id);
240
241 BrowserThread::PostTask(
242 BrowserThread::UI, FROM_HERE,
243 base::Bind(&WorkerCreatedCallback,
244 render_process_id,
245 render_frame_id,
246 process_->GetData().id));
247 return true;
248 }
249
250 void WorkerProcessHost::CreateMessageFilters(int render_process_id) {
251 ChromeBlobStorageContext* blob_storage_context =
252 GetChromeBlobStorageContextForResourceContext(resource_context_);
253 StreamContext* stream_context =
254 GetStreamContextForResourceContext(resource_context_);
255
256 net::URLRequestContextGetter* url_request_context =
257 partition_.url_request_context();
258
259 ResourceMessageFilter::GetContextsCallback get_contexts_callback(
260 base::Bind(&WorkerProcessHost::GetContexts,
261 base::Unretained(this)));
262
263 ResourceMessageFilter* resource_message_filter = new ResourceMessageFilter(
264 process_->GetData().id, PROCESS_TYPE_WORKER,
265 partition_.appcache_service(),
266 blob_storage_context,
267 partition_.filesystem_context(),
268 partition_.service_worker_context(),
269 get_contexts_callback);
270 process_->AddFilter(resource_message_filter);
271
272 MessagePortMessageFilter* message_port_message_filter =
273 new MessagePortMessageFilter(
274 base::Bind(&WorkerServiceImpl::next_worker_route_id,
275 base::Unretained(WorkerServiceImpl::GetInstance())));
276 process_->AddFilter(message_port_message_filter);
277 worker_message_filter_ = new WorkerMessageFilter(render_process_id,
278 resource_context_,
279 partition_,
280 message_port_message_filter);
281 process_->AddFilter(worker_message_filter_.get());
282 process_->AddFilter(new AppCacheDispatcherHost(
283 partition_.appcache_service(), process_->GetData().id));
284 process_->AddFilter(new FileAPIMessageFilter(
285 process_->GetData().id,
286 url_request_context,
287 partition_.filesystem_context(),
288 blob_storage_context,
289 stream_context));
290 process_->AddFilter(new FileUtilitiesMessageFilter(
291 process_->GetData().id));
292 process_->AddFilter(new MimeRegistryMessageFilter());
293 process_->AddFilter(new DatabaseMessageFilter(partition_.database_tracker()));
294 process_->AddFilter(new QuotaDispatcherHost(
295 process_->GetData().id,
296 partition_.quota_manager(),
297 GetContentClient()->browser()->CreateQuotaPermissionContext()));
298
299 SocketStreamDispatcherHost::GetRequestContextCallback
300 request_context_callback(
301 base::Bind(&WorkerProcessHost::GetRequestContext,
302 base::Unretained(this)));
303
304 SocketStreamDispatcherHost* socket_stream_dispatcher_host =
305 new SocketStreamDispatcherHost(
306 render_process_id,
307 request_context_callback,
308 resource_context_);
309 socket_stream_dispatcher_host_ = socket_stream_dispatcher_host;
310 process_->AddFilter(socket_stream_dispatcher_host);
311
312 WebSocketDispatcherHost::GetRequestContextCallback
313 websocket_request_context_callback(
314 base::Bind(&WorkerProcessHost::GetRequestContext,
315 base::Unretained(this),
316 ResourceType::SUB_RESOURCE));
317
318 process_->AddFilter(new WebSocketDispatcherHost(
319 render_process_id, websocket_request_context_callback));
320
321 process_->AddFilter(new WorkerDevToolsMessageFilter(process_->GetData().id));
322 process_->AddFilter(
323 new IndexedDBDispatcherHost(process_->GetData().id,
324 url_request_context,
325 partition_.indexed_db_context(),
326 blob_storage_context));
327 }
328
329 void WorkerProcessHost::CreateWorker(const WorkerInstance& instance,
330 bool pause_on_start) {
331 ChildProcessSecurityPolicyImpl::GetInstance()->GrantRequestURL(
332 process_->GetData().id, instance.url());
333
334 instances_.push_back(instance);
335
336 WorkerProcessMsg_CreateWorker_Params params;
337 params.url = instance.url();
338 params.name = instance.name();
339 params.content_security_policy = instance.content_security_policy();
340 params.security_policy_type = instance.security_policy_type();
341 params.pause_on_start = pause_on_start;
342 params.route_id = instance.worker_route_id();
343 Send(new WorkerProcessMsg_CreateWorker(params));
344
345 UpdateTitle();
346
347 // Walk all pending filters and let them know the worker has been created
348 // (could be more than one in the case where we had to queue up worker
349 // creation because the worker process limit was reached).
350 for (WorkerInstance::FilterList::const_iterator i =
351 instance.filters().begin();
352 i != instance.filters().end(); ++i) {
353 i->filter()->Send(new ViewMsg_WorkerCreated(i->route_id()));
354 }
355 }
356
357 bool WorkerProcessHost::FilterMessage(const IPC::Message& message,
358 WorkerMessageFilter* filter) {
359 for (Instances::iterator i = instances_.begin(); i != instances_.end(); ++i) {
360 if (!i->closed() && i->HasFilter(filter, message.routing_id())) {
361 RelayMessage(message, filter, &(*i));
362 return true;
363 }
364 }
365
366 return false;
367 }
368
369 void WorkerProcessHost::OnProcessLaunched() {
370 process_launched_ = true;
371
372 WorkerServiceImpl::GetInstance()->NotifyWorkerProcessCreated();
373 }
374
375 bool WorkerProcessHost::OnMessageReceived(const IPC::Message& message) {
376 bool handled = true;
377 IPC_BEGIN_MESSAGE_MAP(WorkerProcessHost, message)
378 IPC_MESSAGE_HANDLER(WorkerHostMsg_WorkerContextClosed,
379 OnWorkerContextClosed)
380 IPC_MESSAGE_HANDLER(WorkerHostMsg_WorkerContextDestroyed,
381 OnWorkerContextDestroyed)
382 IPC_MESSAGE_HANDLER(WorkerHostMsg_WorkerScriptLoaded,
383 OnWorkerScriptLoaded)
384 IPC_MESSAGE_HANDLER(WorkerHostMsg_WorkerScriptLoadFailed,
385 OnWorkerScriptLoadFailed)
386 IPC_MESSAGE_HANDLER(WorkerHostMsg_WorkerConnected,
387 OnWorkerConnected)
388 IPC_MESSAGE_HANDLER(WorkerProcessHostMsg_AllowDatabase, OnAllowDatabase)
389 IPC_MESSAGE_HANDLER_DELAY_REPLY(
390 WorkerProcessHostMsg_RequestFileSystemAccessSync,
391 OnRequestFileSystemAccess)
392 IPC_MESSAGE_HANDLER(WorkerProcessHostMsg_AllowIndexedDB, OnAllowIndexedDB)
393 IPC_MESSAGE_HANDLER(WorkerProcessHostMsg_ForceKillWorker,
394 OnForceKillWorkerProcess)
395 IPC_MESSAGE_UNHANDLED(handled = false)
396 IPC_END_MESSAGE_MAP()
397
398 return handled;
399 }
400
401 // Sent to notify the browser process when a worker context invokes close(), so
402 // no new connections are sent to shared workers.
403 void WorkerProcessHost::OnWorkerContextClosed(int worker_route_id) {
404 for (Instances::iterator i = instances_.begin(); i != instances_.end(); ++i) {
405 if (i->worker_route_id() == worker_route_id) {
406 // Set the closed flag - this will stop any further messages from
407 // being sent to the worker (messages can still be sent from the worker,
408 // for exception reporting, etc).
409 i->set_closed(true);
410 break;
411 }
412 }
413 }
414
415 void WorkerProcessHost::OnWorkerContextDestroyed(int worker_route_id) {
416 WorkerServiceImpl::GetInstance()->NotifyWorkerDestroyed(
417 this, worker_route_id);
418 for (Instances::iterator i = instances_.begin(); i != instances_.end(); ++i) {
419 if (i->worker_route_id() == worker_route_id) {
420 instances_.erase(i);
421 UpdateTitle();
422 return;
423 }
424 }
425 }
426
427 void WorkerProcessHost::OnWorkerScriptLoaded(int worker_route_id) {
428 WorkerDevToolsManager::GetInstance()->WorkerContextStarted(this,
429 worker_route_id);
430 }
431
432 void WorkerProcessHost::OnWorkerScriptLoadFailed(int worker_route_id) {
433 bool shutdown = true;
434 for (Instances::iterator i = instances_.begin(); i != instances_.end(); ++i) {
435 if (i->worker_route_id() != worker_route_id) {
436 shutdown = false;
437 continue;
438 }
439 i->set_load_failed(true);
440 for (WorkerInstance::FilterList::const_iterator j = i->filters().begin();
441 j != i->filters().end(); ++j) {
442 j->filter()->Send(new ViewMsg_WorkerScriptLoadFailed(j->route_id()));
443 }
444 }
445 if (shutdown) {
446 base::KillProcess(
447 process_->GetData().handle, RESULT_CODE_NORMAL_EXIT, false);
448 }
449 }
450
451 void WorkerProcessHost::OnWorkerConnected(int message_port_id,
452 int worker_route_id) {
453 for (Instances::iterator i = instances_.begin(); i != instances_.end(); ++i) {
454 if (i->worker_route_id() != worker_route_id)
455 continue;
456 for (WorkerInstance::FilterList::const_iterator j = i->filters().begin();
457 j != i->filters().end(); ++j) {
458 if (j->message_port_id() != message_port_id)
459 continue;
460 j->filter()->Send(new ViewMsg_WorkerConnected(j->route_id()));
461 return;
462 }
463 }
464 }
465
466 void WorkerProcessHost::OnAllowDatabase(int worker_route_id,
467 const GURL& url,
468 const base::string16& name,
469 const base::string16& display_name,
470 unsigned long estimated_size,
471 bool* result) {
472 *result = GetContentClient()->browser()->AllowWorkerDatabase(
473 url, name, display_name, estimated_size, resource_context_,
474 GetRenderFrameIDsForWorker(worker_route_id));
475 }
476
477 void WorkerProcessHost::OnRequestFileSystemAccess(int worker_route_id,
478 const GURL& url,
479 IPC::Message* reply_msg) {
480 GetContentClient()->browser()->AllowWorkerFileSystem(
481 url,
482 resource_context_,
483 GetRenderFrameIDsForWorker(worker_route_id),
484 base::Bind(&WorkerProcessHost::OnRequestFileSystemAccessResponse,
485 weak_factory_.GetWeakPtr(),
486 base::Passed(scoped_ptr<IPC::Message>(reply_msg))));
487 }
488
489 void WorkerProcessHost::OnRequestFileSystemAccessResponse(
490 scoped_ptr<IPC::Message> reply_msg,
491 bool allowed) {
492 WorkerProcessHostMsg_RequestFileSystemAccessSync::WriteReplyParams(
493 reply_msg.get(),
494 allowed);
495 Send(reply_msg.release());
496 }
497
498 void WorkerProcessHost::OnAllowIndexedDB(int worker_route_id,
499 const GURL& url,
500 const base::string16& name,
501 bool* result) {
502 *result = GetContentClient()->browser()->AllowWorkerIndexedDB(
503 url, name, resource_context_,
504 GetRenderFrameIDsForWorker(worker_route_id));
505 }
506
507 void WorkerProcessHost::OnForceKillWorkerProcess() {
508 if (process_ && process_launched_)
509 base::KillProcess(
510 process_->GetData().handle, RESULT_CODE_NORMAL_EXIT, false);
511 else
512 RecordAction(base::UserMetricsAction("WorkerProcess_BadProcessToKill"));
513 }
514
515 void WorkerProcessHost::RelayMessage(
516 const IPC::Message& message,
517 WorkerMessageFilter* incoming_filter,
518 WorkerInstance* instance) {
519 if (message.type() == WorkerMsg_Connect::ID) {
520 // Crack the SharedWorker Connect message to setup routing for the port.
521 WorkerMsg_Connect::Param params;
522 if (!WorkerMsg_Connect::Read(&message, &params))
523 return;
524
525 int sent_message_port_id = params.a;
526 int new_routing_id = params.b;
527 new_routing_id = worker_message_filter_->GetNextRoutingID();
528 MessagePortService::GetInstance()->UpdateMessagePort(
529 sent_message_port_id,
530 worker_message_filter_->message_port_message_filter(),
531 new_routing_id);
532
533 instance->SetMessagePortID(incoming_filter,
534 message.routing_id(),
535 sent_message_port_id);
536 // Resend the message with the new routing id.
537 worker_message_filter_->Send(new WorkerMsg_Connect(
538 instance->worker_route_id(), sent_message_port_id, new_routing_id));
539
540 // Send any queued messages for the sent port.
541 MessagePortService::GetInstance()->SendQueuedMessagesIfPossible(
542 sent_message_port_id);
543 } else {
544 IPC::Message* new_message = new IPC::Message(message);
545 new_message->set_routing_id(instance->worker_route_id());
546 worker_message_filter_->Send(new_message);
547 return;
548 }
549 }
550
551 void WorkerProcessHost::ShutdownSocketStreamDispatcherHostIfNecessary() {
552 if (!instances_.size() && socket_stream_dispatcher_host_.get()) {
553 // We can assume that this object is going to delete, because
554 // currently a WorkerInstance will never be added to a WorkerProcessHost
555 // once it is initialized.
556
557 // SocketStreamDispatcherHost should be notified now that the worker
558 // process will shutdown soon.
559 socket_stream_dispatcher_host_->Shutdown();
560 socket_stream_dispatcher_host_ = NULL;
561 }
562 }
563
564 void WorkerProcessHost::FilterShutdown(WorkerMessageFilter* filter) {
565 for (Instances::iterator i = instances_.begin(); i != instances_.end();) {
566 bool shutdown = false;
567 i->RemoveFilters(filter);
568
569 int render_frame_id = 0;
570 const WorkerDocumentSet::DocumentInfoSet& documents =
571 i->worker_document_set()->documents();
572 for (WorkerDocumentSet::DocumentInfoSet::const_iterator doc =
573 documents.begin(); doc != documents.end(); ++doc) {
574 if (doc->filter() == filter) {
575 render_frame_id = doc->render_frame_id();
576 break;
577 }
578 }
579 i->worker_document_set()->RemoveAll(filter);
580 if (i->worker_document_set()->IsEmpty()) {
581 shutdown = true;
582 }
583 if (shutdown) {
584 BrowserThread::PostTask(
585 BrowserThread::UI, FROM_HERE,
586 base::Bind(&WorkerTerminatedCallback,
587 filter->render_process_id(),
588 render_frame_id,
589 process_->GetData().id));
590 Send(new WorkerMsg_TerminateWorkerContext(i->worker_route_id()));
591 i = instances_.erase(i);
592 } else {
593 ++i;
594 }
595 }
596 ShutdownSocketStreamDispatcherHostIfNecessary();
597 }
598
599 bool WorkerProcessHost::CanShutdown() {
600 return instances_.empty();
601 }
602
603 void WorkerProcessHost::UpdateTitle() {
604 std::set<std::string> titles;
605 for (Instances::iterator i = instances_.begin(); i != instances_.end(); ++i) {
606 // Allow the embedder first crack at special casing the title.
607 std::string title = GetContentClient()->browser()->
608 GetWorkerProcessTitle(i->url(), resource_context_);
609
610 if (title.empty()) {
611 title = net::registry_controlled_domains::GetDomainAndRegistry(
612 i->url(),
613 net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
614 }
615
616 // Use the host name if the domain is empty, i.e. localhost or IP address.
617 if (title.empty())
618 title = i->url().host();
619
620 // If the host name is empty, i.e. file url, use the path.
621 if (title.empty())
622 title = i->url().path();
623 titles.insert(title);
624 }
625
626 std::string display_title;
627 for (std::set<std::string>::iterator i = titles.begin();
628 i != titles.end(); ++i) {
629 if (!display_title.empty())
630 display_title += ", ";
631 display_title += *i;
632 }
633
634 process_->SetName(base::UTF8ToUTF16(display_title));
635 }
636
637 void WorkerProcessHost::DocumentDetached(WorkerMessageFilter* filter,
638 unsigned long long document_id) {
639 // Walk all instances and remove the document from their document set.
640 for (Instances::iterator i = instances_.begin(); i != instances_.end();) {
641 int render_frame_id = 0;
642 const WorkerDocumentSet::DocumentInfoSet& documents =
643 i->worker_document_set()->documents();
644 for (WorkerDocumentSet::DocumentInfoSet::const_iterator doc =
645 documents.begin(); doc != documents.end(); ++doc) {
646 if (doc->filter() == filter && doc->document_id() == document_id) {
647 render_frame_id = doc->render_frame_id();
648 break;
649 }
650 }
651 i->worker_document_set()->Remove(filter, document_id);
652 if (i->worker_document_set()->IsEmpty()) {
653 BrowserThread::PostTask(
654 BrowserThread::UI, FROM_HERE,
655 base::Bind(&WorkerTerminatedCallback,
656 filter->render_process_id(),
657 render_frame_id,
658 process_->GetData().id));
659 // This worker has no more associated documents - shut it down.
660 Send(new WorkerMsg_TerminateWorkerContext(i->worker_route_id()));
661 i = instances_.erase(i);
662 } else {
663 ++i;
664 }
665 }
666 ShutdownSocketStreamDispatcherHostIfNecessary();
667 }
668
669 void WorkerProcessHost::TerminateWorker(int worker_route_id) {
670 Send(new WorkerMsg_TerminateWorkerContext(worker_route_id));
671 }
672
673 void WorkerProcessHost::SetBackgrounded(bool backgrounded) {
674 process_->SetBackgrounded(backgrounded);
675 }
676
677 const ChildProcessData& WorkerProcessHost::GetData() {
678 return process_->GetData();
679 }
680
681 std::vector<std::pair<int, int> > WorkerProcessHost::GetRenderFrameIDsForWorker(
682 int worker_route_id) {
683 std::vector<std::pair<int, int> > result;
684 WorkerProcessHost::Instances::const_iterator i;
685 for (i = instances_.begin(); i != instances_.end(); ++i) {
686 if (i->worker_route_id() != worker_route_id)
687 continue;
688 const WorkerDocumentSet::DocumentInfoSet& documents =
689 i->worker_document_set()->documents();
690 for (WorkerDocumentSet::DocumentInfoSet::const_iterator doc =
691 documents.begin(); doc != documents.end(); ++doc) {
692 result.push_back(
693 std::make_pair(doc->render_process_id(), doc->render_frame_id()));
694 }
695 break;
696 }
697 return result;
698 }
699
700 void WorkerProcessHost::GetContexts(const ResourceHostMsg_Request& request,
701 ResourceContext** resource_context,
702 net::URLRequestContext** request_context) {
703 *resource_context = resource_context_;
704 *request_context = partition_.url_request_context()->GetURLRequestContext();
705 }
706
707 net::URLRequestContext* WorkerProcessHost::GetRequestContext(
708 ResourceType::Type resource_type) {
709 return partition_.url_request_context()->GetURLRequestContext();
710 }
711
712 WorkerProcessHost::WorkerInstance::WorkerInstance(
713 const GURL& url,
714 const base::string16& name,
715 const base::string16& content_security_policy,
716 blink::WebContentSecurityPolicyType security_policy_type,
717 int worker_route_id,
718 int render_frame_id,
719 ResourceContext* resource_context,
720 const WorkerStoragePartition& partition)
721 : url_(url),
722 closed_(false),
723 name_(name),
724 content_security_policy_(content_security_policy),
725 security_policy_type_(security_policy_type),
726 worker_route_id_(worker_route_id),
727 render_frame_id_(render_frame_id),
728 worker_document_set_(new WorkerDocumentSet()),
729 resource_context_(resource_context),
730 partition_(partition),
731 load_failed_(false) {
732 DCHECK(resource_context_);
733 }
734
735 WorkerProcessHost::WorkerInstance::~WorkerInstance() {
736 }
737
738 void WorkerProcessHost::WorkerInstance::SetMessagePortID(
739 WorkerMessageFilter* filter,
740 int route_id,
741 int message_port_id) {
742 for (FilterList::iterator i = filters_.begin(); i != filters_.end(); ++i) {
743 if (i->filter() == filter && i->route_id() == route_id) {
744 i->set_message_port_id(message_port_id);
745 return;
746 }
747 }
748 }
749
750 // Compares an instance based on the algorithm in the WebWorkers spec - an
751 // instance matches if the origins of the URLs match, and:
752 // a) the names are non-empty and equal
753 // -or-
754 // b) the names are both empty, and the urls are equal
755 bool WorkerProcessHost::WorkerInstance::Matches(
756 const GURL& match_url,
757 const base::string16& match_name,
758 const WorkerStoragePartition& partition,
759 ResourceContext* resource_context) const {
760 // Only match open shared workers.
761 if (closed_)
762 return false;
763
764 // ResourceContext equivalence is being used as a proxy to ensure we only
765 // matched shared workers within the same BrowserContext.
766 if (resource_context_ != resource_context)
767 return false;
768
769 // We must be in the same storage partition otherwise sharing will violate
770 // isolation.
771 if (!partition_.Equals(partition))
772 return false;
773
774 if (url_.GetOrigin() != match_url.GetOrigin())
775 return false;
776
777 if (name_.empty() && match_name.empty())
778 return url_ == match_url;
779
780 return name_ == match_name;
781 }
782
783 void WorkerProcessHost::WorkerInstance::AddFilter(WorkerMessageFilter* filter,
784 int route_id) {
785 CHECK(filter);
786 if (!HasFilter(filter, route_id)) {
787 FilterInfo info(filter, route_id);
788 filters_.push_back(info);
789 }
790 }
791
792 void WorkerProcessHost::WorkerInstance::RemoveFilter(
793 WorkerMessageFilter* filter, int route_id) {
794 for (FilterList::iterator i = filters_.begin(); i != filters_.end();) {
795 if (i->filter() == filter && i->route_id() == route_id)
796 i = filters_.erase(i);
797 else
798 ++i;
799 }
800 // Should not be duplicate copies in the filter set.
801 DCHECK(!HasFilter(filter, route_id));
802 }
803
804 void WorkerProcessHost::WorkerInstance::RemoveFilters(
805 WorkerMessageFilter* filter) {
806 for (FilterList::iterator i = filters_.begin(); i != filters_.end();) {
807 if (i->filter() == filter)
808 i = filters_.erase(i);
809 else
810 ++i;
811 }
812 }
813
814 bool WorkerProcessHost::WorkerInstance::HasFilter(
815 WorkerMessageFilter* filter, int route_id) const {
816 for (FilterList::const_iterator i = filters_.begin(); i != filters_.end();
817 ++i) {
818 if (i->filter() == filter && i->route_id() == route_id)
819 return true;
820 }
821 return false;
822 }
823
824 bool WorkerProcessHost::WorkerInstance::FrameIsParent(
825 int render_process_id, int render_frame_id) const {
826 const WorkerDocumentSet::DocumentInfoSet& parents =
827 worker_document_set()->documents();
828 for (WorkerDocumentSet::DocumentInfoSet::const_iterator parent_iter =
829 parents.begin();
830 parent_iter != parents.end(); ++parent_iter) {
831 if (parent_iter->render_process_id() == render_process_id &&
832 parent_iter->render_frame_id() == render_frame_id) {
833 return true;
834 }
835 }
836 return false;
837 }
838
839 WorkerProcessHost::WorkerInstance::FilterInfo
840 WorkerProcessHost::WorkerInstance::GetFilter() const {
841 DCHECK(NumFilters() == 1);
842 return *filters_.begin();
843 }
844
845 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/worker_host/worker_process_host.h ('k') | content/browser/worker_host/worker_service_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698