summaryrefslogtreecommitdiffstats
path: root/chrome/browser/sync
diff options
context:
space:
mode:
authorlipalani@chromium.org <lipalani@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-12-16 07:15:53 +0000
committerlipalani@chromium.org <lipalani@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-12-16 07:15:53 +0000
commita0bc3146a8657b2d47d4d883ac16946b0489a8d0 (patch)
treeb4c926fbffd5f12130ec82e7e2d2e50760e286d0 /chrome/browser/sync
parent351e326d2e335db14f44edfc7bc69aa37133dd92 (diff)
downloadchromium_src-a0bc3146a8657b2d47d4d883ac16946b0489a8d0.zip
chromium_src-a0bc3146a8657b2d47d4d883ac16946b0489a8d0.tar.gz
chromium_src-a0bc3146a8657b2d47d4d883ac16946b0489a8d0.tar.bz2
Rest of the autofill work.
Includes 1. change processor. 2. Migrating code. 3. new datatype registration/enabling/disabling from the UI. (It is keyed off of autofill datatype). Review URL: http://codereview.chromium.org/5159001 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@69382 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/sync')
-rw-r--r--chrome/browser/sync/engine/syncapi.cc80
-rw-r--r--chrome/browser/sync/engine/syncapi.h17
-rw-r--r--chrome/browser/sync/glue/autofill_change_processor.cc53
-rw-r--r--chrome/browser/sync/glue/autofill_change_processor.h5
-rw-r--r--chrome/browser/sync/glue/autofill_change_processor2.cc3
-rw-r--r--chrome/browser/sync/glue/autofill_data_type_controller.cc17
-rw-r--r--chrome/browser/sync/glue/autofill_data_type_controller.h10
-rw-r--r--chrome/browser/sync/glue/autofill_model_associator.cc156
-rw-r--r--chrome/browser/sync/glue/autofill_model_associator.h28
-rw-r--r--chrome/browser/sync/glue/autofill_profile_change_processor.cc338
-rw-r--r--chrome/browser/sync/glue/autofill_profile_change_processor.h120
-rw-r--r--chrome/browser/sync/glue/autofill_profile_data_type_controller.cc33
-rw-r--r--chrome/browser/sync/glue/autofill_profile_data_type_controller.h39
-rw-r--r--chrome/browser/sync/glue/autofill_profile_model_associator.cc140
-rw-r--r--chrome/browser/sync/glue/autofill_profile_model_associator.h15
-rw-r--r--chrome/browser/sync/glue/bookmark_change_processor.cc3
-rw-r--r--chrome/browser/sync/glue/bookmark_model_associator.cc15
-rw-r--r--chrome/browser/sync/glue/bookmark_model_associator.h2
-rw-r--r--chrome/browser/sync/glue/data_type_manager_impl.cc1
-rw-r--r--chrome/browser/sync/glue/do_optimistic_refresh_task.cc23
-rw-r--r--chrome/browser/sync/glue/do_optimistic_refresh_task.h26
-rw-r--r--chrome/browser/sync/glue/sync_backend_host.cc64
-rw-r--r--chrome/browser/sync/glue/sync_backend_host.h15
-rw-r--r--chrome/browser/sync/profile_sync_factory.h9
-rw-r--r--chrome/browser/sync/profile_sync_factory_impl.cc32
-rw-r--r--chrome/browser/sync/profile_sync_factory_impl.h6
-rw-r--r--chrome/browser/sync/profile_sync_factory_mock.h6
-rw-r--r--chrome/browser/sync/profile_sync_service.cc35
-rw-r--r--chrome/browser/sync/sync_ui_util.cc35
-rw-r--r--chrome/browser/sync/syncable/autofill_migration.h49
-rw-r--r--chrome/browser/sync/syncable/directory_backing_store.cc144
-rw-r--r--chrome/browser/sync/syncable/directory_backing_store.h9
-rw-r--r--chrome/browser/sync/syncable/directory_backing_store_unittest.cc165
-rw-r--r--chrome/browser/sync/syncable/model_type.cc10
-rw-r--r--chrome/browser/sync/syncable/model_type.h5
-rw-r--r--chrome/browser/sync/syncable/syncable.cc78
-rw-r--r--chrome/browser/sync/syncable/syncable.h16
37 files changed, 1631 insertions, 171 deletions
diff --git a/chrome/browser/sync/engine/syncapi.cc b/chrome/browser/sync/engine/syncapi.cc
index 7965f65..112878d 100644
--- a/chrome/browser/sync/engine/syncapi.cc
+++ b/chrome/browser/sync/engine/syncapi.cc
@@ -43,6 +43,7 @@
#include "chrome/browser/sync/protocol/theme_specifics.pb.h"
#include "chrome/browser/sync/protocol/typed_url_specifics.pb.h"
#include "chrome/browser/sync/sessions/sync_session_context.h"
+#include "chrome/browser/sync/syncable/autofill_migration.h"
#include "chrome/browser/sync/syncable/directory_manager.h"
#include "chrome/browser/sync/syncable/syncable.h"
#include "chrome/browser/sync/util/crypto_helpers.h"
@@ -375,6 +376,20 @@ void WriteNode::PutAutofillSpecificsAndMarkForSyncing(
PutSpecificsAndMarkForSyncing(entity_specifics);
}
+void WriteNode::SetAutofillProfileSpecifics(
+ const sync_pb::AutofillProfileSpecifics& new_value) {
+ DCHECK_EQ(GetModelType(), syncable::AUTOFILL_PROFILE);
+ PutAutofillProfileSpecificsAndMarkForSyncing(new_value);
+}
+
+void WriteNode::PutAutofillProfileSpecificsAndMarkForSyncing(
+ const sync_pb::AutofillProfileSpecifics& new_value) {
+ sync_pb::EntitySpecifics entity_specifics;
+ entity_specifics.MutableExtension(sync_pb::autofill_profile)->CopyFrom(
+ new_value);
+ PutSpecificsAndMarkForSyncing(entity_specifics);
+}
+
void WriteNode::SetBookmarkSpecifics(
const sync_pb::BookmarkSpecifics& new_value) {
DCHECK(GetModelType() == syncable::BOOKMARKS);
@@ -1094,6 +1109,50 @@ class SyncManager::SyncInternal
return true;
}
+ syncable::AutofillMigrationState GetAutofillMigrationState() {
+ syncable::ScopedDirLookup lookup(dir_manager(), username_for_share());
+ if (!lookup.good()) {
+ DCHECK(false) << "ScopedDirLookup failed when checking initial sync";
+ return syncable::NOT_MIGRATED;
+ }
+
+ return lookup->get_autofill_migration_state();
+ }
+
+ void SetAutofillMigrationState(syncable::AutofillMigrationState state) {
+ syncable::ScopedDirLookup lookup(dir_manager(), username_for_share());
+ if (!lookup.good()) {
+ DCHECK(false) << "ScopedDirLookup failed when checking initial sync";
+ return;
+ }
+
+ return lookup->set_autofill_migration_state(state);
+ }
+
+ void SetAutofillMigrationDebugInfo(
+ syncable::AutofillMigrationDebugInfo::PropertyToSet property_to_set,
+ const syncable::AutofillMigrationDebugInfo& info) {
+ syncable::ScopedDirLookup lookup(dir_manager(), username_for_share());
+ if (!lookup.good()) {
+ DCHECK(false) << "ScopedDirLookup failed when checking initial sync";
+ return;
+ }
+
+ return lookup->set_autofill_migration_state_debug_info(
+ property_to_set, info);
+ }
+
+ syncable::AutofillMigrationDebugInfo
+ GetAutofillMigrationDebugInfo() {
+ syncable::ScopedDirLookup lookup(dir_manager(), username_for_share());
+ if (!lookup.good()) {
+ DCHECK(false) << "ScopedDirLookup failed when checking initial sync";
+ syncable::AutofillMigrationDebugInfo null_value = {0};
+ return null_value;
+ }
+ return lookup->get_autofill_migration_debug_info();
+ }
+
// SyncEngineEventListener implementation.
virtual void OnSyncEngineEvent(const SyncEngineEvent& event);
private:
@@ -1315,6 +1374,27 @@ void SyncManager::StartSyncing() {
data_->StartSyncing();
}
+syncable::AutofillMigrationState
+ SyncManager::GetAutofillMigrationState() {
+ return data_->GetAutofillMigrationState();
+}
+
+void SyncManager::SetAutofillMigrationState(
+ syncable::AutofillMigrationState state) {
+ return data_->SetAutofillMigrationState(state);
+}
+
+syncable::AutofillMigrationDebugInfo
+ SyncManager::GetAutofillMigrationDebugInfo() {
+ return data_->GetAutofillMigrationDebugInfo();
+}
+
+void SyncManager::SetAutofillMigrationDebugInfo(
+ syncable::AutofillMigrationDebugInfo::PropertyToSet property_to_set,
+ const syncable::AutofillMigrationDebugInfo& info) {
+ return data_->SetAutofillMigrationDebugInfo(property_to_set, info);
+}
+
void SyncManager::SetPassphrase(const std::string& passphrase,
bool is_explicit) {
data_->SetPassphrase(passphrase, is_explicit);
diff --git a/chrome/browser/sync/engine/syncapi.h b/chrome/browser/sync/engine/syncapi.h
index 2019f41..e2503cb 100644
--- a/chrome/browser/sync/engine/syncapi.h
+++ b/chrome/browser/sync/engine/syncapi.h
@@ -47,6 +47,7 @@
#include "base/scoped_ptr.h"
#include "build/build_config.h"
#include "chrome/browser/sync/protocol/password_specifics.pb.h"
+#include "chrome/browser/sync/syncable/autofill_migration.h"
#include "chrome/browser/sync/syncable/model_type.h"
#include "chrome/browser/sync/util/cryptographer.h"
#include "chrome/common/net/gaia/google_service_auth_error.h"
@@ -347,6 +348,9 @@ class WriteNode : public BaseNode {
// Should only be called if GetModelType() == AUTOFILL.
void SetAutofillSpecifics(const sync_pb::AutofillSpecifics& specifics);
+ void SetAutofillProfileSpecifics(
+ const sync_pb::AutofillProfileSpecifics& specifics);
+
// Set the nigori specifics.
// Should only be called if GetModelType() == NIGORI.
void SetNigoriSpecifics(const sync_pb::NigoriSpecifics& specifics);
@@ -398,6 +402,8 @@ class WriteNode : public BaseNode {
const sync_pb::AppSpecifics& new_value);
void PutAutofillSpecificsAndMarkForSyncing(
const sync_pb::AutofillSpecifics& new_value);
+ void PutAutofillProfileSpecificsAndMarkForSyncing(
+ const sync_pb::AutofillProfileSpecifics& new_value);
void PutBookmarkSpecificsAndMarkForSyncing(
const sync_pb::BookmarkSpecifics& new_value);
void PutNigoriSpecificsAndMarkForSyncing(
@@ -817,6 +823,17 @@ class SyncManager {
// called.
bool InitialSyncEndedForAllEnabledTypes();
+ syncable::AutofillMigrationState GetAutofillMigrationState();
+
+ void SetAutofillMigrationState(
+ syncable::AutofillMigrationState state);
+
+ syncable::AutofillMigrationDebugInfo GetAutofillMigrationDebugInfo();
+
+ void SetAutofillMigrationDebugInfo(
+ syncable::AutofillMigrationDebugInfo::PropertyToSet property_to_set,
+ const syncable::AutofillMigrationDebugInfo& info);
+
// Migrate tokens from user settings DB to the token service.
void MigrateTokens();
diff --git a/chrome/browser/sync/glue/autofill_change_processor.cc b/chrome/browser/sync/glue/autofill_change_processor.cc
index 155e6e7..6914308 100644
--- a/chrome/browser/sync/glue/autofill_change_processor.cc
+++ b/chrome/browser/sync/glue/autofill_change_processor.cc
@@ -9,16 +9,20 @@
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
-#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/autofill/personal_data_manager.h"
+#include "chrome/browser/prefs/pref_service.h"
+#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/sync/glue/autofill_change_processor2.h"
#include "chrome/browser/sync/glue/autofill_model_associator.h"
+#include "chrome/browser/sync/glue/autofill_profile_model_associator.h"
+#include "chrome/browser/sync/glue/do_optimistic_refresh_task.h"
#include "chrome/browser/sync/profile_sync_service.h"
#include "chrome/browser/webdata/autofill_change.h"
#include "chrome/browser/webdata/web_data_service.h"
#include "chrome/browser/webdata/web_database.h"
#include "chrome/common/guid.h"
#include "chrome/common/notification_service.h"
+#include "chrome/common/pref_names.h"
namespace browser_sync {
@@ -83,7 +87,7 @@ void AutofillChangeProcessor::Observe(NotificationType type,
void AutofillChangeProcessor::PostOptimisticRefreshTask() {
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- new AutofillModelAssociator::DoOptimisticRefreshTask(
+ new DoOptimisticRefreshForAutofill(
personal_data_));
}
@@ -195,6 +199,8 @@ void AutofillChangeProcessor::ApplyChangesFromSyncModel(
return;
StopObserving();
+ bool autofill_profile_not_migrated = HasNotMigratedYet(trans);
+
sync_api::ReadNode autofill_root(trans);
if (!autofill_root.InitByTagLookup(kAutofillTag)) {
error_handler()->OnUnrecoverableError(FROM_HERE,
@@ -210,7 +216,7 @@ void AutofillChangeProcessor::ApplyChangesFromSyncModel(
const sync_pb::AutofillSpecifics& autofill =
changes[i].specifics.GetExtension(sync_pb::autofill);
if (autofill.has_value() ||
- (HasNotMigratedYet() && autofill.has_profile())) {
+ (autofill_profile_not_migrated && autofill.has_profile())) {
autofill_changes_.push_back(AutofillChangeRecord(changes[i].action,
changes[i].id,
autofill));
@@ -236,7 +242,7 @@ void AutofillChangeProcessor::ApplyChangesFromSyncModel(
sync_node.GetAutofillSpecifics());
int64 sync_id = sync_node.GetId();
if (autofill.has_value() ||
- (HasNotMigratedYet() && autofill.has_profile())) {
+ (autofill_profile_not_migrated && autofill.has_profile())) {
autofill_changes_.push_back(AutofillChangeRecord(changes[i].action,
sync_id, autofill));
} else {
@@ -261,7 +267,6 @@ void AutofillChangeProcessor::CommitChangesFromSyncModel() {
if (autofill_changes_[i].autofill_.has_value()) {
ApplySyncAutofillEntryDelete(autofill_changes_[i].autofill_);
} else if (autofill_changes_[i].autofill_.has_profile()) {
- DCHECK(HasNotMigratedYet());
ApplySyncAutofillProfileDelete(autofill_changes_[i].id_);
} else {
NOTREACHED() << "Autofill's CommitChanges received change with no"
@@ -276,7 +281,6 @@ void AutofillChangeProcessor::CommitChangesFromSyncModel() {
autofill_changes_[i].autofill_, &new_entries,
autofill_changes_[i].id_);
} else if (autofill_changes_[i].autofill_.has_profile()) {
- DCHECK(HasNotMigratedYet());
ApplySyncAutofillProfileChange(autofill_changes_[i].action_,
autofill_changes_[i].autofill_.profile(),
autofill_changes_[i].id_);
@@ -433,40 +437,9 @@ void AutofillChangeProcessor::WriteAutofillEntry(
node->SetAutofillSpecifics(autofill);
}
-// static
-void AutofillChangeProcessor::WriteAutofillProfile(
- const AutoFillProfile& profile, sync_api::WriteNode* node) {
- sync_pb::AutofillSpecifics autofill;
- sync_pb::AutofillProfileSpecifics* s(autofill.mutable_profile());
- s->set_name_first(UTF16ToUTF8(
- profile.GetFieldText(AutoFillType(NAME_FIRST))));
- s->set_name_middle(UTF16ToUTF8(
- profile.GetFieldText(AutoFillType(NAME_MIDDLE))));
- s->set_name_last(UTF16ToUTF8(profile.GetFieldText(AutoFillType(NAME_LAST))));
- s->set_address_home_line1(
- UTF16ToUTF8(profile.GetFieldText(AutoFillType(ADDRESS_HOME_LINE1))));
- s->set_address_home_line2(
- UTF16ToUTF8(profile.GetFieldText(AutoFillType(ADDRESS_HOME_LINE2))));
- s->set_address_home_city(UTF16ToUTF8(profile.GetFieldText(
- AutoFillType(ADDRESS_HOME_CITY))));
- s->set_address_home_state(UTF16ToUTF8(profile.GetFieldText(
- AutoFillType(ADDRESS_HOME_STATE))));
- s->set_address_home_country(UTF16ToUTF8(profile.GetFieldText(
- AutoFillType(ADDRESS_HOME_COUNTRY))));
- s->set_address_home_zip(UTF16ToUTF8(profile.GetFieldText(
- AutoFillType(ADDRESS_HOME_ZIP))));
- s->set_email_address(UTF16ToUTF8(profile.GetFieldText(
- AutoFillType(EMAIL_ADDRESS))));
- s->set_company_name(UTF16ToUTF8(profile.GetFieldText(
- AutoFillType(COMPANY_NAME))));
- s->set_phone_fax_whole_number(UTF16ToUTF8(profile.GetFieldText(
- AutoFillType(PHONE_FAX_WHOLE_NUMBER))));
- s->set_phone_home_whole_number(UTF16ToUTF8(profile.GetFieldText(
- AutoFillType(PHONE_HOME_WHOLE_NUMBER))));
- node->SetAutofillSpecifics(autofill);
-}
-bool AutofillChangeProcessor::HasNotMigratedYet() {
- return true;
+bool AutofillChangeProcessor::HasNotMigratedYet(
+ const sync_api::BaseTransaction* trans) {
+ return model_associator_->HasNotMigratedYet(trans);
}
} // namespace browser_sync
diff --git a/chrome/browser/sync/glue/autofill_change_processor.h b/chrome/browser/sync/glue/autofill_change_processor.h
index e901c8e..ba132fa 100644
--- a/chrome/browser/sync/glue/autofill_change_processor.h
+++ b/chrome/browser/sync/glue/autofill_change_processor.h
@@ -63,9 +63,6 @@ class AutofillChangeProcessor : public ChangeProcessor,
// node.
static void WriteAutofillEntry(const AutofillEntry& entry,
sync_api::WriteNode* node);
- // As above, for autofill profiles.
- static void WriteAutofillProfile(const AutoFillProfile& profile,
- sync_api::WriteNode* node);
// TODO(georgey) : add the same processing for CC info (already in protocol
// buffers).
@@ -112,7 +109,7 @@ class AutofillChangeProcessor : public ChangeProcessor,
void PostOptimisticRefreshTask();
// Called to see if we need to upgrade to the new autofill2 profile.
- bool HasNotMigratedYet();
+ bool HasNotMigratedYet(const sync_api::BaseTransaction* trans);
// The two models should be associated according to this ModelAssociator.
AutofillModelAssociator* model_associator_;
diff --git a/chrome/browser/sync/glue/autofill_change_processor2.cc b/chrome/browser/sync/glue/autofill_change_processor2.cc
index eb70809..49b669c 100644
--- a/chrome/browser/sync/glue/autofill_change_processor2.cc
+++ b/chrome/browser/sync/glue/autofill_change_processor2.cc
@@ -9,8 +9,8 @@
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
-#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/autofill/personal_data_manager.h"
+#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/sync/glue/autofill_model_associator.h"
#include "chrome/browser/sync/glue/autofill_model_associator2.h"
#include "chrome/browser/sync/profile_sync_service.h"
@@ -581,4 +581,3 @@ void AutofillChangeProcessor2::WriteAutofillProfile(
}
} // namespace browser_sync
-
diff --git a/chrome/browser/sync/glue/autofill_data_type_controller.cc b/chrome/browser/sync/glue/autofill_data_type_controller.cc
index 6a827c9..8661e14 100644
--- a/chrome/browser/sync/glue/autofill_data_type_controller.cc
+++ b/chrome/browser/sync/glue/autofill_data_type_controller.cc
@@ -12,8 +12,8 @@
#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/sync/profile_sync_service.h"
#include "chrome/browser/webdata/web_data_service.h"
#include "chrome/common/notification_service.h"
@@ -170,6 +170,19 @@ DataTypeController::State AutofillDataTypeController::state() {
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));
@@ -182,7 +195,7 @@ void AutofillDataTypeController::StartImpl() {
return;
}
ProfileSyncFactory::SyncComponents sync_components =
- profile_sync_factory_->CreateAutofillSyncComponents(
+ CreateSyncComponents(
sync_service_,
web_data_service_->GetDatabase(),
profile_->GetPersonalDataManager(),
diff --git a/chrome/browser/sync/glue/autofill_data_type_controller.h b/chrome/browser/sync/glue/autofill_data_type_controller.h
index c66dcfd..d73edf2 100644
--- a/chrome/browser/sync/glue/autofill_data_type_controller.h
+++ b/chrome/browser/sync/glue/autofill_data_type_controller.h
@@ -12,6 +12,7 @@
#include "base/scoped_ptr.h"
#include "base/waitable_event.h"
#include "chrome/browser/autofill/personal_data_manager.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"
@@ -62,6 +63,14 @@ class AutofillDataTypeController : public DataTypeController,
// PersonalDataManager::Observer implementation:
virtual void OnPersonalDataLoaded();
+ protected:
+ 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);
@@ -80,7 +89,6 @@ class AutofillDataTypeController : public DataTypeController,
state_ = state;
}
- ProfileSyncFactory* profile_sync_factory_;
Profile* profile_;
ProfileSyncService* sync_service_;
State state_;
diff --git a/chrome/browser/sync/glue/autofill_model_associator.cc b/chrome/browser/sync/glue/autofill_model_associator.cc
index 06b28af..f1340df 100644
--- a/chrome/browser/sync/glue/autofill_model_associator.cc
+++ b/chrome/browser/sync/glue/autofill_model_associator.cc
@@ -12,13 +12,17 @@
#include "base/utf_string_conversions.h"
#include "chrome/browser/autofill/autofill_profile.h"
#include "chrome/browser/browser_thread.h"
+#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/sync/engine/syncapi.h"
#include "chrome/browser/sync/glue/autofill_change_processor.h"
+#include "chrome/browser/sync/glue/autofill_profile_model_associator.h"
+#include "chrome/browser/sync/glue/do_optimistic_refresh_task.h"
#include "chrome/browser/sync/profile_sync_service.h"
#include "chrome/browser/sync/protocol/autofill_specifics.pb.h"
#include "chrome/browser/webdata/web_database.h"
#include "chrome/common/guid.h"
+#include "chrome/common/pref_names.h"
#include "net/base/escape.h"
using base::TimeTicks;
@@ -37,16 +41,6 @@ struct AutofillModelAssociator::DataBundle {
~DataBundle() { STLDeleteElements(&new_profiles); }
};
-AutofillModelAssociator::DoOptimisticRefreshTask::DoOptimisticRefreshTask(
- PersonalDataManager* pdm) : pdm_(pdm) {}
-
-AutofillModelAssociator::DoOptimisticRefreshTask::~DoOptimisticRefreshTask() {}
-
-void AutofillModelAssociator::DoOptimisticRefreshTask::Run() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- pdm_->Refresh();
-}
-
AutofillModelAssociator::AutofillModelAssociator(
ProfileSyncService* sync_service,
WebDatabase* web_database,
@@ -55,7 +49,8 @@ AutofillModelAssociator::AutofillModelAssociator(
web_database_(web_database),
personal_data_(personal_data),
autofill_node_id_(sync_api::kInvalidId),
- abort_association_pending_(false) {
+ abort_association_pending_(false),
+ number_of_entries_created_(0) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
DCHECK(sync_service_);
DCHECK(web_database_);
@@ -114,6 +109,7 @@ bool AutofillModelAssociator::TraverseAndAssociateChromeAutofillEntries(
node.SetTitle(UTF8ToWide(tag));
AutofillChangeProcessor::WriteAutofillEntry(*ix, &node);
Associate(&tag, node.GetId());
+ number_of_entries_created_++;
}
current_entries->insert(ix->key());
@@ -121,21 +117,6 @@ bool AutofillModelAssociator::TraverseAndAssociateChromeAutofillEntries(
return true;
}
-bool AutofillModelAssociator::MakeNewAutofillProfileSyncNode(
- sync_api::WriteTransaction* trans, const sync_api::BaseNode& autofill_root,
- const std::string& tag, const AutoFillProfile& profile, int64* sync_id) {
- sync_api::WriteNode node(trans);
- if (!node.InitUniqueByCreation(syncable::AUTOFILL, autofill_root, tag)) {
- LOG(ERROR) << "Failed to create autofill sync node.";
- return false;
- }
- node.SetTitle(UTF8ToWide(tag));
- AutofillChangeProcessor::WriteAutofillProfile(profile, &node);
- *sync_id = node.GetId();
- return true;
-}
-
-
bool AutofillModelAssociator::LoadAutofillData(
std::vector<AutofillEntry>* entries,
std::vector<AutoFillProfile*>* profiles) {
@@ -205,8 +186,18 @@ bool AutofillModelAssociator::AssociateModels() {
return false;
}
+ if (sync_service_->backend()->GetAutofillMigrationState() !=
+ syncable::MIGRATED) {
+ syncable::AutofillMigrationDebugInfo debug_info;
+ debug_info.autofill_entries_added_during_migration =
+ number_of_entries_created_;
+ sync_service_->backend()->SetAutofillMigrationDebugInfo(
+ syncable::AutofillMigrationDebugInfo::ENTRIES_ADDED,
+ debug_info);
+ }
+
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- new DoOptimisticRefreshTask(personal_data_));
+ new DoOptimisticRefreshForAutofill(personal_data_));
return true;
}
@@ -244,6 +235,27 @@ bool AutofillModelAssociator::TraverseAndAssociateAllSyncNodes(
const std::vector<AutoFillProfile*>& all_profiles_from_db) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
+ bool autofill_profile_not_migrated = HasNotMigratedYet(write_trans);
+
+ if (MigrationLoggingEnabled() &&
+ autofill_profile_not_migrated) {
+ VLOG(1) << "[AUTOFILL MIGRATION]"
+ << "Printing profiles from web db";
+
+ for (std::vector<AutoFillProfile*>::const_iterator ix =
+ all_profiles_from_db.begin(); ix != all_profiles_from_db.end(); ++ix) {
+ AutoFillProfile* p = *ix;
+ VLOG(1) << "[AUTOFILL MIGRATION] "
+ << p->GetFieldText(AutoFillType(NAME_FIRST))
+ << p->GetFieldText(AutoFillType(NAME_LAST));
+ }
+ }
+
+ if (MigrationLoggingEnabled() && autofill_profile_not_migrated) {
+ VLOG(1) << "[AUTOFILL MIGRATION]"
+ << "Iterating over sync db";
+ }
+
int64 sync_child_id = autofill_root.GetFirstChildId();
while (sync_child_id != sync_api::kInvalidId) {
sync_api::ReadNode sync_child(write_trans);
@@ -256,13 +268,20 @@ bool AutofillModelAssociator::TraverseAndAssociateAllSyncNodes(
if (autofill.has_value()) {
AddNativeEntryIfNeeded(autofill, bundle, sync_child);
- } else if (autofill.has_profile() && HasNotMigratedYet()) {
+ } else if (autofill.has_profile()) {
// Ignore autofill profiles if we are not upgrading.
- AddNativeProfileIfNeeded(
- autofill.profile(),
- bundle,
- sync_child,
- all_profiles_from_db);
+ if (autofill_profile_not_migrated) {
+ if (MigrationLoggingEnabled()) {
+ VLOG(1) << "[AUTOFILL MIGRATION] Looking for "
+ << autofill.profile().name_first()
+ << autofill.profile().name_last();
+ }
+ AddNativeProfileIfNeeded(
+ autofill.profile(),
+ bundle,
+ sync_child,
+ all_profiles_from_db);
+ }
} else {
NOTREACHED() << "AutofillSpecifics has no autofill data!";
}
@@ -332,15 +351,23 @@ void AutofillModelAssociator::AddNativeProfileIfNeeded(
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
- scoped_ptr<AutoFillProfile> profile_in_web_db(FindCorrespondingNodeFromWebDB(
- profile, all_profiles_from_db));
+ AutoFillProfile* profile_in_web_db = FindCorrespondingNodeFromWebDB(
+ profile, all_profiles_from_db);
- if (profile_in_web_db.get() != NULL) {
+ if (profile_in_web_db != NULL) {
+ if (MigrationLoggingEnabled()) {
+ VLOG(1) << "[AUTOFILL MIGRATION]"
+ << "Node found in web db. So associating";
+ }
int64 sync_id = node.GetId();
std::string guid = profile_in_web_db->guid();
Associate(&guid, sync_id);
return;
} else { // Create a new node.
+ if (MigrationLoggingEnabled()) {
+ VLOG(1) << "[AUTOFILL MIGRATION]"
+ << "Node not found in web db so creating and associating";
+ }
std::string guid = guid::GenerateGUID();
Associate(&guid, node.GetId());
AutoFillProfile* p = new AutoFillProfile(guid);
@@ -509,8 +536,61 @@ bool AutofillModelAssociator::FillProfileWithServerData(
return diff;
}
-bool AutofillModelAssociator::HasNotMigratedYet() {
- return true;
+bool AutofillModelAssociator::HasNotMigratedYet(
+ const sync_api::BaseTransaction* trans) {
+
+ // Now read the current value from the directory.
+ syncable::AutofillMigrationState autofill_migration_state =
+ sync_service()->backend()->GetAutofillMigrationState();
+
+ DCHECK_NE(autofill_migration_state, syncable::NOT_DETERMINED);
+
+ if (autofill_migration_state== syncable::NOT_DETERMINED) {
+ VLOG(1) << "Autofill migration state is not determined inside "
+ << " model associator";
+ }
+
+ if (autofill_migration_state == syncable::NOT_MIGRATED) {
+ return true;
+ }
+
+ if (autofill_migration_state == syncable::INSUFFICIENT_INFO_TO_DETERMINE) {
+ if (MigrationLoggingEnabled()) {
+ VLOG(1) << "[AUTOFILL MIGRATION]"
+ << "current autofill migration state is insufficient info to"
+ << "determine.";
+ }
+ sync_api::ReadNode autofill_profile_root_node(trans);
+ if (!autofill_profile_root_node.InitByTagLookup(
+ browser_sync::kAutofillProfileTag) ||
+ autofill_profile_root_node.GetFirstChildId()==
+ static_cast<int64>(0)) {
+ sync_service()->backend()->SetAutofillMigrationState(
+ syncable::NOT_MIGRATED);
+
+ if (MigrationLoggingEnabled()) {
+ VLOG(1) << "[AUTOFILL MIGRATION]"
+ << "Current autofill migration state is NOT Migrated because"
+ << "legacy autofill root node is present whereas new "
+ << "Autofill profile root node is absent.";
+ }
+ return true;
+ }
+
+ sync_service()->backend()->SetAutofillMigrationState(syncable::MIGRATED);
+
+ if (MigrationLoggingEnabled()) {
+ VLOG(1) << "[AUTOFILL MIGRATION]"
+ << "Current autofill migration state is migrated.";
+ }
+ }
+
+ return false;
}
+bool AutofillModelAssociator::MigrationLoggingEnabled() {
+ // [TODO] enable logging via a command line flag.
+ return false;
+}
} // namespace browser_sync
+
diff --git a/chrome/browser/sync/glue/autofill_model_associator.h b/chrome/browser/sync/glue/autofill_model_associator.h
index 63db0e8..3f1104e 100644
--- a/chrome/browser/sync/glue/autofill_model_associator.h
+++ b/chrome/browser/sync/glue/autofill_model_associator.h
@@ -52,17 +52,6 @@ class AutofillModelAssociator
PersonalDataManager* data_manager);
virtual ~AutofillModelAssociator();
- // A task used by this class and the change processor to inform the
- // PersonalDataManager living on the UI thread that it needs to refresh.
- class DoOptimisticRefreshTask : public Task {
- public:
- explicit DoOptimisticRefreshTask(PersonalDataManager* pdm);
- virtual ~DoOptimisticRefreshTask();
- virtual void Run();
- private:
- scoped_refptr<PersonalDataManager> pdm_;
- };
-
// PerDataTypeAssociatorInterface implementation.
//
// Iterates through the sync model looking for matched pairs of items.
@@ -114,13 +103,13 @@ class AutofillModelAssociator
// Returns sync service instance.
ProfileSyncService* sync_service() { return sync_service_; }
- protected:
// Is called to determine if we need to upgrade to the new
// autofillprofile2 data type. If so we need to sync up autofillprofile
// first to the latest available changes on the server and then upgrade
// to autofillprofile2.
- virtual bool HasNotMigratedYet();
+ virtual bool HasNotMigratedYet(const sync_api::BaseTransaction* trans);
+ protected:
// Given a profile from sync db it tries to match the profile against
// one in web db. it ignores the guid and compares the actual data.
AutoFillProfile* FindCorrespondingNodeFromWebDB(
@@ -180,20 +169,12 @@ class AutofillModelAssociator
const sync_api::ReadNode& node,
const std::vector<AutoFillProfile*>& all_profiles_from_db);
- // Helper to insert a sync node for the given AutoFillProfile (e.g. in
- // response to encountering a native profile that doesn't exist yet in the
- // cloud).
- bool MakeNewAutofillProfileSyncNode(
- sync_api::WriteTransaction* trans,
- const sync_api::BaseNode& autofill_root,
- const std::string& tag,
- const AutoFillProfile& profile,
- int64* sync_id);
-
// Called at various points in model association to determine if the
// user requested an abort.
bool IsAbortPending();
+ bool MigrationLoggingEnabled();
+
ProfileSyncService* sync_service_;
WebDatabase* web_database_;
PersonalDataManager* personal_data_;
@@ -207,6 +188,7 @@ class AutofillModelAssociator
// AssociateModels method as soon as possible.
Lock abort_association_pending_lock_;
bool abort_association_pending_;
+ int number_of_entries_created_;
DISALLOW_COPY_AND_ASSIGN(AutofillModelAssociator);
};
diff --git a/chrome/browser/sync/glue/autofill_profile_change_processor.cc b/chrome/browser/sync/glue/autofill_profile_change_processor.cc
new file mode 100644
index 0000000..bb99391
--- /dev/null
+++ b/chrome/browser/sync/glue/autofill_profile_change_processor.cc
@@ -0,0 +1,338 @@
+// 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_profile_change_processor.h"
+
+#include <string>
+#include <vector>
+
+#include "base/string_util.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/browser/autofill/autofill_profile.h"
+#include "chrome/browser/autofill/personal_data_manager.h"
+#include "chrome/browser/sync/engine/syncapi.h"
+#include "chrome/browser/sync/glue/autofill_profile_model_associator.h"
+#include "chrome/browser/sync/glue/change_processor.h"
+#include "chrome/browser/sync/glue/do_optimistic_refresh_task.h"
+#include "chrome/browser/sync/unrecoverable_error_handler.h"
+#include "chrome/browser/webdata/autofill_change.h"
+#include "chrome/browser/webdata/web_database.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
+#include "chrome/common/notification_service.h"
+#include "chrome/common/notification_type.h"
+
+namespace browser_sync {
+
+AutofillProfileChangeProcessor::AutofillProfileChangeProcessor(
+ AutofillProfileModelAssociator *model_associator,
+ WebDatabase* web_database,
+ PersonalDataManager* personal_data_manager,
+ UnrecoverableErrorHandler* error_handler)
+ : ChangeProcessor(error_handler),
+ model_associator_(model_associator),
+ observing_(false),
+ web_database_(web_database),
+ personal_data_(personal_data_manager) {
+ DCHECK(model_associator);
+ DCHECK(web_database);
+ DCHECK(error_handler);
+ DCHECK(personal_data_manager);
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
+
+ StartObserving();
+}
+
+AutofillProfileChangeProcessor::ScopedStopObserving::ScopedStopObserving(
+ AutofillProfileChangeProcessor* processor) {
+ processor_ = processor;
+ processor_->StopObserving();
+}
+
+AutofillProfileChangeProcessor::ScopedStopObserving::~ScopedStopObserving() {
+ processor_->StartObserving();
+}
+
+void AutofillProfileChangeProcessor::ApplyChangesFromSyncModel(
+ const sync_api::BaseTransaction *write_trans,
+ const sync_api::SyncManager::ChangeRecord* changes,
+ int change_count) {
+
+ ScopedStopObserving observer(this);
+
+ sync_api::ReadNode autofill_profile_root(write_trans);
+ if (!autofill_profile_root.InitByTagLookup(kAutofillProfileTag)) {
+ error_handler()->OnUnrecoverableError(FROM_HERE,
+ "Autofill Profile root node lookup failed");
+ return;
+ }
+
+ for (int i = 0; i < change_count; ++i) {
+ if (sync_api::SyncManager::ChangeRecord::ACTION_DELETE ==
+ changes[i].action) {
+ DCHECK(changes[i].specifics.HasExtension(
+ sync_pb::autofill_profile));
+
+ const sync_pb::AutofillProfileSpecifics& specifics =
+ changes[i].specifics.GetExtension(sync_pb::autofill_profile);
+
+ autofill_changes_.push_back(AutofillProfileChangeRecord(changes[i].action,
+ changes[i].id,
+ specifics));
+ continue;
+ }
+
+ // If it is not a delete.
+ sync_api::ReadNode sync_node(write_trans);
+ if (!sync_node.InitByIdLookup(changes[i].id)) {
+ LOG(ERROR) << "Could not find the id in sync db " << changes[i].id;
+ continue;
+ }
+
+ const sync_pb::AutofillProfileSpecifics& autofill(
+ sync_node.GetAutofillProfileSpecifics());
+
+ autofill_changes_.push_back(AutofillProfileChangeRecord(changes[i].action,
+ changes[i].id,
+ autofill));
+ }
+}
+
+void AutofillProfileChangeProcessor::Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details) {
+ DCHECK_EQ(type.value, NotificationType::AUTOFILL_PROFILE_CHANGED_GUID);
+ WebDataService* wds = Source<WebDataService>(source).ptr();
+
+ if (!wds || wds->GetDatabase() != web_database_)
+ return;
+
+ sync_api::WriteTransaction trans(share_handle());
+ sync_api::ReadNode autofill_root(&trans);
+ if (!autofill_root.InitByTagLookup(kAutofillProfileTag)) {
+ error_handler()->OnUnrecoverableError(FROM_HERE,
+ "Server did not create a tolp level node");
+ return;
+ }
+
+ AutofillProfileChangeGUID* change =
+ Details<AutofillProfileChangeGUID>(details).ptr();
+
+ ActOnChange(change, &trans, autofill_root);
+}
+
+void AutofillProfileChangeProcessor::ActOnChange(
+ AutofillProfileChangeGUID* change,
+ sync_api::WriteTransaction* trans,
+ sync_api::ReadNode& autofill_root) {
+ DCHECK(change->type() == AutofillProfileChangeGUID::REMOVE ||
+ change->profile());
+ switch (change->type()) {
+ case AutofillProfileChangeGUID::ADD: {
+ AddAutofillProfileSyncNode(trans, autofill_root, *(change->profile()));
+ break;
+ }
+ case AutofillProfileChangeGUID::UPDATE: {
+ int64 sync_id = model_associator_->GetSyncIdFromChromeId(change->key());
+ if (sync_api::kInvalidId == sync_id) {
+ LOG(ERROR) << "Sync id is not found for " << change->key();
+ break;
+ }
+ sync_api::WriteNode node(trans);
+ if (!node.InitByIdLookup(sync_id)) {
+ LOG(ERROR) << "Could not find sync node for id " << sync_id;
+ break;
+ }
+
+ WriteAutofillProfile(*(change->profile()), &node);
+ break;
+ }
+ case AutofillProfileChangeGUID::REMOVE: {
+ int64 sync_id = model_associator_->GetSyncIdFromChromeId(change->key());
+ if (sync_api::kInvalidId == sync_id) {
+ LOG(ERROR) << "Sync id is not found for " << change->key();
+ break;
+ }
+ sync_api::WriteNode node(trans);
+ if (!node.InitByIdLookup(sync_id)) {
+ LOG(ERROR) << "Could not find sync node for id " << sync_id;
+ break;
+ }
+ node.Remove();
+ model_associator_->Disassociate(sync_id);
+ break;
+ }
+ default:
+ NOTREACHED();
+ }
+}
+
+void AutofillProfileChangeProcessor::CommitChangesFromSyncModel() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
+
+ if (!running())
+ return;
+
+ ScopedStopObserving observer(this);
+
+ for (unsigned int i = 0;i < autofill_changes_.size(); ++i) {
+ if (sync_api::SyncManager::ChangeRecord::ACTION_DELETE ==
+ autofill_changes_[i].action_) {
+ if (!web_database_->RemoveAutoFillProfile(
+ autofill_changes_[i].profile_specifics_.guid())) {
+ LOG(ERROR) << "could not delete the profile " <<
+ autofill_changes_[i].profile_specifics_.guid();
+ continue;
+ }
+ continue;
+ }
+
+ // Now for updates and adds.
+ ApplyAutofillProfileChange(autofill_changes_[i].action_,
+ autofill_changes_[i].profile_specifics_,
+ autofill_changes_[i].id_);
+ }
+
+ autofill_changes_.clear();
+
+ PostOptimisticRefreshTask();
+}
+
+void AutofillProfileChangeProcessor::PostOptimisticRefreshTask() {
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ new DoOptimisticRefreshForAutofill(
+ personal_data_));
+}
+
+void AutofillProfileChangeProcessor::ApplyAutofillProfileChange(
+ sync_api::SyncManager::ChangeRecord::Action action,
+ const sync_pb::AutofillProfileSpecifics& profile_specifics,
+ int64 sync_id) {
+
+ DCHECK_NE(sync_api::SyncManager::ChangeRecord::ACTION_DELETE, action);
+ switch (action) {
+ case sync_api::SyncManager::ChangeRecord::ACTION_ADD: {
+ AutoFillProfile p(profile_specifics.guid());
+ AutofillProfileModelAssociator::OverwriteProfileWithServerData(&p,
+ profile_specifics);
+ if (!web_database_->AddAutoFillProfile(p)) {
+ LOG(ERROR) << "could not add autofill profile for guid " << p.guid();
+ break;
+ }
+
+ // Now that the node has been succesfully created we can associate it.
+ std::string guid = p.guid();
+ model_associator_->Associate(&guid, sync_id);
+ break;
+ }
+ case sync_api::SyncManager::ChangeRecord::ACTION_UPDATE: {
+ AutoFillProfile *p;
+ if (!web_database_->GetAutoFillProfileForGUID(
+ profile_specifics.guid(), &p)) {
+ LOG(ERROR) << "Could not find the autofill profile to update for " <<
+ profile_specifics.guid();
+ break;
+ }
+ scoped_ptr<AutoFillProfile> autofill_pointer(p);
+ AutofillProfileModelAssociator::OverwriteProfileWithServerData(
+ autofill_pointer.get(),
+ profile_specifics);
+
+ if (!web_database_->UpdateAutoFillProfile(*(autofill_pointer.get()))) {
+ LOG(ERROR) << "Could not update autofill profile for " <<
+ profile_specifics.guid();
+ break;
+ }
+ break;
+ }
+ default: {
+ NOTREACHED();
+ break;
+ }
+ }
+}
+
+void AutofillProfileChangeProcessor::RemoveSyncNode(const std::string& guid,
+ sync_api::WriteTransaction* trans) {
+ sync_api::WriteNode node(trans);
+ int64 sync_id = model_associator_->GetSyncIdFromChromeId(guid);
+ if (sync_api::kInvalidId == sync_id) {
+ LOG(ERROR) << "Could not find the node in associator " << guid;
+ return;
+ }
+
+ if (!node.InitByIdLookup(sync_id)) {
+ LOG(ERROR) << "Could not find the sync node for " << guid;
+ return;
+ }
+
+ model_associator_->Disassociate(sync_id);
+ node.Remove();
+}
+
+void AutofillProfileChangeProcessor::AddAutofillProfileSyncNode(
+ sync_api::WriteTransaction* trans,
+ sync_api::BaseNode& autofill_profile_root,
+ const AutoFillProfile& profile) {
+ sync_api::WriteNode node(trans);
+ if (!node.InitUniqueByCreation(syncable::AUTOFILL_PROFILE,
+ autofill_profile_root,
+ profile.guid())) {
+ LOG(ERROR) << "could not create a sync node ";
+ return;
+ }
+
+ node.SetTitle(UTF8ToWide(profile.guid()));
+
+ WriteAutofillProfile(profile, &node);
+}
+
+void AutofillProfileChangeProcessor::StartObserving() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
+ notification_registrar_.Add(this,
+ NotificationType::AUTOFILL_PROFILE_CHANGED_GUID,
+ NotificationService::AllSources());
+}
+
+void AutofillProfileChangeProcessor::StopObserving() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
+ notification_registrar_.RemoveAll();
+}
+
+void AutofillProfileChangeProcessor::WriteAutofillProfile(
+ const AutoFillProfile& profile,
+ sync_api::WriteNode* node) {
+ sync_pb::AutofillProfileSpecifics specifics;
+ specifics.set_guid(profile.guid());
+ specifics.set_name_first(UTF16ToUTF8(
+ profile.GetFieldText(AutoFillType(NAME_FIRST))));
+ specifics.set_name_middle(UTF16ToUTF8(
+ profile.GetFieldText(AutoFillType(NAME_MIDDLE))));
+ specifics.set_name_last(
+ UTF16ToUTF8(profile.GetFieldText(AutoFillType(NAME_LAST))));
+ specifics.set_address_home_line1(
+ UTF16ToUTF8(profile.GetFieldText(AutoFillType(ADDRESS_HOME_LINE1))));
+ specifics.set_address_home_line2(
+ UTF16ToUTF8(profile.GetFieldText(AutoFillType(ADDRESS_HOME_LINE2))));
+ specifics.set_address_home_city(UTF16ToUTF8(profile.GetFieldText(
+ AutoFillType(ADDRESS_HOME_CITY))));
+ specifics.set_address_home_state(UTF16ToUTF8(profile.GetFieldText(
+ AutoFillType(ADDRESS_HOME_STATE))));
+ specifics.set_address_home_country(UTF16ToUTF8(profile.GetFieldText(
+ AutoFillType(ADDRESS_HOME_COUNTRY))));
+ specifics.set_address_home_zip(UTF16ToUTF8(profile.GetFieldText(
+ AutoFillType(ADDRESS_HOME_ZIP))));
+ specifics.set_email_address(UTF16ToUTF8(profile.GetFieldText(
+ AutoFillType(EMAIL_ADDRESS))));
+ specifics.set_company_name(UTF16ToUTF8(profile.GetFieldText(
+ AutoFillType(COMPANY_NAME))));
+ specifics.set_phone_fax_whole_number(UTF16ToUTF8(profile.GetFieldText(
+ AutoFillType(PHONE_FAX_WHOLE_NUMBER))));
+ specifics.set_phone_home_whole_number(UTF16ToUTF8(profile.GetFieldText(
+ AutoFillType(PHONE_HOME_WHOLE_NUMBER))));
+ node->SetAutofillProfileSpecifics(specifics);
+}
+
+} // namespace browser_sync
+
diff --git a/chrome/browser/sync/glue/autofill_profile_change_processor.h b/chrome/browser/sync/glue/autofill_profile_change_processor.h
new file mode 100644
index 0000000..0b408a3
--- /dev/null
+++ b/chrome/browser/sync/glue/autofill_profile_change_processor.h
@@ -0,0 +1,120 @@
+// 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.
+#ifndef CHROME_BROWSER_SYNC_GLUE_AUTOFILL_PROFILE_CHANGE_PROCESSOR_H_
+#define CHROME_BROWSER_SYNC_GLUE_AUTOFILL_PROFILE_CHANGE_PROCESSOR_H_
+#pragma once
+#include <string>
+#include <vector>
+
+#include "chrome/browser/autofill/autofill_profile.h"
+#include "chrome/browser/autofill/personal_data_manager.h"
+#include "chrome/browser/sync/engine/syncapi.h"
+#include "chrome/browser/sync/glue/autofill_profile_model_associator.h"
+#include "chrome/browser/sync/glue/change_processor.h"
+#include "chrome/browser/sync/unrecoverable_error_handler.h"
+#include "chrome/browser/webdata/autofill_change.h"
+#include "chrome/browser/webdata/web_database.h"
+#include "chrome/common/notification_observer.h"
+#include "chrome/common/notification_registrar.h"
+#include "chrome/common/notification_service.h"
+#include "chrome/common/notification_type.h"
+
+namespace browser_sync {
+
+class AutofillProfileChangeProcessor : public ChangeProcessor,
+ public NotificationObserver {
+ public:
+ AutofillProfileChangeProcessor(
+ AutofillProfileModelAssociator *model_associator,
+ WebDatabase* web_database,
+ PersonalDataManager* personal_data_manager,
+ UnrecoverableErrorHandler* error_handler);
+
+ virtual ~AutofillProfileChangeProcessor() {}
+
+ // Virtual methods from ChangeProcessor class.
+ virtual void ApplyChangesFromSyncModel(
+ const sync_api::BaseTransaction *write_trans,
+ const sync_api::SyncManager::ChangeRecord* changes,
+ int change_count);
+
+ virtual void CommitChangesFromSyncModel();
+
+ // Virtual method implemented for the observer class.
+ virtual void Observe(NotificationType type,
+ const NotificationSource& source,
+ const NotificationDetails& details);
+
+
+ static void WriteAutofillProfile(const AutoFillProfile& profile,
+ sync_api::WriteNode* node);
+
+ protected:
+ // Protected methods from ChangeProcessor.
+ virtual void StartImpl(Profile* profile) {}
+ virtual void StopImpl() {}
+
+ struct AutofillProfileChangeRecord {
+ sync_api::SyncManager::ChangeRecord::Action action_;
+ int64 id_;
+ sync_pb::AutofillProfileSpecifics profile_specifics_;
+ AutofillProfileChangeRecord(
+ sync_api::SyncManager::ChangeRecord::Action action,
+ int64 id,
+ const sync_pb::AutofillProfileSpecifics profile_specifics)
+ : action_(action),
+ id_(id),
+ profile_specifics_(profile_specifics) {}
+ };
+
+ std::vector<AutofillProfileChangeRecord> autofill_changes_;
+
+ virtual void AddAutofillProfileSyncNode(sync_api::WriteTransaction* trans,
+ sync_api::BaseNode& autofill_profile_root,
+ const AutoFillProfile& profile);
+
+ void ActOnChange(AutofillProfileChangeGUID* change,
+ sync_api::WriteTransaction* trans,
+ sync_api::ReadNode& autofill_root);
+
+ private:
+
+ // This ensures that startobsrving gets called after stopobserving even
+ // if there is an early return in the function.
+ // TODO(lipalani) - generalize this and add it to other change processors.
+ class ScopedStopObserving {
+ public:
+ explicit ScopedStopObserving(AutofillProfileChangeProcessor* processor);
+ ~ScopedStopObserving();
+
+ private:
+ ScopedStopObserving() {}
+ AutofillProfileChangeProcessor* processor_;
+ };
+
+ void StartObserving();
+ void StopObserving();
+
+ void PostOptimisticRefreshTask();
+
+ void ApplyAutofillProfileChange(
+ sync_api::SyncManager::ChangeRecord::Action action,
+ const sync_pb::AutofillProfileSpecifics& profile,
+ int64 sync_id);
+
+ void RemoveSyncNode(
+ const std::string& guid, sync_api::WriteTransaction *trans);
+
+ AutofillProfileModelAssociator* model_associator_;
+ bool observing_;
+
+ WebDatabase* web_database_;
+ PersonalDataManager* personal_data_;
+ NotificationRegistrar notification_registrar_;
+};
+
+} // namespace browser_sync
+
+#endif // CHROME_BROWSER_SYNC_GLUE_AUTOFILL_PROFILE_CHANGE_PROCESSOR_H_
+
diff --git a/chrome/browser/sync/glue/autofill_profile_data_type_controller.cc b/chrome/browser/sync/glue/autofill_profile_data_type_controller.cc
new file mode 100644
index 0000000..230b680
--- /dev/null
+++ b/chrome/browser/sync/glue/autofill_profile_data_type_controller.cc
@@ -0,0 +1,33 @@
+// Copyright (c) 2020 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_profile_data_type_controller.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,
+ ProfileSyncService* sync_service) : AutofillDataTypeController(
+ profile_sync_factory,
+ profile,
+ sync_service) {}
+
+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);
+}
+} // 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
new file mode 100644
index 0000000..8bb6e8e
--- /dev/null
+++ b/chrome/browser/sync/glue/autofill_profile_data_type_controller.h
@@ -0,0 +1,39 @@
+// 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.
+#ifndef CHROME_BROWSER_SYNC_GLUE_AUTOFILL_PROFILE_DATA_TYPE_CONTROLLER_H_
+#define CHROME_BROWSER_SYNC_GLUE_AUTOFILL_PROFILE_DATA_TYPE_CONTROLLER_H_
+#pragma once
+
+#include "chrome/browser/sync/glue/autofill_data_type_controller.h"
+#include "chrome/browser/sync/profile_sync_factory.h"
+
+namespace browser_sync {
+
+class AutofillProfileDataTypeController : public AutofillDataTypeController {
+ public:
+ AutofillProfileDataTypeController(
+ ProfileSyncFactory* profile_sync_factory,
+ Profile* profile,
+ ProfileSyncService* sync_service);
+ virtual ~AutofillProfileDataTypeController() {}
+
+ virtual syncable::ModelType type() {
+ return syncable::AUTOFILL_PROFILE;
+ }
+
+ virtual const char* name() const {
+ // For logging only.
+ return "autofill_profile";
+ }
+ protected:
+ virtual ProfileSyncFactory::SyncComponents CreateSyncComponents(
+ ProfileSyncService* profile_sync_service,
+ WebDatabase* web_database,
+ PersonalDataManager* personal_data,
+ browser_sync::UnrecoverableErrorHandler* error_handler);
+};
+
+} // namespace browser_sync
+
+#endif // CHROME_BROWSER_SYNC_GLUE_AUTOFILL_PROFILE_DATA_TYPE_CONTROLLER_H_
diff --git a/chrome/browser/sync/glue/autofill_profile_model_associator.cc b/chrome/browser/sync/glue/autofill_profile_model_associator.cc
index 91027e3..b2d2e2c 100644
--- a/chrome/browser/sync/glue/autofill_profile_model_associator.cc
+++ b/chrome/browser/sync/glue/autofill_profile_model_associator.cc
@@ -5,13 +5,15 @@
#include "chrome/browser/sync/glue/autofill_profile_model_associator.h"
#include "base/utf_string_conversions.h"
+#include "chrome/browser/sync/glue/autofill_profile_change_processor.h"
+#include "chrome/browser/sync/glue/do_optimistic_refresh_task.h"
#include "chrome/browser/sync/profile_sync_service.h"
#include "chrome/browser/webdata/web_database.h"
using sync_api::ReadNode;
namespace browser_sync {
-const char kAutofillProfileTag[] = "google_chrome_autofill_profile";
+const char kAutofillProfileTag[] = "google_chrome_autofill_profiles";
AutofillProfileModelAssociator::AutofillProfileModelAssociator(
ProfileSyncService* sync_service,
@@ -21,7 +23,8 @@ AutofillProfileModelAssociator::AutofillProfileModelAssociator(
web_database_(web_database),
personal_data_(personal_data),
autofill_node_id_(sync_api::kInvalidId),
- abort_association_pending_(false) {
+ abort_association_pending_(false),
+ number_of_profiles_created_(0) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
DCHECK(sync_service_);
DCHECK(web_database_);
@@ -43,6 +46,24 @@ bool AutofillProfileModelAssociator::TraverseAndAssociateChromeAutoFillProfiles(
std::vector<AutoFillProfile*>* new_profiles,
std::vector<std::string>* profiles_to_delete) {
+ if (MigrationLoggingEnabled()) {
+ VLOG(1) << "[AUTOFILL MIGRATION]"
+ << "Printing profiles from web db";
+
+ for (std::vector<AutoFillProfile*>::const_iterator ix =
+ all_profiles_from_db.begin(); ix != all_profiles_from_db.end(); ++ix) {
+ AutoFillProfile* p = *ix;
+ VLOG(1) << "[AUTOFILL MIGRATION] "
+ << p->GetFieldText(AutoFillType(NAME_FIRST))
+ << p->GetFieldText(AutoFillType(NAME_LAST))
+ << p->guid();
+ }
+ }
+
+ if (MigrationLoggingEnabled()) {
+ VLOG(1) << "[AUTOFILL MIGRATION]"
+ << "Looking for the above data in sync db..";
+ }
// Alias the all_profiles_from_db so we fit in 80 characters
const std::vector<AutoFillProfile*>& profiles(all_profiles_from_db);
for (std::vector<AutoFillProfile*>::const_iterator ix = profiles.begin();
@@ -52,6 +73,14 @@ bool AutofillProfileModelAssociator::TraverseAndAssociateChromeAutoFillProfiles(
ReadNode node(write_trans);
if (node.InitByClientTagLookup(syncable::AUTOFILL_PROFILE, guid)) {
+ if (MigrationLoggingEnabled()) {
+ VLOG(1) << "[AUTOFILL MIGRATION]"
+ << " Found in sync db: "
+ << (*ix)->GetFieldText(AutoFillType(NAME_FIRST))
+ << (*ix)->GetFieldText(AutoFillType(NAME_LAST))
+ << (*ix)->guid()
+ << " so associating";
+ }
const sync_pb::AutofillProfileSpecifics& autofill(
node.GetAutofillProfileSpecifics());
if (OverwriteProfileWithServerData(*ix, autofill)) {
@@ -68,7 +97,18 @@ bool AutofillProfileModelAssociator::TraverseAndAssociateChromeAutoFillProfiles(
profiles_to_delete);
}
}
+ return true;
+}
+bool AutofillProfileModelAssociator::GetSyncIdForTaggedNode(
+ const std::string& tag,
+ int64* sync_id) {
+ sync_api::ReadTransaction trans(
+ sync_service_->backend()->GetUserShareHandle());
+ sync_api::ReadNode sync_node(&trans);
+ if (!sync_node.InitByTagLookup(tag.c_str()))
+ return false;
+ *sync_id = sync_node.GetId();
return true;
}
@@ -98,6 +138,11 @@ bool AutofillProfileModelAssociator::AssociateModels() {
return false;
}
+ if (MigrationLoggingEnabled()) {
+ VLOG(1) << "[AUTOFILL MIGRATION]"
+ << " Now associating to the new autofill profile model associator"
+ << " root node";
+ }
DataBundle bundle;
{
// The write transaction lock is held inside this block.
@@ -127,12 +172,20 @@ bool AutofillProfileModelAssociator::AssociateModels() {
return false;
}
- // TODO(lipalani) Bug 64111- split out the OptimisticRefreshTask
- // into its own class
- // from autofill_model_associator
- // Will be done as part of the autofill_model_associator work.
- // BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- // new DoOptimisticRefreshTask(personal_data_));
+ if (sync_service_->backend()->GetAutofillMigrationState() !=
+ syncable::MIGRATED) {
+ syncable::AutofillMigrationDebugInfo debug_info;
+ debug_info.autofill_profile_added_during_migration =
+ number_of_profiles_created_;
+ sync_service_->backend()->SetAutofillMigrationDebugInfo(
+ syncable::AutofillMigrationDebugInfo::PROFILES_ADDED,
+ debug_info);
+ sync_service()->backend()->SetAutofillMigrationState(
+ syncable::MIGRATED);
+ }
+
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ new DoOptimisticRefreshForAutofill(personal_data_));
return true;
}
@@ -160,9 +213,7 @@ bool AutofillProfileModelAssociator::SyncModelHasUserCreatedNodes(
sync_api::ReadNode node(&trans);
- if (!node.InitByClientTagLookup(
- syncable::AUTOFILL_PROFILE,
- kAutofillProfileTag)) {
+ if (!node.InitByTagLookup(kAutofillProfileTag)) {
LOG(ERROR) << "Sever did not create a top level node"
<< "Out of data server or autofill type not enabled";
return false;
@@ -205,7 +256,7 @@ int64 AutofillProfileModelAssociator::FindSyncNodeWithProfile(
while (sync_child_id != sync_api::kInvalidId) {
ReadNode read_node(trans);
AutoFillProfile p;
- if (read_node.InitByIdLookup(sync_child_id)) {
+ if (!read_node.InitByIdLookup(sync_child_id)) {
LOG(ERROR) << "unable to find the id given by getfirst child " <<
sync_child_id;
return sync_api::kInvalidId;
@@ -247,6 +298,14 @@ bool AutofillProfileModelAssociator::MakeNewAutofillProfileSyncNodeIfNeeded(
std::string guid = autofill_specifics.guid();
Associate(&guid, sync_node_id);
current_profiles->insert(autofill_specifics.guid());
+ if (MigrationLoggingEnabled()) {
+ VLOG(1) << "[AUTOFILL MIGRATION]"
+ << "Found in sync db but with a different guid: "
+ << UTF16ToUTF8(profile.GetFieldText(AutoFillType(NAME_FIRST)))
+ << UTF16ToUTF8(profile.GetFieldText(AutoFillType(NAME_LAST)))
+ << "New guid " << autofill_specifics.guid()
+ << " so associating";
+ }
} else {
sync_api::WriteNode node(trans);
if (!node.InitUniqueByCreation(
@@ -255,10 +314,18 @@ bool AutofillProfileModelAssociator::MakeNewAutofillProfileSyncNodeIfNeeded(
return false;
}
node.SetTitle(UTF8ToWide(profile.guid()));
+ if (MigrationLoggingEnabled()) {
+ VLOG(1) << "[AUTOFILL MIGRATION]"
+ << "NOT Found in sync db "
+ << UTF16ToUTF8(profile.GetFieldText(AutoFillType(NAME_FIRST)))
+ << UTF16ToUTF8(profile.GetFieldText(AutoFillType(NAME_LAST)))
+ << profile.guid()
+ << " so creating a new sync node.";
+ }
+ AutofillProfileChangeProcessor::WriteAutofillProfile(profile, &node);
+ current_profiles->insert(profile.guid());
+ number_of_profiles_created_++;
- // TODO(lipalani) -Bug 64111 This needs rewriting. This will be tackled
- // when rewriting autofill change processor.
- // AutofillChangeProcessor::WriteAutofillProfile(profile, &node);
}
return true;
}
@@ -269,6 +336,10 @@ bool AutofillProfileModelAssociator::TraverseAndAssociateAllSyncNodes(
DataBundle* bundle) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
+ if (MigrationLoggingEnabled()) {
+ VLOG(1) << "[AUTOFILL MIGRATION] "
+ << " Iterating over sync nodes of autofill profile root node";
+ }
int64 sync_child_id = autofill_root.GetFirstChildId();
while (sync_child_id != sync_api::kInvalidId) {
ReadNode sync_child(write_trans);
@@ -292,6 +363,14 @@ void AutofillProfileModelAssociator::AddNativeProfileIfNeeded(
const sync_api::ReadNode& node) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
+ if (MigrationLoggingEnabled()) {
+ VLOG(1) << "[AUTOFILL MIGRATION] "
+ << "Trying to lookup "
+ << profile.name_first()
+ << " "
+ << profile.name_last()
+ << " in the web db";
+ }
if (bundle->current_profiles.find(profile.guid()) ==
bundle->current_profiles.end()) {
std::string guid(profile.guid());
@@ -299,6 +378,15 @@ void AutofillProfileModelAssociator::AddNativeProfileIfNeeded(
AutoFillProfile* p = new AutoFillProfile(profile.guid());
OverwriteProfileWithServerData(p, profile);
bundle->new_profiles.push_back(p);
+ if (MigrationLoggingEnabled()) {
+ VLOG(1) << "[AUTOFILL MIGRATION] "
+ << " Did not find one so creating it on web db";
+ }
+ } else {
+ if (MigrationLoggingEnabled()) {
+ VLOG(1) << "[AUTOFILL MIGRATION] "
+ << " Found it on web db. Moving on ";
+ }
}
}
@@ -332,23 +420,12 @@ bool AutofillProfileModelAssociator::SaveChangesToWebData(
return true;
}
-const std::string* AutofillProfileModelAssociator::GetChromeNodeFromSyncId(
- int64 sync_id) {
- return NULL;
- }
-
bool AutofillProfileModelAssociator::InitSyncNodeFromChromeId(
const std::string& node_id,
sync_api::BaseNode* sync_node) {
return false;
}
-bool AutofillProfileModelAssociator::GetSyncIdForTaggedNode(
- const std::string& tag,
- int64* sync_id) {
- return false;
-}
-
void AutofillProfileModelAssociator::Associate(
const std::string* autofill,
int64 sync_id) {
@@ -381,10 +458,21 @@ void AutofillProfileModelAssociator::AbortAssociation() {
abort_association_pending_ = true;
}
+const std::string* AutofillProfileModelAssociator::GetChromeNodeFromSyncId(
+ int64 sync_id) {
+ SyncIdToAutofillMap::const_iterator iter = id_map_inverse_.find(sync_id);
+ return iter == id_map_inverse_.end() ? NULL : &(iter->second);
+}
+
bool AutofillProfileModelAssociator::IsAbortPending() {
AutoLock lock(abort_association_pending_lock_);
return abort_association_pending_;
}
+bool AutofillProfileModelAssociator::MigrationLoggingEnabled() {
+ // TODO(lipalani) enable logging via a command line flag.
+ return false;
+}
+
} // namespace browser_sync
diff --git a/chrome/browser/sync/glue/autofill_profile_model_associator.h b/chrome/browser/sync/glue/autofill_profile_model_associator.h
index ad8af5c..f636b63 100644
--- a/chrome/browser/sync/glue/autofill_profile_model_associator.h
+++ b/chrome/browser/sync/glue/autofill_profile_model_associator.h
@@ -31,6 +31,8 @@ class WriteTransaction;
namespace browser_sync {
+extern const char kAutofillProfileTag[];
+
class AutofillChangeProcessor;
class UnrecoverableErrorHandler;
@@ -94,6 +96,10 @@ class AutofillProfileModelAssociator
// Returns sync service instance.
ProfileSyncService* sync_service() { return sync_service_; }
+ static bool OverwriteProfileWithServerData(
+ AutoFillProfile* merge_into,
+ const sync_pb::AutofillProfileSpecifics& specifics);
+
protected:
AutofillProfileModelAssociator();
bool TraverseAndAssociateChromeAutoFillProfiles(
@@ -130,10 +136,6 @@ class AutofillProfileModelAssociator
const sync_api::ReadNode& autofill_root,
DataBundle* bundle);
- static bool OverwriteProfileWithServerData(
- AutoFillProfile* merge_into,
- const sync_pb::AutofillProfileSpecifics& specifics);
-
private:
typedef std::map<std::string, int64> AutofillToSyncIdMap;
typedef std::map<int64, std::string> SyncIdToAutofillMap;
@@ -161,6 +163,8 @@ class AutofillProfileModelAssociator
const sync_api::BaseNode& autofill_root,
const AutoFillProfile& profile);
+ bool MigrationLoggingEnabled();
+
ProfileSyncService* sync_service_;
WebDatabase* web_database_;
PersonalDataManager* personal_data_;
@@ -175,6 +179,8 @@ class AutofillProfileModelAssociator
Lock abort_association_pending_lock_;
bool abort_association_pending_;
+ int number_of_profiles_created_;
+
DISALLOW_COPY_AND_ASSIGN(AutofillProfileModelAssociator);
};
@@ -189,3 +195,4 @@ struct AutofillProfileModelAssociator::DataBundle {
} // namespace browser_sync
#endif // CHROME_BROWSER_SYNC_GLUE_AUTOFILL_PROFILE_MODEL_ASSOCIATOR_H_
+
diff --git a/chrome/browser/sync/glue/bookmark_change_processor.cc b/chrome/browser/sync/glue/bookmark_change_processor.cc
index 80e02c3..ebc7f1f 100644
--- a/chrome/browser/sync/glue/bookmark_change_processor.cc
+++ b/chrome/browser/sync/glue/bookmark_change_processor.cc
@@ -1,7 +1,6 @@
// 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/bookmark_change_processor.h"
#include <stack>
@@ -9,6 +8,7 @@
#include "base/string16.h"
#include "base/string_util.h"
+
#include "base/utf_string_conversions.h"
#include "chrome/browser/bookmarks/bookmark_utils.h"
#include "chrome/browser/browser_thread.h"
@@ -451,6 +451,7 @@ const BookmarkNode* BookmarkChangeProcessor::CreateOrUpdateBookmarkNode(
DLOG(WARNING) << "Could not find parent of node being added/updated."
<< " Node title: " << src->GetTitle()
<< ", parent id = " << src->GetParentId();
+
return NULL;
}
int index = CalculateBookmarkModelInsertionIndex(parent, src);
diff --git a/chrome/browser/sync/glue/bookmark_model_associator.cc b/chrome/browser/sync/glue/bookmark_model_associator.cc
index 9e9fac7..dba6a21 100644
--- a/chrome/browser/sync/glue/bookmark_model_associator.cc
+++ b/chrome/browser/sync/glue/bookmark_model_associator.cc
@@ -14,6 +14,7 @@
#include "chrome/browser/browser_thread.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/sync/engine/syncapi.h"
+#include "chrome/browser/sync/syncable/autofill_migration.h"
#include "chrome/browser/sync/glue/bookmark_change_processor.h"
#include "chrome/browser/sync/profile_sync_service.h"
@@ -159,7 +160,8 @@ BookmarkModelAssociator::BookmarkModelAssociator(
UnrecoverableErrorHandler* persist_ids_error_handler)
: sync_service_(sync_service),
persist_ids_error_handler_(persist_ids_error_handler),
- ALLOW_THIS_IN_INITIALIZER_LIST(persist_associations_(this)) {
+ ALLOW_THIS_IN_INITIALIZER_LIST(persist_associations_(this)),
+ number_of_new_sync_nodes_created_at_association_(0) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(sync_service_);
DCHECK(persist_ids_error_handler_);
@@ -413,8 +415,19 @@ bool BookmarkModelAssociator::BuildAssociations() {
parent_node, model, i, &trans, this, sync_service_);
if (parent_node->GetChild(i)->is_folder())
dfs_stack.push(sync_child_id);
+ number_of_new_sync_nodes_created_at_association_++;
}
}
+
+ if (sync_service_->backend()->GetAutofillMigrationState() !=
+ syncable::MIGRATED) {
+ syncable::AutofillMigrationDebugInfo debug_info;
+ debug_info.bookmarks_added_during_migration =
+ number_of_new_sync_nodes_created_at_association_;
+ sync_service_->backend()->SetAutofillMigrationDebugInfo(
+ syncable::AutofillMigrationDebugInfo::BOOKMARK_ADDED,
+ debug_info);
+ }
return true;
}
diff --git a/chrome/browser/sync/glue/bookmark_model_associator.h b/chrome/browser/sync/glue/bookmark_model_associator.h
index 37b8e35..577979f 100644
--- a/chrome/browser/sync/glue/bookmark_model_associator.h
+++ b/chrome/browser/sync/glue/bookmark_model_associator.h
@@ -135,6 +135,8 @@ class BookmarkModelAssociator
// allows this class to be non-refcounted).
ScopedRunnableMethodFactory<BookmarkModelAssociator> persist_associations_;
+ int number_of_new_sync_nodes_created_at_association_;
+
DISALLOW_COPY_AND_ASSIGN(BookmarkModelAssociator);
};
diff --git a/chrome/browser/sync/glue/data_type_manager_impl.cc b/chrome/browser/sync/glue/data_type_manager_impl.cc
index af980fa..119a616 100644
--- a/chrome/browser/sync/glue/data_type_manager_impl.cc
+++ b/chrome/browser/sync/glue/data_type_manager_impl.cc
@@ -23,6 +23,7 @@ static const syncable::ModelType kStartOrder[] = {
syncable::BOOKMARKS,
syncable::PREFERENCES,
syncable::AUTOFILL,
+ syncable::AUTOFILL_PROFILE,
syncable::THEMES,
syncable::TYPED_URLS,
syncable::PASSWORDS,
diff --git a/chrome/browser/sync/glue/do_optimistic_refresh_task.cc b/chrome/browser/sync/glue/do_optimistic_refresh_task.cc
new file mode 100644
index 0000000..654fed2
--- /dev/null
+++ b/chrome/browser/sync/glue/do_optimistic_refresh_task.cc
@@ -0,0 +1,23 @@
+// 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/do_optimistic_refresh_task.h"
+
+#include "chrome/browser/autofill/personal_data_manager.h"
+#include "chrome/browser/browser_thread.h"
+
+namespace browser_sync {
+
+DoOptimisticRefreshForAutofill::DoOptimisticRefreshForAutofill(
+ PersonalDataManager* pdm) : pdm_(pdm) {}
+
+DoOptimisticRefreshForAutofill::~DoOptimisticRefreshForAutofill() {}
+
+void DoOptimisticRefreshForAutofill::Run() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ pdm_->Refresh();
+}
+
+} // namespace browser_sync
+
diff --git a/chrome/browser/sync/glue/do_optimistic_refresh_task.h b/chrome/browser/sync/glue/do_optimistic_refresh_task.h
new file mode 100644
index 0000000..f98d436
--- /dev/null
+++ b/chrome/browser/sync/glue/do_optimistic_refresh_task.h
@@ -0,0 +1,26 @@
+// 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.
+#ifndef CHROME_BROWSER_SYNC_GLUE_DO_OPTIMISTIC_REFRESH_TASK_H_
+#define CHROME_BROWSER_SYNC_GLUE_DO_OPTIMISTIC_REFRESH_TASK_H_
+#pragma once
+
+#include "base/ref_counted.h"
+#include "chrome/browser/autofill/personal_data_manager.h"
+
+namespace browser_sync {
+
+// A task used by this class and the change processor to inform the
+// PersonalDataManager living on the UI thread that it needs to refresh.
+class DoOptimisticRefreshForAutofill : public Task {
+ public:
+ explicit DoOptimisticRefreshForAutofill(PersonalDataManager* pdm);
+ virtual ~DoOptimisticRefreshForAutofill();
+ virtual void Run();
+ private:
+ scoped_refptr<PersonalDataManager> pdm_;
+};
+
+} // namespace browser_sync
+#endif // CHROME_BROWSER_SYNC_GLUE_DO_OPTIMISTIC_REFRESH_TASK_H_
+
diff --git a/chrome/browser/sync/glue/sync_backend_host.cc b/chrome/browser/sync/glue/sync_backend_host.cc
index fb63ce5..4dafe24 100644
--- a/chrome/browser/sync/glue/sync_backend_host.cc
+++ b/chrome/browser/sync/glue/sync_backend_host.cc
@@ -15,6 +15,8 @@
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/sync/engine/syncapi.h"
+#include "chrome/browser/sync/glue/autofill_model_associator.h"
+#include "chrome/browser/sync/glue/autofill_profile_model_associator.h"
#include "chrome/browser/sync/glue/change_processor.h"
#include "chrome/browser/sync/glue/database_model_worker.h"
#include "chrome/browser/sync/glue/history_model_worker.h"
@@ -24,6 +26,7 @@
#include "chrome/browser/sync/sessions/session_state.h"
// TODO(tim): Remove this! We should have a syncapi pass-thru instead.
#include "chrome/browser/sync/syncable/directory_manager.h" // Cryptographer.
+#include "chrome/browser/sync/syncable/model_type.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/chrome_version_info.h"
#include "chrome/common/net/gaia/gaia_constants.h"
@@ -251,12 +254,73 @@ void SyncBackendHost::Shutdown(bool sync_disabled) {
core_ = NULL; // Releases reference to core_.
}
+syncable::AutofillMigrationState
+ SyncBackendHost::GetAutofillMigrationState() {
+ return core_->syncapi()->GetAutofillMigrationState();
+}
+
+void SyncBackendHost::SetAutofillMigrationState(
+ syncable::AutofillMigrationState state) {
+ return core_->syncapi()->SetAutofillMigrationState(state);
+}
+
+syncable::AutofillMigrationDebugInfo
+ SyncBackendHost::GetAutofillMigrationDebugInfo() {
+ return core_->syncapi()->GetAutofillMigrationDebugInfo();
+}
+
+void SyncBackendHost::SetAutofillMigrationDebugInfo(
+ syncable::AutofillMigrationDebugInfo::PropertyToSet property_to_set,
+ const syncable::AutofillMigrationDebugInfo& info) {
+ return core_->syncapi()->SetAutofillMigrationDebugInfo(property_to_set, info);
+}
+
+void SyncBackendHost::ConfigureAutofillMigration() {
+ if (GetAutofillMigrationState() == syncable::NOT_DETERMINED) {
+ sync_api::ReadTransaction trans(GetUserShareHandle());
+ sync_api::ReadNode autofil_root_node(&trans);
+
+ // Check for the presence of autofill node.
+ if (!autofil_root_node.InitByTagLookup(browser_sync::kAutofillTag)) {
+ SetAutofillMigrationState(syncable::INSUFFICIENT_INFO_TO_DETERMINE);
+ return;
+ }
+
+ // Check for children under autofill node.
+ if (autofil_root_node.GetFirstChildId() == static_cast<int64>(0)) {
+ SetAutofillMigrationState(syncable::INSUFFICIENT_INFO_TO_DETERMINE);
+ return;
+ }
+
+ sync_api::ReadNode autofill_profile_root_node(&trans);
+
+ // Check for the presence of autofill profile root node.
+ if (!autofill_profile_root_node.InitByTagLookup(
+ browser_sync::kAutofillProfileTag)) {
+ SetAutofillMigrationState(syncable::NOT_MIGRATED);
+ return;
+ }
+
+ // If our state is not determined then we should not have the autofill
+ // profile node.
+ DCHECK(false);
+
+ // just set it as not migrated.
+ SetAutofillMigrationState(syncable::NOT_MIGRATED);
+ return;
+ }
+}
+
void SyncBackendHost::ConfigureDataTypes(const syncable::ModelTypeSet& types,
CancelableTask* ready_task) {
// Only one configure is allowed at a time.
DCHECK(!configure_ready_task_.get());
DCHECK(syncapi_initialized_);
+ if (types.count(syncable::AUTOFILL_PROFILE) != 0) {
+ ConfigureAutofillMigration();
+ }
+
bool deleted_type = false;
{
diff --git a/chrome/browser/sync/glue/sync_backend_host.h b/chrome/browser/sync/glue/sync_backend_host.h
index 3edd648..fdfc7b4 100644
--- a/chrome/browser/sync/glue/sync_backend_host.h
+++ b/chrome/browser/sync/glue/sync_backend_host.h
@@ -142,6 +142,19 @@ class SyncBackendHost : public browser_sync::ModelSafeWorkerRegistrar {
virtual void ConfigureDataTypes(const syncable::ModelTypeSet& types,
CancelableTask* ready_task);
+ syncable::AutofillMigrationState
+ GetAutofillMigrationState();
+
+ void SetAutofillMigrationState(
+ syncable::AutofillMigrationState state);
+
+ syncable::AutofillMigrationDebugInfo
+ GetAutofillMigrationDebugInfo();
+
+ void SetAutofillMigrationDebugInfo(
+ syncable::AutofillMigrationDebugInfo::PropertyToSet property_to_set,
+ const syncable::AutofillMigrationDebugInfo& info);
+
// Activates change processing for the given data type. This must
// be called synchronously with the data type's model association so
// no changes are dropped between model association and change
@@ -445,6 +458,8 @@ class SyncBackendHost : public browser_sync::ModelSafeWorkerRegistrar {
UIModelWorker* ui_worker();
+ void ConfigureAutofillMigration();
+
// A thread we dedicate for use by our Core to perform initialization,
// authentication, handle messages from the syncapi, and periodically tell
// the syncapi to persist itself.
diff --git a/chrome/browser/sync/profile_sync_factory.h b/chrome/browser/sync/profile_sync_factory.h
index a4a2550..776b61d 100644
--- a/chrome/browser/sync/profile_sync_factory.h
+++ b/chrome/browser/sync/profile_sync_factory.h
@@ -77,6 +77,15 @@ class ProfileSyncFactory {
browser_sync::UnrecoverableErrorHandler* error_handler) = 0;
// Instantiates both a model associator and change processor for the
+ // autofill data type. The pointers in the return struct are owned
+ // by the caller.
+ virtual SyncComponents CreateAutofillProfileSyncComponents(
+ ProfileSyncService* profile_sync_service,
+ WebDatabase* web_database,
+ PersonalDataManager* personal_data,
+ browser_sync::UnrecoverableErrorHandler* error_handler) = 0;
+
+ // Instantiates both a model associator and change processor for the
// bookmark data type. The pointers in the return struct are owned
// by the caller.
virtual SyncComponents CreateBookmarkSyncComponents(
diff --git a/chrome/browser/sync/profile_sync_factory_impl.cc b/chrome/browser/sync/profile_sync_factory_impl.cc
index a763a4c..07c1145 100644
--- a/chrome/browser/sync/profile_sync_factory_impl.cc
+++ b/chrome/browser/sync/profile_sync_factory_impl.cc
@@ -10,6 +10,9 @@
#include "chrome/browser/sync/glue/autofill_data_type_controller.h"
#include "chrome/browser/sync/glue/autofill_model_associator.h"
#include "chrome/browser/sync/glue/autofill_model_associator2.h"
+#include "chrome/browser/sync/glue/autofill_profile_change_processor.h"
+#include "chrome/browser/sync/glue/autofill_profile_data_type_controller.h"
+#include "chrome/browser/sync/glue/autofill_profile_model_associator.h"
#include "chrome/browser/sync/glue/bookmark_change_processor.h"
#include "chrome/browser/sync/glue/bookmark_data_type_controller.h"
#include "chrome/browser/sync/glue/bookmark_model_associator.h"
@@ -38,13 +41,17 @@
#include "chrome/browser/sync/profile_sync_factory_impl.h"
#include "chrome/browser/webdata/web_data_service.h"
#include "chrome/common/chrome_switches.h"
+#include "chrome/common/pref_names.h"
using browser_sync::AppDataTypeController;
using browser_sync::AutofillChangeProcessor;
using browser_sync::AutofillChangeProcessor2;
+using browser_sync::AutofillProfileChangeProcessor;
using browser_sync::AutofillDataTypeController;
+using browser_sync::AutofillProfileDataTypeController;
using browser_sync::AutofillModelAssociator;
using browser_sync::AutofillModelAssociator2;
+using browser_sync::AutofillProfileModelAssociator;
using browser_sync::BookmarkChangeProcessor;
using browser_sync::BookmarkDataTypeController;
using browser_sync::BookmarkModelAssociator;
@@ -145,6 +152,12 @@ ProfileSyncService* ProfileSyncFactoryImpl::CreateProfileSyncService(
pss->RegisterDataTypeController(
new SessionDataTypeController(this, pss));
}
+
+ if (!command_line_->HasSwitch(switches::kDisableSyncAutofillProfile) &&
+ command_line_->HasSwitch(switches::kEnableSyncNewAutofill)) {
+ pss->RegisterDataTypeController(new AutofillProfileDataTypeController(
+ this, profile_, pss));
+ }
return pss;
}
@@ -202,6 +215,25 @@ ProfileSyncFactoryImpl::CreateAutofillSyncComponents(
}
ProfileSyncFactory::SyncComponents
+ProfileSyncFactoryImpl::CreateAutofillProfileSyncComponents(
+ ProfileSyncService* profile_sync_service,
+ WebDatabase* web_database,
+ PersonalDataManager* personal_data,
+ browser_sync::UnrecoverableErrorHandler* error_handler) {
+
+ AutofillProfileModelAssociator* model_associator =
+ new AutofillProfileModelAssociator(profile_sync_service,
+ web_database,
+ personal_data);
+ AutofillProfileChangeProcessor* change_processor =
+ new AutofillProfileChangeProcessor(model_associator,
+ web_database,
+ personal_data,
+ error_handler);
+ return SyncComponents(model_associator, change_processor);
+}
+
+ProfileSyncFactory::SyncComponents
ProfileSyncFactoryImpl::CreateBookmarkSyncComponents(
ProfileSyncService* profile_sync_service,
UnrecoverableErrorHandler* error_handler) {
diff --git a/chrome/browser/sync/profile_sync_factory_impl.h b/chrome/browser/sync/profile_sync_factory_impl.h
index 233f3f1..eb93f1c 100644
--- a/chrome/browser/sync/profile_sync_factory_impl.h
+++ b/chrome/browser/sync/profile_sync_factory_impl.h
@@ -37,6 +37,12 @@ class ProfileSyncFactoryImpl : public ProfileSyncFactory {
PersonalDataManager* personal_data,
browser_sync::UnrecoverableErrorHandler* error_handler);
+ virtual SyncComponents CreateAutofillProfileSyncComponents(
+ ProfileSyncService* profile_sync_service,
+ WebDatabase* web_database,
+ PersonalDataManager* personal_data,
+ browser_sync::UnrecoverableErrorHandler* error_handler);
+
virtual SyncComponents CreateBookmarkSyncComponents(
ProfileSyncService* profile_sync_service,
browser_sync::UnrecoverableErrorHandler* error_handler);
diff --git a/chrome/browser/sync/profile_sync_factory_mock.h b/chrome/browser/sync/profile_sync_factory_mock.h
index 18cc30c..f5210a0 100644
--- a/chrome/browser/sync/profile_sync_factory_mock.h
+++ b/chrome/browser/sync/profile_sync_factory_mock.h
@@ -38,6 +38,12 @@ class ProfileSyncFactoryMock : public ProfileSyncFactory {
WebDatabase* web_database,
PersonalDataManager* personal_data,
browser_sync::UnrecoverableErrorHandler* error_handler));
+ MOCK_METHOD4(CreateAutofillProfileSyncComponents,
+ SyncComponents(
+ ProfileSyncService* profile_sync_service,
+ WebDatabase* web_database,
+ PersonalDataManager* personal_data,
+ browser_sync::UnrecoverableErrorHandler* error_handler));
MOCK_METHOD2(CreateBookmarkSyncComponents,
SyncComponents(ProfileSyncService* profile_sync_service,
browser_sync::UnrecoverableErrorHandler* error_handler));
diff --git a/chrome/browser/sync/profile_sync_service.cc b/chrome/browser/sync/profile_sync_service.cc
index fb2473f..eac1026 100644
--- a/chrome/browser/sync/profile_sync_service.cc
+++ b/chrome/browser/sync/profile_sync_service.cc
@@ -24,6 +24,7 @@
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/net/gaia/token_service.h"
+#include "chrome/browser/sync/glue/autofill_profile_data_type_controller.h"
#include "chrome/browser/sync/glue/change_processor.h"
#include "chrome/browser/sync/glue/data_type_controller.h"
#include "chrome/browser/sync/glue/data_type_manager.h"
@@ -367,6 +368,9 @@ void ProfileSyncService::RegisterPreferences() {
enable_by_default);
pref_service->RegisterBooleanPref(prefs::kSyncManaged, false);
pref_service->RegisterStringPref(prefs::kEncryptionBootstrapToken, "");
+
+ pref_service->RegisterBooleanPref(prefs::kSyncAutofillProfile,
+ enable_by_default);
}
void ProfileSyncService::ClearPreferences() {
@@ -549,6 +553,9 @@ const char* ProfileSyncService::GetPrefNameForDataType(
return prefs::kSyncPreferences;
case syncable::AUTOFILL:
return prefs::kSyncAutofill;
+ case syncable::AUTOFILL_PROFILE:
+ return prefs::kSyncAutofillProfile;
+ break;
case syncable::THEMES:
return prefs::kSyncThemes;
case syncable::TYPED_URLS:
@@ -882,6 +889,10 @@ void ProfileSyncService::ChangePreferredDataTypes(
continue;
profile_->GetPrefs()->SetBoolean(pref_name,
preferred_types.count(model_type) != 0);
+ if (syncable::AUTOFILL == model_type) {
+ profile_->GetPrefs()->SetBoolean(prefs::kSyncAutofillProfile,
+ preferred_types.count(model_type) != 0);
+ }
}
// If we haven't initialized yet, don't configure the DTM as it could cause
@@ -893,23 +904,33 @@ void ProfileSyncService::ChangePreferredDataTypes(
void ProfileSyncService::GetPreferredDataTypes(
syncable::ModelTypeSet* preferred_types) const {
preferred_types->clear();
-
- // Filter out any datatypes which aren't registered, or for which
- // the preference can't be read.
- syncable::ModelTypeSet registered_types;
- GetRegisteredDataTypes(&registered_types);
if (profile_->GetPrefs()->GetBoolean(prefs::kKeepEverythingSynced)) {
- *preferred_types = registered_types;
+ GetRegisteredDataTypes(preferred_types);
} else {
+ // Filter out any datatypes which aren't registered, or for which
+ // the preference can't be read.
+ syncable::ModelTypeSet registered_types;
+ GetRegisteredDataTypes(&registered_types);
for (int i = 0; i < syncable::MODEL_TYPE_COUNT; ++i) {
syncable::ModelType model_type = syncable::ModelTypeFromInt(i);
if (!registered_types.count(model_type))
continue;
+ if (model_type == syncable::AUTOFILL_PROFILE)
+ continue;
const char* pref_name = GetPrefNameForDataType(model_type);
if (!pref_name)
continue;
- if (profile_->GetPrefs()->GetBoolean(pref_name))
+
+ // We are trying to group autofill_profile tag with the same
+ // enabled/disabled state as autofill. Because the UI only shows autofill.
+ if (profile_->GetPrefs()->GetBoolean(pref_name)) {
preferred_types->insert(model_type);
+ if (model_type == syncable::AUTOFILL) {
+ if (!registered_types.count(syncable::AUTOFILL_PROFILE))
+ continue;
+ preferred_types->insert(syncable::AUTOFILL_PROFILE);
+ }
+ }
}
}
}
diff --git a/chrome/browser/sync/sync_ui_util.cc b/chrome/browser/sync/sync_ui_util.cc
index 2b20eda..30a4ed4 100644
--- a/chrome/browser/sync/sync_ui_util.cc
+++ b/chrome/browser/sync/sync_ui_util.cc
@@ -6,6 +6,8 @@
#include "app/l10n_util.h"
#include "base/i18n/number_formatting.h"
+#include "base/i18n/time_formatting.h"
+#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/sync/profile_sync_service.h"
@@ -215,6 +217,15 @@ void AddIntSyncDetail(ListValue* details, const std::string& stat_name,
details->Append(val);
}
+std::wstring ConstructTime(int64 time_in_int) {
+ base::Time time = base::Time::FromInternalValue(time_in_int);
+
+ // If time is null the format function returns a time in 1969.
+ if (time.is_null())
+ return std::wstring();
+ return base::TimeFormatFriendlyDateAndTime(time);
+}
+
std::string MakeSyncAuthErrorText(
const GoogleServiceAuthError::State& state) {
switch (state) {
@@ -323,6 +334,30 @@ void ConstructAboutInformation(ProfileSyncService* service,
val->SetString("group", ModelSafeGroupToString(it->second));
routing_info->Append(val);
}
+
+ sync_ui_util::AddBoolSyncDetail(details,
+ "Autofill Migrated",
+ service->backend()->GetAutofillMigrationState() ==
+ syncable::MIGRATED);
+ syncable::AutofillMigrationDebugInfo info =
+ service->backend()->GetAutofillMigrationDebugInfo();
+
+ sync_ui_util::AddIntSyncDetail(details,
+ "Bookmarks created during migration",
+ info.bookmarks_added_during_migration);
+ sync_ui_util::AddIntSyncDetail(details,
+ "Autofill entries created during migration",
+ info.autofill_entries_added_during_migration);
+ sync_ui_util::AddIntSyncDetail(details,
+ "Autofill Profiles created during migration",
+ info.autofill_profile_added_during_migration);
+
+ DictionaryValue* val = new DictionaryValue;
+ val->SetString("stat_name", "Autofill Migration Time");
+ val->SetString("stat_value",
+ WideToUTF16Hack(
+ ConstructTime(info.autofill_migration_time)));
+ details->Append(val);
}
}
}
diff --git a/chrome/browser/sync/syncable/autofill_migration.h b/chrome/browser/sync/syncable/autofill_migration.h
new file mode 100644
index 0000000..81a16be
--- /dev/null
+++ b/chrome/browser/sync/syncable/autofill_migration.h
@@ -0,0 +1,49 @@
+// 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.
+
+#ifndef CHROME_BROWSER_SYNC_SYNCABLE_AUTOFILL_MIGRATION_H_
+#define CHROME_BROWSER_SYNC_SYNCABLE_AUTOFILL_MIGRATION_H_
+#pragma once
+
+namespace syncable {
+enum AutofillMigrationState {
+
+ // Indicates the default state. After first run the state would change to
+ // one of the following.
+ NOT_DETERMINED,
+
+ // The autofill profile is not migrated. Current sync should migrate the data
+ // by syncing down the old autofill and syncing profiles back up to the server
+ // as new autofill.
+ NOT_MIGRATED,
+
+ // We have migrated the autofill profile data. From now on autofill and
+ // autofill profiles are 2 seperate data types.
+ MIGRATED,
+
+ // The autofill datatype is being synced new.(either because this is a new
+ // client or the user just enabled them for syncing). In which case if
+ // someother client had migrated the data already then our new state after
+ // first sync would be MIGRATED. Else we would be responsible for migrating
+ // the data.
+ INSUFFICIENT_INFO_TO_DETERMINE
+};
+
+struct AutofillMigrationDebugInfo {
+ enum PropertyToSet {
+ MIGRATION_TIME,
+ BOOKMARK_ADDED,
+ ENTRIES_ADDED,
+ PROFILES_ADDED
+ };
+ int64 autofill_migration_time;
+ int bookmarks_added_during_migration;
+ int autofill_entries_added_during_migration;
+ int autofill_profile_added_during_migration;
+};
+
+} // namespace syncable
+
+#endif // CHROME_BROWSER_SYNC_SYNCABLE_AUTOFILL_MIGRATION_H_
+
diff --git a/chrome/browser/sync/syncable/directory_backing_store.cc b/chrome/browser/sync/syncable/directory_backing_store.cc
index c0036d3..feefd91 100644
--- a/chrome/browser/sync/syncable/directory_backing_store.cc
+++ b/chrome/browser/sync/syncable/directory_backing_store.cc
@@ -44,7 +44,7 @@ static const string::size_type kUpdateStatementBufferSize = 2048;
// Increment this version whenever updating DB tables.
extern const int32 kCurrentDBVersion; // Global visibility for our unittest.
-const int32 kCurrentDBVersion = 73;
+const int32 kCurrentDBVersion = 74;
namespace {
@@ -379,11 +379,28 @@ bool DirectoryBackingStore::SaveChanges(
update.prepare(dbhandle, "UPDATE share_info "
"SET store_birthday = ?, "
"next_id = ?, "
- "notification_state = ?");
+ "notification_state = ?, "
+ "autofill_migration_state = ?, "
+ "bookmarks_added_during_autofill_migration = ?, "
+ "autofill_migration_time = ?, "
+ "autofill_entries_added_during_migration = ?, "
+ "autofill_profiles_added_during_migration = ? ");
+
+ const syncable::AutofillMigrationDebugInfo& debug_info =
+ info.autofill_migration_debug_info;
update.bind_string(0, info.store_birthday);
update.bind_int64(1, info.next_id);
update.bind_blob(2, info.notification_state.data(),
info.notification_state.size());
+ update.bind_int(3, info.autofill_migration_state);
+ update.bind_int(4,
+ debug_info.bookmarks_added_during_migration);
+ update.bind_int64(5,
+ debug_info.autofill_migration_time);
+ update.bind_int(6,
+ debug_info.autofill_entries_added_during_migration);
+ update.bind_int(7,
+ debug_info.autofill_profile_added_during_migration);
if (!(SQLITE_DONE == update.step() &&
SQLITE_OK == update.reset() &&
@@ -456,6 +473,11 @@ DirOpenResult DirectoryBackingStore::InitializeTables() {
version_on_disk = 73;
}
+ if (version_on_disk == 73) {
+ if (MigrateVersion73To74())
+ version_on_disk = 74;
+ }
+
// If one of the migrations requested it, drop columns that aren't current.
// It's only safe to do this after migrating all the way to the current
// version.
@@ -556,13 +578,30 @@ bool DirectoryBackingStore::LoadInfo(Directory::KernelLoadInfo* info) {
SQLStatement query;
query.prepare(load_dbhandle_,
"SELECT store_birthday, next_id, cache_guid, "
- "notification_state FROM share_info");
+ "notification_state, autofill_migration_state, "
+ "bookmarks_added_during_autofill_migration, "
+ "autofill_migration_time, "
+ "autofill_entries_added_during_migration, "
+ "autofill_profiles_added_during_migration "
+ "FROM share_info");
if (SQLITE_ROW != query.step())
return false;
info->kernel_info.store_birthday = query.column_string(0);
info->kernel_info.next_id = query.column_int64(1);
info->cache_guid = query.column_string(2);
query.column_blob_as_string(3, &info->kernel_info.notification_state);
+ info->kernel_info.autofill_migration_state =
+ static_cast<AutofillMigrationState> (query.column_int(4));
+ syncable::AutofillMigrationDebugInfo& debug_info =
+ info->kernel_info.autofill_migration_debug_info;
+ debug_info.bookmarks_added_during_migration =
+ query.column_int(5);
+ debug_info.autofill_migration_time =
+ query.column_int64(6);
+ debug_info.autofill_entries_added_during_migration =
+ query.column_int(7);
+ debug_info.autofill_profile_added_during_migration =
+ query.column_int(8);
}
{
SQLStatement query;
@@ -889,9 +928,9 @@ bool DirectoryBackingStore::MigrateVersion70To71() {
// Drop the columns from the old share_info table via a temp table.
const bool kCreateAsTempShareInfo = true;
- const bool kWithNotificationState = false;
+
int result =
- CreateShareInfoTable(kCreateAsTempShareInfo, kWithNotificationState);
+ CreateShareInfoTableVersion71(kCreateAsTempShareInfo);
if (result != SQLITE_DONE)
return false;
ExecQuery(load_dbhandle_,
@@ -926,6 +965,50 @@ bool DirectoryBackingStore::MigrateVersion72To73() {
return true;
}
+bool DirectoryBackingStore::MigrateVersion73To74() {
+ int result =
+ ExecQuery(load_dbhandle_,
+ "ALTER TABLE share_info ADD COLUMN autofill_migration_state "
+ "INT default 0");
+ if (result != SQLITE_DONE)
+ return false;
+
+ result = ExecQuery(load_dbhandle_,
+ "ALTER TABLE share_info ADD COLUMN "
+ "bookmarks_added_during_autofill_migration "
+ "INT default 0");
+
+ if (result != SQLITE_DONE)
+ return false;
+
+ result = ExecQuery(load_dbhandle_,
+ "ALTER TABLE share_info ADD COLUMN autofill_migration_time "
+ "INT default 0");
+
+ if (result != SQLITE_DONE)
+ return false;
+
+ result = ExecQuery(load_dbhandle_,
+ "ALTER TABLE share_info ADD COLUMN "
+ "autofill_entries_added_during_migration "
+ "INT default 0");
+
+ if (result != SQLITE_DONE)
+ return false;
+
+ result = ExecQuery(load_dbhandle_,
+ "ALTER TABLE share_info ADD COLUMN "
+ "autofill_profiles_added_during_migration "
+ "INT default 0");
+
+ if (result != SQLITE_DONE)
+ return false;
+
+ SetVersion(74);
+ return true;
+}
+
+
int DirectoryBackingStore::CreateTables() {
VLOG(1) << "First run, creating tables";
// Create two little tables share_version and share_info
@@ -945,9 +1028,8 @@ int DirectoryBackingStore::CreateTables() {
return result;
const bool kCreateAsTempShareInfo = false;
- const bool kWithNotificationState = true;
result =
- CreateShareInfoTable(kCreateAsTempShareInfo, kWithNotificationState);
+ CreateShareInfoTable(kCreateAsTempShareInfo);
if (result != SQLITE_DONE)
return result;
{
@@ -960,6 +1042,14 @@ int DirectoryBackingStore::CreateTables() {
"?, " // db_create_time
"-2, " // next_id
"?, " // cache_guid
+ "?, " // autofill_migration_state
+ "?, " // bookmarks_added
+ // _during_autofill_migration
+ "?, " // autofill_migration_time
+ "?, " // autofill_entries
+ // _added_during_migration
+ "?, " // autofill_profiles_added
+ // _during_migration
"?);"); // notification_state
statement.bind_string(0, dir_name_); // id
statement.bind_string(1, dir_name_); // name
@@ -967,7 +1057,12 @@ int DirectoryBackingStore::CreateTables() {
statement.bind_string(3, SYNC_ENGINE_VERSION_STRING); // db_create_version
statement.bind_int(4, static_cast<int32>(time(0))); // db_create_time
statement.bind_string(5, GenerateCacheGUID()); // cache_guid
- statement.bind_blob(6, NULL, 0); // notification_state
+ statement.bind_int(6, 0); // autofill_migration_state
+ statement.bind_int(7, 0); // autofill_migration_time
+ statement.bind_int(8, 0); // bookmarks_added_during_autofill_migration
+ statement.bind_int(9, 0); // autofill_entries_added_during_migration
+ statement.bind_int(10, 0); // autofill_profiles_added_during_migration
+ statement.bind_blob(11, NULL, 0); // notification_state
result = statement.step();
}
if (result != SQLITE_DONE)
@@ -1025,8 +1120,7 @@ int DirectoryBackingStore::CreateModelsTable() {
"initial_sync_ended BOOLEAN default 0)");
}
-int DirectoryBackingStore::CreateShareInfoTable(
- bool is_temporary, bool with_notification_state) {
+int DirectoryBackingStore::CreateShareInfoTable(bool is_temporary) {
const char* name = is_temporary ? "temp_share_info" : "share_info";
string query = "CREATE TABLE ";
query.append(name);
@@ -1040,12 +1134,34 @@ int DirectoryBackingStore::CreateShareInfoTable(
"db_create_version TEXT, "
"db_create_time INT, "
"next_id INT default -2, "
- "cache_guid TEXT");
- if (with_notification_state) {
- query.append(", notification_state BLOB");
- }
+ "cache_guid TEXT, "
+ "autofill_migration_state INT default 0, "
+ "bookmarks_added_during_autofill_migration INT default 0, "
+ "autofill_migration_time INT default 0, "
+ "autofill_entries_added_during_migration INT default 0, "
+ "autofill_profiles_added_during_migration INT default 0 ");
+
+ query.append(", notification_state BLOB");
query.append(")");
return ExecQuery(load_dbhandle_, query.c_str());
}
+int DirectoryBackingStore::CreateShareInfoTableVersion71(
+ bool is_temporary) {
+ const char* name = is_temporary ? "temp_share_info" : "share_info";
+ string query = "CREATE TABLE ";
+ query.append(name);
+ // This is the current schema for the ShareInfo table, from version 71
+ // onward. If you change the schema, you'll probably want to double-check
+ // the use of this function in the v70-v71 migration.
+ query.append(" ("
+ "id TEXT primary key, "
+ "name TEXT, "
+ "store_birthday TEXT, "
+ "db_create_version TEXT, "
+ "db_create_time INT, "
+ "next_id INT default -2, "
+ "cache_guid TEXT )");
+ return ExecQuery(load_dbhandle_, query.c_str());
+}
} // namespace syncable
diff --git a/chrome/browser/sync/syncable/directory_backing_store.h b/chrome/browser/sync/syncable/directory_backing_store.h
index f1a09dd..45187e7 100644
--- a/chrome/browser/sync/syncable/directory_backing_store.h
+++ b/chrome/browser/sync/syncable/directory_backing_store.h
@@ -80,6 +80,7 @@ class DirectoryBackingStore {
FRIEND_TEST_ALL_PREFIXES(DirectoryBackingStoreTest, MigrateVersion70To71);
FRIEND_TEST_ALL_PREFIXES(DirectoryBackingStoreTest, MigrateVersion71To72);
FRIEND_TEST_ALL_PREFIXES(DirectoryBackingStoreTest, MigrateVersion72To73);
+ FRIEND_TEST_ALL_PREFIXES(DirectoryBackingStoreTest, MigrateVersion73To74);
FRIEND_TEST_ALL_PREFIXES(DirectoryBackingStoreTest, ModelTypeIds);
FRIEND_TEST_ALL_PREFIXES(DirectoryBackingStoreTest, Corruption);
FRIEND_TEST_ALL_PREFIXES(DirectoryBackingStoreTest, DeleteEntries);
@@ -92,10 +93,11 @@ class DirectoryBackingStore {
int CreateTables();
// Create 'share_info' or 'temp_share_info' depending on value of
- // is_temporary. If with_notification_state is true, creates the
- // table with the notification_state column. Returns an sqlite
+ // is_temporary. Returns an sqlite
// return code, SQLITE_DONE on success.
- int CreateShareInfoTable(bool is_temporary, bool with_notification_state);
+ int CreateShareInfoTable(bool is_temporary);
+
+ int CreateShareInfoTableVersion71(bool is_temporary);
// Create 'metas' or 'temp_metas' depending on value of is_temporary.
// Returns an sqlite return code, SQLITE_DONE on success.
int CreateMetasTable(bool is_temporary);
@@ -172,6 +174,7 @@ class DirectoryBackingStore {
bool MigrateVersion70To71();
bool MigrateVersion71To72();
bool MigrateVersion72To73();
+ bool MigrateVersion73To74();
// The handle to our sqlite on-disk store for initialization and loading, and
// for saving changes periodically via SaveChanges, respectively.
diff --git a/chrome/browser/sync/syncable/directory_backing_store_unittest.cc b/chrome/browser/sync/syncable/directory_backing_store_unittest.cc
index 214690c..d80200f 100644
--- a/chrome/browser/sync/syncable/directory_backing_store_unittest.cc
+++ b/chrome/browser/sync/syncable/directory_backing_store_unittest.cc
@@ -48,6 +48,7 @@ class MigrationTest : public testing::TestWithParam<int> {
void SetUpVersion70Database();
void SetUpVersion71Database();
void SetUpVersion72Database();
+ void SetUpVersion73Database();
void SetUpCurrentDatabaseAndCheckVersion() {
SetUpVersion70Database(); // Prepopulates data.
@@ -643,7 +644,7 @@ void MigrationTest::SetUpVersion72Database() {
ASSERT_TRUE(connection.BeginTransaction());
ASSERT_TRUE(connection.Execute(
"CREATE TABLE share_version (id VARCHAR(128) primary key, data INT);"
- "INSERT INTO 'share_version' VALUES('nick@chromium.org',71);"
+ "INSERT INTO 'share_version' VALUES('nick@chromium.org',72);"
"CREATE TABLE metas(metahandle bigint primary key ON CONFLICT FAIL,"
"base_version bigint default -1,server_version bigint default 0,"
"mtime bigint default 0,server_mtime bigint default 0,ctime bigint "
@@ -741,6 +742,111 @@ void MigrationTest::SetUpVersion72Database() {
ASSERT_TRUE(connection.CommitTransaction());
}
+void MigrationTest::SetUpVersion73Database() {
+ sql::Connection connection;
+ ASSERT_TRUE(connection.Open(GetDatabasePath()));
+ ASSERT_TRUE(connection.BeginTransaction());
+ ASSERT_TRUE(connection.Execute(
+ "CREATE TABLE share_version (id VARCHAR(128) primary key, data INT);"
+ "INSERT INTO 'share_version' VALUES('nick@chromium.org',73);"
+ "CREATE TABLE metas(metahandle bigint primary key ON CONFLICT FAIL,"
+ "base_version bigint default -1,server_version bigint default 0,"
+ "mtime bigint default 0,server_mtime bigint default 0,ctime bigint "
+ "default 0,server_ctime bigint default 0,server_position_in_parent "
+ "bigint default 0,local_external_id bigint default 0,id varchar(255) "
+ "default 'r',parent_id varchar(255) default 'r',server_parent_id "
+ "varchar(255) default 'r',prev_id varchar(255) default 'r',next_id "
+ "varchar(255) default 'r',is_unsynced bit default 0,"
+ "is_unapplied_update bit default 0,is_del bit default 0,is_dir bit "
+ "default 0,server_is_dir bit default 0,server_is_del bit default 0,"
+ "non_unique_name varchar,server_non_unique_name varchar(255),"
+ "unique_server_tag varchar,unique_client_tag varchar,specifics blob,"
+ "server_specifics blob);"
+ "INSERT INTO 'metas' VALUES(1,-1,0,129079956640320000,0,"
+ "129079956640320000,0,0,0,'r','r','r','r','r',0,0,0,1,0,0,NULL,NULL,"
+ "NULL,NULL,X'',X'');"
+ "INSERT INTO 'metas' VALUES(2,669,669,128976886618480000,"
+ "128976886618480000,128976886618480000,128976886618480000,-2097152,4,"
+ "'s_ID_2','s_ID_9','s_ID_9','s_ID_2','s_ID_2',0,0,1,0,0,1,"
+ "'Deleted Item','Deleted Item',NULL,NULL,X'C28810220A16687474703A2F2F"
+ "7777772E676F6F676C652E636F6D2F12084141534741534741',X'C28810260A1768"
+ "7474703A2F2F7777772E676F6F676C652E636F6D2F32120B41534144474144474144"
+ "47');"
+ "INSERT INTO 'metas' VALUES(4,681,681,129002163642690000,"
+ "129002163642690000,129002163642690000,129002163642690000,-3145728,3,"
+ "'s_ID_4','s_ID_9','s_ID_9','s_ID_4','s_ID_4',0,0,1,0,0,1,"
+ "'Welcome to Chromium','Welcome to Chromium',NULL,NULL,X'C28810350A31"
+ "687474703A2F2F7777772E676F6F676C652E636F6D2F6368726F6D652F696E746C2F"
+ "656E2F77656C636F6D652E68746D6C1200',X'C28810350A31687474703A2F2F7777"
+ "772E676F6F676C652E636F6D2F6368726F6D652F696E746C2F656E2F77656C636F6D"
+ "652E68746D6C1200');"
+ "INSERT INTO 'metas' VALUES(5,677,677,129001555500000000,"
+ "129001555500000000,129001555500000000,129001555500000000,1048576,7,"
+ "'s_ID_5','s_ID_9','s_ID_9','s_ID_5','s_ID_5',0,0,1,0,0,1,'Google',"
+ "'Google',NULL,NULL,X'C28810220A16687474703A2F2F7777772E676F6F676C652"
+ "E636F6D2F12084147415347415347',X'C28810220A16687474703A2F2F7777772E6"
+ "76F6F676C652E636F6D2F12084147464447415347');"
+ "INSERT INTO 'metas' VALUES(6,694,694,129053976170000000,"
+ "129053976170000000,129053976170000000,129053976170000000,-4194304,6,"
+ "'s_ID_6','s_ID_9','s_ID_9','r','r',0,0,0,1,1,0,'The Internet',"
+ "'The Internet',NULL,NULL,X'C2881000',X'C2881000');"
+ "INSERT INTO 'metas' VALUES(7,663,663,128976864758480000,"
+ "128976864758480000,128976864758480000,128976864758480000,1048576,0,"
+ "'s_ID_7','r','r','r','r',0,0,0,1,1,0,'Google Chrome','Google Chrome'"
+ ",'google_chrome',NULL,NULL,NULL);"
+ "INSERT INTO 'metas' VALUES(8,664,664,128976864758480000,"
+ "128976864758480000,128976864758480000,128976864758480000,1048576,0,"
+ "'s_ID_8','s_ID_7','s_ID_7','r','r',0,0,0,1,1,0,'Bookmarks',"
+ "'Bookmarks','google_chrome_bookmarks',NULL,X'C2881000',X'C2881000');"
+ "INSERT INTO 'metas' VALUES(9,665,665,128976864758480000,"
+ "128976864758480000,128976864758480000,128976864758480000,1048576,1,"
+ "'s_ID_9','s_ID_8','s_ID_8','r','s_ID_10',0,0,0,1,1,0,'Bookmark Bar',"
+ "'Bookmark Bar','bookmark_bar',NULL,X'C2881000',X'C2881000');"
+ "INSERT INTO 'metas' VALUES(10,666,666,128976864758480000,"
+ "128976864758480000,128976864758480000,128976864758480000,2097152,2,"
+ "'s_ID_10','s_ID_8','s_ID_8','s_ID_9','r',0,0,0,1,1,0,"
+ "'Other Bookmarks','Other Bookmarks','other_bookmarks',NULL,"
+ "X'C2881000',X'C2881000');"
+ "INSERT INTO 'metas' VALUES(11,683,683,129079956948440000,"
+ "129079956948440000,129079956948440000,129079956948440000,-1048576,8,"
+ "'s_ID_11','s_ID_6','s_ID_6','r','s_ID_13',0,0,0,0,0,0,"
+ "'Home (The Chromium Projects)','Home (The Chromium Projects)',NULL,"
+ "NULL,X'C28810220A18687474703A2F2F6465762E6368726F6D69756D2E6F72672F1"
+ "206414741545741',X'C28810290A1D687474703A2F2F6465762E6368726F6D69756"
+ "D2E6F72672F6F7468657212084146414756415346');"
+ "INSERT INTO 'metas' VALUES(12,685,685,129079957513650000,"
+ "129079957513650000,129079957513650000,129079957513650000,0,9,"
+ "'s_ID_12','s_ID_6','s_ID_6','s_ID_13','s_ID_14',0,0,0,1,1,0,"
+ "'Extra Bookmarks','Extra Bookmarks',NULL,NULL,X'C2881000',"
+ "X'C2881000');"
+ "INSERT INTO 'metas' VALUES(13,687,687,129079957985300000,"
+ "129079957985300000,129079957985300000,129079957985300000,-917504,10,"
+ "'s_ID_13','s_ID_6','s_ID_6','s_ID_11','s_ID_12',0,0,0,0,0,0,"
+ "'ICANN | Internet Corporation for Assigned Names and Numbers',"
+ "'ICANN | Internet Corporation for Assigned Names and Numbers',NULL,"
+ "NULL,X'C28810240A15687474703A2F2F7777772E6963616E6E2E636F6D2F120B504"
+ "E474158463041414646',X'C28810200A15687474703A2F2F7777772E6963616E6E2"
+ "E636F6D2F120744414146415346');"
+ "INSERT INTO 'metas' VALUES(14,692,692,129079958383000000,"
+ "129079958383000000,129079958383000000,129079958383000000,1048576,11,"
+ "'s_ID_14','s_ID_6','s_ID_6','s_ID_12','r',0,0,0,0,0,0,"
+ "'The WebKit Open Source Project','The WebKit Open Source Project',"
+ "NULL,NULL,""X'C288101A0A12687474703A2F2F7765626B69742E6F72672F120450"
+ "4E4758',X'C288101C0A13687474703A2F2F7765626B69742E6F72672F781205504E"
+ "473259');"
+ "CREATE TABLE models (model_id BLOB primary key, "
+ "last_download_timestamp INT, initial_sync_ended BOOLEAN default 0);"
+ "INSERT INTO 'models' VALUES(X'C2881000',694,1);"
+ "CREATE TABLE 'share_info' (id TEXT primary key, name TEXT, "
+ "store_birthday TEXT, db_create_version TEXT, db_create_time INT, "
+ "next_id INT default -2, cache_guid TEXT, "
+ "notification_state BLOB);"
+ "INSERT INTO 'share_info' VALUES('nick@chromium.org','nick@chromium.org',"
+ "'c27e9f59-08ca-46f8-b0cc-f16a2ed778bb','Unknown',1263522064,-65542,"
+ "'9010788312004066376x-6609234393368420856x',X'C2881000');"));
+ ASSERT_TRUE(connection.CommitTransaction());
+}
+
TEST_F(DirectoryBackingStoreTest, MigrateVersion67To68) {
SetUpVersion67Database();
@@ -937,6 +1043,56 @@ TEST_F(DirectoryBackingStoreTest, MigrateVersion72To73) {
connection.DoesColumnExist("share_info", "notification_state"));
}
+TEST_F(DirectoryBackingStoreTest, MigrateVersion73To74) {
+ SetUpVersion73Database();
+
+ {
+ sql::Connection connection;
+ ASSERT_TRUE(connection.Open(GetDatabasePath()));
+ ASSERT_FALSE(
+ connection.DoesColumnExist("share_info", "autofill_migration_state"));
+ ASSERT_FALSE(
+ connection.DoesColumnExist("share_info",
+ "bookmarks_added_during_autofill_migration"));
+ ASSERT_FALSE(
+ connection.DoesColumnExist("share_info", "autofill_migration_time"));
+ ASSERT_FALSE(
+ connection.DoesColumnExist("share_info",
+ "autofill_entries_added_during_migration"));
+
+ ASSERT_FALSE(
+ connection.DoesColumnExist("share_info",
+ "autofill_profiles_added_during_migration"));
+ }
+
+ scoped_ptr<DirectoryBackingStore> dbs(
+ new DirectoryBackingStore(GetUsername(), GetDatabasePath()));
+
+ dbs->BeginLoad();
+ ASSERT_FALSE(dbs->needs_column_refresh_);
+ ASSERT_TRUE(dbs->MigrateVersion73To74());
+ ASSERT_EQ(74, dbs->GetVersion());
+ dbs->EndLoad();
+ ASSERT_FALSE(dbs->needs_column_refresh_);
+
+ sql::Connection connection;
+ ASSERT_TRUE(connection.Open(GetDatabasePath()));
+ ASSERT_TRUE(
+ connection.DoesColumnExist("share_info", "autofill_migration_state"));
+ ASSERT_TRUE(
+ connection.DoesColumnExist("share_info",
+ "bookmarks_added_during_autofill_migration"));
+ ASSERT_TRUE(
+ connection.DoesColumnExist("share_info", "autofill_migration_time"));
+ ASSERT_TRUE(
+ connection.DoesColumnExist("share_info",
+ "autofill_entries_added_during_migration"));
+
+ ASSERT_TRUE(
+ connection.DoesColumnExist("share_info",
+ "autofill_profiles_added_during_migration"));
+}
+
TEST_P(MigrationTest, ToCurrentVersion) {
switch (GetParam()) {
case 67:
@@ -957,6 +1113,9 @@ TEST_P(MigrationTest, ToCurrentVersion) {
case 72:
SetUpVersion72Database();
break;
+ case 73:
+ SetUpVersion73Database();
+ break;
default:
// If you see this error, it may mean that you've increased the
// database version number but you haven't finished adding unit tests
@@ -1015,6 +1174,10 @@ TEST_P(MigrationTest, ToCurrentVersion) {
// Columns added in Version 73.
ASSERT_TRUE(connection.DoesColumnExist(
"share_info", "notification_state"));
+
+ // Columns added in version 74.
+ ASSERT_TRUE(connection.DoesColumnExist("share_info",
+ "autofill_migration_state"));
}
MetahandlesIndex index;
diff --git a/chrome/browser/sync/syncable/model_type.cc b/chrome/browser/sync/syncable/model_type.cc
index c95daa8..7bbb29a 100644
--- a/chrome/browser/sync/syncable/model_type.cc
+++ b/chrome/browser/sync/syncable/model_type.cc
@@ -153,6 +153,9 @@ std::string ModelTypeToString(ModelType model_type) {
return "Sessions";
case APPS:
return "Apps";
+ case AUTOFILL_PROFILE:
+ return "Autofill Profile";
+ break;
default:
NOTREACHED() << "No known extension for model type.";
return "INVALID";
@@ -269,7 +272,7 @@ const char kAppNotificationType[] = "APP";
const char kSessionNotificationType[] = "SESSION";
// TODO(lipalani) Bug 64111.
// talk to akalin to make sure this is what I understand this to be.
-const char kAutofillProfileType[] = "AUTOFILL_PROFILE";
+const char kAutofillProfileNotificationType[] = "AUTOFILL_PROFILE";
// TODO(akalin): This is a hack to make new sync data types work with
// server-issued notifications. Remove this when it's not needed
// anymore.
@@ -310,7 +313,7 @@ bool RealModelTypeToNotificationType(ModelType model_type,
*notification_type = kSessionNotificationType;
return true;
case AUTOFILL_PROFILE:
- *notification_type = kAutofillProfileType;
+ *notification_type = kAutofillProfileNotificationType;
return true;
// TODO(akalin): This is a hack to make new sync data types work with
// server-issued notifications. Remove this when it's not needed
@@ -357,6 +360,9 @@ bool NotificationTypeToRealModelType(const std::string& notification_type,
} else if (notification_type == kSessionNotificationType) {
*model_type = SESSIONS;
return true;
+ } else if (notification_type == kAutofillProfileNotificationType) {
+ *model_type = AUTOFILL_PROFILE;
+ return true;
} else if (notification_type == kUnknownNotificationType) {
// TODO(akalin): This is a hack to make new sync data types work with
// server-issued notifications. Remove this when it's not needed
diff --git a/chrome/browser/sync/syncable/model_type.h b/chrome/browser/sync/syncable/model_type.h
index 442e462..2760fbe 100644
--- a/chrome/browser/sync/syncable/model_type.h
+++ b/chrome/browser/sync/syncable/model_type.h
@@ -49,10 +49,11 @@ enum ModelType {
PREFERENCES,
// A password folder or password object.
PASSWORDS,
+ // An AutofillProfile Object
+ AUTOFILL_PROFILE,
// An autofill folder or an autofill object.
AUTOFILL,
- // An autofill Profile Object
- AUTOFILL_PROFILE,
+
// A themes folder or a themes object.
THEMES,
// A typed_url folder or a typed_url object.
diff --git a/chrome/browser/sync/syncable/syncable.cc b/chrome/browser/sync/syncable/syncable.cc
index 903b71d..2794efa 100644
--- a/chrome/browser/sync/syncable/syncable.cc
+++ b/chrome/browser/sync/syncable/syncable.cc
@@ -179,6 +179,7 @@ Directory::PersistedKernelInfo::PersistedKernelInfo()
for (int i = 0; i < MODEL_TYPE_COUNT; ++i) {
last_download_timestamp[i] = 0;
}
+ autofill_migration_state = NOT_DETERMINED;
}
Directory::PersistedKernelInfo::~PersistedKernelInfo() {}
@@ -720,6 +721,83 @@ bool Directory::initial_sync_ended_for_type(ModelType type) const {
return kernel_->persisted_info.initial_sync_ended[type];
}
+AutofillMigrationState Directory::get_autofill_migration_state() const {
+ ScopedKernelLock lock(this);
+ return kernel_->persisted_info.autofill_migration_state;
+}
+
+AutofillMigrationDebugInfo
+ Directory::get_autofill_migration_debug_info() const {
+ ScopedKernelLock lock(this);
+ return kernel_->persisted_info.autofill_migration_debug_info;
+}
+
+template <class T> void Directory::TestAndSet(
+ T* kernel_data, const T* data_to_set) {
+ if (*kernel_data != *data_to_set) {
+ *kernel_data = *data_to_set;
+ kernel_->info_status = KERNEL_SHARE_INFO_DIRTY;
+ }
+}
+
+void Directory::set_autofill_migration_state_debug_info(
+ AutofillMigrationDebugInfo::PropertyToSet property_to_set,
+ const AutofillMigrationDebugInfo& info) {
+
+ ScopedKernelLock lock(this);
+ switch (property_to_set) {
+ case AutofillMigrationDebugInfo::MIGRATION_TIME: {
+ syncable::AutofillMigrationDebugInfo&
+ debug_info = kernel_->persisted_info.autofill_migration_debug_info;
+ TestAndSet<int64>(
+ &debug_info.autofill_migration_time,
+ &info.autofill_migration_time);
+ break;
+ }
+ case AutofillMigrationDebugInfo::BOOKMARK_ADDED: {
+ AutofillMigrationDebugInfo& debug_info =
+ kernel_->persisted_info.autofill_migration_debug_info;
+ TestAndSet<int>(
+ &debug_info.bookmarks_added_during_migration,
+ &info.bookmarks_added_during_migration);
+ break;
+ }
+ case AutofillMigrationDebugInfo::ENTRIES_ADDED: {
+ AutofillMigrationDebugInfo& debug_info =
+ kernel_->persisted_info.autofill_migration_debug_info;
+ TestAndSet<int>(
+ &debug_info.autofill_entries_added_during_migration,
+ &info.autofill_entries_added_during_migration);
+ break;
+ }
+ case AutofillMigrationDebugInfo::PROFILES_ADDED: {
+ AutofillMigrationDebugInfo& debug_info =
+ kernel_->persisted_info.autofill_migration_debug_info;
+ TestAndSet<int>(
+ &debug_info.autofill_profile_added_during_migration,
+ &info.autofill_profile_added_during_migration);
+ break;
+ }
+ default:
+ NOTREACHED();
+ }
+}
+
+void Directory::set_autofill_migration_state(AutofillMigrationState state) {
+ ScopedKernelLock lock(this);
+ if (state == kernel_->persisted_info.autofill_migration_state) {
+ return;
+ }
+ kernel_->persisted_info.autofill_migration_state = state;
+ if (state == MIGRATED) {
+ syncable::AutofillMigrationDebugInfo& debug_info =
+ kernel_->persisted_info.autofill_migration_debug_info;
+ debug_info.autofill_migration_time =
+ base::Time::Now().ToInternalValue();
+ }
+ kernel_->info_status = KERNEL_SHARE_INFO_DIRTY;
+}
+
void Directory::set_initial_sync_ended_for_type(ModelType type, bool x) {
ScopedKernelLock lock(this);
set_initial_sync_ended_for_type_unsafe(type, x);
diff --git a/chrome/browser/sync/syncable/syncable.h b/chrome/browser/sync/syncable/syncable.h
index 19d98ee..cccf417 100644
--- a/chrome/browser/sync/syncable/syncable.h
+++ b/chrome/browser/sync/syncable/syncable.h
@@ -21,6 +21,7 @@
#include "base/lock.h"
#include "base/time.h"
#include "chrome/browser/sync/protocol/sync.pb.h"
+#include "chrome/browser/sync/syncable/autofill_migration.h"
#include "chrome/browser/sync/syncable/blob.h"
#include "chrome/browser/sync/syncable/dir_open_result.h"
#include "chrome/browser/sync/syncable/directory_event.h"
@@ -660,6 +661,8 @@ class Directory {
// Various data that the Directory::Kernel we are backing (persisting data
// for) needs saved across runs of the application.
struct PersistedKernelInfo {
+ AutofillMigrationDebugInfo autofill_migration_debug_info;
+
PersistedKernelInfo();
~PersistedKernelInfo();
@@ -674,6 +677,8 @@ class Directory {
int64 next_id;
// The persisted notification state.
std::string notification_state;
+
+ AutofillMigrationState autofill_migration_state;
};
// What the Directory needs on initialization to create itself and its Kernel.
@@ -754,6 +759,15 @@ class Directory {
bool initial_sync_ended_for_type(ModelType type) const;
void set_initial_sync_ended_for_type(ModelType type, bool value);
+ AutofillMigrationState get_autofill_migration_state() const;
+
+ AutofillMigrationDebugInfo get_autofill_migration_debug_info() const;
+
+ void set_autofill_migration_state(AutofillMigrationState state);
+
+ void set_autofill_migration_state_debug_info(
+ syncable::AutofillMigrationDebugInfo::PropertyToSet property_to_set,
+ const syncable::AutofillMigrationDebugInfo& info);
const std::string& name() const { return kernel_->name; }
@@ -804,6 +818,8 @@ class Directory {
DirOpenResult OpenImpl(const FilePath& file_path, const std::string& name);
+ template <class T> void TestAndSet(T* kernel_data, const T* data_to_set);
+
struct DirectoryEventTraits {
typedef DirectoryEvent EventType;
static inline bool IsChannelShutdownEvent(const DirectoryEvent& event) {