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_context_observer.h"
12 #include "content/browser/service_worker/service_worker_context_wrapper.h"
13 #include "content/browser/service_worker/service_worker_info.h"
14 #include "content/browser/service_worker/service_worker_job_coordinator.h"
15 #include "content/browser/service_worker/service_worker_process_manager.h"
16 #include "content/browser/service_worker/service_worker_provider_host.h"
17 #include "content/browser/service_worker/service_worker_register_job.h"
18 #include "content/browser/service_worker/service_worker_registration.h"
19 #include "content/browser/service_worker/service_worker_storage.h"
20 #include "content/public/browser/browser_thread.h"
25 ServiceWorkerContextCore::ProviderHostIterator::~ProviderHostIterator() {}
27 ServiceWorkerProviderHost*
28 ServiceWorkerContextCore::ProviderHostIterator::GetProviderHost() {
30 return provider_host_iterator_->GetCurrentValue();
33 void ServiceWorkerContextCore::ProviderHostIterator::Advance() {
35 DCHECK(!provider_host_iterator_->IsAtEnd());
36 DCHECK(!provider_iterator_->IsAtEnd());
38 // Advance the inner iterator. If an element is reached, we're done.
39 provider_host_iterator_->Advance();
40 if (!provider_host_iterator_->IsAtEnd())
43 // Advance the outer iterator until an element is reached, or end is hit.
45 provider_iterator_->Advance();
46 if (provider_iterator_->IsAtEnd())
48 ProviderMap* provider_map = provider_iterator_->GetCurrentValue();
49 provider_host_iterator_.reset(new ProviderMap::iterator(provider_map));
50 if (!provider_host_iterator_->IsAtEnd())
55 bool ServiceWorkerContextCore::ProviderHostIterator::IsAtEnd() {
56 return provider_iterator_->IsAtEnd() &&
57 (!provider_host_iterator_ || provider_host_iterator_->IsAtEnd());
60 ServiceWorkerContextCore::ProviderHostIterator::ProviderHostIterator(
61 ProcessToProviderMap* map)
67 void ServiceWorkerContextCore::ProviderHostIterator::Initialize() {
68 provider_iterator_.reset(new ProcessToProviderMap::iterator(map_));
69 // Advance to the first element.
70 while (!provider_iterator_->IsAtEnd()) {
71 ProviderMap* provider_map = provider_iterator_->GetCurrentValue();
72 provider_host_iterator_.reset(new ProviderMap::iterator(provider_map));
73 if (!provider_host_iterator_->IsAtEnd())
75 provider_iterator_->Advance();
79 ServiceWorkerContextCore::ServiceWorkerContextCore(
80 const base::FilePath& path,
81 base::SequencedTaskRunner* database_task_runner,
82 base::MessageLoopProxy* disk_cache_thread,
83 quota::QuotaManagerProxy* quota_manager_proxy,
84 ObserverListThreadSafe<ServiceWorkerContextObserver>* observer_list,
85 ServiceWorkerContextWrapper* wrapper)
86 : weak_factory_(this),
88 storage_(new ServiceWorkerStorage(path,
92 quota_manager_proxy)),
93 embedded_worker_registry_(new EmbeddedWorkerRegistry(AsWeakPtr())),
94 job_coordinator_(new ServiceWorkerJobCoordinator(AsWeakPtr())),
96 observer_list_(observer_list) {
99 ServiceWorkerContextCore::~ServiceWorkerContextCore() {
100 for (VersionMap::iterator it = live_versions_.begin();
101 it != live_versions_.end();
103 it->second->RemoveListener(this);
105 weak_factory_.InvalidateWeakPtrs();
108 ServiceWorkerProviderHost* ServiceWorkerContextCore::GetProviderHost(
109 int process_id, int provider_id) {
110 ProviderMap* map = GetProviderMapForProcess(process_id);
113 return map->Lookup(provider_id);
116 void ServiceWorkerContextCore::AddProviderHost(
117 scoped_ptr<ServiceWorkerProviderHost> host) {
118 ServiceWorkerProviderHost* host_ptr = host.release(); // we take ownership
119 ProviderMap* map = GetProviderMapForProcess(host_ptr->process_id());
121 map = new ProviderMap;
122 providers_.AddWithID(map, host_ptr->process_id());
124 map->AddWithID(host_ptr, host_ptr->provider_id());
127 void ServiceWorkerContextCore::RemoveProviderHost(
128 int process_id, int provider_id) {
129 ProviderMap* map = GetProviderMapForProcess(process_id);
131 map->Remove(provider_id);
134 void ServiceWorkerContextCore::RemoveAllProviderHostsForProcess(
136 if (providers_.Lookup(process_id))
137 providers_.Remove(process_id);
140 scoped_ptr<ServiceWorkerContextCore::ProviderHostIterator>
141 ServiceWorkerContextCore::GetProviderHostIterator() {
142 return make_scoped_ptr(new ProviderHostIterator(&providers_));
145 void ServiceWorkerContextCore::RegisterServiceWorker(
147 const GURL& script_url,
148 int source_process_id,
149 ServiceWorkerProviderHost* provider_host,
150 const RegistrationCallback& callback) {
151 DCHECK_CURRENTLY_ON(BrowserThread::IO);
153 // TODO(kinuko): Wire the provider_host so that we can tell which document
154 // is calling .register.
156 job_coordinator_->Register(
160 base::Bind(&ServiceWorkerContextCore::RegistrationComplete,
166 void ServiceWorkerContextCore::UnregisterServiceWorker(
168 const UnregistrationCallback& callback) {
169 DCHECK_CURRENTLY_ON(BrowserThread::IO);
171 job_coordinator_->Unregister(
173 base::Bind(&ServiceWorkerContextCore::UnregistrationComplete,
179 void ServiceWorkerContextCore::RegistrationComplete(
181 const ServiceWorkerContextCore::RegistrationCallback& callback,
182 ServiceWorkerStatusCode status,
183 ServiceWorkerRegistration* registration,
184 ServiceWorkerVersion* version) {
185 if (status != SERVICE_WORKER_OK) {
188 kInvalidServiceWorkerRegistrationId,
189 kInvalidServiceWorkerVersionId);
194 DCHECK_EQ(version->registration_id(), registration->id());
197 version->version_id());
198 if (observer_list_) {
199 observer_list_->Notify(&ServiceWorkerContextObserver::OnRegistrationStored,
204 void ServiceWorkerContextCore::UnregistrationComplete(
206 const ServiceWorkerContextCore::UnregistrationCallback& callback,
207 ServiceWorkerStatusCode status) {
208 callback.Run(status);
209 if (observer_list_) {
210 observer_list_->Notify(&ServiceWorkerContextObserver::OnRegistrationDeleted,
215 ServiceWorkerRegistration* ServiceWorkerContextCore::GetLiveRegistration(
217 RegistrationsMap::iterator it = live_registrations_.find(id);
218 return (it != live_registrations_.end()) ? it->second : NULL;
221 void ServiceWorkerContextCore::AddLiveRegistration(
222 ServiceWorkerRegistration* registration) {
223 DCHECK(!GetLiveRegistration(registration->id()));
224 live_registrations_[registration->id()] = registration;
227 void ServiceWorkerContextCore::RemoveLiveRegistration(int64 id) {
228 live_registrations_.erase(id);
231 ServiceWorkerVersion* ServiceWorkerContextCore::GetLiveVersion(
233 VersionMap::iterator it = live_versions_.find(id);
234 return (it != live_versions_.end()) ? it->second : NULL;
237 void ServiceWorkerContextCore::AddLiveVersion(ServiceWorkerVersion* version) {
238 DCHECK(!GetLiveVersion(version->version_id()));
239 live_versions_[version->version_id()] = version;
240 version->AddListener(this);
243 void ServiceWorkerContextCore::RemoveLiveVersion(int64 id) {
244 live_versions_.erase(id);
247 std::vector<ServiceWorkerRegistrationInfo>
248 ServiceWorkerContextCore::GetAllLiveRegistrationInfo() {
249 std::vector<ServiceWorkerRegistrationInfo> infos;
250 for (std::map<int64, ServiceWorkerRegistration*>::const_iterator iter =
251 live_registrations_.begin();
252 iter != live_registrations_.end();
254 infos.push_back(iter->second->GetInfo());
259 std::vector<ServiceWorkerVersionInfo>
260 ServiceWorkerContextCore::GetAllLiveVersionInfo() {
261 std::vector<ServiceWorkerVersionInfo> infos;
262 for (std::map<int64, ServiceWorkerVersion*>::const_iterator iter =
263 live_versions_.begin();
264 iter != live_versions_.end();
266 infos.push_back(iter->second->GetInfo());
271 int ServiceWorkerContextCore::GetNewServiceWorkerHandleId() {
272 return next_handle_id_++;
275 void ServiceWorkerContextCore::OnWorkerStarted(ServiceWorkerVersion* version) {
278 observer_list_->Notify(&ServiceWorkerContextObserver::OnWorkerStarted,
279 version->version_id(),
280 version->embedded_worker()->process_id(),
281 version->embedded_worker()->thread_id());
284 void ServiceWorkerContextCore::OnWorkerStopped(ServiceWorkerVersion* version) {
287 observer_list_->Notify(&ServiceWorkerContextObserver::OnWorkerStopped,
288 version->version_id(),
289 version->embedded_worker()->process_id(),
290 version->embedded_worker()->thread_id());
293 void ServiceWorkerContextCore::OnVersionStateChanged(
294 ServiceWorkerVersion* version) {
297 observer_list_->Notify(&ServiceWorkerContextObserver::OnVersionStateChanged,
298 version->version_id());
301 void ServiceWorkerContextCore::OnErrorReported(
302 ServiceWorkerVersion* version,
303 const base::string16& error_message,
306 const GURL& source_url) {
309 observer_list_->Notify(
310 &ServiceWorkerContextObserver::OnErrorReported,
311 version->version_id(),
312 version->embedded_worker()->process_id(),
313 version->embedded_worker()->thread_id(),
314 ServiceWorkerContextObserver::ErrorInfo(
315 error_message, line_number, column_number, source_url));
318 void ServiceWorkerContextCore::OnReportConsoleMessage(
319 ServiceWorkerVersion* version,
320 int source_identifier,
322 const base::string16& message,
324 const GURL& source_url) {
327 observer_list_->Notify(
328 &ServiceWorkerContextObserver::OnReportConsoleMessage,
329 version->version_id(),
330 version->embedded_worker()->process_id(),
331 version->embedded_worker()->thread_id(),
332 ServiceWorkerContextObserver::ConsoleMessage(
333 source_identifier, message_level, message, line_number, source_url));
336 ServiceWorkerProcessManager* ServiceWorkerContextCore::process_manager() {
337 return wrapper_->process_manager();
340 } // namespace content