1 // Copyright 2013 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 "components/autofill/core/browser/webdata/autofill_webdata_backend_impl.h" 6 7 #include "base/bind.h" 8 #include "base/logging.h" 9 #include "base/memory/scoped_vector.h" 10 #include "base/message_loop/message_loop_proxy.h" 11 #include "base/stl_util.h" 12 #include "components/autofill/core/browser/autofill_country.h" 13 #include "components/autofill/core/browser/autofill_profile.h" 14 #include "components/autofill/core/browser/credit_card.h" 15 #include "components/autofill/core/browser/webdata/autofill_change.h" 16 #include "components/autofill/core/browser/webdata/autofill_entry.h" 17 #include "components/autofill/core/browser/webdata/autofill_table.h" 18 #include "components/autofill/core/browser/webdata/autofill_webdata_service_observer.h" 19 #include "components/autofill/core/common/form_field_data.h" 20 #include "components/webdata/common/web_data_service_backend.h" 21 22 using base::Bind; 23 using base::Time; 24 25 namespace autofill { 26 27 AutofillWebDataBackendImpl::AutofillWebDataBackendImpl( 28 scoped_refptr<WebDataServiceBackend> web_database_backend, 29 scoped_refptr<base::MessageLoopProxy> ui_thread, 30 scoped_refptr<base::MessageLoopProxy> db_thread, 31 const base::Closure& on_changed_callback) 32 : base::RefCountedDeleteOnMessageLoop<AutofillWebDataBackendImpl>( 33 db_thread), 34 ui_thread_(ui_thread), 35 db_thread_(db_thread), 36 web_database_backend_(web_database_backend), 37 on_changed_callback_(on_changed_callback) { 38 } 39 40 void AutofillWebDataBackendImpl::AddObserver( 41 AutofillWebDataServiceObserverOnDBThread* observer) { 42 DCHECK(db_thread_->BelongsToCurrentThread()); 43 db_observer_list_.AddObserver(observer); 44 } 45 46 void AutofillWebDataBackendImpl::RemoveObserver( 47 AutofillWebDataServiceObserverOnDBThread* observer) { 48 DCHECK(db_thread_->BelongsToCurrentThread()); 49 db_observer_list_.RemoveObserver(observer); 50 } 51 52 AutofillWebDataBackendImpl::~AutofillWebDataBackendImpl() { 53 DCHECK(!user_data_.get()); // Forgot to call ResetUserData? 54 } 55 56 WebDatabase* AutofillWebDataBackendImpl::GetDatabase() { 57 DCHECK(db_thread_->BelongsToCurrentThread()); 58 return web_database_backend_->database(); 59 } 60 61 void AutofillWebDataBackendImpl::RemoveExpiredFormElements() { 62 web_database_backend_->ExecuteWriteTask( 63 Bind(&AutofillWebDataBackendImpl::RemoveExpiredFormElementsImpl, 64 this)); 65 } 66 67 void AutofillWebDataBackendImpl::NotifyOfMultipleAutofillChanges() { 68 DCHECK(db_thread_->BelongsToCurrentThread()); 69 ui_thread_->PostTask(FROM_HERE, on_changed_callback_); 70 } 71 72 base::SupportsUserData* AutofillWebDataBackendImpl::GetDBUserData() { 73 DCHECK(db_thread_->BelongsToCurrentThread()); 74 if (!user_data_) 75 user_data_.reset(new SupportsUserDataAggregatable()); 76 return user_data_.get(); 77 } 78 79 void AutofillWebDataBackendImpl::ResetUserData() { 80 user_data_.reset(); 81 } 82 83 WebDatabase::State AutofillWebDataBackendImpl::AddFormElements( 84 const std::vector<FormFieldData>& fields, WebDatabase* db) { 85 DCHECK(db_thread_->BelongsToCurrentThread()); 86 AutofillChangeList changes; 87 if (!AutofillTable::FromWebDatabase(db)->AddFormFieldValues( 88 fields, &changes)) { 89 NOTREACHED(); 90 return WebDatabase::COMMIT_NOT_NEEDED; 91 } 92 93 // Post the notifications including the list of affected keys. 94 // This is sent here so that work resulting from this notification will be 95 // done on the DB thread, and not the UI thread. 96 FOR_EACH_OBSERVER(AutofillWebDataServiceObserverOnDBThread, 97 db_observer_list_, 98 AutofillEntriesChanged(changes)); 99 100 return WebDatabase::COMMIT_NEEDED; 101 } 102 103 scoped_ptr<WDTypedResult> 104 AutofillWebDataBackendImpl::GetFormValuesForElementName( 105 const base::string16& name, const base::string16& prefix, int limit, 106 WebDatabase* db) { 107 DCHECK(db_thread_->BelongsToCurrentThread()); 108 std::vector<base::string16> values; 109 AutofillTable::FromWebDatabase(db)->GetFormValuesForElementName( 110 name, prefix, &values, limit); 111 return scoped_ptr<WDTypedResult>( 112 new WDResult<std::vector<base::string16> >(AUTOFILL_VALUE_RESULT, 113 values)); 114 } 115 116 scoped_ptr<WDTypedResult> AutofillWebDataBackendImpl::HasFormElements( 117 WebDatabase* db) { 118 DCHECK(db_thread_->BelongsToCurrentThread()); 119 bool value = AutofillTable::FromWebDatabase(db)->HasFormElements(); 120 return scoped_ptr<WDTypedResult>( 121 new WDResult<bool>(AUTOFILL_VALUE_RESULT, value)); 122 } 123 124 WebDatabase::State AutofillWebDataBackendImpl::RemoveFormElementsAddedBetween( 125 const base::Time& delete_begin, 126 const base::Time& delete_end, 127 WebDatabase* db) { 128 DCHECK(db_thread_->BelongsToCurrentThread()); 129 AutofillChangeList changes; 130 131 if (AutofillTable::FromWebDatabase(db)->RemoveFormElementsAddedBetween( 132 delete_begin, delete_end, &changes)) { 133 if (!changes.empty()) { 134 // Post the notifications including the list of affected keys. 135 // This is sent here so that work resulting from this notification 136 // will be done on the DB thread, and not the UI thread. 137 FOR_EACH_OBSERVER(AutofillWebDataServiceObserverOnDBThread, 138 db_observer_list_, 139 AutofillEntriesChanged(changes)); 140 } 141 return WebDatabase::COMMIT_NEEDED; 142 } 143 return WebDatabase::COMMIT_NOT_NEEDED; 144 } 145 146 WebDatabase::State AutofillWebDataBackendImpl::RemoveFormValueForElementName( 147 const base::string16& name, const base::string16& value, WebDatabase* db) { 148 DCHECK(db_thread_->BelongsToCurrentThread()); 149 150 if (AutofillTable::FromWebDatabase(db)->RemoveFormElement(name, value)) { 151 AutofillChangeList changes; 152 changes.push_back( 153 AutofillChange(AutofillChange::REMOVE, AutofillKey(name, value))); 154 155 // Post the notifications including the list of affected keys. 156 FOR_EACH_OBSERVER(AutofillWebDataServiceObserverOnDBThread, 157 db_observer_list_, 158 AutofillEntriesChanged(changes)); 159 160 return WebDatabase::COMMIT_NEEDED; 161 } 162 return WebDatabase::COMMIT_NOT_NEEDED; 163 } 164 165 WebDatabase::State AutofillWebDataBackendImpl::AddAutofillProfile( 166 const AutofillProfile& profile, WebDatabase* db) { 167 DCHECK(db_thread_->BelongsToCurrentThread()); 168 if (!AutofillTable::FromWebDatabase(db)->AddAutofillProfile(profile)) { 169 NOTREACHED(); 170 return WebDatabase::COMMIT_NOT_NEEDED; 171 } 172 173 // Send GUID-based notification. 174 AutofillProfileChange change( 175 AutofillProfileChange::ADD, profile.guid(), &profile); 176 FOR_EACH_OBSERVER(AutofillWebDataServiceObserverOnDBThread, 177 db_observer_list_, 178 AutofillProfileChanged(change)); 179 180 return WebDatabase::COMMIT_NEEDED; 181 } 182 183 WebDatabase::State AutofillWebDataBackendImpl::UpdateAutofillProfile( 184 const AutofillProfile& profile, WebDatabase* db) { 185 DCHECK(db_thread_->BelongsToCurrentThread()); 186 // Only perform the update if the profile exists. It is currently 187 // valid to try to update a missing profile. We simply drop the write and 188 // the caller will detect this on the next refresh. 189 AutofillProfile* original_profile = NULL; 190 if (!AutofillTable::FromWebDatabase(db)->GetAutofillProfile(profile.guid(), 191 &original_profile)) { 192 return WebDatabase::COMMIT_NOT_NEEDED; 193 } 194 scoped_ptr<AutofillProfile> scoped_profile(original_profile); 195 196 if (!AutofillTable::FromWebDatabase(db)->UpdateAutofillProfile(profile)) { 197 NOTREACHED(); 198 return WebDatabase::COMMIT_NEEDED; 199 } 200 201 // Send GUID-based notification. 202 AutofillProfileChange change( 203 AutofillProfileChange::UPDATE, profile.guid(), &profile); 204 FOR_EACH_OBSERVER(AutofillWebDataServiceObserverOnDBThread, 205 db_observer_list_, 206 AutofillProfileChanged(change)); 207 208 return WebDatabase::COMMIT_NEEDED; 209 } 210 211 WebDatabase::State AutofillWebDataBackendImpl::RemoveAutofillProfile( 212 const std::string& guid, WebDatabase* db) { 213 DCHECK(db_thread_->BelongsToCurrentThread()); 214 AutofillProfile* profile = NULL; 215 if (!AutofillTable::FromWebDatabase(db)->GetAutofillProfile(guid, &profile)) { 216 NOTREACHED(); 217 return WebDatabase::COMMIT_NOT_NEEDED; 218 } 219 scoped_ptr<AutofillProfile> scoped_profile(profile); 220 221 if (!AutofillTable::FromWebDatabase(db)->RemoveAutofillProfile(guid)) { 222 NOTREACHED(); 223 return WebDatabase::COMMIT_NOT_NEEDED; 224 } 225 226 // Send GUID-based notification. 227 AutofillProfileChange change(AutofillProfileChange::REMOVE, guid, NULL); 228 FOR_EACH_OBSERVER(AutofillWebDataServiceObserverOnDBThread, 229 db_observer_list_, 230 AutofillProfileChanged(change)); 231 232 return WebDatabase::COMMIT_NEEDED; 233 } 234 235 scoped_ptr<WDTypedResult> AutofillWebDataBackendImpl::GetAutofillProfiles( 236 WebDatabase* db) { 237 DCHECK(db_thread_->BelongsToCurrentThread()); 238 std::vector<AutofillProfile*> profiles; 239 AutofillTable::FromWebDatabase(db)->GetAutofillProfiles(&profiles); 240 return scoped_ptr<WDTypedResult>( 241 new WDDestroyableResult<std::vector<AutofillProfile*> >( 242 AUTOFILL_PROFILES_RESULT, 243 profiles, 244 base::Bind(&AutofillWebDataBackendImpl::DestroyAutofillProfileResult, 245 base::Unretained(this)))); 246 } 247 248 WebDatabase::State AutofillWebDataBackendImpl::UpdateAutofillEntries( 249 const std::vector<autofill::AutofillEntry>& autofill_entries, 250 WebDatabase* db) { 251 DCHECK(db_thread_->BelongsToCurrentThread()); 252 if (!AutofillTable::FromWebDatabase(db) 253 ->UpdateAutofillEntries(autofill_entries)) 254 return WebDatabase::COMMIT_NOT_NEEDED; 255 256 return WebDatabase::COMMIT_NEEDED; 257 } 258 259 WebDatabase::State AutofillWebDataBackendImpl::AddCreditCard( 260 const CreditCard& credit_card, WebDatabase* db) { 261 DCHECK(db_thread_->BelongsToCurrentThread()); 262 if (!AutofillTable::FromWebDatabase(db)->AddCreditCard(credit_card)) { 263 NOTREACHED(); 264 return WebDatabase::COMMIT_NOT_NEEDED; 265 } 266 267 return WebDatabase::COMMIT_NEEDED; 268 } 269 270 WebDatabase::State AutofillWebDataBackendImpl::UpdateCreditCard( 271 const CreditCard& credit_card, WebDatabase* db) { 272 DCHECK(db_thread_->BelongsToCurrentThread()); 273 // It is currently valid to try to update a missing profile. We simply drop 274 // the write and the caller will detect this on the next refresh. 275 CreditCard* original_credit_card = NULL; 276 if (!AutofillTable::FromWebDatabase(db)->GetCreditCard(credit_card.guid(), 277 &original_credit_card)) { 278 return WebDatabase::COMMIT_NOT_NEEDED; 279 } 280 scoped_ptr<CreditCard> scoped_credit_card(original_credit_card); 281 282 if (!AutofillTable::FromWebDatabase(db)->UpdateCreditCard(credit_card)) { 283 NOTREACHED(); 284 return WebDatabase::COMMIT_NOT_NEEDED; 285 } 286 return WebDatabase::COMMIT_NEEDED; 287 } 288 289 WebDatabase::State AutofillWebDataBackendImpl::RemoveCreditCard( 290 const std::string& guid, WebDatabase* db) { 291 DCHECK(db_thread_->BelongsToCurrentThread()); 292 if (!AutofillTable::FromWebDatabase(db)->RemoveCreditCard(guid)) { 293 NOTREACHED(); 294 return WebDatabase::COMMIT_NOT_NEEDED; 295 } 296 return WebDatabase::COMMIT_NEEDED; 297 } 298 299 scoped_ptr<WDTypedResult> AutofillWebDataBackendImpl::GetCreditCards( 300 WebDatabase* db) { 301 DCHECK(db_thread_->BelongsToCurrentThread()); 302 std::vector<CreditCard*> credit_cards; 303 AutofillTable::FromWebDatabase(db)->GetCreditCards(&credit_cards); 304 return scoped_ptr<WDTypedResult>( 305 new WDDestroyableResult<std::vector<CreditCard*> >( 306 AUTOFILL_CREDITCARDS_RESULT, 307 credit_cards, 308 base::Bind(&AutofillWebDataBackendImpl::DestroyAutofillCreditCardResult, 309 base::Unretained(this)))); 310 } 311 312 WebDatabase::State 313 AutofillWebDataBackendImpl::RemoveAutofillDataModifiedBetween( 314 const base::Time& delete_begin, 315 const base::Time& delete_end, 316 WebDatabase* db) { 317 DCHECK(db_thread_->BelongsToCurrentThread()); 318 std::vector<std::string> profile_guids; 319 std::vector<std::string> credit_card_guids; 320 if (AutofillTable::FromWebDatabase(db)->RemoveAutofillDataModifiedBetween( 321 delete_begin, 322 delete_end, 323 &profile_guids, 324 &credit_card_guids)) { 325 for (std::vector<std::string>::iterator iter = profile_guids.begin(); 326 iter != profile_guids.end(); ++iter) { 327 AutofillProfileChange change(AutofillProfileChange::REMOVE, *iter, NULL); 328 FOR_EACH_OBSERVER(AutofillWebDataServiceObserverOnDBThread, 329 db_observer_list_, 330 AutofillProfileChanged(change)); 331 } 332 // Note: It is the caller's responsibility to post notifications for any 333 // changes, e.g. by calling the Refresh() method of PersonalDataManager. 334 return WebDatabase::COMMIT_NEEDED; 335 } 336 return WebDatabase::COMMIT_NOT_NEEDED; 337 } 338 339 WebDatabase::State AutofillWebDataBackendImpl::RemoveOriginURLsModifiedBetween( 340 const base::Time& delete_begin, 341 const base::Time& delete_end, 342 WebDatabase* db) { 343 DCHECK(db_thread_->BelongsToCurrentThread()); 344 ScopedVector<AutofillProfile> profiles; 345 if (AutofillTable::FromWebDatabase(db)->RemoveOriginURLsModifiedBetween( 346 delete_begin, delete_end, &profiles)) { 347 for (std::vector<AutofillProfile*>::const_iterator it = profiles.begin(); 348 it != profiles.end(); ++it) { 349 AutofillProfileChange change(AutofillProfileChange::UPDATE, 350 (*it)->guid(), *it); 351 FOR_EACH_OBSERVER(AutofillWebDataServiceObserverOnDBThread, 352 db_observer_list_, 353 AutofillProfileChanged(change)); 354 } 355 // Note: It is the caller's responsibility to post notifications for any 356 // changes, e.g. by calling the Refresh() method of PersonalDataManager. 357 return WebDatabase::COMMIT_NEEDED; 358 } 359 return WebDatabase::COMMIT_NOT_NEEDED; 360 } 361 362 WebDatabase::State AutofillWebDataBackendImpl::RemoveExpiredFormElementsImpl( 363 WebDatabase* db) { 364 DCHECK(db_thread_->BelongsToCurrentThread()); 365 AutofillChangeList changes; 366 367 if (AutofillTable::FromWebDatabase(db)->RemoveExpiredFormElements(&changes)) { 368 if (!changes.empty()) { 369 // Post the notifications including the list of affected keys. 370 // This is sent here so that work resulting from this notification 371 // will be done on the DB thread, and not the UI thread. 372 FOR_EACH_OBSERVER(AutofillWebDataServiceObserverOnDBThread, 373 db_observer_list_, 374 AutofillEntriesChanged(changes)); 375 } 376 return WebDatabase::COMMIT_NEEDED; 377 } 378 return WebDatabase::COMMIT_NOT_NEEDED; 379 } 380 381 void AutofillWebDataBackendImpl::DestroyAutofillProfileResult( 382 const WDTypedResult* result) { 383 DCHECK(result->GetType() == AUTOFILL_PROFILES_RESULT); 384 const WDResult<std::vector<AutofillProfile*> >* r = 385 static_cast<const WDResult<std::vector<AutofillProfile*> >*>(result); 386 std::vector<AutofillProfile*> profiles = r->GetValue(); 387 STLDeleteElements(&profiles); 388 } 389 390 void AutofillWebDataBackendImpl::DestroyAutofillCreditCardResult( 391 const WDTypedResult* result) { 392 DCHECK(result->GetType() == AUTOFILL_CREDITCARDS_RESULT); 393 const WDResult<std::vector<CreditCard*> >* r = 394 static_cast<const WDResult<std::vector<CreditCard*> >*>(result); 395 396 std::vector<CreditCard*> credit_cards = r->GetValue(); 397 STLDeleteElements(&credit_cards); 398 } 399 400 } // namespace autofill 401