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