Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(27)

Unified Diff: chrome/browser/services/gcm/gcm_account_tracker.cc

Issue 1293393003: Componentize gcm_account_tracker (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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
« no previous file with comments | « chrome/browser/services/gcm/gcm_account_tracker.h ('k') | chrome/browser/services/gcm/gcm_account_tracker_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698