Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / ui / browser_commands.cc
blob8580a4480bfd1b041685e70dc0685bf3f7d12373
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/translate/translate_bubble_model.h"
56 #include "chrome/browser/ui/webui/ntp/core_app_launcher_handler.h"
57 #include "chrome/browser/upgrade_detector.h"
58 #include "chrome/browser/web_applications/web_app.h"
59 #include "chrome/common/chrome_switches.h"
60 #include "chrome/common/chrome_version_info.h"
61 #include "chrome/common/content_restriction.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/user_metrics.h"
71 #include "content/public/browser/web_contents.h"
72 #include "content/public/browser/web_contents_view.h"
73 #include "content/public/common/renderer_preferences.h"
74 #include "content/public/common/url_constants.h"
75 #include "content/public/common/url_utils.h"
76 #include "net/base/escape.h"
77 #include "webkit/common/user_agent/user_agent_util.h"
79 #if defined(OS_WIN)
80 #include "chrome/browser/ui/metro_pin_tab_helper_win.h"
81 #include "win8/util/win8_util.h"
82 #endif
84 #if defined(ENABLE_PRINTING)
85 #if defined(ENABLE_FULL_PRINTING)
86 #include "chrome/browser/printing/print_preview_dialog_controller.h"
87 #include "chrome/browser/printing/print_view_manager.h"
88 #else
89 #include "chrome/browser/printing/print_view_manager_basic.h"
90 #endif // defined(ENABLE_FULL_PRINTING)
91 #endif // defined(ENABLE_PRINTING)
93 namespace {
94 const char kOsOverrideForTabletSite[] = "Linux; Android 4.0.3";
97 using base::UserMetricsAction;
98 using content::NavigationController;
99 using content::NavigationEntry;
100 using content::OpenURLParams;
101 using content::Referrer;
102 using content::SSLStatus;
103 using content::WebContents;
104 using web_modal::WebContentsModalDialogManager;
106 namespace chrome {
107 namespace {
109 void BookmarkCurrentPageInternal(Browser* browser, bool from_star) {
110 content::RecordAction(UserMetricsAction("Star"));
112 BookmarkModel* model =
113 BookmarkModelFactory::GetForProfile(browser->profile());
114 if (!model || !model->loaded())
115 return; // Ignore requests until bookmarks are loaded.
117 GURL url;
118 base::string16 title;
119 WebContents* web_contents =
120 browser->tab_strip_model()->GetActiveWebContents();
121 GetURLAndTitleToBookmark(web_contents, &url, &title);
122 bool was_bookmarked = model->IsBookmarked(url);
123 if (!was_bookmarked && web_contents->GetBrowserContext()->IsOffTheRecord()) {
124 // If we're incognito the favicon may not have been saved. Save it now
125 // so that bookmarks have an icon for the page.
126 FaviconTabHelper::FromWebContents(web_contents)->SaveFavicon();
128 bookmark_utils::AddIfNotBookmarked(model, url, title);
129 if (from_star && !was_bookmarked)
130 BookmarkPromptController::AddedBookmark(browser, url);
131 // Make sure the model actually added a bookmark before showing the star. A
132 // bookmark isn't created if the url is invalid.
133 if (browser->window()->IsActive() && model->IsBookmarked(url)) {
134 // Only show the bubble if the window is active, otherwise we may get into
135 // weird situations where the bubble is deleted as soon as it is shown.
136 browser->window()->ShowBookmarkBubble(url, was_bookmarked);
140 WebContents* GetOrCloneTabForDisposition(Browser* browser,
141 WindowOpenDisposition disposition) {
142 WebContents* current_tab = browser->tab_strip_model()->GetActiveWebContents();
143 switch (disposition) {
144 case NEW_FOREGROUND_TAB:
145 case NEW_BACKGROUND_TAB: {
146 current_tab = current_tab->Clone();
147 browser->tab_strip_model()->AddWebContents(
148 current_tab, -1, content::PAGE_TRANSITION_LINK,
149 disposition == NEW_FOREGROUND_TAB ? TabStripModel::ADD_ACTIVE :
150 TabStripModel::ADD_NONE);
151 break;
153 case NEW_WINDOW: {
154 current_tab = current_tab->Clone();
155 Browser* b = new Browser(Browser::CreateParams(
156 browser->profile(), browser->host_desktop_type()));
157 b->tab_strip_model()->AddWebContents(
158 current_tab, -1, content::PAGE_TRANSITION_LINK,
159 TabStripModel::ADD_ACTIVE);
160 b->window()->Show();
161 break;
163 default:
164 break;
166 return current_tab;
169 void ReloadInternal(Browser* browser,
170 WindowOpenDisposition disposition,
171 bool ignore_cache) {
172 // As this is caused by a user action, give the focus to the page.
174 // Also notify RenderViewHostDelegate of the user gesture; this is
175 // normally done in Browser::Navigate, but a reload bypasses Navigate.
176 WebContents* web_contents = GetOrCloneTabForDisposition(browser, disposition);
177 web_contents->UserGestureDone();
178 if (!web_contents->FocusLocationBarByDefault())
179 web_contents->GetView()->Focus();
180 if (ignore_cache)
181 web_contents->GetController().ReloadIgnoringCache(true);
182 else
183 web_contents->GetController().Reload(true);
186 bool IsShowingWebContentsModalDialog(const Browser* browser) {
187 WebContents* web_contents =
188 browser->tab_strip_model()->GetActiveWebContents();
189 if (!web_contents)
190 return false;
192 WebContentsModalDialogManager* web_contents_modal_dialog_manager =
193 WebContentsModalDialogManager::FromWebContents(web_contents);
194 return web_contents_modal_dialog_manager->IsDialogActive();
197 bool PrintPreviewShowing(const Browser* browser) {
198 #if defined(ENABLE_FULL_PRINTING)
199 WebContents* contents = browser->tab_strip_model()->GetActiveWebContents();
200 printing::PrintPreviewDialogController* controller =
201 printing::PrintPreviewDialogController::GetInstance();
202 return controller && (controller->GetPrintPreviewForContents(contents) ||
203 controller->is_creating_print_preview_dialog());
204 #else
205 return false;
206 #endif
209 } // namespace
211 bool IsCommandEnabled(Browser* browser, int command) {
212 return browser->command_controller()->command_updater()->IsCommandEnabled(
213 command);
216 bool SupportsCommand(Browser* browser, int command) {
217 return browser->command_controller()->command_updater()->SupportsCommand(
218 command);
221 bool ExecuteCommand(Browser* browser, int command) {
222 return browser->command_controller()->command_updater()->ExecuteCommand(
223 command);
226 bool ExecuteCommandWithDisposition(Browser* browser,
227 int command,
228 WindowOpenDisposition disposition) {
229 return browser->command_controller()->command_updater()->
230 ExecuteCommandWithDisposition(command, disposition);
233 void UpdateCommandEnabled(Browser* browser, int command, bool enabled) {
234 browser->command_controller()->command_updater()->UpdateCommandEnabled(
235 command, enabled);
238 void AddCommandObserver(Browser* browser,
239 int command,
240 CommandObserver* observer) {
241 browser->command_controller()->command_updater()->AddCommandObserver(
242 command, observer);
245 void RemoveCommandObserver(Browser* browser,
246 int command,
247 CommandObserver* observer) {
248 browser->command_controller()->command_updater()->RemoveCommandObserver(
249 command, observer);
252 int GetContentRestrictions(const Browser* browser) {
253 int content_restrictions = 0;
254 WebContents* current_tab = browser->tab_strip_model()->GetActiveWebContents();
255 if (current_tab) {
256 CoreTabHelper* core_tab_helper =
257 CoreTabHelper::FromWebContents(current_tab);
258 content_restrictions = core_tab_helper->content_restrictions();
259 NavigationEntry* active_entry =
260 current_tab->GetController().GetActiveEntry();
261 // See comment in UpdateCommandsForTabState about why we call url().
262 if (!content::IsSavableURL(
263 active_entry ? active_entry->GetURL() : GURL()) ||
264 current_tab->ShowingInterstitialPage())
265 content_restrictions |= CONTENT_RESTRICTION_SAVE;
266 if (current_tab->ShowingInterstitialPage())
267 content_restrictions |= CONTENT_RESTRICTION_PRINT;
269 return content_restrictions;
272 void NewEmptyWindow(Profile* profile, HostDesktopType desktop_type) {
273 bool incognito = profile->IsOffTheRecord();
274 PrefService* prefs = profile->GetPrefs();
275 if (incognito) {
276 if (IncognitoModePrefs::GetAvailability(prefs) ==
277 IncognitoModePrefs::DISABLED) {
278 incognito = false;
280 } else {
281 if (browser_defaults::kAlwaysOpenIncognitoWindow &&
282 IncognitoModePrefs::ShouldLaunchIncognito(
283 *CommandLine::ForCurrentProcess(), prefs)) {
284 incognito = true;
288 if (incognito) {
289 content::RecordAction(UserMetricsAction("NewIncognitoWindow"));
290 OpenEmptyWindow(profile->GetOffTheRecordProfile(), desktop_type);
291 } else {
292 content::RecordAction(UserMetricsAction("NewWindow"));
293 SessionService* session_service =
294 SessionServiceFactory::GetForProfileForSessionRestore(
295 profile->GetOriginalProfile());
296 if (!session_service ||
297 !session_service->RestoreIfNecessary(std::vector<GURL>())) {
298 OpenEmptyWindow(profile->GetOriginalProfile(), desktop_type);
303 Browser* OpenEmptyWindow(Profile* profile, HostDesktopType desktop_type) {
304 Browser* browser = new Browser(
305 Browser::CreateParams(Browser::TYPE_TABBED, profile, desktop_type));
306 AddTabAt(browser, GURL(), -1, true);
307 browser->window()->Show();
308 return browser;
311 void OpenWindowWithRestoredTabs(Profile* profile,
312 HostDesktopType host_desktop_type) {
313 TabRestoreService* service = TabRestoreServiceFactory::GetForProfile(profile);
314 if (service)
315 service->RestoreMostRecentEntry(NULL, host_desktop_type);
318 void OpenURLOffTheRecord(Profile* profile,
319 const GURL& url,
320 chrome::HostDesktopType desktop_type) {
321 ScopedTabbedBrowserDisplayer displayer(profile->GetOffTheRecordProfile(),
322 desktop_type);
323 AddSelectedTabWithURL(displayer.browser(), url,
324 content::PAGE_TRANSITION_LINK);
327 bool CanGoBack(const Browser* browser) {
328 return browser->tab_strip_model()->GetActiveWebContents()->
329 GetController().CanGoBack();
332 void GoBack(Browser* browser, WindowOpenDisposition disposition) {
333 content::RecordAction(UserMetricsAction("Back"));
335 WebContents* current_tab = browser->tab_strip_model()->GetActiveWebContents();
336 if (CanGoBack(browser)) {
337 WebContents* new_tab = GetOrCloneTabForDisposition(browser, disposition);
338 // If we are on an interstitial page and clone the tab, it won't be copied
339 // to the new tab, so we don't need to go back.
340 if (current_tab->ShowingInterstitialPage() && new_tab != current_tab)
341 return;
342 new_tab->GetController().GoBack();
346 bool CanGoForward(const Browser* browser) {
347 return browser->tab_strip_model()->GetActiveWebContents()->
348 GetController().CanGoForward();
351 void GoForward(Browser* browser, WindowOpenDisposition disposition) {
352 content::RecordAction(UserMetricsAction("Forward"));
353 if (CanGoForward(browser)) {
354 GetOrCloneTabForDisposition(browser, disposition)->
355 GetController().GoForward();
359 bool NavigateToIndexWithDisposition(Browser* browser,
360 int index,
361 WindowOpenDisposition disp) {
362 NavigationController& controller =
363 GetOrCloneTabForDisposition(browser, disp)->GetController();
364 if (index < 0 || index >= controller.GetEntryCount())
365 return false;
366 controller.GoToIndex(index);
367 return true;
370 void Reload(Browser* browser, WindowOpenDisposition disposition) {
371 content::RecordAction(UserMetricsAction("Reload"));
372 ReloadInternal(browser, disposition, false);
375 void ReloadIgnoringCache(Browser* browser, WindowOpenDisposition disposition) {
376 content::RecordAction(UserMetricsAction("ReloadIgnoringCache"));
377 ReloadInternal(browser, disposition, true);
380 bool CanReload(const Browser* browser) {
381 return !browser->is_devtools();
384 void Home(Browser* browser, WindowOpenDisposition disposition) {
385 content::RecordAction(UserMetricsAction("Home"));
387 std::string extra_headers;
388 #if defined(ENABLE_RLZ)
389 // If the home page is a Google home page, add the RLZ header to the request.
390 PrefService* pref_service = browser->profile()->GetPrefs();
391 if (pref_service) {
392 if (google_util::IsGoogleHomePageUrl(
393 GURL(pref_service->GetString(prefs::kHomePage)))) {
394 extra_headers = RLZTracker::GetAccessPointHttpHeader(
395 RLZTracker::CHROME_HOME_PAGE);
398 #endif
400 OpenURLParams params(
401 browser->profile()->GetHomePage(), Referrer(), disposition,
402 content::PageTransitionFromInt(
403 content::PAGE_TRANSITION_AUTO_BOOKMARK |
404 content::PAGE_TRANSITION_HOME_PAGE),
405 false);
406 params.extra_headers = extra_headers;
407 browser->OpenURL(params);
410 void OpenCurrentURL(Browser* browser) {
411 content::RecordAction(UserMetricsAction("LoadURL"));
412 LocationBar* location_bar = browser->window()->GetLocationBar();
413 if (!location_bar)
414 return;
416 GURL url(location_bar->GetDestinationURL());
418 content::PageTransition page_transition = location_bar->GetPageTransition();
419 content::PageTransition page_transition_without_qualifier(
420 PageTransitionStripQualifier(page_transition));
421 WindowOpenDisposition open_disposition =
422 location_bar->GetWindowOpenDisposition();
423 // A PAGE_TRANSITION_TYPED means the user has typed a URL. We do not want to
424 // open URLs with instant_controller since in some cases it disregards it
425 // and performs a search instead. For example, when using CTRL-Enter, the
426 // location_bar is aware of the URL but instant is not.
427 // Instant should also not handle PAGE_TRANSITION_RELOAD because its knowledge
428 // of the omnibox text may be stale if the user focuses in the omnibox and
429 // presses enter without typing anything.
430 if (page_transition_without_qualifier != content::PAGE_TRANSITION_TYPED &&
431 page_transition_without_qualifier != content::PAGE_TRANSITION_RELOAD &&
432 browser->instant_controller() &&
433 browser->instant_controller()->OpenInstant(open_disposition, url))
434 return;
436 NavigateParams params(browser, url, page_transition);
437 params.disposition = open_disposition;
438 // Use ADD_INHERIT_OPENER so that all pages opened by the omnibox at least
439 // inherit the opener. In some cases the tabstrip will determine the group
440 // should be inherited, in which case the group is inherited instead of the
441 // opener.
442 params.tabstrip_add_types =
443 TabStripModel::ADD_FORCE_INDEX | TabStripModel::ADD_INHERIT_OPENER;
444 Navigate(&params);
446 DCHECK(browser->profile()->GetExtensionService());
447 const extensions::Extension* extension =
448 browser->profile()->GetExtensionService()->GetInstalledApp(url);
449 if (extension) {
450 CoreAppLauncherHandler::RecordAppLaunchType(
451 extension_misc::APP_LAUNCH_OMNIBOX_LOCATION,
452 extension->GetType());
456 void Stop(Browser* browser) {
457 content::RecordAction(UserMetricsAction("Stop"));
458 browser->tab_strip_model()->GetActiveWebContents()->Stop();
461 #if !defined(OS_WIN)
462 void NewWindow(Browser* browser) {
463 NewEmptyWindow(browser->profile()->GetOriginalProfile(),
464 browser->host_desktop_type());
467 void NewIncognitoWindow(Browser* browser) {
468 NewEmptyWindow(browser->profile()->GetOffTheRecordProfile(),
469 browser->host_desktop_type());
471 #endif // OS_WIN
473 void CloseWindow(Browser* browser) {
474 content::RecordAction(UserMetricsAction("CloseWindow"));
475 browser->window()->Close();
478 void NewTab(Browser* browser) {
479 content::RecordAction(UserMetricsAction("NewTab"));
480 // TODO(asvitkine): This is invoked programmatically from several places.
481 // Audit the code and change it so that the histogram only gets collected for
482 // user-initiated commands.
483 UMA_HISTOGRAM_ENUMERATION("Tab.NewTab", TabStripModel::NEW_TAB_COMMAND,
484 TabStripModel::NEW_TAB_ENUM_COUNT);
486 if (browser->is_type_tabbed()) {
487 AddTabAt(browser, GURL(), -1, true);
488 browser->tab_strip_model()->GetActiveWebContents()->GetView()->
489 RestoreFocus();
490 } else {
491 ScopedTabbedBrowserDisplayer displayer(browser->profile(),
492 browser->host_desktop_type());
493 Browser* b = displayer.browser();
494 AddTabAt(b, GURL(), -1, true);
495 b->window()->Show();
496 // The call to AddBlankTabAt above did not set the focus to the tab as its
497 // window was not active, so we have to do it explicitly.
498 // See http://crbug.com/6380.
499 b->tab_strip_model()->GetActiveWebContents()->GetView()->RestoreFocus();
503 void CloseTab(Browser* browser) {
504 content::RecordAction(UserMetricsAction("CloseTab_Accelerator"));
505 browser->tab_strip_model()->CloseSelectedTabs();
508 void RestoreTab(Browser* browser) {
509 content::RecordAction(UserMetricsAction("RestoreTab"));
510 TabRestoreService* service =
511 TabRestoreServiceFactory::GetForProfile(browser->profile());
512 if (service)
513 service->RestoreMostRecentEntry(browser->tab_restore_service_delegate(),
514 browser->host_desktop_type());
517 TabStripModelDelegate::RestoreTabType GetRestoreTabType(
518 const Browser* browser) {
519 TabRestoreService* service =
520 TabRestoreServiceFactory::GetForProfile(browser->profile());
521 if (!service || service->entries().empty())
522 return TabStripModelDelegate::RESTORE_NONE;
523 if (service->entries().front()->type == TabRestoreService::WINDOW)
524 return TabStripModelDelegate::RESTORE_WINDOW;
525 return TabStripModelDelegate::RESTORE_TAB;
528 void SelectNextTab(Browser* browser) {
529 content::RecordAction(UserMetricsAction("SelectNextTab"));
530 browser->tab_strip_model()->SelectNextTab();
533 void SelectPreviousTab(Browser* browser) {
534 content::RecordAction(UserMetricsAction("SelectPrevTab"));
535 browser->tab_strip_model()->SelectPreviousTab();
538 void OpenTabpose(Browser* browser) {
539 #if defined(OS_MACOSX)
540 if (!CommandLine::ForCurrentProcess()->HasSwitch(
541 switches::kEnableExposeForTabs)) {
542 return;
545 content::RecordAction(UserMetricsAction("OpenTabpose"));
546 browser->window()->OpenTabpose();
547 #else
548 NOTREACHED();
549 #endif
552 void MoveTabNext(Browser* browser) {
553 content::RecordAction(UserMetricsAction("MoveTabNext"));
554 browser->tab_strip_model()->MoveTabNext();
557 void MoveTabPrevious(Browser* browser) {
558 content::RecordAction(UserMetricsAction("MoveTabPrevious"));
559 browser->tab_strip_model()->MoveTabPrevious();
562 void SelectNumberedTab(Browser* browser, int index) {
563 if (index < browser->tab_strip_model()->count()) {
564 content::RecordAction(UserMetricsAction("SelectNumberedTab"));
565 browser->tab_strip_model()->ActivateTabAt(index, true);
569 void SelectLastTab(Browser* browser) {
570 content::RecordAction(UserMetricsAction("SelectLastTab"));
571 browser->tab_strip_model()->SelectLastTab();
574 void DuplicateTab(Browser* browser) {
575 content::RecordAction(UserMetricsAction("Duplicate"));
576 DuplicateTabAt(browser, browser->tab_strip_model()->active_index());
579 bool CanDuplicateTab(const Browser* browser) {
580 WebContents* contents = browser->tab_strip_model()->GetActiveWebContents();
581 return contents && contents->GetController().GetLastCommittedEntry();
584 WebContents* DuplicateTabAt(Browser* browser, int index) {
585 WebContents* contents = browser->tab_strip_model()->GetWebContentsAt(index);
586 CHECK(contents);
587 WebContents* contents_dupe = contents->Clone();
589 bool pinned = false;
590 if (browser->CanSupportWindowFeature(Browser::FEATURE_TABSTRIP)) {
591 // If this is a tabbed browser, just create a duplicate tab inside the same
592 // window next to the tab being duplicated.
593 int index = browser->tab_strip_model()->GetIndexOfWebContents(contents);
594 pinned = browser->tab_strip_model()->IsTabPinned(index);
595 int add_types = TabStripModel::ADD_ACTIVE |
596 TabStripModel::ADD_INHERIT_GROUP |
597 (pinned ? TabStripModel::ADD_PINNED : 0);
598 browser->tab_strip_model()->InsertWebContentsAt(
599 index + 1, contents_dupe, add_types);
600 } else {
601 Browser* new_browser = NULL;
602 if (browser->is_app() &&
603 !browser->is_type_popup()) {
604 new_browser = new Browser(
605 Browser::CreateParams::CreateForApp(browser->type(),
606 browser->app_name(),
607 gfx::Rect(),
608 browser->profile(),
609 browser->host_desktop_type()));
610 } else {
611 new_browser = new Browser(
612 Browser::CreateParams(browser->type(), browser->profile(),
613 browser->host_desktop_type()));
615 // Preserve the size of the original window. The new window has already
616 // been given an offset by the OS, so we shouldn't copy the old bounds.
617 BrowserWindow* new_window = new_browser->window();
618 new_window->SetBounds(gfx::Rect(new_window->GetRestoredBounds().origin(),
619 browser->window()->GetRestoredBounds().size()));
621 // We need to show the browser now. Otherwise ContainerWin assumes the
622 // WebContents is invisible and won't size it.
623 new_browser->window()->Show();
625 // The page transition below is only for the purpose of inserting the tab.
626 new_browser->tab_strip_model()->AddWebContents(
627 contents_dupe, -1,
628 content::PAGE_TRANSITION_LINK,
629 TabStripModel::ADD_ACTIVE);
632 SessionService* session_service =
633 SessionServiceFactory::GetForProfileIfExisting(browser->profile());
634 if (session_service)
635 session_service->TabRestored(contents_dupe, pinned);
636 return contents_dupe;
639 bool CanDuplicateTabAt(Browser* browser, int index) {
640 content::NavigationController& nc =
641 browser->tab_strip_model()->GetWebContentsAt(index)->GetController();
642 return nc.GetWebContents() && nc.GetLastCommittedEntry();
645 void ConvertPopupToTabbedBrowser(Browser* browser) {
646 content::RecordAction(UserMetricsAction("ShowAsTab"));
647 TabStripModel* tab_strip = browser->tab_strip_model();
648 WebContents* contents =
649 tab_strip->DetachWebContentsAt(tab_strip->active_index());
650 Browser* b = new Browser(Browser::CreateParams(browser->profile(),
651 browser->host_desktop_type()));
652 b->tab_strip_model()->AppendWebContents(contents, true);
653 b->window()->Show();
656 void Exit() {
657 content::RecordAction(UserMetricsAction("Exit"));
658 chrome::AttemptUserExit();
661 void BookmarkCurrentPage(Browser* browser) {
662 BookmarkCurrentPageInternal(browser, false);
665 void BookmarkCurrentPageFromStar(Browser* browser) {
666 BookmarkCurrentPageInternal(browser, true);
669 bool CanBookmarkCurrentPage(const Browser* browser) {
670 BookmarkModel* model =
671 BookmarkModelFactory::GetForProfile(browser->profile());
672 return browser_defaults::bookmarks_enabled &&
673 browser->profile()->GetPrefs()->GetBoolean(
674 prefs::kEditBookmarksEnabled) &&
675 model && model->loaded() && browser->is_type_tabbed();
678 void BookmarkAllTabs(Browser* browser) {
679 chrome::ShowBookmarkAllTabsDialog(browser);
682 bool CanBookmarkAllTabs(const Browser* browser) {
683 return browser->tab_strip_model()->count() > 1 &&
684 CanBookmarkCurrentPage(browser);
687 void Translate(Browser* browser) {
688 if (!browser->window()->IsActive())
689 return;
691 WebContents* web_contents =
692 browser->tab_strip_model()->GetActiveWebContents();
693 TranslateTabHelper* translate_tab_helper =
694 TranslateTabHelper::FromWebContents(web_contents);
696 TranslateBubbleModel::ViewState view_state =
697 TranslateBubbleModel::VIEW_STATE_BEFORE_TRANSLATE;
698 if (translate_tab_helper) {
699 if (translate_tab_helper->language_state().translation_pending())
700 view_state = TranslateBubbleModel::VIEW_STATE_TRANSLATING;
701 else if (translate_tab_helper->language_state().IsPageTranslated())
702 view_state = TranslateBubbleModel::VIEW_STATE_AFTER_TRANSLATE;
704 browser->window()->ShowTranslateBubble(web_contents, view_state,
705 TranslateErrors::NONE);
708 void TogglePagePinnedToStartScreen(Browser* browser) {
709 #if defined(OS_WIN)
710 MetroPinTabHelper::FromWebContents(
711 browser->tab_strip_model()->GetActiveWebContents())->
712 TogglePinnedToStartScreen();
713 #endif
716 void SavePage(Browser* browser) {
717 content::RecordAction(UserMetricsAction("SavePage"));
718 WebContents* current_tab = browser->tab_strip_model()->GetActiveWebContents();
719 if (current_tab && current_tab->GetContentsMimeType() == "application/pdf")
720 content::RecordAction(UserMetricsAction("PDF.SavePage"));
721 current_tab->OnSavePage();
724 bool CanSavePage(const Browser* browser) {
725 // LocalState can be NULL in tests.
726 if (g_browser_process->local_state() &&
727 !g_browser_process->local_state()->GetBoolean(
728 prefs::kAllowFileSelectionDialogs)) {
729 return false;
731 return !browser->is_devtools() &&
732 !(GetContentRestrictions(browser) & CONTENT_RESTRICTION_SAVE);
735 void ShowFindBar(Browser* browser) {
736 browser->GetFindBarController()->Show();
739 void ShowWebsiteSettings(Browser* browser,
740 content::WebContents* web_contents,
741 const GURL& url,
742 const SSLStatus& ssl) {
743 browser->window()->ShowWebsiteSettings(
744 Profile::FromBrowserContext(web_contents->GetBrowserContext()),
745 web_contents, url, ssl);
749 void Print(Browser* browser) {
750 #if defined(ENABLE_PRINTING)
751 WebContents* contents = browser->tab_strip_model()->GetActiveWebContents();
752 #if defined(ENABLE_FULL_PRINTING)
753 printing::PrintViewManager* print_view_manager =
754 printing::PrintViewManager::FromWebContents(contents);
755 if (browser->profile()->GetPrefs()->GetBoolean(prefs::kPrintPreviewDisabled))
756 print_view_manager->PrintNow();
757 else
758 print_view_manager->PrintPreviewNow(false);
759 #else
760 printing::PrintViewManagerBasic* print_view_manager =
761 printing::PrintViewManagerBasic::FromWebContents(contents);
762 print_view_manager->PrintNow();
763 #endif // defined(ENABLE_FULL_PRINTING)
764 #endif // defined(ENABLE_PRINTING)
767 bool CanPrint(const Browser* browser) {
768 // Do not print when printing is disabled via pref or policy.
769 // Do not print when a constrained window is showing. It's confusing.
770 return browser->profile()->GetPrefs()->GetBoolean(prefs::kPrintingEnabled) &&
771 !(IsShowingWebContentsModalDialog(browser) ||
772 GetContentRestrictions(browser) & CONTENT_RESTRICTION_PRINT);
775 void AdvancedPrint(Browser* browser) {
776 #if defined(ENABLE_FULL_PRINTING)
777 printing::PrintViewManager* print_view_manager =
778 printing::PrintViewManager::FromWebContents(
779 browser->tab_strip_model()->GetActiveWebContents());
780 print_view_manager->AdvancedPrintNow();
781 #endif
784 bool CanAdvancedPrint(const Browser* browser) {
785 // If printing is not disabled via pref or policy, it is always possible to
786 // advanced print when the print preview is visible. The exception to this
787 // is under Win8 ash, since showing the advanced print dialog will open it
788 // modally on the Desktop and hang the browser. We can remove this check
789 // once we integrate with the system print charm.
790 #if defined(OS_WIN)
791 if (chrome::GetActiveDesktop() == chrome::HOST_DESKTOP_TYPE_ASH)
792 return false;
793 #endif
795 return browser->profile()->GetPrefs()->GetBoolean(prefs::kPrintingEnabled) &&
796 (PrintPreviewShowing(browser) || CanPrint(browser));
799 void PrintToDestination(Browser* browser) {
800 #if defined(ENABLE_FULL_PRINTING)
801 printing::PrintViewManager* print_view_manager =
802 printing::PrintViewManager::FromWebContents(
803 browser->tab_strip_model()->GetActiveWebContents());
804 print_view_manager->PrintToDestination();
805 #endif
808 void EmailPageLocation(Browser* browser) {
809 content::RecordAction(UserMetricsAction("EmailPageLocation"));
810 WebContents* wc = browser->tab_strip_model()->GetActiveWebContents();
811 DCHECK(wc);
813 std::string title = net::EscapeQueryParamValue(
814 base::UTF16ToUTF8(wc->GetTitle()), false);
815 std::string page_url = net::EscapeQueryParamValue(wc->GetURL().spec(), false);
816 std::string mailto = std::string("mailto:?subject=Fwd:%20") +
817 title + "&body=%0A%0A" + page_url;
818 platform_util::OpenExternal(browser->profile(), GURL(mailto));
821 bool CanEmailPageLocation(const Browser* browser) {
822 return browser->toolbar_model()->ShouldDisplayURL() &&
823 browser->tab_strip_model()->GetActiveWebContents()->GetURL().is_valid();
826 void Cut(Browser* browser) {
827 content::RecordAction(UserMetricsAction("Cut"));
828 browser->window()->Cut();
831 void Copy(Browser* browser) {
832 content::RecordAction(UserMetricsAction("Copy"));
833 browser->window()->Copy();
836 void Paste(Browser* browser) {
837 content::RecordAction(UserMetricsAction("Paste"));
838 browser->window()->Paste();
841 void Find(Browser* browser) {
842 content::RecordAction(UserMetricsAction("Find"));
843 FindInPage(browser, false, false);
846 void FindNext(Browser* browser) {
847 content::RecordAction(UserMetricsAction("FindNext"));
848 FindInPage(browser, true, true);
851 void FindPrevious(Browser* browser) {
852 content::RecordAction(UserMetricsAction("FindPrevious"));
853 FindInPage(browser, true, false);
856 void FindInPage(Browser* browser, bool find_next, bool forward_direction) {
857 ShowFindBar(browser);
858 if (find_next) {
859 base::string16 find_text;
860 FindTabHelper* find_helper = FindTabHelper::FromWebContents(
861 browser->tab_strip_model()->GetActiveWebContents());
862 #if defined(OS_MACOSX)
863 // We always want to search for the current contents of the find bar on
864 // OS X. For regular profile it's always the current find pboard. For
865 // Incognito window it's the newest value of the find pboard content and
866 // user-typed text.
867 FindBar* find_bar = browser->GetFindBarController()->find_bar();
868 find_text = find_bar->GetFindText();
869 #endif
870 find_helper->StartFinding(find_text, forward_direction, false);
874 void Zoom(Browser* browser, content::PageZoom zoom) {
875 if (browser->is_devtools())
876 return;
878 chrome_page_zoom::Zoom(browser->tab_strip_model()->GetActiveWebContents(),
879 zoom);
882 void FocusToolbar(Browser* browser) {
883 content::RecordAction(UserMetricsAction("FocusToolbar"));
884 browser->window()->FocusToolbar();
887 void FocusLocationBar(Browser* browser) {
888 content::RecordAction(UserMetricsAction("FocusLocation"));
889 browser->window()->SetFocusToLocationBar(true);
892 void FocusSearch(Browser* browser) {
893 // TODO(beng): replace this with FocusLocationBar
894 content::RecordAction(UserMetricsAction("FocusSearch"));
895 browser->window()->GetLocationBar()->FocusSearch();
898 void FocusAppMenu(Browser* browser) {
899 content::RecordAction(UserMetricsAction("FocusAppMenu"));
900 browser->window()->FocusAppMenu();
903 void FocusBookmarksToolbar(Browser* browser) {
904 content::RecordAction(UserMetricsAction("FocusBookmarksToolbar"));
905 browser->window()->FocusBookmarksToolbar();
908 void FocusInfobars(Browser* browser) {
909 content::RecordAction(UserMetricsAction("FocusInfobars"));
910 browser->window()->FocusInfobars();
913 void FocusNextPane(Browser* browser) {
914 content::RecordAction(UserMetricsAction("FocusNextPane"));
915 browser->window()->RotatePaneFocus(true);
918 void FocusPreviousPane(Browser* browser) {
919 content::RecordAction(UserMetricsAction("FocusPreviousPane"));
920 browser->window()->RotatePaneFocus(false);
923 void ToggleDevToolsWindow(Browser* browser, DevToolsToggleAction action) {
924 if (action.type() == DevToolsToggleAction::kShowConsole)
925 content::RecordAction(UserMetricsAction("DevTools_ToggleConsole"));
926 else
927 content::RecordAction(UserMetricsAction("DevTools_ToggleWindow"));
928 DevToolsWindow::ToggleDevToolsWindow(browser, action);
931 bool CanOpenTaskManager() {
932 #if defined(OS_WIN)
933 // In metro we can't display the task manager, as it is a native window.
934 return !win8::IsSingleWindowMetroMode();
935 #else
936 return true;
937 #endif
940 void OpenTaskManager(Browser* browser) {
941 content::RecordAction(UserMetricsAction("TaskManager"));
942 chrome::ShowTaskManager(browser);
945 void OpenFeedbackDialog(Browser* browser) {
946 content::RecordAction(UserMetricsAction("Feedback"));
947 chrome::ShowFeedbackPage(browser, std::string(), std::string());
950 void ToggleBookmarkBar(Browser* browser) {
951 content::RecordAction(UserMetricsAction("ShowBookmarksBar"));
952 ToggleBookmarkBarWhenVisible(browser->profile());
955 void ShowAppMenu(Browser* browser) {
956 // We record the user metric for this event in WrenchMenu::RunMenu.
957 browser->window()->ShowAppMenu();
960 void ShowAvatarMenu(Browser* browser) {
961 browser->window()->ShowAvatarBubbleFromAvatarButton();
964 void OpenUpdateChromeDialog(Browser* browser) {
965 if (UpgradeDetector::GetInstance()->is_outdated_install()) {
966 content::NotificationService::current()->Notify(
967 chrome::NOTIFICATION_OUTDATED_INSTALL,
968 content::NotificationService::AllSources(),
969 content::NotificationService::NoDetails());
970 } else {
971 content::RecordAction(UserMetricsAction("UpdateChrome"));
972 browser->window()->ShowUpdateChromeDialog();
976 void ToggleSpeechInput(Browser* browser) {
977 WebContents* web_contents =
978 browser->tab_strip_model()->GetActiveWebContents();
979 web_contents->GetRenderViewHost()->ToggleSpeechInput();
981 SearchTabHelper* search_tab_helper =
982 SearchTabHelper::FromWebContents(web_contents);
983 // |search_tab_helper| can be null in unit tests.
984 if (search_tab_helper)
985 search_tab_helper->ToggleVoiceSearch();
988 bool CanRequestTabletSite(WebContents* current_tab) {
989 if (!current_tab)
990 return false;
991 return current_tab->GetController().GetActiveEntry() != NULL;
994 bool IsRequestingTabletSite(Browser* browser) {
995 WebContents* current_tab = browser->tab_strip_model()->GetActiveWebContents();
996 if (!current_tab)
997 return false;
998 content::NavigationEntry* entry =
999 current_tab->GetController().GetActiveEntry();
1000 if (!entry)
1001 return false;
1002 return entry->GetIsOverridingUserAgent();
1005 void ToggleRequestTabletSite(Browser* browser) {
1006 WebContents* current_tab = browser->tab_strip_model()->GetActiveWebContents();
1007 if (!current_tab)
1008 return;
1009 NavigationController& controller = current_tab->GetController();
1010 NavigationEntry* entry = controller.GetActiveEntry();
1011 if (!entry)
1012 return;
1013 if (entry->GetIsOverridingUserAgent()) {
1014 entry->SetIsOverridingUserAgent(false);
1015 } else {
1016 entry->SetIsOverridingUserAgent(true);
1017 chrome::VersionInfo version_info;
1018 std::string product;
1019 if (version_info.is_valid())
1020 product = version_info.ProductNameAndVersionForUserAgent();
1021 current_tab->SetUserAgentOverride(
1022 webkit_glue::BuildUserAgentFromOSAndProduct(
1023 kOsOverrideForTabletSite, product));
1025 controller.ReloadOriginalRequestURL(true);
1028 void ToggleFullscreenMode(Browser* browser) {
1029 browser->fullscreen_controller()->ToggleFullscreenMode();
1032 void ClearCache(Browser* browser) {
1033 BrowsingDataRemover* remover =
1034 BrowsingDataRemover::CreateForUnboundedRange(browser->profile());
1035 remover->Remove(BrowsingDataRemover::REMOVE_CACHE,
1036 BrowsingDataHelper::UNPROTECTED_WEB);
1037 // BrowsingDataRemover takes care of deleting itself when done.
1040 bool IsDebuggerAttachedToCurrentTab(Browser* browser) {
1041 WebContents* contents = browser->tab_strip_model()->GetActiveWebContents();
1042 return contents ?
1043 content::DevToolsAgentHost::IsDebuggerAttached(contents) : false;
1046 void ViewSource(Browser* browser, WebContents* contents) {
1047 DCHECK(contents);
1049 // Use the last committed entry, since the pending entry hasn't loaded yet and
1050 // won't be copied into the cloned tab.
1051 NavigationEntry* entry = contents->GetController().GetLastCommittedEntry();
1052 if (!entry)
1053 return;
1055 ViewSource(browser, contents, entry->GetURL(), entry->GetPageState());
1058 void ViewSource(Browser* browser,
1059 WebContents* contents,
1060 const GURL& url,
1061 const content::PageState& page_state) {
1062 content::RecordAction(UserMetricsAction("ViewSource"));
1063 DCHECK(contents);
1065 // Note that Clone does not copy the pending or transient entries, so the
1066 // active entry in view_source_contents will be the last committed entry.
1067 WebContents* view_source_contents = contents->Clone();
1068 DCHECK(view_source_contents->GetController().CanPruneAllButLastCommitted());
1069 view_source_contents->GetController().PruneAllButLastCommitted();
1070 NavigationEntry* active_entry =
1071 view_source_contents->GetController().GetActiveEntry();
1072 if (!active_entry)
1073 return;
1075 GURL view_source_url =
1076 GURL(content::kViewSourceScheme + std::string(":") + url.spec());
1077 active_entry->SetVirtualURL(view_source_url);
1079 // Do not restore scroller position.
1080 active_entry->SetPageState(page_state.RemoveScrollOffset());
1082 // Do not restore title, derive it from the url.
1083 active_entry->SetTitle(base::string16());
1085 // Now show view-source entry.
1086 if (browser->CanSupportWindowFeature(Browser::FEATURE_TABSTRIP)) {
1087 // If this is a tabbed browser, just create a duplicate tab inside the same
1088 // window next to the tab being duplicated.
1089 int index = browser->tab_strip_model()->GetIndexOfWebContents(contents);
1090 int add_types = TabStripModel::ADD_ACTIVE |
1091 TabStripModel::ADD_INHERIT_GROUP;
1092 browser->tab_strip_model()->InsertWebContentsAt(
1093 index + 1,
1094 view_source_contents,
1095 add_types);
1096 } else {
1097 Browser* b = new Browser(
1098 Browser::CreateParams(Browser::TYPE_TABBED, browser->profile(),
1099 browser->host_desktop_type()));
1101 // Preserve the size of the original window. The new window has already
1102 // been given an offset by the OS, so we shouldn't copy the old bounds.
1103 BrowserWindow* new_window = b->window();
1104 new_window->SetBounds(gfx::Rect(new_window->GetRestoredBounds().origin(),
1105 browser->window()->GetRestoredBounds().size()));
1107 // We need to show the browser now. Otherwise ContainerWin assumes the
1108 // WebContents is invisible and won't size it.
1109 b->window()->Show();
1111 // The page transition below is only for the purpose of inserting the tab.
1112 b->tab_strip_model()->AddWebContents(view_source_contents, -1,
1113 content::PAGE_TRANSITION_LINK,
1114 TabStripModel::ADD_ACTIVE);
1117 SessionService* session_service =
1118 SessionServiceFactory::GetForProfileIfExisting(browser->profile());
1119 if (session_service)
1120 session_service->TabRestored(view_source_contents, false);
1123 void ViewSelectedSource(Browser* browser) {
1124 ViewSource(browser, browser->tab_strip_model()->GetActiveWebContents());
1127 bool CanViewSource(const Browser* browser) {
1128 return !browser->is_devtools() &&
1129 browser->tab_strip_model()->GetActiveWebContents()->GetController().
1130 CanViewSource();
1133 void CreateApplicationShortcuts(Browser* browser) {
1134 content::RecordAction(UserMetricsAction("CreateShortcut"));
1135 extensions::TabHelper::FromWebContents(
1136 browser->tab_strip_model()->GetActiveWebContents())->
1137 CreateApplicationShortcuts();
1140 void CreateHostedAppFromCurrentWebContents(Browser* browser) {
1141 content::RecordAction(UserMetricsAction("CreateHostedApp"));
1142 extensions::TabHelper::FromWebContents(
1143 browser->tab_strip_model()->GetActiveWebContents())->
1144 CreateHostedAppFromWebContents();
1147 bool CanCreateApplicationShortcuts(const Browser* browser) {
1148 return extensions::TabHelper::FromWebContents(
1149 browser->tab_strip_model()->GetActiveWebContents())->
1150 CanCreateApplicationShortcuts();
1153 void ConvertTabToAppWindow(Browser* browser,
1154 content::WebContents* contents) {
1155 const GURL& url = contents->GetController().GetActiveEntry()->GetURL();
1156 std::string app_name = web_app::GenerateApplicationNameFromURL(url);
1158 int index = browser->tab_strip_model()->GetIndexOfWebContents(contents);
1159 if (index >= 0)
1160 browser->tab_strip_model()->DetachWebContentsAt(index);
1162 Browser* app_browser = new Browser(
1163 Browser::CreateParams::CreateForApp(
1164 Browser::TYPE_POPUP, app_name, gfx::Rect(), browser->profile(),
1165 browser->host_desktop_type()));
1166 app_browser->tab_strip_model()->AppendWebContents(contents, true);
1168 contents->GetMutableRendererPrefs()->can_accept_load_drops = false;
1169 contents->GetRenderViewHost()->SyncRendererPrefs();
1170 app_browser->window()->Show();
1173 } // namespace chrome