Chromium Code Reviews| 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 6ad38973a23333c752c925138a9c9f0afddba045..ccd14dc7a7e5520b63283e4243791293c99105ac 100644 |
| --- a/content/browser/service_worker/service_worker_provider_host.cc |
| +++ b/content/browser/service_worker/service_worker_provider_host.cc |
| @@ -76,6 +76,16 @@ ServiceWorkerClientInfo FocusOnUIThread( |
| } // anonymous namespace |
| +ServiceWorkerProviderHost::OneShotGetReadyCallback::OneShotGetReadyCallback( |
| + const GetRegistrationForReadyCallback& callback) |
| + : callback(callback), |
| + called(false) { |
| +} |
| + |
| +ServiceWorkerProviderHost::OneShotGetReadyCallback::~OneShotGetReadyCallback() { |
| + callback.Reset(); |
|
michaeln
2015/02/26 21:41:06
not sure this line is needed?
xiang
2015/02/27 09:33:46
Done. This's not needed.
|
| +} |
| + |
| ServiceWorkerProviderHost::ServiceWorkerProviderHost( |
| int render_process_id, |
| int render_frame_id, |
| @@ -106,24 +116,39 @@ 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 : matching_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) { |
| + ReturnRegistrationForReadyIfNeeded(); |
| +} |
| + |
| void ServiceWorkerProviderHost::OnRegistrationFailed( |
| ServiceWorkerRegistration* registration) { |
| - DCHECK_EQ(associated_registration_.get(), registration); |
| - DisassociateRegistration(); |
| + if (associated_registration_ == registration) |
| + DisassociateRegistration(); |
| + RemoveMatchingRegistration(registration); |
| +} |
| + |
| +void ServiceWorkerProviderHost::OnRegistrationFinishedUninstalling( |
| + ServiceWorkerRegistration* registration) { |
| + RemoveMatchingRegistration(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. |
| @@ -194,9 +219,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); |
| + AddMatchingRegistration(registration); |
| SendAssociateRegistrationMessage(); |
| SetControllerVersionAttribute(registration->active_version()); |
| } |
| @@ -205,8 +229,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); |
| @@ -219,6 +241,42 @@ void ServiceWorkerProviderHost::DisassociateRegistration() { |
| render_thread_id_, provider_id())); |
| } |
| +void ServiceWorkerProviderHost::AddMatchingRegistration( |
| + ServiceWorkerRegistration* registration) { |
| + DCHECK(ServiceWorkerUtils::ScopeMatches( |
| + registration->pattern(), document_url_)); |
| + size_t key = registration->pattern().spec().size(); |
| + if (ContainsKey(matching_registrations_, key)) |
| + return; |
| + IncreaseProcessReference(registration->pattern()); |
| + registration->AddListener(this); |
| + matching_registrations_[key] = registration; |
| + ReturnRegistrationForReadyIfNeeded(); |
| +} |
| + |
| +void ServiceWorkerProviderHost::RemoveMatchingRegistration( |
| + ServiceWorkerRegistration* registration) { |
| + size_t key = registration->pattern().spec().size(); |
| + DCHECK(ContainsKey(matching_registrations_, key)); |
| + DecreaseProcessReference(registration->pattern()); |
| + registration->RemoveListener(this); |
| + matching_registrations_.erase(key); |
| +} |
| + |
| +ServiceWorkerRegistration* |
| +ServiceWorkerProviderHost::MatchRegistration() const { |
| + ServiceWorkerRegistrationMap::const_reverse_iterator it = |
| + matching_registrations_.rbegin(); |
| + for (; it != matching_registrations_.rend(); ++it) { |
| + if (it->second->is_uninstalled()) |
| + continue; |
| + if (it->second->is_uninstalling()) |
| + return nullptr; |
| + return it->second.get(); |
| + } |
| + return nullptr; |
| +} |
| + |
| scoped_ptr<ServiceWorkerRequestHandler> |
| ServiceWorkerProviderHost::CreateRequestHandler( |
| FetchRequestMode request_mode, |
| @@ -330,6 +388,15 @@ void ServiceWorkerProviderHost::ClaimedByRegistration( |
| is_claiming_ = false; |
| } |
| +bool ServiceWorkerProviderHost::GetRegistrationForReady( |
| + const GetRegistrationForReadyCallback& callback) { |
| + if (get_ready_callback_) |
| + return false; |
| + get_ready_callback_.reset(new OneShotGetReadyCallback(callback)); |
| + ReturnRegistrationForReadyIfNeeded(); |
| + return true; |
| +} |
| + |
| void ServiceWorkerProviderHost::PrepareForCrossSiteTransfer() { |
| DCHECK_NE(ChildProcessHost::kInvalidUniqueID, render_process_id_); |
| DCHECK_NE(MSG_ROUTING_NONE, render_frame_id_); |
| @@ -339,8 +406,10 @@ void ServiceWorkerProviderHost::PrepareForCrossSiteTransfer() { |
| for (const GURL& pattern : associated_patterns_) |
| DecreaseProcessReference(pattern); |
| + for (auto& key_registration : matching_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())); |
| @@ -375,8 +444,10 @@ void ServiceWorkerProviderHost::CompleteCrossSiteTransfer( |
| for (const GURL& pattern : associated_patterns_) |
| IncreaseProcessReference(pattern); |
| + for (auto& key_registration : matching_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( |
| @@ -502,6 +573,20 @@ void ServiceWorkerProviderHost::DecreaseProcessReference( |
| } |
| } |
| +void ServiceWorkerProviderHost::ReturnRegistrationForReadyIfNeeded() { |
| + if (!get_ready_callback_ || get_ready_callback_->called) |
| + return; |
| + ServiceWorkerRegistration* registration = MatchRegistration(); |
| + if (!registration) |
| + return; |
| + if (registration->active_version()) { |
| + get_ready_callback_->callback.Run(registration); |
| + get_ready_callback_->callback.Reset(); |
| + get_ready_callback_->called = true; |
| + return; |
| + } |
| +} |
| + |
| bool ServiceWorkerProviderHost::IsReadyToSendMessages() const { |
| return render_thread_id_ != kInvalidEmbeddedWorkerThreadId; |
| } |