blob: efe07e282028fde7716a56541069e12fc39a77a3 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_SYNC_GLUE_SYNC_BACKEND_REGISTRAR_H_
#define CHROME_BROWSER_SYNC_GLUE_SYNC_BACKEND_REGISTRAR_H_
#include <map>
#include <vector>
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/memory/ref_counted.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread.h"
#include "sync/internal_api/public/base/model_type.h"
#include "sync/internal_api/public/engine/model_safe_worker.h"
#include "sync/internal_api/public/sync_manager.h"
class Profile;
namespace base {
class MessageLoop;
}
namespace syncer {
struct UserShare;
} // namespace syncer
namespace browser_sync {
class ChangeProcessor;
class UIModelWorker;
// A class that keep track of the workers, change processors, and
// routing info for the enabled sync types, and also routes change
// events to the right processors.
class SyncBackendRegistrar : public syncer::SyncManager::ChangeDelegate,
public syncer::WorkerLoopDestructionObserver {
public:
// |name| is used for debugging. Does not take ownership of |profile| or
// |sync_loop|. Must be created on the UI thread.
SyncBackendRegistrar(const std::string& name,
Profile* profile,
scoped_ptr<base::Thread> sync_thread);
// SyncBackendRegistrar must be destroyed as follows:
//
// 1) On the UI thread, call RequestWorkerStopOnUIThread().
// 2) UI posts task to shut down syncer on sync thread.
// 3) If sync is disabled, call ReleaseSyncThread() on the UI thread.
// 3) UI posts SyncBackendRegistrar::ShutDown() on sync thread to
// unregister workers from observing destruction of their working loops.
// 4) Workers notify registrar when unregistration finishes or working
// loops are destroyed. Registrar destroys itself on last worker
// notification. Sync thread will be stopped if ownership was not
// released.
virtual ~SyncBackendRegistrar();
// Informs the SyncBackendRegistrar of the currently enabled set of types.
// These types will be placed in the passive group. This function should be
// called exactly once during startup.
void SetInitialTypes(syncer::ModelTypeSet initial_types);
// Returns whether or not we are currently syncing encryption keys.
// Must be called on the UI thread.
bool IsNigoriEnabled() const;
// Removes all types in |types_to_remove| from the routing info and
// adds all the types in |types_to_add| to the routing info that are
// not already there (initially put in the passive group).
// |types_to_remove| and |types_to_add| must be disjoint. Returns
// the set of newly-added types. Must be called on the UI thread.
syncer::ModelTypeSet ConfigureDataTypes(
syncer::ModelTypeSet types_to_add,
syncer::ModelTypeSet types_to_remove);
// Returns the set of enabled types as of the last configuration. Note that
// this might be different from the current types in the routing info due
// to DeactiveDataType being called separately from ConfigureDataTypes.
syncer::ModelTypeSet GetLastConfiguredTypes() const;
// Must be called from the UI thread. (See destructor comment.)
void RequestWorkerStopOnUIThread();
// Activates the given data type (which should belong to the given
// group) and starts the given change processor. Must be called
// from |group|'s native thread.
void ActivateDataType(syncer::ModelType type,
syncer::ModelSafeGroup group,
ChangeProcessor* change_processor,
syncer::UserShare* user_share);
// Deactivates the given type if necessary. Must be called from the
// UI thread and not |type|'s native thread. Yes, this is
// surprising: see http://crbug.com/92804.
void DeactivateDataType(syncer::ModelType type);
// Returns true only between calls to ActivateDataType(type, ...)
// and DeactivateDataType(type). Used only by tests.
bool IsTypeActivatedForTest(syncer::ModelType type) const;
// SyncManager::ChangeDelegate implementation. May be called from
// any thread.
virtual void OnChangesApplied(
syncer::ModelType model_type,
int64 model_version,
const syncer::BaseTransaction* trans,
const syncer::ImmutableChangeRecordList& changes) OVERRIDE;
virtual void OnChangesComplete(syncer::ModelType model_type) OVERRIDE;
void GetWorkers(std::vector<syncer::ModelSafeWorker*>* out);
void GetModelSafeRoutingInfo(syncer::ModelSafeRoutingInfo* out);
// syncer::WorkerLoopDestructionObserver implementation.
virtual void OnWorkerLoopDestroyed(syncer::ModelSafeGroup group) OVERRIDE;
// Release ownership of |sync_thread_|. Called when sync is disabled.
scoped_ptr<base::Thread> ReleaseSyncThread();
// Unregister workers from loop destruction observation.
void Shutdown();
base::Thread* sync_thread();
private:
typedef std::map<syncer::ModelSafeGroup,
scoped_refptr<syncer::ModelSafeWorker> > WorkerMap;
typedef std::map<syncer::ModelType, ChangeProcessor*>
ProcessorMap;
// Callback after workers unregister from observing destruction of their
// working loops.
void OnWorkerUnregistrationDone(syncer::ModelSafeGroup group);
void RemoveWorker(syncer::ModelSafeGroup group);
// Returns the change processor for the given model, or NULL if none
// exists. Must be called from |group|'s native thread.
ChangeProcessor* GetProcessor(syncer::ModelType type) const;
// Must be called with |lock_| held. Simply returns the change
// processor for the given type, if it exists. May be called from
// any thread.
ChangeProcessor* GetProcessorUnsafe(syncer::ModelType type) const;
// Return true if |model_type| lives on the current thread. Must be
// called with |lock_| held. May be called on any thread.
bool IsCurrentThreadSafeForModel(
syncer::ModelType model_type) const;
// Name used for debugging.
const std::string name_;
Profile* const profile_;
// Protects all variables below.
mutable base::Lock lock_;
// We maintain ownership of all workers. In some cases, we need to
// ensure shutdown occurs in an expected sequence by Stop()ing
// certain workers. They are guaranteed to be valid because we only
// destroy elements of |workers_| after the syncapi has been
// destroyed. Unless a worker is no longer needed because all types
// that get routed to it have been disabled (from syncing). In that
// case, we'll destroy on demand *after* routing any dependent types
// to syncer::GROUP_PASSIVE, so that the syncapi doesn't call into garbage.
// If a key is present, it means at least one ModelType that routes
// to that model safe group is being synced.
WorkerMap workers_;
syncer::ModelSafeRoutingInfo routing_info_;
// The change processors that handle the different data types.
ProcessorMap processors_;
// The types that were enabled as of the last configuration. Updated on each
// call to ConfigureDataTypes as well as SetInitialTypes.
syncer::ModelTypeSet last_configured_types_;
// Parks stopped workers because they may still be referenced by syncer.
std::vector<scoped_refptr<syncer::ModelSafeWorker> > stopped_workers_;
// Declare |sync_thread_| at the end so that it will be destroyed before
// objects above because tasks on sync thread depend on those objects,
// e.g. Shutdown() depends on |lock_|, SyncManager::Init() depends on
// workers, etc.
scoped_ptr<base::Thread> sync_thread_;
DISALLOW_COPY_AND_ASSIGN(SyncBackendRegistrar);
};
} // namespace browser_sync
#endif // CHROME_BROWSER_SYNC_GLUE_SYNC_BACKEND_REGISTRAR_H_