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 = | |
Thiemo Nagel
2017/05/24 10:11:05
Global objects must be constexpr.
Roman Sorokin (ftl)
2017/05/26 12:03:36
Done.
| |
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; | |
Thiemo Nagel
2017/05/24 10:11:05
Are you sure this is necessary? Why not just use
Roman Sorokin (ftl)
2017/05/26 12:03:37
Done.
| |
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) { | |
Thiemo Nagel
2017/05/24 10:11:04
Nit: For weak_factory_, I'd prefer in-class initia
Roman Sorokin (ftl)
2017/05/26 12:03:36
Done.
| |
77 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | |
Thiemo Nagel
2017/05/24 10:11:04
Nit: Any particular reason you're checking for thi
Roman Sorokin (ftl)
2017/05/26 12:03:36
I dunno, just in case :)
Thiemo Nagel
2017/05/26 12:46:21
What is your code doing that requires running on t
Roman Sorokin (ftl)
2017/05/26 13:06:32
make sense! thanks!
| |
78 StartObserveNetwork(); | |
Thiemo Nagel
2017/05/24 10:11:04
Nit: I prefer to have CHECK()'s at the top of the
Roman Sorokin (ftl)
2017/05/26 12:03:36
Done.
| |
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); | |
Thiemo Nagel
2017/05/24 10:11:04
Same as above.
| |
108 DCHECK(!weak_factory_.HasWeakPtrs()); | |
109 should_call_get_status_again_ = false; | |
110 scheduled_get_user_status_call_.Cancel(); | |
111 chromeos::DBusThreadManager::Get()->GetAuthPolicyClient()->GetUserStatus( | |
112 account_id_.GetObjGuid(), | |
113 base::BindOnce(&AuthPolicyCredentialsManager::OnGetUserStatusCallback, | |
114 weak_factory_.GetWeakPtr())); | |
115 } | |
116 | |
117 void AuthPolicyCredentialsManager::OnGetUserStatusCallback( | |
118 authpolicy::ErrorType error, | |
119 const authpolicy::ActiveDirectoryUserStatus& user_status) { | |
120 DCHECK(weak_factory_.HasWeakPtrs()); | |
121 ScheduleGetUserStatus(); | |
122 last_error_ = error; | |
ljusten (tachyonic)
2017/05/22 16:52:00
I believe this will call GetUserStatus() over and
Thiemo Nagel
2017/05/24 10:11:04
Simply setting |should_call_get_status_again_| to
Roman Sorokin (ftl)
2017/05/26 12:03:36
Done.
Roman Sorokin (ftl)
2017/05/26 12:03:36
Done.
| |
123 if (error != authpolicy::ERROR_NONE) { | |
124 DLOG(ERROR) << "GetUserStatus failed with " << error; | |
125 if (should_call_get_status_again_) | |
126 GetUserStatus(); | |
127 return; | |
128 } | |
129 CHECK(user_status.account_info().account_id() == account_id_.GetObjGuid()); | |
130 should_call_get_status_again_ = false; | |
131 if (user_status.has_account_info()) | |
132 UpdateDisplayAndGivenName(user_status.account_info()); | |
133 | |
134 DCHECK(user_status.has_password_status()); | |
135 switch (user_status.password_status()) { | |
136 case authpolicy::ActiveDirectoryUserStatus::PASSWORD_VALID: | |
137 // do nothing | |
138 break; | |
139 case authpolicy::ActiveDirectoryUserStatus::PASSWORD_EXPIRED: | |
140 ShowNotification(IDS_ACTIVE_DIRECTORY_PASSWORD_EXPIRED); | |
141 return; | |
142 case authpolicy::ActiveDirectoryUserStatus::PASSWORD_CHANGED: | |
143 ShowNotification(IDS_ACTIVE_DIRECTORY_PASSWORD_CHANGED); | |
144 return; | |
145 } | |
146 | |
147 DCHECK(user_status.has_tgt_status()); | |
148 switch (user_status.tgt_status()) { | |
149 case authpolicy::ActiveDirectoryUserStatus::TGT_VALID: | |
150 // do nothing | |
151 break; | |
152 case authpolicy::ActiveDirectoryUserStatus::TGT_EXPIRED: | |
153 case authpolicy::ActiveDirectoryUserStatus::TGT_NOT_FOUND: | |
154 ShowNotification(IDS_ACTIVE_DIRECTORY_REFRESH_AUTH_TOKEN); | |
155 return; | |
156 } | |
157 // Everything is ok. | |
158 user_manager::UserManager::Get()->SaveForceOnlineSignin(account_id_, false); | |
159 } | |
160 | |
161 void AuthPolicyCredentialsManager::ScheduleGetUserStatus() { | |
162 scheduled_get_user_status_call_.Reset(base::Bind( | |
163 &AuthPolicyCredentialsManager::GetUserStatus, base::Unretained(this))); | |
Thiemo Nagel
2017/05/24 10:11:04
Why is unretained safe here? Maybe add a comment?
Roman Sorokin (ftl)
2017/05/26 12:03:36
Done.
| |
164 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | |
Thiemo Nagel
2017/05/24 10:11:04
Afaics, this does not re-schedule after wake from
Roman Sorokin (ftl)
2017/05/26 12:03:36
Done.
| |
165 FROM_HERE, scheduled_get_user_status_call_.callback(), | |
166 kGetUserStatusCallsInterval); | |
167 } | |
168 | |
169 void AuthPolicyCredentialsManager::StartObserveNetwork() { | |
170 DCHECK(chromeos::NetworkHandler::IsInitialized()); | |
171 chromeos::NetworkHandler::Get()->network_state_handler()->AddObserver( | |
172 this, FROM_HERE); | |
173 } | |
174 | |
175 void AuthPolicyCredentialsManager::StopObserveNetwork() { | |
176 DCHECK(chromeos::NetworkHandler::IsInitialized()); | |
177 chromeos::NetworkHandler::Get()->network_state_handler()->RemoveObserver( | |
178 this, FROM_HERE); | |
179 } | |
180 | |
181 void AuthPolicyCredentialsManager::UpdateDisplayAndGivenName( | |
182 const authpolicy::ActiveDirectoryAccountInfo& account_info) { | |
183 if (display_name_ == account_info.display_name() && | |
184 given_name_ == account_info.given_name()) { | |
185 return; | |
186 } | |
187 display_name_ = account_info.display_name(); | |
188 given_name_ = account_info.given_name(); | |
189 user_manager::UserManager::Get()->UpdateUserAccountData( | |
190 account_id_, | |
191 user_manager::UserManager::UserAccountData( | |
192 base::UTF8ToUTF16(display_name_), base::UTF8ToUTF16(given_name_), | |
193 std::string() /* locale */)); | |
194 } | |
195 | |
196 void AuthPolicyCredentialsManager::ShowNotification(int message_id) { | |
197 user_manager::UserManager::Get()->SaveForceOnlineSignin(account_id_, true); | |
198 | |
199 if (was_notification_shown_) | |
200 return; | |
201 | |
202 message_center::RichNotificationData data; | |
203 data.buttons.push_back(message_center::ButtonInfo( | |
204 l10n_util::GetStringUTF16(IDS_SYNC_RELOGIN_LINK_LABEL))); | |
205 | |
206 const std::string notification_id = | |
207 kProfileSigninNotificationId + profile_->GetProfileUserName(); | |
208 // Set the delegate for the notification's sign-out button. | |
209 SigninNotificationDelegate* delegate = | |
210 new SigninNotificationDelegate(notification_id); | |
211 | |
212 message_center::NotifierId notifier_id( | |
213 message_center::NotifierId::SYSTEM_COMPONENT, | |
214 kProfileSigninNotificationId); | |
215 | |
216 // Set |profile_id| for multi-user notification blocker. | |
217 notifier_id.profile_id = profile_->GetProfileUserName(); | |
218 | |
219 Notification notification( | |
220 message_center::NOTIFICATION_TYPE_SIMPLE, | |
221 l10n_util::GetStringUTF16(IDS_SIGNIN_ERROR_BUBBLE_VIEW_TITLE), | |
222 l10n_util::GetStringUTF16(message_id), | |
223 ui::ResourceBundle::GetSharedInstance().GetImageNamed( | |
224 IDR_NOTIFICATION_ALERT), | |
225 notifier_id, | |
226 base::string16(), // display_source | |
227 GURL(notification_id), notification_id, data, delegate); | |
228 notification.SetSystemPriority(); | |
229 | |
230 NotificationUIManager* notification_ui_manager = | |
231 g_browser_process->notification_ui_manager(); | |
232 // Add the notification. | |
233 notification_ui_manager->Add(notification, profile_); | |
234 was_notification_shown_ = true; | |
235 } | |
236 | |
237 void AuthPolicyCredentialsManager::GetUserStatusIfConnected( | |
238 const chromeos::NetworkState* network) { | |
239 if (!network || !network->IsConnectedState()) | |
240 return; | |
241 if (weak_factory_.HasWeakPtrs()) { | |
242 // Another call is in progress. | |
243 should_call_get_status_again_ = true; | |
244 return; | |
245 } | |
246 if (last_error_ != authpolicy::ERROR_NONE) | |
247 GetUserStatus(); | |
248 } | |
249 | |
250 // static | |
251 AuthPolicyCredentialsManagerFactory* | |
252 AuthPolicyCredentialsManagerFactory::GetInstance() { | |
253 return base::Singleton<AuthPolicyCredentialsManagerFactory>::get(); | |
254 } | |
255 | |
256 // static | |
257 void AuthPolicyCredentialsManagerFactory::BuildForProfileIfActiveDirectory( | |
258 Profile* profile) { | |
259 const user_manager::User* user = | |
260 chromeos::ProfileHelper::Get()->GetUserByProfile(profile); | |
261 if (!user || !user->IsActiveDirectoryUser()) | |
262 return; | |
263 GetInstance()->GetServiceForBrowserContext(profile, true /* create */); | |
264 } | |
265 | |
266 AuthPolicyCredentialsManagerFactory::AuthPolicyCredentialsManagerFactory() | |
267 : BrowserContextKeyedServiceFactory( | |
268 "AuthPolicyCredentialsManager", | |
269 BrowserContextDependencyManager::GetInstance()) {} | |
270 | |
271 AuthPolicyCredentialsManagerFactory::~AuthPolicyCredentialsManagerFactory() {} | |
272 | |
273 KeyedService* AuthPolicyCredentialsManagerFactory::BuildServiceInstanceFor( | |
274 content::BrowserContext* context) const { | |
275 Profile* profile = Profile::FromBrowserContext(context); | |
276 return new AuthPolicyCredentialsManager(profile); | |
277 } | |
OLD | NEW |