• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
WDAppImagesResult()39 WDAppImagesResult::WDAppImagesResult() : has_all_images(false) {}
40 
~WDAppImagesResult()41 WDAppImagesResult::~WDAppImagesResult() {}
42 
WDKeywordsResult()43 WDKeywordsResult::WDKeywordsResult()
44   : default_search_provider_id(0),
45     builtin_keyword_version(0) {
46 }
47 
~WDKeywordsResult()48 WDKeywordsResult::~WDKeywordsResult() {}
49 
WebDataService()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 
Init(const FilePath & profile_path)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 
Shutdown()65 void WebDataService::Shutdown() {
66   UnloadDatabase();
67 }
68 
IsRunning() const69 bool WebDataService::IsRunning() const {
70   return is_running_;
71 }
72 
UnloadDatabase()73 void WebDataService::UnloadDatabase() {
74   ScheduleTask(NewRunnableMethod(this, &WebDataService::ShutdownDatabase));
75 }
76 
CancelRequest(Handle h)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 
IsDatabaseLoaded()87 bool WebDataService::IsDatabaseLoaded() {
88   return db_ != NULL;
89 }
90 
GetDatabase()91 WebDatabase* WebDataService::GetDatabase() {
92   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
93   return db_;
94 }
95 
96 //////////////////////////////////////////////////////////////////////////////
97 //
98 // Keywords.
99 //
100 //////////////////////////////////////////////////////////////////////////////
101 
AddKeyword(const TemplateURL & url)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 
RemoveKeyword(const TemplateURL & url)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 
UpdateKeyword(const TemplateURL & url)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 
GetKeywords(WebDataServiceConsumer * consumer)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 
SetDefaultSearchProvider(const TemplateURL * url)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 
SetBuiltinKeywordVersion(int version)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 
SetWebAppImage(const GURL & app_url,const SkBitmap & image)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 
SetWebAppHasAllImages(const GURL & app_url,bool has_all_images)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 
RemoveWebApp(const GURL & app_url)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 
GetWebAppImages(const GURL & app_url,WebDataServiceConsumer * consumer)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 
SetTokenForService(const std::string & service,const std::string & token)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 
RemoveAllTokens()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>
GetAllTokens(WebDataServiceConsumer * consumer)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 
AddLogin(const PasswordForm & form)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 
UpdateLogin(const PasswordForm & form)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 
RemoveLogin(const PasswordForm & form)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 
RemoveLoginsCreatedBetween(const Time & delete_begin,const Time & delete_end)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 
RemoveLoginsCreatedAfter(const Time & delete_begin)298 void WebDataService::RemoveLoginsCreatedAfter(const Time& delete_begin) {
299   RemoveLoginsCreatedBetween(delete_begin, Time());
300 }
301 
GetLogins(const PasswordForm & form,WebDataServiceConsumer * consumer)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 
GetAutofillableLogins(WebDataServiceConsumer * consumer)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 
GetBlacklistLogins(WebDataServiceConsumer * consumer)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 
AddFormFields(const std::vector<FormField> & fields)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 
GetFormValuesForElementName(const string16 & name,const string16 & prefix,int limit,WebDataServiceConsumer * consumer)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 
RemoveFormElementsAddedBetween(const Time & delete_begin,const Time & delete_end)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 
RemoveFormValueForElementName(const string16 & name,const string16 & value)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 
AddAutofillProfile(const AutofillProfile & profile)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 
UpdateAutofillProfile(const AutofillProfile & profile)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 
RemoveAutofillProfile(const std::string & guid)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 
GetAutofillProfiles(WebDataServiceConsumer * consumer)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 
EmptyMigrationTrash(bool notify_sync)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 
AddCreditCard(const CreditCard & credit_card)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 
UpdateCreditCard(const CreditCard & credit_card)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 
RemoveCreditCard(const std::string & guid)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 
GetCreditCards(WebDataServiceConsumer * consumer)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 
RemoveAutofillProfilesAndCreditCardsModifiedBetween(const Time & delete_begin,const Time & delete_end)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 
~WebDataService()506 WebDataService::~WebDataService() {
507   if (is_running_ && db_) {
508     DLOG_ASSERT("WebDataService dtor called without Shutdown");
509   }
510 }
511 
InitWithPath(const FilePath & path)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 
RequestCompleted(Handle h)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 
RegisterRequest(WebDataRequest * request)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 
DBInitFailed(sql::InitStatus init_status)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 
InitializeDatabaseIfNecessary()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 
NotifyDatabaseLoadedOnUIThread()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 
ShutdownDatabase()614 void WebDataService::ShutdownDatabase() {
615   should_commit_ = false;
616 
617   if (db_) {
618     db_->CommitTransaction();
619     delete db_;
620     db_ = NULL;
621   }
622 }
623 
Commit()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 
ScheduleTask(Task * t)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 
ScheduleCommit()642 void WebDataService::ScheduleCommit() {
643   if (should_commit_ == false) {
644     should_commit_ = true;
645     ScheduleTask(NewRunnableMethod(this, &WebDataService::Commit));
646   }
647 }
648 
GetNextRequestHandle()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 
AddKeywordImpl(GenericRequest<TemplateURL> * request)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 
RemoveKeywordImpl(GenericRequest<TemplateURLID> * request)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 
UpdateKeywordImpl(GenericRequest<TemplateURL> * request)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 
GetKeywordsImpl(WebDataRequest * request)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 
SetDefaultSearchProviderImpl(GenericRequest<TemplateURLID> * request)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 
SetBuiltinKeywordVersionImpl(GenericRequest<int> * request)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 
SetWebAppImageImpl(GenericRequest2<GURL,SkBitmap> * request)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 
SetWebAppHasAllImagesImpl(GenericRequest2<GURL,bool> * request)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 
RemoveWebAppImpl(GenericRequest<GURL> * request)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 
GetWebAppImagesImpl(GenericRequest<GURL> * request)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
RemoveAllTokensImpl(GenericRequest<std::string> * request)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 
SetTokenForServiceImpl(GenericRequest2<std::string,std::string> * request)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
GetAllTokensImpl(GenericRequest<std::string> * request)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 
AddLoginImpl(GenericRequest<PasswordForm> * request)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 
UpdateLoginImpl(GenericRequest<PasswordForm> * request)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 
RemoveLoginImpl(GenericRequest<PasswordForm> * request)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 
RemoveLoginsCreatedBetweenImpl(GenericRequest2<Time,Time> * request)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 
GetLoginsImpl(GenericRequest<PasswordForm> * request)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 
GetAutofillableLoginsImpl(WebDataRequest * request)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 
GetBlacklistLoginsImpl(WebDataRequest * request)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 
AddFormElementsImpl(GenericRequest<std::vector<FormField>> * request)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 
GetFormValuesForElementNameImpl(WebDataRequest * request,const string16 & name,const string16 & prefix,int limit)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 
RemoveFormElementsAddedBetweenImpl(GenericRequest2<Time,Time> * request)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 
RemoveFormValueForElementNameImpl(GenericRequest2<string16,string16> * request)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 
AddAutofillProfileImpl(GenericRequest<AutofillProfile> * request)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 
UpdateAutofillProfileImpl(GenericRequest<AutofillProfile> * request)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 
RemoveAutofillProfileImpl(GenericRequest<std::string> * request)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 
GetAutofillProfilesImpl(WebDataRequest * request)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 
EmptyMigrationTrashImpl(GenericRequest<bool> * request)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 
AddCreditCardImpl(GenericRequest<CreditCard> * request)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 
UpdateCreditCardImpl(GenericRequest<CreditCard> * request)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 
RemoveCreditCardImpl(GenericRequest<std::string> * request)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 
GetCreditCardsImpl(WebDataRequest * request)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 
RemoveAutofillProfilesAndCreditCardsModifiedBetweenImpl(GenericRequest2<Time,Time> * request)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 
WebDataRequest(WebDataService * service,Handle handle,WebDataServiceConsumer * consumer)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 
~WebDataRequest()1305 WebDataService::WebDataRequest::~WebDataRequest() {
1306   delete result_;
1307 }
1308 
GetHandle() const1309 WebDataService::Handle WebDataService::WebDataRequest::GetHandle() const {
1310   return handle_;
1311 }
1312 
GetConsumer() const1313 WebDataServiceConsumer* WebDataService::WebDataRequest::GetConsumer() const {
1314   return consumer_;
1315 }
1316 
IsCancelled() const1317 bool WebDataService::WebDataRequest::IsCancelled() const {
1318   return canceled_;
1319 }
1320 
Cancel()1321 void WebDataService::WebDataRequest::Cancel() {
1322   canceled_ = true;
1323   consumer_ = NULL;
1324 }
1325 
SetResult(WDTypedResult * r)1326 void WebDataService::WebDataRequest::SetResult(WDTypedResult* r) {
1327   result_ = r;
1328 }
1329 
GetResult() const1330 const WDTypedResult* WebDataService::WebDataRequest::GetResult() const {
1331   return result_;
1332 }
1333 
RequestComplete()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