blob: 2b3f4685536bd9a86082c7a453ee560e0fc87256 [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"
[email protected]5d98294912012-06-27 22:57:4010#include "chrome/browser/bookmarks/bookmark_editor.h"
[email protected]a37d4b02012-06-25 21:56:1011#include "chrome/browser/bookmarks/bookmark_model.h"
12#include "chrome/browser/bookmarks/bookmark_utils.h"
13#include "chrome/browser/browser_process.h"
14#include "chrome/browser/chrome_page_zoom.h"
15#include "chrome/browser/debugger/devtools_window.h"
[email protected]5d98294912012-06-27 22:57:4016#include "chrome/browser/download/download_util.h"
[email protected]a37d4b02012-06-25 21:56:1017#include "chrome/browser/extensions/extension_service.h"
18#include "chrome/browser/favicon/favicon_tab_helper.h"
19#include "chrome/browser/lifetime/application_lifetime.h"
20#include "chrome/browser/platform_util.h"
21#include "chrome/browser/prefs/incognito_mode_prefs.h"
22#include "chrome/browser/prefs/pref_service.h"
[email protected]5d98294912012-06-27 22:57:4023#include "chrome/browser/printing/print_preview_tab_controller.h"
[email protected]a37d4b02012-06-25 21:56:1024#include "chrome/browser/printing/print_view_manager.h"
25#include "chrome/browser/profiles/profile.h"
26#include "chrome/browser/sessions/session_service_factory.h"
27#include "chrome/browser/sessions/tab_restore_service_factory.h"
28#include "chrome/browser/sessions/tab_restore_service.h"
[email protected]5d98294912012-06-27 22:57:4029#include "chrome/browser/sessions/tab_restore_service_delegate.h"
[email protected]a37d4b02012-06-25 21:56:1030#include "chrome/browser/ui/browser.h"
[email protected]5d98294912012-06-27 22:57:4031#include "chrome/browser/ui/browser_command_controller.h"
[email protected]a37d4b02012-06-25 21:56:1032#include "chrome/browser/ui/browser_finder.h"
[email protected]5d98294912012-06-27 22:57:4033#include "chrome/browser/ui/browser_tab_restore_service_delegate.h"
[email protected]a37d4b02012-06-25 21:56:1034#include "chrome/browser/ui/browser_window.h"
[email protected]5d98294912012-06-27 22:57:4035#include "chrome/browser/ui/constrained_window_tab_helper.h"
[email protected]a37d4b02012-06-25 21:56:1036#include "chrome/browser/ui/find_bar/find_bar_controller.h"
37#include "chrome/browser/ui/find_bar/find_tab_helper.h"
38#include "chrome/browser/ui/omnibox/location_bar.h"
39#include "chrome/browser/ui/status_bubble.h"
40#include "chrome/browser/ui/tab_contents/tab_contents.h"
41#include "chrome/browser/ui/tabs/tab_strip_model.h"
42#include "chrome/browser/ui/webui/feedback_ui.h"
43#include "chrome/browser/ui/webui/ntp/app_launcher_handler.h"
[email protected]5d98294912012-06-27 22:57:4044#include "chrome/browser/web_applications/web_app.h"
[email protected]a37d4b02012-06-25 21:56:1045#include "chrome/common/chrome_switches.h"
46#include "chrome/common/net/url_util.h"
47#include "chrome/common/pref_names.h"
[email protected]5d98294912012-06-27 22:57:4048#include "content/public/common/content_restriction.h"
[email protected]a37d4b02012-06-25 21:56:1049#include "content/public/browser/navigation_controller.h"
50#include "content/public/browser/navigation_entry.h"
51#include "content/public/browser/page_navigator.h"
52#include "content/public/browser/render_view_host.h"
53#include "content/public/browser/user_metrics.h"
54#include "content/public/browser/web_contents.h"
55#include "content/public/browser/web_contents_view.h"
[email protected]2cd4fde2012-06-26 03:10:2656#include "content/public/common/url_constants.h"
[email protected]a37d4b02012-06-25 21:56:1057#include "net/base/escape.h"
[email protected]2cd4fde2012-06-26 03:10:2658#include "webkit/glue/webkit_glue.h"
[email protected]a37d4b02012-06-25 21:56:1059
60#if defined(OS_MACOSX)
61#include "ui/base/cocoa/find_pasteboard.h"
62#endif
63
64#if defined(OS_WIN)
65#include "base/win/metro.h"
66#endif
67
68using content::NavigationController;
69using content::NavigationEntry;
70using content::OpenURLParams;
71using content::Referrer;
72using content::SSLStatus;
73using content::UserMetricsAction;
74using content::WebContents;
75
76namespace chrome {
77namespace {
78
79WebContents* GetOrCloneTabForDisposition(Browser* browser,
80 WindowOpenDisposition disposition) {
81 TabContents* current_tab = browser->GetActiveTabContents();
82 switch (disposition) {
83 case NEW_FOREGROUND_TAB:
84 case NEW_BACKGROUND_TAB: {
85 current_tab = current_tab->Clone();
86 browser->tab_strip_model()->AddTabContents(
87 current_tab, -1, content::PAGE_TRANSITION_LINK,
88 disposition == NEW_FOREGROUND_TAB ? TabStripModel::ADD_ACTIVE :
89 TabStripModel::ADD_NONE);
90 break;
91 }
92 case NEW_WINDOW: {
93 current_tab = current_tab->Clone();
94 Browser* b = Browser::Create(browser->profile());
95 b->tab_strip_model()->AddTabContents(
96 current_tab, -1, content::PAGE_TRANSITION_LINK,
97 TabStripModel::ADD_ACTIVE);
98 b->window()->Show();
99 break;
100 }
101 default:
102 break;
103 }
104 return current_tab->web_contents();
105}
106
107void ReloadInternal(Browser* browser,
108 WindowOpenDisposition disposition,
109 bool ignore_cache) {
110 // If we are showing an interstitial, treat this as an OpenURL.
111 WebContents* current_tab = browser->GetActiveWebContents();
112 if (current_tab && current_tab->ShowingInterstitialPage()) {
113 NavigationEntry* entry = current_tab->GetController().GetActiveEntry();
114 DCHECK(entry); // Should exist if interstitial is showing.
115 browser->OpenURL(OpenURLParams(
116 entry->GetURL(), Referrer(), disposition,
117 content::PAGE_TRANSITION_RELOAD, false));
118 return;
119 }
120
121 // As this is caused by a user action, give the focus to the page.
122 //
123 // Also notify RenderViewHostDelegate of the user gesture; this is
124 // normally done in Browser::Navigate, but a reload bypasses Navigate.
125 WebContents* web_contents = GetOrCloneTabForDisposition(browser, disposition);
126 web_contents->UserGestureDone();
127 if (!web_contents->FocusLocationBarByDefault())
128 web_contents->Focus();
129 if (ignore_cache)
130 web_contents->GetController().ReloadIgnoringCache(true);
131 else
132 web_contents->GetController().Reload(true);
133}
134
[email protected]5d98294912012-06-27 22:57:40135bool HasConstrainedWindow(const Browser* browser) {
136 TabContents* tab_contents = browser->GetActiveTabContents();
137 return tab_contents && tab_contents->constrained_window_tab_helper()->
138 constrained_window_count();
139}
140
141bool PrintPreviewShowing(const Browser* browser) {
142 TabContents* contents = browser->GetActiveTabContents();
143 printing::PrintPreviewTabController* controller =
144 printing::PrintPreviewTabController::GetInstance();
145 return controller && (controller->GetPrintPreviewForTab(contents) ||
146 controller->is_creating_print_preview_tab());
147}
148
[email protected]a37d4b02012-06-25 21:56:10149} // namespace
150
[email protected]5d98294912012-06-27 22:57:40151bool IsCommandEnabled(Browser* browser, int command) {
152 return browser->command_controller()->command_updater()->IsCommandEnabled(
153 command);
154}
155
156bool SupportsCommand(Browser* browser, int command) {
157 return browser->command_controller()->command_updater()->SupportsCommand(
158 command);
159}
160
161bool ExecuteCommand(Browser* browser, int command) {
162 return browser->command_controller()->command_updater()->ExecuteCommand(
163 command);
164}
165
166bool ExecuteCommandWithDisposition(Browser* browser,
167 int command,
168 WindowOpenDisposition disposition) {
169 return browser->command_controller()->command_updater()->
170 ExecuteCommandWithDisposition(command, disposition);
171}
172
173void UpdateCommandEnabled(Browser* browser, int command, bool enabled) {
174 browser->command_controller()->command_updater()->UpdateCommandEnabled(
175 command, enabled);
176}
177
178void AddCommandObserver(Browser* browser,
179 int command,
180 CommandObserver* observer) {
181 browser->command_controller()->command_updater()->AddCommandObserver(
182 command, observer);
183}
184
185void RemoveCommandObserver(Browser* browser,
186 int command,
187 CommandObserver* observer) {
188 browser->command_controller()->command_updater()->RemoveCommandObserver(
189 command, observer);
190}
191
192int GetContentRestrictions(const Browser* browser) {
193 int content_restrictions = 0;
194 WebContents* current_tab = browser->GetActiveWebContents();
195 if (current_tab) {
196 content_restrictions = current_tab->GetContentRestrictions();
197 NavigationEntry* active_entry =
198 current_tab->GetController().GetActiveEntry();
199 // See comment in UpdateCommandsForTabState about why we call url().
200 if (!download_util::IsSavableURL(
201 active_entry ? active_entry->GetURL() : GURL()) ||
202 current_tab->ShowingInterstitialPage())
203 content_restrictions |= content::CONTENT_RESTRICTION_SAVE;
204 if (current_tab->ShowingInterstitialPage())
205 content_restrictions |= content::CONTENT_RESTRICTION_PRINT;
206 }
207 return content_restrictions;
208}
209
[email protected]a37d4b02012-06-25 21:56:10210void NewEmptyWindow(Profile* profile) {
211 bool incognito = profile->IsOffTheRecord();
212 PrefService* prefs = profile->GetPrefs();
213 if (incognito) {
214 if (IncognitoModePrefs::GetAvailability(prefs) ==
215 IncognitoModePrefs::DISABLED) {
216 incognito = false;
217 }
218 } else {
219 if (browser_defaults::kAlwaysOpenIncognitoWindow &&
220 IncognitoModePrefs::ShouldLaunchIncognito(
221 *CommandLine::ForCurrentProcess(), prefs)) {
222 incognito = true;
223 }
224 }
225
226 if (incognito) {
227 content::RecordAction(UserMetricsAction("NewIncognitoWindow"));
228 OpenEmptyWindow(profile->GetOffTheRecordProfile());
229 } else {
230 content::RecordAction(UserMetricsAction("NewWindow"));
231 SessionService* session_service =
232 SessionServiceFactory::GetForProfile(profile->GetOriginalProfile());
233 if (!session_service ||
234 !session_service->RestoreIfNecessary(std::vector<GURL>())) {
235 OpenEmptyWindow(profile->GetOriginalProfile());
236 }
237 }
238}
239
240Browser* OpenEmptyWindow(Profile* profile) {
241 Browser* browser = Browser::Create(profile);
242 browser->AddBlankTab(true);
243 browser->window()->Show();
244 return browser;
245}
246
247void OpenWindowWithRestoredTabs(Profile* profile) {
248 TabRestoreService* service = TabRestoreServiceFactory::GetForProfile(profile);
249 if (service)
250 service->RestoreMostRecentEntry(NULL);
251}
252
253void OpenURLOffTheRecord(Profile* profile, const GURL& url) {
254 Browser* browser = browser::FindOrCreateTabbedBrowser(
255 profile->GetOffTheRecordProfile());
256 browser->AddSelectedTabWithURL(url, content::PAGE_TRANSITION_LINK);
257 browser->window()->Show();
258}
259
[email protected]5d98294912012-06-27 22:57:40260bool CanGoBack(const Browser* browser) {
[email protected]a37d4b02012-06-25 21:56:10261 return browser->GetActiveWebContents()->GetController().CanGoBack();
262}
263
264void GoBack(Browser* browser, WindowOpenDisposition disposition) {
265 content::RecordAction(UserMetricsAction("Back"));
266
267 TabContents* current_tab = browser->GetActiveTabContents();
268 if (CanGoBack(browser)) {
269 WebContents* new_tab = GetOrCloneTabForDisposition(browser, disposition);
270 // If we are on an interstitial page and clone the tab, it won't be copied
271 // to the new tab, so we don't need to go back.
272 if (current_tab->web_contents()->ShowingInterstitialPage() &&
273 (new_tab != current_tab->web_contents()))
274 return;
275 new_tab->GetController().GoBack();
276 }
277}
278
[email protected]5d98294912012-06-27 22:57:40279bool CanGoForward(const Browser* browser) {
[email protected]a37d4b02012-06-25 21:56:10280 return browser->GetActiveWebContents()->GetController().CanGoForward();
281}
282
283void GoForward(Browser* browser, WindowOpenDisposition disposition) {
284 content::RecordAction(UserMetricsAction("Forward"));
285 if (CanGoForward(browser)) {
286 GetOrCloneTabForDisposition(browser, disposition)->
287 GetController().GoForward();
288 }
289}
290
291bool NavigateToIndexWithDisposition(Browser* browser,
292 int index,
293 WindowOpenDisposition disp) {
294 NavigationController& controller =
295 GetOrCloneTabForDisposition(browser, disp)->GetController();
296 if (index < 0 || index >= controller.GetEntryCount())
297 return false;
298 controller.GoToIndex(index);
299 return true;
300}
301
302void Reload(Browser* browser, WindowOpenDisposition disposition) {
303 content::RecordAction(UserMetricsAction("Reload"));
304 ReloadInternal(browser, disposition, false);
305}
306
307void ReloadIgnoringCache(Browser* browser, WindowOpenDisposition disposition) {
308 content::RecordAction(UserMetricsAction("ReloadIgnoringCache"));
309 ReloadInternal(browser, disposition, true);
310}
311
[email protected]5d98294912012-06-27 22:57:40312bool CanReload(const Browser* browser) {
313 return !browser->is_devtools();
314}
315
[email protected]a37d4b02012-06-25 21:56:10316void Home(Browser* browser, WindowOpenDisposition disposition) {
317 content::RecordAction(UserMetricsAction("Home"));
318 browser->OpenURL(OpenURLParams(
319 browser->profile()->GetHomePage(), Referrer(), disposition,
320 content::PageTransitionFromInt(
321 content::PAGE_TRANSITION_AUTO_BOOKMARK |
322 content::PAGE_TRANSITION_HOME_PAGE),
323 false));
324}
325
326void OpenCurrentURL(Browser* browser) {
327 content::RecordAction(UserMetricsAction("LoadURL"));
328 LocationBar* location_bar = browser->window()->GetLocationBar();
329 if (!location_bar)
330 return;
331
332 WindowOpenDisposition open_disposition =
333 location_bar->GetWindowOpenDisposition();
334 if (browser->OpenInstant(open_disposition))
335 return;
336
337 GURL url(location_bar->GetInputString());
338
339 browser::NavigateParams params(browser, url,
340 location_bar->GetPageTransition());
341 params.disposition = open_disposition;
342 // Use ADD_INHERIT_OPENER so that all pages opened by the omnibox at least
343 // inherit the opener. In some cases the tabstrip will determine the group
344 // should be inherited, in which case the group is inherited instead of the
345 // opener.
346 params.tabstrip_add_types =
347 TabStripModel::ADD_FORCE_INDEX | TabStripModel::ADD_INHERIT_OPENER;
348 browser::Navigate(&params);
349
350 DCHECK(browser->profile()->GetExtensionService());
351 if (browser->profile()->GetExtensionService()->IsInstalledApp(url)) {
352 AppLauncherHandler::RecordAppLaunchType(
353 extension_misc::APP_LAUNCH_OMNIBOX_LOCATION);
354 }
355}
356
357void Stop(Browser* browser) {
358 content::RecordAction(UserMetricsAction("Stop"));
359 browser->GetActiveWebContents()->Stop();
360}
361
362#if !defined(OS_WIN)
363void NewWindow(Browser* browser) {
364 NewEmptyWindow(browser->profile()->GetOriginalProfile());
365}
366
367void NewIncognitoWindow(Browser* browser) {
368 NewEmptyWindow(browser->profile()->GetOffTheRecordProfile());
369}
370#endif // OS_WIN
371
372void CloseWindow(Browser* browser) {
373 content::RecordAction(UserMetricsAction("CloseWindow"));
374 browser->window()->Close();
375}
376
377void NewTab(Browser* browser) {
378 content::RecordAction(UserMetricsAction("NewTab"));
379 // TODO(asvitkine): This is invoked programmatically from several places.
380 // Audit the code and change it so that the histogram only gets collected for
381 // user-initiated commands.
382 UMA_HISTOGRAM_ENUMERATION("Tab.NewTab", TabStripModel::NEW_TAB_COMMAND,
383 TabStripModel::NEW_TAB_ENUM_COUNT);
384
385 if (browser->is_type_tabbed()) {
386 browser->AddBlankTab(true);
387 browser->GetActiveWebContents()->GetView()->RestoreFocus();
388 } else {
389 Browser* b = browser::FindOrCreateTabbedBrowser(browser->profile());
390 b->AddBlankTab(true);
391 b->window()->Show();
392 // The call to AddBlankTab above did not set the focus to the tab as its
393 // window was not active, so we have to do it explicitly.
394 // See http://crbug.com/6380.
395 b->GetActiveWebContents()->GetView()->RestoreFocus();
396 }
397}
398
399void CloseTab(Browser* browser) {
400 content::RecordAction(UserMetricsAction("CloseTab_Accelerator"));
401 browser->tab_strip_model()->CloseSelectedTabs();
402}
403
[email protected]5d98294912012-06-27 22:57:40404void RestoreTab(Browser* browser) {
405 content::RecordAction(UserMetricsAction("RestoreTab"));
406 TabRestoreService* service =
407 TabRestoreServiceFactory::GetForProfile(browser->profile());
408 if (service)
409 service->RestoreMostRecentEntry(browser->tab_restore_service_delegate());
410}
411
412bool CanRestoreTab(const Browser* browser) {
413 TabRestoreService* service =
414 TabRestoreServiceFactory::GetForProfile(browser->profile());
415 return service && !service->entries().empty();
416}
417
[email protected]a37d4b02012-06-25 21:56:10418void SelectNextTab(Browser* browser) {
419 content::RecordAction(UserMetricsAction("SelectNextTab"));
420 browser->tab_strip_model()->SelectNextTab();
421}
422
423void SelectPreviousTab(Browser* browser) {
424 content::RecordAction(UserMetricsAction("SelectPrevTab"));
425 browser->tab_strip_model()->SelectPreviousTab();
426}
427
428void OpenTabpose(Browser* browser) {
429#if defined(OS_MACOSX)
430 if (!CommandLine::ForCurrentProcess()->HasSwitch(
431 switches::kEnableExposeForTabs)) {
432 return;
433 }
434
435 content::RecordAction(UserMetricsAction("OpenTabpose"));
436 browser->window()->OpenTabpose();
437#else
438 NOTREACHED();
439#endif
440}
441
442void MoveTabNext(Browser* browser) {
443 content::RecordAction(UserMetricsAction("MoveTabNext"));
444 browser->tab_strip_model()->MoveTabNext();
445}
446
447void MoveTabPrevious(Browser* browser) {
448 content::RecordAction(UserMetricsAction("MoveTabPrevious"));
449 browser->tab_strip_model()->MoveTabPrevious();
450}
451
452void SelectNumberedTab(Browser* browser, int index) {
453 if (index < browser->tab_count()) {
454 content::RecordAction(UserMetricsAction("SelectNumberedTab"));
455 browser->ActivateTabAt(index, true);
456 }
457}
458
459void SelectLastTab(Browser* browser) {
460 content::RecordAction(UserMetricsAction("SelectLastTab"));
461 browser->tab_strip_model()->SelectLastTab();
462}
463
464void DuplicateTab(Browser* browser) {
465 content::RecordAction(UserMetricsAction("Duplicate"));
466 browser->DuplicateContentsAt(browser->active_index());
467}
468
[email protected]5d98294912012-06-27 22:57:40469bool CanDuplicateTab(const Browser* browser) {
470 WebContents* contents = browser->GetActiveWebContents();
471 return contents && contents->GetController().GetLastCommittedEntry();
472}
473
[email protected]a37d4b02012-06-25 21:56:10474void WriteCurrentURLToClipboard(Browser* browser) {
475 // TODO(ericu): There isn't currently a metric for this. Should there be?
476 // We don't appear to track the action when it comes from the
477 // RenderContextViewMenu.
478
479 WebContents* contents = browser->GetActiveWebContents();
480 if (!browser->toolbar_model()->ShouldDisplayURL())
481 return;
482
483 chrome_common_net::WriteURLToClipboard(
484 contents->GetURL(),
485 browser->profile()->GetPrefs()->GetString(prefs::kAcceptLanguages),
486 g_browser_process->clipboard());
487}
488
489void ConvertPopupToTabbedBrowser(Browser* browser) {
490 content::RecordAction(UserMetricsAction("ShowAsTab"));
491 TabContents* contents =
492 browser->tab_strip_model()->DetachTabContentsAt(browser->active_index());
493 Browser* b = Browser::Create(browser->profile());
494 b->tab_strip_model()->AppendTabContents(contents, true);
495 b->window()->Show();
496}
497
498void Exit() {
499 content::RecordAction(UserMetricsAction("Exit"));
500 browser::AttemptUserExit();
501}
502
503void BookmarkCurrentPage(Browser* browser) {
504 content::RecordAction(UserMetricsAction("Star"));
505
506 BookmarkModel* model = browser->profile()->GetBookmarkModel();
507 if (!model || !model->IsLoaded())
508 return; // Ignore requests until bookmarks are loaded.
509
510 GURL url;
511 string16 title;
512 TabContents* tab = browser->GetActiveTabContents();
513 bookmark_utils::GetURLAndTitleToBookmark(tab->web_contents(), &url, &title);
514 bool was_bookmarked = model->IsBookmarked(url);
515 if (!was_bookmarked && browser->profile()->IsOffTheRecord()) {
516 // If we're incognito the favicon may not have been saved. Save it now
517 // so that bookmarks have an icon for the page.
518 tab->favicon_tab_helper()->SaveFavicon();
519 }
520 bookmark_utils::AddIfNotBookmarked(model, url, title);
521 // Make sure the model actually added a bookmark before showing the star. A
522 // bookmark isn't created if the url is invalid.
523 if (browser->window()->IsActive() && model->IsBookmarked(url)) {
524 // Only show the bubble if the window is active, otherwise we may get into
525 // weird situations where the bubble is deleted as soon as it is shown.
526 browser->window()->ShowBookmarkBubble(url, was_bookmarked);
527 }
528}
529
[email protected]5d98294912012-06-27 22:57:40530bool CanBookmarkCurrentPage(const Browser* browser) {
531 BookmarkModel* model = browser->profile()->GetBookmarkModel();
532 return browser_defaults::bookmarks_enabled &&
533 browser->profile()->GetPrefs()->GetBoolean(
534 prefs::kEditBookmarksEnabled) &&
535 model && model->IsLoaded() && browser->is_type_tabbed();
536}
537
538void BookmarkAllTabs(Browser* browser) {
539 BookmarkEditor::ShowBookmarkAllTabsDialog(browser);
540}
541
542bool CanBookmarkAllTabs(const Browser* browser) {
543 return browser->tab_count() > 1 && CanBookmarkCurrentPage(browser);
544}
545
[email protected]a37d4b02012-06-25 21:56:10546#if !defined(OS_WIN)
547void PinCurrentPageToStartScreen(Browser* browser) {
548}
549#endif
550
551void SavePage(Browser* browser) {
552 content::RecordAction(UserMetricsAction("SavePage"));
553 WebContents* current_tab = browser->GetActiveWebContents();
554 if (current_tab && current_tab->GetContentsMimeType() == "application/pdf")
555 content::RecordAction(UserMetricsAction("PDF.SavePage"));
556 current_tab->OnSavePage();
557}
558
[email protected]5d98294912012-06-27 22:57:40559bool CanSavePage(const Browser* browser) {
560 // LocalState can be NULL in tests.
561 if (g_browser_process->local_state() &&
562 !g_browser_process->local_state()->GetBoolean(
563 prefs::kAllowFileSelectionDialogs)) {
564 return false;
565 }
566 return !browser->is_devtools() &&
567 !(GetContentRestrictions(browser) & content::CONTENT_RESTRICTION_SAVE);
568}
569
[email protected]a37d4b02012-06-25 21:56:10570void ShowFindBar(Browser* browser) {
571 browser->GetFindBarController()->Show();
572}
573
574void ShowPageInfo(Browser* browser,
575 content::WebContents* web_contents,
576 const GURL& url,
577 const SSLStatus& ssl,
578 bool show_history) {
579 Profile* profile = Profile::FromBrowserContext(
580 web_contents->GetBrowserContext());
581 TabContents* tab_contents = TabContents::FromWebContents(web_contents);
582
583 if (CommandLine::ForCurrentProcess()->HasSwitch(
584 switches::kEnableWebsiteSettings)) {
585 browser->window()->ShowWebsiteSettings(
586 profile, tab_contents, url, ssl, show_history);
587 } else {
588 browser->window()->ShowPageInfo(web_contents, url, ssl, show_history);
589 }
590}
591
592void ShowChromeToMobileBubble(Browser* browser) {
593 // Only show the bubble if the window is active, otherwise we may get into
594 // weird situations where the bubble is deleted as soon as it is shown.
595 if (browser->window()->IsActive())
596 browser->window()->ShowChromeToMobileBubble();
597}
598
599void Print(Browser* browser) {
600 if (g_browser_process->local_state()->GetBoolean(
601 prefs::kPrintPreviewDisabled)) {
602 browser->GetActiveTabContents()->print_view_manager()->PrintNow();
603 } else {
604 browser->GetActiveTabContents()->print_view_manager()->PrintPreviewNow();
605 }
606}
607
[email protected]5d98294912012-06-27 22:57:40608bool CanPrint(const Browser* browser) {
609 // LocalState can be NULL in tests.
610 if (g_browser_process->local_state() &&
611 !g_browser_process->local_state()->GetBoolean(prefs::kPrintingEnabled)) {
612 return false;
613 }
614
615 // Do not print when a constrained window is showing. It's confusing.
616 return !(HasConstrainedWindow(browser) ||
617 GetContentRestrictions(browser) & content::CONTENT_RESTRICTION_PRINT);
618}
619
[email protected]a37d4b02012-06-25 21:56:10620void AdvancedPrint(Browser* browser) {
621 browser->GetActiveTabContents()->print_view_manager()->AdvancedPrintNow();
622}
623
[email protected]5d98294912012-06-27 22:57:40624bool CanAdvancedPrint(const Browser* browser) {
625 // LocalState can be NULL in tests.
626 if (g_browser_process->local_state() &&
627 !g_browser_process->local_state()->GetBoolean(prefs::kPrintingEnabled)) {
628 return false;
629 }
630
631 // It is always possible to advanced print when print preview is visible.
632 return PrintPreviewShowing(browser) || CanPrint(browser);
633}
634
[email protected]a37d4b02012-06-25 21:56:10635void EmailPageLocation(Browser* browser) {
636 content::RecordAction(UserMetricsAction("EmailPageLocation"));
637 WebContents* wc = browser->GetActiveWebContents();
638 DCHECK(wc);
639
640 std::string title = net::EscapeQueryParamValue(
641 UTF16ToUTF8(wc->GetTitle()), false);
642 std::string page_url = net::EscapeQueryParamValue(wc->GetURL().spec(), false);
643 std::string mailto = std::string("mailto:?subject=Fwd:%20") +
644 title + "&body=%0A%0A" + page_url;
645 platform_util::OpenExternal(GURL(mailto));
646}
647
[email protected]5d98294912012-06-27 22:57:40648bool CanEmailPageLocation(const Browser* browser) {
649 return browser->toolbar_model()->ShouldDisplayURL() &&
650 browser->GetActiveWebContents()->GetURL().is_valid();
651}
652
[email protected]a37d4b02012-06-25 21:56:10653void Cut(Browser* browser) {
654 content::RecordAction(UserMetricsAction("Cut"));
655 browser->window()->Cut();
656}
657
658void Copy(Browser* browser) {
659 content::RecordAction(UserMetricsAction("Copy"));
660 browser->window()->Copy();
661}
662
663void Paste(Browser* browser) {
664 content::RecordAction(UserMetricsAction("Paste"));
665 browser->window()->Paste();
666}
667
668void Find(Browser* browser) {
669 content::RecordAction(UserMetricsAction("Find"));
670 FindInPage(browser, false, false);
671}
672
673void FindNext(Browser* browser) {
674 content::RecordAction(UserMetricsAction("FindNext"));
675 FindInPage(browser, true, true);
676}
677
678void FindPrevious(Browser* browser) {
679 content::RecordAction(UserMetricsAction("FindPrevious"));
680 FindInPage(browser, true, false);
681}
682
683void FindInPage(Browser* browser, bool find_next, bool forward_direction) {
684 ShowFindBar(browser);
685 if (find_next) {
686 string16 find_text;
687#if defined(OS_MACOSX)
688 // We always want to search for the contents of the find pasteboard on OS X.
689 find_text = GetFindPboardText();
690#endif
691 browser->GetActiveTabContents()->
692 find_tab_helper()->StartFinding(find_text,
693 forward_direction,
694 false); // Not case sensitive.
695 }
696}
697
698void Zoom(Browser* browser, content::PageZoom zoom) {
699 if (browser->is_devtools())
700 return;
701
702 content::RenderViewHost* host =
703 browser->GetActiveWebContents()->GetRenderViewHost();
704 if (zoom == content::PAGE_ZOOM_RESET) {
705 host->SetZoomLevel(0);
706 content::RecordAction(UserMetricsAction("ZoomNormal"));
707 return;
708 }
709
710 double current_zoom_level = browser->GetActiveWebContents()->GetZoomLevel();
711 double default_zoom_level =
712 browser->profile()->GetPrefs()->GetDouble(prefs::kDefaultZoomLevel);
713
714 // Generate a vector of zoom levels from an array of known presets along with
715 // the default level added if necessary.
716 std::vector<double> zoom_levels =
717 chrome_page_zoom::PresetZoomLevels(default_zoom_level);
718
719 if (zoom == content::PAGE_ZOOM_OUT) {
720 // Iterate through the zoom levels in reverse order to find the next
721 // lower level based on the current zoom level for this page.
722 for (std::vector<double>::reverse_iterator i = zoom_levels.rbegin();
723 i != zoom_levels.rend(); ++i) {
724 double zoom_level = *i;
725 if (content::ZoomValuesEqual(zoom_level, current_zoom_level))
726 continue;
727 if (zoom_level < current_zoom_level) {
728 host->SetZoomLevel(zoom_level);
729 content::RecordAction(UserMetricsAction("ZoomMinus"));
730 return;
731 }
732 content::RecordAction(UserMetricsAction("ZoomMinus_AtMinimum"));
733 }
734 } else {
735 // Iterate through the zoom levels in normal order to find the next
736 // higher level based on the current zoom level for this page.
737 for (std::vector<double>::const_iterator i = zoom_levels.begin();
738 i != zoom_levels.end(); ++i) {
739 double zoom_level = *i;
740 if (content::ZoomValuesEqual(zoom_level, current_zoom_level))
741 continue;
742 if (zoom_level > current_zoom_level) {
743 host->SetZoomLevel(zoom_level);
744 content::RecordAction(UserMetricsAction("ZoomPlus"));
745 return;
746 }
747 }
748 content::RecordAction(UserMetricsAction("ZoomPlus_AtMaximum"));
749 }
750}
751
752void FocusToolbar(Browser* browser) {
753 content::RecordAction(UserMetricsAction("FocusToolbar"));
754 browser->window()->FocusToolbar();
755}
756
757void FocusLocationBar(Browser* browser) {
758 content::RecordAction(UserMetricsAction("FocusLocation"));
759 browser->window()->SetFocusToLocationBar(true);
760}
761
762void FocusSearch(Browser* browser) {
763 // TODO(beng): replace this with FocusLocationBar
764 content::RecordAction(UserMetricsAction("FocusSearch"));
765 browser->window()->GetLocationBar()->FocusSearch();
766}
767
768void FocusAppMenu(Browser* browser) {
769 content::RecordAction(UserMetricsAction("FocusAppMenu"));
770 browser->window()->FocusAppMenu();
771}
772
773void FocusBookmarksToolbar(Browser* browser) {
774 content::RecordAction(UserMetricsAction("FocusBookmarksToolbar"));
775 browser->window()->FocusBookmarksToolbar();
776}
777
778void FocusNextPane(Browser* browser) {
779 content::RecordAction(UserMetricsAction("FocusNextPane"));
780 browser->window()->RotatePaneFocus(true);
781}
782
783void FocusPreviousPane(Browser* browser) {
784 content::RecordAction(UserMetricsAction("FocusPreviousPane"));
785 browser->window()->RotatePaneFocus(false);
786}
787
788void ToggleDevToolsWindow(Browser* browser, DevToolsToggleAction action) {
789 if (action == DEVTOOLS_TOGGLE_ACTION_SHOW_CONSOLE)
790 content::RecordAction(UserMetricsAction("DevTools_ToggleConsole"));
791 else
792 content::RecordAction(UserMetricsAction("DevTools_ToggleWindow"));
793
794 DevToolsWindow::ToggleDevToolsWindow(
795 browser->GetActiveWebContents()->GetRenderViewHost(),
796 action);
797}
798
799bool CanOpenTaskManager() {
800#if defined(OS_WIN)
801 // In metro we can't display the task manager, as it is a native window.
802 return !base::win::IsMetroProcess();
803#else
804 return true;
805#endif
806}
807
808void OpenTaskManager(Browser* browser, bool highlight_background_resources) {
809 content::RecordAction(UserMetricsAction("TaskManager"));
810 if (highlight_background_resources)
811 browser->window()->ShowBackgroundPages();
812 else
813 browser->window()->ShowTaskManager();
814}
815
816void OpenFeedbackDialog(Browser* browser) {
817 content::RecordAction(UserMetricsAction("Feedback"));
818 browser::ShowWebFeedbackView(browser, std::string(), std::string());
819}
820
821void ToggleBookmarkBar(Browser* browser) {
822 content::RecordAction(UserMetricsAction("ShowBookmarksBar"));
823 browser->window()->ToggleBookmarkBar();
824}
825
826void ShowAppMenu(Browser* browser) {
827 // We record the user metric for this event in WrenchMenu::RunMenu.
828 browser->window()->ShowAppMenu();
829}
830
831void ShowAvatarMenu(Browser* browser) {
832 browser->window()->ShowAvatarBubbleFromAvatarButton();
833}
834
835void OpenUpdateChromeDialog(Browser* browser) {
836 content::RecordAction(UserMetricsAction("UpdateChrome"));
837 browser->window()->ShowUpdateChromeDialog();
838}
839
840void ToggleSpeechInput(Browser* browser) {
841 browser->GetActiveWebContents()->GetRenderViewHost()->ToggleSpeechInput();
842}
843
[email protected]2cd4fde2012-06-26 03:10:26844void ViewSource(Browser* browser, TabContents* contents) {
845 DCHECK(contents);
846
847 NavigationEntry* active_entry =
848 contents->web_contents()->GetController().GetActiveEntry();
849 if (!active_entry)
850 return;
851
852 ViewSource(browser, contents, active_entry->GetURL(),
853 active_entry->GetContentState());
854}
855
856void ViewSource(Browser* browser,
857 TabContents* contents,
858 const GURL& url,
859 const std::string& content_state) {
860 content::RecordAction(UserMetricsAction("ViewSource"));
861 DCHECK(contents);
862
863 TabContents* view_source_contents = contents->Clone();
864 view_source_contents->web_contents()->GetController().PruneAllButActive();
865 NavigationEntry* active_entry =
866 view_source_contents->web_contents()->GetController().GetActiveEntry();
867 if (!active_entry)
868 return;
869
870 GURL view_source_url = GURL(chrome::kViewSourceScheme + std::string(":") +
871 url.spec());
872 active_entry->SetVirtualURL(view_source_url);
873
874 // Do not restore scroller position.
875 active_entry->SetContentState(
876 webkit_glue::RemoveScrollOffsetFromHistoryState(content_state));
877
878 // Do not restore title, derive it from the url.
879 active_entry->SetTitle(string16());
880
881 // Now show view-source entry.
882 if (browser->CanSupportWindowFeature(Browser::FEATURE_TABSTRIP)) {
883 // If this is a tabbed browser, just create a duplicate tab inside the same
884 // window next to the tab being duplicated.
885 int index = browser->tab_strip_model()->GetIndexOfTabContents(contents);
886 int add_types = TabStripModel::ADD_ACTIVE |
887 TabStripModel::ADD_INHERIT_GROUP;
888 browser->tab_strip_model()->InsertTabContentsAt(index + 1,
889 view_source_contents,
890 add_types);
891 } else {
892 Browser* b = Browser::CreateWithParams(
893 Browser::CreateParams(Browser::TYPE_TABBED, browser->profile()));
894
895 // Preserve the size of the original window. The new window has already
896 // been given an offset by the OS, so we shouldn't copy the old bounds.
897 BrowserWindow* new_window = b->window();
898 new_window->SetBounds(gfx::Rect(new_window->GetRestoredBounds().origin(),
899 browser->window()->GetRestoredBounds().size()));
900
901 // We need to show the browser now. Otherwise ContainerWin assumes the
902 // WebContents is invisible and won't size it.
903 b->window()->Show();
904
905 // The page transition below is only for the purpose of inserting the tab.
906 b->AddTab(view_source_contents, content::PAGE_TRANSITION_LINK);
907 }
908
909 SessionService* session_service =
910 SessionServiceFactory::GetForProfileIfExisting(browser->profile());
911 if (session_service)
912 session_service->TabRestored(view_source_contents, false);
913}
914
915void ViewSelectedSource(Browser* browser) {
916 ViewSource(browser, browser->GetActiveTabContents());
917}
918
[email protected]5d98294912012-06-27 22:57:40919bool CanViewSource(const Browser* browser) {
920 return browser->GetActiveWebContents()->GetController().CanViewSource();
921}
922
923bool CanCreateApplicationShortcuts(const Browser* browser) {
924 return web_app::IsValidUrl(browser->GetActiveWebContents()->GetURL());
925}
926
[email protected]a37d4b02012-06-25 21:56:10927} // namespace chrome