blob: 48e666e5229c30fc5c905eb5355a37971ebf017c [file] [log] [blame]
[email protected]a37d4b02012-06-25 21:56:101// Copyright (c) 2012 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/browser_commands.h"
6
7#include "base/command_line.h"
8#include "base/metrics/histogram.h"
9#include "base/utf_string_conversions.h"
10#include "chrome/browser/bookmarks/bookmark_model.h"
11#include "chrome/browser/bookmarks/bookmark_utils.h"
12#include "chrome/browser/browser_process.h"
13#include "chrome/browser/chrome_page_zoom.h"
14#include "chrome/browser/debugger/devtools_window.h"
15#include "chrome/browser/extensions/extension_service.h"
16#include "chrome/browser/favicon/favicon_tab_helper.h"
17#include "chrome/browser/lifetime/application_lifetime.h"
18#include "chrome/browser/platform_util.h"
19#include "chrome/browser/prefs/incognito_mode_prefs.h"
20#include "chrome/browser/prefs/pref_service.h"
21#include "chrome/browser/printing/print_view_manager.h"
22#include "chrome/browser/profiles/profile.h"
23#include "chrome/browser/sessions/session_service_factory.h"
24#include "chrome/browser/sessions/tab_restore_service_factory.h"
25#include "chrome/browser/sessions/tab_restore_service.h"
26#include "chrome/browser/ui/browser.h"
27#include "chrome/browser/ui/browser_finder.h"
28#include "chrome/browser/ui/browser_window.h"
29#include "chrome/browser/ui/find_bar/find_bar_controller.h"
30#include "chrome/browser/ui/find_bar/find_tab_helper.h"
31#include "chrome/browser/ui/omnibox/location_bar.h"
32#include "chrome/browser/ui/status_bubble.h"
33#include "chrome/browser/ui/tab_contents/tab_contents.h"
34#include "chrome/browser/ui/tabs/tab_strip_model.h"
35#include "chrome/browser/ui/webui/feedback_ui.h"
36#include "chrome/browser/ui/webui/ntp/app_launcher_handler.h"
37#include "chrome/common/chrome_switches.h"
38#include "chrome/common/net/url_util.h"
39#include "chrome/common/pref_names.h"
40#include "content/public/browser/navigation_controller.h"
41#include "content/public/browser/navigation_entry.h"
42#include "content/public/browser/page_navigator.h"
43#include "content/public/browser/render_view_host.h"
44#include "content/public/browser/user_metrics.h"
45#include "content/public/browser/web_contents.h"
46#include "content/public/browser/web_contents_view.h"
47#include "net/base/escape.h"
48
49#if defined(OS_MACOSX)
50#include "ui/base/cocoa/find_pasteboard.h"
51#endif
52
53#if defined(OS_WIN)
54#include "base/win/metro.h"
55#endif
56
57using content::NavigationController;
58using content::NavigationEntry;
59using content::OpenURLParams;
60using content::Referrer;
61using content::SSLStatus;
62using content::UserMetricsAction;
63using content::WebContents;
64
65namespace chrome {
66namespace {
67
68WebContents* GetOrCloneTabForDisposition(Browser* browser,
69 WindowOpenDisposition disposition) {
70 TabContents* current_tab = browser->GetActiveTabContents();
71 switch (disposition) {
72 case NEW_FOREGROUND_TAB:
73 case NEW_BACKGROUND_TAB: {
74 current_tab = current_tab->Clone();
75 browser->tab_strip_model()->AddTabContents(
76 current_tab, -1, content::PAGE_TRANSITION_LINK,
77 disposition == NEW_FOREGROUND_TAB ? TabStripModel::ADD_ACTIVE :
78 TabStripModel::ADD_NONE);
79 break;
80 }
81 case NEW_WINDOW: {
82 current_tab = current_tab->Clone();
83 Browser* b = Browser::Create(browser->profile());
84 b->tab_strip_model()->AddTabContents(
85 current_tab, -1, content::PAGE_TRANSITION_LINK,
86 TabStripModel::ADD_ACTIVE);
87 b->window()->Show();
88 break;
89 }
90 default:
91 break;
92 }
93 return current_tab->web_contents();
94}
95
96void ReloadInternal(Browser* browser,
97 WindowOpenDisposition disposition,
98 bool ignore_cache) {
99 // If we are showing an interstitial, treat this as an OpenURL.
100 WebContents* current_tab = browser->GetActiveWebContents();
101 if (current_tab && current_tab->ShowingInterstitialPage()) {
102 NavigationEntry* entry = current_tab->GetController().GetActiveEntry();
103 DCHECK(entry); // Should exist if interstitial is showing.
104 browser->OpenURL(OpenURLParams(
105 entry->GetURL(), Referrer(), disposition,
106 content::PAGE_TRANSITION_RELOAD, false));
107 return;
108 }
109
110 // As this is caused by a user action, give the focus to the page.
111 //
112 // Also notify RenderViewHostDelegate of the user gesture; this is
113 // normally done in Browser::Navigate, but a reload bypasses Navigate.
114 WebContents* web_contents = GetOrCloneTabForDisposition(browser, disposition);
115 web_contents->UserGestureDone();
116 if (!web_contents->FocusLocationBarByDefault())
117 web_contents->Focus();
118 if (ignore_cache)
119 web_contents->GetController().ReloadIgnoringCache(true);
120 else
121 web_contents->GetController().Reload(true);
122}
123
124} // namespace
125
126void NewEmptyWindow(Profile* profile) {
127 bool incognito = profile->IsOffTheRecord();
128 PrefService* prefs = profile->GetPrefs();
129 if (incognito) {
130 if (IncognitoModePrefs::GetAvailability(prefs) ==
131 IncognitoModePrefs::DISABLED) {
132 incognito = false;
133 }
134 } else {
135 if (browser_defaults::kAlwaysOpenIncognitoWindow &&
136 IncognitoModePrefs::ShouldLaunchIncognito(
137 *CommandLine::ForCurrentProcess(), prefs)) {
138 incognito = true;
139 }
140 }
141
142 if (incognito) {
143 content::RecordAction(UserMetricsAction("NewIncognitoWindow"));
144 OpenEmptyWindow(profile->GetOffTheRecordProfile());
145 } else {
146 content::RecordAction(UserMetricsAction("NewWindow"));
147 SessionService* session_service =
148 SessionServiceFactory::GetForProfile(profile->GetOriginalProfile());
149 if (!session_service ||
150 !session_service->RestoreIfNecessary(std::vector<GURL>())) {
151 OpenEmptyWindow(profile->GetOriginalProfile());
152 }
153 }
154}
155
156Browser* OpenEmptyWindow(Profile* profile) {
157 Browser* browser = Browser::Create(profile);
158 browser->AddBlankTab(true);
159 browser->window()->Show();
160 return browser;
161}
162
163void OpenWindowWithRestoredTabs(Profile* profile) {
164 TabRestoreService* service = TabRestoreServiceFactory::GetForProfile(profile);
165 if (service)
166 service->RestoreMostRecentEntry(NULL);
167}
168
169void OpenURLOffTheRecord(Profile* profile, const GURL& url) {
170 Browser* browser = browser::FindOrCreateTabbedBrowser(
171 profile->GetOffTheRecordProfile());
172 browser->AddSelectedTabWithURL(url, content::PAGE_TRANSITION_LINK);
173 browser->window()->Show();
174}
175
176bool CanGoBack(Browser* browser) {
177 return browser->GetActiveWebContents()->GetController().CanGoBack();
178}
179
180void GoBack(Browser* browser, WindowOpenDisposition disposition) {
181 content::RecordAction(UserMetricsAction("Back"));
182
183 TabContents* current_tab = browser->GetActiveTabContents();
184 if (CanGoBack(browser)) {
185 WebContents* new_tab = GetOrCloneTabForDisposition(browser, disposition);
186 // If we are on an interstitial page and clone the tab, it won't be copied
187 // to the new tab, so we don't need to go back.
188 if (current_tab->web_contents()->ShowingInterstitialPage() &&
189 (new_tab != current_tab->web_contents()))
190 return;
191 new_tab->GetController().GoBack();
192 }
193}
194
195bool CanGoForward(Browser* browser) {
196 return browser->GetActiveWebContents()->GetController().CanGoForward();
197}
198
199void GoForward(Browser* browser, WindowOpenDisposition disposition) {
200 content::RecordAction(UserMetricsAction("Forward"));
201 if (CanGoForward(browser)) {
202 GetOrCloneTabForDisposition(browser, disposition)->
203 GetController().GoForward();
204 }
205}
206
207bool NavigateToIndexWithDisposition(Browser* browser,
208 int index,
209 WindowOpenDisposition disp) {
210 NavigationController& controller =
211 GetOrCloneTabForDisposition(browser, disp)->GetController();
212 if (index < 0 || index >= controller.GetEntryCount())
213 return false;
214 controller.GoToIndex(index);
215 return true;
216}
217
218void Reload(Browser* browser, WindowOpenDisposition disposition) {
219 content::RecordAction(UserMetricsAction("Reload"));
220 ReloadInternal(browser, disposition, false);
221}
222
223void ReloadIgnoringCache(Browser* browser, WindowOpenDisposition disposition) {
224 content::RecordAction(UserMetricsAction("ReloadIgnoringCache"));
225 ReloadInternal(browser, disposition, true);
226}
227
228void Home(Browser* browser, WindowOpenDisposition disposition) {
229 content::RecordAction(UserMetricsAction("Home"));
230 browser->OpenURL(OpenURLParams(
231 browser->profile()->GetHomePage(), Referrer(), disposition,
232 content::PageTransitionFromInt(
233 content::PAGE_TRANSITION_AUTO_BOOKMARK |
234 content::PAGE_TRANSITION_HOME_PAGE),
235 false));
236}
237
238void OpenCurrentURL(Browser* browser) {
239 content::RecordAction(UserMetricsAction("LoadURL"));
240 LocationBar* location_bar = browser->window()->GetLocationBar();
241 if (!location_bar)
242 return;
243
244 WindowOpenDisposition open_disposition =
245 location_bar->GetWindowOpenDisposition();
246 if (browser->OpenInstant(open_disposition))
247 return;
248
249 GURL url(location_bar->GetInputString());
250
251 browser::NavigateParams params(browser, url,
252 location_bar->GetPageTransition());
253 params.disposition = open_disposition;
254 // Use ADD_INHERIT_OPENER so that all pages opened by the omnibox at least
255 // inherit the opener. In some cases the tabstrip will determine the group
256 // should be inherited, in which case the group is inherited instead of the
257 // opener.
258 params.tabstrip_add_types =
259 TabStripModel::ADD_FORCE_INDEX | TabStripModel::ADD_INHERIT_OPENER;
260 browser::Navigate(&params);
261
262 DCHECK(browser->profile()->GetExtensionService());
263 if (browser->profile()->GetExtensionService()->IsInstalledApp(url)) {
264 AppLauncherHandler::RecordAppLaunchType(
265 extension_misc::APP_LAUNCH_OMNIBOX_LOCATION);
266 }
267}
268
269void Stop(Browser* browser) {
270 content::RecordAction(UserMetricsAction("Stop"));
271 browser->GetActiveWebContents()->Stop();
272}
273
274#if !defined(OS_WIN)
275void NewWindow(Browser* browser) {
276 NewEmptyWindow(browser->profile()->GetOriginalProfile());
277}
278
279void NewIncognitoWindow(Browser* browser) {
280 NewEmptyWindow(browser->profile()->GetOffTheRecordProfile());
281}
282#endif // OS_WIN
283
284void CloseWindow(Browser* browser) {
285 content::RecordAction(UserMetricsAction("CloseWindow"));
286 browser->window()->Close();
287}
288
289void NewTab(Browser* browser) {
290 content::RecordAction(UserMetricsAction("NewTab"));
291 // TODO(asvitkine): This is invoked programmatically from several places.
292 // Audit the code and change it so that the histogram only gets collected for
293 // user-initiated commands.
294 UMA_HISTOGRAM_ENUMERATION("Tab.NewTab", TabStripModel::NEW_TAB_COMMAND,
295 TabStripModel::NEW_TAB_ENUM_COUNT);
296
297 if (browser->is_type_tabbed()) {
298 browser->AddBlankTab(true);
299 browser->GetActiveWebContents()->GetView()->RestoreFocus();
300 } else {
301 Browser* b = browser::FindOrCreateTabbedBrowser(browser->profile());
302 b->AddBlankTab(true);
303 b->window()->Show();
304 // The call to AddBlankTab above did not set the focus to the tab as its
305 // window was not active, so we have to do it explicitly.
306 // See http://crbug.com/6380.
307 b->GetActiveWebContents()->GetView()->RestoreFocus();
308 }
309}
310
311void CloseTab(Browser* browser) {
312 content::RecordAction(UserMetricsAction("CloseTab_Accelerator"));
313 browser->tab_strip_model()->CloseSelectedTabs();
314}
315
316void SelectNextTab(Browser* browser) {
317 content::RecordAction(UserMetricsAction("SelectNextTab"));
318 browser->tab_strip_model()->SelectNextTab();
319}
320
321void SelectPreviousTab(Browser* browser) {
322 content::RecordAction(UserMetricsAction("SelectPrevTab"));
323 browser->tab_strip_model()->SelectPreviousTab();
324}
325
326void OpenTabpose(Browser* browser) {
327#if defined(OS_MACOSX)
328 if (!CommandLine::ForCurrentProcess()->HasSwitch(
329 switches::kEnableExposeForTabs)) {
330 return;
331 }
332
333 content::RecordAction(UserMetricsAction("OpenTabpose"));
334 browser->window()->OpenTabpose();
335#else
336 NOTREACHED();
337#endif
338}
339
340void MoveTabNext(Browser* browser) {
341 content::RecordAction(UserMetricsAction("MoveTabNext"));
342 browser->tab_strip_model()->MoveTabNext();
343}
344
345void MoveTabPrevious(Browser* browser) {
346 content::RecordAction(UserMetricsAction("MoveTabPrevious"));
347 browser->tab_strip_model()->MoveTabPrevious();
348}
349
350void SelectNumberedTab(Browser* browser, int index) {
351 if (index < browser->tab_count()) {
352 content::RecordAction(UserMetricsAction("SelectNumberedTab"));
353 browser->ActivateTabAt(index, true);
354 }
355}
356
357void SelectLastTab(Browser* browser) {
358 content::RecordAction(UserMetricsAction("SelectLastTab"));
359 browser->tab_strip_model()->SelectLastTab();
360}
361
362void DuplicateTab(Browser* browser) {
363 content::RecordAction(UserMetricsAction("Duplicate"));
364 browser->DuplicateContentsAt(browser->active_index());
365}
366
367void WriteCurrentURLToClipboard(Browser* browser) {
368 // TODO(ericu): There isn't currently a metric for this. Should there be?
369 // We don't appear to track the action when it comes from the
370 // RenderContextViewMenu.
371
372 WebContents* contents = browser->GetActiveWebContents();
373 if (!browser->toolbar_model()->ShouldDisplayURL())
374 return;
375
376 chrome_common_net::WriteURLToClipboard(
377 contents->GetURL(),
378 browser->profile()->GetPrefs()->GetString(prefs::kAcceptLanguages),
379 g_browser_process->clipboard());
380}
381
382void ConvertPopupToTabbedBrowser(Browser* browser) {
383 content::RecordAction(UserMetricsAction("ShowAsTab"));
384 TabContents* contents =
385 browser->tab_strip_model()->DetachTabContentsAt(browser->active_index());
386 Browser* b = Browser::Create(browser->profile());
387 b->tab_strip_model()->AppendTabContents(contents, true);
388 b->window()->Show();
389}
390
391void Exit() {
392 content::RecordAction(UserMetricsAction("Exit"));
393 browser::AttemptUserExit();
394}
395
396void BookmarkCurrentPage(Browser* browser) {
397 content::RecordAction(UserMetricsAction("Star"));
398
399 BookmarkModel* model = browser->profile()->GetBookmarkModel();
400 if (!model || !model->IsLoaded())
401 return; // Ignore requests until bookmarks are loaded.
402
403 GURL url;
404 string16 title;
405 TabContents* tab = browser->GetActiveTabContents();
406 bookmark_utils::GetURLAndTitleToBookmark(tab->web_contents(), &url, &title);
407 bool was_bookmarked = model->IsBookmarked(url);
408 if (!was_bookmarked && browser->profile()->IsOffTheRecord()) {
409 // If we're incognito the favicon may not have been saved. Save it now
410 // so that bookmarks have an icon for the page.
411 tab->favicon_tab_helper()->SaveFavicon();
412 }
413 bookmark_utils::AddIfNotBookmarked(model, url, title);
414 // Make sure the model actually added a bookmark before showing the star. A
415 // bookmark isn't created if the url is invalid.
416 if (browser->window()->IsActive() && model->IsBookmarked(url)) {
417 // Only show the bubble if the window is active, otherwise we may get into
418 // weird situations where the bubble is deleted as soon as it is shown.
419 browser->window()->ShowBookmarkBubble(url, was_bookmarked);
420 }
421}
422
423#if !defined(OS_WIN)
424void PinCurrentPageToStartScreen(Browser* browser) {
425}
426#endif
427
428void SavePage(Browser* browser) {
429 content::RecordAction(UserMetricsAction("SavePage"));
430 WebContents* current_tab = browser->GetActiveWebContents();
431 if (current_tab && current_tab->GetContentsMimeType() == "application/pdf")
432 content::RecordAction(UserMetricsAction("PDF.SavePage"));
433 current_tab->OnSavePage();
434}
435
436void ShowFindBar(Browser* browser) {
437 browser->GetFindBarController()->Show();
438}
439
440void ShowPageInfo(Browser* browser,
441 content::WebContents* web_contents,
442 const GURL& url,
443 const SSLStatus& ssl,
444 bool show_history) {
445 Profile* profile = Profile::FromBrowserContext(
446 web_contents->GetBrowserContext());
447 TabContents* tab_contents = TabContents::FromWebContents(web_contents);
448
449 if (CommandLine::ForCurrentProcess()->HasSwitch(
450 switches::kEnableWebsiteSettings)) {
451 browser->window()->ShowWebsiteSettings(
452 profile, tab_contents, url, ssl, show_history);
453 } else {
454 browser->window()->ShowPageInfo(web_contents, url, ssl, show_history);
455 }
456}
457
458void ShowChromeToMobileBubble(Browser* browser) {
459 // Only show the bubble if the window is active, otherwise we may get into
460 // weird situations where the bubble is deleted as soon as it is shown.
461 if (browser->window()->IsActive())
462 browser->window()->ShowChromeToMobileBubble();
463}
464
465void Print(Browser* browser) {
466 if (g_browser_process->local_state()->GetBoolean(
467 prefs::kPrintPreviewDisabled)) {
468 browser->GetActiveTabContents()->print_view_manager()->PrintNow();
469 } else {
470 browser->GetActiveTabContents()->print_view_manager()->PrintPreviewNow();
471 }
472}
473
474void AdvancedPrint(Browser* browser) {
475 browser->GetActiveTabContents()->print_view_manager()->AdvancedPrintNow();
476}
477
478void EmailPageLocation(Browser* browser) {
479 content::RecordAction(UserMetricsAction("EmailPageLocation"));
480 WebContents* wc = browser->GetActiveWebContents();
481 DCHECK(wc);
482
483 std::string title = net::EscapeQueryParamValue(
484 UTF16ToUTF8(wc->GetTitle()), false);
485 std::string page_url = net::EscapeQueryParamValue(wc->GetURL().spec(), false);
486 std::string mailto = std::string("mailto:?subject=Fwd:%20") +
487 title + "&body=%0A%0A" + page_url;
488 platform_util::OpenExternal(GURL(mailto));
489}
490
491void Cut(Browser* browser) {
492 content::RecordAction(UserMetricsAction("Cut"));
493 browser->window()->Cut();
494}
495
496void Copy(Browser* browser) {
497 content::RecordAction(UserMetricsAction("Copy"));
498 browser->window()->Copy();
499}
500
501void Paste(Browser* browser) {
502 content::RecordAction(UserMetricsAction("Paste"));
503 browser->window()->Paste();
504}
505
506void Find(Browser* browser) {
507 content::RecordAction(UserMetricsAction("Find"));
508 FindInPage(browser, false, false);
509}
510
511void FindNext(Browser* browser) {
512 content::RecordAction(UserMetricsAction("FindNext"));
513 FindInPage(browser, true, true);
514}
515
516void FindPrevious(Browser* browser) {
517 content::RecordAction(UserMetricsAction("FindPrevious"));
518 FindInPage(browser, true, false);
519}
520
521void FindInPage(Browser* browser, bool find_next, bool forward_direction) {
522 ShowFindBar(browser);
523 if (find_next) {
524 string16 find_text;
525#if defined(OS_MACOSX)
526 // We always want to search for the contents of the find pasteboard on OS X.
527 find_text = GetFindPboardText();
528#endif
529 browser->GetActiveTabContents()->
530 find_tab_helper()->StartFinding(find_text,
531 forward_direction,
532 false); // Not case sensitive.
533 }
534}
535
536void Zoom(Browser* browser, content::PageZoom zoom) {
537 if (browser->is_devtools())
538 return;
539
540 content::RenderViewHost* host =
541 browser->GetActiveWebContents()->GetRenderViewHost();
542 if (zoom == content::PAGE_ZOOM_RESET) {
543 host->SetZoomLevel(0);
544 content::RecordAction(UserMetricsAction("ZoomNormal"));
545 return;
546 }
547
548 double current_zoom_level = browser->GetActiveWebContents()->GetZoomLevel();
549 double default_zoom_level =
550 browser->profile()->GetPrefs()->GetDouble(prefs::kDefaultZoomLevel);
551
552 // Generate a vector of zoom levels from an array of known presets along with
553 // the default level added if necessary.
554 std::vector<double> zoom_levels =
555 chrome_page_zoom::PresetZoomLevels(default_zoom_level);
556
557 if (zoom == content::PAGE_ZOOM_OUT) {
558 // Iterate through the zoom levels in reverse order to find the next
559 // lower level based on the current zoom level for this page.
560 for (std::vector<double>::reverse_iterator i = zoom_levels.rbegin();
561 i != zoom_levels.rend(); ++i) {
562 double zoom_level = *i;
563 if (content::ZoomValuesEqual(zoom_level, current_zoom_level))
564 continue;
565 if (zoom_level < current_zoom_level) {
566 host->SetZoomLevel(zoom_level);
567 content::RecordAction(UserMetricsAction("ZoomMinus"));
568 return;
569 }
570 content::RecordAction(UserMetricsAction("ZoomMinus_AtMinimum"));
571 }
572 } else {
573 // Iterate through the zoom levels in normal order to find the next
574 // higher level based on the current zoom level for this page.
575 for (std::vector<double>::const_iterator i = zoom_levels.begin();
576 i != zoom_levels.end(); ++i) {
577 double zoom_level = *i;
578 if (content::ZoomValuesEqual(zoom_level, current_zoom_level))
579 continue;
580 if (zoom_level > current_zoom_level) {
581 host->SetZoomLevel(zoom_level);
582 content::RecordAction(UserMetricsAction("ZoomPlus"));
583 return;
584 }
585 }
586 content::RecordAction(UserMetricsAction("ZoomPlus_AtMaximum"));
587 }
588}
589
590void FocusToolbar(Browser* browser) {
591 content::RecordAction(UserMetricsAction("FocusToolbar"));
592 browser->window()->FocusToolbar();
593}
594
595void FocusLocationBar(Browser* browser) {
596 content::RecordAction(UserMetricsAction("FocusLocation"));
597 browser->window()->SetFocusToLocationBar(true);
598}
599
600void FocusSearch(Browser* browser) {
601 // TODO(beng): replace this with FocusLocationBar
602 content::RecordAction(UserMetricsAction("FocusSearch"));
603 browser->window()->GetLocationBar()->FocusSearch();
604}
605
606void FocusAppMenu(Browser* browser) {
607 content::RecordAction(UserMetricsAction("FocusAppMenu"));
608 browser->window()->FocusAppMenu();
609}
610
611void FocusBookmarksToolbar(Browser* browser) {
612 content::RecordAction(UserMetricsAction("FocusBookmarksToolbar"));
613 browser->window()->FocusBookmarksToolbar();
614}
615
616void FocusNextPane(Browser* browser) {
617 content::RecordAction(UserMetricsAction("FocusNextPane"));
618 browser->window()->RotatePaneFocus(true);
619}
620
621void FocusPreviousPane(Browser* browser) {
622 content::RecordAction(UserMetricsAction("FocusPreviousPane"));
623 browser->window()->RotatePaneFocus(false);
624}
625
626void ToggleDevToolsWindow(Browser* browser, DevToolsToggleAction action) {
627 if (action == DEVTOOLS_TOGGLE_ACTION_SHOW_CONSOLE)
628 content::RecordAction(UserMetricsAction("DevTools_ToggleConsole"));
629 else
630 content::RecordAction(UserMetricsAction("DevTools_ToggleWindow"));
631
632 DevToolsWindow::ToggleDevToolsWindow(
633 browser->GetActiveWebContents()->GetRenderViewHost(),
634 action);
635}
636
637bool CanOpenTaskManager() {
638#if defined(OS_WIN)
639 // In metro we can't display the task manager, as it is a native window.
640 return !base::win::IsMetroProcess();
641#else
642 return true;
643#endif
644}
645
646void OpenTaskManager(Browser* browser, bool highlight_background_resources) {
647 content::RecordAction(UserMetricsAction("TaskManager"));
648 if (highlight_background_resources)
649 browser->window()->ShowBackgroundPages();
650 else
651 browser->window()->ShowTaskManager();
652}
653
654void OpenFeedbackDialog(Browser* browser) {
655 content::RecordAction(UserMetricsAction("Feedback"));
656 browser::ShowWebFeedbackView(browser, std::string(), std::string());
657}
658
659void ToggleBookmarkBar(Browser* browser) {
660 content::RecordAction(UserMetricsAction("ShowBookmarksBar"));
661 browser->window()->ToggleBookmarkBar();
662}
663
664void ShowAppMenu(Browser* browser) {
665 // We record the user metric for this event in WrenchMenu::RunMenu.
666 browser->window()->ShowAppMenu();
667}
668
669void ShowAvatarMenu(Browser* browser) {
670 browser->window()->ShowAvatarBubbleFromAvatarButton();
671}
672
673void OpenUpdateChromeDialog(Browser* browser) {
674 content::RecordAction(UserMetricsAction("UpdateChrome"));
675 browser->window()->ShowUpdateChromeDialog();
676}
677
678void ToggleSpeechInput(Browser* browser) {
679 browser->GetActiveWebContents()->GetRenderViewHost()->ToggleSpeechInput();
680}
681
682} // namespace chrome