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 constexpr 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 = default; | |
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 void SigninNotificationDelegate::Click() { | |
60 chrome::AttemptUserExit(); | |
61 } | |
62 | |
63 void SigninNotificationDelegate::ButtonClick(int button_index) { | |
64 chrome::AttemptUserExit(); | |
65 } | |
66 | |
67 std::string SigninNotificationDelegate::id() const { | |
68 return id_; | |
69 } | |
70 | |
71 } // namespace | |
72 | |
73 AuthPolicyCredentialsManager::AuthPolicyCredentialsManager(Profile* profile) | |
74 : profile_(profile) { | |
75 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | |
76 const user_manager::User* user = | |
77 chromeos::ProfileHelper::Get()->GetUserByProfile(profile); | |
78 CHECK(user && user->IsActiveDirectoryUser()); | |
79 StartObserveNetwork(); | |
80 account_id_ = user->GetAccountId(); | |
81 GetUserStatus(); | |
82 } | |
83 | |
84 AuthPolicyCredentialsManager::~AuthPolicyCredentialsManager() {} | |
85 | |
86 void AuthPolicyCredentialsManager::Shutdown() { | |
87 StopObserveNetwork(); | |
88 } | |
89 | |
90 void AuthPolicyCredentialsManager::DefaultNetworkChanged( | |
91 const chromeos::NetworkState* network) { | |
92 GetUserStatusIfConnected(network); | |
93 } | |
94 | |
95 void AuthPolicyCredentialsManager::NetworkConnectionStateChanged( | |
96 const chromeos::NetworkState* network) { | |
97 GetUserStatusIfConnected(network); | |
98 } | |
99 | |
100 void AuthPolicyCredentialsManager::OnShuttingDown() { | |
101 StopObserveNetwork(); | |
102 } | |
103 | |
104 void AuthPolicyCredentialsManager::GetUserStatus() { | |
105 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | |
106 DCHECK(!weak_factory_.HasWeakPtrs()); | |
107 rerun_get_status_on_error_ = false; | |
108 scheduled_get_user_status_call_.Cancel(); | |
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 DCHECK(weak_factory_.HasWeakPtrs()); | |
119 ScheduleGetUserStatus(); | |
120 last_error_ = error; | |
121 if (error != authpolicy::ERROR_NONE) { | |
122 DLOG(ERROR) << "GetUserStatus failed with " << error; | |
123 if (rerun_get_status_on_error_) { | |
124 rerun_get_status_on_error_ = false; | |
125 GetUserStatus(); | |
126 } | |
127 return; | |
128 } | |
129 CHECK(user_status.account_info().account_id() == account_id_.GetObjGuid()); | |
130 rerun_get_status_on_error_ = 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 // Unretained is safe here because the callback is owned by this object. | |
Thiemo Nagel
2017/05/26 12:46:21
As discussed offline: CancelableCallback is the re
Roman Sorokin (ftl)
2017/05/26 13:06:32
Done.
| |
163 scheduled_get_user_status_call_.Reset(base::Bind( | |
164 &AuthPolicyCredentialsManager::GetUserStatus, base::Unretained(this))); | |
165 // TODO(rsorokin): This does not re-schedule after wake from sleep | |
166 // (and thus the maximal interval between two calls can be (sleep time + | |
167 // kGetUserStatusCallsInterval)) (see crbug.com/726672). | |
168 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | |
169 FROM_HERE, scheduled_get_user_status_call_.callback(), | |
170 kGetUserStatusCallsInterval); | |
171 } | |
172 | |
173 void AuthPolicyCredentialsManager::StartObserveNetwork() { | |
174 DCHECK(chromeos::NetworkHandler::IsInitialized()); | |
175 chromeos::NetworkHandler::Get()->network_state_handler()->AddObserver( | |
176 this, FROM_HERE); | |
177 } | |
178 | |
179 void AuthPolicyCredentialsManager::StopObserveNetwork() { | |
180 DCHECK(chromeos::NetworkHandler::IsInitialized()); | |
181 chromeos::NetworkHandler::Get()->network_state_handler()->RemoveObserver( | |
182 this, FROM_HERE); | |
183 } | |
184 | |
185 void AuthPolicyCredentialsManager::UpdateDisplayAndGivenName( | |
186 const authpolicy::ActiveDirectoryAccountInfo& account_info) { | |
187 if (display_name_ == account_info.display_name() && | |
188 given_name_ == account_info.given_name()) { | |
189 return; | |
190 } | |
191 display_name_ = account_info.display_name(); | |
192 given_name_ = account_info.given_name(); | |
193 user_manager::UserManager::Get()->UpdateUserAccountData( | |
194 account_id_, | |
195 user_manager::UserManager::UserAccountData( | |
196 base::UTF8ToUTF16(display_name_), base::UTF8ToUTF16(given_name_), | |
197 std::string() /* locale */)); | |
198 } | |
199 | |
200 void AuthPolicyCredentialsManager::ShowNotification(int message_id) { | |
201 user_manager::UserManager::Get()->SaveForceOnlineSignin(account_id_, true); | |
202 | |
203 if (shown_notifications_.count(message_id) > 0) | |
204 return; | |
205 | |
206 message_center::RichNotificationData data; | |
207 data.buttons.push_back(message_center::ButtonInfo( | |
208 l10n_util::GetStringUTF16(IDS_SYNC_RELOGIN_LINK_LABEL))); | |
209 | |
210 const std::string notification_id = kProfileSigninNotificationId + | |
211 profile_->GetProfileUserName() + | |
212 std::to_string(message_id); | |
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( | |
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 // Add the notification. | |
238 notification_ui_manager->Add(notification, profile_); | |
239 shown_notifications_.insert(message_id); | |
240 } | |
241 | |
242 void AuthPolicyCredentialsManager::GetUserStatusIfConnected( | |
243 const chromeos::NetworkState* network) { | |
244 if (!network || !network->IsConnectedState()) | |
245 return; | |
246 if (weak_factory_.HasWeakPtrs()) { | |
247 // Another call is in progress. | |
248 rerun_get_status_on_error_ = true; | |
249 return; | |
250 } | |
251 if (last_error_ != authpolicy::ERROR_NONE) | |
252 GetUserStatus(); | |
253 } | |
254 | |
255 // static | |
256 AuthPolicyCredentialsManagerFactory* | |
257 AuthPolicyCredentialsManagerFactory::GetInstance() { | |
258 return base::Singleton<AuthPolicyCredentialsManagerFactory>::get(); | |
259 } | |
260 | |
261 // static | |
262 void AuthPolicyCredentialsManagerFactory::BuildForProfileIfActiveDirectory( | |
263 Profile* profile) { | |
264 const user_manager::User* user = | |
265 chromeos::ProfileHelper::Get()->GetUserByProfile(profile); | |
266 if (!user || !user->IsActiveDirectoryUser()) | |
267 return; | |
268 GetInstance()->GetServiceForBrowserContext(profile, true /* create */); | |
269 } | |
270 | |
271 AuthPolicyCredentialsManagerFactory::AuthPolicyCredentialsManagerFactory() | |
272 : BrowserContextKeyedServiceFactory( | |
273 "AuthPolicyCredentialsManager", | |
274 BrowserContextDependencyManager::GetInstance()) {} | |
275 | |
276 AuthPolicyCredentialsManagerFactory::~AuthPolicyCredentialsManagerFactory() {} | |
277 | |
278 KeyedService* AuthPolicyCredentialsManagerFactory::BuildServiceInstanceFor( | |
279 content::BrowserContext* context) const { | |
280 Profile* profile = Profile::FromBrowserContext(context); | |
281 return new AuthPolicyCredentialsManager(profile); | |
282 } | |
OLD | NEW |