1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/glue/preference_change_processor.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <set> 8c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <string> 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/auto_reset.h" 11c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/json/json_reader.h" 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/utf_string_conversions.h" 1321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h" 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/glue/preference_model_associator.h" 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/profile_sync_service.h" 16c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/sync/protocol/preference_specifics.pb.h" 17c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/pref_names.h" 18dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/browser_thread.h" 19ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/json_value_serializer.h" 20ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_details.h" 21ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_source.h" 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace browser_sync { 24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochPreferenceChangeProcessor::PreferenceChangeProcessor( 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PreferenceModelAssociator* model_associator, 27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UnrecoverableErrorHandler* error_handler) 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : ChangeProcessor(error_handler), 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pref_service_(NULL), 303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick model_associator_(model_associator), 313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick processing_pref_change_(false) { 32731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(model_associator); 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(error_handler); 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochPreferenceChangeProcessor::~PreferenceChangeProcessor() { 38731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid PreferenceChangeProcessor::Observe(NotificationType type, 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const NotificationSource& source, 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const NotificationDetails& details) { 44731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(running()); 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(NotificationType::PREF_CHANGED == type); 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_EQ(pref_service_, Source<PrefService>(source).ptr()); 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Avoid recursion. 503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (processing_pref_change_) 513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return; 523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick AutoReset<bool> guard(&processing_pref_change_, true); 543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick std::string* name = Details<std::string>(details).ptr(); 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const PrefService::Preference* preference = 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pref_service_->FindPreference((*name).c_str()); 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(preference); 583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick int64 sync_id = model_associator_->GetSyncIdFromChromeId(*name); 593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick bool user_modifiable = preference->IsUserModifiable(); 603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!user_modifiable) { 613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // We do not track preferences the user cannot change. 623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick model_associator_->Disassociate(sync_id); 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 66c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sync_api::WriteTransaction trans(share_handle()); 67c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sync_api::WriteNode node(&trans); 68c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Since we don't create sync nodes for preferences that are not under control 703345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // of the user or still have their default value, this changed preference may 713345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // not have a sync node yet. If so, we create a node. Similarly, a preference 723345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // may become user-modifiable (e.g. due to laxer policy configuration), in 733345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // which case we also need to create a sync node and associate it. 74c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (sync_api::kInvalidId == sync_id) { 75c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sync_api::ReadNode root(&trans); 76c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!root.InitByTagLookup(browser_sync::kPreferencesTag)) { 77c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_handler()->OnUnrecoverableError(FROM_HERE, "Can't find root."); 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 80c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // InitPrefNodeAndAssociate takes care of writing the value to the sync 823345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // node if appropriate. 833345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!model_associator_->InitPrefNodeAndAssociate(&trans, 843345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick root, 853345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick preference)) { 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_handler()->OnUnrecoverableError(FROM_HERE, 873345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick "Can't create sync node."); 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 893345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return; 903345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 913345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!node.InitByIdLookup(sync_id)) { 933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick error_handler()->OnUnrecoverableError(FROM_HERE, 943345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick "Preference node lookup failed."); 953345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return; 96c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!PreferenceModelAssociator::WritePreferenceToNode( 99c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch preference->name(), 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch *preference->GetValue(), 101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &node)) { 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_handler()->OnUnrecoverableError(FROM_HERE, 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Failed to update preference node."); 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid PreferenceChangeProcessor::ApplyChangesFromSyncModel( 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const sync_api::BaseTransaction* trans, 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const sync_api::SyncManager::ChangeRecord* changes, 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int change_count) { 112731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!running()) 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StopObserving(); 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int i = 0; i < change_count; ++i) { 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sync_api::ReadNode node(trans); 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // TODO(ncarter): Can't look up the name for deletions: lookup of 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // deleted items fails at the syncapi layer. However, the node should 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // generally still exist in the syncable database; we just need to 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // plumb the syncapi so that it succeeds. 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (sync_api::SyncManager::ChangeRecord::ACTION_DELETE == 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch changes[i].action) { 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Until the above is fixed, we have no choice but to ignore deletions. 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << "No way to handle pref deletion"; 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch continue; 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!node.InitByIdLookup(changes[i].id)) { 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_handler()->OnUnrecoverableError(FROM_HERE, 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "Preference node lookup failed."); 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return; 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(syncable::PREFERENCES == node.GetModelType()); 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick std::string name; 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<Value> value(ReadPreference(&node, &name)); 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Skip values we can't deserialize. 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!value.get()) 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch continue; 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // It is possible that we may receive a change to a preference we 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // do not want to sync. For example if the user is syncing a Mac 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // client and a Windows client, the Windows client does not 146ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // support kConfirmToQuitEnabled. Ignore updates from these 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // preferences. 1483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const char* pref_name = name.c_str(); 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (model_associator_->synced_preferences().count(pref_name) == 0) 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch continue; 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Don't try to overwrite preferences not controllable by the user. 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const PrefService::Preference* pref = 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pref_service_->FindPreference(pref_name); 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(pref); 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!pref->IsUserModifiable()) 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch continue; 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (sync_api::SyncManager::ChangeRecord::ACTION_DELETE == 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch changes[i].action) { 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pref_service_->ClearPref(pref_name); 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pref_service_->Set(pref_name, *value); 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If this is a newly added node, associate. 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (sync_api::SyncManager::ChangeRecord::ACTION_ADD == 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch changes[i].action) { 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const PrefService::Preference* preference = 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pref_service_->FindPreference(name.c_str()); 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model_associator_->Associate(preference, changes[i].id); 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model_associator_->AfterUpdateOperations(name); 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StartObserving(); 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochValue* PreferenceChangeProcessor::ReadPreference( 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sync_api::ReadNode* node, 1813345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick std::string* name) { 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const sync_pb::PreferenceSpecifics& preference( 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch node->GetPreferenceSpecifics()); 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::JSONReader reader; 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch scoped_ptr<Value> value(reader.JsonToValue(preference.value(), false, false)); 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!value.get()) { 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string err = "Failed to deserialize preference value: " + 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch reader.GetErrorMessage(); 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch error_handler()->OnUnrecoverableError(FROM_HERE, err); 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return NULL; 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 1923345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick *name = preference.name(); 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return value.release(); 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid PreferenceChangeProcessor::StartImpl(Profile* profile) { 197731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pref_service_ = profile->GetPrefs(); 1993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick registrar_.Init(pref_service_); 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StartObserving(); 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 203c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid PreferenceChangeProcessor::StopImpl() { 204731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 205c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch StopObserving(); 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch pref_service_ = NULL; 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid PreferenceChangeProcessor::StartObserving() { 211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(pref_service_); 2123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick for (std::set<std::string>::const_iterator it = 213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model_associator_->synced_preferences().begin(); 214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch it != model_associator_->synced_preferences().end(); ++it) { 2153345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick registrar_.Add((*it).c_str(), this); 216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid PreferenceChangeProcessor::StopObserving() { 220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(pref_service_); 2213345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick for (std::set<std::string>::const_iterator it = 222c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch model_associator_->synced_preferences().begin(); 223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch it != model_associator_->synced_preferences().end(); ++it) { 2243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick registrar_.Remove((*it).c_str(), this); 225c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 228c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} // namespace browser_sync 229