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