summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorzea@chromium.org <zea@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-19 00:25:40 +0000
committerzea@chromium.org <zea@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-19 00:25:40 +0000
commit0e194cc6261463902915398c3d975d4de64852ff (patch)
tree67494192dd9f87a25334d5e5ab4eeaa00b1e1d4a /chrome
parent4d9a7a854d510f9261b5a918ea1f3ac8ea73c78d (diff)
downloadchromium_src-0e194cc6261463902915398c3d975d4de64852ff.zip
chromium_src-0e194cc6261463902915398c3d975d4de64852ff.tar.gz
chromium_src-0e194cc6261463902915398c3d975d4de64852ff.tar.bz2
Revert 82028 - Reland r81454 (sync non-frontend datatype controllers) with longer timeouts.Original codereview: http://codereview.chromium.org/6811003BUG=77964TEST=unitReview URL: http://codereview.chromium.org/6869016
TBR=zea@chromium.org Review URL: http://codereview.chromium.org/6882032 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@82036 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/profiles/profile_impl.cc1
-rw-r--r--chrome/browser/sync/glue/autofill_data_type_controller.cc316
-rw-r--r--chrome/browser/sync/glue/autofill_data_type_controller.h100
-rw-r--r--chrome/browser/sync/glue/autofill_data_type_controller_unittest.cc5
-rw-r--r--chrome/browser/sync/glue/autofill_profile_data_type_controller.cc55
-rw-r--r--chrome/browser/sync/glue/autofill_profile_data_type_controller.h16
-rw-r--r--chrome/browser/sync/glue/bookmark_data_type_controller.cc2
-rw-r--r--chrome/browser/sync/glue/bookmark_data_type_controller.h2
-rw-r--r--chrome/browser/sync/glue/frontend_data_type_controller.cc58
-rw-r--r--chrome/browser/sync/glue/frontend_data_type_controller.h29
-rw-r--r--chrome/browser/sync/glue/frontend_data_type_controller_mock.h8
-rw-r--r--chrome/browser/sync/glue/frontend_data_type_controller_unittest.cc20
-rw-r--r--chrome/browser/sync/glue/non_frontend_data_type_controller.cc279
-rw-r--r--chrome/browser/sync/glue/non_frontend_data_type_controller.h165
-rw-r--r--chrome/browser/sync/glue/non_frontend_data_type_controller_mock.cc13
-rw-r--r--chrome/browser/sync/glue/non_frontend_data_type_controller_mock.h56
-rw-r--r--chrome/browser/sync/glue/non_frontend_data_type_controller_unittest.cc397
-rw-r--r--chrome/browser/sync/glue/password_data_type_controller.cc217
-rw-r--r--chrome/browser/sync/glue/password_data_type_controller.h73
-rw-r--r--chrome/browser/sync/glue/typed_url_data_type_controller.cc263
-rw-r--r--chrome/browser/sync/glue/typed_url_data_type_controller.h83
-rw-r--r--chrome/browser/sync/profile_sync_factory.h11
-rw-r--r--chrome/browser/sync/profile_sync_factory_impl.cc14
-rw-r--r--chrome/browser/sync/profile_sync_factory_impl.h4
-rw-r--r--chrome/browser/sync/profile_sync_factory_impl_unittest.cc2
-rw-r--r--chrome/browser/sync/profile_sync_factory_mock.h1
-rw-r--r--chrome/browser/sync/profile_sync_service_autofill_unittest.cc9
-rw-r--r--chrome/browser/sync/profile_sync_service_password_unittest.cc5
-rw-r--r--chrome/browser/sync/profile_sync_service_typed_url_unittest.cc5
-rw-r--r--chrome/chrome_browser.gypi2
-rw-r--r--chrome/chrome_tests.gypi3
31 files changed, 898 insertions, 1316 deletions
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc
index b34fff7..8ed41f2 100644
--- a/chrome/browser/profiles/profile_impl.cc
+++ b/chrome/browser/profiles/profile_impl.cc
@@ -1327,7 +1327,6 @@ void ProfileImpl::InitSyncService(const std::string& cros_user) {
new ProfileSyncFactoryImpl(this, CommandLine::ForCurrentProcess()));
sync_service_.reset(
profile_sync_factory_->CreateProfileSyncService(cros_user));
- profile_sync_factory_->RegisterDataTypes(sync_service_.get());
sync_service_->Initialize();
}
diff --git a/chrome/browser/sync/glue/autofill_data_type_controller.cc b/chrome/browser/sync/glue/autofill_data_type_controller.cc
index a4f0e66..fa5dde4 100644
--- a/chrome/browser/sync/glue/autofill_data_type_controller.cc
+++ b/chrome/browser/sync/glue/autofill_data_type_controller.cc
@@ -4,118 +4,165 @@
#include "chrome/browser/sync/glue/autofill_data_type_controller.h"
+#include "base/logging.h"
#include "base/metrics/histogram.h"
#include "base/task.h"
+#include "base/time.h"
#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/sync/glue/autofill_change_processor.h"
+#include "chrome/browser/sync/glue/autofill_model_associator.h"
#include "chrome/browser/sync/profile_sync_factory.h"
#include "chrome/browser/sync/profile_sync_service.h"
#include "chrome/browser/webdata/web_data_service.h"
#include "content/browser/browser_thread.h"
#include "content/common/notification_service.h"
-#include "content/common/notification_source.h"
-#include "content/common/notification_type.h"
namespace browser_sync {
AutofillDataTypeController::AutofillDataTypeController(
ProfileSyncFactory* profile_sync_factory,
- Profile* profile)
- : NonFrontendDataTypeController(profile_sync_factory,
- profile),
- personal_data_(NULL) {
+ Profile* profile,
+ ProfileSyncService* sync_service)
+ : profile_sync_factory_(profile_sync_factory),
+ profile_(profile),
+ sync_service_(sync_service),
+ state_(NOT_RUNNING),
+ personal_data_(NULL),
+ abort_association_(false),
+ abort_association_complete_(false, false),
+ datatype_stopped_(false, false) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(profile_sync_factory);
+ DCHECK(profile);
+ DCHECK(sync_service);
}
AutofillDataTypeController::~AutofillDataTypeController() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ // TODO(zea): remove once crbug.com/61804 is resolved.
+ CHECK_EQ(state_, NOT_RUNNING) << "AutofillDataTypeController destroyed "
+ << "without being stopped.";
+ CHECK(!change_processor_.get()) << "AutofillDataTypeController destroyed "
+ << "while holding a change processor.";
}
-bool AutofillDataTypeController::StartModels() {
+void AutofillDataTypeController::Start(StartCallback* start_callback) {
+ VLOG(1) << "Starting autofill data controller.";
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DCHECK_EQ(state(), MODEL_STARTING);
+ DCHECK(start_callback);
+ if (state() != NOT_RUNNING) {
+ start_callback->Run(BUSY, FROM_HERE);
+ delete start_callback;
+ return;
+ }
+
+ start_callback_.reset(start_callback);
+ abort_association_ = false;
+
// Waiting for the personal data is subtle: we do this as the PDM resets
// its cache of unique IDs once it gets loaded. If we were to proceed with
// association, the local ids in the mappings would wind up colliding.
- personal_data_ = profile()->GetPersonalDataManager();
+ personal_data_ = profile_->GetPersonalDataManager();
if (!personal_data_->IsDataLoaded()) {
+ set_state(MODEL_STARTING);
personal_data_->SetObserver(this);
- return false;
+ return;
}
- web_data_service_ = profile()->GetWebDataService(Profile::IMPLICIT_ACCESS);
+ ContinueStartAfterPersonalDataLoaded();
+}
+
+void AutofillDataTypeController::ContinueStartAfterPersonalDataLoaded() {
+ web_data_service_ = profile_->GetWebDataService(Profile::IMPLICIT_ACCESS);
if (web_data_service_.get() && web_data_service_->IsDatabaseLoaded()) {
- return true;
+ set_state(ASSOCIATING);
+ BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
+ NewRunnableMethod(
+ this,
+ &AutofillDataTypeController::StartImpl));
} else {
+ set_state(MODEL_STARTING);
notification_registrar_.Add(this, NotificationType::WEB_DATABASE_LOADED,
NotificationService::AllSources());
- return false;
}
}
void AutofillDataTypeController::OnPersonalDataLoaded() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DCHECK_EQ(state(), MODEL_STARTING);
+ DCHECK_EQ(state_, MODEL_STARTING);
personal_data_->RemoveObserver(this);
- web_data_service_ = profile()->GetWebDataService(Profile::IMPLICIT_ACCESS);
- if (web_data_service_.get() && web_data_service_->IsDatabaseLoaded()) {
- set_state(ASSOCIATING);
- if (!StartAssociationAsync()) {
- StartDoneImpl(ASSOCIATION_FAILED, NOT_RUNNING, FROM_HERE);
- }
- } else {
- notification_registrar_.Add(this, NotificationType::WEB_DATABASE_LOADED,
- NotificationService::AllSources());
- }
+ ContinueStartAfterPersonalDataLoaded();
}
void AutofillDataTypeController::Observe(NotificationType type,
const NotificationSource& source,
const NotificationDetails& details) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DCHECK_EQ(state(), MODEL_STARTING);
+ VLOG(1) << "Web database loaded observed.";
notification_registrar_.RemoveAll();
set_state(ASSOCIATING);
- if (!StartAssociationAsync()) {
- StartDoneImpl(ASSOCIATION_FAILED, NOT_RUNNING, FROM_HERE);
- }
+ BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
+ NewRunnableMethod(
+ this,
+ &AutofillDataTypeController::StartImpl));
}
-bool AutofillDataTypeController::StartAssociationAsync() {
+// TODO(sync): Blocking the UI thread at shutdown is bad. If we had a way of
+// distinguishing chrome shutdown from sync shutdown, we should be able to avoid
+// this (http://crbug.com/55662). Further, all this functionality should be
+// abstracted to a higher layer, where we could ensure all datatypes are doing
+// the same thing (http://crbug.com/76232).
+void AutofillDataTypeController::Stop() {
+ VLOG(1) << "Stopping autofill data type controller.";
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DCHECK_EQ(state(), ASSOCIATING);
- return BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
- NewRunnableMethod(
- this,
- &AutofillDataTypeController::StartAssociation));
-}
-void AutofillDataTypeController::CreateSyncComponents() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
- DCHECK_EQ(state(), ASSOCIATING);
- ProfileSyncFactory::SyncComponents sync_components =
- profile_sync_factory()->
- CreateAutofillSyncComponents(
- profile_sync_service(),
- web_data_service_->GetDatabase(),
- personal_data_,
- this);
- set_model_associator(sync_components.model_associator);
- set_change_processor(sync_components.change_processor);
-}
-
-void AutofillDataTypeController::StopModels() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DCHECK(state() == STOPPING || state() == NOT_RUNNING);
+ // If Stop() is called while Start() is waiting for association to
+ // complete, we need to abort the association and wait for the DB
+ // thread to finish the StartImpl() task.
+ if (state_ == ASSOCIATING) {
+ {
+ base::AutoLock lock(abort_association_lock_);
+ abort_association_ = true;
+ if (model_associator_.get())
+ model_associator_->AbortAssociation();
+ }
+ // Wait for the model association to abort.
+ abort_association_complete_.Wait();
+ StartDoneImpl(ABORTED, STOPPING, FROM_HERE);
+ }
+
+ // If Stop() is called while Start() is waiting for the personal
+ // data manager or web data service to load, abort the start.
+ if (state_ == MODEL_STARTING)
+ StartDoneImpl(ABORTED, STOPPING, FROM_HERE);
+
+ DCHECK(!start_callback_.get());
+
+ // Deactivate the change processor on the UI thread. We dont want to listen
+ // for any more changes or process them from server.
notification_registrar_.RemoveAll();
personal_data_->RemoveObserver(this);
+ if (change_processor_ != NULL && change_processor_->IsRunning())
+ sync_service_->DeactivateDataType(this, change_processor_.get());
+
+ set_state(NOT_RUNNING);
+ if (BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
+ NewRunnableMethod(
+ this,
+ &AutofillDataTypeController::StopImpl))) {
+ // We need to ensure the data type has fully stoppped before continuing. In
+ // particular, during shutdown we may attempt to destroy the
+ // profile_sync_service before we've removed its observers (BUG 61804).
+ datatype_stopped_.Wait();
+ } else if (change_processor_.get()) {
+ // TODO(zea): remove once crbug.com/61804 is resolved.
+ LOG(FATAL) << "AutofillDataTypeController::Stop() called after DB thread"
+ << " killed.";
+ }
+ CHECK(!change_processor_.get()) << "AutofillChangeProcessor not released.";
}
-bool AutofillDataTypeController::StopAssociationAsync() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DCHECK_EQ(state(), STOPPING);
- return BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
- NewRunnableMethod(
- this,
- &AutofillDataTypeController::StopAssociation));
+bool AutofillDataTypeController::enabled() {
+ return true;
}
syncable::ModelType AutofillDataTypeController::type() const {
@@ -127,31 +174,150 @@ browser_sync::ModelSafeGroup AutofillDataTypeController::model_safe_group()
return browser_sync::GROUP_DB;
}
-void AutofillDataTypeController::RecordUnrecoverableError(
- const tracked_objects::Location& from_here,
- const std::string& message) {
+std::string AutofillDataTypeController::name() const {
+ // For logging only.
+ return "autofill";
+}
+
+DataTypeController::State AutofillDataTypeController::state() const {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ return state_;
+}
+
+ProfileSyncFactory::SyncComponents
+ AutofillDataTypeController::CreateSyncComponents(
+ ProfileSyncService* profile_sync_service,
+ WebDatabase* web_database,
+ PersonalDataManager* personal_data,
+ browser_sync::UnrecoverableErrorHandler* error_handler) {
+ return profile_sync_factory_->CreateAutofillSyncComponents(
+ profile_sync_service,
+ web_database,
+ personal_data,
+ this);
+}
+
+void AutofillDataTypeController::StartImpl() {
+ VLOG(1) << "Autofill data type controller StartImpl called.";
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
- UMA_HISTOGRAM_COUNTS("Sync.AutofillRunFailures", 1);
+ // No additional services need to be started before we can proceed
+ // with model association.
+ {
+ base::AutoLock lock(abort_association_lock_);
+ if (abort_association_) {
+ abort_association_complete_.Signal();
+ return;
+ }
+ ProfileSyncFactory::SyncComponents sync_components =
+ CreateSyncComponents(
+ sync_service_,
+ web_data_service_->GetDatabase(),
+ profile_->GetPersonalDataManager(),
+ this);
+ model_associator_.reset(sync_components.model_associator);
+ change_processor_.reset(sync_components.change_processor);
+ }
+
+ if (!model_associator_->CryptoReadyIfNecessary()) {
+ StartFailed(NEEDS_CRYPTO);
+ return;
+ }
+
+ bool sync_has_nodes = false;
+ if (!model_associator_->SyncModelHasUserCreatedNodes(&sync_has_nodes)) {
+ StartFailed(UNRECOVERABLE_ERROR);
+ return;
+ }
+
+ base::TimeTicks start_time = base::TimeTicks::Now();
+ bool merge_success = model_associator_->AssociateModels();
+ UMA_HISTOGRAM_TIMES("Sync.AutofillAssociationTime",
+ base::TimeTicks::Now() - start_time);
+ VLOG(1) << "Autofill association time: " <<
+ (base::TimeTicks::Now() - start_time).InSeconds();
+ if (!merge_success) {
+ StartFailed(ASSOCIATION_FAILED);
+ return;
+ }
+
+ sync_service_->ActivateDataType(this, change_processor_.get());
+ StartDone(!sync_has_nodes ? OK_FIRST_RUN : OK, RUNNING);
}
-void AutofillDataTypeController::RecordAssociationTime(base::TimeDelta time) {
+void AutofillDataTypeController::StartDone(
+ DataTypeController::StartResult result,
+ DataTypeController::State new_state) {
+ VLOG(1) << "Autofill data type controller StartDone called.";
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
- UMA_HISTOGRAM_TIMES("Sync.AutofillAssociationTime", time);
+
+ abort_association_complete_.Signal();
+ base::AutoLock lock(abort_association_lock_);
+ if (!abort_association_) {
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ NewRunnableMethod(
+ this,
+ &AutofillDataTypeController::StartDoneImpl,
+ result,
+ new_state,
+ FROM_HERE));
+ }
}
-void AutofillDataTypeController::RecordStartFailure(StartResult result) {
+void AutofillDataTypeController::StartDoneImpl(
+ DataTypeController::StartResult result,
+ DataTypeController::State new_state,
+ const tracked_objects::Location& location) {
+ VLOG(1) << "Autofill data type controller StartDoneImpl called.";
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- UMA_HISTOGRAM_ENUMERATION("Sync.AutofillStartFailures",
- result,
- MAX_START_RESULT);
+
+ set_state(new_state);
+ start_callback_->Run(result, location);
+ start_callback_.reset();
+
+ if (result == UNRECOVERABLE_ERROR || result == ASSOCIATION_FAILED) {
+ UMA_HISTOGRAM_ENUMERATION("Sync.AutofillStartFailures",
+ result,
+ MAX_START_RESULT);
+ }
}
-PersonalDataManager* AutofillDataTypeController::personal_data() const {
- return personal_data_;
+void AutofillDataTypeController::StopImpl() {
+ VLOG(1) << "Autofill data type controller StopImpl called.";
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
+
+ if (model_associator_ != NULL)
+ model_associator_->DisassociateModels();
+
+ change_processor_.reset();
+ model_associator_.reset();
+
+ datatype_stopped_.Signal();
}
-WebDataService* AutofillDataTypeController::web_data_service() const {
- return web_data_service_;
+void AutofillDataTypeController::StartFailed(StartResult result) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
+ change_processor_.reset();
+ model_associator_.reset();
+ StartDone(result, NOT_RUNNING);
+}
+
+void AutofillDataTypeController::OnUnrecoverableError(
+ const tracked_objects::Location& from_here,
+ const std::string& message) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ NewRunnableMethod(this,
+ &AutofillDataTypeController::OnUnrecoverableErrorImpl,
+ from_here, message));
+ UMA_HISTOGRAM_COUNTS("Sync.AutofillRunFailures", 1);
+}
+
+void AutofillDataTypeController::OnUnrecoverableErrorImpl(
+ const tracked_objects::Location& from_here,
+ const std::string& message) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ sync_service_->OnUnrecoverableError(from_here, message);
}
} // namespace browser_sync
diff --git a/chrome/browser/sync/glue/autofill_data_type_controller.h b/chrome/browser/sync/glue/autofill_data_type_controller.h
index ee58113..8df5fb8 100644
--- a/chrome/browser/sync/glue/autofill_data_type_controller.h
+++ b/chrome/browser/sync/glue/autofill_data_type_controller.h
@@ -8,31 +8,53 @@
#include <string>
-#include "base/memory/ref_counted.h"
+#include "base/basictypes.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/synchronization/waitable_event.h"
#include "chrome/browser/autofill/personal_data_manager.h"
-#include "chrome/browser/sync/glue/non_frontend_data_type_controller.h"
-#include "content/common/notification_observer.h"
-#include "content/common/notification_registrar.h"
+#include "chrome/browser/sync/profile_sync_factory.h"
+#include "chrome/browser/sync/profile_sync_service.h"
+#include "chrome/browser/sync/glue/data_type_controller.h"
-class NotificationDetails;
-class NotificationType;
-class NotificationSource;
+class Profile;
+class ProfileSyncFactory;
+class ProfileSyncService;
namespace browser_sync {
+class AssociatorInterface;
+class ChangeProcessor;
+
// A class that manages the startup and shutdown of autofill sync.
-class AutofillDataTypeController : public NonFrontendDataTypeController,
+class AutofillDataTypeController : public DataTypeController,
public NotificationObserver,
public PersonalDataManager::Observer {
public:
- AutofillDataTypeController(ProfileSyncFactory* profile_sync_factory,
- Profile* profile);
+ AutofillDataTypeController(
+ ProfileSyncFactory* profile_sync_factory,
+ Profile* profile,
+ ProfileSyncService* sync_service);
virtual ~AutofillDataTypeController();
- // NonFrontendDataTypeController implementation
+ // DataTypeController implementation
+ virtual void Start(StartCallback* start_callback);
+
+ virtual void Stop();
+
+ virtual bool enabled();
+
virtual syncable::ModelType type() const;
+
virtual browser_sync::ModelSafeGroup model_safe_group() const;
+ virtual std::string name() const;
+
+ virtual State state() const;
+
+ // UnrecoverableHandler implementation
+ virtual void OnUnrecoverableError(const tracked_objects::Location& from_here,
+ const std::string& message);
+
// NotificationObserver implementation.
virtual void Observe(NotificationType type,
const NotificationSource& source,
@@ -42,26 +64,52 @@ class AutofillDataTypeController : public NonFrontendDataTypeController,
virtual void OnPersonalDataLoaded();
protected:
- // NonFrontendDataTypeController interface.
- virtual bool StartModels();
- virtual bool StartAssociationAsync();
- virtual void CreateSyncComponents();
- virtual void StopModels();
- virtual bool StopAssociationAsync();
- virtual void RecordUnrecoverableError(
- const tracked_objects::Location& from_here,
- const std::string& message);
- virtual void RecordAssociationTime(base::TimeDelta time);
- virtual void RecordStartFailure(StartResult result);
-
- // Getters and setters
- PersonalDataManager* personal_data() const;
- WebDataService* web_data_service() const;
+ virtual ProfileSyncFactory::SyncComponents CreateSyncComponents(
+ ProfileSyncService* profile_sync_service,
+ WebDatabase* web_database,
+ PersonalDataManager* personal_data,
+ browser_sync::UnrecoverableErrorHandler* error_handler);
+ ProfileSyncFactory* profile_sync_factory_;
+
private:
+ void StartImpl();
+ void StartDone(StartResult result, State state);
+ void StartDoneImpl(StartResult result, State state,
+ const tracked_objects::Location& location);
+ void StopImpl();
+ void StartFailed(StartResult result);
+ void OnUnrecoverableErrorImpl(const tracked_objects::Location& from_here,
+ const std::string& message);
+
+ // Second-half of "Start" implementation, called once personal data has
+ // loaded.
+ void ContinueStartAfterPersonalDataLoaded();
+
+ void set_state(State state) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ state_ = state;
+ }
+
+ Profile* profile_;
+ ProfileSyncService* sync_service_;
+ State state_;
+
PersonalDataManager* personal_data_;
scoped_refptr<WebDataService> web_data_service_;
+ scoped_ptr<AssociatorInterface> model_associator_;
+ scoped_ptr<ChangeProcessor> change_processor_;
+ scoped_ptr<StartCallback> start_callback_;
+
NotificationRegistrar notification_registrar_;
+ base::Lock abort_association_lock_;
+ bool abort_association_;
+ base::WaitableEvent abort_association_complete_;
+
+ // Barrier to ensure that the datatype has been stopped on the DB thread
+ // from the UI thread.
+ base::WaitableEvent datatype_stopped_;
+
DISALLOW_COPY_AND_ASSIGN(AutofillDataTypeController);
};
diff --git a/chrome/browser/sync/glue/autofill_data_type_controller_unittest.cc b/chrome/browser/sync/glue/autofill_data_type_controller_unittest.cc
index a4e854e..01deb74 100644
--- a/chrome/browser/sync/glue/autofill_data_type_controller_unittest.cc
+++ b/chrome/browser/sync/glue/autofill_data_type_controller_unittest.cc
@@ -87,14 +87,13 @@ class AutofillDataTypeControllerTest : public testing::Test {
db_thread_(BrowserThread::DB) {}
virtual void SetUp() {
- EXPECT_CALL(profile_, GetProfileSyncService()).WillRepeatedly(
- Return(&service_));
db_thread_.Start();
web_data_service_ = new WebDataServiceFake(true);
personal_data_manager_ = new PersonalDataManagerMock();
autofill_dtc_ =
new AutofillDataTypeController(&profile_sync_factory_,
- &profile_);
+ &profile_,
+ &service_);
}
virtual void TearDown() {
diff --git a/chrome/browser/sync/glue/autofill_profile_data_type_controller.cc b/chrome/browser/sync/glue/autofill_profile_data_type_controller.cc
index 7ea3959..2203197 100644
--- a/chrome/browser/sync/glue/autofill_profile_data_type_controller.cc
+++ b/chrome/browser/sync/glue/autofill_profile_data_type_controller.cc
@@ -4,17 +4,18 @@
#include "chrome/browser/sync/glue/autofill_profile_data_type_controller.h"
-#include "base/metrics/histogram.h"
+#include "chrome/browser/sync/glue/autofill_data_type_controller.h"
#include "chrome/browser/sync/profile_sync_factory.h"
namespace browser_sync {
AutofillProfileDataTypeController::AutofillProfileDataTypeController(
ProfileSyncFactory* profile_sync_factory,
- Profile* profile)
- : AutofillDataTypeController(
- profile_sync_factory,
- profile) {}
+ Profile* profile,
+ ProfileSyncService* sync_service) : AutofillDataTypeController(
+ profile_sync_factory,
+ profile,
+ sync_service) {}
AutofillProfileDataTypeController::~AutofillProfileDataTypeController() {}
@@ -22,38 +23,22 @@ syncable::ModelType AutofillProfileDataTypeController::type() const {
return syncable::AUTOFILL_PROFILE;
}
-void AutofillProfileDataTypeController::CreateSyncComponents() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
- ProfileSyncFactory::SyncComponents sync_components =
- profile_sync_factory()->
- CreateAutofillProfileSyncComponents(
- profile_sync_service(),
- web_data_service()->GetDatabase(),
- personal_data(),
- this);
- set_model_associator(sync_components.model_associator);
- set_change_processor(sync_components.change_processor);
+std::string AutofillProfileDataTypeController::name() const {
+ // For logging only.
+ return "autofill_profile";
}
-void AutofillProfileDataTypeController::RecordUnrecoverableError(
- const tracked_objects::Location& from_here,
- const std::string& message) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
- UMA_HISTOGRAM_COUNTS("Sync.AutofillProfileRunFailures", 1);
+ProfileSyncFactory::SyncComponents
+ AutofillProfileDataTypeController::CreateSyncComponents(
+ ProfileSyncService* profile_sync_service,
+ WebDatabase* web_database,
+ PersonalDataManager* personal_data,
+ browser_sync::UnrecoverableErrorHandler* error_handler) {
+ return profile_sync_factory_->CreateAutofillProfileSyncComponents(
+ profile_sync_service,
+ web_database,
+ personal_data,
+ this);
}
-
-void AutofillProfileDataTypeController::RecordAssociationTime(
- base::TimeDelta time) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
- UMA_HISTOGRAM_TIMES("Sync.AutofillProfileAssociationTime", time);
-}
-
-void AutofillProfileDataTypeController::RecordStartFailure(StartResult result) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- UMA_HISTOGRAM_ENUMERATION("Sync.AutofillProfileStartFailures",
- result,
- MAX_START_RESULT);
-}
-
} // namepsace browser_sync
diff --git a/chrome/browser/sync/glue/autofill_profile_data_type_controller.h b/chrome/browser/sync/glue/autofill_profile_data_type_controller.h
index 64f0f49..d97a904 100644
--- a/chrome/browser/sync/glue/autofill_profile_data_type_controller.h
+++ b/chrome/browser/sync/glue/autofill_profile_data_type_controller.h
@@ -15,18 +15,20 @@ class AutofillProfileDataTypeController : public AutofillDataTypeController {
public:
AutofillProfileDataTypeController(
ProfileSyncFactory* profile_sync_factory,
- Profile* profile);
+ Profile* profile,
+ ProfileSyncService* sync_service);
virtual ~AutofillProfileDataTypeController();
virtual syncable::ModelType type() const;
+ virtual std::string name() const;
+
protected:
- virtual void CreateSyncComponents();
- virtual void RecordUnrecoverableError(
- const tracked_objects::Location& from_here,
- const std::string& message);
- virtual void RecordAssociationTime(base::TimeDelta time);
- virtual void RecordStartFailure(StartResult result);
+ virtual ProfileSyncFactory::SyncComponents CreateSyncComponents(
+ ProfileSyncService* profile_sync_service,
+ WebDatabase* web_database,
+ PersonalDataManager* personal_data,
+ browser_sync::UnrecoverableErrorHandler* error_handler);
};
} // namespace browser_sync
diff --git a/chrome/browser/sync/glue/bookmark_data_type_controller.cc b/chrome/browser/sync/glue/bookmark_data_type_controller.cc
index 4415240..8cd3d5b 100644
--- a/chrome/browser/sync/glue/bookmark_data_type_controller.cc
+++ b/chrome/browser/sync/glue/bookmark_data_type_controller.cc
@@ -43,7 +43,7 @@ bool BookmarkDataTypeController::StartModels() {
}
// Cleanup for our extra registrar usage.
-void BookmarkDataTypeController::CleanUpState() {
+void BookmarkDataTypeController::CleanupState() {
registrar_.RemoveAll();
}
diff --git a/chrome/browser/sync/glue/bookmark_data_type_controller.h b/chrome/browser/sync/glue/bookmark_data_type_controller.h
index 2655056..8741e84 100644
--- a/chrome/browser/sync/glue/bookmark_data_type_controller.h
+++ b/chrome/browser/sync/glue/bookmark_data_type_controller.h
@@ -39,7 +39,7 @@ class BookmarkDataTypeController : public FrontendDataTypeController,
private:
// FrontendDataTypeController interface.
virtual bool StartModels();
- virtual void CleanUpState();
+ virtual void CleanupState();
virtual void CreateSyncComponents();
virtual void RecordUnrecoverableError(
const tracked_objects::Location& from_here,
diff --git a/chrome/browser/sync/glue/frontend_data_type_controller.cc b/chrome/browser/sync/glue/frontend_data_type_controller.cc
index edec12c..5e324f9 100644
--- a/chrome/browser/sync/glue/frontend_data_type_controller.cc
+++ b/chrome/browser/sync/glue/frontend_data_type_controller.cc
@@ -103,46 +103,15 @@ bool FrontendDataTypeController::Associate() {
return true;
}
-void FrontendDataTypeController::StartFailed(StartResult result,
- const tracked_objects::Location& location) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- CleanUpState();
- model_associator_.reset();
- change_processor_.reset();
- state_ = NOT_RUNNING;
- RecordStartFailure(result);
-
- // We have to release the callback before we call it, since it's possible
- // invoking the callback will trigger a call to STOP(), which will get
- // confused by the non-NULL start_callback_.
- scoped_ptr<StartCallback> callback(start_callback_.release());
- callback->Run(result, location);
-}
-
-void FrontendDataTypeController::FinishStart(StartResult result,
- const tracked_objects::Location& location) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- // We have to release the callback before we call it, since it's possible
- // invoking the callback will trigger a call to STOP(), which will get
- // confused by the non-NULL start_callback_.
- scoped_ptr<StartCallback> callback(start_callback_.release());
- callback->Run(result, location);
-}
-
void FrontendDataTypeController::Stop() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
// If Stop() is called while Start() is waiting for the datatype model to
// load, abort the start.
- if (state_ == MODEL_STARTING) {
- StartFailed(ABORTED, FROM_HERE);
- // We can just return here since we haven't performed association if we're
- // still in MODEL_STARTING.
- return;
- }
+ if (state_ == MODEL_STARTING)
+ FinishStart(ABORTED, FROM_HERE);
DCHECK(!start_callback_.get());
- CleanUpState();
+ CleanupState();
if (change_processor_ != NULL)
sync_service_->DeactivateDataType(this, change_processor_.get());
@@ -156,7 +125,7 @@ void FrontendDataTypeController::Stop() {
state_ = NOT_RUNNING;
}
-void FrontendDataTypeController::CleanUpState() {
+void FrontendDataTypeController::CleanupState() {
// Do nothing by default.
}
@@ -181,4 +150,23 @@ void FrontendDataTypeController::OnUnrecoverableError(
sync_service_->OnUnrecoverableError(from_here, message);
}
+void FrontendDataTypeController::FinishStart(StartResult result,
+ const tracked_objects::Location& location) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ start_callback_->Run(result, location);
+ start_callback_.reset();
+}
+
+void FrontendDataTypeController::StartFailed(StartResult result,
+ const tracked_objects::Location& location) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ CleanupState();
+ model_associator_.reset();
+ change_processor_.reset();
+ state_ = NOT_RUNNING;
+ start_callback_->Run(result, location);
+ start_callback_.reset();
+ RecordStartFailure(result);
+}
+
} // namespace browser_sync
diff --git a/chrome/browser/sync/glue/frontend_data_type_controller.h b/chrome/browser/sync/glue/frontend_data_type_controller.h
index 6a2d863..d228bb9 100644
--- a/chrome/browser/sync/glue/frontend_data_type_controller.h
+++ b/chrome/browser/sync/glue/frontend_data_type_controller.h
@@ -22,8 +22,6 @@ namespace browser_sync {
class AssociatorInterface;
class ChangeProcessor;
-// TODO(zea): have naming and style match NonFrontendDataTypeController.
-// TODO(zea): Rename frontend to UI (http://crbug.com/78833).
// Implementation for datatypes that 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 funtionality is
@@ -46,10 +44,15 @@ class FrontendDataTypeController : public DataTypeController {
// DataTypeController interface.
virtual void Start(StartCallback* start_callback);
+
virtual void Stop();
+
virtual syncable::ModelType type() const = 0;
+
virtual browser_sync::ModelSafeGroup model_safe_group() const;
+
virtual std::string name() const;
+
virtual State state() const;
// UnrecoverableErrorHandler interface.
@@ -61,33 +64,25 @@ class FrontendDataTypeController : public DataTypeController {
// Kick off 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. Associate() should be called when the
- // models are ready. Refer to Start(_) implementation.
virtual bool StartModels();
// Build sync components and associate models.
- // Return value:
- // True - if association was successful. FinishStart should have been
- // invoked.
- // False - if association failed. StartFailed should have been invoked.
virtual bool Associate();
- // Datatype specific creation of sync components.
- virtual void CreateSyncComponents() = 0;
-
// Perform any DataType controller specific state cleanup before stopping
// the datatype controller. The default implementation is a no-op.
- virtual void CleanUpState();
+ virtual void CleanupState();
+
+ // Helper method to run the stashed start callback with a given result.
+ virtual void FinishStart(StartResult result,
+ const tracked_objects::Location& from_here);
// Cleans up state and calls callback when start fails.
virtual void StartFailed(StartResult result,
const tracked_objects::Location& from_here);
- // Helper method to run the stashed start callback with a given result.
- virtual void FinishStart(StartResult result,
- const tracked_objects::Location& from_here);
+ // Datatype specific creation of sync components.
+ virtual void CreateSyncComponents() = 0;
// DataType specific histogram methods. Because histograms use static's, the
// specific datatype controllers must implement this themselves.
diff --git a/chrome/browser/sync/glue/frontend_data_type_controller_mock.h b/chrome/browser/sync/glue/frontend_data_type_controller_mock.h
index a32f3f5..0485b1f 100644
--- a/chrome/browser/sync/glue/frontend_data_type_controller_mock.h
+++ b/chrome/browser/sync/glue/frontend_data_type_controller_mock.h
@@ -30,12 +30,12 @@ class FrontendDataTypeControllerMock : public FrontendDataTypeController {
// FrontendDataTypeController mocks.
MOCK_METHOD0(StartModels, bool());
MOCK_METHOD0(Associate, bool());
- MOCK_METHOD0(CreateSyncComponents, void());
- MOCK_METHOD2(StartFailed, void(StartResult result,
- const tracked_objects::Location& from_here));
+ MOCK_METHOD0(CleanupState, void());
MOCK_METHOD2(FinishStart, void(StartResult result,
const tracked_objects::Location& from_here));
- MOCK_METHOD0(CleanUpState, void());
+ MOCK_METHOD2(StartFailed, void(StartResult result,
+ const tracked_objects::Location& from_here));
+ MOCK_METHOD0(CreateSyncComponents, void());
MOCK_METHOD2(RecordUnrecoverableError, void(const tracked_objects::Location&,
const std::string&));
MOCK_METHOD1(RecordAssociationTime, void(base::TimeDelta time));
diff --git a/chrome/browser/sync/glue/frontend_data_type_controller_unittest.cc b/chrome/browser/sync/glue/frontend_data_type_controller_unittest.cc
index ee3f42f..c0c2290 100644
--- a/chrome/browser/sync/glue/frontend_data_type_controller_unittest.cc
+++ b/chrome/browser/sync/glue/frontend_data_type_controller_unittest.cc
@@ -63,8 +63,8 @@ class FrontendDataTypeControllerFake : public FrontendDataTypeController {
virtual bool StartModels() {
return mock_->StartModels();
}
- virtual void CleanUpState() {
- mock_->CleanUpState();
+ virtual void CleanupState() {
+ mock_->CleanupState();
}
virtual void RecordUnrecoverableError(
const tracked_objects::Location& from_here,
@@ -122,13 +122,13 @@ class FrontendDataTypeControllerTest : public testing::Test {
}
void SetStopExpectations() {
- EXPECT_CALL(*dtc_mock_, CleanUpState());
+ EXPECT_CALL(*dtc_mock_, CleanupState());
EXPECT_CALL(service_, DeactivateDataType(_, _));
EXPECT_CALL(*model_associator_, DisassociateModels());
}
void SetStartFailExpectations(DataTypeController::StartResult result) {
- EXPECT_CALL(*dtc_mock_, CleanUpState());
+ EXPECT_CALL(*dtc_mock_, CleanupState());
EXPECT_CALL(*dtc_mock_, RecordStartFailure(result));
EXPECT_CALL(start_callback_, Run(result,_));
}
@@ -169,16 +169,6 @@ TEST_F(FrontendDataTypeControllerTest, StartFirstRun) {
EXPECT_EQ(DataTypeController::RUNNING, frontend_dtc_->state());
}
-TEST_F(FrontendDataTypeControllerTest, AbortDuringStartModels) {
- EXPECT_CALL(*dtc_mock_, StartModels()).WillOnce(Return(false));
- SetStartFailExpectations(DataTypeController::ABORTED);
- EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
- frontend_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run));
- EXPECT_EQ(DataTypeController::MODEL_STARTING, frontend_dtc_->state());
- frontend_dtc_->Stop();
- EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
-}
-
TEST_F(FrontendDataTypeControllerTest, StartAssociationFailed) {
SetStartExpectations();
EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
@@ -225,6 +215,7 @@ TEST_F(FrontendDataTypeControllerTest, Stop) {
SetAssociateExpectations();
SetActivateExpectations(DataTypeController::OK);
SetStopExpectations();
+
EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
frontend_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run));
EXPECT_EQ(DataTypeController::RUNNING, frontend_dtc_->state());
@@ -241,6 +232,7 @@ TEST_F(FrontendDataTypeControllerTest, OnUnrecoverableError) {
WillOnce(InvokeWithoutArgs(frontend_dtc_.get(),
&FrontendDataTypeController::Stop));
SetStopExpectations();
+
EXPECT_EQ(DataTypeController::NOT_RUNNING, frontend_dtc_->state());
frontend_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run));
EXPECT_EQ(DataTypeController::RUNNING, frontend_dtc_->state());
diff --git a/chrome/browser/sync/glue/non_frontend_data_type_controller.cc b/chrome/browser/sync/glue/non_frontend_data_type_controller.cc
deleted file mode 100644
index d26baef..0000000
--- a/chrome/browser/sync/glue/non_frontend_data_type_controller.cc
+++ /dev/null
@@ -1,279 +0,0 @@
-// Copyright (c) 2011 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.
-
-#include "chrome/browser/sync/glue/non_frontend_data_type_controller.h"
-
-#include "base/logging.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/sync/glue/change_processor.h"
-#include "chrome/browser/sync/glue/model_associator.h"
-#include "chrome/browser/sync/profile_sync_factory.h"
-#include "chrome/browser/sync/profile_sync_service.h"
-#include "chrome/browser/sync/syncable/model_type.h"
-#include "content/browser/browser_thread.h"
-
-namespace browser_sync {
-
-NonFrontendDataTypeController::NonFrontendDataTypeController()
- : profile_sync_factory_(NULL),
- profile_(NULL),
- profile_sync_service_(NULL),
- abort_association_(false),
- abort_association_complete_(false, false),
- datatype_stopped_(false, false) {}
-
-NonFrontendDataTypeController::NonFrontendDataTypeController(
- ProfileSyncFactory* profile_sync_factory,
- Profile* profile)
- : profile_sync_factory_(profile_sync_factory),
- profile_(profile),
- profile_sync_service_(profile->GetProfileSyncService()),
- state_(NOT_RUNNING),
- abort_association_(false),
- abort_association_complete_(false, false),
- datatype_stopped_(false, false) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DCHECK(profile_sync_factory_);
- DCHECK(profile_);
- DCHECK(profile_sync_service_);
-}
-
-NonFrontendDataTypeController::~NonFrontendDataTypeController() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-}
-
-void NonFrontendDataTypeController::Start(StartCallback* start_callback) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DCHECK(start_callback);
- if (state_ != NOT_RUNNING) {
- start_callback->Run(BUSY, FROM_HERE);
- delete start_callback;
- return;
- }
-
- start_callback_.reset(start_callback);
- abort_association_ = false;
-
- state_ = MODEL_STARTING;
- if (!StartModels()) {
- // If we are waiting for some external service to load before associating
- // or we failed to start the models, we exit early. state_ will control
- // what we perform next.
- DCHECK(state_ == NOT_RUNNING || state_ == MODEL_STARTING);
- return;
- }
-
- // Kick off association on the thread the datatype resides on.
- state_ = ASSOCIATING;
- if (!StartAssociationAsync()) {
- StartDoneImpl(ASSOCIATION_FAILED, NOT_RUNNING, FROM_HERE);
- }
-}
-
-bool NonFrontendDataTypeController::StartModels() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DCHECK_EQ(state_, MODEL_STARTING);
- // By default, no additional services need to be started before we can proceed
- // with model association, so do nothing.
- return true;
-}
-
-void NonFrontendDataTypeController::StartAssociation() {
- DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
- DCHECK_EQ(state_, ASSOCIATING);
- {
- base::AutoLock lock(abort_association_lock_);
- if (abort_association_) {
- abort_association_complete_.Signal();
- return;
- }
- CreateSyncComponents();
- }
-
- if (!model_associator_->CryptoReadyIfNecessary()) {
- StartFailed(NEEDS_CRYPTO, FROM_HERE);
- return;
- }
-
- bool sync_has_nodes = false;
- if (!model_associator_->SyncModelHasUserCreatedNodes(&sync_has_nodes)) {
- StartFailed(UNRECOVERABLE_ERROR, FROM_HERE);
- return;
- }
-
- base::TimeTicks start_time = base::TimeTicks::Now();
- bool merge_success = model_associator_->AssociateModels();
- RecordAssociationTime(base::TimeTicks::Now() - start_time);
- if (!merge_success) {
- StartFailed(ASSOCIATION_FAILED, FROM_HERE);
- return;
- }
-
- profile_sync_service_->ActivateDataType(this, change_processor_.get());
- StartDone(!sync_has_nodes ? OK_FIRST_RUN : OK, RUNNING, FROM_HERE);
-}
-
-void NonFrontendDataTypeController::StartFailed(StartResult result,
- const tracked_objects::Location& location) {
- DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
- model_associator_.reset();
- change_processor_.reset();
- StartDone(result, NOT_RUNNING, location);
-}
-
-void NonFrontendDataTypeController::StartDone(
- DataTypeController::StartResult result,
- DataTypeController::State new_state,
- const tracked_objects::Location& location) {
- DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
- abort_association_complete_.Signal();
- base::AutoLock lock(abort_association_lock_);
- if (!abort_association_) {
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- NewRunnableMethod(
- this,
- &NonFrontendDataTypeController::StartDoneImpl,
- result,
- new_state,
- location));
- }
-}
-
-void NonFrontendDataTypeController::StartDoneImpl(
- DataTypeController::StartResult result,
- DataTypeController::State new_state,
- const tracked_objects::Location& location) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- state_ = new_state;
- if (state_ != RUNNING) {
- // Start failed.
- StopModels();
- RecordStartFailure(result);
- }
-
- // We have to release the callback before we call it, since it's possible
- // invoking the callback will trigger a call to STOP(), which will get
- // confused by the non-NULL start_callback_.
- scoped_ptr<StartCallback> callback(start_callback_.release());
- callback->Run(result, location);
-}
-
-// TODO(sync): Blocking the UI thread at shutdown is bad. If we had a way of
-// distinguishing chrome shutdown from sync shutdown, we should be able to avoid
-// this (http://crbug.com/55662).
-void NonFrontendDataTypeController::Stop() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- // If Stop() is called while Start() is waiting for association to
- // complete, we need to abort the association and wait for the DB
- // thread to finish the StartImpl() task.
- if (state_ == ASSOCIATING) {
- state_ = STOPPING;
- {
- base::AutoLock lock(abort_association_lock_);
- abort_association_ = true;
- if (model_associator_.get())
- model_associator_->AbortAssociation();
- }
- // Wait for the model association to abort.
- abort_association_complete_.Wait();
- StartDoneImpl(ABORTED, STOPPING, FROM_HERE);
- } else if (state_ == MODEL_STARTING) {
- state_ = STOPPING;
- // If Stop() is called while Start() is waiting for the models to start,
- // abort the start. We don't need to continue on since it means we haven't
- // kicked off the association, and once we call StopModels, we never will.
- StartDoneImpl(ABORTED, NOT_RUNNING, FROM_HERE);
- return;
- } else {
- state_ = STOPPING;
-
- StopModels();
- }
- DCHECK(!start_callback_.get());
-
- // Deactivate the change processor on the UI thread. We dont want to listen
- // for any more changes or process them from server.
- if (change_processor_ != NULL)
- profile_sync_service_->DeactivateDataType(this, change_processor_.get());
-
- if (StopAssociationAsync()) {
- datatype_stopped_.Wait();
- } else {
- // We do DFATAL here because this will eventually lead to a failed CHECK
- // when the change processor gets destroyed on the wrong thread.
- LOG(DFATAL) << "Failed to destroy datatype " << name();
- }
- state_ = NOT_RUNNING;
-}
-
-void NonFrontendDataTypeController::StopModels() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DCHECK(state_ == STOPPING || state_ == NOT_RUNNING);
- // Do nothing by default.
-}
-
-void NonFrontendDataTypeController::StopAssociation() {
- DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
- if (model_associator_ != NULL)
- model_associator_->DisassociateModels();
- change_processor_.reset();
- model_associator_.reset();
- datatype_stopped_.Signal();
-}
-
-std::string NonFrontendDataTypeController::name() const {
- // For logging only.
- return syncable::ModelTypeToString(type());
-}
-
-DataTypeController::State NonFrontendDataTypeController::state() const {
- return state_;
-}
-
-void NonFrontendDataTypeController::OnUnrecoverableError(
- const tracked_objects::Location& from_here,
- const std::string& message) {
- DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
- RecordUnrecoverableError(from_here, message);
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, NewRunnableMethod(this,
- &NonFrontendDataTypeController::OnUnrecoverableErrorImpl, from_here,
- message));
-}
-
-void NonFrontendDataTypeController::OnUnrecoverableErrorImpl(
- const tracked_objects::Location& from_here,
- const std::string& message) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- profile_sync_service_->OnUnrecoverableError(from_here, message);
-}
-
-ProfileSyncFactory* NonFrontendDataTypeController::profile_sync_factory()
- const {
- return profile_sync_factory_;
-}
-
-Profile* NonFrontendDataTypeController::profile() const {
- return profile_;
-}
-
-ProfileSyncService* NonFrontendDataTypeController::profile_sync_service()
- const {
- return profile_sync_service_;
-}
-
-void NonFrontendDataTypeController::set_state(State state) {
- state_ = state;
-}
-
-void NonFrontendDataTypeController::set_model_associator(
- AssociatorInterface* associator) {
- model_associator_.reset(associator);
-}
-
-void NonFrontendDataTypeController::set_change_processor(
- ChangeProcessor* change_processor) {
- change_processor_.reset(change_processor);
-}
-
-} // namespace browser_sync
diff --git a/chrome/browser/sync/glue/non_frontend_data_type_controller.h b/chrome/browser/sync/glue/non_frontend_data_type_controller.h
deleted file mode 100644
index c2f2ee0..0000000
--- a/chrome/browser/sync/glue/non_frontend_data_type_controller.h
+++ /dev/null
@@ -1,165 +0,0 @@
-// Copyright (c) 2011 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__
-#pragma once
-
-#include <string>
-
-#include "base/basictypes.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/synchronization/waitable_event.h"
-#include "chrome/browser/sync/glue/data_type_controller.h"
-
-class Profile;
-class ProfileSyncService;
-class ProfileSyncFactory;
-
-namespace base { class TimeDelta; }
-namespace browser_sync {
-
-class AssociatorInterface;
-class ChangeProcessor;
-
-// TODO(zea): Rename frontend to UI (http://crbug.com/78833).
-// 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
-// funtionality is implemented by default. Derived classes must implement:
-// type()
-// model_safe_group()
-// StartAssociationAsync()
-// CreateSyncComponents()
-// StopAssociationAsync()
-// RecordUnrecoverableError(...)
-// RecordAssociationTime(...);
-// RecordStartFailure(...);
-class NonFrontendDataTypeController : public DataTypeController {
- public:
- NonFrontendDataTypeController(
- ProfileSyncFactory* profile_sync_factory,
- Profile* profile);
- virtual ~NonFrontendDataTypeController();
-
- // DataTypeController interface.
- virtual void Start(StartCallback* start_callback);
- virtual void Stop();
- virtual syncable::ModelType type() const = 0;
- virtual browser_sync::ModelSafeGroup model_safe_group() const = 0;
- virtual std::string name() const;
- virtual State state() const;
-
- // UnrecoverableErrorHandler interface.
- // Note: this is performed on the datatype's thread.
- virtual void OnUnrecoverableError(const tracked_objects::Location& from_here,
- const std::string& message);
- protected:
- // For testing only.
- NonFrontendDataTypeController();
-
- // 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. KickOffAssociation should be called
- // when the models are ready. Refer to Start(_) implementation.
- // Note: this is performed on the frontend (UI) thread.
- virtual bool StartModels();
-
- // Post the association task to the thread the datatype lives on.
- // Note: this is performed on the frontend (UI) thread.
- // Return value: True if task posted successfully, False otherwise.
- virtual bool StartAssociationAsync() = 0;
-
- // Build sync components and associate models.
- // Note: this is performed on the datatype's thread.
- virtual void StartAssociation();
-
- // Datatype specific creation of sync components.
- // Note: this is performed on the datatype's thread.
- virtual void CreateSyncComponents() = 0;
-
- // Start failed, make sure we record it, clean up state, and invoke the
- // callback on the frontend thread.
- // Note: this is performed on the datatype's thread.
- virtual void StartFailed(StartResult result,
- const tracked_objects::Location& location);
-
- // Start up complete, update the state and invoke the callback.
- // Note: this is performed on the datatype's thread.
- virtual void StartDone(DataTypeController::StartResult result,
- DataTypeController::State new_state,
- const tracked_objects::Location& location);
-
- // UI thread implementation of StartDone.
- virtual void StartDoneImpl(DataTypeController::StartResult result,
- DataTypeController::State new_state,
- const tracked_objects::Location& location);
-
- // Perform any DataType controller specific state cleanup before stopping
- // the datatype controller. The default implementation is a no-op.
- // Note: this is performed on the frontend (UI) thread.
- virtual void StopModels();
-
- // Post the StopAssociation task to the thread the datatype lives on.
- // Note: this is performed on the frontend (UI) thread.
- // Return value: True if task posted successfully, False otherwise.
- virtual bool StopAssociationAsync() = 0;
-
- // Disassociate the models and destroy the sync components.
- // Note: this is performed on the datatype's thread.
- virtual void StopAssociation();
-
- // Implementation of OnUnrecoverableError that lives on UI thread.
- virtual void OnUnrecoverableErrorImpl(
- const tracked_objects::Location& from_here,
- const std::string& message);
-
- // DataType specific histogram methods. Because histograms use static's, the
- // specific datatype controllers must implement this themselves.
- // Important: calling them on other threads can lead to memory corruption!
- // Record unrecoverable errors. Called on Datatype's thread.
- virtual void RecordUnrecoverableError(
- const tracked_objects::Location& from_here,
- const std::string& message) = 0;
- // Record association time. Called on Datatype's thread.
- virtual void RecordAssociationTime(base::TimeDelta time) = 0;
- // Record causes of start failure. Called on UI thread.
- virtual void RecordStartFailure(StartResult result) = 0;
-
- // Accessors and mutators used by derived classes.
- ProfileSyncFactory* profile_sync_factory() const;
- Profile* profile() const;
- ProfileSyncService* profile_sync_service() const;
- void set_state(State state);
- void set_model_associator(AssociatorInterface* associator);
- void set_change_processor(ChangeProcessor* change_processor);
-
- private:
- ProfileSyncFactory* const profile_sync_factory_;
- Profile* const profile_;
- ProfileSyncService* const profile_sync_service_;
-
- State state_;
-
- scoped_ptr<StartCallback> start_callback_;
- scoped_ptr<AssociatorInterface> model_associator_;
- scoped_ptr<ChangeProcessor> change_processor_;
-
- // Locks/Barriers for aborting association early.
- base::Lock abort_association_lock_;
- bool abort_association_;
- base::WaitableEvent abort_association_complete_;
-
- // Barrier to ensure that the datatype has been stopped on the DB thread
- // from the UI thread.
- base::WaitableEvent datatype_stopped_;
-
- DISALLOW_COPY_AND_ASSIGN(NonFrontendDataTypeController);
-};
-
-} // namespace browser_sync
-
-#endif // CHROME_BROWSER_SYNC_GLUE_NON_FRONTEND_DATA_TYPE_CONTROLLER_H__
diff --git a/chrome/browser/sync/glue/non_frontend_data_type_controller_mock.cc b/chrome/browser/sync/glue/non_frontend_data_type_controller_mock.cc
deleted file mode 100644
index dfde595..0000000
--- a/chrome/browser/sync/glue/non_frontend_data_type_controller_mock.cc
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2011 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.
-
-#include "chrome/browser/sync/glue/non_frontend_data_type_controller_mock.h"
-
-namespace browser_sync {
-
-NonFrontendDataTypeControllerMock::NonFrontendDataTypeControllerMock() {}
-
-NonFrontendDataTypeControllerMock::~NonFrontendDataTypeControllerMock() {}
-
-} // namespace browser_sync
diff --git a/chrome/browser/sync/glue/non_frontend_data_type_controller_mock.h b/chrome/browser/sync/glue/non_frontend_data_type_controller_mock.h
deleted file mode 100644
index 8e4316f..0000000
--- a/chrome/browser/sync/glue/non_frontend_data_type_controller_mock.h
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright (c) 2011 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_MOCK_H__
-#define CHROME_BROWSER_SYNC_GLUE_NON_FRONTEND_DATA_TYPE_CONTROLLER_MOCK_H__
-#pragma once
-
-#include "chrome/browser/sync/glue/non_frontend_data_type_controller.h"
-#include "testing/gmock/include/gmock/gmock.h"
-
-namespace browser_sync {
-
-class NonFrontendDataTypeControllerMock : public NonFrontendDataTypeController {
- public:
- NonFrontendDataTypeControllerMock();
- virtual ~NonFrontendDataTypeControllerMock();
-
- // DataTypeController mocks.
- MOCK_METHOD1(Start, void(StartCallback* start_callback));
- MOCK_METHOD0(Stop, void());
- MOCK_METHOD0(enabled, bool());
- MOCK_CONST_METHOD0(type, syncable::ModelType());
- MOCK_CONST_METHOD0(name, std::string());
- MOCK_CONST_METHOD0(model_safe_group, browser_sync::ModelSafeGroup());
- MOCK_CONST_METHOD0(state, State());
- MOCK_METHOD2(OnUnrecoverableError, void(const tracked_objects::Location&,
- const std::string&));
-
- // NonFrontendDataTypeController mocks.
- MOCK_METHOD0(StartModels, bool());
- MOCK_METHOD0(StartAssociationAsync, bool());
- MOCK_METHOD0(StartAssociation, void());
- MOCK_METHOD0(CreateSyncComponents, void());
- MOCK_METHOD2(StartFailed, void(StartResult result,
- const tracked_objects::Location& from_here));
- MOCK_METHOD3(StartDone, void(DataTypeController::StartResult result,
- DataTypeController::State new_state,
- const tracked_objects::Location& location));
- MOCK_METHOD3(StartDoneImpl, void(DataTypeController::StartResult result,
- DataTypeController::State new_state,
- const tracked_objects::Location& location));
- MOCK_METHOD0(StopModels, void());
- MOCK_METHOD0(StopAssociationAsync, bool());
- MOCK_METHOD0(StopAssociation, void());
- MOCK_METHOD2(OnUnrecoverableErrorImpl, void(const tracked_objects::Location&,
- const std::string&));
- MOCK_METHOD2(RecordUnrecoverableError, void(const tracked_objects::Location&,
- const std::string&));
- MOCK_METHOD1(RecordAssociationTime, void(base::TimeDelta time));
- MOCK_METHOD1(RecordStartFailure, void(StartResult result));
-};
-
-} // namespace browser_sync
-
-#endif // CHROME_BROWSER_SYNC_GLUE_NON_FRONTEND_DATA_TYPE_CONTROLLER_MOCK_H__
diff --git a/chrome/browser/sync/glue/non_frontend_data_type_controller_unittest.cc b/chrome/browser/sync/glue/non_frontend_data_type_controller_unittest.cc
deleted file mode 100644
index 602e582..0000000
--- a/chrome/browser/sync/glue/non_frontend_data_type_controller_unittest.cc
+++ /dev/null
@@ -1,397 +0,0 @@
-// Copyright (c) 2011 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.
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-#include "base/callback.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/message_loop.h"
-#include "base/task.h"
-#include "base/test/test_timeouts.h"
-#include "base/tracked_objects.h"
-#include "base/synchronization/waitable_event.h"
-#include "chrome/browser/sync/engine/model_safe_worker.h"
-#include "chrome/browser/sync/glue/change_processor_mock.h"
-#include "chrome/browser/sync/glue/non_frontend_data_type_controller.h"
-#include "chrome/browser/sync/glue/non_frontend_data_type_controller_mock.h"
-#include "chrome/browser/sync/glue/model_associator_mock.h"
-#include "chrome/browser/sync/profile_sync_factory_mock.h"
-#include "chrome/browser/sync/profile_sync_service_mock.h"
-#include "chrome/test/profile_mock.h"
-#include "content/browser/browser_thread.h"
-
-using base::WaitableEvent;
-using browser_sync::ChangeProcessorMock;
-using browser_sync::DataTypeController;
-using browser_sync::GROUP_DB;
-using browser_sync::NonFrontendDataTypeController;
-using browser_sync::NonFrontendDataTypeControllerMock;
-using browser_sync::ModelAssociatorMock;
-using testing::_;
-using testing::DoAll;
-using testing::InvokeWithoutArgs;
-using testing::Return;
-using testing::SetArgumentPointee;
-using testing::StrictMock;
-
-class StartCallback {
- public:
- MOCK_METHOD2(Run, void(DataTypeController::StartResult result,
- const tracked_objects::Location& from_here));
-};
-
-ACTION_P(WaitOnEvent, event) {
- event->Wait();
-}
-
-ACTION_P(SignalEvent, event) {
- event->Signal();
-}
-
-class NonFrontendDataTypeControllerFake : public NonFrontendDataTypeController {
- public:
- NonFrontendDataTypeControllerFake(
- ProfileSyncFactory* profile_sync_factory,
- Profile* profile,
- NonFrontendDataTypeControllerMock* mock)
- : NonFrontendDataTypeController(profile_sync_factory,
- profile),
- mock_(mock) {}
-
- virtual syncable::ModelType type() const { return syncable::BOOKMARKS; }
- virtual browser_sync::ModelSafeGroup model_safe_group() const {
- return GROUP_DB;
- }
-
- private:
- virtual void CreateSyncComponents() {
- ProfileSyncFactory::SyncComponents sync_components =
- profile_sync_factory()->
- CreateBookmarkSyncComponents(profile_sync_service(), this);
- set_model_associator(sync_components.model_associator);
- set_change_processor(sync_components.change_processor);
- }
- virtual bool StartAssociationAsync() {
- mock_->StartAssociationAsync();
- return BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
- NewRunnableMethod(
- this,
- &NonFrontendDataTypeControllerFake::StartAssociation));
- }
- virtual bool StopAssociationAsync() {
- mock_->StopAssociationAsync();
- return BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
- NewRunnableMethod(
- this,
- &NonFrontendDataTypeControllerFake::StopAssociation));
- }
-
- // We mock the following methods because their default implementations do
- // nothing, but we still want to make sure they're called appropriately.
- virtual bool StartModels() {
- return mock_->StartModels();
- }
- virtual void StopModels() {
- mock_->StopModels();
- }
- virtual void RecordUnrecoverableError(
- const tracked_objects::Location& from_here,
- const std::string& message) {
- mock_->RecordUnrecoverableError(from_here, message);
- }
- virtual void RecordAssociationTime(base::TimeDelta time) {
- mock_->RecordAssociationTime(time);
- }
- virtual void RecordStartFailure(DataTypeController::StartResult result) {
- mock_->RecordStartFailure(result);
- }
- private:
- NonFrontendDataTypeControllerMock* mock_;
-};
-
-class NonFrontendDataTypeControllerTest : public testing::Test {
- public:
- NonFrontendDataTypeControllerTest()
- : ui_thread_(BrowserThread::UI, &message_loop_),
- db_thread_(BrowserThread::DB),
- model_associator_(NULL),
- change_processor_(NULL),
- signaled_(false) {}
-
- virtual void SetUp() {
- EXPECT_CALL(profile_, GetProfileSyncService()).WillRepeatedly(
- Return(&service_));
- db_thread_.Start();
- profile_sync_factory_.reset(new ProfileSyncFactoryMock());
-
- // Both of these are refcounted, so don't need to be released.
- dtc_mock_ = new StrictMock<NonFrontendDataTypeControllerMock>();
- non_frontend_dtc_ =
- new NonFrontendDataTypeControllerFake(profile_sync_factory_.get(),
- &profile_,
- dtc_mock_.get());
- }
-
- virtual void TearDown() {
- db_thread_.Stop();
- }
-
- protected:
- void SetStartExpectations() {
- EXPECT_CALL(*dtc_mock_, StartModels()).WillOnce(Return(true));
- model_associator_ = new ModelAssociatorMock();
- change_processor_ = new ChangeProcessorMock();
- EXPECT_CALL(*profile_sync_factory_, CreateBookmarkSyncComponents(_, _)).
- WillOnce(Return(ProfileSyncFactory::SyncComponents(model_associator_,
- change_processor_)));
- }
-
- void SetAssociateExpectations() {
- EXPECT_CALL(*dtc_mock_, StartAssociationAsync());
- EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
- WillOnce(Return(true));
- EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)).
- WillOnce(DoAll(SetArgumentPointee<0>(true), Return(true)));
- EXPECT_CALL(*model_associator_, AssociateModels()).
- WillOnce(Return(true));
- EXPECT_CALL(*dtc_mock_, RecordAssociationTime(_));
- }
-
- void SetActivateExpectations(DataTypeController::StartResult result) {
- EXPECT_CALL(service_, ActivateDataType(_, _));
- EXPECT_CALL(start_callback_, Run(result,_));
- }
-
- void SetStopExpectations() {
- EXPECT_CALL(*dtc_mock_, StopAssociationAsync());
- EXPECT_CALL(*dtc_mock_, StopModels());
- EXPECT_CALL(service_, DeactivateDataType(_, _));
- EXPECT_CALL(*model_associator_, DisassociateModels());
- }
-
- void SetStartFailExpectations(DataTypeController::StartResult result) {
- EXPECT_CALL(*dtc_mock_, StopModels());
- EXPECT_CALL(*dtc_mock_, RecordStartFailure(result));
- EXPECT_CALL(start_callback_, Run(result,_));
- }
-
- static void SignalDone(WaitableEvent* done, bool* signaled) {
- done->Signal();
- *signaled = true;
- }
-
- void WaitForDTC() {
- WaitableEvent done(false, false);
- signaled_ = false;
- BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
- NewRunnableFunction(&NonFrontendDataTypeControllerTest::SignalDone,
- &done, &signaled_));
- done.TimedWait(base::TimeDelta::FromMilliseconds(
- TestTimeouts::action_max_timeout_ms()));
- if (!signaled_) {
- ADD_FAILURE() << "Timed out waiting for DB thread to finish.";
- }
- signaled_ = false;
- MessageLoop::current()->RunAllPending();
- }
-
- MessageLoopForUI message_loop_;
- BrowserThread ui_thread_;
- BrowserThread db_thread_;
- scoped_refptr<NonFrontendDataTypeControllerFake> non_frontend_dtc_;
- scoped_ptr<ProfileSyncFactoryMock> profile_sync_factory_;
- scoped_refptr<NonFrontendDataTypeControllerMock> dtc_mock_;
- ProfileMock profile_;
- ProfileSyncServiceMock service_;
- ModelAssociatorMock* model_associator_;
- ChangeProcessorMock* change_processor_;
- StartCallback start_callback_;
- bool signaled_;
-};
-
-TEST_F(NonFrontendDataTypeControllerTest, StartOk) {
- SetStartExpectations();
- SetAssociateExpectations();
- SetActivateExpectations(DataTypeController::OK);
- EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
- non_frontend_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run));
- WaitForDTC();
- EXPECT_EQ(DataTypeController::RUNNING, non_frontend_dtc_->state());
-}
-
-TEST_F(NonFrontendDataTypeControllerTest, StartFirstRun) {
- SetStartExpectations();
- EXPECT_CALL(*dtc_mock_, StartAssociationAsync());
- EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
- WillOnce(Return(true));
- EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)).
- WillOnce(DoAll(SetArgumentPointee<0>(false), Return(true)));
- EXPECT_CALL(*model_associator_, AssociateModels()).
- WillOnce(Return(true));
- EXPECT_CALL(*dtc_mock_, RecordAssociationTime(_));
- SetActivateExpectations(DataTypeController::OK_FIRST_RUN);
- EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
- non_frontend_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run));
- WaitForDTC();
- EXPECT_EQ(DataTypeController::RUNNING, non_frontend_dtc_->state());
-}
-
-TEST_F(NonFrontendDataTypeControllerTest, AbortDuringStartModels) {
- EXPECT_CALL(*dtc_mock_, StartModels()).WillOnce(Return(false));
- SetStartFailExpectations(DataTypeController::ABORTED);
- EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
- non_frontend_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run));
- WaitForDTC();
- EXPECT_EQ(DataTypeController::MODEL_STARTING, non_frontend_dtc_->state());
- non_frontend_dtc_->Stop();
- EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
-}
-
-TEST_F(NonFrontendDataTypeControllerTest, StartAssociationFailed) {
- SetStartExpectations();
- EXPECT_CALL(*dtc_mock_, StartAssociationAsync());
- EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
- WillOnce(Return(true));
- EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)).
- WillOnce(DoAll(SetArgumentPointee<0>(true), Return(true)));
- EXPECT_CALL(*model_associator_, AssociateModels()).
- WillOnce(Return(false));
- EXPECT_CALL(*dtc_mock_, RecordAssociationTime(_));
- SetStartFailExpectations(DataTypeController::ASSOCIATION_FAILED);
- // Set up association to fail with an association failed error.
- EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
- non_frontend_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run));
- WaitForDTC();
- EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
-}
-
-TEST_F(NonFrontendDataTypeControllerTest,
- StartAssociationTriggersUnrecoverableError) {
- SetStartExpectations();
- SetStartFailExpectations(DataTypeController::UNRECOVERABLE_ERROR);
- // Set up association to fail with an unrecoverable error.
- EXPECT_CALL(*dtc_mock_, StartAssociationAsync());
- EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
- WillRepeatedly(Return(true));
- EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)).
- WillRepeatedly(DoAll(SetArgumentPointee<0>(false), Return(false)));
- EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
- non_frontend_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run));
- WaitForDTC();
- EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
-}
-
-TEST_F(NonFrontendDataTypeControllerTest, StartAssociationCryptoNotReady) {
- SetStartExpectations();
- SetStartFailExpectations(DataTypeController::NEEDS_CRYPTO);
- // Set up association to fail with a NEEDS_CRYPTO error.
- EXPECT_CALL(*dtc_mock_, StartAssociationAsync());
- EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
- WillRepeatedly(Return(false));
- EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
- non_frontend_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run));
- WaitForDTC();
- EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
-}
-
-// Trigger a Stop() call when we check if the model associator has user created
-// nodes.
-TEST_F(NonFrontendDataTypeControllerTest, AbortDuringAssociationInactive) {
- WaitableEvent wait_for_db_thread_pause(false, false);
- WaitableEvent pause_db_thread(false, false);
-
- SetStartExpectations();
- EXPECT_CALL(*dtc_mock_, StartAssociationAsync());
- EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
- WillOnce(Return(true));
- EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)).
- WillOnce(DoAll(
- SignalEvent(&wait_for_db_thread_pause),
- WaitOnEvent(&pause_db_thread),
- SetArgumentPointee<0>(true),
- Return(true)));
- EXPECT_CALL(*model_associator_, AbortAssociation()).WillOnce(
- SignalEvent(&pause_db_thread));
- EXPECT_CALL(*model_associator_, AssociateModels()).WillOnce(Return(true));
- EXPECT_CALL(*dtc_mock_, RecordAssociationTime(_));
- EXPECT_CALL(service_, ActivateDataType(_, _));
- EXPECT_CALL(start_callback_, Run(DataTypeController::ABORTED,_));
- EXPECT_CALL(*dtc_mock_, RecordStartFailure(DataTypeController::ABORTED));
- SetStopExpectations();
- EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
- non_frontend_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run));
- wait_for_db_thread_pause.Wait();
- non_frontend_dtc_->Stop();
- WaitForDTC();
- EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
-}
-
-// Same as above but abort during the Activate call.
-TEST_F(NonFrontendDataTypeControllerTest, AbortDuringAssociationActivated) {
- WaitableEvent wait_for_db_thread_pause(false, false);
- WaitableEvent pause_db_thread(false, false);
-
- SetStartExpectations();
- EXPECT_CALL(*dtc_mock_, StartAssociationAsync());
- EXPECT_CALL(*model_associator_, CryptoReadyIfNecessary()).
- WillOnce(Return(true));
- EXPECT_CALL(*model_associator_, SyncModelHasUserCreatedNodes(_)).
- WillOnce(DoAll(
- SetArgumentPointee<0>(true),
- Return(true)));
- EXPECT_CALL(*model_associator_, AbortAssociation()).WillOnce(
- SignalEvent(&pause_db_thread));
- EXPECT_CALL(*model_associator_, AssociateModels()).
- WillOnce(Return(true));
- EXPECT_CALL(*dtc_mock_, RecordAssociationTime(_));
- EXPECT_CALL(service_, ActivateDataType(_, _)).WillOnce(DoAll(
- SignalEvent(&wait_for_db_thread_pause),
- WaitOnEvent(&pause_db_thread)));
- EXPECT_CALL(start_callback_, Run(DataTypeController::ABORTED,_));
- EXPECT_CALL(*dtc_mock_, RecordStartFailure(DataTypeController::ABORTED));
- SetStopExpectations();
- EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
- non_frontend_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run));
- wait_for_db_thread_pause.Wait();
- non_frontend_dtc_->Stop();
- WaitForDTC();
- EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
-}
-
-TEST_F(NonFrontendDataTypeControllerTest, Stop) {
- SetStartExpectations();
- SetAssociateExpectations();
- SetActivateExpectations(DataTypeController::OK);
- SetStopExpectations();
- EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
- non_frontend_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run));
- WaitForDTC();
- EXPECT_EQ(DataTypeController::RUNNING, non_frontend_dtc_->state());
- non_frontend_dtc_->Stop();
- EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
-}
-
-TEST_F(NonFrontendDataTypeControllerTest, OnUnrecoverableError) {
- SetStartExpectations();
- SetAssociateExpectations();
- SetActivateExpectations(DataTypeController::OK);
- EXPECT_CALL(*dtc_mock_, RecordUnrecoverableError(_, "Test"));
- EXPECT_CALL(service_, OnUnrecoverableError(_,_)).WillOnce(
- InvokeWithoutArgs(non_frontend_dtc_.get(),
- &NonFrontendDataTypeController::Stop));
- SetStopExpectations();
- EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
- non_frontend_dtc_->Start(NewCallback(&start_callback_, &StartCallback::Run));
- WaitForDTC();
- EXPECT_EQ(DataTypeController::RUNNING, non_frontend_dtc_->state());
- // This should cause non_frontend_dtc_->Stop() to be called.
- BrowserThread::PostTask(BrowserThread::DB, FROM_HERE,
- NewRunnableMethod(
- non_frontend_dtc_.get(),
- &NonFrontendDataTypeControllerFake::OnUnrecoverableError,
- FROM_HERE,
- std::string("Test")));
- WaitForDTC();
- EXPECT_EQ(DataTypeController::NOT_RUNNING, non_frontend_dtc_->state());
-}
diff --git a/chrome/browser/sync/glue/password_data_type_controller.cc b/chrome/browser/sync/glue/password_data_type_controller.cc
index 69b1d89..2589861 100644
--- a/chrome/browser/sync/glue/password_data_type_controller.cc
+++ b/chrome/browser/sync/glue/password_data_type_controller.cc
@@ -5,66 +5,105 @@
#include "chrome/browser/sync/glue/password_data_type_controller.h"
#include "base/metrics/histogram.h"
+#include "base/logging.h"
#include "base/task.h"
+#include "base/time.h"
#include "chrome/browser/password_manager/password_store.h"
#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/sync/profile_sync_factory.h"
+#include "chrome/browser/sync/glue/password_change_processor.h"
+#include "chrome/browser/sync/glue/password_model_associator.h"
#include "chrome/browser/sync/profile_sync_service.h"
-#include "chrome/browser/webdata/web_data_service.h"
+#include "chrome/browser/sync/profile_sync_factory.h"
#include "content/browser/browser_thread.h"
namespace browser_sync {
PasswordDataTypeController::PasswordDataTypeController(
ProfileSyncFactory* profile_sync_factory,
- Profile* profile)
- : NonFrontendDataTypeController(profile_sync_factory,
- profile) {
+ Profile* profile,
+ ProfileSyncService* sync_service)
+ : profile_sync_factory_(profile_sync_factory),
+ profile_(profile),
+ sync_service_(sync_service),
+ state_(NOT_RUNNING),
+ abort_association_(false),
+ abort_association_complete_(false, false),
+ datatype_stopped_(false, false) {
+ DCHECK(profile_sync_factory);
+ DCHECK(profile);
+ DCHECK(sync_service);
}
PasswordDataTypeController::~PasswordDataTypeController() {
}
-bool PasswordDataTypeController::StartModels() {
+void PasswordDataTypeController::Start(StartCallback* start_callback) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DCHECK_EQ(state(), MODEL_STARTING);
- password_store_ = profile()->GetPasswordStore(Profile::EXPLICIT_ACCESS);
+ DCHECK(start_callback);
+ if (state_ != NOT_RUNNING) {
+ start_callback->Run(BUSY, FROM_HERE);
+ delete start_callback;
+ return;
+ }
+
+ password_store_ = profile_->GetPasswordStore(Profile::EXPLICIT_ACCESS);
if (!password_store_.get()) {
LOG(ERROR) << "PasswordStore not initialized, password datatype controller"
<< " aborting.";
- StartDoneImpl(ABORTED, NOT_RUNNING, FROM_HERE);
- return false;
+ state_ = NOT_RUNNING;
+ start_callback->Run(ABORTED, FROM_HERE);
+ delete start_callback;
+ return;
}
- return true;
-}
-bool PasswordDataTypeController::StartAssociationAsync() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DCHECK_EQ(state(), ASSOCIATING);
- DCHECK(password_store_.get());
+ start_callback_.reset(start_callback);
+ abort_association_ = false;
+ set_state(ASSOCIATING);
password_store_->ScheduleTask(
- NewRunnableMethod(this, &PasswordDataTypeController::StartAssociation));
- return true;
+ NewRunnableMethod(this, &PasswordDataTypeController::StartImpl));
}
-void PasswordDataTypeController::CreateSyncComponents() {
- DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
- DCHECK_EQ(state(), ASSOCIATING);
- ProfileSyncFactory::SyncComponents sync_components =
- profile_sync_factory()->CreatePasswordSyncComponents(
- profile_sync_service(),
- password_store_.get(),
- this);
- set_model_associator(sync_components.model_associator);
- set_change_processor(sync_components.change_processor);
-}
-
-bool PasswordDataTypeController::StopAssociationAsync() {
+// TODO(sync): Blocking the UI thread at shutdown is bad. If we had a way of
+// distinguishing chrome shutdown from sync shutdown, we should be able to avoid
+// this (http://crbug.com/55662). Further, all this functionality should be
+// abstracted to a higher layer, where we could ensure all datatypes are doing
+// the same thing (http://crbug.com/76232).
+void PasswordDataTypeController::Stop() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DCHECK_EQ(state(), STOPPING);
+
+ // If Stop() is called while Start() is waiting for association to
+ // complete, we need to abort the association and wait for the PASSWORD
+ // thread to finish the StartImpl() task.
+ if (state_ == ASSOCIATING) {
+ {
+ base::AutoLock lock(abort_association_lock_);
+ abort_association_ = true;
+ if (model_associator_.get())
+ model_associator_->AbortAssociation();
+ }
+ // Wait for the model association to abort.
+ abort_association_complete_.Wait();
+ StartDoneImpl(ABORTED, STOPPING);
+ }
+
+ // If Stop() is called while Start() is waiting for another service to load,
+ // abort the start.
+ if (state_ == MODEL_STARTING)
+ StartDoneImpl(ABORTED, STOPPING);
+
+ DCHECK(!start_callback_.get());
+
+ if (change_processor_ != NULL)
+ sync_service_->DeactivateDataType(this, change_processor_.get());
+
+ set_state(NOT_RUNNING);
DCHECK(password_store_.get());
password_store_->ScheduleTask(
- NewRunnableMethod(this, &PasswordDataTypeController::StopAssociation));
+ NewRunnableMethod(this, &PasswordDataTypeController::StopImpl));
+ datatype_stopped_.Wait();
+}
+
+bool PasswordDataTypeController::enabled() {
return true;
}
@@ -77,23 +116,111 @@ browser_sync::ModelSafeGroup PasswordDataTypeController::model_safe_group()
return browser_sync::GROUP_PASSWORD;
}
-void PasswordDataTypeController::RecordUnrecoverableError(
- const tracked_objects::Location& from_here,
- const std::string& message) {
- DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
- UMA_HISTOGRAM_COUNTS("Sync.PasswordRunFailures", 1);
+std::string PasswordDataTypeController::name() const {
+ // For logging only.
+ return "password";
}
-void PasswordDataTypeController::RecordAssociationTime(base::TimeDelta time) {
- DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
- UMA_HISTOGRAM_TIMES("Sync.PasswordAssociationTime", time);
+DataTypeController::State PasswordDataTypeController::state() const {
+ return state_;
}
-void PasswordDataTypeController::RecordStartFailure(StartResult result) {
+void PasswordDataTypeController::StartImpl() {
+ // No additional services need to be started before we can proceed
+ // with model association.
+ {
+ base::AutoLock lock(abort_association_lock_);
+ if (abort_association_) {
+ abort_association_complete_.Signal();
+ return;
+ }
+ ProfileSyncFactory::SyncComponents sync_components =
+ profile_sync_factory_->CreatePasswordSyncComponents(
+ sync_service_,
+ password_store_.get(),
+ this);
+ model_associator_.reset(sync_components.model_associator);
+ change_processor_.reset(sync_components.change_processor);
+ }
+
+ if (!model_associator_->CryptoReadyIfNecessary()) {
+ StartFailed(NEEDS_CRYPTO);
+ return;
+ }
+
+ bool sync_has_nodes = false;
+ if (!model_associator_->SyncModelHasUserCreatedNodes(&sync_has_nodes)) {
+ StartFailed(UNRECOVERABLE_ERROR);
+ return;
+ }
+
+ base::TimeTicks start_time = base::TimeTicks::Now();
+ bool merge_success = model_associator_->AssociateModels();
+ UMA_HISTOGRAM_TIMES("Sync.PasswordAssociationTime",
+ base::TimeTicks::Now() - start_time);
+ if (!merge_success) {
+ StartFailed(ASSOCIATION_FAILED);
+ return;
+ }
+
+ sync_service_->ActivateDataType(this, change_processor_.get());
+ StartDone(!sync_has_nodes ? OK_FIRST_RUN : OK, RUNNING);
+}
+
+void PasswordDataTypeController::StartDone(
+ DataTypeController::StartResult result,
+ DataTypeController::State new_state) {
+ abort_association_complete_.Signal();
+ base::AutoLock lock(abort_association_lock_);
+ if (!abort_association_) {
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ NewRunnableMethod(
+ this,
+ &PasswordDataTypeController::StartDoneImpl,
+ result,
+ new_state));
+ }
+}
+
+void PasswordDataTypeController::StartDoneImpl(
+ DataTypeController::StartResult result,
+ DataTypeController::State new_state) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ set_state(new_state);
+ start_callback_->Run(result, FROM_HERE);
+ start_callback_.reset();
+}
+
+void PasswordDataTypeController::StopImpl() {
+ if (model_associator_ != NULL)
+ model_associator_->DisassociateModels();
+
+ change_processor_.reset();
+ model_associator_.reset();
+
+ datatype_stopped_.Signal();
+}
+
+void PasswordDataTypeController::StartFailed(StartResult result) {
+ change_processor_.reset();
+ model_associator_.reset();
+ StartDone(result, NOT_RUNNING);
+}
+
+void PasswordDataTypeController::OnUnrecoverableError(
+ const tracked_objects::Location& from_here, const std::string& message) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ NewRunnableMethod(this,
+ &PasswordDataTypeController::OnUnrecoverableErrorImpl,
+ from_here, message));
+}
+
+void PasswordDataTypeController::OnUnrecoverableErrorImpl(
+ const tracked_objects::Location& from_here,
+ const std::string& message) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- UMA_HISTOGRAM_ENUMERATION("Sync.PasswordStartFailures",
- result,
- MAX_START_RESULT);
+ sync_service_->OnUnrecoverableError(from_here, message);
}
} // namespace browser_sync
diff --git a/chrome/browser/sync/glue/password_data_type_controller.h b/chrome/browser/sync/glue/password_data_type_controller.h
index f2e14f8..1a3a9e41 100644
--- a/chrome/browser/sync/glue/password_data_type_controller.h
+++ b/chrome/browser/sync/glue/password_data_type_controller.h
@@ -8,40 +8,83 @@
#include <string>
+#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
-#include "chrome/browser/sync/glue/non_frontend_data_type_controller.h"
+#include "base/synchronization/waitable_event.h"
+#include "chrome/browser/sync/profile_sync_service.h"
+#include "chrome/browser/sync/glue/data_type_controller.h"
class PasswordStore;
+class Profile;
+class ProfileSyncFactory;
+class ProfileSyncService;
namespace browser_sync {
+class AssociatorInterface;
+class ChangeProcessor;
+class ControlTask;
+
// A class that manages the startup and shutdown of password sync.
-class PasswordDataTypeController : public NonFrontendDataTypeController {
+class PasswordDataTypeController : public DataTypeController {
public:
PasswordDataTypeController(
ProfileSyncFactory* profile_sync_factory,
- Profile* profile);
+ Profile* profile,
+ ProfileSyncService* sync_service);
virtual ~PasswordDataTypeController();
- // NonFrontendDataTypeController implementation
+ // DataTypeController implementation
+ virtual void Start(StartCallback* start_callback);
+
+ virtual void Stop();
+
+ virtual bool enabled();
+
virtual syncable::ModelType type() const;
+
virtual browser_sync::ModelSafeGroup model_safe_group() const;
- protected:
- // NonFrontendDataTypeController interface.
- virtual bool StartModels();
- virtual bool StartAssociationAsync();
- virtual void CreateSyncComponents();
- virtual bool StopAssociationAsync();
- virtual void RecordUnrecoverableError(
- const tracked_objects::Location& from_here,
- const std::string& message);
- virtual void RecordAssociationTime(base::TimeDelta time);
- virtual void RecordStartFailure(StartResult result);
+ virtual std::string name() const;
+
+ virtual State state() const;
+
+ // UnrecoverableHandler implementation
+ virtual void OnUnrecoverableError(const tracked_objects::Location& from_here,
+ const std::string& message);
private:
+ void StartImpl();
+ void StartDone(StartResult result, State state);
+ void StartDoneImpl(StartResult result, State state);
+ void StopImpl();
+ void StartFailed(StartResult result);
+ void OnUnrecoverableErrorImpl(const tracked_objects::Location& from_here,
+ const std::string& message);
+
+ void set_state(State state) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ state_ = state;
+ }
+
+ ProfileSyncFactory* profile_sync_factory_;
+ Profile* profile_;
+ ProfileSyncService* sync_service_;
+ State state_;
+
+ scoped_ptr<AssociatorInterface> model_associator_;
+ scoped_ptr<ChangeProcessor> change_processor_;
+ scoped_ptr<StartCallback> start_callback_;
scoped_refptr<PasswordStore> password_store_;
+ base::Lock abort_association_lock_;
+ bool abort_association_;
+ base::WaitableEvent abort_association_complete_;
+
+ // Barrier to ensure that the datatype has been stopped on the DB thread
+ // from the UI thread.
+ base::WaitableEvent datatype_stopped_;
+
DISALLOW_COPY_AND_ASSIGN(PasswordDataTypeController);
};
diff --git a/chrome/browser/sync/glue/typed_url_data_type_controller.cc b/chrome/browser/sync/glue/typed_url_data_type_controller.cc
index 73776fe..93be84d 100644
--- a/chrome/browser/sync/glue/typed_url_data_type_controller.cc
+++ b/chrome/browser/sync/glue/typed_url_data_type_controller.cc
@@ -4,10 +4,14 @@
#include "chrome/browser/sync/glue/typed_url_data_type_controller.h"
+#include "base/logging.h"
#include "base/metrics/histogram.h"
#include "base/task.h"
+#include "base/time.h"
#include "chrome/browser/history/history.h"
#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/sync/glue/typed_url_change_processor.h"
+#include "chrome/browser/sync/glue/typed_url_model_associator.h"
#include "chrome/browser/sync/profile_sync_factory.h"
#include "chrome/browser/sync/profile_sync_service.h"
#include "content/browser/browser_thread.h"
@@ -22,7 +26,11 @@ class ControlTask : public HistoryDBTask {
virtual bool RunOnDBThread(history::HistoryBackend* backend,
history::HistoryDatabase* db) {
- controller_->RunOnHistoryThread(start_, backend);
+ if (start_) {
+ controller_->StartImpl(backend);
+ } else {
+ controller_->StopImpl();
+ }
// Release the reference to the controller. This ensures that
// the controller isn't held past its lifetime in unit tests.
@@ -39,90 +47,104 @@ class ControlTask : public HistoryDBTask {
TypedUrlDataTypeController::TypedUrlDataTypeController(
ProfileSyncFactory* profile_sync_factory,
- Profile* profile)
- : NonFrontendDataTypeController(profile_sync_factory,
- profile),
- backend_(NULL) {
+ Profile* profile,
+ ProfileSyncService* sync_service)
+ : profile_sync_factory_(profile_sync_factory),
+ profile_(profile),
+ sync_service_(sync_service),
+ state_(NOT_RUNNING),
+ abort_association_(false),
+ abort_association_complete_(false, false),
+ datatype_stopped_(false, false) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(profile_sync_factory);
+ DCHECK(profile);
+ DCHECK(sync_service);
}
TypedUrlDataTypeController::~TypedUrlDataTypeController() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
}
-void TypedUrlDataTypeController::RunOnHistoryThread(bool start,
- history::HistoryBackend* backend) {
- DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
- // The only variable we can access here is backend_, since it is always
- // read from the DB thread. Touching anything else could lead to memory
- // corruption.
- backend_ = backend;
- if (start) {
- StartAssociation();
- } else {
- StopAssociation();
+void TypedUrlDataTypeController::Start(StartCallback* start_callback) {
+ VLOG(1) << "Starting typed_url data controller.";
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(start_callback);
+ if (state_ != NOT_RUNNING || start_callback_.get()) {
+ start_callback->Run(BUSY, FROM_HERE);
+ delete start_callback;
+ return;
}
- backend_ = NULL;
-}
-bool TypedUrlDataTypeController::StartModels() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DCHECK_EQ(state(), MODEL_STARTING);
- HistoryService* history = profile()->GetHistoryServiceWithoutCreating();
+ start_callback_.reset(start_callback);
+ abort_association_ = false;
+
+ HistoryService* history = profile_->GetHistoryServiceWithoutCreating();
if (history) {
+ set_state(ASSOCIATING);
history_service_ = history;
- return true;
+ history_service_->ScheduleDBTask(new ControlTask(this, true), this);
} else {
+ set_state(MODEL_STARTING);
notification_registrar_.Add(this, NotificationType::HISTORY_LOADED,
NotificationService::AllSources());
- return false;
}
}
-bool TypedUrlDataTypeController::StartAssociationAsync() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DCHECK_EQ(state(), ASSOCIATING);
- DCHECK(history_service_.get());
- history_service_->ScheduleDBTask(new ControlTask(this, true), this);
- return true;
-}
-
-void TypedUrlDataTypeController::CreateSyncComponents() {
- DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
- DCHECK_EQ(state(), ASSOCIATING);
- DCHECK(backend_);
- ProfileSyncFactory::SyncComponents sync_components =
- profile_sync_factory()->CreateTypedUrlSyncComponents(
- profile_sync_service(),
- backend_,
- this);
- set_model_associator(sync_components.model_associator);
- set_change_processor(sync_components.change_processor);
-}
-
void TypedUrlDataTypeController::Observe(NotificationType type,
const NotificationSource& source,
const NotificationDetails& details) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DCHECK_EQ(state(), MODEL_STARTING);
+ VLOG(1) << "History loaded observed.";
notification_registrar_.Remove(this,
NotificationType::HISTORY_LOADED,
NotificationService::AllSources());
- history_service_ = profile()->GetHistoryServiceWithoutCreating();
+
+ history_service_ = profile_->GetHistoryServiceWithoutCreating();
DCHECK(history_service_.get());
- set_state(ASSOCIATING);
- StopAssociationAsync();
+ history_service_->ScheduleDBTask(new ControlTask(this, true), this);
}
-void TypedUrlDataTypeController::StopModels() {
+// TODO(sync): Blocking the UI thread at shutdown is bad. If we had a way of
+// distinguishing chrome shutdown from sync shutdown, we should be able to avoid
+// this (http://crbug.com/55662). Further, all this functionality should be
+// abstracted to a higher layer, where we could ensure all datatypes are doing
+// the same thing (http://crbug.com/76232).
+void TypedUrlDataTypeController::Stop() {
+ VLOG(1) << "Stopping typed_url data type controller.";
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DCHECK(state() == STOPPING || state() == NOT_RUNNING);
- notification_registrar_.RemoveAll();
-}
-bool TypedUrlDataTypeController::StopAssociationAsync() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- DCHECK_EQ(state(), STOPPING);
+ // If Stop() is called while Start() is waiting for association to
+ // complete, we need to abort the association and wait for the DB
+ // thread to finish the StartImpl() task.
+ if (state_ == ASSOCIATING) {
+ {
+ base::AutoLock lock(abort_association_lock_);
+ abort_association_ = true;
+ if (model_associator_.get())
+ model_associator_->AbortAssociation();
+ }
+ // Wait for the model association to abort.
+ abort_association_complete_.Wait();
+ StartDoneImpl(ABORTED, STOPPING);
+ }
+
+ // If Stop() is called while Start() is waiting for the history service to
+ // load, abort the start.
+ if (state_ == MODEL_STARTING)
+ StartDoneImpl(ABORTED, STOPPING);
+
+ DCHECK(!start_callback_.get());
+
+ if (change_processor_ != NULL)
+ sync_service_->DeactivateDataType(this, change_processor_.get());
+
+ set_state(NOT_RUNNING);
DCHECK(history_service_.get());
history_service_->ScheduleDBTask(new ControlTask(this, false), this);
+ datatype_stopped_.Wait();
+}
+
+bool TypedUrlDataTypeController::enabled() {
return true;
}
@@ -135,22 +157,125 @@ browser_sync::ModelSafeGroup TypedUrlDataTypeController::model_safe_group()
return browser_sync::GROUP_HISTORY;
}
-void TypedUrlDataTypeController::RecordUnrecoverableError(
- const tracked_objects::Location& from_here,
- const std::string& message) {
- DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
- UMA_HISTOGRAM_COUNTS("Sync.TypedUrlRunFailures", 1);
+std::string TypedUrlDataTypeController::name() const {
+ // For logging only.
+ return "typed_url";
}
-void TypedUrlDataTypeController::RecordAssociationTime(base::TimeDelta time) {
- DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
- UMA_HISTOGRAM_TIMES("Sync.TypedUrlAssociationTime", time);
+DataTypeController::State TypedUrlDataTypeController::state() const {
+ return state_;
}
-void TypedUrlDataTypeController::RecordStartFailure(StartResult result) {
+void TypedUrlDataTypeController::StartImpl(history::HistoryBackend* backend) {
+ VLOG(1) << "TypedUrl data type controller StartImpl called.";
+ // No additional services need to be started before we can proceed
+ // with model association.
+ {
+ base::AutoLock lock(abort_association_lock_);
+ if (abort_association_) {
+ abort_association_complete_.Signal();
+ return;
+ }
+ ProfileSyncFactory::SyncComponents sync_components =
+ profile_sync_factory_->CreateTypedUrlSyncComponents(
+ sync_service_,
+ backend,
+ this);
+ model_associator_.reset(sync_components.model_associator);
+ change_processor_.reset(sync_components.change_processor);
+ }
+
+ if (!model_associator_->CryptoReadyIfNecessary()) {
+ StartFailed(NEEDS_CRYPTO);
+ return;
+ }
+
+ bool sync_has_nodes = false;
+ if (!model_associator_->SyncModelHasUserCreatedNodes(&sync_has_nodes)) {
+ StartFailed(UNRECOVERABLE_ERROR);
+ return;
+ }
+
+ base::TimeTicks start_time = base::TimeTicks::Now();
+ bool merge_success = model_associator_->AssociateModels();
+ UMA_HISTOGRAM_TIMES("Sync.TypedUrlAssociationTime",
+ base::TimeTicks::Now() - start_time);
+ if (!merge_success) {
+ StartFailed(ASSOCIATION_FAILED);
+ return;
+ }
+
+ sync_service_->ActivateDataType(this, change_processor_.get());
+ StartDone(!sync_has_nodes ? OK_FIRST_RUN : OK, RUNNING);
+}
+
+void TypedUrlDataTypeController::StartDone(
+ DataTypeController::StartResult result,
+ DataTypeController::State new_state) {
+ VLOG(1) << "TypedUrl data type controller StartDone called.";
+
+ abort_association_complete_.Signal();
+ base::AutoLock lock(abort_association_lock_);
+ if (!abort_association_) {
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ NewRunnableMethod(
+ this,
+ &TypedUrlDataTypeController::StartDoneImpl,
+ result,
+ new_state));
+ }
+}
+
+void TypedUrlDataTypeController::StartDoneImpl(
+ DataTypeController::StartResult result,
+ DataTypeController::State new_state) {
+ VLOG(1) << "TypedUrl data type controller StartDoneImpl called.";
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- UMA_HISTOGRAM_ENUMERATION("Sync.TypedUrlStartFailures",
- result,
- MAX_START_RESULT);
+ set_state(new_state);
+ start_callback_->Run(result, FROM_HERE);
+ start_callback_.reset();
+
+ if (result == UNRECOVERABLE_ERROR || result == ASSOCIATION_FAILED) {
+ UMA_HISTOGRAM_ENUMERATION("Sync.TypedUrlStartFailures",
+ result,
+ MAX_START_RESULT);
+ }
}
+
+void TypedUrlDataTypeController::StopImpl() {
+ VLOG(1) << "TypedUrl data type controller StopImpl called.";
+
+ if (model_associator_ != NULL)
+ model_associator_->DisassociateModels();
+
+ change_processor_.reset();
+ model_associator_.reset();
+
+ datatype_stopped_.Signal();
+}
+
+void TypedUrlDataTypeController::StartFailed(StartResult result) {
+ change_processor_.reset();
+ model_associator_.reset();
+ StartDone(result, NOT_RUNNING);
+}
+
+void TypedUrlDataTypeController::OnUnrecoverableError(
+ const tracked_objects::Location& from_here,
+ const std::string& message) {
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ NewRunnableMethod(this,
+ &TypedUrlDataTypeController::OnUnrecoverableErrorImpl,
+ from_here, message));
+}
+
+void TypedUrlDataTypeController::OnUnrecoverableErrorImpl(
+ const tracked_objects::Location& from_here,
+ const std::string& message) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ UMA_HISTOGRAM_COUNTS("Sync.TypedUrlRunFailures", 1);
+ sync_service_->OnUnrecoverableError(from_here, message);
+}
+
} // namespace browser_sync
diff --git a/chrome/browser/sync/glue/typed_url_data_type_controller.h b/chrome/browser/sync/glue/typed_url_data_type_controller.h
index 2db5520..386a01d 100644
--- a/chrome/browser/sync/glue/typed_url_data_type_controller.h
+++ b/chrome/browser/sync/glue/typed_url_data_type_controller.h
@@ -8,8 +8,11 @@
#include <string>
+#include "base/basictypes.h"
#include "base/memory/scoped_ptr.h"
-#include "chrome/browser/sync/glue/non_frontend_data_type_controller.h"
+#include "base/synchronization/waitable_event.h"
+#include "chrome/browser/sync/glue/data_type_controller.h"
+#include "chrome/browser/sync/profile_sync_service.h"
#include "content/browser/cancelable_request.h"
#include "content/common/notification_observer.h"
#include "content/common/notification_registrar.h"
@@ -18,6 +21,9 @@
class NotificationSource;
class NotificationDetails;
class HistoryService;
+class Profile;
+class ProfileSyncFactory;
+class ProfileSyncService;
namespace history {
class HistoryBackend;
@@ -25,22 +31,40 @@ class HistoryBackend;
namespace browser_sync {
+class AssociatorInterface;
+class ChangeProcessor;
class ControlTask;
// A class that manages the startup and shutdown of typed_url sync.
-class TypedUrlDataTypeController : public NonFrontendDataTypeController,
+class TypedUrlDataTypeController : public DataTypeController,
public NotificationObserver,
public CancelableRequestConsumerBase {
public:
TypedUrlDataTypeController(
ProfileSyncFactory* profile_sync_factory,
- Profile* profile);
+ Profile* profile,
+ ProfileSyncService* sync_service);
virtual ~TypedUrlDataTypeController();
- // NonFrontendDataTypeController implementation
+ // DataTypeController implementation
+ virtual void Start(StartCallback* start_callback);
+
+ virtual void Stop();
+
+ virtual bool enabled();
+
virtual syncable::ModelType type() const;
+
virtual browser_sync::ModelSafeGroup model_safe_group() const;
+ virtual std::string name() const;
+
+ virtual State state() const;
+
+ // UnrecoverableHandler implementation
+ virtual void OnUnrecoverableError(const tracked_objects::Location& from_here,
+ const std::string& message);
+
// NotificationObserver implementation.
virtual void Observe(NotificationType type,
const NotificationSource& source,
@@ -49,36 +73,51 @@ class TypedUrlDataTypeController : public NonFrontendDataTypeController,
// CancelableRequestConsumerBase implementation.
virtual void OnRequestAdded(CancelableRequestProvider* provider,
CancelableRequestProvider::Handle handle) {}
+
virtual void OnRequestRemoved(CancelableRequestProvider* provider,
CancelableRequestProvider::Handle handle) {}
+
virtual void WillExecute(CancelableRequestProvider* provider,
CancelableRequestProvider::Handle handle) {}
+
virtual void DidExecute(CancelableRequestProvider* provider,
CancelableRequestProvider::Handle handle) {}
- protected:
- // NonFrontendDataTypeController interface.
- virtual bool StartModels();
- virtual bool StartAssociationAsync();
- virtual void CreateSyncComponents();
- virtual void StopModels();
- virtual bool StopAssociationAsync();
- virtual void RecordUnrecoverableError(
- const tracked_objects::Location& from_here,
- const std::string& message);
- virtual void RecordAssociationTime(base::TimeDelta time);
- virtual void RecordStartFailure(StartResult result);
-
private:
friend class ControlTask;
-
- // Helper method to launch Associate() and Destroy() on the history thread.
- void RunOnHistoryThread(bool start, history::HistoryBackend* backend);
-
- history::HistoryBackend* backend_;
+ void StartImpl(history::HistoryBackend* backend);
+ void StartDone(StartResult result, State state);
+ void StartDoneImpl(StartResult result, State state);
+ void StopImpl();
+ void StartFailed(StartResult result);
+ void OnUnrecoverableErrorImpl(const tracked_objects::Location& from_here,
+ const std::string& message);
+
+ void set_state(State state) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ state_ = state;
+ }
+
+ ProfileSyncFactory* profile_sync_factory_;
+ Profile* profile_;
+ ProfileSyncService* sync_service_;
+ State state_;
+
+ scoped_ptr<AssociatorInterface> model_associator_;
+ scoped_ptr<ChangeProcessor> change_processor_;
+ scoped_ptr<StartCallback> start_callback_;
scoped_refptr<HistoryService> history_service_;
+
NotificationRegistrar notification_registrar_;
+ base::Lock abort_association_lock_;
+ bool abort_association_;
+ base::WaitableEvent abort_association_complete_;
+
+ // Barrier to ensure that the datatype has been stopped on the DB thread
+ // from the UI thread.
+ base::WaitableEvent datatype_stopped_;
+
DISALLOW_COPY_AND_ASSIGN(TypedUrlDataTypeController);
};
diff --git a/chrome/browser/sync/profile_sync_factory.h b/chrome/browser/sync/profile_sync_factory.h
index 8befe35..776b61d 100644
--- a/chrome/browser/sync/profile_sync_factory.h
+++ b/chrome/browser/sync/profile_sync_factory.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
@@ -47,15 +47,12 @@ class ProfileSyncFactory {
virtual ~ProfileSyncFactory() {}
- // Instantiates a new ProfileSyncService. The return pointer is owned by the
- // caller.
+ // Instantiates and initializes a new ProfileSyncService. Enabled
+ // data types are registered with the service. The return pointer
+ // is owned by the caller.
virtual ProfileSyncService* CreateProfileSyncService(
const std::string& cros_user) = 0;
- // Creates and registers enabled datatypes with the provided
- // ProfileSyncService.
- virtual void RegisterDataTypes(ProfileSyncService* pss) = 0;
-
// Instantiates a new DataTypeManager with a SyncBackendHost and a
// list of data type controllers. The return pointer is owned by
// the caller.
diff --git a/chrome/browser/sync/profile_sync_factory_impl.cc b/chrome/browser/sync/profile_sync_factory_impl.cc
index 19f4938..9102e88 100644
--- a/chrome/browser/sync/profile_sync_factory_impl.cc
+++ b/chrome/browser/sync/profile_sync_factory_impl.cc
@@ -86,10 +86,7 @@ ProfileSyncService* ProfileSyncFactoryImpl::CreateProfileSyncService(
ProfileSyncService* pss = new ProfileSyncService(
this, profile_, cros_user);
- return pss;
-}
-void ProfileSyncFactoryImpl::RegisterDataTypes(ProfileSyncService* pss) {
// App sync is enabled by default. Register unless explicitly
// disabled.
if (!command_line_->HasSwitch(switches::kDisableSyncApps)) {
@@ -101,7 +98,7 @@ void ProfileSyncFactoryImpl::RegisterDataTypes(ProfileSyncService* pss) {
// disabled.
if (!command_line_->HasSwitch(switches::kDisableSyncAutofill)) {
pss->RegisterDataTypeController(
- new AutofillDataTypeController(this, profile_));
+ new AutofillDataTypeController(this, profile_, pss));
}
// Bookmark sync is enabled by default. Register unless explicitly
@@ -122,7 +119,7 @@ void ProfileSyncFactoryImpl::RegisterDataTypes(ProfileSyncService* pss) {
// disabled.
if (!command_line_->HasSwitch(switches::kDisableSyncPasswords)) {
pss->RegisterDataTypeController(
- new PasswordDataTypeController(this, profile_));
+ new PasswordDataTypeController(this, profile_, pss));
}
// Preference sync is enabled by default. Register unless explicitly
@@ -142,7 +139,7 @@ void ProfileSyncFactoryImpl::RegisterDataTypes(ProfileSyncService* pss) {
// explicitly enabled.
if (command_line_->HasSwitch(switches::kEnableSyncTypedUrls)) {
pss->RegisterDataTypeController(
- new TypedUrlDataTypeController(this, profile_));
+ new TypedUrlDataTypeController(this, profile_, pss));
}
// Session sync is disabled by default. Register only if explicitly
@@ -153,9 +150,10 @@ void ProfileSyncFactoryImpl::RegisterDataTypes(ProfileSyncService* pss) {
}
if (!command_line_->HasSwitch(switches::kDisableSyncAutofillProfile)) {
- pss->RegisterDataTypeController(
- new AutofillProfileDataTypeController(this, profile_));
+ pss->RegisterDataTypeController(new AutofillProfileDataTypeController(
+ this, profile_, pss));
}
+ return pss;
}
DataTypeManager* ProfileSyncFactoryImpl::CreateDataTypeManager(
diff --git a/chrome/browser/sync/profile_sync_factory_impl.h b/chrome/browser/sync/profile_sync_factory_impl.h
index 2015a40..eb93f1c 100644
--- a/chrome/browser/sync/profile_sync_factory_impl.h
+++ b/chrome/browser/sync/profile_sync_factory_impl.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
@@ -23,8 +23,6 @@ class ProfileSyncFactoryImpl : public ProfileSyncFactory {
virtual ProfileSyncService* CreateProfileSyncService(
const std::string& cros_user);
- virtual void RegisterDataTypes(ProfileSyncService* pss);
-
virtual browser_sync::DataTypeManager* CreateDataTypeManager(
browser_sync::SyncBackendHost* backend,
const browser_sync::DataTypeController::TypeMap& controllers);
diff --git a/chrome/browser/sync/profile_sync_factory_impl_unittest.cc b/chrome/browser/sync/profile_sync_factory_impl_unittest.cc
index 56643ac..907b2f6 100644
--- a/chrome/browser/sync/profile_sync_factory_impl_unittest.cc
+++ b/chrome/browser/sync/profile_sync_factory_impl_unittest.cc
@@ -76,7 +76,6 @@ class ProfileSyncFactoryImplTest : public testing::Test {
command_line_->AppendSwitch(cmd_switch);
scoped_ptr<ProfileSyncService> pss(
profile_sync_service_factory_->CreateProfileSyncService(""));
- profile_sync_service_factory_->RegisterDataTypes(pss.get());
DataTypeController::StateMap controller_states;
pss->GetDataTypeControllerStates(&controller_states);
EXPECT_EQ(DefaultDatatypesCount() - 1, controller_states.size());
@@ -93,7 +92,6 @@ class ProfileSyncFactoryImplTest : public testing::Test {
TEST_F(ProfileSyncFactoryImplTest, CreatePSSDefault) {
scoped_ptr<ProfileSyncService> pss(
profile_sync_service_factory_->CreateProfileSyncService(""));
- profile_sync_service_factory_->RegisterDataTypes(pss.get());
DataTypeController::StateMap controller_states;
pss->GetDataTypeControllerStates(&controller_states);
EXPECT_EQ(DefaultDatatypesCount(), controller_states.size());
diff --git a/chrome/browser/sync/profile_sync_factory_mock.h b/chrome/browser/sync/profile_sync_factory_mock.h
index 3fa856c..2d8d8e2 100644
--- a/chrome/browser/sync/profile_sync_factory_mock.h
+++ b/chrome/browser/sync/profile_sync_factory_mock.h
@@ -26,7 +26,6 @@ class ProfileSyncFactoryMock : public ProfileSyncFactory {
MOCK_METHOD1(CreateProfileSyncService,
ProfileSyncService*(const std::string&));
- MOCK_METHOD1(RegisterDataTypes, void(ProfileSyncService*));
MOCK_METHOD2(CreateDataTypeManager,
browser_sync::DataTypeManager*(
browser_sync::SyncBackendHost*,
diff --git a/chrome/browser/sync/profile_sync_service_autofill_unittest.cc b/chrome/browser/sync/profile_sync_service_autofill_unittest.cc
index 763d6bb..a7b0e36 100644
--- a/chrome/browser/sync/profile_sync_service_autofill_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_autofill_unittest.cc
@@ -207,7 +207,8 @@ class AutofillEntryFactory : public AbstractAutofillFactory {
ProfileMock* profile,
ProfileSyncService* service) {
return new AutofillDataTypeController(factory,
- profile);
+ profile,
+ service);
}
void SetExpectation(ProfileSyncFactoryMock* factory,
@@ -227,7 +228,8 @@ class AutofillProfileFactory : public AbstractAutofillFactory {
ProfileMock* profile,
ProfileSyncService* service) {
return new AutofillProfileDataTypeController(factory,
- profile);
+ profile,
+ service);
}
void SetExpectation(ProfileSyncFactoryMock* factory,
@@ -300,8 +302,6 @@ class ProfileSyncServiceAutofillTest : public AbstractProfileSyncServiceTest {
service_.reset(
new TestProfileSyncService(&factory_, &profile_, "test_user", false,
task));
- EXPECT_CALL(profile_, GetProfileSyncService()).WillRepeatedly(
- Return(service_.get()));
AutofillDataTypeController* data_type_controller =
factory->CreateDataTypeController(&factory_,
&profile_,
@@ -670,6 +670,7 @@ TEST_F(ProfileSyncServiceAutofillTest, HasNativeEntriesEmptySync) {
}
TEST_F(ProfileSyncServiceAutofillTest, HasProfileEmptySync) {
+
std::vector<AutofillProfile*> profiles;
std::vector<AutofillProfile> expected_profiles;
// Owned by GetAutofillProfiles caller.
diff --git a/chrome/browser/sync/profile_sync_service_password_unittest.cc b/chrome/browser/sync/profile_sync_service_password_unittest.cc
index 94f2169..22005ce 100644
--- a/chrome/browser/sync/profile_sync_service_password_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_password_unittest.cc
@@ -189,11 +189,10 @@ class ProfileSyncServicePasswordTest : public AbstractProfileSyncServiceTest {
&factory_, &profile_, "test_user", false, root_task, node_task));
service_->RegisterPreferences();
profile_.GetPrefs()->SetBoolean(prefs::kSyncPasswords, true);
- EXPECT_CALL(profile_, GetProfileSyncService()).WillRepeatedly(
- Return(service_.get()));
PasswordDataTypeController* data_type_controller =
new PasswordDataTypeController(&factory_,
- &profile_);
+ &profile_,
+ service_.get());
EXPECT_CALL(factory_, CreatePasswordSyncComponents(_, _, _)).
Times(AtLeast(1)). // Can be more if we hit NEEDS_CRYPTO.
diff --git a/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc b/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc
index 6184b6a..7125cce 100644
--- a/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc
+++ b/chrome/browser/sync/profile_sync_service_typed_url_unittest.cc
@@ -163,11 +163,10 @@ class ProfileSyncServiceTypedUrlTest : public AbstractProfileSyncServiceTest {
service_.reset(
new TestProfileSyncService(&factory_, &profile_, "test", false,
task));
- EXPECT_CALL(profile_, GetProfileSyncService()).WillRepeatedly(
- Return(service_.get()));
TypedUrlDataTypeController* data_type_controller =
new TypedUrlDataTypeController(&factory_,
- &profile_);
+ &profile_,
+ service_.get());
EXPECT_CALL(factory_, CreateTypedUrlSyncComponents(_, _, _)).
WillOnce(MakeTypedUrlSyncComponents(service_.get(),
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 54618b2..04057ac 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -1932,8 +1932,6 @@
'browser/sync/glue/http_bridge.cc',
'browser/sync/glue/http_bridge.h',
'browser/sync/glue/model_associator.h',
- 'browser/sync/glue/non_frontend_data_type_controller.cc',
- 'browser/sync/glue/non_frontend_data_type_controller.h',
'browser/sync/glue/password_change_processor.cc',
'browser/sync/glue/password_change_processor.h',
'browser/sync/glue/password_data_type_controller.cc',
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi
index 5851c3a..6646ccb 100644
--- a/chrome/chrome_tests.gypi
+++ b/chrome/chrome_tests.gypi
@@ -1551,9 +1551,6 @@
'browser/sync/glue/http_bridge_unittest.cc',
'browser/sync/glue/model_associator_mock.cc',
'browser/sync/glue/model_associator_mock.h',
- 'browser/sync/glue/non_frontend_data_type_controller_mock.cc',
- 'browser/sync/glue/non_frontend_data_type_controller_mock.h',
- 'browser/sync/glue/non_frontend_data_type_controller_unittest.cc',
'browser/sync/glue/preference_data_type_controller_unittest.cc',
'browser/sync/glue/preference_model_associator_unittest.cc',
'browser/sync/glue/session_model_associator_unittest.cc',