Chromium Code Reviews| Index: content/browser/service_worker/service_worker_context_watcher.cc |
| diff --git a/content/browser/service_worker/service_worker_context_watcher.cc b/content/browser/service_worker/service_worker_context_watcher.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..7ad5e817e95e9008ed0fc944e3459a4b4af15796 |
| --- /dev/null |
| +++ b/content/browser/service_worker/service_worker_context_watcher.cc |
| @@ -0,0 +1,212 @@ |
| +// Copyright 2015 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "content/browser/service_worker/service_worker_context_watcher.h" |
| + |
| +#include "base/bind.h" |
| +#include "base/containers/scoped_ptr_hash_map.h" |
| +#include "content/browser/service_worker/service_worker_context_observer.h" |
| +#include "content/browser/service_worker/service_worker_context_wrapper.h" |
| +#include "content/browser/service_worker/service_worker_version.h" |
| +#include "content/public/browser/browser_thread.h" |
| +#include "url/gurl.h" |
| + |
| +namespace content { |
| +namespace { |
| + |
| +bool IsStoppedAndRedundant(const ServiceWorkerVersionInfo& version_info) { |
| + return version_info.running_status == |
| + content::ServiceWorkerVersion::STOPPED && |
| + version_info.status == content::ServiceWorkerVersion::REDUNDANT; |
| +} |
| + |
| +} // namespace |
| + |
| +ServiceWorkerContextWatcher::ServiceWorkerContextWatcher( |
| + scoped_refptr<ServiceWorkerContextWrapper> context, |
| + const WorkerRegistrationUpdatedCallback& registration_callback, |
| + const WorkerVersionUpdatedCallback& version_callback) |
| + : context_(context), |
| + registration_callback_(registration_callback), |
| + version_callback_(version_callback) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| +} |
| + |
| +void ServiceWorkerContextWatcher::Start() { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, |
| + base::Bind(&ServiceWorkerContextWatcher:: |
| + GetStoredRegistrationsOnIOThread, |
| + this)); |
| +} |
| + |
| +void ServiceWorkerContextWatcher::Stop() { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| + BrowserThread::PostTask( |
| + BrowserThread::IO, FROM_HERE, |
| + base::Bind(&ServiceWorkerContextWatcher::StopOnIOThread, this)); |
| +} |
| + |
| +void ServiceWorkerContextWatcher::GetStoredRegistrationsOnIOThread() { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + context_->context()->storage()->GetAllRegistrations(base::Bind( |
| + &ServiceWorkerContextWatcher::OnStoredRegistrationsOnIOThread, |
| + this)); |
|
kinuko
2015/03/13 09:09:21
This is what we've been doing so it's ok, but will
horo
2015/03/13 10:03:49
Yes. In future, it may better to filter the regist
|
| +} |
| + |
| +void ServiceWorkerContextWatcher::OnStoredRegistrationsOnIOThread( |
| + const std::vector<ServiceWorkerRegistrationInfo>& stored_registrations) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + context_->AddObserver(this); |
| + |
| + base::ScopedPtrHashMap<int64, ServiceWorkerRegistrationInfo> |
| + registration_info_map; |
| + for (const auto& registration : stored_registrations) |
| + StoreRegistrationInfo(registration, ®istration_info_map); |
| + for (const auto& registration : |
| + context_->context()->GetAllLiveRegistrationInfo()) { |
| + StoreRegistrationInfo(registration, ®istration_info_map); |
| + } |
| + for (const auto& version : context_->context()->GetAllLiveVersionInfo()) |
| + StoreVersionInfo(version); |
| + |
| + std::vector<ServiceWorkerRegistrationInfo> registrations; |
| + registrations.reserve(registration_info_map.size()); |
| + for (const auto& registration_id_info_pair : registration_info_map) |
| + registrations.push_back(*registration_id_info_pair.second); |
| + |
| + std::vector<ServiceWorkerVersionInfo> versions; |
| + versions.reserve(version_info_map_.size()); |
| + |
| + for (auto version_it = version_info_map_.begin(); |
| + version_it != version_info_map_.end();) { |
| + versions.push_back(*version_it->second); |
| + if (IsStoppedAndRedundant(*version_it->second)) |
| + version_info_map_.erase(version_it++); |
| + else |
| + ++version_it; |
| + } |
| + |
| + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| + base::Bind(registration_callback_, registrations)); |
| + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| + base::Bind(version_callback_, versions)); |
| +} |
| + |
| +void ServiceWorkerContextWatcher::StopOnIOThread() { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + context_->RemoveObserver(this); |
| +} |
| + |
| +ServiceWorkerContextWatcher::~ServiceWorkerContextWatcher() { |
| +} |
| + |
| +void ServiceWorkerContextWatcher::StoreRegistrationInfo( |
| + const ServiceWorkerRegistrationInfo& registration_info, |
| + base::ScopedPtrHashMap<int64, ServiceWorkerRegistrationInfo>* info_map) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + if (registration_info.registration_id == kInvalidServiceWorkerRegistrationId) |
| + return; |
| + info_map->set(registration_info.registration_id, |
| + scoped_ptr<ServiceWorkerRegistrationInfo>( |
| + new ServiceWorkerRegistrationInfo(registration_info))); |
| + StoreVersionInfo(registration_info.active_version); |
| + StoreVersionInfo(registration_info.waiting_version); |
| + StoreVersionInfo(registration_info.installing_version); |
| +} |
| + |
| +void ServiceWorkerContextWatcher::StoreVersionInfo( |
| + const ServiceWorkerVersionInfo& version_info) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + if (version_info.version_id == kInvalidServiceWorkerVersionId) |
| + return; |
| + version_info_map_.set(version_info.version_id, |
| + scoped_ptr<ServiceWorkerVersionInfo>( |
| + new ServiceWorkerVersionInfo(version_info))); |
| +} |
| + |
| +void ServiceWorkerContextWatcher::SendRegistrationInfo( |
| + int64 registration_id, |
| + const GURL& pattern, |
| + bool is_deleted) { |
| + std::vector<ServiceWorkerRegistrationInfo> registrations; |
| + registrations.push_back( |
| + ServiceWorkerRegistrationInfo(pattern, registration_id, is_deleted)); |
| + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| + base::Bind(registration_callback_, registrations)); |
| +} |
| + |
| +void ServiceWorkerContextWatcher::SendVersionInfo( |
| + const ServiceWorkerVersionInfo& version_info) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + std::vector<ServiceWorkerVersionInfo> versions; |
| + versions.push_back(version_info); |
| + BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| + base::Bind(version_callback_, versions)); |
| +} |
| + |
| +void ServiceWorkerContextWatcher::OnNewLiveRegistration( |
| + int64 registration_id, |
| + const GURL& pattern) { |
| + SendRegistrationInfo(registration_id, pattern, false); |
|
kinuko
2015/03/13 09:09:21
nit: please annotate the boolean field with commen
horo
2015/03/13 10:03:49
Done.
|
| +} |
| + |
| +void ServiceWorkerContextWatcher::OnNewLiveVersion( |
| + int64 version_id, |
| + int64 registration_id, |
| + const GURL& script_url) { |
| + if (ServiceWorkerVersionInfo* version = version_info_map_.get(version_id)) { |
| + DCHECK(version->registration_id == registration_id); |
| + DCHECK(version->script_url == script_url); |
|
kinuko
2015/03/13 09:09:21
nit: DCHECK_EQ
horo
2015/03/13 10:03:49
Done.
|
| + return; |
| + } |
| + |
| + scoped_ptr<ServiceWorkerVersionInfo> version(new ServiceWorkerVersionInfo()); |
| + version->version_id = version_id; |
| + version->registration_id = registration_id; |
| + version->script_url = script_url; |
| + SendVersionInfo(*version); |
| + if (!IsStoppedAndRedundant(*version)) |
| + version_info_map_.set(version_id, version.Pass()); |
| +} |
| + |
| +void ServiceWorkerContextWatcher::OnRunningStateChanged( |
| + int64 version_id, |
| + content::ServiceWorkerVersion::RunningStatus running_status) { |
| + ServiceWorkerVersionInfo* version = version_info_map_.get(version_id); |
| + DCHECK(version); |
| + if (version->running_status == running_status) |
| + return; |
| + version->running_status = running_status; |
| + SendVersionInfo(*version); |
| + if (IsStoppedAndRedundant(*version)) |
| + version_info_map_.erase(version_id); |
| +} |
| + |
| +void ServiceWorkerContextWatcher::OnVersionStateChanged( |
| + int64 version_id, |
| + content::ServiceWorkerVersion::Status status) { |
| + ServiceWorkerVersionInfo* version = version_info_map_.get(version_id); |
| + DCHECK(version); |
| + if (version->status == status) |
| + return; |
| + version->status = status; |
| + SendVersionInfo(*version); |
| + if (IsStoppedAndRedundant(*version)) |
| + version_info_map_.erase(version_id); |
| +} |
| + |
| +void ServiceWorkerContextWatcher::OnRegistrationStored( |
| + int64 registration_id, |
| + const GURL& pattern) { |
| + SendRegistrationInfo(registration_id, pattern, false); |
| +} |
| + |
| +void ServiceWorkerContextWatcher::OnRegistrationDeleted( |
| + int64 registration_id, |
| + const GURL& pattern) { |
| + SendRegistrationInfo(registration_id, pattern, true); |
| +} |
| + |
| +} // namespace content |