| 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/syncable_settings_storage.h" | 5 #include "chrome/browser/extensions/api/storage/syncable_settings_storage.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/memory/ptr_util.h" | 9 #include "base/memory/ptr_util.h" |
| 10 #include "base/strings/stringprintf.h" | 10 #include "base/strings/stringprintf.h" |
| 11 #include "chrome/browser/extensions/api/storage/settings_sync_processor.h" | 11 #include "chrome/browser/extensions/api/storage/settings_sync_processor.h" |
| 12 #include "chrome/browser/extensions/api/storage/settings_sync_util.h" | 12 #include "chrome/browser/extensions/api/storage/settings_sync_util.h" |
| 13 #include "components/sync/model/sync_data.h" | 13 #include "components/sync/model/sync_data.h" |
| 14 #include "components/sync/protocol/extension_setting_specifics.pb.h" | 14 #include "components/sync/protocol/extension_setting_specifics.pb.h" |
| 15 #include "content/public/browser/browser_thread.h" | 15 #include "extensions/browser/api/storage/backend_task_runner.h" |
| 16 #include "extensions/browser/api/storage/settings_namespace.h" | 16 #include "extensions/browser/api/storage/settings_namespace.h" |
| 17 | 17 |
| 18 using content::BrowserThread; | |
| 19 | |
| 20 namespace extensions { | 18 namespace extensions { |
| 21 | 19 |
| 22 SyncableSettingsStorage::SyncableSettingsStorage( | 20 SyncableSettingsStorage::SyncableSettingsStorage( |
| 23 const scoped_refptr<base::ObserverListThreadSafe<SettingsObserver>>& | 21 const scoped_refptr<base::ObserverListThreadSafe<SettingsObserver>>& |
| 24 observers, | 22 observers, |
| 25 const std::string& extension_id, | 23 const std::string& extension_id, |
| 26 ValueStore* delegate, | 24 ValueStore* delegate, |
| 27 syncer::ModelType sync_type, | 25 syncer::ModelType sync_type, |
| 28 const syncer::SyncableService::StartSyncFlare& flare) | 26 const syncer::SyncableService::StartSyncFlare& flare) |
| 29 : observers_(observers), | 27 : observers_(observers), |
| 30 extension_id_(extension_id), | 28 extension_id_(extension_id), |
| 31 delegate_(delegate), | 29 delegate_(delegate), |
| 32 sync_type_(sync_type), | 30 sync_type_(sync_type), |
| 33 flare_(flare) { | 31 flare_(flare) { |
| 34 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 32 DCHECK(IsOnBackendSequence()); |
| 35 } | 33 } |
| 36 | 34 |
| 37 SyncableSettingsStorage::~SyncableSettingsStorage() { | 35 SyncableSettingsStorage::~SyncableSettingsStorage() { |
| 38 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 36 DCHECK(IsOnBackendSequence()); |
| 39 } | 37 } |
| 40 | 38 |
| 41 size_t SyncableSettingsStorage::GetBytesInUse(const std::string& key) { | 39 size_t SyncableSettingsStorage::GetBytesInUse(const std::string& key) { |
| 42 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 40 DCHECK(IsOnBackendSequence()); |
| 43 return delegate_->GetBytesInUse(key); | 41 return delegate_->GetBytesInUse(key); |
| 44 } | 42 } |
| 45 | 43 |
| 46 size_t SyncableSettingsStorage::GetBytesInUse( | 44 size_t SyncableSettingsStorage::GetBytesInUse( |
| 47 const std::vector<std::string>& keys) { | 45 const std::vector<std::string>& keys) { |
| 48 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 46 DCHECK(IsOnBackendSequence()); |
| 49 return delegate_->GetBytesInUse(keys); | 47 return delegate_->GetBytesInUse(keys); |
| 50 } | 48 } |
| 51 | 49 |
| 52 size_t SyncableSettingsStorage::GetBytesInUse() { | 50 size_t SyncableSettingsStorage::GetBytesInUse() { |
| 53 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 51 DCHECK(IsOnBackendSequence()); |
| 54 return delegate_->GetBytesInUse(); | 52 return delegate_->GetBytesInUse(); |
| 55 } | 53 } |
| 56 | 54 |
| 57 template <class T> | 55 template <class T> |
| 58 T SyncableSettingsStorage::HandleResult(T result) { | 56 T SyncableSettingsStorage::HandleResult(T result) { |
| 59 if (result->status().restore_status != RESTORE_NONE) { | 57 if (result->status().restore_status != RESTORE_NONE) { |
| 60 // If we're syncing, stop - we don't want to push the deletion of any data. | 58 // If we're syncing, stop - we don't want to push the deletion of any data. |
| 61 // At next startup, when we start up the sync service, we'll get back any | 59 // At next startup, when we start up the sync service, we'll get back any |
| 62 // data which was stored intact on Sync. | 60 // data which was stored intact on Sync. |
| 63 // TODO(devlin): Investigate if there's a way we can trigger | 61 // TODO(devlin): Investigate if there's a way we can trigger |
| 64 // MergeDataAndStartSyncing() to immediately get back any data we can, and | 62 // MergeDataAndStartSyncing() to immediately get back any data we can, and |
| 65 // continue syncing. | 63 // continue syncing. |
| 66 StopSyncing(); | 64 StopSyncing(); |
| 67 } | 65 } |
| 68 return result; | 66 return result; |
| 69 } | 67 } |
| 70 | 68 |
| 71 ValueStore::ReadResult SyncableSettingsStorage::Get( | 69 ValueStore::ReadResult SyncableSettingsStorage::Get( |
| 72 const std::string& key) { | 70 const std::string& key) { |
| 73 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 71 DCHECK(IsOnBackendSequence()); |
| 74 return HandleResult(delegate_->Get(key)); | 72 return HandleResult(delegate_->Get(key)); |
| 75 } | 73 } |
| 76 | 74 |
| 77 ValueStore::ReadResult SyncableSettingsStorage::Get( | 75 ValueStore::ReadResult SyncableSettingsStorage::Get( |
| 78 const std::vector<std::string>& keys) { | 76 const std::vector<std::string>& keys) { |
| 79 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 77 DCHECK(IsOnBackendSequence()); |
| 80 return HandleResult(delegate_->Get(keys)); | 78 return HandleResult(delegate_->Get(keys)); |
| 81 } | 79 } |
| 82 | 80 |
| 83 ValueStore::ReadResult SyncableSettingsStorage::Get() { | 81 ValueStore::ReadResult SyncableSettingsStorage::Get() { |
| 84 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 82 DCHECK(IsOnBackendSequence()); |
| 85 return HandleResult(delegate_->Get()); | 83 return HandleResult(delegate_->Get()); |
| 86 } | 84 } |
| 87 | 85 |
| 88 ValueStore::WriteResult SyncableSettingsStorage::Set( | 86 ValueStore::WriteResult SyncableSettingsStorage::Set( |
| 89 WriteOptions options, const std::string& key, const base::Value& value) { | 87 WriteOptions options, const std::string& key, const base::Value& value) { |
| 90 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 88 DCHECK(IsOnBackendSequence()); |
| 91 WriteResult result = HandleResult(delegate_->Set(options, key, value)); | 89 WriteResult result = HandleResult(delegate_->Set(options, key, value)); |
| 92 if (!result->status().ok()) | 90 if (!result->status().ok()) |
| 93 return result; | 91 return result; |
| 94 SyncResultIfEnabled(result); | 92 SyncResultIfEnabled(result); |
| 95 return result; | 93 return result; |
| 96 } | 94 } |
| 97 | 95 |
| 98 ValueStore::WriteResult SyncableSettingsStorage::Set( | 96 ValueStore::WriteResult SyncableSettingsStorage::Set( |
| 99 WriteOptions options, const base::DictionaryValue& values) { | 97 WriteOptions options, const base::DictionaryValue& values) { |
| 100 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 98 DCHECK(IsOnBackendSequence()); |
| 101 WriteResult result = HandleResult(delegate_->Set(options, values)); | 99 WriteResult result = HandleResult(delegate_->Set(options, values)); |
| 102 if (!result->status().ok()) | 100 if (!result->status().ok()) |
| 103 return result; | 101 return result; |
| 104 SyncResultIfEnabled(result); | 102 SyncResultIfEnabled(result); |
| 105 return result; | 103 return result; |
| 106 } | 104 } |
| 107 | 105 |
| 108 ValueStore::WriteResult SyncableSettingsStorage::Remove( | 106 ValueStore::WriteResult SyncableSettingsStorage::Remove( |
| 109 const std::string& key) { | 107 const std::string& key) { |
| 110 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 108 DCHECK(IsOnBackendSequence()); |
| 111 WriteResult result = HandleResult(delegate_->Remove(key)); | 109 WriteResult result = HandleResult(delegate_->Remove(key)); |
| 112 if (!result->status().ok()) | 110 if (!result->status().ok()) |
| 113 return result; | 111 return result; |
| 114 SyncResultIfEnabled(result); | 112 SyncResultIfEnabled(result); |
| 115 return result; | 113 return result; |
| 116 } | 114 } |
| 117 | 115 |
| 118 ValueStore::WriteResult SyncableSettingsStorage::Remove( | 116 ValueStore::WriteResult SyncableSettingsStorage::Remove( |
| 119 const std::vector<std::string>& keys) { | 117 const std::vector<std::string>& keys) { |
| 120 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 118 DCHECK(IsOnBackendSequence()); |
| 121 WriteResult result = HandleResult(delegate_->Remove(keys)); | 119 WriteResult result = HandleResult(delegate_->Remove(keys)); |
| 122 if (!result->status().ok()) | 120 if (!result->status().ok()) |
| 123 return result; | 121 return result; |
| 124 SyncResultIfEnabled(result); | 122 SyncResultIfEnabled(result); |
| 125 return result; | 123 return result; |
| 126 } | 124 } |
| 127 | 125 |
| 128 ValueStore::WriteResult SyncableSettingsStorage::Clear() { | 126 ValueStore::WriteResult SyncableSettingsStorage::Clear() { |
| 129 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 127 DCHECK(IsOnBackendSequence()); |
| 130 WriteResult result = HandleResult(delegate_->Clear()); | 128 WriteResult result = HandleResult(delegate_->Clear()); |
| 131 if (!result->status().ok()) | 129 if (!result->status().ok()) |
| 132 return result; | 130 return result; |
| 133 SyncResultIfEnabled(result); | 131 SyncResultIfEnabled(result); |
| 134 return result; | 132 return result; |
| 135 } | 133 } |
| 136 | 134 |
| 137 void SyncableSettingsStorage::SyncResultIfEnabled( | 135 void SyncableSettingsStorage::SyncResultIfEnabled( |
| 138 const ValueStore::WriteResult& result) { | 136 const ValueStore::WriteResult& result) { |
| 139 if (result->changes().empty()) | 137 if (result->changes().empty()) |
| 140 return; | 138 return; |
| 141 | 139 |
| 142 if (sync_processor_.get()) { | 140 if (sync_processor_.get()) { |
| 143 syncer::SyncError error = sync_processor_->SendChanges(result->changes()); | 141 syncer::SyncError error = sync_processor_->SendChanges(result->changes()); |
| 144 if (error.IsSet()) | 142 if (error.IsSet()) |
| 145 StopSyncing(); | 143 StopSyncing(); |
| 146 } else { | 144 } else { |
| 147 // Tell sync to try and start soon, because syncable changes to sync_type_ | 145 // Tell sync to try and start soon, because syncable changes to sync_type_ |
| 148 // have started happening. This will cause sync to call us back | 146 // have started happening. This will cause sync to call us back |
| 149 // asynchronously via StartSyncing(...) as soon as possible. | 147 // asynchronously via StartSyncing(...) as soon as possible. |
| 150 flare_.Run(sync_type_); | 148 flare_.Run(sync_type_); |
| 151 } | 149 } |
| 152 } | 150 } |
| 153 | 151 |
| 154 // Sync-related methods. | 152 // Sync-related methods. |
| 155 | 153 |
| 156 syncer::SyncError SyncableSettingsStorage::StartSyncing( | 154 syncer::SyncError SyncableSettingsStorage::StartSyncing( |
| 157 std::unique_ptr<base::DictionaryValue> sync_state, | 155 std::unique_ptr<base::DictionaryValue> sync_state, |
| 158 std::unique_ptr<SettingsSyncProcessor> sync_processor) { | 156 std::unique_ptr<SettingsSyncProcessor> sync_processor) { |
| 159 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 157 DCHECK(IsOnBackendSequence()); |
| 160 DCHECK(sync_state); | 158 DCHECK(sync_state); |
| 161 DCHECK(!sync_processor_.get()); | 159 DCHECK(!sync_processor_.get()); |
| 162 | 160 |
| 163 sync_processor_ = std::move(sync_processor); | 161 sync_processor_ = std::move(sync_processor); |
| 164 sync_processor_->Init(*sync_state); | 162 sync_processor_->Init(*sync_state); |
| 165 | 163 |
| 166 ReadResult maybe_settings = delegate_->Get(); | 164 ReadResult maybe_settings = delegate_->Get(); |
| 167 if (!maybe_settings->status().ok()) { | 165 if (!maybe_settings->status().ok()) { |
| 168 return syncer::SyncError( | 166 return syncer::SyncError( |
| 169 FROM_HERE, syncer::SyncError::DATATYPE_ERROR, | 167 FROM_HERE, syncer::SyncError::DATATYPE_ERROR, |
| 170 base::StringPrintf("Failed to get settings: %s", | 168 base::StringPrintf("Failed to get settings: %s", |
| 171 maybe_settings->status().message.c_str()), | 169 maybe_settings->status().message.c_str()), |
| 172 sync_processor_->type()); | 170 sync_processor_->type()); |
| 173 } | 171 } |
| 174 | 172 |
| 175 std::unique_ptr<base::DictionaryValue> current_settings = | 173 std::unique_ptr<base::DictionaryValue> current_settings = |
| 176 maybe_settings->PassSettings(); | 174 maybe_settings->PassSettings(); |
| 177 return sync_state->empty() | 175 return sync_state->empty() |
| 178 ? SendLocalSettingsToSync(std::move(current_settings)) | 176 ? SendLocalSettingsToSync(std::move(current_settings)) |
| 179 : OverwriteLocalSettingsWithSync(std::move(sync_state), | 177 : OverwriteLocalSettingsWithSync(std::move(sync_state), |
| 180 std::move(current_settings)); | 178 std::move(current_settings)); |
| 181 } | 179 } |
| 182 | 180 |
| 183 syncer::SyncError SyncableSettingsStorage::SendLocalSettingsToSync( | 181 syncer::SyncError SyncableSettingsStorage::SendLocalSettingsToSync( |
| 184 std::unique_ptr<base::DictionaryValue> local_state) { | 182 std::unique_ptr<base::DictionaryValue> local_state) { |
| 185 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 183 DCHECK(IsOnBackendSequence()); |
| 186 | 184 |
| 187 if (local_state->empty()) | 185 if (local_state->empty()) |
| 188 return syncer::SyncError(); | 186 return syncer::SyncError(); |
| 189 | 187 |
| 190 // Transform the current settings into a list of sync changes. | 188 // Transform the current settings into a list of sync changes. |
| 191 ValueStoreChangeList changes; | 189 ValueStoreChangeList changes; |
| 192 while (!local_state->empty()) { | 190 while (!local_state->empty()) { |
| 193 // It's not possible to iterate over a DictionaryValue and modify it at the | 191 // It's not possible to iterate over a DictionaryValue and modify it at the |
| 194 // same time, so hack around that restriction. | 192 // same time, so hack around that restriction. |
| 195 std::string key = base::DictionaryValue::Iterator(*local_state).key(); | 193 std::string key = base::DictionaryValue::Iterator(*local_state).key(); |
| 196 std::unique_ptr<base::Value> value; | 194 std::unique_ptr<base::Value> value; |
| 197 local_state->RemoveWithoutPathExpansion(key, &value); | 195 local_state->RemoveWithoutPathExpansion(key, &value); |
| 198 changes.push_back(ValueStoreChange(key, nullptr, std::move(value))); | 196 changes.push_back(ValueStoreChange(key, nullptr, std::move(value))); |
| 199 } | 197 } |
| 200 | 198 |
| 201 syncer::SyncError error = sync_processor_->SendChanges(changes); | 199 syncer::SyncError error = sync_processor_->SendChanges(changes); |
| 202 if (error.IsSet()) | 200 if (error.IsSet()) |
| 203 StopSyncing(); | 201 StopSyncing(); |
| 204 return error; | 202 return error; |
| 205 } | 203 } |
| 206 | 204 |
| 207 syncer::SyncError SyncableSettingsStorage::OverwriteLocalSettingsWithSync( | 205 syncer::SyncError SyncableSettingsStorage::OverwriteLocalSettingsWithSync( |
| 208 std::unique_ptr<base::DictionaryValue> sync_state, | 206 std::unique_ptr<base::DictionaryValue> sync_state, |
| 209 std::unique_ptr<base::DictionaryValue> local_state) { | 207 std::unique_ptr<base::DictionaryValue> local_state) { |
| 210 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 208 DCHECK(IsOnBackendSequence()); |
| 211 // This is implemented by building up a list of sync changes then sending | 209 // This is implemented by building up a list of sync changes then sending |
| 212 // those to ProcessSyncChanges. This generates events like onStorageChanged. | 210 // those to ProcessSyncChanges. This generates events like onStorageChanged. |
| 213 std::unique_ptr<SettingSyncDataList> changes(new SettingSyncDataList()); | 211 std::unique_ptr<SettingSyncDataList> changes(new SettingSyncDataList()); |
| 214 | 212 |
| 215 for (base::DictionaryValue::Iterator it(*local_state); !it.IsAtEnd(); | 213 for (base::DictionaryValue::Iterator it(*local_state); !it.IsAtEnd(); |
| 216 it.Advance()) { | 214 it.Advance()) { |
| 217 std::unique_ptr<base::Value> sync_value; | 215 std::unique_ptr<base::Value> sync_value; |
| 218 if (sync_state->RemoveWithoutPathExpansion(it.key(), &sync_value)) { | 216 if (sync_state->RemoveWithoutPathExpansion(it.key(), &sync_value)) { |
| 219 if (sync_value->Equals(&it.value())) { | 217 if (sync_value->Equals(&it.value())) { |
| 220 // Sync and local values are the same, no changes to send. | 218 // Sync and local values are the same, no changes to send. |
| (...skipping 21 matching lines...) Expand all Loading... |
| 242 changes->push_back(base::MakeUnique<SettingSyncData>( | 240 changes->push_back(base::MakeUnique<SettingSyncData>( |
| 243 syncer::SyncChange::ACTION_ADD, extension_id_, key, std::move(value))); | 241 syncer::SyncChange::ACTION_ADD, extension_id_, key, std::move(value))); |
| 244 } | 242 } |
| 245 | 243 |
| 246 if (changes->empty()) | 244 if (changes->empty()) |
| 247 return syncer::SyncError(); | 245 return syncer::SyncError(); |
| 248 return ProcessSyncChanges(std::move(changes)); | 246 return ProcessSyncChanges(std::move(changes)); |
| 249 } | 247 } |
| 250 | 248 |
| 251 void SyncableSettingsStorage::StopSyncing() { | 249 void SyncableSettingsStorage::StopSyncing() { |
| 252 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 250 DCHECK(IsOnBackendSequence()); |
| 253 sync_processor_.reset(); | 251 sync_processor_.reset(); |
| 254 } | 252 } |
| 255 | 253 |
| 256 syncer::SyncError SyncableSettingsStorage::ProcessSyncChanges( | 254 syncer::SyncError SyncableSettingsStorage::ProcessSyncChanges( |
| 257 std::unique_ptr<SettingSyncDataList> sync_changes) { | 255 std::unique_ptr<SettingSyncDataList> sync_changes) { |
| 258 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | 256 DCHECK(IsOnBackendSequence()); |
| 259 DCHECK(!sync_changes->empty()) << "No sync changes for " << extension_id_; | 257 DCHECK(!sync_changes->empty()) << "No sync changes for " << extension_id_; |
| 260 | 258 |
| 261 if (!sync_processor_.get()) { | 259 if (!sync_processor_.get()) { |
| 262 return syncer::SyncError( | 260 return syncer::SyncError( |
| 263 FROM_HERE, | 261 FROM_HERE, |
| 264 syncer::SyncError::DATATYPE_ERROR, | 262 syncer::SyncError::DATATYPE_ERROR, |
| 265 std::string("Sync is inactive for ") + extension_id_, | 263 std::string("Sync is inactive for ") + extension_id_, |
| 266 syncer::UNSPECIFIED); | 264 syncer::UNSPECIFIED); |
| 267 } | 265 } |
| 268 | 266 |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 397 FROM_HERE, syncer::SyncError::DATATYPE_ERROR, | 395 FROM_HERE, syncer::SyncError::DATATYPE_ERROR, |
| 398 base::StringPrintf("Error pushing sync remove to local settings: %s", | 396 base::StringPrintf("Error pushing sync remove to local settings: %s", |
| 399 result->status().message.c_str()), | 397 result->status().message.c_str()), |
| 400 sync_processor_->type()); | 398 sync_processor_->type()); |
| 401 } | 399 } |
| 402 changes->push_back(ValueStoreChange(key, std::move(old_value), nullptr)); | 400 changes->push_back(ValueStoreChange(key, std::move(old_value), nullptr)); |
| 403 return syncer::SyncError(); | 401 return syncer::SyncError(); |
| 404 } | 402 } |
| 405 | 403 |
| 406 } // namespace extensions | 404 } // namespace extensions |
| OLD | NEW |