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