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.
5 #include "content/browser/service_worker/service_worker_provider_host.h"
8 #include "base/stl_util.h"
9 #include "content/browser/frame_host/frame_tree.h"
10 #include "content/browser/frame_host/frame_tree_node.h"
11 #include "content/browser/frame_host/render_frame_host_impl.h"
12 #include "content/browser/message_port_message_filter.h"
13 #include "content/browser/service_worker/service_worker_context_core.h"
14 #include "content/browser/service_worker/service_worker_context_request_handler.h"
15 #include "content/browser/service_worker/service_worker_controllee_request_handler.h"
16 #include "content/browser/service_worker/service_worker_dispatcher_host.h"
17 #include "content/browser/service_worker/service_worker_handle.h"
18 #include "content/browser/service_worker/service_worker_registration_handle.h"
19 #include "content/browser/service_worker/service_worker_utils.h"
20 #include "content/browser/service_worker/service_worker_version.h"
21 #include "content/browser/web_contents/web_contents_impl.h"
22 #include "content/common/resource_request_body.h"
23 #include "content/common/service_worker/service_worker_messages.h"
24 #include "content/common/service_worker/service_worker_types.h"
25 #include "content/public/browser/render_frame_host.h"
26 #include "content/public/browser/render_widget_host_view.h"
27 #include "content/public/browser/web_contents.h"
28 #include "content/public/common/child_process_host.h"
34 ServiceWorkerClientInfo
FocusOnUIThread(
35 int render_process_id
,
36 int render_frame_id
) {
37 RenderFrameHostImpl
* render_frame_host
=
38 RenderFrameHostImpl::FromID(render_process_id
, render_frame_id
);
39 WebContentsImpl
* web_contents
= static_cast<WebContentsImpl
*>(
40 WebContents::FromRenderFrameHost(render_frame_host
));
42 if (!render_frame_host
|| !web_contents
)
43 return ServiceWorkerClientInfo();
45 FrameTreeNode
* frame_tree_node
= render_frame_host
->frame_tree_node();
47 // Focus the frame in the frame tree node, in case it has changed.
48 frame_tree_node
->frame_tree()->SetFocusedFrame(frame_tree_node
);
50 // Focus the frame's view to make sure the frame is now considered as focused.
51 render_frame_host
->GetView()->Focus();
53 // Move the web contents to the foreground.
54 web_contents
->Activate();
56 return ServiceWorkerProviderHost::GetWindowClientInfoOnUI(render_process_id
,
60 } // anonymous namespace
62 ServiceWorkerProviderHost::OneShotGetReadyCallback::OneShotGetReadyCallback(
63 const GetRegistrationForReadyCallback
& callback
)
68 ServiceWorkerProviderHost::OneShotGetReadyCallback::~OneShotGetReadyCallback() {
71 ServiceWorkerProviderHost::ServiceWorkerProviderHost(
72 int render_process_id
,
75 ServiceWorkerProviderType provider_type
,
76 base::WeakPtr
<ServiceWorkerContextCore
> context
,
77 ServiceWorkerDispatcherHost
* dispatcher_host
)
78 : client_uuid_(base::GenerateGUID()),
79 render_process_id_(render_process_id
),
80 render_frame_id_(render_frame_id
),
81 render_thread_id_(kDocumentMainThreadId
),
82 provider_id_(provider_id
),
83 provider_type_(provider_type
),
85 dispatcher_host_(dispatcher_host
),
86 allow_association_(true) {
87 DCHECK_NE(ChildProcessHost::kInvalidUniqueID
, render_process_id_
);
88 DCHECK_NE(SERVICE_WORKER_PROVIDER_UNKNOWN
, provider_type_
);
89 if (provider_type_
== SERVICE_WORKER_PROVIDER_FOR_CONTROLLER
) {
90 // Actual thread id is set when the service worker context gets started.
91 render_thread_id_
= kInvalidEmbeddedWorkerThreadId
;
93 context_
->RegisterProviderHostByClientID(client_uuid_
, this);
96 ServiceWorkerProviderHost::~ServiceWorkerProviderHost() {
98 context_
->UnregisterProviderHostByClientID(client_uuid_
);
100 // Clear docurl so the deferred activation of a waiting worker
101 // won't associate the new version with a provider being destroyed.
102 document_url_
= GURL();
103 if (controlling_version_
.get())
104 controlling_version_
->RemoveControllee(this);
106 for (auto& key_registration
: matching_registrations_
) {
107 DecreaseProcessReference(key_registration
.second
->pattern());
108 key_registration
.second
->RemoveListener(this);
111 for (const GURL
& pattern
: associated_patterns_
)
112 DecreaseProcessReference(pattern
);
115 void ServiceWorkerProviderHost::OnVersionAttributesChanged(
116 ServiceWorkerRegistration
* registration
,
117 ChangedVersionAttributesMask changed_mask
,
118 const ServiceWorkerRegistrationInfo
& info
) {
119 if (!get_ready_callback_
|| get_ready_callback_
->called
)
121 if (changed_mask
.active_changed() && registration
->active_version()) {
122 // Wait until the state change so we don't send the get for ready
123 // registration complete message before set version attributes message.
124 registration
->active_version()->RegisterStatusChangeCallback(base::Bind(
125 &ServiceWorkerProviderHost::ReturnRegistrationForReadyIfNeeded
,
130 void ServiceWorkerProviderHost::OnRegistrationFailed(
131 ServiceWorkerRegistration
* registration
) {
132 if (associated_registration_
== registration
)
133 DisassociateRegistration();
134 RemoveMatchingRegistration(registration
);
137 void ServiceWorkerProviderHost::OnRegistrationFinishedUninstalling(
138 ServiceWorkerRegistration
* registration
) {
139 RemoveMatchingRegistration(registration
);
142 void ServiceWorkerProviderHost::OnSkippedWaiting(
143 ServiceWorkerRegistration
* registration
) {
144 if (associated_registration_
!= registration
)
146 // A client is "using" a registration if it is controlled by the active
147 // worker of the registration. skipWaiting doesn't cause a client to start
148 // using the registration.
149 if (!controlling_version_
)
151 ServiceWorkerVersion
* active_version
= registration
->active_version();
152 DCHECK_EQ(active_version
->status(), ServiceWorkerVersion::ACTIVATING
);
153 SetControllerVersionAttribute(active_version
,
154 true /* notify_controllerchange */);
157 void ServiceWorkerProviderHost::SetDocumentUrl(const GURL
& url
) {
158 DCHECK(!url
.has_ref());
162 void ServiceWorkerProviderHost::SetTopmostFrameUrl(const GURL
& url
) {
163 topmost_frame_url_
= url
;
166 void ServiceWorkerProviderHost::SetControllerVersionAttribute(
167 ServiceWorkerVersion
* version
,
168 bool notify_controllerchange
) {
169 if (version
== controlling_version_
.get())
172 scoped_refptr
<ServiceWorkerVersion
> previous_version
= controlling_version_
;
173 controlling_version_
= version
;
175 version
->AddControllee(this);
176 if (previous_version
.get())
177 previous_version
->RemoveControllee(this);
179 if (!dispatcher_host_
)
180 return; // Could be NULL in some tests.
182 // SetController message should be sent only for controllees.
183 DCHECK(IsProviderForClient());
184 Send(new ServiceWorkerMsg_SetControllerServiceWorker(
185 render_thread_id_
, provider_id(), GetOrCreateServiceWorkerHandle(version
),
186 notify_controllerchange
));
189 bool ServiceWorkerProviderHost::SetHostedVersionId(int64 version_id
) {
191 return true; // System is shutting down.
192 if (active_version())
193 return false; // Unexpected bad message.
195 ServiceWorkerVersion
* live_version
= context_
->GetLiveVersion(version_id
);
197 return true; // Was deleted before it got started.
199 ServiceWorkerVersionInfo info
= live_version
->GetInfo();
200 if (info
.running_status
!= ServiceWorkerVersion::STARTING
||
201 info
.process_id
!= render_process_id_
) {
202 // If we aren't trying to start this version in our process
203 // something is amiss.
207 running_hosted_version_
= live_version
;
211 bool ServiceWorkerProviderHost::IsProviderForClient() const {
212 switch (provider_type_
) {
213 case SERVICE_WORKER_PROVIDER_FOR_WINDOW
:
214 case SERVICE_WORKER_PROVIDER_FOR_WORKER
:
215 case SERVICE_WORKER_PROVIDER_FOR_SHARED_WORKER
:
217 case SERVICE_WORKER_PROVIDER_FOR_CONTROLLER
:
218 case SERVICE_WORKER_PROVIDER_UNKNOWN
:
221 NOTREACHED() << provider_type_
;
225 blink::WebServiceWorkerClientType
ServiceWorkerProviderHost::client_type()
227 switch (provider_type_
) {
228 case SERVICE_WORKER_PROVIDER_FOR_WINDOW
:
229 return blink::WebServiceWorkerClientTypeWindow
;
230 case SERVICE_WORKER_PROVIDER_FOR_WORKER
:
231 return blink::WebServiceWorkerClientTypeWorker
;
232 case SERVICE_WORKER_PROVIDER_FOR_SHARED_WORKER
:
233 return blink::WebServiceWorkerClientTypeSharedWorker
;
234 case SERVICE_WORKER_PROVIDER_FOR_CONTROLLER
:
235 case SERVICE_WORKER_PROVIDER_UNKNOWN
:
236 NOTREACHED() << provider_type_
;
238 NOTREACHED() << provider_type_
;
239 return blink::WebServiceWorkerClientTypeWindow
;
242 void ServiceWorkerProviderHost::AssociateRegistration(
243 ServiceWorkerRegistration
* registration
,
244 bool notify_controllerchange
) {
245 DCHECK(CanAssociateRegistration(registration
));
246 associated_registration_
= registration
;
247 AddMatchingRegistration(registration
);
248 SendAssociateRegistrationMessage();
249 SetControllerVersionAttribute(registration
->active_version(),
250 notify_controllerchange
);
253 void ServiceWorkerProviderHost::DisassociateRegistration() {
254 queued_events_
.clear();
255 if (!associated_registration_
.get())
257 associated_registration_
= NULL
;
258 SetControllerVersionAttribute(NULL
, false /* notify_controllerchange */);
260 if (!dispatcher_host_
)
263 // Disassociation message should be sent only for controllees.
264 DCHECK(IsProviderForClient());
265 Send(new ServiceWorkerMsg_DisassociateRegistration(
266 render_thread_id_
, provider_id()));
269 void ServiceWorkerProviderHost::AddMatchingRegistration(
270 ServiceWorkerRegistration
* registration
) {
271 DCHECK(ServiceWorkerUtils::ScopeMatches(
272 registration
->pattern(), document_url_
));
273 size_t key
= registration
->pattern().spec().size();
274 if (ContainsKey(matching_registrations_
, key
))
276 IncreaseProcessReference(registration
->pattern());
277 registration
->AddListener(this);
278 matching_registrations_
[key
] = registration
;
279 ReturnRegistrationForReadyIfNeeded();
282 void ServiceWorkerProviderHost::RemoveMatchingRegistration(
283 ServiceWorkerRegistration
* registration
) {
284 size_t key
= registration
->pattern().spec().size();
285 DCHECK(ContainsKey(matching_registrations_
, key
));
286 DecreaseProcessReference(registration
->pattern());
287 registration
->RemoveListener(this);
288 matching_registrations_
.erase(key
);
291 ServiceWorkerRegistration
*
292 ServiceWorkerProviderHost::MatchRegistration() const {
293 ServiceWorkerRegistrationMap::const_reverse_iterator it
=
294 matching_registrations_
.rbegin();
295 for (; it
!= matching_registrations_
.rend(); ++it
) {
296 if (it
->second
->is_uninstalled())
298 if (it
->second
->is_uninstalling())
300 return it
->second
.get();
305 void ServiceWorkerProviderHost::NotifyControllerActivationFailed() {
306 SetControllerVersionAttribute(nullptr, true /* notify_controllerchange */);
309 scoped_ptr
<ServiceWorkerRequestHandler
>
310 ServiceWorkerProviderHost::CreateRequestHandler(
311 FetchRequestMode request_mode
,
312 FetchCredentialsMode credentials_mode
,
313 ResourceType resource_type
,
314 RequestContextType request_context_type
,
315 RequestContextFrameType frame_type
,
316 base::WeakPtr
<storage::BlobStorageContext
> blob_storage_context
,
317 scoped_refptr
<ResourceRequestBody
> body
) {
318 if (IsHostToRunningServiceWorker()) {
319 return scoped_ptr
<ServiceWorkerRequestHandler
>(
320 new ServiceWorkerContextRequestHandler(
321 context_
, AsWeakPtr(), blob_storage_context
, resource_type
));
323 if (ServiceWorkerUtils::IsMainResourceType(resource_type
) ||
324 controlling_version()) {
325 return scoped_ptr
<ServiceWorkerRequestHandler
>(
326 new ServiceWorkerControlleeRequestHandler(context_
,
328 blob_storage_context
,
332 request_context_type
,
336 return scoped_ptr
<ServiceWorkerRequestHandler
>();
339 ServiceWorkerObjectInfo
340 ServiceWorkerProviderHost::GetOrCreateServiceWorkerHandle(
341 ServiceWorkerVersion
* version
) {
342 DCHECK(dispatcher_host_
);
343 if (!context_
|| !version
)
344 return ServiceWorkerObjectInfo();
345 ServiceWorkerHandle
* handle
= dispatcher_host_
->FindServiceWorkerHandle(
346 provider_id(), version
->version_id());
348 handle
->IncrementRefCount();
349 return handle
->GetObjectInfo();
352 scoped_ptr
<ServiceWorkerHandle
> new_handle(
353 ServiceWorkerHandle::Create(context_
, AsWeakPtr(), version
));
354 handle
= new_handle
.get();
355 dispatcher_host_
->RegisterServiceWorkerHandle(new_handle
.Pass());
356 return handle
->GetObjectInfo();
359 bool ServiceWorkerProviderHost::CanAssociateRegistration(
360 ServiceWorkerRegistration
* registration
) {
363 if (running_hosted_version_
.get())
365 if (!registration
|| associated_registration_
.get() || !allow_association_
)
370 void ServiceWorkerProviderHost::PostMessage(
371 const base::string16
& message
,
372 const std::vector
<TransferredMessagePort
>& sent_message_ports
) {
373 if (!dispatcher_host_
)
374 return; // Could be NULL in some tests.
376 std::vector
<int> new_routing_ids
;
377 dispatcher_host_
->message_port_message_filter()->
378 UpdateMessagePortsWithNewRoutes(sent_message_ports
,
381 Send(new ServiceWorkerMsg_MessageToDocument(
382 kDocumentMainThreadId
, provider_id(),
388 void ServiceWorkerProviderHost::Focus(const GetClientInfoCallback
& callback
) {
389 BrowserThread::PostTaskAndReplyWithResult(
390 BrowserThread::UI
, FROM_HERE
,
391 base::Bind(&FocusOnUIThread
,
397 void ServiceWorkerProviderHost::GetWindowClientInfo(
398 const GetClientInfoCallback
& callback
) const {
399 BrowserThread::PostTaskAndReplyWithResult(
400 BrowserThread::UI
, FROM_HERE
,
401 base::Bind(&ServiceWorkerProviderHost::GetWindowClientInfoOnUI
,
402 render_process_id_
, render_frame_id_
),
407 ServiceWorkerClientInfo
ServiceWorkerProviderHost::GetWindowClientInfoOnUI(
408 int render_process_id
,
409 int render_frame_id
) {
410 RenderFrameHostImpl
* render_frame_host
=
411 RenderFrameHostImpl::FromID(render_process_id
, render_frame_id
);
412 if (!render_frame_host
)
413 return ServiceWorkerClientInfo();
415 // TODO(mlamouri,michaeln): it is possible to end up collecting information
416 // for a frame that is actually being navigated and isn't exactly what we are
418 return ServiceWorkerClientInfo(
419 render_frame_host
->GetVisibilityState(),
420 render_frame_host
->IsFocused(),
421 render_frame_host
->GetLastCommittedURL(),
422 render_frame_host
->GetParent() ? REQUEST_CONTEXT_FRAME_TYPE_NESTED
423 : REQUEST_CONTEXT_FRAME_TYPE_TOP_LEVEL
,
424 blink::WebServiceWorkerClientTypeWindow
);
427 void ServiceWorkerProviderHost::AddScopedProcessReferenceToPattern(
428 const GURL
& pattern
) {
429 associated_patterns_
.push_back(pattern
);
430 IncreaseProcessReference(pattern
);
433 void ServiceWorkerProviderHost::ClaimedByRegistration(
434 ServiceWorkerRegistration
* registration
) {
435 DCHECK(registration
->active_version());
436 if (registration
== associated_registration_
) {
437 SetControllerVersionAttribute(registration
->active_version(),
438 true /* notify_controllerchange */);
439 } else if (allow_association_
) {
440 DisassociateRegistration();
441 AssociateRegistration(registration
, true /* notify_controllerchange */);
445 bool ServiceWorkerProviderHost::GetRegistrationForReady(
446 const GetRegistrationForReadyCallback
& callback
) {
447 if (get_ready_callback_
)
449 get_ready_callback_
.reset(new OneShotGetReadyCallback(callback
));
450 ReturnRegistrationForReadyIfNeeded();
454 void ServiceWorkerProviderHost::PrepareForCrossSiteTransfer() {
455 DCHECK_NE(ChildProcessHost::kInvalidUniqueID
, render_process_id_
);
456 DCHECK_NE(MSG_ROUTING_NONE
, render_frame_id_
);
457 DCHECK_EQ(kDocumentMainThreadId
, render_thread_id_
);
458 DCHECK_NE(SERVICE_WORKER_PROVIDER_UNKNOWN
, provider_type_
);
460 for (const GURL
& pattern
: associated_patterns_
)
461 DecreaseProcessReference(pattern
);
463 for (auto& key_registration
: matching_registrations_
)
464 DecreaseProcessReference(key_registration
.second
->pattern());
466 if (associated_registration_
.get()) {
467 if (dispatcher_host_
) {
468 Send(new ServiceWorkerMsg_DisassociateRegistration(
469 render_thread_id_
, provider_id()));
473 render_process_id_
= ChildProcessHost::kInvalidUniqueID
;
474 render_frame_id_
= MSG_ROUTING_NONE
;
475 render_thread_id_
= kInvalidEmbeddedWorkerThreadId
;
476 provider_id_
= kInvalidServiceWorkerProviderId
;
477 provider_type_
= SERVICE_WORKER_PROVIDER_UNKNOWN
;
478 dispatcher_host_
= nullptr;
481 void ServiceWorkerProviderHost::CompleteCrossSiteTransfer(
485 ServiceWorkerProviderType new_provider_type
,
486 ServiceWorkerDispatcherHost
* new_dispatcher_host
) {
487 DCHECK_EQ(ChildProcessHost::kInvalidUniqueID
, render_process_id_
);
488 DCHECK_NE(ChildProcessHost::kInvalidUniqueID
, new_process_id
);
489 DCHECK_NE(MSG_ROUTING_NONE
, new_frame_id
);
491 render_process_id_
= new_process_id
;
492 render_frame_id_
= new_frame_id
;
493 render_thread_id_
= kDocumentMainThreadId
;
494 provider_id_
= new_provider_id
;
495 provider_type_
= new_provider_type
;
496 dispatcher_host_
= new_dispatcher_host
;
498 for (const GURL
& pattern
: associated_patterns_
)
499 IncreaseProcessReference(pattern
);
501 for (auto& key_registration
: matching_registrations_
)
502 IncreaseProcessReference(key_registration
.second
->pattern());
504 if (associated_registration_
.get()) {
505 SendAssociateRegistrationMessage();
506 if (dispatcher_host_
&& associated_registration_
->active_version()) {
507 Send(new ServiceWorkerMsg_SetControllerServiceWorker(
508 render_thread_id_
, provider_id(),
509 GetOrCreateServiceWorkerHandle(
510 associated_registration_
->active_version()),
511 false /* shouldNotifyControllerChange */));
516 void ServiceWorkerProviderHost::SendUpdateFoundMessage(
517 int registration_handle_id
) {
518 if (!dispatcher_host_
)
519 return; // Could be nullptr in some tests.
521 if (!IsReadyToSendMessages()) {
522 queued_events_
.push_back(
523 base::Bind(&ServiceWorkerProviderHost::SendUpdateFoundMessage
,
524 AsWeakPtr(), registration_handle_id
));
528 Send(new ServiceWorkerMsg_UpdateFound(
529 render_thread_id_
, registration_handle_id
));
532 void ServiceWorkerProviderHost::SendSetVersionAttributesMessage(
533 int registration_handle_id
,
534 ChangedVersionAttributesMask changed_mask
,
535 ServiceWorkerVersion
* installing_version
,
536 ServiceWorkerVersion
* waiting_version
,
537 ServiceWorkerVersion
* active_version
) {
538 if (!dispatcher_host_
)
539 return; // Could be nullptr in some tests.
540 if (!changed_mask
.changed())
543 if (!IsReadyToSendMessages()) {
544 queued_events_
.push_back(
545 base::Bind(&ServiceWorkerProviderHost::SendSetVersionAttributesMessage
,
546 AsWeakPtr(), registration_handle_id
, changed_mask
,
547 make_scoped_refptr(installing_version
),
548 make_scoped_refptr(waiting_version
),
549 make_scoped_refptr(active_version
)));
553 ServiceWorkerVersionAttributes attrs
;
554 if (changed_mask
.installing_changed())
555 attrs
.installing
= GetOrCreateServiceWorkerHandle(installing_version
);
556 if (changed_mask
.waiting_changed())
557 attrs
.waiting
= GetOrCreateServiceWorkerHandle(waiting_version
);
558 if (changed_mask
.active_changed())
559 attrs
.active
= GetOrCreateServiceWorkerHandle(active_version
);
561 Send(new ServiceWorkerMsg_SetVersionAttributes(
562 render_thread_id_
, provider_id_
, registration_handle_id
,
563 changed_mask
.changed(), attrs
));
566 void ServiceWorkerProviderHost::SendServiceWorkerStateChangedMessage(
567 int worker_handle_id
,
568 blink::WebServiceWorkerState state
) {
569 if (!dispatcher_host_
)
572 if (!IsReadyToSendMessages()) {
573 queued_events_
.push_back(base::Bind(
574 &ServiceWorkerProviderHost::SendServiceWorkerStateChangedMessage
,
575 AsWeakPtr(), worker_handle_id
, state
));
579 Send(new ServiceWorkerMsg_ServiceWorkerStateChanged(
580 render_thread_id_
, worker_handle_id
, state
));
583 void ServiceWorkerProviderHost::SetReadyToSendMessagesToWorker(
584 int render_thread_id
) {
585 DCHECK(!IsReadyToSendMessages());
586 render_thread_id_
= render_thread_id
;
588 for (const auto& event
: queued_events_
)
590 queued_events_
.clear();
593 void ServiceWorkerProviderHost::SendAssociateRegistrationMessage() {
594 if (!dispatcher_host_
)
597 ServiceWorkerRegistrationHandle
* handle
=
598 dispatcher_host_
->GetOrCreateRegistrationHandle(
599 AsWeakPtr(), associated_registration_
.get());
601 ServiceWorkerVersionAttributes attrs
;
602 attrs
.installing
= GetOrCreateServiceWorkerHandle(
603 associated_registration_
->installing_version());
604 attrs
.waiting
= GetOrCreateServiceWorkerHandle(
605 associated_registration_
->waiting_version());
606 attrs
.active
= GetOrCreateServiceWorkerHandle(
607 associated_registration_
->active_version());
609 // Association message should be sent only for controllees.
610 DCHECK(IsProviderForClient());
611 dispatcher_host_
->Send(new ServiceWorkerMsg_AssociateRegistration(
612 render_thread_id_
, provider_id(), handle
->GetObjectInfo(), attrs
));
615 void ServiceWorkerProviderHost::IncreaseProcessReference(
616 const GURL
& pattern
) {
617 if (context_
&& context_
->process_manager()) {
618 context_
->process_manager()->AddProcessReferenceToPattern(
619 pattern
, render_process_id_
);
623 void ServiceWorkerProviderHost::DecreaseProcessReference(
624 const GURL
& pattern
) {
625 if (context_
&& context_
->process_manager()) {
626 context_
->process_manager()->RemoveProcessReferenceFromPattern(
627 pattern
, render_process_id_
);
631 void ServiceWorkerProviderHost::ReturnRegistrationForReadyIfNeeded() {
632 if (!get_ready_callback_
|| get_ready_callback_
->called
)
634 ServiceWorkerRegistration
* registration
= MatchRegistration();
637 if (registration
->active_version()) {
638 get_ready_callback_
->callback
.Run(registration
);
639 get_ready_callback_
->callback
.Reset();
640 get_ready_callback_
->called
= true;
645 bool ServiceWorkerProviderHost::IsReadyToSendMessages() const {
646 return render_thread_id_
!= kInvalidEmbeddedWorkerThreadId
;
649 bool ServiceWorkerProviderHost::IsContextAlive() {
650 return context_
!= NULL
;
653 void ServiceWorkerProviderHost::Send(IPC::Message
* message
) const {
654 DCHECK(dispatcher_host_
);
655 DCHECK(IsReadyToSendMessages());
656 dispatcher_host_
->Send(message
);
659 } // namespace content