diff options
author | lipalani@chromium.org <lipalani@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-12-16 07:15:53 +0000 |
---|---|---|
committer | lipalani@chromium.org <lipalani@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-12-16 07:15:53 +0000 |
commit | a0bc3146a8657b2d47d4d883ac16946b0489a8d0 (patch) | |
tree | b4c926fbffd5f12130ec82e7e2d2e50760e286d0 /chrome/browser/sync/glue | |
parent | 351e326d2e335db14f44edfc7bc69aa37133dd92 (diff) | |
download | chromium_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/glue')
21 files changed, 964 insertions, 142 deletions
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. |