OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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_cache_storage.h" | 5 #include "content/browser/service_worker/service_worker_cache_storage.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/files/file_util.h" | 9 #include "base/files/file_util.h" |
10 #include "base/files/memory_mapped_file.h" | 10 #include "base/files/memory_mapped_file.h" |
(...skipping 13 matching lines...) Expand all Loading... |
24 | 24 |
25 | 25 |
26 // Handles the loading and clean up of ServiceWorkerCache objects. The | 26 // Handles the loading and clean up of ServiceWorkerCache objects. The |
27 // callback of every public method is guaranteed to be called. | 27 // callback of every public method is guaranteed to be called. |
28 class ServiceWorkerCacheStorage::CacheLoader { | 28 class ServiceWorkerCacheStorage::CacheLoader { |
29 public: | 29 public: |
30 typedef base::Callback<void(const scoped_refptr<ServiceWorkerCache>&)> | 30 typedef base::Callback<void(const scoped_refptr<ServiceWorkerCache>&)> |
31 CacheCallback; | 31 CacheCallback; |
32 typedef base::Callback<void(bool)> BoolCallback; | 32 typedef base::Callback<void(bool)> BoolCallback; |
33 typedef base::Callback<void(scoped_ptr<std::vector<std::string> >)> | 33 typedef base::Callback<void(scoped_ptr<std::vector<std::string> >)> |
34 StringsCallback; | 34 StringVectorCallback; |
35 | 35 |
36 CacheLoader(base::SequencedTaskRunner* cache_task_runner, | 36 CacheLoader(base::SequencedTaskRunner* cache_task_runner, |
37 net::URLRequestContext* request_context, | 37 net::URLRequestContext* request_context, |
38 base::WeakPtr<storage::BlobStorageContext> blob_context) | 38 base::WeakPtr<storage::BlobStorageContext> blob_context) |
39 : cache_task_runner_(cache_task_runner), | 39 : cache_task_runner_(cache_task_runner), |
40 request_context_(request_context), | 40 request_context_(request_context), |
41 blob_context_(blob_context) {} | 41 blob_context_(blob_context) {} |
42 | 42 |
43 virtual ~CacheLoader() {} | 43 virtual ~CacheLoader() {} |
44 | 44 |
45 // Creates a ServiceWorkerCache with the given name. It does not attempt to | 45 // Creates a ServiceWorkerCache with the given name. It does not attempt to |
46 // load the backend, that happens lazily when the cache is used. | 46 // load the backend, that happens lazily when the cache is used. |
47 virtual scoped_refptr<ServiceWorkerCache> CreateServiceWorkerCache( | 47 virtual scoped_refptr<ServiceWorkerCache> CreateServiceWorkerCache( |
48 const std::string& cache_name) = 0; | 48 const std::string& cache_name) = 0; |
49 | 49 |
50 // Deletes any pre-existing cache of the same name and then loads it. | 50 // Deletes any pre-existing cache of the same name and then loads it. |
51 virtual void CreateCache(const std::string& cache_name, | 51 virtual void CreateCache(const std::string& cache_name, |
52 const CacheCallback& callback) = 0; | 52 const CacheCallback& callback) = 0; |
53 | 53 |
54 // After the backend has been deleted, do any extra house keeping such as | 54 // After the backend has been deleted, do any extra house keeping such as |
55 // removing the cache's directory. | 55 // removing the cache's directory. |
56 virtual void CleanUpDeletedCache(const std::string& key, | 56 virtual void CleanUpDeletedCache(const std::string& key, |
57 const BoolCallback& callback) = 0; | 57 const BoolCallback& callback) = 0; |
58 | 58 |
59 // Writes the cache names (and sizes) to disk if applicable. | 59 // Writes the cache names (and sizes) to disk if applicable. |
60 virtual void WriteIndex(const CacheMap& caches, | 60 virtual void WriteIndex(const StringVector& cache_names, |
61 const BoolCallback& callback) = 0; | 61 const BoolCallback& callback) = 0; |
62 | 62 |
63 // Loads the cache names from disk if applicable. | 63 // Loads the cache names from disk if applicable. |
64 virtual void LoadIndex(scoped_ptr<std::vector<std::string> > cache_names, | 64 virtual void LoadIndex(scoped_ptr<std::vector<std::string> > cache_names, |
65 const StringsCallback& callback) = 0; | 65 const StringVectorCallback& callback) = 0; |
66 | 66 |
67 protected: | 67 protected: |
68 scoped_refptr<base::SequencedTaskRunner> cache_task_runner_; | 68 scoped_refptr<base::SequencedTaskRunner> cache_task_runner_; |
69 net::URLRequestContext* request_context_; | 69 net::URLRequestContext* request_context_; |
70 base::WeakPtr<storage::BlobStorageContext> blob_context_; | 70 base::WeakPtr<storage::BlobStorageContext> blob_context_; |
71 }; | 71 }; |
72 | 72 |
73 // Creates memory-only ServiceWorkerCaches. Because these caches have no | 73 // Creates memory-only ServiceWorkerCaches. Because these caches have no |
74 // persistent storage it is not safe to free them from memory if they might be | 74 // persistent storage it is not safe to free them from memory if they might be |
75 // used again. Therefore this class holds a reference to each cache until the | 75 // used again. Therefore this class holds a reference to each cache until the |
(...skipping 21 matching lines...) Expand all Loading... |
97 } | 97 } |
98 | 98 |
99 virtual void CleanUpDeletedCache(const std::string& cache_name, | 99 virtual void CleanUpDeletedCache(const std::string& cache_name, |
100 const BoolCallback& callback) OVERRIDE { | 100 const BoolCallback& callback) OVERRIDE { |
101 CacheRefMap::iterator it = cache_refs_.find(cache_name); | 101 CacheRefMap::iterator it = cache_refs_.find(cache_name); |
102 DCHECK(it != cache_refs_.end()); | 102 DCHECK(it != cache_refs_.end()); |
103 cache_refs_.erase(it); | 103 cache_refs_.erase(it); |
104 callback.Run(true); | 104 callback.Run(true); |
105 } | 105 } |
106 | 106 |
107 virtual void WriteIndex(const CacheMap& caches, | 107 virtual void WriteIndex(const StringVector& cache_names, |
108 const BoolCallback& callback) OVERRIDE { | 108 const BoolCallback& callback) OVERRIDE { |
109 callback.Run(false); | 109 callback.Run(false); |
110 } | 110 } |
111 | 111 |
112 virtual void LoadIndex(scoped_ptr<std::vector<std::string> > cache_names, | 112 virtual void LoadIndex(scoped_ptr<std::vector<std::string> > cache_names, |
113 const StringsCallback& callback) OVERRIDE { | 113 const StringVectorCallback& callback) OVERRIDE { |
114 callback.Run(cache_names.Pass()); | 114 callback.Run(cache_names.Pass()); |
115 } | 115 } |
116 | 116 |
117 private: | 117 private: |
118 typedef std::map<std::string, scoped_refptr<ServiceWorkerCache> > CacheRefMap; | 118 typedef std::map<std::string, scoped_refptr<ServiceWorkerCache> > CacheRefMap; |
119 virtual ~MemoryLoader() {} | 119 virtual ~MemoryLoader() {} |
120 | 120 |
121 // Keep a reference to each cache to ensure that it's not freed before the | 121 // Keep a reference to each cache to ensure that it's not freed before the |
122 // client calls ServiceWorkerCacheStorage::Delete or the CacheStorage is | 122 // client calls ServiceWorkerCacheStorage::Delete or the CacheStorage is |
123 // freed. | 123 // freed. |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
201 } | 201 } |
202 | 202 |
203 static void CleanUpDeleteCacheDirInPool( | 203 static void CleanUpDeleteCacheDirInPool( |
204 const base::FilePath& cache_path, | 204 const base::FilePath& cache_path, |
205 const BoolCallback& callback, | 205 const BoolCallback& callback, |
206 const scoped_refptr<base::MessageLoopProxy>& original_loop) { | 206 const scoped_refptr<base::MessageLoopProxy>& original_loop) { |
207 bool rv = base::DeleteFile(cache_path, true); | 207 bool rv = base::DeleteFile(cache_path, true); |
208 original_loop->PostTask(FROM_HERE, base::Bind(callback, rv)); | 208 original_loop->PostTask(FROM_HERE, base::Bind(callback, rv)); |
209 } | 209 } |
210 | 210 |
211 virtual void WriteIndex(const CacheMap& caches, | 211 virtual void WriteIndex(const StringVector& cache_names, |
212 const BoolCallback& callback) OVERRIDE { | 212 const BoolCallback& callback) OVERRIDE { |
213 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 213 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
214 | 214 |
215 // 1. Create the index file as a string. (WriteIndex) | 215 // 1. Create the index file as a string. (WriteIndex) |
216 // 2. Write the file to disk. (WriteIndexWriteToFileInPool) | 216 // 2. Write the file to disk. (WriteIndexWriteToFileInPool) |
217 | 217 |
218 ServiceWorkerCacheStorageIndex index; | 218 ServiceWorkerCacheStorageIndex index; |
219 | 219 |
220 for (CacheMap::const_iterator it = caches.begin(); it != caches.end(); | 220 for (size_t i = 0u, max = cache_names.size(); i < max; ++i) { |
221 ++it) { | |
222 ServiceWorkerCacheStorageIndex::Cache* index_cache = index.add_cache(); | 221 ServiceWorkerCacheStorageIndex::Cache* index_cache = index.add_cache(); |
223 index_cache->set_name(it->first); | 222 index_cache->set_name(cache_names[i]); |
224 index_cache->set_size(0); // TODO(jkarlin): Make this real. | 223 index_cache->set_size(0); // TODO(jkarlin): Make this real. |
225 } | 224 } |
226 | 225 |
227 std::string serialized; | 226 std::string serialized; |
228 bool success = index.SerializeToString(&serialized); | 227 bool success = index.SerializeToString(&serialized); |
229 DCHECK(success); | 228 DCHECK(success); |
230 | 229 |
231 base::FilePath tmp_path = origin_path_.AppendASCII("index.txt.tmp"); | 230 base::FilePath tmp_path = origin_path_.AppendASCII("index.txt.tmp"); |
232 base::FilePath index_path = origin_path_.AppendASCII("index.txt"); | 231 base::FilePath index_path = origin_path_.AppendASCII("index.txt"); |
233 | 232 |
(...skipping 18 matching lines...) Expand all Loading... |
252 base::DeleteFile(tmp_path, /* recursive */ false); | 251 base::DeleteFile(tmp_path, /* recursive */ false); |
253 original_loop->PostTask(FROM_HERE, base::Bind(callback, false)); | 252 original_loop->PostTask(FROM_HERE, base::Bind(callback, false)); |
254 } | 253 } |
255 | 254 |
256 // Atomically rename the temporary index file to become the real one. | 255 // Atomically rename the temporary index file to become the real one. |
257 bool rv = base::ReplaceFile(tmp_path, index_path, NULL); | 256 bool rv = base::ReplaceFile(tmp_path, index_path, NULL); |
258 original_loop->PostTask(FROM_HERE, base::Bind(callback, rv)); | 257 original_loop->PostTask(FROM_HERE, base::Bind(callback, rv)); |
259 } | 258 } |
260 | 259 |
261 virtual void LoadIndex(scoped_ptr<std::vector<std::string> > names, | 260 virtual void LoadIndex(scoped_ptr<std::vector<std::string> > names, |
262 const StringsCallback& callback) OVERRIDE { | 261 const StringVectorCallback& callback) OVERRIDE { |
263 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 262 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
264 | 263 |
265 // 1. Read the file from disk. (LoadIndexReadFileInPool) | 264 // 1. Read the file from disk. (LoadIndexReadFileInPool) |
266 // 2. Parse file and return the names of the caches (LoadIndexDidReadFile) | 265 // 2. Parse file and return the names of the caches (LoadIndexDidReadFile) |
267 | 266 |
268 base::FilePath index_path = origin_path_.AppendASCII("index.txt"); | 267 base::FilePath index_path = origin_path_.AppendASCII("index.txt"); |
269 | 268 |
270 cache_task_runner_->PostTask( | 269 cache_task_runner_->PostTask( |
271 FROM_HERE, | 270 FROM_HERE, |
272 base::Bind(&SimpleCacheLoader::LoadIndexReadFileInPool, | 271 base::Bind(&SimpleCacheLoader::LoadIndexReadFileInPool, |
273 index_path, | 272 index_path, |
274 base::Passed(names.Pass()), | 273 base::Passed(names.Pass()), |
275 callback, | 274 callback, |
276 base::MessageLoopProxy::current())); | 275 base::MessageLoopProxy::current())); |
277 } | 276 } |
278 | 277 |
279 static void LoadIndexReadFileInPool( | 278 static void LoadIndexReadFileInPool( |
280 const base::FilePath& index_path, | 279 const base::FilePath& index_path, |
281 scoped_ptr<std::vector<std::string> > names, | 280 scoped_ptr<std::vector<std::string> > names, |
282 const StringsCallback& callback, | 281 const StringVectorCallback& callback, |
283 const scoped_refptr<base::MessageLoopProxy>& original_loop) { | 282 const scoped_refptr<base::MessageLoopProxy>& original_loop) { |
284 std::string body; | 283 std::string body; |
285 base::ReadFileToString(index_path, &body); | 284 base::ReadFileToString(index_path, &body); |
286 | 285 |
287 original_loop->PostTask(FROM_HERE, | 286 original_loop->PostTask(FROM_HERE, |
288 base::Bind(&SimpleCacheLoader::LoadIndexDidReadFile, | 287 base::Bind(&SimpleCacheLoader::LoadIndexDidReadFile, |
289 base::Passed(names.Pass()), | 288 base::Passed(names.Pass()), |
290 callback, | 289 callback, |
291 body)); | 290 body)); |
292 } | 291 } |
293 | 292 |
294 static void LoadIndexDidReadFile(scoped_ptr<std::vector<std::string> > names, | 293 static void LoadIndexDidReadFile(scoped_ptr<std::vector<std::string> > names, |
295 const StringsCallback& callback, | 294 const StringVectorCallback& callback, |
296 const std::string& serialized) { | 295 const std::string& serialized) { |
297 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 296 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
298 | 297 |
299 ServiceWorkerCacheStorageIndex index; | 298 ServiceWorkerCacheStorageIndex index; |
300 if (index.ParseFromString(serialized)) { | 299 if (index.ParseFromString(serialized)) { |
301 for (int i = 0, max = index.cache_size(); i < max; ++i) { | 300 for (int i = 0, max = index.cache_size(); i < max; ++i) { |
302 const ServiceWorkerCacheStorageIndex::Cache& cache = index.cache(i); | 301 const ServiceWorkerCacheStorageIndex::Cache& cache = index.cache(i); |
303 names->push_back(cache.name()); | 302 names->push_back(cache.name()); |
304 } | 303 } |
305 } | 304 } |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
435 callback.Run(false, CACHE_STORAGE_ERROR_NOT_FOUND); | 434 callback.Run(false, CACHE_STORAGE_ERROR_NOT_FOUND); |
436 return; | 435 return; |
437 } | 436 } |
438 | 437 |
439 base::WeakPtr<ServiceWorkerCache> cache = it->second; | 438 base::WeakPtr<ServiceWorkerCache> cache = it->second; |
440 if (cache) | 439 if (cache) |
441 cache->Close(); | 440 cache->Close(); |
442 | 441 |
443 cache_map_.erase(it); | 442 cache_map_.erase(it); |
444 | 443 |
| 444 // Delete the name from ordered_cache_names_. |
| 445 StringVector::iterator iter = std::find( |
| 446 ordered_cache_names_.begin(), ordered_cache_names_.end(), cache_name); |
| 447 DCHECK(iter != ordered_cache_names_.end()); |
| 448 ordered_cache_names_.erase(iter); |
| 449 |
445 // Update the Index | 450 // Update the Index |
446 cache_loader_->WriteIndex( | 451 cache_loader_->WriteIndex( |
447 cache_map_, | 452 ordered_cache_names_, |
448 base::Bind(&ServiceWorkerCacheStorage::DeleteCacheDidWriteIndex, | 453 base::Bind(&ServiceWorkerCacheStorage::DeleteCacheDidWriteIndex, |
449 weak_factory_.GetWeakPtr(), | 454 weak_factory_.GetWeakPtr(), |
450 cache_name, | 455 cache_name, |
451 callback)); | 456 callback)); |
452 } | 457 } |
453 | 458 |
454 void ServiceWorkerCacheStorage::EnumerateCaches( | 459 void ServiceWorkerCacheStorage::EnumerateCaches( |
455 const StringsAndErrorCallback& callback) { | 460 const StringsAndErrorCallback& callback) { |
456 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 461 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
457 | 462 |
458 if (!initialized_) { | 463 if (!initialized_) { |
459 LazyInit(base::Bind(&ServiceWorkerCacheStorage::EnumerateCaches, | 464 LazyInit(base::Bind(&ServiceWorkerCacheStorage::EnumerateCaches, |
460 weak_factory_.GetWeakPtr(), | 465 weak_factory_.GetWeakPtr(), |
461 callback)); | 466 callback)); |
462 return; | 467 return; |
463 } | 468 } |
464 | 469 |
465 std::vector<std::string> names; | 470 callback.Run(ordered_cache_names_, CACHE_STORAGE_ERROR_NO_ERROR); |
466 for (CacheMap::const_iterator it = cache_map_.begin(); it != cache_map_.end(); | |
467 ++it) { | |
468 names.push_back(it->first); | |
469 } | |
470 | |
471 callback.Run(names, CACHE_STORAGE_ERROR_NO_ERROR); | |
472 } | 471 } |
473 | 472 |
474 // Init is run lazily so that it is called on the proper MessageLoop. | 473 // Init is run lazily so that it is called on the proper MessageLoop. |
475 void ServiceWorkerCacheStorage::LazyInit(const base::Closure& callback) { | 474 void ServiceWorkerCacheStorage::LazyInit(const base::Closure& callback) { |
476 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 475 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
477 DCHECK(!initialized_); | 476 DCHECK(!initialized_); |
478 | 477 |
479 init_callbacks_.push_back(callback); | 478 init_callbacks_.push_back(callback); |
480 | 479 |
481 // If this isn't the first call to LazyInit then return as the initialization | 480 // If this isn't the first call to LazyInit then return as the initialization |
(...skipping 17 matching lines...) Expand all Loading... |
499 } | 498 } |
500 | 499 |
501 void ServiceWorkerCacheStorage::LazyInitDidLoadIndex( | 500 void ServiceWorkerCacheStorage::LazyInitDidLoadIndex( |
502 const base::Closure& callback, | 501 const base::Closure& callback, |
503 scoped_ptr<std::vector<std::string> > indexed_cache_names) { | 502 scoped_ptr<std::vector<std::string> > indexed_cache_names) { |
504 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 503 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
505 | 504 |
506 for (size_t i = 0u, max = indexed_cache_names->size(); i < max; ++i) { | 505 for (size_t i = 0u, max = indexed_cache_names->size(); i < max; ++i) { |
507 cache_map_.insert(std::make_pair(indexed_cache_names->at(i), | 506 cache_map_.insert(std::make_pair(indexed_cache_names->at(i), |
508 base::WeakPtr<ServiceWorkerCache>())); | 507 base::WeakPtr<ServiceWorkerCache>())); |
| 508 ordered_cache_names_.push_back(indexed_cache_names->at(i)); |
509 } | 509 } |
510 | 510 |
511 initialized_ = true; | 511 initialized_ = true; |
512 for (std::vector<base::Closure>::iterator it = init_callbacks_.begin(); | 512 for (std::vector<base::Closure>::iterator it = init_callbacks_.begin(); |
513 it != init_callbacks_.end(); | 513 it != init_callbacks_.end(); |
514 ++it) { | 514 ++it) { |
515 it->Run(); | 515 it->Run(); |
516 } | 516 } |
517 init_callbacks_.clear(); | 517 init_callbacks_.clear(); |
518 } | 518 } |
519 | 519 |
520 void ServiceWorkerCacheStorage::CreateCacheDidCreateCache( | 520 void ServiceWorkerCacheStorage::CreateCacheDidCreateCache( |
521 const std::string& cache_name, | 521 const std::string& cache_name, |
522 const CacheAndErrorCallback& callback, | 522 const CacheAndErrorCallback& callback, |
523 const scoped_refptr<ServiceWorkerCache>& cache) { | 523 const scoped_refptr<ServiceWorkerCache>& cache) { |
524 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 524 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
525 | 525 |
526 if (!cache.get()) { | 526 if (!cache.get()) { |
527 callback.Run(scoped_refptr<ServiceWorkerCache>(), | 527 callback.Run(scoped_refptr<ServiceWorkerCache>(), |
528 CACHE_STORAGE_ERROR_CLOSING); | 528 CACHE_STORAGE_ERROR_CLOSING); |
529 return; | 529 return; |
530 } | 530 } |
531 | 531 |
532 cache_map_.insert(std::make_pair(cache_name, cache->AsWeakPtr())); | 532 cache_map_.insert(std::make_pair(cache_name, cache->AsWeakPtr())); |
| 533 ordered_cache_names_.push_back(cache_name); |
533 | 534 |
534 cache_loader_->WriteIndex( | 535 cache_loader_->WriteIndex( |
535 cache_map_, | 536 ordered_cache_names_, |
536 base::Bind(&ServiceWorkerCacheStorage::CreateCacheDidWriteIndex, | 537 base::Bind(&ServiceWorkerCacheStorage::CreateCacheDidWriteIndex, |
537 weak_factory_.GetWeakPtr(), | 538 weak_factory_.GetWeakPtr(), |
538 callback, | 539 callback, |
539 cache)); | 540 cache)); |
540 } | 541 } |
541 | 542 |
542 void ServiceWorkerCacheStorage::CreateCacheDidWriteIndex( | 543 void ServiceWorkerCacheStorage::CreateCacheDidWriteIndex( |
543 const CacheAndErrorCallback& callback, | 544 const CacheAndErrorCallback& callback, |
544 const scoped_refptr<ServiceWorkerCache>& cache, | 545 const scoped_refptr<ServiceWorkerCache>& cache, |
545 bool success) { | 546 bool success) { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
585 scoped_refptr<ServiceWorkerCache> new_cache = | 586 scoped_refptr<ServiceWorkerCache> new_cache = |
586 cache_loader_->CreateServiceWorkerCache(cache_name); | 587 cache_loader_->CreateServiceWorkerCache(cache_name); |
587 map_iter->second = new_cache->AsWeakPtr(); | 588 map_iter->second = new_cache->AsWeakPtr(); |
588 return new_cache; | 589 return new_cache; |
589 } | 590 } |
590 | 591 |
591 return make_scoped_refptr(cache.get()); | 592 return make_scoped_refptr(cache.get()); |
592 } | 593 } |
593 | 594 |
594 } // namespace content | 595 } // namespace content |
OLD | NEW |