| Index: chrome/browser/chromeos/gdata/gdata_contacts_service.cc
|
| diff --git a/chrome/browser/chromeos/gdata/gdata_contacts_service.cc b/chrome/browser/chromeos/gdata/gdata_contacts_service.cc
|
| index fb550dd804bccd8f06a9873689a21280645abe4a..183de396cd9457268283021ecb90958a883a8a54 100644
|
| --- a/chrome/browser/chromeos/gdata/gdata_contacts_service.cc
|
| +++ b/chrome/browser/chromeos/gdata/gdata_contacts_service.cc
|
| @@ -13,6 +13,8 @@
|
| #include "base/logging.h"
|
| #include "base/memory/weak_ptr.h"
|
| #include "base/stl_util.h"
|
| +#include "base/time.h"
|
| +#include "base/timer.h"
|
| #include "base/values.h"
|
| #include "chrome/browser/chromeos/contacts/contact.pb.h"
|
| #include "chrome/browser/chromeos/gdata/gdata_operation_registry.h"
|
| @@ -28,8 +30,9 @@ namespace gdata {
|
|
|
| namespace {
|
|
|
| -// Maximum number of profile photos that we'll download at once.
|
| -const int kMaxSimultaneousPhotoDownloads = 10;
|
| +// Maximum number of profile photos that we'll download per second.
|
| +// At values above 10, Google starts returning 503 errors.
|
| +const int kMaxPhotoDownloadsPerSecond = 10;
|
|
|
| // Field in the top-level object containing the contacts feed.
|
| const char kFeedField[] = "feed";
|
| @@ -319,15 +322,13 @@ class GDataContactsService::DownloadContactsRequest
|
| GDataOperationRunner* runner,
|
| SuccessCallback success_callback,
|
| FailureCallback failure_callback,
|
| - const base::Time& min_update_time,
|
| - int max_simultaneous_photo_downloads)
|
| + const base::Time& min_update_time)
|
| : service_(service),
|
| runner_(runner),
|
| success_callback_(success_callback),
|
| failure_callback_(failure_callback),
|
| min_update_time_(min_update_time),
|
| contacts_(new ScopedVector<contacts::Contact>),
|
| - max_simultaneous_photo_downloads_(max_simultaneous_photo_downloads),
|
| num_in_progress_photo_downloads_(0),
|
| photo_download_failed_(false) {
|
| DCHECK(service_);
|
| @@ -374,6 +375,10 @@ class GDataContactsService::DownloadContactsRequest
|
| return;
|
| }
|
|
|
| + StartPhotoDownloads();
|
| + photo_download_timer_.Start(
|
| + FROM_HERE, service_->photo_download_timer_interval_,
|
| + this, &DownloadContactsRequest::StartPhotoDownloads);
|
| CheckCompletion();
|
| }
|
|
|
| @@ -467,6 +472,7 @@ class GDataContactsService::DownloadContactsRequest
|
| if (contacts_needing_photo_downloads_.empty() &&
|
| num_in_progress_photo_downloads_ == 0) {
|
| VLOG(1) << "Done downloading photos; invoking callback";
|
| + photo_download_timer_.Stop();
|
| if (photo_download_failed_)
|
| failure_callback_.Run();
|
| else
|
| @@ -474,10 +480,14 @@ class GDataContactsService::DownloadContactsRequest
|
| service_->OnRequestComplete(this);
|
| return;
|
| }
|
| + }
|
|
|
| + // Starts photo downloads for contacts in |contacts_needing_photo_downloads_|.
|
| + // Should be invoked only once per second.
|
| + void StartPhotoDownloads() {
|
| while (!contacts_needing_photo_downloads_.empty() &&
|
| (num_in_progress_photo_downloads_ <
|
| - max_simultaneous_photo_downloads_)) {
|
| + service_->max_photo_downloads_per_second_)) {
|
| contacts::Contact* contact = contacts_needing_photo_downloads_.back();
|
| contacts_needing_photo_downloads_.pop_back();
|
| DCHECK(contact_photo_urls_.count(contact));
|
| @@ -505,10 +515,24 @@ class GDataContactsService::DownloadContactsRequest
|
| << " (error=" << error << " size=" << download_data->size() << ")";
|
| num_in_progress_photo_downloads_--;
|
|
|
| + if (error == HTTP_INTERNAL_SERVER_ERROR ||
|
| + error == HTTP_SERVICE_UNAVAILABLE) {
|
| + LOG(WARNING) << "Got error " << error << " while downloading photo "
|
| + << "for " << contact->provider_id() << "; retrying";
|
| + contacts_needing_photo_downloads_.push_back(contact);
|
| + return;
|
| + }
|
| +
|
| + if (error == HTTP_NOT_FOUND) {
|
| + LOG(WARNING) << "Got error " << error << " while downloading photo "
|
| + << "for " << contact->provider_id() << "; skipping";
|
| + CheckCompletion();
|
| + return;
|
| + }
|
| +
|
| if (error != HTTP_SUCCESS) {
|
| LOG(WARNING) << "Got error " << error << " while downloading photo "
|
| - << "for " << contact->provider_id();
|
| - // TODO(derat): Retry several times for temporary failures?
|
| + << "for " << contact->provider_id() << "; giving up";
|
| photo_download_failed_ = true;
|
| // Make sure we don't start any more downloads.
|
| contacts_needing_photo_downloads_.clear();
|
| @@ -537,13 +561,13 @@ class GDataContactsService::DownloadContactsRequest
|
| // Contacts without photos do not appear in this map.
|
| ContactPhotoUrls contact_photo_urls_;
|
|
|
| + // Invokes StartPhotoDownloads() once per second.
|
| + base::RepeatingTimer<DownloadContactsRequest> photo_download_timer_;
|
| +
|
| // Contacts that have photos that we still need to start downloading.
|
| // When we start a download, the contact is removed from this list.
|
| std::vector<contacts::Contact*> contacts_needing_photo_downloads_;
|
|
|
| - // Maximum number of photos we'll try to download at once.
|
| - int max_simultaneous_photo_downloads_;
|
| -
|
| // Number of in-progress photo downloads.
|
| int num_in_progress_photo_downloads_;
|
|
|
| @@ -555,7 +579,8 @@ class GDataContactsService::DownloadContactsRequest
|
|
|
| GDataContactsService::GDataContactsService(Profile* profile)
|
| : runner_(new GDataOperationRunner(profile)),
|
| - max_simultaneous_photo_downloads_(kMaxSimultaneousPhotoDownloads) {
|
| + max_photo_downloads_per_second_(kMaxPhotoDownloadsPerSecond),
|
| + photo_download_timer_interval_(base::TimeDelta::FromSeconds(1)) {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| }
|
|
|
| @@ -584,8 +609,7 @@ void GDataContactsService::DownloadContacts(SuccessCallback success_callback,
|
| runner_.get(),
|
| success_callback,
|
| failure_callback,
|
| - min_update_time,
|
| - max_simultaneous_photo_downloads_);
|
| + min_update_time);
|
| VLOG(1) << "Starting contacts download with request " << request;
|
| requests_.insert(request);
|
| request->Run();
|
|
|