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