Home | History | Annotate | Download | only in webdata
      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/webdata/web_data_service.h"
      6 
      7 #include "base/message_loop.h"
      8 #include "base/stl_util-inl.h"
      9 #include "base/task.h"
     10 #include "base/threading/thread.h"
     11 #include "chrome/browser/autofill/autofill_profile.h"
     12 #include "chrome/browser/autofill/credit_card.h"
     13 #include "chrome/browser/search_engines/template_url.h"
     14 #include "chrome/browser/ui/profile_error_dialog.h"
     15 #include "chrome/browser/webdata/autofill_change.h"
     16 #include "chrome/browser/webdata/autofill_entry.h"
     17 #include "chrome/browser/webdata/web_database.h"
     18 #include "chrome/common/chrome_constants.h"
     19 #include "content/common/notification_details.h"
     20 #include "content/common/notification_service.h"
     21 #include "content/common/notification_source.h"
     22 #include "content/common/notification_type.h"
     23 #include "grit/chromium_strings.h"
     24 #include "grit/generated_resources.h"
     25 #include "third_party/skia/include/core/SkBitmap.h"
     26 #include "webkit/glue/form_field.h"
     27 #include "webkit/glue/password_form.h"
     28 
     29 ////////////////////////////////////////////////////////////////////////////////
     30 //
     31 // WebDataService implementation.
     32 //
     33 ////////////////////////////////////////////////////////////////////////////////
     34 
     35 using base::Time;
     36 using webkit_glue::FormField;
     37 using webkit_glue::PasswordForm;
     38 
     39 WDAppImagesResult::WDAppImagesResult() : has_all_images(false) {}
     40 
     41 WDAppImagesResult::~WDAppImagesResult() {}
     42 
     43 WDKeywordsResult::WDKeywordsResult()
     44   : default_search_provider_id(0),
     45     builtin_keyword_version(0) {
     46 }
     47 
     48 WDKeywordsResult::~WDKeywordsResult() {}
     49 
     50 WebDataService::WebDataService()
     51   : is_running_(false),
     52     db_(NULL),
     53     failed_init_(false),
     54     should_commit_(false),
     55     next_request_handle_(1),
     56     main_loop_(MessageLoop::current()) {
     57 }
     58 
     59 bool WebDataService::Init(const FilePath& profile_path) {
     60   FilePath path = profile_path;
     61   path = path.Append(chrome::kWebDataFilename);
     62   return InitWithPath(path);
     63 }
     64 
     65 void WebDataService::Shutdown() {
     66   UnloadDatabase();
     67 }
     68 
     69 bool WebDataService::IsRunning() const {
     70   return is_running_;
     71 }
     72 
     73 void WebDataService::UnloadDatabase() {
     74   ScheduleTask(NewRunnableMethod(this, &WebDataService::ShutdownDatabase));
     75 }
     76 
     77 void WebDataService::CancelRequest(Handle h) {
     78   base::AutoLock l(pending_lock_);
     79   RequestMap::iterator i = pending_requests_.find(h);
     80   if (i == pending_requests_.end()) {
     81     NOTREACHED() << "Canceling a nonexistent web data service request";
     82     return;
     83   }
     84   i->second->Cancel();
     85 }
     86 
     87 bool WebDataService::IsDatabaseLoaded() {
     88   return db_ != NULL;
     89 }
     90 
     91 WebDatabase* WebDataService::GetDatabase() {
     92   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
     93   return db_;
     94 }
     95 
     96 //////////////////////////////////////////////////////////////////////////////
     97 //
     98 // Keywords.
     99 //
    100 //////////////////////////////////////////////////////////////////////////////
    101 
    102 void WebDataService::AddKeyword(const TemplateURL& url) {
    103   // Ensure that the keyword is already generated (and cached) before caching
    104   // the TemplateURL for use on another keyword.
    105   url.EnsureKeyword();
    106   GenericRequest<TemplateURL>* request =
    107     new GenericRequest<TemplateURL>(this, GetNextRequestHandle(), NULL, url);
    108   RegisterRequest(request);
    109   ScheduleTask(NewRunnableMethod(this, &WebDataService::AddKeywordImpl,
    110                                  request));
    111 }
    112 
    113 void WebDataService::RemoveKeyword(const TemplateURL& url) {
    114   GenericRequest<TemplateURLID>* request =
    115       new GenericRequest<TemplateURLID>(this, GetNextRequestHandle(),
    116                                         NULL, url.id());
    117   RegisterRequest(request);
    118   ScheduleTask(
    119       NewRunnableMethod(this, &WebDataService::RemoveKeywordImpl, request));
    120 }
    121 
    122 void WebDataService::UpdateKeyword(const TemplateURL& url) {
    123   // Ensure that the keyword is already generated (and cached) before caching
    124   // the TemplateURL for use on another keyword.
    125   url.EnsureKeyword();
    126   GenericRequest<TemplateURL>* request =
    127       new GenericRequest<TemplateURL>(this, GetNextRequestHandle(), NULL, url);
    128   RegisterRequest(request);
    129   ScheduleTask(
    130       NewRunnableMethod(this, &WebDataService::UpdateKeywordImpl, request));
    131 }
    132 
    133 WebDataService::Handle WebDataService::GetKeywords(
    134                                        WebDataServiceConsumer* consumer) {
    135   WebDataRequest* request =
    136       new WebDataRequest(this, GetNextRequestHandle(), consumer);
    137   RegisterRequest(request);
    138   ScheduleTask(
    139       NewRunnableMethod(this,
    140                         &WebDataService::GetKeywordsImpl,
    141                         request));
    142   return request->GetHandle();
    143 }
    144 
    145 void WebDataService::SetDefaultSearchProvider(const TemplateURL* url) {
    146   GenericRequest<TemplateURLID>* request =
    147     new GenericRequest<TemplateURLID>(this,
    148                                       GetNextRequestHandle(),
    149                                       NULL,
    150                                       url ? url->id() : 0);
    151   RegisterRequest(request);
    152   ScheduleTask(
    153       NewRunnableMethod(this, &WebDataService::SetDefaultSearchProviderImpl,
    154                         request));
    155 }
    156 
    157 void WebDataService::SetBuiltinKeywordVersion(int version) {
    158   GenericRequest<int>* request =
    159     new GenericRequest<int>(this, GetNextRequestHandle(), NULL, version);
    160   RegisterRequest(request);
    161   ScheduleTask(
    162       NewRunnableMethod(this, &WebDataService::SetBuiltinKeywordVersionImpl,
    163                         request));
    164 }
    165 
    166 //////////////////////////////////////////////////////////////////////////////
    167 //
    168 // Web Apps
    169 //
    170 //////////////////////////////////////////////////////////////////////////////
    171 
    172 void WebDataService::SetWebAppImage(const GURL& app_url,
    173                                     const SkBitmap& image) {
    174   GenericRequest2<GURL, SkBitmap>* request =
    175       new GenericRequest2<GURL, SkBitmap>(this, GetNextRequestHandle(),
    176                                          NULL, app_url, image);
    177   RegisterRequest(request);
    178   ScheduleTask(NewRunnableMethod(this, &WebDataService::SetWebAppImageImpl,
    179                                  request));
    180 }
    181 
    182 void WebDataService::SetWebAppHasAllImages(const GURL& app_url,
    183                                            bool has_all_images) {
    184   GenericRequest2<GURL, bool>* request =
    185       new GenericRequest2<GURL, bool>(this, GetNextRequestHandle(),
    186                                      NULL, app_url, has_all_images);
    187   RegisterRequest(request);
    188   ScheduleTask(NewRunnableMethod(this,
    189                                  &WebDataService::SetWebAppHasAllImagesImpl,
    190                                  request));
    191 }
    192 
    193 void WebDataService::RemoveWebApp(const GURL& app_url) {
    194   GenericRequest<GURL>* request =
    195       new GenericRequest<GURL>(this, GetNextRequestHandle(), NULL, app_url);
    196   RegisterRequest(request);
    197   ScheduleTask(NewRunnableMethod(this, &WebDataService::RemoveWebAppImpl,
    198                                  request));
    199 }
    200 
    201 WebDataService::Handle WebDataService::GetWebAppImages(
    202     const GURL& app_url,
    203     WebDataServiceConsumer* consumer) {
    204   GenericRequest<GURL>* request =
    205       new GenericRequest<GURL>(this, GetNextRequestHandle(), consumer, app_url);
    206   RegisterRequest(request);
    207   ScheduleTask(NewRunnableMethod(this, &WebDataService::GetWebAppImagesImpl,
    208                                  request));
    209   return request->GetHandle();
    210 }
    211 
    212 ////////////////////////////////////////////////////////////////////////////////
    213 //
    214 // Token Service
    215 //
    216 ////////////////////////////////////////////////////////////////////////////////
    217 
    218 void WebDataService::SetTokenForService(const std::string& service,
    219                                         const std::string& token) {
    220   GenericRequest2<std::string, std::string>* request =
    221       new GenericRequest2<std::string, std::string>(
    222           this, GetNextRequestHandle(), NULL, service, token);
    223   RegisterRequest(request);
    224   ScheduleTask(NewRunnableMethod(this, &WebDataService::SetTokenForServiceImpl,
    225                                  request));
    226 }
    227 
    228 void WebDataService::RemoveAllTokens() {
    229   GenericRequest<std::string>* request =
    230       new GenericRequest<std::string>(
    231           this, GetNextRequestHandle(), NULL, std::string());
    232   RegisterRequest(request);
    233   ScheduleTask(NewRunnableMethod(this,
    234                                  &WebDataService::RemoveAllTokensImpl,
    235                                  request));
    236 }
    237 
    238 // Null on failure. Success is WDResult<std::string>
    239 WebDataService::Handle WebDataService::GetAllTokens(
    240     WebDataServiceConsumer* consumer) {
    241 
    242   GenericRequest<std::string>* request =
    243       new GenericRequest<std::string>(
    244           this, GetNextRequestHandle(), consumer, std::string());
    245   RegisterRequest(request);
    246   ScheduleTask(NewRunnableMethod(this,
    247                                  &WebDataService::GetAllTokensImpl,
    248                                  request));
    249   return request->GetHandle();
    250 }
    251 
    252 ////////////////////////////////////////////////////////////////////////////////
    253 //
    254 // Password manager.
    255 //
    256 ////////////////////////////////////////////////////////////////////////////////
    257 
    258 void WebDataService::AddLogin(const PasswordForm& form) {
    259   GenericRequest<PasswordForm>* request =
    260       new GenericRequest<PasswordForm>(this, GetNextRequestHandle(), NULL,
    261                                        form);
    262   RegisterRequest(request);
    263   ScheduleTask(NewRunnableMethod(this, &WebDataService::AddLoginImpl,
    264                                  request));
    265 }
    266 
    267 void WebDataService::UpdateLogin(const PasswordForm& form) {
    268   GenericRequest<PasswordForm>* request =
    269       new GenericRequest<PasswordForm>(this, GetNextRequestHandle(),
    270                                        NULL, form);
    271   RegisterRequest(request);
    272   ScheduleTask(NewRunnableMethod(this, &WebDataService::UpdateLoginImpl,
    273                                  request));
    274 }
    275 
    276 void WebDataService::RemoveLogin(const PasswordForm& form) {
    277   GenericRequest<PasswordForm>* request =
    278      new GenericRequest<PasswordForm>(this, GetNextRequestHandle(), NULL,
    279                                       form);
    280   RegisterRequest(request);
    281   ScheduleTask(NewRunnableMethod(this, &WebDataService::RemoveLoginImpl,
    282                                  request));
    283 }
    284 
    285 void WebDataService::RemoveLoginsCreatedBetween(const Time& delete_begin,
    286                                                 const Time& delete_end) {
    287   GenericRequest2<Time, Time>* request =
    288     new GenericRequest2<Time, Time>(this,
    289                                     GetNextRequestHandle(),
    290                                     NULL,
    291                                     delete_begin,
    292                                     delete_end);
    293   RegisterRequest(request);
    294   ScheduleTask(NewRunnableMethod(this,
    295       &WebDataService::RemoveLoginsCreatedBetweenImpl, request));
    296 }
    297 
    298 void WebDataService::RemoveLoginsCreatedAfter(const Time& delete_begin) {
    299   RemoveLoginsCreatedBetween(delete_begin, Time());
    300 }
    301 
    302 WebDataService::Handle WebDataService::GetLogins(
    303                                        const PasswordForm& form,
    304                                        WebDataServiceConsumer* consumer) {
    305   GenericRequest<PasswordForm>* request =
    306       new GenericRequest<PasswordForm>(this, GetNextRequestHandle(),
    307                                        consumer, form);
    308   RegisterRequest(request);
    309   ScheduleTask(NewRunnableMethod(this, &WebDataService::GetLoginsImpl,
    310                                  request));
    311   return request->GetHandle();
    312 }
    313 
    314 WebDataService::Handle WebDataService::GetAutofillableLogins(
    315     WebDataServiceConsumer* consumer) {
    316   WebDataRequest* request =
    317       new WebDataRequest(this, GetNextRequestHandle(), consumer);
    318   RegisterRequest(request);
    319   ScheduleTask(NewRunnableMethod(this,
    320                                  &WebDataService::GetAutofillableLoginsImpl,
    321                                  request));
    322   return request->GetHandle();
    323 }
    324 
    325 WebDataService::Handle WebDataService::GetBlacklistLogins(
    326     WebDataServiceConsumer* consumer) {
    327   WebDataRequest* request =
    328       new WebDataRequest(this, GetNextRequestHandle(), consumer);
    329   RegisterRequest(request);
    330   ScheduleTask(NewRunnableMethod(this,
    331                                  &WebDataService::GetBlacklistLoginsImpl,
    332                                  request));
    333   return request->GetHandle();
    334 }
    335 
    336 ////////////////////////////////////////////////////////////////////////////////
    337 //
    338 // Autofill.
    339 //
    340 ////////////////////////////////////////////////////////////////////////////////
    341 
    342 void WebDataService::AddFormFields(
    343     const std::vector<FormField>& fields) {
    344   GenericRequest<std::vector<FormField> >* request =
    345       new GenericRequest<std::vector<FormField> >(
    346           this, GetNextRequestHandle(), NULL, fields);
    347   RegisterRequest(request);
    348   ScheduleTask(NewRunnableMethod(this,
    349                                  &WebDataService::AddFormElementsImpl,
    350                                  request));
    351 }
    352 
    353 WebDataService::Handle WebDataService::GetFormValuesForElementName(
    354     const string16& name, const string16& prefix, int limit,
    355     WebDataServiceConsumer* consumer) {
    356   WebDataRequest* request =
    357       new WebDataRequest(this, GetNextRequestHandle(), consumer);
    358   RegisterRequest(request);
    359   ScheduleTask(
    360       NewRunnableMethod(this,
    361                         &WebDataService::GetFormValuesForElementNameImpl,
    362                         request,
    363                         name,
    364                         prefix,
    365                         limit));
    366   return request->GetHandle();
    367 }
    368 
    369 void WebDataService::RemoveFormElementsAddedBetween(const Time& delete_begin,
    370                                                     const Time& delete_end) {
    371   GenericRequest2<Time, Time>* request =
    372     new GenericRequest2<Time, Time>(this,
    373                                     GetNextRequestHandle(),
    374                                     NULL,
    375                                     delete_begin,
    376                                     delete_end);
    377   RegisterRequest(request);
    378   ScheduleTask(NewRunnableMethod(this,
    379       &WebDataService::RemoveFormElementsAddedBetweenImpl, request));
    380 }
    381 
    382 void WebDataService::RemoveFormValueForElementName(
    383     const string16& name, const string16& value) {
    384   GenericRequest2<string16, string16>* request =
    385       new GenericRequest2<string16, string16>(this,
    386                                               GetNextRequestHandle(),
    387                                               NULL,
    388                                               name, value);
    389   RegisterRequest(request);
    390   ScheduleTask(
    391       NewRunnableMethod(this,
    392                         &WebDataService::RemoveFormValueForElementNameImpl,
    393                         request));
    394 }
    395 
    396 void WebDataService::AddAutofillProfile(const AutofillProfile& profile) {
    397   GenericRequest<AutofillProfile>* request =
    398       new GenericRequest<AutofillProfile>(
    399           this, GetNextRequestHandle(), NULL, profile);
    400   RegisterRequest(request);
    401   ScheduleTask(NewRunnableMethod(this,
    402                                  &WebDataService::AddAutofillProfileImpl,
    403                                  request));
    404 }
    405 
    406 void WebDataService::UpdateAutofillProfile(const AutofillProfile& profile) {
    407   GenericRequest<AutofillProfile>* request =
    408       new GenericRequest<AutofillProfile>(
    409           this, GetNextRequestHandle(), NULL, profile);
    410   RegisterRequest(request);
    411   ScheduleTask(NewRunnableMethod(this,
    412                                  &WebDataService::UpdateAutofillProfileImpl,
    413                                  request));
    414 }
    415 
    416 void WebDataService::RemoveAutofillProfile(const std::string& guid) {
    417   GenericRequest<std::string>* request =
    418       new GenericRequest<std::string>(
    419           this, GetNextRequestHandle(), NULL, guid);
    420   RegisterRequest(request);
    421   ScheduleTask(NewRunnableMethod(this,
    422                                  &WebDataService::RemoveAutofillProfileImpl,
    423                                  request));
    424 }
    425 
    426 WebDataService::Handle WebDataService::GetAutofillProfiles(
    427     WebDataServiceConsumer* consumer) {
    428   WebDataRequest* request =
    429       new WebDataRequest(this, GetNextRequestHandle(), consumer);
    430   RegisterRequest(request);
    431   ScheduleTask(
    432       NewRunnableMethod(this,
    433                         &WebDataService::GetAutofillProfilesImpl,
    434                         request));
    435   return request->GetHandle();
    436 }
    437 
    438 void WebDataService::EmptyMigrationTrash(bool notify_sync) {
    439   GenericRequest<bool>* request =
    440       new GenericRequest<bool>(
    441           this, GetNextRequestHandle(), NULL, notify_sync);
    442   RegisterRequest(request);
    443   ScheduleTask(NewRunnableMethod(this,
    444                                  &WebDataService::EmptyMigrationTrashImpl,
    445                                  request));
    446 }
    447 
    448 void WebDataService::AddCreditCard(const CreditCard& credit_card) {
    449   GenericRequest<CreditCard>* request =
    450       new GenericRequest<CreditCard>(
    451           this, GetNextRequestHandle(), NULL, credit_card);
    452   RegisterRequest(request);
    453   ScheduleTask(NewRunnableMethod(this,
    454                                  &WebDataService::AddCreditCardImpl,
    455                                  request));
    456 }
    457 
    458 void WebDataService::UpdateCreditCard(const CreditCard& credit_card) {
    459   GenericRequest<CreditCard>* request =
    460       new GenericRequest<CreditCard>(
    461           this, GetNextRequestHandle(), NULL, credit_card);
    462   RegisterRequest(request);
    463   ScheduleTask(NewRunnableMethod(this,
    464                                  &WebDataService::UpdateCreditCardImpl,
    465                                  request));
    466 }
    467 
    468 void WebDataService::RemoveCreditCard(const std::string& guid) {
    469   GenericRequest<std::string>* request =
    470       new GenericRequest<std::string>(
    471           this, GetNextRequestHandle(), NULL, guid);
    472   RegisterRequest(request);
    473   ScheduleTask(NewRunnableMethod(this,
    474                                  &WebDataService::RemoveCreditCardImpl,
    475                                  request));
    476 }
    477 
    478 WebDataService::Handle WebDataService::GetCreditCards(
    479     WebDataServiceConsumer* consumer) {
    480   WebDataRequest* request =
    481       new WebDataRequest(this, GetNextRequestHandle(), consumer);
    482   RegisterRequest(request);
    483   ScheduleTask(
    484       NewRunnableMethod(this,
    485                         &WebDataService::GetCreditCardsImpl,
    486                         request));
    487   return request->GetHandle();
    488 }
    489 
    490 void WebDataService::RemoveAutofillProfilesAndCreditCardsModifiedBetween(
    491     const Time& delete_begin,
    492     const Time& delete_end) {
    493   GenericRequest2<Time, Time>* request =
    494       new GenericRequest2<Time, Time>(this,
    495                                       GetNextRequestHandle(),
    496                                       NULL,
    497                                       delete_begin,
    498                                       delete_end);
    499   RegisterRequest(request);
    500   ScheduleTask(NewRunnableMethod(
    501       this,
    502       &WebDataService::RemoveAutofillProfilesAndCreditCardsModifiedBetweenImpl,
    503       request));
    504 }
    505 
    506 WebDataService::~WebDataService() {
    507   if (is_running_ && db_) {
    508     DLOG_ASSERT("WebDataService dtor called without Shutdown");
    509   }
    510 }
    511 
    512 bool WebDataService::InitWithPath(const FilePath& path) {
    513   path_ = path;
    514   is_running_ = true;
    515   ScheduleTask(NewRunnableMethod(this,
    516       &WebDataService::InitializeDatabaseIfNecessary));
    517   return true;
    518 }
    519 
    520 void WebDataService::RequestCompleted(Handle h) {
    521   pending_lock_.Acquire();
    522   RequestMap::iterator i = pending_requests_.find(h);
    523   if (i == pending_requests_.end()) {
    524     NOTREACHED() << "Request completed called for an unknown request";
    525     pending_lock_.Release();
    526     return;
    527   }
    528 
    529   // Take ownership of the request object and remove it from the map.
    530   scoped_ptr<WebDataRequest> request(i->second);
    531   pending_requests_.erase(i);
    532   pending_lock_.Release();
    533 
    534   // Notify the consumer if needed.
    535   WebDataServiceConsumer* consumer;
    536   if (!request->IsCancelled() && (consumer = request->GetConsumer())) {
    537     consumer->OnWebDataServiceRequestDone(request->GetHandle(),
    538                                           request->GetResult());
    539   } else {
    540     // Nobody is taken ownership of the result, either because it is canceled
    541     // or there is no consumer. Destroy results that require special handling.
    542     WDTypedResult const *result = request->GetResult();
    543     if (result) {
    544       if (result->GetType() == AUTOFILL_PROFILES_RESULT) {
    545         const WDResult<std::vector<AutofillProfile*> >* r =
    546             static_cast<const WDResult<std::vector<AutofillProfile*> >*>(
    547                 result);
    548         std::vector<AutofillProfile*> profiles = r->GetValue();
    549         STLDeleteElements(&profiles);
    550       } else if (result->GetType() == AUTOFILL_CREDITCARDS_RESULT) {
    551         const WDResult<std::vector<CreditCard*> >* r =
    552             static_cast<const WDResult<std::vector<CreditCard*> >*>(result);
    553 
    554         std::vector<CreditCard*> credit_cards = r->GetValue();
    555         STLDeleteElements(&credit_cards);
    556       }
    557     }
    558   }
    559 }
    560 
    561 void WebDataService::RegisterRequest(WebDataRequest* request) {
    562   base::AutoLock l(pending_lock_);
    563   pending_requests_[request->GetHandle()] = request;
    564 }
    565 
    566 ////////////////////////////////////////////////////////////////////////////////
    567 //
    568 // The following methods are executed in Chrome_WebDataThread.
    569 //
    570 ////////////////////////////////////////////////////////////////////////////////
    571 
    572 void WebDataService::DBInitFailed(sql::InitStatus init_status) {
    573   ShowProfileErrorDialog(
    574       (init_status == sql::INIT_FAILURE) ?
    575       IDS_COULDNT_OPEN_PROFILE_ERROR : IDS_PROFILE_TOO_NEW_ERROR);
    576 }
    577 
    578 void WebDataService::InitializeDatabaseIfNecessary() {
    579   if (db_ || failed_init_ || path_.empty())
    580     return;
    581 
    582   // In the rare case where the db fails to initialize a dialog may get shown
    583   // that blocks the caller, yet allows other messages through. For this reason
    584   // we only set db_ to the created database if creation is successful. That
    585   // way other methods won't do anything as db_ is still NULL.
    586   WebDatabase* db = new WebDatabase();
    587   sql::InitStatus init_status = db->Init(path_);
    588   if (init_status != sql::INIT_OK) {
    589     LOG(ERROR) << "Cannot initialize the web database: " << init_status;
    590     failed_init_ = true;
    591     delete db;
    592     if (main_loop_) {
    593       main_loop_->PostTask(FROM_HERE,
    594           NewRunnableMethod(this, &WebDataService::DBInitFailed, init_status));
    595     }
    596     return;
    597   }
    598 
    599   BrowserThread::PostTask(
    600       BrowserThread::UI, FROM_HERE,
    601       NewRunnableMethod(this, &WebDataService::NotifyDatabaseLoadedOnUIThread));
    602 
    603   db_ = db;
    604   db_->BeginTransaction();
    605 }
    606 
    607 void WebDataService::NotifyDatabaseLoadedOnUIThread() {
    608   // Notify that the database has been initialized.
    609   NotificationService::current()->Notify(NotificationType::WEB_DATABASE_LOADED,
    610                                          Source<WebDataService>(this),
    611                                          NotificationService::NoDetails());
    612 }
    613 
    614 void WebDataService::ShutdownDatabase() {
    615   should_commit_ = false;
    616 
    617   if (db_) {
    618     db_->CommitTransaction();
    619     delete db_;
    620     db_ = NULL;
    621   }
    622 }
    623 
    624 void WebDataService::Commit() {
    625   if (should_commit_) {
    626     should_commit_ = false;
    627 
    628     if (db_) {
    629       db_->CommitTransaction();
    630       db_->BeginTransaction();
    631     }
    632   }
    633 }
    634 
    635 void WebDataService::ScheduleTask(Task* t) {
    636   if (is_running_)
    637     BrowserThread::PostTask(BrowserThread::DB, FROM_HERE, t);
    638   else
    639     NOTREACHED() << "Task scheduled after Shutdown()";
    640 }
    641 
    642 void WebDataService::ScheduleCommit() {
    643   if (should_commit_ == false) {
    644     should_commit_ = true;
    645     ScheduleTask(NewRunnableMethod(this, &WebDataService::Commit));
    646   }
    647 }
    648 
    649 int WebDataService::GetNextRequestHandle() {
    650   base::AutoLock l(pending_lock_);
    651   return ++next_request_handle_;
    652 }
    653 
    654 ////////////////////////////////////////////////////////////////////////////////
    655 //
    656 // Keywords implementation.
    657 //
    658 ////////////////////////////////////////////////////////////////////////////////
    659 
    660 void WebDataService::AddKeywordImpl(GenericRequest<TemplateURL>* request) {
    661   InitializeDatabaseIfNecessary();
    662   if (db_ && !request->IsCancelled()) {
    663     db_->GetKeywordTable()->AddKeyword(request->GetArgument());
    664     ScheduleCommit();
    665   }
    666   request->RequestComplete();
    667 }
    668 
    669 void WebDataService::RemoveKeywordImpl(
    670     GenericRequest<TemplateURLID>* request) {
    671   InitializeDatabaseIfNecessary();
    672   if (db_ && !request->IsCancelled()) {
    673     DCHECK(request->GetArgument());
    674     db_->GetKeywordTable()->RemoveKeyword(request->GetArgument());
    675     ScheduleCommit();
    676   }
    677   request->RequestComplete();
    678 }
    679 
    680 void WebDataService::UpdateKeywordImpl(GenericRequest<TemplateURL>* request) {
    681   InitializeDatabaseIfNecessary();
    682   if (db_ && !request->IsCancelled()) {
    683     if (!db_->GetKeywordTable()->UpdateKeyword(request->GetArgument())) {
    684       NOTREACHED();
    685       return;
    686     }
    687     ScheduleCommit();
    688   }
    689   request->RequestComplete();
    690 }
    691 
    692 void WebDataService::GetKeywordsImpl(WebDataRequest* request) {
    693   InitializeDatabaseIfNecessary();
    694   if (db_ && !request->IsCancelled()) {
    695     WDKeywordsResult result;
    696     db_->GetKeywordTable()->GetKeywords(&result.keywords);
    697     result.default_search_provider_id =
    698         db_->GetKeywordTable()->GetDefaulSearchProviderID();
    699     result.builtin_keyword_version =
    700         db_->GetKeywordTable()->GetBuitinKeywordVersion();
    701     request->SetResult(
    702         new WDResult<WDKeywordsResult>(KEYWORDS_RESULT, result));
    703   }
    704   request->RequestComplete();
    705 }
    706 
    707 void WebDataService::SetDefaultSearchProviderImpl(
    708     GenericRequest<TemplateURLID>* request) {
    709   InitializeDatabaseIfNecessary();
    710   if (db_ && !request->IsCancelled()) {
    711     if (!db_->GetKeywordTable()->SetDefaultSearchProviderID(
    712         request->GetArgument())) {
    713       NOTREACHED();
    714       return;
    715     }
    716     ScheduleCommit();
    717   }
    718   request->RequestComplete();
    719 }
    720 
    721 void WebDataService::SetBuiltinKeywordVersionImpl(
    722     GenericRequest<int>* request) {
    723   InitializeDatabaseIfNecessary();
    724   if (db_ && !request->IsCancelled()) {
    725     if (!db_->GetKeywordTable()->SetBuitinKeywordVersion(
    726         request->GetArgument())) {
    727       NOTREACHED();
    728       return;
    729     }
    730     ScheduleCommit();
    731   }
    732   request->RequestComplete();
    733 }
    734 
    735 ////////////////////////////////////////////////////////////////////////////////
    736 //
    737 // Web Apps implementation.
    738 //
    739 ////////////////////////////////////////////////////////////////////////////////
    740 
    741 void WebDataService::SetWebAppImageImpl(
    742     GenericRequest2<GURL, SkBitmap>* request) {
    743   InitializeDatabaseIfNecessary();
    744   if (db_ && !request->IsCancelled()) {
    745     db_->GetWebAppsTable()->SetWebAppImage(
    746         request->GetArgument1(), request->GetArgument2());
    747     ScheduleCommit();
    748   }
    749   request->RequestComplete();
    750 }
    751 
    752 void WebDataService::SetWebAppHasAllImagesImpl(
    753     GenericRequest2<GURL, bool>* request) {
    754   InitializeDatabaseIfNecessary();
    755   if (db_ && !request->IsCancelled()) {
    756     db_->GetWebAppsTable()->SetWebAppHasAllImages(request->GetArgument1(),
    757                                                   request->GetArgument2());
    758     ScheduleCommit();
    759   }
    760   request->RequestComplete();
    761 }
    762 
    763 void WebDataService::RemoveWebAppImpl(GenericRequest<GURL>* request) {
    764   InitializeDatabaseIfNecessary();
    765   if (db_ && !request->IsCancelled()) {
    766     db_->GetWebAppsTable()->RemoveWebApp(request->GetArgument());
    767     ScheduleCommit();
    768   }
    769   request->RequestComplete();
    770 }
    771 
    772 void WebDataService::GetWebAppImagesImpl(GenericRequest<GURL>* request) {
    773   InitializeDatabaseIfNecessary();
    774   if (db_ && !request->IsCancelled()) {
    775     WDAppImagesResult result;
    776     result.has_all_images =
    777         db_->GetWebAppsTable()->GetWebAppHasAllImages(request->GetArgument());
    778     db_->GetWebAppsTable()->GetWebAppImages(
    779         request->GetArgument(), &result.images);
    780     request->SetResult(
    781         new WDResult<WDAppImagesResult>(WEB_APP_IMAGES, result));
    782   }
    783   request->RequestComplete();
    784 }
    785 
    786 ////////////////////////////////////////////////////////////////////////////////
    787 //
    788 // Token Service implementation.
    789 //
    790 ////////////////////////////////////////////////////////////////////////////////
    791 
    792 // argument std::string is unused
    793 void WebDataService::RemoveAllTokensImpl(
    794     GenericRequest<std::string>* request) {
    795   InitializeDatabaseIfNecessary();
    796   if (db_ && !request->IsCancelled()) {
    797     if (db_->GetTokenServiceTable()->RemoveAllTokens()) {
    798       ScheduleCommit();
    799     }
    800   }
    801   request->RequestComplete();
    802 }
    803 
    804 void WebDataService::SetTokenForServiceImpl(
    805     GenericRequest2<std::string, std::string>* request) {
    806   InitializeDatabaseIfNecessary();
    807   if (db_ && !request->IsCancelled()) {
    808     if (db_->GetTokenServiceTable()->SetTokenForService(
    809             request->GetArgument1(), request->GetArgument2())) {
    810       ScheduleCommit();
    811     }
    812   }
    813   request->RequestComplete();
    814 }
    815 
    816 // argument is unused
    817 void WebDataService::GetAllTokensImpl(
    818     GenericRequest<std::string>* request) {
    819   InitializeDatabaseIfNecessary();
    820   if (db_ && !request->IsCancelled()) {
    821     std::map<std::string, std::string> map;
    822     db_->GetTokenServiceTable()->GetAllTokens(&map);
    823     request->SetResult(
    824         new WDResult<std::map<std::string, std::string> >(TOKEN_RESULT, map));
    825   }
    826   request->RequestComplete();
    827 }
    828 
    829 ////////////////////////////////////////////////////////////////////////////////
    830 //
    831 // Password manager implementation.
    832 //
    833 ////////////////////////////////////////////////////////////////////////////////
    834 
    835 void WebDataService::AddLoginImpl(GenericRequest<PasswordForm>* request) {
    836   InitializeDatabaseIfNecessary();
    837   if (db_ && !request->IsCancelled()) {
    838     if (db_->GetLoginsTable()->AddLogin(request->GetArgument()))
    839       ScheduleCommit();
    840   }
    841   request->RequestComplete();
    842 }
    843 
    844 void WebDataService::UpdateLoginImpl(GenericRequest<PasswordForm>* request) {
    845   InitializeDatabaseIfNecessary();
    846   if (db_ && !request->IsCancelled()) {
    847     if (db_->GetLoginsTable()->UpdateLogin(request->GetArgument()))
    848       ScheduleCommit();
    849   }
    850   request->RequestComplete();
    851 }
    852 
    853 void WebDataService::RemoveLoginImpl(GenericRequest<PasswordForm>* request) {
    854   InitializeDatabaseIfNecessary();
    855   if (db_ && !request->IsCancelled()) {
    856     if (db_->GetLoginsTable()->RemoveLogin(request->GetArgument()))
    857       ScheduleCommit();
    858   }
    859   request->RequestComplete();
    860 }
    861 
    862 void WebDataService::RemoveLoginsCreatedBetweenImpl(
    863     GenericRequest2<Time, Time>* request) {
    864   InitializeDatabaseIfNecessary();
    865   if (db_ && !request->IsCancelled()) {
    866     if (db_->GetLoginsTable()->RemoveLoginsCreatedBetween(
    867             request->GetArgument1(), request->GetArgument2())) {
    868       ScheduleCommit();
    869     }
    870   }
    871   request->RequestComplete();
    872 }
    873 
    874 void WebDataService::GetLoginsImpl(GenericRequest<PasswordForm>* request) {
    875   InitializeDatabaseIfNecessary();
    876   if (db_ && !request->IsCancelled()) {
    877     std::vector<PasswordForm*> forms;
    878     db_->GetLoginsTable()->GetLogins(request->GetArgument(), &forms);
    879     request->SetResult(
    880         new WDResult<std::vector<PasswordForm*> >(PASSWORD_RESULT, forms));
    881   }
    882   request->RequestComplete();
    883 }
    884 
    885 void WebDataService::GetAutofillableLoginsImpl(WebDataRequest* request) {
    886   InitializeDatabaseIfNecessary();
    887   if (db_ && !request->IsCancelled()) {
    888     std::vector<PasswordForm*> forms;
    889     db_->GetLoginsTable()->GetAllLogins(&forms, false);
    890     request->SetResult(
    891         new WDResult<std::vector<PasswordForm*> >(PASSWORD_RESULT, forms));
    892   }
    893   request->RequestComplete();
    894 }
    895 
    896 void WebDataService::GetBlacklistLoginsImpl(WebDataRequest* request) {
    897   InitializeDatabaseIfNecessary();
    898   if (db_ && !request->IsCancelled()) {
    899     std::vector<PasswordForm*> all_forms;
    900     db_->GetLoginsTable()->GetAllLogins(&all_forms, true);
    901     std::vector<PasswordForm*> blacklist_forms;
    902     for (std::vector<PasswordForm*>::iterator i = all_forms.begin();
    903          i != all_forms.end(); ++i) {
    904       scoped_ptr<PasswordForm> form(*i);
    905       if (form->blacklisted_by_user) {
    906         blacklist_forms.push_back(form.release());
    907       }
    908     }
    909     all_forms.clear();
    910     request->SetResult(
    911         new WDResult<std::vector<PasswordForm*> >(PASSWORD_RESULT,
    912                                                   blacklist_forms));
    913   }
    914   request->RequestComplete();
    915 }
    916 
    917 ////////////////////////////////////////////////////////////////////////////////
    918 //
    919 // Autofill implementation.
    920 //
    921 ////////////////////////////////////////////////////////////////////////////////
    922 
    923 void WebDataService::AddFormElementsImpl(
    924     GenericRequest<std::vector<FormField> >* request) {
    925   InitializeDatabaseIfNecessary();
    926   const std::vector<FormField>& form_fields = request->GetArgument();
    927   if (db_ && !request->IsCancelled()) {
    928     AutofillChangeList changes;
    929     if (!db_->GetAutofillTable()->AddFormFieldValues(form_fields, &changes)) {
    930       NOTREACHED();
    931       return;
    932     }
    933     request->SetResult(
    934         new WDResult<AutofillChangeList>(AUTOFILL_CHANGES, changes));
    935     ScheduleCommit();
    936 
    937     // Post the notifications including the list of affected keys.
    938     // This is sent here so that work resulting from this notification will be
    939     // done on the DB thread, and not the UI thread.
    940     NotificationService::current()->Notify(
    941         NotificationType::AUTOFILL_ENTRIES_CHANGED,
    942         Source<WebDataService>(this),
    943         Details<AutofillChangeList>(&changes));
    944   }
    945 
    946   request->RequestComplete();
    947 }
    948 
    949 void WebDataService::GetFormValuesForElementNameImpl(WebDataRequest* request,
    950     const string16& name, const string16& prefix, int limit) {
    951   InitializeDatabaseIfNecessary();
    952   if (db_ && !request->IsCancelled()) {
    953     std::vector<string16> values;
    954     db_->GetAutofillTable()->GetFormValuesForElementName(
    955         name, prefix, &values, limit);
    956     request->SetResult(
    957         new WDResult<std::vector<string16> >(AUTOFILL_VALUE_RESULT, values));
    958   }
    959   request->RequestComplete();
    960 }
    961 
    962 void WebDataService::RemoveFormElementsAddedBetweenImpl(
    963     GenericRequest2<Time, Time>* request) {
    964   InitializeDatabaseIfNecessary();
    965   if (db_ && !request->IsCancelled()) {
    966     AutofillChangeList changes;
    967     if (db_->GetAutofillTable()->RemoveFormElementsAddedBetween(
    968         request->GetArgument1(), request->GetArgument2(), &changes)) {
    969       if (!changes.empty()) {
    970         request->SetResult(
    971             new WDResult<AutofillChangeList>(AUTOFILL_CHANGES, changes));
    972 
    973         // Post the notifications including the list of affected keys.
    974         // This is sent here so that work resulting from this notification
    975         // will be done on the DB thread, and not the UI thread.
    976         NotificationService::current()->Notify(
    977             NotificationType::AUTOFILL_ENTRIES_CHANGED,
    978             Source<WebDataService>(this),
    979             Details<AutofillChangeList>(&changes));
    980       }
    981       ScheduleCommit();
    982     }
    983   }
    984   request->RequestComplete();
    985 }
    986 
    987 void WebDataService::RemoveFormValueForElementNameImpl(
    988     GenericRequest2<string16, string16>* request) {
    989   InitializeDatabaseIfNecessary();
    990   if (db_ && !request->IsCancelled()) {
    991     const string16& name = request->GetArgument1();
    992     const string16& value = request->GetArgument2();
    993 
    994     if (db_->GetAutofillTable()->RemoveFormElement(name, value)) {
    995       AutofillChangeList changes;
    996       changes.push_back(AutofillChange(AutofillChange::REMOVE,
    997                                        AutofillKey(name, value)));
    998       request->SetResult(
    999           new WDResult<AutofillChangeList>(AUTOFILL_CHANGES, changes));
   1000       ScheduleCommit();
   1001 
   1002       // Post the notifications including the list of affected keys.
   1003       NotificationService::current()->Notify(
   1004           NotificationType::AUTOFILL_ENTRIES_CHANGED,
   1005           Source<WebDataService>(this),
   1006           Details<AutofillChangeList>(&changes));
   1007     }
   1008   }
   1009   request->RequestComplete();
   1010 }
   1011 
   1012 void WebDataService::AddAutofillProfileImpl(
   1013     GenericRequest<AutofillProfile>* request) {
   1014   InitializeDatabaseIfNecessary();
   1015   if (db_ && !request->IsCancelled()) {
   1016     const AutofillProfile& profile = request->GetArgument();
   1017     if (!db_->GetAutofillTable()->AddAutofillProfile(profile)) {
   1018       NOTREACHED();
   1019       return;
   1020     }
   1021     ScheduleCommit();
   1022 
   1023     // Send GUID-based notification.
   1024     AutofillProfileChange change(AutofillProfileChange::ADD,
   1025                                  profile.guid(), &profile);
   1026     NotificationService::current()->Notify(
   1027         NotificationType::AUTOFILL_PROFILE_CHANGED,
   1028         Source<WebDataService>(this),
   1029         Details<AutofillProfileChange>(&change));
   1030   }
   1031   request->RequestComplete();
   1032 }
   1033 
   1034 void WebDataService::UpdateAutofillProfileImpl(
   1035     GenericRequest<AutofillProfile>* request) {
   1036   InitializeDatabaseIfNecessary();
   1037   if (db_ && !request->IsCancelled()) {
   1038     const AutofillProfile& profile = request->GetArgument();
   1039 
   1040     // Only perform the update if the profile exists.  It is currently
   1041     // valid to try to update a missing profile.  We simply drop the write and
   1042     // the caller will detect this on the next refresh.
   1043     AutofillProfile* original_profile = NULL;
   1044     if (!db_->GetAutofillTable()->GetAutofillProfile(profile.guid(),
   1045                                                      &original_profile)) {
   1046       request->RequestComplete();
   1047       return;
   1048     }
   1049     scoped_ptr<AutofillProfile> scoped_profile(original_profile);
   1050 
   1051     if (!db_->GetAutofillTable()->UpdateAutofillProfileMulti(profile)) {
   1052       NOTREACHED();
   1053       return;
   1054     }
   1055     ScheduleCommit();
   1056 
   1057     // Send GUID-based notification.
   1058     AutofillProfileChange change(AutofillProfileChange::UPDATE,
   1059                                  profile.guid(), &profile);
   1060     NotificationService::current()->Notify(
   1061         NotificationType::AUTOFILL_PROFILE_CHANGED,
   1062         Source<WebDataService>(this),
   1063         Details<AutofillProfileChange>(&change));
   1064   }
   1065   request->RequestComplete();
   1066 }
   1067 
   1068 void WebDataService::RemoveAutofillProfileImpl(
   1069     GenericRequest<std::string>* request) {
   1070   InitializeDatabaseIfNecessary();
   1071   if (db_ && !request->IsCancelled()) {
   1072     std::string guid = request->GetArgument();
   1073 
   1074     AutofillProfile* profile = NULL;
   1075     if (!db_->GetAutofillTable()->GetAutofillProfile(guid, &profile)) {
   1076       NOTREACHED();
   1077       return;
   1078     }
   1079     scoped_ptr<AutofillProfile> scoped_profile(profile);
   1080 
   1081     if (!db_->GetAutofillTable()->RemoveAutofillProfile(guid)) {
   1082       NOTREACHED();
   1083       return;
   1084     }
   1085     ScheduleCommit();
   1086 
   1087     // Send GUID-based notification.
   1088     AutofillProfileChange change(AutofillProfileChange::REMOVE, guid, NULL);
   1089     NotificationService::current()->Notify(
   1090         NotificationType::AUTOFILL_PROFILE_CHANGED,
   1091         Source<WebDataService>(this),
   1092         Details<AutofillProfileChange>(&change));
   1093   }
   1094   request->RequestComplete();
   1095 }
   1096 
   1097 void WebDataService::GetAutofillProfilesImpl(WebDataRequest* request) {
   1098   InitializeDatabaseIfNecessary();
   1099   if (db_ && !request->IsCancelled()) {
   1100     std::vector<AutofillProfile*> profiles;
   1101     db_->GetAutofillTable()->GetAutofillProfiles(&profiles);
   1102     request->SetResult(
   1103         new WDResult<std::vector<AutofillProfile*> >(AUTOFILL_PROFILES_RESULT,
   1104                                                      profiles));
   1105   }
   1106   request->RequestComplete();
   1107 }
   1108 
   1109 void WebDataService::EmptyMigrationTrashImpl(
   1110     GenericRequest<bool>* request) {
   1111   InitializeDatabaseIfNecessary();
   1112   if (db_ && !request->IsCancelled()) {
   1113     bool notify_sync = request->GetArgument();
   1114     if (notify_sync) {
   1115       std::vector<std::string> guids;
   1116       if (!db_->GetAutofillTable()->GetAutofillProfilesInTrash(&guids)) {
   1117         NOTREACHED();
   1118         return;
   1119       }
   1120 
   1121       for (std::vector<std::string>::const_iterator iter = guids.begin();
   1122            iter != guids.end(); ++iter) {
   1123         // Send GUID-based notification.
   1124         AutofillProfileChange change(AutofillProfileChange::REMOVE,
   1125                                      *iter, NULL);
   1126         NotificationService::current()->Notify(
   1127             NotificationType::AUTOFILL_PROFILE_CHANGED,
   1128             Source<WebDataService>(this),
   1129             Details<AutofillProfileChange>(&change));
   1130       }
   1131 
   1132       // If we trashed any profiles they may have been merged, so send out
   1133       // update notifications as well.
   1134       if (!guids.empty()) {
   1135         std::vector<AutofillProfile*> profiles;
   1136         db_->GetAutofillTable()->GetAutofillProfiles(&profiles);
   1137         for (std::vector<AutofillProfile*>::const_iterator
   1138                 iter = profiles.begin();
   1139              iter != profiles.end(); ++iter) {
   1140           AutofillProfileChange change(AutofillProfileChange::UPDATE,
   1141                                        (*iter)->guid(), *iter);
   1142           NotificationService::current()->Notify(
   1143               NotificationType::AUTOFILL_PROFILE_CHANGED,
   1144               Source<WebDataService>(this),
   1145               Details<AutofillProfileChange>(&change));
   1146         }
   1147         STLDeleteElements(&profiles);
   1148       }
   1149     }
   1150 
   1151     if (!db_->GetAutofillTable()->EmptyAutofillProfilesTrash()) {
   1152       NOTREACHED();
   1153       return;
   1154     }
   1155     ScheduleCommit();
   1156   }
   1157   request->RequestComplete();
   1158 }
   1159 
   1160 void WebDataService::AddCreditCardImpl(
   1161     GenericRequest<CreditCard>* request) {
   1162   InitializeDatabaseIfNecessary();
   1163   if (db_ && !request->IsCancelled()) {
   1164     const CreditCard& credit_card = request->GetArgument();
   1165     if (!db_->GetAutofillTable()->AddCreditCard(credit_card)) {
   1166       NOTREACHED();
   1167       return;
   1168     }
   1169     ScheduleCommit();
   1170 
   1171     // Send GUID-based notification.
   1172     AutofillCreditCardChange change(AutofillCreditCardChange::ADD,
   1173                                     credit_card.guid(), &credit_card);
   1174     NotificationService::current()->Notify(
   1175         NotificationType::AUTOFILL_CREDIT_CARD_CHANGED,
   1176         Source<WebDataService>(this),
   1177         Details<AutofillCreditCardChange>(&change));
   1178   }
   1179   request->RequestComplete();
   1180 }
   1181 
   1182 void WebDataService::UpdateCreditCardImpl(
   1183     GenericRequest<CreditCard>* request) {
   1184   InitializeDatabaseIfNecessary();
   1185   if (db_ && !request->IsCancelled()) {
   1186     const CreditCard& credit_card = request->GetArgument();
   1187 
   1188     // It is currently valid to try to update a missing profile.  We simply drop
   1189     // the write and the caller will detect this on the next refresh.
   1190     CreditCard* original_credit_card = NULL;
   1191     if (!db_->GetAutofillTable()->GetCreditCard(credit_card.guid(),
   1192                                                 &original_credit_card)) {
   1193       request->RequestComplete();
   1194       return;
   1195     }
   1196     scoped_ptr<CreditCard> scoped_credit_card(original_credit_card);
   1197 
   1198     if (!db_->GetAutofillTable()->UpdateCreditCard(credit_card)) {
   1199       NOTREACHED();
   1200       return;
   1201     }
   1202     ScheduleCommit();
   1203 
   1204     // Send GUID-based notification.
   1205     AutofillCreditCardChange change(AutofillCreditCardChange::UPDATE,
   1206                                     credit_card.guid(), &credit_card);
   1207     NotificationService::current()->Notify(
   1208         NotificationType::AUTOFILL_CREDIT_CARD_CHANGED,
   1209         Source<WebDataService>(this),
   1210         Details<AutofillCreditCardChange>(&change));
   1211   }
   1212   request->RequestComplete();
   1213 }
   1214 
   1215 void WebDataService::RemoveCreditCardImpl(
   1216     GenericRequest<std::string>* request) {
   1217   InitializeDatabaseIfNecessary();
   1218   if (db_ && !request->IsCancelled()) {
   1219     std::string guid = request->GetArgument();
   1220     if (!db_->GetAutofillTable()->RemoveCreditCard(guid)) {
   1221       NOTREACHED();
   1222       return;
   1223     }
   1224     ScheduleCommit();
   1225 
   1226     // Send GUID-based notification.
   1227     AutofillCreditCardChange change(AutofillCreditCardChange::REMOVE,
   1228                                     guid, NULL);
   1229     NotificationService::current()->Notify(
   1230         NotificationType::AUTOFILL_CREDIT_CARD_CHANGED,
   1231         Source<WebDataService>(this),
   1232         Details<AutofillCreditCardChange>(&change));
   1233   }
   1234   request->RequestComplete();
   1235 }
   1236 
   1237 void WebDataService::GetCreditCardsImpl(WebDataRequest* request) {
   1238   InitializeDatabaseIfNecessary();
   1239   if (db_ && !request->IsCancelled()) {
   1240     std::vector<CreditCard*> credit_cards;
   1241     db_->GetAutofillTable()->GetCreditCards(&credit_cards);
   1242     request->SetResult(
   1243         new WDResult<std::vector<CreditCard*> >(AUTOFILL_CREDITCARDS_RESULT,
   1244                                                 credit_cards));
   1245   }
   1246   request->RequestComplete();
   1247 }
   1248 
   1249 void WebDataService::RemoveAutofillProfilesAndCreditCardsModifiedBetweenImpl(
   1250     GenericRequest2<Time, Time>* request) {
   1251   InitializeDatabaseIfNecessary();
   1252   if (db_ && !request->IsCancelled()) {
   1253     std::vector<std::string> profile_guids;
   1254     std::vector<std::string> credit_card_guids;
   1255     if (db_->GetAutofillTable()->
   1256         RemoveAutofillProfilesAndCreditCardsModifiedBetween(
   1257             request->GetArgument1(),
   1258             request->GetArgument2(),
   1259             &profile_guids,
   1260             &credit_card_guids)) {
   1261       for (std::vector<std::string>::iterator iter = profile_guids.begin();
   1262            iter != profile_guids.end(); ++iter) {
   1263         AutofillProfileChange change(AutofillProfileChange::REMOVE, *iter,
   1264                                      NULL);
   1265         NotificationService::current()->Notify(
   1266             NotificationType::AUTOFILL_PROFILE_CHANGED,
   1267             Source<WebDataService>(this),
   1268             Details<AutofillProfileChange>(&change));
   1269       }
   1270 
   1271       for (std::vector<std::string>::iterator iter = credit_card_guids.begin();
   1272            iter != credit_card_guids.end(); ++iter) {
   1273         AutofillCreditCardChange change(AutofillCreditCardChange::REMOVE,
   1274                                         *iter, NULL);
   1275         NotificationService::current()->Notify(
   1276             NotificationType::AUTOFILL_CREDIT_CARD_CHANGED,
   1277             Source<WebDataService>(this),
   1278             Details<AutofillCreditCardChange>(&change));
   1279       }
   1280       // Note: It is the caller's responsibility to post notifications for any
   1281       // changes, e.g. by calling the Refresh() method of PersonalDataManager.
   1282       ScheduleCommit();
   1283     }
   1284   }
   1285   request->RequestComplete();
   1286 }
   1287 
   1288 ////////////////////////////////////////////////////////////////////////////////
   1289 //
   1290 // WebDataRequest implementation.
   1291 //
   1292 ////////////////////////////////////////////////////////////////////////////////
   1293 
   1294 WebDataService::WebDataRequest::WebDataRequest(WebDataService* service,
   1295                                                Handle handle,
   1296                                                WebDataServiceConsumer* consumer)
   1297     : service_(service),
   1298       handle_(handle),
   1299       canceled_(false),
   1300       consumer_(consumer),
   1301       result_(NULL) {
   1302   message_loop_ = MessageLoop::current();
   1303 }
   1304 
   1305 WebDataService::WebDataRequest::~WebDataRequest() {
   1306   delete result_;
   1307 }
   1308 
   1309 WebDataService::Handle WebDataService::WebDataRequest::GetHandle() const {
   1310   return handle_;
   1311 }
   1312 
   1313 WebDataServiceConsumer* WebDataService::WebDataRequest::GetConsumer() const {
   1314   return consumer_;
   1315 }
   1316 
   1317 bool WebDataService::WebDataRequest::IsCancelled() const {
   1318   return canceled_;
   1319 }
   1320 
   1321 void WebDataService::WebDataRequest::Cancel() {
   1322   canceled_ = true;
   1323   consumer_ = NULL;
   1324 }
   1325 
   1326 void WebDataService::WebDataRequest::SetResult(WDTypedResult* r) {
   1327   result_ = r;
   1328 }
   1329 
   1330 const WDTypedResult* WebDataService::WebDataRequest::GetResult() const {
   1331   return result_;
   1332 }
   1333 
   1334 void WebDataService::WebDataRequest::RequestComplete() {
   1335   WebDataService* s = service_;
   1336   Task* t = NewRunnableMethod(s,
   1337                               &WebDataService::RequestCompleted,
   1338                               handle_);
   1339   message_loop_->PostTask(FROM_HERE, t);
   1340 }
   1341