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/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"
     78 
     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
     83 
     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)
     92 
     93 namespace {
     94 const char kOsOverrideForTabletSite[] = "Linux; Android 4.0.3";
     95 }
     96 
     97 using content::NavigationController;
     98 using content::NavigationEntry;
     99 using content::OpenURLParams;
    100 using content::Referrer;
    101 using content::SSLStatus;
    102 using content::UserMetricsAction;
    103 using content::WebContents;
    104 using web_modal::WebContentsModalDialogManager;
    105 
    106 namespace chrome {
    107 namespace {
    108 
    109 void BookmarkCurrentPageInternal(Browser* browser, bool from_star) {
    110   content::RecordAction(UserMetricsAction("Star"));
    111 
    112   BookmarkModel* model =
    113       BookmarkModelFactory::GetForProfile(browser->profile());
    114   if (!model || !model->loaded())
    115     return;  // Ignore requests until bookmarks are loaded.
    116 
    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();
    127   }
    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);
    137   }
    138 }
    139 
    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;
    152     }
    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;
    162     }
    163     default:
    164       break;
    165   }
    166   return current_tab;
    167 }
    168 
    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.
    173   //
    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);
    184 }
    185 
    186 bool IsShowingWebContentsModalDialog(const Browser* browser) {
    187   WebContents* web_contents =
    188       browser->tab_strip_model()->GetActiveWebContents();
    189   if (!web_contents)
    190     return false;
    191 
    192   WebContentsModalDialogManager* web_contents_modal_dialog_manager =
    193       WebContentsModalDialogManager::FromWebContents(web_contents);
    194   return web_contents_modal_dialog_manager->IsDialogActive();
    195 }
    196 
    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
    207 }
    208 
    209 }  // namespace
    210 
    211 bool IsCommandEnabled(Browser* browser, int command) {
    212   return browser->command_controller()->command_updater()->IsCommandEnabled(
    213       command);
    214 }
    215 
    216 bool SupportsCommand(Browser* browser, int command) {
    217   return browser->command_controller()->command_updater()->SupportsCommand(
    218       command);
    219 }
    220 
    221 bool ExecuteCommand(Browser* browser, int command) {
    222   return browser->command_controller()->command_updater()->ExecuteCommand(
    223       command);
    224 }
    225 
    226 bool ExecuteCommandWithDisposition(Browser* browser,
    227                                    int command,
    228                                    WindowOpenDisposition disposition) {
    229   return browser->command_controller()->command_updater()->
    230       ExecuteCommandWithDisposition(command, disposition);
    231 }
    232 
    233 void UpdateCommandEnabled(Browser* browser, int command, bool enabled) {
    234   browser->command_controller()->command_updater()->UpdateCommandEnabled(
    235       command, enabled);
    236 }
    237 
    238 void AddCommandObserver(Browser* browser,
    239                         int command,
    240                         CommandObserver* observer) {
    241   browser->command_controller()->command_updater()->AddCommandObserver(
    242       command, observer);
    243 }
    244 
    245 void RemoveCommandObserver(Browser* browser,
    246                            int command,
    247                            CommandObserver* observer) {
    248   browser->command_controller()->command_updater()->RemoveCommandObserver(
    249       command, observer);
    250 }
    251 
    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;
    268   }
    269   return content_restrictions;
    270 }
    271 
    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;
    279     }
    280   } else {
    281     if (browser_defaults::kAlwaysOpenIncognitoWindow &&
    282         IncognitoModePrefs::ShouldLaunchIncognito(
    283             *CommandLine::ForCurrentProcess(), prefs)) {
    284       incognito = true;
    285     }
    286   }
    287 
    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);
    299     }
    300   }
    301 }
    302 
    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;
    309 }
    310 
    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);
    316 }
    317 
    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);
    325 }
    326 
    327 bool CanGoBack(const Browser* browser) {
    328   return browser->tab_strip_model()->GetActiveWebContents()->
    329       GetController().CanGoBack();
    330 }
    331 
    332 void GoBack(Browser* browser, WindowOpenDisposition disposition) {
    333   content::RecordAction(UserMetricsAction("Back"));
    334 
    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();
    343   }
    344 }
    345 
    346 bool CanGoForward(const Browser* browser) {
    347   return browser->tab_strip_model()->GetActiveWebContents()->
    348       GetController().CanGoForward();
    349 }
    350 
    351 void GoForward(Browser* browser, WindowOpenDisposition disposition) {
    352   content::RecordAction(UserMetricsAction("Forward"));
    353   if (CanGoForward(browser)) {
    354     GetOrCloneTabForDisposition(browser, disposition)->
    355         GetController().GoForward();
    356   }
    357 }
    358 
    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;
    368 }
    369 
    370 void Reload(Browser* browser, WindowOpenDisposition disposition) {
    371   content::RecordAction(UserMetricsAction("Reload"));
    372   ReloadInternal(browser, disposition, false);
    373 }
    374 
    375 void ReloadIgnoringCache(Browser* browser, WindowOpenDisposition disposition) {
    376   content::RecordAction(UserMetricsAction("ReloadIgnoringCache"));
    377   ReloadInternal(browser, disposition, true);
    378 }
    379 
    380 bool CanReload(const Browser* browser) {
    381   return !browser->is_devtools();
    382 }
    383 
    384 void Home(Browser* browser, WindowOpenDisposition disposition) {
    385   content::RecordAction(UserMetricsAction("Home"));
    386 
    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);
    396     }
    397   }
    398 #endif
    399 
    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);
    408 }
    409 
    410 void OpenCurrentURL(Browser* browser) {
    411   content::RecordAction(UserMetricsAction("LoadURL"));
    412   LocationBar* location_bar = browser->window()->GetLocationBar();
    413   if (!location_bar)
    414     return;
    415 
    416   GURL url(location_bar->GetDestinationURL());
    417 
    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;
    435 
    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);
    445 
    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());
    453   }
    454 }
    455 
    456 void Stop(Browser* browser) {
    457   content::RecordAction(UserMetricsAction("Stop"));
    458   browser->tab_strip_model()->GetActiveWebContents()->Stop();
    459 }
    460 
    461 #if !defined(OS_WIN)
    462 void NewWindow(Browser* browser) {
    463   NewEmptyWindow(browser->profile()->GetOriginalProfile(),
    464                  browser->host_desktop_type());
    465 }
    466 
    467 void NewIncognitoWindow(Browser* browser) {
    468   NewEmptyWindow(browser->profile()->GetOffTheRecordProfile(),
    469                  browser->host_desktop_type());
    470 }
    471 #endif  // OS_WIN
    472 
    473 void CloseWindow(Browser* browser) {
    474   content::RecordAction(UserMetricsAction("CloseWindow"));
    475   browser->window()->Close();
    476 }
    477 
    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);
    485 
    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();
    500   }
    501 }
    502 
    503 void CloseTab(Browser* browser) {
    504   content::RecordAction(UserMetricsAction("CloseTab_Accelerator"));
    505   browser->tab_strip_model()->CloseSelectedTabs();
    506 }
    507 
    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());
    515 }
    516 
    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;
    526 }
    527 
    528 void SelectNextTab(Browser* browser) {
    529   content::RecordAction(UserMetricsAction("SelectNextTab"));
    530   browser->tab_strip_model()->SelectNextTab();
    531 }
    532 
    533 void SelectPreviousTab(Browser* browser) {
    534   content::RecordAction(UserMetricsAction("SelectPrevTab"));
    535   browser->tab_strip_model()->SelectPreviousTab();
    536 }
    537 
    538 void OpenTabpose(Browser* browser) {
    539 #if defined(OS_MACOSX)
    540   if (!CommandLine::ForCurrentProcess()->HasSwitch(
    541         switches::kEnableExposeForTabs)) {
    542     return;
    543   }
    544 
    545   content::RecordAction(UserMetricsAction("OpenTabpose"));
    546   browser->window()->OpenTabpose();
    547 #else
    548   NOTREACHED();
    549 #endif
    550 }
    551 
    552 void MoveTabNext(Browser* browser) {
    553   content::RecordAction(UserMetricsAction("MoveTabNext"));
    554   browser->tab_strip_model()->MoveTabNext();
    555 }
    556 
    557 void MoveTabPrevious(Browser* browser) {
    558   content::RecordAction(UserMetricsAction("MoveTabPrevious"));
    559   browser->tab_strip_model()->MoveTabPrevious();
    560 }
    561 
    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);
    566   }
    567 }
    568 
    569 void SelectLastTab(Browser* browser) {
    570   content::RecordAction(UserMetricsAction("SelectLastTab"));
    571   browser->tab_strip_model()->SelectLastTab();
    572 }
    573 
    574 void DuplicateTab(Browser* browser) {
    575   content::RecordAction(UserMetricsAction("Duplicate"));
    576   DuplicateTabAt(browser, browser->tab_strip_model()->active_index());
    577 }
    578 
    579 bool CanDuplicateTab(const Browser* browser) {
    580   WebContents* contents = browser->tab_strip_model()->GetActiveWebContents();
    581   return contents && contents->GetController().GetLastCommittedEntry();
    582 }
    583 
    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();
    588 
    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()));
    614     }
    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()));
    620 
    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();
    624 
    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);
    630   }
    631 
    632   SessionService* session_service =
    633       SessionServiceFactory::GetForProfileIfExisting(browser->profile());
    634   if (session_service)
    635     session_service->TabRestored(contents_dupe, pinned);
    636   return contents_dupe;
    637 }
    638 
    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();
    643 }
    644 
    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();
    654 }
    655 
    656 void Exit() {
    657   content::RecordAction(UserMetricsAction("Exit"));
    658   chrome::AttemptUserExit();
    659 }
    660 
    661 void BookmarkCurrentPage(Browser* browser) {
    662   BookmarkCurrentPageInternal(browser, false);
    663 }
    664 
    665 void BookmarkCurrentPageFromStar(Browser* browser) {
    666   BookmarkCurrentPageInternal(browser, true);
    667 }
    668 
    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();
    676 }
    677 
    678 void BookmarkAllTabs(Browser* browser) {
    679   chrome::ShowBookmarkAllTabsDialog(browser);
    680 }
    681 
    682 bool CanBookmarkAllTabs(const Browser* browser) {
    683   return browser->tab_strip_model()->count() > 1 &&
    684              CanBookmarkCurrentPage(browser);
    685 }
    686 
    687 void Translate(Browser* browser) {
    688   if (!browser->window()->IsActive())
    689     return;
    690 
    691   WebContents* web_contents =
    692       browser->tab_strip_model()->GetActiveWebContents();
    693   TranslateTabHelper* translate_tab_helper =
    694       TranslateTabHelper::FromWebContents(web_contents);
    695 
    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;
    703   }
    704   browser->window()->ShowTranslateBubble(web_contents, view_state,
    705                                          TranslateErrors::NONE);
    706 }
    707 
    708 void TogglePagePinnedToStartScreen(Browser* browser) {
    709 #if defined(OS_WIN)
    710   MetroPinTabHelper::FromWebContents(
    711       browser->tab_strip_model()->GetActiveWebContents())->
    712           TogglePinnedToStartScreen();
    713 #endif
    714 }
    715 
    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();
    722 }
    723 
    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;
    730   }
    731   return !browser->is_devtools() &&
    732       !(GetContentRestrictions(browser) & CONTENT_RESTRICTION_SAVE);
    733 }
    734 
    735 void ShowFindBar(Browser* browser) {
    736   browser->GetFindBarController()->Show();
    737 }
    738 
    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);
    746 }
    747 
    748 
    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)
    765 }
    766 
    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);
    773 }
    774 
    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
    782 }
    783 
    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
    794 
    795   return browser->profile()->GetPrefs()->GetBoolean(prefs::kPrintingEnabled) &&
    796       (PrintPreviewShowing(browser) || CanPrint(browser));
    797 }
    798 
    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
    806 }
    807 
    808 void EmailPageLocation(Browser* browser) {
    809   content::RecordAction(UserMetricsAction("EmailPageLocation"));
    810   WebContents* wc = browser->tab_strip_model()->GetActiveWebContents();
    811   DCHECK(wc);
    812 
    813   std::string title = net::EscapeQueryParamValue(
    814       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));
    819 }
    820 
    821 bool CanEmailPageLocation(const Browser* browser) {
    822   return browser->toolbar_model()->ShouldDisplayURL() &&
    823       browser->tab_strip_model()->GetActiveWebContents()->GetURL().is_valid();
    824 }
    825 
    826 void Cut(Browser* browser) {
    827   content::RecordAction(UserMetricsAction("Cut"));
    828   browser->window()->Cut();
    829 }
    830 
    831 void Copy(Browser* browser) {
    832   content::RecordAction(UserMetricsAction("Copy"));
    833   browser->window()->Copy();
    834 }
    835 
    836 void Paste(Browser* browser) {
    837   content::RecordAction(UserMetricsAction("Paste"));
    838   browser->window()->Paste();
    839 }
    840 
    841 void Find(Browser* browser) {
    842   content::RecordAction(UserMetricsAction("Find"));
    843   FindInPage(browser, false, false);
    844 }
    845 
    846 void FindNext(Browser* browser) {
    847   content::RecordAction(UserMetricsAction("FindNext"));
    848   FindInPage(browser, true, true);
    849 }
    850 
    851 void FindPrevious(Browser* browser) {
    852   content::RecordAction(UserMetricsAction("FindPrevious"));
    853   FindInPage(browser, true, false);
    854 }
    855 
    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);
    871   }
    872 }
    873 
    874 void Zoom(Browser* browser, content::PageZoom zoom) {
    875   if (browser->is_devtools())
    876     return;
    877 
    878   chrome_page_zoom::Zoom(browser->tab_strip_model()->GetActiveWebContents(),
    879                          zoom);
    880 }
    881 
    882 void FocusToolbar(Browser* browser) {
    883   content::RecordAction(UserMetricsAction("FocusToolbar"));
    884   browser->window()->FocusToolbar();
    885 }
    886 
    887 void FocusLocationBar(Browser* browser) {
    888   content::RecordAction(UserMetricsAction("FocusLocation"));
    889   browser->window()->SetFocusToLocationBar(true);
    890 }
    891 
    892 void FocusSearch(Browser* browser) {
    893   // TODO(beng): replace this with FocusLocationBar
    894   content::RecordAction(UserMetricsAction("FocusSearch"));
    895   browser->window()->GetLocationBar()->FocusSearch();
    896 }
    897 
    898 void FocusAppMenu(Browser* browser) {
    899   content::RecordAction(UserMetricsAction("FocusAppMenu"));
    900   browser->window()->FocusAppMenu();
    901 }
    902 
    903 void FocusBookmarksToolbar(Browser* browser) {
    904   content::RecordAction(UserMetricsAction("FocusBookmarksToolbar"));
    905   browser->window()->FocusBookmarksToolbar();
    906 }
    907 
    908 void FocusInfobars(Browser* browser) {
    909   content::RecordAction(UserMetricsAction("FocusInfobars"));
    910   browser->window()->FocusInfobars();
    911 }
    912 
    913 void FocusNextPane(Browser* browser) {
    914   content::RecordAction(UserMetricsAction("FocusNextPane"));
    915   browser->window()->RotatePaneFocus(true);
    916 }
    917 
    918 void FocusPreviousPane(Browser* browser) {
    919   content::RecordAction(UserMetricsAction("FocusPreviousPane"));
    920   browser->window()->RotatePaneFocus(false);
    921 }
    922 
    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);
    929 }
    930 
    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
    938 }
    939 
    940 void OpenTaskManager(Browser* browser) {
    941   content::RecordAction(UserMetricsAction("TaskManager"));
    942   chrome::ShowTaskManager(browser);
    943 }
    944 
    945 void OpenFeedbackDialog(Browser* browser) {
    946   content::RecordAction(UserMetricsAction("Feedback"));
    947   chrome::ShowFeedbackPage(browser, std::string(), std::string());
    948 }
    949 
    950 void ToggleBookmarkBar(Browser* browser) {
    951   content::RecordAction(UserMetricsAction("ShowBookmarksBar"));
    952   ToggleBookmarkBarWhenVisible(browser->profile());
    953 }
    954 
    955 void ShowAppMenu(Browser* browser) {
    956   // We record the user metric for this event in WrenchMenu::RunMenu.
    957   browser->window()->ShowAppMenu();
    958 }
    959 
    960 void ShowAvatarMenu(Browser* browser) {
    961   browser->window()->ShowAvatarBubbleFromAvatarButton();
    962 }
    963 
    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();
    973   }
    974 }
    975 
    976 void ToggleSpeechInput(Browser* browser) {
    977   WebContents* web_contents =
    978       browser->tab_strip_model()->GetActiveWebContents();
    979   web_contents->GetRenderViewHost()->ToggleSpeechInput();
    980 
    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();
    986 }
    987 
    988 bool CanRequestTabletSite(WebContents* current_tab) {
    989   if (!current_tab)
    990     return false;
    991   return current_tab->GetController().GetActiveEntry() != NULL;
    992 }
    993 
    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();
   1003 }
   1004 
   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));
   1024   }
   1025   controller.ReloadOriginalRequestURL(true);
   1026 }
   1027 
   1028 void ToggleFullscreenMode(Browser* browser) {
   1029   browser->fullscreen_controller()->ToggleFullscreenMode();
   1030 }
   1031 
   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.
   1038 }
   1039 
   1040 bool IsDebuggerAttachedToCurrentTab(Browser* browser) {
   1041   WebContents* contents = browser->tab_strip_model()->GetActiveWebContents();
   1042   return contents ?
   1043       content::DevToolsAgentHost::IsDebuggerAttached(contents) : false;
   1044 }
   1045 
   1046 void ViewSource(Browser* browser, WebContents* contents) {
   1047   DCHECK(contents);
   1048 
   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;
   1054 
   1055   ViewSource(browser, contents, entry->GetURL(), entry->GetPageState());
   1056 }
   1057 
   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);
   1064 
   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;
   1074 
   1075   GURL view_source_url =
   1076       GURL(content::kViewSourceScheme + std::string(":") + url.spec());
   1077   active_entry->SetVirtualURL(view_source_url);
   1078 
   1079   // Do not restore scroller position.
   1080   active_entry->SetPageState(page_state.RemoveScrollOffset());
   1081 
   1082   // Do not restore title, derive it from the url.
   1083   active_entry->SetTitle(string16());
   1084 
   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()));
   1100 
   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()));
   1106 
   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();
   1110 
   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);
   1115   }
   1116 
   1117   SessionService* session_service =
   1118       SessionServiceFactory::GetForProfileIfExisting(browser->profile());
   1119   if (session_service)
   1120     session_service->TabRestored(view_source_contents, false);
   1121 }
   1122 
   1123 void ViewSelectedSource(Browser* browser) {
   1124   ViewSource(browser, browser->tab_strip_model()->GetActiveWebContents());
   1125 }
   1126 
   1127 bool CanViewSource(const Browser* browser) {
   1128   return browser->tab_strip_model()->GetActiveWebContents()->
   1129       GetController().CanViewSource();
   1130 }
   1131 
   1132 void CreateApplicationShortcuts(Browser* browser) {
   1133   content::RecordAction(UserMetricsAction("CreateShortcut"));
   1134   extensions::TabHelper::FromWebContents(
   1135       browser->tab_strip_model()->GetActiveWebContents())->
   1136           CreateApplicationShortcuts();
   1137 }
   1138 
   1139 void CreateHostedAppFromCurrentWebContents(Browser* browser) {
   1140   content::RecordAction(UserMetricsAction("CreateHostedApp"));
   1141   extensions::TabHelper::FromWebContents(
   1142       browser->tab_strip_model()->GetActiveWebContents())->
   1143           CreateHostedAppFromWebContents();
   1144 }
   1145 
   1146 bool CanCreateApplicationShortcuts(const Browser* browser) {
   1147   return extensions::TabHelper::FromWebContents(
   1148       browser->tab_strip_model()->GetActiveWebContents())->
   1149           CanCreateApplicationShortcuts();
   1150 }
   1151 
   1152 void ConvertTabToAppWindow(Browser* browser,
   1153                            content::WebContents* contents) {
   1154   const GURL& url = contents->GetController().GetActiveEntry()->GetURL();
   1155   std::string app_name = web_app::GenerateApplicationNameFromURL(url);
   1156 
   1157   int index = browser->tab_strip_model()->GetIndexOfWebContents(contents);
   1158   if (index >= 0)
   1159     browser->tab_strip_model()->DetachWebContentsAt(index);
   1160 
   1161   Browser* app_browser = new Browser(
   1162       Browser::CreateParams::CreateForApp(
   1163           Browser::TYPE_POPUP, app_name, gfx::Rect(), browser->profile(),
   1164           browser->host_desktop_type()));
   1165   app_browser->tab_strip_model()->AppendWebContents(contents, true);
   1166 
   1167   contents->GetMutableRendererPrefs()->can_accept_load_drops = false;
   1168   contents->GetRenderViewHost()->SyncRendererPrefs();
   1169   app_browser->window()->Show();
   1170 }
   1171 
   1172 }  // namespace chrome
   1173