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/message_loop/message_loop_proxy.h"
9 #include "base/strings/string_util.h"
10 #include "content/browser/service_worker/embedded_worker_registry.h"
11 #include "content/browser/service_worker/service_worker_cache_storage_manager.h"
12 #include "content/browser/service_worker/service_worker_context_observer.h"
13 #include "content/browser/service_worker/service_worker_context_wrapper.h"
14 #include "content/browser/service_worker/service_worker_info.h"
15 #include "content/browser/service_worker/service_worker_job_coordinator.h"
16 #include "content/browser/service_worker/service_worker_process_manager.h"
17 #include "content/browser/service_worker/service_worker_provider_host.h"
18 #include "content/browser/service_worker/service_worker_register_job.h"
19 #include "content/browser/service_worker/service_worker_registration.h"
20 #include "content/browser/service_worker/service_worker_storage.h"
21 #include "content/public/browser/browser_thread.h"
26 const base::FilePath::CharType
27 ServiceWorkerContextCore::kServiceWorkerDirectory[] =
28 FILE_PATH_LITERAL("Service Worker");
30 ServiceWorkerContextCore::ProviderHostIterator::~ProviderHostIterator() {}
32 ServiceWorkerProviderHost*
33 ServiceWorkerContextCore::ProviderHostIterator::GetProviderHost() {
35 return provider_host_iterator_->GetCurrentValue();
38 void ServiceWorkerContextCore::ProviderHostIterator::Advance() {
40 DCHECK(!provider_host_iterator_->IsAtEnd());
41 DCHECK(!process_iterator_->IsAtEnd());
43 // Advance the inner iterator. If an element is reached, we're done.
44 provider_host_iterator_->Advance();
45 if (!provider_host_iterator_->IsAtEnd())
48 // Advance the outer iterator until an element is reached, or end is hit.
50 process_iterator_->Advance();
51 if (process_iterator_->IsAtEnd())
53 ProviderMap* provider_map = process_iterator_->GetCurrentValue();
54 provider_host_iterator_.reset(new ProviderMap::iterator(provider_map));
55 if (!provider_host_iterator_->IsAtEnd())
60 bool ServiceWorkerContextCore::ProviderHostIterator::IsAtEnd() {
61 return process_iterator_->IsAtEnd() &&
62 (!provider_host_iterator_ || provider_host_iterator_->IsAtEnd());
65 ServiceWorkerContextCore::ProviderHostIterator::ProviderHostIterator(
66 ProcessToProviderMap* map)
72 void ServiceWorkerContextCore::ProviderHostIterator::Initialize() {
73 process_iterator_.reset(new ProcessToProviderMap::iterator(map_));
74 // Advance to the first element.
75 while (!process_iterator_->IsAtEnd()) {
76 ProviderMap* provider_map = process_iterator_->GetCurrentValue();
77 provider_host_iterator_.reset(new ProviderMap::iterator(provider_map));
78 if (!provider_host_iterator_->IsAtEnd())
80 process_iterator_->Advance();
84 ServiceWorkerContextCore::ServiceWorkerContextCore(
85 const base::FilePath& path,
86 base::SequencedTaskRunner* cache_task_runner,
87 base::SequencedTaskRunner* database_task_runner,
88 base::MessageLoopProxy* disk_cache_thread,
89 quota::QuotaManagerProxy* quota_manager_proxy,
90 ObserverListThreadSafe<ServiceWorkerContextObserver>* observer_list,
91 ServiceWorkerContextWrapper* wrapper)
92 : weak_factory_(this),
94 providers_(new ProcessToProviderMap),
95 storage_(ServiceWorkerStorage::Create(path,
99 quota_manager_proxy)),
101 ServiceWorkerCacheStorageManager::Create(path, cache_task_runner)),
102 embedded_worker_registry_(EmbeddedWorkerRegistry::Create(AsWeakPtr())),
103 job_coordinator_(new ServiceWorkerJobCoordinator(AsWeakPtr())),
105 next_registration_handle_id_(0),
106 observer_list_(observer_list) {
109 ServiceWorkerContextCore::ServiceWorkerContextCore(
110 ServiceWorkerContextCore* old_context,
111 ServiceWorkerContextWrapper* wrapper)
112 : weak_factory_(this),
114 providers_(old_context->providers_.release()),
116 ServiceWorkerStorage::Create(AsWeakPtr(), old_context->storage())),
117 cache_manager_(ServiceWorkerCacheStorageManager::Create(
118 old_context->cache_manager())),
119 embedded_worker_registry_(EmbeddedWorkerRegistry::Create(
121 old_context->embedded_worker_registry())),
122 job_coordinator_(new ServiceWorkerJobCoordinator(AsWeakPtr())),
124 next_registration_handle_id_(0),
125 observer_list_(old_context->observer_list_) {
128 ServiceWorkerContextCore::~ServiceWorkerContextCore() {
129 for (VersionMap::iterator it = live_versions_.begin();
130 it != live_versions_.end();
132 it->second->RemoveListener(this);
134 weak_factory_.InvalidateWeakPtrs();
137 ServiceWorkerProviderHost* ServiceWorkerContextCore::GetProviderHost(
138 int process_id, int provider_id) {
139 ProviderMap* map = GetProviderMapForProcess(process_id);
142 return map->Lookup(provider_id);
145 void ServiceWorkerContextCore::AddProviderHost(
146 scoped_ptr<ServiceWorkerProviderHost> host) {
147 ServiceWorkerProviderHost* host_ptr = host.release(); // we take ownership
148 ProviderMap* map = GetProviderMapForProcess(host_ptr->process_id());
150 map = new ProviderMap;
151 providers_->AddWithID(map, host_ptr->process_id());
153 map->AddWithID(host_ptr, host_ptr->provider_id());
156 void ServiceWorkerContextCore::RemoveProviderHost(
157 int process_id, int provider_id) {
158 ProviderMap* map = GetProviderMapForProcess(process_id);
160 map->Remove(provider_id);
163 void ServiceWorkerContextCore::RemoveAllProviderHostsForProcess(
165 if (providers_->Lookup(process_id))
166 providers_->Remove(process_id);
169 scoped_ptr<ServiceWorkerContextCore::ProviderHostIterator>
170 ServiceWorkerContextCore::GetProviderHostIterator() {
171 return make_scoped_ptr(new ProviderHostIterator(providers_.get()));
174 void ServiceWorkerContextCore::RegisterServiceWorker(
176 const GURL& script_url,
177 int source_process_id,
178 ServiceWorkerProviderHost* provider_host,
179 const RegistrationCallback& callback) {
180 DCHECK_CURRENTLY_ON(BrowserThread::IO);
181 if (storage()->IsDisabled()) {
182 callback.Run(SERVICE_WORKER_ERROR_ABORT,
183 kInvalidServiceWorkerRegistrationId,
184 kInvalidServiceWorkerVersionId);
188 // TODO(kinuko): Wire the provider_host so that we can tell which document
189 // is calling .register.
191 job_coordinator_->Register(
195 base::Bind(&ServiceWorkerContextCore::RegistrationComplete,
201 void ServiceWorkerContextCore::UnregisterServiceWorker(
203 const UnregistrationCallback& callback) {
204 DCHECK_CURRENTLY_ON(BrowserThread::IO);
205 if (storage()->IsDisabled()) {
206 callback.Run(SERVICE_WORKER_ERROR_ABORT);
210 job_coordinator_->Unregister(
212 base::Bind(&ServiceWorkerContextCore::UnregistrationComplete,
218 void ServiceWorkerContextCore::UpdateServiceWorker(
219 ServiceWorkerRegistration* registration) {
220 DCHECK_CURRENTLY_ON(BrowserThread::IO);
221 if (storage()->IsDisabled())
223 job_coordinator_->Update(registration);
226 void ServiceWorkerContextCore::RegistrationComplete(
228 const ServiceWorkerContextCore::RegistrationCallback& callback,
229 ServiceWorkerStatusCode status,
230 ServiceWorkerRegistration* registration,
231 ServiceWorkerVersion* version) {
232 if (status != SERVICE_WORKER_OK) {
235 kInvalidServiceWorkerRegistrationId,
236 kInvalidServiceWorkerVersionId);
241 DCHECK_EQ(version->registration_id(), registration->id());
244 version->version_id());
245 if (observer_list_) {
246 observer_list_->Notify(&ServiceWorkerContextObserver::OnRegistrationStored,
251 void ServiceWorkerContextCore::UnregistrationComplete(
253 const ServiceWorkerContextCore::UnregistrationCallback& callback,
254 ServiceWorkerStatusCode status) {
255 callback.Run(status);
256 if (observer_list_) {
257 observer_list_->Notify(&ServiceWorkerContextObserver::OnRegistrationDeleted,
262 ServiceWorkerRegistration* ServiceWorkerContextCore::GetLiveRegistration(
264 RegistrationsMap::iterator it = live_registrations_.find(id);
265 return (it != live_registrations_.end()) ? it->second : NULL;
268 void ServiceWorkerContextCore::AddLiveRegistration(
269 ServiceWorkerRegistration* registration) {
270 DCHECK(!GetLiveRegistration(registration->id()));
271 live_registrations_[registration->id()] = registration;
274 void ServiceWorkerContextCore::RemoveLiveRegistration(int64 id) {
275 live_registrations_.erase(id);
278 ServiceWorkerVersion* ServiceWorkerContextCore::GetLiveVersion(
280 VersionMap::iterator it = live_versions_.find(id);
281 return (it != live_versions_.end()) ? it->second : NULL;
284 void ServiceWorkerContextCore::AddLiveVersion(ServiceWorkerVersion* version) {
285 DCHECK(!GetLiveVersion(version->version_id()));
286 live_versions_[version->version_id()] = version;
287 version->AddListener(this);
290 void ServiceWorkerContextCore::RemoveLiveVersion(int64 id) {
291 live_versions_.erase(id);
294 std::vector<ServiceWorkerRegistrationInfo>
295 ServiceWorkerContextCore::GetAllLiveRegistrationInfo() {
296 std::vector<ServiceWorkerRegistrationInfo> infos;
297 for (std::map<int64, ServiceWorkerRegistration*>::const_iterator iter =
298 live_registrations_.begin();
299 iter != live_registrations_.end();
301 infos.push_back(iter->second->GetInfo());
306 std::vector<ServiceWorkerVersionInfo>
307 ServiceWorkerContextCore::GetAllLiveVersionInfo() {
308 std::vector<ServiceWorkerVersionInfo> infos;
309 for (std::map<int64, ServiceWorkerVersion*>::const_iterator iter =
310 live_versions_.begin();
311 iter != live_versions_.end();
313 infos.push_back(iter->second->GetInfo());
318 int ServiceWorkerContextCore::GetNewServiceWorkerHandleId() {
319 return next_handle_id_++;
322 int ServiceWorkerContextCore::GetNewRegistrationHandleId() {
323 return next_registration_handle_id_++;
326 void ServiceWorkerContextCore::ScheduleDeleteAndStartOver() const {
328 base::MessageLoop::current()->PostTask(
330 base::Bind(&ServiceWorkerContextWrapper::DeleteAndStartOver, wrapper_));
333 void ServiceWorkerContextCore::DeleteAndStartOver(
334 const StatusCallback& callback) {
335 job_coordinator_->AbortAll();
336 storage_->DeleteAndStartOver(callback);
339 void ServiceWorkerContextCore::SetBlobParametersForCache(
340 net::URLRequestContext* request_context,
341 base::WeakPtr<webkit_blob::BlobStorageContext> blob_storage_context) {
342 DCHECK_CURRENTLY_ON(BrowserThread::IO);
344 cache_manager_->SetBlobParametersForCache(request_context,
345 blob_storage_context);
348 void ServiceWorkerContextCore::OnWorkerStarted(ServiceWorkerVersion* version) {
351 observer_list_->Notify(&ServiceWorkerContextObserver::OnWorkerStarted,
352 version->version_id(),
353 version->embedded_worker()->process_id(),
354 version->embedded_worker()->thread_id());
357 void ServiceWorkerContextCore::OnWorkerStopped(ServiceWorkerVersion* version) {
360 observer_list_->Notify(&ServiceWorkerContextObserver::OnWorkerStopped,
361 version->version_id(),
362 version->embedded_worker()->process_id(),
363 version->embedded_worker()->thread_id());
366 void ServiceWorkerContextCore::OnVersionStateChanged(
367 ServiceWorkerVersion* version) {
370 observer_list_->Notify(&ServiceWorkerContextObserver::OnVersionStateChanged,
371 version->version_id());
374 void ServiceWorkerContextCore::OnErrorReported(
375 ServiceWorkerVersion* version,
376 const base::string16& error_message,
379 const GURL& source_url) {
382 observer_list_->Notify(
383 &ServiceWorkerContextObserver::OnErrorReported,
384 version->version_id(),
385 version->embedded_worker()->process_id(),
386 version->embedded_worker()->thread_id(),
387 ServiceWorkerContextObserver::ErrorInfo(
388 error_message, line_number, column_number, source_url));
391 void ServiceWorkerContextCore::OnReportConsoleMessage(
392 ServiceWorkerVersion* version,
393 int source_identifier,
395 const base::string16& message,
397 const GURL& source_url) {
400 observer_list_->Notify(
401 &ServiceWorkerContextObserver::OnReportConsoleMessage,
402 version->version_id(),
403 version->embedded_worker()->process_id(),
404 version->embedded_worker()->thread_id(),
405 ServiceWorkerContextObserver::ConsoleMessage(
406 source_identifier, message_level, message, line_number, source_url));
409 ServiceWorkerProcessManager* ServiceWorkerContextCore::process_manager() {
410 return wrapper_->process_manager();
413 } // namespace content