OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2016 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/ui/ash/session_controller_client.h" | |
6 | |
7 #include <algorithm> | |
8 #include <utility> | |
9 | |
10 #include "ash/public/cpp/session_types.h" | |
11 #include "base/bind.h" | |
12 #include "base/logging.h" | |
13 #include "base/strings/utf_string_conversions.h" | |
14 #include "chrome/browser/chromeos/login/users/multi_profile_user_controller.h" | |
15 #include "chrome/browser/chromeos/profiles/profile_helper.h" | |
16 #include "chrome/browser/profiles/profile.h" | |
17 #include "chrome/browser/ui/ash/ash_util.h" | |
18 #include "chrome/browser/ui/ash/multi_user/user_switch_util.h" | |
19 #include "chrome/common/pref_names.h" | |
20 #include "chrome/grit/theme_resources.h" | |
21 #include "chromeos/dbus/dbus_thread_manager.h" | |
22 #include "chromeos/dbus/session_manager_client.h" | |
23 #include "components/prefs/pref_service.h" | |
24 #include "components/session_manager/core/session_manager.h" | |
25 #include "content/public/common/service_manager_connection.h" | |
26 #include "content/public/common/service_names.mojom.h" | |
27 #include "services/service_manager/public/cpp/connector.h" | |
28 #include "ui/base/resource/resource_bundle.h" | |
29 | |
30 namespace { | |
31 | |
32 // Limits the number of logged in users to 10 due to memory constraints. | |
33 constexpr uint32_t kMaxUsers = 10; | |
34 | |
35 SessionControllerClient* instance = nullptr; | |
James Cook
2016/12/01 23:01:44
nit: I like g_instance for these.
xiyuan
2016/12/06 00:46:34
No longer needed and removed.
| |
36 | |
37 std::vector<ash::mojom::UserSessionPtr> GetUserSessions() { | |
38 user_manager::UserManager* const user_manager = | |
39 user_manager::UserManager::Get(); | |
40 | |
41 std::vector<ash::mojom::UserSessionPtr> sessions; | |
42 for (auto* user : user_manager->GetLRULoggedInUsers()) { | |
43 ash::mojom::UserSessionPtr session = ash::mojom::UserSession::New(); | |
44 session->type = user->GetType(); | |
45 // TODO(xiyuan): Add type map for AccountId. | |
46 session->account_id = user->GetAccountId().Serialize(); | |
47 session->display_name = base::UTF16ToUTF8(user->display_name()); | |
48 session->display_email = user->display_email(); | |
49 | |
50 // TODO(xiyuan): Observe user image change and update. | |
51 // Tracked in http://crbug.com/670422 | |
52 // TODO(xiyuan): Support multiple scale factor. | |
53 session->avatar = *user->GetImage().bitmap(); | |
54 if (session->avatar.isNull()) { | |
55 session->avatar = *ResourceBundle::GetSharedInstance() | |
56 .GetImageSkiaNamed(IDR_PROFILE_PICTURE_LOADING) | |
57 ->bitmap(); | |
58 } | |
59 | |
60 sessions.push_back(std::move(session)); | |
61 } | |
62 return sessions; | |
63 } | |
64 | |
65 void DoSwitchUser(const AccountId& account_id) { | |
66 user_manager::UserManager::Get()->SwitchActiveUser(account_id); | |
67 } | |
68 | |
69 } // namespace | |
70 | |
71 SessionControllerClient::SessionControllerClient() : binding_(this) { | |
72 DCHECK(!instance); | |
73 instance = this; | |
74 | |
75 session_manager::SessionManager::Get()->AddObserver(this); | |
76 user_manager::UserManager::Get()->AddSessionStateObserver(this); | |
77 | |
78 SendSessionInfo(); | |
79 } | |
80 | |
81 SessionControllerClient::~SessionControllerClient() { | |
82 DCHECK_EQ(this, instance); | |
83 instance = nullptr; | |
84 | |
85 session_manager::SessionManager::Get()->RemoveObserver(this); | |
86 user_manager::UserManager::Get()->RemoveSessionStateObserver(this); | |
87 } | |
88 | |
89 SessionControllerClient* SessionControllerClient::Get() { | |
90 return instance; | |
91 } | |
92 | |
93 void SessionControllerClient::RequestLockScreen() { | |
94 DoLockScreen(); | |
95 } | |
96 | |
97 void SessionControllerClient::SwitchActiveUser( | |
98 const std::string& serialized_account_id) { | |
99 // TODO(xiyuan): Add type map for AccountId. | |
100 AccountId account_id(EmptyAccountId()); | |
101 if (!AccountId::Deserialize(serialized_account_id, &account_id)) { | |
102 LOG(ERROR) << "Bad account id for SwitchActiveUser."; | |
103 return; | |
104 } | |
105 | |
106 DoSwitchActiveUser(account_id); | |
107 } | |
108 | |
109 void SessionControllerClient::CycleActiveUser(bool next_user) { | |
110 DoCycleActiveUser(next_user); | |
111 } | |
112 | |
113 void SessionControllerClient::ActiveUserChanged( | |
114 const user_manager::User* active_user) { | |
115 SendSessionInfo(); | |
116 } | |
117 | |
118 void SessionControllerClient::UserAddedToSession( | |
119 const user_manager::User* added_user) { | |
120 SendSessionInfo(); | |
121 } | |
122 | |
123 // static | |
124 bool SessionControllerClient::CanLockScreen() { | |
125 return !user_manager::UserManager::Get()->GetUnlockUsers().empty(); | |
126 } | |
127 | |
128 // static | |
129 bool SessionControllerClient::ShouldLockScreenAutomatically() { | |
130 // TODO(xiyuan): Observe prefs::kEnableAutoScreenLock and update ash. | |
131 // Tracked in http://crbug.com/670423 | |
132 const user_manager::UserList logged_in_users = | |
133 user_manager::UserManager::Get()->GetLoggedInUsers(); | |
134 for (auto* user : logged_in_users) { | |
135 Profile* profile = chromeos::ProfileHelper::Get()->GetProfileByUser(user); | |
136 if (profile && | |
137 profile->GetPrefs()->GetBoolean(prefs::kEnableAutoScreenLock)) { | |
138 return true; | |
139 } | |
140 } | |
141 return false; | |
142 } | |
143 | |
144 // static | |
145 ash::AddUserSessionPolicy SessionControllerClient::GetAddUserSessionPolicy() { | |
146 user_manager::UserManager* const user_manager = | |
James Cook
2016/12/01 23:01:44
optional: Feel free to add "using user_manager::Us
xiyuan
2016/12/06 00:46:34
Done. And using user_manager::UserList and User as
| |
147 user_manager::UserManager::Get(); | |
148 if (user_manager->GetUsersAllowedForMultiProfile().empty()) | |
149 return ash::AddUserSessionPolicy::ERROR_NO_ELIGIBLE_USERS; | |
150 | |
151 if (chromeos::MultiProfileUserController::GetPrimaryUserPolicy() != | |
152 chromeos::MultiProfileUserController::ALLOWED) { | |
153 return ash::AddUserSessionPolicy::ERROR_NOT_ALLOWED_PRIMARY_USER; | |
154 } | |
155 | |
156 if (user_manager::UserManager::Get()->GetLoggedInUsers().size() >= kMaxUsers) | |
157 return ash::AddUserSessionPolicy::ERROR_MAXIMUM_USERS_REACHED; | |
158 | |
159 return ash::AddUserSessionPolicy::ALLOWED; | |
160 } | |
161 | |
162 // static | |
163 void SessionControllerClient::DoLockScreen() { | |
164 if (!CanLockScreen()) | |
165 return; | |
166 | |
167 VLOG(1) << "Requesting screen lock from SessionControllerClient"; | |
168 chromeos::DBusThreadManager::Get() | |
169 ->GetSessionManagerClient() | |
170 ->RequestLockScreen(); | |
171 } | |
172 | |
173 // static | |
174 void SessionControllerClient::DoSwitchActiveUser(const AccountId& account_id) { | |
175 // Disallow switching to an already active user since that might crash. | |
176 // Also check that we got a user id and not an email address. | |
177 DCHECK_EQ( | |
178 account_id.GetUserEmail(), | |
179 gaia::CanonicalizeEmail(gaia::SanitizeEmail(account_id.GetUserEmail()))); | |
180 if (account_id == | |
181 user_manager::UserManager::Get()->GetActiveUser()->GetAccountId()) { | |
182 return; | |
183 } | |
184 | |
185 TrySwitchingActiveUser(base::Bind(&DoSwitchUser, account_id)); | |
186 } | |
187 | |
188 // static | |
189 void SessionControllerClient::DoCycleActiveUser(bool next_user) { | |
190 const user_manager::UserList& logged_in_users = | |
191 user_manager::UserManager::Get()->GetLoggedInUsers(); | |
192 if (logged_in_users.size() <= 1) | |
193 return; | |
194 | |
195 AccountId account_id = | |
196 user_manager::UserManager::Get()->GetActiveUser()->GetAccountId(); | |
197 | |
198 // Get an iterator positioned at the active user. | |
199 auto it = std::find_if(logged_in_users.begin(), logged_in_users.end(), | |
200 [account_id](const user_manager::User* user) { | |
201 return user->GetAccountId() == account_id; | |
202 }); | |
203 | |
204 // Active user not found. | |
205 if (it == logged_in_users.end()) | |
206 return; | |
207 | |
208 // Get the user's email to select, wrapping to the start/end of the list if | |
209 // necessary. | |
210 if (next_user) { | |
211 if (++it == logged_in_users.end()) | |
212 account_id = (*logged_in_users.begin())->GetAccountId(); | |
213 else | |
214 account_id = (*it)->GetAccountId(); | |
215 } else { | |
216 if (it == logged_in_users.begin()) | |
217 it = logged_in_users.end(); | |
218 account_id = (*(--it))->GetAccountId(); | |
219 } | |
220 | |
221 DoSwitchActiveUser(account_id); | |
222 } | |
223 | |
224 void SessionControllerClient::OnSessionStateChanged() { | |
225 SendSessionInfo(); | |
226 } | |
227 | |
228 void SessionControllerClient::ConnectToSessionControllerAndSetClient() { | |
229 if (session_controller_.is_bound()) | |
230 return; | |
231 | |
232 service_manager::Connector* connector = | |
233 content::ServiceManagerConnection::GetForProcess()->GetConnector(); | |
234 | |
235 // Under mash the SessionController interface is in the ash process. In | |
236 // classic ash we provide it to ourself. | |
237 if (chrome::IsRunningInMash()) { | |
238 connector->ConnectToInterface("ash", &session_controller_); | |
239 } else { | |
240 connector->ConnectToInterface(content::mojom::kBrowserServiceName, | |
241 &session_controller_); | |
242 } | |
243 | |
244 // Tolerate ash crashing and coming back up. | |
James Cook
2016/12/01 23:01:44
Aside: This is fine, but for version 1 (and maybe
xiyuan
2016/12/06 00:46:34
Removed.
| |
245 session_controller_.set_connection_error_handler( | |
246 base::Bind(&SessionControllerClient::OnClientConnectionError, | |
247 base::Unretained(this))); | |
248 | |
249 // Set as |session_controller_|'s client. | |
250 session_controller_->SetClient(binding_.CreateInterfacePtrAndBind()); | |
251 } | |
252 | |
253 void SessionControllerClient::OnClientConnectionError() { | |
254 session_controller_.reset(); | |
255 } | |
256 | |
257 void SessionControllerClient::SendSessionInfo() { | |
258 ConnectToSessionControllerAndSetClient(); | |
259 | |
260 session_controller_->SetMaxUsers(kMaxUsers); | |
261 session_controller_->SetSessionState( | |
262 session_manager::SessionManager::Get()->session_state()); | |
263 session_controller_->SetCanLockScreen(CanLockScreen()); | |
264 session_controller_->SetShouldLockScreenAutomatically( | |
265 ShouldLockScreenAutomatically()); | |
266 session_controller_->SetAddUserSessionPolicy(GetAddUserSessionPolicy()); | |
267 session_controller_->SetUserSessions(GetUserSessions()); | |
James Cook
2016/12/01 23:01:44
Hmm, that's a lot of IPCs for a single state chang
xiyuan
2016/12/06 00:46:34
Changed.
- Combined simple info into a SessionInfo
| |
268 } | |
OLD | NEW |