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