summaryrefslogtreecommitdiff
path: root/chromium/components/signin
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2017-04-05 17:15:33 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2017-04-11 07:47:18 +0000
commit7324afb043a0b1e623d8e8eb906cdc53bdeb4685 (patch)
treea3fe2d74ea9c9e142c390dac4ca0e219382ace46 /chromium/components/signin
parent6a4cabb866f66d4128a97cdc6d9d08ce074f1247 (diff)
downloadqtwebengine-chromium-7324afb043a0b1e623d8e8eb906cdc53bdeb4685.tar.gz
BASELINE: Update Chromium to 58.0.3029.54
Change-Id: I67f57065a7afdc8e4614adb5c0230281428df4d1 Reviewed-by: Peter Varga <pvarga@inf.u-szeged.hu>
Diffstat (limited to 'chromium/components/signin')
-rw-r--r--chromium/components/signin/core/browser/BUILD.gn7
-rw-r--r--chromium/components/signin/core/browser/DEPS1
-rw-r--r--chromium/components/signin/core/browser/about_signin_internals.cc33
-rw-r--r--chromium/components/signin/core/browser/about_signin_internals.h4
-rw-r--r--chromium/components/signin/core/browser/access_token_fetcher.cc169
-rw-r--r--chromium/components/signin/core/browser/access_token_fetcher.h85
-rw-r--r--chromium/components/signin/core/browser/access_token_fetcher_unittest.cc390
-rw-r--r--chromium/components/signin/core/browser/account_tracker_service.cc12
-rw-r--r--chromium/components/signin/core/browser/account_tracker_service_unittest.cc6
-rw-r--r--chromium/components/signin/core/browser/device_activity_fetcher.cc204
-rw-r--r--chromium/components/signin/core/browser/device_activity_fetcher.h81
-rw-r--r--chromium/components/signin/core/browser/fake_profile_oauth2_token_service.cc7
-rw-r--r--chromium/components/signin/core/browser/fake_profile_oauth2_token_service.h3
-rw-r--r--chromium/components/signin/core/browser/fake_signin_manager.h1
-rw-r--r--chromium/components/signin/core/browser/gaia_cookie_manager_service.cc45
-rw-r--r--chromium/components/signin/core/browser/profile_oauth2_token_service.cc28
-rw-r--r--chromium/components/signin/core/browser/profile_oauth2_token_service.h3
-rw-r--r--chromium/components/signin/core/browser/signin_client.cc4
-rw-r--r--chromium/components/signin/core/browser/signin_client.h4
-rw-r--r--chromium/components/signin/core/browser/signin_header_helper.cc4
-rw-r--r--chromium/components/signin/core/browser/signin_internals_util.h8
-rw-r--r--chromium/components/signin/core/browser/signin_manager.cc3
-rw-r--r--chromium/components/signin/core/browser/signin_manager_base.cc4
-rw-r--r--chromium/components/signin/core/browser/webdata/token_service_table.cc46
-rw-r--r--chromium/components/signin/core/browser/webdata/token_service_table.h9
-rw-r--r--chromium/components/signin/core/browser/webdata/token_web_data.cc13
-rw-r--r--chromium/components/signin/core/browser/webdata/token_web_data.h11
27 files changed, 811 insertions, 374 deletions
diff --git a/chromium/components/signin/core/browser/BUILD.gn b/chromium/components/signin/core/browser/BUILD.gn
index a381719d0ba..5265026b314 100644
--- a/chromium/components/signin/core/browser/BUILD.gn
+++ b/chromium/components/signin/core/browser/BUILD.gn
@@ -10,6 +10,8 @@ static_library("browser") {
sources = [
"about_signin_internals.cc",
"about_signin_internals.h",
+ "access_token_fetcher.cc",
+ "access_token_fetcher.h",
"account_fetcher_service.cc",
"account_fetcher_service.h",
"account_info.cc",
@@ -30,8 +32,6 @@ static_library("browser") {
"child_account_info_fetcher_android.h",
"child_account_info_fetcher_impl.cc",
"child_account_info_fetcher_impl.h",
- "device_activity_fetcher.cc",
- "device_activity_fetcher.h",
"gaia_cookie_manager_service.cc",
"gaia_cookie_manager_service.h",
"profile_identity_provider.cc",
@@ -83,6 +83,7 @@ static_library("browser") {
"//base:i18n",
"//components/content_settings/core/browser",
"//components/content_settings/core/common",
+ "//components/data_use_measurement/core",
"//components/google/core/browser",
"//components/invalidation/public",
"//components/keyed_service/core",
@@ -146,6 +147,7 @@ static_library("test_support") {
source_set("unit_tests") {
testonly = true
sources = [
+ "access_token_fetcher_unittest.cc",
"account_info_unittest.cc",
"account_investigator_unittest.cc",
"account_tracker_service_unittest.cc",
@@ -160,6 +162,7 @@ source_set("unit_tests") {
deps = [
":test_support",
+ "//base/test:test_support",
"//components/content_settings/core/browser",
"//components/os_crypt:test_support",
"//components/pref_registry:pref_registry",
diff --git a/chromium/components/signin/core/browser/DEPS b/chromium/components/signin/core/browser/DEPS
index 2619fdcfa73..8ca3732081c 100644
--- a/chromium/components/signin/core/browser/DEPS
+++ b/chromium/components/signin/core/browser/DEPS
@@ -1,4 +1,5 @@
include_rules = [
+ "+components/data_use_measurement/core",
"+components/invalidation/public",
"+components/metrics",
"+google/cacheinvalidation",
diff --git a/chromium/components/signin/core/browser/about_signin_internals.cc b/chromium/components/signin/core/browser/about_signin_internals.cc
index ec21740ccb8..d925e375482 100644
--- a/chromium/components/signin/core/browser/about_signin_internals.cc
+++ b/chromium/components/signin/core/browser/about_signin_internals.cc
@@ -28,6 +28,7 @@
#include "components/signin/core/browser/signin_manager.h"
#include "components/signin/core/common/profile_management_switches.h"
#include "components/signin/core/common/signin_switches.h"
+#include "google_apis/gaia/oauth2_token_service_delegate.h"
#include "net/base/backoff_entry.h"
using base::Time;
@@ -88,6 +89,30 @@ std::string SigninStatusFieldToLabel(UntimedSigninStatusField field) {
return std::string();
}
+std::string TokenServiceLoadCredentialsStateToLabel(
+ OAuth2TokenServiceDelegate::LoadCredentialsState state) {
+ switch (state) {
+ case OAuth2TokenServiceDelegate::LOAD_CREDENTIALS_UNKNOWN:
+ return "Unknown";
+ case OAuth2TokenServiceDelegate::LOAD_CREDENTIALS_NOT_STARTED:
+ return "Load credentials not started";
+ case OAuth2TokenServiceDelegate::LOAD_CREDENTIALS_IN_PROGRESS:
+ return "Load credentials in progress";
+ case OAuth2TokenServiceDelegate::LOAD_CREDENTIALS_FINISHED_WITH_SUCCESS:
+ return "Load credentials finished with success";
+ case OAuth2TokenServiceDelegate::LOAD_CREDENTIALS_FINISHED_WITH_DB_ERRORS:
+ return "Load credentials failed with database errors";
+ case OAuth2TokenServiceDelegate::
+ LOAD_CREDENTIALS_FINISHED_WITH_DECRYPT_ERRORS:
+ return "Load credentials failed with decrypt errors";
+ case OAuth2TokenServiceDelegate::
+ LOAD_CREDENTIALS_FINISHED_WITH_UNKNOWN_ERRORS:
+ return "Load credentials failed with unknown errors";
+ }
+ NOTREACHED();
+ return std::string();
+}
+
#if !defined (OS_CHROMEOS)
std::string SigninStatusFieldToLabel(TimedSigninStatusField field) {
switch (field) {
@@ -334,6 +359,10 @@ void AboutSigninInternals::OnFetchAccessTokenComplete(
NotifyObservers();
}
+void AboutSigninInternals::OnRefreshTokensLoaded() {
+ NotifyObservers();
+}
+
void AboutSigninInternals::OnTokenRemoved(
const std::string& account_id,
const OAuth2TokenService::ScopeSet& scopes) {
@@ -514,6 +543,10 @@ AboutSigninInternals::SigninStatus::ToValue(
switches::IsEnableAccountConsistency() == true ? "On" : "Off");
AddSectionEntry(basic_info, "Signin Status",
signin_manager->IsAuthenticated() ? "Signed In" : "Not Signed In");
+ OAuth2TokenServiceDelegate::LoadCredentialsState load_tokens_state =
+ token_service->GetDelegate()->GetLoadCredentialsState();
+ AddSectionEntry(basic_info, "TokenService Status",
+ TokenServiceLoadCredentialsStateToLabel(load_tokens_state));
// TODO(robliao): Remove ScopedTracker below once https://crbug.com/422460 is
// fixed.
diff --git a/chromium/components/signin/core/browser/about_signin_internals.h b/chromium/components/signin/core/browser/about_signin_internals.h
index 3caeb6ebd3e..8e42feab409 100644
--- a/chromium/components/signin/core/browser/about_signin_internals.h
+++ b/chromium/components/signin/core/browser/about_signin_internals.h
@@ -37,6 +37,7 @@ using TimedSigninStatusValue = std::pair<std::string, std::string>;
class AboutSigninInternals
: public KeyedService,
public signin_internals_util::SigninDiagnosticsObserver,
+ public OAuth2TokenService::Observer,
public OAuth2TokenService::DiagnosticsObserver,
public GaiaCookieManagerService::Observer,
SigninManagerBase::Observer,
@@ -184,6 +185,9 @@ class AboutSigninInternals
void OnTokenRemoved(const std::string& account_id,
const OAuth2TokenService::ScopeSet& scopes) override;
+ // OAuth2TokenServiceDelegate::Observer implementations.
+ void OnRefreshTokensLoaded() override;
+
// SigninManagerBase::Observer implementations.
void GoogleSigninFailed(const GoogleServiceAuthError& error) override;
void GoogleSigninSucceeded(const std::string& account_id,
diff --git a/chromium/components/signin/core/browser/access_token_fetcher.cc b/chromium/components/signin/core/browser/access_token_fetcher.cc
new file mode 100644
index 00000000000..d301d3708da
--- /dev/null
+++ b/chromium/components/signin/core/browser/access_token_fetcher.cc
@@ -0,0 +1,169 @@
+// Copyright 2017 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 "components/signin/core/browser/access_token_fetcher.h"
+
+#include <utility>
+
+#include "base/logging.h"
+
+AccessTokenFetcher::AccessTokenFetcher(
+ const std::string& oauth_consumer_name,
+ SigninManagerBase* signin_manager,
+ OAuth2TokenService* token_service,
+ const OAuth2TokenService::ScopeSet& scopes,
+ TokenCallback callback)
+ : OAuth2TokenService::Consumer(oauth_consumer_name),
+ signin_manager_(signin_manager),
+ token_service_(token_service),
+ scopes_(scopes),
+ callback_(std::move(callback)),
+ waiting_for_sign_in_(false),
+ waiting_for_refresh_token_(false),
+ access_token_retried_(false) {
+ Start();
+}
+
+AccessTokenFetcher::~AccessTokenFetcher() {
+ if (waiting_for_sign_in_) {
+ signin_manager_->RemoveObserver(this);
+ }
+ if (waiting_for_refresh_token_) {
+ token_service_->RemoveObserver(this);
+ }
+}
+
+void AccessTokenFetcher::Start() {
+ if (signin_manager_->IsAuthenticated()) {
+ // Already signed in: Make sure we have a refresh token, then get the access
+ // token.
+ WaitForRefreshToken();
+ return;
+ }
+
+ // Not signed in: Wait for a sign-in to complete (to get the refresh token),
+ // then get the access token.
+ DCHECK(!waiting_for_sign_in_);
+ waiting_for_sign_in_ = true;
+ signin_manager_->AddObserver(this);
+}
+
+void AccessTokenFetcher::WaitForRefreshToken() {
+ DCHECK(signin_manager_->IsAuthenticated());
+ DCHECK(!waiting_for_refresh_token_);
+
+ if (token_service_->RefreshTokenIsAvailable(
+ signin_manager_->GetAuthenticatedAccountId())) {
+ // Already have refresh token: Get the access token directly.
+ StartAccessTokenRequest();
+ return;
+ }
+
+ // Signed in, but refresh token isn't there yet: Wait for the refresh
+ // token to be loaded, then get the access token.
+ waiting_for_refresh_token_ = true;
+ token_service_->AddObserver(this);
+}
+
+void AccessTokenFetcher::StartAccessTokenRequest() {
+ // Note: We might get here even in cases where we know that there's no refresh
+ // token. We're requesting an access token anyway, so that the token service
+ // will generate an appropriate error code that we can return to the client.
+ DCHECK(!access_token_request_);
+ access_token_request_ = token_service_->StartRequest(
+ signin_manager_->GetAuthenticatedAccountId(), scopes_, this);
+}
+
+void AccessTokenFetcher::GoogleSigninSucceeded(const std::string& account_id,
+ const std::string& username,
+ const std::string& password) {
+ DCHECK(waiting_for_sign_in_);
+ DCHECK(!waiting_for_refresh_token_);
+ DCHECK(signin_manager_->IsAuthenticated());
+ waiting_for_sign_in_ = false;
+ signin_manager_->RemoveObserver(this);
+
+ WaitForRefreshToken();
+}
+
+void AccessTokenFetcher::GoogleSigninFailed(
+ const GoogleServiceAuthError& error) {
+ DCHECK(waiting_for_sign_in_);
+ DCHECK(!waiting_for_refresh_token_);
+ waiting_for_sign_in_ = false;
+ signin_manager_->RemoveObserver(this);
+
+ std::move(callback_).Run(error, std::string());
+}
+
+void AccessTokenFetcher::OnRefreshTokenAvailable(
+ const std::string& account_id) {
+ DCHECK(waiting_for_refresh_token_);
+ DCHECK(!waiting_for_sign_in_);
+
+ // Only react on tokens for the account the user has signed in with.
+ if (account_id != signin_manager_->GetAuthenticatedAccountId()) {
+ return;
+ }
+
+ waiting_for_refresh_token_ = false;
+ token_service_->RemoveObserver(this);
+ StartAccessTokenRequest();
+}
+
+void AccessTokenFetcher::OnRefreshTokensLoaded() {
+ DCHECK(waiting_for_refresh_token_);
+ DCHECK(!waiting_for_sign_in_);
+ DCHECK(!access_token_request_);
+
+ // All refresh tokens were loaded, but we didn't get one for the account we
+ // care about. We probably won't get one any time soon.
+ // Attempt to fetch an access token anyway, so that the token service will
+ // provide us with an appropriate error code.
+ waiting_for_refresh_token_ = false;
+ token_service_->RemoveObserver(this);
+ StartAccessTokenRequest();
+}
+
+void AccessTokenFetcher::OnGetTokenSuccess(
+ const OAuth2TokenService::Request* request,
+ const std::string& access_token,
+ const base::Time& expiration_time) {
+ DCHECK_EQ(request, access_token_request_.get());
+ std::unique_ptr<OAuth2TokenService::Request> request_deleter(
+ std::move(access_token_request_));
+
+ std::move(callback_).Run(GoogleServiceAuthError::AuthErrorNone(),
+ access_token);
+}
+
+void AccessTokenFetcher::OnGetTokenFailure(
+ const OAuth2TokenService::Request* request,
+ const GoogleServiceAuthError& error) {
+ DCHECK_EQ(request, access_token_request_.get());
+ std::unique_ptr<OAuth2TokenService::Request> request_deleter(
+ std::move(access_token_request_));
+
+ // There is a special case for Android that RefreshTokenIsAvailable and
+ // StartRequest are called to pre-fetch the account image and name before
+ // sign-in. In that case, our ongoing access token request gets cancelled.
+ // Moreover, OnRefreshTokenAvailable might happen after startup when the
+ // credentials are changed/updated.
+ // To handle these cases, we retry a canceled request once.
+ // However, a request may also get cancelled for legitimate reasons, e.g.
+ // because the user signed out. In those cases, there's no point in retrying,
+ // so only retry if there (still) is a valid refresh token.
+ // NOTE: Maybe we should retry for all transient errors here, so that clients
+ // don't have to.
+ if (!access_token_retried_ &&
+ error.state() == GoogleServiceAuthError::State::REQUEST_CANCELED &&
+ token_service_->RefreshTokenIsAvailable(
+ signin_manager_->GetAuthenticatedAccountId())) {
+ access_token_retried_ = true;
+ StartAccessTokenRequest();
+ return;
+ }
+
+ std::move(callback_).Run(error, std::string());
+}
diff --git a/chromium/components/signin/core/browser/access_token_fetcher.h b/chromium/components/signin/core/browser/access_token_fetcher.h
new file mode 100644
index 00000000000..2963ab8b797
--- /dev/null
+++ b/chromium/components/signin/core/browser/access_token_fetcher.h
@@ -0,0 +1,85 @@
+// Copyright 2017 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.
+
+#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_ACCESS_TOKEN_FETCHER_H_
+#define COMPONENTS_SIGNIN_CORE_BROWSER_ACCESS_TOKEN_FETCHER_H_
+
+#include <memory>
+#include <string>
+
+#include "base/callback.h"
+#include "base/macros.h"
+#include "components/signin/core/browser/signin_manager_base.h"
+#include "google_apis/gaia/google_service_auth_error.h"
+#include "google_apis/gaia/oauth2_token_service.h"
+
+// Helper class to ease the task of obtaining an OAuth2 access token for the
+// authenticated account. This handles various special cases, e.g. when the
+// refresh token isn't loaded yet (during startup), or when there is some
+// transient error.
+// May only be used on the UI thread.
+class AccessTokenFetcher : public SigninManagerBase::Observer,
+ public OAuth2TokenService::Observer,
+ public OAuth2TokenService::Consumer {
+ public:
+ // Callback for when a request completes (successful or not). On successful
+ // requests, |error| is NONE and |access_token| contains the obtained OAuth2
+ // access token. On failed requests, |error| contains the actual error and
+ // |access_token| is empty.
+ using TokenCallback =
+ base::OnceCallback<void(const GoogleServiceAuthError& error,
+ const std::string& access_token)>;
+
+ // Instantiates a fetcher and immediately starts the process of obtaining an
+ // OAuth2 access token for the given |scopes|. The |callback| is called once
+ // the request completes (successful or not). If the AccessTokenFetcher is
+ // destroyed before the process completes, the callback is not called.
+ AccessTokenFetcher(const std::string& oauth_consumer_name,
+ SigninManagerBase* signin_manager,
+ OAuth2TokenService* token_service,
+ const OAuth2TokenService::ScopeSet& scopes,
+ TokenCallback callback);
+
+ ~AccessTokenFetcher() override;
+
+ private:
+ void Start();
+
+ void WaitForRefreshToken();
+ void StartAccessTokenRequest();
+
+ // SigninManagerBase::Observer implementation.
+ void GoogleSigninSucceeded(const std::string& account_id,
+ const std::string& username,
+ const std::string& password) override;
+ void GoogleSigninFailed(const GoogleServiceAuthError& error) override;
+
+ // OAuth2TokenService::Observer implementation.
+ void OnRefreshTokenAvailable(const std::string& account_id) override;
+ void OnRefreshTokensLoaded() override;
+
+ // OAuth2TokenService::Consumer implementation.
+ void OnGetTokenSuccess(const OAuth2TokenService::Request* request,
+ const std::string& access_token,
+ const base::Time& expiration_time) override;
+ void OnGetTokenFailure(const OAuth2TokenService::Request* request,
+ const GoogleServiceAuthError& error) override;
+
+ SigninManagerBase* signin_manager_;
+ OAuth2TokenService* token_service_;
+ OAuth2TokenService::ScopeSet scopes_;
+ TokenCallback callback_;
+
+ bool waiting_for_sign_in_;
+ bool waiting_for_refresh_token_;
+
+ std::unique_ptr<OAuth2TokenService::Request> access_token_request_;
+
+ // When a token request gets canceled, we want to retry once.
+ bool access_token_retried_;
+
+ DISALLOW_COPY_AND_ASSIGN(AccessTokenFetcher);
+};
+
+#endif // COMPONENTS_SIGNIN_CORE_BROWSER_ACCESS_TOKEN_FETCHER_H_
diff --git a/chromium/components/signin/core/browser/access_token_fetcher_unittest.cc b/chromium/components/signin/core/browser/access_token_fetcher_unittest.cc
new file mode 100644
index 00000000000..331468b0e15
--- /dev/null
+++ b/chromium/components/signin/core/browser/access_token_fetcher_unittest.cc
@@ -0,0 +1,390 @@
+// Copyright 2017 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 "components/signin/core/browser/access_token_fetcher.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
+#include "base/test/mock_callback.h"
+#include "components/prefs/testing_pref_service.h"
+#include "components/signin/core/browser/account_tracker_service.h"
+#include "components/signin/core/browser/fake_profile_oauth2_token_service.h"
+#include "components/signin/core/browser/fake_signin_manager.h"
+#include "components/signin/core/browser/test_signin_client.h"
+#include "components/sync_preferences/testing_pref_service_syncable.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gmock_mutant.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using base::MockCallback;
+using sync_preferences::TestingPrefServiceSyncable;
+using testing::CallbackToFunctor;
+using testing::InvokeWithoutArgs;
+using testing::StrictMock;
+
+#if defined(OS_CHROMEOS)
+// ChromeOS doesn't have SigninManager.
+using SigninManagerForTest = FakeSigninManagerBase;
+#else
+using SigninManagerForTest = FakeSigninManager;
+#endif // OS_CHROMEOS
+
+class AccessTokenFetcherTest : public testing::Test {
+ public:
+ using TestTokenCallback =
+ StrictMock<MockCallback<AccessTokenFetcher::TokenCallback>>;
+
+ AccessTokenFetcherTest() : signin_client_(&pref_service_) {
+ AccountTrackerService::RegisterPrefs(pref_service_.registry());
+#if defined(OS_CHROMEOS)
+ SigninManagerBase::RegisterProfilePrefs(pref_service_.registry());
+ SigninManagerBase::RegisterPrefs(pref_service_.registry());
+#else
+ SigninManager::RegisterProfilePrefs(pref_service_.registry());
+ SigninManager::RegisterPrefs(pref_service_.registry());
+#endif // OS_CHROMEOS
+
+ account_tracker_ = base::MakeUnique<AccountTrackerService>();
+ account_tracker_->Initialize(&signin_client_);
+
+#if defined(OS_CHROMEOS)
+ signin_manager_ = base::MakeUnique<FakeSigninManagerBase>(
+ &signin_client_, account_tracker_.get());
+#else
+ signin_manager_ = base::MakeUnique<FakeSigninManager>(
+ &signin_client_, &token_service_, account_tracker_.get(),
+ /*cookie_manager_service=*/nullptr);
+#endif // OS_CHROMEOS
+ }
+
+ ~AccessTokenFetcherTest() override {}
+
+ std::unique_ptr<AccessTokenFetcher> CreateFetcher(
+ AccessTokenFetcher::TokenCallback callback) {
+ std::set<std::string> scopes{"scope"};
+ return base::MakeUnique<AccessTokenFetcher>(
+ "test_consumer", signin_manager_.get(), &token_service_, scopes,
+ std::move(callback));
+ }
+
+ FakeProfileOAuth2TokenService* token_service() { return &token_service_; }
+ SigninManagerForTest* signin_manager() { return signin_manager_.get(); }
+
+ void SignIn(const std::string& account) {
+#if defined(OS_CHROMEOS)
+ signin_manager_->SignIn(account);
+#else
+ signin_manager_->SignIn(account, "user", "pass");
+#endif // OS_CHROMEOS
+ }
+
+ private:
+ TestingPrefServiceSyncable pref_service_;
+ TestSigninClient signin_client_;
+ FakeProfileOAuth2TokenService token_service_;
+
+ std::unique_ptr<AccountTrackerService> account_tracker_;
+ std::unique_ptr<SigninManagerForTest> signin_manager_;
+};
+
+TEST_F(AccessTokenFetcherTest, ShouldReturnAccessToken) {
+ TestTokenCallback callback;
+
+ SignIn("account");
+ token_service()->GetDelegate()->UpdateCredentials("account", "refresh token");
+
+ // Signed in and refresh token already exists, so this should result in a
+ // request for an access token.
+ auto fetcher = CreateFetcher(callback.Get());
+
+ // Once the access token request is fulfilled, we should get called back with
+ // the access token.
+ EXPECT_CALL(callback,
+ Run(GoogleServiceAuthError::AuthErrorNone(), "access token"));
+ token_service()->IssueAllTokensForAccount(
+ "account", "access token",
+ base::Time::Now() + base::TimeDelta::FromHours(1));
+}
+
+TEST_F(AccessTokenFetcherTest, ShouldNotReplyIfDestroyed) {
+ TestTokenCallback callback;
+
+ SignIn("account");
+ token_service()->GetDelegate()->UpdateCredentials("account", "refresh token");
+
+ // Signed in and refresh token already exists, so this should result in a
+ // request for an access token.
+ auto fetcher = CreateFetcher(callback.Get());
+
+ // Destroy the fetcher before the access token request is fulfilled.
+ fetcher.reset();
+
+ // Now fulfilling the access token request should have no effect.
+ token_service()->IssueAllTokensForAccount(
+ "account", "access token",
+ base::Time::Now() + base::TimeDelta::FromHours(1));
+}
+
+TEST_F(AccessTokenFetcherTest, ShouldNotReturnWhenSignedOut) {
+ TestTokenCallback callback;
+
+ // Signed out -> the fetcher should wait for a sign-in which never happens
+ // in this test, so we shouldn't get called back.
+ auto fetcher = CreateFetcher(callback.Get());
+}
+
+// Tests related to waiting for sign-in don't apply on ChromeOS (it doesn't have
+// that concept).
+#if !defined(OS_CHROMEOS)
+
+TEST_F(AccessTokenFetcherTest, ShouldWaitForSignIn) {
+ TestTokenCallback callback;
+
+ // Not signed in, so this should wait for a sign-in to complete.
+ auto fetcher = CreateFetcher(callback.Get());
+
+ SignIn("account");
+ token_service()->GetDelegate()->UpdateCredentials("account", "refresh token");
+
+ // Once the access token request is fulfilled, we should get called back with
+ // the access token.
+ EXPECT_CALL(callback,
+ Run(GoogleServiceAuthError::AuthErrorNone(), "access token"));
+ token_service()->IssueAllTokensForAccount(
+ "account", "access token",
+ base::Time::Now() + base::TimeDelta::FromHours(1));
+}
+
+TEST_F(AccessTokenFetcherTest, ShouldWaitForSignInInProgress) {
+ TestTokenCallback callback;
+
+ signin_manager()->set_auth_in_progress("account");
+
+ // A sign-in is currently in progress, so this should wait for the sign-in to
+ // complete.
+ auto fetcher = CreateFetcher(callback.Get());
+
+ SignIn("account");
+ token_service()->GetDelegate()->UpdateCredentials("account", "refresh token");
+
+ // Once the access token request is fulfilled, we should get called back with
+ // the access token.
+ EXPECT_CALL(callback,
+ Run(GoogleServiceAuthError::AuthErrorNone(), "access token"));
+ token_service()->IssueAllTokensForAccount(
+ "account", "access token",
+ base::Time::Now() + base::TimeDelta::FromHours(1));
+}
+
+TEST_F(AccessTokenFetcherTest, ShouldWaitForFailedSignIn) {
+ TestTokenCallback callback;
+
+ signin_manager()->set_auth_in_progress("account");
+
+ // A sign-in is currently in progress, so this should wait for the sign-in to
+ // complete.
+ auto fetcher = CreateFetcher(callback.Get());
+
+ // The fetcher should detect the failed sign-in and call us with an empty
+ // access token.
+ EXPECT_CALL(
+ callback,
+ Run(GoogleServiceAuthError(GoogleServiceAuthError::CONNECTION_FAILED),
+ std::string()));
+
+ signin_manager()->FailSignin(
+ GoogleServiceAuthError(GoogleServiceAuthError::CONNECTION_FAILED));
+}
+
+#endif // !OS_CHROMEOS
+
+TEST_F(AccessTokenFetcherTest, ShouldWaitForRefreshToken) {
+ TestTokenCallback callback;
+
+ SignIn("account");
+
+ // Signed in, but there is no refresh token -> we should not get called back
+ // (yet).
+ auto fetcher = CreateFetcher(callback.Get());
+
+ // Getting a refresh token should result in a request for an access token.
+ token_service()->GetDelegate()->UpdateCredentials("account", "refresh token");
+
+ // Once the access token request is fulfilled, we should get called back with
+ // the access token.
+ EXPECT_CALL(callback,
+ Run(GoogleServiceAuthError::AuthErrorNone(), "access token"));
+ token_service()->IssueAllTokensForAccount(
+ "account", "access token",
+ base::Time::Now() + base::TimeDelta::FromHours(1));
+}
+
+TEST_F(AccessTokenFetcherTest, ShouldIgnoreRefreshTokensForOtherAccounts) {
+ TestTokenCallback callback;
+
+ // Signed-in to "account", but there's only a refresh token for a different
+ // account.
+ SignIn("account");
+ token_service()->GetDelegate()->UpdateCredentials("account 2", "refresh");
+
+ // The fetcher should wait for the correct refresh token.
+ auto fetcher = CreateFetcher(callback.Get());
+
+ // A refresh token for yet another account shouldn't matter either.
+ token_service()->GetDelegate()->UpdateCredentials("account 3", "refresh");
+}
+
+TEST_F(AccessTokenFetcherTest, ShouldReturnWhenNoRefreshTokenAvailable) {
+ TestTokenCallback callback;
+
+ SignIn("account");
+
+ // Signed in, but there is no refresh token -> we should not get called back
+ // (yet).
+ auto fetcher = CreateFetcher(callback.Get());
+
+ // Getting a refresh token for some other account should have no effect.
+ token_service()->GetDelegate()->UpdateCredentials("different account",
+ "refresh token");
+
+ // The OAuth2TokenService posts a task to the current thread when we try to
+ // get an access token for an account without a refresh token, so we need a
+ // MessageLoop in this test to not crash.
+ base::MessageLoop message_loop;
+
+ // When all refresh tokens have been loaded by the token service, but the one
+ // for our account wasn't among them, we should get called back with an empty
+ // access token.
+ EXPECT_CALL(callback, Run(testing::_, std::string()));
+ token_service()->GetDelegate()->LoadCredentials("account doesn't matter");
+
+ // Wait for the task posted by OAuth2TokenService to run.
+ base::RunLoop().RunUntilIdle();
+}
+
+TEST_F(AccessTokenFetcherTest, ShouldRetryCanceledAccessTokenRequest) {
+ TestTokenCallback callback;
+
+ SignIn("account");
+ token_service()->GetDelegate()->UpdateCredentials("account", "refresh token");
+
+ // Signed in and refresh token already exists, so this should result in a
+ // request for an access token.
+ auto fetcher = CreateFetcher(callback.Get());
+
+ // A canceled access token request should get retried once.
+ token_service()->IssueErrorForAllPendingRequestsForAccount(
+ "account",
+ GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED));
+
+ // Once the access token request is fulfilled, we should get called back with
+ // the access token.
+ EXPECT_CALL(callback,
+ Run(GoogleServiceAuthError::AuthErrorNone(), "access token"));
+ token_service()->IssueAllTokensForAccount(
+ "account", "access token",
+ base::Time::Now() + base::TimeDelta::FromHours(1));
+}
+
+TEST_F(AccessTokenFetcherTest, ShouldRetryCanceledAccessTokenRequestOnlyOnce) {
+ TestTokenCallback callback;
+
+ SignIn("account");
+ token_service()->GetDelegate()->UpdateCredentials("account", "refresh token");
+
+ // Signed in and refresh token already exists, so this should result in a
+ // request for an access token.
+ auto fetcher = CreateFetcher(callback.Get());
+
+ // A canceled access token request should get retried once.
+ token_service()->IssueErrorForAllPendingRequestsForAccount(
+ "account",
+ GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED));
+
+ // On the second failure, we should get called back with an empty access
+ // token.
+ EXPECT_CALL(
+ callback,
+ Run(GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED),
+ std::string()));
+ token_service()->IssueErrorForAllPendingRequestsForAccount(
+ "account",
+ GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED));
+}
+
+#if !defined(OS_CHROMEOS)
+
+TEST_F(AccessTokenFetcherTest,
+ ShouldNotRetryCanceledAccessTokenRequestIfSignedOut) {
+ TestTokenCallback callback;
+
+ SignIn("account");
+ token_service()->GetDelegate()->UpdateCredentials("account", "refresh token");
+
+ // Signed in and refresh token already exists, so this should result in a
+ // request for an access token.
+ auto fetcher = CreateFetcher(callback.Get());
+
+ // Simulate the user signing out while the access token request is pending.
+ // In this case, the pending request gets canceled, and the fetcher should
+ // *not* retry.
+ signin_manager()->ForceSignOut();
+ EXPECT_CALL(
+ callback,
+ Run(GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED),
+ std::string()));
+ token_service()->IssueErrorForAllPendingRequestsForAccount(
+ "account",
+ GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED));
+}
+
+#endif // !OS_CHROMEOS
+
+TEST_F(AccessTokenFetcherTest,
+ ShouldNotRetryCanceledAccessTokenRequestIfRefreshTokenRevoked) {
+ TestTokenCallback callback;
+
+ SignIn("account");
+ token_service()->GetDelegate()->UpdateCredentials("account", "refresh token");
+
+ // Signed in and refresh token already exists, so this should result in a
+ // request for an access token.
+ auto fetcher = CreateFetcher(callback.Get());
+
+ // Simulate the refresh token getting invalidated. In this case, pending
+ // access token requests get canceled, and the fetcher should *not* retry.
+ token_service()->GetDelegate()->RevokeCredentials("account");
+ EXPECT_CALL(
+ callback,
+ Run(GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED),
+ std::string()));
+ token_service()->IssueErrorForAllPendingRequestsForAccount(
+ "account",
+ GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED));
+}
+
+TEST_F(AccessTokenFetcherTest, ShouldNotRetryFailedAccessTokenRequest) {
+ TestTokenCallback callback;
+
+ SignIn("account");
+ token_service()->GetDelegate()->UpdateCredentials("account", "refresh token");
+
+ // Signed in and refresh token already exists, so this should result in a
+ // request for an access token.
+ auto fetcher = CreateFetcher(callback.Get());
+
+ // An access token failure other than "canceled" should not be retried; we
+ // should immediately get called back with an empty access token.
+ EXPECT_CALL(
+ callback,
+ Run(GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE),
+ std::string()));
+ token_service()->IssueErrorForAllPendingRequestsForAccount(
+ "account",
+ GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE));
+}
diff --git a/chromium/components/signin/core/browser/account_tracker_service.cc b/chromium/components/signin/core/browser/account_tracker_service.cc
index efe9e6e36c7..dd3f339588f 100644
--- a/chromium/components/signin/core/browser/account_tracker_service.cc
+++ b/chromium/components/signin/core/browser/account_tracker_service.cc
@@ -238,7 +238,7 @@ void AccountTrackerService::SetAccountStateFromUserInfo(
state.info.picture_url = kNoPictureURLFound;
}
}
- if (state.info.IsValid())
+ if (!state.info.gaia.empty())
NotifyAccountUpdated(state);
SaveToPrefs(state);
}
@@ -250,7 +250,7 @@ void AccountTrackerService::SetIsChildAccount(const std::string& account_id,
if (state.info.is_child_account == is_child_account)
return;
state.info.is_child_account = is_child_account;
- if (state.info.IsValid())
+ if (!state.info.gaia.empty())
NotifyAccountUpdated(state);
SaveToPrefs(state);
}
@@ -361,7 +361,7 @@ void AccountTrackerService::LoadFromPrefs() {
if (dict->GetBoolean(kAccountChildAccountStatusPath, &is_child_account))
state.info.is_child_account = is_child_account;
- if (state.info.IsValid())
+ if (!state.info.gaia.empty())
NotifyAccountUpdated(state);
}
}
@@ -496,11 +496,9 @@ std::string AccountTrackerService::SeedAccountInfo(AccountInfo info) {
AccountState& state = accounts_[info.account_id];
// Update the missing fields in |state.info| with |info|.
if (state.info.UpdateWith(info)) {
- if (state.info.IsValid()) {
- // Notify only if the account info is fully updated, as it is equivalent
- // to having the account fully fetched.
+ if (!state.info.gaia.empty())
NotifyAccountUpdated(state);
- }
+
SaveToPrefs(state);
}
return info.account_id;
diff --git a/chromium/components/signin/core/browser/account_tracker_service_unittest.cc b/chromium/components/signin/core/browser/account_tracker_service_unittest.cc
index b6847009f33..9fae742506b 100644
--- a/chromium/components/signin/core/browser/account_tracker_service_unittest.cc
+++ b/chromium/components/signin/core/browser/account_tracker_service_unittest.cc
@@ -678,13 +678,13 @@ TEST_F(AccountTrackerServiceTest, SeedAccountInfoFull) {
info.full_name = AccountIdToFullName("alpha");
info.account_id = account_tracker()->SeedAccountInfo(info);
- // Validate that seeding an unexisting account works and doesn't send a
- // notification if the info isn't full.
+ // Validate that seeding an unexisting account works and sends a notification.
AccountInfo stored_info = account_tracker()->GetAccountInfo(info.account_id);
EXPECT_EQ(info.gaia, stored_info.gaia);
EXPECT_EQ(info.email, stored_info.email);
EXPECT_EQ(info.full_name, stored_info.full_name);
- EXPECT_TRUE(observer.CheckEvents());
+ EXPECT_TRUE(
+ observer.CheckEvents(TrackingEvent(UPDATED, info.account_id, info.gaia)));
// Validate that seeding new full informations to an existing account works
// and sends a notification.
diff --git a/chromium/components/signin/core/browser/device_activity_fetcher.cc b/chromium/components/signin/core/browser/device_activity_fetcher.cc
deleted file mode 100644
index 39b7433c8f5..00000000000
--- a/chromium/components/signin/core/browser/device_activity_fetcher.cc
+++ /dev/null
@@ -1,204 +0,0 @@
-// Copyright 2015 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 "components/signin/core/browser/device_activity_fetcher.h"
-
-#include "base/strings/stringprintf.h"
-#include "components/signin/core/browser/signin_client.h"
-#include "google_apis/gaia/gaia_auth_fetcher.h"
-#include "google_apis/gaia/gaia_constants.h"
-#include "google_apis/gaia/gaia_urls.h"
-#include "google_apis/gaia/google_service_auth_error.h"
-#include "net/http/http_status_code.h"
-#include "net/url_request/url_fetcher.h"
-
-namespace {
-
-// TODO(mlerman,anthonyvd): Replace the three parameters following with the
-// necessary parameters for calling the ListDevices endpoint, once live.
-// crbug.com/463611 for details!
-const char kSyncListDevicesScope[] =
- "https://www.googleapis.com/auth/chromesynclistdevices";
-const char kChromeDomain[] = "http://www.chrome.com";
-const char kListDevicesEndpoint[] = "http://127.0.0.1";
-// Template for optional authorization header when using an OAuth access token.
-const char kAuthorizationHeader[] = "Authorization: Bearer %s";
-
-// In case of an error while fetching using the GaiaAuthFetcher, retry with
-// exponential backoff. Try up to 9 times within 10 minutes.
-const net::BackoffEntry::Policy kBackoffPolicy = {
- // Number of initial errors (in sequence) to ignore before applying
- // exponential back-off rules.
- 0,
- // Initial delay for exponential backoff in ms.
- 1000,
- // Factor by which the waiting time will be multiplied.
- 2,
- // Fuzzing percentage. ex: 10% will spread requests randomly
- // between 90%-100% of the calculated time.
- 0.1, // 10%
- // Maximum amount of time we are willing to delay our request in ms.
- 1000 * 60 * 15, // 15 minutes.
- // Time to keep an entry from being discarded even when it
- // has no significant state, -1 to never discard.
- -1,
- // Don't use initial delay unless the last request was an error.
- false,
-};
-
-const int kMaxFetcherRetries = 9;
-
-} // namespace
-
-DeviceActivityFetcher::DeviceActivityFetcher(
- SigninClient* signin_client,
- DeviceActivityFetcher::Observer* observer)
- : fetcher_backoff_(&kBackoffPolicy),
- fetcher_retries_(0),
- signin_client_(signin_client),
- observer_(observer) {
-}
-
-DeviceActivityFetcher::~DeviceActivityFetcher() {
-}
-
-void DeviceActivityFetcher::Start() {
- fetcher_retries_ = 0;
- login_hint_ = std::string();
- StartFetchingListIdpSessions();
-}
-
-void DeviceActivityFetcher::Stop() {
- if (gaia_auth_fetcher_)
- gaia_auth_fetcher_->CancelRequest();
- if (url_fetcher_)
- url_fetcher_.reset();
-}
-
-void DeviceActivityFetcher::StartFetchingListIdpSessions() {
- gaia_auth_fetcher_.reset(signin_client_->CreateGaiaAuthFetcher(
- this, GaiaConstants::kChromeSource,
- signin_client_->GetURLRequestContext()));
- gaia_auth_fetcher_->StartListIDPSessions(kSyncListDevicesScope,
- kChromeDomain);
-}
-
-void DeviceActivityFetcher::StartFetchingGetTokenResponse() {
- gaia_auth_fetcher_.reset(signin_client_->CreateGaiaAuthFetcher(
- this, GaiaConstants::kChromeSource,
- signin_client_->GetURLRequestContext()));
- gaia_auth_fetcher_->StartGetTokenResponse(kSyncListDevicesScope,
- kChromeDomain, login_hint_);
-}
-
-void DeviceActivityFetcher::StartFetchingListDevices() {
- // Call the Sync Endpoint.
- url_fetcher_ = net::URLFetcher::Create(GURL(kListDevicesEndpoint),
- net::URLFetcher::GET, this);
- url_fetcher_->SetRequestContext(signin_client_->GetURLRequestContext());
- if (!access_token_.empty()) {
- url_fetcher_->SetExtraRequestHeaders(
- base::StringPrintf(kAuthorizationHeader, access_token_.c_str()));
- }
- url_fetcher_->Start();
-}
-
-void DeviceActivityFetcher::OnURLFetchComplete(const net::URLFetcher* source) {
- // TODO(mlerman): Uncomment the code below once we have a working proto.
- // Work done under crbug.com/463611
-
- // std::string response_string;
- // ListDevices list_devices;
-
- // if (!source->GetStatus().is_success()) {
- // VLOG(1) << "Failed to fetch listdevices response. Retrying.";
- // if (++fetcher_retries_ < kMaxFetcherRetries) {
- // fetcher_backoff_.InformOfRequest(false);
- // fetcher_timer_.Start(
- // FROM_HERE, fetcher_backoff_.GetTimeUntilRelease(), this,
- // &DeviceActivityFetcher::StartFetchingListDevices);
- // return;
- // } else {
- // observer_->OnFetchDeviceActivityFailure();
- // return;
- // }
- // }
-
- // net::HttpStatusCode response_status = static_cast<net::HttpStatusCode>(
- // source->GetResponseCode());
- // if (response_status == net::HTTP_BAD_REQUEST ||
- // response_status == net::HTTP_UNAUTHORIZED) {
- // // BAD_REQUEST indicates that the request was malformed.
- // // UNAUTHORIZED indicates that security token didn't match the id.
- // VLOG(1) << "No point retrying the checkin with status: "
- // << response_status << ". Checkin failed.";
- // CheckinRequestStatus status = response_status == net::HTTP_BAD_REQUEST ?
- // HTTP_BAD_REQUEST : HTTP_UNAUTHORIZED;
- // RecordCheckinStatusAndReportUMA(status, recorder_, false);
- // callback_.Run(response_proto);
- // return;
- // }
-
- // if (response_status != net::HTTP_OK ||
- // !source->GetResponseAsString(&response_string) ||
- // !list_devices.ParseFromString(response_string)) {
- // LOG(ERROR) << "Failed to get list devices response. HTTP Status: "
- // << response_status;
- // if (++fetcher_retries_ < kMaxFetcherRetries) {
- // fetcher_backoff_.InformOfRequest(false);
- // fetcher_timer_.Start(
- // FROM_HERE, fetcher_backoff_.GetTimeUntilRelease(), this,
- // &DeviceActivityFetcher::StartFetchingListDevices);
- // return;
- // } else {
- // observer_->OnFetchDeviceActivityFailure();
- // return;
- // }
- // }
-
- std::vector<DeviceActivity> devices;
- // TODO(mlerman): Fill |devices| from the proto in |source|.
-
- // Call this last as OnFetchDeviceActivitySuccess will delete |this|.
- observer_->OnFetchDeviceActivitySuccess(devices);
-}
-
-void DeviceActivityFetcher::OnListIdpSessionsSuccess(
- const std::string& login_hint) {
- fetcher_backoff_.InformOfRequest(true);
- login_hint_ = login_hint;
- access_token_ = std::string();
- StartFetchingGetTokenResponse();
-}
-
-void DeviceActivityFetcher::OnListIdpSessionsError(
- const GoogleServiceAuthError& error) {
- if (++fetcher_retries_ < kMaxFetcherRetries && error.IsTransientError()) {
- fetcher_backoff_.InformOfRequest(false);
- fetcher_timer_.Start(FROM_HERE, fetcher_backoff_.GetTimeUntilRelease(),
- this,
- &DeviceActivityFetcher::StartFetchingListIdpSessions);
- return;
- }
- observer_->OnFetchDeviceActivityFailure();
-}
-
-void DeviceActivityFetcher::OnGetTokenResponseSuccess(
- const ClientOAuthResult& result) {
- fetcher_backoff_.InformOfRequest(true);
- access_token_ = result.access_token;
- StartFetchingListDevices();
-}
-
-void DeviceActivityFetcher::OnGetTokenResponseError(
- const GoogleServiceAuthError& error) {
- if (++fetcher_retries_ < kMaxFetcherRetries && error.IsTransientError()) {
- fetcher_backoff_.InformOfRequest(false);
- fetcher_timer_.Start(FROM_HERE, fetcher_backoff_.GetTimeUntilRelease(),
- this,
- &DeviceActivityFetcher::StartFetchingGetTokenResponse);
- return;
- }
- observer_->OnFetchDeviceActivityFailure();
-}
diff --git a/chromium/components/signin/core/browser/device_activity_fetcher.h b/chromium/components/signin/core/browser/device_activity_fetcher.h
deleted file mode 100644
index f91e7dfc672..00000000000
--- a/chromium/components/signin/core/browser/device_activity_fetcher.h
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright 2015 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.
-
-#ifndef COMPONENTS_SIGNIN_CORE_BROWSER_DEVICE_ACTVITIY_FETCHER_H_
-#define COMPONENTS_SIGNIN_CORE_BROWSER_DEVICE_ACTVITIY_FETCHER_H_
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "base/macros.h"
-#include "base/time/time.h"
-#include "base/timer/timer.h"
-#include "google_apis/gaia/gaia_auth_consumer.h"
-#include "net/base/backoff_entry.h"
-#include "net/url_request/url_fetcher_delegate.h"
-
-class GaiaAuthFetcher;
-class SigninClient;
-
-namespace net {
-class URLFetcher;
-}
-
-class DeviceActivityFetcher : public GaiaAuthConsumer,
- public net::URLFetcherDelegate {
- public:
- struct DeviceActivity {
- base::Time last_active;
- std::string name;
- };
-
- class Observer {
- public:
- virtual void OnFetchDeviceActivitySuccess(
- const std::vector<DeviceActivityFetcher::DeviceActivity>& devices) = 0;
- virtual void OnFetchDeviceActivityFailure() {}
- };
-
- DeviceActivityFetcher(SigninClient* signin_client,
- DeviceActivityFetcher::Observer* observer);
- ~DeviceActivityFetcher() override;
-
- void Start();
- void Stop();
-
- // GaiaAuthConsumer:
- void OnListIdpSessionsSuccess(const std::string& login_hint) override;
- void OnListIdpSessionsError(const GoogleServiceAuthError& error) override;
- void OnGetTokenResponseSuccess(const ClientOAuthResult& result) override;
- void OnGetTokenResponseError(const GoogleServiceAuthError& error) override;
-
- // net::URLFetcherDelegate:
- void OnURLFetchComplete(const net::URLFetcher* source) override;
-
- private:
- void StartFetchingListIdpSessions();
- void StartFetchingGetTokenResponse();
- void StartFetchingListDevices();
-
- // Gaia fetcher used for acquiring an access token.
- std::unique_ptr<GaiaAuthFetcher> gaia_auth_fetcher_;
- // URL Fetcher used for calling List Devices.
- std::unique_ptr<net::URLFetcher> url_fetcher_;
-
- // If either fetcher fails, retry with exponential backoff.
- net::BackoffEntry fetcher_backoff_;
- base::OneShotTimer fetcher_timer_;
- int fetcher_retries_;
-
- std::string access_token_;
- std::string login_hint_;
-
- SigninClient* signin_client_; // Weak pointer.
- Observer* observer_;
-
- DISALLOW_COPY_AND_ASSIGN(DeviceActivityFetcher);
-};
-
-#endif // COMPONENTS_SIGNIN_CORE_BROWSER_DEVICE_ACTVITIY_FETCHER_H_
diff --git a/chromium/components/signin/core/browser/fake_profile_oauth2_token_service.cc b/chromium/components/signin/core/browser/fake_profile_oauth2_token_service.cc
index 876e8063f5c..c15a1c3510a 100644
--- a/chromium/components/signin/core/browser/fake_profile_oauth2_token_service.cc
+++ b/chromium/components/signin/core/browser/fake_profile_oauth2_token_service.cc
@@ -6,6 +6,7 @@
#include "base/bind.h"
#include "base/location.h"
+#include "base/memory/ptr_util.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "google_apis/gaia/fake_oauth2_token_service_delegate.h"
@@ -19,11 +20,11 @@ FakeProfileOAuth2TokenService::PendingRequest::~PendingRequest() {}
FakeProfileOAuth2TokenService::FakeProfileOAuth2TokenService()
: FakeProfileOAuth2TokenService(
- new FakeOAuth2TokenServiceDelegate(nullptr)) {}
+ base::MakeUnique<FakeOAuth2TokenServiceDelegate>(nullptr)) {}
FakeProfileOAuth2TokenService::FakeProfileOAuth2TokenService(
- OAuth2TokenServiceDelegate* delegate)
- : ProfileOAuth2TokenService(delegate),
+ std::unique_ptr<OAuth2TokenServiceDelegate> delegate)
+ : ProfileOAuth2TokenService(std::move(delegate)),
auto_post_fetch_response_on_message_loop_(false),
weak_ptr_factory_(this) {}
diff --git a/chromium/components/signin/core/browser/fake_profile_oauth2_token_service.h b/chromium/components/signin/core/browser/fake_profile_oauth2_token_service.h
index 043fc9a7cdb..f2301fdbd80 100644
--- a/chromium/components/signin/core/browser/fake_profile_oauth2_token_service.h
+++ b/chromium/components/signin/core/browser/fake_profile_oauth2_token_service.h
@@ -48,7 +48,8 @@ class FakeProfileOAuth2TokenService : public ProfileOAuth2TokenService {
};
FakeProfileOAuth2TokenService();
- explicit FakeProfileOAuth2TokenService(OAuth2TokenServiceDelegate* delegate);
+ explicit FakeProfileOAuth2TokenService(
+ std::unique_ptr<OAuth2TokenServiceDelegate> delegate);
~FakeProfileOAuth2TokenService() override;
// Gets a list of active requests (can be used by tests to validate that the
diff --git a/chromium/components/signin/core/browser/fake_signin_manager.h b/chromium/components/signin/core/browser/fake_signin_manager.h
index 83b2728e189..5ba63b81e53 100644
--- a/chromium/components/signin/core/browser/fake_signin_manager.h
+++ b/chromium/components/signin/core/browser/fake_signin_manager.h
@@ -17,7 +17,6 @@
// SigninManagerForTesting to ensure that the right type for their platform is
// used.
-// Overrides InitTokenService to do-nothing in tests.
class FakeSigninManagerBase : public SigninManagerBase {
public:
FakeSigninManagerBase(SigninClient* client,
diff --git a/chromium/components/signin/core/browser/gaia_cookie_manager_service.cc b/chromium/components/signin/core/browser/gaia_cookie_manager_service.cc
index 3d14c265528..28f30f1d2ff 100644
--- a/chromium/components/signin/core/browser/gaia_cookie_manager_service.cc
+++ b/chromium/components/signin/core/browser/gaia_cookie_manager_service.cc
@@ -15,6 +15,7 @@
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "base/values.h"
+#include "components/data_use_measurement/core/data_use_user_data.h"
#include "components/signin/core/browser/account_tracker_service.h"
#include "components/signin/core/browser/signin_metrics.h"
#include "google_apis/gaia/gaia_auth_fetcher.h"
@@ -62,9 +63,6 @@ const int kMaxFetcherRetries = 8;
// accounts have changed in the content-area.
const char* kGaiaCookieName = "APISID";
-// String format appended to GAIA fetcher source if request context has changed.
-const char* kRequestContextChangedTag = "__changed_%d__";
-
enum GaiaCookieRequestType {
ADD_ACCOUNT,
LOG_OUT_ALL_ACCOUNTS,
@@ -72,11 +70,6 @@ enum GaiaCookieRequestType {
LIST_ACCOUNTS
};
-void AppendRequestContextChangedTagIfNeeded(std::string* source, int changes) {
- if (changes != 0)
- base::StringAppendF(source, kRequestContextChangedTag, changes);
-}
-
} // namespace
GaiaCookieManagerService::GaiaCookieRequest::GaiaCookieRequest(
@@ -223,6 +216,8 @@ GaiaCookieManagerService::ExternalCcResultFetcher::CreateFetcher(
fetcher->SetRequestContext(helper_->request_context());
fetcher->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
net::LOAD_DO_NOT_SAVE_COOKIES);
+ data_use_measurement::DataUseUserData::AttachToFetcher(
+ fetcher.get(), data_use_measurement::DataUseUserData::SIGNIN);
// Fetchers are sometimes cancelled because a network change was detected,
// especially at startup and after sign-in on ChromeOS.
@@ -402,7 +397,7 @@ void GaiaCookieManagerService::ForceOnCookieChangedProcessing() {
std::unique_ptr<net::CanonicalCookie> cookie(net::CanonicalCookie::Create(
google_url, kGaiaCookieName, std::string(), "." + google_url.host(),
std::string(), base::Time(), base::Time(), false, false,
- net::CookieSameSite::DEFAULT_MODE, false, net::COOKIE_PRIORITY_DEFAULT));
+ net::CookieSameSite::DEFAULT_MODE, net::COOKIE_PRIORITY_DEFAULT));
OnCookieChanged(*cookie, net::CookieStore::ChangeCause::UNKNOWN_DELETION);
}
@@ -473,19 +468,12 @@ void GaiaCookieManagerService::CancelAll() {
std::string GaiaCookieManagerService::GetSourceForRequest(
const GaiaCookieManagerService::GaiaCookieRequest& request) {
- std::string source = request.source().empty() ? source_ : request.source();
- AppendRequestContextChangedTagIfNeeded(
- &source,
- signin_client_->number_of_request_context_pointer_changes());
- return source;
+ return request.source().empty() ? GetDefaultSourceForRequest() :
+ request.source();
}
std::string GaiaCookieManagerService::GetDefaultSourceForRequest() {
- std::string source = source_;
- AppendRequestContextChangedTagIfNeeded(
- &source,
- signin_client_->number_of_request_context_pointer_changes());
- return source;
+ return source_;
}
void GaiaCookieManagerService::OnCookieChanged(
@@ -506,17 +494,20 @@ void GaiaCookieManagerService::OnCookieChanged(
case net::CookieStore::ChangeCause::INSERTED:
source += "INSERTED";
break;
- case net::CookieStore::ChangeCause::EXPLICIT_DELETE:
- source += "EXPLICIT_DELETE";
+ case net::CookieStore::ChangeCause::EXPLICIT:
+ source += "EXPLICIT";
+ break;
+ case net::CookieStore::ChangeCause::EXPLICIT_DELETE_BETWEEN:
+ source += "EXPLICIT_DELETE_BETWEEN";
break;
- case net::CookieStore::ChangeCause::EXPLICIT_DUPLICATE_IN_BACKING_STORE:
- source += "EXPLICIT_DUPLICATE_IN_BACKING_STORE";
+ case net::CookieStore::ChangeCause::EXPLICIT_DELETE_PREDICATE:
+ source += "EXPLICIT_DELETE_PREDICATE";
break;
- case net::CookieStore::ChangeCause::EXPLICIT_DONT_RECORD:
- source += "EXPLICIT_DONT_RECORD";
+ case net::CookieStore::ChangeCause::EXPLICIT_DELETE_SINGLE:
+ source += "EXPLICIT_DELETE_SINGLE";
break;
- case net::CookieStore::ChangeCause::EXPLICIT_LAST_ENTRY:
- source += "EXPLICIT_LAST_ENTRY";
+ case net::CookieStore::ChangeCause::EXPLICIT_DELETE_CANONICAL:
+ source += "EXPLICIT_DELETE_CANONICAL";
break;
case net::CookieStore::ChangeCause::UNKNOWN_DELETION:
source += "UNKNOWN_DELETION";
diff --git a/chromium/components/signin/core/browser/profile_oauth2_token_service.cc b/chromium/components/signin/core/browser/profile_oauth2_token_service.cc
index b7fd8d01da3..7e8eb2a22c9 100644
--- a/chromium/components/signin/core/browser/profile_oauth2_token_service.cc
+++ b/chromium/components/signin/core/browser/profile_oauth2_token_service.cc
@@ -4,21 +4,9 @@
#include "components/signin/core/browser/profile_oauth2_token_service.h"
-void ProfileOAuth2TokenService::OnRefreshTokenAvailable(
- const std::string& account_id) {
- CancelRequestsForAccount(account_id);
- ClearCacheForAccount(account_id);
-}
-
-void ProfileOAuth2TokenService::OnRefreshTokenRevoked(
- const std::string& account_id) {
- CancelRequestsForAccount(account_id);
- ClearCacheForAccount(account_id);
-}
-
ProfileOAuth2TokenService::ProfileOAuth2TokenService(
- OAuth2TokenServiceDelegate* delegate)
- : OAuth2TokenService(delegate) {
+ std::unique_ptr<OAuth2TokenServiceDelegate> delegate)
+ : OAuth2TokenService(std::move(delegate)) {
AddObserver(this);
}
@@ -50,3 +38,15 @@ void ProfileOAuth2TokenService::RevokeCredentials(
const net::BackoffEntry* ProfileOAuth2TokenService::GetDelegateBackoffEntry() {
return GetDelegate()->BackoffEntry();
}
+
+void ProfileOAuth2TokenService::OnRefreshTokenAvailable(
+ const std::string& account_id) {
+ CancelRequestsForAccount(account_id);
+ ClearCacheForAccount(account_id);
+}
+
+void ProfileOAuth2TokenService::OnRefreshTokenRevoked(
+ const std::string& account_id) {
+ CancelRequestsForAccount(account_id);
+ ClearCacheForAccount(account_id);
+}
diff --git a/chromium/components/signin/core/browser/profile_oauth2_token_service.h b/chromium/components/signin/core/browser/profile_oauth2_token_service.h
index 199c7909ebc..fadf1417bd1 100644
--- a/chromium/components/signin/core/browser/profile_oauth2_token_service.h
+++ b/chromium/components/signin/core/browser/profile_oauth2_token_service.h
@@ -32,7 +32,8 @@ class ProfileOAuth2TokenService : public OAuth2TokenService,
public OAuth2TokenService::Observer,
public KeyedService {
public:
- ProfileOAuth2TokenService(OAuth2TokenServiceDelegate* delegate);
+ ProfileOAuth2TokenService(
+ std::unique_ptr<OAuth2TokenServiceDelegate> delegate);
~ProfileOAuth2TokenService() override;
// KeyedService implementation.
diff --git a/chromium/components/signin/core/browser/signin_client.cc b/chromium/components/signin/core/browser/signin_client.cc
index f9018c85900..9473e0bb59c 100644
--- a/chromium/components/signin/core/browser/signin_client.cc
+++ b/chromium/components/signin/core/browser/signin_client.cc
@@ -36,10 +36,6 @@ void SigninClient::PreSignOut(const base::Callback<void()>& sign_out) {
sign_out.Run();
}
-int SigninClient::number_of_request_context_pointer_changes() const {
- return 0;
-}
-
void SigninClient::SignOut() {
GetPrefs()->ClearPref(prefs::kGoogleServicesSigninScopedDeviceId);
OnSignedOut();
diff --git a/chromium/components/signin/core/browser/signin_client.h b/chromium/components/signin/core/browser/signin_client.h
index 43d90bc9d69..a4910c154df 100644
--- a/chromium/components/signin/core/browser/signin_client.h
+++ b/chromium/components/signin/core/browser/signin_client.h
@@ -126,10 +126,6 @@ class SigninClient : public KeyedService {
// Called once the credentials has been copied to another SigninManager.
virtual void AfterCredentialsCopied() {}
- // Used do debug channel id binding problem in chrome. Returns the number of
- // times the request context changed unexpectedly.
- virtual int number_of_request_context_pointer_changes() const;
-
protected:
// Returns device id that is scoped to single signin.
// Stores the ID in the kGoogleServicesSigninScopedDeviceId pref.
diff --git a/chromium/components/signin/core/browser/signin_header_helper.cc b/chromium/components/signin/core/browser/signin_header_helper.cc
index 0d192ea5668..668d25d4492 100644
--- a/chromium/components/signin/core/browser/signin_header_helper.cc
+++ b/chromium/components/signin/core/browser/signin_header_helper.cc
@@ -164,8 +164,8 @@ bool SettingsAllowSigninCookies(
GURL gaia_url = GaiaUrls::GetInstance()->gaia_url();
GURL google_url = GaiaUrls::GetInstance()->google_url();
return cookie_settings &&
- cookie_settings->IsSettingCookieAllowed(gaia_url, gaia_url) &&
- cookie_settings->IsSettingCookieAllowed(google_url, google_url);
+ cookie_settings->IsCookieAccessAllowed(gaia_url, gaia_url) &&
+ cookie_settings->IsCookieAccessAllowed(google_url, google_url);
}
std::string BuildMirrorRequestCookieIfPossible(
diff --git a/chromium/components/signin/core/browser/signin_internals_util.h b/chromium/components/signin/core/browser/signin_internals_util.h
index 3dda94c9af2..03e5c6fa8db 100644
--- a/chromium/components/signin/core/browser/signin_internals_util.h
+++ b/chromium/components/signin/core/browser/signin_internals_util.h
@@ -69,13 +69,7 @@ class SigninDiagnosticsObserver {
// Credentials and signin related changes.
virtual void NotifySigninValueChanged(const TimedSigninStatusField& field,
const std::string& value) {}
- // OAuth tokens related changes.
- virtual void NotifyTokenReceivedSuccess(const std::string& token_name,
- const std::string& token,
- bool update_time) {}
- virtual void NotifyTokenReceivedFailure(const std::string& token_name,
- const std::string& error) {}
- virtual void NotifyClearStoredToken(const std::string& token_name) {}};
+};
// Gets the first 6 hex characters of the SHA256 hash of the passed in string.
// These are enough to perform equality checks across a single users tokens,
diff --git a/chromium/components/signin/core/browser/signin_manager.cc b/chromium/components/signin/core/browser/signin_manager.cc
index 2e3a7044510..27fce040ba6 100644
--- a/chromium/components/signin/core/browser/signin_manager.cc
+++ b/chromium/components/signin/core/browser/signin_manager.cc
@@ -409,6 +409,9 @@ void SigninManager::PostSignedIn() {
}
void SigninManager::OnAccountUpdated(const AccountInfo& info) {
+ if (!info.IsValid())
+ return;
+
user_info_fetched_by_account_tracker_ = true;
PostSignedIn();
}
diff --git a/chromium/components/signin/core/browser/signin_manager_base.cc b/chromium/components/signin/core/browser/signin_manager_base.cc
index 68d68b477b4..b36d21d0f56 100644
--- a/chromium/components/signin/core/browser/signin_manager_base.cc
+++ b/chromium/components/signin/core/browser/signin_manager_base.cc
@@ -216,6 +216,10 @@ void SigninManagerBase::SetAuthenticatedAccountId(
account_id);
client_->GetPrefs()->SetString(prefs::kGoogleServicesLastUsername,
info.email);
+
+ // Commit authenticated account info immediately so that it does not get lost
+ // if Chrome crashes before the next commit interval.
+ client_->GetPrefs()->CommitPendingWrite();
}
bool SigninManagerBase::IsAuthenticated() const {
diff --git a/chromium/components/signin/core/browser/webdata/token_service_table.cc b/chromium/components/signin/core/browser/webdata/token_service_table.cc
index d1ccb08da29..8c9075c9e5a 100644
--- a/chromium/components/signin/core/browser/webdata/token_service_table.cc
+++ b/chromium/components/signin/core/browser/webdata/token_service_table.cc
@@ -8,6 +8,7 @@
#include <string>
#include "base/logging.h"
+#include "base/metrics/histogram_macros.h"
#include "components/os_crypt/os_crypt.h"
#include "components/webdata/common/web_database.h"
#include "sql/statement.h"
@@ -21,6 +22,14 @@ WebDatabaseTable::TypeKey GetKey() {
return reinterpret_cast<void*>(&table_key);
}
+// Entries in the |Signin.TokenTable.ReadTokenFromDBResult| histogram.
+enum ReadOneTokenResult {
+ READ_ONE_TOKEN_SUCCESS,
+ READ_ONE_TOKEN_DB_SUCCESS_DECRYPT_FAILED,
+ READ_ONE_TOKEN_DB_FAILED_BAD_ENTRY,
+ READ_ONE_TOKEN_MAX_VALUE
+};
+
} // namespace
TokenServiceTable* TokenServiceTable::FromWebDatabase(WebDatabase* db) {
@@ -88,15 +97,23 @@ bool TokenServiceTable::SetTokenForService(const std::string& service,
return s.Run();
}
-bool TokenServiceTable::GetAllTokens(
+TokenServiceTable::Result TokenServiceTable::GetAllTokens(
std::map<std::string, std::string>* tokens) {
sql::Statement s(db_->GetUniqueStatement(
"SELECT service, encrypted_token FROM token_service"));
- if (!s.is_valid())
- return false;
+ UMA_HISTOGRAM_BOOLEAN("Signin.TokenTable.GetAllTokensSqlStatementValidity",
+ s.is_valid());
+
+ if (!s.is_valid()) {
+ LOG(ERROR) << "Failed to load tokens (invalid SQL statement).";
+ return TOKEN_DB_RESULT_SQL_INVALID_STATEMENT;
+ }
+ Result read_all_tokens_result = TOKEN_DB_RESULT_SUCCESS;
while (s.Step()) {
+ ReadOneTokenResult read_token_result = READ_ONE_TOKEN_MAX_VALUE;
+
std::string encrypted_token;
std::string decrypted_token;
std::string service;
@@ -104,12 +121,25 @@ bool TokenServiceTable::GetAllTokens(
bool entry_ok = !service.empty() &&
s.ColumnBlobAsString(1, &encrypted_token);
if (entry_ok) {
- OSCrypt::DecryptString(encrypted_token, &decrypted_token);
- (*tokens)[service] = decrypted_token;
+ if (OSCrypt::DecryptString(encrypted_token, &decrypted_token)) {
+ (*tokens)[service] = decrypted_token;
+ read_token_result = READ_ONE_TOKEN_SUCCESS;
+ } else {
+ // Chrome relies on native APIs to encrypt and decrypt the tokens which
+ // may fail (see http://crbug.com/686485).
+ LOG(ERROR) << "Failed to decrypt token for service " << service;
+ read_token_result = READ_ONE_TOKEN_DB_SUCCESS_DECRYPT_FAILED;
+ read_all_tokens_result = TOKEN_DB_RESULT_DECRYPT_ERROR;
+ }
} else {
- NOTREACHED();
- return false;
+ LOG(ERROR) << "Bad token entry for service " << service;
+ read_token_result = READ_ONE_TOKEN_DB_FAILED_BAD_ENTRY;
+ read_all_tokens_result = TOKEN_DB_RESULT_BAD_ENTRY;
}
+ DCHECK_LT(read_token_result, READ_ONE_TOKEN_MAX_VALUE);
+ UMA_HISTOGRAM_ENUMERATION("Signin.TokenTable.ReadTokenFromDBResult",
+ read_token_result,
+ READ_ONE_TOKEN_MAX_VALUE);
}
- return true;
+ return read_all_tokens_result;
}
diff --git a/chromium/components/signin/core/browser/webdata/token_service_table.h b/chromium/components/signin/core/browser/webdata/token_service_table.h
index 70cf20e93dc..b6d750f0ce5 100644
--- a/chromium/components/signin/core/browser/webdata/token_service_table.h
+++ b/chromium/components/signin/core/browser/webdata/token_service_table.h
@@ -16,6 +16,13 @@ class WebDatabase;
class TokenServiceTable : public WebDatabaseTable {
public:
+ enum Result {
+ TOKEN_DB_RESULT_SQL_INVALID_STATEMENT,
+ TOKEN_DB_RESULT_BAD_ENTRY,
+ TOKEN_DB_RESULT_DECRYPT_ERROR,
+ TOKEN_DB_RESULT_SUCCESS
+ };
+
TokenServiceTable() {}
~TokenServiceTable() override {}
@@ -36,7 +43,7 @@ class TokenServiceTable : public WebDatabaseTable {
// Retrieves all tokens previously set with SetTokenForService.
// Returns true if there were tokens and we decrypted them,
// false if there was a failure somehow
- bool GetAllTokens(std::map<std::string, std::string>* tokens);
+ Result GetAllTokens(std::map<std::string, std::string>* tokens);
// Store a token in the token_service table. Stored encrypted. May cause
// a mac keychain popup.
diff --git a/chromium/components/signin/core/browser/webdata/token_web_data.cc b/chromium/components/signin/core/browser/webdata/token_web_data.cc
index 0c6425529c0..d8c405f0605 100644
--- a/chromium/components/signin/core/browser/webdata/token_web_data.cc
+++ b/chromium/components/signin/core/browser/webdata/token_web_data.cc
@@ -47,10 +47,10 @@ class TokenWebDataBackend
}
std::unique_ptr<WDTypedResult> GetAllTokens(WebDatabase* db) {
- std::map<std::string, std::string> map;
- TokenServiceTable::FromWebDatabase(db)->GetAllTokens(&map);
- return base::MakeUnique<WDResult<std::map<std::string, std::string>>>(
- TOKEN_RESULT, map);
+ TokenResult result;
+ result.db_result =
+ TokenServiceTable::FromWebDatabase(db)->GetAllTokens(&result.tokens);
+ return base::MakeUnique<WDResult<TokenResult>>(TOKEN_RESULT, result);
}
protected:
@@ -62,6 +62,11 @@ class TokenWebDataBackend
friend class base::DeleteHelper<TokenWebDataBackend>;
};
+TokenResult::TokenResult()
+ : db_result(TokenServiceTable::TOKEN_DB_RESULT_SQL_INVALID_STATEMENT) {}
+TokenResult::TokenResult(const TokenResult& other) = default;
+TokenResult::~TokenResult(){};
+
TokenWebData::TokenWebData(
scoped_refptr<WebDatabaseService> wdbs,
scoped_refptr<base::SingleThreadTaskRunner> ui_thread,
diff --git a/chromium/components/signin/core/browser/webdata/token_web_data.h b/chromium/components/signin/core/browser/webdata/token_web_data.h
index ceec9cdcc86..f47f371c252 100644
--- a/chromium/components/signin/core/browser/webdata/token_web_data.h
+++ b/chromium/components/signin/core/browser/webdata/token_web_data.h
@@ -18,6 +18,7 @@
#include "base/location.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "components/signin/core/browser/webdata/token_service_table.h"
#include "components/webdata/common/web_data_results.h"
#include "components/webdata/common/web_data_service_base.h"
#include "components/webdata/common/web_data_service_consumer.h"
@@ -31,6 +32,16 @@ class TokenWebDataBackend;
class WebDatabaseService;
class WebDataServiceConsumer;
+// The result of a get tokens operation.
+struct TokenResult {
+ TokenResult();
+ TokenResult(const TokenResult& other);
+ ~TokenResult();
+
+ TokenServiceTable::Result db_result;
+ std::map<std::string, std::string> tokens;
+};
+
// TokenWebData is a data repository for storage of authentication tokens.
class TokenWebData : public WebDataServiceBase {