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 "ui/base/l10n/l10n_util.h" | |
27 #include "ui/base/resource/resource_bundle.h" | |
28 | |
29 namespace { | |
30 | |
31 constexpr base::TimeDelta kGetUserStatusCallsInterval = | |
32 base::TimeDelta::FromHours(1); | |
33 const char kProfileSigninNotificationId[] = "chrome://settings/signin/"; | |
34 | |
35 // A notification delegate for the sign-out button. | |
36 class SigninNotificationDelegate : public NotificationDelegate { | |
37 public: | |
38 explicit SigninNotificationDelegate(const std::string& id); | |
39 | |
40 // NotificationDelegate: | |
41 void Click() override; | |
42 void ButtonClick(int button_index) override; | |
43 std::string id() const override; | |
44 | |
45 protected: | |
46 ~SigninNotificationDelegate() override = default; | |
47 | |
48 private: | |
49 // Unique id of the notification. | |
50 const std::string id_; | |
51 | |
52 DISALLOW_COPY_AND_ASSIGN(SigninNotificationDelegate); | |
53 }; | |
54 | |
55 SigninNotificationDelegate::SigninNotificationDelegate(const std::string& id) | |
56 : id_(id) {} | |
57 | |
58 void SigninNotificationDelegate::Click() { | |
59 chrome::AttemptUserExit(); | |
60 } | |
61 | |
62 void SigninNotificationDelegate::ButtonClick(int button_index) { | |
63 chrome::AttemptUserExit(); | |
64 } | |
65 | |
66 std::string SigninNotificationDelegate::id() const { | |
67 return id_; | |
68 } | |
69 | |
70 } // namespace | |
71 | |
72 AuthPolicyCredentialsManager::AuthPolicyCredentialsManager(Profile* profile) | |
73 : profile_(profile) { | |
74 const user_manager::User* user = | |
75 chromeos::ProfileHelper::Get()->GetUserByProfile(profile); | |
76 CHECK(user && user->IsActiveDirectoryUser()); | |
77 StartObserveNetwork(); | |
78 account_id_ = user->GetAccountId(); | |
79 GetUserStatus(); | |
80 } | |
81 | |
82 AuthPolicyCredentialsManager::~AuthPolicyCredentialsManager() {} | |
83 | |
84 void AuthPolicyCredentialsManager::Shutdown() { | |
85 StopObserveNetwork(); | |
xiyuan
2017/05/30 17:32:58
What if this is called after OnShuttingDown() is c
Roman Sorokin (ftl)
2017/05/31 15:37:10
Done.
| |
86 } | |
87 | |
88 void AuthPolicyCredentialsManager::DefaultNetworkChanged( | |
89 const chromeos::NetworkState* network) { | |
90 GetUserStatusIfConnected(network); | |
91 } | |
92 | |
93 void AuthPolicyCredentialsManager::NetworkConnectionStateChanged( | |
94 const chromeos::NetworkState* network) { | |
95 GetUserStatusIfConnected(network); | |
96 } | |
97 | |
98 void AuthPolicyCredentialsManager::OnShuttingDown() { | |
99 StopObserveNetwork(); | |
100 } | |
101 | |
102 void AuthPolicyCredentialsManager::GetUserStatus() { | |
103 DCHECK(!weak_factory_.HasWeakPtrs()); | |
104 rerun_get_status_on_error_ = false; | |
105 scheduled_get_user_status_call_.Cancel(); | |
106 chromeos::DBusThreadManager::Get()->GetAuthPolicyClient()->GetUserStatus( | |
107 account_id_.GetObjGuid(), | |
108 base::BindOnce(&AuthPolicyCredentialsManager::OnGetUserStatusCallback, | |
109 weak_factory_.GetWeakPtr())); | |
110 } | |
111 | |
112 void AuthPolicyCredentialsManager::OnGetUserStatusCallback( | |
113 authpolicy::ErrorType error, | |
114 const authpolicy::ActiveDirectoryUserStatus& user_status) { | |
115 DCHECK(weak_factory_.HasWeakPtrs()); | |
116 ScheduleGetUserStatus(); | |
117 last_error_ = error; | |
118 if (error != authpolicy::ERROR_NONE) { | |
119 DLOG(ERROR) << "GetUserStatus failed with " << error; | |
120 if (rerun_get_status_on_error_) { | |
121 rerun_get_status_on_error_ = false; | |
122 GetUserStatus(); | |
123 } | |
124 return; | |
125 } | |
126 CHECK(user_status.account_info().account_id() == account_id_.GetObjGuid()); | |
127 rerun_get_status_on_error_ = false; | |
128 if (user_status.has_account_info()) | |
129 UpdateDisplayAndGivenName(user_status.account_info()); | |
130 | |
131 DCHECK(user_status.has_password_status()); | |
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()); | |
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 // Unretained is safe here because it is a CancelableClosure and owned by this | |
160 // object. | |
161 scheduled_get_user_status_call_.Reset(base::Bind( | |
162 &AuthPolicyCredentialsManager::GetUserStatus, base::Unretained(this))); | |
163 // TODO(rsorokin): This does not re-schedule after wake from sleep | |
164 // (and thus the maximal interval between two calls can be (sleep time + | |
165 // kGetUserStatusCallsInterval)) (see crbug.com/726672). | |
166 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | |
167 FROM_HERE, scheduled_get_user_status_call_.callback(), | |
168 kGetUserStatusCallsInterval); | |
169 } | |
170 | |
171 void AuthPolicyCredentialsManager::StartObserveNetwork() { | |
172 DCHECK(chromeos::NetworkHandler::IsInitialized()); | |
173 chromeos::NetworkHandler::Get()->network_state_handler()->AddObserver( | |
174 this, FROM_HERE); | |
175 } | |
176 | |
177 void AuthPolicyCredentialsManager::StopObserveNetwork() { | |
178 DCHECK(chromeos::NetworkHandler::IsInitialized()); | |
179 chromeos::NetworkHandler::Get()->network_state_handler()->RemoveObserver( | |
180 this, FROM_HERE); | |
181 } | |
182 | |
183 void AuthPolicyCredentialsManager::UpdateDisplayAndGivenName( | |
184 const authpolicy::ActiveDirectoryAccountInfo& account_info) { | |
185 if (display_name_ == account_info.display_name() && | |
186 given_name_ == account_info.given_name()) { | |
187 return; | |
188 } | |
189 display_name_ = account_info.display_name(); | |
190 given_name_ = account_info.given_name(); | |
191 user_manager::UserManager::Get()->UpdateUserAccountData( | |
192 account_id_, | |
193 user_manager::UserManager::UserAccountData( | |
194 base::UTF8ToUTF16(display_name_), base::UTF8ToUTF16(given_name_), | |
195 std::string() /* locale */)); | |
196 } | |
197 | |
198 void AuthPolicyCredentialsManager::ShowNotification(int message_id) { | |
199 user_manager::UserManager::Get()->SaveForceOnlineSignin(account_id_, true); | |
200 | |
201 if (shown_notifications_.count(message_id) > 0) | |
202 return; | |
203 | |
204 message_center::RichNotificationData data; | |
205 data.buttons.push_back(message_center::ButtonInfo( | |
206 l10n_util::GetStringUTF16(IDS_SYNC_RELOGIN_LINK_LABEL))); | |
207 | |
208 const std::string notification_id = kProfileSigninNotificationId + | |
209 profile_->GetProfileUserName() + | |
210 std::to_string(message_id); | |
211 // Set the delegate for the notification's sign-out button. | |
212 SigninNotificationDelegate* delegate = | |
213 new SigninNotificationDelegate(notification_id); | |
214 | |
215 message_center::NotifierId notifier_id( | |
216 message_center::NotifierId::SYSTEM_COMPONENT, | |
217 kProfileSigninNotificationId); | |
218 | |
219 // Set |profile_id| for multi-user notification blocker. | |
220 notifier_id.profile_id = profile_->GetProfileUserName(); | |
221 | |
222 Notification notification( | |
223 message_center::NOTIFICATION_TYPE_SIMPLE, | |
224 l10n_util::GetStringUTF16(IDS_SIGNIN_ERROR_BUBBLE_VIEW_TITLE), | |
225 l10n_util::GetStringUTF16(message_id), | |
226 ui::ResourceBundle::GetSharedInstance().GetImageNamed( | |
227 IDR_NOTIFICATION_ALERT), | |
228 notifier_id, | |
229 base::string16(), // display_source | |
230 GURL(notification_id), notification_id, data, delegate); | |
231 notification.SetSystemPriority(); | |
232 | |
233 NotificationUIManager* notification_ui_manager = | |
234 g_browser_process->notification_ui_manager(); | |
235 // Add the notification. | |
236 notification_ui_manager->Add(notification, profile_); | |
237 shown_notifications_.insert(message_id); | |
238 } | |
239 | |
240 void AuthPolicyCredentialsManager::GetUserStatusIfConnected( | |
241 const chromeos::NetworkState* network) { | |
242 if (!network || !network->IsConnectedState()) | |
243 return; | |
244 if (weak_factory_.HasWeakPtrs()) { | |
245 // Another call is in progress. | |
246 rerun_get_status_on_error_ = true; | |
247 return; | |
248 } | |
249 if (last_error_ != authpolicy::ERROR_NONE) | |
250 GetUserStatus(); | |
251 } | |
252 | |
253 // static | |
254 AuthPolicyCredentialsManagerFactory* | |
255 AuthPolicyCredentialsManagerFactory::GetInstance() { | |
256 return base::Singleton<AuthPolicyCredentialsManagerFactory>::get(); | |
257 } | |
258 | |
259 // static | |
260 void AuthPolicyCredentialsManagerFactory::BuildForProfileIfActiveDirectory( | |
261 Profile* profile) { | |
262 const user_manager::User* user = | |
263 chromeos::ProfileHelper::Get()->GetUserByProfile(profile); | |
264 if (!user || !user->IsActiveDirectoryUser()) | |
265 return; | |
266 GetInstance()->GetServiceForBrowserContext(profile, true /* create */); | |
267 } | |
268 | |
269 AuthPolicyCredentialsManagerFactory::AuthPolicyCredentialsManagerFactory() | |
270 : BrowserContextKeyedServiceFactory( | |
271 "AuthPolicyCredentialsManager", | |
272 BrowserContextDependencyManager::GetInstance()) {} | |
273 | |
274 AuthPolicyCredentialsManagerFactory::~AuthPolicyCredentialsManagerFactory() {} | |
275 | |
276 KeyedService* AuthPolicyCredentialsManagerFactory::BuildServiceInstanceFor( | |
277 content::BrowserContext* context) const { | |
278 Profile* profile = Profile::FromBrowserContext(context); | |
279 return new AuthPolicyCredentialsManager(profile); | |
280 } | |
OLD | NEW |