Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(25)

Side by Side Diff: chrome/browser/sync/glue/autofill_profile_change_processor.cc

Issue 7819002: Migrate AutofillProfile sync to new API. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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 #include "chrome/browser/sync/glue/autofill_profile_change_processor.h"
6
7 #include <string>
8 #include <vector>
9
10 #include "base/string_util.h"
11 #include "base/tracked.h"
12 #include "base/utf_string_conversions.h"
13 #include "chrome/browser/autofill/autofill_profile.h"
14 #include "chrome/browser/autofill/personal_data_manager.h"
15 #include "chrome/browser/sync/glue/autofill_profile_model_associator.h"
16 #include "chrome/browser/sync/glue/change_processor.h"
17 #include "chrome/browser/sync/glue/do_optimistic_refresh_task.h"
18 #include "chrome/browser/sync/internal_api/read_node.h"
19 #include "chrome/browser/sync/internal_api/sync_manager.h"
20 #include "chrome/browser/sync/internal_api/write_node.h"
21 #include "chrome/browser/sync/internal_api/write_transaction.h"
22 #include "chrome/browser/sync/unrecoverable_error_handler.h"
23 #include "chrome/browser/webdata/autofill_change.h"
24 #include "chrome/browser/webdata/autofill_table.h"
25 #include "chrome/browser/webdata/web_database.h"
26 #include "chrome/common/chrome_notification_types.h"
27 #include "chrome/common/guid.h"
28 #include "content/common/notification_registrar.h"
29 #include "content/common/notification_service.h"
30
31 namespace browser_sync {
32
33 AutofillProfileChangeProcessor::AutofillProfileChangeProcessor(
34 AutofillProfileModelAssociator *model_associator,
35 WebDatabase* web_database,
36 PersonalDataManager* personal_data_manager,
37 UnrecoverableErrorHandler* error_handler)
38 : ChangeProcessor(error_handler),
39 model_associator_(model_associator),
40 observing_(false),
41 web_database_(web_database),
42 personal_data_(personal_data_manager) {
43 DCHECK(model_associator);
44 DCHECK(web_database);
45 DCHECK(error_handler);
46 DCHECK(personal_data_manager);
47 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
48
49 StartObserving();
50 }
51
52 AutofillProfileChangeProcessor::~AutofillProfileChangeProcessor() {}
53
54 void AutofillProfileChangeProcessor::ApplyChangesFromSyncModel(
55 const sync_api::BaseTransaction *write_trans,
56 const sync_api::SyncManager::ChangeRecord* changes,
57 int change_count) {
58
59 ScopedStopObserving<AutofillProfileChangeProcessor> observer(this);
60
61 sync_api::ReadNode autofill_profile_root(write_trans);
62 if (!autofill_profile_root.InitByTagLookup(kAutofillProfileTag)) {
63 error_handler()->OnUnrecoverableError(FROM_HERE,
64 "Autofill Profile root node lookup failed");
65 return;
66 }
67
68 for (int i = 0; i < change_count; ++i) {
69 if (sync_api::SyncManager::ChangeRecord::ACTION_DELETE ==
70 changes[i].action) {
71 DCHECK(changes[i].specifics.HasExtension(
72 sync_pb::autofill_profile));
73
74 const sync_pb::AutofillProfileSpecifics& specifics =
75 changes[i].specifics.GetExtension(sync_pb::autofill_profile);
76
77 autofill_changes_.push_back(AutofillProfileChangeRecord(changes[i].action,
78 changes[i].id,
79 specifics));
80 continue;
81 }
82
83 // If it is not a delete.
84 sync_api::ReadNode sync_node(write_trans);
85 if (!sync_node.InitByIdLookup(changes[i].id)) {
86 LOG(ERROR) << "Could not find the id in sync db " << changes[i].id;
87 continue;
88 }
89
90 const sync_pb::AutofillProfileSpecifics& autofill(
91 sync_node.GetAutofillProfileSpecifics());
92
93 autofill_changes_.push_back(AutofillProfileChangeRecord(changes[i].action,
94 changes[i].id,
95 autofill));
96 }
97 }
98
99 void AutofillProfileChangeProcessor::Observe(int type,
100 const NotificationSource& source,
101 const NotificationDetails& details) {
102 DCHECK_EQ(type, chrome::NOTIFICATION_AUTOFILL_PROFILE_CHANGED);
103 WebDataService* wds = Source<WebDataService>(source).ptr();
104
105 if (!wds || wds->GetDatabase() != web_database_)
106 return;
107
108 sync_api::WriteTransaction trans(FROM_HERE, share_handle());
109 sync_api::ReadNode autofill_root(&trans);
110 if (!autofill_root.InitByTagLookup(kAutofillProfileTag)) {
111 error_handler()->OnUnrecoverableError(FROM_HERE,
112 "Server did not create a tolp level node");
113 return;
114 }
115
116 AutofillProfileChange* change = Details<AutofillProfileChange>(details).ptr();
117
118 ActOnChange(change, &trans, autofill_root);
119 }
120
121 void AutofillProfileChangeProcessor::ActOnChange(
122 AutofillProfileChange* change,
123 sync_api::WriteTransaction* trans,
124 sync_api::ReadNode& autofill_root) {
125 DCHECK(change->type() == AutofillProfileChange::REMOVE || change->profile());
126 switch (change->type()) {
127 case AutofillProfileChange::ADD: {
128 AddAutofillProfileSyncNode(trans, autofill_root, *(change->profile()));
129 break;
130 }
131 case AutofillProfileChange::UPDATE: {
132 int64 sync_id = model_associator_->GetSyncIdFromChromeId(change->key());
133 if (sync_api::kInvalidId == sync_id) {
134 LOG(ERROR) << "Sync id is not found for " << change->key();
135 break;
136 }
137 sync_api::WriteNode node(trans);
138 if (!node.InitByIdLookup(sync_id)) {
139 LOG(ERROR) << "Could not find sync node for id " << sync_id;
140 break;
141 }
142
143 WriteAutofillProfile(*(change->profile()), &node);
144 break;
145 }
146 case AutofillProfileChange::REMOVE: {
147 int64 sync_id = model_associator_->GetSyncIdFromChromeId(change->key());
148 if (sync_api::kInvalidId == sync_id) {
149 LOG(ERROR) << "Sync id is not found for " << change->key();
150 break;
151 }
152 sync_api::WriteNode node(trans);
153 if (!node.InitByIdLookup(sync_id)) {
154 LOG(ERROR) << "Could not find sync node for id " << sync_id;
155 break;
156 }
157 node.Remove();
158 model_associator_->Disassociate(sync_id);
159 break;
160 }
161 default:
162 NOTREACHED();
163 }
164 }
165
166 void AutofillProfileChangeProcessor::CommitChangesFromSyncModel() {
167 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
168
169 if (!running())
170 return;
171
172 ScopedStopObserving<AutofillProfileChangeProcessor> observer(this);
173
174 for (unsigned int i = 0;i < autofill_changes_.size(); ++i) {
175 if (sync_api::SyncManager::ChangeRecord::ACTION_DELETE ==
176 autofill_changes_[i].action_) {
177 if (!web_database_->GetAutofillTable()->RemoveAutofillProfile(
178 autofill_changes_[i].profile_specifics_.guid())) {
179 LOG(ERROR) << "could not delete the profile " <<
180 autofill_changes_[i].profile_specifics_.guid();
181 continue;
182 }
183 continue;
184 }
185
186 // Now for updates and adds.
187 ApplyAutofillProfileChange(autofill_changes_[i].action_,
188 autofill_changes_[i].profile_specifics_,
189 autofill_changes_[i].id_);
190 }
191
192 autofill_changes_.clear();
193
194 PostOptimisticRefreshTask();
195 }
196
197 void AutofillProfileChangeProcessor::PostOptimisticRefreshTask() {
198 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
199 new DoOptimisticRefreshForAutofill(
200 personal_data_));
201 }
202
203 void AutofillProfileChangeProcessor::ApplyAutofillProfileChange(
204 sync_api::SyncManager::ChangeRecord::Action action,
205 const sync_pb::AutofillProfileSpecifics& profile_specifics,
206 int64 sync_id) {
207
208 DCHECK_NE(sync_api::SyncManager::ChangeRecord::ACTION_DELETE, action);
209 switch (action) {
210 case sync_api::SyncManager::ChangeRecord::ACTION_ADD: {
211 if (guid::IsValidGUID(profile_specifics.guid()) == false) {
212 NOTREACHED() << "Guid from the server is invalid " <<
213 profile_specifics.guid();
214 return;
215 }
216 AutofillProfile p(profile_specifics.guid());
217 AutofillProfileModelAssociator::OverwriteProfileWithServerData(&p,
218 profile_specifics);
219 if (!web_database_->GetAutofillTable()->AddAutofillProfile(p)) {
220 LOG(ERROR) << "could not add autofill profile for guid " << p.guid();
221 break;
222 }
223
224 // Now that the node has been succesfully created we can associate it.
225 std::string guid = p.guid();
226 model_associator_->Associate(&guid, sync_id);
227 break;
228 }
229 case sync_api::SyncManager::ChangeRecord::ACTION_UPDATE: {
230 AutofillProfile *p;
231 if (!web_database_->GetAutofillTable()->GetAutofillProfile(
232 profile_specifics.guid(), &p)) {
233 LOG(ERROR) << "Could not find the autofill profile to update for " <<
234 profile_specifics.guid();
235 break;
236 }
237 scoped_ptr<AutofillProfile> autofill_pointer(p);
238 AutofillProfileModelAssociator::OverwriteProfileWithServerData(
239 autofill_pointer.get(),
240 profile_specifics);
241
242 if (!web_database_->GetAutofillTable()->UpdateAutofillProfile(
243 *(autofill_pointer.get()))) {
244 LOG(ERROR) << "Could not update autofill profile for " <<
245 profile_specifics.guid();
246 break;
247 }
248 break;
249 }
250 default: {
251 NOTREACHED();
252 break;
253 }
254 }
255 }
256
257 void AutofillProfileChangeProcessor::RemoveSyncNode(const std::string& guid,
258 sync_api::WriteTransaction* trans) {
259 sync_api::WriteNode node(trans);
260 int64 sync_id = model_associator_->GetSyncIdFromChromeId(guid);
261 if (sync_api::kInvalidId == sync_id) {
262 LOG(ERROR) << "Could not find the node in associator " << guid;
263 return;
264 }
265
266 if (!node.InitByIdLookup(sync_id)) {
267 LOG(ERROR) << "Could not find the sync node for " << guid;
268 return;
269 }
270
271 model_associator_->Disassociate(sync_id);
272 node.Remove();
273 }
274
275 void AutofillProfileChangeProcessor::AddAutofillProfileSyncNode(
276 sync_api::WriteTransaction* trans,
277 sync_api::BaseNode& autofill_profile_root,
278 const AutofillProfile& profile) {
279
280 std::string guid = profile.guid();
281
282 if (guid::IsValidGUID(guid) == false) {
283 DCHECK(false) << "Guid set on the profile is invalid " << guid;
284 return;
285 }
286
287 sync_api::WriteNode node(trans);
288 if (!node.InitUniqueByCreation(syncable::AUTOFILL_PROFILE,
289 autofill_profile_root,
290 profile.guid())) {
291 LOG(ERROR) << "could not create a sync node ";
292 return;
293 }
294
295 node.SetTitle(UTF8ToWide(profile.guid()));
296
297 WriteAutofillProfile(profile, &node);
298
299 model_associator_->Associate(&guid, node.GetId());
300 }
301
302 void AutofillProfileChangeProcessor::StartObserving() {
303 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
304 notification_registrar_.Add(this,
305 chrome::NOTIFICATION_AUTOFILL_PROFILE_CHANGED,
306 NotificationService::AllSources());
307 }
308
309 void AutofillProfileChangeProcessor::StopObserving() {
310 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
311 notification_registrar_.RemoveAll();
312 }
313
314 void AutofillProfileChangeProcessor::WriteAutofillProfile(
315 const AutofillProfile& profile,
316 sync_api::WriteNode* node) {
317 sync_pb::AutofillProfileSpecifics specifics;
318
319 // This would get compiled out in official builds. The caller is expected to
320 // pass in a valid profile object with valid guid.(i.e., the caller might
321 // have to a DCHECK and log before calling. Having to check in 2 places is
322 // not optimal.)
323 DCHECK(guid::IsValidGUID(profile.guid()));
324
325 specifics.set_guid(profile.guid());
326 specifics.set_name_first(UTF16ToUTF8(profile.GetInfo(NAME_FIRST)));
327 specifics.set_name_middle(UTF16ToUTF8(profile.GetInfo(NAME_MIDDLE)));
328 specifics.set_name_last(UTF16ToUTF8(profile.GetInfo(NAME_LAST)));
329 specifics.set_address_home_line1(
330 UTF16ToUTF8(profile.GetInfo(ADDRESS_HOME_LINE1)));
331 specifics.set_address_home_line2(
332 UTF16ToUTF8(profile.GetInfo(ADDRESS_HOME_LINE2)));
333 specifics.set_address_home_city(UTF16ToUTF8(profile.GetInfo(
334 ADDRESS_HOME_CITY)));
335 specifics.set_address_home_state(UTF16ToUTF8(profile.GetInfo(
336 ADDRESS_HOME_STATE)));
337 specifics.set_address_home_country(UTF16ToUTF8(profile.GetInfo(
338 ADDRESS_HOME_COUNTRY)));
339 specifics.set_address_home_zip(UTF16ToUTF8(profile.GetInfo(
340 ADDRESS_HOME_ZIP)));
341 specifics.set_email_address(UTF16ToUTF8(profile.GetInfo(EMAIL_ADDRESS)));
342 specifics.set_company_name(UTF16ToUTF8(profile.GetInfo(COMPANY_NAME)));
343 specifics.set_phone_fax_whole_number(UTF16ToUTF8(profile.GetInfo(
344 PHONE_FAX_WHOLE_NUMBER)));
345 specifics.set_phone_home_whole_number(UTF16ToUTF8(profile.GetInfo(
346 PHONE_HOME_WHOLE_NUMBER)));
347 node->SetAutofillProfileSpecifics(specifics);
348 }
349
350 } // namespace browser_sync
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698