| Index: chrome/browser/extensions/api/storage/storage_api.cc
|
| diff --git a/chrome/browser/extensions/api/storage/storage_api.cc b/chrome/browser/extensions/api/storage/storage_api.cc
|
| index 1d6b361110b9b72aa7694a844be3f8073014ee09..2bf88d7558a07215eeb91603146b30c73285a372 100644
|
| --- a/chrome/browser/extensions/api/storage/storage_api.cc
|
| +++ b/chrome/browser/extensions/api/storage/storage_api.cc
|
| @@ -73,23 +73,21 @@ void SettingsFunction::AsyncRunWithStorage(ValueStore* storage) {
|
| base::Bind(&SettingsFunction::SendResponse, this, success));
|
| }
|
|
|
| -bool SettingsFunction::UseReadResult(ValueStore::ReadResult read_result) {
|
| - if (read_result->HasError()) {
|
| - error_ = read_result->error().message;
|
| - return false;
|
| - }
|
| -
|
| - base::DictionaryValue* result = new base::DictionaryValue();
|
| - result->Swap(&read_result->settings());
|
| - SetResult(result);
|
| +bool SettingsFunction::UseReadResult(ValueStore::ReadResult result,
|
| + ValueStore* storage) {
|
| + if (result->HasError())
|
| + return HandleError(result->error(), storage);
|
| +
|
| + base::DictionaryValue* dict = new base::DictionaryValue();
|
| + dict->Swap(&result->settings());
|
| + SetResult(dict);
|
| return true;
|
| }
|
|
|
| -bool SettingsFunction::UseWriteResult(ValueStore::WriteResult result) {
|
| - if (result->HasError()) {
|
| - error_ = result->error().message;
|
| - return false;
|
| - }
|
| +bool SettingsFunction::UseWriteResult(ValueStore::WriteResult result,
|
| + ValueStore* storage) {
|
| + if (result->HasError())
|
| + return HandleError(result->error(), storage);
|
|
|
| if (!result->changes().empty()) {
|
| observers_->Notify(
|
| @@ -102,6 +100,29 @@ bool SettingsFunction::UseWriteResult(ValueStore::WriteResult result) {
|
| return true;
|
| }
|
|
|
| +bool SettingsFunction::HandleError(const ValueStore::Error& error,
|
| + ValueStore* storage) {
|
| + // If the method failed due to corruption, and we haven't tried to fix it, we
|
| + // can try to restore the storage and re-run it. Otherwise, the method has
|
| + // failed.
|
| + if (error.code == ValueStore::CORRUPTION && !tried_restoring_storage_) {
|
| + tried_restoring_storage_ = true;
|
| +
|
| + // If the corruption is on a particular key, try to restore that key and
|
| + // re-run.
|
| + if (error.key.get() && storage->RestoreKey(*error.key))
|
| + return RunWithStorage(storage);
|
| +
|
| + // If the full database is corrupted, try to restore the whole thing and
|
| + // re-run.
|
| + if (storage->Restore())
|
| + return RunWithStorage(storage);
|
| + }
|
| +
|
| + error_ = error.message;
|
| + return false;
|
| +}
|
| +
|
| // Concrete settings functions
|
|
|
| namespace {
|
| @@ -161,32 +182,34 @@ bool StorageStorageAreaGetFunction::RunWithStorage(ValueStore* storage) {
|
|
|
| switch (input->GetType()) {
|
| case base::Value::TYPE_NULL:
|
| - return UseReadResult(storage->Get());
|
| + return UseReadResult(storage->Get(), storage);
|
|
|
| case base::Value::TYPE_STRING: {
|
| std::string as_string;
|
| input->GetAsString(&as_string);
|
| - return UseReadResult(storage->Get(as_string));
|
| + return UseReadResult(storage->Get(as_string), storage);
|
| }
|
|
|
| case base::Value::TYPE_LIST: {
|
| std::vector<std::string> as_string_list;
|
| AddAllStringValues(*static_cast<base::ListValue*>(input),
|
| &as_string_list);
|
| - return UseReadResult(storage->Get(as_string_list));
|
| + return UseReadResult(storage->Get(as_string_list), storage);
|
| }
|
|
|
| case base::Value::TYPE_DICTIONARY: {
|
| - base::DictionaryValue* as_dict = static_cast<base::DictionaryValue*>(input);
|
| + base::DictionaryValue* as_dict =
|
| + static_cast<base::DictionaryValue*>(input);
|
| ValueStore::ReadResult result = storage->Get(GetKeys(*as_dict));
|
| if (result->HasError()) {
|
| - return UseReadResult(result.Pass());
|
| + return UseReadResult(result.Pass(), storage);
|
| }
|
|
|
| base::DictionaryValue* with_default_values = as_dict->DeepCopy();
|
| with_default_values->MergeDictionary(&result->settings());
|
| return UseReadResult(
|
| - ValueStore::MakeReadResult(make_scoped_ptr(with_default_values)));
|
| + ValueStore::MakeReadResult(make_scoped_ptr(with_default_values)),
|
| + storage);
|
| }
|
|
|
| default:
|
| @@ -234,7 +257,7 @@ bool StorageStorageAreaGetBytesInUseFunction::RunWithStorage(
|
| bool StorageStorageAreaSetFunction::RunWithStorage(ValueStore* storage) {
|
| base::DictionaryValue* input = NULL;
|
| EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &input));
|
| - return UseWriteResult(storage->Set(ValueStore::DEFAULTS, *input));
|
| + return UseWriteResult(storage->Set(ValueStore::DEFAULTS, *input), storage);
|
| }
|
|
|
| void StorageStorageAreaSetFunction::GetQuotaLimitHeuristics(
|
| @@ -250,14 +273,14 @@ bool StorageStorageAreaRemoveFunction::RunWithStorage(ValueStore* storage) {
|
| case base::Value::TYPE_STRING: {
|
| std::string as_string;
|
| input->GetAsString(&as_string);
|
| - return UseWriteResult(storage->Remove(as_string));
|
| + return UseWriteResult(storage->Remove(as_string), storage);
|
| }
|
|
|
| case base::Value::TYPE_LIST: {
|
| std::vector<std::string> as_string_list;
|
| AddAllStringValues(*static_cast<base::ListValue*>(input),
|
| &as_string_list);
|
| - return UseWriteResult(storage->Remove(as_string_list));
|
| + return UseWriteResult(storage->Remove(as_string_list), storage);
|
| }
|
|
|
| default:
|
| @@ -272,7 +295,7 @@ void StorageStorageAreaRemoveFunction::GetQuotaLimitHeuristics(
|
| }
|
|
|
| bool StorageStorageAreaClearFunction::RunWithStorage(ValueStore* storage) {
|
| - return UseWriteResult(storage->Clear());
|
| + return UseWriteResult(storage->Clear(), storage);
|
| }
|
|
|
| void StorageStorageAreaClearFunction::GetQuotaLimitHeuristics(
|
|
|