Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(358)

Side by Side Diff: chrome/browser/ui/ash/session_controller_client.cc

Issue 2545723003: ash: Add SessionController/Client mojo interfaces (Closed)
Patch Set: use a default to fix null avatar image failures Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698