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