cc: Make picture pile base thread safe.
[chromium-blink-merge.git] / content / browser / service_worker / service_worker_context_wrapper.cc
blobb135a85056b3bed00f969ae7059a047f2803fc7a
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"
7 #include <map>
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"
25 namespace content {
27 ServiceWorkerContextWrapper::ServiceWorkerContextWrapper(
28 BrowserContext* browser_context)
29 : observer_list_(
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,
53 cache_task_runner,
54 database_task_manager.Pass(),
55 disk_cache_thread,
56 quota_manager_proxy,
57 special_storage_policy);
60 void ServiceWorkerContextWrapper::Shutdown() {
61 DCHECK_CURRENTLY_ON(BrowserThread::UI);
62 process_manager_->Shutdown();
63 BrowserThread::PostTask(
64 BrowserThread::IO,
65 FROM_HERE,
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(
86 BrowserThread::UI,
87 FROM_HERE,
88 base::Bind(continuation, status == SERVICE_WORKER_OK));
91 void ServiceWorkerContextWrapper::RegisterServiceWorker(
92 const GURL& pattern,
93 const GURL& script_url,
94 const ResultCallback& continuation) {
95 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
96 BrowserThread::PostTask(
97 BrowserThread::IO,
98 FROM_HERE,
99 base::Bind(&ServiceWorkerContextWrapper::RegisterServiceWorker,
100 this,
101 pattern,
102 script_url,
103 continuation));
104 return;
106 if (!context_core_.get()) {
107 LOG(ERROR) << "ServiceWorkerContextCore is no longer alive.";
108 BrowserThread::PostTask(
109 BrowserThread::IO,
110 FROM_HERE,
111 base::Bind(continuation, false));
112 return;
114 context()->RegisterServiceWorker(
115 pattern,
116 script_url,
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(
126 BrowserThread::UI,
127 FROM_HERE,
128 base::Bind(continuation, status == SERVICE_WORKER_OK));
131 void ServiceWorkerContextWrapper::UnregisterServiceWorker(
132 const GURL& pattern,
133 const ResultCallback& continuation) {
134 if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) {
135 BrowserThread::PostTask(
136 BrowserThread::IO,
137 FROM_HERE,
138 base::Bind(&ServiceWorkerContextWrapper::UnregisterServiceWorker,
139 this,
140 pattern,
141 continuation));
142 return;
144 if (!context_core_.get()) {
145 LOG(ERROR) << "ServiceWorkerContextCore is no longer alive.";
146 BrowserThread::PostTask(
147 BrowserThread::IO,
148 FROM_HERE,
149 base::Bind(continuation, false));
150 return;
153 context()->UnregisterServiceWorker(
154 pattern,
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(
169 BrowserThread::IO,
170 FROM_HERE,
171 base::Bind(callback, std::vector<ServiceWorkerUsageInfo>()));
172 return;
174 context()->storage()->GetAllRegistrations(base::Bind(
175 &ServiceWorkerContextWrapper::DidGetAllRegistrationsForGetAllOrigins,
176 this,
177 callback));
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();
190 ++it) {
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 =
201 origins.begin();
202 it != origins.end();
203 ++it) {
204 usage_infos.push_back(it->second);
207 callback.Run(usage_infos);
210 namespace {
211 void StatusCodeToBoolCallbackAdapter(
212 const ServiceWorkerContext::ResultCallback& callback,
213 ServiceWorkerStatusCode code) {
214 callback.Run(code == ServiceWorkerStatusCode::SERVICE_WORKER_OK);
217 void EmptySuccessCallback(bool success) {
219 } // namespace
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(
228 BrowserThread::IO,
229 FROM_HERE,
230 base::Bind(result, false));
231 return;
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(
272 BrowserThread::IO,
273 FROM_HERE,
274 base::Bind(&ServiceWorkerContextWrapper::InitInternal,
275 this,
276 user_data_directory,
277 stores_task_runner,
278 base::Passed(&database_task_manager),
279 disk_cache_thread,
280 make_scoped_refptr(quota_manager_proxy),
281 make_scoped_refptr(special_storage_policy)));
282 return;
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,
289 stores_task_runner,
290 database_task_manager.Pass(),
291 disk_cache_thread,
292 quota_manager_proxy,
293 special_storage_policy,
294 observer_list_.get(),
295 this));
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();
308 return;
310 context_core_.reset(new ServiceWorkerContextCore(context_core_.get(), this));
311 DVLOG(1) << "Restarted ServiceWorkerContextCore successfully.";
314 } // namespace content