// Copyright 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/browser_commands.h"

#include "base/command_line.h"
#include "base/metrics/histogram.h"
#include "base/prefs/pref_service.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/bookmarks/bookmark_model_factory.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browsing_data/browsing_data_helper.h"
#include "chrome/browser/browsing_data/browsing_data_remover.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/chrome_page_zoom.h"
#include "chrome/browser/devtools/devtools_window.h"
#include "chrome/browser/dom_distiller/tab_utils.h"
#include "chrome/browser/extensions/api/commands/command_service.h"
#include "chrome/browser/extensions/tab_helper.h"
#include "chrome/browser/favicon/favicon_tab_helper.h"
#include "chrome/browser/lifetime/application_lifetime.h"
#include "chrome/browser/platform_util.h"
#include "chrome/browser/prefs/incognito_mode_prefs.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/rlz/rlz.h"
#include "chrome/browser/search/search.h"
#include "chrome/browser/sessions/session_service_factory.h"
#include "chrome/browser/sessions/tab_restore_service.h"
#include "chrome/browser/sessions/tab_restore_service_delegate.h"
#include "chrome/browser/sessions/tab_restore_service_factory.h"
#include "chrome/browser/signin/signin_header_helper.h"
#include "chrome/browser/translate/chrome_translate_client.h"
#include "chrome/browser/ui/accelerator_utils.h"
#include "chrome/browser/ui/bookmarks/bookmark_utils.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_command_controller.h"
#include "chrome/browser/ui/browser_dialogs.h"
#include "chrome/browser/ui/browser_instant_controller.h"
#include "chrome/browser/ui/browser_tab_restore_service_delegate.h"
#include "chrome/browser/ui/browser_tabstrip.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/chrome_pages.h"
#include "chrome/browser/ui/find_bar/find_bar.h"
#include "chrome/browser/ui/find_bar/find_bar_controller.h"
#include "chrome/browser/ui/find_bar/find_tab_helper.h"
#include "chrome/browser/ui/fullscreen/fullscreen_controller.h"
#include "chrome/browser/ui/omnibox/location_bar.h"
#include "chrome/browser/ui/scoped_tabbed_browser_displayer.h"
#include "chrome/browser/ui/search/search_tab_helper.h"
#include "chrome/browser/ui/status_bubble.h"
#include "chrome/browser/ui/tab_contents/core_tab_helper.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/webui/ntp/core_app_launcher_handler.h"
#include "chrome/browser/upgrade_detector.h"
#include "chrome/browser/web_applications/web_app.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/chrome_version_info.h"
#include "chrome/common/content_restriction.h"
#include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
#include "chrome/common/pref_names.h"
#include "components/bookmarks/browser/bookmark_model.h"
#include "components/bookmarks/browser/bookmark_utils.h"
#include "components/google/core/browser/google_util.h"
#include "components/translate/core/browser/language_state.h"
#include "components/web_modal/web_contents_modal_dialog_manager.h"
#include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/page_navigator.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/user_metrics.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/renderer_preferences.h"
#include "content/public/common/url_constants.h"
#include "content/public/common/url_utils.h"
#include "content/public/common/user_agent.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/common/extension.h"
#include "extensions/common/extension_set.h"
#include "net/base/escape.h"
#include "ui/events/keycodes/keyboard_codes.h"

#if defined(OS_WIN)
#include "chrome/browser/ui/metro_pin_tab_helper_win.h"
#endif

#if defined(ENABLE_PRINTING)
#if defined(ENABLE_FULL_PRINTING)
#include "chrome/browser/printing/print_preview_dialog_controller.h"
#include "chrome/browser/printing/print_view_manager.h"
#else
#include "chrome/browser/printing/print_view_manager_basic.h"
#endif  // defined(ENABLE_FULL_PRINTING)
#endif  // defined(ENABLE_PRINTING)

namespace {
const char kOsOverrideForTabletSite[] = "Linux; Android 4.0.3";
}

using base::UserMetricsAction;
using content::NavigationController;
using content::NavigationEntry;
using content::OpenURLParams;
using content::Referrer;
using content::SSLStatus;
using content::WebContents;
using web_modal::WebContentsModalDialogManager;

namespace chrome {
namespace {

bool CanBookmarkCurrentPageInternal(const Browser* browser,
                                    bool check_remove_bookmark_ui) {
  BookmarkModel* model =
      BookmarkModelFactory::GetForProfile(browser->profile());
  return browser_defaults::bookmarks_enabled &&
      browser->profile()->GetPrefs()->GetBoolean(
          prefs::kEditBookmarksEnabled) &&
      model && model->loaded() && browser->is_type_tabbed() &&
      (!check_remove_bookmark_ui ||
           !chrome::ShouldRemoveBookmarkThisPageUI(browser->profile()));
}

bool GetBookmarkOverrideCommand(
    Profile* profile,
    const extensions::Extension** extension,
    extensions::Command* command,
    extensions::CommandService::ExtensionCommandType* command_type) {
  DCHECK(extension);
  DCHECK(command);
  DCHECK(command_type);

  ui::Accelerator bookmark_page_accelerator =
      chrome::GetPrimaryChromeAcceleratorForCommandId(IDC_BOOKMARK_PAGE);
  if (bookmark_page_accelerator.key_code() == ui::VKEY_UNKNOWN)
    return false;

  extensions::CommandService* command_service =
      extensions::CommandService::Get(profile);
  const extensions::ExtensionSet& extension_set =
      extensions::ExtensionRegistry::Get(profile)->enabled_extensions();
  for (extensions::ExtensionSet::const_iterator i = extension_set.begin();
       i != extension_set.end();
       ++i) {
    extensions::Command prospective_command;
    extensions::CommandService::ExtensionCommandType prospective_command_type;
    if (command_service->GetBoundExtensionCommand((*i)->id(),
                                                  bookmark_page_accelerator,
                                                  &prospective_command,
                                                  &prospective_command_type)) {
      *extension = i->get();
      *command = prospective_command;
      *command_type = prospective_command_type;
      return true;
    }
  }

  return false;
}

void BookmarkCurrentPageInternal(Browser* browser) {
  content::RecordAction(UserMetricsAction("Star"));

  BookmarkModel* model =
      BookmarkModelFactory::GetForProfile(browser->profile());
  if (!model || !model->loaded())
    return;  // Ignore requests until bookmarks are loaded.

  GURL url;
  base::string16 title;
  WebContents* web_contents =
      browser->tab_strip_model()->GetActiveWebContents();
  GetURLAndTitleToBookmark(web_contents, &url, &title);
  bool is_bookmarked_by_any = model->IsBookmarked(url);
  if (!is_bookmarked_by_any &&
      web_contents->GetBrowserContext()->IsOffTheRecord()) {
    // If we're incognito the favicon may not have been saved. Save it now
    // so that bookmarks have an icon for the page.
    FaviconTabHelper::FromWebContents(web_contents)->SaveFavicon();
  }
  bool was_bookmarked_by_user = bookmark_utils::IsBookmarkedByUser(model, url);
  bookmark_utils::AddIfNotBookmarked(model, url, title);
  bool is_bookmarked_by_user = bookmark_utils::IsBookmarkedByUser(model, url);
  // Make sure the model actually added a bookmark before showing the star. A
  // bookmark isn't created if the url is invalid.
  if (browser->window()->IsActive() && is_bookmarked_by_user) {
    // Only show the bubble if the window is active, otherwise we may get into
    // weird situations where the bubble is deleted as soon as it is shown.
    browser->window()->ShowBookmarkBubble(url, was_bookmarked_by_user);
  }
}

// Based on |disposition|, creates a new tab as necessary, and returns the
// appropriate tab to navigate.  If that tab is the current tab, reverts the
// location bar contents, since all browser-UI-triggered navigations should
// revert any omnibox edits in the current tab.
WebContents* GetTabAndRevertIfNecessary(Browser* browser,
                                        WindowOpenDisposition disposition) {
  WebContents* current_tab = browser->tab_strip_model()->GetActiveWebContents();
  switch (disposition) {
    case NEW_FOREGROUND_TAB:
    case NEW_BACKGROUND_TAB: {
      WebContents* new_tab = current_tab->Clone();
      browser->tab_strip_model()->AddWebContents(
          new_tab, -1, content::PAGE_TRANSITION_LINK,
          (disposition == NEW_FOREGROUND_TAB) ?
              TabStripModel::ADD_ACTIVE : TabStripModel::ADD_NONE);
      return new_tab;
    }
    case NEW_WINDOW: {
      WebContents* new_tab = current_tab->Clone();
      Browser* new_browser = new Browser(Browser::CreateParams(
          browser->profile(), browser->host_desktop_type()));
      new_browser->tab_strip_model()->AddWebContents(
          new_tab, -1, content::PAGE_TRANSITION_LINK,
          TabStripModel::ADD_ACTIVE);
      new_browser->window()->Show();
      return new_tab;
    }
    default:
      browser->window()->GetLocationBar()->Revert();
      return current_tab;
  }
}

void ReloadInternal(Browser* browser,
                    WindowOpenDisposition disposition,
                    bool ignore_cache) {
  // As this is caused by a user action, give the focus to the page.
  //
  // Also notify RenderViewHostDelegate of the user gesture; this is
  // normally done in Browser::Navigate, but a reload bypasses Navigate.
  WebContents* new_tab = GetTabAndRevertIfNecessary(browser, disposition);
  new_tab->UserGestureDone();
  if (!new_tab->FocusLocationBarByDefault())
    new_tab->Focus();
  if (ignore_cache)
    new_tab->GetController().ReloadIgnoringCache(true);
  else
    new_tab->GetController().Reload(true);
}

bool IsShowingWebContentsModalDialog(const Browser* browser) {
  WebContents* web_contents =
      browser->tab_strip_model()->GetActiveWebContents();
  if (!web_contents)
    return false;

  WebContentsModalDialogManager* web_contents_modal_dialog_manager =
      WebContentsModalDialogManager::FromWebContents(web_contents);
  return web_contents_modal_dialog_manager->IsDialogActive();
}

bool PrintPreviewShowing(const Browser* browser) {
#if defined(ENABLE_FULL_PRINTING)
  WebContents* contents = browser->tab_strip_model()->GetActiveWebContents();
  printing::PrintPreviewDialogController* controller =
      printing::PrintPreviewDialogController::GetInstance();
  return controller && (controller->GetPrintPreviewForContents(contents) ||
                        controller->is_creating_print_preview_dialog());
#else
  return false;
#endif
}

}  // namespace

bool IsCommandEnabled(Browser* browser, int command) {
  return browser->command_controller()->command_updater()->IsCommandEnabled(
      command);
}

bool SupportsCommand(Browser* browser, int command) {
  return browser->command_controller()->command_updater()->SupportsCommand(
      command);
}

bool ExecuteCommand(Browser* browser, int command) {
  return browser->command_controller()->command_updater()->ExecuteCommand(
      command);
}

bool ExecuteCommandWithDisposition(Browser* browser,
                                   int command,
                                   WindowOpenDisposition disposition) {
  return browser->command_controller()->command_updater()->
      ExecuteCommandWithDisposition(command, disposition);
}

void UpdateCommandEnabled(Browser* browser, int command, bool enabled) {
  browser->command_controller()->command_updater()->UpdateCommandEnabled(
      command, enabled);
}

void AddCommandObserver(Browser* browser,
                        int command,
                        CommandObserver* observer) {
  browser->command_controller()->command_updater()->AddCommandObserver(
      command, observer);
}

void RemoveCommandObserver(Browser* browser,
                           int command,
                           CommandObserver* observer) {
  browser->command_controller()->command_updater()->RemoveCommandObserver(
      command, observer);
}

int GetContentRestrictions(const Browser* browser) {
  int content_restrictions = 0;
  WebContents* current_tab = browser->tab_strip_model()->GetActiveWebContents();
  if (current_tab) {
    CoreTabHelper* core_tab_helper =
        CoreTabHelper::FromWebContents(current_tab);
    content_restrictions = core_tab_helper->content_restrictions();
    NavigationEntry* last_committed_entry =
        current_tab->GetController().GetLastCommittedEntry();
    if (!content::IsSavableURL(
            last_committed_entry ? last_committed_entry->GetURL() : GURL()) ||
        current_tab->ShowingInterstitialPage())
      content_restrictions |= CONTENT_RESTRICTION_SAVE;
    if (current_tab->ShowingInterstitialPage())
      content_restrictions |= CONTENT_RESTRICTION_PRINT;
  }
  return content_restrictions;
}

void NewEmptyWindow(Profile* profile, HostDesktopType desktop_type) {
  bool incognito = profile->IsOffTheRecord();
  PrefService* prefs = profile->GetPrefs();
  if (incognito) {
    if (IncognitoModePrefs::GetAvailability(prefs) ==
          IncognitoModePrefs::DISABLED) {
      incognito = false;
    }
  } else if (profile->IsGuestSession() ||
      (browser_defaults::kAlwaysOpenIncognitoWindow &&
      IncognitoModePrefs::ShouldLaunchIncognito(
          *CommandLine::ForCurrentProcess(), prefs))) {
    incognito = true;
  }

  if (incognito) {
    content::RecordAction(UserMetricsAction("NewIncognitoWindow"));
    OpenEmptyWindow(profile->GetOffTheRecordProfile(), desktop_type);
  } else {
    content::RecordAction(UserMetricsAction("NewWindow"));
    SessionService* session_service =
        SessionServiceFactory::GetForProfileForSessionRestore(
            profile->GetOriginalProfile());
    if (!session_service ||
        !session_service->RestoreIfNecessary(std::vector<GURL>())) {
      OpenEmptyWindow(profile->GetOriginalProfile(), desktop_type);
    }
  }
}

Browser* OpenEmptyWindow(Profile* profile, HostDesktopType desktop_type) {
  Browser* browser = new Browser(
      Browser::CreateParams(Browser::TYPE_TABBED, profile, desktop_type));
  AddTabAt(browser, GURL(), -1, true);
  browser->window()->Show();
  return browser;
}

void OpenWindowWithRestoredTabs(Profile* profile,
                                HostDesktopType host_desktop_type) {
  TabRestoreService* service = TabRestoreServiceFactory::GetForProfile(profile);
  if (service)
    service->RestoreMostRecentEntry(NULL, host_desktop_type);
}

void OpenURLOffTheRecord(Profile* profile,
                         const GURL& url,
                         chrome::HostDesktopType desktop_type) {
  ScopedTabbedBrowserDisplayer displayer(profile->GetOffTheRecordProfile(),
                                         desktop_type);
  AddSelectedTabWithURL(displayer.browser(), url,
      content::PAGE_TRANSITION_LINK);
}

bool CanGoBack(const Browser* browser) {
  return browser->tab_strip_model()->GetActiveWebContents()->
      GetController().CanGoBack();
}

void GoBack(Browser* browser, WindowOpenDisposition disposition) {
  content::RecordAction(UserMetricsAction("Back"));

  if (CanGoBack(browser)) {
    WebContents* current_tab =
        browser->tab_strip_model()->GetActiveWebContents();
    WebContents* new_tab = GetTabAndRevertIfNecessary(browser, disposition);
    // If we are on an interstitial page and clone the tab, it won't be copied
    // to the new tab, so we don't need to go back.
    if ((new_tab == current_tab) || !current_tab->ShowingInterstitialPage())
      new_tab->GetController().GoBack();
  }
}

bool CanGoForward(const Browser* browser) {
  return browser->tab_strip_model()->GetActiveWebContents()->
      GetController().CanGoForward();
}

void GoForward(Browser* browser, WindowOpenDisposition disposition) {
  content::RecordAction(UserMetricsAction("Forward"));
  if (CanGoForward(browser)) {
    GetTabAndRevertIfNecessary(browser, disposition)->
        GetController().GoForward();
  }
}

bool NavigateToIndexWithDisposition(Browser* browser,
                                    int index,
                                    WindowOpenDisposition disposition) {
  NavigationController* controller =
      &GetTabAndRevertIfNecessary(browser, disposition)->GetController();
  if (index < 0 || index >= controller->GetEntryCount())
    return false;
  controller->GoToIndex(index);
  return true;
}

void Reload(Browser* browser, WindowOpenDisposition disposition) {
  content::RecordAction(UserMetricsAction("Reload"));
  ReloadInternal(browser, disposition, false);
}

void ReloadIgnoringCache(Browser* browser, WindowOpenDisposition disposition) {
  content::RecordAction(UserMetricsAction("ReloadIgnoringCache"));
  ReloadInternal(browser, disposition, true);
}

bool CanReload(const Browser* browser) {
  return !browser->is_devtools();
}

void Home(Browser* browser, WindowOpenDisposition disposition) {
  content::RecordAction(UserMetricsAction("Home"));

  std::string extra_headers;
#if defined(ENABLE_RLZ) && !defined(OS_IOS)
  // If the home page is a Google home page, add the RLZ header to the request.
  PrefService* pref_service = browser->profile()->GetPrefs();
  if (pref_service) {
    if (google_util::IsGoogleHomePageUrl(
        GURL(pref_service->GetString(prefs::kHomePage)))) {
      extra_headers = RLZTracker::GetAccessPointHttpHeader(
          RLZTracker::ChromeHomePage());
    }
  }
#endif  // defined(ENABLE_RLZ) && !defined(OS_IOS)

  GURL url = browser->profile()->GetHomePage();

  // Streamlined hosted apps should return to their launch page when the home
  // button is pressed.
  if (browser->is_app()) {
    const extensions::Extension* extension =
        extensions::ExtensionRegistry::Get(browser->profile())
            ->GetExtensionById(
                web_app::GetExtensionIdFromApplicationName(browser->app_name()),
                extensions::ExtensionRegistry::EVERYTHING);
    if (!extension)
      return;

    url = extensions::AppLaunchInfo::GetLaunchWebURL(extension);
  }

  OpenURLParams params(
      url, Referrer(), disposition,
      content::PageTransitionFromInt(
          content::PAGE_TRANSITION_AUTO_BOOKMARK |
          content::PAGE_TRANSITION_HOME_PAGE),
      false);
  params.extra_headers = extra_headers;
  browser->OpenURL(params);
}

void OpenCurrentURL(Browser* browser) {
  content::RecordAction(UserMetricsAction("LoadURL"));
  LocationBar* location_bar = browser->window()->GetLocationBar();
  if (!location_bar)
    return;

  GURL url(location_bar->GetDestinationURL());

  content::PageTransition page_transition = location_bar->GetPageTransition();
  content::PageTransition page_transition_without_qualifier(
      PageTransitionStripQualifier(page_transition));
  WindowOpenDisposition open_disposition =
      location_bar->GetWindowOpenDisposition();
  // A PAGE_TRANSITION_TYPED means the user has typed a URL. We do not want to
  // open URLs with instant_controller since in some cases it disregards it
  // and performs a search instead. For example, when using CTRL-Enter, the
  // location_bar is aware of the URL but instant is not.
  // Instant should also not handle PAGE_TRANSITION_RELOAD because its knowledge
  // of the omnibox text may be stale if the user focuses in the omnibox and
  // presses enter without typing anything.
  if (page_transition_without_qualifier != content::PAGE_TRANSITION_TYPED &&
      page_transition_without_qualifier != content::PAGE_TRANSITION_RELOAD &&
      browser->instant_controller() &&
      browser->instant_controller()->OpenInstant(open_disposition, url))
    return;

  NavigateParams params(browser, url, page_transition);
  params.disposition = open_disposition;
  // Use ADD_INHERIT_OPENER so that all pages opened by the omnibox at least
  // inherit the opener. In some cases the tabstrip will determine the group
  // should be inherited, in which case the group is inherited instead of the
  // opener.
  params.tabstrip_add_types =
      TabStripModel::ADD_FORCE_INDEX | TabStripModel::ADD_INHERIT_OPENER;
  Navigate(&params);

  DCHECK(browser->profile()->GetExtensionService());
  const extensions::Extension* extension =
      extensions::ExtensionRegistry::Get(browser->profile())
          ->enabled_extensions().GetAppByURL(url);
  if (extension) {
    CoreAppLauncherHandler::RecordAppLaunchType(
        extension_misc::APP_LAUNCH_OMNIBOX_LOCATION,
        extension->GetType());
  }
}

void Stop(Browser* browser) {
  content::RecordAction(UserMetricsAction("Stop"));
  browser->tab_strip_model()->GetActiveWebContents()->Stop();
}

void NewWindow(Browser* browser) {
  NewEmptyWindow(browser->profile()->GetOriginalProfile(),
                 browser->host_desktop_type());
}

void NewIncognitoWindow(Browser* browser) {
  NewEmptyWindow(browser->profile()->GetOffTheRecordProfile(),
                 browser->host_desktop_type());
}

void CloseWindow(Browser* browser) {
  content::RecordAction(UserMetricsAction("CloseWindow"));
  browser->window()->Close();
}

void NewTab(Browser* browser) {
  content::RecordAction(UserMetricsAction("NewTab"));
  // TODO(asvitkine): This is invoked programmatically from several places.
  // Audit the code and change it so that the histogram only gets collected for
  // user-initiated commands.
  UMA_HISTOGRAM_ENUMERATION("Tab.NewTab", TabStripModel::NEW_TAB_COMMAND,
                            TabStripModel::NEW_TAB_ENUM_COUNT);

  if (browser->is_type_tabbed()) {
    AddTabAt(browser, GURL(), -1, true);
    browser->tab_strip_model()->GetActiveWebContents()->RestoreFocus();
  } else {
    ScopedTabbedBrowserDisplayer displayer(browser->profile(),
                                           browser->host_desktop_type());
    Browser* b = displayer.browser();
    AddTabAt(b, GURL(), -1, true);
    b->window()->Show();
    // The call to AddBlankTabAt above did not set the focus to the tab as its
    // window was not active, so we have to do it explicitly.
    // See http://crbug.com/6380.
    b->tab_strip_model()->GetActiveWebContents()->RestoreFocus();
  }
}

void CloseTab(Browser* browser) {
  content::RecordAction(UserMetricsAction("CloseTab_Accelerator"));
  browser->tab_strip_model()->CloseSelectedTabs();
}

void RestoreTab(Browser* browser) {
  content::RecordAction(UserMetricsAction("RestoreTab"));
  TabRestoreService* service =
      TabRestoreServiceFactory::GetForProfile(browser->profile());
  if (service)
    service->RestoreMostRecentEntry(browser->tab_restore_service_delegate(),
                                    browser->host_desktop_type());
}

TabStripModelDelegate::RestoreTabType GetRestoreTabType(
    const Browser* browser) {
  TabRestoreService* service =
      TabRestoreServiceFactory::GetForProfile(browser->profile());
  if (!service || service->entries().empty())
    return TabStripModelDelegate::RESTORE_NONE;
  if (service->entries().front()->type == TabRestoreService::WINDOW)
    return TabStripModelDelegate::RESTORE_WINDOW;
  return TabStripModelDelegate::RESTORE_TAB;
}

void SelectNextTab(Browser* browser) {
  content::RecordAction(UserMetricsAction("SelectNextTab"));
  browser->tab_strip_model()->SelectNextTab();
}

void SelectPreviousTab(Browser* browser) {
  content::RecordAction(UserMetricsAction("SelectPrevTab"));
  browser->tab_strip_model()->SelectPreviousTab();
}

void MoveTabNext(Browser* browser) {
  content::RecordAction(UserMetricsAction("MoveTabNext"));
  browser->tab_strip_model()->MoveTabNext();
}

void MoveTabPrevious(Browser* browser) {
  content::RecordAction(UserMetricsAction("MoveTabPrevious"));
  browser->tab_strip_model()->MoveTabPrevious();
}

void SelectNumberedTab(Browser* browser, int index) {
  if (index < browser->tab_strip_model()->count()) {
    content::RecordAction(UserMetricsAction("SelectNumberedTab"));
    browser->tab_strip_model()->ActivateTabAt(index, true);
  }
}

void SelectLastTab(Browser* browser) {
  content::RecordAction(UserMetricsAction("SelectLastTab"));
  browser->tab_strip_model()->SelectLastTab();
}

void DuplicateTab(Browser* browser) {
  content::RecordAction(UserMetricsAction("Duplicate"));
  DuplicateTabAt(browser, browser->tab_strip_model()->active_index());
}

bool CanDuplicateTab(const Browser* browser) {
  WebContents* contents = browser->tab_strip_model()->GetActiveWebContents();
  return contents && contents->GetController().GetLastCommittedEntry();
}

WebContents* DuplicateTabAt(Browser* browser, int index) {
  WebContents* contents = browser->tab_strip_model()->GetWebContentsAt(index);
  CHECK(contents);
  WebContents* contents_dupe = contents->Clone();

  bool pinned = false;
  if (browser->CanSupportWindowFeature(Browser::FEATURE_TABSTRIP)) {
    // If this is a tabbed browser, just create a duplicate tab inside the same
    // window next to the tab being duplicated.
    int index = browser->tab_strip_model()->GetIndexOfWebContents(contents);
    pinned = browser->tab_strip_model()->IsTabPinned(index);
    int add_types = TabStripModel::ADD_ACTIVE |
        TabStripModel::ADD_INHERIT_GROUP |
        (pinned ? TabStripModel::ADD_PINNED : 0);
    browser->tab_strip_model()->InsertWebContentsAt(
        index + 1, contents_dupe, add_types);
  } else {
    Browser* new_browser = NULL;
    if (browser->is_app() && !browser->is_type_popup()) {
      new_browser = new Browser(
          Browser::CreateParams::CreateForApp(browser->app_name(),
                                              browser->is_trusted_source(),
                                              gfx::Rect(),
                                              browser->profile(),
                                              browser->host_desktop_type()));
    } else {
      new_browser = new Browser(
          Browser::CreateParams(browser->type(), browser->profile(),
                                browser->host_desktop_type()));
    }
    // Preserve the size of the original window. The new window has already
    // been given an offset by the OS, so we shouldn't copy the old bounds.
    BrowserWindow* new_window = new_browser->window();
    new_window->SetBounds(gfx::Rect(new_window->GetRestoredBounds().origin(),
                          browser->window()->GetRestoredBounds().size()));

    // We need to show the browser now.  Otherwise ContainerWin assumes the
    // WebContents is invisible and won't size it.
    new_browser->window()->Show();

    // The page transition below is only for the purpose of inserting the tab.
    new_browser->tab_strip_model()->AddWebContents(
        contents_dupe, -1,
        content::PAGE_TRANSITION_LINK,
        TabStripModel::ADD_ACTIVE);
  }

  SessionService* session_service =
      SessionServiceFactory::GetForProfileIfExisting(browser->profile());
  if (session_service)
    session_service->TabRestored(contents_dupe, pinned);
  return contents_dupe;
}

bool CanDuplicateTabAt(Browser* browser, int index) {
  content::NavigationController& nc =
      browser->tab_strip_model()->GetWebContentsAt(index)->GetController();
  return nc.GetWebContents() && nc.GetLastCommittedEntry();
}

void ConvertPopupToTabbedBrowser(Browser* browser) {
  content::RecordAction(UserMetricsAction("ShowAsTab"));
  TabStripModel* tab_strip = browser->tab_strip_model();
  WebContents* contents =
      tab_strip->DetachWebContentsAt(tab_strip->active_index());
  Browser* b = new Browser(Browser::CreateParams(browser->profile(),
                                                 browser->host_desktop_type()));
  b->tab_strip_model()->AppendWebContents(contents, true);
  b->window()->Show();
}

void Exit() {
  content::RecordAction(UserMetricsAction("Exit"));
  chrome::AttemptUserExit();
}

void BookmarkCurrentPage(Browser* browser) {
  DCHECK(!chrome::ShouldRemoveBookmarkThisPageUI(browser->profile()));

  const extensions::Extension* extension = NULL;
  extensions::Command command;
  extensions::CommandService::ExtensionCommandType command_type;
  if (GetBookmarkOverrideCommand(browser->profile(),
                                 &extension,
                                 &command,
                                 &command_type)) {
    switch (command_type) {
      case extensions::CommandService::NAMED:
        browser->window()->ExecuteExtensionCommand(extension, command);
        return;

      case extensions::CommandService::BROWSER_ACTION:
        // BookmarkCurrentPage is called through a user gesture, so it is safe
        // to call ShowBrowserActionPopup.
        browser->window()->ShowBrowserActionPopup(extension);
        return;

      case extensions::CommandService::PAGE_ACTION:
        browser->window()->ShowPageActionPopup(extension);
        return;
    }
  }

  BookmarkCurrentPageInternal(browser);
}

bool CanBookmarkCurrentPage(const Browser* browser) {
  return CanBookmarkCurrentPageInternal(browser, true);
}

void BookmarkAllTabs(Browser* browser) {
  chrome::ShowBookmarkAllTabsDialog(browser);
}

bool CanBookmarkAllTabs(const Browser* browser) {
  return browser->tab_strip_model()->count() > 1 &&
             !chrome::ShouldRemoveBookmarkOpenPagesUI(browser->profile()) &&
             CanBookmarkCurrentPageInternal(browser, false);
}

void Translate(Browser* browser) {
  if (!browser->window()->IsActive())
    return;

  WebContents* web_contents =
      browser->tab_strip_model()->GetActiveWebContents();
  ChromeTranslateClient* chrome_translate_client =
      ChromeTranslateClient::FromWebContents(web_contents);

  translate::TranslateStep step = translate::TRANSLATE_STEP_BEFORE_TRANSLATE;
  if (chrome_translate_client) {
    if (chrome_translate_client->GetLanguageState().translation_pending())
      step = translate::TRANSLATE_STEP_TRANSLATING;
    else if (chrome_translate_client->GetLanguageState().IsPageTranslated())
      step = translate::TRANSLATE_STEP_AFTER_TRANSLATE;
  }
  browser->window()->ShowTranslateBubble(
      web_contents, step, TranslateErrors::NONE);
}

void ManagePasswordsForPage(Browser* browser) {
// TODO(mkwst): Implement this feature on Mac: http://crbug.com/261628
#if !defined(OS_MACOSX)
  if (!browser->window()->IsActive())
    return;

  WebContents* web_contents =
      browser->tab_strip_model()->GetActiveWebContents();
  chrome::ShowManagePasswordsBubble(web_contents);
#endif
}

void TogglePagePinnedToStartScreen(Browser* browser) {
#if defined(OS_WIN)
  MetroPinTabHelper::FromWebContents(
      browser->tab_strip_model()->GetActiveWebContents())->
          TogglePinnedToStartScreen();
#endif
}

void SavePage(Browser* browser) {
  content::RecordAction(UserMetricsAction("SavePage"));
  WebContents* current_tab = browser->tab_strip_model()->GetActiveWebContents();
  if (current_tab && current_tab->GetContentsMimeType() == "application/pdf")
    content::RecordAction(UserMetricsAction("PDF.SavePage"));
  current_tab->OnSavePage();
}

bool CanSavePage(const Browser* browser) {
  // LocalState can be NULL in tests.
  if (g_browser_process->local_state() &&
      !g_browser_process->local_state()->GetBoolean(
      prefs::kAllowFileSelectionDialogs)) {
    return false;
  }
  return !browser->is_devtools() &&
      !(GetContentRestrictions(browser) & CONTENT_RESTRICTION_SAVE);
}

void ShowFindBar(Browser* browser) {
  browser->GetFindBarController()->Show();
}

void ShowWebsiteSettings(Browser* browser,
                         content::WebContents* web_contents,
                         const GURL& url,
                         const SSLStatus& ssl) {
  browser->window()->ShowWebsiteSettings(
      Profile::FromBrowserContext(web_contents->GetBrowserContext()),
      web_contents, url, ssl);
}


void Print(Browser* browser) {
#if defined(ENABLE_PRINTING)
  WebContents* contents = browser->tab_strip_model()->GetActiveWebContents();
#if defined(ENABLE_FULL_PRINTING)
  printing::PrintViewManager* print_view_manager =
      printing::PrintViewManager::FromWebContents(contents);
  if (browser->profile()->GetPrefs()->GetBoolean(prefs::kPrintPreviewDisabled))
    print_view_manager->PrintNow();
  else
    print_view_manager->PrintPreviewNow(false);
#else
  printing::PrintViewManagerBasic* print_view_manager =
      printing::PrintViewManagerBasic::FromWebContents(contents);
  print_view_manager->PrintNow();
#endif  // defined(ENABLE_FULL_PRINTING)
#endif  // defined(ENABLE_PRINTING)
}

bool CanPrint(const Browser* browser) {
  // Do not print when printing is disabled via pref or policy.
  // Do not print when a constrained window is showing. It's confusing.
  return browser->profile()->GetPrefs()->GetBoolean(prefs::kPrintingEnabled) &&
      !(IsShowingWebContentsModalDialog(browser) ||
      GetContentRestrictions(browser) & CONTENT_RESTRICTION_PRINT);
}

void AdvancedPrint(Browser* browser) {
#if defined(ENABLE_FULL_PRINTING)
  printing::PrintViewManager* print_view_manager =
      printing::PrintViewManager::FromWebContents(
          browser->tab_strip_model()->GetActiveWebContents());
  print_view_manager->AdvancedPrintNow();
#endif
}

bool CanAdvancedPrint(const Browser* browser) {
  // If printing is not disabled via pref or policy, it is always possible to
  // advanced print when the print preview is visible.  The exception to this
  // is under Win8 ash, since showing the advanced print dialog will open it
  // modally on the Desktop and hang the browser.  We can remove this check
  // once we integrate with the system print charm.
#if defined(OS_WIN)
  if (chrome::GetActiveDesktop() == chrome::HOST_DESKTOP_TYPE_ASH)
    return false;
#endif

  return browser->profile()->GetPrefs()->GetBoolean(prefs::kPrintingEnabled) &&
      (PrintPreviewShowing(browser) || CanPrint(browser));
}

void PrintToDestination(Browser* browser) {
#if defined(ENABLE_FULL_PRINTING)
  printing::PrintViewManager* print_view_manager =
      printing::PrintViewManager::FromWebContents(
          browser->tab_strip_model()->GetActiveWebContents());
  print_view_manager->PrintToDestination();
#endif
}

void EmailPageLocation(Browser* browser) {
  content::RecordAction(UserMetricsAction("EmailPageLocation"));
  WebContents* wc = browser->tab_strip_model()->GetActiveWebContents();
  DCHECK(wc);

  std::string title = net::EscapeQueryParamValue(
      base::UTF16ToUTF8(wc->GetTitle()), false);
  std::string page_url = net::EscapeQueryParamValue(wc->GetURL().spec(), false);
  std::string mailto = std::string("mailto:?subject=Fwd:%20") +
      title + "&body=%0A%0A" + page_url;
  platform_util::OpenExternal(browser->profile(), GURL(mailto));
}

bool CanEmailPageLocation(const Browser* browser) {
  return browser->toolbar_model()->ShouldDisplayURL() &&
      browser->tab_strip_model()->GetActiveWebContents()->GetURL().is_valid();
}

void Cut(Browser* browser) {
  content::RecordAction(UserMetricsAction("Cut"));
  browser->window()->Cut();
}

void Copy(Browser* browser) {
  content::RecordAction(UserMetricsAction("Copy"));
  browser->window()->Copy();
}

void Paste(Browser* browser) {
  content::RecordAction(UserMetricsAction("Paste"));
  browser->window()->Paste();
}

void Find(Browser* browser) {
  content::RecordAction(UserMetricsAction("Find"));
  FindInPage(browser, false, false);
}

void FindNext(Browser* browser) {
  content::RecordAction(UserMetricsAction("FindNext"));
  FindInPage(browser, true, true);
}

void FindPrevious(Browser* browser) {
  content::RecordAction(UserMetricsAction("FindPrevious"));
  FindInPage(browser, true, false);
}

void FindInPage(Browser* browser, bool find_next, bool forward_direction) {
  ShowFindBar(browser);
  if (find_next) {
    base::string16 find_text;
    FindTabHelper* find_helper = FindTabHelper::FromWebContents(
        browser->tab_strip_model()->GetActiveWebContents());
#if defined(OS_MACOSX)
    // We always want to search for the current contents of the find bar on
    // OS X. For regular profile it's always the current find pboard. For
    // Incognito window it's the newest value of the find pboard content and
    // user-typed text.
    FindBar* find_bar = browser->GetFindBarController()->find_bar();
    find_text = find_bar->GetFindText();
#endif
    find_helper->StartFinding(find_text, forward_direction, false);
  }
}

void Zoom(Browser* browser, content::PageZoom zoom) {
  chrome_page_zoom::Zoom(browser->tab_strip_model()->GetActiveWebContents(),
                         zoom);
}

void FocusToolbar(Browser* browser) {
  content::RecordAction(UserMetricsAction("FocusToolbar"));
  browser->window()->FocusToolbar();
}

void FocusLocationBar(Browser* browser) {
  content::RecordAction(UserMetricsAction("FocusLocation"));
  browser->window()->SetFocusToLocationBar(true);
}

void FocusSearch(Browser* browser) {
  // TODO(beng): replace this with FocusLocationBar
  content::RecordAction(UserMetricsAction("FocusSearch"));
  browser->window()->GetLocationBar()->FocusSearch();
}

void FocusAppMenu(Browser* browser) {
  content::RecordAction(UserMetricsAction("FocusAppMenu"));
  browser->window()->FocusAppMenu();
}

void FocusBookmarksToolbar(Browser* browser) {
  content::RecordAction(UserMetricsAction("FocusBookmarksToolbar"));
  browser->window()->FocusBookmarksToolbar();
}

void FocusInfobars(Browser* browser) {
  content::RecordAction(UserMetricsAction("FocusInfobars"));
  browser->window()->FocusInfobars();
}

void FocusNextPane(Browser* browser) {
  content::RecordAction(UserMetricsAction("FocusNextPane"));
  browser->window()->RotatePaneFocus(true);
}

void FocusPreviousPane(Browser* browser) {
  content::RecordAction(UserMetricsAction("FocusPreviousPane"));
  browser->window()->RotatePaneFocus(false);
}

void ToggleDevToolsWindow(Browser* browser, DevToolsToggleAction action) {
  if (action.type() == DevToolsToggleAction::kShowConsole)
    content::RecordAction(UserMetricsAction("DevTools_ToggleConsole"));
  else
    content::RecordAction(UserMetricsAction("DevTools_ToggleWindow"));
  DevToolsWindow::ToggleDevToolsWindow(browser, action);
}

bool CanOpenTaskManager() {
#if defined(ENABLE_TASK_MANAGER)
  return true;
#else
  return false;
#endif
}

void OpenTaskManager(Browser* browser) {
#if defined(ENABLE_TASK_MANAGER)
  content::RecordAction(UserMetricsAction("TaskManager"));
  chrome::ShowTaskManager(browser);
#else
  NOTREACHED();
#endif
}

void OpenFeedbackDialog(Browser* browser) {
  content::RecordAction(UserMetricsAction("Feedback"));
  chrome::ShowFeedbackPage(browser, std::string(), std::string());
}

void ToggleBookmarkBar(Browser* browser) {
  content::RecordAction(UserMetricsAction("ShowBookmarksBar"));
  ToggleBookmarkBarWhenVisible(browser->profile());
}

void ShowAppMenu(Browser* browser) {
  // We record the user metric for this event in WrenchMenu::RunMenu.
  browser->window()->ShowAppMenu();
}

void ShowAvatarMenu(Browser* browser) {
  browser->window()->ShowAvatarBubbleFromAvatarButton(
      BrowserWindow::AVATAR_BUBBLE_MODE_DEFAULT,
      signin::ManageAccountsParams());
}

void OpenUpdateChromeDialog(Browser* browser) {
  if (UpgradeDetector::GetInstance()->is_outdated_install()) {
    content::NotificationService::current()->Notify(
        chrome::NOTIFICATION_OUTDATED_INSTALL,
        content::NotificationService::AllSources(),
        content::NotificationService::NoDetails());
  } else if (UpgradeDetector::GetInstance()->is_outdated_install_no_au()) {
    content::NotificationService::current()->Notify(
        chrome::NOTIFICATION_OUTDATED_INSTALL_NO_AU,
        content::NotificationService::AllSources(),
        content::NotificationService::NoDetails());
  } else {
    content::RecordAction(UserMetricsAction("UpdateChrome"));
    browser->window()->ShowUpdateChromeDialog();
  }
}

void ToggleSpeechInput(Browser* browser) {
  SearchTabHelper* search_tab_helper =
      SearchTabHelper::FromWebContents(
          browser->tab_strip_model()->GetActiveWebContents());
  // |search_tab_helper| can be null in unit tests.
  if (search_tab_helper)
    search_tab_helper->ToggleVoiceSearch();
}

void DistillCurrentPage(Browser* browser) {
  DistillCurrentPageAndView(browser->tab_strip_model()->GetActiveWebContents());
}

bool CanRequestTabletSite(WebContents* current_tab) {
  return current_tab &&
      current_tab->GetController().GetLastCommittedEntry() != NULL;
}

bool IsRequestingTabletSite(Browser* browser) {
  WebContents* current_tab = browser->tab_strip_model()->GetActiveWebContents();
  if (!current_tab)
    return false;
  content::NavigationEntry* entry =
      current_tab->GetController().GetLastCommittedEntry();
  if (!entry)
    return false;
  return entry->GetIsOverridingUserAgent();
}

void ToggleRequestTabletSite(Browser* browser) {
  WebContents* current_tab = browser->tab_strip_model()->GetActiveWebContents();
  if (!current_tab)
    return;
  NavigationController& controller = current_tab->GetController();
  NavigationEntry* entry = controller.GetLastCommittedEntry();
  if (!entry)
    return;
  if (entry->GetIsOverridingUserAgent()) {
    entry->SetIsOverridingUserAgent(false);
  } else {
    entry->SetIsOverridingUserAgent(true);
    chrome::VersionInfo version_info;
    std::string product;
    if (version_info.is_valid())
      product = version_info.ProductNameAndVersionForUserAgent();
    current_tab->SetUserAgentOverride(content::BuildUserAgentFromOSAndProduct(
        kOsOverrideForTabletSite, product));
  }
  controller.ReloadOriginalRequestURL(true);
}

void ToggleFullscreenMode(Browser* browser) {
  DCHECK(browser);
  browser->fullscreen_controller()->ToggleBrowserFullscreenMode();
}

void ClearCache(Browser* browser) {
  BrowsingDataRemover* remover =
      BrowsingDataRemover::CreateForUnboundedRange(browser->profile());
  remover->Remove(BrowsingDataRemover::REMOVE_CACHE,
                  BrowsingDataHelper::UNPROTECTED_WEB);
  // BrowsingDataRemover takes care of deleting itself when done.
}

bool IsDebuggerAttachedToCurrentTab(Browser* browser) {
  WebContents* contents = browser->tab_strip_model()->GetActiveWebContents();
  return contents ?
      content::DevToolsAgentHost::IsDebuggerAttached(contents) : false;
}

void ViewSource(Browser* browser, WebContents* contents) {
  DCHECK(contents);

  // Use the last committed entry, since the pending entry hasn't loaded yet and
  // won't be copied into the cloned tab.
  NavigationEntry* entry = contents->GetController().GetLastCommittedEntry();
  if (!entry)
    return;

  ViewSource(browser, contents, entry->GetURL(), entry->GetPageState());
}

void ViewSource(Browser* browser,
                WebContents* contents,
                const GURL& url,
                const content::PageState& page_state) {
  content::RecordAction(UserMetricsAction("ViewSource"));
  DCHECK(contents);

  WebContents* view_source_contents = contents->Clone();
  DCHECK(view_source_contents->GetController().CanPruneAllButLastCommitted());
  view_source_contents->GetController().PruneAllButLastCommitted();
  NavigationEntry* last_committed_entry =
      view_source_contents->GetController().GetLastCommittedEntry();
  if (!last_committed_entry)
    return;

  GURL view_source_url =
      GURL(content::kViewSourceScheme + std::string(":") + url.spec());
  last_committed_entry->SetVirtualURL(view_source_url);

  // Do not restore scroller position.
  last_committed_entry->SetPageState(page_state.RemoveScrollOffset());

  // Do not restore title, derive it from the url.
  last_committed_entry->SetTitle(base::string16());

  // Now show view-source entry.
  if (browser->CanSupportWindowFeature(Browser::FEATURE_TABSTRIP)) {
    // If this is a tabbed browser, just create a duplicate tab inside the same
    // window next to the tab being duplicated.
    int index = browser->tab_strip_model()->GetIndexOfWebContents(contents);
    int add_types = TabStripModel::ADD_ACTIVE |
        TabStripModel::ADD_INHERIT_GROUP;
    browser->tab_strip_model()->InsertWebContentsAt(
        index + 1,
        view_source_contents,
        add_types);
  } else {
    Browser* b = new Browser(
        Browser::CreateParams(Browser::TYPE_TABBED, browser->profile(),
                              browser->host_desktop_type()));

    // Preserve the size of the original window. The new window has already
    // been given an offset by the OS, so we shouldn't copy the old bounds.
    BrowserWindow* new_window = b->window();
    new_window->SetBounds(gfx::Rect(new_window->GetRestoredBounds().origin(),
                          browser->window()->GetRestoredBounds().size()));

    // We need to show the browser now. Otherwise ContainerWin assumes the
    // WebContents is invisible and won't size it.
    b->window()->Show();

    // The page transition below is only for the purpose of inserting the tab.
    b->tab_strip_model()->AddWebContents(view_source_contents, -1,
                                         content::PAGE_TRANSITION_LINK,
                                         TabStripModel::ADD_ACTIVE);
  }

  SessionService* session_service =
      SessionServiceFactory::GetForProfileIfExisting(browser->profile());
  if (session_service)
    session_service->TabRestored(view_source_contents, false);
}

void ViewSelectedSource(Browser* browser) {
  ViewSource(browser, browser->tab_strip_model()->GetActiveWebContents());
}

bool CanViewSource(const Browser* browser) {
  return !browser->is_devtools() &&
      browser->tab_strip_model()->GetActiveWebContents()->GetController().
          CanViewSource();
}

void CreateApplicationShortcuts(Browser* browser) {
  content::RecordAction(UserMetricsAction("CreateShortcut"));
  extensions::TabHelper::FromWebContents(
      browser->tab_strip_model()->GetActiveWebContents())->
          CreateApplicationShortcuts();
}

void CreateBookmarkAppFromCurrentWebContents(Browser* browser) {
  content::RecordAction(UserMetricsAction("CreateHostedApp"));
  extensions::TabHelper::FromWebContents(
      browser->tab_strip_model()->GetActiveWebContents())->
          CreateHostedAppFromWebContents();
}

bool CanCreateApplicationShortcuts(const Browser* browser) {
  return extensions::TabHelper::FromWebContents(
      browser->tab_strip_model()->GetActiveWebContents())->
          CanCreateApplicationShortcuts();
}

bool CanCreateBookmarkApp(const Browser* browser) {
  return extensions::TabHelper::FromWebContents(
             browser->tab_strip_model()->GetActiveWebContents())
      ->CanCreateBookmarkApp();
}

void ConvertTabToAppWindow(Browser* browser,
                           content::WebContents* contents) {
  const GURL& url = contents->GetController().GetLastCommittedEntry()->GetURL();
  std::string app_name = web_app::GenerateApplicationNameFromURL(url);

  int index = browser->tab_strip_model()->GetIndexOfWebContents(contents);
  if (index >= 0)
    browser->tab_strip_model()->DetachWebContentsAt(index);

  Browser* app_browser = new Browser(
      Browser::CreateParams::CreateForApp(app_name,
                                          true /* trusted_source */,
                                          gfx::Rect(),
                                          browser->profile(),
                                          browser->host_desktop_type()));
  app_browser->tab_strip_model()->AppendWebContents(contents, true);

  contents->GetMutableRendererPrefs()->can_accept_load_drops = false;
  contents->GetRenderViewHost()->SyncRendererPrefs();
  app_browser->window()->Show();
}

}  // namespace chrome
