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 |