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