Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / content / browser / service_worker / service_worker_context_core.cc
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.
4
5 #include "content/browser/service_worker/service_worker_context_core.h"
6
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"
20 #include "url/gurl.h"
21
22 namespace content {
23
24 ServiceWorkerContextCore::ProviderHostIterator::~ProviderHostIterator() {}
25
26 ServiceWorkerProviderHost*
27 ServiceWorkerContextCore::ProviderHostIterator::GetProviderHost() {
28   DCHECK(!IsAtEnd());
29   return provider_host_iterator_->GetCurrentValue();
30 }
31
32 void ServiceWorkerContextCore::ProviderHostIterator::Advance() {
33   DCHECK(!IsAtEnd());
34   DCHECK(!provider_host_iterator_->IsAtEnd());
35   DCHECK(!provider_iterator_->IsAtEnd());
36
37   // Advance the inner iterator. If an element is reached, we're done.
38   provider_host_iterator_->Advance();
39   if (!provider_host_iterator_->IsAtEnd())
40     return;
41
42   // Advance the outer iterator until an element is reached, or end is hit.
43   while (true) {
44     provider_iterator_->Advance();
45     if (provider_iterator_->IsAtEnd())
46       return;
47     ProviderMap* provider_map = provider_iterator_->GetCurrentValue();
48     provider_host_iterator_.reset(new ProviderMap::iterator(provider_map));
49     if (!provider_host_iterator_->IsAtEnd())
50       return;
51   }
52 }
53
54 bool ServiceWorkerContextCore::ProviderHostIterator::IsAtEnd() {
55   return provider_iterator_->IsAtEnd() &&
56          (!provider_host_iterator_ || provider_host_iterator_->IsAtEnd());
57 }
58
59 ServiceWorkerContextCore::ProviderHostIterator::ProviderHostIterator(
60     ProcessToProviderMap* map)
61     : map_(map) {
62   DCHECK(map);
63   Initialize();
64 }
65
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())
73       return;
74     provider_iterator_->Advance();
75   }
76 }
77
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()),
89       next_handle_id_(0),
90       observer_list_(observer_list) {
91 }
92
93 ServiceWorkerContextCore::~ServiceWorkerContextCore() {
94   for (VersionMap::iterator it = live_versions_.begin();
95        it != live_versions_.end();
96        ++it) {
97     it->second->RemoveListener(this);
98   }
99   providers_.Clear();
100   storage_.reset();
101   job_coordinator_.reset();
102   embedded_worker_registry_ = NULL;
103 }
104
105 ServiceWorkerProviderHost* ServiceWorkerContextCore::GetProviderHost(
106     int process_id, int provider_id) {
107   ProviderMap* map = GetProviderMapForProcess(process_id);
108   if (!map)
109     return NULL;
110   return map->Lookup(provider_id);
111 }
112
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());
117   if (!map) {
118     map = new ProviderMap;
119     providers_.AddWithID(map, host_ptr->process_id());
120   }
121   map->AddWithID(host_ptr, host_ptr->provider_id());
122 }
123
124 void ServiceWorkerContextCore::RemoveProviderHost(
125     int process_id, int provider_id) {
126   ProviderMap* map = GetProviderMapForProcess(process_id);
127   DCHECK(map);
128   map->Remove(provider_id);
129 }
130
131 void ServiceWorkerContextCore::RemoveAllProviderHostsForProcess(
132     int process_id) {
133   if (providers_.Lookup(process_id))
134     providers_.Remove(process_id);
135 }
136
137 scoped_ptr<ServiceWorkerContextCore::ProviderHostIterator>
138 ServiceWorkerContextCore::GetProviderHostIterator() {
139   return make_scoped_ptr(new ProviderHostIterator(&providers_));
140 }
141
142 void ServiceWorkerContextCore::RegisterServiceWorker(
143     const GURL& pattern,
144     const GURL& script_url,
145     int source_process_id,
146     ServiceWorkerProviderHost* provider_host,
147     const RegistrationCallback& callback) {
148   DCHECK_CURRENTLY_ON(BrowserThread::IO);
149
150   // TODO(kinuko): Wire the provider_host so that we can tell which document
151   // is calling .register.
152
153   job_coordinator_->Register(
154       pattern,
155       script_url,
156       source_process_id,
157       base::Bind(&ServiceWorkerContextCore::RegistrationComplete,
158                  AsWeakPtr(),
159                  callback));
160 }
161
162 void ServiceWorkerContextCore::UnregisterServiceWorker(
163     const GURL& pattern,
164     const UnregistrationCallback& callback) {
165   DCHECK_CURRENTLY_ON(BrowserThread::IO);
166
167   job_coordinator_->Unregister(pattern, callback);
168 }
169
170 void ServiceWorkerContextCore::RegistrationComplete(
171     const ServiceWorkerContextCore::RegistrationCallback& callback,
172     ServiceWorkerStatusCode status,
173     ServiceWorkerRegistration* registration,
174     ServiceWorkerVersion* version) {
175   if (status != SERVICE_WORKER_OK) {
176     DCHECK(!version);
177     callback.Run(status,
178                  kInvalidServiceWorkerRegistrationId,
179                  kInvalidServiceWorkerVersionId);
180     return;
181   }
182
183   DCHECK(version);
184   DCHECK_EQ(version->registration_id(), registration->id());
185   callback.Run(status,
186                registration->id(),
187                version->version_id());
188 }
189
190 ServiceWorkerRegistration* ServiceWorkerContextCore::GetLiveRegistration(
191     int64 id) {
192   RegistrationsMap::iterator it = live_registrations_.find(id);
193   return (it != live_registrations_.end()) ? it->second : NULL;
194 }
195
196 void ServiceWorkerContextCore::AddLiveRegistration(
197     ServiceWorkerRegistration* registration) {
198   DCHECK(!GetLiveRegistration(registration->id()));
199   live_registrations_[registration->id()] = registration;
200 }
201
202 void ServiceWorkerContextCore::RemoveLiveRegistration(int64 id) {
203   live_registrations_.erase(id);
204 }
205
206 ServiceWorkerVersion* ServiceWorkerContextCore::GetLiveVersion(
207     int64 id) {
208   VersionMap::iterator it = live_versions_.find(id);
209   return (it != live_versions_.end()) ? it->second : NULL;
210 }
211
212 void ServiceWorkerContextCore::AddLiveVersion(ServiceWorkerVersion* version) {
213   DCHECK(!GetLiveVersion(version->version_id()));
214   live_versions_[version->version_id()] = version;
215   version->AddListener(this);
216 }
217
218 void ServiceWorkerContextCore::RemoveLiveVersion(int64 id) {
219   live_versions_.erase(id);
220 }
221
222 int ServiceWorkerContextCore::GetNewServiceWorkerHandleId() {
223   return next_handle_id_++;
224 }
225
226 void ServiceWorkerContextCore::OnWorkerStarted(ServiceWorkerVersion* version) {
227   if (!observer_list_)
228     return;
229   observer_list_->Notify(&ServiceWorkerContextObserver::OnWorkerStarted,
230                          version->version_id(),
231                          version->embedded_worker()->process_id(),
232                          version->embedded_worker()->thread_id());
233 }
234
235 void ServiceWorkerContextCore::OnWorkerStopped(ServiceWorkerVersion* version) {
236   if (!observer_list_)
237     return;
238   observer_list_->Notify(&ServiceWorkerContextObserver::OnWorkerStopped,
239                          version->version_id(),
240                          version->embedded_worker()->process_id(),
241                          version->embedded_worker()->thread_id());
242 }
243
244 void ServiceWorkerContextCore::OnVersionStateChanged(
245     ServiceWorkerVersion* version) {
246   if (!observer_list_)
247     return;
248   observer_list_->Notify(&ServiceWorkerContextObserver::OnVersionStateChanged,
249                          version->version_id());
250 }
251
252 void ServiceWorkerContextCore::OnErrorReported(
253     ServiceWorkerVersion* version,
254     const base::string16& error_message,
255     int line_number,
256     int column_number,
257     const GURL& source_url) {
258   if (!observer_list_)
259     return;
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));
267 }
268
269 void ServiceWorkerContextCore::OnReportConsoleMessage(
270     ServiceWorkerVersion* version,
271     int source_identifier,
272     int message_level,
273     const base::string16& message,
274     int line_number,
275     const GURL& source_url) {
276   if (!observer_list_)
277     return;
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));
285 }
286
287 }  // namespace content