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