| Index: chrome/browser/policy/user_policy_identity_strategy.cc
|
| diff --git a/chrome/browser/policy/user_policy_identity_strategy.cc b/chrome/browser/policy/user_policy_identity_strategy.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..5270ca3d0ff3eec13b8bec9fef35e48efa5a75c0
|
| --- /dev/null
|
| +++ b/chrome/browser/policy/user_policy_identity_strategy.cc
|
| @@ -0,0 +1,236 @@
|
| +// Copyright (c) 2011 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/policy/user_policy_identity_strategy.h"
|
| +
|
| +#include "base/file_util.h"
|
| +#include "chrome/browser/browser_signin.h"
|
| +#include "chrome/browser/browser_thread.h"
|
| +#include "chrome/browser/chromeos/login/user_manager.h"
|
| +#include "chrome/browser/net/gaia/token_service.h"
|
| +#include "chrome/browser/policy/proto/device_management_local.pb.h"
|
| +#include "chrome/browser/profiles/profile.h"
|
| +#include "chrome/common/guid.h"
|
| +#include "chrome/common/net/gaia/gaia_constants.h"
|
| +#include "chrome/common/notification_details.h"
|
| +#include "chrome/common/notification_service.h"
|
| +#include "chrome/common/notification_source.h"
|
| +
|
| +namespace policy {
|
| +
|
| +namespace em = enterprise_management;
|
| +
|
| +// Responsible for managing the on-disk token cache.
|
| +class UserPolicyIdentityStrategy::TokenCache
|
| + : public base::RefCountedThreadSafe<
|
| + UserPolicyIdentityStrategy::TokenCache> {
|
| + public:
|
| + TokenCache(const base::WeakPtr<UserPolicyIdentityStrategy>& identity_strategy,
|
| + const FilePath& cache_file);
|
| +
|
| + void Load();
|
| + void Store(const std::string& token, const std::string& device_id);
|
| +
|
| + private:
|
| + friend class base::RefCountedThreadSafe<
|
| + UserPolicyIdentityStrategy::TokenCache>;
|
| + ~TokenCache() {}
|
| + void LoadOnFileThread();
|
| + void NotifyOnUIThread(const std::string& token,
|
| + const std::string& device_id);
|
| + void StoreOnFileThread(const std::string& token,
|
| + const std::string& device_id);
|
| +
|
| + const base::WeakPtr<UserPolicyIdentityStrategy> identity_strategy_;
|
| + const FilePath cache_file_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(TokenCache);
|
| +};
|
| +
|
| +UserPolicyIdentityStrategy::TokenCache::TokenCache(
|
| + const base::WeakPtr<UserPolicyIdentityStrategy>& identity_strategy,
|
| + const FilePath& cache_file)
|
| + : identity_strategy_(identity_strategy),
|
| + cache_file_(cache_file) {}
|
| +
|
| +void UserPolicyIdentityStrategy::TokenCache::Load() {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| + BrowserThread::PostTask(
|
| + BrowserThread::FILE, FROM_HERE,
|
| + NewRunnableMethod(
|
| + this, &UserPolicyIdentityStrategy::TokenCache::LoadOnFileThread));
|
| +}
|
| +
|
| +void UserPolicyIdentityStrategy::TokenCache::Store(
|
| + const std::string& token,
|
| + const std::string& device_id) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| + BrowserThread::PostTask(
|
| + BrowserThread::FILE, FROM_HERE,
|
| + NewRunnableMethod(
|
| + this,
|
| + &UserPolicyIdentityStrategy::TokenCache::StoreOnFileThread,
|
| + token,
|
| + device_id));
|
| +}
|
| +
|
| +void UserPolicyIdentityStrategy::TokenCache::LoadOnFileThread() {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
|
| + std::string device_token;
|
| + std::string device_id;
|
| +
|
| + if (file_util::PathExists(cache_file_)) {
|
| + std::string data;
|
| + em::DeviceCredentials device_credentials;
|
| + if (file_util::ReadFileToString(cache_file_, &data) &&
|
| + device_credentials.ParseFromArray(data.c_str(), data.size())) {
|
| + device_token = device_credentials.device_token();
|
| + device_id = device_credentials.device_id();
|
| + }
|
| + }
|
| +
|
| + BrowserThread::PostTask(
|
| + BrowserThread::UI, FROM_HERE,
|
| + NewRunnableMethod(
|
| + this,
|
| + &UserPolicyIdentityStrategy::TokenCache::NotifyOnUIThread,
|
| + device_token,
|
| + device_id));
|
| +}
|
| +
|
| +void UserPolicyIdentityStrategy::TokenCache::NotifyOnUIThread(
|
| + const std::string& token,
|
| + const std::string& device_id) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| + if (identity_strategy_.get())
|
| + identity_strategy_->OnCacheLoaded(token, device_id);
|
| +}
|
| +
|
| +void UserPolicyIdentityStrategy::TokenCache::StoreOnFileThread(
|
| + const std::string& token,
|
| + const std::string& device_id) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
|
| + em::DeviceCredentials device_credentials;
|
| + device_credentials.set_device_token(token);
|
| + device_credentials.set_device_id(device_id);
|
| + std::string data;
|
| + bool success = device_credentials.SerializeToString(&data);
|
| + if (!success) {
|
| + LOG(WARNING) << "Failed serialize device token data, will not write "
|
| + << cache_file_.value();
|
| + return;
|
| + }
|
| +
|
| + file_util::WriteFile(cache_file_, data.c_str(), data.length());
|
| +}
|
| +
|
| +UserPolicyIdentityStrategy::UserPolicyIdentityStrategy(
|
| + Profile* profile,
|
| + const FilePath& cache_file)
|
| + : profile_(profile),
|
| + ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
|
| + cache_ = new TokenCache(weak_ptr_factory_.GetWeakPtr(), cache_file);
|
| + registrar_.Add(this,
|
| + NotificationType::TOKEN_AVAILABLE,
|
| + Source<TokenService>(profile->GetTokenService()));
|
| +
|
| + // Register for the event of user login. The device management token won't
|
| + // be fetched until we know the domain of the currently logged in user.
|
| +#if defined(OS_CHROMEOS)
|
| + registrar_.Add(this,
|
| + NotificationType::LOGIN_USER_CHANGED,
|
| + NotificationService::AllSources());
|
| +#else
|
| + registrar_.Add(this,
|
| + NotificationType::GOOGLE_SIGNIN_SUCCESSFUL,
|
| + Source<Profile>(profile_));
|
| +#endif
|
| +
|
| + cache_->Load();
|
| +}
|
| +
|
| +UserPolicyIdentityStrategy::~UserPolicyIdentityStrategy() {}
|
| +
|
| +std::string UserPolicyIdentityStrategy::GetDeviceToken() {
|
| + return device_token_;
|
| +}
|
| +
|
| +std::string UserPolicyIdentityStrategy::GetDeviceID() {
|
| + return device_id_;
|
| +}
|
| +
|
| +bool UserPolicyIdentityStrategy::GetCredentials(std::string* username,
|
| + std::string* auth_token) {
|
| + *username = GetCurrentUser();
|
| + *auth_token = profile_->GetTokenService()->GetTokenForService(
|
| + GaiaConstants::kDeviceManagementService);
|
| +
|
| + return !username->empty() && !auth_token->empty() && !device_id_.empty();
|
| +}
|
| +
|
| +void UserPolicyIdentityStrategy::OnDeviceTokenAvailable(
|
| + const std::string& token) {
|
| + DCHECK(!device_id_.empty());
|
| + device_token_ = token;
|
| + cache_->Store(device_token_, device_id_);
|
| + NotifyDeviceTokenChanged();
|
| +}
|
| +
|
| +std::string UserPolicyIdentityStrategy::GetCurrentUser() {
|
| +#if defined(OS_CHROMEOS)
|
| + // TODO(mnissler) On CrOS it seems impossible to figure out what user belongs
|
| + // to a profile. Revisit after multi-profile support landed.
|
| + return chromeos::UserManager::Get()->logged_in_user().email();
|
| +#else
|
| + return profile_->GetBrowserSignin()->GetSignedInUsername();
|
| +#endif
|
| +}
|
| +
|
| +void UserPolicyIdentityStrategy::CheckAndTriggerFetch() {
|
| + if (!GetCurrentUser().empty() &&
|
| + profile_->GetTokenService()->HasTokenForService(
|
| + GaiaConstants::kDeviceManagementService)) {
|
| + // For user tokens, there is no actual identifier. We generate a random
|
| + // identifier instead each time we ask for the token.
|
| + device_id_ = guid::GenerateGUID();
|
| + NotifyAuthChanged();
|
| + }
|
| +}
|
| +
|
| +void UserPolicyIdentityStrategy::OnCacheLoaded(const std::string& token,
|
| + const std::string& device_id) {
|
| + if (!token.empty() && !device_id.empty()) {
|
| + device_token_ = token;
|
| + device_id_ = device_id;
|
| + NotifyDeviceTokenChanged();
|
| + } else {
|
| + CheckAndTriggerFetch();
|
| + }
|
| +}
|
| +
|
| +void UserPolicyIdentityStrategy::Observe(NotificationType type,
|
| + const NotificationSource& source,
|
| + const NotificationDetails& details) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| + if (type == NotificationType::TOKEN_AVAILABLE) {
|
| + if (Source<TokenService>(source).ptr() == profile_->GetTokenService()) {
|
| + const TokenService::TokenAvailableDetails* token_details =
|
| + Details<const TokenService::TokenAvailableDetails>(details).ptr();
|
| + if (token_details->service() == GaiaConstants::kDeviceManagementService)
|
| + CheckAndTriggerFetch();
|
| + }
|
| +#if defined(OS_CHROMEOS)
|
| + } else if (type == NotificationType::LOGIN_USER_CHANGED) {
|
| + CheckAndTriggerFetch();
|
| +#else
|
| + } else if (type == NotificationType::GOOGLE_SIGNIN_SUCCESSFUL) {
|
| + if (profile_ == Source<Profile>(source).ptr())
|
| + CheckAndTriggerFetch();
|
| +#endif
|
| + } else {
|
| + NOTREACHED();
|
| + }
|
| +}
|
| +
|
| +} // namespace policy
|
|
|