| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/chromeos/contacts/gdata_contacts_service.h" | 5 #include "chrome/browser/chromeos/contacts/gdata_contacts_service.h" |
| 6 | 6 |
| 7 #include <cstring> | 7 #include <cstring> |
| 8 #include <map> | 8 #include <map> |
| 9 #include <string> | 9 #include <string> |
| 10 #include <utility> | 10 #include <utility> |
| 11 | 11 |
| 12 #include "base/json/json_value_converter.h" | 12 #include "base/json/json_value_converter.h" |
| 13 #include "base/json/json_writer.h" | 13 #include "base/json/json_writer.h" |
| 14 #include "base/logging.h" | 14 #include "base/logging.h" |
| 15 #include "base/memory/weak_ptr.h" | 15 #include "base/memory/weak_ptr.h" |
| 16 #include "base/metrics/histogram.h" | 16 #include "base/metrics/histogram.h" |
| 17 #include "base/stl_util.h" | 17 #include "base/stl_util.h" |
| 18 #include "base/string_util.h" | 18 #include "base/string_util.h" |
| 19 #include "base/time.h" | 19 #include "base/time.h" |
| 20 #include "base/timer.h" | 20 #include "base/timer.h" |
| 21 #include "base/values.h" | 21 #include "base/values.h" |
| 22 #include "chrome/browser/chromeos/contacts/contact.pb.h" | 22 #include "chrome/browser/chromeos/contacts/contact.pb.h" |
| 23 #include "chrome/browser/google_apis/gdata_contacts_operations.h" |
| 23 #include "chrome/browser/google_apis/gdata_errorcode.h" | 24 #include "chrome/browser/google_apis/gdata_errorcode.h" |
| 24 #include "chrome/browser/google_apis/gdata_contacts_operations.h" | 25 #include "chrome/browser/google_apis/request_sender.h" |
| 25 #include "chrome/browser/google_apis/operation_runner.h" | |
| 26 #include "chrome/browser/google_apis/time_util.h" | 26 #include "chrome/browser/google_apis/time_util.h" |
| 27 #include "content/public/browser/browser_thread.h" | 27 #include "content/public/browser/browser_thread.h" |
| 28 | 28 |
| 29 using content::BrowserThread; | 29 using content::BrowserThread; |
| 30 | 30 |
| 31 namespace contacts { | 31 namespace contacts { |
| 32 | 32 |
| 33 namespace { | 33 namespace { |
| 34 | 34 |
| 35 // Download outcomes reported via the "Contacts.FullUpdateResult" and | 35 // Download outcomes reported via the "Contacts.FullUpdateResult" and |
| (...skipping 393 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 429 // Individual contacts::Contact objects are created using the data from the | 429 // Individual contacts::Contact objects are created using the data from the |
| 430 // feed. | 430 // feed. |
| 431 // | 431 // |
| 432 // Finally, GetContactPhotoOperations are created and used to start downloading | 432 // Finally, GetContactPhotoOperations are created and used to start downloading |
| 433 // contacts' photos in parallel. When all photos have been downloaded, the | 433 // contacts' photos in parallel. When all photos have been downloaded, the |
| 434 // contacts are passed to the passed-in callback. | 434 // contacts are passed to the passed-in callback. |
| 435 class GDataContactsService::DownloadContactsRequest { | 435 class GDataContactsService::DownloadContactsRequest { |
| 436 public: | 436 public: |
| 437 DownloadContactsRequest( | 437 DownloadContactsRequest( |
| 438 GDataContactsService* service, | 438 GDataContactsService* service, |
| 439 google_apis::OperationRunner* runner, | 439 google_apis::RequestSender* runner, |
| 440 net::URLRequestContextGetter* url_request_context_getter, | 440 net::URLRequestContextGetter* url_request_context_getter, |
| 441 SuccessCallback success_callback, | 441 SuccessCallback success_callback, |
| 442 FailureCallback failure_callback, | 442 FailureCallback failure_callback, |
| 443 const base::Time& min_update_time) | 443 const base::Time& min_update_time) |
| 444 : service_(service), | 444 : service_(service), |
| 445 runner_(runner), | 445 sender_(runner), |
| 446 url_request_context_getter_(url_request_context_getter), | 446 url_request_context_getter_(url_request_context_getter), |
| 447 success_callback_(success_callback), | 447 success_callback_(success_callback), |
| 448 failure_callback_(failure_callback), | 448 failure_callback_(failure_callback), |
| 449 min_update_time_(min_update_time), | 449 min_update_time_(min_update_time), |
| 450 contacts_(new ScopedVector<contacts::Contact>), | 450 contacts_(new ScopedVector<contacts::Contact>), |
| 451 my_contacts_group_id_(service->cached_my_contacts_group_id_), | 451 my_contacts_group_id_(service->cached_my_contacts_group_id_), |
| 452 num_in_progress_photo_downloads_(0), | 452 num_in_progress_photo_downloads_(0), |
| 453 photo_download_failed_(false), | 453 photo_download_failed_(false), |
| 454 num_photo_download_404_errors_(0), | 454 num_photo_download_404_errors_(0), |
| 455 total_photo_bytes_(0), | 455 total_photo_bytes_(0), |
| 456 weak_ptr_factory_(this) { | 456 weak_ptr_factory_(this) { |
| 457 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 457 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 458 DCHECK(service_); | 458 DCHECK(service_); |
| 459 DCHECK(runner_); | 459 DCHECK(sender_); |
| 460 } | 460 } |
| 461 | 461 |
| 462 ~DownloadContactsRequest() { | 462 ~DownloadContactsRequest() { |
| 463 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 463 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 464 service_ = NULL; | 464 service_ = NULL; |
| 465 runner_ = NULL; | 465 sender_ = NULL; |
| 466 } | 466 } |
| 467 | 467 |
| 468 const std::string my_contacts_group_id() const { | 468 const std::string my_contacts_group_id() const { |
| 469 return my_contacts_group_id_; | 469 return my_contacts_group_id_; |
| 470 } | 470 } |
| 471 | 471 |
| 472 // Begins the contacts-downloading process. If the ID for the "My Contacts" | 472 // Begins the contacts-downloading process. If the ID for the "My Contacts" |
| 473 // group has previously been cached, then the contacts download is started. | 473 // group has previously been cached, then the contacts download is started. |
| 474 // Otherwise, the contact groups download is started. | 474 // Otherwise, the contact groups download is started. |
| 475 void Run() { | 475 void Run() { |
| 476 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 476 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 477 download_start_time_ = base::TimeTicks::Now(); | 477 download_start_time_ = base::TimeTicks::Now(); |
| 478 if (!my_contacts_group_id_.empty()) { | 478 if (!my_contacts_group_id_.empty()) { |
| 479 StartContactsDownload(); | 479 StartContactsDownload(); |
| 480 } else { | 480 } else { |
| 481 google_apis::GetContactGroupsOperation* operation = | 481 google_apis::GetContactGroupsOperation* operation = |
| 482 new google_apis::GetContactGroupsOperation( | 482 new google_apis::GetContactGroupsOperation( |
| 483 runner_, | 483 sender_, |
| 484 url_request_context_getter_, | 484 url_request_context_getter_, |
| 485 base::Bind(&DownloadContactsRequest::HandleGroupsFeedData, | 485 base::Bind(&DownloadContactsRequest::HandleGroupsFeedData, |
| 486 weak_ptr_factory_.GetWeakPtr())); | 486 weak_ptr_factory_.GetWeakPtr())); |
| 487 if (!service_->groups_feed_url_for_testing_.is_empty()) { | 487 if (!service_->groups_feed_url_for_testing_.is_empty()) { |
| 488 operation->set_feed_url_for_testing( | 488 operation->set_feed_url_for_testing( |
| 489 service_->groups_feed_url_for_testing_); | 489 service_->groups_feed_url_for_testing_); |
| 490 } | 490 } |
| 491 runner_->StartOperationWithRetry(operation); | 491 sender_->StartRequestWithRetry(operation); |
| 492 } | 492 } |
| 493 } | 493 } |
| 494 | 494 |
| 495 private: | 495 private: |
| 496 // Invokes the failure callback and notifies GDataContactsService that the | 496 // Invokes the failure callback and notifies GDataContactsService that the |
| 497 // request is done. | 497 // request is done. |
| 498 void ReportFailure(HistogramResult histogram_result) { | 498 void ReportFailure(HistogramResult histogram_result) { |
| 499 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 499 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 500 SendHistograms(histogram_result); | 500 SendHistograms(histogram_result); |
| 501 failure_callback_.Run(); | 501 failure_callback_.Run(); |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 581 LOG(WARNING) << "Unable to find ID for \"My Contacts\" group"; | 581 LOG(WARNING) << "Unable to find ID for \"My Contacts\" group"; |
| 582 ReportFailure(HISTOGRAM_RESULT_MY_CONTACTS_GROUP_NOT_FOUND); | 582 ReportFailure(HISTOGRAM_RESULT_MY_CONTACTS_GROUP_NOT_FOUND); |
| 583 } | 583 } |
| 584 } | 584 } |
| 585 | 585 |
| 586 // Starts a download of the contacts from the "My Contacts" group. | 586 // Starts a download of the contacts from the "My Contacts" group. |
| 587 void StartContactsDownload() { | 587 void StartContactsDownload() { |
| 588 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 588 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 589 google_apis::GetContactsOperation* operation = | 589 google_apis::GetContactsOperation* operation = |
| 590 new google_apis::GetContactsOperation( | 590 new google_apis::GetContactsOperation( |
| 591 runner_, | 591 sender_, |
| 592 url_request_context_getter_, | 592 url_request_context_getter_, |
| 593 my_contacts_group_id_, | 593 my_contacts_group_id_, |
| 594 min_update_time_, | 594 min_update_time_, |
| 595 base::Bind(&DownloadContactsRequest::HandleContactsFeedData, | 595 base::Bind(&DownloadContactsRequest::HandleContactsFeedData, |
| 596 weak_ptr_factory_.GetWeakPtr())); | 596 weak_ptr_factory_.GetWeakPtr())); |
| 597 if (!service_->contacts_feed_url_for_testing_.is_empty()) { | 597 if (!service_->contacts_feed_url_for_testing_.is_empty()) { |
| 598 operation->set_feed_url_for_testing( | 598 operation->set_feed_url_for_testing( |
| 599 service_->contacts_feed_url_for_testing_); | 599 service_->contacts_feed_url_for_testing_); |
| 600 } | 600 } |
| 601 runner_->StartOperationWithRetry(operation); | 601 sender_->StartRequestWithRetry(operation); |
| 602 } | 602 } |
| 603 | 603 |
| 604 // Callback for GetContactsOperation calls. | 604 // Callback for GetContactsOperation calls. |
| 605 void HandleContactsFeedData(google_apis::GDataErrorCode error, | 605 void HandleContactsFeedData(google_apis::GDataErrorCode error, |
| 606 scoped_ptr<base::Value> feed_data) { | 606 scoped_ptr<base::Value> feed_data) { |
| 607 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 607 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 608 if (error != google_apis::HTTP_SUCCESS) { | 608 if (error != google_apis::HTTP_SUCCESS) { |
| 609 LOG(WARNING) << "Got error " << error << " while downloading contacts"; | 609 LOG(WARNING) << "Got error " << error << " while downloading contacts"; |
| 610 ReportFailure(HISTOGRAM_RESULT_CONTACTS_DOWNLOAD_FAILURE); | 610 ReportFailure(HISTOGRAM_RESULT_CONTACTS_DOWNLOAD_FAILURE); |
| 611 return; | 611 return; |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 736 while (!contacts_needing_photo_downloads_.empty() && | 736 while (!contacts_needing_photo_downloads_.empty() && |
| 737 (num_in_progress_photo_downloads_ < | 737 (num_in_progress_photo_downloads_ < |
| 738 service_->max_photo_downloads_per_second_)) { | 738 service_->max_photo_downloads_per_second_)) { |
| 739 contacts::Contact* contact = contacts_needing_photo_downloads_.back(); | 739 contacts::Contact* contact = contacts_needing_photo_downloads_.back(); |
| 740 contacts_needing_photo_downloads_.pop_back(); | 740 contacts_needing_photo_downloads_.pop_back(); |
| 741 DCHECK(contact_photo_urls_.count(contact)); | 741 DCHECK(contact_photo_urls_.count(contact)); |
| 742 std::string url = contact_photo_urls_[contact]; | 742 std::string url = contact_photo_urls_[contact]; |
| 743 | 743 |
| 744 VLOG(1) << "Starting download of photo " << url << " for " | 744 VLOG(1) << "Starting download of photo " << url << " for " |
| 745 << contact->contact_id(); | 745 << contact->contact_id(); |
| 746 runner_->StartOperationWithRetry( | 746 sender_->StartRequestWithRetry( |
| 747 new google_apis::GetContactPhotoOperation( | 747 new google_apis::GetContactPhotoOperation( |
| 748 runner_, | 748 sender_, |
| 749 url_request_context_getter_, | 749 url_request_context_getter_, |
| 750 GURL(url), | 750 GURL(url), |
| 751 base::Bind(&DownloadContactsRequest::HandlePhotoData, | 751 base::Bind(&DownloadContactsRequest::HandlePhotoData, |
| 752 weak_ptr_factory_.GetWeakPtr(), | 752 weak_ptr_factory_.GetWeakPtr(), |
| 753 contact))); | 753 contact))); |
| 754 num_in_progress_photo_downloads_++; | 754 num_in_progress_photo_downloads_++; |
| 755 } | 755 } |
| 756 } | 756 } |
| 757 | 757 |
| 758 // Callback for GetContactPhotoOperation calls. Updates the associated | 758 // Callback for GetContactPhotoOperation calls. Updates the associated |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 795 } | 795 } |
| 796 | 796 |
| 797 total_photo_bytes_ += download_data->size(); | 797 total_photo_bytes_ += download_data->size(); |
| 798 contact->set_raw_untrusted_photo(*download_data); | 798 contact->set_raw_untrusted_photo(*download_data); |
| 799 CheckCompletion(); | 799 CheckCompletion(); |
| 800 } | 800 } |
| 801 | 801 |
| 802 typedef std::map<contacts::Contact*, std::string> ContactPhotoUrls; | 802 typedef std::map<contacts::Contact*, std::string> ContactPhotoUrls; |
| 803 | 803 |
| 804 GDataContactsService* service_; // not owned | 804 GDataContactsService* service_; // not owned |
| 805 google_apis::OperationRunner* runner_; // not owned | 805 google_apis::RequestSender* sender_; // not owned |
| 806 net::URLRequestContextGetter* url_request_context_getter_; // not owned | 806 net::URLRequestContextGetter* url_request_context_getter_; // not owned |
| 807 | 807 |
| 808 SuccessCallback success_callback_; | 808 SuccessCallback success_callback_; |
| 809 FailureCallback failure_callback_; | 809 FailureCallback failure_callback_; |
| 810 | 810 |
| 811 base::Time min_update_time_; | 811 base::Time min_update_time_; |
| 812 | 812 |
| 813 scoped_ptr<ScopedVector<contacts::Contact> > contacts_; | 813 scoped_ptr<ScopedVector<contacts::Contact> > contacts_; |
| 814 | 814 |
| 815 // ID of the "My Contacts" contacts group. | 815 // ID of the "My Contacts" contacts group. |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 856 | 856 |
| 857 GDataContactsService::GDataContactsService( | 857 GDataContactsService::GDataContactsService( |
| 858 net::URLRequestContextGetter* url_request_context_getter, | 858 net::URLRequestContextGetter* url_request_context_getter, |
| 859 Profile* profile) | 859 Profile* profile) |
| 860 : url_request_context_getter_(url_request_context_getter), | 860 : url_request_context_getter_(url_request_context_getter), |
| 861 max_photo_downloads_per_second_(kMaxPhotoDownloadsPerSecond), | 861 max_photo_downloads_per_second_(kMaxPhotoDownloadsPerSecond), |
| 862 photo_download_timer_interval_(base::TimeDelta::FromSeconds(1)) { | 862 photo_download_timer_interval_(base::TimeDelta::FromSeconds(1)) { |
| 863 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 863 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 864 std::vector<std::string> scopes; | 864 std::vector<std::string> scopes; |
| 865 scopes.push_back(kContactsScope); | 865 scopes.push_back(kContactsScope); |
| 866 runner_.reset(new google_apis::OperationRunner(profile, | 866 sender_.reset(new google_apis::RequestSender(profile, |
| 867 url_request_context_getter_, | 867 url_request_context_getter_, |
| 868 scopes, | 868 scopes, |
| 869 "" /* custom_user_agent */)); | 869 "" /* custom_user_agent */)); |
| 870 } | 870 } |
| 871 | 871 |
| 872 GDataContactsService::~GDataContactsService() { | 872 GDataContactsService::~GDataContactsService() { |
| 873 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 873 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 874 runner_->CancelAll(); | 874 sender_->CancelAll(); |
| 875 STLDeleteContainerPointers(requests_.begin(), requests_.end()); | 875 STLDeleteContainerPointers(requests_.begin(), requests_.end()); |
| 876 requests_.clear(); | 876 requests_.clear(); |
| 877 } | 877 } |
| 878 | 878 |
| 879 google_apis::AuthService* GDataContactsService::auth_service_for_testing() { | 879 google_apis::AuthService* GDataContactsService::auth_service_for_testing() { |
| 880 return runner_->auth_service(); | 880 return sender_->auth_service(); |
| 881 } | 881 } |
| 882 | 882 |
| 883 void GDataContactsService::Initialize() { | 883 void GDataContactsService::Initialize() { |
| 884 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 884 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 885 runner_->Initialize(); | 885 sender_->Initialize(); |
| 886 } | 886 } |
| 887 | 887 |
| 888 void GDataContactsService::DownloadContacts(SuccessCallback success_callback, | 888 void GDataContactsService::DownloadContacts(SuccessCallback success_callback, |
| 889 FailureCallback failure_callback, | 889 FailureCallback failure_callback, |
| 890 const base::Time& min_update_time) { | 890 const base::Time& min_update_time) { |
| 891 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 891 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 892 DownloadContactsRequest* request = | 892 DownloadContactsRequest* request = |
| 893 new DownloadContactsRequest(this, | 893 new DownloadContactsRequest(this, |
| 894 runner_.get(), | 894 sender_.get(), |
| 895 url_request_context_getter_, | 895 url_request_context_getter_, |
| 896 success_callback, | 896 success_callback, |
| 897 failure_callback, | 897 failure_callback, |
| 898 min_update_time); | 898 min_update_time); |
| 899 VLOG(1) << "Starting contacts download with request " << request; | 899 VLOG(1) << "Starting contacts download with request " << request; |
| 900 requests_.insert(request); | 900 requests_.insert(request); |
| 901 request->Run(); | 901 request->Run(); |
| 902 } | 902 } |
| 903 | 903 |
| 904 void GDataContactsService::OnRequestComplete(DownloadContactsRequest* request) { | 904 void GDataContactsService::OnRequestComplete(DownloadContactsRequest* request) { |
| 905 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 905 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 906 DCHECK(request); | 906 DCHECK(request); |
| 907 VLOG(1) << "Download request " << request << " complete"; | 907 VLOG(1) << "Download request " << request << " complete"; |
| 908 if (!request->my_contacts_group_id().empty()) | 908 if (!request->my_contacts_group_id().empty()) |
| 909 cached_my_contacts_group_id_ = request->my_contacts_group_id(); | 909 cached_my_contacts_group_id_ = request->my_contacts_group_id(); |
| 910 requests_.erase(request); | 910 requests_.erase(request); |
| 911 delete request; | 911 delete request; |
| 912 } | 912 } |
| 913 | 913 |
| 914 } // namespace contacts | 914 } // namespace contacts |
| OLD | NEW |