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