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_fetch_stores.h" | 5 #include "content/browser/service_worker/service_worker_fetch_stores.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/file_util.h" | |
| 10 #include "base/strings/string_number_conversions.h" | |
| 11 #include "base/strings/string_util.h" | |
| 12 #include "content/browser/service_worker/service_worker_fetch_store.h" | |
| 9 #include "content/public/browser/browser_thread.h" | 13 #include "content/public/browser/browser_thread.h" |
| 14 #include "net/base/directory_lister.h" | |
| 10 | 15 |
| 11 namespace content { | 16 namespace content { |
| 12 | 17 |
| 18 // Handles the loading of ServiceWorkerFetchStore and any extra clean up other | |
| 19 // than deleting the ServiceWorkerFetchStore object. | |
| 20 class ServiceWorkerFetchStores::StoresLoader { | |
| 21 public: | |
| 22 virtual ~StoresLoader() {}; | |
| 23 virtual ServiceWorkerFetchStore* CreateStore(const std::string& key) = 0; | |
| 24 virtual bool CleanUpDeletedStore(const std::string& key) = 0; | |
| 25 virtual void LoadPersistentStores( | |
| 26 std::vector<content::ServiceWorkerFetchStore*>* stores) = 0; | |
| 27 }; | |
| 28 | |
| 29 class ServiceWorkerFetchStores::MemoryLoader | |
| 30 : public ServiceWorkerFetchStores::StoresLoader { | |
| 31 public: | |
| 32 virtual content::ServiceWorkerFetchStore* CreateStore( | |
| 33 const std::string& key) OVERRIDE { | |
| 34 return ServiceWorkerFetchStore::CreateMemoryStore(key); | |
| 35 } | |
| 36 | |
| 37 virtual bool CleanUpDeletedStore(const std::string& key) OVERRIDE { | |
| 38 return true; | |
| 39 } | |
| 40 | |
| 41 virtual void LoadPersistentStores( | |
| 42 std::vector<ServiceWorkerFetchStore*>* stores) OVERRIDE { | |
| 43 return; | |
| 44 } | |
| 45 }; | |
| 46 | |
| 47 class ServiceWorkerFetchStores::SimpleCacheLoader | |
| 48 : public ServiceWorkerFetchStores::StoresLoader { | |
| 49 public: | |
| 50 explicit SimpleCacheLoader(const base::FilePath& origin_path) | |
| 51 : origin_path_(origin_path) {} | |
| 52 | |
| 53 virtual ServiceWorkerFetchStore* CreateStore( | |
| 54 const std::string& key) OVERRIDE { | |
| 55 base::CreateDirectory(CreatePersistentStorePath(origin_path_, key)); | |
| 56 return ServiceWorkerFetchStore::CreatePersistentStore( | |
| 57 CreatePersistentStorePath(origin_path_, key), key); | |
| 58 } | |
| 59 | |
| 60 virtual bool CleanUpDeletedStore(const std::string& key) OVERRIDE { | |
| 61 return base::DeleteFile(CreatePersistentStorePath(origin_path_, key), true); | |
| 62 } | |
| 63 | |
| 64 virtual void LoadPersistentStores( | |
| 65 std::vector<ServiceWorkerFetchStore*>* stores) OVERRIDE { | |
| 66 base::FileEnumerator files( | |
| 67 origin_path_, false, base::FileEnumerator::DIRECTORIES); | |
| 68 for (base::FilePath path = files.Next(); !path.empty(); | |
| 69 path = files.Next()) { | |
| 70 std::vector<uint8> bytes; | |
| 71 base::HexStringToBytes(path.BaseName().MaybeAsASCII(), &bytes); | |
| 72 std::string name(bytes.begin(), bytes.end()); | |
| 73 | |
| 74 stores->push_back( | |
| 75 ServiceWorkerFetchStore::CreatePersistentStore(path, name)); | |
|
michaeln
2014/08/05 23:34:30
This assumes that directories in here are all legi
jkarlin
2014/08/06 18:56:00
I'm not aware of a definition of legitimate store
| |
| 76 } | |
| 77 return; | |
| 78 } | |
| 79 | |
| 80 private: | |
| 81 base::FilePath CreatePersistentStorePath(const base::FilePath& origin_path, | |
| 82 const std::string& store_name) { | |
| 83 // Hexlify the store name for encoding and sanitization purposes. | |
| 84 std::string hex = StringToLowerASCII( | |
| 85 base::HexEncode(store_name.c_str(), store_name.length())); | |
|
michaeln
2014/08/05 23:34:30
I'm not sure that having the length of store_name
jkarlin
2014/08/06 18:56:00
Yes, the plan was to patch that up after MVP but h
| |
| 86 return origin_path.AppendASCII(hex); | |
| 87 } | |
| 88 | |
| 89 const base::FilePath origin_path_; | |
| 90 }; | |
| 91 | |
| 13 ServiceWorkerFetchStores::ServiceWorkerFetchStores( | 92 ServiceWorkerFetchStores::ServiceWorkerFetchStores( |
| 14 const base::FilePath& path, | 93 const base::FilePath& path, |
| 15 BackendType backend_type, | 94 bool memory_only, |
| 16 const scoped_refptr<base::MessageLoopProxy>& callback_loop) | 95 const scoped_refptr<base::MessageLoopProxy>& callback_loop) |
| 17 : origin_path_(path), | 96 : initialized_(false), origin_path_(path), callback_loop_(callback_loop) { |
| 18 backend_type_(backend_type), | 97 if (memory_only) |
| 19 callback_loop_(callback_loop) { | 98 stores_loader_.reset(new MemoryLoader()); |
| 99 else | |
| 100 stores_loader_.reset(new SimpleCacheLoader(origin_path_)); | |
| 20 } | 101 } |
| 21 | 102 |
| 22 ServiceWorkerFetchStores::~ServiceWorkerFetchStores() { | 103 ServiceWorkerFetchStores::~ServiceWorkerFetchStores() { |
| 23 } | 104 } |
| 24 | 105 |
| 25 void ServiceWorkerFetchStores::CreateStore( | 106 void ServiceWorkerFetchStores::CreateStore( |
| 26 const std::string& key, | 107 const std::string& key, |
| 27 const StoreAndErrorCallback& callback) { | 108 const StoreAndErrorCallback& callback) { |
| 28 // TODO(jkarlin): Implement this. | 109 LazyInit(); |
| 29 | 110 |
| 30 callback_loop_->PostTask(FROM_HERE, | 111 if (key.empty()) { |
| 31 base::Bind(callback, 0, FETCH_STORES_ERROR_EXISTS)); | 112 callback_loop_->PostTask( |
| 32 return; | 113 FROM_HERE, base::Bind(callback, 0, FETCH_STORES_ERROR_EMPTY_KEY)); |
| 114 return; | |
| 115 } | |
| 116 | |
| 117 if (GetLoadedStore(key)) { | |
| 118 callback_loop_->PostTask( | |
| 119 FROM_HERE, base::Bind(callback, 0, FETCH_STORES_ERROR_EXISTS)); | |
| 120 return; | |
| 121 } | |
| 122 | |
| 123 ServiceWorkerFetchStore* store = stores_loader_->CreateStore(key); | |
| 124 | |
| 125 if (!store) { | |
| 126 callback_loop_->PostTask( | |
| 127 FROM_HERE, base::Bind(callback, 0, FETCH_STORES_ERROR_STORAGE)); | |
| 128 return; | |
| 129 } | |
| 130 | |
| 131 InitStore(store); | |
| 132 | |
| 133 callback_loop_->PostTask( | |
| 134 FROM_HERE, | |
| 135 base::Bind(callback, store->id(), FETCH_STORES_ERROR_NO_ERROR)); | |
| 33 } | 136 } |
| 34 | 137 |
| 35 void ServiceWorkerFetchStores::Get(const std::string& key, | 138 void ServiceWorkerFetchStores::Get(const std::string& key, |
| 36 const StoreAndErrorCallback& callback) { | 139 const StoreAndErrorCallback& callback) { |
| 37 // TODO(jkarlin): Implement this. | 140 LazyInit(); |
| 38 | 141 |
| 39 callback_loop_->PostTask(FROM_HERE, | 142 if (key.empty()) { |
| 40 base::Bind(callback, 0, FETCH_STORES_ERROR_EXISTS)); | 143 callback_loop_->PostTask( |
| 41 return; | 144 FROM_HERE, base::Bind(callback, 0, FETCH_STORES_ERROR_EMPTY_KEY)); |
| 145 return; | |
| 146 } | |
| 147 | |
| 148 ServiceWorkerFetchStore* store = GetLoadedStore(key); | |
| 149 if (!store) { | |
| 150 callback_loop_->PostTask( | |
| 151 FROM_HERE, base::Bind(callback, 0, FETCH_STORES_ERROR_NOT_FOUND)); | |
| 152 return; | |
| 153 } | |
| 154 callback_loop_->PostTask( | |
| 155 FROM_HERE, | |
| 156 base::Bind(callback, store->id(), FETCH_STORES_ERROR_NO_ERROR)); | |
| 42 } | 157 } |
| 43 | 158 |
| 44 void ServiceWorkerFetchStores::Has(const std::string& key, | 159 void ServiceWorkerFetchStores::Has(const std::string& key, |
| 45 const BoolAndErrorCallback& callback) const { | 160 const BoolAndErrorCallback& callback) { |
| 46 // TODO(jkarlin): Implement this. | 161 LazyInit(); |
| 162 | |
| 163 if (key.empty()) { | |
| 164 callback_loop_->PostTask( | |
| 165 FROM_HERE, base::Bind(callback, 0, FETCH_STORES_ERROR_EMPTY_KEY)); | |
| 166 return; | |
| 167 } | |
| 47 | 168 |
| 48 callback_loop_->PostTask( | 169 callback_loop_->PostTask( |
| 49 FROM_HERE, base::Bind(callback, false, FETCH_STORES_ERROR_EXISTS)); | 170 FROM_HERE, |
| 50 return; | 171 base::Bind(callback, GetLoadedStore(key), FETCH_STORES_ERROR_NO_ERROR)); |
| 51 } | 172 } |
| 52 | 173 |
| 53 void ServiceWorkerFetchStores::Delete(const std::string& key, | 174 void ServiceWorkerFetchStores::Delete(const std::string& key, |
| 54 const StoreAndErrorCallback& callback) { | 175 const BoolAndErrorCallback& callback) { |
| 55 // TODO(jkarlin): Implement this. | 176 LazyInit(); |
| 56 | 177 |
| 57 callback_loop_->PostTask(FROM_HERE, | 178 if (key.empty()) { |
| 58 base::Bind(callback, 0, FETCH_STORES_ERROR_EXISTS)); | 179 callback_loop_->PostTask( |
| 59 return; | 180 FROM_HERE, base::Bind(callback, false, FETCH_STORES_ERROR_EMPTY_KEY)); |
| 181 return; | |
| 182 } | |
| 183 | |
| 184 ServiceWorkerFetchStore* store = GetLoadedStore(key); | |
| 185 if (!store) { | |
| 186 callback_loop_->PostTask( | |
| 187 FROM_HERE, base::Bind(callback, false, FETCH_STORES_ERROR_NOT_FOUND)); | |
| 188 return; | |
| 189 } | |
| 190 | |
| 191 loaded_store_names_.erase(key); | |
| 192 loaded_store_ids_.Remove(store->id()); // deletes store | |
| 193 | |
| 194 stores_loader_->CleanUpDeletedStore(key); | |
| 195 | |
| 196 callback_loop_->PostTask( | |
| 197 FROM_HERE, base::Bind(callback, true, FETCH_STORES_ERROR_NO_ERROR)); | |
| 60 } | 198 } |
| 61 | 199 |
| 62 void ServiceWorkerFetchStores::Keys( | 200 void ServiceWorkerFetchStores::Keys(const StringsAndErrorCallback& callback) { |
| 63 const StringsAndErrorCallback& callback) const { | 201 LazyInit(); |
| 64 // TODO(jkarlin): Implement this. | 202 |
| 65 std::vector<std::string> out; | 203 std::vector<std::string> names; |
| 204 for (NameMap::const_iterator it = loaded_store_names_.begin(); | |
| 205 it != loaded_store_names_.end(); | |
| 206 ++it) { | |
| 207 names.push_back(it->first); | |
| 208 } | |
| 209 | |
| 66 callback_loop_->PostTask( | 210 callback_loop_->PostTask( |
| 67 FROM_HERE, base::Bind(callback, out, FETCH_STORES_ERROR_EXISTS)); | 211 FROM_HERE, base::Bind(callback, names, FETCH_STORES_ERROR_NO_ERROR)); |
| 68 return; | 212 } |
| 213 | |
| 214 void ServiceWorkerFetchStores::LazyInit() { | |
| 215 if (initialized_) | |
| 216 return; | |
| 217 | |
| 218 // Load up all of the existing caches. | |
| 219 std::vector<ServiceWorkerFetchStore*> stores; | |
| 220 stores_loader_->LoadPersistentStores(&stores); | |
| 221 | |
| 222 for (size_t i = 0, size = stores.size(); i < size; ++i) | |
| 223 InitStore(stores[i]); | |
| 224 | |
| 225 initialized_ = true; | |
| 226 } | |
| 227 | |
| 228 void ServiceWorkerFetchStores::InitStore(ServiceWorkerFetchStore* store) { | |
| 229 StoreID id = loaded_store_ids_.Add(store); | |
| 230 loaded_store_names_.insert(std::make_pair(store->name(), id)); | |
| 231 store->set_id(id); | |
|
michaeln
2014/08/05 23:34:30
What is the purpose if the store id and having two
jkarlin
2014/08/06 18:55:59
Yep yep.
| |
| 232 } | |
| 233 | |
| 234 ServiceWorkerFetchStore* ServiceWorkerFetchStores::GetLoadedStore( | |
| 235 const std::string& key) const { | |
| 236 DCHECK(initialized_); | |
| 237 NameMap::const_iterator it = loaded_store_names_.find(key); | |
| 238 if (it == loaded_store_names_.end()) | |
| 239 return NULL; | |
| 240 | |
| 241 ServiceWorkerFetchStore* store = loaded_store_ids_.Lookup(it->second); | |
| 242 DCHECK(store); | |
| 243 return store; | |
| 69 } | 244 } |
| 70 | 245 |
| 71 } // namespace content | 246 } // namespace content |
| OLD | NEW |