1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/service_worker/service_worker_context_core.h"
7 #include "base/files/file_path.h"
8 #include "base/strings/string_util.h"
9 #include "content/browser/service_worker/embedded_worker_registry.h"
10 #include "content/browser/service_worker/service_worker_context_observer.h"
11 #include "content/browser/service_worker/service_worker_context_wrapper.h"
12 #include "content/browser/service_worker/service_worker_info.h"
13 #include "content/browser/service_worker/service_worker_job_coordinator.h"
14 #include "content/browser/service_worker/service_worker_process_manager.h"
15 #include "content/browser/service_worker/service_worker_provider_host.h"
16 #include "content/browser/service_worker/service_worker_register_job.h"
17 #include "content/browser/service_worker/service_worker_registration.h"
18 #include "content/browser/service_worker/service_worker_storage.h"
19 #include "content/public/browser/browser_thread.h"
24 ServiceWorkerContextCore::ProviderHostIterator::~ProviderHostIterator() {}
26 ServiceWorkerProviderHost*
27 ServiceWorkerContextCore::ProviderHostIterator::GetProviderHost() {
29 return provider_host_iterator_->GetCurrentValue();
32 void ServiceWorkerContextCore::ProviderHostIterator::Advance() {
34 DCHECK(!provider_host_iterator_->IsAtEnd());
35 DCHECK(!provider_iterator_->IsAtEnd());
37 // Advance the inner iterator. If an element is reached, we're done.
38 provider_host_iterator_->Advance();
39 if (!provider_host_iterator_->IsAtEnd())
42 // Advance the outer iterator until an element is reached, or end is hit.
44 provider_iterator_->Advance();
45 if (provider_iterator_->IsAtEnd())
47 ProviderMap* provider_map = provider_iterator_->GetCurrentValue();
48 provider_host_iterator_.reset(new ProviderMap::iterator(provider_map));
49 if (!provider_host_iterator_->IsAtEnd())
54 bool ServiceWorkerContextCore::ProviderHostIterator::IsAtEnd() {
55 return provider_iterator_->IsAtEnd() &&
56 (!provider_host_iterator_ || provider_host_iterator_->IsAtEnd());
59 ServiceWorkerContextCore::ProviderHostIterator::ProviderHostIterator(
60 ProcessToProviderMap* map)
66 void ServiceWorkerContextCore::ProviderHostIterator::Initialize() {
67 provider_iterator_.reset(new ProcessToProviderMap::iterator(map_));
68 // Advance to the first element.
69 while (!provider_iterator_->IsAtEnd()) {
70 ProviderMap* provider_map = provider_iterator_->GetCurrentValue();
71 provider_host_iterator_.reset(new ProviderMap::iterator(provider_map));
72 if (!provider_host_iterator_->IsAtEnd())
74 provider_iterator_->Advance();
78 ServiceWorkerContextCore::ServiceWorkerContextCore(
79 const base::FilePath& path,
80 base::SequencedTaskRunner* database_task_runner,
81 quota::QuotaManagerProxy* quota_manager_proxy,
82 ObserverListThreadSafe<ServiceWorkerContextObserver>* observer_list,
83 scoped_ptr<ServiceWorkerProcessManager> process_manager)
84 : storage_(new ServiceWorkerStorage(
85 path, AsWeakPtr(), database_task_runner, quota_manager_proxy)),
86 embedded_worker_registry_(new EmbeddedWorkerRegistry(AsWeakPtr())),
87 job_coordinator_(new ServiceWorkerJobCoordinator(AsWeakPtr())),
88 process_manager_(process_manager.Pass()),
90 observer_list_(observer_list) {
93 ServiceWorkerContextCore::~ServiceWorkerContextCore() {
94 for (VersionMap::iterator it = live_versions_.begin();
95 it != live_versions_.end();
97 it->second->RemoveListener(this);
101 job_coordinator_.reset();
102 embedded_worker_registry_ = NULL;
105 ServiceWorkerProviderHost* ServiceWorkerContextCore::GetProviderHost(
106 int process_id, int provider_id) {
107 ProviderMap* map = GetProviderMapForProcess(process_id);
110 return map->Lookup(provider_id);
113 void ServiceWorkerContextCore::AddProviderHost(
114 scoped_ptr<ServiceWorkerProviderHost> host) {
115 ServiceWorkerProviderHost* host_ptr = host.release(); // we take ownership
116 ProviderMap* map = GetProviderMapForProcess(host_ptr->process_id());
118 map = new ProviderMap;
119 providers_.AddWithID(map, host_ptr->process_id());
121 map->AddWithID(host_ptr, host_ptr->provider_id());
124 void ServiceWorkerContextCore::RemoveProviderHost(
125 int process_id, int provider_id) {
126 ProviderMap* map = GetProviderMapForProcess(process_id);
128 map->Remove(provider_id);
131 void ServiceWorkerContextCore::RemoveAllProviderHostsForProcess(
133 if (providers_.Lookup(process_id))
134 providers_.Remove(process_id);
137 scoped_ptr<ServiceWorkerContextCore::ProviderHostIterator>
138 ServiceWorkerContextCore::GetProviderHostIterator() {
139 return make_scoped_ptr(new ProviderHostIterator(&providers_));
142 void ServiceWorkerContextCore::RegisterServiceWorker(
144 const GURL& script_url,
145 int source_process_id,
146 ServiceWorkerProviderHost* provider_host,
147 const RegistrationCallback& callback) {
148 DCHECK_CURRENTLY_ON(BrowserThread::IO);
150 // TODO(kinuko): Wire the provider_host so that we can tell which document
151 // is calling .register.
153 job_coordinator_->Register(
157 base::Bind(&ServiceWorkerContextCore::RegistrationComplete,
162 void ServiceWorkerContextCore::UnregisterServiceWorker(
164 const UnregistrationCallback& callback) {
165 DCHECK_CURRENTLY_ON(BrowserThread::IO);
167 job_coordinator_->Unregister(pattern, callback);
170 void ServiceWorkerContextCore::RegistrationComplete(
171 const ServiceWorkerContextCore::RegistrationCallback& callback,
172 ServiceWorkerStatusCode status,
173 ServiceWorkerRegistration* registration,
174 ServiceWorkerVersion* version) {
175 if (status != SERVICE_WORKER_OK) {
178 kInvalidServiceWorkerRegistrationId,
179 kInvalidServiceWorkerVersionId);
184 DCHECK_EQ(version->registration_id(), registration->id());
187 version->version_id());
190 ServiceWorkerRegistration* ServiceWorkerContextCore::GetLiveRegistration(
192 RegistrationsMap::iterator it = live_registrations_.find(id);
193 return (it != live_registrations_.end()) ? it->second : NULL;
196 void ServiceWorkerContextCore::AddLiveRegistration(
197 ServiceWorkerRegistration* registration) {
198 DCHECK(!GetLiveRegistration(registration->id()));
199 live_registrations_[registration->id()] = registration;
202 void ServiceWorkerContextCore::RemoveLiveRegistration(int64 id) {
203 live_registrations_.erase(id);
206 ServiceWorkerVersion* ServiceWorkerContextCore::GetLiveVersion(
208 VersionMap::iterator it = live_versions_.find(id);
209 return (it != live_versions_.end()) ? it->second : NULL;
212 void ServiceWorkerContextCore::AddLiveVersion(ServiceWorkerVersion* version) {
213 DCHECK(!GetLiveVersion(version->version_id()));
214 live_versions_[version->version_id()] = version;
215 version->AddListener(this);
218 void ServiceWorkerContextCore::RemoveLiveVersion(int64 id) {
219 live_versions_.erase(id);
222 int ServiceWorkerContextCore::GetNewServiceWorkerHandleId() {
223 return next_handle_id_++;
226 void ServiceWorkerContextCore::OnWorkerStarted(ServiceWorkerVersion* version) {
229 observer_list_->Notify(&ServiceWorkerContextObserver::OnWorkerStarted,
230 version->version_id(),
231 version->embedded_worker()->process_id(),
232 version->embedded_worker()->thread_id());
235 void ServiceWorkerContextCore::OnWorkerStopped(ServiceWorkerVersion* version) {
238 observer_list_->Notify(&ServiceWorkerContextObserver::OnWorkerStopped,
239 version->version_id(),
240 version->embedded_worker()->process_id(),
241 version->embedded_worker()->thread_id());
244 void ServiceWorkerContextCore::OnVersionStateChanged(
245 ServiceWorkerVersion* version) {
248 observer_list_->Notify(&ServiceWorkerContextObserver::OnVersionStateChanged,
249 version->version_id());
252 void ServiceWorkerContextCore::OnErrorReported(
253 ServiceWorkerVersion* version,
254 const base::string16& error_message,
257 const GURL& source_url) {
260 observer_list_->Notify(
261 &ServiceWorkerContextObserver::OnErrorReported,
262 version->version_id(),
263 version->embedded_worker()->process_id(),
264 version->embedded_worker()->thread_id(),
265 ServiceWorkerContextObserver::ErrorInfo(
266 error_message, line_number, column_number, source_url));
269 void ServiceWorkerContextCore::OnReportConsoleMessage(
270 ServiceWorkerVersion* version,
271 int source_identifier,
273 const base::string16& message,
275 const GURL& source_url) {
278 observer_list_->Notify(
279 &ServiceWorkerContextObserver::OnReportConsoleMessage,
280 version->version_id(),
281 version->embedded_worker()->process_id(),
282 version->embedded_worker()->thread_id(),
283 ServiceWorkerContextObserver::ConsoleMessage(
284 source_identifier, message_level, message, line_number, source_url));
287 } // namespace content