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