#include "base/files/file_path.h"
#include "base/strings/string_util.h"
#include "content/browser/service_worker/embedded_worker_registry.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_info.h"
#include "content/browser/service_worker/service_worker_job_coordinator.h"
+#include "content/browser/service_worker/service_worker_process_manager.h"
#include "content/browser/service_worker/service_worker_provider_host.h"
#include "content/browser/service_worker/service_worker_register_job.h"
#include "content/browser/service_worker/service_worker_registration.h"
namespace content {
+ServiceWorkerContextCore::ProviderHostIterator::~ProviderHostIterator() {}
+
+ServiceWorkerProviderHost*
+ServiceWorkerContextCore::ProviderHostIterator::GetProviderHost() {
+ DCHECK(!IsAtEnd());
+ return provider_host_iterator_->GetCurrentValue();
+}
+
+void ServiceWorkerContextCore::ProviderHostIterator::Advance() {
+ DCHECK(!IsAtEnd());
+ DCHECK(!provider_host_iterator_->IsAtEnd());
+ DCHECK(!provider_iterator_->IsAtEnd());
+
+ // Advance the inner iterator. If an element is reached, we're done.
+ provider_host_iterator_->Advance();
+ if (!provider_host_iterator_->IsAtEnd())
+ return;
+
+ // Advance the outer iterator until an element is reached, or end is hit.
+ while (true) {
+ provider_iterator_->Advance();
+ if (provider_iterator_->IsAtEnd())
+ return;
+ ProviderMap* provider_map = provider_iterator_->GetCurrentValue();
+ provider_host_iterator_.reset(new ProviderMap::iterator(provider_map));
+ if (!provider_host_iterator_->IsAtEnd())
+ return;
+ }
+}
+
+bool ServiceWorkerContextCore::ProviderHostIterator::IsAtEnd() {
+ return provider_iterator_->IsAtEnd() &&
+ (!provider_host_iterator_ || provider_host_iterator_->IsAtEnd());
+}
+
+ServiceWorkerContextCore::ProviderHostIterator::ProviderHostIterator(
+ ProcessToProviderMap* map)
+ : map_(map) {
+ DCHECK(map);
+ Initialize();
+}
+
+void ServiceWorkerContextCore::ProviderHostIterator::Initialize() {
+ provider_iterator_.reset(new ProcessToProviderMap::iterator(map_));
+ // Advance to the first element.
+ while (!provider_iterator_->IsAtEnd()) {
+ ProviderMap* provider_map = provider_iterator_->GetCurrentValue();
+ provider_host_iterator_.reset(new ProviderMap::iterator(provider_map));
+ if (!provider_host_iterator_->IsAtEnd())
+ return;
+ provider_iterator_->Advance();
+ }
+}
+
ServiceWorkerContextCore::ServiceWorkerContextCore(
const base::FilePath& path,
- quota::QuotaManagerProxy* quota_manager_proxy)
- : storage_(new ServiceWorkerStorage(path, quota_manager_proxy)),
+ base::SequencedTaskRunner* database_task_runner,
+ quota::QuotaManagerProxy* quota_manager_proxy,
+ ObserverListThreadSafe<ServiceWorkerContextObserver>* observer_list,
+ scoped_ptr<ServiceWorkerProcessManager> process_manager)
+ : storage_(new ServiceWorkerStorage(
+ path, AsWeakPtr(), database_task_runner, quota_manager_proxy)),
embedded_worker_registry_(new EmbeddedWorkerRegistry(AsWeakPtr())),
- job_coordinator_(
- new ServiceWorkerJobCoordinator(storage_.get(),
- embedded_worker_registry_)) {}
+ job_coordinator_(new ServiceWorkerJobCoordinator(AsWeakPtr())),
+ process_manager_(process_manager.Pass()),
+ next_handle_id_(0),
+ observer_list_(observer_list) {
+}
-ServiceWorkerContextCore::~ServiceWorkerContextCore() {}
+ServiceWorkerContextCore::~ServiceWorkerContextCore() {
+ for (VersionMap::iterator it = live_versions_.begin();
+ it != live_versions_.end();
+ ++it) {
+ it->second->RemoveListener(this);
+ }
+ providers_.Clear();
+ storage_.reset();
+ job_coordinator_.reset();
+ embedded_worker_registry_ = NULL;
+}
ServiceWorkerProviderHost* ServiceWorkerContextCore::GetProviderHost(
int process_id, int provider_id) {
providers_.Remove(process_id);
}
+scoped_ptr<ServiceWorkerContextCore::ProviderHostIterator>
+ServiceWorkerContextCore::GetProviderHostIterator() {
+ return make_scoped_ptr(new ProviderHostIterator(&providers_));
+}
+
void ServiceWorkerContextCore::RegisterServiceWorker(
const GURL& pattern,
const GURL& script_url,
int source_process_id,
+ ServiceWorkerProviderHost* provider_host,
const RegistrationCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
+ // TODO(kinuko): Wire the provider_host so that we can tell which document
+ // is calling .register.
+
job_coordinator_->Register(
pattern,
script_url,
void ServiceWorkerContextCore::UnregisterServiceWorker(
const GURL& pattern,
- int source_process_id,
const UnregistrationCallback& callback) {
DCHECK_CURRENTLY_ON(BrowserThread::IO);
- job_coordinator_->Unregister(pattern, source_process_id, callback);
+ job_coordinator_->Unregister(pattern, callback);
}
void ServiceWorkerContextCore::RegistrationComplete(
const ServiceWorkerContextCore::RegistrationCallback& callback,
ServiceWorkerStatusCode status,
- const scoped_refptr<ServiceWorkerRegistration>& registration) {
+ ServiceWorkerRegistration* registration,
+ ServiceWorkerVersion* version) {
if (status != SERVICE_WORKER_OK) {
- DCHECK(!registration);
- callback.Run(status, -1L);
+ DCHECK(!version);
+ callback.Run(status,
+ kInvalidServiceWorkerRegistrationId,
+ kInvalidServiceWorkerVersionId);
+ return;
}
- callback.Run(status, registration->id());
+ DCHECK(version);
+ DCHECK_EQ(version->registration_id(), registration->id());
+ callback.Run(status,
+ registration->id(),
+ version->version_id());
+}
+
+ServiceWorkerRegistration* ServiceWorkerContextCore::GetLiveRegistration(
+ int64 id) {
+ RegistrationsMap::iterator it = live_registrations_.find(id);
+ return (it != live_registrations_.end()) ? it->second : NULL;
+}
+
+void ServiceWorkerContextCore::AddLiveRegistration(
+ ServiceWorkerRegistration* registration) {
+ DCHECK(!GetLiveRegistration(registration->id()));
+ live_registrations_[registration->id()] = registration;
+}
+
+void ServiceWorkerContextCore::RemoveLiveRegistration(int64 id) {
+ live_registrations_.erase(id);
+}
+
+ServiceWorkerVersion* ServiceWorkerContextCore::GetLiveVersion(
+ int64 id) {
+ VersionMap::iterator it = live_versions_.find(id);
+ return (it != live_versions_.end()) ? it->second : NULL;
+}
+
+void ServiceWorkerContextCore::AddLiveVersion(ServiceWorkerVersion* version) {
+ DCHECK(!GetLiveVersion(version->version_id()));
+ live_versions_[version->version_id()] = version;
+ version->AddListener(this);
+}
+
+void ServiceWorkerContextCore::RemoveLiveVersion(int64 id) {
+ live_versions_.erase(id);
+}
+
+int ServiceWorkerContextCore::GetNewServiceWorkerHandleId() {
+ return next_handle_id_++;
+}
+
+void ServiceWorkerContextCore::OnWorkerStarted(ServiceWorkerVersion* version) {
+ if (!observer_list_)
+ return;
+ observer_list_->Notify(&ServiceWorkerContextObserver::OnWorkerStarted,
+ version->version_id(),
+ version->embedded_worker()->process_id(),
+ version->embedded_worker()->thread_id());
+}
+
+void ServiceWorkerContextCore::OnWorkerStopped(ServiceWorkerVersion* version) {
+ if (!observer_list_)
+ return;
+ observer_list_->Notify(&ServiceWorkerContextObserver::OnWorkerStopped,
+ version->version_id(),
+ version->embedded_worker()->process_id(),
+ version->embedded_worker()->thread_id());
+}
+
+void ServiceWorkerContextCore::OnVersionStateChanged(
+ ServiceWorkerVersion* version) {
+ if (!observer_list_)
+ return;
+ observer_list_->Notify(&ServiceWorkerContextObserver::OnVersionStateChanged,
+ version->version_id());
+}
+
+void ServiceWorkerContextCore::OnErrorReported(
+ ServiceWorkerVersion* version,
+ const base::string16& error_message,
+ int line_number,
+ int column_number,
+ const GURL& source_url) {
+ if (!observer_list_)
+ return;
+ observer_list_->Notify(
+ &ServiceWorkerContextObserver::OnErrorReported,
+ version->version_id(),
+ version->embedded_worker()->process_id(),
+ version->embedded_worker()->thread_id(),
+ ServiceWorkerContextObserver::ErrorInfo(
+ error_message, line_number, column_number, source_url));
+}
+
+void ServiceWorkerContextCore::OnReportConsoleMessage(
+ ServiceWorkerVersion* version,
+ int source_identifier,
+ int message_level,
+ const base::string16& message,
+ int line_number,
+ const GURL& source_url) {
+ if (!observer_list_)
+ return;
+ observer_list_->Notify(
+ &ServiceWorkerContextObserver::OnReportConsoleMessage,
+ version->version_id(),
+ version->embedded_worker()->process_id(),
+ version->embedded_worker()->thread_id(),
+ ServiceWorkerContextObserver::ConsoleMessage(
+ source_identifier, message_level, message, line_number, source_url));
}
} // namespace content