OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/service_worker/service_worker_storage.h" | 5 #include "content/browser/service_worker/service_worker_storage.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/bind_helpers.h" | 9 #include "base/bind_helpers.h" |
10 #include "base/message_loop/message_loop.h" | 10 #include "base/message_loop/message_loop.h" |
11 #include "base/sequenced_task_runner.h" | 11 #include "base/sequenced_task_runner.h" |
12 #include "base/task_runner_util.h" | 12 #include "base/task_runner_util.h" |
13 #include "content/browser/service_worker/service_worker_context_core.h" | 13 #include "content/browser/service_worker/service_worker_context_core.h" |
14 #include "content/browser/service_worker/service_worker_disk_cache.h" | 14 #include "content/browser/service_worker/service_worker_disk_cache.h" |
15 #include "content/browser/service_worker/service_worker_info.h" | 15 #include "content/browser/service_worker/service_worker_info.h" |
16 #include "content/browser/service_worker/service_worker_registration.h" | 16 #include "content/browser/service_worker/service_worker_registration.h" |
17 #include "content/browser/service_worker/service_worker_utils.h" | 17 #include "content/browser/service_worker/service_worker_utils.h" |
18 #include "content/browser/service_worker/service_worker_version.h" | 18 #include "content/browser/service_worker/service_worker_version.h" |
19 #include "content/common/service_worker/service_worker_types.h" | 19 #include "content/common/service_worker/service_worker_types.h" |
20 #include "content/public/browser/browser_thread.h" | 20 #include "content/public/browser/browser_thread.h" |
21 #include "net/base/net_errors.h" | 21 #include "net/base/net_errors.h" |
22 #include "webkit/browser/quota/quota_manager_proxy.h" | 22 #include "webkit/browser/quota/quota_manager_proxy.h" |
23 | 23 |
24 namespace content { | 24 namespace content { |
25 | 25 |
26 namespace { | 26 namespace { |
27 | 27 |
28 typedef base::Callback<void( | |
29 ServiceWorkerStorage::InitialData* data, | |
30 ServiceWorkerDatabase::Status status)> InitializeCallback; | |
31 typedef base::Callback<void( | |
32 const ServiceWorkerDatabase::RegistrationData& data, | |
33 const std::vector<ServiceWorkerDatabase::ResourceRecord>& resources, | |
34 ServiceWorkerDatabase::Status status)> ReadRegistrationCallback; | |
35 typedef base::Callback<void( | |
36 bool origin_is_deletable, | |
37 ServiceWorkerDatabase::Status status)> DeleteRegistrationCallback; | |
38 | |
39 void RunSoon(const tracked_objects::Location& from_here, | 28 void RunSoon(const tracked_objects::Location& from_here, |
40 const base::Closure& closure) { | 29 const base::Closure& closure) { |
41 base::MessageLoop::current()->PostTask(from_here, closure); | 30 base::MessageLoop::current()->PostTask(from_here, closure); |
42 } | 31 } |
43 | 32 |
44 void CompleteFindNow( | 33 void CompleteFindNow( |
45 const scoped_refptr<ServiceWorkerRegistration>& registration, | 34 const scoped_refptr<ServiceWorkerRegistration>& registration, |
46 ServiceWorkerStatusCode status, | 35 ServiceWorkerStatusCode status, |
47 const ServiceWorkerStorage::FindRegistrationCallback& callback) { | 36 const ServiceWorkerStorage::FindRegistrationCallback& callback) { |
48 callback.Run(status, registration); | 37 callback.Run(status, registration); |
49 } | 38 } |
50 | 39 |
51 void CompleteFindSoon( | 40 void CompleteFindSoon( |
52 const tracked_objects::Location& from_here, | 41 const tracked_objects::Location& from_here, |
53 const scoped_refptr<ServiceWorkerRegistration>& registration, | 42 const scoped_refptr<ServiceWorkerRegistration>& registration, |
54 ServiceWorkerStatusCode status, | 43 ServiceWorkerStatusCode status, |
55 const ServiceWorkerStorage::FindRegistrationCallback& callback) { | 44 const ServiceWorkerStorage::FindRegistrationCallback& callback) { |
56 RunSoon(from_here, base::Bind(callback, status, registration)); | 45 RunSoon(from_here, base::Bind(callback, status, registration)); |
57 } | 46 } |
58 | 47 |
59 const base::FilePath::CharType kServiceWorkerDirectory[] = | 48 const base::FilePath::CharType kServiceWorkerDirectory[] = |
60 FILE_PATH_LITERAL("Service Worker"); | 49 FILE_PATH_LITERAL("Service Worker"); |
61 const base::FilePath::CharType kDatabaseName[] = | 50 const base::FilePath::CharType kDatabaseName[] = |
62 FILE_PATH_LITERAL("Database"); | 51 FILE_PATH_LITERAL("Database"); |
| 52 const base::FilePath::CharType kDiskCacheName[] = |
| 53 FILE_PATH_LITERAL("Cache"); |
63 | 54 |
64 const int kMaxMemDiskCacheSize = 10 * 1024 * 1024; | 55 const int kMaxMemDiskCacheSize = 10 * 1024 * 1024; |
| 56 const int kMaxDiskCacheSize = 250 * 1024 * 1024; |
65 | 57 |
66 void EmptyCompletionCallback(int) {} | 58 void EmptyCompletionCallback(int) {} |
67 | 59 |
68 ServiceWorkerStatusCode DatabaseStatusToStatusCode( | 60 ServiceWorkerStatusCode DatabaseStatusToStatusCode( |
69 ServiceWorkerDatabase::Status status) { | 61 ServiceWorkerDatabase::Status status) { |
70 switch (status) { | 62 switch (status) { |
71 case ServiceWorkerDatabase::STATUS_OK: | 63 case ServiceWorkerDatabase::STATUS_OK: |
72 return SERVICE_WORKER_OK; | 64 return SERVICE_WORKER_OK; |
73 case ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND: | 65 case ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND: |
74 return SERVICE_WORKER_ERROR_NOT_FOUND; | 66 return SERVICE_WORKER_ERROR_NOT_FOUND; |
75 default: | 67 default: |
76 return SERVICE_WORKER_ERROR_FAILED; | 68 return SERVICE_WORKER_ERROR_FAILED; |
77 } | 69 } |
78 } | 70 } |
79 | 71 |
80 void ReadInitialDataFromDB( | |
81 ServiceWorkerDatabase* database, | |
82 scoped_refptr<base::SequencedTaskRunner> original_task_runner, | |
83 const InitializeCallback& callback) { | |
84 DCHECK(database); | |
85 scoped_ptr<ServiceWorkerStorage::InitialData> data( | |
86 new ServiceWorkerStorage::InitialData()); | |
87 | |
88 ServiceWorkerDatabase::Status status = | |
89 database->GetNextAvailableIds(&data->next_registration_id, | |
90 &data->next_version_id, | |
91 &data->next_resource_id); | |
92 if (status != ServiceWorkerDatabase::STATUS_OK) { | |
93 original_task_runner->PostTask( | |
94 FROM_HERE, base::Bind(callback, base::Owned(data.release()), status)); | |
95 return; | |
96 } | |
97 | |
98 status = database->GetOriginsWithRegistrations(&data->origins); | |
99 original_task_runner->PostTask( | |
100 FROM_HERE, base::Bind(callback, base::Owned(data.release()), status)); | |
101 } | |
102 | |
103 void DeleteRegistrationFromDB( | |
104 ServiceWorkerDatabase* database, | |
105 scoped_refptr<base::SequencedTaskRunner> original_task_runner, | |
106 int64 registration_id, | |
107 const GURL& origin, | |
108 const DeleteRegistrationCallback& callback) { | |
109 DCHECK(database); | |
110 ServiceWorkerDatabase::Status status = | |
111 database->DeleteRegistration(registration_id, origin); | |
112 if (status != ServiceWorkerDatabase::STATUS_OK) { | |
113 original_task_runner->PostTask( | |
114 FROM_HERE, base::Bind(callback, false, status)); | |
115 return; | |
116 } | |
117 | |
118 // TODO(nhiroki): Add convenient method to ServiceWorkerDatabase to check the | |
119 // unique origin list. | |
120 std::vector<ServiceWorkerDatabase::RegistrationData> registrations; | |
121 status = database->GetRegistrationsForOrigin(origin, ®istrations); | |
122 if (status != ServiceWorkerDatabase::STATUS_OK) { | |
123 original_task_runner->PostTask( | |
124 FROM_HERE, base::Bind(callback, false, status)); | |
125 return; | |
126 } | |
127 | |
128 bool deletable = registrations.empty(); | |
129 original_task_runner->PostTask( | |
130 FROM_HERE, base::Bind(callback, deletable, status)); | |
131 } | |
132 | |
133 } // namespace | 72 } // namespace |
134 | 73 |
135 ServiceWorkerStorage::InitialData::InitialData() | 74 ServiceWorkerStorage::InitialData::InitialData() |
136 : next_registration_id(kInvalidServiceWorkerRegistrationId), | 75 : next_registration_id(kInvalidServiceWorkerRegistrationId), |
137 next_version_id(kInvalidServiceWorkerVersionId), | 76 next_version_id(kInvalidServiceWorkerVersionId), |
138 next_resource_id(kInvalidServiceWorkerResourceId) { | 77 next_resource_id(kInvalidServiceWorkerResourceId) { |
139 } | 78 } |
140 | 79 |
141 ServiceWorkerStorage::InitialData::~InitialData() { | 80 ServiceWorkerStorage::InitialData::~InitialData() { |
142 } | 81 } |
143 | 82 |
144 ServiceWorkerStorage::ServiceWorkerStorage( | 83 ServiceWorkerStorage::ServiceWorkerStorage( |
145 const base::FilePath& path, | 84 const base::FilePath& path, |
146 base::WeakPtr<ServiceWorkerContextCore> context, | 85 base::WeakPtr<ServiceWorkerContextCore> context, |
147 base::SequencedTaskRunner* database_task_runner, | 86 base::SequencedTaskRunner* database_task_runner, |
148 base::MessageLoopProxy* disk_cache_thread, | 87 base::MessageLoopProxy* disk_cache_thread, |
149 quota::QuotaManagerProxy* quota_manager_proxy) | 88 quota::QuotaManagerProxy* quota_manager_proxy) |
150 : next_registration_id_(kInvalidServiceWorkerRegistrationId), | 89 : next_registration_id_(kInvalidServiceWorkerRegistrationId), |
151 next_version_id_(kInvalidServiceWorkerVersionId), | 90 next_version_id_(kInvalidServiceWorkerVersionId), |
152 next_resource_id_(kInvalidServiceWorkerResourceId), | 91 next_resource_id_(kInvalidServiceWorkerResourceId), |
153 state_(UNINITIALIZED), | 92 state_(UNINITIALIZED), |
154 context_(context), | 93 context_(context), |
155 database_task_runner_(database_task_runner), | 94 database_task_runner_(database_task_runner), |
156 disk_cache_thread_(disk_cache_thread), | 95 disk_cache_thread_(disk_cache_thread), |
157 quota_manager_proxy_(quota_manager_proxy), | 96 quota_manager_proxy_(quota_manager_proxy), |
| 97 is_purge_pending_(false), |
158 weak_factory_(this) { | 98 weak_factory_(this) { |
159 if (!path.empty()) { | 99 if (!path.empty()) |
160 path_ = path.Append(kServiceWorkerDirectory); | 100 path_ = path.Append(kServiceWorkerDirectory); |
161 database_.reset(new ServiceWorkerDatabase(path_.Append(kDatabaseName))); | 101 database_.reset(new ServiceWorkerDatabase(GetDatabasePath())); |
162 } else { | |
163 // Create an in-memory database. | |
164 database_.reset(new ServiceWorkerDatabase(base::FilePath())); | |
165 } | |
166 } | 102 } |
167 | 103 |
168 ServiceWorkerStorage::~ServiceWorkerStorage() { | 104 ServiceWorkerStorage::~ServiceWorkerStorage() { |
169 weak_factory_.InvalidateWeakPtrs(); | 105 weak_factory_.InvalidateWeakPtrs(); |
170 database_task_runner_->DeleteSoon(FROM_HERE, database_.release()); | 106 database_task_runner_->DeleteSoon(FROM_HERE, database_.release()); |
171 } | 107 } |
172 | 108 |
| 109 void ServiceWorkerStorage::FindRegistrationForDocument( |
| 110 const GURL& document_url, |
| 111 const FindRegistrationCallback& callback) { |
| 112 if (!LazyInitialize(base::Bind( |
| 113 &ServiceWorkerStorage::FindRegistrationForDocument, |
| 114 weak_factory_.GetWeakPtr(), document_url, callback))) { |
| 115 if (state_ != INITIALIZING || !context_) { |
| 116 CompleteFindNow(scoped_refptr<ServiceWorkerRegistration>(), |
| 117 SERVICE_WORKER_ERROR_FAILED, callback); |
| 118 } |
| 119 return; |
| 120 } |
| 121 DCHECK_EQ(INITIALIZED, state_); |
| 122 |
| 123 // See if there are any stored registrations for the origin. |
| 124 if (!ContainsKey(registered_origins_, document_url.GetOrigin())) { |
| 125 // Look for something currently being installed. |
| 126 scoped_refptr<ServiceWorkerRegistration> installing_registration = |
| 127 FindInstallingRegistrationForDocument(document_url); |
| 128 CompleteFindNow( |
| 129 installing_registration, |
| 130 installing_registration ? |
| 131 SERVICE_WORKER_OK : SERVICE_WORKER_ERROR_NOT_FOUND, |
| 132 callback); |
| 133 return; |
| 134 } |
| 135 |
| 136 database_task_runner_->PostTask( |
| 137 FROM_HERE, |
| 138 base::Bind( |
| 139 &FindForDocumentInDB, |
| 140 database_.get(), |
| 141 base::MessageLoopProxy::current(), |
| 142 document_url, |
| 143 base::Bind(&ServiceWorkerStorage::DidFindRegistrationForDocument, |
| 144 weak_factory_.GetWeakPtr(), document_url, callback))); |
| 145 } |
| 146 |
173 void ServiceWorkerStorage::FindRegistrationForPattern( | 147 void ServiceWorkerStorage::FindRegistrationForPattern( |
174 const GURL& scope, | 148 const GURL& scope, |
175 const FindRegistrationCallback& callback) { | 149 const FindRegistrationCallback& callback) { |
176 scoped_refptr<ServiceWorkerRegistration> null_registration; | |
177 if (!LazyInitialize(base::Bind( | 150 if (!LazyInitialize(base::Bind( |
178 &ServiceWorkerStorage::FindRegistrationForPattern, | 151 &ServiceWorkerStorage::FindRegistrationForPattern, |
179 weak_factory_.GetWeakPtr(), scope, callback))) { | 152 weak_factory_.GetWeakPtr(), scope, callback))) { |
180 if (state_ != INITIALIZING || !context_) { | 153 if (state_ != INITIALIZING || !context_) { |
181 CompleteFindSoon(FROM_HERE, null_registration, | 154 CompleteFindSoon(FROM_HERE, scoped_refptr<ServiceWorkerRegistration>(), |
182 SERVICE_WORKER_ERROR_FAILED, callback); | 155 SERVICE_WORKER_ERROR_FAILED, callback); |
183 } | 156 } |
184 return; | 157 return; |
185 } | 158 } |
186 DCHECK_EQ(INITIALIZED, state_); | 159 DCHECK_EQ(INITIALIZED, state_); |
187 | 160 |
188 // See if there are any stored registrations for the origin. | 161 // See if there are any stored registrations for the origin. |
189 if (!ContainsKey(registered_origins_, scope.GetOrigin())) { | 162 if (!ContainsKey(registered_origins_, scope.GetOrigin())) { |
190 // Look for something currently being installed. | 163 // Look for something currently being installed. |
191 scoped_refptr<ServiceWorkerRegistration> installing_registration = | 164 scoped_refptr<ServiceWorkerRegistration> installing_registration = |
192 FindInstallingRegistrationForPattern(scope); | 165 FindInstallingRegistrationForPattern(scope); |
193 if (installing_registration) { | |
194 CompleteFindSoon( | |
195 FROM_HERE, installing_registration, SERVICE_WORKER_OK, callback); | |
196 return; | |
197 } | |
198 CompleteFindSoon( | 166 CompleteFindSoon( |
199 FROM_HERE, null_registration, SERVICE_WORKER_ERROR_NOT_FOUND, callback); | 167 FROM_HERE, installing_registration, |
| 168 installing_registration ? |
| 169 SERVICE_WORKER_OK : SERVICE_WORKER_ERROR_NOT_FOUND, |
| 170 callback); |
200 return; | 171 return; |
201 } | 172 } |
202 | 173 |
203 RegistrationList* registrations = new RegistrationList(); | 174 database_task_runner_->PostTask( |
204 PostTaskAndReplyWithResult( | |
205 database_task_runner_, | |
206 FROM_HERE, | 175 FROM_HERE, |
207 base::Bind(&ServiceWorkerDatabase::GetRegistrationsForOrigin, | 176 base::Bind( |
208 base::Unretained(database_.get()), | 177 &FindForPatternInDB, |
209 scope.GetOrigin(), base::Unretained(registrations)), | 178 database_.get(), |
210 base::Bind(&ServiceWorkerStorage::DidGetRegistrationsForPattern, | 179 base::MessageLoopProxy::current(), |
211 weak_factory_.GetWeakPtr(), scope, callback, | 180 scope, |
212 base::Owned(registrations))); | 181 base::Bind(&ServiceWorkerStorage::DidFindRegistrationForPattern, |
213 } | 182 weak_factory_.GetWeakPtr(), scope, callback))); |
214 | |
215 void ServiceWorkerStorage::FindRegistrationForDocument( | |
216 const GURL& document_url, | |
217 const FindRegistrationCallback& callback) { | |
218 scoped_refptr<ServiceWorkerRegistration> null_registration; | |
219 if (!LazyInitialize(base::Bind( | |
220 &ServiceWorkerStorage::FindRegistrationForDocument, | |
221 weak_factory_.GetWeakPtr(), document_url, callback))) { | |
222 if (state_ != INITIALIZING || !context_) | |
223 CompleteFindNow(null_registration, SERVICE_WORKER_ERROR_FAILED, callback); | |
224 return; | |
225 } | |
226 DCHECK_EQ(INITIALIZED, state_); | |
227 | |
228 // See if there are any stored registrations for the origin. | |
229 if (!ContainsKey(registered_origins_, document_url.GetOrigin())) { | |
230 // Look for something currently being installed. | |
231 scoped_refptr<ServiceWorkerRegistration> installing_registration = | |
232 FindInstallingRegistrationForDocument(document_url); | |
233 if (installing_registration) { | |
234 CompleteFindNow(installing_registration, SERVICE_WORKER_OK, callback); | |
235 return; | |
236 } | |
237 CompleteFindNow( | |
238 null_registration, SERVICE_WORKER_ERROR_NOT_FOUND, callback); | |
239 return; | |
240 } | |
241 | |
242 RegistrationList* registrations = new RegistrationList(); | |
243 PostTaskAndReplyWithResult( | |
244 database_task_runner_, | |
245 FROM_HERE, | |
246 base::Bind(&ServiceWorkerDatabase::GetRegistrationsForOrigin, | |
247 base::Unretained(database_.get()), | |
248 document_url.GetOrigin(), base::Unretained(registrations)), | |
249 base::Bind(&ServiceWorkerStorage::DidGetRegistrationsForDocument, | |
250 weak_factory_.GetWeakPtr(), document_url, callback, | |
251 base::Owned(registrations))); | |
252 } | 183 } |
253 | 184 |
254 void ServiceWorkerStorage::FindRegistrationForId( | 185 void ServiceWorkerStorage::FindRegistrationForId( |
255 int64 registration_id, | 186 int64 registration_id, |
256 const GURL& origin, | 187 const GURL& origin, |
257 const FindRegistrationCallback& callback) { | 188 const FindRegistrationCallback& callback) { |
258 scoped_refptr<ServiceWorkerRegistration> null_registration; | |
259 if (!LazyInitialize(base::Bind( | 189 if (!LazyInitialize(base::Bind( |
260 &ServiceWorkerStorage::FindRegistrationForId, | 190 &ServiceWorkerStorage::FindRegistrationForId, |
261 weak_factory_.GetWeakPtr(), registration_id, origin, callback))) { | 191 weak_factory_.GetWeakPtr(), registration_id, origin, callback))) { |
262 if (state_ != INITIALIZING || !context_) | 192 if (state_ != INITIALIZING || !context_) { |
263 CompleteFindNow(null_registration, SERVICE_WORKER_ERROR_FAILED, callback); | 193 CompleteFindNow(scoped_refptr<ServiceWorkerRegistration>(), |
| 194 SERVICE_WORKER_ERROR_FAILED, callback); |
| 195 } |
264 return; | 196 return; |
265 } | 197 } |
266 DCHECK_EQ(INITIALIZED, state_); | 198 DCHECK_EQ(INITIALIZED, state_); |
267 | 199 |
268 // See if there are any stored registrations for the origin. | 200 // See if there are any stored registrations for the origin. |
269 if (!ContainsKey(registered_origins_, origin)) { | 201 if (!ContainsKey(registered_origins_, origin)) { |
270 // Look for somthing currently being installed. | 202 // Look for something currently being installed. |
271 scoped_refptr<ServiceWorkerRegistration> installing_registration = | 203 scoped_refptr<ServiceWorkerRegistration> installing_registration = |
272 FindInstallingRegistrationForId(registration_id); | 204 FindInstallingRegistrationForId(registration_id); |
273 if (installing_registration) { | |
274 CompleteFindNow(installing_registration, SERVICE_WORKER_OK, callback); | |
275 return; | |
276 } | |
277 CompleteFindNow( | 205 CompleteFindNow( |
278 null_registration, SERVICE_WORKER_ERROR_NOT_FOUND, callback); | 206 installing_registration, |
| 207 installing_registration ? |
| 208 SERVICE_WORKER_OK : SERVICE_WORKER_ERROR_NOT_FOUND, |
| 209 callback); |
279 return; | 210 return; |
280 } | 211 } |
281 | 212 |
282 scoped_refptr<ServiceWorkerRegistration> registration = | 213 scoped_refptr<ServiceWorkerRegistration> registration = |
283 context_->GetLiveRegistration(registration_id); | 214 context_->GetLiveRegistration(registration_id); |
284 if (registration) { | 215 if (registration) { |
285 CompleteFindNow(registration, SERVICE_WORKER_OK, callback); | 216 CompleteFindNow(registration, SERVICE_WORKER_OK, callback); |
286 return; | 217 return; |
287 } | 218 } |
288 | 219 |
289 ServiceWorkerDatabase::RegistrationData* data = | 220 database_task_runner_->PostTask( |
290 new ServiceWorkerDatabase::RegistrationData; | |
291 ResourceList* resources = new ResourceList; | |
292 PostTaskAndReplyWithResult( | |
293 database_task_runner_, | |
294 FROM_HERE, | 221 FROM_HERE, |
295 base::Bind(&ServiceWorkerDatabase::ReadRegistration, | 222 base::Bind(&FindForIdInDB, |
296 base::Unretained(database_.get()), | 223 database_.get(), |
| 224 base::MessageLoopProxy::current(), |
297 registration_id, origin, | 225 registration_id, origin, |
298 base::Unretained(data), | 226 base::Bind(&ServiceWorkerStorage::DidFindRegistrationForId, |
299 base::Unretained(resources)), | 227 weak_factory_.GetWeakPtr(), callback))); |
300 base::Bind(&ServiceWorkerStorage::DidReadRegistrationForId, | |
301 weak_factory_.GetWeakPtr(), | |
302 callback, base::Owned(data), base::Owned(resources))); | |
303 } | 228 } |
304 | 229 |
305 void ServiceWorkerStorage::GetAllRegistrations( | 230 void ServiceWorkerStorage::GetAllRegistrations( |
306 const GetAllRegistrationInfosCallback& callback) { | 231 const GetAllRegistrationInfosCallback& callback) { |
307 if (!LazyInitialize(base::Bind( | 232 if (!LazyInitialize(base::Bind( |
308 &ServiceWorkerStorage::GetAllRegistrations, | 233 &ServiceWorkerStorage::GetAllRegistrations, |
309 weak_factory_.GetWeakPtr(), callback))) { | 234 weak_factory_.GetWeakPtr(), callback))) { |
310 if (state_ != INITIALIZING || !context_) { | 235 if (state_ != INITIALIZING || !context_) { |
311 RunSoon(FROM_HERE, base::Bind( | 236 RunSoon(FROM_HERE, base::Bind( |
312 callback, std::vector<ServiceWorkerRegistrationInfo>())); | 237 callback, std::vector<ServiceWorkerRegistrationInfo>())); |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
344 ServiceWorkerDatabase::RegistrationData data; | 269 ServiceWorkerDatabase::RegistrationData data; |
345 data.registration_id = registration->id(); | 270 data.registration_id = registration->id(); |
346 data.scope = registration->pattern(); | 271 data.scope = registration->pattern(); |
347 data.script = registration->script_url(); | 272 data.script = registration->script_url(); |
348 data.has_fetch_handler = true; | 273 data.has_fetch_handler = true; |
349 data.version_id = version->version_id(); | 274 data.version_id = version->version_id(); |
350 data.last_update_check = base::Time::Now(); | 275 data.last_update_check = base::Time::Now(); |
351 data.is_active = false; // initially stored in the waiting state | 276 data.is_active = false; // initially stored in the waiting state |
352 | 277 |
353 ResourceList resources; | 278 ResourceList resources; |
354 PostTaskAndReplyWithResult( | 279 version->script_cache_map()->GetResources(&resources); |
355 database_task_runner_, | 280 |
| 281 database_task_runner_->PostTask( |
356 FROM_HERE, | 282 FROM_HERE, |
357 base::Bind(&ServiceWorkerDatabase::WriteRegistration, | 283 base::Bind(&WriteRegistrationInDB, |
358 base::Unretained(database_.get()), data, resources), | 284 database_.get(), |
359 base::Bind(&ServiceWorkerStorage::DidStoreRegistration, | 285 base::MessageLoopProxy::current(), |
360 weak_factory_.GetWeakPtr(), | 286 data, resources, |
361 registration->script_url().GetOrigin(), | 287 base::Bind(&ServiceWorkerStorage::DidStoreRegistration, |
362 callback)); | 288 weak_factory_.GetWeakPtr(), |
| 289 callback))); |
363 } | 290 } |
364 | 291 |
365 void ServiceWorkerStorage::UpdateToActiveState( | 292 void ServiceWorkerStorage::UpdateToActiveState( |
366 ServiceWorkerRegistration* registration, | 293 ServiceWorkerRegistration* registration, |
367 const StatusCallback& callback) { | 294 const StatusCallback& callback) { |
368 DCHECK(registration); | 295 DCHECK(registration); |
369 | 296 |
370 DCHECK(state_ == INITIALIZED || state_ == DISABLED); | 297 DCHECK(state_ == INITIALIZED || state_ == DISABLED); |
371 if (state_ != INITIALIZED || !context_) { | 298 if (state_ != INITIALIZED || !context_) { |
372 RunSoon(FROM_HERE, base::Bind(callback, SERVICE_WORKER_ERROR_FAILED)); | 299 RunSoon(FROM_HERE, base::Bind(callback, SERVICE_WORKER_ERROR_FAILED)); |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
446 void ServiceWorkerStorage::NotifyInstallingRegistration( | 373 void ServiceWorkerStorage::NotifyInstallingRegistration( |
447 ServiceWorkerRegistration* registration) { | 374 ServiceWorkerRegistration* registration) { |
448 installing_registrations_[registration->id()] = registration; | 375 installing_registrations_[registration->id()] = registration; |
449 } | 376 } |
450 | 377 |
451 void ServiceWorkerStorage::NotifyDoneInstallingRegistration( | 378 void ServiceWorkerStorage::NotifyDoneInstallingRegistration( |
452 ServiceWorkerRegistration* registration) { | 379 ServiceWorkerRegistration* registration) { |
453 installing_registrations_.erase(registration->id()); | 380 installing_registrations_.erase(registration->id()); |
454 } | 381 } |
455 | 382 |
| 383 base::FilePath ServiceWorkerStorage::GetDatabasePath() { |
| 384 if (path_.empty()) |
| 385 return base::FilePath(); |
| 386 return path_.Append(kDatabaseName); |
| 387 } |
| 388 |
| 389 base::FilePath ServiceWorkerStorage::GetDiskCachePath() { |
| 390 if (path_.empty()) |
| 391 return base::FilePath(); |
| 392 return path_.Append(kDiskCacheName); |
| 393 } |
| 394 |
456 bool ServiceWorkerStorage::LazyInitialize(const base::Closure& callback) { | 395 bool ServiceWorkerStorage::LazyInitialize(const base::Closure& callback) { |
457 if (!context_) | 396 if (!context_) |
458 return false; | 397 return false; |
459 | 398 |
460 switch (state_) { | 399 switch (state_) { |
461 case INITIALIZED: | 400 case INITIALIZED: |
462 return true; | 401 return true; |
463 case DISABLED: | 402 case DISABLED: |
464 return false; | 403 return false; |
465 case INITIALIZING: | 404 case INITIALIZING: |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
500 state_ = DISABLED; | 439 state_ = DISABLED; |
501 } | 440 } |
502 | 441 |
503 for (std::vector<base::Closure>::const_iterator it = pending_tasks_.begin(); | 442 for (std::vector<base::Closure>::const_iterator it = pending_tasks_.begin(); |
504 it != pending_tasks_.end(); ++it) { | 443 it != pending_tasks_.end(); ++it) { |
505 RunSoon(FROM_HERE, *it); | 444 RunSoon(FROM_HERE, *it); |
506 } | 445 } |
507 pending_tasks_.clear(); | 446 pending_tasks_.clear(); |
508 } | 447 } |
509 | 448 |
510 void ServiceWorkerStorage::DidGetRegistrationsForPattern( | 449 void ServiceWorkerStorage::DidFindRegistrationForDocument( |
511 const GURL& scope, | |
512 const FindRegistrationCallback& callback, | |
513 RegistrationList* registrations, | |
514 ServiceWorkerDatabase::Status status) { | |
515 DCHECK(registrations); | |
516 if (status != ServiceWorkerDatabase::STATUS_OK) { | |
517 // TODO(nhiroki): Handle database error (http://crbug.com/371675). | |
518 callback.Run(SERVICE_WORKER_ERROR_FAILED, | |
519 scoped_refptr<ServiceWorkerRegistration>()); | |
520 return; | |
521 } | |
522 | |
523 // Find one with a matching scope. | |
524 for (RegistrationList::const_iterator it = registrations->begin(); | |
525 it != registrations->end(); ++it) { | |
526 if (scope == it->scope) { | |
527 scoped_refptr<ServiceWorkerRegistration> registration = | |
528 context_->GetLiveRegistration(it->registration_id); | |
529 if (!registration) | |
530 registration = CreateRegistration(*it); | |
531 callback.Run(SERVICE_WORKER_OK, registration); | |
532 return; | |
533 } | |
534 } | |
535 | |
536 // Look for something currently being installed. | |
537 scoped_refptr<ServiceWorkerRegistration> installing_registration = | |
538 FindInstallingRegistrationForPattern(scope); | |
539 if (installing_registration) { | |
540 callback.Run(SERVICE_WORKER_OK, installing_registration); | |
541 return; | |
542 } | |
543 | |
544 callback.Run(SERVICE_WORKER_ERROR_NOT_FOUND, | |
545 scoped_refptr<ServiceWorkerRegistration>()); | |
546 } | |
547 | |
548 void ServiceWorkerStorage::DidGetRegistrationsForDocument( | |
549 const GURL& document_url, | 450 const GURL& document_url, |
550 const FindRegistrationCallback& callback, | 451 const FindRegistrationCallback& callback, |
551 RegistrationList* registrations, | 452 const ServiceWorkerDatabase::RegistrationData& data, |
| 453 const ResourceList& resources, |
552 ServiceWorkerDatabase::Status status) { | 454 ServiceWorkerDatabase::Status status) { |
553 DCHECK(registrations); | |
554 if (status != ServiceWorkerDatabase::STATUS_OK) { | |
555 // TODO(nhiroki): Handle database error (http://crbug.com/371675). | |
556 callback.Run(SERVICE_WORKER_ERROR_FAILED, | |
557 scoped_refptr<ServiceWorkerRegistration>()); | |
558 return; | |
559 } | |
560 | |
561 // Find one with a pattern match. | |
562 for (RegistrationList::const_iterator it = registrations->begin(); | |
563 it != registrations->end(); ++it) { | |
564 // TODO(michaeln): if there are multiple matches the one with | |
565 // the longest scope should win. | |
566 if (ServiceWorkerUtils::ScopeMatches(it->scope, document_url)) { | |
567 scoped_refptr<ServiceWorkerRegistration> registration = | |
568 context_->GetLiveRegistration(it->registration_id); | |
569 if (registration) { | |
570 callback.Run(SERVICE_WORKER_OK, registration); | |
571 return; | |
572 } | |
573 callback.Run(SERVICE_WORKER_OK, CreateRegistration(*it)); | |
574 return; | |
575 } | |
576 } | |
577 | |
578 // Look for something currently being installed. | |
579 // TODO(michaeln): Should be mixed in with the stored registrations | |
580 // for this test. | |
581 scoped_refptr<ServiceWorkerRegistration> installing_registration = | |
582 FindInstallingRegistrationForDocument(document_url); | |
583 if (installing_registration) { | |
584 callback.Run(SERVICE_WORKER_OK, installing_registration); | |
585 return; | |
586 } | |
587 | |
588 callback.Run(SERVICE_WORKER_ERROR_NOT_FOUND, | |
589 scoped_refptr<ServiceWorkerRegistration>()); | |
590 } | |
591 | |
592 void ServiceWorkerStorage::DidReadRegistrationForId( | |
593 const FindRegistrationCallback& callback, | |
594 ServiceWorkerDatabase::RegistrationData* registration, | |
595 ResourceList* resources, | |
596 ServiceWorkerDatabase::Status status) { | |
597 DCHECK(registration); | |
598 DCHECK(resources); | |
599 | |
600 if (status == ServiceWorkerDatabase::STATUS_OK) { | 455 if (status == ServiceWorkerDatabase::STATUS_OK) { |
601 callback.Run(SERVICE_WORKER_OK, CreateRegistration(*registration)); | 456 callback.Run(SERVICE_WORKER_OK, GetOrCreateRegistration(data, resources)); |
602 return; | 457 return; |
603 } | 458 } |
604 | 459 |
605 if (status == ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND) { | 460 if (status == ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND) { |
606 // Look for somthing currently being installed. | 461 // Look for something currently being installed. |
607 scoped_refptr<ServiceWorkerRegistration> installing_registration = | 462 scoped_refptr<ServiceWorkerRegistration> installing_registration = |
608 FindInstallingRegistrationForId(registration->registration_id); | 463 FindInstallingRegistrationForDocument(document_url); |
609 if (installing_registration) { | 464 callback.Run(installing_registration ? |
610 callback.Run(SERVICE_WORKER_OK, installing_registration); | 465 SERVICE_WORKER_OK : SERVICE_WORKER_ERROR_NOT_FOUND, |
611 return; | 466 installing_registration); |
612 } | |
613 callback.Run(SERVICE_WORKER_ERROR_NOT_FOUND, | |
614 scoped_refptr<ServiceWorkerRegistration>()); | |
615 return; | 467 return; |
616 } | 468 } |
617 | 469 |
618 // TODO(nhiroki): Handle database error (http://crbug.com/371675). | 470 // TODO(nhiroki): Handle database error (http://crbug.com/371675). |
619 callback.Run(DatabaseStatusToStatusCode(status), | 471 callback.Run(DatabaseStatusToStatusCode(status), |
620 scoped_refptr<ServiceWorkerRegistration>()); | 472 scoped_refptr<ServiceWorkerRegistration>()); |
621 return; | 473 } |
| 474 |
| 475 void ServiceWorkerStorage::DidFindRegistrationForPattern( |
| 476 const GURL& scope, |
| 477 const FindRegistrationCallback& callback, |
| 478 const ServiceWorkerDatabase::RegistrationData& data, |
| 479 const ResourceList& resources, |
| 480 ServiceWorkerDatabase::Status status) { |
| 481 if (status == ServiceWorkerDatabase::STATUS_OK) { |
| 482 callback.Run(SERVICE_WORKER_OK, GetOrCreateRegistration(data, resources)); |
| 483 return; |
| 484 } |
| 485 |
| 486 if (status == ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND) { |
| 487 scoped_refptr<ServiceWorkerRegistration> installing_registration = |
| 488 FindInstallingRegistrationForPattern(scope); |
| 489 callback.Run(installing_registration ? |
| 490 SERVICE_WORKER_OK : SERVICE_WORKER_ERROR_NOT_FOUND, |
| 491 installing_registration); |
| 492 return; |
| 493 } |
| 494 |
| 495 // TODO(nhiroki): Handle database error (http://crbug.com/371675). |
| 496 callback.Run(DatabaseStatusToStatusCode(status), |
| 497 scoped_refptr<ServiceWorkerRegistration>()); |
| 498 } |
| 499 |
| 500 void ServiceWorkerStorage::DidFindRegistrationForId( |
| 501 const FindRegistrationCallback& callback, |
| 502 const ServiceWorkerDatabase::RegistrationData& data, |
| 503 const ResourceList& resources, |
| 504 ServiceWorkerDatabase::Status status) { |
| 505 if (status == ServiceWorkerDatabase::STATUS_OK) { |
| 506 callback.Run(SERVICE_WORKER_OK, |
| 507 GetOrCreateRegistration(data, resources)); |
| 508 return; |
| 509 } |
| 510 // TODO(nhiroki): Handle database error (http://crbug.com/371675). |
| 511 callback.Run(DatabaseStatusToStatusCode(status), |
| 512 scoped_refptr<ServiceWorkerRegistration>()); |
622 } | 513 } |
623 | 514 |
624 void ServiceWorkerStorage::DidGetAllRegistrations( | 515 void ServiceWorkerStorage::DidGetAllRegistrations( |
625 const GetAllRegistrationInfosCallback& callback, | 516 const GetAllRegistrationInfosCallback& callback, |
626 RegistrationList* registrations, | 517 RegistrationList* registrations, |
627 ServiceWorkerDatabase::Status status) { | 518 ServiceWorkerDatabase::Status status) { |
628 DCHECK(registrations); | 519 DCHECK(registrations); |
629 if (status != ServiceWorkerDatabase::STATUS_OK) { | 520 if (status != ServiceWorkerDatabase::STATUS_OK) { |
630 // TODO(nhiroki): Handle database error (http://crbug.com/371675). | 521 // TODO(nhiroki): Handle database error (http://crbug.com/371675). |
631 callback.Run(std::vector<ServiceWorkerRegistrationInfo>()); | 522 callback.Run(std::vector<ServiceWorkerRegistrationInfo>()); |
(...skipping 29 matching lines...) Expand all Loading... |
661 installing_registrations_.begin(); | 552 installing_registrations_.begin(); |
662 it != installing_registrations_.end(); ++it) { | 553 it != installing_registrations_.end(); ++it) { |
663 if (pushed_registrations.insert(it->first).second) | 554 if (pushed_registrations.insert(it->first).second) |
664 infos.push_back(it->second->GetInfo()); | 555 infos.push_back(it->second->GetInfo()); |
665 } | 556 } |
666 | 557 |
667 callback.Run(infos); | 558 callback.Run(infos); |
668 } | 559 } |
669 | 560 |
670 void ServiceWorkerStorage::DidStoreRegistration( | 561 void ServiceWorkerStorage::DidStoreRegistration( |
| 562 const StatusCallback& callback, |
671 const GURL& origin, | 563 const GURL& origin, |
672 const StatusCallback& callback, | 564 const std::vector<int64>& newly_purgeable_resources, |
673 ServiceWorkerDatabase::Status status) { | 565 ServiceWorkerDatabase::Status status) { |
674 if (status != ServiceWorkerDatabase::STATUS_OK) { | 566 if (status != ServiceWorkerDatabase::STATUS_OK) { |
675 // TODO(nhiroki): Handle database error (http://crbug.com/371675). | 567 // TODO(nhiroki): Handle database error (http://crbug.com/371675). |
676 callback.Run(DatabaseStatusToStatusCode(status)); | 568 callback.Run(DatabaseStatusToStatusCode(status)); |
677 return; | 569 return; |
678 } | 570 } |
679 registered_origins_.insert(origin); | 571 registered_origins_.insert(origin); |
680 callback.Run(SERVICE_WORKER_OK); | 572 callback.Run(SERVICE_WORKER_OK); |
| 573 StartPurgingResources(newly_purgeable_resources); |
681 } | 574 } |
682 | 575 |
683 void ServiceWorkerStorage::DidUpdateToActiveState( | 576 void ServiceWorkerStorage::DidUpdateToActiveState( |
684 const StatusCallback& callback, | 577 const StatusCallback& callback, |
685 ServiceWorkerDatabase::Status status) { | 578 ServiceWorkerDatabase::Status status) { |
686 // TODO(nhiroki): Handle database error (http://crbug.com/371675). | 579 // TODO(nhiroki): Handle database error (http://crbug.com/371675). |
687 callback.Run(DatabaseStatusToStatusCode(status)); | 580 callback.Run(DatabaseStatusToStatusCode(status)); |
688 } | 581 } |
689 | 582 |
690 void ServiceWorkerStorage::DidDeleteRegistration( | 583 void ServiceWorkerStorage::DidDeleteRegistration( |
691 const GURL& origin, | 584 const GURL& origin, |
692 const StatusCallback& callback, | 585 const StatusCallback& callback, |
693 bool origin_is_deletable, | 586 bool origin_is_deletable, |
| 587 const std::vector<int64>& newly_purgeable_resources, |
694 ServiceWorkerDatabase::Status status) { | 588 ServiceWorkerDatabase::Status status) { |
695 if (status != ServiceWorkerDatabase::STATUS_OK) { | 589 if (status != ServiceWorkerDatabase::STATUS_OK) { |
696 // TODO(nhiroki): Handle database error (http://crbug.com/371675). | 590 // TODO(nhiroki): Handle database error (http://crbug.com/371675). |
697 callback.Run(DatabaseStatusToStatusCode(status)); | 591 callback.Run(DatabaseStatusToStatusCode(status)); |
698 return; | 592 return; |
699 } | 593 } |
700 if (origin_is_deletable) | 594 if (origin_is_deletable) |
701 registered_origins_.erase(origin); | 595 registered_origins_.erase(origin); |
702 callback.Run(SERVICE_WORKER_OK); | 596 callback.Run(SERVICE_WORKER_OK); |
| 597 StartPurgingResources(newly_purgeable_resources); |
703 } | 598 } |
704 | 599 |
705 scoped_refptr<ServiceWorkerRegistration> | 600 scoped_refptr<ServiceWorkerRegistration> |
706 ServiceWorkerStorage::CreateRegistration( | 601 ServiceWorkerStorage::GetOrCreateRegistration( |
707 const ServiceWorkerDatabase::RegistrationData& data) { | 602 const ServiceWorkerDatabase::RegistrationData& data, |
708 scoped_refptr<ServiceWorkerRegistration> registration( | 603 const ResourceList& resources) { |
709 new ServiceWorkerRegistration( | 604 scoped_refptr<ServiceWorkerRegistration> registration = |
710 data.scope, data.script, data.registration_id, context_)); | 605 context_->GetLiveRegistration(data.registration_id); |
| 606 if (registration) |
| 607 return registration; |
711 | 608 |
| 609 registration = new ServiceWorkerRegistration( |
| 610 data.scope, data.script, data.registration_id, context_); |
712 scoped_refptr<ServiceWorkerVersion> version = | 611 scoped_refptr<ServiceWorkerVersion> version = |
713 context_->GetLiveVersion(data.version_id); | 612 context_->GetLiveVersion(data.version_id); |
714 if (!version) { | 613 if (!version) { |
715 version = new ServiceWorkerVersion(registration, data.version_id, context_); | 614 version = new ServiceWorkerVersion(registration, data.version_id, context_); |
716 version->SetStatus(data.is_active ? | 615 version->SetStatus(data.is_active ? |
717 ServiceWorkerVersion::ACTIVE : ServiceWorkerVersion::INSTALLED); | 616 ServiceWorkerVersion::ACTIVE : ServiceWorkerVersion::INSTALLED); |
| 617 version->script_cache_map()->SetResources(resources); |
718 } | 618 } |
719 | 619 |
720 if (version->status() == ServiceWorkerVersion::ACTIVE) | 620 if (version->status() == ServiceWorkerVersion::ACTIVE) |
721 registration->set_active_version(version); | 621 registration->set_active_version(version); |
722 else if (version->status() == ServiceWorkerVersion::INSTALLED) | 622 else if (version->status() == ServiceWorkerVersion::INSTALLED) |
723 registration->set_pending_version(version); | 623 registration->set_pending_version(version); |
724 else | 624 else |
725 NOTREACHED(); | 625 NOTREACHED(); |
726 // TODO(michaeln): Hmmm, what if DeleteReg was invoked after | 626 // TODO(michaeln): Hmmm, what if DeleteReg was invoked after |
727 // the Find result we're returning here? NOTREACHED condition? | 627 // the Find result we're returning here? NOTREACHED condition? |
728 | |
729 return registration; | 628 return registration; |
730 } | 629 } |
731 | 630 |
732 ServiceWorkerRegistration* | 631 ServiceWorkerRegistration* |
733 ServiceWorkerStorage::FindInstallingRegistrationForDocument( | 632 ServiceWorkerStorage::FindInstallingRegistrationForDocument( |
734 const GURL& document_url) { | 633 const GURL& document_url) { |
735 // TODO(michaeln): if there are multiple matches the one with | 634 // TODO(michaeln): if there are multiple matches the one with |
736 // the longest scope should win, and these should on equal footing | 635 // the longest scope should win. |
737 // with the stored registrations in FindRegistrationForDocument(). | |
738 for (RegistrationRefsById::const_iterator it = | 636 for (RegistrationRefsById::const_iterator it = |
739 installing_registrations_.begin(); | 637 installing_registrations_.begin(); |
740 it != installing_registrations_.end(); ++it) { | 638 it != installing_registrations_.end(); ++it) { |
741 if (ServiceWorkerUtils::ScopeMatches( | 639 if (ServiceWorkerUtils::ScopeMatches( |
742 it->second->pattern(), document_url)) { | 640 it->second->pattern(), document_url)) { |
743 return it->second; | 641 return it->second; |
744 } | 642 } |
745 } | 643 } |
746 return NULL; | 644 return NULL; |
747 } | 645 } |
(...skipping 17 matching lines...) Expand all Loading... |
765 installing_registrations_.find(registration_id); | 663 installing_registrations_.find(registration_id); |
766 if (found == installing_registrations_.end()) | 664 if (found == installing_registrations_.end()) |
767 return NULL; | 665 return NULL; |
768 return found->second; | 666 return found->second; |
769 } | 667 } |
770 | 668 |
771 ServiceWorkerDiskCache* ServiceWorkerStorage::disk_cache() { | 669 ServiceWorkerDiskCache* ServiceWorkerStorage::disk_cache() { |
772 if (disk_cache_) | 670 if (disk_cache_) |
773 return disk_cache_.get(); | 671 return disk_cache_.get(); |
774 | 672 |
775 // TODO(michaeln): Store data on disk and do error checking. | |
776 disk_cache_.reset(new ServiceWorkerDiskCache); | 673 disk_cache_.reset(new ServiceWorkerDiskCache); |
777 int rv = disk_cache_->InitWithMemBackend( | 674 |
778 kMaxMemDiskCacheSize, | 675 base::FilePath path = GetDiskCachePath(); |
779 base::Bind(&EmptyCompletionCallback)); | 676 if (path.empty()) { |
780 DCHECK_EQ(net::OK, rv); | 677 int rv = disk_cache_->InitWithMemBackend( |
| 678 kMaxMemDiskCacheSize, |
| 679 base::Bind(&EmptyCompletionCallback)); |
| 680 DCHECK_EQ(net::OK, rv); |
| 681 return disk_cache_.get(); |
| 682 } |
| 683 |
| 684 int rv = disk_cache_->InitWithDiskBackend( |
| 685 path, kMaxDiskCacheSize, false, |
| 686 disk_cache_thread_.get(), |
| 687 base::Bind(&ServiceWorkerStorage::OnDiskCacheInitialized, |
| 688 weak_factory_.GetWeakPtr())); |
| 689 if (rv != net::ERR_IO_PENDING) |
| 690 OnDiskCacheInitialized(rv); |
| 691 |
781 return disk_cache_.get(); | 692 return disk_cache_.get(); |
782 } | 693 } |
783 | 694 |
| 695 void ServiceWorkerStorage::OnDiskCacheInitialized(int rv) { |
| 696 if (rv != net::OK) { |
| 697 LOG(ERROR) << "Failed to open the serviceworker diskcache."; |
| 698 // TODO(michaeln): DeleteAndStartOver() |
| 699 disk_cache_->Disable(); |
| 700 state_ = DISABLED; |
| 701 } |
| 702 } |
| 703 |
| 704 void ServiceWorkerStorage::StartPurgingResources( |
| 705 const std::vector<int64>& ids) { |
| 706 for (size_t i = 0; i < ids.size(); ++i) |
| 707 purgeable_reource_ids_.push_back(ids[i]); |
| 708 |
| 709 if (purgeable_reource_ids_.empty() || is_purge_pending_) |
| 710 return; |
| 711 |
| 712 // Do one at a time until we're done, use RunSoon to avoid recursion when |
| 713 // DoomEntry returns immediately. |
| 714 is_purge_pending_ = true; |
| 715 int64 id = purgeable_reource_ids_.front(); |
| 716 purgeable_reource_ids_.pop_front(); |
| 717 RunSoon(FROM_HERE, |
| 718 base::Bind(&ServiceWorkerStorage::PurgeResource, |
| 719 weak_factory_.GetWeakPtr(), id)); |
| 720 } |
| 721 |
| 722 void ServiceWorkerStorage::PurgeResource(int64 id) { |
| 723 DCHECK(is_purge_pending_); |
| 724 int rv = disk_cache()->DoomEntry( |
| 725 id, base::Bind(&ServiceWorkerStorage::OnResourcePurged, |
| 726 weak_factory_.GetWeakPtr(), id)); |
| 727 if (rv != net::ERR_IO_PENDING) |
| 728 OnResourcePurged(id, rv); |
| 729 } |
| 730 |
| 731 void ServiceWorkerStorage::OnResourcePurged(int64 id, int rv) { |
| 732 DCHECK(is_purge_pending_); |
| 733 is_purge_pending_ = false; |
| 734 |
| 735 database_task_runner_->PostTask( |
| 736 FROM_HERE, |
| 737 base::Bind(base::IgnoreResult( |
| 738 &ServiceWorkerDatabase::ClearPurgeableResourceIds), |
| 739 base::Unretained(database_.get()), |
| 740 std::set<int64>(&id, &id + 1))); |
| 741 |
| 742 // Continue purging the remaining resources. |
| 743 StartPurgingResources(std::vector<int64>()); |
| 744 } |
| 745 |
| 746 void ServiceWorkerStorage::ReadInitialDataFromDB( |
| 747 ServiceWorkerDatabase* database, |
| 748 scoped_refptr<base::SequencedTaskRunner> original_task_runner, |
| 749 const InitializeCallback& callback) { |
| 750 DCHECK(database); |
| 751 scoped_ptr<ServiceWorkerStorage::InitialData> data( |
| 752 new ServiceWorkerStorage::InitialData()); |
| 753 |
| 754 ServiceWorkerDatabase::Status status = |
| 755 database->GetNextAvailableIds(&data->next_registration_id, |
| 756 &data->next_version_id, |
| 757 &data->next_resource_id); |
| 758 if (status != ServiceWorkerDatabase::STATUS_OK) { |
| 759 original_task_runner->PostTask( |
| 760 FROM_HERE, base::Bind(callback, base::Owned(data.release()), status)); |
| 761 return; |
| 762 } |
| 763 |
| 764 status = database->GetOriginsWithRegistrations(&data->origins); |
| 765 original_task_runner->PostTask( |
| 766 FROM_HERE, base::Bind(callback, base::Owned(data.release()), status)); |
| 767 } |
| 768 |
| 769 void ServiceWorkerStorage::DeleteRegistrationFromDB( |
| 770 ServiceWorkerDatabase* database, |
| 771 scoped_refptr<base::SequencedTaskRunner> original_task_runner, |
| 772 int64 registration_id, |
| 773 const GURL& origin, |
| 774 const DeleteRegistrationCallback& callback) { |
| 775 DCHECK(database); |
| 776 |
| 777 std::vector<int64> newly_purgeable_resources; |
| 778 ServiceWorkerDatabase::Status status = |
| 779 database->DeleteRegistration(registration_id, origin, |
| 780 &newly_purgeable_resources); |
| 781 if (status != ServiceWorkerDatabase::STATUS_OK) { |
| 782 original_task_runner->PostTask( |
| 783 FROM_HERE, base::Bind(callback, false, std::vector<int64>(), status)); |
| 784 return; |
| 785 } |
| 786 |
| 787 // TODO(nhiroki): Add convenient method to ServiceWorkerDatabase to check the |
| 788 // unique origin list. |
| 789 std::vector<ServiceWorkerDatabase::RegistrationData> registrations; |
| 790 status = database->GetRegistrationsForOrigin(origin, ®istrations); |
| 791 if (status != ServiceWorkerDatabase::STATUS_OK) { |
| 792 original_task_runner->PostTask( |
| 793 FROM_HERE, base::Bind(callback, false, std::vector<int64>(), status)); |
| 794 return; |
| 795 } |
| 796 |
| 797 bool deletable = registrations.empty(); |
| 798 original_task_runner->PostTask( |
| 799 FROM_HERE, base::Bind(callback, deletable, |
| 800 newly_purgeable_resources, status)); |
| 801 } |
| 802 |
| 803 void ServiceWorkerStorage::WriteRegistrationInDB( |
| 804 ServiceWorkerDatabase* database, |
| 805 scoped_refptr<base::SequencedTaskRunner> original_task_runner, |
| 806 const ServiceWorkerDatabase::RegistrationData& data, |
| 807 const ResourceList& resources, |
| 808 const WriteRegistrationCallback& callback) { |
| 809 DCHECK(database); |
| 810 std::vector<int64> newly_purgeable_resources; |
| 811 ServiceWorkerDatabase::Status status = |
| 812 database->WriteRegistration(data, resources, &newly_purgeable_resources); |
| 813 original_task_runner->PostTask( |
| 814 FROM_HERE, |
| 815 base::Bind(callback, data.script.GetOrigin(), |
| 816 newly_purgeable_resources, status)); |
| 817 } |
| 818 |
| 819 void ServiceWorkerStorage::FindForDocumentInDB( |
| 820 ServiceWorkerDatabase* database, |
| 821 scoped_refptr<base::SequencedTaskRunner> original_task_runner, |
| 822 const GURL& document_url, |
| 823 const FindInDBCallback& callback) { |
| 824 GURL origin = document_url.GetOrigin(); |
| 825 RegistrationList registrations; |
| 826 ServiceWorkerDatabase::Status status = |
| 827 database->GetRegistrationsForOrigin(origin, ®istrations); |
| 828 if (status != ServiceWorkerDatabase::STATUS_OK) { |
| 829 original_task_runner->PostTask( |
| 830 FROM_HERE, |
| 831 base::Bind(callback, |
| 832 ServiceWorkerDatabase::RegistrationData(), |
| 833 ResourceList(), |
| 834 status)); |
| 835 return; |
| 836 } |
| 837 |
| 838 // Find one with a pattern match. |
| 839 // TODO(michaeln): if there are multiple matches the one with |
| 840 // the longest scope should win. |
| 841 ServiceWorkerDatabase::RegistrationData data; |
| 842 ResourceList resources; |
| 843 status = ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND; |
| 844 for (RegistrationList::const_iterator it = registrations.begin(); |
| 845 it != registrations.end(); ++it) { |
| 846 if (!ServiceWorkerUtils::ScopeMatches(it->scope, document_url)) |
| 847 continue; |
| 848 status = database->ReadRegistration(it->registration_id, origin, |
| 849 &data, &resources); |
| 850 break; // We're done looping. |
| 851 } |
| 852 |
| 853 original_task_runner->PostTask( |
| 854 FROM_HERE, |
| 855 base::Bind(callback, data, resources, status)); |
| 856 } |
| 857 |
| 858 void ServiceWorkerStorage::FindForPatternInDB( |
| 859 ServiceWorkerDatabase* database, |
| 860 scoped_refptr<base::SequencedTaskRunner> original_task_runner, |
| 861 const GURL& scope, |
| 862 const FindInDBCallback& callback) { |
| 863 GURL origin = scope.GetOrigin(); |
| 864 std::vector<ServiceWorkerDatabase::RegistrationData> registrations; |
| 865 ServiceWorkerDatabase::Status status = |
| 866 database->GetRegistrationsForOrigin(origin, ®istrations); |
| 867 if (status != ServiceWorkerDatabase::STATUS_OK) { |
| 868 original_task_runner->PostTask( |
| 869 FROM_HERE, |
| 870 base::Bind(callback, |
| 871 ServiceWorkerDatabase::RegistrationData(), |
| 872 ResourceList(), |
| 873 status)); |
| 874 return; |
| 875 } |
| 876 |
| 877 // Find one with an exact matching scope. |
| 878 ServiceWorkerDatabase::RegistrationData data; |
| 879 ResourceList resources; |
| 880 status = ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND; |
| 881 for (RegistrationList::const_iterator it = registrations.begin(); |
| 882 it != registrations.end(); ++it) { |
| 883 if (scope != it->scope) |
| 884 continue; |
| 885 status = database->ReadRegistration(it->registration_id, origin, |
| 886 &data, &resources); |
| 887 break; // We're done looping. |
| 888 } |
| 889 |
| 890 original_task_runner->PostTask( |
| 891 FROM_HERE, |
| 892 base::Bind(callback, data, resources, status)); |
| 893 } |
| 894 |
| 895 void ServiceWorkerStorage::FindForIdInDB( |
| 896 ServiceWorkerDatabase* database, |
| 897 scoped_refptr<base::SequencedTaskRunner> original_task_runner, |
| 898 int64 registration_id, |
| 899 const GURL& origin, |
| 900 const FindInDBCallback& callback) { |
| 901 ServiceWorkerDatabase::RegistrationData data; |
| 902 ResourceList resources; |
| 903 ServiceWorkerDatabase::Status status = |
| 904 database->ReadRegistration(registration_id, origin, &data, &resources); |
| 905 original_task_runner->PostTask( |
| 906 FROM_HERE, base::Bind(callback, data, resources, status)); |
| 907 } |
| 908 |
784 } // namespace content | 909 } // namespace content |
OLD | NEW |