190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)// found in the LICENSE file.
490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/ui/ash/launcher/browser_shortcut_launcher_item_controller.h"
690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include <vector>
890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/shelf/shelf.h"
10f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ash/shelf/shelf_model.h"
11f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ash/shelf/shelf_util.h"
1290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ash/shell.h"
1390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ash/wm/window_util.h"
1490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/profiles/profile.h"
1590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/ui/ash/launcher/chrome_launcher_app_menu_item.h"
1690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/ui/ash/launcher/chrome_launcher_app_menu_item_browser.h"
1790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/ui/ash/launcher/chrome_launcher_app_menu_item_tab.h"
183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h"
194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chrome/browser/ui/ash/launcher/launcher_application_menu_item_model.h"
204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chrome/browser/ui/ash/launcher/launcher_context_menu.h"
2190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/ui/browser.h"
2290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/ui/browser_finder.h"
2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/ui/browser_list.h"
2490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/ui/browser_window.h"
250529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "chrome/browser/ui/chrome_pages.h"
266d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "chrome/browser/ui/settings_window_manager.h"
2790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model.h"
2858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "chrome/browser/web_applications/web_app.h"
2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/common/extensions/extension_constants.h"
301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/grit/chromium_strings.h"
311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/grit/generated_resources.h"
3290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "content/public/browser/web_contents.h"
330529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include "content/public/common/url_constants.h"
3490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "grit/ash_resources.h"
3590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/aura/window.h"
3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/base/resource/resource_bundle.h"
38d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/events/event.h"
3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/gfx/image/image.h"
40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/wm/core/window_animations.h"
4190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)BrowserShortcutLauncherItemController::BrowserShortcutLauncherItemController(
434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    ChromeLauncherController* launcher_controller)
4490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    : LauncherItemController(TYPE_SHORTCUT,
4590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                             extension_misc::kChromeAppId,
464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                             launcher_controller) {
4790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
49ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben MurdochBrowserShortcutLauncherItemController::
50ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    ~BrowserShortcutLauncherItemController() {
51ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
52ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
5358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void BrowserShortcutLauncherItemController::UpdateBrowserItemState() {
5458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // The shell will not be available for win7_aura unittests like
5558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // ChromeLauncherControllerTest.BrowserMenuGeneration.
5658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (!ash::Shell::HasInstance())
5758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    return;
5858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ash::ShelfModel* model = launcher_controller()->model();
6058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
6158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  // Determine the new browser's active state and change if necessary.
62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int browser_index = model->GetItemIndexForType(ash::TYPE_BROWSER_SHORTCUT);
631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  DCHECK_GE(browser_index, 0);
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ash::ShelfItem browser_item = model->items()[browser_index];
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ash::ShelfItemStatus browser_status = ash::STATUS_CLOSED;
6658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
6758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  aura::Window* window = ash::wm::GetActiveWindow();
6858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (window) {
6958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // Check if the active browser / tab is a browser which is not an app,
7058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // a windowed app, a popup or any other item which is not a browser of
7158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // interest.
7258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    Browser* browser = chrome::FindBrowserWithWindow(window);
7358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (IsBrowserRepresentedInBrowserList(browser)) {
7458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      browser_status = ash::STATUS_ACTIVE;
75f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      // If an app that has item is running in active WebContents, browser item
76f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      // status cannot be active.
77f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      content::WebContents* contents =
78f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          browser->tab_strip_model()->GetActiveWebContents();
79f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (contents &&
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          (launcher_controller()->GetShelfIDForWebContents(contents) !=
81f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)              browser_item.id))
8258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        browser_status = ash::STATUS_RUNNING;
8358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
8458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
8558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
8658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (browser_status == ash::STATUS_CLOSED) {
8758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    const BrowserList* ash_browser_list =
8858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH);
8958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    for (BrowserList::const_reverse_iterator it =
9058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)             ash_browser_list->begin_last_active();
9158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)         it != ash_browser_list->end_last_active() &&
9258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)         browser_status == ash::STATUS_CLOSED; ++it) {
9358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      if (IsBrowserRepresentedInBrowserList(*it))
9458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        browser_status = ash::STATUS_RUNNING;
9558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
9658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
9758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
9858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (browser_status != browser_item.status) {
9958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    browser_item.status = browser_status;
10058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    model->Set(browser_index, browser_item);
10158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
10258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
10358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
1040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdochvoid BrowserShortcutLauncherItemController::SetShelfIDForBrowserWindowContents(
1050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    Browser* browser,
1060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    content::WebContents* web_contents) {
10746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // We need to call SetShelfIDForWindow for V1 applications since they are
10846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // content which might change and as such change the application type.
10946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (!browser ||
11046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      !launcher_controller()->IsBrowserFromActiveUser(browser) ||
11146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      browser->host_desktop_type() != chrome::HOST_DESKTOP_TYPE_ASH ||
11246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      chrome::IsTrustedPopupWindowWithScheme(browser, content::kChromeUIScheme))
1130529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return;
11446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
1150529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  ash::SetShelfIDForWindow(
1160529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      launcher_controller()->GetShelfIDForWebContents(web_contents),
1170529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      browser->window()->GetNativeWindow());
1180529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch}
1190529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
12090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool BrowserShortcutLauncherItemController::IsOpen() const {
12190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const BrowserList* ash_browser_list =
12290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH);
1231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  for (BrowserList::const_iterator it = ash_browser_list->begin();
1241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)       it != ash_browser_list->end(); ++it) {
1251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (launcher_controller()->IsBrowserFromActiveUser(*it))
1261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      return true;
1271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
1281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  return false;
12990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
13090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
13190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool BrowserShortcutLauncherItemController::IsVisible() const {
13290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  Browser* last_browser = chrome::FindTabbedBrowser(
1334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      launcher_controller()->profile(),
13490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      true,
13590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      chrome::HOST_DESKTOP_TYPE_ASH);
13690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
13790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!last_browser) {
13890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return false;
13990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
14090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
14190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  aura::Window* window = last_browser->window()->GetNativeWindow();
14290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return ash::wm::IsActiveWindow(window);
14390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
14490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
14568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void BrowserShortcutLauncherItemController::Launch(ash::LaunchSource source,
14668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                                   int event_flags) {
14790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
14890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
149f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool BrowserShortcutLauncherItemController::Activate(ash::LaunchSource source) {
15090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  Browser* last_browser = chrome::FindTabbedBrowser(
1514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      launcher_controller()->profile(),
15290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      true,
15390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      chrome::HOST_DESKTOP_TYPE_ASH);
15490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
15590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!last_browser) {
15690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    launcher_controller()->CreateNewWindow();
157f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return true;
15890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
15990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
16090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  launcher_controller()->ActivateWindowOrMinimizeIfActive(
16190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      last_browser->window(), GetApplicationList(0).size() == 2);
162f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return false;
16390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
16490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
16590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void BrowserShortcutLauncherItemController::Close() {
16690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
16790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
16890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)ChromeLauncherAppMenuItems
16990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)BrowserShortcutLauncherItemController::GetApplicationList(int event_flags) {
17090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ChromeLauncherAppMenuItems items;
17190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  bool found_tabbed_browser = false;
17290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Add the application name to the menu.
17390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  items.push_back(new ChromeLauncherAppMenuItem(GetTitle(), NULL, false));
17490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const BrowserList* ash_browser_list =
17590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH);
17690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  for (BrowserList::const_iterator it = ash_browser_list->begin();
17790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)       it != ash_browser_list->end(); ++it) {
17890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    Browser* browser = *it;
1791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // Make sure that the browser was already shown, is from the current user
1801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // and has a proper window.
1811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (!launcher_controller()->IsBrowserFromActiveUser(browser) ||
1821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        std::find(ash_browser_list->begin_last_active(),
18390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                  ash_browser_list->end_last_active(),
18490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                  browser) == ash_browser_list->end_last_active() ||
18590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        !browser->window())
18690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      continue;
18790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (browser->is_type_tabbed())
18890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      found_tabbed_browser = true;
18958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    else if (!IsBrowserRepresentedInBrowserList(browser))
19090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      continue;
19190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    TabStripModel* tab_strip = browser->tab_strip_model();
19290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (tab_strip->active_index() == -1)
19390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      continue;
19490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (!(event_flags & ui::EF_SHIFT_DOWN)) {
19590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      content::WebContents* web_contents =
19690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          tab_strip->GetWebContentsAt(tab_strip->active_index());
19790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      gfx::Image app_icon = GetBrowserListIcon(web_contents);
198a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      base::string16 title = GetBrowserListTitle(web_contents);
19990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      items.push_back(new ChromeLauncherAppMenuItemBrowser(
20090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)          title, &app_icon, browser, items.size() == 1));
20190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    } else {
20290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      for (int index = 0; index  < tab_strip->count(); ++index) {
20390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        content::WebContents* web_contents =
20490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            tab_strip->GetWebContentsAt(index);
2053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        gfx::Image app_icon =
2063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)            launcher_controller()->GetAppListIcon(web_contents);
207a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        base::string16 title =
208a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            launcher_controller()->GetAppListTitle(web_contents);
20990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        // Check if we need to insert a separator in front.
21090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        bool leading_separator = !index;
21190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        items.push_back(new ChromeLauncherAppMenuItemTab(
21290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)            title, &app_icon, web_contents, leading_separator));
21390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      }
21490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
21590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
21690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // If only windowed applications are open, we return an empty list to
21790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // enforce the creation of a new browser.
21890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!found_tabbed_browser)
21990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    items.clear();
22090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return items.Pass();
22190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
22290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
223f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)bool BrowserShortcutLauncherItemController::ItemSelected(
2244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const ui::Event& event) {
2254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (event.flags() & ui::EF_CONTROL_DOWN) {
2264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    launcher_controller()->CreateNewWindow();
227f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return true;
2284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
2294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // In case of a keyboard event, we were called by a hotkey. In that case we
2314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // activate the next item in line if an item of our list is already active.
2324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (event.type() & ui::ET_KEY_RELEASED) {
2334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    ActivateOrAdvanceToNextBrowser();
234f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    return false;
2354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
2364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
237f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return Activate(ash::LAUNCH_FROM_UNKNOWN);
2384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
2394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::string16 BrowserShortcutLauncherItemController::GetTitle() {
2414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return l10n_util::GetStringUTF16(IDS_PRODUCT_NAME);
2424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
2434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)ui::MenuModel* BrowserShortcutLauncherItemController::CreateContextMenu(
2451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    aura::Window* root_window) {
2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ash::ShelfItem item =
2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      *(launcher_controller()->model()->ItemByID(shelf_id()));
2484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return new LauncherContextMenu(launcher_controller(), &item, root_window);
2494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
2504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
251a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)ash::ShelfMenuModel*
2524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)BrowserShortcutLauncherItemController::CreateApplicationMenu(int event_flags) {
2534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return new LauncherApplicationMenuItemModel(GetApplicationList(event_flags));
2544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
2554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool BrowserShortcutLauncherItemController::IsDraggable() {
2574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return launcher_controller()->CanPin() ? true : false;
2584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
2594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool BrowserShortcutLauncherItemController::ShouldShowTooltip() {
2614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return true;
2624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
2634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
26490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)gfx::Image BrowserShortcutLauncherItemController::GetBrowserListIcon(
26590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    content::WebContents* web_contents) const {
266c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
26790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return rb.GetImageNamed(IsIncognito(web_contents) ?
268c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      IDR_ASH_SHELF_LIST_INCOGNITO_BROWSER :
269c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      IDR_ASH_SHELF_LIST_BROWSER);
27090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
27190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)base::string16 BrowserShortcutLauncherItemController::GetBrowserListTitle(
27390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    content::WebContents* web_contents) const {
274a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 title = web_contents->GetTitle();
27590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (!title.empty())
27690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return title;
27790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return l10n_util::GetStringUTF16(IDS_NEW_TAB_TITLE);
27890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
27990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
28090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)bool BrowserShortcutLauncherItemController::IsIncognito(
28190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    content::WebContents* web_contents) const {
28290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const Profile* profile =
28390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      Profile::FromBrowserContext(web_contents->GetBrowserContext());
28490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  return profile->IsOffTheRecord() && !profile->IsGuestSession();
28590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
28690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
28790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void BrowserShortcutLauncherItemController::ActivateOrAdvanceToNextBrowser() {
28890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // Create a list of all suitable running browsers.
28990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  std::vector<Browser*> items;
29090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // We use the list in the order of how the browsers got created - not the LRU
29190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // order.
29290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  const BrowserList* ash_browser_list =
29390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH);
29490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  for (BrowserList::const_iterator it =
29590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)           ash_browser_list->begin();
29690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)       it != ash_browser_list->end(); ++it) {
29758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (IsBrowserRepresentedInBrowserList(*it))
29890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      items.push_back(*it);
29990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
30090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // If there are no suitable browsers we create a new one.
30158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (items.empty()) {
30290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    launcher_controller()->CreateNewWindow();
30390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    return;
30490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
30590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  Browser* browser = chrome::FindBrowserWithWindow(ash::wm::GetActiveWindow());
30690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  if (items.size() == 1) {
30790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // If there is only one suitable browser, we can either activate it, or
30890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // bounce it (if it is already active).
30990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (browser == items[0]) {
31090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      AnimateWindow(browser->window()->GetNativeWindow(),
311a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                    wm::WINDOW_ANIMATION_TYPE_BOUNCE);
31290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return;
31390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
31490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    browser = items[0];
31590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  } else {
31690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    // If there is more then one suitable browser, we advance to the next if
31758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // |browser| is already active - or - check the last used browser if it can
31858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    // be used.
31990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    std::vector<Browser*>::iterator i =
32090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        std::find(items.begin(), items.end(), browser);
32190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    if (i != items.end()) {
32290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      browser = (++i == items.end()) ? items[0] : *i;
32390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    } else {
3244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      browser = chrome::FindTabbedBrowser(launcher_controller()->profile(),
32590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                          true,
32690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                                          chrome::HOST_DESKTOP_TYPE_ASH);
32790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      if (!browser ||
32858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)          !IsBrowserRepresentedInBrowserList(browser))
32990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        browser = items[0];
33090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    }
33190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
33290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK(browser);
33390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  browser->window()->Show();
33490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  browser->window()->Activate();
33590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
33658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
33758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)bool BrowserShortcutLauncherItemController::IsBrowserRepresentedInBrowserList(
33858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    Browser* browser) {
3390529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // Only Ash desktop browser windows for the active user are represented.
3400529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (!browser ||
3410529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      !launcher_controller()->IsBrowserFromActiveUser(browser) ||
3420529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      browser->host_desktop_type() != chrome::HOST_DESKTOP_TYPE_ASH)
3430529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return false;
3440529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
3450529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // v1 App popup windows with a valid app id have their own icon.
3460529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (browser->is_app() &&
3470529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      browser->is_type_popup() &&
3480529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      launcher_controller()->GetShelfIDForAppID(
3490529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch          web_app::GetExtensionIdFromApplicationName(browser->app_name())) > 0)
3500529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return false;
3510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
3520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // Stand-alone chrome:// windows (e.g. settings) have their own icon.
3530529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  if (chrome::IsTrustedPopupWindowWithScheme(browser, content::kChromeUIScheme))
3540529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    return false;
3550529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch
3560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  // Tabbed browser and other popup windows are all represented.
3570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  return true;
35858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
359