| 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   if (browser_index >= browser_menu_items_.size()) | 
 |  253     return; | 
 |  254  | 
 |  255   // The indicated browser may have closed while the menu was open. | 
 |  256   Browser* browser = browser_menu_items_[browser_index]; | 
 |  257   if (!browser) | 
 |  258     return; | 
 |  259  | 
 |  260   TabStripModel* tab_strip = browser->tab_strip_model(); | 
 |  261   const uint16_t tab_index = GetWebContentsIndex(command_id); | 
 |  262   if (event_flags & (ui::EF_SHIFT_DOWN | ui::EF_MIDDLE_MOUSE_BUTTON)) { | 
 |  263     if (tab_index == kNoTab) { | 
 |  264       tab_strip->CloseAllTabs(); | 
 |  265     } else if (tab_strip->ContainsIndex(tab_index)) { | 
 |  266       tab_strip->CloseWebContentsAt(tab_index, | 
 |  267                                     TabStripModel::CLOSE_USER_GESTURE); | 
 |  268     } | 
 |  269   } else { | 
 |  270     multi_user_util::MoveWindowToCurrentDesktop( | 
 |  271         browser->window()->GetNativeWindow()); | 
 |  272     if (tab_index != kNoTab && tab_strip->ContainsIndex(tab_index)) | 
 |  273       tab_strip->ActivateTabAt(tab_index, false); | 
 |  274     browser->window()->Show(); | 
 |  275     browser->window()->Activate(); | 
 |  276   } | 
 |  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 |