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::AddCreditCard( 249 const CreditCard& credit_card, WebDatabase* db) { 250 DCHECK(db_thread_->BelongsToCurrentThread()); 251 if (!AutofillTable::FromWebDatabase(db)->AddCreditCard(credit_card)) { 252 NOTREACHED(); 253 return WebDatabase::COMMIT_NOT_NEEDED; 254 } 255 256 return WebDatabase::COMMIT_NEEDED; 257 } 258 259 WebDatabase::State AutofillWebDataBackendImpl::UpdateCreditCard( 260 const CreditCard& credit_card, WebDatabase* db) { 261 DCHECK(db_thread_->BelongsToCurrentThread()); 262 // It is currently valid to try to update a missing profile. We simply drop 263 // the write and the caller will detect this on the next refresh. 264 CreditCard* original_credit_card = NULL; 265 if (!AutofillTable::FromWebDatabase(db)->GetCreditCard(credit_card.guid(), 266 &original_credit_card)) { 267 return WebDatabase::COMMIT_NOT_NEEDED; 268 } 269 scoped_ptr<CreditCard> scoped_credit_card(original_credit_card); 270 271 if (!AutofillTable::FromWebDatabase(db)->UpdateCreditCard(credit_card)) { 272 NOTREACHED(); 273 return WebDatabase::COMMIT_NOT_NEEDED; 274 } 275 return WebDatabase::COMMIT_NEEDED; 276 } 277 278 WebDatabase::State AutofillWebDataBackendImpl::RemoveCreditCard( 279 const std::string& guid, WebDatabase* db) { 280 DCHECK(db_thread_->BelongsToCurrentThread()); 281 if (!AutofillTable::FromWebDatabase(db)->RemoveCreditCard(guid)) { 282 NOTREACHED(); 283 return WebDatabase::COMMIT_NOT_NEEDED; 284 } 285 return WebDatabase::COMMIT_NEEDED; 286 } 287 288 scoped_ptr<WDTypedResult> AutofillWebDataBackendImpl::GetCreditCards( 289 WebDatabase* db) { 290 DCHECK(db_thread_->BelongsToCurrentThread()); 291 std::vector<CreditCard*> credit_cards; 292 AutofillTable::FromWebDatabase(db)->GetCreditCards(&credit_cards); 293 return scoped_ptr<WDTypedResult>( 294 new WDDestroyableResult<std::vector<CreditCard*> >( 295 AUTOFILL_CREDITCARDS_RESULT, 296 credit_cards, 297 base::Bind(&AutofillWebDataBackendImpl::DestroyAutofillCreditCardResult, 298 base::Unretained(this)))); 299 } 300 301 WebDatabase::State 302 AutofillWebDataBackendImpl::RemoveAutofillDataModifiedBetween( 303 const base::Time& delete_begin, 304 const base::Time& delete_end, 305 WebDatabase* db) { 306 DCHECK(db_thread_->BelongsToCurrentThread()); 307 std::vector<std::string> profile_guids; 308 std::vector<std::string> credit_card_guids; 309 if (AutofillTable::FromWebDatabase(db)->RemoveAutofillDataModifiedBetween( 310 delete_begin, 311 delete_end, 312 &profile_guids, 313 &credit_card_guids)) { 314 for (std::vector<std::string>::iterator iter = profile_guids.begin(); 315 iter != profile_guids.end(); ++iter) { 316 AutofillProfileChange change(AutofillProfileChange::REMOVE, *iter, NULL); 317 FOR_EACH_OBSERVER(AutofillWebDataServiceObserverOnDBThread, 318 db_observer_list_, 319 AutofillProfileChanged(change)); 320 } 321 // Note: It is the caller's responsibility to post notifications for any 322 // changes, e.g. by calling the Refresh() method of PersonalDataManager. 323 return WebDatabase::COMMIT_NEEDED; 324 } 325 return WebDatabase::COMMIT_NOT_NEEDED; 326 } 327 328 WebDatabase::State AutofillWebDataBackendImpl::RemoveOriginURLsModifiedBetween( 329 const base::Time& delete_begin, 330 const base::Time& delete_end, 331 WebDatabase* db) { 332 DCHECK(db_thread_->BelongsToCurrentThread()); 333 ScopedVector<AutofillProfile> profiles; 334 if (AutofillTable::FromWebDatabase(db)->RemoveOriginURLsModifiedBetween( 335 delete_begin, delete_end, &profiles)) { 336 for (std::vector<AutofillProfile*>::const_iterator it = profiles.begin(); 337 it != profiles.end(); ++it) { 338 AutofillProfileChange change(AutofillProfileChange::UPDATE, 339 (*it)->guid(), *it); 340 FOR_EACH_OBSERVER(AutofillWebDataServiceObserverOnDBThread, 341 db_observer_list_, 342 AutofillProfileChanged(change)); 343 } 344 // Note: It is the caller's responsibility to post notifications for any 345 // changes, e.g. by calling the Refresh() method of PersonalDataManager. 346 return WebDatabase::COMMIT_NEEDED; 347 } 348 return WebDatabase::COMMIT_NOT_NEEDED; 349 } 350 351 WebDatabase::State AutofillWebDataBackendImpl::RemoveExpiredFormElementsImpl( 352 WebDatabase* db) { 353 DCHECK(db_thread_->BelongsToCurrentThread()); 354 AutofillChangeList changes; 355 356 if (AutofillTable::FromWebDatabase(db)->RemoveExpiredFormElements(&changes)) { 357 if (!changes.empty()) { 358 // Post the notifications including the list of affected keys. 359 // This is sent here so that work resulting from this notification 360 // will be done on the DB thread, and not the UI thread. 361 FOR_EACH_OBSERVER(AutofillWebDataServiceObserverOnDBThread, 362 db_observer_list_, 363 AutofillEntriesChanged(changes)); 364 } 365 return WebDatabase::COMMIT_NEEDED; 366 } 367 return WebDatabase::COMMIT_NOT_NEEDED; 368 } 369 370 void AutofillWebDataBackendImpl::DestroyAutofillProfileResult( 371 const WDTypedResult* result) { 372 DCHECK(result->GetType() == AUTOFILL_PROFILES_RESULT); 373 const WDResult<std::vector<AutofillProfile*> >* r = 374 static_cast<const WDResult<std::vector<AutofillProfile*> >*>(result); 375 std::vector<AutofillProfile*> profiles = r->GetValue(); 376 STLDeleteElements(&profiles); 377 } 378 379 void AutofillWebDataBackendImpl::DestroyAutofillCreditCardResult( 380 const WDTypedResult* result) { 381 DCHECK(result->GetType() == AUTOFILL_CREDITCARDS_RESULT); 382 const WDResult<std::vector<CreditCard*> >* r = 383 static_cast<const WDResult<std::vector<CreditCard*> >*>(result); 384 385 std::vector<CreditCard*> credit_cards = r->GetValue(); 386 STLDeleteElements(&credit_cards); 387 } 388 389 } // namespace autofill 390