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 ca2cda5c401b99616ef8c54a3269489ffb6510de..a2cdba0a05ad13692b32836939b881090bfcf776 100644 |
--- a/chrome/browser/services/gcm/gcm_account_tracker.cc |
+++ b/chrome/browser/services/gcm/gcm_account_tracker.cc |
@@ -8,7 +8,9 @@ |
#include <vector> |
#include "base/time/time.h" |
+#include "components/gcm_driver/gcm_driver.h" |
#include "google_apis/gaia/google_service_auth_error.h" |
+#include "net/base/ip_endpoint.h" |
namespace gcm { |
@@ -17,6 +19,7 @@ const char kGCMGroupServerScope[] = "https://www.googleapis.com/auth/gcm"; |
const char kGCMCheckinServerScope[] = |
"https://www.googleapis.com/auth/android_checkin"; |
const char kGCMAccountTrackerName[] = "gcm_account_tracker"; |
+const int64 kMinimumTokenValidityMs = 500; |
} // namespace |
GCMAccountTracker::AccountInfo::AccountInfo(const std::string& email, |
@@ -29,12 +32,11 @@ GCMAccountTracker::AccountInfo::~AccountInfo() { |
GCMAccountTracker::GCMAccountTracker( |
scoped_ptr<gaia::AccountTracker> account_tracker, |
- const UpdateAccountsCallback& callback) |
+ GCMDriver* driver) |
: OAuth2TokenService::Consumer(kGCMAccountTrackerName), |
account_tracker_(account_tracker.release()), |
- callback_(callback), |
+ driver_(driver), |
shutdown_called_(false) { |
- DCHECK(!callback_.is_null()); |
} |
GCMAccountTracker::~GCMAccountTracker() { |
@@ -42,14 +44,16 @@ GCMAccountTracker::~GCMAccountTracker() { |
} |
void GCMAccountTracker::Shutdown() { |
- Stop(); |
shutdown_called_ = true; |
+ driver_->RemoveConnectionObserver(this); |
+ account_tracker_->RemoveObserver(this); |
account_tracker_->Shutdown(); |
} |
void GCMAccountTracker::Start() { |
DCHECK(!shutdown_called_); |
account_tracker_->AddObserver(this); |
+ driver_->AddConnectionObserver(this); |
std::vector<gaia::AccountIds> accounts = account_tracker_->GetAccounts(); |
if (accounts.empty()) { |
@@ -69,12 +73,6 @@ void GCMAccountTracker::Start() { |
GetAllNeededTokens(); |
} |
-void GCMAccountTracker::Stop() { |
- DCHECK(!shutdown_called_); |
- account_tracker_->RemoveObserver(this); |
- pending_token_requests_.clear(); |
-} |
- |
void GCMAccountTracker::OnAccountAdded(const gaia::AccountIds& ids) { |
DVLOG(1) << "Account added: " << ids.email; |
// We listen for the account signing in, which happens after account is added. |
@@ -112,6 +110,7 @@ void GCMAccountTracker::OnGetTokenSuccess( |
if (iter->second.state == GETTING_TOKEN) { |
iter->second.state = TOKEN_PRESENT; |
iter->second.access_token = access_token; |
+ iter->second.expiration_time = expiration_time; |
} |
} |
@@ -141,8 +140,22 @@ void GCMAccountTracker::OnGetTokenFailure( |
CompleteCollectingTokens(); |
} |
+void GCMAccountTracker::OnConnected(const net::IPEndPoint& ip_endpoint) { |
+ if (SanitizeTokens()) |
+ GetAllNeededTokens(); |
+} |
+ |
+void GCMAccountTracker::OnDisconnected() { |
+ // We are disconnected, so no point in trying to work with tokens. |
+} |
+ |
void GCMAccountTracker::CompleteCollectingTokens() { |
- DCHECK(!callback_.is_null()); |
+ // Make sure all tokens are valid. |
+ if (SanitizeTokens()) { |
+ GetAllNeededTokens(); |
+ return; |
+ } |
+ |
// Wait for gaia::AccountTracker to be done with fetching the user info, as |
// well as all of the pending token requests from GCMAccountTracker to be done |
// before you report the results. |
@@ -152,54 +165,65 @@ void GCMAccountTracker::CompleteCollectingTokens() { |
} |
bool account_removed = false; |
- std::vector<GCMClient::AccountTokenInfo> account_tokens; |
+ // Stop tracking the accounts, that were removed, as it will be reported to |
+ // the driver. |
for (AccountInfos::iterator iter = account_infos_.begin(); |
iter != account_infos_.end();) { |
- switch (iter->second.state) { |
- case ACCOUNT_REMOVED: |
- // We only mark accounts as removed when there was an account that was |
- // explicitly signed out. |
- account_removed = true; |
- // We also stop tracking the account, now that it will be reported as |
- // removed. |
- account_infos_.erase(iter++); |
- break; |
- |
- case TOKEN_PRESENT: { |
- GCMClient::AccountTokenInfo token_info; |
- token_info.account_id = iter->first; |
- token_info.email = iter->second.email; |
- token_info.access_token = iter->second.access_token; |
- account_tokens.push_back(token_info); |
- ++iter; |
- break; |
- } |
- |
- case GETTING_TOKEN: |
- // This should not happen, as we are making a check that there are no |
- // pending requests above. |
- NOTREACHED(); |
- ++iter; |
- break; |
- |
- case TOKEN_NEEDED: |
- // We failed to fetch an access token for the account, but it has not |
- // been signed out (perhaps there is a network issue). We don't report |
- // it, but next time there is a sign-in change we will update its state. |
- ++iter; |
- break; |
+ if (iter->second.state == ACCOUNT_REMOVED) { |
+ account_removed = true; |
+ account_infos_.erase(iter++); |
+ } else { |
+ ++iter; |
+ } |
+ } |
+ |
+ std::vector<GCMClient::AccountTokenInfo> account_tokens; |
+ for (AccountInfos::iterator iter = account_infos_.begin(); |
+ iter != account_infos_.end(); ++iter) { |
+ if (iter->second.state == TOKEN_PRESENT) { |
+ GCMClient::AccountTokenInfo token_info; |
+ token_info.account_id = iter->first; |
+ token_info.email = iter->second.email; |
+ token_info.access_token = iter->second.access_token; |
+ account_tokens.push_back(token_info); |
+ } else { |
+ // This should not happen, as we are making a check that there are no |
+ // pending requests above, stopping tracking of removed accounts, or start |
+ // fetching tokens. |
+ NOTREACHED(); |
} |
} |
// Make sure that there is something to report, otherwise bail out. |
if (!account_tokens.empty() || account_removed) { |
- DVLOG(1) << "Calling callback: " << account_tokens.size(); |
- callback_.Run(account_tokens); |
+ DVLOG(1) << "Reporting the tokens to driver: " << account_tokens.size(); |
+ driver_->SetAccountTokens(account_tokens); |
} else { |
DVLOG(1) << "No tokens and nothing removed. Skipping callback."; |
} |
} |
+bool GCMAccountTracker::SanitizeTokens() { |
+ bool tokens_needed = false; |
+ for (AccountInfos::iterator iter = account_infos_.begin(); |
+ iter != account_infos_.end(); |
+ ++iter) { |
+ if (iter->second.state == TOKEN_PRESENT && |
+ iter->second.expiration_time < |
+ base::Time::Now() + |
+ base::TimeDelta::FromMilliseconds(kMinimumTokenValidityMs)) { |
+ iter->second.access_token.clear(); |
+ iter->second.state = TOKEN_NEEDED; |
+ iter->second.expiration_time = base::Time(); |
+ } |
+ |
+ if (iter->second.state == TOKEN_NEEDED) |
+ tokens_needed = true; |
+ } |
+ |
+ return tokens_needed; |
+} |
+ |
void GCMAccountTracker::DeleteTokenRequest( |
const OAuth2TokenService::Request* request) { |
ScopedVector<OAuth2TokenService::Request>::iterator iter = std::find( |
@@ -209,6 +233,11 @@ 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 (!driver_->IsConnected()) |
+ return; |
+ |
for (AccountInfos::iterator iter = account_infos_.begin(); |
iter != account_infos_.end(); |
++iter) { |