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

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

Issue 5159001: Rest of the autofill work. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Couple of lint errors sneaked into my previous patch. This is clean of lint errors. Created 10 years 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) 2010 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/utf_string_conversions.h"
12 #include "chrome/browser/autofill/autofill_profile.h"
13 #include "chrome/browser/autofill/personal_data_manager.h"
14 #include "chrome/browser/sync/engine/syncapi.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/unrecoverable_error_handler.h"
19 #include "chrome/browser/webdata/autofill_change.h"
20 #include "chrome/browser/webdata/web_database.h"
21 #include "chrome/common/notification_observer.h"
22 #include "chrome/common/notification_registrar.h"
23 #include "chrome/common/notification_service.h"
24 #include "chrome/common/notification_type.h"
25
26 namespace browser_sync {
27
28 AutofillProfileChangeProcessor::AutofillProfileChangeProcessor(
29 AutofillProfileModelAssociator *model_associator,
30 WebDatabase* web_database,
31 PersonalDataManager* personal_data_manager,
32 UnrecoverableErrorHandler* error_handler)
33 : ChangeProcessor(error_handler),
34 model_associator_(model_associator),
35 web_database_(web_database),
36 personal_data_(personal_data_manager),
37 observing_(false) {
38 DCHECK(model_associator);
39 DCHECK(web_database);
40 DCHECK(error_handler);
41 DCHECK(personal_data_manager);
42 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
43
44 StartObserving();
45 }
46
47 AutofillProfileChangeProcessor::ScopedObserver::ScopedObserver(
48 AutofillProfileChangeProcessor* processor) {
49 processor_ = processor;
50 processor_->StopObserving();
51 }
52
53 AutofillProfileChangeProcessor::ScopedObserver::~ScopedObserver() {
54 processor_->StartObserving();
55 }
56
57 void AutofillProfileChangeProcessor::ApplyChangesFromSyncModel(
58 const sync_api::BaseTransaction *write_trans,
59 const sync_api::SyncManager::ChangeRecord* changes,
60 int change_count) {
61
62 ScopedObserver observer(this);
tim (not reviewing) 2010/12/13 19:24:33 this should be ScopedStopObserving or something to
lipalani 2010/12/14 21:05:57 Done.
63
64 sync_api::ReadNode autofill_profile_root(write_trans);
65 if (!autofill_profile_root.InitByTagLookup(kAutofillProfileTag)) {
66 error_handler()->OnUnrecoverableError(FROM_HERE,
67 "Autofill Profile root node lookup failed");
68 return;
69 }
70
71 for (int i = 0;i < change_count; ++i) {
tim (not reviewing) 2010/12/13 19:24:33 space after 0;
lipalani 2010/12/14 21:05:57 Done.
72 if (sync_api::SyncManager::ChangeRecord::ACTION_DELETE ==
73 changes[i].action) {
74 DCHECK(changes[i].specifics.HasExtension(
75 sync_pb::autofill_profile));
76
77 const sync_pb::AutofillProfileSpecifics& specifics =
78 changes[i].specifics.GetExtension(sync_pb::autofill_profile);
tim (not reviewing) 2010/12/13 19:24:33 indent 4 spaces.
lipalani 2010/12/14 21:05:57 Done.
79
80 autofill_changes_.push_back(AutofillProfileChangeRecord(changes[i].action,
81 changes[i].id,
82 specifics));
83 continue;
84 }
85
86 // If it is not a delete.
87 sync_api::ReadNode sync_node(write_trans);
88 if (!sync_node.InitByIdLookup(changes[i].id)) {
89 LOG(ERROR) << "Could not find the id in sync db " << changes[i].id;
90 continue;
91 }
92
93 const sync_pb::AutofillProfileSpecifics& autofill(
94 sync_node.GetAutofillProfileSpecifics());
95
96 autofill_changes_.push_back(AutofillProfileChangeRecord(changes[i].action,
97 changes[i].id,
98 autofill));
99 }
100 }
101
102 void AutofillProfileChangeProcessor::Observe(NotificationType type,
103 const NotificationSource& source,
104 const NotificationDetails& details) {
105 DCHECK_EQ(type.value, NotificationType::AUTOFILL_PROFILE_CHANGED_GUID);
106 WebDataService* wds = Source<WebDataService>(source).ptr();
107
108 if (!wds || wds->GetDatabase() != web_database_)
109 return;
110
111 sync_api::WriteTransaction trans(share_handle());
112 sync_api::ReadNode autofill_root(&trans);
113 if (!autofill_root.InitByTagLookup(kAutofillProfileTag)) {
114 error_handler()->OnUnrecoverableError(FROM_HERE,
115 "Server did not create a tolp level node");
116 return;
117 }
118
119 AutofillProfileChangeGUID* change =
120 Details<AutofillProfileChangeGUID>(details).ptr();
121
122 ActOnChange(change, &trans, autofill_root);
123 }
124
125 void AutofillProfileChangeProcessor::ActOnChange(
126 AutofillProfileChangeGUID* change,
127 sync_api::WriteTransaction* trans,
128 sync_api::ReadNode& autofill_root) {
129 DCHECK(change->type() == AutofillProfileChangeGUID::REMOVE ||
130 change->profile());
131 switch (change->type()) {
132 case AutofillProfileChangeGUID::ADD: {
133 AddAutofillProfileSyncNode(trans, autofill_root, *(change->profile()));
134 break;
135 }
136 case AutofillProfileChangeGUID::UPDATE: {
137 int64 sync_id = model_associator_->GetSyncIdFromChromeId(change->key());
138 if (sync_api::kInvalidId == sync_id) {
139 LOG(ERROR) << "Sync id is not found for " << change->key();
140 break;
141 }
142 sync_api::WriteNode node(trans);
143 if (!node.InitByIdLookup(sync_id)) {
144 LOG(ERROR) << "Could not find sync node for id " << sync_id;
145 break;
146 }
147
148 WriteAutofillProfile(*(change->profile()), &node);
149 break;
150 }
151 case AutofillProfileChangeGUID::REMOVE: {
152 int64 sync_id = model_associator_->GetSyncIdFromChromeId(change->key());
153 if (sync_api::kInvalidId == sync_id) {
154 LOG(ERROR) << "Sync id is not found for " << change->key();
155 break;
156 }
157 sync_api::WriteNode node(trans);
158 if (!node.InitByIdLookup(sync_id)) {
159 LOG(ERROR) << "Could not find sync node for id " << sync_id;
160 break;
161 }
162 node.Remove();
163 model_associator_->Disassociate(sync_id);
164 break;
165 }
166 default:
167 NOTREACHED();
168 }
169 }
170
171 void AutofillProfileChangeProcessor::CommitChangesFromSyncModel() {
172 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
173
174 if (!running())
175 return;
176
177 ScopedObserver observer(this);
178
179 for (unsigned int i = 0;i < autofill_changes_.size(); ++i) {
180 if (sync_api::SyncManager::ChangeRecord::ACTION_DELETE ==
181 autofill_changes_[i].action_) {
tim (not reviewing) 2010/12/13 19:24:33 needs 4 space indent.
lipalani 2010/12/14 21:05:57 Done.
182 if (!web_database_->RemoveAutoFillProfile(
183 autofill_changes_[i].profile_specifics_.guid())) {
184 LOG(ERROR) << "could not delete the profile " <<
185 autofill_changes_[i].profile_specifics_.guid();
186 continue;
187 }
188 continue;
189 }
190
191 // Now for updates and adds.
192 ApplyAutofillProfileChange(autofill_changes_[i].action_,
193 autofill_changes_[i].profile_specifics_,
194 autofill_changes_[i].id_);
195 }
196
197 autofill_changes_.clear();
198
199 PostOptimisticRefreshTask();
200 }
201
202 void AutofillProfileChangeProcessor::PostOptimisticRefreshTask() {
203 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
204 new DoOptimisticRefreshForAutofill(
205 personal_data_));
206 }
207
208 void AutofillProfileChangeProcessor::ApplyAutofillProfileChange(
209 sync_api::SyncManager::ChangeRecord::Action action,
210 const sync_pb::AutofillProfileSpecifics& profile_specifics,
211 int64 sync_id) {
212
213 DCHECK_NE(sync_api::SyncManager::ChangeRecord::ACTION_DELETE, action);
214 switch (action) {
215 case sync_api::SyncManager::ChangeRecord::ACTION_ADD: {
216 AutoFillProfile p(profile_specifics.guid());
217 AutofillProfileModelAssociator::OverwriteProfileWithServerData(&p,
218 profile_specifics);
219 if (!web_database_->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 model_associator_->Associate(&(p.guid()), sync_id);
226 break;
227 }
228 case sync_api::SyncManager::ChangeRecord::ACTION_UPDATE: {
229 AutoFillProfile *p;
230 if (!web_database_->GetAutoFillProfileForGUID(
231 profile_specifics.guid(), &p)) {
232 LOG(ERROR) << "Could not find the autofill profile to update for " <<
233 profile_specifics.guid();
234 break;
235 }
236 scoped_ptr<AutoFillProfile> autofill_pointer(p);
237 AutofillProfileModelAssociator::OverwriteProfileWithServerData(
238 autofill_pointer.get(),
239 profile_specifics);
240
241 if (!web_database_->UpdateAutoFillProfile(*(autofill_pointer.get()))) {
242 LOG(ERROR) << "Could not update autofill profile for " <<
243 profile_specifics.guid();
244 break;
245 }
246 break;
247 }
248 default: {
249 NOTREACHED();
250 break;
251 }
252 }
253 }
254
255 void AutofillProfileChangeProcessor::RemoveSyncNode(const std::string& guid,
256 sync_api::WriteTransaction* trans) {
257 sync_api::WriteNode node(trans);
258 int64 sync_id = model_associator_->GetSyncIdFromChromeId(guid);
259 if (sync_api::kInvalidId == sync_id) {
260 LOG(ERROR) << "Could not find the node in associator " << guid;
261 return;
262 }
263
264 if (!node.InitByIdLookup(sync_id)) {
265 LOG(ERROR) << "Could not find the sync node for " << guid;
266 return;
267 }
268
269 model_associator_->Disassociate(sync_id);
270 node.Remove();
271 }
272
273 void AutofillProfileChangeProcessor::AddAutofillProfileSyncNode(
274 sync_api::WriteTransaction* trans,
275 sync_api::BaseNode& autofill_profile_root,
276 const AutoFillProfile& profile) {
277 sync_api::WriteNode node(trans);
278 if (!node.InitUniqueByCreation(syncable::AUTOFILL_PROFILE,
279 autofill_profile_root,
280 profile.guid())) {
281 LOG(ERROR) << "could not create a sync node ";
282 return;
283 }
284
285 node.SetTitle(UTF8ToWide(profile.guid()));
286
287 WriteAutofillProfile(profile, &node);
288 }
289
290 void AutofillProfileChangeProcessor::StartObserving() {
291 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
292 notification_registrar_.Add(this,
293 NotificationType::AUTOFILL_PROFILE_CHANGED_GUID,
294 NotificationService::AllSources());
295 }
296
297 void AutofillProfileChangeProcessor::StopObserving() {
298 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
299 notification_registrar_.RemoveAll();
300 }
301
302 void AutofillProfileChangeProcessor::WriteAutofillProfile(
303 const AutoFillProfile& profile,
304 sync_api::WriteNode* node) {
305 sync_pb::AutofillProfileSpecifics specifics;
306 specifics.set_guid(profile.guid());
307 specifics.set_name_first(UTF16ToUTF8(
308 profile.GetFieldText(AutoFillType(NAME_FIRST))));
309 specifics.set_name_middle(UTF16ToUTF8(
310 profile.GetFieldText(AutoFillType(NAME_MIDDLE))));
311 specifics.set_name_last(
312 UTF16ToUTF8(profile.GetFieldText(AutoFillType(NAME_LAST))));
313 specifics.set_address_home_line1(
314 UTF16ToUTF8(profile.GetFieldText(AutoFillType(ADDRESS_HOME_LINE1))));
315 specifics.set_address_home_line2(
316 UTF16ToUTF8(profile.GetFieldText(AutoFillType(ADDRESS_HOME_LINE2))));
317 specifics.set_address_home_city(UTF16ToUTF8(profile.GetFieldText(
318 AutoFillType(ADDRESS_HOME_CITY))));
319 specifics.set_address_home_state(UTF16ToUTF8(profile.GetFieldText(
320 AutoFillType(ADDRESS_HOME_STATE))));
321 specifics.set_address_home_country(UTF16ToUTF8(profile.GetFieldText(
322 AutoFillType(ADDRESS_HOME_COUNTRY))));
323 specifics.set_address_home_zip(UTF16ToUTF8(profile.GetFieldText(
324 AutoFillType(ADDRESS_HOME_ZIP))));
325 specifics.set_email_address(UTF16ToUTF8(profile.GetFieldText(
326 AutoFillType(EMAIL_ADDRESS))));
327 specifics.set_company_name(UTF16ToUTF8(profile.GetFieldText(
328 AutoFillType(COMPANY_NAME))));
329 specifics.set_phone_fax_whole_number(UTF16ToUTF8(profile.GetFieldText(
330 AutoFillType(PHONE_FAX_WHOLE_NUMBER))));
331 specifics.set_phone_home_whole_number(UTF16ToUTF8(profile.GetFieldText(
332 AutoFillType(PHONE_HOME_WHOLE_NUMBER))));
333 node->SetAutofillProfileSpecifics(specifics);
334 }
335
336 } // namespace browser_sync
337
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698