• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/single_thread_task_runner.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"
22 #include "url/gurl.h"
23 
24 namespace content {
25 
26 const base::FilePath::CharType
27     ServiceWorkerContextCore::kServiceWorkerDirectory[] =
28         FILE_PATH_LITERAL("Service Worker");
29 
~ProviderHostIterator()30 ServiceWorkerContextCore::ProviderHostIterator::~ProviderHostIterator() {}
31 
32 ServiceWorkerProviderHost*
GetProviderHost()33 ServiceWorkerContextCore::ProviderHostIterator::GetProviderHost() {
34   DCHECK(!IsAtEnd());
35   return provider_host_iterator_->GetCurrentValue();
36 }
37 
Advance()38 void ServiceWorkerContextCore::ProviderHostIterator::Advance() {
39   DCHECK(!IsAtEnd());
40   DCHECK(!provider_host_iterator_->IsAtEnd());
41   DCHECK(!process_iterator_->IsAtEnd());
42 
43   // Advance the inner iterator. If an element is reached, we're done.
44   provider_host_iterator_->Advance();
45   if (!provider_host_iterator_->IsAtEnd())
46     return;
47 
48   // Advance the outer iterator until an element is reached, or end is hit.
49   while (true) {
50     process_iterator_->Advance();
51     if (process_iterator_->IsAtEnd())
52       return;
53     ProviderMap* provider_map = process_iterator_->GetCurrentValue();
54     provider_host_iterator_.reset(new ProviderMap::iterator(provider_map));
55     if (!provider_host_iterator_->IsAtEnd())
56       return;
57   }
58 }
59 
IsAtEnd()60 bool ServiceWorkerContextCore::ProviderHostIterator::IsAtEnd() {
61   return process_iterator_->IsAtEnd() &&
62          (!provider_host_iterator_ || provider_host_iterator_->IsAtEnd());
63 }
64 
ProviderHostIterator(ProcessToProviderMap * map)65 ServiceWorkerContextCore::ProviderHostIterator::ProviderHostIterator(
66     ProcessToProviderMap* map)
67     : map_(map) {
68   DCHECK(map);
69   Initialize();
70 }
71 
Initialize()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())
79       return;
80     process_iterator_->Advance();
81   }
82 }
83 
ServiceWorkerContextCore(const base::FilePath & path,const scoped_refptr<base::SequencedTaskRunner> & cache_task_runner,const scoped_refptr<base::SequencedTaskRunner> & database_task_runner,const scoped_refptr<base::SingleThreadTaskRunner> & disk_cache_thread,storage::QuotaManagerProxy * quota_manager_proxy,ObserverListThreadSafe<ServiceWorkerContextObserver> * observer_list,ServiceWorkerContextWrapper * wrapper)84 ServiceWorkerContextCore::ServiceWorkerContextCore(
85     const base::FilePath& path,
86     const scoped_refptr<base::SequencedTaskRunner>& cache_task_runner,
87     const scoped_refptr<base::SequencedTaskRunner>& database_task_runner,
88     const scoped_refptr<base::SingleThreadTaskRunner>& disk_cache_thread,
89     storage::QuotaManagerProxy* quota_manager_proxy,
90     ObserverListThreadSafe<ServiceWorkerContextObserver>* observer_list,
91     ServiceWorkerContextWrapper* wrapper)
92     : weak_factory_(this),
93       wrapper_(wrapper),
94       providers_(new ProcessToProviderMap),
95       storage_(ServiceWorkerStorage::Create(path,
96                                             AsWeakPtr(),
97                                             database_task_runner,
98                                             disk_cache_thread,
99                                             quota_manager_proxy)),
100       cache_manager_(
101           ServiceWorkerCacheStorageManager::Create(path,
102                                                    cache_task_runner.get())),
103       embedded_worker_registry_(EmbeddedWorkerRegistry::Create(AsWeakPtr())),
104       job_coordinator_(new ServiceWorkerJobCoordinator(AsWeakPtr())),
105       next_handle_id_(0),
106       next_registration_handle_id_(0),
107       observer_list_(observer_list) {
108 }
109 
ServiceWorkerContextCore(ServiceWorkerContextCore * old_context,ServiceWorkerContextWrapper * wrapper)110 ServiceWorkerContextCore::ServiceWorkerContextCore(
111     ServiceWorkerContextCore* old_context,
112     ServiceWorkerContextWrapper* wrapper)
113     : weak_factory_(this),
114       wrapper_(wrapper),
115       providers_(old_context->providers_.release()),
116       storage_(
117           ServiceWorkerStorage::Create(AsWeakPtr(), old_context->storage())),
118       cache_manager_(ServiceWorkerCacheStorageManager::Create(
119           old_context->cache_manager())),
120       embedded_worker_registry_(EmbeddedWorkerRegistry::Create(
121           AsWeakPtr(),
122           old_context->embedded_worker_registry())),
123       job_coordinator_(new ServiceWorkerJobCoordinator(AsWeakPtr())),
124       next_handle_id_(0),
125       next_registration_handle_id_(0),
126       observer_list_(old_context->observer_list_) {
127 }
128 
~ServiceWorkerContextCore()129 ServiceWorkerContextCore::~ServiceWorkerContextCore() {
130   for (VersionMap::iterator it = live_versions_.begin();
131        it != live_versions_.end();
132        ++it) {
133     it->second->RemoveListener(this);
134   }
135   weak_factory_.InvalidateWeakPtrs();
136 }
137 
GetProviderHost(int process_id,int provider_id)138 ServiceWorkerProviderHost* ServiceWorkerContextCore::GetProviderHost(
139     int process_id, int provider_id) {
140   ProviderMap* map = GetProviderMapForProcess(process_id);
141   if (!map)
142     return NULL;
143   return map->Lookup(provider_id);
144 }
145 
AddProviderHost(scoped_ptr<ServiceWorkerProviderHost> host)146 void ServiceWorkerContextCore::AddProviderHost(
147     scoped_ptr<ServiceWorkerProviderHost> host) {
148   ServiceWorkerProviderHost* host_ptr = host.release();   // we take ownership
149   ProviderMap* map = GetProviderMapForProcess(host_ptr->process_id());
150   if (!map) {
151     map = new ProviderMap;
152     providers_->AddWithID(map, host_ptr->process_id());
153   }
154   map->AddWithID(host_ptr, host_ptr->provider_id());
155 }
156 
RemoveProviderHost(int process_id,int provider_id)157 void ServiceWorkerContextCore::RemoveProviderHost(
158     int process_id, int provider_id) {
159   ProviderMap* map = GetProviderMapForProcess(process_id);
160   DCHECK(map);
161   map->Remove(provider_id);
162 }
163 
RemoveAllProviderHostsForProcess(int process_id)164 void ServiceWorkerContextCore::RemoveAllProviderHostsForProcess(
165     int process_id) {
166   if (providers_->Lookup(process_id))
167     providers_->Remove(process_id);
168 }
169 
170 scoped_ptr<ServiceWorkerContextCore::ProviderHostIterator>
GetProviderHostIterator()171 ServiceWorkerContextCore::GetProviderHostIterator() {
172   return make_scoped_ptr(new ProviderHostIterator(providers_.get()));
173 }
174 
RegisterServiceWorker(const GURL & pattern,const GURL & script_url,ServiceWorkerProviderHost * provider_host,const RegistrationCallback & callback)175 void ServiceWorkerContextCore::RegisterServiceWorker(
176     const GURL& pattern,
177     const GURL& script_url,
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);
185     return;
186   }
187 
188   job_coordinator_->Register(
189       pattern,
190       script_url,
191       provider_host,
192       base::Bind(&ServiceWorkerContextCore::RegistrationComplete,
193                  AsWeakPtr(),
194                  pattern,
195                  callback));
196 }
197 
UnregisterServiceWorker(const GURL & pattern,const UnregistrationCallback & callback)198 void ServiceWorkerContextCore::UnregisterServiceWorker(
199     const GURL& pattern,
200     const UnregistrationCallback& callback) {
201   DCHECK_CURRENTLY_ON(BrowserThread::IO);
202   if (storage()->IsDisabled()) {
203     callback.Run(SERVICE_WORKER_ERROR_ABORT);
204     return;
205   }
206 
207   job_coordinator_->Unregister(
208       pattern,
209       base::Bind(&ServiceWorkerContextCore::UnregistrationComplete,
210                  AsWeakPtr(),
211                  pattern,
212                  callback));
213 }
214 
UpdateServiceWorker(ServiceWorkerRegistration * registration)215 void ServiceWorkerContextCore::UpdateServiceWorker(
216     ServiceWorkerRegistration* registration) {
217   DCHECK_CURRENTLY_ON(BrowserThread::IO);
218   if (storage()->IsDisabled())
219     return;
220   job_coordinator_->Update(registration);
221 }
222 
RegistrationComplete(const GURL & pattern,const ServiceWorkerContextCore::RegistrationCallback & callback,ServiceWorkerStatusCode status,ServiceWorkerRegistration * registration,ServiceWorkerVersion * version)223 void ServiceWorkerContextCore::RegistrationComplete(
224     const GURL& pattern,
225     const ServiceWorkerContextCore::RegistrationCallback& callback,
226     ServiceWorkerStatusCode status,
227     ServiceWorkerRegistration* registration,
228     ServiceWorkerVersion* version) {
229   if (status != SERVICE_WORKER_OK) {
230     DCHECK(!version);
231     callback.Run(status,
232                  kInvalidServiceWorkerRegistrationId,
233                  kInvalidServiceWorkerVersionId);
234     return;
235   }
236 
237   DCHECK(version);
238   DCHECK_EQ(version->registration_id(), registration->id());
239   callback.Run(status,
240                registration->id(),
241                version->version_id());
242   if (observer_list_.get()) {
243     observer_list_->Notify(&ServiceWorkerContextObserver::OnRegistrationStored,
244                            pattern);
245   }
246 }
247 
UnregistrationComplete(const GURL & pattern,const ServiceWorkerContextCore::UnregistrationCallback & callback,ServiceWorkerStatusCode status)248 void ServiceWorkerContextCore::UnregistrationComplete(
249     const GURL& pattern,
250     const ServiceWorkerContextCore::UnregistrationCallback& callback,
251     ServiceWorkerStatusCode status) {
252   callback.Run(status);
253   if (observer_list_.get()) {
254     observer_list_->Notify(&ServiceWorkerContextObserver::OnRegistrationDeleted,
255                            pattern);
256   }
257 }
258 
GetLiveRegistration(int64 id)259 ServiceWorkerRegistration* ServiceWorkerContextCore::GetLiveRegistration(
260     int64 id) {
261   RegistrationsMap::iterator it = live_registrations_.find(id);
262   return (it != live_registrations_.end()) ? it->second : NULL;
263 }
264 
AddLiveRegistration(ServiceWorkerRegistration * registration)265 void ServiceWorkerContextCore::AddLiveRegistration(
266     ServiceWorkerRegistration* registration) {
267   DCHECK(!GetLiveRegistration(registration->id()));
268   live_registrations_[registration->id()] = registration;
269 }
270 
RemoveLiveRegistration(int64 id)271 void ServiceWorkerContextCore::RemoveLiveRegistration(int64 id) {
272   live_registrations_.erase(id);
273 }
274 
GetLiveVersion(int64 id)275 ServiceWorkerVersion* ServiceWorkerContextCore::GetLiveVersion(
276     int64 id) {
277   VersionMap::iterator it = live_versions_.find(id);
278   return (it != live_versions_.end()) ? it->second : NULL;
279 }
280 
AddLiveVersion(ServiceWorkerVersion * version)281 void ServiceWorkerContextCore::AddLiveVersion(ServiceWorkerVersion* version) {
282   DCHECK(!GetLiveVersion(version->version_id()));
283   live_versions_[version->version_id()] = version;
284   version->AddListener(this);
285 }
286 
RemoveLiveVersion(int64 id)287 void ServiceWorkerContextCore::RemoveLiveVersion(int64 id) {
288   live_versions_.erase(id);
289 }
290 
291 std::vector<ServiceWorkerRegistrationInfo>
GetAllLiveRegistrationInfo()292 ServiceWorkerContextCore::GetAllLiveRegistrationInfo() {
293   std::vector<ServiceWorkerRegistrationInfo> infos;
294   for (std::map<int64, ServiceWorkerRegistration*>::const_iterator iter =
295            live_registrations_.begin();
296        iter != live_registrations_.end();
297        ++iter) {
298     infos.push_back(iter->second->GetInfo());
299   }
300   return infos;
301 }
302 
303 std::vector<ServiceWorkerVersionInfo>
GetAllLiveVersionInfo()304 ServiceWorkerContextCore::GetAllLiveVersionInfo() {
305   std::vector<ServiceWorkerVersionInfo> infos;
306   for (std::map<int64, ServiceWorkerVersion*>::const_iterator iter =
307            live_versions_.begin();
308        iter != live_versions_.end();
309        ++iter) {
310     infos.push_back(iter->second->GetInfo());
311   }
312   return infos;
313 }
314 
GetNewServiceWorkerHandleId()315 int ServiceWorkerContextCore::GetNewServiceWorkerHandleId() {
316   return next_handle_id_++;
317 }
318 
GetNewRegistrationHandleId()319 int ServiceWorkerContextCore::GetNewRegistrationHandleId() {
320   return next_registration_handle_id_++;
321 }
322 
ScheduleDeleteAndStartOver() const323 void ServiceWorkerContextCore::ScheduleDeleteAndStartOver() const {
324   storage_->Disable();
325   base::MessageLoop::current()->PostTask(
326       FROM_HERE,
327       base::Bind(&ServiceWorkerContextWrapper::DeleteAndStartOver, wrapper_));
328 }
329 
DeleteAndStartOver(const StatusCallback & callback)330 void ServiceWorkerContextCore::DeleteAndStartOver(
331     const StatusCallback& callback) {
332   job_coordinator_->AbortAll();
333   storage_->DeleteAndStartOver(callback);
334 }
335 
SetBlobParametersForCache(net::URLRequestContext * request_context,base::WeakPtr<storage::BlobStorageContext> blob_storage_context)336 void ServiceWorkerContextCore::SetBlobParametersForCache(
337     net::URLRequestContext* request_context,
338     base::WeakPtr<storage::BlobStorageContext> blob_storage_context) {
339   DCHECK_CURRENTLY_ON(BrowserThread::IO);
340 
341   cache_manager_->SetBlobParametersForCache(request_context,
342                                             blob_storage_context);
343 }
344 
OnWorkerStarted(ServiceWorkerVersion * version)345 void ServiceWorkerContextCore::OnWorkerStarted(ServiceWorkerVersion* version) {
346   if (!observer_list_.get())
347     return;
348   observer_list_->Notify(&ServiceWorkerContextObserver::OnWorkerStarted,
349                          version->version_id(),
350                          version->embedded_worker()->process_id(),
351                          version->embedded_worker()->thread_id());
352 }
353 
OnWorkerStopped(ServiceWorkerVersion * version)354 void ServiceWorkerContextCore::OnWorkerStopped(ServiceWorkerVersion* version) {
355   if (!observer_list_.get())
356     return;
357   observer_list_->Notify(&ServiceWorkerContextObserver::OnWorkerStopped,
358                          version->version_id(),
359                          version->embedded_worker()->process_id(),
360                          version->embedded_worker()->thread_id());
361 }
362 
OnVersionStateChanged(ServiceWorkerVersion * version)363 void ServiceWorkerContextCore::OnVersionStateChanged(
364     ServiceWorkerVersion* version) {
365   if (!observer_list_.get())
366     return;
367   observer_list_->Notify(&ServiceWorkerContextObserver::OnVersionStateChanged,
368                          version->version_id());
369 }
370 
OnErrorReported(ServiceWorkerVersion * version,const base::string16 & error_message,int line_number,int column_number,const GURL & source_url)371 void ServiceWorkerContextCore::OnErrorReported(
372     ServiceWorkerVersion* version,
373     const base::string16& error_message,
374     int line_number,
375     int column_number,
376     const GURL& source_url) {
377   if (!observer_list_.get())
378     return;
379   observer_list_->Notify(
380       &ServiceWorkerContextObserver::OnErrorReported,
381       version->version_id(),
382       version->embedded_worker()->process_id(),
383       version->embedded_worker()->thread_id(),
384       ServiceWorkerContextObserver::ErrorInfo(
385           error_message, line_number, column_number, source_url));
386 }
387 
OnReportConsoleMessage(ServiceWorkerVersion * version,int source_identifier,int message_level,const base::string16 & message,int line_number,const GURL & source_url)388 void ServiceWorkerContextCore::OnReportConsoleMessage(
389     ServiceWorkerVersion* version,
390     int source_identifier,
391     int message_level,
392     const base::string16& message,
393     int line_number,
394     const GURL& source_url) {
395   if (!observer_list_.get())
396     return;
397   observer_list_->Notify(
398       &ServiceWorkerContextObserver::OnReportConsoleMessage,
399       version->version_id(),
400       version->embedded_worker()->process_id(),
401       version->embedded_worker()->thread_id(),
402       ServiceWorkerContextObserver::ConsoleMessage(
403           source_identifier, message_level, message, line_number, source_url));
404 }
405 
process_manager()406 ServiceWorkerProcessManager* ServiceWorkerContextCore::process_manager() {
407   if (wrapper_)
408     return wrapper_->process_manager();
409   return NULL;
410 }
411 
412 }  // namespace content
413