OLD | NEW |
---|---|
(Empty) | |
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/browser_thread.h" | |
10 #include "chrome/browser/chromeos/login/user_manager.h" | |
11 #include "chrome/browser/net/gaia/token_service.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 "chrome/common/notification_details.h" | |
17 #include "chrome/common/notification_service.h" | |
18 #include "chrome/common/notification_source.h" | |
19 | |
20 namespace policy { | |
21 | |
22 namespace em = enterprise_management; | |
23 | |
24 // Responsible for managing the on-disk token cache. | |
25 class UserPolicyIdentityStrategy::TokenCache | |
26 : public base::RefCountedThreadSafe< | |
27 UserPolicyIdentityStrategy::TokenCache> { | |
gfeher
2011/02/18 20:21:29
Nit: please create a private destructor and make b
Jakob Kummerow
2011/02/21 12:12:15
Done.
| |
28 public: | |
29 TokenCache(const base::WeakPtr<UserPolicyIdentityStrategy>& identity_strategy, | |
30 const FilePath& cache_file); | |
31 | |
32 void Load(); | |
33 void Store(const std::string& token, const std::string& device_id); | |
34 | |
35 private: | |
36 void LoadOnFileThread(); | |
37 void NotifyOnUIThread(const std::string& token, | |
38 const std::string& device_id); | |
39 void StoreOnFileThread(const std::string& token, | |
40 const std::string& device_id); | |
41 | |
42 const base::WeakPtr<UserPolicyIdentityStrategy> identity_strategy_; | |
43 const FilePath& cache_file_; | |
gfeher
2011/02/18 20:12:26
This shouldn't be a reference.
Jakob Kummerow
2011/02/21 12:12:15
Done.
| |
44 | |
45 DISALLOW_COPY_AND_ASSIGN(TokenCache); | |
46 }; | |
47 | |
48 UserPolicyIdentityStrategy::TokenCache::TokenCache( | |
49 const base::WeakPtr<UserPolicyIdentityStrategy>& identity_strategy, | |
50 const FilePath& cache_file) | |
51 : identity_strategy_(identity_strategy), | |
52 cache_file_(cache_file) {} | |
53 | |
54 void UserPolicyIdentityStrategy::TokenCache::Load() { | |
55 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
56 BrowserThread::PostTask( | |
57 BrowserThread::FILE, FROM_HERE, | |
58 NewRunnableMethod( | |
59 this, &UserPolicyIdentityStrategy::TokenCache::LoadOnFileThread)); | |
60 } | |
61 | |
62 void UserPolicyIdentityStrategy::TokenCache::Store( | |
63 const std::string& token, | |
64 const std::string& device_id) { | |
65 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
66 BrowserThread::PostTask( | |
67 BrowserThread::FILE, FROM_HERE, | |
68 NewRunnableMethod( | |
69 this, | |
70 &UserPolicyIdentityStrategy::TokenCache::StoreOnFileThread, | |
71 token, | |
72 device_id)); | |
73 } | |
74 | |
75 void UserPolicyIdentityStrategy::TokenCache::LoadOnFileThread() { | |
76 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | |
77 std::string device_token; | |
78 std::string device_id; | |
79 | |
80 if (file_util::PathExists(cache_file_)) { | |
81 std::string data; | |
82 em::DeviceCredentials device_credentials; | |
83 if (file_util::ReadFileToString(cache_file_, &data) && | |
84 device_credentials.ParseFromArray(data.c_str(), data.size())) { | |
85 device_token = device_credentials.device_token(); | |
86 device_id = device_credentials.device_id(); | |
87 } | |
88 } | |
89 | |
90 BrowserThread::PostTask( | |
91 BrowserThread::UI, FROM_HERE, | |
92 NewRunnableMethod( | |
93 this, | |
94 &UserPolicyIdentityStrategy::TokenCache::NotifyOnUIThread, | |
95 device_token, | |
96 device_id)); | |
97 } | |
98 | |
99 void UserPolicyIdentityStrategy::TokenCache::NotifyOnUIThread( | |
100 const std::string& token, | |
101 const std::string& device_id) { | |
102 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
103 if (identity_strategy_.get()) | |
104 identity_strategy_->OnCacheLoaded(token, device_id); | |
105 } | |
106 | |
107 void UserPolicyIdentityStrategy::TokenCache::StoreOnFileThread( | |
108 const std::string& token, | |
109 const std::string& device_id) { | |
110 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | |
111 em::DeviceCredentials device_credentials; | |
112 device_credentials.set_device_token(token); | |
113 device_credentials.set_device_id(device_id); | |
114 std::string data; | |
115 bool success = device_credentials.SerializeToString(&data); | |
116 if (!success) { | |
117 LOG(WARNING) << "Failed serialize device token data, will not write " | |
118 << cache_file_.value(); | |
119 return; | |
120 } | |
121 | |
122 file_util::WriteFile(cache_file_, data.c_str(), data.length()); | |
123 } | |
124 | |
125 UserPolicyIdentityStrategy::UserPolicyIdentityStrategy( | |
126 Profile* profile, | |
127 const FilePath& cache_file) | |
128 : profile_(profile), | |
129 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { | |
130 cache_ = new TokenCache(weak_ptr_factory_.GetWeakPtr(), cache_file); | |
131 registrar_.Add(this, | |
132 NotificationType::TOKEN_AVAILABLE, | |
133 Source<TokenService>(profile->GetTokenService())); | |
134 | |
135 // Register for the event of user login. The device management token won't | |
136 // be fetched until we know the domain of the currently logged in user. | |
137 #if defined(OS_CHROMEOS) | |
138 registrar_.Add(this, | |
139 NotificationType::LOGIN_USER_CHANGED, | |
140 NotificationService::AllSources()); | |
141 #else | |
142 registrar_.Add(this, | |
143 NotificationType::GOOGLE_SIGNIN_SUCCESSFUL, | |
144 Source<Profile>(profile_)); | |
145 #endif | |
146 | |
147 cache_->Load(); | |
148 } | |
149 | |
150 UserPolicyIdentityStrategy::~UserPolicyIdentityStrategy() {} | |
151 | |
152 std::string UserPolicyIdentityStrategy::GetDeviceToken() { | |
153 return device_token_; | |
154 } | |
155 | |
156 std::string UserPolicyIdentityStrategy::GetDeviceID() { | |
157 return device_id_; | |
158 } | |
159 | |
160 bool UserPolicyIdentityStrategy::GetCredentials(std::string* username, | |
161 std::string* auth_token) { | |
162 *username = GetCurrentUser(); | |
163 *auth_token = profile_->GetTokenService()->GetTokenForService( | |
164 GaiaConstants::kDeviceManagementService); | |
165 | |
166 return !username->empty() && !auth_token->empty() && !device_id_.empty(); | |
167 } | |
168 | |
169 void UserPolicyIdentityStrategy::OnDeviceTokenAvailable( | |
170 const std::string& token) { | |
171 DCHECK(!device_id_.empty()); | |
172 device_token_ = token; | |
173 cache_->Store(device_token_, device_id_); | |
174 NotifyDeviceTokenChanged(); | |
175 } | |
176 | |
177 std::string UserPolicyIdentityStrategy::GetCurrentUser() { | |
178 #if defined(OS_CHROMEOS) | |
179 // TODO(mnissler) On CrOS it seems impossible to figure out what user belongs | |
180 // to a profile. Revisit after multi-profile support landed. | |
181 return chromeos::UserManager::Get()->logged_in_user().email(); | |
182 #else | |
183 return profile_->GetBrowserSignin()->GetSignedInUsername(); | |
184 #endif | |
185 } | |
186 | |
187 void UserPolicyIdentityStrategy::CheckAndTriggerFetch() { | |
188 if (!GetCurrentUser().empty() && | |
189 profile_->GetTokenService()->HasTokenForService( | |
190 GaiaConstants::kDeviceManagementService)) { | |
191 // For user tokens, there is no actual identifier. We generate a random | |
192 // identifier instead each time we ask for the token. | |
193 device_id_ = guid::GenerateGUID(); | |
194 NotifyAuthChanged(); | |
195 } | |
196 } | |
197 | |
198 void UserPolicyIdentityStrategy::OnCacheLoaded(const std::string& token, | |
199 const std::string& device_id) { | |
200 if (!token.empty() && !device_id.empty()) { | |
201 device_token_ = token; | |
202 device_id_ = device_id; | |
203 NotifyDeviceTokenChanged(); | |
204 } else { | |
205 CheckAndTriggerFetch(); | |
206 } | |
207 } | |
208 | |
209 void UserPolicyIdentityStrategy::Observe(NotificationType type, | |
210 const NotificationSource& source, | |
211 const NotificationDetails& details) { | |
212 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
213 if (type == NotificationType::TOKEN_AVAILABLE) { | |
214 if (Source<TokenService>(source).ptr() == profile_->GetTokenService()) { | |
215 const TokenService::TokenAvailableDetails* token_details = | |
216 Details<const TokenService::TokenAvailableDetails>(details).ptr(); | |
217 if (token_details->service() == GaiaConstants::kDeviceManagementService) | |
218 CheckAndTriggerFetch(); | |
219 } | |
220 #if defined(OS_CHROMEOS) | |
221 } else if (type == NotificationType::LOGIN_USER_CHANGED) { | |
222 CheckAndTriggerFetch(); | |
223 #else | |
224 } else if (type == NotificationType::GOOGLE_SIGNIN_SUCCESSFUL) { | |
225 if (profile_ == Source<Profile>(source).ptr()) | |
226 CheckAndTriggerFetch(); | |
227 #endif | |
228 } else { | |
229 NOTREACHED(); | |
230 } | |
231 } | |
232 | |
233 } // namespace policy | |
OLD | NEW |