Index: chrome/browser/policy/user_policy_controller.cc |
diff --git a/chrome/browser/policy/user_policy_controller.cc b/chrome/browser/policy/user_policy_controller.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..273610deb7540684f3b84aa3634d2d7d6b2beb27 |
--- /dev/null |
+++ b/chrome/browser/policy/user_policy_controller.cc |
@@ -0,0 +1,230 @@ |
+// 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_controller.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 UserPolicyController::TokenCache |
+ : public base::RefCountedThreadSafe<UserPolicyController::TokenCache> { |
+ public: |
+ TokenCache(const base::WeakPtr<UserPolicyController>& provider, |
+ const FilePath& cache_file); |
+ |
+ void Load(); |
+ void Store(const std::string& token, const std::string& device_id); |
+ |
+ private: |
+ 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<UserPolicyController> provider_; |
+ const FilePath& cache_file_; |
+ |
+ DISALLOW_COPY_AND_ASSIGN(TokenCache); |
+}; |
+ |
+UserPolicyController::TokenCache::TokenCache( |
+ const base::WeakPtr<UserPolicyController>& provider, |
+ const FilePath& cache_file) |
+ : provider_(provider), |
+ cache_file_(cache_file) {} |
+ |
+void UserPolicyController::TokenCache::Load() { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ BrowserThread::PostTask( |
+ BrowserThread::FILE, FROM_HERE, |
+ NewRunnableMethod( |
+ this, &UserPolicyController::TokenCache::LoadOnFileThread)); |
+} |
+ |
+void UserPolicyController::TokenCache::Store(const std::string& token, |
+ const std::string& device_id) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ BrowserThread::PostTask( |
+ BrowserThread::FILE, FROM_HERE, |
+ NewRunnableMethod( |
+ this, |
+ &UserPolicyController::TokenCache::StoreOnFileThread, |
+ token, |
+ device_id)); |
+} |
+ |
+void UserPolicyController::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, |
+ &UserPolicyController::TokenCache::NotifyOnUIThread, |
+ device_token, |
+ device_id)); |
+} |
+ |
+void UserPolicyController::TokenCache::NotifyOnUIThread( |
+ const std::string& token, |
+ const std::string& device_id) { |
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
+ if (provider_.get()) |
+ provider_->OnCacheLoaded(token, device_id); |
+} |
+ |
+void UserPolicyController::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()); |
+} |
+ |
+UserPolicyController::UserPolicyController(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(); |
+} |
+ |
+UserPolicyController::~UserPolicyController() {} |
+ |
+std::string UserPolicyController::GetDeviceToken() { |
+ return device_token_; |
+} |
+ |
+std::string UserPolicyController::GetDeviceID() { |
+ return device_id_; |
+} |
+ |
+bool UserPolicyController::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 UserPolicyController::OnTokenAvailable(const std::string& token) { |
+ DCHECK(!device_id_.empty()); |
+ device_token_ = token; |
+ cache_->Store(device_token_, device_id_); |
+ NotifyTokenChanged(); |
+} |
+ |
+std::string UserPolicyController::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 UserPolicyController::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 UserPolicyController::OnCacheLoaded(const std::string& token, |
+ const std::string& device_id) { |
+ if (!token.empty() && !device_id.empty()) { |
+ device_token_ = token; |
+ device_id_ = device_id; |
+ NotifyTokenChanged(); |
+ } else { |
+ CheckAndTriggerFetch(); |
+ } |
+} |
+ |
+void UserPolicyController::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 |