Chromium Code Reviews| 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/file_util.h" | 9 #include "base/file_util.h" |
| 10 #include "base/files/memory_mapped_file.h" | 10 #include "base/files/memory_mapped_file.h" |
| 11 #include "base/sha1.h" | 11 #include "base/sha1.h" |
| 12 #include "base/strings/string_number_conversions.h" | 12 #include "base/strings/string_number_conversions.h" |
| 13 #include "base/strings/string_util.h" | 13 #include "base/strings/string_util.h" |
| 14 #include "content/browser/service_worker/service_worker_cache.h" | 14 #include "content/browser/service_worker/service_worker_cache.h" |
| 15 #include "content/browser/service_worker/service_worker_cache.pb.h" | 15 #include "content/browser/service_worker/service_worker_cache.pb.h" |
| 16 #include "content/public/browser/browser_thread.h" | 16 #include "content/public/browser/browser_thread.h" |
| 17 #include "net/base/directory_lister.h" | 17 #include "net/base/directory_lister.h" |
| 18 #include "net/base/net_errors.h" | |
| 18 | 19 |
| 19 namespace content { | 20 namespace content { |
| 20 | 21 |
| 21 // Handles the loading and clean up of ServiceWorkerCache objects. | 22 // Handles the loading and clean up of ServiceWorkerCache objects. |
| 22 class ServiceWorkerCacheStorage::CacheLoader { | 23 class ServiceWorkerCacheStorage::CacheLoader { |
| 23 public: | 24 public: |
| 25 typedef base::Callback<void(ServiceWorkerCache*)> CacheCallback; | |
| 26 typedef base::Callback<void(bool)> BoolCallback; | |
| 27 typedef base::Callback<void(scoped_ptr<std::vector<std::string> >)> | |
| 28 StringsCallback; | |
| 29 | |
| 30 explicit CacheLoader(base::SequencedTaskRunner* cache_task_runner) | |
| 31 : cache_task_runner_(cache_task_runner) {} | |
| 32 | |
| 24 virtual ~CacheLoader() {}; | 33 virtual ~CacheLoader() {}; |
| 25 virtual ServiceWorkerCache* LoadCache(const std::string& cache_name) = 0; | 34 |
| 26 // Creates a new cache, deleting any pre-existing cache of the same name. | 35 // Loads the given cache_name, the cache is NULL if it fails. If the cache |
| 27 virtual ServiceWorkerCache* CreateCache(const std::string& cache_name) = 0; | 36 // doesn't exist a new one is created. |
| 28 virtual bool CleanUpDeletedCache(const std::string& key) = 0; | 37 virtual void LoadCache(const std::string& cache_name, |
| 29 virtual bool WriteIndex(CacheMap* caches) = 0; | 38 const CacheCallback& callback) = 0; |
| 30 virtual void LoadIndex(std::vector<std::string>* cache_names) = 0; | 39 |
| 40 // Deletes any pre-existing cache of the same name and then loads it. | |
| 41 virtual void CreateCache(const std::string& cache_name, | |
| 42 const CacheCallback& callback) = 0; | |
| 43 | |
| 44 // After the backend has been deleted, do any extra house keeping such as | |
| 45 // removing the cache's directory. | |
| 46 virtual void CleanUpDeletedCache(const std::string& key, | |
| 47 const BoolCallback& callback) = 0; | |
| 48 | |
| 49 // Writes the cache names to disk if applicable. | |
| 50 virtual void WriteIndex(CacheMap* caches, const BoolCallback& callback) = 0; | |
| 51 | |
| 52 // Loads the cache names from disk if applicable. | |
| 53 virtual void LoadIndex(scoped_ptr<std::vector<std::string> > cache_names, | |
| 54 const StringsCallback& callback) = 0; | |
| 55 | |
| 56 protected: | |
| 57 virtual void LoadCacheImpl(const std::string&) {} | |
| 58 scoped_refptr<base::SequencedTaskRunner> cache_task_runner_; | |
| 31 }; | 59 }; |
| 32 | 60 |
| 33 class ServiceWorkerCacheStorage::MemoryLoader | 61 class ServiceWorkerCacheStorage::MemoryLoader |
| 34 : public ServiceWorkerCacheStorage::CacheLoader { | 62 : public ServiceWorkerCacheStorage::CacheLoader { |
| 35 public: | 63 public: |
| 36 virtual content::ServiceWorkerCache* LoadCache( | 64 explicit MemoryLoader(base::SequencedTaskRunner* cache_task_runner) |
| 37 const std::string& cache_name) OVERRIDE { | 65 : CacheLoader(cache_task_runner) {} |
| 66 virtual void LoadCache(const std::string& cache_name, | |
| 67 const CacheCallback& callback) OVERRIDE { | |
| 38 NOTREACHED(); | 68 NOTREACHED(); |
| 39 return NULL; | 69 } |
| 40 } | 70 |
| 41 | 71 virtual void CreateCache(const std::string& cache_name, |
| 42 virtual ServiceWorkerCache* CreateCache( | 72 const CacheCallback& callback) OVERRIDE { |
| 43 const std::string& cache_name) OVERRIDE { | 73 ServiceWorkerCache* cache = |
| 44 return ServiceWorkerCache::CreateMemoryCache(cache_name); | 74 ServiceWorkerCache::CreateMemoryCache(cache_name); |
| 45 } | 75 callback.Run(cache); |
| 46 | 76 } |
| 47 virtual bool CleanUpDeletedCache(const std::string& cache_name) OVERRIDE { | 77 |
| 48 return true; | 78 virtual void CleanUpDeletedCache(const std::string& cache_name, |
| 49 } | 79 const BoolCallback& callback) OVERRIDE { |
| 50 | 80 callback.Run(true); |
| 51 virtual bool WriteIndex(CacheMap* caches) OVERRIDE { return false; } | 81 } |
| 52 | 82 |
| 53 virtual void LoadIndex(std::vector<std::string>* cache_names) OVERRIDE { | 83 virtual void WriteIndex(CacheMap* caches, |
| 54 return; | 84 const BoolCallback& callback) OVERRIDE { |
| 85 callback.Run(false); | |
| 86 } | |
| 87 | |
| 88 virtual void LoadIndex(scoped_ptr<std::vector<std::string> > cache_names, | |
| 89 const StringsCallback& callback) OVERRIDE { | |
| 90 callback.Run(cache_names.Pass()); | |
| 55 } | 91 } |
| 56 }; | 92 }; |
| 57 | 93 |
| 58 class ServiceWorkerCacheStorage::SimpleCacheLoader | 94 class ServiceWorkerCacheStorage::SimpleCacheLoader |
| 59 : public ServiceWorkerCacheStorage::CacheLoader { | 95 : public ServiceWorkerCacheStorage::CacheLoader { |
| 60 public: | 96 public: |
| 61 explicit SimpleCacheLoader(const base::FilePath& origin_path) | 97 SimpleCacheLoader(const base::FilePath& origin_path, |
| 62 : origin_path_(origin_path) {} | 98 base::SequencedTaskRunner* cache_task_runner) |
| 63 | 99 : CacheLoader(cache_task_runner), origin_path_(origin_path) {} |
| 64 virtual ServiceWorkerCache* LoadCache( | 100 |
| 65 const std::string& cache_name) OVERRIDE { | 101 virtual void LoadCache(const std::string& cache_name, |
| 66 base::CreateDirectory(CreatePersistentCachePath(origin_path_, cache_name)); | 102 const CacheCallback& callback) OVERRIDE { |
| 67 return ServiceWorkerCache::CreatePersistentCache( | 103 DCHECK(thread_checker_.CalledOnValidThread()); |
| 104 | |
| 105 // 1. Create the cache's directory if necessary. (LoadCreateDirectory) | |
| 106 // 2. Create the cache object. (LoadDidCreateDirectory) | |
| 107 | |
| 108 cache_task_runner_->PostTask( | |
| 109 FROM_HERE, | |
| 110 base::Bind(&SimpleCacheLoader::LoadCreateDirectoryInPool, | |
| 111 base::Unretained(this), // should be weak_ptr? | |
|
michaeln
2014/08/11 19:30:17
unretained is no good... deriving CacheLoader from
jkarlin
2014/08/12 14:55:02
Done.
| |
| 112 CreatePersistentCachePath(origin_path_, cache_name), | |
| 113 cache_name, | |
| 114 callback, | |
| 115 base::MessageLoopProxy::current())); | |
| 116 } | |
| 117 | |
| 118 void LoadCreateDirectoryInPool( | |
| 119 const base::FilePath& path, | |
| 120 const std::string& cache_name, | |
| 121 const CacheCallback& callback, | |
| 122 scoped_refptr<base::MessageLoopProxy> original_loop) { | |
| 123 bool rv = base::CreateDirectory(path); | |
| 124 original_loop->PostTask( | |
| 125 FROM_HERE, | |
| 126 base::Bind(&SimpleCacheLoader::LoadDidCreateDirectory, | |
| 127 base::Unretained(this), | |
| 128 cache_name, | |
| 129 callback, | |
| 130 rv)); | |
| 131 } | |
| 132 | |
| 133 void LoadDidCreateDirectory(const std::string& cache_name, | |
| 134 const CacheCallback& callback, | |
| 135 bool dir_rv) { | |
| 136 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 137 | |
| 138 if (!dir_rv) { | |
| 139 callback.Run(NULL); | |
| 140 return; | |
| 141 } | |
| 142 ServiceWorkerCache* cache = ServiceWorkerCache::CreatePersistentCache( | |
| 68 CreatePersistentCachePath(origin_path_, cache_name), cache_name); | 143 CreatePersistentCachePath(origin_path_, cache_name), cache_name); |
| 69 } | 144 callback.Run(cache); |
| 70 | 145 } |
| 71 virtual ServiceWorkerCache* CreateCache( | 146 |
| 72 const std::string& cache_name) OVERRIDE { | 147 virtual void CreateCache(const std::string& cache_name, |
| 148 const CacheCallback& callback) OVERRIDE { | |
| 149 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 150 | |
| 151 // 1. Delete the cache's directory if it exists. (CreateDeleteFiles) | |
|
michaeln
2014/08/11 20:30:14
(CreateDeleteFiles) s/b (CreateCacheDeleteFilesInP
jkarlin
2014/08/12 14:55:03
Done.
| |
| 152 // 2. Load the cache. (LoadCache) | |
| 153 | |
| 73 base::FilePath cache_path = | 154 base::FilePath cache_path = |
| 74 CreatePersistentCachePath(origin_path_, cache_name); | 155 CreatePersistentCachePath(origin_path_, cache_name); |
| 75 if (base::PathExists(cache_path)) | 156 |
| 76 base::DeleteFile(cache_path, /* recursive */ true); | 157 cache_task_runner_->PostTask( |
| 77 return LoadCache(cache_name); | 158 FROM_HERE, |
| 78 } | 159 base::Bind(&SimpleCacheLoader::CreateCacheDeleteFilesInPool, |
| 79 | 160 base::Unretained(this), // should be weak_ptr? |
| 80 virtual bool CleanUpDeletedCache(const std::string& cache_name) OVERRIDE { | 161 cache_path, |
| 81 return base::DeleteFile(CreatePersistentCachePath(origin_path_, cache_name), | 162 cache_name, |
| 82 true); | 163 callback, |
| 83 } | 164 base::MessageLoopProxy::current())); |
| 84 | 165 } |
| 85 virtual bool WriteIndex(CacheMap* caches) OVERRIDE { | 166 |
| 167 void CreateCacheDeleteFilesInPool( | |
| 168 const base::FilePath& cache_path, | |
| 169 const std::string& cache_name, | |
| 170 const CacheCallback& callback, | |
| 171 scoped_refptr<base::MessageLoopProxy> original_loop) { | |
|
michaeln
2014/08/11 20:30:14
maybe add DCHECKS for cache_task_runner_.RunTasksO
jkarlin
2014/08/12 14:55:03
Great idea, thanks!
| |
| 172 base::FilePath path(cache_path); | |
| 173 if (base::PathExists(path)) | |
| 174 base::DeleteFile(path, /* recursive */ true); | |
| 175 original_loop->PostTask(FROM_HERE, | |
| 176 base::Bind(&SimpleCacheLoader::LoadCache, | |
|
michaeln
2014/08/11 20:30:14
This operation take multiple hops to the cache_thr
jkarlin
2014/08/12 14:55:03
Done.
| |
| 177 base::Unretained(this), | |
| 178 cache_name, | |
| 179 callback)); | |
| 180 } | |
| 181 | |
| 182 virtual void CleanUpDeletedCache(const std::string& cache_name, | |
| 183 const BoolCallback& callback) OVERRIDE { | |
| 184 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 185 | |
| 186 // 1. Delete the cache's directory. (CleanUpDeleteCacheDir) | |
| 187 | |
| 188 base::FilePath cache_path = | |
| 189 CreatePersistentCachePath(origin_path_, cache_name); | |
| 190 cache_task_runner_->PostTask( | |
| 191 FROM_HERE, | |
| 192 base::Bind(&SimpleCacheLoader::CleanUpDeleteCacheDirInPool, | |
| 193 base::Unretained(this), | |
| 194 cache_path, | |
| 195 callback, | |
| 196 base::MessageLoopProxy::current())); | |
| 197 } | |
| 198 | |
| 199 void CleanUpDeleteCacheDirInPool( | |
| 200 const base::FilePath& cache_path, | |
| 201 const BoolCallback& callback, | |
| 202 scoped_refptr<base::MessageLoopProxy> original_loop) { | |
|
michaeln
2014/08/11 20:30:14
can these be const refs (or a rawptr) to the Messa
jkarlin
2014/08/12 14:55:02
Thanks! Done.
| |
| 203 bool rv = base::DeleteFile(cache_path, true); | |
| 204 original_loop->PostTask(FROM_HERE, base::Bind(callback, rv)); | |
| 205 } | |
| 206 | |
| 207 virtual void WriteIndex(CacheMap* caches, | |
| 208 const BoolCallback& callback) OVERRIDE { | |
| 209 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 210 | |
| 211 // 1. Create the index file as a string. (WriteIndex) | |
| 212 // 2. Write the file to disk. (WriteIndexWriteToFile) | |
| 213 | |
| 86 ServiceWorkerCacheStorageIndex index; | 214 ServiceWorkerCacheStorageIndex index; |
| 87 | 215 |
| 88 for (CacheMap::const_iterator iter(caches); !iter.IsAtEnd(); | 216 for (CacheMap::const_iterator iter(caches); !iter.IsAtEnd(); |
| 89 iter.Advance()) { | 217 iter.Advance()) { |
| 90 const ServiceWorkerCache* cache = iter.GetCurrentValue(); | 218 const ServiceWorkerCache* cache = iter.GetCurrentValue(); |
| 91 ServiceWorkerCacheStorageIndex::Cache* index_cache = index.add_cache(); | 219 ServiceWorkerCacheStorageIndex::Cache* index_cache = index.add_cache(); |
| 92 index_cache->set_name(cache->name()); | 220 index_cache->set_name(cache->name()); |
| 93 index_cache->set_size(0); // TODO(jkarlin): Make this real. | 221 index_cache->set_size(0); // TODO(jkarlin): Make this real. |
| 94 } | 222 } |
| 95 | 223 |
| 96 std::string serialized; | 224 std::string serialized; |
| 97 bool success = index.SerializeToString(&serialized); | 225 bool success = index.SerializeToString(&serialized); |
| 98 DCHECK(success); | 226 DCHECK(success); |
| 99 | 227 |
| 100 base::FilePath tmp_path = origin_path_.AppendASCII("index.txt.tmp"); | 228 base::FilePath tmp_path = origin_path_.AppendASCII("index.txt.tmp"); |
| 101 base::FilePath index_path = origin_path_.AppendASCII("index.txt"); | 229 base::FilePath index_path = origin_path_.AppendASCII("index.txt"); |
| 102 | 230 |
| 103 int bytes_written = | 231 cache_task_runner_->PostTask( |
| 104 base::WriteFile(tmp_path, serialized.c_str(), serialized.size()); | 232 FROM_HERE, |
| 105 if (bytes_written != implicit_cast<int>(serialized.size())) { | 233 base::Bind(&SimpleCacheLoader::WriteIndexWriteToFileInPool, |
| 234 base::Unretained(this), // should be weak? | |
| 235 tmp_path, | |
| 236 index_path, | |
| 237 serialized, | |
| 238 caches, | |
| 239 callback, | |
| 240 base::MessageLoopProxy::current())); | |
| 241 } | |
| 242 | |
| 243 void WriteIndexWriteToFileInPool( | |
| 244 const base::FilePath& tmp_path, | |
| 245 const base::FilePath& index_path, | |
| 246 const std::string& data, | |
| 247 CacheMap* caches, | |
| 248 const BoolCallback& callback, | |
| 249 scoped_refptr<base::MessageLoopProxy> original_loop) { | |
| 250 int bytes_written = base::WriteFile(tmp_path, data.c_str(), data.size()); | |
| 251 if (bytes_written != implicit_cast<int>(data.size())) { | |
| 106 base::DeleteFile(tmp_path, /* recursive */ false); | 252 base::DeleteFile(tmp_path, /* recursive */ false); |
| 107 return false; | 253 original_loop->PostTask(FROM_HERE, base::Bind(callback, false)); |
| 108 } | 254 } |
| 109 | 255 |
| 110 // Atomically rename the temporary index file to become the real one. | 256 // Atomically rename the temporary index file to become the real one. |
| 111 return base::ReplaceFile(tmp_path, index_path, NULL); | 257 bool rv = base::ReplaceFile(tmp_path, index_path, NULL); |
| 258 original_loop->PostTask(FROM_HERE, base::Bind(callback, rv)); | |
| 112 } | 259 } |
| 113 | 260 |
| 114 virtual void LoadIndex(std::vector<std::string>* names) OVERRIDE { | 261 virtual void LoadIndex(scoped_ptr<std::vector<std::string> > names, |
| 262 const StringsCallback& callback) OVERRIDE { | |
| 263 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 264 | |
| 265 // 1. Read the file from disk. (LoadIndexReadFile) | |
| 266 // 2. Parse file and return the names of the caches (LoadIndexDidReadFile) | |
| 267 | |
| 115 base::FilePath index_path = origin_path_.AppendASCII("index.txt"); | 268 base::FilePath index_path = origin_path_.AppendASCII("index.txt"); |
| 116 | 269 |
| 117 std::string serialized; | 270 cache_task_runner_->PostTask( |
| 118 if (!base::ReadFileToString(index_path, &serialized)) | 271 FROM_HERE, |
| 119 return; | 272 base::Bind(&SimpleCacheLoader::LoadIndexReadFileInPool, |
| 273 base::Unretained(this), | |
| 274 index_path, | |
| 275 base::Passed(names.Pass()), | |
| 276 callback, | |
| 277 base::MessageLoopProxy::current())); | |
| 278 } | |
| 279 | |
| 280 void LoadIndexReadFileInPool( | |
| 281 const base::FilePath& index_path, | |
| 282 scoped_ptr<std::vector<std::string> > names, | |
| 283 const StringsCallback& callback, | |
| 284 scoped_refptr<base::MessageLoopProxy> original_loop) { | |
| 285 std::string body; | |
| 286 base::ReadFileToString(index_path, &body); | |
| 287 | |
| 288 original_loop->PostTask(FROM_HERE, | |
| 289 base::Bind(&SimpleCacheLoader::LoadIndexDidReadFile, | |
| 290 base::Unretained(this), | |
| 291 base::Passed(names.Pass()), | |
| 292 callback, | |
| 293 body)); | |
| 294 } | |
| 295 | |
| 296 void LoadIndexDidReadFile(scoped_ptr<std::vector<std::string> > names, | |
| 297 const StringsCallback& callback, | |
| 298 const std::string& serialized) { | |
| 299 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 120 | 300 |
| 121 ServiceWorkerCacheStorageIndex index; | 301 ServiceWorkerCacheStorageIndex index; |
| 122 index.ParseFromString(serialized); | 302 index.ParseFromString(serialized); |
| 123 | 303 |
| 124 for (int i = 0, max = index.cache_size(); i < max; ++i) { | 304 for (int i = 0, max = index.cache_size(); i < max; ++i) { |
| 125 const ServiceWorkerCacheStorageIndex::Cache& cache = index.cache(i); | 305 const ServiceWorkerCacheStorageIndex::Cache& cache = index.cache(i); |
| 126 names->push_back(cache.name()); | 306 names->push_back(cache.name()); |
| 127 } | 307 } |
| 128 | 308 |
| 129 // TODO(jkarlin): Delete caches that are in the directory and not returned | 309 // TODO(jkarlin): Delete caches that are in the directory and not returned |
| 130 // in LoadIndex. | 310 // in LoadIndex. |
| 131 return; | 311 callback.Run(names.Pass()); |
| 132 } | 312 } |
| 133 | 313 |
| 134 private: | 314 private: |
| 135 std::string HexedHash(const std::string& value) { | 315 std::string HexedHash(const std::string& value) { |
| 136 std::string value_hash = base::SHA1HashString(value); | 316 std::string value_hash = base::SHA1HashString(value); |
| 137 std::string valued_hexed_hash = base::StringToLowerASCII( | 317 std::string valued_hexed_hash = base::StringToLowerASCII( |
| 138 base::HexEncode(value_hash.c_str(), value_hash.length())); | 318 base::HexEncode(value_hash.c_str(), value_hash.length())); |
| 139 return valued_hexed_hash; | 319 return valued_hexed_hash; |
| 140 } | 320 } |
| 141 | 321 |
| 142 base::FilePath CreatePersistentCachePath(const base::FilePath& origin_path, | 322 base::FilePath CreatePersistentCachePath(const base::FilePath& origin_path, |
| 143 const std::string& cache_name) { | 323 const std::string& cache_name) { |
| 144 return origin_path.AppendASCII(HexedHash(cache_name)); | 324 return origin_path.AppendASCII(HexedHash(cache_name)); |
| 145 } | 325 } |
| 146 | 326 |
| 327 base::ThreadChecker thread_checker_; | |
| 147 const base::FilePath origin_path_; | 328 const base::FilePath origin_path_; |
| 148 }; | 329 }; |
| 149 | 330 |
| 150 ServiceWorkerCacheStorage::ServiceWorkerCacheStorage( | 331 ServiceWorkerCacheStorage::ServiceWorkerCacheStorage( |
| 151 const base::FilePath& path, | 332 const base::FilePath& path, |
| 152 bool memory_only, | 333 bool memory_only, |
| 153 const scoped_refptr<base::MessageLoopProxy>& callback_loop) | 334 base::SequencedTaskRunner* cache_task_runner) |
| 154 : initialized_(false), origin_path_(path), callback_loop_(callback_loop) { | 335 : initialized_(false), |
| 336 origin_path_(path), | |
| 337 cache_task_runner_(cache_task_runner) { | |
| 155 if (memory_only) | 338 if (memory_only) |
| 156 cache_loader_.reset(new MemoryLoader()); | 339 cache_loader_.reset(new MemoryLoader(cache_task_runner_)); |
| 157 else | 340 else |
| 158 cache_loader_.reset(new SimpleCacheLoader(origin_path_)); | 341 cache_loader_.reset( |
| 342 new SimpleCacheLoader(origin_path_, cache_task_runner_)); | |
| 159 } | 343 } |
| 160 | 344 |
| 161 ServiceWorkerCacheStorage::~ServiceWorkerCacheStorage() { | 345 ServiceWorkerCacheStorage::~ServiceWorkerCacheStorage() { |
| 162 } | 346 } |
| 163 | 347 |
| 164 void ServiceWorkerCacheStorage::CreateCache( | 348 void ServiceWorkerCacheStorage::CreateCache( |
| 165 const std::string& cache_name, | 349 const std::string& cache_name, |
| 166 const CacheAndErrorCallback& callback) { | 350 const CacheAndErrorCallback& callback) { |
| 167 LazyInit(); | 351 if (!initialized_) { |
| 352 LazyInit(base::Bind(&ServiceWorkerCacheStorage::CreateCache, | |
| 353 base::Unretained(this), | |
| 354 cache_name, | |
| 355 callback)); | |
| 356 return; | |
| 357 } | |
| 168 | 358 |
| 169 if (cache_name.empty()) { | 359 if (cache_name.empty()) { |
| 170 callback_loop_->PostTask( | 360 callback.Run(0, CACHE_STORAGE_ERROR_EMPTY_KEY); |
| 171 FROM_HERE, base::Bind(callback, 0, CACHE_STORAGE_ERROR_EMPTY_KEY)); | |
| 172 return; | 361 return; |
| 173 } | 362 } |
| 174 | 363 |
| 175 if (GetLoadedCache(cache_name)) { | 364 if (GetLoadedCache(cache_name)) { |
| 176 callback_loop_->PostTask( | 365 callback.Run(0, CACHE_STORAGE_ERROR_EXISTS); |
| 177 FROM_HERE, base::Bind(callback, 0, CACHE_STORAGE_ERROR_EXISTS)); | |
| 178 return; | 366 return; |
| 179 } | 367 } |
| 180 | 368 |
| 181 ServiceWorkerCache* cache = cache_loader_->CreateCache(cache_name); | 369 cache_loader_->CreateCache( |
| 182 | 370 cache_name, |
| 183 if (!cache) { | 371 base::Bind(&ServiceWorkerCacheStorage::CreateCacheDidCreateCache, |
| 184 callback_loop_->PostTask( | |
| 185 FROM_HERE, base::Bind(callback, 0, CACHE_STORAGE_ERROR_STORAGE)); | |
| 186 return; | |
| 187 } | |
| 188 | |
| 189 InitCache(cache); | |
| 190 | |
| 191 cache_loader_->WriteIndex(&cache_map_); | |
| 192 | |
| 193 cache->CreateBackend( | |
| 194 base::Bind(&ServiceWorkerCacheStorage::InitializeCacheCallback, | |
| 195 base::Unretained(this), | 372 base::Unretained(this), |
|
michaeln
2014/08/11 19:30:17
use of unretained here and in other callbacks can
jkarlin
2014/08/12 14:55:03
Done.
| |
| 196 cache, | 373 cache_name, |
| 197 callback)); | 374 callback)); |
| 198 } | 375 } |
| 199 | 376 |
| 200 void ServiceWorkerCacheStorage::GetCache( | 377 void ServiceWorkerCacheStorage::GetCache( |
| 201 const std::string& cache_name, | 378 const std::string& cache_name, |
| 202 const CacheAndErrorCallback& callback) { | 379 const CacheAndErrorCallback& callback) { |
| 203 LazyInit(); | 380 DCHECK(thread_checker_.CalledOnValidThread()); |
| 381 | |
| 382 if (!initialized_) { | |
| 383 LazyInit(base::Bind(&ServiceWorkerCacheStorage::GetCache, | |
| 384 base::Unretained(this), | |
| 385 cache_name, | |
| 386 callback)); | |
| 387 return; | |
| 388 } | |
| 204 | 389 |
| 205 if (cache_name.empty()) { | 390 if (cache_name.empty()) { |
| 206 callback_loop_->PostTask( | 391 callback.Run(0, CACHE_STORAGE_ERROR_EMPTY_KEY); |
| 207 FROM_HERE, base::Bind(callback, 0, CACHE_STORAGE_ERROR_EMPTY_KEY)); | |
| 208 return; | 392 return; |
| 209 } | 393 } |
| 210 | 394 |
| 211 ServiceWorkerCache* cache = GetLoadedCache(cache_name); | 395 ServiceWorkerCache* cache = GetLoadedCache(cache_name); |
| 212 if (!cache) { | 396 if (!cache) { |
| 213 callback_loop_->PostTask( | 397 callback.Run(0, CACHE_STORAGE_ERROR_NOT_FOUND); |
| 214 FROM_HERE, base::Bind(callback, 0, CACHE_STORAGE_ERROR_NOT_FOUND)); | |
| 215 return; | 398 return; |
| 216 } | 399 } |
| 217 | 400 |
| 218 cache->CreateBackend( | 401 cache->CreateBackend(base::Bind(&ServiceWorkerCacheStorage::DidCreateBackend, |
| 219 base::Bind(&ServiceWorkerCacheStorage::InitializeCacheCallback, | 402 base::Unretained(this), |
| 220 base::Unretained(this), | 403 cache, |
| 221 cache, | 404 callback)); |
| 222 callback)); | |
| 223 } | 405 } |
| 224 | 406 |
| 225 void ServiceWorkerCacheStorage::HasCache(const std::string& cache_name, | 407 void ServiceWorkerCacheStorage::HasCache(const std::string& cache_name, |
| 226 const BoolAndErrorCallback& callback) { | 408 const BoolAndErrorCallback& callback) { |
| 227 LazyInit(); | 409 DCHECK(thread_checker_.CalledOnValidThread()); |
| 410 | |
| 411 if (!initialized_) { | |
| 412 LazyInit(base::Bind(&ServiceWorkerCacheStorage::HasCache, | |
| 413 base::Unretained(this), | |
| 414 cache_name, | |
| 415 callback)); | |
| 416 return; | |
| 417 } | |
| 228 | 418 |
| 229 if (cache_name.empty()) { | 419 if (cache_name.empty()) { |
| 230 callback_loop_->PostTask( | 420 callback.Run(false, CACHE_STORAGE_ERROR_EMPTY_KEY); |
| 231 FROM_HERE, base::Bind(callback, false, CACHE_STORAGE_ERROR_EMPTY_KEY)); | |
| 232 return; | 421 return; |
| 233 } | 422 } |
| 234 | 423 |
| 235 bool has_cache = GetLoadedCache(cache_name) != NULL; | 424 bool has_cache = GetLoadedCache(cache_name) != NULL; |
| 236 | 425 |
| 237 callback_loop_->PostTask( | 426 callback.Run(has_cache, CACHE_STORAGE_ERROR_NO_ERROR); |
| 238 FROM_HERE, | |
| 239 base::Bind( | |
| 240 callback, has_cache, CACHE_STORAGE_ERROR_NO_ERROR)); | |
| 241 } | 427 } |
| 242 | 428 |
| 243 void ServiceWorkerCacheStorage::DeleteCache( | 429 void ServiceWorkerCacheStorage::DeleteCache( |
| 244 const std::string& cache_name, | 430 const std::string& cache_name, |
| 245 const BoolAndErrorCallback& callback) { | 431 const BoolAndErrorCallback& callback) { |
| 246 LazyInit(); | 432 DCHECK(thread_checker_.CalledOnValidThread()); |
| 433 | |
| 434 if (!initialized_) { | |
| 435 LazyInit(base::Bind(&ServiceWorkerCacheStorage::DeleteCache, | |
| 436 base::Unretained(this), | |
| 437 cache_name, | |
| 438 callback)); | |
| 439 return; | |
| 440 } | |
| 247 | 441 |
| 248 if (cache_name.empty()) { | 442 if (cache_name.empty()) { |
| 249 callback_loop_->PostTask( | 443 callback.Run(false, CACHE_STORAGE_ERROR_EMPTY_KEY); |
| 250 FROM_HERE, base::Bind(callback, false, CACHE_STORAGE_ERROR_EMPTY_KEY)); | |
| 251 return; | 444 return; |
| 252 } | 445 } |
| 253 | 446 |
| 254 ServiceWorkerCache* cache = GetLoadedCache(cache_name); | 447 ServiceWorkerCache* cache = GetLoadedCache(cache_name); |
| 255 if (!cache) { | 448 if (!cache) { |
| 256 callback_loop_->PostTask( | 449 callback.Run(false, CACHE_STORAGE_ERROR_NOT_FOUND); |
| 257 FROM_HERE, base::Bind(callback, false, CACHE_STORAGE_ERROR_NOT_FOUND)); | |
| 258 return; | 450 return; |
| 259 } | 451 } |
| 260 | 452 |
| 261 name_map_.erase(cache_name); | 453 name_map_.erase(cache_name); |
| 262 cache_map_.Remove(cache->id()); // deletes cache | 454 cache_map_.Remove(cache->id()); // deletes cache |
| 263 | 455 |
| 264 cache_loader_->WriteIndex(&cache_map_); // Update the index. | 456 // Update the Index |
| 265 | 457 cache_loader_->WriteIndex( |
| 266 cache_loader_->CleanUpDeletedCache(cache_name); | 458 &cache_map_, |
| 267 | 459 base::Bind(&ServiceWorkerCacheStorage::DeleteCacheDidWriteIndex, |
| 268 callback_loop_->PostTask( | 460 base::Unretained(this), |
| 269 FROM_HERE, base::Bind(callback, true, CACHE_STORAGE_ERROR_NO_ERROR)); | 461 cache_name, |
| 462 callback)); | |
| 270 } | 463 } |
| 271 | 464 |
| 272 void ServiceWorkerCacheStorage::EnumerateCaches( | 465 void ServiceWorkerCacheStorage::EnumerateCaches( |
| 273 const StringsAndErrorCallback& callback) { | 466 const StringsAndErrorCallback& callback) { |
| 274 LazyInit(); | 467 DCHECK(thread_checker_.CalledOnValidThread()); |
| 468 | |
| 469 if (!initialized_) { | |
| 470 LazyInit(base::Bind(&ServiceWorkerCacheStorage::EnumerateCaches, | |
| 471 base::Unretained(this), | |
| 472 callback)); | |
| 473 return; | |
| 474 } | |
| 275 | 475 |
| 276 std::vector<std::string> names; | 476 std::vector<std::string> names; |
| 277 for (NameMap::const_iterator it = name_map_.begin(); it != name_map_.end(); | 477 for (NameMap::const_iterator it = name_map_.begin(); it != name_map_.end(); |
| 278 ++it) { | 478 ++it) { |
| 279 names.push_back(it->first); | 479 names.push_back(it->first); |
| 280 } | 480 } |
| 281 | 481 |
| 282 callback_loop_->PostTask( | 482 callback.Run(names, CACHE_STORAGE_ERROR_NO_ERROR); |
| 283 FROM_HERE, base::Bind(callback, names, CACHE_STORAGE_ERROR_NO_ERROR)); | |
| 284 } | 483 } |
| 285 | 484 |
| 286 void ServiceWorkerCacheStorage::InitializeCacheCallback( | 485 void ServiceWorkerCacheStorage::DidCreateBackend( |
| 287 const ServiceWorkerCache* cache, | 486 const ServiceWorkerCache* cache, |
| 288 const CacheAndErrorCallback& callback, | 487 const CacheAndErrorCallback& callback, |
| 289 bool success) { | 488 bool success) { |
| 489 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 490 | |
| 290 if (!success) { | 491 if (!success) { |
| 291 // TODO(jkarlin): This should delete the directory and try again in case | 492 // TODO(jkarlin): This should delete the directory and try again in case |
| 292 // the cache is simply corrupt. | 493 // the cache is simply corrupt. |
| 293 callback_loop_->PostTask( | 494 callback.Run(0, CACHE_STORAGE_ERROR_STORAGE); |
| 294 FROM_HERE, base::Bind(callback, 0, CACHE_STORAGE_ERROR_STORAGE)); | |
| 295 return; | 495 return; |
| 296 } | 496 } |
| 297 callback_loop_->PostTask( | 497 callback.Run(cache->id(), CACHE_STORAGE_ERROR_NO_ERROR); |
| 298 FROM_HERE, | |
| 299 base::Bind(callback, cache->id(), CACHE_STORAGE_ERROR_NO_ERROR)); | |
| 300 } | 498 } |
| 301 | 499 |
| 302 // Init is run lazily so that it is called on the proper MessageLoop. | 500 // Init is run lazily so that it is called on the proper MessageLoop. |
| 303 void ServiceWorkerCacheStorage::LazyInit() { | 501 void ServiceWorkerCacheStorage::LazyInit(const base::Closure& callback) { |
| 304 if (initialized_) | 502 DCHECK(thread_checker_.CalledOnValidThread()); |
| 503 DCHECK(!initialized_); | |
| 504 | |
| 505 init_callbacks_.push_back(callback); | |
| 506 | |
| 507 // If this isn't the first call to LazyInit then return as the initialization | |
| 508 // has already started. | |
| 509 if (init_callbacks_.size() > 1u) | |
| 305 return; | 510 return; |
| 306 | 511 |
| 307 std::vector<std::string> indexed_cache_names; | 512 // 1. Get the list of cache names (async call) |
| 308 cache_loader_->LoadIndex(&indexed_cache_names); | 513 // 2. For each cache name, load the cache (async call) |
| 514 // 3. Once each load is complete, update the map variables. | |
| 515 // 4. Call the list of waiting callbacks. | |
| 309 | 516 |
| 310 for (std::vector<std::string>::const_iterator it = | 517 scoped_ptr<std::vector<std::string> > indexed_cache_names( |
| 311 indexed_cache_names.begin(); | 518 new std::vector<std::string>()); |
| 312 it != indexed_cache_names.end(); | 519 |
| 313 ++it) { | 520 cache_loader_->LoadIndex( |
| 314 ServiceWorkerCache* cache = cache_loader_->LoadCache(*it); | 521 indexed_cache_names.Pass(), |
| 315 InitCache(cache); | 522 base::Bind(&ServiceWorkerCacheStorage::LazyInitDidLoadIndex, |
| 316 } | 523 base::Unretained(this), |
| 317 initialized_ = true; | 524 callback)); |
| 318 } | 525 } |
| 319 | 526 |
| 320 void ServiceWorkerCacheStorage::InitCache(ServiceWorkerCache* cache) { | 527 void ServiceWorkerCacheStorage::LazyInitDidLoadIndex( |
| 528 const base::Closure& callback, | |
| 529 scoped_ptr<std::vector<std::string> > indexed_cache_names) { | |
| 530 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 531 | |
| 532 if (indexed_cache_names->empty()) { | |
| 533 LazyInitDone(); | |
| 534 return; | |
| 535 } | |
| 536 | |
| 537 std::vector<std::string>::const_iterator iter = indexed_cache_names->begin(); | |
| 538 std::vector<std::string>::const_iterator iter_next = iter + 1; | |
| 539 | |
| 540 cache_loader_->LoadCache( | |
| 541 *iter, | |
| 542 base::Bind(&ServiceWorkerCacheStorage::LazyInitIterateAndLoadCacheName, | |
| 543 base::Unretained(this), | |
| 544 callback, | |
| 545 base::Passed(indexed_cache_names.Pass()), | |
| 546 iter_next)); | |
| 547 } | |
| 548 | |
| 549 void ServiceWorkerCacheStorage::LazyInitIterateAndLoadCacheName( | |
| 550 const base::Closure& callback, | |
| 551 scoped_ptr<std::vector<std::string> > indexed_cache_names, | |
| 552 std::vector<std::string>::const_iterator iter, | |
| 553 ServiceWorkerCache* cache) { | |
| 554 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 555 | |
| 556 if (cache) | |
| 557 AddCacheToMaps(cache); | |
| 558 | |
| 559 if (iter == indexed_cache_names->end()) { | |
| 560 LazyInitDone(); | |
| 561 return; | |
| 562 } | |
| 563 | |
| 564 std::vector<std::string>::const_iterator iter_next = iter + 1; | |
| 565 cache_loader_->LoadCache( | |
| 566 *iter, | |
| 567 base::Bind(&ServiceWorkerCacheStorage::LazyInitIterateAndLoadCacheName, | |
| 568 base::Unretained(this), | |
| 569 callback, | |
| 570 base::Passed(indexed_cache_names.Pass()), | |
| 571 iter_next)); | |
| 572 } | |
| 573 | |
| 574 void ServiceWorkerCacheStorage::LazyInitDone() { | |
| 575 initialized_ = true; | |
| 576 for (std::vector<base::Closure>::iterator it = init_callbacks_.begin(); | |
| 577 it != init_callbacks_.end(); | |
| 578 ++it) { | |
| 579 it->Run(); | |
| 580 } | |
| 581 init_callbacks_.clear(); | |
| 582 } | |
| 583 | |
| 584 void ServiceWorkerCacheStorage::AddCacheToMaps(ServiceWorkerCache* cache) { | |
| 585 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 586 | |
| 321 CacheID id = cache_map_.Add(cache); | 587 CacheID id = cache_map_.Add(cache); |
| 322 name_map_.insert(std::make_pair(cache->name(), id)); | 588 name_map_.insert(std::make_pair(cache->name(), id)); |
| 323 cache->set_id(id); | 589 cache->set_id(id); |
| 324 } | 590 } |
| 325 | 591 |
| 592 void ServiceWorkerCacheStorage::CreateCacheDidCreateCache( | |
| 593 const std::string& cache_name, | |
| 594 const CacheAndErrorCallback& callback, | |
| 595 ServiceWorkerCache* cache) { | |
| 596 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 597 | |
| 598 if (!cache) { | |
| 599 callback.Run(0, CACHE_STORAGE_ERROR_STORAGE); | |
| 600 return; | |
| 601 } | |
| 602 | |
| 603 AddCacheToMaps(cache); | |
| 604 | |
| 605 cache_loader_->WriteIndex( | |
| 606 &cache_map_, | |
| 607 base::Bind(&ServiceWorkerCacheStorage::CreateCacheDidWriteIndex, | |
| 608 base::Unretained(this), | |
| 609 callback, | |
| 610 base::Unretained(cache))); | |
| 611 } | |
| 612 | |
| 613 void ServiceWorkerCacheStorage::CreateCacheDidWriteIndex( | |
| 614 const CacheAndErrorCallback& callback, | |
| 615 ServiceWorkerCache* cache, | |
| 616 bool success) { | |
| 617 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 618 cache->CreateBackend(base::Bind(&ServiceWorkerCacheStorage::DidCreateBackend, | |
| 619 base::Unretained(this), | |
| 620 cache, | |
| 621 callback)); | |
| 622 } | |
| 623 | |
| 624 void ServiceWorkerCacheStorage::DeleteCacheDidWriteIndex( | |
| 625 const std::string& cache_name, | |
| 626 const BoolAndErrorCallback& callback, | |
| 627 bool success) { | |
| 628 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 629 | |
| 630 cache_loader_->CleanUpDeletedCache( | |
| 631 cache_name, | |
| 632 base::Bind(&ServiceWorkerCacheStorage::DeleteCacheDidCleanUp, | |
| 633 base::Unretained(this), | |
| 634 callback)); | |
| 635 } | |
| 636 | |
| 637 void ServiceWorkerCacheStorage::DeleteCacheDidCleanUp( | |
| 638 const BoolAndErrorCallback& callback, | |
| 639 bool success) { | |
| 640 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 641 | |
| 642 callback.Run(true, CACHE_STORAGE_ERROR_NO_ERROR); | |
| 643 } | |
| 644 | |
| 326 ServiceWorkerCache* ServiceWorkerCacheStorage::GetLoadedCache( | 645 ServiceWorkerCache* ServiceWorkerCacheStorage::GetLoadedCache( |
| 327 const std::string& cache_name) const { | 646 const std::string& cache_name) const { |
| 647 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 328 DCHECK(initialized_); | 648 DCHECK(initialized_); |
| 329 | 649 |
| 330 NameMap::const_iterator it = name_map_.find(cache_name); | 650 NameMap::const_iterator it = name_map_.find(cache_name); |
| 331 if (it == name_map_.end()) | 651 if (it == name_map_.end()) |
| 332 return NULL; | 652 return NULL; |
| 333 | 653 |
| 334 ServiceWorkerCache* cache = cache_map_.Lookup(it->second); | 654 ServiceWorkerCache* cache = cache_map_.Lookup(it->second); |
| 335 DCHECK(cache); | 655 DCHECK(cache); |
| 336 return cache; | 656 return cache; |
| 337 } | 657 } |
| 338 | 658 |
| 339 } // namespace content | 659 } // namespace content |
| OLD | NEW |