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