| 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;
|
| }
|
|
|