Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(277)

Side by Side Diff: chrome/browser/extensions/api/storage/sync_storage_backend.cc

Issue 165223003: Add a Restore() method to ValueStore and make StorageAPI use it (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/settings_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"
11 #include "chrome/browser/extensions/api/storage/syncable_settings_storage.h" 11 #include "chrome/browser/extensions/api/storage/syncable_settings_storage.h"
12 #include "content/public/browser/browser_thread.h" 12 #include "content/public/browser/browser_thread.h"
13 #include "sync/api/sync_error_factory.h" 13 #include "sync/api/sync_error_factory.h"
14 14
15 using content::BrowserThread; 15 using content::BrowserThread;
16 16
17 namespace extensions { 17 namespace extensions {
18 18
19 SettingsBackend::SettingsBackend( 19 namespace {
20
21 void AddAllSyncData(const std::string& extension_id,
22 const base::DictionaryValue& src,
23 syncer::ModelType type,
24 syncer::SyncDataList* dst) {
25 for (base::DictionaryValue::Iterator it(src); !it.IsAtEnd(); it.Advance()) {
26 dst->push_back(settings_sync_util::CreateData(
27 extension_id, it.key(), it.value(), type));
28 }
29 }
30
31 } // namespace
32
33 SyncStorageBackend::SyncStorageBackend(
20 const scoped_refptr<SettingsStorageFactory>& storage_factory, 34 const scoped_refptr<SettingsStorageFactory>& storage_factory,
21 const base::FilePath& base_path, 35 const base::FilePath& base_path,
36 const SettingsStorageQuotaEnforcer::Limits& quota,
37 const scoped_refptr<SettingsObserverList>& observers,
22 syncer::ModelType sync_type, 38 syncer::ModelType sync_type,
23 const syncer::SyncableService::StartSyncFlare& flare, 39 const syncer::SyncableService::StartSyncFlare& flare)
24 const SettingsStorageQuotaEnforcer::Limits& quota, 40 : SettingsBackend(storage_factory, base_path, quota),
25 const scoped_refptr<SettingsObserverList>& observers)
26 : storage_factory_(storage_factory),
27 base_path_(base_path),
28 quota_(quota),
29 observers_(observers), 41 observers_(observers),
30 sync_type_(sync_type), 42 sync_type_(sync_type),
31 flare_(flare) { 43 flare_(flare) {
32 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 44 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
33 DCHECK(sync_type_ == syncer::EXTENSION_SETTINGS || 45 DCHECK(sync_type_ == syncer::EXTENSION_SETTINGS ||
34 sync_type_ == syncer::APP_SETTINGS); 46 sync_type_ == syncer::APP_SETTINGS);
35 } 47 }
36 48
37 SettingsBackend::~SettingsBackend() { 49 SyncStorageBackend::~SyncStorageBackend() {}
38 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
39 }
40 50
41 ValueStore* SettingsBackend::GetStorage( 51 ValueStore* SyncStorageBackend::GetStorage(const std::string& extension_id) {
42 const std::string& extension_id) const {
43 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 52 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
44 base::DictionaryValue empty; 53 base::DictionaryValue empty;
45 return GetOrCreateStorageWithSyncData(extension_id, empty); 54 return GetOrCreateStorageWithSyncData(extension_id, empty);
46 } 55 }
47 56
48 SyncableSettingsStorage* SettingsBackend::GetOrCreateStorageWithSyncData( 57 SyncableSettingsStorage* SyncStorageBackend::GetOrCreateStorageWithSyncData(
49 const std::string& extension_id, 58 const std::string& extension_id,
50 const base::DictionaryValue& sync_data) const { 59 const base::DictionaryValue& sync_data) const {
51 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 60 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
52 61
53 StorageObjMap::iterator maybe_storage = storage_objs_.find(extension_id); 62 StorageObjMap::iterator maybe_storage = storage_objs_.find(extension_id);
54 if (maybe_storage != storage_objs_.end()) { 63 if (maybe_storage != storage_objs_.end()) {
55 return maybe_storage->second.get(); 64 return maybe_storage->second.get();
56 } 65 }
57 66
58 ValueStore* storage = storage_factory_->Create(base_path_, extension_id); 67 ValueStore* storage = storage_factory()->Create(base_path(), extension_id);
59 CHECK(storage); 68 CHECK(storage);
60 69
70 // Check the ValueStore to ensure that it's not corrupted. If it is corrupted,
71 // make an effort to restore it, and, failing that, clear it forcefully.
72 // This is slow and not ideal, because it means that we always read the full
73 // synced database for corruption. Unfortunately, there's no good alternative,
74 // because we have to catch this *before* we sync. Thankfully, sync databases
75 // are small by policy.
76 ValueStore::ReadResult result = storage->Get();
not at google - send to devlin 2014/02/14 19:35:56 corruption seems pretty rare, and there isn't much
Devlin 2014/02/18 23:55:22 Oooh, good point. We can actually do more, becaus
77 if (result->HasError())
78 storage->Restore();
79
61 // It's fine to create the quota enforcer underneath the sync layer, since 80 // It's fine to create the quota enforcer underneath the sync layer, since
62 // sync will only go ahead if each underlying storage operation succeeds. 81 // sync will only go ahead if each underlying storage operation succeeds.
63 storage = new SettingsStorageQuotaEnforcer(quota_, storage); 82 storage = new SettingsStorageQuotaEnforcer(quota(), storage);
64 83
65 linked_ptr<SyncableSettingsStorage> syncable_storage( 84 linked_ptr<SyncableSettingsStorage> syncable_storage(
66 new SyncableSettingsStorage( 85 new SyncableSettingsStorage(
67 observers_, 86 observers_, extension_id, storage, sync_type_, flare_));
68 extension_id,
69 storage,
70 sync_type_,
71 flare_));
72 storage_objs_[extension_id] = syncable_storage; 87 storage_objs_[extension_id] = syncable_storage;
73 88
74 if (sync_processor_.get()) { 89 if (sync_processor_.get()) {
75 syncer::SyncError error = 90 syncer::SyncError error = syncable_storage->StartSyncing(
76 syncable_storage->StartSyncing( 91 sync_data, CreateSettingsSyncProcessor(extension_id).Pass());
77 sync_data,
78 CreateSettingsSyncProcessor(extension_id).Pass());
79 if (error.IsSet()) 92 if (error.IsSet())
80 syncable_storage.get()->StopSyncing(); 93 syncable_storage.get()->StopSyncing();
81 } 94 }
82 return syncable_storage.get(); 95 return syncable_storage.get();
83 } 96 }
84 97
85 void SettingsBackend::DeleteStorage(const std::string& extension_id) { 98 void SyncStorageBackend::DeleteStorage(const std::string& extension_id) {
86 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 99 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
87 100
88 // Clear settings when the extension is uninstalled. Leveldb implementations 101 // Clear settings when the extension is uninstalled. Leveldb implementations
89 // will also delete the database from disk when the object is destroyed as a 102 // will also delete the database from disk when the object is destroyed as a
90 // result of being removed from |storage_objs_|. 103 // result of being removed from |storage_objs_|.
91 // 104 //
92 // TODO(kalman): always GetStorage here (rather than only clearing if it 105 // TODO(kalman): always GetStorage here (rather than only clearing if it
93 // exists) since the storage area may have been unloaded, but we still want 106 // exists) since the storage area may have been unloaded, but we still want
94 // to clear the data from disk. 107 // to clear the data from disk.
95 // However, this triggers http://crbug.com/111072. 108 // However, this triggers http://crbug.com/111072.
96 StorageObjMap::iterator maybe_storage = storage_objs_.find(extension_id); 109 StorageObjMap::iterator maybe_storage = storage_objs_.find(extension_id);
97 if (maybe_storage == storage_objs_.end()) 110 if (maybe_storage == storage_objs_.end())
98 return; 111 return;
99 maybe_storage->second->Clear(); 112 maybe_storage->second->Clear();
100 storage_objs_.erase(extension_id); 113 storage_objs_.erase(extension_id);
101 } 114 }
102 115
103 std::set<std::string> SettingsBackend::GetKnownExtensionIDs() const { 116 syncer::SyncableService* SyncStorageBackend::GetAsSyncableService() {
117 return this;
118 }
119
120 std::set<std::string> SyncStorageBackend::GetKnownExtensionIDs() const {
104 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 121 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
105 std::set<std::string> result; 122 std::set<std::string> result;
106 123
107 // Storage areas can be in-memory as well as on disk. |storage_objs_| will 124 // Storage areas can be in-memory as well as on disk. |storage_objs_| will
108 // contain all that are in-memory. 125 // contain all that are in-memory.
109 for (StorageObjMap::iterator it = storage_objs_.begin(); 126 for (StorageObjMap::iterator it = storage_objs_.begin();
110 it != storage_objs_.end(); ++it) { 127 it != storage_objs_.end();
128 ++it) {
111 result.insert(it->first); 129 result.insert(it->first);
112 } 130 }
113 131
114 // Leveldb databases are directories inside base_path_. 132 // Leveldb databases are directories inside base_path().
115 base::FileEnumerator extension_dirs( 133 base::FileEnumerator extension_dirs(
116 base_path_, false, base::FileEnumerator::DIRECTORIES); 134 base_path(), false, base::FileEnumerator::DIRECTORIES);
117 while (!extension_dirs.Next().empty()) { 135 while (!extension_dirs.Next().empty()) {
118 base::FilePath extension_dir = extension_dirs.GetInfo().GetName(); 136 base::FilePath extension_dir = extension_dirs.GetInfo().GetName();
119 DCHECK(!extension_dir.IsAbsolute()); 137 DCHECK(!extension_dir.IsAbsolute());
120 // Extension IDs are created as std::strings so they *should* be ASCII. 138 // Extension IDs are created as std::strings so they *should* be ASCII.
121 std::string maybe_as_ascii(extension_dir.MaybeAsASCII()); 139 std::string maybe_as_ascii(extension_dir.MaybeAsASCII());
122 if (!maybe_as_ascii.empty()) { 140 if (!maybe_as_ascii.empty()) {
123 result.insert(maybe_as_ascii); 141 result.insert(maybe_as_ascii);
124 } 142 }
125 } 143 }
126 144
127 return result; 145 return result;
128 } 146 }
129 147
130 static void AddAllSyncData( 148 syncer::SyncDataList SyncStorageBackend::GetAllSyncData(syncer::ModelType type)
131 const std::string& extension_id, 149 const {
132 const base::DictionaryValue& src,
133 syncer::ModelType type,
134 syncer::SyncDataList* dst) {
135 for (base::DictionaryValue::Iterator it(src); !it.IsAtEnd(); it.Advance()) {
136 dst->push_back(settings_sync_util::CreateData(
137 extension_id, it.key(), it.value(), type));
138 }
139 }
140
141 syncer::SyncDataList SettingsBackend::GetAllSyncData(
142 syncer::ModelType type) const {
143 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 150 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
144 // Ignore the type, it's just for sanity checking; assume that whatever base 151 // Ignore the type, it's just for sanity checking; assume that whatever base
145 // path we're constructed with is correct for the sync type. 152 // path we're constructed with is correct for the sync type.
146 DCHECK(type == syncer::EXTENSION_SETTINGS || 153 DCHECK(type == syncer::EXTENSION_SETTINGS || type == syncer::APP_SETTINGS);
147 type == syncer::APP_SETTINGS);
148 154
149 // For all extensions, get all their settings. This has the effect 155 // For all extensions, get all their settings. This has the effect
150 // of bringing in the entire state of extension settings in memory; sad. 156 // of bringing in the entire state of extension settings in memory; sad.
151 syncer::SyncDataList all_sync_data; 157 syncer::SyncDataList all_sync_data;
152 std::set<std::string> known_extension_ids(GetKnownExtensionIDs()); 158 std::set<std::string> known_extension_ids(GetKnownExtensionIDs());
153 159
154 for (std::set<std::string>::const_iterator it = known_extension_ids.begin(); 160 for (std::set<std::string>::const_iterator it = known_extension_ids.begin();
155 it != known_extension_ids.end(); ++it) { 161 it != known_extension_ids.end();
156 ValueStore::ReadResult maybe_settings = GetStorage(*it)->Get(); 162 ++it) {
163 ValueStore::ReadResult maybe_settings =
164 GetOrCreateStorageWithSyncData(*it, base::DictionaryValue())->Get();
157 if (maybe_settings->HasError()) { 165 if (maybe_settings->HasError()) {
158 LOG(WARNING) << "Failed to get settings for " << *it << ": " << 166 LOG(WARNING) << "Failed to get settings for " << *it << ": "
159 maybe_settings->error().message; 167 << maybe_settings->error().message;
160 continue; 168 continue;
161 } 169 }
162 AddAllSyncData(*it, maybe_settings->settings(), type, &all_sync_data); 170 AddAllSyncData(*it, maybe_settings->settings(), type, &all_sync_data);
163 } 171 }
164 172
165 return all_sync_data; 173 return all_sync_data;
166 } 174 }
167 175
168 syncer::SyncMergeResult SettingsBackend::MergeDataAndStartSyncing( 176 syncer::SyncMergeResult SyncStorageBackend::MergeDataAndStartSyncing(
169 syncer::ModelType type, 177 syncer::ModelType type,
170 const syncer::SyncDataList& initial_sync_data, 178 const syncer::SyncDataList& initial_sync_data,
171 scoped_ptr<syncer::SyncChangeProcessor> sync_processor, 179 scoped_ptr<syncer::SyncChangeProcessor> sync_processor,
172 scoped_ptr<syncer::SyncErrorFactory> sync_error_factory) { 180 scoped_ptr<syncer::SyncErrorFactory> sync_error_factory) {
173 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 181 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
174 DCHECK_EQ(sync_type_, type); 182 DCHECK_EQ(sync_type_, type);
175 DCHECK(!sync_processor_.get()); 183 DCHECK(!sync_processor_.get());
176 DCHECK(sync_processor.get()); 184 DCHECK(sync_processor.get());
177 DCHECK(sync_error_factory.get()); 185 DCHECK(sync_error_factory.get());
178 186
179 sync_processor_ = sync_processor.Pass(); 187 sync_processor_ = sync_processor.Pass();
180 sync_error_factory_ = sync_error_factory.Pass(); 188 sync_error_factory_ = sync_error_factory.Pass();
181 189
182 // Group the initial sync data by extension id. 190 // Group the initial sync data by extension id.
183 std::map<std::string, linked_ptr<base::DictionaryValue> > grouped_sync_data; 191 std::map<std::string, linked_ptr<base::DictionaryValue> > grouped_sync_data;
184 for (syncer::SyncDataList::const_iterator it = initial_sync_data.begin(); 192 for (syncer::SyncDataList::const_iterator it = initial_sync_data.begin();
185 it != initial_sync_data.end(); ++it) { 193 it != initial_sync_data.end();
194 ++it) {
186 SettingSyncData data(*it); 195 SettingSyncData data(*it);
187 linked_ptr<base::DictionaryValue> sync_data = 196 linked_ptr<base::DictionaryValue> sync_data =
188 grouped_sync_data[data.extension_id()]; 197 grouped_sync_data[data.extension_id()];
189 if (!sync_data.get()) { 198 if (!sync_data.get()) {
190 sync_data = linked_ptr<base::DictionaryValue>( 199 sync_data =
191 new base::DictionaryValue()); 200 linked_ptr<base::DictionaryValue>(new base::DictionaryValue());
192 grouped_sync_data[data.extension_id()] = sync_data; 201 grouped_sync_data[data.extension_id()] = sync_data;
193 } 202 }
194 DCHECK(!sync_data->HasKey(data.key())) << 203 DCHECK(!sync_data->HasKey(data.key())) << "Duplicate settings for "
195 "Duplicate settings for " << data.extension_id() << "/" << data.key(); 204 << data.extension_id() << "/"
205 << data.key();
196 sync_data->SetWithoutPathExpansion(data.key(), data.value().DeepCopy()); 206 sync_data->SetWithoutPathExpansion(data.key(), data.value().DeepCopy());
197 } 207 }
198 208
199 // Start syncing all existing storage areas. Any storage areas created in 209 // Start syncing all existing storage areas. Any storage areas created in
200 // the future will start being synced as part of the creation process. 210 // the future will start being synced as part of the creation process.
201 for (StorageObjMap::iterator it = storage_objs_.begin(); 211 for (StorageObjMap::iterator it = storage_objs_.begin();
202 it != storage_objs_.end(); ++it) { 212 it != storage_objs_.end();
213 ++it) {
203 std::map<std::string, linked_ptr<base::DictionaryValue> >::iterator 214 std::map<std::string, linked_ptr<base::DictionaryValue> >::iterator
204 maybe_sync_data = grouped_sync_data.find(it->first); 215 maybe_sync_data = grouped_sync_data.find(it->first);
205 syncer::SyncError error; 216 syncer::SyncError error;
206 if (maybe_sync_data != grouped_sync_data.end()) { 217 if (maybe_sync_data != grouped_sync_data.end()) {
207 error = it->second->StartSyncing( 218 error = it->second->StartSyncing(
208 *maybe_sync_data->second, 219 *maybe_sync_data->second,
209 CreateSettingsSyncProcessor(it->first).Pass()); 220 CreateSettingsSyncProcessor(it->first).Pass());
210 grouped_sync_data.erase(it->first); 221 grouped_sync_data.erase(it->first);
211 } else { 222 } else {
212 base::DictionaryValue empty; 223 base::DictionaryValue empty;
213 error = it->second->StartSyncing( 224 error = it->second->StartSyncing(
214 empty, 225 empty, CreateSettingsSyncProcessor(it->first).Pass());
215 CreateSettingsSyncProcessor(it->first).Pass());
216 } 226 }
217 if (error.IsSet()) 227 if (error.IsSet())
218 it->second->StopSyncing(); 228 it->second->StopSyncing();
219 } 229 }
220 230
221 // Eagerly create and init the rest of the storage areas that have sync data. 231 // Eagerly create and init the rest of the storage areas that have sync data.
222 // Under normal circumstances (i.e. not first-time sync) this will be all of 232 // Under normal circumstances (i.e. not first-time sync) this will be all of
223 // them. 233 // them.
224 for (std::map<std::string, linked_ptr<base::DictionaryValue> >::iterator it = 234 for (std::map<std::string, linked_ptr<base::DictionaryValue> >::iterator it =
225 grouped_sync_data.begin(); it != grouped_sync_data.end(); ++it) { 235 grouped_sync_data.begin();
236 it != grouped_sync_data.end();
237 ++it) {
226 GetOrCreateStorageWithSyncData(it->first, *it->second); 238 GetOrCreateStorageWithSyncData(it->first, *it->second);
227 } 239 }
228 240
229 return syncer::SyncMergeResult(type); 241 return syncer::SyncMergeResult(type);
230 } 242 }
231 243
232 syncer::SyncError SettingsBackend::ProcessSyncChanges( 244 syncer::SyncError SyncStorageBackend::ProcessSyncChanges(
233 const tracked_objects::Location& from_here, 245 const tracked_objects::Location& from_here,
234 const syncer::SyncChangeList& sync_changes) { 246 const syncer::SyncChangeList& sync_changes) {
235 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 247 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
236 DCHECK(sync_processor_.get()); 248 DCHECK(sync_processor_.get());
237 249
238 // Group changes by extension, to pass all changes in a single method call. 250 // Group changes by extension, to pass all changes in a single method call.
239 std::map<std::string, SettingSyncDataList> grouped_sync_data; 251 std::map<std::string, SettingSyncDataList> grouped_sync_data;
240 for (syncer::SyncChangeList::const_iterator it = sync_changes.begin(); 252 for (syncer::SyncChangeList::const_iterator it = sync_changes.begin();
241 it != sync_changes.end(); ++it) { 253 it != sync_changes.end();
254 ++it) {
242 SettingSyncData data(*it); 255 SettingSyncData data(*it);
243 grouped_sync_data[data.extension_id()].push_back(data); 256 grouped_sync_data[data.extension_id()].push_back(data);
244 } 257 }
245 258
246 // Create any storage areas that don't exist yet but have sync data. 259 // Create any storage areas that don't exist yet but have sync data.
247 base::DictionaryValue empty; 260 base::DictionaryValue empty;
248 for (std::map<std::string, SettingSyncDataList>::iterator 261 for (std::map<std::string, SettingSyncDataList>::iterator it =
249 it = grouped_sync_data.begin(); it != grouped_sync_data.end(); ++it) { 262 grouped_sync_data.begin();
263 it != grouped_sync_data.end();
264 ++it) {
250 SyncableSettingsStorage* storage = 265 SyncableSettingsStorage* storage =
251 GetOrCreateStorageWithSyncData(it->first, empty); 266 GetOrCreateStorageWithSyncData(it->first, empty);
252 syncer::SyncError error = storage->ProcessSyncChanges(it->second); 267 syncer::SyncError error = storage->ProcessSyncChanges(it->second);
253 if (error.IsSet()) 268 if (error.IsSet())
254 storage->StopSyncing(); 269 storage->StopSyncing();
255 } 270 }
256 271
257 return syncer::SyncError(); 272 return syncer::SyncError();
258 } 273 }
259 274
260 void SettingsBackend::StopSyncing(syncer::ModelType type) { 275 void SyncStorageBackend::StopSyncing(syncer::ModelType type) {
261 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 276 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
262 DCHECK(type == syncer::EXTENSION_SETTINGS || 277 DCHECK(type == syncer::EXTENSION_SETTINGS || type == syncer::APP_SETTINGS);
263 type == syncer::APP_SETTINGS);
264 DCHECK_EQ(sync_type_, type); 278 DCHECK_EQ(sync_type_, type);
265 279
266 for (StorageObjMap::iterator it = storage_objs_.begin(); 280 for (StorageObjMap::iterator it = storage_objs_.begin();
267 it != storage_objs_.end(); ++it) { 281 it != storage_objs_.end();
282 ++it) {
268 // Some storage areas may have already stopped syncing if they had areas 283 // Some storage areas may have already stopped syncing if they had areas
269 // and syncing was disabled, but StopSyncing is safe to call multiple times. 284 // and syncing was disabled, but StopSyncing is safe to call multiple times.
270 it->second->StopSyncing(); 285 it->second->StopSyncing();
271 } 286 }
272 287
273 sync_processor_.reset(); 288 sync_processor_.reset();
274 sync_error_factory_.reset(); 289 sync_error_factory_.reset();
275 } 290 }
276 291
277 scoped_ptr<SettingsSyncProcessor> SettingsBackend::CreateSettingsSyncProcessor( 292 scoped_ptr<SettingsSyncProcessor>
278 const std::string& extension_id) const { 293 SyncStorageBackend::CreateSettingsSyncProcessor(const std::string& extension_id)
294 const {
279 CHECK(sync_processor_.get()); 295 CHECK(sync_processor_.get());
280 return scoped_ptr<SettingsSyncProcessor>( 296 return scoped_ptr<SettingsSyncProcessor>(new SettingsSyncProcessor(
281 new SettingsSyncProcessor(extension_id, 297 extension_id, sync_type_, sync_processor_.get()));
282 sync_type_,
283 sync_processor_.get()));
284 } 298 }
285 299
286 } // namespace extensions 300 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698