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
33class ProfileSyncServiceAutofillTest;
34class WebDataServiceBase;
35
36namespace autofill {
37
38class AutofillProfile;
39class AutofillTable;
40class AutofillWebDataService;
41class FormGroup;
42
43extern 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.
49class 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.
206struct 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