Chromium Code Reviews| Index: chrome/browser/services/gcm/gcm_account_tracker.cc |
| diff --git a/chrome/browser/services/gcm/gcm_account_tracker.cc b/chrome/browser/services/gcm/gcm_account_tracker.cc |
| index a2cdba0a05ad13692b32836939b881090bfcf776..d64ec0ef5574d58c2c4bdc24e861b37928a97b37 100644 |
| --- a/chrome/browser/services/gcm/gcm_account_tracker.cc |
| +++ b/chrome/browser/services/gcm/gcm_account_tracker.cc |
| @@ -15,11 +15,18 @@ |
| namespace gcm { |
| namespace { |
| + |
| +// Scopes needed by the OAuth2 access tokens. |
| const char kGCMGroupServerScope[] = "https://www.googleapis.com/auth/gcm"; |
| const char kGCMCheckinServerScope[] = |
| "https://www.googleapis.com/auth/android_checkin"; |
| +// Name of the GCM account tracker for the OAuth2TokenService. |
| const char kGCMAccountTrackerName[] = "gcm_account_tracker"; |
| +// Minimum token validity when sending to GCM groups server. |
| const int64 kMinimumTokenValidityMs = 500; |
| +// Token fetching interval, when no account changes are detected. |
| +const int64 kTokenFetchingIntervalMs = 12 * 60 * 60 * 1000; // 12 hours in ms. |
| + |
| } // namespace |
| GCMAccountTracker::AccountInfo::AccountInfo(const std::string& email, |
| @@ -36,7 +43,8 @@ GCMAccountTracker::GCMAccountTracker( |
| : OAuth2TokenService::Consumer(kGCMAccountTrackerName), |
| account_tracker_(account_tracker.release()), |
| driver_(driver), |
| - shutdown_called_(false) { |
| + shutdown_called_(false), |
| + weak_ptr_factory_(this) { |
| } |
| GCMAccountTracker::~GCMAccountTracker() { |
| @@ -56,11 +64,6 @@ void GCMAccountTracker::Start() { |
| driver_->AddConnectionObserver(this); |
| std::vector<gaia::AccountIds> accounts = account_tracker_->GetAccounts(); |
| - if (accounts.empty()) { |
| - CompleteCollectingTokens(); |
| - return; |
| - } |
| - |
| for (std::vector<gaia::AccountIds>::const_iterator iter = accounts.begin(); |
| iter != accounts.end(); |
| ++iter) { |
| @@ -70,7 +73,23 @@ void GCMAccountTracker::Start() { |
| } |
| } |
| - GetAllNeededTokens(); |
| + ScheduleFetchingTokens(); |
| +} |
| + |
| +void GCMAccountTracker::ScheduleFetchingTokens() { |
| + if (!IsTokenReportingRequired()) { |
| + DVLOG(1) << "Deferring the token fetching for: " |
| + << GetTimeToNextTokenFetching().InSeconds() << " seconds."; |
| + base::MessageLoop::current()->PostDelayedTask( |
| + FROM_HERE, |
| + base::Bind(&GCMAccountTracker::ReportTokens, |
| + weak_ptr_factory_.GetWeakPtr()), |
| + GetTimeToNextTokenFetching()); |
| + return; |
| + } |
| + |
| + DVLOG(1) << "Token fetching is due calling Complete immediately."; |
| + ReportTokens(); |
| } |
| void GCMAccountTracker::OnAccountAdded(const gaia::AccountIds& ids) { |
| @@ -115,7 +134,7 @@ void GCMAccountTracker::OnGetTokenSuccess( |
| } |
| DeleteTokenRequest(request); |
| - CompleteCollectingTokens(); |
| + ReportTokens(); |
| } |
| void GCMAccountTracker::OnGetTokenFailure( |
| @@ -137,21 +156,22 @@ void GCMAccountTracker::OnGetTokenFailure( |
| } |
| DeleteTokenRequest(request); |
| - CompleteCollectingTokens(); |
| + ReportTokens(); |
| } |
| void GCMAccountTracker::OnConnected(const net::IPEndPoint& ip_endpoint) { |
| - if (SanitizeTokens()) |
| - GetAllNeededTokens(); |
| + if (IsTokenReportingRequired()) |
| + ReportTokens(); |
| } |
| void GCMAccountTracker::OnDisconnected() { |
| // We are disconnected, so no point in trying to work with tokens. |
| } |
| -void GCMAccountTracker::CompleteCollectingTokens() { |
| +void GCMAccountTracker::ReportTokens() { |
| + SanitizeTokens(); |
|
Nicolas Zea
2014/11/06 21:43:17
Why do we ignore the return value now and use IsTo
fgorski
2014/11/07 01:42:12
I think that was the comment we discussed with one
|
| // Make sure all tokens are valid. |
| - if (SanitizeTokens()) { |
| + if (IsTokenFetchingRequired()) { |
| GetAllNeededTokens(); |
| return; |
| } |
| @@ -198,6 +218,13 @@ void GCMAccountTracker::CompleteCollectingTokens() { |
| if (!account_tokens.empty() || account_removed) { |
| DVLOG(1) << "Reporting the tokens to driver: " << account_tokens.size(); |
| driver_->SetAccountTokens(account_tokens); |
| + driver_->SetLastTokenFetchTime(base::Time::Now()); |
| + weak_ptr_factory_.InvalidateWeakPtrs(); |
| + base::MessageLoop::current()->PostDelayedTask( |
| + FROM_HERE, |
| + base::Bind(&GCMAccountTracker::ReportTokens, |
| + weak_ptr_factory_.GetWeakPtr()), |
| + GetTimeToNextTokenFetching()); |
| } else { |
| DVLOG(1) << "No tokens and nothing removed. Skipping callback."; |
| } |
| @@ -224,6 +251,42 @@ bool GCMAccountTracker::SanitizeTokens() { |
| return tokens_needed; |
| } |
| +bool GCMAccountTracker::IsTokenReportingRequired() const { |
| + if (GetTimeToNextTokenFetching() == base::TimeDelta()) |
| + return true; |
| + |
| + bool reporting_required = false; |
| + for (AccountInfos::const_iterator iter = account_infos_.begin(); |
| + iter != account_infos_.end(); |
| + ++iter) { |
| + if (iter->second.state == ACCOUNT_REMOVED) |
| + reporting_required = true; |
| + } |
| + |
| + return reporting_required; |
| +} |
| + |
| +bool GCMAccountTracker::IsTokenFetchingRequired() const { |
| + bool token_needed = false; |
| + for (AccountInfos::const_iterator iter = account_infos_.begin(); |
| + iter != account_infos_.end(); |
| + ++iter) { |
| + if (iter->second.state == TOKEN_NEEDED) |
| + token_needed = true; |
| + } |
| + |
| + return token_needed; |
| +} |
| + |
| +base::TimeDelta GCMAccountTracker::GetTimeToNextTokenFetching() const { |
| + base::TimeDelta time_till_next_fetching = |
| + driver_->GetLastTokenFetchTime() + |
| + base::TimeDelta::FromMilliseconds(kTokenFetchingIntervalMs) - |
| + base::Time::Now(); |
| + return time_till_next_fetching < base::TimeDelta() ? base::TimeDelta() |
| + : time_till_next_fetching; |
| +} |
| + |
| void GCMAccountTracker::DeleteTokenRequest( |
| const OAuth2TokenService::Request* request) { |
| ScopedVector<OAuth2TokenService::Request>::iterator iter = std::find( |
| @@ -235,6 +298,9 @@ void GCMAccountTracker::DeleteTokenRequest( |
| void GCMAccountTracker::GetAllNeededTokens() { |
| // Only start fetching tokens if driver is running, they have a limited |
| // validity time and GCM connection is a good indication of network running. |
| + // If the GetAllNeededTokens was called as part of periodic schedule, it may |
| + // not have network. In that case the next network change will trigger token |
| + // fetching. |
|
Nicolas Zea
2014/11/06 21:43:17
What code is listening to the network change?
fgorski
2014/11/07 01:42:12
Lines 162:169 above.
|
| if (!driver_->IsConnected()) |
| return; |
| @@ -282,7 +348,7 @@ void GCMAccountTracker::OnAccountSignedOut(const gaia::AccountIds& ids) { |
| iter->second.access_token.clear(); |
| iter->second.state = ACCOUNT_REMOVED; |
| - CompleteCollectingTokens(); |
| + ReportTokens(); |
| } |
| OAuth2TokenService* GCMAccountTracker::GetTokenService() { |