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