Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / content / browser / service_worker / service_worker_dispatcher_host.cc
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
3 // found in the LICENSE file.
4
5 #include "content/browser/service_worker/service_worker_dispatcher_host.h"
6
7 #include "base/debug/trace_event.h"
8 #include "base/logging.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "content/browser/message_port_message_filter.h"
11 #include "content/browser/message_port_service.h"
12 #include "content/browser/service_worker/embedded_worker_registry.h"
13 #include "content/browser/service_worker/service_worker_context_core.h"
14 #include "content/browser/service_worker/service_worker_context_wrapper.h"
15 #include "content/browser/service_worker/service_worker_handle.h"
16 #include "content/browser/service_worker/service_worker_registration.h"
17 #include "content/browser/service_worker/service_worker_registration_handle.h"
18 #include "content/browser/service_worker/service_worker_utils.h"
19 #include "content/common/service_worker/embedded_worker_messages.h"
20 #include "content/common/service_worker/service_worker_messages.h"
21 #include "content/public/browser/content_browser_client.h"
22 #include "content/public/common/content_client.h"
23 #include "ipc/ipc_message_macros.h"
24 #include "net/base/net_util.h"
25 #include "third_party/WebKit/public/platform/WebServiceWorkerError.h"
26 #include "url/gurl.h"
27
28 using blink::WebServiceWorkerError;
29
30 namespace content {
31
32 namespace {
33
34 const char kShutdownErrorMessage[] =
35     "The Service Worker system has shutdown.";
36 const char kDisabledErrorMessage[] = "The browser has disabled Service Worker.";
37
38 const uint32 kFilteredMessageClasses[] = {
39   ServiceWorkerMsgStart,
40   EmbeddedWorkerMsgStart,
41 };
42
43 bool AllOriginsMatch(const GURL& url_a, const GURL& url_b, const GURL& url_c) {
44   return url_a.GetOrigin() == url_b.GetOrigin() &&
45          url_a.GetOrigin() == url_c.GetOrigin();
46 }
47
48 // TODO(dominicc): When crbug.com/362214 is fixed use that to be
49 // consistent with Blink's
50 // SecurityOrigin::canAccessFeatureRequiringSecureOrigin.
51 bool OriginCanAccessServiceWorkers(const GURL& url) {
52   return url.SchemeIsSecure() || net::IsLocalhost(url.host());
53 }
54
55 bool CheckPatternIsUnderTheScriptDirectory(const GURL& pattern,
56                                            const GURL& script_url) {
57   size_t slash_pos = script_url.spec().rfind('/');
58   if (slash_pos == std::string::npos)
59     return false;
60   return pattern.spec().compare(
61              0, slash_pos + 1, script_url.spec(), 0, slash_pos + 1) == 0;
62 }
63
64 bool CanRegisterServiceWorker(const GURL& document_url,
65                               const GURL& pattern,
66                               const GURL& script_url) {
67   DCHECK(document_url.is_valid());
68   DCHECK(pattern.is_valid());
69   DCHECK(script_url.is_valid());
70   return AllOriginsMatch(document_url, pattern, script_url) &&
71          OriginCanAccessServiceWorkers(document_url) &&
72          CheckPatternIsUnderTheScriptDirectory(pattern, script_url);
73 }
74
75 bool CanUnregisterServiceWorker(const GURL& document_url,
76                                 const GURL& pattern) {
77   DCHECK(document_url.is_valid());
78   DCHECK(pattern.is_valid());
79   return document_url.GetOrigin() == pattern.GetOrigin() &&
80          OriginCanAccessServiceWorkers(document_url);
81 }
82
83 bool CanGetRegistration(const GURL& document_url,
84                         const GURL& given_document_url) {
85   DCHECK(document_url.is_valid());
86   DCHECK(given_document_url.is_valid());
87   return document_url.GetOrigin() == given_document_url.GetOrigin() &&
88          OriginCanAccessServiceWorkers(document_url);
89 }
90
91 }  // namespace
92
93 ServiceWorkerDispatcherHost::ServiceWorkerDispatcherHost(
94     int render_process_id,
95     MessagePortMessageFilter* message_port_message_filter,
96     ResourceContext* resource_context)
97     : BrowserMessageFilter(kFilteredMessageClasses,
98                            arraysize(kFilteredMessageClasses)),
99       render_process_id_(render_process_id),
100       message_port_message_filter_(message_port_message_filter),
101       resource_context_(resource_context),
102       channel_ready_(false) {
103 }
104
105 ServiceWorkerDispatcherHost::~ServiceWorkerDispatcherHost() {
106   if (GetContext()) {
107     GetContext()->RemoveAllProviderHostsForProcess(render_process_id_);
108     GetContext()->embedded_worker_registry()->RemoveChildProcessSender(
109         render_process_id_);
110   }
111 }
112
113 void ServiceWorkerDispatcherHost::Init(
114     ServiceWorkerContextWrapper* context_wrapper) {
115   if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
116     BrowserThread::PostTask(
117         BrowserThread::IO, FROM_HERE,
118         base::Bind(&ServiceWorkerDispatcherHost::Init,
119                    this, make_scoped_refptr(context_wrapper)));
120     return;
121   }
122
123   context_wrapper_ = context_wrapper;
124   GetContext()->embedded_worker_registry()->AddChildProcessSender(
125       render_process_id_, this);
126 }
127
128 void ServiceWorkerDispatcherHost::OnFilterAdded(IPC::Sender* sender) {
129   TRACE_EVENT0("ServiceWorker",
130                "ServiceWorkerDispatcherHost::OnFilterAdded");
131   channel_ready_ = true;
132   std::vector<IPC::Message*> messages;
133   pending_messages_.release(&messages);
134   for (size_t i = 0; i < messages.size(); ++i) {
135     BrowserMessageFilter::Send(messages[i]);
136   }
137 }
138
139 void ServiceWorkerDispatcherHost::OnFilterRemoved() {
140   // Don't wait until the destructor to teardown since a new dispatcher host
141   // for this process might be created before then.
142   if (GetContext()) {
143     GetContext()->RemoveAllProviderHostsForProcess(render_process_id_);
144     GetContext()->embedded_worker_registry()->RemoveChildProcessSender(
145         render_process_id_);
146   }
147   context_wrapper_ = nullptr;
148   channel_ready_ = false;
149 }
150
151 void ServiceWorkerDispatcherHost::OnDestruct() const {
152   BrowserThread::DeleteOnIOThread::Destruct(this);
153 }
154
155 bool ServiceWorkerDispatcherHost::OnMessageReceived(
156     const IPC::Message& message) {
157   bool handled = true;
158   IPC_BEGIN_MESSAGE_MAP(ServiceWorkerDispatcherHost, message)
159     IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_RegisterServiceWorker,
160                         OnRegisterServiceWorker)
161     IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_UnregisterServiceWorker,
162                         OnUnregisterServiceWorker)
163     IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_GetRegistration,
164                         OnGetRegistration)
165     IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_ProviderCreated,
166                         OnProviderCreated)
167     IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_ProviderDestroyed,
168                         OnProviderDestroyed)
169     IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_SetVersionId,
170                         OnSetHostedVersionId)
171     IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_PostMessageToWorker,
172                         OnPostMessageToWorker)
173     IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerReadyForInspection,
174                         OnWorkerReadyForInspection)
175     IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerScriptLoaded,
176                         OnWorkerScriptLoaded)
177     IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerScriptLoadFailed,
178                         OnWorkerScriptLoadFailed)
179     IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerScriptEvaluated,
180                         OnWorkerScriptEvaluated)
181     IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerStarted,
182                         OnWorkerStarted)
183     IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerStopped,
184                         OnWorkerStopped)
185     IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_DidPauseAfterDownload,
186                         OnPausedAfterDownload)
187     IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_ReportException,
188                         OnReportException)
189     IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_ReportConsoleMessage,
190                         OnReportConsoleMessage)
191     IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_IncrementServiceWorkerRefCount,
192                         OnIncrementServiceWorkerRefCount)
193     IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_DecrementServiceWorkerRefCount,
194                         OnDecrementServiceWorkerRefCount)
195     IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_IncrementRegistrationRefCount,
196                         OnIncrementRegistrationRefCount)
197     IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_DecrementRegistrationRefCount,
198                         OnDecrementRegistrationRefCount)
199     IPC_MESSAGE_UNHANDLED(handled = false)
200   IPC_END_MESSAGE_MAP()
201
202   if (!handled && GetContext()) {
203     handled =
204         GetContext()->embedded_worker_registry()->OnMessageReceived(message);
205     if (!handled)
206       BadMessageReceived();
207   }
208
209   return handled;
210 }
211
212 bool ServiceWorkerDispatcherHost::Send(IPC::Message* message) {
213   if (channel_ready_) {
214     BrowserMessageFilter::Send(message);
215     // Don't bother passing through Send()'s result: it's not reliable.
216     return true;
217   }
218
219   pending_messages_.push_back(message);
220   return true;
221 }
222
223 ServiceWorkerRegistrationHandle*
224 ServiceWorkerDispatcherHost::GetOrCreateRegistrationHandle(
225     int provider_id,
226     ServiceWorkerRegistration* registration) {
227   ServiceWorkerRegistrationHandle* handle =
228       FindRegistrationHandle(provider_id, registration->id());
229   if (handle) {
230     handle->IncrementRefCount();
231     return handle;
232   }
233
234   scoped_ptr<ServiceWorkerRegistrationHandle> new_handle(
235       new ServiceWorkerRegistrationHandle(
236           GetContext()->AsWeakPtr(), this, provider_id, registration));
237   handle = new_handle.get();
238   RegisterServiceWorkerRegistrationHandle(new_handle.Pass());
239   return handle;
240 }
241
242 void ServiceWorkerDispatcherHost::RegisterServiceWorkerHandle(
243     scoped_ptr<ServiceWorkerHandle> handle) {
244   int handle_id = handle->handle_id();
245   handles_.AddWithID(handle.release(), handle_id);
246 }
247
248 void ServiceWorkerDispatcherHost::RegisterServiceWorkerRegistrationHandle(
249     scoped_ptr<ServiceWorkerRegistrationHandle> handle) {
250   int handle_id = handle->handle_id();
251   registration_handles_.AddWithID(handle.release(), handle_id);
252 }
253
254 void ServiceWorkerDispatcherHost::OnRegisterServiceWorker(
255     int thread_id,
256     int request_id,
257     int provider_id,
258     const GURL& pattern,
259     const GURL& script_url) {
260   TRACE_EVENT0("ServiceWorker",
261                "ServiceWorkerDispatcherHost::OnRegisterServiceWorker");
262   if (!GetContext()) {
263     Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
264         thread_id,
265         request_id,
266         WebServiceWorkerError::ErrorTypeAbort,
267         base::ASCIIToUTF16(kShutdownErrorMessage)));
268     return;
269   }
270   if (!pattern.is_valid() || !script_url.is_valid()) {
271     BadMessageReceived();
272     return;
273   }
274
275   ServiceWorkerProviderHost* provider_host = GetContext()->GetProviderHost(
276       render_process_id_, provider_id);
277   if (!provider_host) {
278     BadMessageReceived();
279     return;
280   }
281   if (!provider_host->IsContextAlive()) {
282     Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
283         thread_id,
284         request_id,
285         WebServiceWorkerError::ErrorTypeAbort,
286         base::ASCIIToUTF16(kShutdownErrorMessage)));
287     return;
288   }
289
290   if (!CanRegisterServiceWorker(
291       provider_host->document_url(), pattern, script_url)) {
292     BadMessageReceived();
293     return;
294   }
295
296   if (!GetContentClient()->browser()->AllowServiceWorker(
297           pattern, provider_host->topmost_frame_url(), resource_context_)) {
298     Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
299         thread_id,
300         request_id,
301         WebServiceWorkerError::ErrorTypeDisabled,
302         base::ASCIIToUTF16(kDisabledErrorMessage)));
303     return;
304   }
305
306   TRACE_EVENT_ASYNC_BEGIN2("ServiceWorker",
307                            "ServiceWorkerDispatcherHost::RegisterServiceWorker",
308                            request_id,
309                            "Pattern", pattern.spec(),
310                            "Script URL", script_url.spec());
311   GetContext()->RegisterServiceWorker(
312       pattern,
313       script_url,
314       provider_host,
315       base::Bind(&ServiceWorkerDispatcherHost::RegistrationComplete,
316                  this,
317                  thread_id,
318                  provider_id,
319                  request_id));
320 }
321
322 void ServiceWorkerDispatcherHost::OnUnregisterServiceWorker(
323     int thread_id,
324     int request_id,
325     int provider_id,
326     const GURL& pattern) {
327   TRACE_EVENT0("ServiceWorker",
328                "ServiceWorkerDispatcherHost::OnUnregisterServiceWorker");
329   if (!GetContext()) {
330     Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
331         thread_id,
332         request_id,
333         blink::WebServiceWorkerError::ErrorTypeAbort,
334         base::ASCIIToUTF16(kShutdownErrorMessage)));
335     return;
336   }
337   if (!pattern.is_valid()) {
338     BadMessageReceived();
339     return;
340   }
341
342   ServiceWorkerProviderHost* provider_host = GetContext()->GetProviderHost(
343       render_process_id_, provider_id);
344   if (!provider_host) {
345     BadMessageReceived();
346     return;
347   }
348   if (!provider_host->IsContextAlive()) {
349     Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
350         thread_id,
351         request_id,
352         blink::WebServiceWorkerError::ErrorTypeAbort,
353         base::ASCIIToUTF16(kShutdownErrorMessage)));
354     return;
355   }
356
357   if (!CanUnregisterServiceWorker(provider_host->document_url(), pattern)) {
358     BadMessageReceived();
359     return;
360   }
361
362   if (!GetContentClient()->browser()->AllowServiceWorker(
363           pattern, provider_host->topmost_frame_url(), resource_context_)) {
364     Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
365         thread_id,
366         request_id,
367         WebServiceWorkerError::ErrorTypeDisabled,
368         base::ASCIIToUTF16(kDisabledErrorMessage)));
369     return;
370   }
371
372   TRACE_EVENT_ASYNC_BEGIN1(
373       "ServiceWorker",
374       "ServiceWorkerDispatcherHost::UnregisterServiceWorker",
375       request_id,
376       "Pattern", pattern.spec());
377   GetContext()->UnregisterServiceWorker(
378       pattern,
379       base::Bind(&ServiceWorkerDispatcherHost::UnregistrationComplete,
380                  this,
381                  thread_id,
382                  request_id));
383 }
384
385 void ServiceWorkerDispatcherHost::OnGetRegistration(
386     int thread_id,
387     int request_id,
388     int provider_id,
389     const GURL& document_url) {
390   TRACE_EVENT0("ServiceWorker",
391                "ServiceWorkerDispatcherHost::OnGetRegistration");
392   if (!GetContext()) {
393     Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
394         thread_id,
395         request_id,
396         blink::WebServiceWorkerError::ErrorTypeAbort,
397         base::ASCIIToUTF16(kShutdownErrorMessage)));
398     return;
399   }
400   if (!document_url.is_valid()) {
401     BadMessageReceived();
402     return;
403   }
404
405   ServiceWorkerProviderHost* provider_host = GetContext()->GetProviderHost(
406       render_process_id_, provider_id);
407   if (!provider_host) {
408     BadMessageReceived();
409     return;
410   }
411   if (!provider_host->IsContextAlive()) {
412     Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
413         thread_id,
414         request_id,
415         blink::WebServiceWorkerError::ErrorTypeAbort,
416         base::ASCIIToUTF16(kShutdownErrorMessage)));
417     return;
418   }
419
420   if (!CanGetRegistration(provider_host->document_url(), document_url)) {
421     BadMessageReceived();
422     return;
423   }
424
425   if (!GetContentClient()->browser()->AllowServiceWorker(
426           provider_host->document_url(),
427           provider_host->topmost_frame_url(),
428           resource_context_)) {
429     Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
430         thread_id,
431         request_id,
432         WebServiceWorkerError::ErrorTypeDisabled,
433         base::ASCIIToUTF16(kDisabledErrorMessage)));
434     return;
435   }
436
437   DCHECK_CURRENTLY_ON(BrowserThread::IO);
438   if (GetContext()->storage()->IsDisabled()) {
439     SendGetRegistrationError(thread_id, request_id, SERVICE_WORKER_ERROR_ABORT);
440     return;
441   }
442
443   TRACE_EVENT_ASYNC_BEGIN1(
444       "ServiceWorker",
445       "ServiceWorkerDispatcherHost::GetRegistration",
446       request_id,
447       "Document URL", document_url.spec());
448
449   GetContext()->storage()->FindRegistrationForDocument(
450       document_url,
451       base::Bind(&ServiceWorkerDispatcherHost::GetRegistrationComplete,
452                  this,
453                  thread_id,
454                  provider_id,
455                  request_id));
456 }
457
458 void ServiceWorkerDispatcherHost::OnPostMessageToWorker(
459     int handle_id,
460     const base::string16& message,
461     const std::vector<int>& sent_message_port_ids) {
462   TRACE_EVENT0("ServiceWorker",
463                "ServiceWorkerDispatcherHost::OnPostMessageToWorker");
464   if (!GetContext())
465     return;
466
467   ServiceWorkerHandle* handle = handles_.Lookup(handle_id);
468   if (!handle) {
469     BadMessageReceived();
470     return;
471   }
472
473   std::vector<int> new_routing_ids;
474   message_port_message_filter_->UpdateMessagePortsWithNewRoutes(
475       sent_message_port_ids, &new_routing_ids);
476   handle->version()->SendMessage(
477       ServiceWorkerMsg_MessageToWorker(message,
478                                        sent_message_port_ids,
479                                        new_routing_ids),
480       base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
481 }
482
483 void ServiceWorkerDispatcherHost::OnProviderCreated(int provider_id) {
484   TRACE_EVENT0("ServiceWorker",
485                "ServiceWorkerDispatcherHost::OnProviderCreated");
486   if (!GetContext())
487     return;
488   if (GetContext()->GetProviderHost(render_process_id_, provider_id)) {
489     BadMessageReceived();
490     return;
491   }
492   scoped_ptr<ServiceWorkerProviderHost> provider_host(
493       new ServiceWorkerProviderHost(
494           render_process_id_, provider_id, GetContext()->AsWeakPtr(), this));
495   GetContext()->AddProviderHost(provider_host.Pass());
496 }
497
498 void ServiceWorkerDispatcherHost::OnProviderDestroyed(int provider_id) {
499   TRACE_EVENT0("ServiceWorker",
500                "ServiceWorkerDispatcherHost::OnProviderDestroyed");
501   if (!GetContext())
502     return;
503   if (!GetContext()->GetProviderHost(render_process_id_, provider_id)) {
504     BadMessageReceived();
505     return;
506   }
507   GetContext()->RemoveProviderHost(render_process_id_, provider_id);
508 }
509
510 void ServiceWorkerDispatcherHost::OnSetHostedVersionId(
511     int provider_id, int64 version_id) {
512   TRACE_EVENT0("ServiceWorker",
513                "ServiceWorkerDispatcherHost::OnSetHostedVersionId");
514   if (!GetContext())
515     return;
516   ServiceWorkerProviderHost* provider_host =
517       GetContext()->GetProviderHost(render_process_id_, provider_id);
518   if (!provider_host) {
519     BadMessageReceived();
520     return;
521   }
522   if (!provider_host->IsContextAlive())
523     return;
524   if (!provider_host->SetHostedVersionId(version_id))
525     BadMessageReceived();
526 }
527
528 ServiceWorkerRegistrationHandle*
529 ServiceWorkerDispatcherHost::FindRegistrationHandle(int provider_id,
530                                                     int64 registration_id) {
531   for (IDMap<ServiceWorkerRegistrationHandle, IDMapOwnPointer>::iterator
532            iter(&registration_handles_);
533        !iter.IsAtEnd();
534        iter.Advance()) {
535     ServiceWorkerRegistrationHandle* handle = iter.GetCurrentValue();
536     DCHECK(handle);
537     if (handle->provider_id() == provider_id && handle->registration() &&
538         handle->registration()->id() == registration_id) {
539       return handle;
540     }
541   }
542   return NULL;
543 }
544
545 void ServiceWorkerDispatcherHost::GetRegistrationObjectInfoAndVersionAttributes(
546     int provider_id,
547     ServiceWorkerRegistration* registration,
548     ServiceWorkerRegistrationObjectInfo* info,
549     ServiceWorkerVersionAttributes* attrs) {
550   ServiceWorkerRegistrationHandle* handle =
551     GetOrCreateRegistrationHandle(provider_id, registration);
552   *info = handle->GetObjectInfo();
553
554   attrs->installing = handle->CreateServiceWorkerHandleAndPass(
555       registration->installing_version());
556   attrs->waiting = handle->CreateServiceWorkerHandleAndPass(
557       registration->waiting_version());
558   attrs->active = handle->CreateServiceWorkerHandleAndPass(
559       registration->active_version());
560 }
561
562 void ServiceWorkerDispatcherHost::RegistrationComplete(
563     int thread_id,
564     int provider_id,
565     int request_id,
566     ServiceWorkerStatusCode status,
567     int64 registration_id) {
568   if (!GetContext())
569     return;
570
571   if (status != SERVICE_WORKER_OK) {
572     SendRegistrationError(thread_id, request_id, status);
573     return;
574   }
575
576   ServiceWorkerRegistration* registration =
577       GetContext()->GetLiveRegistration(registration_id);
578   DCHECK(registration);
579
580   ServiceWorkerRegistrationObjectInfo info;
581   ServiceWorkerVersionAttributes attrs;
582   GetRegistrationObjectInfoAndVersionAttributes(
583       provider_id, registration, &info, &attrs);
584
585   Send(new ServiceWorkerMsg_ServiceWorkerRegistered(
586       thread_id, request_id, info, attrs));
587   TRACE_EVENT_ASYNC_END1("ServiceWorker",
588                          "ServiceWorkerDispatcherHost::RegisterServiceWorker",
589                          request_id,
590                          "Registration ID",
591                          registration_id);
592 }
593
594 void ServiceWorkerDispatcherHost::OnWorkerReadyForInspection(
595     int embedded_worker_id) {
596   TRACE_EVENT0("ServiceWorker",
597                "ServiceWorkerDispatcherHost::OnWorkerReadyForInspection");
598   if (!GetContext())
599     return;
600   EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
601   if (!registry->CanHandle(embedded_worker_id))
602     return;
603   registry->OnWorkerReadyForInspection(render_process_id_, embedded_worker_id);
604 }
605
606 void ServiceWorkerDispatcherHost::OnWorkerScriptLoaded(
607     int embedded_worker_id,
608     int thread_id) {
609   TRACE_EVENT0("ServiceWorker",
610                "ServiceWorkerDispatcherHost::OnWorkerScriptLoaded");
611   if (!GetContext())
612     return;
613   EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
614   if (!registry->CanHandle(embedded_worker_id))
615     return;
616   registry->OnWorkerScriptLoaded(
617       render_process_id_, thread_id, embedded_worker_id);
618 }
619
620 void ServiceWorkerDispatcherHost::OnWorkerScriptLoadFailed(
621     int embedded_worker_id) {
622   TRACE_EVENT0("ServiceWorker",
623                "ServiceWorkerDispatcherHost::OnWorkerScriptLoadFailed");
624   if (!GetContext())
625     return;
626   EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
627   if (!registry->CanHandle(embedded_worker_id))
628     return;
629   registry->OnWorkerScriptLoadFailed(render_process_id_, embedded_worker_id);
630 }
631
632 void ServiceWorkerDispatcherHost::OnWorkerScriptEvaluated(
633     int embedded_worker_id,
634     bool success) {
635   TRACE_EVENT0("ServiceWorker",
636                "ServiceWorkerDispatcherHost::OnWorkerScriptEvaluated");
637   if (!GetContext())
638     return;
639   EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
640   if (!registry->CanHandle(embedded_worker_id))
641     return;
642   registry->OnWorkerScriptEvaluated(
643       render_process_id_, embedded_worker_id, success);
644 }
645
646 void ServiceWorkerDispatcherHost::OnWorkerStarted(int embedded_worker_id) {
647   TRACE_EVENT0("ServiceWorker",
648                "ServiceWorkerDispatcherHost::OnWorkerStarted");
649   if (!GetContext())
650     return;
651   EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
652   if (!registry->CanHandle(embedded_worker_id))
653     return;
654   registry->OnWorkerStarted(render_process_id_, embedded_worker_id);
655 }
656
657 void ServiceWorkerDispatcherHost::OnWorkerStopped(int embedded_worker_id) {
658   TRACE_EVENT0("ServiceWorker",
659                "ServiceWorkerDispatcherHost::OnWorkerStopped");
660   if (!GetContext())
661     return;
662   EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
663   if (!registry->CanHandle(embedded_worker_id))
664     return;
665   registry->OnWorkerStopped(render_process_id_, embedded_worker_id);
666 }
667
668 void ServiceWorkerDispatcherHost::OnPausedAfterDownload(
669     int embedded_worker_id) {
670   TRACE_EVENT0("ServiceWorker",
671                "ServiceWorkerDispatcherHost::OnPausedAfterDownload");
672   if (!GetContext())
673     return;
674   GetContext()->embedded_worker_registry()->OnPausedAfterDownload(
675       render_process_id_, embedded_worker_id);
676 }
677
678 void ServiceWorkerDispatcherHost::OnReportException(
679     int embedded_worker_id,
680     const base::string16& error_message,
681     int line_number,
682     int column_number,
683     const GURL& source_url) {
684   TRACE_EVENT0("ServiceWorker",
685                "ServiceWorkerDispatcherHost::OnReportException");
686   if (!GetContext())
687     return;
688   EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
689   if (!registry->CanHandle(embedded_worker_id))
690     return;
691   registry->OnReportException(embedded_worker_id,
692                               error_message,
693                               line_number,
694                               column_number,
695                               source_url);
696 }
697
698 void ServiceWorkerDispatcherHost::OnReportConsoleMessage(
699     int embedded_worker_id,
700     const EmbeddedWorkerHostMsg_ReportConsoleMessage_Params& params) {
701   TRACE_EVENT0("ServiceWorker",
702                "ServiceWorkerDispatcherHost::OnReportConsoleMessage");
703   if (!GetContext())
704     return;
705   EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry();
706   if (!registry->CanHandle(embedded_worker_id))
707     return;
708   registry->OnReportConsoleMessage(embedded_worker_id,
709                                    params.source_identifier,
710                                    params.message_level,
711                                    params.message,
712                                    params.line_number,
713                                    params.source_url);
714 }
715
716 void ServiceWorkerDispatcherHost::OnIncrementServiceWorkerRefCount(
717     int handle_id) {
718   TRACE_EVENT0("ServiceWorker",
719                "ServiceWorkerDispatcherHost::OnIncrementServiceWorkerRefCount");
720   ServiceWorkerHandle* handle = handles_.Lookup(handle_id);
721   if (!handle) {
722     BadMessageReceived();
723     return;
724   }
725   handle->IncrementRefCount();
726 }
727
728 void ServiceWorkerDispatcherHost::OnDecrementServiceWorkerRefCount(
729     int handle_id) {
730   TRACE_EVENT0("ServiceWorker",
731                "ServiceWorkerDispatcherHost::OnDecrementServiceWorkerRefCount");
732   ServiceWorkerHandle* handle = handles_.Lookup(handle_id);
733   if (!handle) {
734     BadMessageReceived();
735     return;
736   }
737   handle->DecrementRefCount();
738   if (handle->HasNoRefCount())
739     handles_.Remove(handle_id);
740 }
741
742 void ServiceWorkerDispatcherHost::OnIncrementRegistrationRefCount(
743     int registration_handle_id) {
744   TRACE_EVENT0("ServiceWorker",
745                "ServiceWorkerDispatcherHost::OnIncrementRegistrationRefCount");
746   ServiceWorkerRegistrationHandle* handle =
747       registration_handles_.Lookup(registration_handle_id);
748   if (!handle) {
749     BadMessageReceived();
750     return;
751   }
752   handle->IncrementRefCount();
753 }
754
755 void ServiceWorkerDispatcherHost::OnDecrementRegistrationRefCount(
756     int registration_handle_id) {
757   TRACE_EVENT0("ServiceWorker",
758                "ServiceWorkerDispatcherHost::OnDecrementRegistrationRefCount");
759   ServiceWorkerRegistrationHandle* handle =
760       registration_handles_.Lookup(registration_handle_id);
761   if (!handle) {
762     BadMessageReceived();
763     return;
764   }
765   handle->DecrementRefCount();
766   if (handle->HasNoRefCount())
767     registration_handles_.Remove(registration_handle_id);
768 }
769
770 void ServiceWorkerDispatcherHost::UnregistrationComplete(
771     int thread_id,
772     int request_id,
773     ServiceWorkerStatusCode status) {
774   if (status != SERVICE_WORKER_OK && status != SERVICE_WORKER_ERROR_NOT_FOUND) {
775     SendUnregistrationError(thread_id, request_id, status);
776     return;
777   }
778   const bool is_success = (status == SERVICE_WORKER_OK);
779   Send(new ServiceWorkerMsg_ServiceWorkerUnregistered(thread_id,
780                                                       request_id,
781                                                       is_success));
782   TRACE_EVENT_ASYNC_END1(
783       "ServiceWorker",
784       "ServiceWorkerDispatcherHost::UnregisterServiceWorker",
785       request_id,
786       "Status", status);
787 }
788
789 void ServiceWorkerDispatcherHost::GetRegistrationComplete(
790     int thread_id,
791     int provider_id,
792     int request_id,
793     ServiceWorkerStatusCode status,
794     const scoped_refptr<ServiceWorkerRegistration>& registration) {
795   TRACE_EVENT_ASYNC_END1("ServiceWorker",
796                          "ServiceWorkerDispatcherHost::GetRegistration",
797                          request_id,
798                          "Registration ID",
799                          registration.get() ? registration->id()
800                              : kInvalidServiceWorkerRegistrationId);
801
802   if (!GetContext())
803     return;
804
805   if (status != SERVICE_WORKER_OK && status != SERVICE_WORKER_ERROR_NOT_FOUND) {
806     SendGetRegistrationError(thread_id, request_id, status);
807     return;
808   }
809
810   ServiceWorkerRegistrationObjectInfo info;
811   ServiceWorkerVersionAttributes attrs;
812   if (status == SERVICE_WORKER_OK) {
813     DCHECK(registration.get());
814     if (!registration->is_uninstalling()) {
815       GetRegistrationObjectInfoAndVersionAttributes(
816           provider_id, registration.get(), &info, &attrs);
817     }
818   }
819
820   Send(new ServiceWorkerMsg_DidGetRegistration(
821       thread_id, request_id, info, attrs));
822 }
823
824 void ServiceWorkerDispatcherHost::SendRegistrationError(
825     int thread_id,
826     int request_id,
827     ServiceWorkerStatusCode status) {
828   base::string16 error_message;
829   blink::WebServiceWorkerError::ErrorType error_type;
830   GetServiceWorkerRegistrationStatusResponse(
831       status, &error_type, &error_message);
832   Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
833       thread_id, request_id, error_type, error_message));
834 }
835
836 void ServiceWorkerDispatcherHost::SendUnregistrationError(
837     int thread_id,
838     int request_id,
839     ServiceWorkerStatusCode status) {
840   base::string16 error_message;
841   blink::WebServiceWorkerError::ErrorType error_type;
842   GetServiceWorkerRegistrationStatusResponse(
843       status, &error_type, &error_message);
844   Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
845       thread_id, request_id, error_type, error_message));
846 }
847
848 void ServiceWorkerDispatcherHost::SendGetRegistrationError(
849     int thread_id,
850     int request_id,
851     ServiceWorkerStatusCode status) {
852   base::string16 error_message;
853   blink::WebServiceWorkerError::ErrorType error_type;
854   GetServiceWorkerRegistrationStatusResponse(
855       status, &error_type, &error_message);
856   Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
857       thread_id, request_id, error_type, error_message));
858 }
859
860 ServiceWorkerContextCore* ServiceWorkerDispatcherHost::GetContext() {
861   if (!context_wrapper_.get())
862     return nullptr;
863   return context_wrapper_->context();
864 }
865
866 }  // namespace content