| OLD | NEW |
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controll
er.h" | 5 #include "chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controll
er.h" |
| 6 | 6 |
| 7 #include <limits> |
| 7 #include <vector> | 8 #include <vector> |
| 8 | 9 |
| 9 #include "ash/common/shelf/shelf_delegate.h" | 10 #include "ash/common/shelf/shelf_delegate.h" |
| 10 #include "ash/common/shelf/shelf_model.h" | 11 #include "ash/common/shelf/shelf_model.h" |
| 11 #include "ash/common/wm_shell.h" | 12 #include "ash/common/wm_shell.h" |
| 12 #include "ash/common/wm_window.h" | 13 #include "ash/common/wm_window.h" |
| 13 #include "ash/common/wm_window_property.h" | 14 #include "ash/common/wm_window_property.h" |
| 14 #include "ash/public/cpp/shelf_application_menu_item.h" | 15 #include "ash/public/cpp/shelf_application_menu_item.h" |
| 15 #include "ash/resources/grit/ash_resources.h" | 16 #include "ash/resources/grit/ash_resources.h" |
| 16 #include "ash/wm/window_util.h" | 17 #include "ash/wm/window_util.h" |
| 17 #include "base/memory/ptr_util.h" | 18 #include "base/memory/ptr_util.h" |
| 19 #include "chrome/browser/chrome_notification_types.h" |
| 18 #include "chrome/browser/profiles/profile.h" | 20 #include "chrome/browser/profiles/profile.h" |
| 19 #include "chrome/browser/ui/ash/launcher/chrome_launcher_app_menu_item_browser.h
" | |
| 20 #include "chrome/browser/ui/ash/launcher/chrome_launcher_app_menu_item_tab.h" | |
| 21 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h" | 21 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h" |
| 22 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller_util.h" | 22 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller_util.h" |
| 23 #include "chrome/browser/ui/ash/launcher/launcher_context_menu.h" | 23 #include "chrome/browser/ui/ash/launcher/launcher_context_menu.h" |
| 24 #include "chrome/browser/ui/ash/multi_user/multi_user_util.h" |
| 24 #include "chrome/browser/ui/browser.h" | 25 #include "chrome/browser/ui/browser.h" |
| 25 #include "chrome/browser/ui/browser_commands.h" | 26 #include "chrome/browser/ui/browser_commands.h" |
| 26 #include "chrome/browser/ui/browser_finder.h" | 27 #include "chrome/browser/ui/browser_finder.h" |
| 27 #include "chrome/browser/ui/browser_window.h" | 28 #include "chrome/browser/ui/browser_window.h" |
| 28 #include "chrome/browser/ui/chrome_pages.h" | 29 #include "chrome/browser/ui/chrome_pages.h" |
| 29 #include "chrome/browser/ui/settings_window_manager.h" | 30 #include "chrome/browser/ui/settings_window_manager.h" |
| 30 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 31 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
| 31 #include "chrome/browser/web_applications/web_app.h" | 32 #include "chrome/browser/web_applications/web_app.h" |
| 32 #include "chrome/common/extensions/extension_constants.h" | 33 #include "chrome/common/extensions/extension_constants.h" |
| 33 #include "chrome/grit/chromium_strings.h" | 34 #include "chrome/grit/chromium_strings.h" |
| 34 #include "chrome/grit/generated_resources.h" | 35 #include "chrome/grit/generated_resources.h" |
| 35 #include "components/strings/grit/components_strings.h" | 36 #include "components/strings/grit/components_strings.h" |
| 37 #include "content/public/browser/notification_service.h" |
| 36 #include "content/public/browser/web_contents.h" | 38 #include "content/public/browser/web_contents.h" |
| 37 #include "content/public/common/url_constants.h" | 39 #include "content/public/common/url_constants.h" |
| 38 #include "ui/aura/window.h" | 40 #include "ui/aura/window.h" |
| 39 #include "ui/base/l10n/l10n_util.h" | 41 #include "ui/base/l10n/l10n_util.h" |
| 40 #include "ui/base/resource/resource_bundle.h" | 42 #include "ui/base/resource/resource_bundle.h" |
| 41 #include "ui/events/event.h" | 43 #include "ui/events/event.h" |
| 44 #include "ui/events/event_constants.h" |
| 42 #include "ui/gfx/image/image.h" | 45 #include "ui/gfx/image/image.h" |
| 43 #include "ui/wm/core/window_animations.h" | 46 #include "ui/wm/core/window_animations.h" |
| 44 | 47 |
| 45 namespace { | 48 namespace { |
| 46 | 49 |
| 50 // The maximum number of browser or tab items supported in the application menu. |
| 51 constexpr uint16_t kMaxItems = std::numeric_limits<uint16_t>::max(); |
| 52 // The tab-index flag for browser window menu items that do not specify a tab. |
| 53 constexpr uint16_t kNoTab = std::numeric_limits<uint16_t>::max(); |
| 54 |
| 47 bool IsSettingsBrowser(Browser* browser) { | 55 bool IsSettingsBrowser(Browser* browser) { |
| 48 // Normally this test is sufficient. TODO(stevenjb): Replace this with a | 56 // Normally this test is sufficient. TODO(stevenjb): Replace this with a |
| 49 // better mechanism (Settings WebUI or Browser type). | 57 // better mechanism (Settings WebUI or Browser type). |
| 50 if (chrome::IsTrustedPopupWindowWithScheme(browser, content::kChromeUIScheme)) | 58 if (chrome::IsTrustedPopupWindowWithScheme(browser, content::kChromeUIScheme)) |
| 51 return true; | 59 return true; |
| 52 // If a settings window navigates away from a kChromeUIScheme (e.g. after a | 60 // If a settings window navigates away from a kChromeUIScheme (e.g. after a |
| 53 // crash), the above may not be true, so also test against the known list | 61 // crash), the above may not be true, so also test against the known list |
| 54 // of settings browsers (which will not be valid during chrome::Navigate | 62 // of settings browsers (which will not be valid during chrome::Navigate |
| 55 // which is why we still need the above test). | 63 // which is why we still need the above test). |
| 56 if (chrome::SettingsWindowManager::GetInstance()->IsSettingsBrowser(browser)) | 64 if (chrome::SettingsWindowManager::GetInstance()->IsSettingsBrowser(browser)) |
| 57 return true; | 65 return true; |
| 58 return false; | 66 return false; |
| 59 } | 67 } |
| 60 | 68 |
| 69 // Returns a 32-bit command id from 16-bit browser and web-contents indices. |
| 70 uint32_t GetCommandId(uint16_t browser_index, uint16_t web_contents_index) { |
| 71 return (browser_index << 16) | web_contents_index; |
| 72 } |
| 73 |
| 74 // Get the 16-bit browser index from a 32-bit command id. |
| 75 uint16_t GetBrowserIndex(uint32_t command_id) { |
| 76 return base::checked_cast<uint16_t>((command_id >> 16) & 0xFFFF); |
| 77 } |
| 78 |
| 79 // Get the 16-bit web-contents index from a 32-bit command id. |
| 80 uint16_t GetWebContentsIndex(uint32_t command_id) { |
| 81 return base::checked_cast<uint16_t>(command_id & 0xFFFF); |
| 82 } |
| 83 |
| 84 // Check if the given |web_contents| is in incognito mode. |
| 85 bool IsIncognito(content::WebContents* web_contents) { |
| 86 const Profile* profile = |
| 87 Profile::FromBrowserContext(web_contents->GetBrowserContext()); |
| 88 return profile->IsOffTheRecord() && !profile->IsGuestSession(); |
| 89 } |
| 90 |
| 91 // Get the favicon for the browser list entry for |web_contents|. |
| 92 // Note that for incognito windows the incognito icon will be returned. |
| 93 gfx::Image GetBrowserListIcon(content::WebContents* web_contents) { |
| 94 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); |
| 95 return rb.GetImageNamed(IsIncognito(web_contents) |
| 96 ? IDR_ASH_SHELF_LIST_INCOGNITO_BROWSER |
| 97 : IDR_ASH_SHELF_LIST_BROWSER); |
| 98 } |
| 99 |
| 100 // Get the title for the browser list entry for |web_contents|. |
| 101 // If |web_contents| has not loaded, returns "New Tab". |
| 102 base::string16 GetBrowserListTitle(content::WebContents* web_contents) { |
| 103 const base::string16& title = web_contents->GetTitle(); |
| 104 return title.empty() ? l10n_util::GetStringUTF16(IDS_NEW_TAB_TITLE) : title; |
| 105 } |
| 106 |
| 61 } // namespace | 107 } // namespace |
| 62 | 108 |
| 63 BrowserShortcutLauncherItemController::BrowserShortcutLauncherItemController( | 109 BrowserShortcutLauncherItemController::BrowserShortcutLauncherItemController( |
| 64 ChromeLauncherController* launcher_controller, | 110 ChromeLauncherController* launcher_controller, |
| 65 ash::ShelfModel* shelf_model) | 111 ash::ShelfModel* shelf_model) |
| 66 : LauncherItemController(extension_misc::kChromeAppId, | 112 : LauncherItemController(extension_misc::kChromeAppId, |
| 67 std::string(), | 113 std::string(), |
| 68 launcher_controller), | 114 launcher_controller), |
| 69 shelf_model_(shelf_model) {} | 115 shelf_model_(shelf_model) {} |
| 70 | 116 |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 150 chrome::NewEmptyWindow(launcher_controller()->profile()); | 196 chrome::NewEmptyWindow(launcher_controller()->profile()); |
| 151 return ash::SHELF_ACTION_NEW_WINDOW_CREATED; | 197 return ash::SHELF_ACTION_NEW_WINDOW_CREATED; |
| 152 } | 198 } |
| 153 | 199 |
| 154 return launcher_controller()->ActivateWindowOrMinimizeIfActive( | 200 return launcher_controller()->ActivateWindowOrMinimizeIfActive( |
| 155 last_browser->window(), GetAppMenuItems(0).size() == 1); | 201 last_browser->window(), GetAppMenuItems(0).size() == 1); |
| 156 } | 202 } |
| 157 | 203 |
| 158 ash::ShelfAppMenuItemList | 204 ash::ShelfAppMenuItemList |
| 159 BrowserShortcutLauncherItemController::GetAppMenuItems(int event_flags) { | 205 BrowserShortcutLauncherItemController::GetAppMenuItems(int event_flags) { |
| 206 browser_menu_items_.clear(); |
| 207 registrar_.RemoveAll(); |
| 208 |
| 160 ash::ShelfAppMenuItemList items; | 209 ash::ShelfAppMenuItemList items; |
| 161 bool found_tabbed_browser = false; | 210 bool found_tabbed_browser = false; |
| 162 for (auto* browser : GetListOfActiveBrowsers()) { | 211 for (auto* browser : GetListOfActiveBrowsers()) { |
| 212 if (browser_menu_items_.size() >= kMaxItems) |
| 213 break; |
| 163 TabStripModel* tab_strip = browser->tab_strip_model(); | 214 TabStripModel* tab_strip = browser->tab_strip_model(); |
| 164 if (tab_strip->active_index() == -1) | 215 const int tab_index = tab_strip->active_index(); |
| 216 if (tab_index < 0 || tab_index >= kMaxItems) |
| 165 continue; | 217 continue; |
| 166 if (browser->is_type_tabbed()) | 218 if (browser->is_type_tabbed()) |
| 167 found_tabbed_browser = true; | 219 found_tabbed_browser = true; |
| 168 if (!(event_flags & ui::EF_SHIFT_DOWN)) { | 220 if (!(event_flags & ui::EF_SHIFT_DOWN)) { |
| 169 content::WebContents* web_contents = | 221 content::WebContents* tab = tab_strip->GetWebContentsAt(tab_index); |
| 170 tab_strip->GetWebContentsAt(tab_strip->active_index()); | 222 gfx::Image icon = GetBrowserListIcon(tab); |
| 171 gfx::Image app_icon = GetBrowserListIcon(web_contents); | 223 base::string16 title = GetBrowserListTitle(tab); |
| 172 base::string16 title = GetBrowserListTitle(web_contents); | 224 items.push_back(base::MakeUnique<ash::ShelfApplicationMenuItem>( |
| 173 items.push_back(base::MakeUnique<ChromeLauncherAppMenuItemBrowser>( | 225 GetCommandId(browser_menu_items_.size(), kNoTab), title, &icon)); |
| 174 title, &app_icon, browser)); | |
| 175 } else { | 226 } else { |
| 176 for (int index = 0; index < tab_strip->count(); ++index) { | 227 for (uint16_t i = 0; i < tab_strip->count() && i < kMaxItems; ++i) { |
| 177 content::WebContents* web_contents = | 228 content::WebContents* tab = tab_strip->GetWebContentsAt(i); |
| 178 tab_strip->GetWebContentsAt(index); | 229 gfx::Image icon = launcher_controller()->GetAppListIcon(tab); |
| 179 gfx::Image app_icon = | 230 base::string16 title = launcher_controller()->GetAppListTitle(tab); |
| 180 launcher_controller()->GetAppListIcon(web_contents); | 231 items.push_back(base::MakeUnique<ash::ShelfApplicationMenuItem>( |
| 181 base::string16 title = | 232 GetCommandId(browser_menu_items_.size(), i), title, &icon)); |
| 182 launcher_controller()->GetAppListTitle(web_contents); | |
| 183 items.push_back(base::MakeUnique<ChromeLauncherAppMenuItemTab>( | |
| 184 title, &app_icon, web_contents)); | |
| 185 } | 233 } |
| 186 } | 234 } |
| 235 browser_menu_items_.push_back(browser); |
| 236 registrar_.Add(this, chrome::NOTIFICATION_BROWSER_CLOSING, |
| 237 content::Source<Browser>(browser)); |
| 187 } | 238 } |
| 188 // If only windowed applications are open, we return an empty list to | 239 // If only windowed applications are open, we return an empty list to |
| 189 // enforce the creation of a new browser. | 240 // enforce the creation of a new browser. |
| 190 if (!found_tabbed_browser) | 241 if (!found_tabbed_browser) { |
| 191 items.clear(); | 242 items.clear(); |
| 243 browser_menu_items_.clear(); |
| 244 registrar_.RemoveAll(); |
| 245 } |
| 192 return items; | 246 return items; |
| 193 } | 247 } |
| 194 | 248 |
| 249 void BrowserShortcutLauncherItemController::ExecuteCommand(uint32_t command_id, |
| 250 int event_flags) { |
| 251 const uint16_t browser_index = GetBrowserIndex(command_id); |
| 252 // Check that the index is valid and the browser has not been closed. |
| 253 if (browser_index < browser_menu_items_.size() && |
| 254 browser_menu_items_[browser_index]) { |
| 255 Browser* browser = browser_menu_items_[browser_index]; |
| 256 TabStripModel* tab_strip = browser->tab_strip_model(); |
| 257 const uint16_t tab_index = GetWebContentsIndex(command_id); |
| 258 if (event_flags & (ui::EF_SHIFT_DOWN | ui::EF_MIDDLE_MOUSE_BUTTON)) { |
| 259 if (tab_index == kNoTab) { |
| 260 tab_strip->CloseAllTabs(); |
| 261 } else if (tab_strip->ContainsIndex(tab_index)) { |
| 262 tab_strip->CloseWebContentsAt(tab_index, |
| 263 TabStripModel::CLOSE_USER_GESTURE); |
| 264 } |
| 265 } else { |
| 266 multi_user_util::MoveWindowToCurrentDesktop( |
| 267 browser->window()->GetNativeWindow()); |
| 268 if (tab_index != kNoTab && tab_strip->ContainsIndex(tab_index)) |
| 269 tab_strip->ActivateTabAt(tab_index, false); |
| 270 browser->window()->Show(); |
| 271 browser->window()->Activate(); |
| 272 } |
| 273 } |
| 274 |
| 275 browser_menu_items_.clear(); |
| 276 registrar_.RemoveAll(); |
| 277 } |
| 278 |
| 195 void BrowserShortcutLauncherItemController::Close() { | 279 void BrowserShortcutLauncherItemController::Close() { |
| 196 for (auto* browser : GetListOfActiveBrowsers()) | 280 for (auto* browser : GetListOfActiveBrowsers()) |
| 197 browser->window()->Close(); | 281 browser->window()->Close(); |
| 198 } | 282 } |
| 199 | 283 |
| 200 bool BrowserShortcutLauncherItemController::IsListOfActiveBrowserEmpty() { | 284 bool BrowserShortcutLauncherItemController::IsListOfActiveBrowserEmpty() { |
| 201 return GetListOfActiveBrowsers().empty(); | 285 return GetListOfActiveBrowsers().empty(); |
| 202 } | 286 } |
| 203 | 287 |
| 204 gfx::Image BrowserShortcutLauncherItemController::GetBrowserListIcon( | |
| 205 content::WebContents* web_contents) const { | |
| 206 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); | |
| 207 return rb.GetImageNamed(IsIncognito(web_contents) ? | |
| 208 IDR_ASH_SHELF_LIST_INCOGNITO_BROWSER : | |
| 209 IDR_ASH_SHELF_LIST_BROWSER); | |
| 210 } | |
| 211 | |
| 212 base::string16 BrowserShortcutLauncherItemController::GetBrowserListTitle( | |
| 213 content::WebContents* web_contents) const { | |
| 214 base::string16 title = web_contents->GetTitle(); | |
| 215 if (!title.empty()) | |
| 216 return title; | |
| 217 return l10n_util::GetStringUTF16(IDS_NEW_TAB_TITLE); | |
| 218 } | |
| 219 | |
| 220 bool BrowserShortcutLauncherItemController::IsIncognito( | |
| 221 content::WebContents* web_contents) const { | |
| 222 const Profile* profile = | |
| 223 Profile::FromBrowserContext(web_contents->GetBrowserContext()); | |
| 224 return profile->IsOffTheRecord() && !profile->IsGuestSession(); | |
| 225 } | |
| 226 | |
| 227 ash::ShelfAction | 288 ash::ShelfAction |
| 228 BrowserShortcutLauncherItemController::ActivateOrAdvanceToNextBrowser() { | 289 BrowserShortcutLauncherItemController::ActivateOrAdvanceToNextBrowser() { |
| 229 // Create a list of all suitable running browsers. | 290 // Create a list of all suitable running browsers. |
| 230 std::vector<Browser*> items; | 291 std::vector<Browser*> items; |
| 231 // We use the list in the order of how the browsers got created - not the LRU | 292 // We use the list in the order of how the browsers got created - not the LRU |
| 232 // order. | 293 // order. |
| 233 const BrowserList* browser_list = BrowserList::GetInstance(); | 294 const BrowserList* browser_list = BrowserList::GetInstance(); |
| 234 for (BrowserList::const_iterator it = browser_list->begin(); | 295 for (BrowserList::const_iterator it = browser_list->begin(); |
| 235 it != browser_list->end(); ++it) { | 296 it != browser_list->end(); ++it) { |
| 236 if (IsBrowserRepresentedInBrowserList(*it)) | 297 if (IsBrowserRepresentedInBrowserList(*it)) |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 304 !browser->window()->IsMinimized()) { | 365 !browser->window()->IsMinimized()) { |
| 305 continue; | 366 continue; |
| 306 } | 367 } |
| 307 if (!IsBrowserRepresentedInBrowserList(browser) && | 368 if (!IsBrowserRepresentedInBrowserList(browser) && |
| 308 !browser->is_type_tabbed()) | 369 !browser->is_type_tabbed()) |
| 309 continue; | 370 continue; |
| 310 active_browsers.push_back(browser); | 371 active_browsers.push_back(browser); |
| 311 } | 372 } |
| 312 return active_browsers; | 373 return active_browsers; |
| 313 } | 374 } |
| 375 |
| 376 void BrowserShortcutLauncherItemController::Observe( |
| 377 int type, |
| 378 const content::NotificationSource& source, |
| 379 const content::NotificationDetails& details) { |
| 380 DCHECK_EQ(chrome::NOTIFICATION_BROWSER_CLOSING, type); |
| 381 Browser* browser = content::Source<Browser>(source).ptr(); |
| 382 DCHECK(browser); |
| 383 BrowserList::BrowserVector::iterator item = std::find( |
| 384 browser_menu_items_.begin(), browser_menu_items_.end(), browser); |
| 385 DCHECK(item != browser_menu_items_.end()); |
| 386 // Clear the entry for the closed browser and leave other indices intact. |
| 387 *item = nullptr; |
| 388 registrar_.Remove(this, chrome::NOTIFICATION_BROWSER_CLOSING, |
| 389 content::Source<Browser>(browser)); |
| 390 } |
| OLD | NEW |