Refactor OAuth2TokenService to have profile- and device-based implementations.

OAuth2TokenService was refactored into an abstract base class without
dependencies on Profile and the TokenService's OAuth2 login refresh token.

Added ProfileOAuth2TokenService as an implementation of OAuth2TokenService
that requires a Profile and the user's login refresh token from
TokenService. Migrated the existing OAuth2TokenServiceFactory and
OAuth2TokenServiceRequest to Profile* varients that use this new class.

Added DeviceOAuth2TokenService that serves up API access tokens for
enterprise enrolled devices (via a robot account with an any-api refresh
token). These tokens are global to all accounts on the device including
Public Accounts, and hence don't depend on a particular profile's login
credentials.

BUG=164606

Review URL: https://chromiumcodereview.appspot.com/12647008

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@194796 0039d316-1c4b-4281-b951-d872f2087c98
parent 29a093b6
...@@ -65,6 +65,7 @@ ...@@ -65,6 +65,7 @@
#include "chrome/browser/chromeos/power/user_activity_notifier.h" #include "chrome/browser/chromeos/power/user_activity_notifier.h"
#include "chrome/browser/chromeos/power/video_activity_notifier.h" #include "chrome/browser/chromeos/power/video_activity_notifier.h"
#include "chrome/browser/chromeos/screensaver/screensaver_controller.h" #include "chrome/browser/chromeos/screensaver/screensaver_controller.h"
#include "chrome/browser/chromeos/settings/device_oauth2_token_service_factory.h"
#include "chrome/browser/chromeos/settings/device_settings_service.h" #include "chrome/browser/chromeos/settings/device_settings_service.h"
#include "chrome/browser/chromeos/settings/owner_key_util.h" #include "chrome/browser/chromeos/settings/owner_key_util.h"
#include "chrome/browser/chromeos/system/automatic_reboot_manager.h" #include "chrome/browser/chromeos/system/automatic_reboot_manager.h"
...@@ -472,6 +473,8 @@ void ChromeBrowserMainPartsChromeos::PreMainMessageLoopRun() { ...@@ -472,6 +473,8 @@ void ChromeBrowserMainPartsChromeos::PreMainMessageLoopRun() {
SystemKeyEventListener::Initialize(); SystemKeyEventListener::Initialize();
} }
chromeos::DeviceOAuth2TokenServiceFactory::Initialize();
ChromeBrowserMainPartsLinux::PreMainMessageLoopRun(); ChromeBrowserMainPartsLinux::PreMainMessageLoopRun();
} }
...@@ -723,6 +726,9 @@ void ChromeBrowserMainPartsChromeos::PostMainMessageLoopRun() { ...@@ -723,6 +726,9 @@ void ChromeBrowserMainPartsChromeos::PostMainMessageLoopRun() {
// cause it to crash during shutdown. // cause it to crash during shutdown.
LoginUtils::Get()->StopBackgroundFetchers(); LoginUtils::Get()->StopBackgroundFetchers();
// Stops all in-flight OAuth2 token fetchers before the IO thread stops.
chromeos::DeviceOAuth2TokenServiceFactory::Shutdown();
// Shutdown the upgrade detector for Chrome OS. The upgrade detector // Shutdown the upgrade detector for Chrome OS. The upgrade detector
// stops monitoring changes from the update engine. // stops monitoring changes from the update engine.
if (UpgradeDetectorChromeos::GetInstance()) if (UpgradeDetectorChromeos::GetInstance())
......
// Copyright 2013 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/chromeos/settings/device_oauth2_token_service.h"
#include "base/prefs/pref_registry_simple.h"
#include "base/prefs/pref_service.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/cros/cert_library.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
#include "chrome/common/pref_names.h"
#include "content/public/browser/browser_thread.h"
namespace chromeos {
DeviceOAuth2TokenService::DeviceOAuth2TokenService(
net::URLRequestContextGetter* getter,
PrefService* local_state)
: OAuth2TokenService(getter),
local_state_(local_state) {
}
DeviceOAuth2TokenService::~DeviceOAuth2TokenService() {
}
// static
void DeviceOAuth2TokenService::RegisterPrefs(PrefRegistrySimple* registry) {
registry->RegisterStringPref(prefs::kDeviceRobotAnyApiRefreshToken,
std::string());
}
void DeviceOAuth2TokenService::SetAndSaveRefreshToken(
const std::string& refresh_token) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
std::string encrypted_refresh_token =
CrosLibrary::Get()->GetCertLibrary()->EncryptWithSystemSalt(
refresh_token);
local_state_->SetString(prefs::kDeviceRobotAnyApiRefreshToken,
encrypted_refresh_token);
}
std::string DeviceOAuth2TokenService::GetRefreshToken() {
if (refresh_token_.empty()) {
std::string encrypted_refresh_token =
local_state_->GetString(prefs::kDeviceRobotAnyApiRefreshToken);
refresh_token_ =
CrosLibrary::Get()->GetCertLibrary()->DecryptWithSystemSalt(
encrypted_refresh_token);
}
return refresh_token_;
}
} // namespace chromeos
// Copyright 2013 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 CHROME_BROWSER_CHROMEOS_SETTINGS_DEVICE_OAUTH2_TOKEN_SERVICE_H_
#define CHROME_BROWSER_CHROMEOS_SETTINGS_DEVICE_OAUTH2_TOKEN_SERVICE_H_
#include <string>
#include "base/basictypes.h"
#include "base/gtest_prod_util.h"
#include "base/memory/scoped_ptr.h"
#include "chrome/browser/signin/oauth2_token_service.h"
#include "net/url_request/url_request_context_getter.h"
namespace net {
class URLRequestContextGetter;
}
class GoogleServiceAuthError;
class PrefRegistrySimple;
class PrefService;
class Profile;
namespace chromeos {
// DeviceOAuth2TokenService retrieves OAuth2 access tokens for a given
// set of scopes using the device-level OAuth2 any-api refresh token
// obtained during enterprise device enrollment.
//
// See |OAuth2TokenService| for usage details.
//
// Note that requests must be made from the UI thread.
class DeviceOAuth2TokenService : public OAuth2TokenService {
public:
// Persist the given refresh token on the device. Overwrites any previous
// value. Should only be called during initial device setup.
void SetAndSaveRefreshToken(const std::string& refresh_token);
static void RegisterPrefs(PrefRegistrySimple* registry);
protected:
virtual std::string GetRefreshToken() OVERRIDE;
private:
friend class DeviceOAuth2TokenServiceFactory;
FRIEND_TEST_ALL_PREFIXES(DeviceOAuth2TokenServiceTest, SaveEncryptedToken);
// Use DeviceOAuth2TokenServiceFactory to get an instance of this class.
explicit DeviceOAuth2TokenService(net::URLRequestContextGetter* getter,
PrefService* local_state);
virtual ~DeviceOAuth2TokenService();
// Cache the decrypted refresh token, so we only decrypt once.
std::string refresh_token_;
PrefService* local_state_;
DISALLOW_COPY_AND_ASSIGN(DeviceOAuth2TokenService);
};
} // namespace chromeos
#endif // CHROME_BROWSER_CHROMEOS_SETTINGS_DEVICE_OAUTH2_TOKEN_SERVICE_H_
// Copyright (c) 2012 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/chromeos/settings/device_oauth2_token_service_factory.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chromeos/settings/device_oauth2_token_service.h"
#include "content/public/browser/browser_thread.h"
namespace chromeos {
static DeviceOAuth2TokenService* g_device_oauth2_token_service_ = NULL;
DeviceOAuth2TokenServiceFactory::DeviceOAuth2TokenServiceFactory() {
}
// static
DeviceOAuth2TokenService* DeviceOAuth2TokenServiceFactory::Get() {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
return g_device_oauth2_token_service_;
}
// static
void DeviceOAuth2TokenServiceFactory::Initialize() {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
DCHECK(!g_device_oauth2_token_service_);
g_device_oauth2_token_service_ = new DeviceOAuth2TokenService(
g_browser_process->system_request_context(),
g_browser_process->local_state());
}
// static
void DeviceOAuth2TokenServiceFactory::Shutdown() {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
if (g_device_oauth2_token_service_) {
delete g_device_oauth2_token_service_;
g_device_oauth2_token_service_ = NULL;
}
}
} // namespace chromeos
// Copyright 2013 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 CHROME_BROWSER_CHROMEOS_SETTINGS_DEVICE_OAUTH2_TOKEN_SERVICE_FACTORY_H_
#define CHROME_BROWSER_CHROMEOS_SETTINGS_DEVICE_OAUTH2_TOKEN_SERVICE_FACTORY_H_
#include "base/basictypes.h"
namespace chromeos {
class DeviceOAuth2TokenService;
class DeviceOAuth2TokenServiceFactory {
public:
// Returns the instance of the DeviceOAuth2TokenService singleton.
// May return null during browser startup and shutdown. Do not hold
// the pointer returned by this method; call this method every time
// and check for null to handle the case where this instance is destroyed
// during shutdown.
static DeviceOAuth2TokenService* Get();
private:
friend class ChromeBrowserMainPartsChromeos;
DeviceOAuth2TokenServiceFactory();
// Called by ChromeBrowserMainPartsChromeOS in order to bootstrap the
// DeviceOAuth2TokenService instance after the required global data is
// available (local state and request context getter).
static void Initialize();
// Called by ChromeBrowserMainPartsChromeOS in order to shutdown the
// DeviceOAuth2TokenService instance and cancel all in-flight requests
// before the required global data is destroyed (local state and request
// context getter).
static void Shutdown();
DISALLOW_COPY_AND_ASSIGN(DeviceOAuth2TokenServiceFactory);
};
} // namespace chromeos
#endif // CHROME_BROWSER_CHROMEOS_SETTINGS_DEVICE_OAUTH2_TOKEN_SERVICE_FACTORY_H_
// Copyright 2013 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/chromeos/settings/device_oauth2_token_service.h"
#include "base/message_loop.h"
#include "base/prefs/testing_pref_service.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
#include "chrome/browser/chromeos/cros/mock_cert_library.h"
#include "chrome/test/base/scoped_testing_local_state.h"
#include "chrome/test/base/testing_browser_process.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/test/test_browser_thread.h"
#include "net/url_request/url_request_test_util.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using ::testing::_;
using ::testing::AnyNumber;
using ::testing::Return;
using ::testing::StrEq;
using ::testing::StrictMock;
namespace chromeos {
class DeviceOAuth2TokenServiceTest : public testing::Test {
public:
DeviceOAuth2TokenServiceTest()
: ui_thread_(content::BrowserThread::UI, &message_loop_),
scoped_testing_local_state_(TestingBrowserProcess::GetGlobal()) {}
virtual ~DeviceOAuth2TokenServiceTest() {}
virtual void SetUp() OVERRIDE {
chromeos::CrosLibrary::Initialize(true);
}
virtual void TearDown() OVERRIDE {
chromeos::CrosLibrary::Shutdown();
}
protected:
MessageLoop message_loop_;
content::TestBrowserThread ui_thread_;
ScopedTestingLocalState scoped_testing_local_state_;
};
TEST_F(DeviceOAuth2TokenServiceTest, SaveEncryptedToken) {
StrictMock<MockCertLibrary> mock_cert_library;
chromeos::CrosLibrary::Get()->GetTestApi()->SetCertLibrary(
&mock_cert_library, false);
EXPECT_CALL(mock_cert_library, DecryptWithSystemSalt(StrEq("")))
.Times(1)
.WillOnce(Return(""));
EXPECT_CALL(mock_cert_library, EncryptWithSystemSalt(StrEq("test-token")))
.Times(1)
.WillOnce(Return("encrypted"));
EXPECT_CALL(mock_cert_library, DecryptWithSystemSalt(StrEq("encrypted")))
.Times(1)
.WillOnce(Return("test-token"));
DeviceOAuth2TokenService oauth2_service(
new net::TestURLRequestContextGetter(
content::BrowserThread::GetMessageLoopProxyForThread(
content::BrowserThread::IO)),
scoped_testing_local_state_.Get());
ASSERT_EQ("", oauth2_service.GetRefreshToken());
oauth2_service.SetAndSaveRefreshToken("test-token");
ASSERT_EQ("test-token", oauth2_service.GetRefreshToken());
// This call won't invoke decrypt again, since the value is cached.
ASSERT_EQ("test-token", oauth2_service.GetRefreshToken());
}
} // namespace chromeos
...@@ -40,7 +40,8 @@ include_rules = [ ...@@ -40,7 +40,8 @@ include_rules = [
"!chrome/browser/profiles/refcounted_profile_keyed_service_factory.h", "!chrome/browser/profiles/refcounted_profile_keyed_service_factory.h",
"!chrome/browser/profiles/refcounted_profile_keyed_service_factory.h", "!chrome/browser/profiles/refcounted_profile_keyed_service_factory.h",
"!chrome/browser/signin/oauth2_token_service.h", "!chrome/browser/signin/oauth2_token_service.h",
"!chrome/browser/signin/oauth2_token_service_factory.h", "!chrome/browser/signin/profile_oauth2_token_service.h",
"!chrome/browser/signin/profile_oauth2_token_service_factory.h",
"!chrome/browser/signin/token_service_factory.h", "!chrome/browser/signin/token_service_factory.h",
"!chrome/browser/sync/profile_sync_service.h", "!chrome/browser/sync/profile_sync_service.h",
"!chrome/browser/sync/profile_sync_service_factory.h", "!chrome/browser/sync/profile_sync_service_factory.h",
......
...@@ -11,7 +11,8 @@ ...@@ -11,7 +11,8 @@
#include "base/utf_string_conversions.h" #include "base/utf_string_conversions.h"
#include "base/values.h" #include "base/values.h"
#include "chrome/browser/signin/oauth2_token_service.h" #include "chrome/browser/signin/oauth2_token_service.h"
#include "chrome/browser/signin/oauth2_token_service_factory.h" #include "chrome/browser/signin/profile_oauth2_token_service.h"
#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
#include "google_apis/gaia/gaia_urls.h" #include "google_apis/gaia/gaia_urls.h"
#include "google_apis/gaia/google_service_auth_error.h" #include "google_apis/gaia/google_service_auth_error.h"
#include "googleurl/src/gurl.h" #include "googleurl/src/gurl.h"
...@@ -73,8 +74,8 @@ class RequestImpl : public WebHistoryService::Request, ...@@ -73,8 +74,8 @@ class RequestImpl : public WebHistoryService::Request,
OAuth2TokenService::ScopeSet oauth_scopes; OAuth2TokenService::ScopeSet oauth_scopes;
oauth_scopes.insert(kHistoryOAuthScope); oauth_scopes.insert(kHistoryOAuthScope);
OAuth2TokenService* token_service = ProfileOAuth2TokenService* token_service =
OAuth2TokenServiceFactory::GetForProfile(profile_); ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
token_request_ = token_service->StartRequest(oauth_scopes, this); token_request_ = token_service->StartRequest(oauth_scopes, this);
} }
...@@ -88,8 +89,8 @@ class RequestImpl : public WebHistoryService::Request, ...@@ -88,8 +89,8 @@ class RequestImpl : public WebHistoryService::Request,
if (response_code_ == net::HTTP_UNAUTHORIZED && ++auth_retry_count_ <= 1) { if (response_code_ == net::HTTP_UNAUTHORIZED && ++auth_retry_count_ <= 1) {
OAuth2TokenService::ScopeSet oauth_scopes; OAuth2TokenService::ScopeSet oauth_scopes;
oauth_scopes.insert(kHistoryOAuthScope); oauth_scopes.insert(kHistoryOAuthScope);
OAuth2TokenServiceFactory::GetForProfile(profile_)->InvalidateToken( ProfileOAuth2TokenServiceFactory::GetForProfile(profile_)
oauth_scopes, access_token_); ->InvalidateToken(oauth_scopes, access_token_);
access_token_ = std::string(); access_token_ = std::string();
Start(); Start();
......
...@@ -129,6 +129,7 @@ ...@@ -129,6 +129,7 @@
#include "chrome/browser/chromeos/policy/device_status_collector.h" #include "chrome/browser/chromeos/policy/device_status_collector.h"
#include "chrome/browser/chromeos/preferences.h" #include "chrome/browser/chromeos/preferences.h"
#include "chrome/browser/chromeos/proxy_config_service_impl.h" #include "chrome/browser/chromeos/proxy_config_service_impl.h"
#include "chrome/browser/chromeos/settings/device_oauth2_token_service.h"
#include "chrome/browser/chromeos/settings/device_settings_cache.h" #include "chrome/browser/chromeos/settings/device_settings_cache.h"
#include "chrome/browser/chromeos/status/data_promo_notification.h" #include "chrome/browser/chromeos/status/data_promo_notification.h"
#include "chrome/browser/chromeos/system/automatic_reboot_manager.h" #include "chrome/browser/chromeos/system/automatic_reboot_manager.h"
...@@ -239,6 +240,7 @@ void RegisterLocalState(PrefRegistrySimple* registry) { ...@@ -239,6 +240,7 @@ void RegisterLocalState(PrefRegistrySimple* registry) {
#if defined(OS_CHROMEOS) #if defined(OS_CHROMEOS)
chromeos::AudioHandler::RegisterPrefs(registry); chromeos::AudioHandler::RegisterPrefs(registry);
chromeos::DataPromoNotification::RegisterPrefs(registry); chromeos::DataPromoNotification::RegisterPrefs(registry);
chromeos::DeviceOAuth2TokenService::RegisterPrefs(registry);
chromeos::device_settings_cache::RegisterPrefs(registry); chromeos::device_settings_cache::RegisterPrefs(registry);
chromeos::language_prefs::RegisterPrefs(registry); chromeos::language_prefs::RegisterPrefs(registry);
chromeos::KioskAppManager::RegisterPrefs(registry); chromeos::KioskAppManager::RegisterPrefs(registry);
......
// Copyright 2013 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/signin/android_profile_oauth2_token_service.h"
#include "base/bind.h"
#include "chrome/browser/sync/profile_sync_service_android.h"
#include "content/public/browser/browser_thread.h"
#include "net/url_request/url_request_context_getter.h"
AndroidProfileOAuth2TokenService::AndroidProfileOAuth2TokenService(
net::URLRequestContextGetter* getter)
: ProfileOAuth2TokenService(getter) {
}
AndroidProfileOAuth2TokenService::~AndroidProfileOAuth2TokenService() {
}
scoped_ptr<OAuth2TokenService::Request>
AndroidProfileOAuth2TokenService::StartRequest(
const OAuth2TokenService::ScopeSet& scopes,
OAuth2TokenService::Consumer* consumer) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
if (HasCacheEntry(scopes))
return StartCacheLookupRequest(scopes, consumer);
scoped_ptr<RequestImpl> request(new RequestImpl(consumer));
DCHECK_EQ(scopes.size(), 1U);
std::vector<std::string> scope_list(scopes.begin(), scopes.end());
ProfileSyncServiceAndroid* sync_service =
ProfileSyncServiceAndroid::GetProfileSyncServiceAndroid();
sync_service->FetchOAuth2Token(
scope_list.front(),
base::Bind(&OAuth2TokenService::InformConsumer,
request->AsWeakPtr()));
return request.PassAs<Request>();
}
void AndroidProfileOAuth2TokenService::InvalidateToken(
const ScopeSet& scopes,
const std::string& invalid_token) {
OAuth2TokenService::InvalidateToken(scopes, invalid_token);
DCHECK_EQ(scopes.size(), 1U);
std::vector<std::string> scope_list(scopes.begin(), scopes.end());
ProfileSyncServiceAndroid* sync_service =
ProfileSyncServiceAndroid::GetProfileSyncServiceAndroid();
sync_service->InvalidateOAuth2Token(
scope_list.front(),
invalid_token);
}
bool AndroidProfileOAuth2TokenService::ShouldCacheForRefreshToken(
TokenService *token_service,
const std::string& refresh_token) {
// The parent class skips caching if the TokenService login token is stale,
// but on Android the user is always logged in to exactly one profile, so
// this concept doesn't exist and we can simply always cache.
return true;
}
// Copyright 2013 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 CHROME_BROWSER_SIGNIN_ANDROID_PROFILE_OAUTH2_TOKEN_SERVICE_H_
#define CHROME_BROWSER_SIGNIN_ANDROID_PROFILE_OAUTH2_TOKEN_SERVICE_H_
#include <string>
#include "chrome/browser/signin/profile_oauth2_token_service.h"
namespace net {
class URLRequestContextGetter;
}
class TokenService;
// A specialization of ProfileOAuth2TokenService that will be returned by
// ProfileOAuth2TokenServiceFactory for OS_ANDROID. This instance uses
// native Android features to lookup OAuth2 tokens.
//
// See |ProfileOAuth2TokenService| for usage details.
//
// Note: requests should be started from the UI thread. To start a
// request from other thread, please use ProfileOAuth2TokenServiceRequest.
class AndroidProfileOAuth2TokenService : public ProfileOAuth2TokenService {
public:
// Start the OAuth2 access token for the given scopes using
// ProfileSyncServiceAndroid.
virtual scoped_ptr<OAuth2TokenService::Request> StartRequest(
const OAuth2TokenService::ScopeSet& scopes,
OAuth2TokenService::Consumer* consumer) OVERRIDE;
virtual void InvalidateToken(const ScopeSet& scopes,
const std::string& invalid_token) OVERRIDE;
protected:
friend class ProfileOAuth2TokenServiceFactory;
explicit AndroidProfileOAuth2TokenService(
net::URLRequestContextGetter* getter);
virtual ~AndroidProfileOAuth2TokenService();
// Takes injected TokenService for testing.
bool ShouldCacheForRefreshToken(TokenService *token_service,
const std::string& refresh_token);
private:
DISALLOW_COPY_AND_ASSIGN(AndroidProfileOAuth2TokenService);
};
#endif // CHROME_BROWSER_SIGNIN_ANDROID_PROFILE_OAUTH2_TOKEN_SERVICE_H_
...@@ -9,23 +9,27 @@ ...@@ -9,23 +9,27 @@
#include <set> #include <set>
#include <string> #include <string>
#include "base/basictypes.h"
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/time.h" #include "base/time.h"
#include "chrome/browser/profiles/profile_keyed_service.h"
#include "chrome/browser/signin/signin_global_error.h" namespace base {
#include "content/public/browser/notification_observer.h" class Time;
#include "content/public/browser/notification_registrar.h" }
#include "net/url_request/url_request_context_getter.h"
namespace net {
class URLRequestContextGetter;
}
class GoogleServiceAuthError; class GoogleServiceAuthError;
class OAuth2AccessTokenConsumer;
class Profile;
// OAuth2TokenService is a ProfileKeyedService that retrieves OAuth2 access // Abstract base class for a service that fetches and caches OAuth2 access
// tokens for a given set of scopes using the OAuth2 refresh token maintained by // tokens. Concrete subclasses should implement GetRefreshToken to return
// TokenService. All calls are expected from the UI thread. // the appropriate refresh token.
//
// All calls are expected from the UI thread.
// //
// To use this service, call StartRequest() with a given set of scopes and a // To use this service, call StartRequest() with a given set of scopes and a
// consumer of the request results. The consumer is required to outlive the // consumer of the request results. The consumer is required to outlive the
...@@ -43,12 +47,7 @@ class Profile; ...@@ -43,12 +47,7 @@ class Profile;
// //
// The caller of StartRequest() owns the returned request and is responsible to // The caller of StartRequest() owns the returned request and is responsible to
// delete the request even once the callback has been invoked. // delete the request even once the callback has been invoked.
// class OAuth2TokenService {
// Note the request should be started from the UI thread. To start a request
// from other thread, please use OAuth2TokenServiceRequest.
class OAuth2TokenService : public content::NotificationObserver,
public SigninGlobalError::AuthStatusProvider,
public ProfileKeyedService {
public: public:
// Class representing a request that fetches an OAuth2 access token. // Class representing a request that fetches an OAuth2 access token.
class Request { class Request {
...@@ -76,58 +75,90 @@ class OAuth2TokenService : public content::NotificationObserver, ...@@ -76,58 +75,90 @@ class OAuth2TokenService : public content::NotificationObserver,
// A set of scopes in OAuth2 authentication. // A set of scopes in OAuth2 authentication.
typedef std::set<std::string> ScopeSet; typedef std::set<std::string> ScopeSet;
OAuth2TokenService(); explicit OAuth2TokenService(net::URLRequestContextGetter* getter);
virtual ~OAuth2TokenService(); virtual ~OAuth2TokenService();
// Initializes this token service with the profile. // Checks in the cache for a valid access token, and if not found starts
void Initialize(Profile* profile); // a request for an OAuth2 access token using the OAuth2 refresh token
// maintained by this instance. The caller owns the returned Request.
// ProfileKeyedService implementation. // |scopes| is the set of scopes to get an access token for, |consumer| is
virtual void Shutdown() OVERRIDE; // the object that will be called back with results if the returned request
// is not deleted.
// Starts a request for an OAuth2 access token using the OAuth2 refresh token virtual scoped_ptr<Request> StartRequest(const ScopeSet& scopes,
// maintained by TokenService. The caller owns the returned Request. |scopes| Consumer* consumer);
// is the set of scopes to get an access token for, |consumer| is the object
// that will be called back with results if the returned request is not // Returns true if a refresh token exists. If false, calls to
// deleted. // |StartRequest| will result in a Consumer::OnGetTokenFailure callback.
// Note the refresh token has been collected from TokenService when this bool RefreshTokenIsAvailable();
// method returns, and the request can continue even if TokenService clears
// its tokens after this method returns. This means that outstanding
// StartRequest actions will still complete even if the user signs out in the
// meantime.
virtual scoped_ptr<Request> StartRequest(
const ScopeSet& scopes,
OAuth2TokenService::Consumer* consumer);
// Mark an OAuth2 access token as invalid. This should be done if the token // Mark an OAuth2 access token as invalid. This should be done if the token
// was received from this class, but was not accepted by the server (e.g., // was received from this class, but was not accepted by the server (e.g.,
// the server returned 401 Unauthorized). The token will be removed from the // the server returned 401 Unauthorized). The token will be removed from the
// cache for the given scopes. // cache for the given scopes.
void InvalidateToken(const ScopeSet& scopes, virtual void InvalidateToken(const ScopeSet& scopes,
const std::string& invalid_token); const std::string& invalid_token);
// content::NotificationObserver // Return the current number of entries in the cache.
virtual void Observe(int type, int cache_size_for_testing() const;
const content::NotificationSource& source,
const content::NotificationDetails& details) OVERRIDE; protected:
// Subclasses should return the refresh token maintained.
// If no token is available, return an empty string.
virtual std::string GetRefreshToken() = 0;
// Subclasses can override if they want to report errors to the user.
virtual void UpdateAuthError(const GoogleServiceAuthError& error);
// Add a new entry to the cache.
// Subclasses can override if there are implementation-specific reasons
// that an access token should ever not be cached.
virtual void RegisterCacheEntry(const std::string& refresh_token,
const ScopeSet& scopes,
const std::string& access_token,
const base::Time& expiration_date);
// Returns true if GetCacheEntry would return a valid cache entry for the
// given scopes.
bool HasCacheEntry(const ScopeSet& scopes);
// Posts a task to fire the Consumer callback with the cached token. Must
// only be called if HasCacheEntry() returns true.
scoped_ptr<Request> StartCacheLookupRequest(const ScopeSet& scopes,
Consumer* consumer);
// Clears the internal token cache.
void ClearCache();
// Implements a cancelable |OAuth2TokenService::Request|, which should be
// operated on the UI thread.
class RequestImpl : public base::SupportsWeakPtr<RequestImpl>,
public Request {
public:
// |consumer| is required to outlive this.
explicit RequestImpl(Consumer* consumer);
virtual ~RequestImpl();
// Informs |consumer_| that this request is completed.
void InformConsumer(const GoogleServiceAuthError& error,
const std::string& access_token,
const base::Time& expiration_date);
private:
// |consumer_| to call back when this request completes.
Consumer* const consumer_;
};
// SigninGlobalError::AuthStatusProvider implementation. // Informs the consumer of |request| fetch results.
virtual GoogleServiceAuthError GetAuthStatus() const OVERRIDE; static void InformConsumer(base::WeakPtr<RequestImpl> request,
const GoogleServiceAuthError& error,
const std::string& access_token,
const base::Time& expiration_date);
private: private:
// Class that fetches an OAuth2 access token for a given set of scopes and // Class that fetches an OAuth2 access token for a given set of scopes and
// OAuth2 refresh token. // OAuth2 refresh token.
class Fetcher; class Fetcher;
friend class Fetcher; friend class Fetcher;
// Implementation of Request.
class RequestImpl;
// Informs the consumer of |request| fetch results.
static void InformConsumer(
base::WeakPtr<OAuth2TokenService::RequestImpl> request,
const GoogleServiceAuthError& error,
const std::string& access_token,
const base::Time& expiration_date);
// Struct that contains the information of an OAuth2 access token. // Struct that contains the information of an OAuth2 access token.
struct CacheEntry { struct CacheEntry {
...@@ -141,12 +172,6 @@ class OAuth2TokenService : public content::NotificationObserver, ...@@ -141,12 +172,6 @@ class OAuth2TokenService : public content::NotificationObserver,
// returned entry is done. // returned entry is done.
const CacheEntry* GetCacheEntry(const ScopeSet& scopes); const CacheEntry* GetCacheEntry(const ScopeSet& scopes);
// Registers a new access token in the cache if |refresh_token| is the one
// currently held by TokenService.
void RegisterCacheEntry(const std::string& refresh_token,
const ScopeSet& scopes,
const std::string& access_token,
const base::Time& expiration_date);
// Removes an access token for the given set of scopes from the cache. // Removes an access token for the given set of scopes from the cache.
// Returns true if the entry was removed, otherwise false. // Returns true if the entry was removed, otherwise false.
...@@ -157,18 +182,8 @@ class OAuth2TokenService : public content::NotificationObserver, ...@@ -157,18 +182,8 @@ class OAuth2TokenService : public content::NotificationObserver,
// Called when |fetcher| finishes fetching. // Called when |fetcher| finishes fetching.
void OnFetchComplete(Fetcher* fetcher); void OnFetchComplete(Fetcher* fetcher);
// Updates the internal cache of the result from the most-recently-completed
// auth request (used for reporting errors to the user).
void UpdateAuthError(const GoogleServiceAuthError& error);
// The profile with which this instance was initialized, or NULL.
Profile* profile_;
// The auth status from the most-recently-completed request.
GoogleServiceAuthError last_auth_error_;
// Getter to use for fetchers. // Getter to use for fetchers.
scoped_refptr<net::URLRequestContextGetter> getter_; scoped_refptr<net::URLRequestContextGetter> request_context_getter_;
// The cache of currently valid tokens. // The cache of currently valid tokens.
typedef std::map<ScopeSet, CacheEntry> TokenCache; typedef std::map<ScopeSet, CacheEntry> TokenCache;
...@@ -181,9 +196,6 @@ class OAuth2TokenService : public content::NotificationObserver, ...@@ -181,9 +196,6 @@ class OAuth2TokenService : public content::NotificationObserver,
// token using these parameters. // token using these parameters.
std::map<FetchParameters, Fetcher*> pending_fetchers_; std::map<FetchParameters, Fetcher*> pending_fetchers_;
// Registrar for notifications from the TokenService.
content::NotificationRegistrar registrar_;
DISALLOW_COPY_AND_ASSIGN(OAuth2TokenService); DISALLOW_COPY_AND_ASSIGN(OAuth2TokenService);
}; };
......
// Copyright 2013 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/signin/oauth2_token_service_test_util.h"
const char kValidTokenResponse[] =
"{"
" \"access_token\": \"%s\","
" \"expires_in\": %d,"
" \"token_type\": \"Bearer\""
"}";
std::string GetValidTokenResponse(std::string token, int expiration) {
return base::StringPrintf(kValidTokenResponse, token.c_str(), expiration);
}
TestingOAuth2TokenServiceConsumer::TestingOAuth2TokenServiceConsumer()
: number_of_successful_tokens_(0),
last_error_(GoogleServiceAuthError::AuthErrorNone()),
number_of_errors_(0) {
}
TestingOAuth2TokenServiceConsumer::~TestingOAuth2TokenServiceConsumer() {
}
void TestingOAuth2TokenServiceConsumer::OnGetTokenSuccess(
const OAuth2TokenService::Request* request,
const std::string& token,
const base::Time& expiration_date) {
last_token_ = token;
++number_of_successful_tokens_;
}
void TestingOAuth2TokenServiceConsumer::OnGetTokenFailure(
const OAuth2TokenService::Request* request,
const GoogleServiceAuthError& error) {
last_error_ = error;
++number_of_errors_;
}
// Copyright 2013 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 CHROME_BROWSER_SIGNIN_OAUTH2_TOKEN_SERVICE_TEST_UTIL_H_
#define CHROME_BROWSER_SIGNIN_OAUTH2_TOKEN_SERVICE_TEST_UTIL_H_
#include "chrome/browser/signin/oauth2_token_service.h"
#include <string>
#include "base/stringprintf.h"
#include "google_apis/gaia/google_service_auth_error.h"
extern const char kValidTokenResponse[];
std::string GetValidTokenResponse(std::string token, int expiration);
// A simple testing consumer.
class TestingOAuth2TokenServiceConsumer : public OAuth2TokenService::Consumer {
public:
TestingOAuth2TokenServiceConsumer();
virtual ~TestingOAuth2TokenServiceConsumer();
// OAuth2TokenService::Consumer overrides.
virtual void OnGetTokenSuccess(const OAuth2TokenService::Request* request,
const std::string& token,
const base::Time& expiration_date) OVERRIDE;
virtual void OnGetTokenFailure(const OAuth2TokenService::Request* request,
const GoogleServiceAuthError& error) OVERRIDE;
std::string last_token_;
int number_of_successful_tokens_;
GoogleServiceAuthError last_error_;
int number_of_errors_;
};
#endif // CHROME_BROWSER_SIGNIN_OAUTH2_TOKEN_SERVICE_TEST_UTIL_H_
// Copyright 2013 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/signin/profile_oauth2_token_service.h"
#include "base/bind.h"
#include "base/message_loop.h"
#include "base/stl_util.h"
#include "base/time.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/signin/signin_manager.h"
#include "chrome/browser/signin/signin_manager_factory.h"
#include "chrome/browser/signin/token_service.h"
#include "chrome/browser/signin/token_service_factory.h"
#include "chrome/common/chrome_notification_types.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_source.h"
#include "google_apis/gaia/gaia_constants.h"
#include "google_apis/gaia/google_service_auth_error.h"
#include "net/url_request/url_request_context_getter.h"
ProfileOAuth2TokenService::ProfileOAuth2TokenService(
net::URLRequestContextGetter* getter)
: OAuth2TokenService(getter),
profile_(NULL),
last_auth_error_(GoogleServiceAuthError::NONE) {
}
ProfileOAuth2TokenService::~ProfileOAuth2TokenService() {
}
void ProfileOAuth2TokenService::Initialize(Profile* profile) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
DCHECK(profile);
DCHECK(!profile_);
profile_ = profile;
content::Source<TokenService> token_service_source(
TokenServiceFactory::GetForProfile(profile));
registrar_.Add(this,
chrome::NOTIFICATION_TOKENS_CLEARED,
token_service_source);
registrar_.Add(this,
chrome::NOTIFICATION_TOKEN_AVAILABLE,
token_service_source);
SigninManagerFactory::GetForProfile(profile_)->signin_global_error()->
AddProvider(this);
}
void ProfileOAuth2TokenService::Shutdown() {
if (profile_) {
SigninManagerFactory::GetForProfile(profile_)->signin_global_error()->
RemoveProvider(this);
}
}
std::string ProfileOAuth2TokenService::GetRefreshToken() {
TokenService* token_service = TokenServiceFactory::GetForProfile(profile_);
if (!token_service || !token_service->HasOAuthLoginToken()) {
return std::string();
}
return token_service->GetOAuth2LoginRefreshToken();
}
void ProfileOAuth2TokenService::UpdateAuthError(
const GoogleServiceAuthError& error) {
// Do not report connection errors as these are not actually auth errors.
// We also want to avoid masking a "real" auth error just because we
// subsequently get a transient network error.
if (error.state() == GoogleServiceAuthError::CONNECTION_FAILED)
return;
if (error.state() != last_auth_error_.state()) {
last_auth_error_ = error;
SigninManagerFactory::GetForProfile(profile_)->signin_global_error()->
AuthStatusChanged();
}
}
void ProfileOAuth2TokenService::Observe(
int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
DCHECK(type == chrome::NOTIFICATION_TOKENS_CLEARED ||
type == chrome::NOTIFICATION_TOKEN_AVAILABLE);
if (type == chrome::NOTIFICATION_TOKEN_AVAILABLE) {
TokenService::TokenAvailableDetails* tok_details =
content::Details<TokenService::TokenAvailableDetails>(details).ptr();
if (tok_details->service() != GaiaConstants::kGaiaOAuth2LoginRefreshToken)
return;
}
// The GaiaConstants::kGaiaOAuth2LoginRefreshToken token is used to create
// OAuth2 access tokens. If this token either changes or is cleared, any
// available tokens must be invalidated.
ClearCache();
UpdateAuthError(GoogleServiceAuthError::AuthErrorNone());
}
GoogleServiceAuthError ProfileOAuth2TokenService::GetAuthStatus() const {
return last_auth_error_;
}
void ProfileOAuth2TokenService::RegisterCacheEntry(
const std::string& refresh_token,
const ScopeSet& scopes,
const std::string& access_token,
const base::Time& expiration_date) {
if (ShouldCacheForRefreshToken(TokenServiceFactory::GetForProfile(profile_),
refresh_token)) {
OAuth2TokenService::RegisterCacheEntry(refresh_token,
scopes,
access_token,
expiration_date);
}
}
bool ProfileOAuth2TokenService::ShouldCacheForRefreshToken(
TokenService *token_service,
const std::string& refresh_token) {
if (!token_service ||
!token_service->HasOAuthLoginToken() ||
token_service->GetOAuth2LoginRefreshToken().compare(refresh_token) != 0) {
DLOG(INFO) <<
"Received a token with a refresh token not maintained by TokenService.";
return false;
}
return true;
}
// Copyright 2013 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 CHROME_BROWSER_SIGNIN_PROFILE_OAUTH2_TOKEN_SERVICE_H_
#define CHROME_BROWSER_SIGNIN_PROFILE_OAUTH2_TOKEN_SERVICE_H_
#include <string>
#include "base/gtest_prod_util.h"
#include "chrome/browser/profiles/profile_keyed_service.h"
#include "chrome/browser/signin/oauth2_token_service.h"
#include "chrome/browser/signin/signin_global_error.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
namespace net {
class URLRequestContextGetter;
}
class GoogleServiceAuthError;
class Profile;
class TokenService;
// ProfileOAuth2TokenService is a ProfileKeyedService that retrieves
// OAuth2 access tokens for a given set of scopes using the OAuth2 login
// refresh token maintained by TokenService.
//
// See |OAuth2TokenService| for usage details.
//
// Note: after StartRequest returns, in-flight requests will continue
// even if the TokenService refresh token that was used to initiate
// the request changes or is cleared. When the request completes,
// Consumer::OnGetTokenSuccess will be invoked, but the access token
// won't be cached.
//
// Note: requests should be started from the UI thread. To start a
// request from other thread, please use ProfileOAuth2TokenServiceRequest.
class ProfileOAuth2TokenService : public OAuth2TokenService,
public content::NotificationObserver,
public SigninGlobalError::AuthStatusProvider,
public ProfileKeyedService {
public:
// content::NotificationObserver listening for TokenService updates.
virtual void Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) OVERRIDE;
// Initializes this token service with the profile.
virtual void Initialize(Profile* profile);
// ProfileKeyedService implementation.
virtual void Shutdown() OVERRIDE;
// SigninGlobalError::AuthStatusProvider implementation.
virtual GoogleServiceAuthError GetAuthStatus() const OVERRIDE;
// Takes injected TokenService for testing.
bool ShouldCacheForRefreshToken(TokenService *token_service,
const std::string& refresh_token);
protected:
friend class ProfileOAuth2TokenServiceFactory;
explicit ProfileOAuth2TokenService(net::URLRequestContextGetter* getter);
virtual ~ProfileOAuth2TokenService();
virtual std::string GetRefreshToken() OVERRIDE;
// Updates the internal cache of the result from the most-recently-completed
// auth request (used for reporting errors to the user).
virtual void UpdateAuthError(const GoogleServiceAuthError& error) OVERRIDE;
// Overridden to not cache tokens if the TokenService refresh token
// changes while a token fetch is in-flight. If the user logs out and
// logs back in with a different account, then any in-flight token
// fetches will be for the old account's refresh token. Therefore
// when they come back, they shouldn't be cached.
virtual void RegisterCacheEntry(const std::string& refresh_token,
const ScopeSet& scopes,
const std::string& access_token,
const base::Time& expiration_date) OVERRIDE;
private:
FRIEND_TEST_ALL_PREFIXES(ProfileOAuth2TokenServiceTest,
StaleRefreshTokensNotCached);
FRIEND_TEST_ALL_PREFIXES(ProfileOAuth2TokenServiceTest,
TokenServiceUpdateClearsCache);
// The profile with which this instance was initialized, or NULL.
Profile* profile_;
// The auth status from the most-recently-completed request.
GoogleServiceAuthError last_auth_error_;
// Registrar for notifications from the TokenService.
content::NotificationRegistrar registrar_;
DISALLOW_COPY_AND_ASSIGN(ProfileOAuth2TokenService);
};
#endif // CHROME_BROWSER_SIGNIN_PROFILE_OAUTH2_TOKEN_SERVICE_H_
...@@ -2,37 +2,49 @@ ...@@ -2,37 +2,49 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "chrome/browser/signin/oauth2_token_service_factory.h" #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_dependency_manager.h" #include "chrome/browser/profiles/profile_dependency_manager.h"
#include "chrome/browser/signin/oauth2_token_service.h" #include "chrome/browser/signin/profile_oauth2_token_service.h"
#include "chrome/browser/signin/signin_manager_factory.h" #include "chrome/browser/signin/signin_manager_factory.h"
#include "chrome/browser/signin/token_service_factory.h" #include "chrome/browser/signin/token_service_factory.h"
OAuth2TokenServiceFactory::OAuth2TokenServiceFactory() #if defined(OS_ANDROID)
: ProfileKeyedServiceFactory("OAuth2TokenService", #include "chrome/browser/signin/android_profile_oauth2_token_service.h"
#endif
ProfileOAuth2TokenServiceFactory::ProfileOAuth2TokenServiceFactory()
: ProfileKeyedServiceFactory("ProfileOAuth2TokenService",
ProfileDependencyManager::GetInstance()) { ProfileDependencyManager::GetInstance()) {
DependsOn(SigninManagerFactory::GetInstance()); DependsOn(SigninManagerFactory::GetInstance());
DependsOn(TokenServiceFactory::GetInstance()); DependsOn(TokenServiceFactory::GetInstance());
} }
OAuth2TokenServiceFactory::~OAuth2TokenServiceFactory() { ProfileOAuth2TokenServiceFactory::~ProfileOAuth2TokenServiceFactory() {
} }
// static // static
OAuth2TokenService* OAuth2TokenServiceFactory::GetForProfile(Profile* profile) { ProfileOAuth2TokenService* ProfileOAuth2TokenServiceFactory::GetForProfile(
return static_cast<OAuth2TokenService*>( Profile* profile) {
return static_cast<ProfileOAuth2TokenService*>(
GetInstance()->GetServiceForProfile(profile, true)); GetInstance()->GetServiceForProfile(profile, true));
} }
// static // static
OAuth2TokenServiceFactory* OAuth2TokenServiceFactory::GetInstance() { ProfileOAuth2TokenServiceFactory*
return Singleton<OAuth2TokenServiceFactory>::get(); ProfileOAuth2TokenServiceFactory::GetInstance() {
return Singleton<ProfileOAuth2TokenServiceFactory>::get();
} }
ProfileKeyedService* OAuth2TokenServiceFactory::BuildServiceInstanceFor( ProfileKeyedService* ProfileOAuth2TokenServiceFactory::BuildServiceInstanceFor(
Profile* profile) const { Profile* profile) const {
OAuth2TokenService* service = new OAuth2TokenService(); ProfileOAuth2TokenService* service;
#if defined(OS_ANDROID)
service = new AndroidProfileOAuth2TokenService(profile->GetRequestContext());
#else
service = new ProfileOAuth2TokenService(profile->GetRequestContext());
#endif
service->Initialize(profile); service->Initialize(profile);
return service; return service;
} }
...@@ -2,39 +2,41 @@ ...@@ -2,39 +2,41 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#ifndef CHROME_BROWSER_SIGNIN_OAUTH2_TOKEN_SERVICE_FACTORY_H_ #ifndef CHROME_BROWSER_SIGNIN_PROFILE_OAUTH2_TOKEN_SERVICE_FACTORY_H_
#define CHROME_BROWSER_SIGNIN_OAUTH2_TOKEN_SERVICE_FACTORY_H_ #define CHROME_BROWSER_SIGNIN_PROFILE_OAUTH2_TOKEN_SERVICE_FACTORY_H_
#include "base/memory/singleton.h" #include "base/memory/singleton.h"
#include "chrome/browser/profiles/profile_keyed_service_factory.h" #include "chrome/browser/profiles/profile_keyed_service_factory.h"
class OAuth2TokenService; class ProfileOAuth2TokenService;
class Profile; class Profile;
// Singleton that owns all OAuth2TokenServices and associates them with // Singleton that owns all ProfileOAuth2TokenServices and associates them with
// Profiles. Listens for the Profile's destruction notification and cleans up // Profiles. Listens for the Profile's destruction notification and cleans up
// the associated OAuth2TokenService. // the associated ProfileOAuth2TokenService.
class OAuth2TokenServiceFactory : public ProfileKeyedServiceFactory { class ProfileOAuth2TokenServiceFactory : public ProfileKeyedServiceFactory {
public: public:
// Returns the instance of OAuth2TokenService associated with this profile // Returns the instance of ProfileOAuth2TokenService associated with this
// (creating one if none exists). Returns NULL if this profile cannot have a // profile (creating one if none exists). Returns NULL if this profile
// OAuth2TokenService (for example, if |profile| is incognito). // cannot have a ProfileOAuth2TokenService (for example, if |profile| is
static OAuth2TokenService* GetForProfile(Profile* profile); // incognito). On Android, returns the AndroidProfileOAuth2TokenService
// specialization.
static ProfileOAuth2TokenService* GetForProfile(Profile* profile);
// Returns an instance of the OAuth2TokenServiceFactory singleton. // Returns an instance of the ProfileOAuth2TokenServiceFactory singleton.
static OAuth2TokenServiceFactory* GetInstance(); static ProfileOAuth2TokenServiceFactory* GetInstance();
private: private:
friend struct DefaultSingletonTraits<OAuth2TokenServiceFactory>; friend struct DefaultSingletonTraits<ProfileOAuth2TokenServiceFactory>;
OAuth2TokenServiceFactory(); ProfileOAuth2TokenServiceFactory();
virtual ~OAuth2TokenServiceFactory(); virtual ~ProfileOAuth2TokenServiceFactory();
// ProfileKeyedServiceFactory implementation. // ProfileKeyedServiceFactory implementation.
virtual ProfileKeyedService* BuildServiceInstanceFor( virtual ProfileKeyedService* BuildServiceInstanceFor(
Profile* profile) const OVERRIDE; Profile* profile) const OVERRIDE;
DISALLOW_COPY_AND_ASSIGN(OAuth2TokenServiceFactory); DISALLOW_COPY_AND_ASSIGN(ProfileOAuth2TokenServiceFactory);
}; };
#endif // CHROME_BROWSER_SIGNIN_OAUTH2_TOKEN_SERVICE_FACTORY_H_ #endif // CHROME_BROWSER_SIGNIN_PROFILE_OAUTH2_TOKEN_SERVICE_FACTORY_H_
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "chrome/browser/signin/oauth2_token_service_request.h" #include "chrome/browser/signin/profile_oauth2_token_service_request.h"
#include "base/bind.h" #include "base/bind.h"
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
...@@ -10,20 +10,20 @@ ...@@ -10,20 +10,20 @@
#include "base/single_thread_task_runner.h" #include "base/single_thread_task_runner.h"
#include "base/thread_task_runner_handle.h" #include "base/thread_task_runner_handle.h"
#include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile.h"
#include "chrome/browser/signin/oauth2_token_service.h" #include "chrome/browser/signin/profile_oauth2_token_service.h"
#include "chrome/browser/signin/oauth2_token_service_factory.h" #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
#include "google_apis/gaia/google_service_auth_error.h" #include "google_apis/gaia/google_service_auth_error.h"
#include "google_apis/gaia/oauth2_access_token_consumer.h" #include "google_apis/gaia/oauth2_access_token_consumer.h"
class OAuth2TokenServiceRequest::Core class ProfileOAuth2TokenServiceRequest::Core
: public base::RefCountedThreadSafe<OAuth2TokenServiceRequest::Core>, : public base::RefCountedThreadSafe<ProfileOAuth2TokenServiceRequest::Core>,
public OAuth2TokenService::Consumer { public OAuth2TokenService::Consumer {
public: public:
// Note the thread where an instance of Core is constructed is referred to as // Note the thread where an instance of Core is constructed is referred to as
// the "owner thread" here. This will be the thread of |owner_task_runner_|. // the "owner thread" here. This will be the thread of |owner_task_runner_|.
Core(Profile* profile, Core(Profile* profile,
OAuth2TokenServiceRequest* owner); ProfileOAuth2TokenServiceRequest* owner);
// Starts fetching an OAuth2 access token for |scopes|. It should be called // Starts fetching an OAuth2 access token for |scopes|. It should be called
// on the owner thread. // on the owner thread.
void Start(const OAuth2TokenService::ScopeSet& scopes); void Start(const OAuth2TokenService::ScopeSet& scopes);
...@@ -39,7 +39,8 @@ class OAuth2TokenServiceRequest::Core ...@@ -39,7 +39,8 @@ class OAuth2TokenServiceRequest::Core
const GoogleServiceAuthError& error) OVERRIDE; const GoogleServiceAuthError& error) OVERRIDE;
private: private:
friend class base::RefCountedThreadSafe<OAuth2TokenServiceRequest::Core>; friend class
base::RefCountedThreadSafe<ProfileOAuth2TokenServiceRequest::Core>;
// Note this can be destructed on the owner thread or on the UI thread, // Note this can be destructed on the owner thread or on the UI thread,
// depending on the reference count. // depending on the reference count.
...@@ -62,7 +63,7 @@ class OAuth2TokenServiceRequest::Core ...@@ -62,7 +63,7 @@ class OAuth2TokenServiceRequest::Core
// The object to call back when fetching completes. |owner_| should be // The object to call back when fetching completes. |owner_| should be
// called back only on the owner thread. // called back only on the owner thread.
OAuth2TokenServiceRequest* owner_; ProfileOAuth2TokenServiceRequest* owner_;
// Task runner on which |owner_| should be called back. // Task runner on which |owner_| should be called back.
scoped_refptr<base::SingleThreadTaskRunner> owner_task_runner_; scoped_refptr<base::SingleThreadTaskRunner> owner_task_runner_;
...@@ -73,9 +74,9 @@ class OAuth2TokenServiceRequest::Core ...@@ -73,9 +74,9 @@ class OAuth2TokenServiceRequest::Core
DISALLOW_COPY_AND_ASSIGN(Core); DISALLOW_COPY_AND_ASSIGN(Core);
}; };
OAuth2TokenServiceRequest::Core::Core( ProfileOAuth2TokenServiceRequest::Core::Core(
Profile* profile, Profile* profile,
OAuth2TokenServiceRequest* owner) ProfileOAuth2TokenServiceRequest* owner)
: profile_(profile), : profile_(profile),
owner_(owner), owner_(owner),
owner_task_runner_(base::ThreadTaskRunnerHandle::Get()) { owner_task_runner_(base::ThreadTaskRunnerHandle::Get()) {
...@@ -83,10 +84,10 @@ OAuth2TokenServiceRequest::Core::Core( ...@@ -83,10 +84,10 @@ OAuth2TokenServiceRequest::Core::Core(
DCHECK(owner); DCHECK(owner);
} }
OAuth2TokenServiceRequest::Core::~Core() { ProfileOAuth2TokenServiceRequest::Core::~Core() {
} }
void OAuth2TokenServiceRequest::Core::Start( void ProfileOAuth2TokenServiceRequest::Core::Start(
const OAuth2TokenService::ScopeSet& scopes) { const OAuth2TokenService::ScopeSet& scopes) {
DCHECK(owner_task_runner_->BelongsToCurrentThread()); DCHECK(owner_task_runner_->BelongsToCurrentThread());
...@@ -96,12 +97,12 @@ void OAuth2TokenServiceRequest::Core::Start( ...@@ -96,12 +97,12 @@ void OAuth2TokenServiceRequest::Core::Start(
content::BrowserThread::PostTask( content::BrowserThread::PostTask(
content::BrowserThread::UI, content::BrowserThread::UI,
FROM_HERE, FROM_HERE,
base::Bind(&OAuth2TokenServiceRequest::Core::StartOnUIThread, base::Bind(&ProfileOAuth2TokenServiceRequest::Core::StartOnUIThread,
this, scopes)); this, scopes));
} }
} }
void OAuth2TokenServiceRequest::Core::Stop() { void ProfileOAuth2TokenServiceRequest::Core::Stop() {
DCHECK(owner_task_runner_->BelongsToCurrentThread()); DCHECK(owner_task_runner_->BelongsToCurrentThread());
// Detaches |owner_| from this instance so |owner_| will be called back only // Detaches |owner_| from this instance so |owner_| will be called back only
...@@ -113,49 +114,53 @@ void OAuth2TokenServiceRequest::Core::Stop() { ...@@ -113,49 +114,53 @@ void OAuth2TokenServiceRequest::Core::Stop() {
content::BrowserThread::PostTask( content::BrowserThread::PostTask(
content::BrowserThread::UI, content::BrowserThread::UI,
FROM_HERE, FROM_HERE,
base::Bind(&OAuth2TokenServiceRequest::Core::StopOnUIThread, this)); base::Bind(&ProfileOAuth2TokenServiceRequest::Core::StopOnUIThread,
this));
} }
} }
void OAuth2TokenServiceRequest::Core::StopOnUIThread() { void ProfileOAuth2TokenServiceRequest::Core::StopOnUIThread() {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
request_.reset(); request_.reset();
} }
void OAuth2TokenServiceRequest::Core::StartOnUIThread( void ProfileOAuth2TokenServiceRequest::Core::StartOnUIThread(
const OAuth2TokenService::ScopeSet& scopes) { const OAuth2TokenService::ScopeSet& scopes) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
OAuth2TokenService* service = OAuth2TokenServiceFactory::GetForProfile( ProfileOAuth2TokenService* service =
profile_); ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
DCHECK(service); DCHECK(service);
request_.reset(service->StartRequest(scopes, this).release()); request_.reset(service->StartRequest(scopes, this).release());
} }
void OAuth2TokenServiceRequest::Core::OnGetTokenSuccess( void ProfileOAuth2TokenServiceRequest::Core::OnGetTokenSuccess(
const OAuth2TokenService::Request* request, const OAuth2TokenService::Request* request,
const std::string& access_token, const std::string& access_token,
const base::Time& expiration_time) { const base::Time& expiration_time) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
DCHECK_EQ(request_.get(), request); DCHECK_EQ(request_.get(), request);
owner_task_runner_->PostTask(FROM_HERE, base::Bind( owner_task_runner_->PostTask(FROM_HERE, base::Bind(
&OAuth2TokenServiceRequest::Core::InformOwnerOnGetTokenSuccess, this, &ProfileOAuth2TokenServiceRequest::Core::InformOwnerOnGetTokenSuccess,
access_token, expiration_time)); this,
access_token,
expiration_time));
request_.reset(); request_.reset();
} }
void OAuth2TokenServiceRequest::Core::OnGetTokenFailure( void ProfileOAuth2TokenServiceRequest::Core::OnGetTokenFailure(
const OAuth2TokenService::Request* request, const OAuth2TokenService::Request* request,
const GoogleServiceAuthError& error) { const GoogleServiceAuthError& error) {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
DCHECK_EQ(request_.get(), request); DCHECK_EQ(request_.get(), request);
owner_task_runner_->PostTask(FROM_HERE, base::Bind( owner_task_runner_->PostTask(FROM_HERE, base::Bind(
&OAuth2TokenServiceRequest::Core::InformOwnerOnGetTokenFailure, this, &ProfileOAuth2TokenServiceRequest::Core::InformOwnerOnGetTokenFailure,
this,
error)); error));
request_.reset(); request_.reset();
} }
void OAuth2TokenServiceRequest::Core::InformOwnerOnGetTokenSuccess( void ProfileOAuth2TokenServiceRequest::Core::InformOwnerOnGetTokenSuccess(
std::string access_token, std::string access_token,
base::Time expiration_time) { base::Time expiration_time) {
DCHECK(owner_task_runner_->BelongsToCurrentThread()); DCHECK(owner_task_runner_->BelongsToCurrentThread());
...@@ -164,7 +169,7 @@ void OAuth2TokenServiceRequest::Core::InformOwnerOnGetTokenSuccess( ...@@ -164,7 +169,7 @@ void OAuth2TokenServiceRequest::Core::InformOwnerOnGetTokenSuccess(
owner_->consumer_->OnGetTokenSuccess(owner_, access_token, expiration_time); owner_->consumer_->OnGetTokenSuccess(owner_, access_token, expiration_time);
} }
void OAuth2TokenServiceRequest::Core::InformOwnerOnGetTokenFailure( void ProfileOAuth2TokenServiceRequest::Core::InformOwnerOnGetTokenFailure(
GoogleServiceAuthError error) { GoogleServiceAuthError error) {
DCHECK(owner_task_runner_->BelongsToCurrentThread()); DCHECK(owner_task_runner_->BelongsToCurrentThread());
...@@ -173,14 +178,15 @@ void OAuth2TokenServiceRequest::Core::InformOwnerOnGetTokenFailure( ...@@ -173,14 +178,15 @@ void OAuth2TokenServiceRequest::Core::InformOwnerOnGetTokenFailure(
} }
// static // static
OAuth2TokenServiceRequest* OAuth2TokenServiceRequest::CreateAndStart( ProfileOAuth2TokenServiceRequest*
Profile* profile, ProfileOAuth2TokenServiceRequest::CreateAndStart(
const OAuth2TokenService::ScopeSet& scopes, Profile* profile,
OAuth2TokenService::Consumer* consumer) { const OAuth2TokenService::ScopeSet& scopes,
return new OAuth2TokenServiceRequest(profile, scopes, consumer); OAuth2TokenService::Consumer* consumer) {
return new ProfileOAuth2TokenServiceRequest(profile, scopes, consumer);
} }
OAuth2TokenServiceRequest::OAuth2TokenServiceRequest( ProfileOAuth2TokenServiceRequest::ProfileOAuth2TokenServiceRequest(
Profile* profile, Profile* profile,
const OAuth2TokenService::ScopeSet& scopes, const OAuth2TokenService::ScopeSet& scopes,
OAuth2TokenService::Consumer* consumer) OAuth2TokenService::Consumer* consumer)
...@@ -189,7 +195,7 @@ OAuth2TokenServiceRequest::OAuth2TokenServiceRequest( ...@@ -189,7 +195,7 @@ OAuth2TokenServiceRequest::OAuth2TokenServiceRequest(
core_->Start(scopes); core_->Start(scopes);
} }
OAuth2TokenServiceRequest::~OAuth2TokenServiceRequest() { ProfileOAuth2TokenServiceRequest::~ProfileOAuth2TokenServiceRequest() {
DCHECK(CalledOnValidThread()); DCHECK(CalledOnValidThread());
core_->Stop(); core_->Stop();
} }
...@@ -2,50 +2,46 @@ ...@@ -2,50 +2,46 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#ifndef CHROME_BROWSER_SIGNIN_OAUTH2_TOKEN_SERVICE_REQUEST_H_ #ifndef CHROME_BROWSER_SIGNIN_PROFILE_OAUTH2_TOKEN_SERVICE_REQUEST_H_
#define CHROME_BROWSER_SIGNIN_OAUTH2_TOKEN_SERVICE_REQUEST_H_ #define CHROME_BROWSER_SIGNIN_PROFILE_OAUTH2_TOKEN_SERVICE_REQUEST_H_
#include <set> #include <set>
#include <string> #include <string>
#include "base/memory/ref_counted.h"
#include "base/threading/non_thread_safe.h" #include "base/threading/non_thread_safe.h"
#include "base/time.h"
#include "chrome/browser/signin/oauth2_token_service.h" #include "chrome/browser/signin/oauth2_token_service.h"
#include "google_apis/gaia/google_service_auth_error.h"
class Profile; class Profile;
// OAuth2TokenServiceRequest represents a request to fetch an OAuth2 access // ProfileOAuth2TokenServiceRequest represents a request to fetch an
// token for a given set of |scopes| by calling |profile|'s // OAuth2 access token for a given set of |scopes| by calling |profile|'s
// OAuth2TokenService. A request can be created and started from any thread // ProfileOAuth2TokenService. A request can be created and started from
// with an object |consumer| that will be called back on the same thread when // any thread with an object |consumer| that will be called back on the
// fetching completes. // same thread when fetching completes. If the request is destructed
// If the request is destructed before |consumer| is called, |consumer| will // before |consumer| is called, |consumer| will never be called back. (Note
// never be called back. (Note the actual network activities are not canceled // the actual network activities are not canceled and the cache in
// and the cache in OAuth2TokenService will be populated with the fetched // ProfileOAuth2TokenService will be populated with the fetched results.)
// results.) class ProfileOAuth2TokenServiceRequest : public OAuth2TokenService::Request,
class OAuth2TokenServiceRequest : public OAuth2TokenService::Request, public base::NonThreadSafe {
public base::NonThreadSafe {
public: public:
static OAuth2TokenServiceRequest* CreateAndStart( static ProfileOAuth2TokenServiceRequest* CreateAndStart(
Profile* profile, Profile* profile,
const OAuth2TokenService::ScopeSet& scopes, const OAuth2TokenService::ScopeSet& scopes,
OAuth2TokenService::Consumer* consumer); OAuth2TokenService::Consumer* consumer);
virtual ~OAuth2TokenServiceRequest(); virtual ~ProfileOAuth2TokenServiceRequest();
private: private:
class Core; class Core;
friend class Core; friend class Core;
OAuth2TokenServiceRequest(Profile* profile, ProfileOAuth2TokenServiceRequest(Profile* profile,
const OAuth2TokenService::ScopeSet& scopes, const OAuth2TokenService::ScopeSet& scopes,
OAuth2TokenService::Consumer* consumer); OAuth2TokenService::Consumer* consumer);
OAuth2TokenService::Consumer* const consumer_; OAuth2TokenService::Consumer* const consumer_;
scoped_refptr<Core> core_; scoped_refptr<Core> core_;
DISALLOW_COPY_AND_ASSIGN(OAuth2TokenServiceRequest); DISALLOW_COPY_AND_ASSIGN(ProfileOAuth2TokenServiceRequest);
}; };
#endif // CHROME_BROWSER_SIGNIN_OAUTH2_TOKEN_SERVICE_REQUEST_H_ #endif // CHROME_BROWSER_SIGNIN_PROFILE_OAUTH2_TOKEN_SERVICE_REQUEST_H_
// Copyright 2012 The Chromium Authors. All rights reserved. // Copyright 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "chrome/browser/signin/oauth2_token_service_request.h" #include "chrome/browser/signin/profile_oauth2_token_service_request.h"
#include <set> #include <set>
#include <string> #include <string>
#include <vector> #include <vector>
#include "base/threading/thread.h" #include "base/threading/thread.h"
#include "chrome/browser/signin/oauth2_token_service.h" #include "chrome/browser/signin/oauth2_token_service.h"
#include "chrome/browser/signin/oauth2_token_service_factory.h" #include "chrome/browser/signin/profile_oauth2_token_service.h"
#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
#include "chrome/browser/signin/token_service_factory.h" #include "chrome/browser/signin/token_service_factory.h"
#include "chrome/test/base/testing_profile.h" #include "chrome/test/base/testing_profile.h"
#include "content/public/test/test_browser_thread.h" #include "content/public/test/test_browser_thread.h"
...@@ -29,13 +30,13 @@ class TestingOAuth2TokenServiceConsumer : public OAuth2TokenService::Consumer { ...@@ -29,13 +30,13 @@ class TestingOAuth2TokenServiceConsumer : public OAuth2TokenService::Consumer {
const GoogleServiceAuthError& error) OVERRIDE; const GoogleServiceAuthError& error) OVERRIDE;
std::string last_token_; std::string last_token_;
int number_of_correct_tokens_; int number_of_successful_tokens_;
GoogleServiceAuthError last_error_; GoogleServiceAuthError last_error_;
int number_of_errors_; int number_of_errors_;
}; };
TestingOAuth2TokenServiceConsumer::TestingOAuth2TokenServiceConsumer() TestingOAuth2TokenServiceConsumer::TestingOAuth2TokenServiceConsumer()
: number_of_correct_tokens_(0), : number_of_successful_tokens_(0),
last_error_(GoogleServiceAuthError::AuthErrorNone()), last_error_(GoogleServiceAuthError::AuthErrorNone()),
number_of_errors_(0) { number_of_errors_(0) {
} }
...@@ -48,7 +49,7 @@ void TestingOAuth2TokenServiceConsumer::OnGetTokenSuccess( ...@@ -48,7 +49,7 @@ void TestingOAuth2TokenServiceConsumer::OnGetTokenSuccess(
const std::string& token, const std::string& token,
const base::Time& expiration_date) { const base::Time& expiration_date) {
last_token_ = token; last_token_ = token;
++number_of_correct_tokens_; ++number_of_successful_tokens_;
} }
void TestingOAuth2TokenServiceConsumer::OnGetTokenFailure( void TestingOAuth2TokenServiceConsumer::OnGetTokenFailure(
...@@ -58,7 +59,7 @@ void TestingOAuth2TokenServiceConsumer::OnGetTokenFailure( ...@@ -58,7 +59,7 @@ void TestingOAuth2TokenServiceConsumer::OnGetTokenFailure(
++number_of_errors_; ++number_of_errors_;
} }
class MockOAuth2TokenService : public OAuth2TokenService { class MockProfileOAuth2TokenService : public ProfileOAuth2TokenService {
public: public:
class Request : public OAuth2TokenService::Request, class Request : public OAuth2TokenService::Request,
public base::SupportsWeakPtr<Request> { public base::SupportsWeakPtr<Request> {
...@@ -77,8 +78,8 @@ class MockOAuth2TokenService : public OAuth2TokenService { ...@@ -77,8 +78,8 @@ class MockOAuth2TokenService : public OAuth2TokenService {
base::Time expiration_date_; base::Time expiration_date_;
}; };
MockOAuth2TokenService(); MockProfileOAuth2TokenService();
virtual ~MockOAuth2TokenService(); virtual ~MockProfileOAuth2TokenService();
virtual scoped_ptr<OAuth2TokenService::Request> StartRequest( virtual scoped_ptr<OAuth2TokenService::Request> StartRequest(
const std::set<std::string>& scopes, const std::set<std::string>& scopes,
...@@ -88,13 +89,13 @@ class MockOAuth2TokenService : public OAuth2TokenService { ...@@ -88,13 +89,13 @@ class MockOAuth2TokenService : public OAuth2TokenService {
private: private:
static void InformConsumer( static void InformConsumer(
base::WeakPtr<MockOAuth2TokenService::Request> request); base::WeakPtr<MockProfileOAuth2TokenService::Request> request);
bool success_; bool success_;
std::string oauth2_access_token_; std::string oauth2_access_token_;
}; };
MockOAuth2TokenService::Request::Request( MockProfileOAuth2TokenService::Request::Request(
OAuth2TokenService::Consumer* consumer, OAuth2TokenService::Consumer* consumer,
GoogleServiceAuthError error, GoogleServiceAuthError error,
std::string access_token) std::string access_token)
...@@ -103,62 +104,64 @@ MockOAuth2TokenService::Request::Request( ...@@ -103,62 +104,64 @@ MockOAuth2TokenService::Request::Request(
access_token_(access_token) { access_token_(access_token) {
} }
MockOAuth2TokenService::Request::~Request() { MockProfileOAuth2TokenService::Request::~Request() {
} }
void MockOAuth2TokenService::Request::InformConsumer() const { void MockProfileOAuth2TokenService::Request::InformConsumer() const {
if (error_.state() == GoogleServiceAuthError::NONE) if (error_.state() == GoogleServiceAuthError::NONE)
consumer_->OnGetTokenSuccess(this, access_token_, expiration_date_); consumer_->OnGetTokenSuccess(this, access_token_, expiration_date_);
else else
consumer_->OnGetTokenFailure(this, error_); consumer_->OnGetTokenFailure(this, error_);
} }
MockOAuth2TokenService::MockOAuth2TokenService() MockProfileOAuth2TokenService::MockProfileOAuth2TokenService()
: success_(true), : ProfileOAuth2TokenService(NULL /* URLRequestContextGetter */),
success_(true),
oauth2_access_token_(std::string("success token")) { oauth2_access_token_(std::string("success token")) {
} }
MockOAuth2TokenService::~MockOAuth2TokenService() { MockProfileOAuth2TokenService::~MockProfileOAuth2TokenService() {
} }
void MockOAuth2TokenService::SetExpectation(bool success, void MockProfileOAuth2TokenService::SetExpectation(bool success,
std::string oauth2_access_token) { std::string oauth2_access_token) {
success_ = success; success_ = success;
oauth2_access_token_ = oauth2_access_token; oauth2_access_token_ = oauth2_access_token;
} }
// static // static
void MockOAuth2TokenService::InformConsumer( void MockProfileOAuth2TokenService::InformConsumer(
base::WeakPtr<MockOAuth2TokenService::Request> request) { base::WeakPtr<MockProfileOAuth2TokenService::Request> request) {
if (request) if (request)
request->InformConsumer(); request->InformConsumer();
} }
scoped_ptr<OAuth2TokenService::Request> MockOAuth2TokenService::StartRequest( scoped_ptr<OAuth2TokenService::Request>
const std::set<std::string>& scopes, MockProfileOAuth2TokenService::StartRequest(
OAuth2TokenService::Consumer* consumer) { const std::set<std::string>& scopes,
OAuth2TokenService::Consumer* consumer) {
scoped_ptr<Request> request; scoped_ptr<Request> request;
if (success_) { if (success_) {
request.reset(new MockOAuth2TokenService::Request( request.reset(new MockProfileOAuth2TokenService::Request(
consumer, consumer,
GoogleServiceAuthError(GoogleServiceAuthError::NONE), GoogleServiceAuthError(GoogleServiceAuthError::NONE),
oauth2_access_token_)); oauth2_access_token_));
} else { } else {
request.reset(new MockOAuth2TokenService::Request( request.reset(new MockProfileOAuth2TokenService::Request(
consumer, consumer,
GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE), GoogleServiceAuthError(GoogleServiceAuthError::SERVICE_UNAVAILABLE),
std::string())); std::string()));
} }
MessageLoop::current()->PostTask(FROM_HERE, base::Bind( MessageLoop::current()->PostTask(FROM_HERE, base::Bind(
&MockOAuth2TokenService::InformConsumer, request->AsWeakPtr())); &MockProfileOAuth2TokenService::InformConsumer, request->AsWeakPtr()));
return request.PassAs<OAuth2TokenService::Request>(); return request.PassAs<OAuth2TokenService::Request>();
} }
static ProfileKeyedService* CreateOAuth2TokenService(Profile* profile) { static ProfileKeyedService* CreateOAuth2TokenService(Profile* profile) {
return new MockOAuth2TokenService(); return new MockProfileOAuth2TokenService();
} }
class OAuth2TokenServiceRequestTest : public testing::Test { class ProfileOAuth2TokenServiceRequestTest : public testing::Test {
public: public:
virtual void SetUp() OVERRIDE; virtual void SetUp() OVERRIDE;
...@@ -168,70 +171,70 @@ class OAuth2TokenServiceRequestTest : public testing::Test { ...@@ -168,70 +171,70 @@ class OAuth2TokenServiceRequestTest : public testing::Test {
scoped_ptr<Profile> profile_; scoped_ptr<Profile> profile_;
TestingOAuth2TokenServiceConsumer consumer_; TestingOAuth2TokenServiceConsumer consumer_;
MockOAuth2TokenService* oauth2_service_; MockProfileOAuth2TokenService* oauth2_service_;
scoped_ptr<OAuth2TokenServiceRequest> request_; scoped_ptr<ProfileOAuth2TokenServiceRequest> request_;
}; };
void OAuth2TokenServiceRequestTest::SetUp() { void ProfileOAuth2TokenServiceRequestTest::SetUp() {
ui_thread_.reset(new content::TestBrowserThread(content::BrowserThread::UI, ui_thread_.reset(new content::TestBrowserThread(content::BrowserThread::UI,
&ui_loop_)); &ui_loop_));
profile_.reset(new TestingProfile()); profile_.reset(new TestingProfile());
OAuth2TokenServiceFactory::GetInstance()->SetTestingFactory( ProfileOAuth2TokenServiceFactory::GetInstance()->SetTestingFactory(
profile_.get(), &CreateOAuth2TokenService); profile_.get(), &CreateOAuth2TokenService);
oauth2_service_ = (MockOAuth2TokenService*) oauth2_service_ = (MockProfileOAuth2TokenService*)
OAuth2TokenServiceFactory::GetForProfile(profile_.get()); ProfileOAuth2TokenServiceFactory::GetForProfile(profile_.get());
} }
TEST_F(OAuth2TokenServiceRequestTest, TEST_F(ProfileOAuth2TokenServiceRequestTest,
Failure) { Failure) {
oauth2_service_->SetExpectation(false, std::string()); oauth2_service_->SetExpectation(false, std::string());
scoped_ptr<OAuth2TokenServiceRequest> request( scoped_ptr<ProfileOAuth2TokenServiceRequest> request(
OAuth2TokenServiceRequest::CreateAndStart( ProfileOAuth2TokenServiceRequest::CreateAndStart(
profile_.get(), profile_.get(),
std::set<std::string>(), std::set<std::string>(),
&consumer_)); &consumer_));
ui_loop_.RunUntilIdle(); ui_loop_.RunUntilIdle();
EXPECT_EQ(0, consumer_.number_of_correct_tokens_); EXPECT_EQ(0, consumer_.number_of_successful_tokens_);
EXPECT_EQ(1, consumer_.number_of_errors_); EXPECT_EQ(1, consumer_.number_of_errors_);
} }
TEST_F(OAuth2TokenServiceRequestTest, TEST_F(ProfileOAuth2TokenServiceRequestTest,
Success) { Success) {
scoped_ptr<OAuth2TokenServiceRequest> request( scoped_ptr<ProfileOAuth2TokenServiceRequest> request(
OAuth2TokenServiceRequest::CreateAndStart( ProfileOAuth2TokenServiceRequest::CreateAndStart(
profile_.get(), profile_.get(),
std::set<std::string>(), std::set<std::string>(),
&consumer_)); &consumer_));
ui_loop_.RunUntilIdle(); ui_loop_.RunUntilIdle();
EXPECT_EQ(1, consumer_.number_of_correct_tokens_); EXPECT_EQ(1, consumer_.number_of_successful_tokens_);
EXPECT_EQ("success token", consumer_.last_token_); EXPECT_EQ("success token", consumer_.last_token_);
EXPECT_EQ(0, consumer_.number_of_errors_); EXPECT_EQ(0, consumer_.number_of_errors_);
} }
TEST_F(OAuth2TokenServiceRequestTest, TEST_F(ProfileOAuth2TokenServiceRequestTest,
RequestDeletionBeforeServiceComplete) { RequestDeletionBeforeServiceComplete) {
scoped_ptr<OAuth2TokenServiceRequest> request( scoped_ptr<ProfileOAuth2TokenServiceRequest> request(
OAuth2TokenServiceRequest::CreateAndStart( ProfileOAuth2TokenServiceRequest::CreateAndStart(
profile_.get(), profile_.get(),
std::set<std::string>(), std::set<std::string>(),
&consumer_)); &consumer_));
request.reset(); request.reset();
ui_loop_.RunUntilIdle(); ui_loop_.RunUntilIdle();
EXPECT_EQ(0, consumer_.number_of_correct_tokens_); EXPECT_EQ(0, consumer_.number_of_successful_tokens_);
EXPECT_EQ(0, consumer_.number_of_errors_); EXPECT_EQ(0, consumer_.number_of_errors_);
} }
TEST_F(OAuth2TokenServiceRequestTest, TEST_F(ProfileOAuth2TokenServiceRequestTest,
RequestDeletionAfterServiceComplete) { RequestDeletionAfterServiceComplete) {
scoped_ptr<OAuth2TokenServiceRequest> request( scoped_ptr<ProfileOAuth2TokenServiceRequest> request(
OAuth2TokenServiceRequest::CreateAndStart( ProfileOAuth2TokenServiceRequest::CreateAndStart(
profile_.get(), profile_.get(),
std::set<std::string>(), std::set<std::string>(),
&consumer_)); &consumer_));
ui_loop_.RunUntilIdle(); ui_loop_.RunUntilIdle();
request.reset(); request.reset();
EXPECT_EQ(1, consumer_.number_of_correct_tokens_); EXPECT_EQ(1, consumer_.number_of_successful_tokens_);
EXPECT_EQ(0, consumer_.number_of_errors_); EXPECT_EQ(0, consumer_.number_of_errors_);
} }
......
// Copyright 2013 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/signin/oauth2_token_service.h"
#include "chrome/browser/signin/oauth2_token_service_test_util.h"
#include "chrome/browser/signin/profile_oauth2_token_service.h"
#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
#include "chrome/browser/signin/token_service_unittest.h"
#include "content/public/browser/browser_thread.h"
#include "google_apis/gaia/gaia_constants.h"
#include "net/http/http_status_code.h"
#include "net/url_request/test_url_fetcher_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
using content::BrowserThread;
class ProfileOAuth2TokenServiceTest : public TokenServiceTestHarness {
public:
ProfileOAuth2TokenServiceTest() {}
virtual void SetUp() OVERRIDE {
TokenServiceTestHarness::SetUp();
io_thread_.reset(new content::TestBrowserThread(content::BrowserThread::IO,
&message_loop_));
service_->UpdateCredentials(credentials_);
profile_->CreateRequestContext();
oauth2_service_ = ProfileOAuth2TokenServiceFactory::GetForProfile(
profile_.get());
}
virtual void TearDown() OVERRIDE {
TokenServiceTestHarness::TearDown();
}
protected:
scoped_ptr<content::TestBrowserThread> io_thread_;
net::TestURLFetcherFactory factory_;
ProfileOAuth2TokenService* oauth2_service_;
TestingOAuth2TokenServiceConsumer consumer_;
};
TEST_F(ProfileOAuth2TokenServiceTest, TokenServiceUpdateClearsCache) {
EXPECT_EQ(0, oauth2_service_->cache_size_for_testing());
std::set<std::string> scope_list;
scope_list.insert("scope");
service_->IssueAuthTokenForTest(GaiaConstants::kGaiaOAuth2LoginRefreshToken,
"refreshToken");
scoped_ptr<OAuth2TokenService::Request> request(oauth2_service_->StartRequest(
scope_list, &consumer_));
message_loop_.RunUntilIdle();
net::TestURLFetcher* fetcher = factory_.GetFetcherByID(0);
fetcher->set_response_code(net::HTTP_OK);
fetcher->SetResponseString(GetValidTokenResponse("token", 3600));
fetcher->delegate()->OnURLFetchComplete(fetcher);
EXPECT_EQ(1, consumer_.number_of_successful_tokens_);
EXPECT_EQ(0, consumer_.number_of_errors_);
EXPECT_EQ("token", consumer_.last_token_);
EXPECT_EQ(1, oauth2_service_->cache_size_for_testing());
// Signs out and signs in
service_->IssueAuthTokenForTest(GaiaConstants::kGaiaOAuth2LoginRefreshToken,
"");
service_->EraseTokensFromDB();
EXPECT_EQ(0, oauth2_service_->cache_size_for_testing());
service_->IssueAuthTokenForTest(GaiaConstants::kGaiaOAuth2LoginRefreshToken,
"refreshToken");
request = oauth2_service_->StartRequest(scope_list, &consumer_);
message_loop_.RunUntilIdle();
fetcher = factory_.GetFetcherByID(0);
fetcher->set_response_code(net::HTTP_OK);
fetcher->SetResponseString(GetValidTokenResponse("another token", 3600));
fetcher->delegate()->OnURLFetchComplete(fetcher);
EXPECT_EQ(2, consumer_.number_of_successful_tokens_);
EXPECT_EQ(0, consumer_.number_of_errors_);
EXPECT_EQ("another token", consumer_.last_token_);
EXPECT_EQ(1, oauth2_service_->cache_size_for_testing());
}
// Android doesn't use the current profile's TokenService login refresh token.
#if !defined(OS_ANDROID)
TEST_F(ProfileOAuth2TokenServiceTest, StaleRefreshTokensNotCached) {
EXPECT_FALSE(service_->HasOAuthLoginToken());
EXPECT_FALSE(oauth2_service_->ShouldCacheForRefreshToken(service_, "T1"));
service_->IssueAuthTokenForTest(GaiaConstants::kGaiaOAuth2LoginRefreshToken,
"T1");
EXPECT_TRUE(oauth2_service_->ShouldCacheForRefreshToken(service_, "T1"));
EXPECT_FALSE(oauth2_service_->ShouldCacheForRefreshToken(service_, "T2"));
service_->IssueAuthTokenForTest(GaiaConstants::kGaiaOAuth2LoginRefreshToken,
"T2");
EXPECT_TRUE(oauth2_service_->ShouldCacheForRefreshToken(service_, "T2"));
EXPECT_FALSE(oauth2_service_->ShouldCacheForRefreshToken(NULL, "T2"));
}
#endif
...@@ -231,7 +231,8 @@ TEST_F(TokenServiceTest, OnTokenSuccessUpdate) { ...@@ -231,7 +231,8 @@ TEST_F(TokenServiceTest, OnTokenSuccessUpdate) {
} }
TEST_F(TokenServiceTest, OnOAuth2LoginTokenSuccessUpdate) { TEST_F(TokenServiceTest, OnOAuth2LoginTokenSuccessUpdate) {
std::string service = GaiaConstants::kGaiaOAuth2LoginRefreshToken; EXPECT_FALSE(service_->HasOAuthLoginToken());
service_->OnClientOAuthSuccess( service_->OnClientOAuthSuccess(
GaiaAuthConsumer::ClientOAuthResult("rt1", "at1", 3600)); GaiaAuthConsumer::ClientOAuthResult("rt1", "at1", 3600));
EXPECT_TRUE(service_->HasOAuthLoginToken()); EXPECT_TRUE(service_->HasOAuthLoginToken());
......
...@@ -1716,10 +1716,12 @@ ...@@ -1716,10 +1716,12 @@
'browser/signin/about_signin_internals_factory.h', 'browser/signin/about_signin_internals_factory.h',
'browser/signin/oauth2_token_service.cc', 'browser/signin/oauth2_token_service.cc',
'browser/signin/oauth2_token_service.h', 'browser/signin/oauth2_token_service.h',
'browser/signin/oauth2_token_service_factory.cc', 'browser/signin/profile_oauth2_token_service.cc',
'browser/signin/oauth2_token_service_factory.h', 'browser/signin/profile_oauth2_token_service.h',
'browser/signin/oauth2_token_service_request.cc', 'browser/signin/profile_oauth2_token_service_factory.cc',
'browser/signin/oauth2_token_service_request.h', 'browser/signin/profile_oauth2_token_service_factory.h',
'browser/signin/profile_oauth2_token_service_request.cc',
'browser/signin/profile_oauth2_token_service_request.h',
'browser/signin/signin_global_error.cc', 'browser/signin/signin_global_error.cc',
'browser/signin/signin_global_error.h', 'browser/signin/signin_global_error.h',
'browser/signin/signin_internals_util.cc', 'browser/signin/signin_internals_util.cc',
...@@ -2628,6 +2630,8 @@ ...@@ -2628,6 +2630,8 @@
'sources': [ 'sources': [
'browser/sessions/in_memory_tab_restore_service.cc', 'browser/sessions/in_memory_tab_restore_service.cc',
'browser/sessions/in_memory_tab_restore_service.h', 'browser/sessions/in_memory_tab_restore_service.h',
'browser/signin/android_profile_oauth2_token_service.cc',
'browser/signin/android_profile_oauth2_token_service.h',
'browser/ssl/ssl_add_certificate_android.cc', 'browser/ssl/ssl_add_certificate_android.cc',
'browser/web_resource/notification_promo_mobile_ntp.cc', 'browser/web_resource/notification_promo_mobile_ntp.cc',
'browser/web_resource/notification_promo_mobile_ntp.h', 'browser/web_resource/notification_promo_mobile_ntp.h',
......
...@@ -642,6 +642,10 @@ ...@@ -642,6 +642,10 @@
'browser/chromeos/settings/cros_settings_names.h', 'browser/chromeos/settings/cros_settings_names.h',
'browser/chromeos/settings/cros_settings_provider.cc', 'browser/chromeos/settings/cros_settings_provider.cc',
'browser/chromeos/settings/cros_settings_provider.h', 'browser/chromeos/settings/cros_settings_provider.h',
'browser/chromeos/settings/device_oauth2_token_service.cc',
'browser/chromeos/settings/device_oauth2_token_service.h',
'browser/chromeos/settings/device_oauth2_token_service_factory.cc',
'browser/chromeos/settings/device_oauth2_token_service_factory.h',
'browser/chromeos/settings/device_settings_cache.cc', 'browser/chromeos/settings/device_settings_cache.cc',
'browser/chromeos/settings/device_settings_cache.h', 'browser/chromeos/settings/device_settings_cache.h',
'browser/chromeos/settings/device_settings_provider.cc', 'browser/chromeos/settings/device_settings_provider.cc',
......
...@@ -633,6 +633,7 @@ ...@@ -633,6 +633,7 @@
'browser/chromeos/session_length_limiter_unittest.cc', 'browser/chromeos/session_length_limiter_unittest.cc',
'browser/chromeos/proxy_config_service_impl_unittest.cc', 'browser/chromeos/proxy_config_service_impl_unittest.cc',
'browser/chromeos/settings/cros_settings_unittest.cc', 'browser/chromeos/settings/cros_settings_unittest.cc',
'browser/chromeos/settings/device_oauth2_token_service_unittest.cc',
'browser/chromeos/settings/device_settings_provider_unittest.cc', 'browser/chromeos/settings/device_settings_provider_unittest.cc',
'browser/chromeos/settings/device_settings_service_unittest.cc', 'browser/chromeos/settings/device_settings_service_unittest.cc',
'browser/chromeos/settings/owner_key_util_unittest.cc', 'browser/chromeos/settings/owner_key_util_unittest.cc',
...@@ -1058,8 +1059,11 @@ ...@@ -1058,8 +1059,11 @@
'browser/shell_integration_win_unittest.cc', 'browser/shell_integration_win_unittest.cc',
'browser/signin/fake_auth_status_provider.cc', 'browser/signin/fake_auth_status_provider.cc',
'browser/signin/fake_auth_status_provider.h', 'browser/signin/fake_auth_status_provider.h',
'browser/signin/oauth2_token_service_request_unittest.cc', 'browser/signin/oauth2_token_service_test_util.cc',
'browser/signin/oauth2_token_service_test_util.h',
'browser/signin/oauth2_token_service_unittest.cc', 'browser/signin/oauth2_token_service_unittest.cc',
'browser/signin/profile_oauth2_token_service_request_unittest.cc',
'browser/signin/profile_oauth2_token_service_unittest.cc',
'browser/signin/signin_global_error_unittest.cc', 'browser/signin/signin_global_error_unittest.cc',
'browser/signin/signin_manager_unittest.cc', 'browser/signin/signin_manager_unittest.cc',
'browser/signin/signin_names_io_thread_unittest.cc', 'browser/signin/signin_names_io_thread_unittest.cc',
...@@ -2181,7 +2185,7 @@ ...@@ -2181,7 +2185,7 @@
'browser/page_cycler/page_cycler_unittest.cc', 'browser/page_cycler/page_cycler_unittest.cc',
'browser/profiles/off_the_record_profile_impl_unittest.cc', 'browser/profiles/off_the_record_profile_impl_unittest.cc',
'browser/search/search_unittest.cc', 'browser/search/search_unittest.cc',
'browser/signin/oauth2_token_service_unittest.cc', 'browser/signin/profile_oauth2_token_service_unittest.cc',
'browser/sync/profile_sync_service_session_unittest.cc', 'browser/sync/profile_sync_service_session_unittest.cc',
'browser/sync/sync_global_error_unittest.cc', 'browser/sync/sync_global_error_unittest.cc',
'browser/tab_contents/render_view_context_menu_unittest.cc', 'browser/tab_contents/render_view_context_menu_unittest.cc',
......
...@@ -2046,6 +2046,13 @@ const char kUptimeLimit[] = "automatic_reboot.uptime_limit"; ...@@ -2046,6 +2046,13 @@ const char kUptimeLimit[] = "automatic_reboot.uptime_limit";
// Whether an automatic reboot should be scheduled when an update has been // Whether an automatic reboot should be scheduled when an update has been
// applied and a reboot is required to complete the update process. // applied and a reboot is required to complete the update process.
const char kRebootAfterUpdate[] = "automatic_reboot.reboot_after_update"; const char kRebootAfterUpdate[] = "automatic_reboot.reboot_after_update";
// An any-api scoped refresh token for enterprise-enrolled devices. Allows
// for connection to Google APIs when the user isn't logged in. Currently used
// for for getting a cloudprint scoped token to allow printing in Guest mode,
// Public Accounts and kiosks.
const char kDeviceRobotAnyApiRefreshToken[] =
"device_robot_refresh_token.any-api";
#endif #endif
// Whether there is a Flash version installed that supports clearing LSO data. // Whether there is a Flash version installed that supports clearing LSO data.
......
...@@ -750,6 +750,7 @@ extern const char kOwnerPrimaryMouseButtonRight[]; ...@@ -750,6 +750,7 @@ extern const char kOwnerPrimaryMouseButtonRight[];
extern const char kOwnerTapToClickEnabled[]; extern const char kOwnerTapToClickEnabled[];
extern const char kUptimeLimit[]; extern const char kUptimeLimit[];
extern const char kRebootAfterUpdate[]; extern const char kRebootAfterUpdate[];
extern const char kDeviceRobotAnyApiRefreshToken[];
#endif #endif
extern const char kClearPluginLSODataEnabled[]; extern const char kClearPluginLSODataEnabled[];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment