Home | History | Annotate | Download | only in ui
      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.
      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/prefs/pref_service.h"
     10 #include "base/strings/utf_string_conversions.h"
     11 #include "chrome/app/chrome_command_ids.h"
     12 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
     13 #include "chrome/browser/browser_process.h"
     14 #include "chrome/browser/browsing_data/browsing_data_helper.h"
     15 #include "chrome/browser/browsing_data/browsing_data_remover.h"
     16 #include "chrome/browser/chrome_notification_types.h"
     17 #include "chrome/browser/chrome_page_zoom.h"
     18 #include "chrome/browser/devtools/devtools_window.h"
     19 #include "chrome/browser/dom_distiller/tab_utils.h"
     20 #include "chrome/browser/extensions/api/commands/command_service.h"
     21 #include "chrome/browser/extensions/tab_helper.h"
     22 #include "chrome/browser/favicon/favicon_tab_helper.h"
     23 #include "chrome/browser/lifetime/application_lifetime.h"
     24 #include "chrome/browser/platform_util.h"
     25 #include "chrome/browser/prefs/incognito_mode_prefs.h"
     26 #include "chrome/browser/profiles/profile.h"
     27 #include "chrome/browser/rlz/rlz.h"
     28 #include "chrome/browser/search/search.h"
     29 #include "chrome/browser/sessions/session_service_factory.h"
     30 #include "chrome/browser/sessions/tab_restore_service.h"
     31 #include "chrome/browser/sessions/tab_restore_service_delegate.h"
     32 #include "chrome/browser/sessions/tab_restore_service_factory.h"
     33 #include "chrome/browser/signin/signin_header_helper.h"
     34 #include "chrome/browser/translate/chrome_translate_client.h"
     35 #include "chrome/browser/ui/accelerator_utils.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/bookmarks/browser/bookmark_model.h"
     64 #include "components/bookmarks/browser/bookmark_utils.h"
     65 #include "components/google/core/browser/google_util.h"
     66 #include "components/translate/core/browser/language_state.h"
     67 #include "components/web_modal/web_contents_modal_dialog_manager.h"
     68 #include "content/public/browser/devtools_agent_host.h"
     69 #include "content/public/browser/navigation_controller.h"
     70 #include "content/public/browser/navigation_entry.h"
     71 #include "content/public/browser/notification_service.h"
     72 #include "content/public/browser/page_navigator.h"
     73 #include "content/public/browser/render_view_host.h"
     74 #include "content/public/browser/render_widget_host_view.h"
     75 #include "content/public/browser/user_metrics.h"
     76 #include "content/public/browser/web_contents.h"
     77 #include "content/public/common/renderer_preferences.h"
     78 #include "content/public/common/url_constants.h"
     79 #include "content/public/common/url_utils.h"
     80 #include "content/public/common/user_agent.h"
     81 #include "extensions/browser/extension_registry.h"
     82 #include "extensions/common/extension.h"
     83 #include "extensions/common/extension_set.h"
     84 #include "net/base/escape.h"
     85 #include "ui/events/keycodes/keyboard_codes.h"
     86 
     87 #if defined(OS_WIN)
     88 #include "chrome/browser/ui/metro_pin_tab_helper_win.h"
     89 #endif
     90 
     91 #if defined(ENABLE_PRINTING)
     92 #if defined(ENABLE_FULL_PRINTING)
     93 #include "chrome/browser/printing/print_preview_dialog_controller.h"
     94 #include "chrome/browser/printing/print_view_manager.h"
     95 #else
     96 #include "chrome/browser/printing/print_view_manager_basic.h"
     97 #endif  // defined(ENABLE_FULL_PRINTING)
     98 #endif  // defined(ENABLE_PRINTING)
     99 
    100 namespace {
    101 const char kOsOverrideForTabletSite[] = "Linux; Android 4.0.3";
    102 }
    103 
    104 using base::UserMetricsAction;
    105 using content::NavigationController;
    106 using content::NavigationEntry;
    107 using content::OpenURLParams;
    108 using content::Referrer;
    109 using content::SSLStatus;
    110 using content::WebContents;
    111 using web_modal::WebContentsModalDialogManager;
    112 
    113 namespace chrome {
    114 namespace {
    115 
    116 bool CanBookmarkCurrentPageInternal(const Browser* browser,
    117                                     bool check_remove_bookmark_ui) {
    118   BookmarkModel* model =
    119       BookmarkModelFactory::GetForProfile(browser->profile());
    120   return browser_defaults::bookmarks_enabled &&
    121       browser->profile()->GetPrefs()->GetBoolean(
    122           prefs::kEditBookmarksEnabled) &&
    123       model && model->loaded() && browser->is_type_tabbed() &&
    124       (!check_remove_bookmark_ui ||
    125            !chrome::ShouldRemoveBookmarkThisPageUI(browser->profile()));
    126 }
    127 
    128 bool GetBookmarkOverrideCommand(
    129     Profile* profile,
    130     const extensions::Extension** extension,
    131     extensions::Command* command,
    132     extensions::CommandService::ExtensionCommandType* command_type) {
    133   DCHECK(extension);
    134   DCHECK(command);
    135   DCHECK(command_type);
    136 
    137   ui::Accelerator bookmark_page_accelerator =
    138       chrome::GetPrimaryChromeAcceleratorForCommandId(IDC_BOOKMARK_PAGE);
    139   if (bookmark_page_accelerator.key_code() == ui::VKEY_UNKNOWN)
    140     return false;
    141 
    142   extensions::CommandService* command_service =
    143       extensions::CommandService::Get(profile);
    144   const extensions::ExtensionSet& extension_set =
    145       extensions::ExtensionRegistry::Get(profile)->enabled_extensions();
    146   for (extensions::ExtensionSet::const_iterator i = extension_set.begin();
    147        i != extension_set.end();
    148        ++i) {
    149     extensions::Command prospective_command;
    150     extensions::CommandService::ExtensionCommandType prospective_command_type;
    151     if (command_service->GetBoundExtensionCommand((*i)->id(),
    152                                                   bookmark_page_accelerator,
    153                                                   &prospective_command,
    154                                                   &prospective_command_type)) {
    155       *extension = i->get();
    156       *command = prospective_command;
    157       *command_type = prospective_command_type;
    158       return true;
    159     }
    160   }
    161 
    162   return false;
    163 }
    164 
    165 void BookmarkCurrentPageInternal(Browser* browser) {
    166   content::RecordAction(UserMetricsAction("Star"));
    167 
    168   BookmarkModel* model =
    169       BookmarkModelFactory::GetForProfile(browser->profile());
    170   if (!model || !model->loaded())
    171     return;  // Ignore requests until bookmarks are loaded.
    172 
    173   GURL url;
    174   base::string16 title;
    175   WebContents* web_contents =
    176       browser->tab_strip_model()->GetActiveWebContents();
    177   GetURLAndTitleToBookmark(web_contents, &url, &title);
    178   bool is_bookmarked_by_any = model->IsBookmarked(url);
    179   if (!is_bookmarked_by_any &&
    180       web_contents->GetBrowserContext()->IsOffTheRecord()) {
    181     // If we're incognito the favicon may not have been saved. Save it now
    182     // so that bookmarks have an icon for the page.
    183     FaviconTabHelper::FromWebContents(web_contents)->SaveFavicon();
    184   }
    185   bool was_bookmarked_by_user = bookmark_utils::IsBookmarkedByUser(model, url);
    186   bookmark_utils::AddIfNotBookmarked(model, url, title);
    187   bool is_bookmarked_by_user = bookmark_utils::IsBookmarkedByUser(model, url);
    188   // Make sure the model actually added a bookmark before showing the star. A
    189   // bookmark isn't created if the url is invalid.
    190   if (browser->window()->IsActive() && is_bookmarked_by_user) {
    191     // Only show the bubble if the window is active, otherwise we may get into
    192     // weird situations where the bubble is deleted as soon as it is shown.
    193     browser->window()->ShowBookmarkBubble(url, was_bookmarked_by_user);
    194   }
    195 }
    196 
    197 // Based on |disposition|, creates a new tab as necessary, and returns the
    198 // appropriate tab to navigate.  If that tab is the current tab, reverts the
    199 // location bar contents, since all browser-UI-triggered navigations should
    200 // revert any omnibox edits in the current tab.
    201 WebContents* GetTabAndRevertIfNecessary(Browser* browser,
    202                                         WindowOpenDisposition disposition) {
    203   WebContents* current_tab = browser->tab_strip_model()->GetActiveWebContents();
    204   switch (disposition) {
    205     case NEW_FOREGROUND_TAB:
    206     case NEW_BACKGROUND_TAB: {
    207       WebContents* new_tab = current_tab->Clone();
    208       browser->tab_strip_model()->AddWebContents(
    209           new_tab, -1, content::PAGE_TRANSITION_LINK,
    210           (disposition == NEW_FOREGROUND_TAB) ?
    211               TabStripModel::ADD_ACTIVE : TabStripModel::ADD_NONE);
    212       return new_tab;
    213     }
    214     case NEW_WINDOW: {
    215       WebContents* new_tab = current_tab->Clone();
    216       Browser* new_browser = new Browser(Browser::CreateParams(
    217           browser->profile(), browser->host_desktop_type()));
    218       new_browser->tab_strip_model()->AddWebContents(
    219           new_tab, -1, content::PAGE_TRANSITION_LINK,
    220           TabStripModel::ADD_ACTIVE);
    221       new_browser->window()->Show();
    222       return new_tab;
    223     }
    224     default:
    225       browser->window()->GetLocationBar()->Revert();
    226       return current_tab;
    227   }
    228 }
    229 
    230 void ReloadInternal(Browser* browser,
    231                     WindowOpenDisposition disposition,
    232                     bool ignore_cache) {
    233   // As this is caused by a user action, give the focus to the page.
    234   //
    235   // Also notify RenderViewHostDelegate of the user gesture; this is
    236   // normally done in Browser::Navigate, but a reload bypasses Navigate.
    237   WebContents* new_tab = GetTabAndRevertIfNecessary(browser, disposition);
    238   new_tab->UserGestureDone();
    239   if (!new_tab->FocusLocationBarByDefault())
    240     new_tab->Focus();
    241   if (ignore_cache)
    242     new_tab->GetController().ReloadIgnoringCache(true);
    243   else
    244     new_tab->GetController().Reload(true);
    245 }
    246 
    247 bool IsShowingWebContentsModalDialog(const Browser* browser) {
    248   WebContents* web_contents =
    249       browser->tab_strip_model()->GetActiveWebContents();
    250   if (!web_contents)
    251     return false;
    252 
    253   WebContentsModalDialogManager* web_contents_modal_dialog_manager =
    254       WebContentsModalDialogManager::FromWebContents(web_contents);
    255   return web_contents_modal_dialog_manager->IsDialogActive();
    256 }
    257 
    258 bool PrintPreviewShowing(const Browser* browser) {
    259 #if defined(ENABLE_FULL_PRINTING)
    260   WebContents* contents = browser->tab_strip_model()->GetActiveWebContents();
    261   printing::PrintPreviewDialogController* controller =
    262       printing::PrintPreviewDialogController::GetInstance();
    263   return controller && (controller->GetPrintPreviewForContents(contents) ||
    264                         controller->is_creating_print_preview_dialog());
    265 #else
    266   return false;
    267 #endif
    268 }
    269 
    270 }  // namespace
    271 
    272 bool IsCommandEnabled(Browser* browser, int command) {
    273   return browser->command_controller()->command_updater()->IsCommandEnabled(
    274       command);
    275 }
    276 
    277 bool SupportsCommand(Browser* browser, int command) {
    278   return browser->command_controller()->command_updater()->SupportsCommand(
    279       command);
    280 }
    281 
    282 bool ExecuteCommand(Browser* browser, int command) {
    283   return browser->command_controller()->command_updater()->ExecuteCommand(
    284       command);
    285 }
    286 
    287 bool ExecuteCommandWithDisposition(Browser* browser,
    288                                    int command,
    289                                    WindowOpenDisposition disposition) {
    290   return browser->command_controller()->command_updater()->
    291       ExecuteCommandWithDisposition(command, disposition);
    292 }
    293 
    294 void UpdateCommandEnabled(Browser* browser, int command, bool enabled) {
    295   browser->command_controller()->command_updater()->UpdateCommandEnabled(
    296       command, enabled);
    297 }
    298 
    299 void AddCommandObserver(Browser* browser,
    300                         int command,
    301                         CommandObserver* observer) {
    302   browser->command_controller()->command_updater()->AddCommandObserver(
    303       command, observer);
    304 }
    305 
    306 void RemoveCommandObserver(Browser* browser,
    307                            int command,
    308                            CommandObserver* observer) {
    309   browser->command_controller()->command_updater()->RemoveCommandObserver(
    310       command, observer);
    311 }
    312 
    313 int GetContentRestrictions(const Browser* browser) {
    314   int content_restrictions = 0;
    315   WebContents* current_tab = browser->tab_strip_model()->GetActiveWebContents();
    316   if (current_tab) {
    317     CoreTabHelper* core_tab_helper =
    318         CoreTabHelper::FromWebContents(current_tab);
    319     content_restrictions = core_tab_helper->content_restrictions();
    320     NavigationEntry* last_committed_entry =
    321         current_tab->GetController().GetLastCommittedEntry();
    322     if (!content::IsSavableURL(
    323             last_committed_entry ? last_committed_entry->GetURL() : GURL()) ||
    324         current_tab->ShowingInterstitialPage())
    325       content_restrictions |= CONTENT_RESTRICTION_SAVE;
    326     if (current_tab->ShowingInterstitialPage())
    327       content_restrictions |= CONTENT_RESTRICTION_PRINT;
    328   }
    329   return content_restrictions;
    330 }
    331 
    332 void NewEmptyWindow(Profile* profile, HostDesktopType desktop_type) {
    333   bool incognito = profile->IsOffTheRecord();
    334   PrefService* prefs = profile->GetPrefs();
    335   if (incognito) {
    336     if (IncognitoModePrefs::GetAvailability(prefs) ==
    337           IncognitoModePrefs::DISABLED) {
    338       incognito = false;
    339     }
    340   } else if (profile->IsGuestSession() ||
    341       (browser_defaults::kAlwaysOpenIncognitoWindow &&
    342       IncognitoModePrefs::ShouldLaunchIncognito(
    343           *CommandLine::ForCurrentProcess(), prefs))) {
    344     incognito = true;
    345   }
    346 
    347   if (incognito) {
    348     content::RecordAction(UserMetricsAction("NewIncognitoWindow"));
    349     OpenEmptyWindow(profile->GetOffTheRecordProfile(), desktop_type);
    350   } else {
    351     content::RecordAction(UserMetricsAction("NewWindow"));
    352     SessionService* session_service =
    353         SessionServiceFactory::GetForProfileForSessionRestore(
    354             profile->GetOriginalProfile());
    355     if (!session_service ||
    356         !session_service->RestoreIfNecessary(std::vector<GURL>())) {
    357       OpenEmptyWindow(profile->GetOriginalProfile(), desktop_type);
    358     }
    359   }
    360 }
    361 
    362 Browser* OpenEmptyWindow(Profile* profile, HostDesktopType desktop_type) {
    363   Browser* browser = new Browser(
    364       Browser::CreateParams(Browser::TYPE_TABBED, profile, desktop_type));
    365   AddTabAt(browser, GURL(), -1, true);
    366   browser->window()->Show();
    367   return browser;
    368 }
    369 
    370 void OpenWindowWithRestoredTabs(Profile* profile,
    371                                 HostDesktopType host_desktop_type) {
    372   TabRestoreService* service = TabRestoreServiceFactory::GetForProfile(profile);
    373   if (service)
    374     service->RestoreMostRecentEntry(NULL, host_desktop_type);
    375 }
    376 
    377 void OpenURLOffTheRecord(Profile* profile,
    378                          const GURL& url,
    379                          chrome::HostDesktopType desktop_type) {
    380   ScopedTabbedBrowserDisplayer displayer(profile->GetOffTheRecordProfile(),
    381                                          desktop_type);
    382   AddSelectedTabWithURL(displayer.browser(), url,
    383       content::PAGE_TRANSITION_LINK);
    384 }
    385 
    386 bool CanGoBack(const Browser* browser) {
    387   return browser->tab_strip_model()->GetActiveWebContents()->
    388       GetController().CanGoBack();
    389 }
    390 
    391 void GoBack(Browser* browser, WindowOpenDisposition disposition) {
    392   content::RecordAction(UserMetricsAction("Back"));
    393 
    394   if (CanGoBack(browser)) {
    395     WebContents* current_tab =
    396         browser->tab_strip_model()->GetActiveWebContents();
    397     WebContents* new_tab = GetTabAndRevertIfNecessary(browser, disposition);
    398     // If we are on an interstitial page and clone the tab, it won't be copied
    399     // to the new tab, so we don't need to go back.
    400     if ((new_tab == current_tab) || !current_tab->ShowingInterstitialPage())
    401       new_tab->GetController().GoBack();
    402   }
    403 }
    404 
    405 bool CanGoForward(const Browser* browser) {
    406   return browser->tab_strip_model()->GetActiveWebContents()->
    407       GetController().CanGoForward();
    408 }
    409 
    410 void GoForward(Browser* browser, WindowOpenDisposition disposition) {
    411   content::RecordAction(UserMetricsAction("Forward"));
    412   if (CanGoForward(browser)) {
    413     GetTabAndRevertIfNecessary(browser, disposition)->
    414         GetController().GoForward();
    415   }
    416 }
    417 
    418 bool NavigateToIndexWithDisposition(Browser* browser,
    419                                     int index,
    420                                     WindowOpenDisposition disposition) {
    421   NavigationController* controller =
    422       &GetTabAndRevertIfNecessary(browser, disposition)->GetController();
    423   if (index < 0 || index >= controller->GetEntryCount())
    424     return false;
    425   controller->GoToIndex(index);
    426   return true;
    427 }
    428 
    429 void Reload(Browser* browser, WindowOpenDisposition disposition) {
    430   content::RecordAction(UserMetricsAction("Reload"));
    431   ReloadInternal(browser, disposition, false);
    432 }
    433 
    434 void ReloadIgnoringCache(Browser* browser, WindowOpenDisposition disposition) {
    435   content::RecordAction(UserMetricsAction("ReloadIgnoringCache"));
    436   ReloadInternal(browser, disposition, true);
    437 }
    438 
    439 bool CanReload(const Browser* browser) {
    440   return !browser->is_devtools();
    441 }
    442 
    443 void Home(Browser* browser, WindowOpenDisposition disposition) {
    444   content::RecordAction(UserMetricsAction("Home"));
    445 
    446   std::string extra_headers;
    447 #if defined(ENABLE_RLZ) && !defined(OS_IOS)
    448   // If the home page is a Google home page, add the RLZ header to the request.
    449   PrefService* pref_service = browser->profile()->GetPrefs();
    450   if (pref_service) {
    451     if (google_util::IsGoogleHomePageUrl(
    452         GURL(pref_service->GetString(prefs::kHomePage)))) {
    453       extra_headers = RLZTracker::GetAccessPointHttpHeader(
    454           RLZTracker::ChromeHomePage());
    455     }
    456   }
    457 #endif  // defined(ENABLE_RLZ) && !defined(OS_IOS)
    458 
    459   GURL url = browser->profile()->GetHomePage();
    460 
    461   // Streamlined hosted apps should return to their launch page when the home
    462   // button is pressed.
    463   if (browser->is_app()) {
    464     const extensions::Extension* extension =
    465         extensions::ExtensionRegistry::Get(browser->profile())
    466             ->GetExtensionById(
    467                 web_app::GetExtensionIdFromApplicationName(browser->app_name()),
    468                 extensions::ExtensionRegistry::EVERYTHING);
    469     if (!extension)
    470       return;
    471 
    472     url = extensions::AppLaunchInfo::GetLaunchWebURL(extension);
    473   }
    474 
    475   OpenURLParams params(
    476       url, Referrer(), disposition,
    477       content::PageTransitionFromInt(
    478           content::PAGE_TRANSITION_AUTO_BOOKMARK |
    479           content::PAGE_TRANSITION_HOME_PAGE),
    480       false);
    481   params.extra_headers = extra_headers;
    482   browser->OpenURL(params);
    483 }
    484 
    485 void OpenCurrentURL(Browser* browser) {
    486   content::RecordAction(UserMetricsAction("LoadURL"));
    487   LocationBar* location_bar = browser->window()->GetLocationBar();
    488   if (!location_bar)
    489     return;
    490 
    491   GURL url(location_bar->GetDestinationURL());
    492 
    493   content::PageTransition page_transition = location_bar->GetPageTransition();
    494   content::PageTransition page_transition_without_qualifier(
    495       PageTransitionStripQualifier(page_transition));
    496   WindowOpenDisposition open_disposition =
    497       location_bar->GetWindowOpenDisposition();
    498   // A PAGE_TRANSITION_TYPED means the user has typed a URL. We do not want to
    499   // open URLs with instant_controller since in some cases it disregards it
    500   // and performs a search instead. For example, when using CTRL-Enter, the
    501   // location_bar is aware of the URL but instant is not.
    502   // Instant should also not handle PAGE_TRANSITION_RELOAD because its knowledge
    503   // of the omnibox text may be stale if the user focuses in the omnibox and
    504   // presses enter without typing anything.
    505   if (page_transition_without_qualifier != content::PAGE_TRANSITION_TYPED &&
    506       page_transition_without_qualifier != content::PAGE_TRANSITION_RELOAD &&
    507       browser->instant_controller() &&
    508       browser->instant_controller()->OpenInstant(open_disposition, url))
    509     return;
    510 
    511   NavigateParams params(browser, url, page_transition);
    512   params.disposition = open_disposition;
    513   // Use ADD_INHERIT_OPENER so that all pages opened by the omnibox at least
    514   // inherit the opener. In some cases the tabstrip will determine the group
    515   // should be inherited, in which case the group is inherited instead of the
    516   // opener.
    517   params.tabstrip_add_types =
    518       TabStripModel::ADD_FORCE_INDEX | TabStripModel::ADD_INHERIT_OPENER;
    519   Navigate(&params);
    520 
    521   DCHECK(browser->profile()->GetExtensionService());
    522   const extensions::Extension* extension =
    523       extensions::ExtensionRegistry::Get(browser->profile())
    524           ->enabled_extensions().GetAppByURL(url);
    525   if (extension) {
    526     CoreAppLauncherHandler::RecordAppLaunchType(
    527         extension_misc::APP_LAUNCH_OMNIBOX_LOCATION,
    528         extension->GetType());
    529   }
    530 }
    531 
    532 void Stop(Browser* browser) {
    533   content::RecordAction(UserMetricsAction("Stop"));
    534   browser->tab_strip_model()->GetActiveWebContents()->Stop();
    535 }
    536 
    537 void NewWindow(Browser* browser) {
    538   NewEmptyWindow(browser->profile()->GetOriginalProfile(),
    539                  browser->host_desktop_type());
    540 }
    541 
    542 void NewIncognitoWindow(Browser* browser) {
    543   NewEmptyWindow(browser->profile()->GetOffTheRecordProfile(),
    544                  browser->host_desktop_type());
    545 }
    546 
    547 void CloseWindow(Browser* browser) {
    548   content::RecordAction(UserMetricsAction("CloseWindow"));
    549   browser->window()->Close();
    550 }
    551 
    552 void NewTab(Browser* browser) {
    553   content::RecordAction(UserMetricsAction("NewTab"));
    554   // TODO(asvitkine): This is invoked programmatically from several places.
    555   // Audit the code and change it so that the histogram only gets collected for
    556   // user-initiated commands.
    557   UMA_HISTOGRAM_ENUMERATION("Tab.NewTab", TabStripModel::NEW_TAB_COMMAND,
    558                             TabStripModel::NEW_TAB_ENUM_COUNT);
    559 
    560   if (browser->is_type_tabbed()) {
    561     AddTabAt(browser, GURL(), -1, true);
    562     browser->tab_strip_model()->GetActiveWebContents()->RestoreFocus();
    563   } else {
    564     ScopedTabbedBrowserDisplayer displayer(browser->profile(),
    565                                            browser->host_desktop_type());
    566     Browser* b = displayer.browser();
    567     AddTabAt(b, GURL(), -1, true);
    568     b->window()->Show();
    569     // The call to AddBlankTabAt above did not set the focus to the tab as its
    570     // window was not active, so we have to do it explicitly.
    571     // See http://crbug.com/6380.
    572     b->tab_strip_model()->GetActiveWebContents()->RestoreFocus();
    573   }
    574 }
    575 
    576 void CloseTab(Browser* browser) {
    577   content::RecordAction(UserMetricsAction("CloseTab_Accelerator"));
    578   browser->tab_strip_model()->CloseSelectedTabs();
    579 }
    580 
    581 void RestoreTab(Browser* browser) {
    582   content::RecordAction(UserMetricsAction("RestoreTab"));
    583   TabRestoreService* service =
    584       TabRestoreServiceFactory::GetForProfile(browser->profile());
    585   if (service)
    586     service->RestoreMostRecentEntry(browser->tab_restore_service_delegate(),
    587                                     browser->host_desktop_type());
    588 }
    589 
    590 TabStripModelDelegate::RestoreTabType GetRestoreTabType(
    591     const Browser* browser) {
    592   TabRestoreService* service =
    593       TabRestoreServiceFactory::GetForProfile(browser->profile());
    594   if (!service || service->entries().empty())
    595     return TabStripModelDelegate::RESTORE_NONE;
    596   if (service->entries().front()->type == TabRestoreService::WINDOW)
    597     return TabStripModelDelegate::RESTORE_WINDOW;
    598   return TabStripModelDelegate::RESTORE_TAB;
    599 }
    600 
    601 void SelectNextTab(Browser* browser) {
    602   content::RecordAction(UserMetricsAction("SelectNextTab"));
    603   browser->tab_strip_model()->SelectNextTab();
    604 }
    605 
    606 void SelectPreviousTab(Browser* browser) {
    607   content::RecordAction(UserMetricsAction("SelectPrevTab"));
    608   browser->tab_strip_model()->SelectPreviousTab();
    609 }
    610 
    611 void MoveTabNext(Browser* browser) {
    612   content::RecordAction(UserMetricsAction("MoveTabNext"));
    613   browser->tab_strip_model()->MoveTabNext();
    614 }
    615 
    616 void MoveTabPrevious(Browser* browser) {
    617   content::RecordAction(UserMetricsAction("MoveTabPrevious"));
    618   browser->tab_strip_model()->MoveTabPrevious();
    619 }
    620 
    621 void SelectNumberedTab(Browser* browser, int index) {
    622   if (index < browser->tab_strip_model()->count()) {
    623     content::RecordAction(UserMetricsAction("SelectNumberedTab"));
    624     browser->tab_strip_model()->ActivateTabAt(index, true);
    625   }
    626 }
    627 
    628 void SelectLastTab(Browser* browser) {
    629   content::RecordAction(UserMetricsAction("SelectLastTab"));
    630   browser->tab_strip_model()->SelectLastTab();
    631 }
    632 
    633 void DuplicateTab(Browser* browser) {
    634   content::RecordAction(UserMetricsAction("Duplicate"));
    635   DuplicateTabAt(browser, browser->tab_strip_model()->active_index());
    636 }
    637 
    638 bool CanDuplicateTab(const Browser* browser) {
    639   WebContents* contents = browser->tab_strip_model()->GetActiveWebContents();
    640   return contents && contents->GetController().GetLastCommittedEntry();
    641 }
    642 
    643 WebContents* DuplicateTabAt(Browser* browser, int index) {
    644   WebContents* contents = browser->tab_strip_model()->GetWebContentsAt(index);
    645   CHECK(contents);
    646   WebContents* contents_dupe = contents->Clone();
    647 
    648   bool pinned = false;
    649   if (browser->CanSupportWindowFeature(Browser::FEATURE_TABSTRIP)) {
    650     // If this is a tabbed browser, just create a duplicate tab inside the same
    651     // window next to the tab being duplicated.
    652     int index = browser->tab_strip_model()->GetIndexOfWebContents(contents);
    653     pinned = browser->tab_strip_model()->IsTabPinned(index);
    654     int add_types = TabStripModel::ADD_ACTIVE |
    655         TabStripModel::ADD_INHERIT_GROUP |
    656         (pinned ? TabStripModel::ADD_PINNED : 0);
    657     browser->tab_strip_model()->InsertWebContentsAt(
    658         index + 1, contents_dupe, add_types);
    659   } else {
    660     Browser* new_browser = NULL;
    661     if (browser->is_app() && !browser->is_type_popup()) {
    662       new_browser = new Browser(
    663           Browser::CreateParams::CreateForApp(browser->app_name(),
    664                                               browser->is_trusted_source(),
    665                                               gfx::Rect(),
    666                                               browser->profile(),
    667                                               browser->host_desktop_type()));
    668     } else {
    669       new_browser = new Browser(
    670           Browser::CreateParams(browser->type(), browser->profile(),
    671                                 browser->host_desktop_type()));
    672     }
    673     // Preserve the size of the original window. The new window has already
    674     // been given an offset by the OS, so we shouldn't copy the old bounds.
    675     BrowserWindow* new_window = new_browser->window();
    676     new_window->SetBounds(gfx::Rect(new_window->GetRestoredBounds().origin(),
    677                           browser->window()->GetRestoredBounds().size()));
    678 
    679     // We need to show the browser now.  Otherwise ContainerWin assumes the
    680     // WebContents is invisible and won't size it.
    681     new_browser->window()->Show();
    682 
    683     // The page transition below is only for the purpose of inserting the tab.
    684     new_browser->tab_strip_model()->AddWebContents(
    685         contents_dupe, -1,
    686         content::PAGE_TRANSITION_LINK,
    687         TabStripModel::ADD_ACTIVE);
    688   }
    689 
    690   SessionService* session_service =
    691       SessionServiceFactory::GetForProfileIfExisting(browser->profile());
    692   if (session_service)
    693     session_service->TabRestored(contents_dupe, pinned);
    694   return contents_dupe;
    695 }
    696 
    697 bool CanDuplicateTabAt(Browser* browser, int index) {
    698   content::NavigationController& nc =
    699       browser->tab_strip_model()->GetWebContentsAt(index)->GetController();
    700   return nc.GetWebContents() && nc.GetLastCommittedEntry();
    701 }
    702 
    703 void ConvertPopupToTabbedBrowser(Browser* browser) {
    704   content::RecordAction(UserMetricsAction("ShowAsTab"));
    705   TabStripModel* tab_strip = browser->tab_strip_model();
    706   WebContents* contents =
    707       tab_strip->DetachWebContentsAt(tab_strip->active_index());
    708   Browser* b = new Browser(Browser::CreateParams(browser->profile(),
    709                                                  browser->host_desktop_type()));
    710   b->tab_strip_model()->AppendWebContents(contents, true);
    711   b->window()->Show();
    712 }
    713 
    714 void Exit() {
    715   content::RecordAction(UserMetricsAction("Exit"));
    716   chrome::AttemptUserExit();
    717 }
    718 
    719 void BookmarkCurrentPage(Browser* browser) {
    720   DCHECK(!chrome::ShouldRemoveBookmarkThisPageUI(browser->profile()));
    721 
    722   const extensions::Extension* extension = NULL;
    723   extensions::Command command;
    724   extensions::CommandService::ExtensionCommandType command_type;
    725   if (GetBookmarkOverrideCommand(browser->profile(),
    726                                  &extension,
    727                                  &command,
    728                                  &command_type)) {
    729     switch (command_type) {
    730       case extensions::CommandService::NAMED:
    731         browser->window()->ExecuteExtensionCommand(extension, command);
    732         return;
    733 
    734       case extensions::CommandService::BROWSER_ACTION:
    735         // BookmarkCurrentPage is called through a user gesture, so it is safe
    736         // to call ShowBrowserActionPopup.
    737         browser->window()->ShowBrowserActionPopup(extension);
    738         return;
    739 
    740       case extensions::CommandService::PAGE_ACTION:
    741         browser->window()->ShowPageActionPopup(extension);
    742         return;
    743     }
    744   }
    745 
    746   BookmarkCurrentPageInternal(browser);
    747 }
    748 
    749 bool CanBookmarkCurrentPage(const Browser* browser) {
    750   return CanBookmarkCurrentPageInternal(browser, true);
    751 }
    752 
    753 void BookmarkAllTabs(Browser* browser) {
    754   chrome::ShowBookmarkAllTabsDialog(browser);
    755 }
    756 
    757 bool CanBookmarkAllTabs(const Browser* browser) {
    758   return browser->tab_strip_model()->count() > 1 &&
    759              !chrome::ShouldRemoveBookmarkOpenPagesUI(browser->profile()) &&
    760              CanBookmarkCurrentPageInternal(browser, false);
    761 }
    762 
    763 void Translate(Browser* browser) {
    764   if (!browser->window()->IsActive())
    765     return;
    766 
    767   WebContents* web_contents =
    768       browser->tab_strip_model()->GetActiveWebContents();
    769   ChromeTranslateClient* chrome_translate_client =
    770       ChromeTranslateClient::FromWebContents(web_contents);
    771 
    772   translate::TranslateStep step = translate::TRANSLATE_STEP_BEFORE_TRANSLATE;
    773   if (chrome_translate_client) {
    774     if (chrome_translate_client->GetLanguageState().translation_pending())
    775       step = translate::TRANSLATE_STEP_TRANSLATING;
    776     else if (chrome_translate_client->GetLanguageState().IsPageTranslated())
    777       step = translate::TRANSLATE_STEP_AFTER_TRANSLATE;
    778   }
    779   browser->window()->ShowTranslateBubble(
    780       web_contents, step, TranslateErrors::NONE);
    781 }
    782 
    783 void ManagePasswordsForPage(Browser* browser) {
    784 // TODO(mkwst): Implement this feature on Mac: http://crbug.com/261628
    785 #if !defined(OS_MACOSX)
    786   if (!browser->window()->IsActive())
    787     return;
    788 
    789   WebContents* web_contents =
    790       browser->tab_strip_model()->GetActiveWebContents();
    791   chrome::ShowManagePasswordsBubble(web_contents);
    792 #endif
    793 }
    794 
    795 void TogglePagePinnedToStartScreen(Browser* browser) {
    796 #if defined(OS_WIN)
    797   MetroPinTabHelper::FromWebContents(
    798       browser->tab_strip_model()->GetActiveWebContents())->
    799           TogglePinnedToStartScreen();
    800 #endif
    801 }
    802 
    803 void SavePage(Browser* browser) {
    804   content::RecordAction(UserMetricsAction("SavePage"));
    805   WebContents* current_tab = browser->tab_strip_model()->GetActiveWebContents();
    806   if (current_tab && current_tab->GetContentsMimeType() == "application/pdf")
    807     content::RecordAction(UserMetricsAction("PDF.SavePage"));
    808   current_tab->OnSavePage();
    809 }
    810 
    811 bool CanSavePage(const Browser* browser) {
    812   // LocalState can be NULL in tests.
    813   if (g_browser_process->local_state() &&
    814       !g_browser_process->local_state()->GetBoolean(
    815       prefs::kAllowFileSelectionDialogs)) {
    816     return false;
    817   }
    818   return !browser->is_devtools() &&
    819       !(GetContentRestrictions(browser) & CONTENT_RESTRICTION_SAVE);
    820 }
    821 
    822 void ShowFindBar(Browser* browser) {
    823   browser->GetFindBarController()->Show();
    824 }
    825 
    826 void ShowWebsiteSettings(Browser* browser,
    827                          content::WebContents* web_contents,
    828                          const GURL& url,
    829                          const SSLStatus& ssl) {
    830   browser->window()->ShowWebsiteSettings(
    831       Profile::FromBrowserContext(web_contents->GetBrowserContext()),
    832       web_contents, url, ssl);
    833 }
    834 
    835 
    836 void Print(Browser* browser) {
    837 #if defined(ENABLE_PRINTING)
    838   WebContents* contents = browser->tab_strip_model()->GetActiveWebContents();
    839 #if defined(ENABLE_FULL_PRINTING)
    840   printing::PrintViewManager* print_view_manager =
    841       printing::PrintViewManager::FromWebContents(contents);
    842   if (browser->profile()->GetPrefs()->GetBoolean(prefs::kPrintPreviewDisabled))
    843     print_view_manager->PrintNow();
    844   else
    845     print_view_manager->PrintPreviewNow(false);
    846 #else
    847   printing::PrintViewManagerBasic* print_view_manager =
    848       printing::PrintViewManagerBasic::FromWebContents(contents);
    849   print_view_manager->PrintNow();
    850 #endif  // defined(ENABLE_FULL_PRINTING)
    851 #endif  // defined(ENABLE_PRINTING)
    852 }
    853 
    854 bool CanPrint(const Browser* browser) {
    855   // Do not print when printing is disabled via pref or policy.
    856   // Do not print when a constrained window is showing. It's confusing.
    857   return browser->profile()->GetPrefs()->GetBoolean(prefs::kPrintingEnabled) &&
    858       !(IsShowingWebContentsModalDialog(browser) ||
    859       GetContentRestrictions(browser) & CONTENT_RESTRICTION_PRINT);
    860 }
    861 
    862 void AdvancedPrint(Browser* browser) {
    863 #if defined(ENABLE_FULL_PRINTING)
    864   printing::PrintViewManager* print_view_manager =
    865       printing::PrintViewManager::FromWebContents(
    866           browser->tab_strip_model()->GetActiveWebContents());
    867   print_view_manager->AdvancedPrintNow();
    868 #endif
    869 }
    870 
    871 bool CanAdvancedPrint(const Browser* browser) {
    872   // If printing is not disabled via pref or policy, it is always possible to
    873   // advanced print when the print preview is visible.  The exception to this
    874   // is under Win8 ash, since showing the advanced print dialog will open it
    875   // modally on the Desktop and hang the browser.  We can remove this check
    876   // once we integrate with the system print charm.
    877 #if defined(OS_WIN)
    878   if (chrome::GetActiveDesktop() == chrome::HOST_DESKTOP_TYPE_ASH)
    879     return false;
    880 #endif
    881 
    882   return browser->profile()->GetPrefs()->GetBoolean(prefs::kPrintingEnabled) &&
    883       (PrintPreviewShowing(browser) || CanPrint(browser));
    884 }
    885 
    886 void PrintToDestination(Browser* browser) {
    887 #if defined(ENABLE_FULL_PRINTING)
    888   printing::PrintViewManager* print_view_manager =
    889       printing::PrintViewManager::FromWebContents(
    890           browser->tab_strip_model()->GetActiveWebContents());
    891   print_view_manager->PrintToDestination();
    892 #endif
    893 }
    894 
    895 void EmailPageLocation(Browser* browser) {
    896   content::RecordAction(UserMetricsAction("EmailPageLocation"));
    897   WebContents* wc = browser->tab_strip_model()->GetActiveWebContents();
    898   DCHECK(wc);
    899 
    900   std::string title = net::EscapeQueryParamValue(
    901       base::UTF16ToUTF8(wc->GetTitle()), false);
    902   std::string page_url = net::EscapeQueryParamValue(wc->GetURL().spec(), false);
    903   std::string mailto = std::string("mailto:?subject=Fwd:%20") +
    904       title + "&body=%0A%0A" + page_url;
    905   platform_util::OpenExternal(browser->profile(), GURL(mailto));
    906 }
    907 
    908 bool CanEmailPageLocation(const Browser* browser) {
    909   return browser->toolbar_model()->ShouldDisplayURL() &&
    910       browser->tab_strip_model()->GetActiveWebContents()->GetURL().is_valid();
    911 }
    912 
    913 void Cut(Browser* browser) {
    914   content::RecordAction(UserMetricsAction("Cut"));
    915   browser->window()->Cut();
    916 }
    917 
    918 void Copy(Browser* browser) {
    919   content::RecordAction(UserMetricsAction("Copy"));
    920   browser->window()->Copy();
    921 }
    922 
    923 void Paste(Browser* browser) {
    924   content::RecordAction(UserMetricsAction("Paste"));
    925   browser->window()->Paste();
    926 }
    927 
    928 void Find(Browser* browser) {
    929   content::RecordAction(UserMetricsAction("Find"));
    930   FindInPage(browser, false, false);
    931 }
    932 
    933 void FindNext(Browser* browser) {
    934   content::RecordAction(UserMetricsAction("FindNext"));
    935   FindInPage(browser, true, true);
    936 }
    937 
    938 void FindPrevious(Browser* browser) {
    939   content::RecordAction(UserMetricsAction("FindPrevious"));
    940   FindInPage(browser, true, false);
    941 }
    942 
    943 void FindInPage(Browser* browser, bool find_next, bool forward_direction) {
    944   ShowFindBar(browser);
    945   if (find_next) {
    946     base::string16 find_text;
    947     FindTabHelper* find_helper = FindTabHelper::FromWebContents(
    948         browser->tab_strip_model()->GetActiveWebContents());
    949 #if defined(OS_MACOSX)
    950     // We always want to search for the current contents of the find bar on
    951     // OS X. For regular profile it's always the current find pboard. For
    952     // Incognito window it's the newest value of the find pboard content and
    953     // user-typed text.
    954     FindBar* find_bar = browser->GetFindBarController()->find_bar();
    955     find_text = find_bar->GetFindText();
    956 #endif
    957     find_helper->StartFinding(find_text, forward_direction, false);
    958   }
    959 }
    960 
    961 void Zoom(Browser* browser, content::PageZoom zoom) {
    962   chrome_page_zoom::Zoom(browser->tab_strip_model()->GetActiveWebContents(),
    963                          zoom);
    964 }
    965 
    966 void FocusToolbar(Browser* browser) {
    967   content::RecordAction(UserMetricsAction("FocusToolbar"));
    968   browser->window()->FocusToolbar();
    969 }
    970 
    971 void FocusLocationBar(Browser* browser) {
    972   content::RecordAction(UserMetricsAction("FocusLocation"));
    973   browser->window()->SetFocusToLocationBar(true);
    974 }
    975 
    976 void FocusSearch(Browser* browser) {
    977   // TODO(beng): replace this with FocusLocationBar
    978   content::RecordAction(UserMetricsAction("FocusSearch"));
    979   browser->window()->GetLocationBar()->FocusSearch();
    980 }
    981 
    982 void FocusAppMenu(Browser* browser) {
    983   content::RecordAction(UserMetricsAction("FocusAppMenu"));
    984   browser->window()->FocusAppMenu();
    985 }
    986 
    987 void FocusBookmarksToolbar(Browser* browser) {
    988   content::RecordAction(UserMetricsAction("FocusBookmarksToolbar"));
    989   browser->window()->FocusBookmarksToolbar();
    990 }
    991 
    992 void FocusInfobars(Browser* browser) {
    993   content::RecordAction(UserMetricsAction("FocusInfobars"));
    994   browser->window()->FocusInfobars();
    995 }
    996 
    997 void FocusNextPane(Browser* browser) {
    998   content::RecordAction(UserMetricsAction("FocusNextPane"));
    999   browser->window()->RotatePaneFocus(true);
   1000 }
   1001 
   1002 void FocusPreviousPane(Browser* browser) {
   1003   content::RecordAction(UserMetricsAction("FocusPreviousPane"));
   1004   browser->window()->RotatePaneFocus(false);
   1005 }
   1006 
   1007 void ToggleDevToolsWindow(Browser* browser, DevToolsToggleAction action) {
   1008   if (action.type() == DevToolsToggleAction::kShowConsole)
   1009     content::RecordAction(UserMetricsAction("DevTools_ToggleConsole"));
   1010   else
   1011     content::RecordAction(UserMetricsAction("DevTools_ToggleWindow"));
   1012   DevToolsWindow::ToggleDevToolsWindow(browser, action);
   1013 }
   1014 
   1015 bool CanOpenTaskManager() {
   1016 #if defined(ENABLE_TASK_MANAGER)
   1017   return true;
   1018 #else
   1019   return false;
   1020 #endif
   1021 }
   1022 
   1023 void OpenTaskManager(Browser* browser) {
   1024 #if defined(ENABLE_TASK_MANAGER)
   1025   content::RecordAction(UserMetricsAction("TaskManager"));
   1026   chrome::ShowTaskManager(browser);
   1027 #else
   1028   NOTREACHED();
   1029 #endif
   1030 }
   1031 
   1032 void OpenFeedbackDialog(Browser* browser) {
   1033   content::RecordAction(UserMetricsAction("Feedback"));
   1034   chrome::ShowFeedbackPage(browser, std::string(), std::string());
   1035 }
   1036 
   1037 void ToggleBookmarkBar(Browser* browser) {
   1038   content::RecordAction(UserMetricsAction("ShowBookmarksBar"));
   1039   ToggleBookmarkBarWhenVisible(browser->profile());
   1040 }
   1041 
   1042 void ShowAppMenu(Browser* browser) {
   1043   // We record the user metric for this event in WrenchMenu::RunMenu.
   1044   browser->window()->ShowAppMenu();
   1045 }
   1046 
   1047 void ShowAvatarMenu(Browser* browser) {
   1048   browser->window()->ShowAvatarBubbleFromAvatarButton(
   1049       BrowserWindow::AVATAR_BUBBLE_MODE_DEFAULT,
   1050       signin::ManageAccountsParams());
   1051 }
   1052 
   1053 void OpenUpdateChromeDialog(Browser* browser) {
   1054   if (UpgradeDetector::GetInstance()->is_outdated_install()) {
   1055     content::NotificationService::current()->Notify(
   1056         chrome::NOTIFICATION_OUTDATED_INSTALL,
   1057         content::NotificationService::AllSources(),
   1058         content::NotificationService::NoDetails());
   1059   } else if (UpgradeDetector::GetInstance()->is_outdated_install_no_au()) {
   1060     content::NotificationService::current()->Notify(
   1061         chrome::NOTIFICATION_OUTDATED_INSTALL_NO_AU,
   1062         content::NotificationService::AllSources(),
   1063         content::NotificationService::NoDetails());
   1064   } else {
   1065     content::RecordAction(UserMetricsAction("UpdateChrome"));
   1066     browser->window()->ShowUpdateChromeDialog();
   1067   }
   1068 }
   1069 
   1070 void ToggleSpeechInput(Browser* browser) {
   1071   SearchTabHelper* search_tab_helper =
   1072       SearchTabHelper::FromWebContents(
   1073           browser->tab_strip_model()->GetActiveWebContents());
   1074   // |search_tab_helper| can be null in unit tests.
   1075   if (search_tab_helper)
   1076     search_tab_helper->ToggleVoiceSearch();
   1077 }
   1078 
   1079 void DistillCurrentPage(Browser* browser) {
   1080   DistillCurrentPageAndView(browser->tab_strip_model()->GetActiveWebContents());
   1081 }
   1082 
   1083 bool CanRequestTabletSite(WebContents* current_tab) {
   1084   return current_tab &&
   1085       current_tab->GetController().GetLastCommittedEntry() != NULL;
   1086 }
   1087 
   1088 bool IsRequestingTabletSite(Browser* browser) {
   1089   WebContents* current_tab = browser->tab_strip_model()->GetActiveWebContents();
   1090   if (!current_tab)
   1091     return false;
   1092   content::NavigationEntry* entry =
   1093       current_tab->GetController().GetLastCommittedEntry();
   1094   if (!entry)
   1095     return false;
   1096   return entry->GetIsOverridingUserAgent();
   1097 }
   1098 
   1099 void ToggleRequestTabletSite(Browser* browser) {
   1100   WebContents* current_tab = browser->tab_strip_model()->GetActiveWebContents();
   1101   if (!current_tab)
   1102     return;
   1103   NavigationController& controller = current_tab->GetController();
   1104   NavigationEntry* entry = controller.GetLastCommittedEntry();
   1105   if (!entry)
   1106     return;
   1107   if (entry->GetIsOverridingUserAgent()) {
   1108     entry->SetIsOverridingUserAgent(false);
   1109   } else {
   1110     entry->SetIsOverridingUserAgent(true);
   1111     chrome::VersionInfo version_info;
   1112     std::string product;
   1113     if (version_info.is_valid())
   1114       product = version_info.ProductNameAndVersionForUserAgent();
   1115     current_tab->SetUserAgentOverride(content::BuildUserAgentFromOSAndProduct(
   1116         kOsOverrideForTabletSite, product));
   1117   }
   1118   controller.ReloadOriginalRequestURL(true);
   1119 }
   1120 
   1121 void ToggleFullscreenMode(Browser* browser) {
   1122   DCHECK(browser);
   1123   browser->fullscreen_controller()->ToggleBrowserFullscreenMode();
   1124 }
   1125 
   1126 void ClearCache(Browser* browser) {
   1127   BrowsingDataRemover* remover =
   1128       BrowsingDataRemover::CreateForUnboundedRange(browser->profile());
   1129   remover->Remove(BrowsingDataRemover::REMOVE_CACHE,
   1130                   BrowsingDataHelper::UNPROTECTED_WEB);
   1131   // BrowsingDataRemover takes care of deleting itself when done.
   1132 }
   1133 
   1134 bool IsDebuggerAttachedToCurrentTab(Browser* browser) {
   1135   WebContents* contents = browser->tab_strip_model()->GetActiveWebContents();
   1136   return contents ?
   1137       content::DevToolsAgentHost::IsDebuggerAttached(contents) : false;
   1138 }
   1139 
   1140 void ViewSource(Browser* browser, WebContents* contents) {
   1141   DCHECK(contents);
   1142 
   1143   // Use the last committed entry, since the pending entry hasn't loaded yet and
   1144   // won't be copied into the cloned tab.
   1145   NavigationEntry* entry = contents->GetController().GetLastCommittedEntry();
   1146   if (!entry)
   1147     return;
   1148 
   1149   ViewSource(browser, contents, entry->GetURL(), entry->GetPageState());
   1150 }
   1151 
   1152 void ViewSource(Browser* browser,
   1153                 WebContents* contents,
   1154                 const GURL& url,
   1155                 const content::PageState& page_state) {
   1156   content::RecordAction(UserMetricsAction("ViewSource"));
   1157   DCHECK(contents);
   1158 
   1159   WebContents* view_source_contents = contents->Clone();
   1160   DCHECK(view_source_contents->GetController().CanPruneAllButLastCommitted());
   1161   view_source_contents->GetController().PruneAllButLastCommitted();
   1162   NavigationEntry* last_committed_entry =
   1163       view_source_contents->GetController().GetLastCommittedEntry();
   1164   if (!last_committed_entry)
   1165     return;
   1166 
   1167   GURL view_source_url =
   1168       GURL(content::kViewSourceScheme + std::string(":") + url.spec());
   1169   last_committed_entry->SetVirtualURL(view_source_url);
   1170 
   1171   // Do not restore scroller position.
   1172   last_committed_entry->SetPageState(page_state.RemoveScrollOffset());
   1173 
   1174   // Do not restore title, derive it from the url.
   1175   last_committed_entry->SetTitle(base::string16());
   1176 
   1177   // Now show view-source entry.
   1178   if (browser->CanSupportWindowFeature(Browser::FEATURE_TABSTRIP)) {
   1179     // If this is a tabbed browser, just create a duplicate tab inside the same
   1180     // window next to the tab being duplicated.
   1181     int index = browser->tab_strip_model()->GetIndexOfWebContents(contents);
   1182     int add_types = TabStripModel::ADD_ACTIVE |
   1183         TabStripModel::ADD_INHERIT_GROUP;
   1184     browser->tab_strip_model()->InsertWebContentsAt(
   1185         index + 1,
   1186         view_source_contents,
   1187         add_types);
   1188   } else {
   1189     Browser* b = new Browser(
   1190         Browser::CreateParams(Browser::TYPE_TABBED, browser->profile(),
   1191                               browser->host_desktop_type()));
   1192 
   1193     // Preserve the size of the original window. The new window has already
   1194     // been given an offset by the OS, so we shouldn't copy the old bounds.
   1195     BrowserWindow* new_window = b->window();
   1196     new_window->SetBounds(gfx::Rect(new_window->GetRestoredBounds().origin(),
   1197                           browser->window()->GetRestoredBounds().size()));
   1198 
   1199     // We need to show the browser now. Otherwise ContainerWin assumes the
   1200     // WebContents is invisible and won't size it.
   1201     b->window()->Show();
   1202 
   1203     // The page transition below is only for the purpose of inserting the tab.
   1204     b->tab_strip_model()->AddWebContents(view_source_contents, -1,
   1205                                          content::PAGE_TRANSITION_LINK,
   1206                                          TabStripModel::ADD_ACTIVE);
   1207   }
   1208 
   1209   SessionService* session_service =
   1210       SessionServiceFactory::GetForProfileIfExisting(browser->profile());
   1211   if (session_service)
   1212     session_service->TabRestored(view_source_contents, false);
   1213 }
   1214 
   1215 void ViewSelectedSource(Browser* browser) {
   1216   ViewSource(browser, browser->tab_strip_model()->GetActiveWebContents());
   1217 }
   1218 
   1219 bool CanViewSource(const Browser* browser) {
   1220   return !browser->is_devtools() &&
   1221       browser->tab_strip_model()->GetActiveWebContents()->GetController().
   1222           CanViewSource();
   1223 }
   1224 
   1225 void CreateApplicationShortcuts(Browser* browser) {
   1226   content::RecordAction(UserMetricsAction("CreateShortcut"));
   1227   extensions::TabHelper::FromWebContents(
   1228       browser->tab_strip_model()->GetActiveWebContents())->
   1229           CreateApplicationShortcuts();
   1230 }
   1231 
   1232 void CreateBookmarkAppFromCurrentWebContents(Browser* browser) {
   1233   content::RecordAction(UserMetricsAction("CreateHostedApp"));
   1234   extensions::TabHelper::FromWebContents(
   1235       browser->tab_strip_model()->GetActiveWebContents())->
   1236           CreateHostedAppFromWebContents();
   1237 }
   1238 
   1239 bool CanCreateApplicationShortcuts(const Browser* browser) {
   1240   return extensions::TabHelper::FromWebContents(
   1241       browser->tab_strip_model()->GetActiveWebContents())->
   1242           CanCreateApplicationShortcuts();
   1243 }
   1244 
   1245 bool CanCreateBookmarkApp(const Browser* browser) {
   1246   return extensions::TabHelper::FromWebContents(
   1247              browser->tab_strip_model()->GetActiveWebContents())
   1248       ->CanCreateBookmarkApp();
   1249 }
   1250 
   1251 void ConvertTabToAppWindow(Browser* browser,
   1252                            content::WebContents* contents) {
   1253   const GURL& url = contents->GetController().GetLastCommittedEntry()->GetURL();
   1254   std::string app_name = web_app::GenerateApplicationNameFromURL(url);
   1255 
   1256   int index = browser->tab_strip_model()->GetIndexOfWebContents(contents);
   1257   if (index >= 0)
   1258     browser->tab_strip_model()->DetachWebContentsAt(index);
   1259 
   1260   Browser* app_browser = new Browser(
   1261       Browser::CreateParams::CreateForApp(app_name,
   1262                                           true /* trusted_source */,
   1263                                           gfx::Rect(),
   1264                                           browser->profile(),
   1265                                           browser->host_desktop_type()));
   1266   app_browser->tab_strip_model()->AppendWebContents(contents, true);
   1267 
   1268   contents->GetMutableRendererPrefs()->can_accept_load_drops = false;
   1269   contents->GetRenderViewHost()->SyncRendererPrefs();
   1270   app_browser->window()->Show();
   1271 }
   1272 
   1273 }  // namespace chrome
   1274