Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / content / browser / service_worker / service_worker_context_core.cc
index c1eab54..7a8e386 100644 (file)
@@ -7,8 +7,11 @@
 #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) {
@@ -61,13 +134,22 @@ void ServiceWorkerContextCore::RemoveAllProviderHostsForProcess(
     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,
@@ -79,23 +161,127 @@ void ServiceWorkerContextCore::RegisterServiceWorker(
 
 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