NaCl: Update revision in DEPS, r12770 -> r12773
[chromium-blink-merge.git] / chrome / browser / ui / browser_commands.cc
blobaea704fe04366c84a510ea4ef8fe912e31f48df3
1 // Copyright 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.
5 #include "chrome/browser/ui/browser_commands.h"
7 #include "base/command_line.h"
8 #include "base/metrics/histogram.h"
9 #include "base/prefs/pref_service.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "chrome/browser/bookmarks/bookmark_model.h"
12 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
13 #include "chrome/browser/bookmarks/bookmark_utils.h"
14 #include "chrome/browser/browser_process.h"
15 #include "chrome/browser/browsing_data/browsing_data_helper.h"
16 #include "chrome/browser/browsing_data/browsing_data_remover.h"
17 #include "chrome/browser/chrome_notification_types.h"
18 #include "chrome/browser/chrome_page_zoom.h"
19 #include "chrome/browser/devtools/devtools_window.h"
20 #include "chrome/browser/extensions/extension_service.h"
21 #include "chrome/browser/extensions/tab_helper.h"
22 #include "chrome/browser/favicon/favicon_tab_helper.h"
23 #include "chrome/browser/google/google_util.h"
24 #include "chrome/browser/lifetime/application_lifetime.h"
25 #include "chrome/browser/platform_util.h"
26 #include "chrome/browser/prefs/incognito_mode_prefs.h"
27 #include "chrome/browser/profiles/profile.h"
28 #include "chrome/browser/rlz/rlz.h"
29 #include "chrome/browser/search/search.h"
30 #include "chrome/browser/sessions/session_service_factory.h"
31 #include "chrome/browser/sessions/tab_restore_service.h"
32 #include "chrome/browser/sessions/tab_restore_service_delegate.h"
33 #include "chrome/browser/sessions/tab_restore_service_factory.h"
34 #include "chrome/browser/translate/translate_tab_helper.h"
35 #include "chrome/browser/ui/bookmarks/bookmark_prompt_controller.h"
36 #include "chrome/browser/ui/bookmarks/bookmark_utils.h"
37 #include "chrome/browser/ui/browser.h"
38 #include "chrome/browser/ui/browser_command_controller.h"
39 #include "chrome/browser/ui/browser_dialogs.h"
40 #include "chrome/browser/ui/browser_instant_controller.h"
41 #include "chrome/browser/ui/browser_tab_restore_service_delegate.h"
42 #include "chrome/browser/ui/browser_tabstrip.h"
43 #include "chrome/browser/ui/browser_window.h"
44 #include "chrome/browser/ui/chrome_pages.h"
45 #include "chrome/browser/ui/find_bar/find_bar.h"
46 #include "chrome/browser/ui/find_bar/find_bar_controller.h"
47 #include "chrome/browser/ui/find_bar/find_tab_helper.h"
48 #include "chrome/browser/ui/fullscreen/fullscreen_controller.h"
49 #include "chrome/browser/ui/omnibox/location_bar.h"
50 #include "chrome/browser/ui/scoped_tabbed_browser_displayer.h"
51 #include "chrome/browser/ui/search/search_tab_helper.h"
52 #include "chrome/browser/ui/status_bubble.h"
53 #include "chrome/browser/ui/tab_contents/core_tab_helper.h"
54 #include "chrome/browser/ui/tabs/tab_strip_model.h"
55 #include "chrome/browser/ui/webui/ntp/core_app_launcher_handler.h"
56 #include "chrome/browser/upgrade_detector.h"
57 #include "chrome/browser/web_applications/web_app.h"
58 #include "chrome/common/chrome_switches.h"
59 #include "chrome/common/chrome_version_info.h"
60 #include "chrome/common/content_restriction.h"
61 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
62 #include "chrome/common/pref_names.h"
63 #include "components/web_modal/web_contents_modal_dialog_manager.h"
64 #include "content/public/browser/devtools_agent_host.h"
65 #include "content/public/browser/navigation_controller.h"
66 #include "content/public/browser/navigation_entry.h"
67 #include "content/public/browser/notification_service.h"
68 #include "content/public/browser/page_navigator.h"
69 #include "content/public/browser/render_view_host.h"
70 #include "content/public/browser/render_widget_host_view.h"
71 #include "content/public/browser/user_metrics.h"
72 #include "content/public/browser/web_contents.h"
73 #include "content/public/browser/web_contents_view.h"
74 #include "content/public/common/renderer_preferences.h"
75 #include "content/public/common/url_constants.h"
76 #include "content/public/common/url_utils.h"
77 #include "net/base/escape.h"
78 #include "webkit/common/user_agent/user_agent_util.h"
80 #if defined(OS_WIN)
81 #include "chrome/browser/ui/metro_pin_tab_helper_win.h"
82 #include "win8/util/win8_util.h"
83 #endif
85 #if defined(ENABLE_PRINTING)
86 #if defined(ENABLE_FULL_PRINTING)
87 #include "chrome/browser/printing/print_preview_dialog_controller.h"
88 #include "chrome/browser/printing/print_view_manager.h"
89 #else
90 #include "chrome/browser/printing/print_view_manager_basic.h"
91 #endif // defined(ENABLE_FULL_PRINTING)
92 #endif // defined(ENABLE_PRINTING)
94 namespace {
95 const char kOsOverrideForTabletSite[] = "Linux; Android 4.0.3";
98 using base::UserMetricsAction;
99 using content::NavigationController;
100 using content::NavigationEntry;
101 using content::OpenURLParams;
102 using content::Referrer;
103 using content::SSLStatus;
104 using content::WebContents;
105 using web_modal::WebContentsModalDialogManager;
107 namespace chrome {
108 namespace {
110 void BookmarkCurrentPageInternal(Browser* browser, bool from_star) {
111 content::RecordAction(UserMetricsAction("Star"));
113 BookmarkModel* model =
114 BookmarkModelFactory::GetForProfile(browser->profile());
115 if (!model || !model->loaded())
116 return; // Ignore requests until bookmarks are loaded.
118 GURL url;
119 base::string16 title;
120 WebContents* web_contents =
121 browser->tab_strip_model()->GetActiveWebContents();
122 GetURLAndTitleToBookmark(web_contents, &url, &title);
123 bool was_bookmarked = model->IsBookmarked(url);
124 if (!was_bookmarked && web_contents->GetBrowserContext()->IsOffTheRecord()) {
125 // If we're incognito the favicon may not have been saved. Save it now
126 // so that bookmarks have an icon for the page.
127 FaviconTabHelper::FromWebContents(web_contents)->SaveFavicon();
129 bookmark_utils::AddIfNotBookmarked(model, url, title);
130 if (from_star && !was_bookmarked)
131 BookmarkPromptController::AddedBookmark(browser, url);
132 // Make sure the model actually added a bookmark before showing the star. A
133 // bookmark isn't created if the url is invalid.
134 if (browser->window()->IsActive() && model->IsBookmarked(url)) {
135 // Only show the bubble if the window is active, otherwise we may get into
136 // weird situations where the bubble is deleted as soon as it is shown.
137 browser->window()->ShowBookmarkBubble(url, was_bookmarked);
141 WebContents* GetOrCloneTabForDisposition(Browser* browser,
142 WindowOpenDisposition disposition) {
143 WebContents* current_tab = browser->tab_strip_model()->GetActiveWebContents();
144 switch (disposition) {
145 case NEW_FOREGROUND_TAB:
146 case NEW_BACKGROUND_TAB: {
147 current_tab = current_tab->Clone();
148 browser->tab_strip_model()->AddWebContents(
149 current_tab, -1, content::PAGE_TRANSITION_LINK,
150 disposition == NEW_FOREGROUND_TAB ? TabStripModel::ADD_ACTIVE :
151 TabStripModel::ADD_NONE);
152 break;
154 case NEW_WINDOW: {
155 current_tab = current_tab->Clone();
156 Browser* b = new Browser(Browser::CreateParams(
157 browser->profile(), browser->host_desktop_type()));
158 b->tab_strip_model()->AddWebContents(
159 current_tab, -1, content::PAGE_TRANSITION_LINK,
160 TabStripModel::ADD_ACTIVE);
161 b->window()->Show();
162 break;
164 default:
165 break;
167 return current_tab;
170 void ReloadInternal(Browser* browser,
171 WindowOpenDisposition disposition,
172 bool ignore_cache) {
173 // As this is caused by a user action, give the focus to the page.
175 // Also notify RenderViewHostDelegate of the user gesture; this is
176 // normally done in Browser::Navigate, but a reload bypasses Navigate.
177 WebContents* web_contents = GetOrCloneTabForDisposition(browser, disposition);
178 web_contents->UserGestureDone();
179 if (!web_contents->FocusLocationBarByDefault())
180 web_contents->GetView()->Focus();
181 if (ignore_cache)
182 web_contents->GetController().ReloadIgnoringCache(true);
183 else
184 web_contents->GetController().Reload(true);
187 bool IsShowingWebContentsModalDialog(const Browser* browser) {
188 WebContents* web_contents =
189 browser->tab_strip_model()->GetActiveWebContents();
190 if (!web_contents)
191 return false;
193 WebContentsModalDialogManager* web_contents_modal_dialog_manager =
194 WebContentsModalDialogManager::FromWebContents(web_contents);
195 return web_contents_modal_dialog_manager->IsDialogActive();
198 bool PrintPreviewShowing(const Browser* browser) {
199 #if defined(ENABLE_FULL_PRINTING)
200 WebContents* contents = browser->tab_strip_model()->GetActiveWebContents();
201 printing::PrintPreviewDialogController* controller =
202 printing::PrintPreviewDialogController::GetInstance();
203 return controller && (controller->GetPrintPreviewForContents(contents) ||
204 controller->is_creating_print_preview_dialog());
205 #else
206 return false;
207 #endif
210 } // namespace
212 bool IsCommandEnabled(Browser* browser, int command) {
213 return browser->command_controller()->command_updater()->IsCommandEnabled(
214 command);
217 bool SupportsCommand(Browser* browser, int command) {
218 return browser->command_controller()->command_updater()->SupportsCommand(
219 command);
222 bool ExecuteCommand(Browser* browser, int command) {
223 return browser->command_controller()->command_updater()->ExecuteCommand(
224 command);
227 bool ExecuteCommandWithDisposition(Browser* browser,
228 int command,
229 WindowOpenDisposition disposition) {
230 return browser->command_controller()->command_updater()->
231 ExecuteCommandWithDisposition(command, disposition);
234 void UpdateCommandEnabled(Browser* browser, int command, bool enabled) {
235 browser->command_controller()->command_updater()->UpdateCommandEnabled(
236 command, enabled);
239 void AddCommandObserver(Browser* browser,
240 int command,
241 CommandObserver* observer) {
242 browser->command_controller()->command_updater()->AddCommandObserver(
243 command, observer);
246 void RemoveCommandObserver(Browser* browser,
247 int command,
248 CommandObserver* observer) {
249 browser->command_controller()->command_updater()->RemoveCommandObserver(
250 command, observer);
253 int GetContentRestrictions(const Browser* browser) {
254 int content_restrictions = 0;
255 WebContents* current_tab = browser->tab_strip_model()->GetActiveWebContents();
256 if (current_tab) {
257 CoreTabHelper* core_tab_helper =
258 CoreTabHelper::FromWebContents(current_tab);
259 content_restrictions = core_tab_helper->content_restrictions();
260 NavigationEntry* active_entry =
261 current_tab->GetController().GetActiveEntry();
262 // See comment in UpdateCommandsForTabState about why we call url().
263 if (!content::IsSavableURL(
264 active_entry ? active_entry->GetURL() : GURL()) ||
265 current_tab->ShowingInterstitialPage())
266 content_restrictions |= CONTENT_RESTRICTION_SAVE;
267 if (current_tab->ShowingInterstitialPage())
268 content_restrictions |= CONTENT_RESTRICTION_PRINT;
270 return content_restrictions;
273 void NewEmptyWindow(Profile* profile, HostDesktopType desktop_type) {
274 bool incognito = profile->IsOffTheRecord();
275 PrefService* prefs = profile->GetPrefs();
276 if (incognito) {
277 if (IncognitoModePrefs::GetAvailability(prefs) ==
278 IncognitoModePrefs::DISABLED) {
279 incognito = false;
281 } else {
282 if (browser_defaults::kAlwaysOpenIncognitoWindow &&
283 IncognitoModePrefs::ShouldLaunchIncognito(
284 *CommandLine::ForCurrentProcess(), prefs)) {
285 incognito = true;
289 if (incognito) {
290 content::RecordAction(UserMetricsAction("NewIncognitoWindow"));
291 OpenEmptyWindow(profile->GetOffTheRecordProfile(), desktop_type);
292 } else {
293 content::RecordAction(UserMetricsAction("NewWindow"));
294 SessionService* session_service =
295 SessionServiceFactory::GetForProfileForSessionRestore(
296 profile->GetOriginalProfile());
297 if (!session_service ||
298 !session_service->RestoreIfNecessary(std::vector<GURL>())) {
299 OpenEmptyWindow(profile->GetOriginalProfile(), desktop_type);
304 Browser* OpenEmptyWindow(Profile* profile, HostDesktopType desktop_type) {
305 Browser* browser = new Browser(
306 Browser::CreateParams(Browser::TYPE_TABBED, profile, desktop_type));
307 AddTabAt(browser, GURL(), -1, true);
308 browser->window()->Show();
309 return browser;
312 void OpenWindowWithRestoredTabs(Profile* profile,
313 HostDesktopType host_desktop_type) {
314 TabRestoreService* service = TabRestoreServiceFactory::GetForProfile(profile);
315 if (service)
316 service->RestoreMostRecentEntry(NULL, host_desktop_type);
319 void OpenURLOffTheRecord(Profile* profile,
320 const GURL& url,
321 chrome::HostDesktopType desktop_type) {
322 ScopedTabbedBrowserDisplayer displayer(profile->GetOffTheRecordProfile(),
323 desktop_type);
324 AddSelectedTabWithURL(displayer.browser(), url,
325 content::PAGE_TRANSITION_LINK);
328 bool CanGoBack(const Browser* browser) {
329 return browser->tab_strip_model()->GetActiveWebContents()->
330 GetController().CanGoBack();
333 void GoBack(Browser* browser, WindowOpenDisposition disposition) {
334 content::RecordAction(UserMetricsAction("Back"));
336 WebContents* current_tab = browser->tab_strip_model()->GetActiveWebContents();
337 if (CanGoBack(browser)) {
338 WebContents* new_tab = GetOrCloneTabForDisposition(browser, disposition);
339 // If we are on an interstitial page and clone the tab, it won't be copied
340 // to the new tab, so we don't need to go back.
341 if (current_tab->ShowingInterstitialPage() && new_tab != current_tab)
342 return;
343 new_tab->GetController().GoBack();
347 bool CanGoForward(const Browser* browser) {
348 return browser->tab_strip_model()->GetActiveWebContents()->
349 GetController().CanGoForward();
352 void GoForward(Browser* browser, WindowOpenDisposition disposition) {
353 content::RecordAction(UserMetricsAction("Forward"));
354 if (CanGoForward(browser)) {
355 GetOrCloneTabForDisposition(browser, disposition)->
356 GetController().GoForward();
360 bool NavigateToIndexWithDisposition(Browser* browser,
361 int index,
362 WindowOpenDisposition disp) {
363 NavigationController& controller =
364 GetOrCloneTabForDisposition(browser, disp)->GetController();
365 if (index < 0 || index >= controller.GetEntryCount())
366 return false;
367 controller.GoToIndex(index);
368 return true;
371 void Reload(Browser* browser, WindowOpenDisposition disposition) {
372 content::RecordAction(UserMetricsAction("Reload"));
373 ReloadInternal(browser, disposition, false);
376 void ReloadIgnoringCache(Browser* browser, WindowOpenDisposition disposition) {
377 content::RecordAction(UserMetricsAction("ReloadIgnoringCache"));
378 ReloadInternal(browser, disposition, true);
381 bool CanReload(const Browser* browser) {
382 return !browser->is_devtools();
385 void Home(Browser* browser, WindowOpenDisposition disposition) {
386 content::RecordAction(UserMetricsAction("Home"));
388 std::string extra_headers;
389 #if defined(ENABLE_RLZ)
390 // If the home page is a Google home page, add the RLZ header to the request.
391 PrefService* pref_service = browser->profile()->GetPrefs();
392 if (pref_service) {
393 if (google_util::IsGoogleHomePageUrl(
394 GURL(pref_service->GetString(prefs::kHomePage)))) {
395 extra_headers = RLZTracker::GetAccessPointHttpHeader(
396 RLZTracker::CHROME_HOME_PAGE);
399 #endif
401 GURL url = browser->profile()->GetHomePage();
403 // Streamlined hosted apps should return to their launch page when the home
404 // button is pressed.
405 if (browser->is_app()) {
406 const ExtensionService* service = browser->profile()->GetExtensionService();
407 if (!service)
408 return;
410 const extensions::Extension* extension =
411 service->GetInstalledExtension(
412 web_app::GetExtensionIdFromApplicationName(browser->app_name()));
413 if (!extension)
414 return;
416 url = extensions::AppLaunchInfo::GetLaunchWebURL(extension);
419 OpenURLParams params(
420 url, Referrer(), disposition,
421 content::PageTransitionFromInt(
422 content::PAGE_TRANSITION_AUTO_BOOKMARK |
423 content::PAGE_TRANSITION_HOME_PAGE),
424 false);
425 params.extra_headers = extra_headers;
426 browser->OpenURL(params);
429 void OpenCurrentURL(Browser* browser) {
430 content::RecordAction(UserMetricsAction("LoadURL"));
431 LocationBar* location_bar = browser->window()->GetLocationBar();
432 if (!location_bar)
433 return;
435 GURL url(location_bar->GetDestinationURL());
437 content::PageTransition page_transition = location_bar->GetPageTransition();
438 content::PageTransition page_transition_without_qualifier(
439 PageTransitionStripQualifier(page_transition));
440 WindowOpenDisposition open_disposition =
441 location_bar->GetWindowOpenDisposition();
442 // A PAGE_TRANSITION_TYPED means the user has typed a URL. We do not want to
443 // open URLs with instant_controller since in some cases it disregards it
444 // and performs a search instead. For example, when using CTRL-Enter, the
445 // location_bar is aware of the URL but instant is not.
446 // Instant should also not handle PAGE_TRANSITION_RELOAD because its knowledge
447 // of the omnibox text may be stale if the user focuses in the omnibox and
448 // presses enter without typing anything.
449 if (page_transition_without_qualifier != content::PAGE_TRANSITION_TYPED &&
450 page_transition_without_qualifier != content::PAGE_TRANSITION_RELOAD &&
451 browser->instant_controller() &&
452 browser->instant_controller()->OpenInstant(open_disposition, url))
453 return;
455 NavigateParams params(browser, url, page_transition);
456 params.disposition = open_disposition;
457 // Use ADD_INHERIT_OPENER so that all pages opened by the omnibox at least
458 // inherit the opener. In some cases the tabstrip will determine the group
459 // should be inherited, in which case the group is inherited instead of the
460 // opener.
461 params.tabstrip_add_types =
462 TabStripModel::ADD_FORCE_INDEX | TabStripModel::ADD_INHERIT_OPENER;
463 Navigate(&params);
465 DCHECK(browser->profile()->GetExtensionService());
466 const extensions::Extension* extension =
467 browser->profile()->GetExtensionService()->GetInstalledApp(url);
468 if (extension) {
469 CoreAppLauncherHandler::RecordAppLaunchType(
470 extension_misc::APP_LAUNCH_OMNIBOX_LOCATION,
471 extension->GetType());
475 void Stop(Browser* browser) {
476 content::RecordAction(UserMetricsAction("Stop"));
477 browser->tab_strip_model()->GetActiveWebContents()->Stop();
480 #if !defined(OS_WIN)
481 void NewWindow(Browser* browser) {
482 NewEmptyWindow(browser->profile()->GetOriginalProfile(),
483 browser->host_desktop_type());
486 void NewIncognitoWindow(Browser* browser) {
487 NewEmptyWindow(browser->profile()->GetOffTheRecordProfile(),
488 browser->host_desktop_type());
490 #endif // OS_WIN
492 void CloseWindow(Browser* browser) {
493 content::RecordAction(UserMetricsAction("CloseWindow"));
494 browser->window()->Close();
497 void NewTab(Browser* browser) {
498 content::RecordAction(UserMetricsAction("NewTab"));
499 // TODO(asvitkine): This is invoked programmatically from several places.
500 // Audit the code and change it so that the histogram only gets collected for
501 // user-initiated commands.
502 UMA_HISTOGRAM_ENUMERATION("Tab.NewTab", TabStripModel::NEW_TAB_COMMAND,
503 TabStripModel::NEW_TAB_ENUM_COUNT);
505 if (browser->is_type_tabbed()) {
506 AddTabAt(browser, GURL(), -1, true);
507 browser->tab_strip_model()->GetActiveWebContents()->GetView()->
508 RestoreFocus();
509 } else {
510 ScopedTabbedBrowserDisplayer displayer(browser->profile(),
511 browser->host_desktop_type());
512 Browser* b = displayer.browser();
513 AddTabAt(b, GURL(), -1, true);
514 b->window()->Show();
515 // The call to AddBlankTabAt above did not set the focus to the tab as its
516 // window was not active, so we have to do it explicitly.
517 // See http://crbug.com/6380.
518 b->tab_strip_model()->GetActiveWebContents()->GetView()->RestoreFocus();
522 void CloseTab(Browser* browser) {
523 content::RecordAction(UserMetricsAction("CloseTab_Accelerator"));
524 browser->tab_strip_model()->CloseSelectedTabs();
527 void RestoreTab(Browser* browser) {
528 content::RecordAction(UserMetricsAction("RestoreTab"));
529 TabRestoreService* service =
530 TabRestoreServiceFactory::GetForProfile(browser->profile());
531 if (service)
532 service->RestoreMostRecentEntry(browser->tab_restore_service_delegate(),
533 browser->host_desktop_type());
536 TabStripModelDelegate::RestoreTabType GetRestoreTabType(
537 const Browser* browser) {
538 TabRestoreService* service =
539 TabRestoreServiceFactory::GetForProfile(browser->profile());
540 if (!service || service->entries().empty())
541 return TabStripModelDelegate::RESTORE_NONE;
542 if (service->entries().front()->type == TabRestoreService::WINDOW)
543 return TabStripModelDelegate::RESTORE_WINDOW;
544 return TabStripModelDelegate::RESTORE_TAB;
547 void SelectNextTab(Browser* browser) {
548 content::RecordAction(UserMetricsAction("SelectNextTab"));
549 browser->tab_strip_model()->SelectNextTab();
552 void SelectPreviousTab(Browser* browser) {
553 content::RecordAction(UserMetricsAction("SelectPrevTab"));
554 browser->tab_strip_model()->SelectPreviousTab();
557 void MoveTabNext(Browser* browser) {
558 content::RecordAction(UserMetricsAction("MoveTabNext"));
559 browser->tab_strip_model()->MoveTabNext();
562 void MoveTabPrevious(Browser* browser) {
563 content::RecordAction(UserMetricsAction("MoveTabPrevious"));
564 browser->tab_strip_model()->MoveTabPrevious();
567 void SelectNumberedTab(Browser* browser, int index) {
568 if (index < browser->tab_strip_model()->count()) {
569 content::RecordAction(UserMetricsAction("SelectNumberedTab"));
570 browser->tab_strip_model()->ActivateTabAt(index, true);
574 void SelectLastTab(Browser* browser) {
575 content::RecordAction(UserMetricsAction("SelectLastTab"));
576 browser->tab_strip_model()->SelectLastTab();
579 void DuplicateTab(Browser* browser) {
580 content::RecordAction(UserMetricsAction("Duplicate"));
581 DuplicateTabAt(browser, browser->tab_strip_model()->active_index());
584 bool CanDuplicateTab(const Browser* browser) {
585 WebContents* contents = browser->tab_strip_model()->GetActiveWebContents();
586 return contents && contents->GetController().GetLastCommittedEntry();
589 WebContents* DuplicateTabAt(Browser* browser, int index) {
590 WebContents* contents = browser->tab_strip_model()->GetWebContentsAt(index);
591 CHECK(contents);
592 WebContents* contents_dupe = contents->Clone();
594 bool pinned = false;
595 if (browser->CanSupportWindowFeature(Browser::FEATURE_TABSTRIP)) {
596 // If this is a tabbed browser, just create a duplicate tab inside the same
597 // window next to the tab being duplicated.
598 int index = browser->tab_strip_model()->GetIndexOfWebContents(contents);
599 pinned = browser->tab_strip_model()->IsTabPinned(index);
600 int add_types = TabStripModel::ADD_ACTIVE |
601 TabStripModel::ADD_INHERIT_GROUP |
602 (pinned ? TabStripModel::ADD_PINNED : 0);
603 browser->tab_strip_model()->InsertWebContentsAt(
604 index + 1, contents_dupe, add_types);
605 } else {
606 Browser* new_browser = NULL;
607 if (browser->is_app() &&
608 !browser->is_type_popup()) {
609 new_browser = new Browser(
610 Browser::CreateParams::CreateForApp(browser->type(),
611 browser->app_name(),
612 gfx::Rect(),
613 browser->profile(),
614 browser->host_desktop_type()));
615 } else {
616 new_browser = new Browser(
617 Browser::CreateParams(browser->type(), browser->profile(),
618 browser->host_desktop_type()));
620 // Preserve the size of the original window. The new window has already
621 // been given an offset by the OS, so we shouldn't copy the old bounds.
622 BrowserWindow* new_window = new_browser->window();
623 new_window->SetBounds(gfx::Rect(new_window->GetRestoredBounds().origin(),
624 browser->window()->GetRestoredBounds().size()));
626 // We need to show the browser now. Otherwise ContainerWin assumes the
627 // WebContents is invisible and won't size it.
628 new_browser->window()->Show();
630 // The page transition below is only for the purpose of inserting the tab.
631 new_browser->tab_strip_model()->AddWebContents(
632 contents_dupe, -1,
633 content::PAGE_TRANSITION_LINK,
634 TabStripModel::ADD_ACTIVE);
637 SessionService* session_service =
638 SessionServiceFactory::GetForProfileIfExisting(browser->profile());
639 if (session_service)
640 session_service->TabRestored(contents_dupe, pinned);
641 return contents_dupe;
644 bool CanDuplicateTabAt(Browser* browser, int index) {
645 content::NavigationController& nc =
646 browser->tab_strip_model()->GetWebContentsAt(index)->GetController();
647 return nc.GetWebContents() && nc.GetLastCommittedEntry();
650 void ConvertPopupToTabbedBrowser(Browser* browser) {
651 content::RecordAction(UserMetricsAction("ShowAsTab"));
652 TabStripModel* tab_strip = browser->tab_strip_model();
653 WebContents* contents =
654 tab_strip->DetachWebContentsAt(tab_strip->active_index());
655 Browser* b = new Browser(Browser::CreateParams(browser->profile(),
656 browser->host_desktop_type()));
657 b->tab_strip_model()->AppendWebContents(contents, true);
658 b->window()->Show();
661 void Exit() {
662 content::RecordAction(UserMetricsAction("Exit"));
663 chrome::AttemptUserExit();
666 void BookmarkCurrentPage(Browser* browser) {
667 BookmarkCurrentPageInternal(browser, false);
670 void BookmarkCurrentPageFromStar(Browser* browser) {
671 BookmarkCurrentPageInternal(browser, true);
674 bool CanBookmarkCurrentPage(const Browser* browser) {
675 BookmarkModel* model =
676 BookmarkModelFactory::GetForProfile(browser->profile());
677 return browser_defaults::bookmarks_enabled &&
678 browser->profile()->GetPrefs()->GetBoolean(
679 prefs::kEditBookmarksEnabled) &&
680 model && model->loaded() && browser->is_type_tabbed();
683 void BookmarkAllTabs(Browser* browser) {
684 chrome::ShowBookmarkAllTabsDialog(browser);
687 bool CanBookmarkAllTabs(const Browser* browser) {
688 return browser->tab_strip_model()->count() > 1 &&
689 CanBookmarkCurrentPage(browser);
692 void Translate(Browser* browser) {
693 if (!browser->window()->IsActive())
694 return;
696 WebContents* web_contents =
697 browser->tab_strip_model()->GetActiveWebContents();
698 TranslateTabHelper* translate_tab_helper =
699 TranslateTabHelper::FromWebContents(web_contents);
701 TranslateTabHelper::TranslateStep step = TranslateTabHelper::BEFORE_TRANSLATE;
702 if (translate_tab_helper) {
703 if (translate_tab_helper->GetLanguageState().translation_pending())
704 step = TranslateTabHelper::TRANSLATING;
705 else if (translate_tab_helper->GetLanguageState().IsPageTranslated())
706 step = TranslateTabHelper::AFTER_TRANSLATE;
708 browser->window()->ShowTranslateBubble(
709 web_contents, step, TranslateErrors::NONE);
712 void TogglePagePinnedToStartScreen(Browser* browser) {
713 #if defined(OS_WIN)
714 MetroPinTabHelper::FromWebContents(
715 browser->tab_strip_model()->GetActiveWebContents())->
716 TogglePinnedToStartScreen();
717 #endif
720 void SavePage(Browser* browser) {
721 content::RecordAction(UserMetricsAction("SavePage"));
722 WebContents* current_tab = browser->tab_strip_model()->GetActiveWebContents();
723 if (current_tab && current_tab->GetContentsMimeType() == "application/pdf")
724 content::RecordAction(UserMetricsAction("PDF.SavePage"));
725 current_tab->OnSavePage();
728 bool CanSavePage(const Browser* browser) {
729 // LocalState can be NULL in tests.
730 if (g_browser_process->local_state() &&
731 !g_browser_process->local_state()->GetBoolean(
732 prefs::kAllowFileSelectionDialogs)) {
733 return false;
735 return !browser->is_devtools() &&
736 !(GetContentRestrictions(browser) & CONTENT_RESTRICTION_SAVE);
739 void ShowFindBar(Browser* browser) {
740 browser->GetFindBarController()->Show();
743 void ShowWebsiteSettings(Browser* browser,
744 content::WebContents* web_contents,
745 const GURL& url,
746 const SSLStatus& ssl) {
747 browser->window()->ShowWebsiteSettings(
748 Profile::FromBrowserContext(web_contents->GetBrowserContext()),
749 web_contents, url, ssl);
753 void Print(Browser* browser) {
754 #if defined(ENABLE_PRINTING)
755 WebContents* contents = browser->tab_strip_model()->GetActiveWebContents();
756 #if defined(ENABLE_FULL_PRINTING)
757 printing::PrintViewManager* print_view_manager =
758 printing::PrintViewManager::FromWebContents(contents);
759 if (browser->profile()->GetPrefs()->GetBoolean(prefs::kPrintPreviewDisabled))
760 print_view_manager->PrintNow();
761 else
762 print_view_manager->PrintPreviewNow(false);
763 #else
764 printing::PrintViewManagerBasic* print_view_manager =
765 printing::PrintViewManagerBasic::FromWebContents(contents);
766 print_view_manager->PrintNow();
767 #endif // defined(ENABLE_FULL_PRINTING)
768 #endif // defined(ENABLE_PRINTING)
771 bool CanPrint(const Browser* browser) {
772 // Do not print when printing is disabled via pref or policy.
773 // Do not print when a constrained window is showing. It's confusing.
774 return browser->profile()->GetPrefs()->GetBoolean(prefs::kPrintingEnabled) &&
775 !(IsShowingWebContentsModalDialog(browser) ||
776 GetContentRestrictions(browser) & CONTENT_RESTRICTION_PRINT);
779 void AdvancedPrint(Browser* browser) {
780 #if defined(ENABLE_FULL_PRINTING)
781 printing::PrintViewManager* print_view_manager =
782 printing::PrintViewManager::FromWebContents(
783 browser->tab_strip_model()->GetActiveWebContents());
784 print_view_manager->AdvancedPrintNow();
785 #endif
788 bool CanAdvancedPrint(const Browser* browser) {
789 // If printing is not disabled via pref or policy, it is always possible to
790 // advanced print when the print preview is visible. The exception to this
791 // is under Win8 ash, since showing the advanced print dialog will open it
792 // modally on the Desktop and hang the browser. We can remove this check
793 // once we integrate with the system print charm.
794 #if defined(OS_WIN)
795 if (chrome::GetActiveDesktop() == chrome::HOST_DESKTOP_TYPE_ASH)
796 return false;
797 #endif
799 return browser->profile()->GetPrefs()->GetBoolean(prefs::kPrintingEnabled) &&
800 (PrintPreviewShowing(browser) || CanPrint(browser));
803 void PrintToDestination(Browser* browser) {
804 #if defined(ENABLE_FULL_PRINTING)
805 printing::PrintViewManager* print_view_manager =
806 printing::PrintViewManager::FromWebContents(
807 browser->tab_strip_model()->GetActiveWebContents());
808 print_view_manager->PrintToDestination();
809 #endif
812 void EmailPageLocation(Browser* browser) {
813 content::RecordAction(UserMetricsAction("EmailPageLocation"));
814 WebContents* wc = browser->tab_strip_model()->GetActiveWebContents();
815 DCHECK(wc);
817 std::string title = net::EscapeQueryParamValue(
818 base::UTF16ToUTF8(wc->GetTitle()), false);
819 std::string page_url = net::EscapeQueryParamValue(wc->GetURL().spec(), false);
820 std::string mailto = std::string("mailto:?subject=Fwd:%20") +
821 title + "&body=%0A%0A" + page_url;
822 platform_util::OpenExternal(browser->profile(), GURL(mailto));
825 bool CanEmailPageLocation(const Browser* browser) {
826 return browser->toolbar_model()->ShouldDisplayURL() &&
827 browser->tab_strip_model()->GetActiveWebContents()->GetURL().is_valid();
830 void Cut(Browser* browser) {
831 content::RecordAction(UserMetricsAction("Cut"));
832 browser->window()->Cut();
835 void Copy(Browser* browser) {
836 content::RecordAction(UserMetricsAction("Copy"));
837 browser->window()->Copy();
840 void Paste(Browser* browser) {
841 content::RecordAction(UserMetricsAction("Paste"));
842 browser->window()->Paste();
845 void Find(Browser* browser) {
846 content::RecordAction(UserMetricsAction("Find"));
847 FindInPage(browser, false, false);
850 void FindNext(Browser* browser) {
851 content::RecordAction(UserMetricsAction("FindNext"));
852 FindInPage(browser, true, true);
855 void FindPrevious(Browser* browser) {
856 content::RecordAction(UserMetricsAction("FindPrevious"));
857 FindInPage(browser, true, false);
860 void FindInPage(Browser* browser, bool find_next, bool forward_direction) {
861 ShowFindBar(browser);
862 if (find_next) {
863 base::string16 find_text;
864 FindTabHelper* find_helper = FindTabHelper::FromWebContents(
865 browser->tab_strip_model()->GetActiveWebContents());
866 #if defined(OS_MACOSX)
867 // We always want to search for the current contents of the find bar on
868 // OS X. For regular profile it's always the current find pboard. For
869 // Incognito window it's the newest value of the find pboard content and
870 // user-typed text.
871 FindBar* find_bar = browser->GetFindBarController()->find_bar();
872 find_text = find_bar->GetFindText();
873 #endif
874 find_helper->StartFinding(find_text, forward_direction, false);
878 void Zoom(Browser* browser, content::PageZoom zoom) {
879 chrome_page_zoom::Zoom(browser->tab_strip_model()->GetActiveWebContents(),
880 zoom);
883 void FocusToolbar(Browser* browser) {
884 content::RecordAction(UserMetricsAction("FocusToolbar"));
885 browser->window()->FocusToolbar();
888 void FocusLocationBar(Browser* browser) {
889 content::RecordAction(UserMetricsAction("FocusLocation"));
890 browser->window()->SetFocusToLocationBar(true);
893 void FocusSearch(Browser* browser) {
894 // TODO(beng): replace this with FocusLocationBar
895 content::RecordAction(UserMetricsAction("FocusSearch"));
896 browser->window()->GetLocationBar()->FocusSearch();
899 void FocusAppMenu(Browser* browser) {
900 content::RecordAction(UserMetricsAction("FocusAppMenu"));
901 browser->window()->FocusAppMenu();
904 void FocusBookmarksToolbar(Browser* browser) {
905 content::RecordAction(UserMetricsAction("FocusBookmarksToolbar"));
906 browser->window()->FocusBookmarksToolbar();
909 void FocusInfobars(Browser* browser) {
910 content::RecordAction(UserMetricsAction("FocusInfobars"));
911 browser->window()->FocusInfobars();
914 void FocusNextPane(Browser* browser) {
915 content::RecordAction(UserMetricsAction("FocusNextPane"));
916 browser->window()->RotatePaneFocus(true);
919 void FocusPreviousPane(Browser* browser) {
920 content::RecordAction(UserMetricsAction("FocusPreviousPane"));
921 browser->window()->RotatePaneFocus(false);
924 void ToggleDevToolsWindow(Browser* browser, DevToolsToggleAction action) {
925 if (action.type() == DevToolsToggleAction::kShowConsole)
926 content::RecordAction(UserMetricsAction("DevTools_ToggleConsole"));
927 else
928 content::RecordAction(UserMetricsAction("DevTools_ToggleWindow"));
929 DevToolsWindow::ToggleDevToolsWindow(browser, action);
932 bool CanOpenTaskManager() {
933 #if defined(OS_WIN)
934 // In metro we can't display the task manager, as it is a native window.
935 return !win8::IsSingleWindowMetroMode();
936 #else
937 return true;
938 #endif
941 void OpenTaskManager(Browser* browser) {
942 content::RecordAction(UserMetricsAction("TaskManager"));
943 chrome::ShowTaskManager(browser);
946 void OpenFeedbackDialog(Browser* browser) {
947 content::RecordAction(UserMetricsAction("Feedback"));
948 chrome::ShowFeedbackPage(browser, std::string(), std::string());
951 void ToggleBookmarkBar(Browser* browser) {
952 content::RecordAction(UserMetricsAction("ShowBookmarksBar"));
953 ToggleBookmarkBarWhenVisible(browser->profile());
956 void ShowAppMenu(Browser* browser) {
957 // We record the user metric for this event in WrenchMenu::RunMenu.
958 browser->window()->ShowAppMenu();
961 void ShowAvatarMenu(Browser* browser) {
962 browser->window()->ShowAvatarBubbleFromAvatarButton();
965 void OpenUpdateChromeDialog(Browser* browser) {
966 if (UpgradeDetector::GetInstance()->is_outdated_install()) {
967 content::NotificationService::current()->Notify(
968 chrome::NOTIFICATION_OUTDATED_INSTALL,
969 content::NotificationService::AllSources(),
970 content::NotificationService::NoDetails());
971 } else {
972 content::RecordAction(UserMetricsAction("UpdateChrome"));
973 browser->window()->ShowUpdateChromeDialog();
977 void ToggleSpeechInput(Browser* browser) {
978 WebContents* web_contents =
979 browser->tab_strip_model()->GetActiveWebContents();
980 web_contents->GetRenderViewHost()->ToggleSpeechInput();
982 SearchTabHelper* search_tab_helper =
983 SearchTabHelper::FromWebContents(web_contents);
984 // |search_tab_helper| can be null in unit tests.
985 if (search_tab_helper)
986 search_tab_helper->ToggleVoiceSearch();
989 bool CanRequestTabletSite(WebContents* current_tab) {
990 if (!current_tab)
991 return false;
992 return current_tab->GetController().GetActiveEntry() != NULL;
995 bool IsRequestingTabletSite(Browser* browser) {
996 WebContents* current_tab = browser->tab_strip_model()->GetActiveWebContents();
997 if (!current_tab)
998 return false;
999 content::NavigationEntry* entry =
1000 current_tab->GetController().GetActiveEntry();
1001 if (!entry)
1002 return false;
1003 return entry->GetIsOverridingUserAgent();
1006 void ToggleRequestTabletSite(Browser* browser) {
1007 WebContents* current_tab = browser->tab_strip_model()->GetActiveWebContents();
1008 if (!current_tab)
1009 return;
1010 NavigationController& controller = current_tab->GetController();
1011 NavigationEntry* entry = controller.GetActiveEntry();
1012 if (!entry)
1013 return;
1014 if (entry->GetIsOverridingUserAgent()) {
1015 entry->SetIsOverridingUserAgent(false);
1016 } else {
1017 entry->SetIsOverridingUserAgent(true);
1018 chrome::VersionInfo version_info;
1019 std::string product;
1020 if (version_info.is_valid())
1021 product = version_info.ProductNameAndVersionForUserAgent();
1022 current_tab->SetUserAgentOverride(
1023 webkit_glue::BuildUserAgentFromOSAndProduct(
1024 kOsOverrideForTabletSite, product));
1026 controller.ReloadOriginalRequestURL(true);
1029 void ToggleFullscreenMode(Browser* browser) {
1030 browser->fullscreen_controller()->ToggleFullscreenMode();
1033 void ClearCache(Browser* browser) {
1034 BrowsingDataRemover* remover =
1035 BrowsingDataRemover::CreateForUnboundedRange(browser->profile());
1036 remover->Remove(BrowsingDataRemover::REMOVE_CACHE,
1037 BrowsingDataHelper::UNPROTECTED_WEB);
1038 // BrowsingDataRemover takes care of deleting itself when done.
1041 bool IsDebuggerAttachedToCurrentTab(Browser* browser) {
1042 WebContents* contents = browser->tab_strip_model()->GetActiveWebContents();
1043 return contents ?
1044 content::DevToolsAgentHost::IsDebuggerAttached(contents) : false;
1047 void ViewSource(Browser* browser, WebContents* contents) {
1048 DCHECK(contents);
1050 // Use the last committed entry, since the pending entry hasn't loaded yet and
1051 // won't be copied into the cloned tab.
1052 NavigationEntry* entry = contents->GetController().GetLastCommittedEntry();
1053 if (!entry)
1054 return;
1056 ViewSource(browser, contents, entry->GetURL(), entry->GetPageState());
1059 void ViewSource(Browser* browser,
1060 WebContents* contents,
1061 const GURL& url,
1062 const content::PageState& page_state) {
1063 content::RecordAction(UserMetricsAction("ViewSource"));
1064 DCHECK(contents);
1066 // Note that Clone does not copy the pending or transient entries, so the
1067 // active entry in view_source_contents will be the last committed entry.
1068 WebContents* view_source_contents = contents->Clone();
1069 DCHECK(view_source_contents->GetController().CanPruneAllButLastCommitted());
1070 view_source_contents->GetController().PruneAllButLastCommitted();
1071 NavigationEntry* active_entry =
1072 view_source_contents->GetController().GetActiveEntry();
1073 if (!active_entry)
1074 return;
1076 GURL view_source_url =
1077 GURL(content::kViewSourceScheme + std::string(":") + url.spec());
1078 active_entry->SetVirtualURL(view_source_url);
1080 // Do not restore scroller position.
1081 active_entry->SetPageState(page_state.RemoveScrollOffset());
1083 // Do not restore title, derive it from the url.
1084 active_entry->SetTitle(base::string16());
1086 // Now show view-source entry.
1087 if (browser->CanSupportWindowFeature(Browser::FEATURE_TABSTRIP)) {
1088 // If this is a tabbed browser, just create a duplicate tab inside the same
1089 // window next to the tab being duplicated.
1090 int index = browser->tab_strip_model()->GetIndexOfWebContents(contents);
1091 int add_types = TabStripModel::ADD_ACTIVE |
1092 TabStripModel::ADD_INHERIT_GROUP;
1093 browser->tab_strip_model()->InsertWebContentsAt(
1094 index + 1,
1095 view_source_contents,
1096 add_types);
1097 } else {
1098 Browser* b = new Browser(
1099 Browser::CreateParams(Browser::TYPE_TABBED, browser->profile(),
1100 browser->host_desktop_type()));
1102 // Preserve the size of the original window. The new window has already
1103 // been given an offset by the OS, so we shouldn't copy the old bounds.
1104 BrowserWindow* new_window = b->window();
1105 new_window->SetBounds(gfx::Rect(new_window->GetRestoredBounds().origin(),
1106 browser->window()->GetRestoredBounds().size()));
1108 // We need to show the browser now. Otherwise ContainerWin assumes the
1109 // WebContents is invisible and won't size it.
1110 b->window()->Show();
1112 // The page transition below is only for the purpose of inserting the tab.
1113 b->tab_strip_model()->AddWebContents(view_source_contents, -1,
1114 content::PAGE_TRANSITION_LINK,
1115 TabStripModel::ADD_ACTIVE);
1118 SessionService* session_service =
1119 SessionServiceFactory::GetForProfileIfExisting(browser->profile());
1120 if (session_service)
1121 session_service->TabRestored(view_source_contents, false);
1124 void ViewSelectedSource(Browser* browser) {
1125 ViewSource(browser, browser->tab_strip_model()->GetActiveWebContents());
1128 bool CanViewSource(const Browser* browser) {
1129 return !browser->is_devtools() &&
1130 browser->tab_strip_model()->GetActiveWebContents()->GetController().
1131 CanViewSource();
1134 void CreateApplicationShortcuts(Browser* browser) {
1135 content::RecordAction(UserMetricsAction("CreateShortcut"));
1136 extensions::TabHelper::FromWebContents(
1137 browser->tab_strip_model()->GetActiveWebContents())->
1138 CreateApplicationShortcuts();
1141 void CreateHostedAppFromCurrentWebContents(Browser* browser) {
1142 content::RecordAction(UserMetricsAction("CreateHostedApp"));
1143 extensions::TabHelper::FromWebContents(
1144 browser->tab_strip_model()->GetActiveWebContents())->
1145 CreateHostedAppFromWebContents();
1148 bool CanCreateApplicationShortcuts(const Browser* browser) {
1149 return extensions::TabHelper::FromWebContents(
1150 browser->tab_strip_model()->GetActiveWebContents())->
1151 CanCreateApplicationShortcuts();
1154 void ConvertTabToAppWindow(Browser* browser,
1155 content::WebContents* contents) {
1156 const GURL& url = contents->GetController().GetActiveEntry()->GetURL();
1157 std::string app_name = web_app::GenerateApplicationNameFromURL(url);
1159 int index = browser->tab_strip_model()->GetIndexOfWebContents(contents);
1160 if (index >= 0)
1161 browser->tab_strip_model()->DetachWebContentsAt(index);
1163 Browser* app_browser = new Browser(
1164 Browser::CreateParams::CreateForApp(
1165 Browser::TYPE_POPUP, app_name, gfx::Rect(), browser->profile(),
1166 browser->host_desktop_type()));
1167 app_browser->tab_strip_model()->AppendWebContents(contents, true);
1169 contents->GetMutableRendererPrefs()->can_accept_load_drops = false;
1170 contents->GetRenderViewHost()->SyncRendererPrefs();
1171 app_browser->window()->Show();
1174 } // namespace chrome