OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2017 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/chromeos/authpolicy/auth_policy_credentials_manager.h" | |
6 | |
7 #include "base/location.h" | |
8 #include "base/memory/singleton.h" | |
9 #include "base/strings/utf_string_conversions.h" | |
10 #include "chrome/browser/browser_process.h" | |
11 #include "chrome/browser/chromeos/profiles/profile_helper.h" | |
12 #include "chrome/browser/lifetime/application_lifetime.h" | |
13 #include "chrome/browser/notifications/notification.h" | |
14 #include "chrome/browser/notifications/notification_delegate.h" | |
15 #include "chrome/browser/notifications/notification_ui_manager.h" | |
16 #include "chrome/browser/profiles/profile.h" | |
17 #include "chrome/grit/chromium_strings.h" | |
18 #include "chrome/grit/generated_resources.h" | |
19 #include "chrome/grit/theme_resources.h" | |
20 #include "chromeos/dbus/auth_policy_client.h" | |
21 #include "chromeos/dbus/dbus_thread_manager.h" | |
22 #include "chromeos/network/network_handler.h" | |
23 #include "chromeos/network/network_state.h" | |
24 #include "chromeos/network/network_state_handler.h" | |
25 #include "components/keyed_service/content/browser_context_dependency_manager.h" | |
26 #include "content/public/browser/browser_thread.h" | |
27 #include "ui/base/l10n/l10n_util.h" | |
28 #include "ui/base/resource/resource_bundle.h" | |
29 | |
30 namespace { | |
31 | |
32 const base::TimeDelta kGetUserStatusCallsInterval = | |
33 base::TimeDelta::FromHours(1); | |
34 const char kProfileSigninNotificationId[] = "chrome://settings/signin/"; | |
35 | |
36 // A notification delegate for the sign-out button. | |
37 class SigninNotificationDelegate : public NotificationDelegate { | |
38 public: | |
39 explicit SigninNotificationDelegate(const std::string& id); | |
40 | |
41 // NotificationDelegate: | |
42 void Click() override; | |
43 void ButtonClick(int button_index) override; | |
44 std::string id() const override; | |
45 | |
46 protected: | |
47 ~SigninNotificationDelegate() override; | |
48 | |
49 private: | |
50 void FixSignIn(); | |
ljusten (tachyonic)
2017/05/03 10:12:17
Comment? From the class definition, shouldn't it b
Roman Sorokin (ftl)
2017/05/19 12:13:47
Done.
ljusten (tachyonic)
2017/05/19 16:06:13
β
Roman Sorokin (ftl)
2017/05/22 12:35:27
wat?
ljusten (tachyonic)
2017/05/22 14:27:49
beta = better (at least if you pronounce it like a
| |
51 | |
52 // Unique id of the notification. | |
53 const std::string id_; | |
54 | |
55 DISALLOW_COPY_AND_ASSIGN(SigninNotificationDelegate); | |
56 }; | |
57 | |
58 SigninNotificationDelegate::SigninNotificationDelegate(const std::string& id) | |
59 : id_(id) {} | |
60 | |
61 SigninNotificationDelegate::~SigninNotificationDelegate() {} | |
62 | |
63 void SigninNotificationDelegate::Click() { | |
64 FixSignIn(); | |
65 } | |
66 | |
67 void SigninNotificationDelegate::ButtonClick(int button_index) { | |
68 FixSignIn(); | |
69 } | |
70 | |
71 std::string SigninNotificationDelegate::id() const { | |
72 return id_; | |
73 } | |
74 | |
75 void SigninNotificationDelegate::FixSignIn() { | |
76 chrome::AttemptUserExit(); | |
77 } | |
78 } // namespace | |
79 | |
80 AuthPolicyCredentialsManager::AuthPolicyCredentialsManager(Profile* profile) | |
81 : profile_(profile), weak_factory_(this) { | |
82 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | |
83 StartObserveNetwork(); | |
84 const user_manager::User* user = | |
85 chromeos::ProfileHelper::Get()->GetUserByProfile(profile); | |
86 CHECK(user && user->IsActiveDirectoryUser()); | |
87 account_id_ = user->GetAccountId(); | |
88 GetUserStatus(); | |
89 } | |
90 | |
91 AuthPolicyCredentialsManager::~AuthPolicyCredentialsManager() {} | |
92 | |
93 void AuthPolicyCredentialsManager::Shutdown() { | |
94 StopObserveNetwork(); | |
ljusten (tachyonic)
2017/05/03 10:12:17
Cancel scheduled_get_user_status_call_? Note that
Roman Sorokin (ftl)
2017/05/19 12:13:48
It does.
ljusten (tachyonic)
2017/05/19 16:06:13
Nm, it actually is cancelled.
Roman Sorokin (ftl)
2017/05/22 12:35:27
Acknowledged.
| |
95 } | |
96 | |
97 void AuthPolicyCredentialsManager::DefaultNetworkChanged( | |
98 const chromeos::NetworkState* network) { | |
99 CallGetStatusIfConnected(network); | |
100 } | |
101 | |
102 void AuthPolicyCredentialsManager::NetworkConnectionStateChanged( | |
103 const chromeos::NetworkState* network) { | |
104 CallGetStatusIfConnected(network); | |
105 } | |
106 | |
107 void AuthPolicyCredentialsManager::OnShuttingDown() { | |
108 StopObserveNetwork(); | |
109 } | |
110 | |
111 void AuthPolicyCredentialsManager::GetUserStatus() { | |
112 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | |
113 should_call_get_status_again_ = false; | |
114 chromeos::DBusThreadManager::Get()->GetAuthPolicyClient()->GetUserStatus( | |
115 account_id_.GetObjGuid(), | |
116 base::BindOnce(&AuthPolicyCredentialsManager::OnGetUserStatusCallback, | |
117 weak_factory_.GetWeakPtr())); | |
118 } | |
119 | |
120 void AuthPolicyCredentialsManager::OnGetUserStatusCallback( | |
121 authpolicy::ErrorType error, | |
122 const authpolicy::ActiveDirectoryUserStatus& user_status) { | |
123 last_error_ = error; | |
124 if (error != authpolicy::ERROR_NONE) { | |
125 DCHECK(error == authpolicy::ERROR_CONTACTING_KDC_FAILED); | |
ljusten (tachyonic)
2017/05/03 10:12:16
Suggest remove. This is dangerous. Even though ERR
Roman Sorokin (ftl)
2017/05/19 12:13:48
Done.
| |
126 DLOG(ERROR) << "GetUserStatus failed with " << error; | |
127 return; | |
128 } | |
129 CHECK(user_status.account_info().account_id() == account_id_.GetObjGuid()); | |
130 if (user_status.has_account_info()) | |
131 UpdateDisplayAndGivenName(user_status.account_info()); | |
132 | |
133 if (should_call_get_status_again_) { | |
134 GetUserStatus(); | |
ljusten (tachyonic)
2017/05/03 10:12:16
Why do you update names if should_call_get_status_
Roman Sorokin (ftl)
2017/05/19 12:13:47
We don't want to spam notifications. Updating name
ljusten (tachyonic)
2017/05/19 16:06:13
But then the next call could fail and the user wou
Roman Sorokin (ftl)
2017/05/22 12:35:27
Yeah, it's a good idea
| |
135 return; | |
136 } | |
137 | |
138 ScheduleGetUserStatus(); | |
139 | |
140 if (user_status.has_password_status()) { | |
ljusten (tachyonic)
2017/05/19 16:06:13
DCHECK instead. It should always be present.
Roman Sorokin (ftl)
2017/05/22 12:35:27
Done.
| |
141 switch (user_status.password_status()) { | |
142 case authpolicy::ActiveDirectoryUserStatus::PASSWORD_VALID: | |
143 // do nothing | |
144 break; | |
145 case authpolicy::ActiveDirectoryUserStatus::PASSWORD_EXPIRED: | |
146 ShowNotification(IDS_ACTIVE_DIRECTORY_PASSWORD_EXPIRED); | |
147 return; | |
148 case authpolicy::ActiveDirectoryUserStatus::PASSWORD_CHANGED: | |
149 ShowNotification(IDS_ACTIVE_DIRECTORY_PASSWORD_CHANGED); | |
150 return; | |
151 } | |
152 } | |
153 | |
154 if (user_status.has_tgt_status()) { | |
ljusten (tachyonic)
2017/05/19 16:06:13
DCHECK instead. It should always be present.
Roman Sorokin (ftl)
2017/05/22 12:35:27
Done.
| |
155 switch (user_status.tgt_status()) { | |
156 case authpolicy::ActiveDirectoryUserStatus::TGT_VALID: | |
157 // do nothing | |
158 break; | |
159 case authpolicy::ActiveDirectoryUserStatus::TGT_EXPIRED: | |
160 case authpolicy::ActiveDirectoryUserStatus::TGT_NOT_FOUND: | |
161 ShowNotification(IDS_ACTIVE_DIRECTORY_REFRESH_AUTH_TOKEN); | |
162 return; | |
163 } | |
164 } | |
165 // Everything is ok. | |
166 user_manager::UserManager::Get()->SaveForceOnlineSignin(account_id_, false); | |
167 } | |
168 | |
169 void AuthPolicyCredentialsManager::ScheduleGetUserStatus() { | |
170 scheduled_get_user_status_call_.Reset(base::Bind( | |
171 &AuthPolicyCredentialsManager::GetUserStatus, base::Unretained(this))); | |
172 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | |
173 FROM_HERE, scheduled_get_user_status_call_.callback(), | |
174 kGetUserStatusCallsInterval); | |
175 } | |
176 | |
177 void AuthPolicyCredentialsManager::StartObserveNetwork() { | |
178 if (chromeos::NetworkHandler::IsInitialized()) | |
ljusten (tachyonic)
2017/05/03 10:12:16
Since this can fail, return bool? Or DCHECK?
Roman Sorokin (ftl)
2017/05/19 12:13:46
Done.
| |
179 chromeos::NetworkHandler::Get()->network_state_handler()->AddObserver( | |
180 this, FROM_HERE); | |
181 } | |
182 | |
183 void AuthPolicyCredentialsManager::StopObserveNetwork() { | |
184 if (chromeos::NetworkHandler::IsInitialized()) | |
ljusten (tachyonic)
2017/05/03 10:12:16
Since this can fail, return bool? Or DCHECK?
Roman Sorokin (ftl)
2017/05/19 12:13:46
Done.
| |
185 chromeos::NetworkHandler::Get()->network_state_handler()->RemoveObserver( | |
186 this, FROM_HERE); | |
187 } | |
188 | |
189 void AuthPolicyCredentialsManager::UpdateDisplayAndGivenName( | |
190 const authpolicy::ActiveDirectoryAccountInfo& account_info) { | |
191 if (display_name_ == account_info.display_name() && | |
192 given_name_ == account_info.given_name()) { | |
193 return; | |
194 } | |
195 display_name_ = account_info.display_name(); | |
196 given_name_ = account_info.given_name(); | |
197 user_manager::UserManager::Get()->UpdateUserAccountData( | |
198 account_id_, | |
199 user_manager::UserManager::UserAccountData( | |
200 base::UTF8ToUTF16(display_name_), base::UTF8ToUTF16(given_name_), | |
201 std::string() /* locale */)); | |
202 } | |
203 | |
204 void AuthPolicyCredentialsManager::ShowNotification(int message_id) const { | |
205 user_manager::UserManager::Get()->SaveForceOnlineSignin(account_id_, true); | |
206 | |
207 message_center::RichNotificationData data; | |
208 data.buttons.push_back(message_center::ButtonInfo( | |
209 l10n_util::GetStringUTF16(IDS_SYNC_RELOGIN_LINK_LABEL))); | |
210 | |
211 std::string notification_id = | |
ljusten (tachyonic)
2017/05/03 10:12:17
const
Roman Sorokin (ftl)
2017/05/19 12:13:48
Done.
| |
212 kProfileSigninNotificationId + profile_->GetProfileUserName(); | |
213 // Set the delegate for the notification's sign-out button. | |
214 SigninNotificationDelegate* delegate = | |
215 new SigninNotificationDelegate(notification_id); | |
216 | |
217 message_center::NotifierId notifier_id( | |
ljusten (tachyonic)
2017/05/03 10:12:16
const
Roman Sorokin (ftl)
2017/05/19 12:13:47
Nope
ljusten (tachyonic)
2017/05/19 16:06:13
Acknowledged.
Roman Sorokin (ftl)
2017/05/22 12:35:27
Acknowledged.
| |
218 message_center::NotifierId::SYSTEM_COMPONENT, | |
219 kProfileSigninNotificationId); | |
220 | |
221 // Set |profile_id| for multi-user notification blocker. | |
222 notifier_id.profile_id = profile_->GetProfileUserName(); | |
223 | |
224 Notification notification( | |
225 message_center::NOTIFICATION_TYPE_SIMPLE, | |
226 l10n_util::GetStringUTF16(IDS_SIGNIN_ERROR_BUBBLE_VIEW_TITLE), | |
227 l10n_util::GetStringUTF16(message_id), | |
228 ui::ResourceBundle::GetSharedInstance().GetImageNamed( | |
229 IDR_NOTIFICATION_ALERT), | |
230 notifier_id, | |
231 base::string16(), // display_source | |
232 GURL(notification_id), notification_id, data, delegate); | |
233 notification.SetSystemPriority(); | |
234 | |
235 NotificationUIManager* notification_ui_manager = | |
236 g_browser_process->notification_ui_manager(); | |
237 // Update or add the notification. | |
238 if (notification_ui_manager->FindById( | |
239 notification_id, NotificationUIManager::GetProfileID(profile_))) | |
240 notification_ui_manager->Update(notification, profile_); | |
241 else | |
242 notification_ui_manager->Add(notification, profile_); | |
243 } | |
244 | |
245 void AuthPolicyCredentialsManager::CallGetStatusIfConnected( | |
246 const chromeos::NetworkState* network) { | |
247 if (last_error_ != authpolicy::ERROR_NONE) | |
ljusten (tachyonic)
2017/05/19 16:06:13
Modify as discussed offline to handle the followin
Roman Sorokin (ftl)
2017/05/22 12:35:27
Done.
| |
248 return; | |
249 if (!network || !network->IsConnectedState()) | |
250 return; | |
251 if (weak_factory_.HasWeakPtrs()) { | |
252 // Another call is in progress. | |
253 should_call_get_status_again_ = true; | |
254 return; | |
255 } | |
256 GetUserStatus(); | |
257 } | |
258 | |
259 // static | |
260 AuthPolicyCredentialsManagerFactory* | |
261 AuthPolicyCredentialsManagerFactory::GetInstance() { | |
262 return base::Singleton<AuthPolicyCredentialsManagerFactory>::get(); | |
263 } | |
264 | |
265 // static | |
266 void AuthPolicyCredentialsManagerFactory::BuildForProfileIfActiveDirectory( | |
267 Profile* profile) { | |
268 const user_manager::User* user = | |
269 chromeos::ProfileHelper::Get()->GetUserByProfile(profile); | |
270 if (!user || !user->IsActiveDirectoryUser()) | |
271 return; | |
272 GetInstance()->GetServiceForBrowserContext(profile, true /* create */); | |
273 } | |
274 | |
275 AuthPolicyCredentialsManagerFactory::AuthPolicyCredentialsManagerFactory() | |
276 : BrowserContextKeyedServiceFactory( | |
277 "AuthPolicyCredentialsManager", | |
278 BrowserContextDependencyManager::GetInstance()) {} | |
279 | |
280 AuthPolicyCredentialsManagerFactory::~AuthPolicyCredentialsManagerFactory() {} | |
281 | |
282 KeyedService* AuthPolicyCredentialsManagerFactory::BuildServiceInstanceFor( | |
ljusten (tachyonic)
2017/05/03 10:12:16
Unused?
Roman Sorokin (ftl)
2017/05/19 12:13:46
This is the factory method.
| |
283 content::BrowserContext* context) const { | |
284 Profile* profile = Profile::FromBrowserContext(context); | |
285 return new AuthPolicyCredentialsManager(profile); | |
286 } | |
OLD | NEW |