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 |
deleted file mode 100644 |
index e9d5d0982cb4cef3cc309b43ec4e6bf70f78d723..0000000000000000000000000000000000000000 |
--- a/chrome/browser/services/gcm/gcm_account_tracker.cc |
+++ /dev/null |
@@ -1,376 +0,0 @@ |
-// Copyright 2014 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "chrome/browser/services/gcm/gcm_account_tracker.h" |
- |
-#include <algorithm> |
-#include <vector> |
- |
-#include "base/bind.h" |
-#include "base/location.h" |
-#include "base/single_thread_task_runner.h" |
-#include "base/thread_task_runner_handle.h" |
-#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 { |
- |
-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 reporting interval, when no account changes are detected. |
-const int64 kTokenReportingIntervalMs = 12 * 60 * 60 * 1000; // 12 hours in ms. |
- |
-} // namespace |
- |
-GCMAccountTracker::AccountInfo::AccountInfo(const std::string& email, |
- AccountState state) |
- : email(email), state(state) { |
-} |
- |
-GCMAccountTracker::AccountInfo::~AccountInfo() { |
-} |
- |
-GCMAccountTracker::GCMAccountTracker( |
- scoped_ptr<gaia::AccountTracker> account_tracker, |
- GCMDriver* driver) |
- : OAuth2TokenService::Consumer(kGCMAccountTrackerName), |
- account_tracker_(account_tracker.release()), |
- driver_(driver), |
- shutdown_called_(false), |
- reporting_weak_ptr_factory_(this) { |
-} |
- |
-GCMAccountTracker::~GCMAccountTracker() { |
- DCHECK(shutdown_called_); |
-} |
- |
-void GCMAccountTracker::Shutdown() { |
- 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(); |
- for (std::vector<gaia::AccountIds>::const_iterator iter = accounts.begin(); |
- iter != accounts.end(); |
- ++iter) { |
- if (!iter->email.empty()) { |
- account_infos_.insert(std::make_pair( |
- iter->account_key, AccountInfo(iter->email, TOKEN_NEEDED))); |
- } |
- } |
- |
- if (IsTokenReportingRequired()) |
- ReportTokens(); |
- else |
- ScheduleReportTokens(); |
-} |
- |
-void GCMAccountTracker::ScheduleReportTokens() { |
- // Shortcutting here, in case GCM Driver is not yet connected. In that case |
- // reporting will be scheduled/started when the connection is made. |
- if (!driver_->IsConnected()) |
- return; |
- |
- DVLOG(1) << "Deferring the token reporting for: " |
- << GetTimeToNextTokenReporting().InSeconds() << " seconds."; |
- |
- reporting_weak_ptr_factory_.InvalidateWeakPtrs(); |
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
- FROM_HERE, base::Bind(&GCMAccountTracker::ReportTokens, |
- reporting_weak_ptr_factory_.GetWeakPtr()), |
- GetTimeToNextTokenReporting()); |
-} |
- |
-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. |
-} |
- |
-void GCMAccountTracker::OnAccountRemoved(const gaia::AccountIds& ids) { |
- DVLOG(1) << "Account removed: " << ids.email; |
- // We listen for the account signing out, which happens before account is |
- // removed. |
-} |
- |
-void GCMAccountTracker::OnAccountSignInChanged(const gaia::AccountIds& ids, |
- bool is_signed_in) { |
- if (is_signed_in) |
- OnAccountSignedIn(ids); |
- else |
- OnAccountSignedOut(ids); |
-} |
- |
-void GCMAccountTracker::OnGetTokenSuccess( |
- const OAuth2TokenService::Request* request, |
- const std::string& access_token, |
- const base::Time& expiration_time) { |
- DCHECK(request); |
- DCHECK(!request->GetAccountId().empty()); |
- DVLOG(1) << "Get token success: " << request->GetAccountId(); |
- |
- AccountInfos::iterator iter = account_infos_.find(request->GetAccountId()); |
- DCHECK(iter != account_infos_.end()); |
- if (iter != account_infos_.end()) { |
- DCHECK(iter->second.state == GETTING_TOKEN || |
- iter->second.state == ACCOUNT_REMOVED); |
- // If OnAccountSignedOut(..) was called most recently, account is kept in |
- // ACCOUNT_REMOVED state. |
- if (iter->second.state == GETTING_TOKEN) { |
- iter->second.state = TOKEN_PRESENT; |
- iter->second.access_token = access_token; |
- iter->second.expiration_time = expiration_time; |
- } |
- } |
- |
- DeleteTokenRequest(request); |
- ReportTokens(); |
-} |
- |
-void GCMAccountTracker::OnGetTokenFailure( |
- const OAuth2TokenService::Request* request, |
- const GoogleServiceAuthError& error) { |
- DCHECK(request); |
- DCHECK(!request->GetAccountId().empty()); |
- DVLOG(1) << "Get token failure: " << request->GetAccountId(); |
- |
- AccountInfos::iterator iter = account_infos_.find(request->GetAccountId()); |
- DCHECK(iter != account_infos_.end()); |
- if (iter != account_infos_.end()) { |
- DCHECK(iter->second.state == GETTING_TOKEN || |
- iter->second.state == ACCOUNT_REMOVED); |
- // If OnAccountSignedOut(..) was called most recently, account is kept in |
- // ACCOUNT_REMOVED state. |
- if (iter->second.state == GETTING_TOKEN) { |
- // Given the fetcher has a built in retry logic, consider this situation |
- // to be invalid refresh token, that is only fixed when user signs in. |
- // Once the users signs in properly the minting will retry. |
- iter->second.access_token.clear(); |
- iter->second.state = ACCOUNT_REMOVED; |
- } |
- } |
- |
- DeleteTokenRequest(request); |
- ReportTokens(); |
-} |
- |
-void GCMAccountTracker::OnConnected(const net::IPEndPoint& ip_endpoint) { |
- // We are sure here, that GCM is running and connected. We can start reporting |
- // tokens if reporting is due now, or schedule reporting for later. |
- if (IsTokenReportingRequired()) |
- ReportTokens(); |
- else |
- ScheduleReportTokens(); |
-} |
- |
-void GCMAccountTracker::OnDisconnected() { |
- // We are disconnected, so no point in trying to work with tokens. |
-} |
- |
-void GCMAccountTracker::ReportTokens() { |
- SanitizeTokens(); |
- // Make sure all tokens are valid. |
- if (IsTokenFetchingRequired()) { |
- 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. |
- if (!account_tracker_->IsAllUserInfoFetched() || |
- !pending_token_requests_.empty()) { |
- return; |
- } |
- |
- bool account_removed = false; |
- // 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();) { |
- 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) << "Reporting the tokens to driver: " << account_tokens.size(); |
- driver_->SetAccountTokens(account_tokens); |
- driver_->SetLastTokenFetchTime(base::Time::Now()); |
- ScheduleReportTokens(); |
- } else { |
- DVLOG(1) << "No tokens and nothing removed. Skipping callback."; |
- } |
-} |
- |
-void GCMAccountTracker::SanitizeTokens() { |
- 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(); |
- } |
- } |
-} |
- |
-bool GCMAccountTracker::IsTokenReportingRequired() const { |
- if (GetTimeToNextTokenReporting() == 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::GetTimeToNextTokenReporting() const { |
- base::TimeDelta time_till_next_reporting = |
- driver_->GetLastTokenFetchTime() + |
- base::TimeDelta::FromMilliseconds(kTokenReportingIntervalMs) - |
- base::Time::Now(); |
- |
- // Case when token fetching is overdue. |
- if (time_till_next_reporting < base::TimeDelta()) |
- return base::TimeDelta(); |
- |
- // Case when calculated period is larger than expected, including the |
- // situation when the method is called before GCM driver is completely |
- // initialized. |
- if (time_till_next_reporting > |
- base::TimeDelta::FromMilliseconds(kTokenReportingIntervalMs)) { |
- return base::TimeDelta::FromMilliseconds(kTokenReportingIntervalMs); |
- } |
- |
- return time_till_next_reporting; |
-} |
- |
-void GCMAccountTracker::DeleteTokenRequest( |
- const OAuth2TokenService::Request* request) { |
- ScopedVector<OAuth2TokenService::Request>::iterator iter = std::find( |
- pending_token_requests_.begin(), pending_token_requests_.end(), request); |
- if (iter != pending_token_requests_.end()) |
- pending_token_requests_.erase(iter); |
-} |
- |
-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. |
- if (!driver_->IsConnected()) |
- return; |
- |
- for (AccountInfos::iterator iter = account_infos_.begin(); |
- iter != account_infos_.end(); |
- ++iter) { |
- if (iter->second.state == TOKEN_NEEDED) |
- GetToken(iter); |
- } |
-} |
- |
-void GCMAccountTracker::GetToken(AccountInfos::iterator& account_iter) { |
- DCHECK(GetTokenService()); |
- DCHECK_EQ(account_iter->second.state, TOKEN_NEEDED); |
- |
- OAuth2TokenService::ScopeSet scopes; |
- scopes.insert(kGCMGroupServerScope); |
- scopes.insert(kGCMCheckinServerScope); |
- scoped_ptr<OAuth2TokenService::Request> request = |
- GetTokenService()->StartRequest(account_iter->first, scopes, this); |
- |
- pending_token_requests_.push_back(request.release()); |
- account_iter->second.state = GETTING_TOKEN; |
-} |
- |
-void GCMAccountTracker::OnAccountSignedIn(const gaia::AccountIds& ids) { |
- DVLOG(1) << "Account signed in: " << ids.email; |
- AccountInfos::iterator iter = account_infos_.find(ids.account_key); |
- if (iter == account_infos_.end()) { |
- DCHECK(!ids.email.empty()); |
- account_infos_.insert( |
- std::make_pair(ids.account_key, AccountInfo(ids.email, TOKEN_NEEDED))); |
- } else if (iter->second.state == ACCOUNT_REMOVED) { |
- iter->second.state = TOKEN_NEEDED; |
- } |
- |
- GetAllNeededTokens(); |
-} |
- |
-void GCMAccountTracker::OnAccountSignedOut(const gaia::AccountIds& ids) { |
- DVLOG(1) << "Account signed out: " << ids.email; |
- AccountInfos::iterator iter = account_infos_.find(ids.account_key); |
- if (iter == account_infos_.end()) |
- return; |
- |
- iter->second.access_token.clear(); |
- iter->second.state = ACCOUNT_REMOVED; |
- ReportTokens(); |
-} |
- |
-OAuth2TokenService* GCMAccountTracker::GetTokenService() { |
- DCHECK(account_tracker_->identity_provider()); |
- return account_tracker_->identity_provider()->GetTokenService(); |
-} |
- |
-} // namespace gcm |