Re-subimission of https://codereview.chromium.org/1041213003/
[chromium-blink-merge.git] / content / browser / service_worker / service_worker_provider_host.cc
blob6a79c56d753730f444f8e027745818d1db8ea1ea
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"
7 #include "base/guid.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"
30 namespace content {
32 namespace {
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,
57 render_frame_id);
60 } // anonymous namespace
62 ServiceWorkerProviderHost::OneShotGetReadyCallback::OneShotGetReadyCallback(
63 const GetRegistrationForReadyCallback& callback)
64 : callback(callback),
65 called(false) {
68 ServiceWorkerProviderHost::OneShotGetReadyCallback::~OneShotGetReadyCallback() {
71 ServiceWorkerProviderHost::ServiceWorkerProviderHost(
72 int render_process_id,
73 int render_frame_id,
74 int provider_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),
84 context_(context),
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() {
97 if (context_)
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)
120 return;
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,
126 AsWeakPtr()));
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)
145 return;
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_)
150 return;
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());
159 document_url_ = url;
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())
170 return;
172 scoped_refptr<ServiceWorkerVersion> previous_version = controlling_version_;
173 controlling_version_ = version;
174 if (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) {
190 if (!context_)
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);
196 if (!live_version)
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.
204 return false;
207 running_hosted_version_ = live_version;
208 return true;
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:
216 return true;
217 case SERVICE_WORKER_PROVIDER_FOR_CONTROLLER:
218 case SERVICE_WORKER_PROVIDER_UNKNOWN:
219 return false;
221 NOTREACHED() << provider_type_;
222 return false;
225 blink::WebServiceWorkerClientType ServiceWorkerProviderHost::client_type()
226 const {
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())
256 return;
257 associated_registration_ = NULL;
258 SetControllerVersionAttribute(NULL, false /* notify_controllerchange */);
260 if (!dispatcher_host_)
261 return;
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))
275 return;
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())
297 continue;
298 if (it->second->is_uninstalling())
299 return nullptr;
300 return it->second.get();
302 return nullptr;
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_,
327 AsWeakPtr(),
328 blob_storage_context,
329 request_mode,
330 credentials_mode,
331 resource_type,
332 request_context_type,
333 frame_type,
334 body));
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());
347 if (handle) {
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) {
361 if (!context_)
362 return false;
363 if (running_hosted_version_.get())
364 return false;
365 if (!registration || associated_registration_.get() || !allow_association_)
366 return false;
367 return true;
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,
379 &new_routing_ids);
381 Send(new ServiceWorkerMsg_MessageToDocument(
382 kDocumentMainThreadId, provider_id(),
383 message,
384 sent_message_ports,
385 new_routing_ids));
388 void ServiceWorkerProviderHost::Focus(const GetClientInfoCallback& callback) {
389 BrowserThread::PostTaskAndReplyWithResult(
390 BrowserThread::UI, FROM_HERE,
391 base::Bind(&FocusOnUIThread,
392 render_process_id_,
393 render_frame_id_),
394 callback);
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_),
403 callback);
406 // static
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
417 // expecting.
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_)
448 return false;
449 get_ready_callback_.reset(new OneShotGetReadyCallback(callback));
450 ReturnRegistrationForReadyIfNeeded();
451 return true;
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(
482 int new_process_id,
483 int new_frame_id,
484 int new_provider_id,
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));
525 return;
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())
541 return;
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)));
550 return;
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_)
570 return;
572 if (!IsReadyToSendMessages()) {
573 queued_events_.push_back(base::Bind(
574 &ServiceWorkerProviderHost::SendServiceWorkerStateChangedMessage,
575 AsWeakPtr(), worker_handle_id, state));
576 return;
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_)
589 event.Run();
590 queued_events_.clear();
593 void ServiceWorkerProviderHost::SendAssociateRegistrationMessage() {
594 if (!dispatcher_host_)
595 return;
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)
633 return;
634 ServiceWorkerRegistration* registration = MatchRegistration();
635 if (!registration)
636 return;
637 if (registration->active_version()) {
638 get_ready_callback_->callback.Run(registration);
639 get_ready_callback_->callback.Reset();
640 get_ready_callback_->called = true;
641 return;
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