| 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
|
|
|