Index: content/browser/service_worker/service_worker_provider_host.cc |
diff --git a/content/browser/service_worker/service_worker_provider_host.cc b/content/browser/service_worker/service_worker_provider_host.cc |
index a94d4d98a52bd0c6f1ed36f61c70ae980315753d..d9c22cb2fefc9d48bbc9a2b07feae32be96116a6 100644 |
--- a/content/browser/service_worker/service_worker_provider_host.cc |
+++ b/content/browser/service_worker/service_worker_provider_host.cc |
@@ -84,7 +84,6 @@ ServiceWorkerProviderHost::ServiceWorkerProviderHost( |
provider_id_(provider_id), |
context_(context), |
dispatcher_host_(dispatcher_host), |
- allow_association_(true), |
is_claiming_(false) { |
DCHECK_NE(ChildProcessHost::kInvalidUniqueID, render_process_id_); |
if (render_frame_id == MSG_ROUTING_NONE) { |
@@ -99,24 +98,40 @@ ServiceWorkerProviderHost::~ServiceWorkerProviderHost() { |
document_url_ = GURL(); |
if (controlling_version_.get()) |
controlling_version_->RemoveControllee(this); |
- if (associated_registration_.get()) { |
- DecreaseProcessReference(associated_registration_->pattern()); |
- associated_registration_->RemoveListener(this); |
+ |
+ for (auto& key_registration : potential_registrations_) { |
+ DecreaseProcessReference(key_registration.second->pattern()); |
+ key_registration.second->RemoveListener(this); |
} |
for (const GURL& pattern : associated_patterns_) |
DecreaseProcessReference(pattern); |
} |
+void ServiceWorkerProviderHost::OnVersionAttributesChanged( |
+ ServiceWorkerRegistration* registration, |
+ ChangedVersionAttributesMask changed_mask, |
+ const ServiceWorkerRegistrationInfo& info) { |
+ ReturnReadyRegistrationIfNeeded(); |
+} |
+ |
void ServiceWorkerProviderHost::OnRegistrationFailed( |
ServiceWorkerRegistration* registration) { |
- DCHECK_EQ(associated_registration_.get(), registration); |
- DisassociateRegistration(); |
+ if (associated_registration_ == registration) |
+ DisassociateRegistration(); |
+ else |
+ RemovePotentialRegistration(registration); |
+} |
+ |
+void ServiceWorkerProviderHost::OnRegistrationFinishedUninstalling( |
+ ServiceWorkerRegistration* registration) { |
+ RemovePotentialRegistration(registration); |
} |
void ServiceWorkerProviderHost::OnSkippedWaiting( |
ServiceWorkerRegistration* registration) { |
- DCHECK_EQ(associated_registration_.get(), registration); |
+ if (associated_registration_ != registration) |
+ return; |
// A client is "using" a registration if it is controlled by the active |
// worker of the registration. skipWaiting doesn't cause a client to start |
// using the registration. |
@@ -187,9 +202,8 @@ bool ServiceWorkerProviderHost::SetHostedVersionId(int64 version_id) { |
void ServiceWorkerProviderHost::AssociateRegistration( |
ServiceWorkerRegistration* registration) { |
DCHECK(CanAssociateRegistration(registration)); |
- IncreaseProcessReference(registration->pattern()); |
associated_registration_ = registration; |
- associated_registration_->AddListener(this); |
+ AddPotentialRegistration(registration); |
SendAssociateRegistrationMessage(); |
SetControllerVersionAttribute(registration->active_version()); |
} |
@@ -198,8 +212,6 @@ void ServiceWorkerProviderHost::DisassociateRegistration() { |
queued_events_.clear(); |
if (!associated_registration_.get()) |
return; |
- DecreaseProcessReference(associated_registration_->pattern()); |
- associated_registration_->RemoveListener(this); |
associated_registration_ = NULL; |
SetControllerVersionAttribute(NULL); |
@@ -212,6 +224,40 @@ void ServiceWorkerProviderHost::DisassociateRegistration() { |
render_thread_id_, provider_id())); |
} |
+void ServiceWorkerProviderHost::AddPotentialRegistration( |
+ ServiceWorkerRegistration* registration) { |
+ size_t key = registration->pattern().spec().size(); |
+ if (ContainsKey(potential_registrations_, key)) |
+ return; |
+ IncreaseProcessReference(registration->pattern()); |
+ registration->AddListener(this); |
+ potential_registrations_[key] = registration; |
+ ReturnReadyRegistrationIfNeeded(); |
+} |
+ |
+void ServiceWorkerProviderHost::RemovePotentialRegistration( |
+ ServiceWorkerRegistration* registration) { |
+ size_t key = registration->pattern().spec().size(); |
+ DCHECK(ContainsKey(potential_registrations_, key)); |
+ DecreaseProcessReference(registration->pattern()); |
+ registration->RemoveListener(this); |
+ potential_registrations_.erase(key); |
+} |
+ |
+ServiceWorkerRegistration* |
+ServiceWorkerProviderHost::GetMatchedRegistration() const { |
+ ServiceWorkerRegistrationMap::const_reverse_iterator it = |
+ potential_registrations_.rbegin(); |
+ for (; it != potential_registrations_.rend(); ++it) { |
+ if (it->second->is_uninstalled()) |
+ continue; |
+ if (it->second->is_uninstalling()) |
+ return nullptr; |
+ break; |
+ } |
+ return it == potential_registrations_.rend() ? nullptr : it->second.get(); |
+} |
+ |
scoped_ptr<ServiceWorkerRequestHandler> |
ServiceWorkerProviderHost::CreateRequestHandler( |
FetchRequestMode request_mode, |
@@ -322,6 +368,12 @@ void ServiceWorkerProviderHost::ClaimedByRegistration( |
is_claiming_ = false; |
} |
+void ServiceWorkerProviderHost::GetReadyRegistration( |
+ const GetReadyRegistrationCallback& callback) { |
+ registration_ready_callback_ = callback; |
+ ReturnReadyRegistrationIfNeeded(); |
+} |
+ |
void ServiceWorkerProviderHost::PrepareForCrossSiteTransfer() { |
DCHECK_NE(ChildProcessHost::kInvalidUniqueID, render_process_id_); |
DCHECK_NE(MSG_ROUTING_NONE, render_frame_id_); |
@@ -330,8 +382,10 @@ void ServiceWorkerProviderHost::PrepareForCrossSiteTransfer() { |
for (const GURL& pattern : associated_patterns_) |
DecreaseProcessReference(pattern); |
+ for (auto& key_registration : potential_registrations_) |
+ DecreaseProcessReference(key_registration.second->pattern()); |
+ |
if (associated_registration_.get()) { |
- DecreaseProcessReference(associated_registration_->pattern()); |
if (dispatcher_host_) { |
Send(new ServiceWorkerMsg_DisassociateRegistration( |
render_thread_id_, provider_id())); |
@@ -363,8 +417,10 @@ void ServiceWorkerProviderHost::CompleteCrossSiteTransfer( |
for (const GURL& pattern : associated_patterns_) |
IncreaseProcessReference(pattern); |
+ for (auto& key_registration : potential_registrations_) |
+ IncreaseProcessReference(key_registration.second->pattern()); |
+ |
if (associated_registration_.get()) { |
- IncreaseProcessReference(associated_registration_->pattern()); |
SendAssociateRegistrationMessage(); |
if (dispatcher_host_ && associated_registration_->active_version()) { |
Send(new ServiceWorkerMsg_SetControllerServiceWorker( |
@@ -490,6 +546,19 @@ void ServiceWorkerProviderHost::DecreaseProcessReference( |
} |
} |
+void ServiceWorkerProviderHost::ReturnReadyRegistrationIfNeeded() { |
+ if (registration_ready_callback_.is_null()) |
+ return; |
+ ServiceWorkerRegistration* registration = GetMatchedRegistration(); |
+ if (!registration) |
+ return; |
+ if (registration->active_version()) { |
+ registration_ready_callback_.Run(registration); |
+ registration_ready_callback_.Reset(); |
+ return; |
+ } |
+} |
+ |
bool ServiceWorkerProviderHost::IsReadyToSendMessages() const { |
return render_thread_id_ != kInvalidEmbeddedWorkerThreadId; |
} |