15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sync/glue/sync_backend_registrar.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <cstddef> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 119ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/history_service_factory.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/password_manager/password_store_factory.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sync/glue/browser_thread_model_worker.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sync/glue/history_model_worker.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sync/glue/password_model_worker.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/sync/glue/ui_model_worker.h" 195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "components/password_manager/core/browser/password_store.h" 200529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "components/sync_driver/change_processor.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/internal_api/public/engine/passive_model_worker.h" 23a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "sync/internal_api/public/user_share.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread; 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace browser_sync { 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true if the current thread is the native thread for the 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// given group (or if it is undeterminable). 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool IsOnThreadForGroup(syncer::ModelType type, syncer::ModelSafeGroup group) { 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (group) { 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case syncer::GROUP_PASSIVE: 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return IsControlType(type); 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case syncer::GROUP_UI: 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return BrowserThread::CurrentlyOn(BrowserThread::UI); 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case syncer::GROUP_DB: 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return BrowserThread::CurrentlyOn(BrowserThread::DB); 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case syncer::GROUP_FILE: 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return BrowserThread::CurrentlyOn(BrowserThread::FILE); 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case syncer::GROUP_HISTORY: 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(sync): How to check we're on the right thread? 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return type == syncer::TYPED_URLS; 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case syncer::GROUP_PASSWORD: 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(sync): How to check we're on the right thread? 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return type == syncer::PASSWORDS; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case syncer::MODEL_SAFE_GROUP_COUNT: 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SyncBackendRegistrar::SyncBackendRegistrar( 58a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) const std::string& name, 59a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) Profile* profile, 60a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) scoped_ptr<base::Thread> sync_thread) : 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name_(name), 62a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) profile_(profile) { 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(profile_); 65a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 66a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) sync_thread_ = sync_thread.Pass(); 67a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (!sync_thread_) { 68a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) sync_thread_.reset(new base::Thread("Chrome_SyncThread")); 69116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch base::Thread::Options options; 70116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch options.timer_slack = base::TIMER_SLACK_MAXIMUM; 71116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch CHECK(sync_thread_->StartWithOptions(options)); 72a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 73a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) workers_[syncer::GROUP_DB] = new DatabaseModelWorker(this); 75a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) workers_[syncer::GROUP_DB]->RegisterForLoopDestruction(); 76a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) workers_[syncer::GROUP_FILE] = new FileModelWorker(this); 78a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) workers_[syncer::GROUP_FILE]->RegisterForLoopDestruction(); 79a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 80a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) workers_[syncer::GROUP_UI] = new UIModelWorker(this); 81a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) workers_[syncer::GROUP_UI]->RegisterForLoopDestruction(); 82a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 83a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // GROUP_PASSIVE worker does work on sync_loop_. But sync_loop_ is not 84a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // stopped until all workers have stopped. To break the cycle, use UI loop 85a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // instead. 86a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) workers_[syncer::GROUP_PASSIVE] = 87a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) new syncer::PassiveModelWorker(sync_thread_->message_loop(), this); 88a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) workers_[syncer::GROUP_PASSIVE]->RegisterForLoopDestruction(); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HistoryService* history_service = 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HistoryServiceFactory::GetForProfile(profile, Profile::IMPLICIT_ACCESS); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (history_service) { 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) workers_[syncer::GROUP_HISTORY] = 9490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) new HistoryModelWorker(history_service->AsWeakPtr(), this); 95a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) workers_[syncer::GROUP_HISTORY]->RegisterForLoopDestruction(); 96a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 99c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch scoped_refptr<password_manager::PasswordStore> password_store = 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PasswordStoreFactory::GetForProfile(profile, Profile::IMPLICIT_ACCESS); 101868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (password_store.get()) { 102868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) workers_[syncer::GROUP_PASSWORD] = 103868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) new PasswordModelWorker(password_store, this); 104a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) workers_[syncer::GROUP_PASSWORD]->RegisterForLoopDestruction(); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncBackendRegistrar::SetInitialTypes(syncer::ModelTypeSet initial_types) { 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock lock(lock_); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 111a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // This function should be called only once, shortly after construction. The 112a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // routing info at that point is expected to be empty. 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(routing_info_.empty()); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set our initial state to reflect the current status of the sync directory. 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This will ensure that our calculations in ConfigureDataTypes() will always 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // return correct results. 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (syncer::ModelTypeSet::Iterator it = initial_types.First(); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it.Good(); it.Inc()) { 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) routing_info_[it.Get()] = syncer::GROUP_PASSIVE; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!workers_.count(syncer::GROUP_HISTORY)) { 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG_IF(WARNING, initial_types.Has(syncer::TYPED_URLS)) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "History store disabled, cannot sync Omnibox History"; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) routing_info_.erase(syncer::TYPED_URLS); 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!workers_.count(syncer::GROUP_PASSWORD)) { 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG_IF(WARNING, initial_types.Has(syncer::PASSWORDS)) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "Password store not initialized, cannot sync passwords"; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) routing_info_.erase(syncer::PASSWORDS); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 135eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch last_configured_types_ = syncer::GetRoutingInfoTypes(routing_info_); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SyncBackendRegistrar::IsNigoriEnabled() const { 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock lock(lock_); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return routing_info_.find(syncer::NIGORI) != routing_info_.end(); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)syncer::ModelTypeSet SyncBackendRegistrar::ConfigureDataTypes( 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::ModelTypeSet types_to_add, 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::ModelTypeSet types_to_remove) { 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(Intersection(types_to_add, types_to_remove).Empty()); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::ModelTypeSet filtered_types_to_add = types_to_add; 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (workers_.count(syncer::GROUP_HISTORY) == 0) { 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "No history worker -- removing TYPED_URLS"; 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) filtered_types_to_add.Remove(syncer::TYPED_URLS); 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (workers_.count(syncer::GROUP_PASSWORD) == 0) { 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "No password worker -- removing PASSWORDS"; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) filtered_types_to_add.Remove(syncer::PASSWORDS); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock lock(lock_); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::ModelTypeSet newly_added_types; 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (syncer::ModelTypeSet::Iterator it = 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) filtered_types_to_add.First(); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it.Good(); it.Inc()) { 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add a newly specified data type as syncer::GROUP_PASSIVE into the 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // routing_info, if it does not already exist. 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (routing_info_.count(it.Get()) == 0) { 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) routing_info_[it.Get()] = syncer::GROUP_PASSIVE; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) newly_added_types.Put(it.Get()); 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (syncer::ModelTypeSet::Iterator it = types_to_remove.First(); 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it.Good(); it.Inc()) { 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) routing_info_.erase(it.Get()); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(akalin): Use SVLOG/SLOG if we add any more logging. 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DVLOG(1) << name_ << ": Adding types " 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << syncer::ModelTypeSetToString(types_to_add) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " (with newly-added types " 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << syncer::ModelTypeSetToString(newly_added_types) 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << ") and removing types " 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << syncer::ModelTypeSetToString(types_to_remove) 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " to get new routing info " 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) <<syncer::ModelSafeRoutingInfoToString(routing_info_); 184eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch last_configured_types_ = syncer::GetRoutingInfoTypes(routing_info_); 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return newly_added_types; 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 189eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochsyncer::ModelTypeSet SyncBackendRegistrar::GetLastConfiguredTypes() const { 190eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch return last_configured_types_; 191eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch} 192eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 193a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void SyncBackendRegistrar::RequestWorkerStopOnUIThread() { 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 195a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) base::AutoLock lock(lock_); 196a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) for (WorkerMap::const_iterator it = workers_.begin(); 197a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) it != workers_.end(); ++it) { 198a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) it->second->RequestStop(); 199a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncBackendRegistrar::ActivateDataType( 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::ModelType type, 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::ModelSafeGroup group, 2055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) sync_driver::ChangeProcessor* change_processor, 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::UserShare* user_share) { 207a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) DVLOG(1) << "Activate: " << syncer::ModelTypeToString(type); 208a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock lock(lock_); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ensure that the given data type is in the PASSIVE group. 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::ModelSafeRoutingInfo::iterator i = routing_info_.find(type); 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(i != routing_info_.end()); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(i->second, syncer::GROUP_PASSIVE); 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) routing_info_[type] = group; 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add the data type's change processor to the list of change 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // processors so it can receive updates. 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(processors_.count(type), 0U); 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) processors_[type] = change_processor; 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Start the change processor. 2220529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch change_processor->Start(user_share); 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(GetProcessorUnsafe(type)); 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncBackendRegistrar::DeactivateDataType(syncer::ModelType type) { 227a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) DVLOG(1) << "Deactivate: " << syncer::ModelTypeToString(type); 228a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) || IsControlType(type)); 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock lock(lock_); 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) routing_info_.erase(type); 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ignore_result(processors_.erase(type)); 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!GetProcessorUnsafe(type)); 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SyncBackendRegistrar::IsTypeActivatedForTest( 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::ModelType type) const { 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetProcessor(type) != NULL; 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncBackendRegistrar::OnChangesApplied( 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::ModelType model_type, 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 model_version, 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const syncer::BaseTransaction* trans, 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const syncer::ImmutableChangeRecordList& changes) { 2475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) sync_driver::ChangeProcessor* processor = GetProcessor(model_type); 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!processor) 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) processor->ApplyChangesFromSyncModel(trans, model_version, changes); 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncBackendRegistrar::OnChangesComplete(syncer::ModelType model_type) { 2555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) sync_driver::ChangeProcessor* processor = GetProcessor(model_type); 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!processor) 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This call just notifies the processor that it can commit; it 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // already buffered any changes it plans to makes so needs no 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // further information. 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) processor->CommitChangesFromSyncModel(); 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncBackendRegistrar::GetWorkers( 2665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::vector<scoped_refptr<syncer::ModelSafeWorker> >* out) { 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock lock(lock_); 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) out->clear(); 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (WorkerMap::const_iterator it = workers_.begin(); 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != workers_.end(); ++it) { 271868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) out->push_back(it->second.get()); 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SyncBackendRegistrar::GetModelSafeRoutingInfo( 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::ModelSafeRoutingInfo* out) { 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock lock(lock_); 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::ModelSafeRoutingInfo copy(routing_info_); 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) out->swap(copy); 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)sync_driver::ChangeProcessor* SyncBackendRegistrar::GetProcessor( 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::ModelType type) const { 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::AutoLock lock(lock_); 2855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) sync_driver::ChangeProcessor* processor = GetProcessorUnsafe(type); 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!processor) 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We can only check if |processor| exists, as otherwise the type is 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // mapped to syncer::GROUP_PASSIVE. 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(IsCurrentThreadSafeForModel(type)); 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return processor; 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)sync_driver::ChangeProcessor* SyncBackendRegistrar::GetProcessorUnsafe( 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::ModelType type) const { 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lock_.AssertAcquired(); 2985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::map<syncer::ModelType, sync_driver::ChangeProcessor*>::const_iterator 299a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) it = processors_.find(type); 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Until model association happens for a datatype, it will not 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // appear in the processors list. During this time, it is OK to 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // drop changes on the floor (since model association has not 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // happened yet). When the data type is activated, model 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // association takes place then the change processor is added to the 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |processors_| list. 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it == processors_.end()) 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return it->second; 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SyncBackendRegistrar::IsCurrentThreadSafeForModel( 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) syncer::ModelType model_type) const { 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lock_.AssertAcquired(); 3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return IsOnThreadForGroup(model_type, 3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetGroupForModelType(model_type, routing_info_)); 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 320a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)SyncBackendRegistrar::~SyncBackendRegistrar() { 321a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) DCHECK(workers_.empty()); 322a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 323a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 32490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void SyncBackendRegistrar::OnWorkerLoopDestroyed(syncer::ModelSafeGroup group) { 325a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) RemoveWorker(group); 326a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 327a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 328a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void SyncBackendRegistrar::OnWorkerUnregistrationDone( 329a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) syncer::ModelSafeGroup group) { 330a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) RemoveWorker(group); 331a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 332a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 333a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void SyncBackendRegistrar::RemoveWorker(syncer::ModelSafeGroup group) { 334a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) DVLOG(1) << "Remove " << ModelSafeGroupToString(group) << " worker."; 335a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 336a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) bool last_worker = false; 337a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) { 338a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) base::AutoLock al(lock_); 339a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) WorkerMap::iterator it = workers_.find(group); 340a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) CHECK(it != workers_.end()); 341a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) stopped_workers_.push_back(it->second); 342a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) workers_.erase(it); 343a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) last_worker = workers_.empty(); 344a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 345a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 346a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (last_worker) { 347a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Self-destruction after last worker. 348a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) DVLOG(1) << "Destroy registrar on loop of " 349a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) << ModelSafeGroupToString(group); 350a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) delete this; 351a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 352a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 353a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 354a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)scoped_ptr<base::Thread> SyncBackendRegistrar::ReleaseSyncThread() { 355a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return sync_thread_.Pass(); 356a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 357a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 358a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void SyncBackendRegistrar::Shutdown() { 359a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // All data types should have been deactivated by now. 360a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) DCHECK(processors_.empty()); 361a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 362a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Unregister worker from observing loop destruction. 363a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) base::AutoLock al(lock_); 364a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) for (WorkerMap::iterator it = workers_.begin(); 365a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) it != workers_.end(); ++it) { 366a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) it->second->UnregisterForLoopDestruction( 367a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) base::Bind(&SyncBackendRegistrar::OnWorkerUnregistrationDone, 368a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) base::Unretained(this))); 369a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 370a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)} 371a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 372a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)base::Thread* SyncBackendRegistrar::sync_thread() { 373a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return sync_thread_.get(); 37490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 37590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace browser_sync 377