• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "chrome/browser/policy/user_policy_identity_strategy.h"
6 
7 #include "base/file_util.h"
8 #include "chrome/browser/browser_signin.h"
9 #include "chrome/browser/net/gaia/token_service.h"
10 #include "chrome/browser/policy/proto/device_management_backend.pb.h"
11 #include "chrome/browser/policy/proto/device_management_constants.h"
12 #include "chrome/browser/policy/proto/device_management_local.pb.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/common/guid.h"
15 #include "chrome/common/net/gaia/gaia_constants.h"
16 #include "content/browser/browser_thread.h"
17 #include "content/common/notification_details.h"
18 #include "content/common/notification_service.h"
19 #include "content/common/notification_source.h"
20 
21 #if defined(OS_CHROMEOS)
22 #include "chrome/browser/chromeos/login/user_manager.h"
23 #endif
24 
25 namespace policy {
26 
27 namespace em = enterprise_management;
28 
29 // Responsible for managing the on-disk token cache.
30 class UserPolicyIdentityStrategy::TokenCache
31     : public base::RefCountedThreadSafe<
32           UserPolicyIdentityStrategy::TokenCache> {
33  public:
34   TokenCache(const base::WeakPtr<UserPolicyIdentityStrategy>& identity_strategy,
35              const FilePath& cache_file);
36 
37   void Load();
38   void Store(const std::string& token, const std::string& device_id);
39 
40  private:
41   friend class base::RefCountedThreadSafe<
42       UserPolicyIdentityStrategy::TokenCache>;
~TokenCache()43   ~TokenCache() {}
44   void LoadOnFileThread();
45   void NotifyOnUIThread(const std::string& token,
46                         const std::string& device_id);
47   void StoreOnFileThread(const std::string& token,
48                          const std::string& device_id);
49 
50   const base::WeakPtr<UserPolicyIdentityStrategy> identity_strategy_;
51   const FilePath cache_file_;
52 
53   DISALLOW_COPY_AND_ASSIGN(TokenCache);
54 };
55 
TokenCache(const base::WeakPtr<UserPolicyIdentityStrategy> & identity_strategy,const FilePath & cache_file)56 UserPolicyIdentityStrategy::TokenCache::TokenCache(
57     const base::WeakPtr<UserPolicyIdentityStrategy>& identity_strategy,
58     const FilePath& cache_file)
59     : identity_strategy_(identity_strategy),
60       cache_file_(cache_file) {}
61 
Load()62 void UserPolicyIdentityStrategy::TokenCache::Load() {
63   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
64   BrowserThread::PostTask(
65       BrowserThread::FILE, FROM_HERE,
66       NewRunnableMethod(
67           this, &UserPolicyIdentityStrategy::TokenCache::LoadOnFileThread));
68 }
69 
Store(const std::string & token,const std::string & device_id)70 void UserPolicyIdentityStrategy::TokenCache::Store(
71     const std::string& token,
72     const std::string& device_id) {
73   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
74   BrowserThread::PostTask(
75       BrowserThread::FILE, FROM_HERE,
76       NewRunnableMethod(
77           this,
78           &UserPolicyIdentityStrategy::TokenCache::StoreOnFileThread,
79           token,
80           device_id));
81 }
82 
LoadOnFileThread()83 void UserPolicyIdentityStrategy::TokenCache::LoadOnFileThread() {
84   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
85   std::string device_token;
86   std::string device_id;
87 
88   if (file_util::PathExists(cache_file_)) {
89     std::string data;
90     em::DeviceCredentials device_credentials;
91     if (file_util::ReadFileToString(cache_file_, &data) &&
92         device_credentials.ParseFromArray(data.c_str(), data.size())) {
93       device_token = device_credentials.device_token();
94       device_id = device_credentials.device_id();
95     }
96   }
97 
98   BrowserThread::PostTask(
99       BrowserThread::UI, FROM_HERE,
100       NewRunnableMethod(
101           this,
102           &UserPolicyIdentityStrategy::TokenCache::NotifyOnUIThread,
103           device_token,
104           device_id));
105 }
106 
NotifyOnUIThread(const std::string & token,const std::string & device_id)107 void UserPolicyIdentityStrategy::TokenCache::NotifyOnUIThread(
108     const std::string& token,
109     const std::string& device_id) {
110   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
111   if (identity_strategy_.get())
112     identity_strategy_->OnCacheLoaded(token, device_id);
113 }
114 
StoreOnFileThread(const std::string & token,const std::string & device_id)115 void UserPolicyIdentityStrategy::TokenCache::StoreOnFileThread(
116     const std::string& token,
117     const std::string& device_id) {
118   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
119   em::DeviceCredentials device_credentials;
120   device_credentials.set_device_token(token);
121   device_credentials.set_device_id(device_id);
122   std::string data;
123   bool success = device_credentials.SerializeToString(&data);
124   if (!success) {
125     LOG(WARNING) << "Failed serialize device token data, will not write "
126                  << cache_file_.value();
127     return;
128   }
129 
130   file_util::WriteFile(cache_file_, data.c_str(), data.length());
131 }
132 
UserPolicyIdentityStrategy(Profile * profile,const FilePath & cache_file)133 UserPolicyIdentityStrategy::UserPolicyIdentityStrategy(
134     Profile* profile,
135     const FilePath& cache_file)
136     : profile_(profile),
137       ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
138   cache_ = new TokenCache(weak_ptr_factory_.GetWeakPtr(), cache_file);
139   registrar_.Add(this,
140                  NotificationType::TOKEN_AVAILABLE,
141                  Source<TokenService>(profile->GetTokenService()));
142 
143   // Register for the event of user login. The device management token won't
144   // be fetched until we know the domain of the currently logged in user.
145 #if defined(OS_CHROMEOS)
146   registrar_.Add(this,
147                  NotificationType::LOGIN_USER_CHANGED,
148                  NotificationService::AllSources());
149 #else
150   registrar_.Add(this,
151                  NotificationType::GOOGLE_SIGNIN_SUCCESSFUL,
152                  Source<Profile>(profile_));
153 #endif
154 
155   cache_->Load();
156 }
157 
~UserPolicyIdentityStrategy()158 UserPolicyIdentityStrategy::~UserPolicyIdentityStrategy() {}
159 
GetDeviceToken()160 std::string UserPolicyIdentityStrategy::GetDeviceToken() {
161   return device_token_;
162 }
163 
GetDeviceID()164 std::string UserPolicyIdentityStrategy::GetDeviceID() {
165   return device_id_;
166 }
167 
GetMachineID()168 std::string UserPolicyIdentityStrategy::GetMachineID() {
169   return std::string();
170 }
171 
GetMachineModel()172 std::string UserPolicyIdentityStrategy::GetMachineModel() {
173   return std::string();
174 }
175 
176 em::DeviceRegisterRequest_Type
GetPolicyRegisterType()177 UserPolicyIdentityStrategy::GetPolicyRegisterType() {
178   return em::DeviceRegisterRequest::USER;
179 }
180 
GetPolicyType()181 std::string UserPolicyIdentityStrategy::GetPolicyType() {
182   return kChromeUserPolicyType;
183 }
184 
GetCredentials(std::string * username,std::string * auth_token)185 bool UserPolicyIdentityStrategy::GetCredentials(std::string* username,
186                                                 std::string* auth_token) {
187   *username = GetCurrentUser();
188   *auth_token = profile_->GetTokenService()->GetTokenForService(
189       GaiaConstants::kDeviceManagementService);
190 
191   return !username->empty() && !auth_token->empty() && !device_id_.empty();
192 }
193 
OnDeviceTokenAvailable(const std::string & token)194 void UserPolicyIdentityStrategy::OnDeviceTokenAvailable(
195     const std::string& token) {
196   DCHECK(!device_id_.empty());
197   device_token_ = token;
198   cache_->Store(device_token_, device_id_);
199   NotifyDeviceTokenChanged();
200 }
201 
GetCurrentUser()202 std::string UserPolicyIdentityStrategy::GetCurrentUser() {
203 #if defined(OS_CHROMEOS)
204   // TODO(mnissler) On CrOS it seems impossible to figure out what user belongs
205   // to a profile. Revisit after multi-profile support landed.
206   return chromeos::UserManager::Get()->logged_in_user().email();
207 #else
208   return profile_->GetBrowserSignin()->GetSignedInUsername();
209 #endif
210 }
211 
CheckAndTriggerFetch()212 void UserPolicyIdentityStrategy::CheckAndTriggerFetch() {
213   if (!GetCurrentUser().empty() &&
214       profile_->GetTokenService()->HasTokenForService(
215           GaiaConstants::kDeviceManagementService)) {
216     // For user tokens, there is no actual identifier. We generate a random
217     // identifier instead each time we ask for the token.
218     device_id_ = guid::GenerateGUID();
219     NotifyAuthChanged();
220   }
221 }
222 
OnCacheLoaded(const std::string & token,const std::string & device_id)223 void UserPolicyIdentityStrategy::OnCacheLoaded(const std::string& token,
224                                                const std::string& device_id) {
225   if (!token.empty() && !device_id.empty()) {
226     device_token_ = token;
227     device_id_ = device_id;
228     NotifyDeviceTokenChanged();
229   } else {
230     CheckAndTriggerFetch();
231   }
232 }
233 
Observe(NotificationType type,const NotificationSource & source,const NotificationDetails & details)234 void UserPolicyIdentityStrategy::Observe(NotificationType type,
235                                          const NotificationSource& source,
236                                          const NotificationDetails& details) {
237   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
238   if (type == NotificationType::TOKEN_AVAILABLE) {
239     if (Source<TokenService>(source).ptr() == profile_->GetTokenService()) {
240       const TokenService::TokenAvailableDetails* token_details =
241           Details<const TokenService::TokenAvailableDetails>(details).ptr();
242       if (token_details->service() == GaiaConstants::kDeviceManagementService)
243         if (device_token_.empty()) {
244           // Request a new device management server token, but only in case we
245           // don't already have it.
246           CheckAndTriggerFetch();
247         }
248     }
249 #if defined(OS_CHROMEOS)
250   } else if (type == NotificationType::LOGIN_USER_CHANGED) {
251     CheckAndTriggerFetch();
252 #else
253   } else if (type == NotificationType::GOOGLE_SIGNIN_SUCCESSFUL) {
254     if (profile_ == Source<Profile>(source).ptr())
255       CheckAndTriggerFetch();
256 #endif
257   } else {
258     NOTREACHED();
259   }
260 }
261 
262 }  // namespace policy
263