1 // Copyright 2013 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/multi_user/multi_user_context_menu.h"
6
7 #include "ash/public/cpp/multi_user_window_manager.h"
8 #include "base/bind.h"
9 #include "base/callback.h"
10 #include "base/macros.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "chrome/app/chrome_command_ids.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/profiles/profile_manager.h"
15 #include "chrome/browser/ui/ash/multi_user/multi_user_util.h"
16 #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager_helper.h"
17 #include "chrome/browser/ui/ash/session_controller_client_impl.h"
18 #include "chrome/browser/ui/browser_dialogs.h"
19 #include "chrome/common/pref_names.h"
20 #include "chrome/grit/generated_resources.h"
21 #include "components/account_id/account_id.h"
22 #include "components/prefs/pref_service.h"
23 #include "components/user_manager/user.h"
24 #include "components/user_manager/user_manager.h"
25 #include "ui/aura/window.h"
26 #include "ui/base/l10n/l10n_util.h"
27 #include "ui/base/models/simple_menu_model.h"
28
29 namespace {
30
31 class MultiUserContextMenuChromeos : public ui::SimpleMenuModel,
32 public ui::SimpleMenuModel::Delegate {
33 public:
34 explicit MultiUserContextMenuChromeos(aura::Window* window);
~MultiUserContextMenuChromeos()35 ~MultiUserContextMenuChromeos() override {}
36
37 // SimpleMenuModel::Delegate:
IsCommandIdChecked(int command_id) const38 bool IsCommandIdChecked(int command_id) const override { return false; }
IsCommandIdEnabled(int command_id) const39 bool IsCommandIdEnabled(int command_id) const override { return true; }
40 void ExecuteCommand(int command_id, int event_flags) override;
41
42 private:
43 // The window for which this menu is.
44 aura::Window* window_;
45
46 DISALLOW_COPY_AND_ASSIGN(MultiUserContextMenuChromeos);
47 };
48
MultiUserContextMenuChromeos(aura::Window * window)49 MultiUserContextMenuChromeos::MultiUserContextMenuChromeos(aura::Window* window)
50 : ui::SimpleMenuModel(this), window_(window) {}
51
ExecuteCommand(int command_id,int event_flags)52 void MultiUserContextMenuChromeos::ExecuteCommand(int command_id,
53 int event_flags) {
54 ExecuteVisitDesktopCommand(command_id, window_);
55 }
56
OnAcceptTeleportWarning(const AccountId & account_id,aura::Window * window_,bool accepted,bool no_show_again)57 void OnAcceptTeleportWarning(const AccountId& account_id,
58 aura::Window* window_,
59 bool accepted,
60 bool no_show_again) {
61 if (!accepted)
62 return;
63
64 PrefService* pref = ProfileManager::GetActiveUserProfile()->GetPrefs();
65 pref->SetBoolean(prefs::kMultiProfileWarningShowDismissed, no_show_again);
66
67 MultiUserWindowManagerHelper::GetWindowManager()->ShowWindowForUser(
68 window_, account_id);
69 }
70
71 } // namespace
72
CreateMultiUserContextMenu(aura::Window * window)73 std::unique_ptr<ui::MenuModel> CreateMultiUserContextMenu(
74 aura::Window* window) {
75 std::unique_ptr<ui::MenuModel> model;
76 const user_manager::UserList logged_in_users =
77 user_manager::UserManager::Get()->GetLRULoggedInUsers();
78
79 if (logged_in_users.size() > 1u) {
80 // If this window is not owned, we don't show the menu addition.
81 auto* window_manager = MultiUserWindowManagerHelper::GetWindowManager();
82 const AccountId& account_id = window_manager->GetWindowOwner(window);
83 if (!account_id.is_valid() || !window)
84 return model;
85 auto* menu = new MultiUserContextMenuChromeos(window);
86 model.reset(menu);
87 int command_id = IDC_VISIT_DESKTOP_OF_LRU_USER_NEXT;
88 for (size_t user_index = 1; user_index < logged_in_users.size();
89 ++user_index) {
90 if (command_id > IDC_VISIT_DESKTOP_OF_LRU_USER_LAST) {
91 break;
92 }
93 const user_manager::UserInfo* user_info = logged_in_users[user_index];
94 menu->AddItem(
95 command_id,
96 l10n_util::GetStringFUTF16(
97 IDS_VISIT_DESKTOP_OF_LRU_USER, user_info->GetDisplayName(),
98 base::ASCIIToUTF16(user_info->GetDisplayEmail())));
99 ++command_id;
100 }
101 }
102 return model;
103 }
104
ExecuteVisitDesktopCommand(int command_id,aura::Window * window)105 void ExecuteVisitDesktopCommand(int command_id, aura::Window* window) {
106 switch (command_id) {
107 case IDC_VISIT_DESKTOP_OF_LRU_USER_2:
108 case IDC_VISIT_DESKTOP_OF_LRU_USER_3:
109 case IDC_VISIT_DESKTOP_OF_LRU_USER_4:
110 case IDC_VISIT_DESKTOP_OF_LRU_USER_5: {
111 const user_manager::UserList logged_in_users =
112 user_manager::UserManager::Get()->GetLRULoggedInUsers();
113 // When running the multi user mode on Chrome OS, windows can "visit"
114 // another user's desktop.
115 const AccountId account_id =
116 logged_in_users[command_id - IDC_VISIT_DESKTOP_OF_LRU_USER_NEXT + 1]
117 ->GetAccountId();
118 base::OnceCallback<void(bool, bool)> on_accept =
119 base::BindOnce(&OnAcceptTeleportWarning, account_id, window);
120
121 // Don't show warning dialog if any logged in user in multi-profiles
122 // session dismissed it.
123 for (user_manager::UserList::const_iterator it = logged_in_users.begin();
124 it != logged_in_users.end(); ++it) {
125 if (multi_user_util::GetProfileFromAccountId((*it)->GetAccountId())
126 ->GetPrefs()
127 ->GetBoolean(prefs::kMultiProfileWarningShowDismissed)) {
128 bool active_user_show_option =
129 ProfileManager::GetActiveUserProfile()->GetPrefs()->GetBoolean(
130 prefs::kMultiProfileWarningShowDismissed);
131 std::move(on_accept).Run(true, active_user_show_option);
132 return;
133 }
134 }
135
136 SessionControllerClientImpl::Get()->ShowTeleportWarningDialog(
137 std::move(on_accept));
138 return;
139 }
140 default:
141 NOTREACHED();
142 }
143 }
144