blob: 35cacb01f050e17475d677c71485e2613c4a10aa [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_NON_FRONTEND_DATA_TYPE_CONTROLLER_H__
#define CHROME_BROWSER_SYNC_GLUE_NON_FRONTEND_DATA_TYPE_CONTROLLER_H__
#include <string>
#include "base/basictypes.h"
#include "base/callback_forward.h"
#include "base/compiler_specific.h"
#include "base/memory/scoped_ptr.h"
#include "base/synchronization/lock.h"
#include "base/synchronization/waitable_event.h"
#include "chrome/browser/sync/glue/data_type_controller.h"
#include "chrome/browser/sync/glue/data_type_error_handler.h"
#include "chrome/browser/sync/profile_sync_components_factory.h"
class Profile;
class ProfileSyncService;
class ProfileSyncComponentsFactory;
namespace base {
class TimeDelta;
}
namespace syncer {
class SyncError;
}
namespace browser_sync {
class AssociatorInterface;
class ChangeProcessor;
// Implementation for datatypes that do not reside on the frontend thread
// (UI thread). This is the same thread we perform initialization
// on, so we don't have to worry about thread safety. The main start/stop
// functionality is implemented by default. Derived classes must implement:
// type()
// model_safe_group()
// PostTaskOnBackendThread()
// CreateSyncComponents()
class NonFrontendDataTypeController : public DataTypeController {
public:
// For creating non-frontend processor/associator and associating on backend.
class BackendComponentsContainer;
NonFrontendDataTypeController(
ProfileSyncComponentsFactory* profile_sync_factory,
Profile* profile,
ProfileSyncService* sync_service);
// DataTypeController interface.
virtual void LoadModels(
const ModelLoadCallback& model_load_callback) OVERRIDE;
virtual void StartAssociating(const StartCallback& start_callback) OVERRIDE;
virtual void Stop() OVERRIDE;
virtual syncer::ModelType type() const = 0;
virtual syncer::ModelSafeGroup model_safe_group() const = 0;
virtual std::string name() const OVERRIDE;
virtual State state() const OVERRIDE;
// DataTypeErrorHandler interface.
// Note: this is performed on the datatype's thread.
virtual void OnSingleDatatypeUnrecoverableError(
const tracked_objects::Location& from_here,
const std::string& message) OVERRIDE;
// Callback to receive background association results.
struct AssociationResult {
explicit AssociationResult(syncer::ModelType type);
~AssociationResult();
bool needs_crypto;
bool unrecoverable_error;
bool sync_has_nodes;
syncer::SyncError error;
syncer::SyncMergeResult local_merge_result;
syncer::SyncMergeResult syncer_merge_result;
base::TimeDelta association_time;
ChangeProcessor* change_processor;
AssociatorInterface* model_associator;
};
void AssociationCallback(AssociationResult result);
protected:
// For testing only.
NonFrontendDataTypeController();
virtual ~NonFrontendDataTypeController();
// DataTypeController interface.
virtual void OnModelLoaded() OVERRIDE;
// Start any dependent services that need to be running before we can
// associate models. The default implementation is a no-op.
// Return value:
// True - if models are ready and association can proceed.
// False - if models are not ready. StartAssociationAsync should be called
// when the models are ready.
// Note: this is performed on the frontend (UI) thread.
virtual bool StartModels();
// Posts the given task to the backend thread, i.e. the thread the
// datatype lives on. Return value: True if task posted successfully,
// false otherwise.
// NOTE: The StopAssociationAsync() implementation relies on the fact that
// implementations of this API do not hold any references to the DTC while
// the task is executing. See http://crbug.com/127706.
virtual bool PostTaskOnBackendThread(
const tracked_objects::Location& from_here,
const base::Closure& task) = 0;
// Datatype specific creation of sync components.
// Note: this is performed on the datatype's thread.
virtual ProfileSyncComponentsFactory::SyncComponents
CreateSyncComponents() = 0;
// Called on UI thread during shutdown to effectively disable processing
// any changes.
virtual void DisconnectProcessor(ChangeProcessor* processor) = 0;
// Start up complete, update the state and invoke the callback.
// Note: this is performed on the datatype's thread.
virtual void StartDone(
DataTypeController::StartResult start_result,
const syncer::SyncMergeResult& local_merge_result,
const syncer::SyncMergeResult& syncer_merge_result);
// UI thread implementation of StartDone.
virtual void StartDoneImpl(
DataTypeController::StartResult start_result,
DataTypeController::State new_state,
const syncer::SyncMergeResult& local_merge_result,
const syncer::SyncMergeResult& syncer_merge_result);
// The actual implementation of Disabling the datatype. This happens
// on the UI thread.
virtual void DisableImpl(const tracked_objects::Location& from_here,
const std::string& message);
// Record association time. Called on Datatype's thread.
virtual void RecordAssociationTime(base::TimeDelta time);
// Record causes of start failure. Called on UI thread.
virtual void RecordStartFailure(StartResult result);
// Accessors and mutators used by derived classes.
ProfileSyncComponentsFactory* profile_sync_factory() const;
Profile* profile() const;
ProfileSyncService* profile_sync_service() const;
void set_start_callback(const StartCallback& callback);
void set_state(State state);
virtual AssociatorInterface* associator() const;
virtual ChangeProcessor* change_processor() const;
State state_;
StartCallback start_callback_;
ModelLoadCallback model_load_callback_;
private:
friend class BackendComponentsContainer;
ProfileSyncComponentsFactory* const profile_sync_factory_;
Profile* const profile_;
ProfileSyncService* const profile_sync_service_;
// Created on UI thread and passed to backend to create processor/associator
// and associate model. Released on backend.
scoped_ptr<BackendComponentsContainer> components_container_;
AssociatorInterface* model_associator_;
ChangeProcessor* change_processor_;
base::WeakPtrFactory<NonFrontendDataTypeController> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(NonFrontendDataTypeController);
};
} // namespace browser_sync
#endif // CHROME_BROWSER_SYNC_GLUE_NON_FRONTEND_DATA_TYPE_CONTROLLER_H__