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 "chrome/browser/extensions/api/storage/sync_storage_backend.h" | 5 #include "chrome/browser/extensions/api/storage/sync_storage_backend.h" |
6 | 6 |
7 #include "base/files/file_enumerator.h" | 7 #include "base/files/file_enumerator.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "chrome/browser/extensions/api/storage/settings_sync_processor.h" | 9 #include "chrome/browser/extensions/api/storage/settings_sync_processor.h" |
10 #include "chrome/browser/extensions/api/storage/settings_sync_util.h" | 10 #include "chrome/browser/extensions/api/storage/settings_sync_util.h" |
(...skipping 25 matching lines...) Expand all Loading... |
36 const SettingsStorageQuotaEnforcer::Limits& quota, | 36 const SettingsStorageQuotaEnforcer::Limits& quota, |
37 const scoped_refptr<SettingsObserverList>& observers, | 37 const scoped_refptr<SettingsObserverList>& observers, |
38 syncer::ModelType sync_type, | 38 syncer::ModelType sync_type, |
39 const syncer::SyncableService::StartSyncFlare& flare) | 39 const syncer::SyncableService::StartSyncFlare& flare) |
40 : storage_factory_(storage_factory), | 40 : storage_factory_(storage_factory), |
41 base_path_(base_path), | 41 base_path_(base_path), |
42 quota_(quota), | 42 quota_(quota), |
43 observers_(observers), | 43 observers_(observers), |
44 sync_type_(sync_type), | 44 sync_type_(sync_type), |
45 flare_(flare) { | 45 flare_(flare) { |
46 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 46 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
47 DCHECK(sync_type_ == syncer::EXTENSION_SETTINGS || | 47 DCHECK(sync_type_ == syncer::EXTENSION_SETTINGS || |
48 sync_type_ == syncer::APP_SETTINGS); | 48 sync_type_ == syncer::APP_SETTINGS); |
49 } | 49 } |
50 | 50 |
51 SyncStorageBackend::~SyncStorageBackend() {} | 51 SyncStorageBackend::~SyncStorageBackend() {} |
52 | 52 |
53 ValueStore* SyncStorageBackend::GetStorage(const std::string& extension_id) { | 53 ValueStore* SyncStorageBackend::GetStorage(const std::string& extension_id) { |
54 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 54 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
55 base::DictionaryValue empty; | 55 base::DictionaryValue empty; |
56 return GetOrCreateStorageWithSyncData(extension_id, empty); | 56 return GetOrCreateStorageWithSyncData(extension_id, empty); |
57 } | 57 } |
58 | 58 |
59 SyncableSettingsStorage* SyncStorageBackend::GetOrCreateStorageWithSyncData( | 59 SyncableSettingsStorage* SyncStorageBackend::GetOrCreateStorageWithSyncData( |
60 const std::string& extension_id, | 60 const std::string& extension_id, |
61 const base::DictionaryValue& sync_data) const { | 61 const base::DictionaryValue& sync_data) const { |
62 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 62 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
63 | 63 |
64 StorageObjMap::iterator maybe_storage = storage_objs_.find(extension_id); | 64 StorageObjMap::iterator maybe_storage = storage_objs_.find(extension_id); |
65 if (maybe_storage != storage_objs_.end()) { | 65 if (maybe_storage != storage_objs_.end()) { |
66 return maybe_storage->second.get(); | 66 return maybe_storage->second.get(); |
67 } | 67 } |
68 | 68 |
69 scoped_ptr<SettingsStorageQuotaEnforcer> storage( | 69 scoped_ptr<SettingsStorageQuotaEnforcer> storage( |
70 new SettingsStorageQuotaEnforcer( | 70 new SettingsStorageQuotaEnforcer( |
71 quota_, storage_factory_->Create(base_path_, extension_id))); | 71 quota_, storage_factory_->Create(base_path_, extension_id))); |
72 | 72 |
73 // It's fine to create the quota enforcer underneath the sync layer, since | 73 // It's fine to create the quota enforcer underneath the sync layer, since |
74 // sync will only go ahead if each underlying storage operation succeeds. | 74 // sync will only go ahead if each underlying storage operation succeeds. |
75 linked_ptr<SyncableSettingsStorage> syncable_storage( | 75 linked_ptr<SyncableSettingsStorage> syncable_storage( |
76 new SyncableSettingsStorage( | 76 new SyncableSettingsStorage( |
77 observers_, extension_id, storage.release(), sync_type_, flare_)); | 77 observers_, extension_id, storage.release(), sync_type_, flare_)); |
78 storage_objs_[extension_id] = syncable_storage; | 78 storage_objs_[extension_id] = syncable_storage; |
79 | 79 |
80 if (sync_processor_.get()) { | 80 if (sync_processor_.get()) { |
81 syncer::SyncError error = syncable_storage->StartSyncing( | 81 syncer::SyncError error = syncable_storage->StartSyncing( |
82 sync_data, CreateSettingsSyncProcessor(extension_id).Pass()); | 82 sync_data, CreateSettingsSyncProcessor(extension_id).Pass()); |
83 if (error.IsSet()) | 83 if (error.IsSet()) |
84 syncable_storage.get()->StopSyncing(); | 84 syncable_storage.get()->StopSyncing(); |
85 } | 85 } |
86 return syncable_storage.get(); | 86 return syncable_storage.get(); |
87 } | 87 } |
88 | 88 |
89 void SyncStorageBackend::DeleteStorage(const std::string& extension_id) { | 89 void SyncStorageBackend::DeleteStorage(const std::string& extension_id) { |
90 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 90 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
91 | 91 |
92 // Clear settings when the extension is uninstalled. Leveldb implementations | 92 // Clear settings when the extension is uninstalled. Leveldb implementations |
93 // will also delete the database from disk when the object is destroyed as a | 93 // will also delete the database from disk when the object is destroyed as a |
94 // result of being removed from |storage_objs_|. | 94 // result of being removed from |storage_objs_|. |
95 // | 95 // |
96 // TODO(kalman): always GetStorage here (rather than only clearing if it | 96 // TODO(kalman): always GetStorage here (rather than only clearing if it |
97 // exists) since the storage area may have been unloaded, but we still want | 97 // exists) since the storage area may have been unloaded, but we still want |
98 // to clear the data from disk. | 98 // to clear the data from disk. |
99 // However, this triggers http://crbug.com/111072. | 99 // However, this triggers http://crbug.com/111072. |
100 StorageObjMap::iterator maybe_storage = storage_objs_.find(extension_id); | 100 StorageObjMap::iterator maybe_storage = storage_objs_.find(extension_id); |
101 if (maybe_storage == storage_objs_.end()) | 101 if (maybe_storage == storage_objs_.end()) |
102 return; | 102 return; |
103 maybe_storage->second->Clear(); | 103 maybe_storage->second->Clear(); |
104 storage_objs_.erase(extension_id); | 104 storage_objs_.erase(extension_id); |
105 } | 105 } |
106 | 106 |
107 std::set<std::string> SyncStorageBackend::GetKnownExtensionIDs() const { | 107 std::set<std::string> SyncStorageBackend::GetKnownExtensionIDs() const { |
108 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 108 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
109 std::set<std::string> result; | 109 std::set<std::string> result; |
110 | 110 |
111 // Storage areas can be in-memory as well as on disk. |storage_objs_| will | 111 // Storage areas can be in-memory as well as on disk. |storage_objs_| will |
112 // contain all that are in-memory. | 112 // contain all that are in-memory. |
113 for (StorageObjMap::iterator it = storage_objs_.begin(); | 113 for (StorageObjMap::iterator it = storage_objs_.begin(); |
114 it != storage_objs_.end(); | 114 it != storage_objs_.end(); |
115 ++it) { | 115 ++it) { |
116 result.insert(it->first); | 116 result.insert(it->first); |
117 } | 117 } |
118 | 118 |
119 // Leveldb databases are directories inside |base_path_|. | 119 // Leveldb databases are directories inside |base_path_|. |
120 base::FileEnumerator extension_dirs( | 120 base::FileEnumerator extension_dirs( |
121 base_path_, false, base::FileEnumerator::DIRECTORIES); | 121 base_path_, false, base::FileEnumerator::DIRECTORIES); |
122 while (!extension_dirs.Next().empty()) { | 122 while (!extension_dirs.Next().empty()) { |
123 base::FilePath extension_dir = extension_dirs.GetInfo().GetName(); | 123 base::FilePath extension_dir = extension_dirs.GetInfo().GetName(); |
124 DCHECK(!extension_dir.IsAbsolute()); | 124 DCHECK(!extension_dir.IsAbsolute()); |
125 // Extension IDs are created as std::strings so they *should* be ASCII. | 125 // Extension IDs are created as std::strings so they *should* be ASCII. |
126 std::string maybe_as_ascii(extension_dir.MaybeAsASCII()); | 126 std::string maybe_as_ascii(extension_dir.MaybeAsASCII()); |
127 if (!maybe_as_ascii.empty()) { | 127 if (!maybe_as_ascii.empty()) { |
128 result.insert(maybe_as_ascii); | 128 result.insert(maybe_as_ascii); |
129 } | 129 } |
130 } | 130 } |
131 | 131 |
132 return result; | 132 return result; |
133 } | 133 } |
134 | 134 |
135 syncer::SyncDataList SyncStorageBackend::GetAllSyncData(syncer::ModelType type) | 135 syncer::SyncDataList SyncStorageBackend::GetAllSyncData(syncer::ModelType type) |
136 const { | 136 const { |
137 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 137 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
138 // Ignore the type, it's just for sanity checking; assume that whatever base | 138 // Ignore the type, it's just for sanity checking; assume that whatever base |
139 // path we're constructed with is correct for the sync type. | 139 // path we're constructed with is correct for the sync type. |
140 DCHECK(type == syncer::EXTENSION_SETTINGS || type == syncer::APP_SETTINGS); | 140 DCHECK(type == syncer::EXTENSION_SETTINGS || type == syncer::APP_SETTINGS); |
141 | 141 |
142 // For all extensions, get all their settings. This has the effect | 142 // For all extensions, get all their settings. This has the effect |
143 // of bringing in the entire state of extension settings in memory; sad. | 143 // of bringing in the entire state of extension settings in memory; sad. |
144 syncer::SyncDataList all_sync_data; | 144 syncer::SyncDataList all_sync_data; |
145 std::set<std::string> known_extension_ids(GetKnownExtensionIDs()); | 145 std::set<std::string> known_extension_ids(GetKnownExtensionIDs()); |
146 | 146 |
147 for (std::set<std::string>::const_iterator it = known_extension_ids.begin(); | 147 for (std::set<std::string>::const_iterator it = known_extension_ids.begin(); |
(...skipping 10 matching lines...) Expand all Loading... |
158 } | 158 } |
159 | 159 |
160 return all_sync_data; | 160 return all_sync_data; |
161 } | 161 } |
162 | 162 |
163 syncer::SyncMergeResult SyncStorageBackend::MergeDataAndStartSyncing( | 163 syncer::SyncMergeResult SyncStorageBackend::MergeDataAndStartSyncing( |
164 syncer::ModelType type, | 164 syncer::ModelType type, |
165 const syncer::SyncDataList& initial_sync_data, | 165 const syncer::SyncDataList& initial_sync_data, |
166 scoped_ptr<syncer::SyncChangeProcessor> sync_processor, | 166 scoped_ptr<syncer::SyncChangeProcessor> sync_processor, |
167 scoped_ptr<syncer::SyncErrorFactory> sync_error_factory) { | 167 scoped_ptr<syncer::SyncErrorFactory> sync_error_factory) { |
168 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 168 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
169 DCHECK_EQ(sync_type_, type); | 169 DCHECK_EQ(sync_type_, type); |
170 DCHECK(!sync_processor_.get()); | 170 DCHECK(!sync_processor_.get()); |
171 DCHECK(sync_processor.get()); | 171 DCHECK(sync_processor.get()); |
172 DCHECK(sync_error_factory.get()); | 172 DCHECK(sync_error_factory.get()); |
173 | 173 |
174 sync_processor_ = sync_processor.Pass(); | 174 sync_processor_ = sync_processor.Pass(); |
175 sync_error_factory_ = sync_error_factory.Pass(); | 175 sync_error_factory_ = sync_error_factory.Pass(); |
176 | 176 |
177 // Group the initial sync data by extension id. | 177 // Group the initial sync data by extension id. |
178 std::map<std::string, linked_ptr<base::DictionaryValue> > grouped_sync_data; | 178 std::map<std::string, linked_ptr<base::DictionaryValue> > grouped_sync_data; |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
224 ++it) { | 224 ++it) { |
225 GetOrCreateStorageWithSyncData(it->first, *it->second); | 225 GetOrCreateStorageWithSyncData(it->first, *it->second); |
226 } | 226 } |
227 | 227 |
228 return syncer::SyncMergeResult(type); | 228 return syncer::SyncMergeResult(type); |
229 } | 229 } |
230 | 230 |
231 syncer::SyncError SyncStorageBackend::ProcessSyncChanges( | 231 syncer::SyncError SyncStorageBackend::ProcessSyncChanges( |
232 const tracked_objects::Location& from_here, | 232 const tracked_objects::Location& from_here, |
233 const syncer::SyncChangeList& sync_changes) { | 233 const syncer::SyncChangeList& sync_changes) { |
234 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 234 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
235 DCHECK(sync_processor_.get()); | 235 DCHECK(sync_processor_.get()); |
236 | 236 |
237 // Group changes by extension, to pass all changes in a single method call. | 237 // Group changes by extension, to pass all changes in a single method call. |
238 std::map<std::string, SettingSyncDataList> grouped_sync_data; | 238 std::map<std::string, SettingSyncDataList> grouped_sync_data; |
239 for (syncer::SyncChangeList::const_iterator it = sync_changes.begin(); | 239 for (syncer::SyncChangeList::const_iterator it = sync_changes.begin(); |
240 it != sync_changes.end(); | 240 it != sync_changes.end(); |
241 ++it) { | 241 ++it) { |
242 SettingSyncData data(*it); | 242 SettingSyncData data(*it); |
243 grouped_sync_data[data.extension_id()].push_back(data); | 243 grouped_sync_data[data.extension_id()].push_back(data); |
244 } | 244 } |
245 | 245 |
246 // Create any storage areas that don't exist yet but have sync data. | 246 // Create any storage areas that don't exist yet but have sync data. |
247 base::DictionaryValue empty; | 247 base::DictionaryValue empty; |
248 for (std::map<std::string, SettingSyncDataList>::iterator it = | 248 for (std::map<std::string, SettingSyncDataList>::iterator it = |
249 grouped_sync_data.begin(); | 249 grouped_sync_data.begin(); |
250 it != grouped_sync_data.end(); | 250 it != grouped_sync_data.end(); |
251 ++it) { | 251 ++it) { |
252 SyncableSettingsStorage* storage = | 252 SyncableSettingsStorage* storage = |
253 GetOrCreateStorageWithSyncData(it->first, empty); | 253 GetOrCreateStorageWithSyncData(it->first, empty); |
254 syncer::SyncError error = storage->ProcessSyncChanges(it->second); | 254 syncer::SyncError error = storage->ProcessSyncChanges(it->second); |
255 if (error.IsSet()) | 255 if (error.IsSet()) |
256 storage->StopSyncing(); | 256 storage->StopSyncing(); |
257 } | 257 } |
258 | 258 |
259 return syncer::SyncError(); | 259 return syncer::SyncError(); |
260 } | 260 } |
261 | 261 |
262 void SyncStorageBackend::StopSyncing(syncer::ModelType type) { | 262 void SyncStorageBackend::StopSyncing(syncer::ModelType type) { |
263 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 263 DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
264 DCHECK(type == syncer::EXTENSION_SETTINGS || type == syncer::APP_SETTINGS); | 264 DCHECK(type == syncer::EXTENSION_SETTINGS || type == syncer::APP_SETTINGS); |
265 DCHECK_EQ(sync_type_, type); | 265 DCHECK_EQ(sync_type_, type); |
266 | 266 |
267 for (StorageObjMap::iterator it = storage_objs_.begin(); | 267 for (StorageObjMap::iterator it = storage_objs_.begin(); |
268 it != storage_objs_.end(); | 268 it != storage_objs_.end(); |
269 ++it) { | 269 ++it) { |
270 // Some storage areas may have already stopped syncing if they had areas | 270 // Some storage areas may have already stopped syncing if they had areas |
271 // and syncing was disabled, but StopSyncing is safe to call multiple times. | 271 // and syncing was disabled, but StopSyncing is safe to call multiple times. |
272 it->second->StopSyncing(); | 272 it->second->StopSyncing(); |
273 } | 273 } |
274 | 274 |
275 sync_processor_.reset(); | 275 sync_processor_.reset(); |
276 sync_error_factory_.reset(); | 276 sync_error_factory_.reset(); |
277 } | 277 } |
278 | 278 |
279 scoped_ptr<SettingsSyncProcessor> | 279 scoped_ptr<SettingsSyncProcessor> |
280 SyncStorageBackend::CreateSettingsSyncProcessor(const std::string& extension_id) | 280 SyncStorageBackend::CreateSettingsSyncProcessor(const std::string& extension_id) |
281 const { | 281 const { |
282 CHECK(sync_processor_.get()); | 282 CHECK(sync_processor_.get()); |
283 return scoped_ptr<SettingsSyncProcessor>(new SettingsSyncProcessor( | 283 return scoped_ptr<SettingsSyncProcessor>(new SettingsSyncProcessor( |
284 extension_id, sync_type_, sync_processor_.get())); | 284 extension_id, sync_type_, sync_processor_.get())); |
285 } | 285 } |
286 | 286 |
287 } // namespace extensions | 287 } // namespace extensions |
OLD | NEW |