Home | History | Annotate | Download | only in frame
      1 // Copyright (c) 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/views/frame/system_menu_model_builder.h"
      6 
      7 #include "base/command_line.h"
      8 #include "base/strings/utf_string_conversions.h"
      9 #include "chrome/app/chrome_command_ids.h"
     10 #include "chrome/browser/ui/browser_commands.h"
     11 #include "chrome/browser/ui/host_desktop.h"
     12 #include "chrome/browser/ui/toolbar/wrench_menu_model.h"
     13 #include "chrome/common/chrome_switches.h"
     14 #include "grit/generated_resources.h"
     15 #include "ui/base/accelerators/accelerator.h"
     16 #include "ui/base/models/simple_menu_model.h"
     17 
     18 #if defined(OS_CHROMEOS)
     19 #include "ash/session/session_state_delegate.h"
     20 #include "ash/session/user_info.h"
     21 #include "ash/shell.h"
     22 #include "chrome/browser/ui/ash/multi_user/multi_user_util.h"
     23 #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h"
     24 #include "chrome/browser/ui/browser_window.h"
     25 #include "ui/base/l10n/l10n_util.h"
     26 #endif
     27 
     28 SystemMenuModelBuilder::SystemMenuModelBuilder(
     29     ui::AcceleratorProvider* provider,
     30     Browser* browser)
     31     : menu_delegate_(provider, browser) {
     32 }
     33 
     34 SystemMenuModelBuilder::~SystemMenuModelBuilder() {
     35 }
     36 
     37 void SystemMenuModelBuilder::Init() {
     38   ui::SimpleMenuModel* model = new ui::SimpleMenuModel(&menu_delegate_);
     39   menu_model_.reset(model);
     40   BuildMenu(model);
     41 #if defined(OS_WIN)
     42   // On Windows with HOST_DESKTOP_TYPE_NATIVE we put the menu items in the
     43   // system menu (not at the end). Doing this necessitates adding a trailing
     44   // separator.
     45   if (browser()->host_desktop_type() == chrome::HOST_DESKTOP_TYPE_NATIVE)
     46     model->AddSeparator(ui::NORMAL_SEPARATOR);
     47 #endif
     48 }
     49 
     50 void SystemMenuModelBuilder::BuildMenu(ui::SimpleMenuModel* model) {
     51   // We add the menu items in reverse order so that insertion_index never needs
     52   // to change.
     53   if (browser()->is_type_tabbed())
     54     BuildSystemMenuForBrowserWindow(model);
     55   else
     56     BuildSystemMenuForAppOrPopupWindow(model);
     57   AddFrameToggleItems(model);
     58 }
     59 
     60 void SystemMenuModelBuilder::BuildSystemMenuForBrowserWindow(
     61     ui::SimpleMenuModel* model) {
     62   model->AddItemWithStringId(IDC_NEW_TAB, IDS_NEW_TAB);
     63   model->AddItemWithStringId(IDC_RESTORE_TAB, IDS_RESTORE_TAB);
     64   if (chrome::CanOpenTaskManager()) {
     65     model->AddSeparator(ui::NORMAL_SEPARATOR);
     66     model->AddItemWithStringId(IDC_TASK_MANAGER, IDS_TASK_MANAGER);
     67   }
     68 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
     69   model->AddSeparator(ui::NORMAL_SEPARATOR);
     70   model->AddCheckItemWithStringId(IDC_USE_SYSTEM_TITLE_BAR,
     71                                   IDS_SHOW_WINDOW_DECORATIONS_MENU);
     72 #endif
     73   AppendTeleportMenu(model);
     74   // If it's a regular browser window with tabs, we don't add any more items,
     75   // since it already has menus (Page, Chrome).
     76 }
     77 
     78 void SystemMenuModelBuilder::BuildSystemMenuForAppOrPopupWindow(
     79     ui::SimpleMenuModel* model) {
     80   model->AddItemWithStringId(IDC_BACK, IDS_CONTENT_CONTEXT_BACK);
     81   model->AddItemWithStringId(IDC_FORWARD, IDS_CONTENT_CONTEXT_FORWARD);
     82   model->AddItemWithStringId(IDC_RELOAD, IDS_APP_MENU_RELOAD);
     83   model->AddSeparator(ui::NORMAL_SEPARATOR);
     84   if (browser()->is_app())
     85     model->AddItemWithStringId(IDC_NEW_TAB, IDS_APP_MENU_NEW_WEB_PAGE);
     86   else
     87     model->AddItemWithStringId(IDC_SHOW_AS_TAB, IDS_SHOW_AS_TAB);
     88   model->AddSeparator(ui::NORMAL_SEPARATOR);
     89   model->AddItemWithStringId(IDC_CUT, IDS_CUT);
     90   model->AddItemWithStringId(IDC_COPY, IDS_COPY);
     91   model->AddItemWithStringId(IDC_PASTE, IDS_PASTE);
     92   model->AddSeparator(ui::NORMAL_SEPARATOR);
     93   model->AddItemWithStringId(IDC_FIND, IDS_FIND);
     94   model->AddItemWithStringId(IDC_PRINT, IDS_PRINT);
     95   zoom_menu_contents_.reset(new ZoomMenuModel(&menu_delegate_));
     96   model->AddSubMenuWithStringId(IDC_ZOOM_MENU, IDS_ZOOM_MENU,
     97                                 zoom_menu_contents_.get());
     98   encoding_menu_contents_.reset(new EncodingMenuModel(browser()));
     99   model->AddSubMenuWithStringId(IDC_ENCODING_MENU,
    100                                 IDS_ENCODING_MENU,
    101                                 encoding_menu_contents_.get());
    102   if (browser()->is_app() && chrome::CanOpenTaskManager()) {
    103     model->AddSeparator(ui::NORMAL_SEPARATOR);
    104     model->AddItemWithStringId(IDC_TASK_MANAGER, IDS_TASK_MANAGER);
    105   }
    106 #if defined(OS_LINUX) && !defined(OS_CHROMEOS)
    107   model->AddSeparator(ui::NORMAL_SEPARATOR);
    108   model->AddItemWithStringId(IDC_CLOSE_WINDOW, IDS_CLOSE);
    109 #endif
    110 
    111   AppendTeleportMenu(model);
    112 }
    113 
    114 void SystemMenuModelBuilder::AddFrameToggleItems(ui::SimpleMenuModel* model) {
    115   if (CommandLine::ForCurrentProcess()->HasSwitch(
    116           switches::kDebugEnableFrameToggle)) {
    117     model->AddSeparator(ui::NORMAL_SEPARATOR);
    118     model->AddItem(IDC_DEBUG_FRAME_TOGGLE,
    119                    base::ASCIIToUTF16("Toggle Frame Type"));
    120   }
    121 }
    122 
    123 void SystemMenuModelBuilder::AppendTeleportMenu(ui::SimpleMenuModel* model) {
    124 #if defined(OS_CHROMEOS)
    125   DCHECK(browser()->window());
    126   // If there is no manager, we are not in the proper multi user mode.
    127   if (chrome::MultiUserWindowManager::GetMultiProfileMode() !=
    128           chrome::MultiUserWindowManager::MULTI_PROFILE_MODE_SEPARATED)
    129     return;
    130 
    131   // Don't show the menu for incognito windows.
    132   if (browser()->profile()->IsOffTheRecord())
    133     return;
    134 
    135   // To show the menu we need at least two logged in users.
    136   ash::SessionStateDelegate* delegate =
    137       ash::Shell::GetInstance()->session_state_delegate();
    138   int logged_in_users = delegate->NumberOfLoggedInUsers();
    139   if (logged_in_users <= 1)
    140     return;
    141 
    142   // If this does not belong to a profile or there is no window, or the window
    143   // is not owned by anyone, we don't show the menu addition.
    144   chrome::MultiUserWindowManager* manager =
    145       chrome::MultiUserWindowManager::GetInstance();
    146   const std::string user_id =
    147       multi_user_util::GetUserIDFromProfile(browser()->profile());
    148   aura::Window* window = browser()->window()->GetNativeWindow();
    149   if (user_id.empty() || !window || manager->GetWindowOwner(window).empty())
    150     return;
    151 
    152   model->AddSeparator(ui::NORMAL_SEPARATOR);
    153   DCHECK(logged_in_users <= 3);
    154   for (int user_index = 1; user_index < logged_in_users; ++user_index) {
    155     const ash::UserInfo* user_info = delegate->GetUserInfo(user_index);
    156     model->AddItem(
    157         user_index == 1 ? IDC_VISIT_DESKTOP_OF_LRU_USER_2
    158                         : IDC_VISIT_DESKTOP_OF_LRU_USER_3,
    159         l10n_util::GetStringFUTF16(IDS_VISIT_DESKTOP_OF_LRU_USER,
    160                                    user_info->GetDisplayName(),
    161                                    base::ASCIIToUTF16(user_info->GetEmail())));
    162   }
    163 #endif
    164 }
    165