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