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

Unified 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/ui/ash/session_controller_client.cc
diff --git a/chrome/browser/ui/ash/session_controller_client.cc b/chrome/browser/ui/ash/session_controller_client.cc
new file mode 100644
index 0000000000000000000000000000000000000000..01eae177fd25f9a815b70d55de7a6235a1304103
--- /dev/null
+++ b/chrome/browser/ui/ash/session_controller_client.cc
@@ -0,0 +1,268 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/ash/session_controller_client.h"
+
+#include <algorithm>
+#include <utility>
+
+#include "ash/public/cpp/session_types.h"
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/chromeos/login/users/multi_profile_user_controller.h"
+#include "chrome/browser/chromeos/profiles/profile_helper.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/ash/ash_util.h"
+#include "chrome/browser/ui/ash/multi_user/user_switch_util.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/grit/theme_resources.h"
+#include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/session_manager_client.h"
+#include "components/prefs/pref_service.h"
+#include "components/session_manager/core/session_manager.h"
+#include "content/public/common/service_manager_connection.h"
+#include "content/public/common/service_names.mojom.h"
+#include "services/service_manager/public/cpp/connector.h"
+#include "ui/base/resource/resource_bundle.h"
+
+namespace {
+
+// Limits the number of logged in users to 10 due to memory constraints.
+constexpr uint32_t kMaxUsers = 10;
+
+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.
+
+std::vector<ash::mojom::UserSessionPtr> GetUserSessions() {
+ user_manager::UserManager* const user_manager =
+ user_manager::UserManager::Get();
+
+ std::vector<ash::mojom::UserSessionPtr> sessions;
+ for (auto* user : user_manager->GetLRULoggedInUsers()) {
+ ash::mojom::UserSessionPtr session = ash::mojom::UserSession::New();
+ session->type = user->GetType();
+ // TODO(xiyuan): Add type map for AccountId.
+ session->account_id = user->GetAccountId().Serialize();
+ session->display_name = base::UTF16ToUTF8(user->display_name());
+ session->display_email = user->display_email();
+
+ // TODO(xiyuan): Observe user image change and update.
+ // Tracked in http://crbug.com/670422
+ // TODO(xiyuan): Support multiple scale factor.
+ session->avatar = *user->GetImage().bitmap();
+ if (session->avatar.isNull()) {
+ session->avatar = *ResourceBundle::GetSharedInstance()
+ .GetImageSkiaNamed(IDR_PROFILE_PICTURE_LOADING)
+ ->bitmap();
+ }
+
+ sessions.push_back(std::move(session));
+ }
+ return sessions;
+}
+
+void DoSwitchUser(const AccountId& account_id) {
+ user_manager::UserManager::Get()->SwitchActiveUser(account_id);
+}
+
+} // namespace
+
+SessionControllerClient::SessionControllerClient() : binding_(this) {
+ DCHECK(!instance);
+ instance = this;
+
+ session_manager::SessionManager::Get()->AddObserver(this);
+ user_manager::UserManager::Get()->AddSessionStateObserver(this);
+
+ SendSessionInfo();
+}
+
+SessionControllerClient::~SessionControllerClient() {
+ DCHECK_EQ(this, instance);
+ instance = nullptr;
+
+ session_manager::SessionManager::Get()->RemoveObserver(this);
+ user_manager::UserManager::Get()->RemoveSessionStateObserver(this);
+}
+
+SessionControllerClient* SessionControllerClient::Get() {
+ return instance;
+}
+
+void SessionControllerClient::RequestLockScreen() {
+ DoLockScreen();
+}
+
+void SessionControllerClient::SwitchActiveUser(
+ const std::string& serialized_account_id) {
+ // TODO(xiyuan): Add type map for AccountId.
+ AccountId account_id(EmptyAccountId());
+ if (!AccountId::Deserialize(serialized_account_id, &account_id)) {
+ LOG(ERROR) << "Bad account id for SwitchActiveUser.";
+ return;
+ }
+
+ DoSwitchActiveUser(account_id);
+}
+
+void SessionControllerClient::CycleActiveUser(bool next_user) {
+ DoCycleActiveUser(next_user);
+}
+
+void SessionControllerClient::ActiveUserChanged(
+ const user_manager::User* active_user) {
+ SendSessionInfo();
+}
+
+void SessionControllerClient::UserAddedToSession(
+ const user_manager::User* added_user) {
+ SendSessionInfo();
+}
+
+// static
+bool SessionControllerClient::CanLockScreen() {
+ return !user_manager::UserManager::Get()->GetUnlockUsers().empty();
+}
+
+// static
+bool SessionControllerClient::ShouldLockScreenAutomatically() {
+ // TODO(xiyuan): Observe prefs::kEnableAutoScreenLock and update ash.
+ // Tracked in http://crbug.com/670423
+ const user_manager::UserList logged_in_users =
+ user_manager::UserManager::Get()->GetLoggedInUsers();
+ for (auto* user : logged_in_users) {
+ Profile* profile = chromeos::ProfileHelper::Get()->GetProfileByUser(user);
+ if (profile &&
+ profile->GetPrefs()->GetBoolean(prefs::kEnableAutoScreenLock)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+// static
+ash::AddUserSessionPolicy SessionControllerClient::GetAddUserSessionPolicy() {
+ 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
+ user_manager::UserManager::Get();
+ if (user_manager->GetUsersAllowedForMultiProfile().empty())
+ return ash::AddUserSessionPolicy::ERROR_NO_ELIGIBLE_USERS;
+
+ if (chromeos::MultiProfileUserController::GetPrimaryUserPolicy() !=
+ chromeos::MultiProfileUserController::ALLOWED) {
+ return ash::AddUserSessionPolicy::ERROR_NOT_ALLOWED_PRIMARY_USER;
+ }
+
+ if (user_manager::UserManager::Get()->GetLoggedInUsers().size() >= kMaxUsers)
+ return ash::AddUserSessionPolicy::ERROR_MAXIMUM_USERS_REACHED;
+
+ return ash::AddUserSessionPolicy::ALLOWED;
+}
+
+// static
+void SessionControllerClient::DoLockScreen() {
+ if (!CanLockScreen())
+ return;
+
+ VLOG(1) << "Requesting screen lock from SessionControllerClient";
+ chromeos::DBusThreadManager::Get()
+ ->GetSessionManagerClient()
+ ->RequestLockScreen();
+}
+
+// static
+void SessionControllerClient::DoSwitchActiveUser(const AccountId& account_id) {
+ // Disallow switching to an already active user since that might crash.
+ // Also check that we got a user id and not an email address.
+ DCHECK_EQ(
+ account_id.GetUserEmail(),
+ gaia::CanonicalizeEmail(gaia::SanitizeEmail(account_id.GetUserEmail())));
+ if (account_id ==
+ user_manager::UserManager::Get()->GetActiveUser()->GetAccountId()) {
+ return;
+ }
+
+ TrySwitchingActiveUser(base::Bind(&DoSwitchUser, account_id));
+}
+
+// static
+void SessionControllerClient::DoCycleActiveUser(bool next_user) {
+ const user_manager::UserList& logged_in_users =
+ user_manager::UserManager::Get()->GetLoggedInUsers();
+ if (logged_in_users.size() <= 1)
+ return;
+
+ AccountId account_id =
+ user_manager::UserManager::Get()->GetActiveUser()->GetAccountId();
+
+ // Get an iterator positioned at the active user.
+ auto it = std::find_if(logged_in_users.begin(), logged_in_users.end(),
+ [account_id](const user_manager::User* user) {
+ return user->GetAccountId() == account_id;
+ });
+
+ // Active user not found.
+ if (it == logged_in_users.end())
+ return;
+
+ // Get the user's email to select, wrapping to the start/end of the list if
+ // necessary.
+ if (next_user) {
+ if (++it == logged_in_users.end())
+ account_id = (*logged_in_users.begin())->GetAccountId();
+ else
+ account_id = (*it)->GetAccountId();
+ } else {
+ if (it == logged_in_users.begin())
+ it = logged_in_users.end();
+ account_id = (*(--it))->GetAccountId();
+ }
+
+ DoSwitchActiveUser(account_id);
+}
+
+void SessionControllerClient::OnSessionStateChanged() {
+ SendSessionInfo();
+}
+
+void SessionControllerClient::ConnectToSessionControllerAndSetClient() {
+ if (session_controller_.is_bound())
+ return;
+
+ service_manager::Connector* connector =
+ content::ServiceManagerConnection::GetForProcess()->GetConnector();
+
+ // Under mash the SessionController interface is in the ash process. In
+ // classic ash we provide it to ourself.
+ if (chrome::IsRunningInMash()) {
+ connector->ConnectToInterface("ash", &session_controller_);
+ } else {
+ connector->ConnectToInterface(content::mojom::kBrowserServiceName,
+ &session_controller_);
+ }
+
+ // 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.
+ session_controller_.set_connection_error_handler(
+ base::Bind(&SessionControllerClient::OnClientConnectionError,
+ base::Unretained(this)));
+
+ // Set as |session_controller_|'s client.
+ session_controller_->SetClient(binding_.CreateInterfacePtrAndBind());
+}
+
+void SessionControllerClient::OnClientConnectionError() {
+ session_controller_.reset();
+}
+
+void SessionControllerClient::SendSessionInfo() {
+ ConnectToSessionControllerAndSetClient();
+
+ session_controller_->SetMaxUsers(kMaxUsers);
+ session_controller_->SetSessionState(
+ session_manager::SessionManager::Get()->session_state());
+ session_controller_->SetCanLockScreen(CanLockScreen());
+ session_controller_->SetShouldLockScreenAutomatically(
+ ShouldLockScreenAutomatically());
+ session_controller_->SetAddUserSessionPolicy(GetAddUserSessionPolicy());
+ 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
+}

Powered by Google App Engine
This is Rietveld 408576698