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