browser_shortcut_launcher_item_controller.cc revision bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3
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/ash/launcher/browser_shortcut_launcher_item_controller.h" 6 7#include <vector> 8 9#include "ash/launcher/launcher.h" 10#include "ash/shell.h" 11#include "ash/wm/window_util.h" 12#include "chrome/browser/profiles/profile.h" 13#include "chrome/browser/ui/ash/launcher/chrome_launcher_app_menu_item.h" 14#include "chrome/browser/ui/ash/launcher/chrome_launcher_app_menu_item_browser.h" 15#include "chrome/browser/ui/ash/launcher/chrome_launcher_app_menu_item_tab.h" 16#include "chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_app.h" 17#include "chrome/browser/ui/browser.h" 18#include "chrome/browser/ui/browser_finder.h" 19#include "chrome/browser/ui/browser_list.h" 20#include "chrome/browser/ui/browser_window.h" 21#include "chrome/browser/ui/tabs/tab_strip_model.h" 22#include "chrome/common/extensions/extension_constants.h" 23#include "content/public/browser/web_contents.h" 24#include "grit/ash_resources.h" 25#include "grit/chromium_strings.h" 26#include "grit/generated_resources.h" 27#include "ui/aura/window.h" 28#include "ui/base/events/event.h" 29#include "ui/base/l10n/l10n_util.h" 30#include "ui/base/resource/resource_bundle.h" 31#include "ui/gfx/image/image.h" 32#include "ui/views/corewm/window_animations.h" 33 34#if defined(OS_CHROMEOS) 35#include "chrome/browser/chromeos/login/default_pinned_apps_field_trial.h" 36#endif 37 38BrowserShortcutLauncherItemController::BrowserShortcutLauncherItemController( 39 ChromeLauncherControllerPerApp* launcher_controller, 40 Profile* profile) 41 : LauncherItemController(TYPE_SHORTCUT, 42 extension_misc::kChromeAppId, 43 launcher_controller), 44 app_controller_(launcher_controller), 45 profile_(profile) { 46} 47 48string16 BrowserShortcutLauncherItemController::GetTitle() { 49 return l10n_util::GetStringUTF16(IDS_PRODUCT_NAME); 50} 51 52bool BrowserShortcutLauncherItemController::HasWindow( 53 aura::Window* window) const { 54 const BrowserList* ash_browser_list = 55 BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH); 56 for (BrowserList::const_iterator it = ash_browser_list->begin(); 57 it != ash_browser_list->end(); ++it) { 58 // During browser creation it is possible that this function is called 59 // before a browser got a window (see crbug.com/263563). 60 if ((*it)->window() && 61 (*it)->window()->GetNativeWindow() == window) 62 return true; 63 } 64 return false; 65} 66 67bool BrowserShortcutLauncherItemController::IsOpen() const { 68 const BrowserList* ash_browser_list = 69 BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH); 70 return ash_browser_list->empty() ? false : true; 71} 72 73bool BrowserShortcutLauncherItemController::IsVisible() const { 74 Browser* last_browser = chrome::FindTabbedBrowser( 75 profile_, 76 true, 77 chrome::HOST_DESKTOP_TYPE_ASH); 78 79 if (!last_browser) { 80 return false; 81 } 82 83 aura::Window* window = last_browser->window()->GetNativeWindow(); 84 return ash::wm::IsActiveWindow(window); 85} 86 87void BrowserShortcutLauncherItemController::Launch(int event_flags) { 88} 89 90void BrowserShortcutLauncherItemController::Activate() { 91 Browser* last_browser = chrome::FindTabbedBrowser( 92 profile_, 93 true, 94 chrome::HOST_DESKTOP_TYPE_ASH); 95 96 if (!last_browser) { 97 launcher_controller()->CreateNewWindow(); 98 return; 99 } 100 101 launcher_controller()->ActivateWindowOrMinimizeIfActive( 102 last_browser->window(), GetApplicationList(0).size() == 2); 103} 104 105void BrowserShortcutLauncherItemController::Close() { 106} 107 108void BrowserShortcutLauncherItemController::LauncherItemChanged( 109 int model_index, 110 const ash::LauncherItem& old_item) { 111} 112 113void BrowserShortcutLauncherItemController::Clicked(const ui::Event& event) { 114 #if defined(OS_CHROMEOS) 115 chromeos::default_pinned_apps_field_trial::RecordShelfClick( 116 chromeos::default_pinned_apps_field_trial::CHROME); 117 #endif 118 119 if (event.flags() & ui::EF_CONTROL_DOWN) { 120 launcher_controller()->CreateNewWindow(); 121 return; 122 } 123 124 // In case of a keyboard event, we were called by a hotkey. In that case we 125 // activate the next item in line if an item of our list is already active. 126 if (event.type() & ui::ET_KEY_RELEASED) { 127 ActivateOrAdvanceToNextBrowser(); 128 return; 129 } 130 131 Activate(); 132} 133 134void BrowserShortcutLauncherItemController::OnRemoved() { 135 // BrowserShortcutLauncherItemController is owned by ChromeLauncherController. 136} 137 138ChromeLauncherAppMenuItems 139BrowserShortcutLauncherItemController::GetApplicationList(int event_flags) { 140 ChromeLauncherAppMenuItems items; 141 bool found_tabbed_browser = false; 142 // Add the application name to the menu. 143 items.push_back(new ChromeLauncherAppMenuItem(GetTitle(), NULL, false)); 144 const BrowserList* ash_browser_list = 145 BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH); 146 for (BrowserList::const_iterator it = ash_browser_list->begin(); 147 it != ash_browser_list->end(); ++it) { 148 Browser* browser = *it; 149 // Make sure that the browser was already shown and it has a proper window. 150 if (std::find(ash_browser_list->begin_last_active(), 151 ash_browser_list->end_last_active(), 152 browser) == ash_browser_list->end_last_active() || 153 !browser->window()) 154 continue; 155 if (browser->is_type_tabbed()) 156 found_tabbed_browser = true; 157 else if (!app_controller_->IsBrowserRepresentedInBrowserList(browser)) 158 continue; 159 TabStripModel* tab_strip = browser->tab_strip_model(); 160 if (tab_strip->active_index() == -1) 161 continue; 162 if (!(event_flags & ui::EF_SHIFT_DOWN)) { 163 content::WebContents* web_contents = 164 tab_strip->GetWebContentsAt(tab_strip->active_index()); 165 gfx::Image app_icon = GetBrowserListIcon(web_contents); 166 string16 title = GetBrowserListTitle(web_contents); 167 items.push_back(new ChromeLauncherAppMenuItemBrowser( 168 title, &app_icon, browser, items.size() == 1)); 169 } else { 170 for (int index = 0; index < tab_strip->count(); ++index) { 171 content::WebContents* web_contents = 172 tab_strip->GetWebContentsAt(index); 173 gfx::Image app_icon = app_controller_->GetAppListIcon(web_contents); 174 string16 title = app_controller_->GetAppListTitle(web_contents); 175 // Check if we need to insert a separator in front. 176 bool leading_separator = !index; 177 items.push_back(new ChromeLauncherAppMenuItemTab( 178 title, &app_icon, web_contents, leading_separator)); 179 } 180 } 181 } 182 // If only windowed applications are open, we return an empty list to 183 // enforce the creation of a new browser. 184 if (!found_tabbed_browser) 185 items.clear(); 186 return items.Pass(); 187} 188 189gfx::Image BrowserShortcutLauncherItemController::GetBrowserListIcon( 190 content::WebContents* web_contents) const { 191 ResourceBundle& rb = ResourceBundle::GetSharedInstance(); 192 return rb.GetImageNamed(IsIncognito(web_contents) ? 193 IDR_AURA_LAUNCHER_LIST_INCOGNITO_BROWSER : 194 IDR_AURA_LAUNCHER_LIST_BROWSER); 195} 196 197string16 BrowserShortcutLauncherItemController::GetBrowserListTitle( 198 content::WebContents* web_contents) const { 199 string16 title = web_contents->GetTitle(); 200 if (!title.empty()) 201 return title; 202 return l10n_util::GetStringUTF16(IDS_NEW_TAB_TITLE); 203} 204 205bool BrowserShortcutLauncherItemController::IsIncognito( 206 content::WebContents* web_contents) const { 207 const Profile* profile = 208 Profile::FromBrowserContext(web_contents->GetBrowserContext()); 209 return profile->IsOffTheRecord() && !profile->IsGuestSession(); 210} 211 212void BrowserShortcutLauncherItemController::ActivateOrAdvanceToNextBrowser() { 213 // Create a list of all suitable running browsers. 214 std::vector<Browser*> items; 215 // We use the list in the order of how the browsers got created - not the LRU 216 // order. 217 const BrowserList* ash_browser_list = 218 BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH); 219 for (BrowserList::const_iterator it = 220 ash_browser_list->begin(); 221 it != ash_browser_list->end(); ++it) { 222 if (app_controller_->IsBrowserRepresentedInBrowserList(*it)) 223 items.push_back(*it); 224 } 225 // If there are no suitable browsers we create a new one. 226 if (!items.size()) { 227 launcher_controller()->CreateNewWindow(); 228 return; 229 } 230 Browser* browser = chrome::FindBrowserWithWindow(ash::wm::GetActiveWindow()); 231 if (items.size() == 1) { 232 // If there is only one suitable browser, we can either activate it, or 233 // bounce it (if it is already active). 234 if (browser == items[0]) { 235 AnimateWindow(browser->window()->GetNativeWindow(), 236 views::corewm::WINDOW_ANIMATION_TYPE_BOUNCE); 237 return; 238 } 239 browser = items[0]; 240 } else { 241 // If there is more then one suitable browser, we advance to the next if 242 // |current_browser| is already active - or - check the last used browser 243 // if it can be used. 244 std::vector<Browser*>::iterator i = 245 std::find(items.begin(), items.end(), browser); 246 if (i != items.end()) { 247 browser = (++i == items.end()) ? items[0] : *i; 248 } else { 249 browser = chrome::FindTabbedBrowser(profile_, 250 true, 251 chrome::HOST_DESKTOP_TYPE_ASH); 252 if (!browser || 253 !app_controller_->IsBrowserRepresentedInBrowserList(browser)) 254 browser = items[0]; 255 } 256 } 257 DCHECK(browser); 258 browser->window()->Show(); 259 browser->window()->Activate(); 260} 261