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_wrapper.h"
9 #include "base/barrier_closure.h"
10 #include "base/files/file_path.h"
11 #include "base/logging.h"
12 #include "base/threading/sequenced_worker_pool.h"
13 #include "content/browser/fileapi/chrome_blob_storage_context.h"
14 #include "content/browser/service_worker/service_worker_context_core.h"
15 #include "content/browser/service_worker/service_worker_context_observer.h"
16 #include "content/browser/service_worker/service_worker_process_manager.h"
17 #include "content/browser/service_worker/service_worker_quota_client.h"
18 #include "content/public/browser/browser_context.h"
19 #include "content/public/browser/browser_thread.h"
20 #include "net/url_request/url_request_context_getter.h"
21 #include "storage/browser/blob/blob_storage_context.h"
22 #include "storage/browser/quota/quota_manager_proxy.h"
23 #include "storage/browser/quota/special_storage_policy.h"
27 ServiceWorkerContextWrapper::ServiceWorkerContextWrapper(
28 BrowserContext
* browser_context
)
30 new ObserverListThreadSafe
<ServiceWorkerContextObserver
>()),
31 process_manager_(new ServiceWorkerProcessManager(browser_context
)),
32 is_incognito_(false) {
35 ServiceWorkerContextWrapper::~ServiceWorkerContextWrapper() {
38 void ServiceWorkerContextWrapper::Init(
39 const base::FilePath
& user_data_directory
,
40 storage::QuotaManagerProxy
* quota_manager_proxy
,
41 storage::SpecialStoragePolicy
* special_storage_policy
) {
42 is_incognito_
= user_data_directory
.empty();
43 base::SequencedWorkerPool
* pool
= BrowserThread::GetBlockingPool();
44 scoped_ptr
<ServiceWorkerDatabaseTaskManager
> database_task_manager(
45 new ServiceWorkerDatabaseTaskManagerImpl(pool
));
46 scoped_refptr
<base::SingleThreadTaskRunner
> disk_cache_thread
=
47 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::CACHE
);
48 scoped_refptr
<base::SequencedTaskRunner
> cache_task_runner
=
49 pool
->GetSequencedTaskRunnerWithShutdownBehavior(
50 BrowserThread::GetBlockingPool()->GetSequenceToken(),
51 base::SequencedWorkerPool::SKIP_ON_SHUTDOWN
);
52 InitInternal(user_data_directory
,
54 database_task_manager
.Pass(),
57 special_storage_policy
);
60 void ServiceWorkerContextWrapper::Shutdown() {
61 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
62 process_manager_
->Shutdown();
63 BrowserThread::PostTask(
66 base::Bind(&ServiceWorkerContextWrapper::ShutdownOnIO
, this));
69 void ServiceWorkerContextWrapper::DeleteAndStartOver() {
70 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
71 context_core_
->DeleteAndStartOver(
72 base::Bind(&ServiceWorkerContextWrapper::DidDeleteAndStartOver
, this));
75 ServiceWorkerContextCore
* ServiceWorkerContextWrapper::context() {
76 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
77 return context_core_
.get();
80 static void FinishRegistrationOnIO(
81 const ServiceWorkerContext::ResultCallback
& continuation
,
82 ServiceWorkerStatusCode status
,
83 int64 registration_id
) {
84 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
85 BrowserThread::PostTask(
88 base::Bind(continuation
, status
== SERVICE_WORKER_OK
));
91 void ServiceWorkerContextWrapper::RegisterServiceWorker(
93 const GURL
& script_url
,
94 const ResultCallback
& continuation
) {
95 if (!BrowserThread::CurrentlyOn(BrowserThread::IO
)) {
96 BrowserThread::PostTask(
99 base::Bind(&ServiceWorkerContextWrapper::RegisterServiceWorker
,
106 if (!context_core_
.get()) {
107 LOG(ERROR
) << "ServiceWorkerContextCore is no longer alive.";
108 BrowserThread::PostTask(
111 base::Bind(continuation
, false));
114 context()->RegisterServiceWorker(
117 NULL
/* provider_host */,
118 base::Bind(&FinishRegistrationOnIO
, continuation
));
121 static void FinishUnregistrationOnIO(
122 const ServiceWorkerContext::ResultCallback
& continuation
,
123 ServiceWorkerStatusCode status
) {
124 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
125 BrowserThread::PostTask(
128 base::Bind(continuation
, status
== SERVICE_WORKER_OK
));
131 void ServiceWorkerContextWrapper::UnregisterServiceWorker(
133 const ResultCallback
& continuation
) {
134 if (!BrowserThread::CurrentlyOn(BrowserThread::IO
)) {
135 BrowserThread::PostTask(
138 base::Bind(&ServiceWorkerContextWrapper::UnregisterServiceWorker
,
144 if (!context_core_
.get()) {
145 LOG(ERROR
) << "ServiceWorkerContextCore is no longer alive.";
146 BrowserThread::PostTask(
149 base::Bind(continuation
, false));
153 context()->UnregisterServiceWorker(
155 base::Bind(&FinishUnregistrationOnIO
, continuation
));
158 void ServiceWorkerContextWrapper::Terminate() {
159 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
160 process_manager_
->Shutdown();
163 void ServiceWorkerContextWrapper::GetAllOriginsInfo(
164 const GetUsageInfoCallback
& callback
) {
165 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
166 if (!context_core_
.get()) {
167 LOG(ERROR
) << "ServiceWorkerContextCore is no longer alive.";
168 BrowserThread::PostTask(
171 base::Bind(callback
, std::vector
<ServiceWorkerUsageInfo
>()));
174 context()->storage()->GetAllRegistrations(base::Bind(
175 &ServiceWorkerContextWrapper::DidGetAllRegistrationsForGetAllOrigins
,
180 void ServiceWorkerContextWrapper::DidGetAllRegistrationsForGetAllOrigins(
181 const GetUsageInfoCallback
& callback
,
182 const std::vector
<ServiceWorkerRegistrationInfo
>& registrations
) {
183 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
184 std::vector
<ServiceWorkerUsageInfo
> usage_infos
;
186 std::map
<GURL
, ServiceWorkerUsageInfo
> origins
;
187 for (std::vector
<ServiceWorkerRegistrationInfo
>::const_iterator it
=
188 registrations
.begin();
189 it
!= registrations
.end();
191 const ServiceWorkerRegistrationInfo
& registration_info
= *it
;
192 GURL origin
= registration_info
.pattern
.GetOrigin();
194 ServiceWorkerUsageInfo
& usage_info
= origins
[origin
];
195 if (usage_info
.origin
.is_empty())
196 usage_info
.origin
= origin
;
197 usage_info
.scopes
.push_back(registration_info
.pattern
);
200 for (std::map
<GURL
, ServiceWorkerUsageInfo
>::const_iterator it
=
204 usage_infos
.push_back(it
->second
);
207 callback
.Run(usage_infos
);
211 void StatusCodeToBoolCallbackAdapter(
212 const ServiceWorkerContext::ResultCallback
& callback
,
213 ServiceWorkerStatusCode code
) {
214 callback
.Run(code
== ServiceWorkerStatusCode::SERVICE_WORKER_OK
);
217 void EmptySuccessCallback(bool success
) {
221 void ServiceWorkerContextWrapper::DeleteForOrigin(
222 const GURL
& origin_url
,
223 const ResultCallback
& result
) {
224 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
225 if (!context_core_
.get()) {
226 LOG(ERROR
) << "ServiceWorkerContextCore is no longer alive.";
227 BrowserThread::PostTask(
230 base::Bind(result
, false));
233 context()->UnregisterServiceWorkers(
234 origin_url
, base::Bind(&StatusCodeToBoolCallbackAdapter
, result
));
237 void ServiceWorkerContextWrapper::DeleteForOrigin(const GURL
& origin_url
) {
238 DeleteForOrigin(origin_url
, base::Bind(&EmptySuccessCallback
));
241 void ServiceWorkerContextWrapper::AddObserver(
242 ServiceWorkerContextObserver
* observer
) {
243 observer_list_
->AddObserver(observer
);
246 void ServiceWorkerContextWrapper::RemoveObserver(
247 ServiceWorkerContextObserver
* observer
) {
248 observer_list_
->RemoveObserver(observer
);
251 void ServiceWorkerContextWrapper::SetBlobParametersForCache(
252 net::URLRequestContextGetter
* request_context
,
253 ChromeBlobStorageContext
* blob_storage_context
) {
254 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
256 if (context_core_
&& request_context
&& blob_storage_context
) {
257 context_core_
->SetBlobParametersForCache(
258 request_context
->GetURLRequestContext(),
259 blob_storage_context
->context()->AsWeakPtr());
263 void ServiceWorkerContextWrapper::InitInternal(
264 const base::FilePath
& user_data_directory
,
265 const scoped_refptr
<base::SequencedTaskRunner
>& stores_task_runner
,
266 scoped_ptr
<ServiceWorkerDatabaseTaskManager
> database_task_manager
,
267 const scoped_refptr
<base::SingleThreadTaskRunner
>& disk_cache_thread
,
268 storage::QuotaManagerProxy
* quota_manager_proxy
,
269 storage::SpecialStoragePolicy
* special_storage_policy
) {
270 if (!BrowserThread::CurrentlyOn(BrowserThread::IO
)) {
271 BrowserThread::PostTask(
274 base::Bind(&ServiceWorkerContextWrapper::InitInternal
,
278 base::Passed(&database_task_manager
),
280 make_scoped_refptr(quota_manager_proxy
),
281 make_scoped_refptr(special_storage_policy
)));
284 DCHECK(!context_core_
);
285 if (quota_manager_proxy
) {
286 quota_manager_proxy
->RegisterClient(new ServiceWorkerQuotaClient(this));
288 context_core_
.reset(new ServiceWorkerContextCore(user_data_directory
,
290 database_task_manager
.Pass(),
293 special_storage_policy
,
294 observer_list_
.get(),
298 void ServiceWorkerContextWrapper::ShutdownOnIO() {
299 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
300 context_core_
.reset();
303 void ServiceWorkerContextWrapper::DidDeleteAndStartOver(
304 ServiceWorkerStatusCode status
) {
305 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
306 if (status
!= SERVICE_WORKER_OK
) {
307 context_core_
.reset();
310 context_core_
.reset(new ServiceWorkerContextCore(context_core_
.get(), this));
311 DVLOG(1) << "Restarted ServiceWorkerContextCore successfully.";
314 } // namespace content