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