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