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
35using base::Time;
36using webkit_glue::FormField;
37using webkit_glue::PasswordForm;
38
39WDAppImagesResult::WDAppImagesResult() : has_all_images(false) {}
40
41WDAppImagesResult::~WDAppImagesResult() {}
42
43WDKeywordsResult::WDKeywordsResult()
44  : default_search_provider_id(0),
45    builtin_keyword_version(0) {
46}
47
48WDKeywordsResult::~WDKeywordsResult() {}
49
50WebDataService::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
59bool WebDataService::Init(const FilePath& profile_path) {
60  FilePath path = profile_path;
61  path = path.Append(chrome::kWebDataFilename);
62  return InitWithPath(path);
63}
64
65void WebDataService::Shutdown() {
66  UnloadDatabase();
67}
68
69bool WebDataService::IsRunning() const {
70  return is_running_;
71}
72
73void WebDataService::UnloadDatabase() {
74  ScheduleTask(NewRunnableMethod(this, &WebDataService::ShutdownDatabase));
75}
76
77void 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
87bool WebDataService::IsDatabaseLoaded() {
88  return db_ != NULL;
89}
90
91WebDatabase* WebDataService::GetDatabase() {
92  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::DB));
93  return db_;
94}
95
96//////////////////////////////////////////////////////////////////////////////
97//
98// Keywords.
99//
100//////////////////////////////////////////////////////////////////////////////
101
102void 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
113void 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
122void 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
133WebDataService::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
145void 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
157void 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
172void 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
182void 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
193void 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
201WebDataService::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
218void 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
228void 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>
239WebDataService::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
258void 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
267void 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
276void 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
285void 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
298void WebDataService::RemoveLoginsCreatedAfter(const Time& delete_begin) {
299  RemoveLoginsCreatedBetween(delete_begin, Time());
300}
301
302WebDataService::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
314WebDataService::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
325WebDataService::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
342void 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
353WebDataService::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
369void 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
382void 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
396void 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
406void 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
416void 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
426WebDataService::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
438void 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
448void 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
458void 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
468void 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
478WebDataService::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
490void 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
506WebDataService::~WebDataService() {
507  if (is_running_ && db_) {
508    DLOG_ASSERT("WebDataService dtor called without Shutdown");
509  }
510}
511
512bool WebDataService::InitWithPath(const FilePath& path) {
513  path_ = path;
514  is_running_ = true;
515  ScheduleTask(NewRunnableMethod(this,
516      &WebDataService::InitializeDatabaseIfNecessary));
517  return true;
518}
519
520void 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
561void 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
572void 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
578void 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
607void 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
614void WebDataService::ShutdownDatabase() {
615  should_commit_ = false;
616
617  if (db_) {
618    db_->CommitTransaction();
619    delete db_;
620    db_ = NULL;
621  }
622}
623
624void WebDataService::Commit() {
625  if (should_commit_) {
626    should_commit_ = false;
627
628    if (db_) {
629      db_->CommitTransaction();
630      db_->BeginTransaction();
631    }
632  }
633}
634
635void 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
642void WebDataService::ScheduleCommit() {
643  if (should_commit_ == false) {
644    should_commit_ = true;
645    ScheduleTask(NewRunnableMethod(this, &WebDataService::Commit));
646  }
647}
648
649int WebDataService::GetNextRequestHandle() {
650  base::AutoLock l(pending_lock_);
651  return ++next_request_handle_;
652}
653
654////////////////////////////////////////////////////////////////////////////////
655//
656// Keywords implementation.
657//
658////////////////////////////////////////////////////////////////////////////////
659
660void 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
669void 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
680void 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
692void 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
707void 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
721void 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
741void 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
752void 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
763void 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
772void 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
793void 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
804void 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
817void 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
835void 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
844void 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
853void 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
862void 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
874void 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
885void 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
896void 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
923void 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
949void 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
962void 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
987void 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
1012void 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
1034void 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
1068void 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
1097void 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
1109void 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
1160void 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
1182void 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
1215void 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
1237void 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
1249void 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
1294WebDataService::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
1305WebDataService::WebDataRequest::~WebDataRequest() {
1306  delete result_;
1307}
1308
1309WebDataService::Handle WebDataService::WebDataRequest::GetHandle() const {
1310  return handle_;
1311}
1312
1313WebDataServiceConsumer* WebDataService::WebDataRequest::GetConsumer() const {
1314  return consumer_;
1315}
1316
1317bool WebDataService::WebDataRequest::IsCancelled() const {
1318  return canceled_;
1319}
1320
1321void WebDataService::WebDataRequest::Cancel() {
1322  canceled_ = true;
1323  consumer_ = NULL;
1324}
1325
1326void WebDataService::WebDataRequest::SetResult(WDTypedResult* r) {
1327  result_ = r;
1328}
1329
1330const WDTypedResult* WebDataService::WebDataRequest::GetResult() const {
1331  return result_;
1332}
1333
1334void 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