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/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 "webkit/browser/blob/blob_storage_context.h"
20 #include "webkit/browser/quota/quota_manager_proxy.h"
24 ServiceWorkerContextWrapper::ServiceWorkerContextWrapper(
25 BrowserContext
* browser_context
)
27 new ObserverListThreadSafe
<ServiceWorkerContextObserver
>()),
28 process_manager_(new ServiceWorkerProcessManager(browser_context
)),
29 is_incognito_(false) {
32 ServiceWorkerContextWrapper::~ServiceWorkerContextWrapper() {
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
,
58 void ServiceWorkerContextWrapper::Shutdown() {
59 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
60 process_manager_
->Shutdown();
61 BrowserThread::PostTask(
64 base::Bind(&ServiceWorkerContextWrapper::ShutdownOnIO
, this));
67 void ServiceWorkerContextWrapper::DeleteAndStartOver() {
68 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
69 context_core_
->DeleteAndStartOver(
70 base::Bind(&ServiceWorkerContextWrapper::DidDeleteAndStartOver
, this));
73 ServiceWorkerContextCore
* ServiceWorkerContextWrapper::context() {
74 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
75 return context_core_
.get();
78 static void FinishRegistrationOnIO(
79 const ServiceWorkerContext::ResultCallback
& continuation
,
80 ServiceWorkerStatusCode status
,
81 int64 registration_id
,
83 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
84 BrowserThread::PostTask(
87 base::Bind(continuation
, status
== SERVICE_WORKER_OK
));
90 void ServiceWorkerContextWrapper::RegisterServiceWorker(
92 const GURL
& script_url
,
93 const ResultCallback
& continuation
) {
94 if (!BrowserThread::CurrentlyOn(BrowserThread::IO
)) {
95 BrowserThread::PostTask(
98 base::Bind(&ServiceWorkerContextWrapper::RegisterServiceWorker
,
106 context()->RegisterServiceWorker(
110 NULL
/* provider_host */,
111 base::Bind(&FinishRegistrationOnIO
, continuation
));
114 static void FinishUnregistrationOnIO(
115 const ServiceWorkerContext::ResultCallback
& continuation
,
116 ServiceWorkerStatusCode status
) {
117 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
118 BrowserThread::PostTask(
121 base::Bind(continuation
, status
== SERVICE_WORKER_OK
));
124 void ServiceWorkerContextWrapper::UnregisterServiceWorker(
126 const ResultCallback
& continuation
) {
127 if (!BrowserThread::CurrentlyOn(BrowserThread::IO
)) {
128 BrowserThread::PostTask(
131 base::Bind(&ServiceWorkerContextWrapper::UnregisterServiceWorker
,
138 context()->UnregisterServiceWorker(
140 base::Bind(&FinishUnregistrationOnIO
, continuation
));
143 void ServiceWorkerContextWrapper::Terminate() {
144 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
145 process_manager_
->Shutdown();
148 void ServiceWorkerContextWrapper::GetAllOriginsInfo(
149 const GetUsageInfoCallback
& callback
) {
150 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
151 context_core_
->storage()->GetAllRegistrations(base::Bind(
152 &ServiceWorkerContextWrapper::DidGetAllRegistrationsForGetAllOrigins
,
157 void ServiceWorkerContextWrapper::DidGetAllRegistrationsForGetAllOrigins(
158 const GetUsageInfoCallback
& callback
,
159 const std::vector
<ServiceWorkerRegistrationInfo
>& registrations
) {
160 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
161 std::vector
<ServiceWorkerUsageInfo
> usage_infos
;
163 std::map
<GURL
, ServiceWorkerUsageInfo
> origins
;
164 for (std::vector
<ServiceWorkerRegistrationInfo
>::const_iterator it
=
165 registrations
.begin();
166 it
!= registrations
.end();
168 const ServiceWorkerRegistrationInfo
& registration_info
= *it
;
169 GURL origin
= registration_info
.pattern
.GetOrigin();
171 ServiceWorkerUsageInfo
& usage_info
= origins
[origin
];
172 if (usage_info
.origin
.is_empty())
173 usage_info
.origin
= origin
;
174 usage_info
.scopes
.push_back(registration_info
.pattern
);
177 for (std::map
<GURL
, ServiceWorkerUsageInfo
>::const_iterator it
=
181 usage_infos
.push_back(it
->second
);
184 callback
.Run(usage_infos
);
189 void EmptySuccessCallback(bool success
) {
194 void ServiceWorkerContextWrapper::DeleteForOrigin(const GURL
& origin_url
) {
195 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
196 context_core_
->storage()->GetAllRegistrations(base::Bind(
197 &ServiceWorkerContextWrapper::DidGetAllRegistrationsForDeleteForOrigin
,
202 void ServiceWorkerContextWrapper::DidGetAllRegistrationsForDeleteForOrigin(
204 const std::vector
<ServiceWorkerRegistrationInfo
>& registrations
) {
205 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
207 for (std::vector
<ServiceWorkerRegistrationInfo
>::const_iterator it
=
208 registrations
.begin();
209 it
!= registrations
.end();
211 const ServiceWorkerRegistrationInfo
& registration_info
= *it
;
212 if (origin
== registration_info
.pattern
.GetOrigin()) {
213 UnregisterServiceWorker(registration_info
.pattern
,
214 base::Bind(&EmptySuccessCallback
));
219 void ServiceWorkerContextWrapper::AddObserver(
220 ServiceWorkerContextObserver
* observer
) {
221 observer_list_
->AddObserver(observer
);
224 void ServiceWorkerContextWrapper::RemoveObserver(
225 ServiceWorkerContextObserver
* observer
) {
226 observer_list_
->RemoveObserver(observer
);
229 void ServiceWorkerContextWrapper::SetBlobParametersForCache(
230 net::URLRequestContextGetter
* request_context
,
231 ChromeBlobStorageContext
* blob_storage_context
) {
232 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
234 if (context_core_
&& request_context
&& blob_storage_context
) {
235 context_core_
->SetBlobParametersForCache(
236 request_context
->GetURLRequestContext(),
237 blob_storage_context
->context()->AsWeakPtr());
241 void ServiceWorkerContextWrapper::InitInternal(
242 const base::FilePath
& user_data_directory
,
243 const scoped_refptr
<base::SequencedTaskRunner
>& stores_task_runner
,
244 const scoped_refptr
<base::SequencedTaskRunner
>& database_task_runner
,
245 const scoped_refptr
<base::SingleThreadTaskRunner
>& disk_cache_thread
,
246 storage::QuotaManagerProxy
* quota_manager_proxy
) {
247 if (!BrowserThread::CurrentlyOn(BrowserThread::IO
)) {
248 BrowserThread::PostTask(
251 base::Bind(&ServiceWorkerContextWrapper::InitInternal
,
255 database_task_runner
,
257 make_scoped_refptr(quota_manager_proxy
)));
260 DCHECK(!context_core_
);
261 context_core_
.reset(new ServiceWorkerContextCore(user_data_directory
,
263 database_task_runner
,
266 observer_list_
.get(),
270 void ServiceWorkerContextWrapper::ShutdownOnIO() {
271 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
272 context_core_
.reset();
275 void ServiceWorkerContextWrapper::DidDeleteAndStartOver(
276 ServiceWorkerStatusCode status
) {
277 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
278 if (status
!= SERVICE_WORKER_OK
) {
279 context_core_
.reset();
282 context_core_
.reset(new ServiceWorkerContextCore(context_core_
.get(), this));
283 DVLOG(1) << "Restarted ServiceWorkerContextCore successfully.";
286 } // namespace content