1// Copyright (c) 2011 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
5#ifndef CHROME_BROWSER_SYNC_GLUE_AUTOFILL_PROFILE_MODEL_ASSOCIATOR_H_
6#define CHROME_BROWSER_SYNC_GLUE_AUTOFILL_PROFILE_MODEL_ASSOCIATOR_H_
7#pragma once
8
9#include <map>
10#include <set>
11#include <string>
12#include <vector>
13
14#include "base/basictypes.h"
15#include "base/memory/ref_counted.h"
16#include "base/synchronization/lock.h"
17#include "chrome/browser/autofill/personal_data_manager.h"
18#include "chrome/browser/sync/engine/syncapi.h"
19#include "chrome/browser/sync/glue/model_associator.h"
20#include "chrome/browser/sync/protocol/autofill_specifics.pb.h"
21#include "chrome/browser/webdata/autofill_entry.h"
22
23class AutofillProfile;
24
25class ProfileSyncService;
26class WebDatabase;
27
28namespace sync_api {
29class WriteTransaction;
30}
31
32namespace browser_sync {
33
34extern const char kAutofillProfileTag[];
35
36class AutofillChangeProcessor;
37class UnrecoverableErrorHandler;
38
39// Contains all model association related logic:
40// * Algorithm to associate autofill model and sync model.
41// We do not check if we have local data before this run; we always
42// merge and sync.
43class AutofillProfileModelAssociator
44    : public PerDataTypeAssociatorInterface<std::string, std::string> {
45 public:
46  AutofillProfileModelAssociator(ProfileSyncService* sync_service,
47                                 WebDatabase* web_database,
48                                 PersonalDataManager* data_manager);
49  virtual ~AutofillProfileModelAssociator();
50
51  // A convenience wrapper of a bunch of state we pass around while
52  // associating models, and send to the WebDatabase for persistence.
53  // We do this so we hold the write lock for only a small period.
54  // When storing the web db we are out of the write lock.
55  struct DataBundle;
56
57  static syncable::ModelType model_type() { return syncable::AUTOFILL_PROFILE; }
58
59  // PerDataTypeAssociatorInterface implementation.
60  //
61  // Iterates through the sync model looking for matched pairs of items.
62  virtual bool AssociateModels();
63
64  // Clears all associations.
65  virtual bool DisassociateModels();
66
67  // TODO(lipalani) Bug 64111.
68  // The has_nodes out param is true if the sync model has nodes other
69  // than the permanent tagged nodes.
70  virtual bool SyncModelHasUserCreatedNodes(bool* has_nodes);
71
72  // See ModelAssociator interface.
73  virtual void AbortAssociation();
74
75  // See ModelAssociator interface.
76  virtual bool CryptoReadyIfNecessary();
77
78  virtual const std::string* GetChromeNodeFromSyncId(int64 sync_id);
79
80  virtual bool InitSyncNodeFromChromeId(const std::string& node_id,
81                                        sync_api::BaseNode* sync_node);
82
83  // Returns the sync id for the given autofill name, or sync_api::kInvalidId
84  // if the autofill name is not associated to any sync id.
85  virtual int64 GetSyncIdFromChromeId(const std::string& node_id);
86
87  // Associates the given autofill name with the given sync id.
88  virtual void Associate(const std::string* node, int64 sync_id);
89
90  // Remove the association that corresponds to the given sync id.
91  virtual void Disassociate(int64 sync_id);
92
93  // TODO(lipalani) Bug 64111. Returns whether a node with the
94  // given permanent tag was found and update
95  // |sync_id| with that node's id. No current use. To Implement
96  // only for completeness.
97  virtual bool GetSyncIdForTaggedNode(const std::string& tag, int64* sync_id);
98
99  static bool OverwriteProfileWithServerData(
100      AutofillProfile* merge_into,
101      const sync_pb::AutofillProfileSpecifics& specifics);
102
103 protected:
104  AutofillProfileModelAssociator();
105  bool TraverseAndAssociateChromeAutofillProfiles(
106      sync_api::WriteTransaction* write_trans,
107      const sync_api::ReadNode& autofill_root,
108      const std::vector<AutofillProfile*>& all_profiles_from_db,
109      std::set<std::string>* current_profiles,
110      std::vector<AutofillProfile*>* updated_profiles,
111      std::vector<AutofillProfile*>* new_profiles,
112      std::vector<std::string>* profiles_to_delete);
113
114  // Helper to insert an AutofillProfile into the WebDatabase (e.g. in response
115  // to encountering a sync node that doesn't exist yet locally).
116  virtual void AddNativeProfileIfNeeded(
117      const sync_pb::AutofillProfileSpecifics& profile,
118      DataBundle* bundle,
119      const sync_api::ReadNode& node);
120
121  // Helper to insert a sync node for the given AutofillProfile (e.g. in
122  // response to encountering a native profile that doesn't exist yet in the
123  // cloud).
124  virtual bool MakeNewAutofillProfileSyncNodeIfNeeded(
125      sync_api::WriteTransaction* trans,
126      const sync_api::BaseNode& autofill_root,
127      const AutofillProfile& profile,
128      std::vector<AutofillProfile*>* new_profiles,
129      std::set<std::string>* current_profiles,
130      std::vector<std::string>* profiles_to_delete);
131
132  // Once the above traversals are complete, we traverse the sync model to
133  // associate all remaining nodes.
134  bool TraverseAndAssociateAllSyncNodes(
135      sync_api::WriteTransaction* write_trans,
136      const sync_api::ReadNode& autofill_root,
137      DataBundle* bundle);
138
139 private:
140  typedef std::map<std::string, int64> AutofillToSyncIdMap;
141  typedef std::map<int64, std::string> SyncIdToAutofillMap;
142
143  // A convenience wrapper of a bunch of state we pass around while associating
144  // models, and send to the WebDatabase for persistence.
145  // struct DataBundle;
146
147  // Helper to query WebDatabase for the current autofill state.
148  bool LoadAutofillData(std::vector<AutofillProfile*>* profiles);
149
150  static bool MergeField(FormGroup* f,
151                         AutofillFieldType t,
152                         const std::string& specifics_field);
153
154  // Helper to persist any changes that occured during model association to
155  // the WebDatabase.
156  bool SaveChangesToWebData(const DataBundle& bundle);
157
158  // Called at various points in model association to determine if the
159  // user requested an abort.
160  bool IsAbortPending();
161
162  int64 FindSyncNodeWithProfile(sync_api::WriteTransaction* trans,
163      const sync_api::BaseNode& autofill_root,
164      const AutofillProfile& profile,
165      std::set<std::string>* current_profiles);
166
167  ProfileSyncService* sync_service_;
168  WebDatabase* web_database_;
169  PersonalDataManager* personal_data_;
170  int64 autofill_node_id_;
171
172  AutofillToSyncIdMap id_map_;
173  SyncIdToAutofillMap id_map_inverse_;
174
175  // Abort association pending flag and lock.  If this is set to true
176  // (via the AbortAssociation method), return from the
177  // AssociateModels method as soon as possible.
178  base::Lock abort_association_pending_lock_;
179  bool abort_association_pending_;
180
181  int number_of_profiles_created_;
182
183  DISALLOW_COPY_AND_ASSIGN(AutofillProfileModelAssociator);
184};
185
186struct AutofillProfileModelAssociator::DataBundle {
187  DataBundle();
188  ~DataBundle();
189
190  std::set<std::string> current_profiles;
191  std::vector<std::string> profiles_to_delete;
192  std::vector<AutofillProfile*> updated_profiles;
193  std::vector<AutofillProfile*> new_profiles;  // We own these pointers.
194};
195
196}  // namespace browser_sync
197
198#endif  // CHROME_BROWSER_SYNC_GLUE_AUTOFILL_PROFILE_MODEL_ASSOCIATOR_H_
199
200