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 // Unique id of the notification. | |
51 const std::string id_; | |
52 | |
53 DISALLOW_COPY_AND_ASSIGN(SigninNotificationDelegate); | |
54 }; | |
55 | |
56 SigninNotificationDelegate::SigninNotificationDelegate(const std::string& id) | |
57 : id_(id) {} | |
58 | |
59 SigninNotificationDelegate::~SigninNotificationDelegate() {} | |
60 | |
61 void SigninNotificationDelegate::Click() { | |
62 chrome::AttemptUserExit(); | |
63 } | |
64 | |
65 void SigninNotificationDelegate::ButtonClick(int button_index) { | |
66 chrome::AttemptUserExit(); | |
67 } | |
68 | |
69 std::string SigninNotificationDelegate::id() const { | |
70 return id_; | |
71 } | |
72 | |
73 } // namespace | |
74 | |
75 AuthPolicyCredentialsManager::AuthPolicyCredentialsManager(Profile* profile) | |
76 : profile_(profile), weak_factory_(this) { | |
77 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | |
78 StartObserveNetwork(); | |
79 const user_manager::User* user = | |
80 chromeos::ProfileHelper::Get()->GetUserByProfile(profile); | |
81 CHECK(user && user->IsActiveDirectoryUser()); | |
82 account_id_ = user->GetAccountId(); | |
83 GetUserStatus(); | |
84 } | |
85 | |
86 AuthPolicyCredentialsManager::~AuthPolicyCredentialsManager() {} | |
87 | |
88 void AuthPolicyCredentialsManager::Shutdown() { | |
89 StopObserveNetwork(); | |
90 } | |
91 | |
92 void AuthPolicyCredentialsManager::DefaultNetworkChanged( | |
93 const chromeos::NetworkState* network) { | |
94 GetUserStatusIfConnected(network); | |
95 } | |
96 | |
97 void AuthPolicyCredentialsManager::NetworkConnectionStateChanged( | |
98 const chromeos::NetworkState* network) { | |
99 GetUserStatusIfConnected(network); | |
100 } | |
101 | |
102 void AuthPolicyCredentialsManager::OnShuttingDown() { | |
103 StopObserveNetwork(); | |
104 } | |
105 | |
106 void AuthPolicyCredentialsManager::GetUserStatus() { | |
107 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | |
ljusten (tachyonic)
2017/05/22 14:27:49
I'd suggest to cancel scheduled_get_user_status_ca
Roman Sorokin (ftl)
2017/05/22 16:38:23
Done.
| |
108 should_call_get_status_again_ = false; | |
109 chromeos::DBusThreadManager::Get()->GetAuthPolicyClient()->GetUserStatus( | |
110 account_id_.GetObjGuid(), | |
111 base::BindOnce(&AuthPolicyCredentialsManager::OnGetUserStatusCallback, | |
112 weak_factory_.GetWeakPtr())); | |
113 } | |
114 | |
115 void AuthPolicyCredentialsManager::OnGetUserStatusCallback( | |
116 authpolicy::ErrorType error, | |
117 const authpolicy::ActiveDirectoryUserStatus& user_status) { | |
118 last_error_ = error; | |
119 if (error != authpolicy::ERROR_NONE) { | |
120 DLOG(ERROR) << "GetUserStatus failed with " << error; | |
121 if (should_call_get_status_again_) | |
122 GetUserStatus(); | |
123 return; | |
124 } | |
125 CHECK(user_status.account_info().account_id() == account_id_.GetObjGuid()); | |
ljusten (tachyonic)
2017/05/22 14:27:49
should_call_get_status_again_ = false; ?
Roman Sorokin (ftl)
2017/05/22 16:38:23
Done.
| |
126 if (user_status.has_account_info()) | |
127 UpdateDisplayAndGivenName(user_status.account_info()); | |
128 | |
129 ScheduleGetUserStatus(); | |
ljusten (tachyonic)
2017/05/22 14:27:49
Will this ever get rescheduled in case of error?
Roman Sorokin (ftl)
2017/05/22 16:38:23
Done.
| |
130 | |
131 DCHECK(user_status.has_password_status()); | |
ljusten (tachyonic)
2017/05/22 14:27:49
I just realized that the code that sets this hasn'
Roman Sorokin (ftl)
2017/05/22 16:38:23
Acknowledged.
| |
132 switch (user_status.password_status()) { | |
133 case authpolicy::ActiveDirectoryUserStatus::PASSWORD_VALID: | |
134 // do nothing | |
135 break; | |
136 case authpolicy::ActiveDirectoryUserStatus::PASSWORD_EXPIRED: | |
137 ShowNotification(IDS_ACTIVE_DIRECTORY_PASSWORD_EXPIRED); | |
138 return; | |
139 case authpolicy::ActiveDirectoryUserStatus::PASSWORD_CHANGED: | |
140 ShowNotification(IDS_ACTIVE_DIRECTORY_PASSWORD_CHANGED); | |
141 return; | |
142 } | |
143 | |
144 DCHECK(user_status.has_tgt_status()); | |
ljusten (tachyonic)
2017/05/22 14:27:49
Same here.
Roman Sorokin (ftl)
2017/05/22 16:38:23
Acknowledged.
| |
145 switch (user_status.tgt_status()) { | |
146 case authpolicy::ActiveDirectoryUserStatus::TGT_VALID: | |
147 // do nothing | |
148 break; | |
149 case authpolicy::ActiveDirectoryUserStatus::TGT_EXPIRED: | |
150 case authpolicy::ActiveDirectoryUserStatus::TGT_NOT_FOUND: | |
151 ShowNotification(IDS_ACTIVE_DIRECTORY_REFRESH_AUTH_TOKEN); | |
152 return; | |
153 } | |
154 // Everything is ok. | |
155 user_manager::UserManager::Get()->SaveForceOnlineSignin(account_id_, false); | |
156 } | |
157 | |
158 void AuthPolicyCredentialsManager::ScheduleGetUserStatus() { | |
159 scheduled_get_user_status_call_.Reset(base::Bind( | |
160 &AuthPolicyCredentialsManager::GetUserStatus, base::Unretained(this))); | |
161 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | |
162 FROM_HERE, scheduled_get_user_status_call_.callback(), | |
163 kGetUserStatusCallsInterval); | |
164 } | |
165 | |
166 void AuthPolicyCredentialsManager::StartObserveNetwork() { | |
167 DCHECK(chromeos::NetworkHandler::IsInitialized()); | |
168 chromeos::NetworkHandler::Get()->network_state_handler()->AddObserver( | |
169 this, FROM_HERE); | |
170 } | |
171 | |
172 void AuthPolicyCredentialsManager::StopObserveNetwork() { | |
173 DCHECK(chromeos::NetworkHandler::IsInitialized()); | |
174 chromeos::NetworkHandler::Get()->network_state_handler()->RemoveObserver( | |
175 this, FROM_HERE); | |
176 } | |
177 | |
178 void AuthPolicyCredentialsManager::UpdateDisplayAndGivenName( | |
179 const authpolicy::ActiveDirectoryAccountInfo& account_info) { | |
180 if (display_name_ == account_info.display_name() && | |
181 given_name_ == account_info.given_name()) { | |
182 return; | |
183 } | |
184 display_name_ = account_info.display_name(); | |
185 given_name_ = account_info.given_name(); | |
186 user_manager::UserManager::Get()->UpdateUserAccountData( | |
187 account_id_, | |
188 user_manager::UserManager::UserAccountData( | |
189 base::UTF8ToUTF16(display_name_), base::UTF8ToUTF16(given_name_), | |
190 std::string() /* locale */)); | |
191 } | |
192 | |
193 void AuthPolicyCredentialsManager::ShowNotification(int message_id) { | |
194 user_manager::UserManager::Get()->SaveForceOnlineSignin(account_id_, true); | |
195 | |
196 if (was_notification_shown_) | |
197 return; | |
198 | |
199 message_center::RichNotificationData data; | |
200 data.buttons.push_back(message_center::ButtonInfo( | |
201 l10n_util::GetStringUTF16(IDS_SYNC_RELOGIN_LINK_LABEL))); | |
202 | |
203 const std::string notification_id = | |
204 kProfileSigninNotificationId + profile_->GetProfileUserName(); | |
205 // Set the delegate for the notification's sign-out button. | |
206 SigninNotificationDelegate* delegate = | |
207 new SigninNotificationDelegate(notification_id); | |
208 | |
209 message_center::NotifierId notifier_id( | |
210 message_center::NotifierId::SYSTEM_COMPONENT, | |
211 kProfileSigninNotificationId); | |
212 | |
213 // Set |profile_id| for multi-user notification blocker. | |
214 notifier_id.profile_id = profile_->GetProfileUserName(); | |
215 | |
216 Notification notification( | |
217 message_center::NOTIFICATION_TYPE_SIMPLE, | |
218 l10n_util::GetStringUTF16(IDS_SIGNIN_ERROR_BUBBLE_VIEW_TITLE), | |
219 l10n_util::GetStringUTF16(message_id), | |
220 ui::ResourceBundle::GetSharedInstance().GetImageNamed( | |
221 IDR_NOTIFICATION_ALERT), | |
222 notifier_id, | |
223 base::string16(), // display_source | |
224 GURL(notification_id), notification_id, data, delegate); | |
225 notification.SetSystemPriority(); | |
226 | |
227 NotificationUIManager* notification_ui_manager = | |
228 g_browser_process->notification_ui_manager(); | |
229 // Add the notification. | |
230 notification_ui_manager->Add(notification, profile_); | |
231 was_notification_shown_ = true; | |
232 } | |
233 | |
234 void AuthPolicyCredentialsManager::GetUserStatusIfConnected( | |
235 const chromeos::NetworkState* network) { | |
236 if (!network || !network->IsConnectedState()) | |
237 return; | |
238 if (weak_factory_.HasWeakPtrs()) { | |
239 // Another call is in progress. | |
240 should_call_get_status_again_ = true; | |
241 return; | |
242 } | |
243 if (last_error_ != authpolicy::ERROR_NONE) | |
244 GetUserStatus(); | |
245 } | |
246 | |
247 // static | |
248 AuthPolicyCredentialsManagerFactory* | |
249 AuthPolicyCredentialsManagerFactory::GetInstance() { | |
250 return base::Singleton<AuthPolicyCredentialsManagerFactory>::get(); | |
251 } | |
252 | |
253 // static | |
254 void AuthPolicyCredentialsManagerFactory::BuildForProfileIfActiveDirectory( | |
255 Profile* profile) { | |
256 const user_manager::User* user = | |
257 chromeos::ProfileHelper::Get()->GetUserByProfile(profile); | |
258 if (!user || !user->IsActiveDirectoryUser()) | |
259 return; | |
260 GetInstance()->GetServiceForBrowserContext(profile, true /* create */); | |
261 } | |
262 | |
263 AuthPolicyCredentialsManagerFactory::AuthPolicyCredentialsManagerFactory() | |
264 : BrowserContextKeyedServiceFactory( | |
265 "AuthPolicyCredentialsManager", | |
266 BrowserContextDependencyManager::GetInstance()) {} | |
267 | |
268 AuthPolicyCredentialsManagerFactory::~AuthPolicyCredentialsManagerFactory() {} | |
269 | |
270 KeyedService* AuthPolicyCredentialsManagerFactory::BuildServiceInstanceFor( | |
271 content::BrowserContext* context) const { | |
272 Profile* profile = Profile::FromBrowserContext(context); | |
273 return new AuthPolicyCredentialsManager(profile); | |
274 } | |
OLD | NEW |