1 // Copyright 2014 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 #ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_AUTOFILL_PROFILE_SYNCABLE_SERVICE_H_ 5 #define COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_AUTOFILL_PROFILE_SYNCABLE_SERVICE_H_ 6 7 #if !defined(AUTOFILL_ENABLE_SYNC) 8 #error "This file should be built only when sync is enabled in Autofill" 9 #endif 10 11 #include <map> 12 #include <string> 13 #include <vector> 14 15 #include "base/basictypes.h" 16 #include "base/gtest_prod_util.h" 17 #include "base/memory/scoped_vector.h" 18 #include "base/scoped_observer.h" 19 #include "base/supports_user_data.h" 20 #include "base/synchronization/lock.h" 21 #include "base/threading/non_thread_safe.h" 22 #include "components/autofill/core/browser/field_types.h" 23 #include "components/autofill/core/browser/webdata/autofill_change.h" 24 #include "components/autofill/core/browser/webdata/autofill_entry.h" 25 #include "components/autofill/core/browser/webdata/autofill_webdata_backend.h" 26 #include "components/autofill/core/browser/webdata/autofill_webdata_service_observer.h" 27 #include "sync/api/sync_change.h" 28 #include "sync/api/sync_data.h" 29 #include "sync/api/sync_error.h" 30 #include "sync/api/syncable_service.h" 31 #include "sync/protocol/autofill_specifics.pb.h" 32 33 class ProfileSyncServiceAutofillTest; 34 class WebDataServiceBase; 35 36 namespace autofill { 37 38 class AutofillProfile; 39 class AutofillTable; 40 class AutofillWebDataService; 41 class FormGroup; 42 43 extern const char kAutofillProfileTag[]; 44 45 // The sync implementation for AutofillProfiles. 46 // MergeDataAndStartSyncing() called first, it does cloud->local and 47 // local->cloud syncs. Then for each cloud change we receive 48 // ProcessSyncChanges() and for each local change Observe() is called. 49 class AutofillProfileSyncableService 50 : public base::SupportsUserData::Data, 51 public syncer::SyncableService, 52 public AutofillWebDataServiceObserverOnDBThread, 53 public base::NonThreadSafe { 54 public: 55 virtual ~AutofillProfileSyncableService(); 56 57 // Creates a new AutofillProfileSyncableService and hangs it off of 58 // |web_data_service|, which takes ownership. This method should only be 59 // called on |web_data_service|'s DB thread. 60 static void CreateForWebDataServiceAndBackend( 61 AutofillWebDataService* web_data_service, 62 AutofillWebDataBackend* webdata_backend, 63 const std::string& app_locale); 64 65 // Retrieves the AutofillProfileSyncableService stored on |web_data_service|. 66 static AutofillProfileSyncableService* FromWebDataService( 67 AutofillWebDataService* web_data_service); 68 69 static syncer::ModelType model_type() { return syncer::AUTOFILL_PROFILE; } 70 71 // syncer::SyncableService implementation. 72 virtual syncer::SyncMergeResult MergeDataAndStartSyncing( 73 syncer::ModelType type, 74 const syncer::SyncDataList& initial_sync_data, 75 scoped_ptr<syncer::SyncChangeProcessor> sync_processor, 76 scoped_ptr<syncer::SyncErrorFactory> sync_error_factory) OVERRIDE; 77 virtual void StopSyncing(syncer::ModelType type) OVERRIDE; 78 virtual syncer::SyncDataList GetAllSyncData( 79 syncer::ModelType type) const OVERRIDE; 80 virtual syncer::SyncError ProcessSyncChanges( 81 const tracked_objects::Location& from_here, 82 const syncer::SyncChangeList& change_list) OVERRIDE; 83 84 // AutofillWebDataServiceObserverOnDBThread implementation. 85 virtual void AutofillProfileChanged( 86 const AutofillProfileChange& change) OVERRIDE; 87 88 // Provides a StartSyncFlare to the SyncableService. See 89 // sync_start_util for more. 90 void InjectStartSyncFlare( 91 const syncer::SyncableService::StartSyncFlare& flare); 92 93 protected: 94 AutofillProfileSyncableService(AutofillWebDataBackend* webdata_backend, 95 const std::string& app_locale); 96 97 // A convenience wrapper of a bunch of state we pass around while 98 // associating models, and send to the WebDatabase for persistence. 99 // We do this so we hold the write lock for only a small period. 100 // When storing the web db we are out of the write lock. 101 struct DataBundle; 102 103 // Helper to query WebDatabase for the current autofill state. 104 // Made virtual for ease of mocking in unit tests. 105 // Caller owns returned |profiles|. 106 virtual bool LoadAutofillData(std::vector<AutofillProfile*>* profiles); 107 108 // Helper to persist any changes that occured during model association to 109 // the WebDatabase. 110 // Made virtual for ease of mocking in unit tests. 111 virtual bool SaveChangesToWebData(const DataBundle& bundle); 112 113 // For unit tests. 114 AutofillProfileSyncableService(); 115 void set_sync_processor(syncer::SyncChangeProcessor* sync_processor) { 116 sync_processor_.reset(sync_processor); 117 } 118 119 // Creates syncer::SyncData based on supplied |profile|. 120 // Exposed for unit tests. 121 static syncer::SyncData CreateData(const AutofillProfile& profile); 122 123 private: 124 friend class ::ProfileSyncServiceAutofillTest; 125 FRIEND_TEST_ALL_PREFIXES(AutofillProfileSyncableServiceTest, 126 UpdateField); 127 FRIEND_TEST_ALL_PREFIXES(AutofillProfileSyncableServiceTest, 128 UpdateMultivaluedField); 129 FRIEND_TEST_ALL_PREFIXES(AutofillProfileSyncableServiceTest, 130 MergeProfile); 131 132 // The map of the guid to profiles owned by the |profiles_| vector. 133 typedef std::map<std::string, AutofillProfile*> GUIDToProfileMap; 134 135 // Helper function that overwrites |profile| with data from proto-buffer 136 // |specifics|. 137 static bool OverwriteProfileWithServerData( 138 const sync_pb::AutofillProfileSpecifics& specifics, 139 AutofillProfile* profile, 140 const std::string& app_locale); 141 142 // Writes |profile| data into supplied |profile_specifics|. 143 static void WriteAutofillProfile(const AutofillProfile& profile, 144 sync_pb::EntitySpecifics* profile_specifics); 145 146 // Creates |profile_map| from the supplied |profiles| vector. Necessary for 147 // fast processing of the changes. 148 void CreateGUIDToProfileMap(const std::vector<AutofillProfile*>& profiles, 149 GUIDToProfileMap* profile_map); 150 151 // Creates or updates a profile based on |data|. Looks at the guid of the data 152 // and if a profile with such guid is present in |profile_map| updates it. If 153 // not, searches through it for similar profiles. If similar profile is 154 // found substitutes it for the new one, otherwise adds a new profile. Returns 155 // iterator pointing to added/updated profile. 156 GUIDToProfileMap::iterator CreateOrUpdateProfile( 157 const syncer::SyncData& data, 158 GUIDToProfileMap* profile_map, 159 DataBundle* bundle); 160 161 // Syncs |change| to the cloud. 162 void ActOnChange(const AutofillProfileChange& change); 163 164 AutofillTable* GetAutofillTable() const; 165 166 // Helper to compare the local value and cloud value of a field, copy into 167 // the local value if they differ, and return whether the change happened. 168 static bool UpdateField(ServerFieldType field_type, 169 const std::string& new_value, 170 AutofillProfile* autofill_profile); 171 // The same as |UpdateField|, but for multi-valued fields. 172 static bool UpdateMultivaluedField( 173 ServerFieldType field_type, 174 const ::google::protobuf::RepeatedPtrField<std::string>& new_value, 175 AutofillProfile* autofill_profile); 176 177 // Calls merge_into->OverwriteWithOrAddTo() and then checks if the 178 // |merge_into| has extra data. Returns |true| if |merge_into| posseses some 179 // multi-valued field values that are not in |merge_from|. 180 // TODO(isherman): Seems like this should return |true| if |merge_into| was 181 // modified at all: http://crbug.com/248440 182 static bool MergeProfile(const AutofillProfile& merge_from, 183 AutofillProfile* merge_into, 184 const std::string& app_locale); 185 186 AutofillWebDataBackend* webdata_backend_; // WEAK 187 std::string app_locale_; 188 ScopedObserver<AutofillWebDataBackend, 189 AutofillProfileSyncableService> scoped_observer_; 190 191 // Cached Autofill profiles. *Warning* deleted profiles are still in the 192 // vector - use the |profiles_map_| to iterate through actual profiles. 193 ScopedVector<AutofillProfile> profiles_; 194 GUIDToProfileMap profiles_map_; 195 196 scoped_ptr<syncer::SyncChangeProcessor> sync_processor_; 197 198 scoped_ptr<syncer::SyncErrorFactory> sync_error_factory_; 199 200 syncer::SyncableService::StartSyncFlare flare_; 201 202 DISALLOW_COPY_AND_ASSIGN(AutofillProfileSyncableService); 203 }; 204 205 // This object is used in unit tests as well, so it defined here. 206 struct AutofillProfileSyncableService::DataBundle { 207 DataBundle(); 208 ~DataBundle(); 209 210 std::vector<std::string> profiles_to_delete; 211 std::vector<AutofillProfile*> profiles_to_update; 212 std::vector<AutofillProfile*> profiles_to_add; 213 214 // When we go through sync we find profiles that are similar but unmatched. 215 // Merge such profiles. 216 GUIDToProfileMap candidates_to_merge; 217 // Profiles that have multi-valued fields that are not in sync. 218 std::vector<AutofillProfile*> profiles_to_sync_back; 219 }; 220 221 } // namespace autofill 222 223 #endif // COMPONENTS_AUTOFILL_CORE_BROWSER_WEBDATA_AUTOFILL_PROFILE_SYNCABLE_SERVICE_H_ 224