Index: chrome/browser/sync/glue/autofill_data_type_controller.cc |
diff --git a/chrome/browser/sync/glue/autofill_data_type_controller.cc b/chrome/browser/sync/glue/autofill_data_type_controller.cc |
index 63c9e267096c061097ae09f4359b50df2107fd06..2b5cfbb3b6ae49ed26dca62e50bc2bc4defff682 100644 |
--- a/chrome/browser/sync/glue/autofill_data_type_controller.cc |
+++ b/chrome/browser/sync/glue/autofill_data_type_controller.cc |
@@ -1,264 +1,278 @@ |
-// 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. |
- |
-#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/browser_thread.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_service.h" |
-#include "chrome/browser/sync/profile_sync_factory.h" |
-#include "chrome/browser/webdata/web_data_service.h" |
-#include "chrome/common/notification_service.h" |
- |
-namespace browser_sync { |
- |
-AutofillDataTypeController::AutofillDataTypeController( |
- ProfileSyncFactory* profile_sync_factory, |
- 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)); |
-} |
- |
-void AutofillDataTypeController::Start(StartCallback* start_callback) { |
- VLOG(1) << "Starting autofill data controller."; |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- DCHECK(start_callback); |
- if (state() != NOT_RUNNING) { |
- start_callback->Run(BUSY); |
- 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(); |
- if (!personal_data_->IsDataLoaded()) { |
- set_state(MODEL_STARTING); |
- personal_data_->SetObserver(this); |
- return; |
- } |
- |
- ContinueStartAfterPersonalDataLoaded(); |
-} |
- |
-void AutofillDataTypeController::ContinueStartAfterPersonalDataLoaded() { |
- web_data_service_ = profile_->GetWebDataService(Profile::IMPLICIT_ACCESS); |
- if (web_data_service_.get() && web_data_service_->IsDatabaseLoaded()) { |
- 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()); |
- } |
-} |
- |
-void AutofillDataTypeController::OnPersonalDataLoaded() { |
- DCHECK_EQ(state_, MODEL_STARTING); |
- personal_data_->RemoveObserver(this); |
- ContinueStartAfterPersonalDataLoaded(); |
-} |
- |
-void AutofillDataTypeController::Observe(NotificationType type, |
- const NotificationSource& source, |
- const NotificationDetails& details) { |
- VLOG(1) << "Web database loaded observed."; |
- notification_registrar_.RemoveAll(); |
- set_state(ASSOCIATING); |
- BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, |
- NewRunnableMethod( |
- this, |
- &AutofillDataTypeController::StartImpl)); |
-} |
- |
-void AutofillDataTypeController::Stop() { |
- VLOG(1) << "Stopping autofill data type controller."; |
- 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) { |
- { |
- 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 personal |
- // data manager or web data service to load, abort the start. |
- if (state_ == MODEL_STARTING) |
- StartDoneImpl(ABORTED, STOPPING); |
- |
- // Note that we are doing most of the stop work here (deactivate and |
- // disassociate) on the UI thread even though the associate & |
- // activate were done on the DB thread. This is because Stop() must |
- // be synchronous. |
- notification_registrar_.RemoveAll(); |
- personal_data_->RemoveObserver(this); |
- if (change_processor_ != NULL && change_processor_->IsRunning()) |
- sync_service_->DeactivateDataType(this, change_processor_.get()); |
- |
- if (model_associator_ != NULL) |
- model_associator_->DisassociateModels(); |
- |
- 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(); |
- } |
-} |
- |
-void AutofillDataTypeController::StartImpl() { |
- VLOG(1) << "Autofill data type controller StartImpl called."; |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
- // No additional services need to be started before we can proceed |
- // with model association. |
- { |
- AutoLock lock(abort_association_lock_); |
- if (abort_association_) { |
- abort_association_complete_.Signal(); |
- return; |
- } |
- ProfileSyncFactory::SyncComponents sync_components = |
- profile_sync_factory_->CreateAutofillSyncComponents( |
- sync_service_, |
- web_data_service_->GetDatabase(), |
- profile_->GetPersonalDataManager(), |
- this); |
- model_associator_.reset(sync_components.model_associator); |
- change_processor_.reset(sync_components.change_processor); |
- } |
- |
- 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::StartDone( |
- DataTypeController::StartResult result, |
- DataTypeController::State new_state) { |
- VLOG(1) << "Autofill data type controller StartDone called."; |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
- |
- abort_association_complete_.Signal(); |
- AutoLock lock(abort_association_lock_); |
- if (!abort_association_) { |
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
- NewRunnableMethod( |
- this, |
- &AutofillDataTypeController::StartDoneImpl, |
- result, |
- new_state)); |
- } |
-} |
- |
-void AutofillDataTypeController::StartDoneImpl( |
- DataTypeController::StartResult result, |
- DataTypeController::State new_state) { |
- VLOG(1) << "Autofill data type controller StartDoneImpl called."; |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
- |
- set_state(new_state); |
- start_callback_->Run(result); |
- start_callback_.reset(); |
- |
- if (result == UNRECOVERABLE_ERROR || result == ASSOCIATION_FAILED) { |
- UMA_HISTOGRAM_ENUMERATION("Sync.AutofillStartFailures", |
- result, |
- MAX_START_RESULT); |
- } |
-} |
- |
-void AutofillDataTypeController::StopImpl() { |
- VLOG(1) << "Autofill data type controller StopImpl called."; |
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
- |
- change_processor_.reset(); |
- model_associator_.reset(); |
- |
- datatype_stopped_.Signal(); |
-} |
- |
-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 |
+// 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. |
+ |
+#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/browser_thread.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 "chrome/common/notification_service.h" |
+ |
+namespace browser_sync { |
+ |
+AutofillDataTypeController::AutofillDataTypeController( |
+ ProfileSyncFactory* profile_sync_factory, |
+ 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)); |
+} |
+ |
+void AutofillDataTypeController::Start(StartCallback* start_callback) { |
+ VLOG(1) << "Starting autofill data controller."; |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ DCHECK(start_callback); |
+ if (state() != NOT_RUNNING) { |
+ start_callback->Run(BUSY); |
+ 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(); |
+ if (!personal_data_->IsDataLoaded()) { |
+ set_state(MODEL_STARTING); |
+ personal_data_->SetObserver(this); |
+ return; |
+ } |
+ |
+ ContinueStartAfterPersonalDataLoaded(); |
+} |
+ |
+void AutofillDataTypeController::ContinueStartAfterPersonalDataLoaded() { |
+ web_data_service_ = profile_->GetWebDataService(Profile::IMPLICIT_ACCESS); |
+ if (web_data_service_.get() && web_data_service_->IsDatabaseLoaded()) { |
+ 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()); |
+ } |
+} |
+ |
+void AutofillDataTypeController::OnPersonalDataLoaded() { |
+ DCHECK_EQ(state_, MODEL_STARTING); |
+ personal_data_->RemoveObserver(this); |
+ ContinueStartAfterPersonalDataLoaded(); |
+} |
+ |
+void AutofillDataTypeController::Observe(NotificationType type, |
+ const NotificationSource& source, |
+ const NotificationDetails& details) { |
+ VLOG(1) << "Web database loaded observed."; |
+ notification_registrar_.RemoveAll(); |
+ set_state(ASSOCIATING); |
+ BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, |
+ NewRunnableMethod( |
+ this, |
+ &AutofillDataTypeController::StartImpl)); |
+} |
+ |
+void AutofillDataTypeController::Stop() { |
+ VLOG(1) << "Stopping autofill data type controller."; |
+ 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) { |
+ { |
+ 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 personal |
+ // data manager or web data service to load, abort the start. |
+ if (state_ == MODEL_STARTING) |
+ StartDoneImpl(ABORTED, STOPPING); |
+ |
+ // Note that we are doing most of the stop work here (deactivate and |
+ // disassociate) on the UI thread even though the associate & |
+ // activate were done on the DB thread. This is because Stop() must |
+ // be synchronous. |
+ notification_registrar_.RemoveAll(); |
+ personal_data_->RemoveObserver(this); |
+ if (change_processor_ != NULL && change_processor_->IsRunning()) |
+ sync_service_->DeactivateDataType(this, change_processor_.get()); |
+ |
+ if (model_associator_ != NULL) |
+ model_associator_->DisassociateModels(); |
+ |
+ 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(); |
+ } |
+} |
+ |
+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)); |
+ // No additional services need to be started before we can proceed |
+ // with model association. |
+ { |
+ 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); |
+ } |
+ |
+ 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::StartDone( |
+ DataTypeController::StartResult result, |
+ DataTypeController::State new_state) { |
+ VLOG(1) << "Autofill data type controller StartDone called."; |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
+ |
+ abort_association_complete_.Signal(); |
+ AutoLock lock(abort_association_lock_); |
+ if (!abort_association_) { |
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
+ NewRunnableMethod( |
+ this, |
+ &AutofillDataTypeController::StartDoneImpl, |
+ result, |
+ new_state)); |
+ } |
+} |
+ |
+void AutofillDataTypeController::StartDoneImpl( |
+ DataTypeController::StartResult result, |
+ DataTypeController::State new_state) { |
+ VLOG(1) << "Autofill data type controller StartDoneImpl called."; |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ |
+ set_state(new_state); |
+ start_callback_->Run(result); |
+ start_callback_.reset(); |
+ |
+ if (result == UNRECOVERABLE_ERROR || result == ASSOCIATION_FAILED) { |
+ UMA_HISTOGRAM_ENUMERATION("Sync.AutofillStartFailures", |
+ result, |
+ MAX_START_RESULT); |
+ } |
+} |
+ |
+void AutofillDataTypeController::StopImpl() { |
+ VLOG(1) << "Autofill data type controller StopImpl called."; |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB)); |
+ |
+ change_processor_.reset(); |
+ model_associator_.reset(); |
+ |
+ datatype_stopped_.Signal(); |
+} |
+ |
+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 |
+ |
tim (not reviewing)
2010/12/13 19:24:33
extra newline
lipalani
2010/12/14 21:05:57
Done.
|