Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / ash / launcher / browser_shortcut_launcher_item_controller.cc
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/shelf/shelf.h"
10 #include "ash/shelf/shelf_model.h"
11 #include "ash/shelf/shelf_util.h"
12 #include "ash/shell.h"
13 #include "ash/wm/window_util.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/ui/ash/launcher/chrome_launcher_app_menu_item.h"
16 #include "chrome/browser/ui/ash/launcher/chrome_launcher_app_menu_item_browser.h"
17 #include "chrome/browser/ui/ash/launcher/chrome_launcher_app_menu_item_tab.h"
18 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h"
19 #include "chrome/browser/ui/ash/launcher/launcher_application_menu_item_model.h"
20 #include "chrome/browser/ui/ash/launcher/launcher_context_menu.h"
21 #include "chrome/browser/ui/browser.h"
22 #include "chrome/browser/ui/browser_finder.h"
23 #include "chrome/browser/ui/browser_list.h"
24 #include "chrome/browser/ui/browser_window.h"
25 #include "chrome/browser/ui/chrome_pages.h"
26 #include "chrome/browser/ui/tabs/tab_strip_model.h"
27 #include "chrome/browser/web_applications/web_app.h"
28 #include "chrome/common/extensions/extension_constants.h"
29 #include "content/public/browser/web_contents.h"
30 #include "content/public/common/url_constants.h"
31 #include "grit/ash_resources.h"
32 #include "grit/chromium_strings.h"
33 #include "grit/generated_resources.h"
34 #include "ui/aura/window.h"
35 #include "ui/base/l10n/l10n_util.h"
36 #include "ui/base/resource/resource_bundle.h"
37 #include "ui/events/event.h"
38 #include "ui/gfx/image/image.h"
39 #include "ui/wm/core/window_animations.h"
40
41 BrowserShortcutLauncherItemController::BrowserShortcutLauncherItemController(
42     ChromeLauncherController* launcher_controller)
43     : LauncherItemController(TYPE_SHORTCUT,
44                              extension_misc::kChromeAppId,
45                              launcher_controller) {
46 }
47
48 BrowserShortcutLauncherItemController::
49     ~BrowserShortcutLauncherItemController() {
50 }
51
52 void BrowserShortcutLauncherItemController::UpdateBrowserItemState() {
53   // The shell will not be available for win7_aura unittests like
54   // ChromeLauncherControllerTest.BrowserMenuGeneration.
55   if (!ash::Shell::HasInstance())
56     return;
57
58   ash::ShelfModel* model = launcher_controller()->model();
59
60   // Determine the new browser's active state and change if necessary.
61   int browser_index = model->GetItemIndexForType(ash::TYPE_BROWSER_SHORTCUT);
62   DCHECK_GE(browser_index, 0);
63   ash::ShelfItem browser_item = model->items()[browser_index];
64   ash::ShelfItemStatus browser_status = ash::STATUS_CLOSED;
65
66   aura::Window* window = ash::wm::GetActiveWindow();
67   if (window) {
68     // Check if the active browser / tab is a browser which is not an app,
69     // a windowed app, a popup or any other item which is not a browser of
70     // interest.
71     Browser* browser = chrome::FindBrowserWithWindow(window);
72     if (IsBrowserRepresentedInBrowserList(browser)) {
73       browser_status = ash::STATUS_ACTIVE;
74       // If an app that has item is running in active WebContents, browser item
75       // status cannot be active.
76       content::WebContents* contents =
77           browser->tab_strip_model()->GetActiveWebContents();
78       if (contents &&
79           (launcher_controller()->GetShelfIDForWebContents(contents) !=
80               browser_item.id))
81         browser_status = ash::STATUS_RUNNING;
82     }
83   }
84
85   if (browser_status == ash::STATUS_CLOSED) {
86     const BrowserList* ash_browser_list =
87         BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH);
88     for (BrowserList::const_reverse_iterator it =
89              ash_browser_list->begin_last_active();
90          it != ash_browser_list->end_last_active() &&
91          browser_status == ash::STATUS_CLOSED; ++it) {
92       if (IsBrowserRepresentedInBrowserList(*it))
93         browser_status = ash::STATUS_RUNNING;
94     }
95   }
96
97   if (browser_status != browser_item.status) {
98     browser_item.status = browser_status;
99     model->Set(browser_index, browser_item);
100   }
101 }
102
103 void BrowserShortcutLauncherItemController::SetShelfIDForBrowserWindowContents(
104     Browser* browser,
105     content::WebContents* web_contents) {
106   if (!IsBrowserRepresentedInBrowserList(browser))
107     return;
108   ash::SetShelfIDForWindow(
109       launcher_controller()->GetShelfIDForWebContents(web_contents),
110       browser->window()->GetNativeWindow());
111 }
112
113 bool BrowserShortcutLauncherItemController::IsOpen() const {
114   const BrowserList* ash_browser_list =
115       BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH);
116   for (BrowserList::const_iterator it = ash_browser_list->begin();
117        it != ash_browser_list->end(); ++it) {
118     if (launcher_controller()->IsBrowserFromActiveUser(*it))
119       return true;
120   }
121   return false;
122 }
123
124 bool BrowserShortcutLauncherItemController::IsVisible() const {
125   Browser* last_browser = chrome::FindTabbedBrowser(
126       launcher_controller()->profile(),
127       true,
128       chrome::HOST_DESKTOP_TYPE_ASH);
129
130   if (!last_browser) {
131     return false;
132   }
133
134   aura::Window* window = last_browser->window()->GetNativeWindow();
135   return ash::wm::IsActiveWindow(window);
136 }
137
138 void BrowserShortcutLauncherItemController::Launch(ash::LaunchSource source,
139                                                    int event_flags) {
140 }
141
142 bool BrowserShortcutLauncherItemController::Activate(ash::LaunchSource source) {
143   Browser* last_browser = chrome::FindTabbedBrowser(
144       launcher_controller()->profile(),
145       true,
146       chrome::HOST_DESKTOP_TYPE_ASH);
147
148   if (!last_browser) {
149     launcher_controller()->CreateNewWindow();
150     return true;
151   }
152
153   launcher_controller()->ActivateWindowOrMinimizeIfActive(
154       last_browser->window(), GetApplicationList(0).size() == 2);
155   return false;
156 }
157
158 void BrowserShortcutLauncherItemController::Close() {
159 }
160
161 ChromeLauncherAppMenuItems
162 BrowserShortcutLauncherItemController::GetApplicationList(int event_flags) {
163   ChromeLauncherAppMenuItems items;
164   bool found_tabbed_browser = false;
165   // Add the application name to the menu.
166   items.push_back(new ChromeLauncherAppMenuItem(GetTitle(), NULL, false));
167   const BrowserList* ash_browser_list =
168       BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH);
169   for (BrowserList::const_iterator it = ash_browser_list->begin();
170        it != ash_browser_list->end(); ++it) {
171     Browser* browser = *it;
172     // Make sure that the browser was already shown, is from the current user
173     // and has a proper window.
174     if (!launcher_controller()->IsBrowserFromActiveUser(browser) ||
175         std::find(ash_browser_list->begin_last_active(),
176                   ash_browser_list->end_last_active(),
177                   browser) == ash_browser_list->end_last_active() ||
178         !browser->window())
179       continue;
180     if (browser->is_type_tabbed())
181       found_tabbed_browser = true;
182     else if (!IsBrowserRepresentedInBrowserList(browser))
183       continue;
184     TabStripModel* tab_strip = browser->tab_strip_model();
185     if (tab_strip->active_index() == -1)
186       continue;
187     if (!(event_flags & ui::EF_SHIFT_DOWN)) {
188       content::WebContents* web_contents =
189           tab_strip->GetWebContentsAt(tab_strip->active_index());
190       gfx::Image app_icon = GetBrowserListIcon(web_contents);
191       base::string16 title = GetBrowserListTitle(web_contents);
192       items.push_back(new ChromeLauncherAppMenuItemBrowser(
193           title, &app_icon, browser, items.size() == 1));
194     } else {
195       for (int index = 0; index  < tab_strip->count(); ++index) {
196         content::WebContents* web_contents =
197             tab_strip->GetWebContentsAt(index);
198         gfx::Image app_icon =
199             launcher_controller()->GetAppListIcon(web_contents);
200         base::string16 title =
201             launcher_controller()->GetAppListTitle(web_contents);
202         // Check if we need to insert a separator in front.
203         bool leading_separator = !index;
204         items.push_back(new ChromeLauncherAppMenuItemTab(
205             title, &app_icon, web_contents, leading_separator));
206       }
207     }
208   }
209   // If only windowed applications are open, we return an empty list to
210   // enforce the creation of a new browser.
211   if (!found_tabbed_browser)
212     items.clear();
213   return items.Pass();
214 }
215
216 bool BrowserShortcutLauncherItemController::ItemSelected(
217     const ui::Event& event) {
218   if (event.flags() & ui::EF_CONTROL_DOWN) {
219     launcher_controller()->CreateNewWindow();
220     return true;
221   }
222
223   // In case of a keyboard event, we were called by a hotkey. In that case we
224   // activate the next item in line if an item of our list is already active.
225   if (event.type() & ui::ET_KEY_RELEASED) {
226     ActivateOrAdvanceToNextBrowser();
227     return false;
228   }
229
230   return Activate(ash::LAUNCH_FROM_UNKNOWN);
231 }
232
233 base::string16 BrowserShortcutLauncherItemController::GetTitle() {
234   return l10n_util::GetStringUTF16(IDS_PRODUCT_NAME);
235 }
236
237 ui::MenuModel* BrowserShortcutLauncherItemController::CreateContextMenu(
238     aura::Window* root_window) {
239   ash::ShelfItem item =
240       *(launcher_controller()->model()->ItemByID(shelf_id()));
241   return new LauncherContextMenu(launcher_controller(), &item, root_window);
242 }
243
244 ash::ShelfMenuModel*
245 BrowserShortcutLauncherItemController::CreateApplicationMenu(int event_flags) {
246   return new LauncherApplicationMenuItemModel(GetApplicationList(event_flags));
247 }
248
249 bool BrowserShortcutLauncherItemController::IsDraggable() {
250   return launcher_controller()->CanPin() ? true : false;
251 }
252
253 bool BrowserShortcutLauncherItemController::ShouldShowTooltip() {
254   return true;
255 }
256
257 gfx::Image BrowserShortcutLauncherItemController::GetBrowserListIcon(
258     content::WebContents* web_contents) const {
259   ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
260   return rb.GetImageNamed(IsIncognito(web_contents) ?
261       IDR_ASH_SHELF_LIST_INCOGNITO_BROWSER :
262       IDR_ASH_SHELF_LIST_BROWSER);
263 }
264
265 base::string16 BrowserShortcutLauncherItemController::GetBrowserListTitle(
266     content::WebContents* web_contents) const {
267   base::string16 title = web_contents->GetTitle();
268   if (!title.empty())
269     return title;
270   return l10n_util::GetStringUTF16(IDS_NEW_TAB_TITLE);
271 }
272
273 bool BrowserShortcutLauncherItemController::IsIncognito(
274     content::WebContents* web_contents) const {
275   const Profile* profile =
276       Profile::FromBrowserContext(web_contents->GetBrowserContext());
277   return profile->IsOffTheRecord() && !profile->IsGuestSession();
278 }
279
280 void BrowserShortcutLauncherItemController::ActivateOrAdvanceToNextBrowser() {
281   // Create a list of all suitable running browsers.
282   std::vector<Browser*> items;
283   // We use the list in the order of how the browsers got created - not the LRU
284   // order.
285   const BrowserList* ash_browser_list =
286       BrowserList::GetInstance(chrome::HOST_DESKTOP_TYPE_ASH);
287   for (BrowserList::const_iterator it =
288            ash_browser_list->begin();
289        it != ash_browser_list->end(); ++it) {
290     if (IsBrowserRepresentedInBrowserList(*it))
291       items.push_back(*it);
292   }
293   // If there are no suitable browsers we create a new one.
294   if (items.empty()) {
295     launcher_controller()->CreateNewWindow();
296     return;
297   }
298   Browser* browser = chrome::FindBrowserWithWindow(ash::wm::GetActiveWindow());
299   if (items.size() == 1) {
300     // If there is only one suitable browser, we can either activate it, or
301     // bounce it (if it is already active).
302     if (browser == items[0]) {
303       AnimateWindow(browser->window()->GetNativeWindow(),
304                     wm::WINDOW_ANIMATION_TYPE_BOUNCE);
305       return;
306     }
307     browser = items[0];
308   } else {
309     // If there is more then one suitable browser, we advance to the next if
310     // |browser| is already active - or - check the last used browser if it can
311     // be used.
312     std::vector<Browser*>::iterator i =
313         std::find(items.begin(), items.end(), browser);
314     if (i != items.end()) {
315       browser = (++i == items.end()) ? items[0] : *i;
316     } else {
317       browser = chrome::FindTabbedBrowser(launcher_controller()->profile(),
318                                           true,
319                                           chrome::HOST_DESKTOP_TYPE_ASH);
320       if (!browser ||
321           !IsBrowserRepresentedInBrowserList(browser))
322         browser = items[0];
323     }
324   }
325   DCHECK(browser);
326   browser->window()->Show();
327   browser->window()->Activate();
328 }
329
330 bool BrowserShortcutLauncherItemController::IsBrowserRepresentedInBrowserList(
331     Browser* browser) {
332   // Only Ash desktop browser windows for the active user are represented.
333   if (!browser ||
334       !launcher_controller()->IsBrowserFromActiveUser(browser) ||
335       browser->host_desktop_type() != chrome::HOST_DESKTOP_TYPE_ASH)
336     return false;
337
338   // v1 App popup windows with a valid app id have their own icon.
339   if (browser->is_app() &&
340       browser->is_type_popup() &&
341       launcher_controller()->GetShelfIDForAppID(
342           web_app::GetExtensionIdFromApplicationName(browser->app_name())) > 0)
343     return false;
344
345   // Stand-alone chrome:// windows (e.g. settings) have their own icon.
346   if (chrome::IsTrustedPopupWindowWithScheme(browser, content::kChromeUIScheme))
347     return false;
348
349   // Tabbed browser and other popup windows are all represented.
350   return true;
351 }