Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "chrome/browser/extensions/api/storage/storage_api.h" | 5 #include "chrome/browser/extensions/api/storage/storage_api.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| 11 #include "base/strings/stringprintf.h" | 11 #include "base/strings/stringprintf.h" |
| 12 #include "base/values.h" | 12 #include "base/values.h" |
| 13 #include "chrome/browser/extensions/api/storage/settings_frontend.h" | 13 #include "chrome/browser/extensions/api/storage/settings_frontend.h" |
| 14 #include "chrome/browser/extensions/extension_service.h" | 14 #include "chrome/browser/extensions/extension_service.h" |
| 15 #include "chrome/browser/profiles/profile.h" | 15 #include "chrome/browser/profiles/profile.h" |
| 16 #include "chrome/common/extensions/api/storage.h" | 16 #include "chrome/common/extensions/api/storage.h" |
| 17 #include "content/public/browser/browser_thread.h" | 17 #include "content/public/browser/browser_thread.h" |
| 18 #include "extensions/browser/quota_service.h" | 18 #include "extensions/browser/quota_service.h" |
| 19 | 19 |
| 20 namespace extensions { | 20 namespace extensions { |
| 21 | 21 |
| 22 using content::BrowserThread; | 22 using content::BrowserThread; |
| 23 | 23 |
| 24 // SettingsFunction | 24 // SettingsFunction |
| 25 | 25 |
| 26 SettingsFunction::SettingsFunction() | 26 SettingsFunction::SettingsFunction() |
| 27 : settings_namespace_(settings_namespace::INVALID) {} | 27 : settings_namespace_(settings_namespace::INVALID), |
| 28 tried_restoring_storage_(false) {} | |
|
Devlin
2014/02/25 19:39:36
So, after more debugging than I'd like to admit, I
not at google - send to devlin
2014/02/25 20:39:20
Heh been there :)
| |
| 28 | 29 |
| 29 SettingsFunction::~SettingsFunction() {} | 30 SettingsFunction::~SettingsFunction() {} |
| 30 | 31 |
| 31 bool SettingsFunction::ShouldSkipQuotaLimiting() const { | 32 bool SettingsFunction::ShouldSkipQuotaLimiting() const { |
| 32 // Only apply quota if this is for sync storage. | 33 // Only apply quota if this is for sync storage. |
| 33 std::string settings_namespace_string; | 34 std::string settings_namespace_string; |
| 34 if (!args_->GetString(0, &settings_namespace_string)) { | 35 if (!args_->GetString(0, &settings_namespace_string)) { |
| 35 // This should be EXTENSION_FUNCTION_VALIDATE(false) but there is no way | 36 // This should be EXTENSION_FUNCTION_VALIDATE(false) but there is no way |
| 36 // to signify that from this function. It will be caught in RunImpl(). | 37 // to signify that from this function. It will be caught in RunImpl(). |
| 37 return false; | 38 return false; |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 66 } | 67 } |
| 67 | 68 |
| 68 void SettingsFunction::AsyncRunWithStorage(ValueStore* storage) { | 69 void SettingsFunction::AsyncRunWithStorage(ValueStore* storage) { |
| 69 bool success = RunWithStorage(storage); | 70 bool success = RunWithStorage(storage); |
| 70 BrowserThread::PostTask( | 71 BrowserThread::PostTask( |
| 71 BrowserThread::UI, | 72 BrowserThread::UI, |
| 72 FROM_HERE, | 73 FROM_HERE, |
| 73 base::Bind(&SettingsFunction::SendResponse, this, success)); | 74 base::Bind(&SettingsFunction::SendResponse, this, success)); |
| 74 } | 75 } |
| 75 | 76 |
| 76 bool SettingsFunction::UseReadResult(ValueStore::ReadResult read_result) { | 77 bool SettingsFunction::UseReadResult(ValueStore::ReadResult result, |
| 77 if (read_result->HasError()) { | 78 ValueStore* storage) { |
| 78 error_ = read_result->error().message; | 79 if (result->HasError()) |
| 79 return false; | 80 return HandleError(result->error(), storage); |
| 80 } | |
| 81 | 81 |
| 82 base::DictionaryValue* result = new base::DictionaryValue(); | 82 base::DictionaryValue* dict = new base::DictionaryValue(); |
| 83 result->Swap(&read_result->settings()); | 83 dict->Swap(&result->settings()); |
| 84 SetResult(result); | 84 SetResult(dict); |
| 85 return true; | 85 return true; |
| 86 } | 86 } |
| 87 | 87 |
| 88 bool SettingsFunction::UseWriteResult(ValueStore::WriteResult result) { | 88 bool SettingsFunction::UseWriteResult(ValueStore::WriteResult result, |
| 89 if (result->HasError()) { | 89 ValueStore* storage) { |
| 90 error_ = result->error().message; | 90 if (result->HasError()) |
| 91 return false; | 91 return HandleError(result->error(), storage); |
| 92 } | |
| 93 | 92 |
| 94 if (!result->changes().empty()) { | 93 if (!result->changes().empty()) { |
| 95 observers_->Notify( | 94 observers_->Notify( |
| 96 &SettingsObserver::OnSettingsChanged, | 95 &SettingsObserver::OnSettingsChanged, |
| 97 extension_id(), | 96 extension_id(), |
| 98 settings_namespace_, | 97 settings_namespace_, |
| 99 ValueStoreChange::ToJson(result->changes())); | 98 ValueStoreChange::ToJson(result->changes())); |
| 100 } | 99 } |
| 101 | 100 |
| 102 return true; | 101 return true; |
| 103 } | 102 } |
| 104 | 103 |
| 104 bool SettingsFunction::HandleError(const ValueStore::Error& error, | |
| 105 ValueStore* storage) { | |
| 106 // If the method failed due to corruption, and we haven't tried to fix it, we | |
| 107 // can try to restore the storage and re-run it. Otherwise, the method has | |
| 108 // failed. | |
| 109 if (error.code == ValueStore::CORRUPTION && !tried_restoring_storage_) { | |
| 110 tried_restoring_storage_ = true; | |
| 111 | |
| 112 // If the corruption is on a particular key, try to restore that key and | |
| 113 // re-run. | |
| 114 if (error.key.get() && storage->RestoreKey(*error.key)) | |
| 115 return RunWithStorage(storage); | |
| 116 | |
| 117 // If the full database is corrupted, try to restore the whole thing and | |
| 118 // re-run. | |
| 119 if (storage->Restore()) | |
| 120 return RunWithStorage(storage); | |
| 121 } | |
| 122 | |
| 123 error_ = error.message; | |
| 124 return false; | |
| 125 } | |
| 126 | |
| 105 // Concrete settings functions | 127 // Concrete settings functions |
| 106 | 128 |
| 107 namespace { | 129 namespace { |
| 108 | 130 |
| 109 // Adds all StringValues from a ListValue to a vector of strings. | 131 // Adds all StringValues from a ListValue to a vector of strings. |
| 110 void AddAllStringValues(const base::ListValue& from, | 132 void AddAllStringValues(const base::ListValue& from, |
| 111 std::vector<std::string>* to) { | 133 std::vector<std::string>* to) { |
| 112 DCHECK(to->empty()); | 134 DCHECK(to->empty()); |
| 113 std::string as_string; | 135 std::string as_string; |
| 114 for (base::ListValue::const_iterator it = from.begin(); | 136 for (base::ListValue::const_iterator it = from.begin(); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 154 }; | 176 }; |
| 155 | 177 |
| 156 } // namespace | 178 } // namespace |
| 157 | 179 |
| 158 bool StorageStorageAreaGetFunction::RunWithStorage(ValueStore* storage) { | 180 bool StorageStorageAreaGetFunction::RunWithStorage(ValueStore* storage) { |
| 159 base::Value* input = NULL; | 181 base::Value* input = NULL; |
| 160 EXTENSION_FUNCTION_VALIDATE(args_->Get(0, &input)); | 182 EXTENSION_FUNCTION_VALIDATE(args_->Get(0, &input)); |
| 161 | 183 |
| 162 switch (input->GetType()) { | 184 switch (input->GetType()) { |
| 163 case base::Value::TYPE_NULL: | 185 case base::Value::TYPE_NULL: |
| 164 return UseReadResult(storage->Get()); | 186 return UseReadResult(storage->Get(), storage); |
| 165 | 187 |
| 166 case base::Value::TYPE_STRING: { | 188 case base::Value::TYPE_STRING: { |
| 167 std::string as_string; | 189 std::string as_string; |
| 168 input->GetAsString(&as_string); | 190 input->GetAsString(&as_string); |
| 169 return UseReadResult(storage->Get(as_string)); | 191 return UseReadResult(storage->Get(as_string), storage); |
| 170 } | 192 } |
| 171 | 193 |
| 172 case base::Value::TYPE_LIST: { | 194 case base::Value::TYPE_LIST: { |
| 173 std::vector<std::string> as_string_list; | 195 std::vector<std::string> as_string_list; |
| 174 AddAllStringValues(*static_cast<base::ListValue*>(input), | 196 AddAllStringValues(*static_cast<base::ListValue*>(input), |
| 175 &as_string_list); | 197 &as_string_list); |
| 176 return UseReadResult(storage->Get(as_string_list)); | 198 return UseReadResult(storage->Get(as_string_list), storage); |
| 177 } | 199 } |
| 178 | 200 |
| 179 case base::Value::TYPE_DICTIONARY: { | 201 case base::Value::TYPE_DICTIONARY: { |
| 180 base::DictionaryValue* as_dict = static_cast<base::DictionaryValue*>(input ); | 202 base::DictionaryValue* as_dict = |
| 203 static_cast<base::DictionaryValue*>(input); | |
| 181 ValueStore::ReadResult result = storage->Get(GetKeys(*as_dict)); | 204 ValueStore::ReadResult result = storage->Get(GetKeys(*as_dict)); |
| 182 if (result->HasError()) { | 205 if (result->HasError()) { |
| 183 return UseReadResult(result.Pass()); | 206 return UseReadResult(result.Pass(), storage); |
| 184 } | 207 } |
| 185 | 208 |
| 186 base::DictionaryValue* with_default_values = as_dict->DeepCopy(); | 209 base::DictionaryValue* with_default_values = as_dict->DeepCopy(); |
| 187 with_default_values->MergeDictionary(&result->settings()); | 210 with_default_values->MergeDictionary(&result->settings()); |
| 188 return UseReadResult( | 211 return UseReadResult( |
| 189 ValueStore::MakeReadResult(make_scoped_ptr(with_default_values))); | 212 ValueStore::MakeReadResult(make_scoped_ptr(with_default_values)), |
| 213 storage); | |
| 190 } | 214 } |
| 191 | 215 |
| 192 default: | 216 default: |
| 193 EXTENSION_FUNCTION_VALIDATE(false); | 217 EXTENSION_FUNCTION_VALIDATE(false); |
| 194 return false; | 218 return false; |
| 195 } | 219 } |
| 196 } | 220 } |
| 197 | 221 |
| 198 bool StorageStorageAreaGetBytesInUseFunction::RunWithStorage( | 222 bool StorageStorageAreaGetBytesInUseFunction::RunWithStorage( |
| 199 ValueStore* storage) { | 223 ValueStore* storage) { |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 227 return false; | 251 return false; |
| 228 } | 252 } |
| 229 | 253 |
| 230 SetResult(new base::FundamentalValue(static_cast<int>(bytes_in_use))); | 254 SetResult(new base::FundamentalValue(static_cast<int>(bytes_in_use))); |
| 231 return true; | 255 return true; |
| 232 } | 256 } |
| 233 | 257 |
| 234 bool StorageStorageAreaSetFunction::RunWithStorage(ValueStore* storage) { | 258 bool StorageStorageAreaSetFunction::RunWithStorage(ValueStore* storage) { |
| 235 base::DictionaryValue* input = NULL; | 259 base::DictionaryValue* input = NULL; |
| 236 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &input)); | 260 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &input)); |
| 237 return UseWriteResult(storage->Set(ValueStore::DEFAULTS, *input)); | 261 return UseWriteResult(storage->Set(ValueStore::DEFAULTS, *input), storage); |
| 238 } | 262 } |
| 239 | 263 |
| 240 void StorageStorageAreaSetFunction::GetQuotaLimitHeuristics( | 264 void StorageStorageAreaSetFunction::GetQuotaLimitHeuristics( |
| 241 QuotaLimitHeuristics* heuristics) const { | 265 QuotaLimitHeuristics* heuristics) const { |
| 242 GetModificationQuotaLimitHeuristics(heuristics); | 266 GetModificationQuotaLimitHeuristics(heuristics); |
| 243 } | 267 } |
| 244 | 268 |
| 245 bool StorageStorageAreaRemoveFunction::RunWithStorage(ValueStore* storage) { | 269 bool StorageStorageAreaRemoveFunction::RunWithStorage(ValueStore* storage) { |
| 246 base::Value* input = NULL; | 270 base::Value* input = NULL; |
| 247 EXTENSION_FUNCTION_VALIDATE(args_->Get(0, &input)); | 271 EXTENSION_FUNCTION_VALIDATE(args_->Get(0, &input)); |
| 248 | 272 |
| 249 switch (input->GetType()) { | 273 switch (input->GetType()) { |
| 250 case base::Value::TYPE_STRING: { | 274 case base::Value::TYPE_STRING: { |
| 251 std::string as_string; | 275 std::string as_string; |
| 252 input->GetAsString(&as_string); | 276 input->GetAsString(&as_string); |
| 253 return UseWriteResult(storage->Remove(as_string)); | 277 return UseWriteResult(storage->Remove(as_string), storage); |
| 254 } | 278 } |
| 255 | 279 |
| 256 case base::Value::TYPE_LIST: { | 280 case base::Value::TYPE_LIST: { |
| 257 std::vector<std::string> as_string_list; | 281 std::vector<std::string> as_string_list; |
| 258 AddAllStringValues(*static_cast<base::ListValue*>(input), | 282 AddAllStringValues(*static_cast<base::ListValue*>(input), |
| 259 &as_string_list); | 283 &as_string_list); |
| 260 return UseWriteResult(storage->Remove(as_string_list)); | 284 return UseWriteResult(storage->Remove(as_string_list), storage); |
| 261 } | 285 } |
| 262 | 286 |
| 263 default: | 287 default: |
| 264 EXTENSION_FUNCTION_VALIDATE(false); | 288 EXTENSION_FUNCTION_VALIDATE(false); |
| 265 return false; | 289 return false; |
| 266 }; | 290 }; |
| 267 } | 291 } |
| 268 | 292 |
| 269 void StorageStorageAreaRemoveFunction::GetQuotaLimitHeuristics( | 293 void StorageStorageAreaRemoveFunction::GetQuotaLimitHeuristics( |
| 270 QuotaLimitHeuristics* heuristics) const { | 294 QuotaLimitHeuristics* heuristics) const { |
| 271 GetModificationQuotaLimitHeuristics(heuristics); | 295 GetModificationQuotaLimitHeuristics(heuristics); |
| 272 } | 296 } |
| 273 | 297 |
| 274 bool StorageStorageAreaClearFunction::RunWithStorage(ValueStore* storage) { | 298 bool StorageStorageAreaClearFunction::RunWithStorage(ValueStore* storage) { |
| 275 return UseWriteResult(storage->Clear()); | 299 return UseWriteResult(storage->Clear(), storage); |
| 276 } | 300 } |
| 277 | 301 |
| 278 void StorageStorageAreaClearFunction::GetQuotaLimitHeuristics( | 302 void StorageStorageAreaClearFunction::GetQuotaLimitHeuristics( |
| 279 QuotaLimitHeuristics* heuristics) const { | 303 QuotaLimitHeuristics* heuristics) const { |
| 280 GetModificationQuotaLimitHeuristics(heuristics); | 304 GetModificationQuotaLimitHeuristics(heuristics); |
| 281 } | 305 } |
| 282 | 306 |
| 283 } // namespace extensions | 307 } // namespace extensions |
| OLD | NEW |