Upstream version 8.37.180.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/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"
21 #include "url/gurl.h"
22
23 namespace content {
24
25 ServiceWorkerContextCore::ProviderHostIterator::~ProviderHostIterator() {}
26
27 ServiceWorkerProviderHost*
28 ServiceWorkerContextCore::ProviderHostIterator::GetProviderHost() {
29   DCHECK(!IsAtEnd());
30   return provider_host_iterator_->GetCurrentValue();
31 }
32
33 void ServiceWorkerContextCore::ProviderHostIterator::Advance() {
34   DCHECK(!IsAtEnd());
35   DCHECK(!provider_host_iterator_->IsAtEnd());
36   DCHECK(!provider_iterator_->IsAtEnd());
37
38   // Advance the inner iterator. If an element is reached, we're done.
39   provider_host_iterator_->Advance();
40   if (!provider_host_iterator_->IsAtEnd())
41     return;
42
43   // Advance the outer iterator until an element is reached, or end is hit.
44   while (true) {
45     provider_iterator_->Advance();
46     if (provider_iterator_->IsAtEnd())
47       return;
48     ProviderMap* provider_map = provider_iterator_->GetCurrentValue();
49     provider_host_iterator_.reset(new ProviderMap::iterator(provider_map));
50     if (!provider_host_iterator_->IsAtEnd())
51       return;
52   }
53 }
54
55 bool ServiceWorkerContextCore::ProviderHostIterator::IsAtEnd() {
56   return provider_iterator_->IsAtEnd() &&
57          (!provider_host_iterator_ || provider_host_iterator_->IsAtEnd());
58 }
59
60 ServiceWorkerContextCore::ProviderHostIterator::ProviderHostIterator(
61     ProcessToProviderMap* map)
62     : map_(map) {
63   DCHECK(map);
64   Initialize();
65 }
66
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())
74       return;
75     provider_iterator_->Advance();
76   }
77 }
78
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),
87       wrapper_(wrapper),
88       storage_(new ServiceWorkerStorage(path,
89                                         AsWeakPtr(),
90                                         database_task_runner,
91                                         disk_cache_thread,
92                                         quota_manager_proxy)),
93       embedded_worker_registry_(new EmbeddedWorkerRegistry(AsWeakPtr())),
94       job_coordinator_(new ServiceWorkerJobCoordinator(AsWeakPtr())),
95       next_handle_id_(0),
96       observer_list_(observer_list) {
97 }
98
99 ServiceWorkerContextCore::~ServiceWorkerContextCore() {
100   for (VersionMap::iterator it = live_versions_.begin();
101        it != live_versions_.end();
102        ++it) {
103     it->second->RemoveListener(this);
104   }
105   weak_factory_.InvalidateWeakPtrs();
106 }
107
108 ServiceWorkerProviderHost* ServiceWorkerContextCore::GetProviderHost(
109     int process_id, int provider_id) {
110   ProviderMap* map = GetProviderMapForProcess(process_id);
111   if (!map)
112     return NULL;
113   return map->Lookup(provider_id);
114 }
115
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());
120   if (!map) {
121     map = new ProviderMap;
122     providers_.AddWithID(map, host_ptr->process_id());
123   }
124   map->AddWithID(host_ptr, host_ptr->provider_id());
125 }
126
127 void ServiceWorkerContextCore::RemoveProviderHost(
128     int process_id, int provider_id) {
129   ProviderMap* map = GetProviderMapForProcess(process_id);
130   DCHECK(map);
131   map->Remove(provider_id);
132 }
133
134 void ServiceWorkerContextCore::RemoveAllProviderHostsForProcess(
135     int process_id) {
136   if (providers_.Lookup(process_id))
137     providers_.Remove(process_id);
138 }
139
140 scoped_ptr<ServiceWorkerContextCore::ProviderHostIterator>
141 ServiceWorkerContextCore::GetProviderHostIterator() {
142   return make_scoped_ptr(new ProviderHostIterator(&providers_));
143 }
144
145 void ServiceWorkerContextCore::RegisterServiceWorker(
146     const GURL& pattern,
147     const GURL& script_url,
148     int source_process_id,
149     ServiceWorkerProviderHost* provider_host,
150     const RegistrationCallback& callback) {
151   DCHECK_CURRENTLY_ON(BrowserThread::IO);
152
153   // TODO(kinuko): Wire the provider_host so that we can tell which document
154   // is calling .register.
155
156   job_coordinator_->Register(
157       pattern,
158       script_url,
159       source_process_id,
160       base::Bind(&ServiceWorkerContextCore::RegistrationComplete,
161                  AsWeakPtr(),
162                  pattern,
163                  callback));
164 }
165
166 void ServiceWorkerContextCore::UnregisterServiceWorker(
167     const GURL& pattern,
168     const UnregistrationCallback& callback) {
169   DCHECK_CURRENTLY_ON(BrowserThread::IO);
170
171   job_coordinator_->Unregister(
172       pattern,
173       base::Bind(&ServiceWorkerContextCore::UnregistrationComplete,
174                  AsWeakPtr(),
175                  pattern,
176                  callback));
177 }
178
179 void ServiceWorkerContextCore::RegistrationComplete(
180     const GURL& pattern,
181     const ServiceWorkerContextCore::RegistrationCallback& callback,
182     ServiceWorkerStatusCode status,
183     ServiceWorkerRegistration* registration,
184     ServiceWorkerVersion* version) {
185   if (status != SERVICE_WORKER_OK) {
186     DCHECK(!version);
187     callback.Run(status,
188                  kInvalidServiceWorkerRegistrationId,
189                  kInvalidServiceWorkerVersionId);
190     return;
191   }
192
193   DCHECK(version);
194   DCHECK_EQ(version->registration_id(), registration->id());
195   callback.Run(status,
196                registration->id(),
197                version->version_id());
198   if (observer_list_) {
199     observer_list_->Notify(&ServiceWorkerContextObserver::OnRegistrationStored,
200                            pattern);
201   }
202 }
203
204 void ServiceWorkerContextCore::UnregistrationComplete(
205     const GURL& pattern,
206     const ServiceWorkerContextCore::UnregistrationCallback& callback,
207     ServiceWorkerStatusCode status) {
208   callback.Run(status);
209   if (observer_list_) {
210     observer_list_->Notify(&ServiceWorkerContextObserver::OnRegistrationDeleted,
211                            pattern);
212   }
213 }
214
215 ServiceWorkerRegistration* ServiceWorkerContextCore::GetLiveRegistration(
216     int64 id) {
217   RegistrationsMap::iterator it = live_registrations_.find(id);
218   return (it != live_registrations_.end()) ? it->second : NULL;
219 }
220
221 void ServiceWorkerContextCore::AddLiveRegistration(
222     ServiceWorkerRegistration* registration) {
223   DCHECK(!GetLiveRegistration(registration->id()));
224   live_registrations_[registration->id()] = registration;
225 }
226
227 void ServiceWorkerContextCore::RemoveLiveRegistration(int64 id) {
228   live_registrations_.erase(id);
229 }
230
231 ServiceWorkerVersion* ServiceWorkerContextCore::GetLiveVersion(
232     int64 id) {
233   VersionMap::iterator it = live_versions_.find(id);
234   return (it != live_versions_.end()) ? it->second : NULL;
235 }
236
237 void ServiceWorkerContextCore::AddLiveVersion(ServiceWorkerVersion* version) {
238   DCHECK(!GetLiveVersion(version->version_id()));
239   live_versions_[version->version_id()] = version;
240   version->AddListener(this);
241 }
242
243 void ServiceWorkerContextCore::RemoveLiveVersion(int64 id) {
244   live_versions_.erase(id);
245 }
246
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();
253        ++iter) {
254     infos.push_back(iter->second->GetInfo());
255   }
256   return infos;
257 }
258
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();
265        ++iter) {
266     infos.push_back(iter->second->GetInfo());
267   }
268   return infos;
269 }
270
271 int ServiceWorkerContextCore::GetNewServiceWorkerHandleId() {
272   return next_handle_id_++;
273 }
274
275 void ServiceWorkerContextCore::OnWorkerStarted(ServiceWorkerVersion* version) {
276   if (!observer_list_)
277     return;
278   observer_list_->Notify(&ServiceWorkerContextObserver::OnWorkerStarted,
279                          version->version_id(),
280                          version->embedded_worker()->process_id(),
281                          version->embedded_worker()->thread_id());
282 }
283
284 void ServiceWorkerContextCore::OnWorkerStopped(ServiceWorkerVersion* version) {
285   if (!observer_list_)
286     return;
287   observer_list_->Notify(&ServiceWorkerContextObserver::OnWorkerStopped,
288                          version->version_id(),
289                          version->embedded_worker()->process_id(),
290                          version->embedded_worker()->thread_id());
291 }
292
293 void ServiceWorkerContextCore::OnVersionStateChanged(
294     ServiceWorkerVersion* version) {
295   if (!observer_list_)
296     return;
297   observer_list_->Notify(&ServiceWorkerContextObserver::OnVersionStateChanged,
298                          version->version_id());
299 }
300
301 void ServiceWorkerContextCore::OnErrorReported(
302     ServiceWorkerVersion* version,
303     const base::string16& error_message,
304     int line_number,
305     int column_number,
306     const GURL& source_url) {
307   if (!observer_list_)
308     return;
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));
316 }
317
318 void ServiceWorkerContextCore::OnReportConsoleMessage(
319     ServiceWorkerVersion* version,
320     int source_identifier,
321     int message_level,
322     const base::string16& message,
323     int line_number,
324     const GURL& source_url) {
325   if (!observer_list_)
326     return;
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));
334 }
335
336 ServiceWorkerProcessManager* ServiceWorkerContextCore::process_manager() {
337   return wrapper_->process_manager();
338 }
339
340 }  // namespace content