Home | History | Annotate | Download | only in ui
      1 // Copyright (c) 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_command_controller.h"
      6 
      7 #include "base/prefs/pref_service.h"
      8 #include "chrome/app/chrome_command_ids.h"
      9 #include "chrome/browser/browser_process.h"
     10 #include "chrome/browser/chrome_notification_types.h"
     11 #include "chrome/browser/defaults.h"
     12 #include "chrome/browser/extensions/extension_service.h"
     13 #include "chrome/browser/prefs/incognito_mode_prefs.h"
     14 #include "chrome/browser/profiles/avatar_menu_model.h"
     15 #include "chrome/browser/profiles/profile.h"
     16 #include "chrome/browser/profiles/profile_manager.h"
     17 #include "chrome/browser/sessions/tab_restore_service.h"
     18 #include "chrome/browser/sessions/tab_restore_service_factory.h"
     19 #include "chrome/browser/shell_integration.h"
     20 #include "chrome/browser/signin/signin_promo.h"
     21 #include "chrome/browser/sync/profile_sync_service.h"
     22 #include "chrome/browser/sync/profile_sync_service_factory.h"
     23 #include "chrome/browser/ui/bookmarks/bookmark_tab_helper.h"
     24 #include "chrome/browser/ui/browser.h"
     25 #include "chrome/browser/ui/browser_commands.h"
     26 #include "chrome/browser/ui/browser_window.h"
     27 #include "chrome/browser/ui/chrome_pages.h"
     28 #include "chrome/browser/ui/tabs/tab_strip_model.h"
     29 #include "chrome/browser/ui/tabs/tab_strip_model_utils.h"
     30 #include "chrome/common/content_restriction.h"
     31 #include "chrome/common/pref_names.h"
     32 #include "chrome/common/profiling.h"
     33 #include "content/public/browser/native_web_keyboard_event.h"
     34 #include "content/public/browser/navigation_controller.h"
     35 #include "content/public/browser/navigation_entry.h"
     36 #include "content/public/browser/user_metrics.h"
     37 #include "content/public/browser/web_contents.h"
     38 #include "content/public/browser/web_contents_observer.h"
     39 #include "content/public/common/url_constants.h"
     40 #include "ui/base/keycodes/keyboard_codes.h"
     41 
     42 #if defined(OS_MACOSX)
     43 #include "chrome/browser/ui/browser_commands_mac.h"
     44 #endif
     45 
     46 #if defined(OS_WIN)
     47 #include "base/win/metro.h"
     48 #include "base/win/windows_version.h"
     49 #include "chrome/browser/ui/extensions/apps_metro_handler_win.h"
     50 #endif
     51 
     52 #if defined(USE_ASH)
     53 #include "chrome/browser/ui/ash/ash_util.h"
     54 #endif
     55 
     56 using content::NavigationEntry;
     57 using content::NavigationController;
     58 using content::WebContents;
     59 
     60 namespace {
     61 
     62 // Returns |true| if entry has an internal chrome:// URL, |false| otherwise.
     63 bool HasInternalURL(const NavigationEntry* entry) {
     64   if (!entry)
     65     return false;
     66 
     67   // Check the |virtual_url()| first. This catches regular chrome:// URLs
     68   // including URLs that were rewritten (such as chrome://bookmarks).
     69   if (entry->GetVirtualURL().SchemeIs(chrome::kChromeUIScheme))
     70     return true;
     71 
     72   // If the |virtual_url()| isn't a chrome:// URL, check if it's actually
     73   // view-source: of a chrome:// URL.
     74   if (entry->GetVirtualURL().SchemeIs(content::kViewSourceScheme))
     75     return entry->GetURL().SchemeIs(chrome::kChromeUIScheme);
     76 
     77   return false;
     78 }
     79 
     80 #if defined(OS_WIN)
     81 // Windows 8 specific helper class to manage DefaultBrowserWorker. It does the
     82 // following asynchronous actions in order:
     83 // 1- Check that chrome is the default browser
     84 // 2- If we are the default, restart chrome in metro and exit
     85 // 3- If not the default browser show the 'select default browser' system dialog
     86 // 4- When dialog dismisses check again who got made the default
     87 // 5- If we are the default then restart chrome in metro and exit
     88 // 6- If we are not the default exit.
     89 //
     90 // Note: this class deletes itself.
     91 class SwitchToMetroUIHandler
     92     : public ShellIntegration::DefaultWebClientObserver {
     93  public:
     94   SwitchToMetroUIHandler()
     95       : default_browser_worker_(
     96             new ShellIntegration::DefaultBrowserWorker(this)),
     97         first_check_(true) {
     98     default_browser_worker_->StartCheckIsDefault();
     99   }
    100 
    101   virtual ~SwitchToMetroUIHandler() {
    102     default_browser_worker_->ObserverDestroyed();
    103   }
    104 
    105  private:
    106   virtual void SetDefaultWebClientUIState(
    107       ShellIntegration::DefaultWebClientUIState state) OVERRIDE {
    108     switch (state) {
    109       case ShellIntegration::STATE_PROCESSING:
    110         return;
    111       case ShellIntegration::STATE_UNKNOWN :
    112         break;
    113       case ShellIntegration::STATE_IS_DEFAULT:
    114         chrome::AttemptRestartWithModeSwitch();
    115         break;
    116       case ShellIntegration::STATE_NOT_DEFAULT:
    117         if (first_check_) {
    118           default_browser_worker_->StartSetAsDefault();
    119           return;
    120         }
    121         break;
    122       default:
    123         NOTREACHED();
    124     }
    125     delete this;
    126   }
    127 
    128   virtual void OnSetAsDefaultConcluded(bool success)  OVERRIDE {
    129     if (!success) {
    130       delete this;
    131       return;
    132     }
    133     first_check_ = false;
    134     default_browser_worker_->StartCheckIsDefault();
    135   }
    136 
    137   virtual bool IsInteractiveSetDefaultPermitted() OVERRIDE {
    138     return true;
    139   }
    140 
    141   scoped_refptr<ShellIntegration::DefaultBrowserWorker> default_browser_worker_;
    142   bool first_check_;
    143 
    144   DISALLOW_COPY_AND_ASSIGN(SwitchToMetroUIHandler);
    145 };
    146 #endif  // defined(OS_WIN)
    147 
    148 }  // namespace
    149 
    150 namespace chrome {
    151 
    152 ///////////////////////////////////////////////////////////////////////////////
    153 // BrowserCommandController, public:
    154 
    155 BrowserCommandController::BrowserCommandController(
    156     Browser* browser,
    157     ProfileManager* profile_manager)
    158     : browser_(browser),
    159       profile_manager_(profile_manager),
    160       command_updater_(this),
    161       block_command_execution_(false),
    162       last_blocked_command_id_(-1),
    163       last_blocked_command_disposition_(CURRENT_TAB) {
    164   if (profile_manager_)
    165     profile_manager_->GetProfileInfoCache().AddObserver(this);
    166   browser_->tab_strip_model()->AddObserver(this);
    167   PrefService* local_state = g_browser_process->local_state();
    168   if (local_state) {
    169     local_pref_registrar_.Init(local_state);
    170     local_pref_registrar_.Add(
    171         prefs::kAllowFileSelectionDialogs,
    172         base::Bind(
    173             &BrowserCommandController::UpdateCommandsForFileSelectionDialogs,
    174             base::Unretained(this)));
    175   }
    176 
    177   profile_pref_registrar_.Init(profile()->GetPrefs());
    178   profile_pref_registrar_.Add(
    179       prefs::kDevToolsDisabled,
    180       base::Bind(&BrowserCommandController::UpdateCommandsForDevTools,
    181                  base::Unretained(this)));
    182   profile_pref_registrar_.Add(
    183       prefs::kEditBookmarksEnabled,
    184       base::Bind(&BrowserCommandController::UpdateCommandsForBookmarkEditing,
    185                  base::Unretained(this)));
    186   profile_pref_registrar_.Add(
    187       prefs::kShowBookmarkBar,
    188       base::Bind(&BrowserCommandController::UpdateCommandsForBookmarkBar,
    189                  base::Unretained(this)));
    190   profile_pref_registrar_.Add(
    191       prefs::kIncognitoModeAvailability,
    192       base::Bind(
    193           &BrowserCommandController::UpdateCommandsForIncognitoAvailability,
    194           base::Unretained(this)));
    195   profile_pref_registrar_.Add(
    196       prefs::kPrintingEnabled,
    197       base::Bind(&BrowserCommandController::UpdatePrintingState,
    198                  base::Unretained(this)));
    199   pref_signin_allowed_.Init(
    200       prefs::kSigninAllowed,
    201       profile()->GetOriginalProfile()->GetPrefs(),
    202       base::Bind(&BrowserCommandController::OnSigninAllowedPrefChange,
    203                  base::Unretained(this)));
    204 
    205   InitCommandState();
    206 
    207   TabRestoreService* tab_restore_service =
    208       TabRestoreServiceFactory::GetForProfile(profile());
    209   if (tab_restore_service) {
    210     tab_restore_service->AddObserver(this);
    211     TabRestoreServiceChanged(tab_restore_service);
    212   }
    213 }
    214 
    215 BrowserCommandController::~BrowserCommandController() {
    216   // TabRestoreService may have been shutdown by the time we get here. Don't
    217   // trigger creating it.
    218   TabRestoreService* tab_restore_service =
    219       TabRestoreServiceFactory::GetForProfileIfExisting(profile());
    220   if (tab_restore_service)
    221     tab_restore_service->RemoveObserver(this);
    222   profile_pref_registrar_.RemoveAll();
    223   local_pref_registrar_.RemoveAll();
    224   browser_->tab_strip_model()->RemoveObserver(this);
    225   if (profile_manager_)
    226     profile_manager_->GetProfileInfoCache().RemoveObserver(this);
    227 }
    228 
    229 bool BrowserCommandController::IsReservedCommandOrKey(
    230     int command_id,
    231     const content::NativeWebKeyboardEvent& event) {
    232   // In Apps mode, no keys are reserved.
    233   if (browser_->is_app())
    234     return false;
    235 
    236 #if defined(OS_CHROMEOS)
    237   // On Chrome OS, the top row of keys are mapped to F1-F10.  We don't want web
    238   // pages to be able to change the behavior of these keys.  Ash handles F4 and
    239   // up; this leaves us needing to reserve F1-F3 here.
    240   ui::KeyboardCode key_code =
    241     static_cast<ui::KeyboardCode>(event.windowsKeyCode);
    242   if ((key_code == ui::VKEY_F1 && command_id == IDC_BACK) ||
    243       (key_code == ui::VKEY_F2 && command_id == IDC_FORWARD) ||
    244       (key_code == ui::VKEY_F3 && command_id == IDC_RELOAD)) {
    245     return true;
    246   }
    247 #endif
    248 
    249   if (window()->IsFullscreen() && command_id == IDC_FULLSCREEN)
    250     return true;
    251   return command_id == IDC_CLOSE_TAB ||
    252          command_id == IDC_CLOSE_WINDOW ||
    253          command_id == IDC_NEW_INCOGNITO_WINDOW ||
    254          command_id == IDC_NEW_TAB ||
    255          command_id == IDC_NEW_WINDOW ||
    256          command_id == IDC_RESTORE_TAB ||
    257          command_id == IDC_SELECT_NEXT_TAB ||
    258          command_id == IDC_SELECT_PREVIOUS_TAB ||
    259          command_id == IDC_TABPOSE ||
    260          command_id == IDC_EXIT;
    261 }
    262 
    263 void BrowserCommandController::SetBlockCommandExecution(bool block) {
    264   block_command_execution_ = block;
    265   if (block) {
    266     last_blocked_command_id_ = -1;
    267     last_blocked_command_disposition_ = CURRENT_TAB;
    268   }
    269 }
    270 
    271 int BrowserCommandController::GetLastBlockedCommand(
    272     WindowOpenDisposition* disposition) {
    273   if (disposition)
    274     *disposition = last_blocked_command_disposition_;
    275   return last_blocked_command_id_;
    276 }
    277 
    278 void BrowserCommandController::TabStateChanged() {
    279   UpdateCommandsForTabState();
    280 }
    281 
    282 void BrowserCommandController::ContentRestrictionsChanged() {
    283   UpdateCommandsForContentRestrictionState();
    284 }
    285 
    286 void BrowserCommandController::FullscreenStateChanged() {
    287   FullScreenMode fullscreen_mode = FULLSCREEN_DISABLED;
    288   if (window()->IsFullscreen()) {
    289 #if defined(OS_WIN)
    290     fullscreen_mode = window()->IsInMetroSnapMode() ? FULLSCREEN_METRO_SNAP :
    291                                                       FULLSCREEN_NORMAL;
    292 #else
    293     fullscreen_mode = FULLSCREEN_NORMAL;
    294 #endif
    295   }
    296   UpdateCommandsForFullscreenMode(fullscreen_mode);
    297 }
    298 
    299 void BrowserCommandController::PrintingStateChanged() {
    300   UpdatePrintingState();
    301 }
    302 
    303 void BrowserCommandController::LoadingStateChanged(bool is_loading,
    304                                                    bool force) {
    305   UpdateReloadStopState(is_loading, force);
    306 }
    307 
    308 ////////////////////////////////////////////////////////////////////////////////
    309 // BrowserCommandController, CommandUpdaterDelegate implementation:
    310 
    311 void BrowserCommandController::ExecuteCommandWithDisposition(
    312     int id,
    313     WindowOpenDisposition disposition) {
    314   // No commands are enabled if there is not yet any selected tab.
    315   // TODO(pkasting): It seems like we should not need this, because either
    316   // most/all commands should not have been enabled yet anyway or the ones that
    317   // are enabled should be global, or safe themselves against having no selected
    318   // tab.  However, Ben says he tried removing this before and got lots of
    319   // crashes, e.g. from Windows sending WM_COMMANDs at random times during
    320   // window construction.  This probably could use closer examination someday.
    321   if (browser_->tab_strip_model()->active_index() == TabStripModel::kNoTab)
    322     return;
    323 
    324   DCHECK(command_updater_.IsCommandEnabled(id)) << "Invalid/disabled command "
    325                                                 << id;
    326 
    327   // If command execution is blocked then just record the command and return.
    328   if (block_command_execution_) {
    329     // We actually only allow no more than one blocked command, otherwise some
    330     // commands maybe lost.
    331     DCHECK_EQ(last_blocked_command_id_, -1);
    332     last_blocked_command_id_ = id;
    333     last_blocked_command_disposition_ = disposition;
    334     return;
    335   }
    336 
    337   // The order of commands in this switch statement must match the function
    338   // declaration order in browser.h!
    339   switch (id) {
    340     // Navigation commands
    341     case IDC_BACK:
    342       GoBack(browser_, disposition);
    343       break;
    344     case IDC_FORWARD:
    345       GoForward(browser_, disposition);
    346       break;
    347     case IDC_RELOAD:
    348       Reload(browser_, disposition);
    349       break;
    350     case IDC_RELOAD_CLEARING_CACHE:
    351       ClearCache(browser_);
    352       // FALL THROUGH
    353     case IDC_RELOAD_IGNORING_CACHE:
    354       ReloadIgnoringCache(browser_, disposition);
    355       break;
    356     case IDC_HOME:
    357       Home(browser_, disposition);
    358       break;
    359     case IDC_OPEN_CURRENT_URL:
    360       OpenCurrentURL(browser_);
    361       break;
    362     case IDC_STOP:
    363       Stop(browser_);
    364       break;
    365 
    366      // Window management commands
    367     case IDC_NEW_WINDOW:
    368       NewWindow(browser_);
    369       break;
    370     case IDC_NEW_INCOGNITO_WINDOW:
    371       NewIncognitoWindow(browser_);
    372       break;
    373     case IDC_CLOSE_WINDOW:
    374       content::RecordAction(content::UserMetricsAction("CloseWindowByKey"));
    375       CloseWindow(browser_);
    376       break;
    377     case IDC_NEW_TAB:
    378       NewTab(browser_);
    379       break;
    380     case IDC_CLOSE_TAB:
    381       content::RecordAction(content::UserMetricsAction("CloseTabByKey"));
    382       CloseTab(browser_);
    383       break;
    384     case IDC_SELECT_NEXT_TAB:
    385       content::RecordAction(content::UserMetricsAction("Accel_SelectNextTab"));
    386       SelectNextTab(browser_);
    387       break;
    388     case IDC_SELECT_PREVIOUS_TAB:
    389       content::RecordAction(
    390           content::UserMetricsAction("Accel_SelectPreviousTab"));
    391       SelectPreviousTab(browser_);
    392       break;
    393     case IDC_TABPOSE:
    394       OpenTabpose(browser_);
    395       break;
    396     case IDC_MOVE_TAB_NEXT:
    397       MoveTabNext(browser_);
    398       break;
    399     case IDC_MOVE_TAB_PREVIOUS:
    400       MoveTabPrevious(browser_);
    401       break;
    402     case IDC_SELECT_TAB_0:
    403     case IDC_SELECT_TAB_1:
    404     case IDC_SELECT_TAB_2:
    405     case IDC_SELECT_TAB_3:
    406     case IDC_SELECT_TAB_4:
    407     case IDC_SELECT_TAB_5:
    408     case IDC_SELECT_TAB_6:
    409     case IDC_SELECT_TAB_7:
    410       SelectNumberedTab(browser_, id - IDC_SELECT_TAB_0);
    411       break;
    412     case IDC_SELECT_LAST_TAB:
    413       SelectLastTab(browser_);
    414       break;
    415     case IDC_DUPLICATE_TAB:
    416       DuplicateTab(browser_);
    417       break;
    418     case IDC_RESTORE_TAB:
    419       RestoreTab(browser_);
    420       break;
    421     case IDC_SHOW_AS_TAB:
    422       ConvertPopupToTabbedBrowser(browser_);
    423       break;
    424     case IDC_FULLSCREEN:
    425 #if defined(OS_MACOSX)
    426       chrome::ToggleFullscreenWithChromeOrFallback(browser_);
    427 #else
    428       chrome::ToggleFullscreenMode(browser_);
    429 #endif
    430       break;
    431 
    432 #if defined(USE_ASH)
    433     case IDC_TOGGLE_ASH_DESKTOP:
    434       chrome::ToggleAshDesktop();
    435       break;
    436 #endif
    437 
    438 #if defined(OS_WIN)
    439     // Windows 8 specific commands.
    440     case IDC_METRO_SNAP_ENABLE:
    441       browser_->SetMetroSnapMode(true);
    442       break;
    443     case IDC_METRO_SNAP_DISABLE:
    444       browser_->SetMetroSnapMode(false);
    445       break;
    446     case IDC_WIN8_DESKTOP_RESTART:
    447       chrome::AttemptRestartWithModeSwitch();
    448       content::RecordAction(content::UserMetricsAction("Win8DesktopRestart"));
    449       break;
    450     case IDC_WIN8_METRO_RESTART:
    451       if (!chrome::VerifySwitchToMetroForApps(window()->GetNativeWindow()))
    452         break;
    453 
    454       // SwitchToMetroUIHandler deletes itself.
    455       new SwitchToMetroUIHandler;
    456       content::RecordAction(content::UserMetricsAction("Win8MetroRestart"));
    457       break;
    458 #endif
    459 
    460 #if defined(OS_MACOSX)
    461     case IDC_PRESENTATION_MODE:
    462       chrome::ToggleFullscreenMode(browser_);
    463       break;
    464 #endif
    465     case IDC_EXIT:
    466       Exit();
    467       break;
    468 
    469     // Page-related commands
    470     case IDC_SAVE_PAGE:
    471       SavePage(browser_);
    472       break;
    473     case IDC_BOOKMARK_PAGE:
    474       BookmarkCurrentPage(browser_);
    475       break;
    476     case IDC_BOOKMARK_PAGE_FROM_STAR:
    477       BookmarkCurrentPageFromStar(browser_);
    478       break;
    479     case IDC_PIN_TO_START_SCREEN:
    480       TogglePagePinnedToStartScreen(browser_);
    481       break;
    482     case IDC_BOOKMARK_ALL_TABS:
    483       BookmarkAllTabs(browser_);
    484       break;
    485     case IDC_VIEW_SOURCE:
    486       ViewSelectedSource(browser_);
    487       break;
    488     case IDC_EMAIL_PAGE_LOCATION:
    489       EmailPageLocation(browser_);
    490       break;
    491     case IDC_PRINT:
    492       Print(browser_);
    493       break;
    494     case IDC_ADVANCED_PRINT:
    495       AdvancedPrint(browser_);
    496       break;
    497     case IDC_PRINT_TO_DESTINATION:
    498       PrintToDestination(browser_);
    499       break;
    500     case IDC_ENCODING_AUTO_DETECT:
    501       browser_->ToggleEncodingAutoDetect();
    502       break;
    503     case IDC_ENCODING_UTF8:
    504     case IDC_ENCODING_UTF16LE:
    505     case IDC_ENCODING_ISO88591:
    506     case IDC_ENCODING_WINDOWS1252:
    507     case IDC_ENCODING_GBK:
    508     case IDC_ENCODING_GB18030:
    509     case IDC_ENCODING_BIG5HKSCS:
    510     case IDC_ENCODING_BIG5:
    511     case IDC_ENCODING_KOREAN:
    512     case IDC_ENCODING_SHIFTJIS:
    513     case IDC_ENCODING_ISO2022JP:
    514     case IDC_ENCODING_EUCJP:
    515     case IDC_ENCODING_THAI:
    516     case IDC_ENCODING_ISO885915:
    517     case IDC_ENCODING_MACINTOSH:
    518     case IDC_ENCODING_ISO88592:
    519     case IDC_ENCODING_WINDOWS1250:
    520     case IDC_ENCODING_ISO88595:
    521     case IDC_ENCODING_WINDOWS1251:
    522     case IDC_ENCODING_KOI8R:
    523     case IDC_ENCODING_KOI8U:
    524     case IDC_ENCODING_ISO88597:
    525     case IDC_ENCODING_WINDOWS1253:
    526     case IDC_ENCODING_ISO88594:
    527     case IDC_ENCODING_ISO885913:
    528     case IDC_ENCODING_WINDOWS1257:
    529     case IDC_ENCODING_ISO88593:
    530     case IDC_ENCODING_ISO885910:
    531     case IDC_ENCODING_ISO885914:
    532     case IDC_ENCODING_ISO885916:
    533     case IDC_ENCODING_WINDOWS1254:
    534     case IDC_ENCODING_ISO88596:
    535     case IDC_ENCODING_WINDOWS1256:
    536     case IDC_ENCODING_ISO88598:
    537     case IDC_ENCODING_ISO88598I:
    538     case IDC_ENCODING_WINDOWS1255:
    539     case IDC_ENCODING_WINDOWS1258:
    540       browser_->OverrideEncoding(id);
    541       break;
    542 
    543     // Clipboard commands
    544     case IDC_CUT:
    545       Cut(browser_);
    546       break;
    547     case IDC_COPY:
    548       Copy(browser_);
    549       break;
    550     case IDC_PASTE:
    551       Paste(browser_);
    552       break;
    553 
    554     // Find-in-page
    555     case IDC_FIND:
    556       Find(browser_);
    557       break;
    558     case IDC_FIND_NEXT:
    559       FindNext(browser_);
    560       break;
    561     case IDC_FIND_PREVIOUS:
    562       FindPrevious(browser_);
    563       break;
    564 
    565     // Zoom
    566     case IDC_ZOOM_PLUS:
    567       Zoom(browser_, content::PAGE_ZOOM_IN);
    568       break;
    569     case IDC_ZOOM_NORMAL:
    570       Zoom(browser_, content::PAGE_ZOOM_RESET);
    571       break;
    572     case IDC_ZOOM_MINUS:
    573       Zoom(browser_, content::PAGE_ZOOM_OUT);
    574       break;
    575 
    576     // Focus various bits of UI
    577     case IDC_FOCUS_TOOLBAR:
    578       FocusToolbar(browser_);
    579       break;
    580     case IDC_FOCUS_LOCATION:
    581       FocusLocationBar(browser_);
    582       break;
    583     case IDC_FOCUS_SEARCH:
    584       FocusSearch(browser_);
    585       break;
    586     case IDC_FOCUS_MENU_BAR:
    587       FocusAppMenu(browser_);
    588       break;
    589     case IDC_FOCUS_BOOKMARKS:
    590       FocusBookmarksToolbar(browser_);
    591       break;
    592     case IDC_FOCUS_INFOBARS:
    593       FocusInfobars(browser_);
    594       break;
    595     case IDC_FOCUS_NEXT_PANE:
    596       FocusNextPane(browser_);
    597       break;
    598     case IDC_FOCUS_PREVIOUS_PANE:
    599       FocusPreviousPane(browser_);
    600       break;
    601 
    602     // Show various bits of UI
    603     case IDC_OPEN_FILE:
    604       browser_->OpenFile();
    605       break;
    606     case IDC_CREATE_SHORTCUTS:
    607       CreateApplicationShortcuts(browser_);
    608       break;
    609     case IDC_DEV_TOOLS:
    610       ToggleDevToolsWindow(browser_, DEVTOOLS_TOGGLE_ACTION_SHOW);
    611       break;
    612     case IDC_DEV_TOOLS_CONSOLE:
    613       ToggleDevToolsWindow(browser_, DEVTOOLS_TOGGLE_ACTION_SHOW_CONSOLE);
    614       break;
    615     case IDC_DEV_TOOLS_INSPECT:
    616       ToggleDevToolsWindow(browser_, DEVTOOLS_TOGGLE_ACTION_INSPECT);
    617       break;
    618     case IDC_DEV_TOOLS_TOGGLE:
    619       ToggleDevToolsWindow(browser_, DEVTOOLS_TOGGLE_ACTION_TOGGLE);
    620       break;
    621     case IDC_TASK_MANAGER:
    622       OpenTaskManager(browser_);
    623       break;
    624     case IDC_FEEDBACK:
    625       OpenFeedbackDialog(browser_);
    626       break;
    627 
    628     case IDC_SHOW_BOOKMARK_BAR:
    629       ToggleBookmarkBar(browser_);
    630       break;
    631     case IDC_PROFILING_ENABLED:
    632       Profiling::Toggle();
    633       break;
    634 
    635     case IDC_SHOW_BOOKMARK_MANAGER:
    636       ShowBookmarkManager(browser_);
    637       break;
    638     case IDC_SHOW_APP_MENU:
    639       ShowAppMenu(browser_);
    640       break;
    641     case IDC_SHOW_AVATAR_MENU:
    642       ShowAvatarMenu(browser_);
    643       break;
    644     case IDC_SHOW_HISTORY:
    645       ShowHistory(browser_);
    646       break;
    647     case IDC_SHOW_DOWNLOADS:
    648       ShowDownloads(browser_);
    649       break;
    650     case IDC_MANAGE_EXTENSIONS:
    651       ShowExtensions(browser_, std::string());
    652       break;
    653     case IDC_OPTIONS:
    654       ShowSettings(browser_);
    655       break;
    656     case IDC_EDIT_SEARCH_ENGINES:
    657       ShowSearchEngineSettings(browser_);
    658       break;
    659     case IDC_VIEW_PASSWORDS:
    660       ShowPasswordManager(browser_);
    661       break;
    662     case IDC_CLEAR_BROWSING_DATA:
    663       ShowClearBrowsingDataDialog(browser_);
    664       break;
    665     case IDC_IMPORT_SETTINGS:
    666       ShowImportDialog(browser_);
    667       break;
    668     case IDC_TOGGLE_REQUEST_TABLET_SITE:
    669       ToggleRequestTabletSite(browser_);
    670       break;
    671     case IDC_ABOUT:
    672       ShowAboutChrome(browser_);
    673       break;
    674     case IDC_UPGRADE_DIALOG:
    675       OpenUpdateChromeDialog(browser_);
    676       break;
    677     case IDC_VIEW_INCOMPATIBILITIES:
    678       ShowConflicts(browser_);
    679       break;
    680     case IDC_HELP_PAGE_VIA_KEYBOARD:
    681       ShowHelp(browser_, HELP_SOURCE_KEYBOARD);
    682       break;
    683     case IDC_HELP_PAGE_VIA_MENU:
    684       ShowHelp(browser_, HELP_SOURCE_MENU);
    685       break;
    686     case IDC_SHOW_SIGNIN:
    687       ShowBrowserSignin(browser_, signin::SOURCE_MENU);
    688       break;
    689     case IDC_TOGGLE_SPEECH_INPUT:
    690       ToggleSpeechInput(browser_);
    691       break;
    692 
    693     default:
    694       LOG(WARNING) << "Received Unimplemented Command: " << id;
    695       break;
    696   }
    697 }
    698 
    699 ////////////////////////////////////////////////////////////////////////////////
    700 // BrowserCommandController, ProfileInfoCacheObserver implementation:
    701 
    702 void BrowserCommandController::OnProfileAdded(
    703     const base::FilePath& profile_path) {
    704   UpdateCommandsForMultipleProfiles();
    705 }
    706 
    707 void BrowserCommandController::OnProfileWasRemoved(
    708     const base::FilePath& profile_path,
    709     const string16& profile_name) {
    710   UpdateCommandsForMultipleProfiles();
    711 }
    712 
    713 ////////////////////////////////////////////////////////////////////////////////
    714 // BrowserCommandController, SigninPrefObserver implementation:
    715 
    716 void BrowserCommandController::OnSigninAllowedPrefChange() {
    717   // For unit tests, we don't have a window.
    718   if (!window())
    719     return;
    720   UpdateShowSyncState(IsShowingMainUI());
    721 }
    722 
    723 // BrowserCommandController, TabStripModelObserver implementation:
    724 
    725 void BrowserCommandController::TabInsertedAt(WebContents* contents,
    726                                              int index,
    727                                              bool foreground) {
    728   AddInterstitialObservers(contents);
    729 }
    730 
    731 void BrowserCommandController::TabDetachedAt(WebContents* contents, int index) {
    732   RemoveInterstitialObservers(contents);
    733 }
    734 
    735 void BrowserCommandController::TabReplacedAt(TabStripModel* tab_strip_model,
    736                                              WebContents* old_contents,
    737                                              WebContents* new_contents,
    738                                              int index) {
    739   RemoveInterstitialObservers(old_contents);
    740   AddInterstitialObservers(new_contents);
    741 }
    742 
    743 void BrowserCommandController::TabBlockedStateChanged(
    744     content::WebContents* contents,
    745     int index) {
    746   PrintingStateChanged();
    747   FullscreenStateChanged();
    748   UpdateCommandsForFind();
    749 }
    750 
    751 ////////////////////////////////////////////////////////////////////////////////
    752 // BrowserCommandController, TabRestoreServiceObserver implementation:
    753 
    754 void BrowserCommandController::TabRestoreServiceChanged(
    755     TabRestoreService* service) {
    756   command_updater_.UpdateCommandEnabled(
    757       IDC_RESTORE_TAB,
    758       GetRestoreTabType(browser_) != TabStripModelDelegate::RESTORE_NONE);
    759 }
    760 
    761 void BrowserCommandController::TabRestoreServiceDestroyed(
    762     TabRestoreService* service) {
    763   service->RemoveObserver(this);
    764 }
    765 
    766 ////////////////////////////////////////////////////////////////////////////////
    767 // BrowserCommandController, private:
    768 
    769 class BrowserCommandController::InterstitialObserver
    770     : public content::WebContentsObserver {
    771  public:
    772   InterstitialObserver(BrowserCommandController* controller,
    773                        content::WebContents* web_contents)
    774       : WebContentsObserver(web_contents),
    775         controller_(controller) {
    776   }
    777 
    778   using content::WebContentsObserver::web_contents;
    779 
    780   virtual void DidAttachInterstitialPage() OVERRIDE {
    781     controller_->UpdateCommandsForTabState();
    782   }
    783 
    784   virtual void DidDetachInterstitialPage() OVERRIDE {
    785     controller_->UpdateCommandsForTabState();
    786   }
    787 
    788  private:
    789   BrowserCommandController* controller_;
    790 
    791   DISALLOW_COPY_AND_ASSIGN(InterstitialObserver);
    792 };
    793 
    794 bool BrowserCommandController::IsShowingMainUI() {
    795   bool should_hide_ui = window() && window()->ShouldHideUIForFullscreen();
    796   return browser_->is_type_tabbed() && !should_hide_ui;
    797 }
    798 
    799 void BrowserCommandController::InitCommandState() {
    800   // All browser commands whose state isn't set automagically some other way
    801   // (like Back & Forward with initial page load) must have their state
    802   // initialized here, otherwise they will be forever disabled.
    803 
    804   // Navigation commands
    805   command_updater_.UpdateCommandEnabled(IDC_RELOAD, true);
    806   command_updater_.UpdateCommandEnabled(IDC_RELOAD_IGNORING_CACHE, true);
    807   command_updater_.UpdateCommandEnabled(IDC_RELOAD_CLEARING_CACHE, true);
    808 
    809   // Window management commands
    810   command_updater_.UpdateCommandEnabled(IDC_CLOSE_WINDOW, true);
    811   command_updater_.UpdateCommandEnabled(IDC_NEW_TAB, true);
    812   command_updater_.UpdateCommandEnabled(IDC_CLOSE_TAB, true);
    813   command_updater_.UpdateCommandEnabled(IDC_DUPLICATE_TAB, true);
    814   command_updater_.UpdateCommandEnabled(IDC_RESTORE_TAB, false);
    815 #if defined(OS_WIN) && defined(USE_ASH)
    816   if (browser_->host_desktop_type() != chrome::HOST_DESKTOP_TYPE_ASH)
    817     command_updater_.UpdateCommandEnabled(IDC_EXIT, true);
    818 #else
    819   command_updater_.UpdateCommandEnabled(IDC_EXIT, true);
    820 #endif
    821   command_updater_.UpdateCommandEnabled(IDC_DEBUG_FRAME_TOGGLE, true);
    822 #if defined(OS_WIN) && defined(USE_ASH) && !defined(NDEBUG)
    823   if (base::win::GetVersion() < base::win::VERSION_WIN8 &&
    824       chrome::HOST_DESKTOP_TYPE_NATIVE != chrome::HOST_DESKTOP_TYPE_ASH)
    825     command_updater_.UpdateCommandEnabled(IDC_TOGGLE_ASH_DESKTOP, true);
    826 #endif
    827 
    828   // Page-related commands
    829   command_updater_.UpdateCommandEnabled(IDC_EMAIL_PAGE_LOCATION, true);
    830   command_updater_.UpdateCommandEnabled(IDC_ENCODING_AUTO_DETECT, true);
    831   command_updater_.UpdateCommandEnabled(IDC_ENCODING_UTF8, true);
    832   command_updater_.UpdateCommandEnabled(IDC_ENCODING_UTF16LE, true);
    833   command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88591, true);
    834   command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1252, true);
    835   command_updater_.UpdateCommandEnabled(IDC_ENCODING_GBK, true);
    836   command_updater_.UpdateCommandEnabled(IDC_ENCODING_GB18030, true);
    837   command_updater_.UpdateCommandEnabled(IDC_ENCODING_BIG5HKSCS, true);
    838   command_updater_.UpdateCommandEnabled(IDC_ENCODING_BIG5, true);
    839   command_updater_.UpdateCommandEnabled(IDC_ENCODING_THAI, true);
    840   command_updater_.UpdateCommandEnabled(IDC_ENCODING_KOREAN, true);
    841   command_updater_.UpdateCommandEnabled(IDC_ENCODING_SHIFTJIS, true);
    842   command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO2022JP, true);
    843   command_updater_.UpdateCommandEnabled(IDC_ENCODING_EUCJP, true);
    844   command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO885915, true);
    845   command_updater_.UpdateCommandEnabled(IDC_ENCODING_MACINTOSH, true);
    846   command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88592, true);
    847   command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1250, true);
    848   command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88595, true);
    849   command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1251, true);
    850   command_updater_.UpdateCommandEnabled(IDC_ENCODING_KOI8R, true);
    851   command_updater_.UpdateCommandEnabled(IDC_ENCODING_KOI8U, true);
    852   command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88597, true);
    853   command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1253, true);
    854   command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88594, true);
    855   command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO885913, true);
    856   command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1257, true);
    857   command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88593, true);
    858   command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO885910, true);
    859   command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO885914, true);
    860   command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO885916, true);
    861   command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1254, true);
    862   command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88596, true);
    863   command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1256, true);
    864   command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88598, true);
    865   command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88598I, true);
    866   command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1255, true);
    867   command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1258, true);
    868 
    869   // Zoom
    870   command_updater_.UpdateCommandEnabled(IDC_ZOOM_MENU, true);
    871   command_updater_.UpdateCommandEnabled(IDC_ZOOM_PLUS, true);
    872   command_updater_.UpdateCommandEnabled(IDC_ZOOM_NORMAL, true);
    873   command_updater_.UpdateCommandEnabled(IDC_ZOOM_MINUS, true);
    874 
    875   // Show various bits of UI
    876   UpdateOpenFileState(&command_updater_);
    877   command_updater_.UpdateCommandEnabled(IDC_CREATE_SHORTCUTS, false);
    878   UpdateCommandsForDevTools();
    879   command_updater_.UpdateCommandEnabled(IDC_TASK_MANAGER, CanOpenTaskManager());
    880   command_updater_.UpdateCommandEnabled(IDC_SHOW_HISTORY,
    881                                         !profile()->IsGuestSession());
    882   command_updater_.UpdateCommandEnabled(IDC_SHOW_DOWNLOADS, true);
    883   command_updater_.UpdateCommandEnabled(IDC_HELP_PAGE_VIA_KEYBOARD, true);
    884   command_updater_.UpdateCommandEnabled(IDC_HELP_PAGE_VIA_MENU, true);
    885   command_updater_.UpdateCommandEnabled(IDC_BOOKMARKS_MENU,
    886                                         !profile()->IsGuestSession());
    887   command_updater_.UpdateCommandEnabled(IDC_RECENT_TABS_MENU,
    888                                         !profile()->IsGuestSession() &&
    889                                         !profile()->IsOffTheRecord());
    890 
    891   UpdateShowSyncState(true);
    892 
    893   // Initialize other commands based on the window type.
    894   bool normal_window = browser_->is_type_tabbed();
    895 
    896   // Navigation commands
    897   command_updater_.UpdateCommandEnabled(IDC_HOME, normal_window);
    898 
    899   // Window management commands
    900   command_updater_.UpdateCommandEnabled(IDC_SELECT_NEXT_TAB, normal_window);
    901   command_updater_.UpdateCommandEnabled(IDC_SELECT_PREVIOUS_TAB,
    902                                         normal_window);
    903   command_updater_.UpdateCommandEnabled(IDC_MOVE_TAB_NEXT, normal_window);
    904   command_updater_.UpdateCommandEnabled(IDC_MOVE_TAB_PREVIOUS, normal_window);
    905   command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_0, normal_window);
    906   command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_1, normal_window);
    907   command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_2, normal_window);
    908   command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_3, normal_window);
    909   command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_4, normal_window);
    910   command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_5, normal_window);
    911   command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_6, normal_window);
    912   command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_7, normal_window);
    913   command_updater_.UpdateCommandEnabled(IDC_SELECT_LAST_TAB, normal_window);
    914 #if defined(OS_WIN)
    915   const bool metro_mode = base::win::IsMetroProcess();
    916   command_updater_.UpdateCommandEnabled(IDC_METRO_SNAP_ENABLE, metro_mode);
    917   command_updater_.UpdateCommandEnabled(IDC_METRO_SNAP_DISABLE, metro_mode);
    918   int restart_mode = metro_mode ?
    919       IDC_WIN8_DESKTOP_RESTART : IDC_WIN8_METRO_RESTART;
    920   command_updater_.UpdateCommandEnabled(restart_mode, normal_window);
    921 #endif
    922   command_updater_.UpdateCommandEnabled(IDC_TABPOSE, normal_window);
    923 
    924   // Show various bits of UI
    925   command_updater_.UpdateCommandEnabled(IDC_CLEAR_BROWSING_DATA, normal_window);
    926 
    927   // The upgrade entry and the view incompatibility entry should always be
    928   // enabled. Whether they are visible is a separate matter determined on menu
    929   // show.
    930   command_updater_.UpdateCommandEnabled(IDC_UPGRADE_DIALOG, true);
    931   command_updater_.UpdateCommandEnabled(IDC_VIEW_INCOMPATIBILITIES, true);
    932 
    933   // Toggle speech input
    934   command_updater_.UpdateCommandEnabled(IDC_TOGGLE_SPEECH_INPUT, true);
    935 
    936   // Initialize other commands whose state changes based on fullscreen mode.
    937   UpdateCommandsForFullscreenMode(FULLSCREEN_DISABLED);
    938 
    939   UpdateCommandsForContentRestrictionState();
    940 
    941   UpdateCommandsForBookmarkEditing();
    942 
    943   UpdateCommandsForIncognitoAvailability();
    944 }
    945 
    946 // static
    947 void BrowserCommandController::UpdateSharedCommandsForIncognitoAvailability(
    948     CommandUpdater* command_updater,
    949     Profile* profile) {
    950   IncognitoModePrefs::Availability incognito_availability =
    951       IncognitoModePrefs::GetAvailability(profile->GetPrefs());
    952   command_updater->UpdateCommandEnabled(
    953       IDC_NEW_WINDOW,
    954       incognito_availability != IncognitoModePrefs::FORCED);
    955   command_updater->UpdateCommandEnabled(
    956       IDC_NEW_INCOGNITO_WINDOW,
    957       incognito_availability != IncognitoModePrefs::DISABLED);
    958 
    959   // Bookmark manager and settings page/subpages are forced to open in normal
    960   // mode. For this reason we disable these commands when incognito is forced.
    961   const bool command_enabled =
    962       incognito_availability != IncognitoModePrefs::FORCED;
    963   command_updater->UpdateCommandEnabled(
    964       IDC_SHOW_BOOKMARK_MANAGER,
    965       browser_defaults::bookmarks_enabled && command_enabled);
    966   ExtensionService* extension_service = profile->GetExtensionService();
    967   bool enable_extensions =
    968       extension_service && extension_service->extensions_enabled();
    969   command_updater->UpdateCommandEnabled(IDC_MANAGE_EXTENSIONS,
    970                                         enable_extensions && command_enabled);
    971 
    972   command_updater->UpdateCommandEnabled(IDC_IMPORT_SETTINGS, command_enabled);
    973   command_updater->UpdateCommandEnabled(IDC_OPTIONS, command_enabled);
    974   command_updater->UpdateCommandEnabled(IDC_SHOW_SIGNIN, command_enabled);
    975 }
    976 
    977 void BrowserCommandController::UpdateCommandsForIncognitoAvailability() {
    978   UpdateSharedCommandsForIncognitoAvailability(&command_updater_, profile());
    979 
    980   if (!IsShowingMainUI()) {
    981     command_updater_.UpdateCommandEnabled(IDC_IMPORT_SETTINGS, false);
    982     command_updater_.UpdateCommandEnabled(IDC_OPTIONS, false);
    983   }
    984 }
    985 
    986 void BrowserCommandController::UpdateCommandsForTabState() {
    987   WebContents* current_web_contents =
    988       browser_->tab_strip_model()->GetActiveWebContents();
    989   if (!current_web_contents)  // May be NULL during tab restore.
    990     return;
    991 
    992   // Navigation commands
    993   command_updater_.UpdateCommandEnabled(IDC_BACK, CanGoBack(browser_));
    994   command_updater_.UpdateCommandEnabled(IDC_FORWARD, CanGoForward(browser_));
    995   command_updater_.UpdateCommandEnabled(IDC_RELOAD, CanReload(browser_));
    996   command_updater_.UpdateCommandEnabled(IDC_RELOAD_IGNORING_CACHE,
    997                                         CanReload(browser_));
    998   command_updater_.UpdateCommandEnabled(IDC_RELOAD_CLEARING_CACHE,
    999                                         CanReload(browser_));
   1000 
   1001   // Window management commands
   1002   command_updater_.UpdateCommandEnabled(IDC_DUPLICATE_TAB,
   1003       !browser_->is_app() && CanDuplicateTab(browser_));
   1004 
   1005   // Page-related commands
   1006   window()->SetStarredState(
   1007       BookmarkTabHelper::FromWebContents(current_web_contents)->is_starred());
   1008   window()->ZoomChangedForActiveTab(false);
   1009   command_updater_.UpdateCommandEnabled(IDC_VIEW_SOURCE,
   1010                                         CanViewSource(browser_));
   1011   command_updater_.UpdateCommandEnabled(IDC_EMAIL_PAGE_LOCATION,
   1012                                         CanEmailPageLocation(browser_));
   1013   if (browser_->is_devtools())
   1014     command_updater_.UpdateCommandEnabled(IDC_OPEN_FILE, false);
   1015 
   1016   // Changing the encoding is not possible on Chrome-internal webpages.
   1017   NavigationController& nc = current_web_contents->GetController();
   1018   bool is_chrome_internal = HasInternalURL(nc.GetActiveEntry()) ||
   1019       current_web_contents->ShowingInterstitialPage();
   1020   command_updater_.UpdateCommandEnabled(IDC_ENCODING_MENU,
   1021       !is_chrome_internal && current_web_contents->IsSavable());
   1022 
   1023   // Show various bits of UI
   1024   // TODO(pinkerton): Disable app-mode in the model until we implement it
   1025   // on the Mac. Be sure to remove both ifdefs. http://crbug.com/13148
   1026 #if !defined(OS_MACOSX)
   1027   command_updater_.UpdateCommandEnabled(
   1028       IDC_CREATE_SHORTCUTS,
   1029       CanCreateApplicationShortcuts(browser_));
   1030 #endif
   1031 
   1032   command_updater_.UpdateCommandEnabled(
   1033       IDC_TOGGLE_REQUEST_TABLET_SITE,
   1034       CanRequestTabletSite(current_web_contents));
   1035 
   1036   UpdateCommandsForContentRestrictionState();
   1037   UpdateCommandsForBookmarkEditing();
   1038   UpdateCommandsForFind();
   1039 }
   1040 
   1041 void BrowserCommandController::UpdateCommandsForContentRestrictionState() {
   1042   int restrictions = GetContentRestrictions(browser_);
   1043 
   1044   command_updater_.UpdateCommandEnabled(
   1045       IDC_COPY, !(restrictions & CONTENT_RESTRICTION_COPY));
   1046   command_updater_.UpdateCommandEnabled(
   1047       IDC_CUT, !(restrictions & CONTENT_RESTRICTION_CUT));
   1048   command_updater_.UpdateCommandEnabled(
   1049       IDC_PASTE, !(restrictions & CONTENT_RESTRICTION_PASTE));
   1050   UpdateSaveAsState();
   1051   UpdatePrintingState();
   1052 }
   1053 
   1054 void BrowserCommandController::UpdateCommandsForDevTools() {
   1055   bool dev_tools_enabled =
   1056       !profile()->GetPrefs()->GetBoolean(prefs::kDevToolsDisabled);
   1057   command_updater_.UpdateCommandEnabled(IDC_DEV_TOOLS,
   1058                                         dev_tools_enabled);
   1059   command_updater_.UpdateCommandEnabled(IDC_DEV_TOOLS_CONSOLE,
   1060                                         dev_tools_enabled);
   1061   command_updater_.UpdateCommandEnabled(IDC_DEV_TOOLS_INSPECT,
   1062                                         dev_tools_enabled);
   1063   command_updater_.UpdateCommandEnabled(IDC_DEV_TOOLS_TOGGLE,
   1064                                         dev_tools_enabled);
   1065 }
   1066 
   1067 void BrowserCommandController::UpdateCommandsForBookmarkEditing() {
   1068   command_updater_.UpdateCommandEnabled(IDC_BOOKMARK_PAGE,
   1069                                         CanBookmarkCurrentPage(browser_));
   1070   command_updater_.UpdateCommandEnabled(IDC_BOOKMARK_ALL_TABS,
   1071                                         CanBookmarkAllTabs(browser_));
   1072   command_updater_.UpdateCommandEnabled(IDC_PIN_TO_START_SCREEN,
   1073                                         true);
   1074 }
   1075 
   1076 void BrowserCommandController::UpdateCommandsForBookmarkBar() {
   1077   command_updater_.UpdateCommandEnabled(IDC_SHOW_BOOKMARK_BAR,
   1078       browser_defaults::bookmarks_enabled &&
   1079       !profile()->GetPrefs()->IsManagedPreference(prefs::kShowBookmarkBar) &&
   1080       IsShowingMainUI());
   1081 }
   1082 
   1083 void BrowserCommandController::UpdateCommandsForFileSelectionDialogs() {
   1084   UpdateSaveAsState();
   1085   UpdateOpenFileState(&command_updater_);
   1086 }
   1087 
   1088 void BrowserCommandController::UpdateCommandsForFullscreenMode(
   1089     FullScreenMode fullscreen_mode) {
   1090   bool show_main_ui = IsShowingMainUI();
   1091   bool main_not_fullscreen = show_main_ui &&
   1092                              (fullscreen_mode == FULLSCREEN_DISABLED);
   1093 
   1094   // Navigation commands
   1095   command_updater_.UpdateCommandEnabled(IDC_OPEN_CURRENT_URL, show_main_ui);
   1096 
   1097   // Window management commands
   1098   command_updater_.UpdateCommandEnabled(
   1099       IDC_SHOW_AS_TAB,
   1100       !browser_->is_type_tabbed() && fullscreen_mode == FULLSCREEN_DISABLED);
   1101 
   1102   // Focus various bits of UI
   1103   command_updater_.UpdateCommandEnabled(IDC_FOCUS_TOOLBAR, show_main_ui);
   1104   command_updater_.UpdateCommandEnabled(IDC_FOCUS_LOCATION, show_main_ui);
   1105   command_updater_.UpdateCommandEnabled(IDC_FOCUS_SEARCH, show_main_ui);
   1106   command_updater_.UpdateCommandEnabled(
   1107       IDC_FOCUS_MENU_BAR, main_not_fullscreen);
   1108   command_updater_.UpdateCommandEnabled(
   1109       IDC_FOCUS_NEXT_PANE, main_not_fullscreen);
   1110   command_updater_.UpdateCommandEnabled(
   1111       IDC_FOCUS_PREVIOUS_PANE, main_not_fullscreen);
   1112   command_updater_.UpdateCommandEnabled(
   1113       IDC_FOCUS_BOOKMARKS, main_not_fullscreen);
   1114   command_updater_.UpdateCommandEnabled(
   1115       IDC_FOCUS_INFOBARS, main_not_fullscreen);
   1116 
   1117   // Show various bits of UI
   1118   command_updater_.UpdateCommandEnabled(IDC_DEVELOPER_MENU, show_main_ui);
   1119   command_updater_.UpdateCommandEnabled(IDC_FEEDBACK, show_main_ui);
   1120   UpdateShowSyncState(show_main_ui);
   1121 
   1122   // Settings page/subpages are forced to open in normal mode. We disable these
   1123   // commands when incognito is forced.
   1124   const bool options_enabled = show_main_ui &&
   1125       IncognitoModePrefs::GetAvailability(
   1126           profile()->GetPrefs()) != IncognitoModePrefs::FORCED;
   1127   command_updater_.UpdateCommandEnabled(IDC_OPTIONS, options_enabled);
   1128   command_updater_.UpdateCommandEnabled(IDC_IMPORT_SETTINGS, options_enabled);
   1129 
   1130   command_updater_.UpdateCommandEnabled(IDC_EDIT_SEARCH_ENGINES, show_main_ui);
   1131   command_updater_.UpdateCommandEnabled(IDC_VIEW_PASSWORDS, show_main_ui);
   1132   command_updater_.UpdateCommandEnabled(IDC_ABOUT, show_main_ui);
   1133   command_updater_.UpdateCommandEnabled(IDC_SHOW_APP_MENU, show_main_ui);
   1134 #if defined (ENABLE_PROFILING) && !defined(NO_TCMALLOC)
   1135   command_updater_.UpdateCommandEnabled(IDC_PROFILING_ENABLED, show_main_ui);
   1136 #endif
   1137 
   1138   // Disable explicit fullscreen toggling when in metro snap mode.
   1139   bool fullscreen_enabled = fullscreen_mode != FULLSCREEN_METRO_SNAP;
   1140 #if defined(OS_MACOSX)
   1141   // The Mac implementation doesn't support switching to fullscreen while
   1142   // a tab modal dialog is displayed.
   1143   int tab_index = chrome::IndexOfFirstBlockedTab(browser_->tab_strip_model());
   1144   bool has_blocked_tab = tab_index != browser_->tab_strip_model()->count();
   1145   fullscreen_enabled &= !has_blocked_tab;
   1146 #endif
   1147 
   1148   command_updater_.UpdateCommandEnabled(IDC_FULLSCREEN, fullscreen_enabled);
   1149   command_updater_.UpdateCommandEnabled(IDC_PRESENTATION_MODE,
   1150                                         fullscreen_enabled);
   1151 
   1152   UpdateCommandsForBookmarkBar();
   1153   UpdateCommandsForMultipleProfiles();
   1154 }
   1155 
   1156 void BrowserCommandController::UpdateCommandsForMultipleProfiles() {
   1157   bool enable = IsShowingMainUI() &&
   1158       !profile()->IsOffTheRecord() &&
   1159       profile_manager_ &&
   1160       AvatarMenuModel::ShouldShowAvatarMenu();
   1161   command_updater_.UpdateCommandEnabled(IDC_SHOW_AVATAR_MENU,
   1162                                         enable);
   1163 }
   1164 
   1165 void BrowserCommandController::UpdatePrintingState() {
   1166   bool print_enabled = CanPrint(browser_);
   1167   command_updater_.UpdateCommandEnabled(IDC_PRINT, print_enabled);
   1168   command_updater_.UpdateCommandEnabled(IDC_ADVANCED_PRINT,
   1169                                         CanAdvancedPrint(browser_));
   1170   command_updater_.UpdateCommandEnabled(IDC_PRINT_TO_DESTINATION,
   1171                                         print_enabled);
   1172 #if defined(OS_WIN)
   1173   HMODULE metro_module = base::win::GetMetroModule();
   1174   if (metro_module != NULL) {
   1175     typedef void (*MetroEnablePrinting)(BOOL);
   1176     MetroEnablePrinting metro_enable_printing =
   1177         reinterpret_cast<MetroEnablePrinting>(
   1178             ::GetProcAddress(metro_module, "MetroEnablePrinting"));
   1179     if (metro_enable_printing)
   1180       metro_enable_printing(print_enabled);
   1181   }
   1182 #endif
   1183 }
   1184 
   1185 void BrowserCommandController::UpdateSaveAsState() {
   1186   command_updater_.UpdateCommandEnabled(IDC_SAVE_PAGE, CanSavePage(browser_));
   1187 }
   1188 
   1189 void BrowserCommandController::UpdateShowSyncState(bool show_main_ui) {
   1190   command_updater_.UpdateCommandEnabled(
   1191       IDC_SHOW_SYNC_SETUP, show_main_ui && pref_signin_allowed_.GetValue());
   1192 }
   1193 
   1194 // static
   1195 void BrowserCommandController::UpdateOpenFileState(
   1196     CommandUpdater* command_updater) {
   1197   bool enabled = true;
   1198   PrefService* local_state = g_browser_process->local_state();
   1199   if (local_state)
   1200     enabled = local_state->GetBoolean(prefs::kAllowFileSelectionDialogs);
   1201 
   1202   command_updater->UpdateCommandEnabled(IDC_OPEN_FILE, enabled);
   1203 }
   1204 
   1205 void BrowserCommandController::UpdateReloadStopState(bool is_loading,
   1206                                                      bool force) {
   1207   window()->UpdateReloadStopState(is_loading, force);
   1208   command_updater_.UpdateCommandEnabled(IDC_STOP, is_loading);
   1209 }
   1210 
   1211 void BrowserCommandController::UpdateCommandsForFind() {
   1212   TabStripModel* model = browser_->tab_strip_model();
   1213   bool enabled = !model->IsTabBlocked(model->active_index()) &&
   1214                  !browser_->is_devtools();
   1215 
   1216   command_updater_.UpdateCommandEnabled(IDC_FIND, enabled);
   1217   command_updater_.UpdateCommandEnabled(IDC_FIND_NEXT, enabled);
   1218   command_updater_.UpdateCommandEnabled(IDC_FIND_PREVIOUS, enabled);
   1219 }
   1220 
   1221 void BrowserCommandController::AddInterstitialObservers(WebContents* contents) {
   1222   interstitial_observers_.push_back(new InterstitialObserver(this, contents));
   1223 }
   1224 
   1225 void BrowserCommandController::RemoveInterstitialObservers(
   1226     WebContents* contents) {
   1227   for (size_t i = 0; i < interstitial_observers_.size(); i++) {
   1228     if (interstitial_observers_[i]->web_contents() != contents)
   1229       continue;
   1230 
   1231     delete interstitial_observers_[i];
   1232     interstitial_observers_.erase(interstitial_observers_.begin() + i);
   1233     return;
   1234   }
   1235 }
   1236 
   1237 BrowserWindow* BrowserCommandController::window() {
   1238   return browser_->window();
   1239 }
   1240 
   1241 Profile* BrowserCommandController::profile() {
   1242   return browser_->profile();
   1243 }
   1244 
   1245 }  // namespace chrome
   1246