• 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_wrapper.h"
6 
7 #include <map>
8 
9 #include "base/files/file_path.h"
10 #include "base/logging.h"
11 #include "base/threading/sequenced_worker_pool.h"
12 #include "content/browser/fileapi/chrome_blob_storage_context.h"
13 #include "content/browser/service_worker/service_worker_context_core.h"
14 #include "content/browser/service_worker/service_worker_context_observer.h"
15 #include "content/browser/service_worker/service_worker_process_manager.h"
16 #include "content/public/browser/browser_context.h"
17 #include "content/public/browser/browser_thread.h"
18 #include "net/url_request/url_request_context_getter.h"
19 #include "storage/browser/blob/blob_storage_context.h"
20 #include "storage/browser/quota/quota_manager_proxy.h"
21 
22 namespace content {
23 
ServiceWorkerContextWrapper(BrowserContext * browser_context)24 ServiceWorkerContextWrapper::ServiceWorkerContextWrapper(
25     BrowserContext* browser_context)
26     : observer_list_(
27           new ObserverListThreadSafe<ServiceWorkerContextObserver>()),
28       process_manager_(new ServiceWorkerProcessManager(browser_context)),
29       is_incognito_(false) {
30 }
31 
~ServiceWorkerContextWrapper()32 ServiceWorkerContextWrapper::~ServiceWorkerContextWrapper() {
33 }
34 
Init(const base::FilePath & user_data_directory,storage::QuotaManagerProxy * quota_manager_proxy)35 void ServiceWorkerContextWrapper::Init(
36     const base::FilePath& user_data_directory,
37     storage::QuotaManagerProxy* quota_manager_proxy) {
38   is_incognito_ = user_data_directory.empty();
39   scoped_refptr<base::SequencedTaskRunner> database_task_runner =
40       BrowserThread::GetBlockingPool()->
41           GetSequencedTaskRunnerWithShutdownBehavior(
42               BrowserThread::GetBlockingPool()->GetSequenceToken(),
43               base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
44   scoped_refptr<base::SingleThreadTaskRunner> disk_cache_thread =
45       BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE);
46   scoped_refptr<base::SequencedTaskRunner> cache_task_runner =
47       BrowserThread::GetBlockingPool()
48           ->GetSequencedTaskRunnerWithShutdownBehavior(
49               BrowserThread::GetBlockingPool()->GetSequenceToken(),
50               base::SequencedWorkerPool::SKIP_ON_SHUTDOWN);
51   InitInternal(user_data_directory,
52                cache_task_runner,
53                database_task_runner,
54                disk_cache_thread,
55                quota_manager_proxy);
56 }
57 
Shutdown()58 void ServiceWorkerContextWrapper::Shutdown() {
59   DCHECK_CURRENTLY_ON(BrowserThread::UI);
60   process_manager_->Shutdown();
61   BrowserThread::PostTask(
62       BrowserThread::IO,
63       FROM_HERE,
64       base::Bind(&ServiceWorkerContextWrapper::ShutdownOnIO, this));
65 }
66 
DeleteAndStartOver()67 void ServiceWorkerContextWrapper::DeleteAndStartOver() {
68   DCHECK_CURRENTLY_ON(BrowserThread::IO);
69   context_core_->DeleteAndStartOver(
70       base::Bind(&ServiceWorkerContextWrapper::DidDeleteAndStartOver, this));
71 }
72 
context()73 ServiceWorkerContextCore* ServiceWorkerContextWrapper::context() {
74   DCHECK_CURRENTLY_ON(BrowserThread::IO);
75   return context_core_.get();
76 }
77 
FinishRegistrationOnIO(const ServiceWorkerContext::ResultCallback & continuation,ServiceWorkerStatusCode status,int64 registration_id,int64 version_id)78 static void FinishRegistrationOnIO(
79     const ServiceWorkerContext::ResultCallback& continuation,
80     ServiceWorkerStatusCode status,
81     int64 registration_id,
82     int64 version_id) {
83   DCHECK_CURRENTLY_ON(BrowserThread::IO);
84   BrowserThread::PostTask(
85       BrowserThread::UI,
86       FROM_HERE,
87       base::Bind(continuation, status == SERVICE_WORKER_OK));
88 }
89 
RegisterServiceWorker(const GURL & pattern,const GURL & script_url,const ResultCallback & continuation)90 void ServiceWorkerContextWrapper::RegisterServiceWorker(
91     const GURL& pattern,
92     const GURL& script_url,
93     const ResultCallback& continuation) {
94   if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
95     BrowserThread::PostTask(
96         BrowserThread::IO,
97         FROM_HERE,
98         base::Bind(&ServiceWorkerContextWrapper::RegisterServiceWorker,
99                    this,
100                    pattern,
101                    script_url,
102                    continuation));
103     return;
104   }
105 
106   context()->RegisterServiceWorker(
107       pattern,
108       script_url,
109       NULL /* provider_host */,
110       base::Bind(&FinishRegistrationOnIO, continuation));
111 }
112 
FinishUnregistrationOnIO(const ServiceWorkerContext::ResultCallback & continuation,ServiceWorkerStatusCode status)113 static void FinishUnregistrationOnIO(
114     const ServiceWorkerContext::ResultCallback& continuation,
115     ServiceWorkerStatusCode status) {
116   DCHECK_CURRENTLY_ON(BrowserThread::IO);
117   BrowserThread::PostTask(
118       BrowserThread::UI,
119       FROM_HERE,
120       base::Bind(continuation, status == SERVICE_WORKER_OK));
121 }
122 
UnregisterServiceWorker(const GURL & pattern,const ResultCallback & continuation)123 void ServiceWorkerContextWrapper::UnregisterServiceWorker(
124     const GURL& pattern,
125     const ResultCallback& continuation) {
126   if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
127     BrowserThread::PostTask(
128         BrowserThread::IO,
129         FROM_HERE,
130         base::Bind(&ServiceWorkerContextWrapper::UnregisterServiceWorker,
131                    this,
132                    pattern,
133                    continuation));
134     return;
135   }
136 
137   context()->UnregisterServiceWorker(
138       pattern,
139       base::Bind(&FinishUnregistrationOnIO, continuation));
140 }
141 
Terminate()142 void ServiceWorkerContextWrapper::Terminate() {
143   DCHECK_CURRENTLY_ON(BrowserThread::UI);
144   process_manager_->Shutdown();
145 }
146 
GetAllOriginsInfo(const GetUsageInfoCallback & callback)147 void ServiceWorkerContextWrapper::GetAllOriginsInfo(
148     const GetUsageInfoCallback& callback) {
149   DCHECK_CURRENTLY_ON(BrowserThread::IO);
150   context_core_->storage()->GetAllRegistrations(base::Bind(
151       &ServiceWorkerContextWrapper::DidGetAllRegistrationsForGetAllOrigins,
152       this,
153       callback));
154 }
155 
DidGetAllRegistrationsForGetAllOrigins(const GetUsageInfoCallback & callback,const std::vector<ServiceWorkerRegistrationInfo> & registrations)156 void ServiceWorkerContextWrapper::DidGetAllRegistrationsForGetAllOrigins(
157     const GetUsageInfoCallback& callback,
158     const std::vector<ServiceWorkerRegistrationInfo>& registrations) {
159   DCHECK_CURRENTLY_ON(BrowserThread::IO);
160   std::vector<ServiceWorkerUsageInfo> usage_infos;
161 
162   std::map<GURL, ServiceWorkerUsageInfo> origins;
163   for (std::vector<ServiceWorkerRegistrationInfo>::const_iterator it =
164            registrations.begin();
165        it != registrations.end();
166        ++it) {
167     const ServiceWorkerRegistrationInfo& registration_info = *it;
168     GURL origin = registration_info.pattern.GetOrigin();
169 
170     ServiceWorkerUsageInfo& usage_info = origins[origin];
171     if (usage_info.origin.is_empty())
172       usage_info.origin = origin;
173     usage_info.scopes.push_back(registration_info.pattern);
174   }
175 
176   for (std::map<GURL, ServiceWorkerUsageInfo>::const_iterator it =
177            origins.begin();
178        it != origins.end();
179        ++it) {
180     usage_infos.push_back(it->second);
181   }
182 
183   callback.Run(usage_infos);
184 }
185 
186 namespace {
187 
EmptySuccessCallback(bool success)188 void EmptySuccessCallback(bool success) {
189 }
190 
191 }  // namespace
192 
DeleteForOrigin(const GURL & origin_url)193 void ServiceWorkerContextWrapper::DeleteForOrigin(const GURL& origin_url) {
194   DCHECK_CURRENTLY_ON(BrowserThread::IO);
195   context_core_->storage()->GetAllRegistrations(base::Bind(
196       &ServiceWorkerContextWrapper::DidGetAllRegistrationsForDeleteForOrigin,
197       this,
198       origin_url));
199 }
200 
DidGetAllRegistrationsForDeleteForOrigin(const GURL & origin,const std::vector<ServiceWorkerRegistrationInfo> & registrations)201 void ServiceWorkerContextWrapper::DidGetAllRegistrationsForDeleteForOrigin(
202     const GURL& origin,
203     const std::vector<ServiceWorkerRegistrationInfo>& registrations) {
204   DCHECK_CURRENTLY_ON(BrowserThread::IO);
205 
206   for (std::vector<ServiceWorkerRegistrationInfo>::const_iterator it =
207            registrations.begin();
208        it != registrations.end();
209        ++it) {
210     const ServiceWorkerRegistrationInfo& registration_info = *it;
211     if (origin == registration_info.pattern.GetOrigin()) {
212       UnregisterServiceWorker(registration_info.pattern,
213                               base::Bind(&EmptySuccessCallback));
214     }
215   }
216 }
217 
AddObserver(ServiceWorkerContextObserver * observer)218 void ServiceWorkerContextWrapper::AddObserver(
219     ServiceWorkerContextObserver* observer) {
220   observer_list_->AddObserver(observer);
221 }
222 
RemoveObserver(ServiceWorkerContextObserver * observer)223 void ServiceWorkerContextWrapper::RemoveObserver(
224     ServiceWorkerContextObserver* observer) {
225   observer_list_->RemoveObserver(observer);
226 }
227 
SetBlobParametersForCache(net::URLRequestContextGetter * request_context,ChromeBlobStorageContext * blob_storage_context)228 void ServiceWorkerContextWrapper::SetBlobParametersForCache(
229     net::URLRequestContextGetter* request_context,
230     ChromeBlobStorageContext* blob_storage_context) {
231   DCHECK_CURRENTLY_ON(BrowserThread::IO);
232 
233   if (context_core_ && request_context && blob_storage_context) {
234     context_core_->SetBlobParametersForCache(
235         request_context->GetURLRequestContext(),
236         blob_storage_context->context()->AsWeakPtr());
237   }
238 }
239 
InitInternal(const base::FilePath & user_data_directory,const scoped_refptr<base::SequencedTaskRunner> & stores_task_runner,const scoped_refptr<base::SequencedTaskRunner> & database_task_runner,const scoped_refptr<base::SingleThreadTaskRunner> & disk_cache_thread,storage::QuotaManagerProxy * quota_manager_proxy)240 void ServiceWorkerContextWrapper::InitInternal(
241     const base::FilePath& user_data_directory,
242     const scoped_refptr<base::SequencedTaskRunner>& stores_task_runner,
243     const scoped_refptr<base::SequencedTaskRunner>& database_task_runner,
244     const scoped_refptr<base::SingleThreadTaskRunner>& disk_cache_thread,
245     storage::QuotaManagerProxy* quota_manager_proxy) {
246   if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
247     BrowserThread::PostTask(
248         BrowserThread::IO,
249         FROM_HERE,
250         base::Bind(&ServiceWorkerContextWrapper::InitInternal,
251                    this,
252                    user_data_directory,
253                    stores_task_runner,
254                    database_task_runner,
255                    disk_cache_thread,
256                    make_scoped_refptr(quota_manager_proxy)));
257     return;
258   }
259   DCHECK(!context_core_);
260   context_core_.reset(new ServiceWorkerContextCore(user_data_directory,
261                                                    stores_task_runner,
262                                                    database_task_runner,
263                                                    disk_cache_thread,
264                                                    quota_manager_proxy,
265                                                    observer_list_.get(),
266                                                    this));
267 }
268 
ShutdownOnIO()269 void ServiceWorkerContextWrapper::ShutdownOnIO() {
270   DCHECK_CURRENTLY_ON(BrowserThread::IO);
271   context_core_.reset();
272 }
273 
DidDeleteAndStartOver(ServiceWorkerStatusCode status)274 void ServiceWorkerContextWrapper::DidDeleteAndStartOver(
275     ServiceWorkerStatusCode status) {
276   DCHECK_CURRENTLY_ON(BrowserThread::IO);
277   if (status != SERVICE_WORKER_OK) {
278     context_core_.reset();
279     return;
280   }
281   context_core_.reset(new ServiceWorkerContextCore(context_core_.get(), this));
282   DVLOG(1) << "Restarted ServiceWorkerContextCore successfully.";
283 }
284 
285 }  // namespace content
286