blob: 158e74dd8e0215d7a779d71ed487e82523916f86 [file] [log] [blame]
[email protected]5d98294912012-06-27 22:57:401// 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 "chrome/app/chrome_command_ids.h"
8#include "chrome/browser/browser_process.h"
9#include "chrome/browser/defaults.h"
10#include "chrome/browser/extensions/extension_service.h"
11#include "chrome/browser/prefs/incognito_mode_prefs.h"
12#include "chrome/browser/prefs/pref_service.h"
13#include "chrome/browser/printing/print_preview_tab_controller.h"
14#include "chrome/browser/profiles/profile.h"
15#include "chrome/browser/profiles/profile_manager.h"
16#include "chrome/browser/sessions/tab_restore_service.h"
17#include "chrome/browser/sessions/tab_restore_service_factory.h"
18#include "chrome/browser/sync/profile_sync_service.h"
19#include "chrome/browser/sync/profile_sync_service_factory.h"
20#include "chrome/browser/ui/bookmarks/bookmark_tab_helper.h"
21#include "chrome/browser/ui/browser.h"
22#include "chrome/browser/ui/browser_commands.h"
23#include "chrome/browser/ui/browser_window.h"
24#include "chrome/browser/ui/chrome_pages.h"
25#include "chrome/browser/ui/tab_contents/tab_contents.h"
26#include "chrome/browser/ui/tabs/tab_strip_model.h"
27#include "chrome/browser/ui/webui/sync_promo/sync_promo_ui.h"
28#include "chrome/common/chrome_notification_types.h"
29#include "chrome/common/pref_names.h"
30#include "chrome/common/profiling.h"
31#include "content/public/browser/native_web_keyboard_event.h"
32#include "content/public/browser/navigation_controller.h"
33#include "content/public/browser/navigation_entry.h"
34#include "content/public/browser/notification_details.h"
35#include "content/public/browser/notification_source.h"
36#include "content/public/browser/web_contents.h"
37#include "content/public/common/content_restriction.h"
38#include "content/public/common/url_constants.h"
39#include "ui/base/keycodes/keyboard_codes.h"
40
41#if defined(OS_WIN)
42#include "base/win/metro.h"
43#endif
44
45using content::WebContents;
46using content::NavigationEntry;
47using content::NavigationController;
48using content::WebContents;
49
50namespace {
51
52// Returns |true| if entry has an internal chrome:// URL, |false| otherwise.
53bool HasInternalURL(const NavigationEntry* entry) {
54 if (!entry)
55 return false;
56
57 // Check the |virtual_url()| first. This catches regular chrome:// URLs
58 // including URLs that were rewritten (such as chrome://bookmarks).
59 if (entry->GetVirtualURL().SchemeIs(chrome::kChromeUIScheme))
60 return true;
61
62 // If the |virtual_url()| isn't a chrome:// URL, check if it's actually
63 // view-source: of a chrome:// URL.
64 if (entry->GetVirtualURL().SchemeIs(chrome::kViewSourceScheme))
65 return entry->GetURL().SchemeIs(chrome::kChromeUIScheme);
66
67 return false;
68}
69
70} // namespace
71
72namespace chrome {
73
74///////////////////////////////////////////////////////////////////////////////
75// BrowserCommandController, public:
76
77BrowserCommandController::BrowserCommandController(Browser* browser)
78 : browser_(browser),
79 ALLOW_THIS_IN_INITIALIZER_LIST(command_updater_(this)),
80 block_command_execution_(false),
81 last_blocked_command_id_(-1),
82 last_blocked_command_disposition_(CURRENT_TAB) {
83 browser_->tab_strip_model()->AddObserver(this);
84 PrefService* local_state = g_browser_process->local_state();
85 if (local_state) {
86 local_pref_registrar_.Init(local_state);
87 local_pref_registrar_.Add(prefs::kPrintingEnabled, this);
88 local_pref_registrar_.Add(prefs::kAllowFileSelectionDialogs, this);
89 local_pref_registrar_.Add(prefs::kInManagedMode, this);
90 }
91
92 profile_pref_registrar_.Init(profile()->GetPrefs());
93 profile_pref_registrar_.Add(prefs::kDevToolsDisabled, this);
94 profile_pref_registrar_.Add(prefs::kEditBookmarksEnabled, this);
95 profile_pref_registrar_.Add(prefs::kShowBookmarkBar, this);
96 profile_pref_registrar_.Add(prefs::kIncognitoModeAvailability, this);
97
98 InitCommandState();
99
100 TabRestoreService* tab_restore_service =
101 TabRestoreServiceFactory::GetForProfile(profile());
102 if (tab_restore_service) {
103 tab_restore_service->AddObserver(this);
104 TabRestoreServiceChanged(tab_restore_service);
105 }
106
107 ProfileSyncService* service =
108 ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile());
109 if (service)
110 service->AddObserver(this);
111}
112
113BrowserCommandController::~BrowserCommandController() {
114 ProfileSyncService* service =
115 ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile());
116 if (service)
117 service->RemoveObserver(this);
118
119 TabRestoreService* tab_restore_service =
120 TabRestoreServiceFactory::GetForProfile(profile());
121 if (tab_restore_service)
122 tab_restore_service->RemoveObserver(this);
123 profile_pref_registrar_.RemoveAll();
124 local_pref_registrar_.RemoveAll();
125 browser_->tab_strip_model()->RemoveObserver(this);
126}
127
128bool BrowserCommandController::IsReservedCommandOrKey(
129 int command_id,
130 const content::NativeWebKeyboardEvent& event) {
131 // In Apps mode, no keys are reserved.
132 if (browser_->is_app())
133 return false;
134
135#if defined(OS_CHROMEOS)
136 // Chrome OS's top row of keys produces F1-10. Make sure that web pages
137 // aren't able to block Chrome from performing the standard actions for F1-F4.
138 // We should not handle F5-10 here since they are processed by Ash. See also:
139 // crbug.com/127333#c8
140 ui::KeyboardCode key_code =
141 static_cast<ui::KeyboardCode>(event.windowsKeyCode);
142 if ((key_code == ui::VKEY_F1 ||
143 key_code == ui::VKEY_F2 ||
144 key_code == ui::VKEY_F3 ||
145 key_code == ui::VKEY_F4) &&
146 // Make sure it's a browser shortcut (i.e. not an Ash one like Alt+F4).
147 command_id != -1) {
148 return true;
149 }
150#endif
151
152 if (window()->IsFullscreen() && command_id == IDC_FULLSCREEN)
153 return true;
154 return command_id == IDC_CLOSE_TAB ||
155 command_id == IDC_CLOSE_WINDOW ||
156 command_id == IDC_NEW_INCOGNITO_WINDOW ||
157 command_id == IDC_NEW_TAB ||
158 command_id == IDC_NEW_WINDOW ||
159 command_id == IDC_RESTORE_TAB ||
160 command_id == IDC_SELECT_NEXT_TAB ||
161 command_id == IDC_SELECT_PREVIOUS_TAB ||
162 command_id == IDC_TABPOSE ||
163 command_id == IDC_EXIT ||
164 command_id == IDC_SEARCH;
165}
166
167void BrowserCommandController::SetBlockCommandExecution(bool block) {
168 block_command_execution_ = block;
169 if (block) {
170 last_blocked_command_id_ = -1;
171 last_blocked_command_disposition_ = CURRENT_TAB;
172 }
173}
174
175int BrowserCommandController::GetLastBlockedCommand(
176 WindowOpenDisposition* disposition) {
177 if (disposition)
178 *disposition = last_blocked_command_disposition_;
179 return last_blocked_command_id_;
180}
181
182void BrowserCommandController::TabStateChanged() {
183 UpdateCommandsForTabState();
184}
185
186void BrowserCommandController::ContentRestrictionsChanged() {
187 UpdateCommandsForContentRestrictionState();
188}
189
190void BrowserCommandController::FullscreenStateChanged() {
191 FullScreenMode fullscreen_mode = FULLSCREEN_DISABLED;
192 if (window()->IsFullscreen()) {
193#if defined(OS_WIN)
194 fullscreen_mode = window()->IsInMetroSnapMode() ? FULLSCREEN_METRO_SNAP :
195 FULLSCREEN_NORMAL;
196#else
197 fullscreen_mode = FULLSCREEN_NORMAL;
198#endif
199 }
200 UpdateCommandsForFullscreenMode(fullscreen_mode);
201}
202
203void BrowserCommandController::PrintingStateChanged() {
204 UpdatePrintingState();
205}
206
207void BrowserCommandController::LoadingStateChanged(bool is_loading,
208 bool force) {
209 UpdateReloadStopState(is_loading, force);
210}
211
212void BrowserCommandController::SendToMobileStateChanged(
213 bool send_to_mobile_available) {
214 command_updater_.UpdateCommandEnabled(IDC_CHROME_TO_MOBILE_PAGE,
215 send_to_mobile_available);
216}
217
218////////////////////////////////////////////////////////////////////////////////
219// BrowserCommandController,
220// CommandUpdater::CommandUpdaterDelegate implementation:
221
222void BrowserCommandController::ExecuteCommandWithDisposition(
223 int id, WindowOpenDisposition disposition) {
224 // No commands are enabled if there is not yet any selected tab.
225 // TODO(pkasting): It seems like we should not need this, because either
226 // most/all commands should not have been enabled yet anyway or the ones that
227 // are enabled should be global, or safe themselves against having no selected
228 // tab. However, Ben says he tried removing this before and got lots of
229 // crashes, e.g. from Windows sending WM_COMMANDs at random times during
230 // window construction. This probably could use closer examination someday.
231 if (!browser_->GetActiveTabContents())
232 return;
233
234 DCHECK(command_updater_.IsCommandEnabled(id)) << "Invalid/disabled command "
235 << id;
236
237 // If command execution is blocked then just record the command and return.
238 if (block_command_execution_) {
239 // We actually only allow no more than one blocked command, otherwise some
240 // commands maybe lost.
241 DCHECK_EQ(last_blocked_command_id_, -1);
242 last_blocked_command_id_ = id;
243 last_blocked_command_disposition_ = disposition;
244 return;
245 }
246
247 // The order of commands in this switch statement must match the function
248 // declaration order in browser.h!
249 switch (id) {
250 // Navigation commands
251 case IDC_BACK:
252 GoBack(browser_, disposition);
253 break;
254 case IDC_FORWARD:
255 GoForward(browser_, disposition);
256 break;
257 case IDC_RELOAD:
258 Reload(browser_, disposition);
259 break;
260 case IDC_RELOAD_IGNORING_CACHE:
261 ReloadIgnoringCache(browser_, disposition);
262 break;
263 case IDC_HOME:
264 Home(browser_, disposition);
265 break;
266 case IDC_OPEN_CURRENT_URL:
267 OpenCurrentURL(browser_);
268 break;
269 case IDC_STOP:
270 Stop(browser_);
271 break;
272
273 // Window management commands
274 case IDC_NEW_WINDOW:
275 NewWindow(browser_);
276 break;
277 case IDC_NEW_INCOGNITO_WINDOW:
278 NewIncognitoWindow(browser_);
279 break;
280 case IDC_CLOSE_WINDOW:
281 CloseWindow(browser_);
282 break;
283 case IDC_NEW_TAB:
284 NewTab(browser_);
285 break;
286 case IDC_CLOSE_TAB:
287 CloseTab(browser_);
288 break;
289 case IDC_SELECT_NEXT_TAB:
290 SelectNextTab(browser_);
291 break;
292 case IDC_SELECT_PREVIOUS_TAB:
293 SelectPreviousTab(browser_);
294 break;
295 case IDC_TABPOSE:
296 OpenTabpose(browser_);
297 break;
298 case IDC_MOVE_TAB_NEXT:
299 MoveTabNext(browser_);
300 break;
301 case IDC_MOVE_TAB_PREVIOUS:
302 MoveTabPrevious(browser_);
303 break;
304 case IDC_SELECT_TAB_0:
305 case IDC_SELECT_TAB_1:
306 case IDC_SELECT_TAB_2:
307 case IDC_SELECT_TAB_3:
308 case IDC_SELECT_TAB_4:
309 case IDC_SELECT_TAB_5:
310 case IDC_SELECT_TAB_6:
311 case IDC_SELECT_TAB_7:
312 SelectNumberedTab(browser_, id - IDC_SELECT_TAB_0);
313 break;
314 case IDC_SELECT_LAST_TAB:
315 SelectLastTab(browser_);
316 break;
317 case IDC_DUPLICATE_TAB:
318 DuplicateTab(browser_);
319 break;
320 case IDC_RESTORE_TAB:
321 RestoreTab(browser_);
322 break;
323 case IDC_COPY_URL:
324 WriteCurrentURLToClipboard(browser_);
325 break;
326 case IDC_SHOW_AS_TAB:
327 ConvertPopupToTabbedBrowser(browser_);
328 break;
329 case IDC_FULLSCREEN:
330 browser_->ToggleFullscreenMode();
331 break;
332#if defined(OS_WIN)
333 case IDC_METRO_SNAP_ENABLE:
334 browser_->SetMetroSnapMode(true);
335 break;
336 case IDC_METRO_SNAP_DISABLE:
337 browser_->SetMetroSnapMode(false);
338 break;
339#endif
340#if defined(OS_MACOSX)
341 case IDC_PRESENTATION_MODE:
342 browser_->TogglePresentationMode();
343 break;
344#endif
345 case IDC_EXIT:
346 Exit();
347 break;
348
349 // Page-related commands
350 case IDC_SAVE_PAGE:
351 SavePage(browser_);
352 break;
353 case IDC_BOOKMARK_PAGE:
354 BookmarkCurrentPage(browser_);
355 break;
356 case IDC_PIN_TO_START_SCREEN:
357 PinCurrentPageToStartScreen(browser_);
358 break;
359 case IDC_BOOKMARK_ALL_TABS:
360 BookmarkAllTabs(browser_);
361 break;
362 case IDC_VIEW_SOURCE:
363 ViewSelectedSource(browser_);
364 break;
365 case IDC_EMAIL_PAGE_LOCATION:
366 EmailPageLocation(browser_);
367 break;
368 case IDC_PRINT:
369 Print(browser_);
370 break;
371 case IDC_ADVANCED_PRINT:
372 AdvancedPrint(browser_);
373 break;
[email protected]d53e4032012-06-29 18:58:34374 case IDC_PRINT_TO_DESTINATION:
375 PrintToDestination(browser_);
376 break;
[email protected]5d98294912012-06-27 22:57:40377 case IDC_CHROME_TO_MOBILE_PAGE:
378 ShowChromeToMobileBubble(browser_);
379 break;
380 case IDC_ENCODING_AUTO_DETECT:
381 browser_->ToggleEncodingAutoDetect();
382 break;
383 case IDC_ENCODING_UTF8:
384 case IDC_ENCODING_UTF16LE:
385 case IDC_ENCODING_ISO88591:
386 case IDC_ENCODING_WINDOWS1252:
387 case IDC_ENCODING_GBK:
388 case IDC_ENCODING_GB18030:
389 case IDC_ENCODING_BIG5HKSCS:
390 case IDC_ENCODING_BIG5:
391 case IDC_ENCODING_KOREAN:
392 case IDC_ENCODING_SHIFTJIS:
393 case IDC_ENCODING_ISO2022JP:
394 case IDC_ENCODING_EUCJP:
395 case IDC_ENCODING_THAI:
396 case IDC_ENCODING_ISO885915:
397 case IDC_ENCODING_MACINTOSH:
398 case IDC_ENCODING_ISO88592:
399 case IDC_ENCODING_WINDOWS1250:
400 case IDC_ENCODING_ISO88595:
401 case IDC_ENCODING_WINDOWS1251:
402 case IDC_ENCODING_KOI8R:
403 case IDC_ENCODING_KOI8U:
404 case IDC_ENCODING_ISO88597:
405 case IDC_ENCODING_WINDOWS1253:
406 case IDC_ENCODING_ISO88594:
407 case IDC_ENCODING_ISO885913:
408 case IDC_ENCODING_WINDOWS1257:
409 case IDC_ENCODING_ISO88593:
410 case IDC_ENCODING_ISO885910:
411 case IDC_ENCODING_ISO885914:
412 case IDC_ENCODING_ISO885916:
413 case IDC_ENCODING_WINDOWS1254:
414 case IDC_ENCODING_ISO88596:
415 case IDC_ENCODING_WINDOWS1256:
416 case IDC_ENCODING_ISO88598:
417 case IDC_ENCODING_ISO88598I:
418 case IDC_ENCODING_WINDOWS1255:
419 case IDC_ENCODING_WINDOWS1258:
420 browser_->OverrideEncoding(id);
421 break;
422
423 // Clipboard commands
424 case IDC_CUT:
425 Cut(browser_);
426 break;
427 case IDC_COPY:
428 Copy(browser_);
429 break;
430 case IDC_PASTE:
431 Paste(browser_);
432 break;
433
434 // Find-in-page
435 case IDC_FIND:
436 Find(browser_);
437 break;
438 case IDC_FIND_NEXT:
439 FindNext(browser_);
440 break;
441 case IDC_FIND_PREVIOUS:
442 FindPrevious(browser_);
443 break;
444
445 // Zoom
446 case IDC_ZOOM_PLUS:
447 Zoom(browser_, content::PAGE_ZOOM_IN);
448 break;
449 case IDC_ZOOM_NORMAL:
450 Zoom(browser_, content::PAGE_ZOOM_RESET);
451 break;
452 case IDC_ZOOM_MINUS:
453 Zoom(browser_, content::PAGE_ZOOM_OUT);
454 break;
455
456 // Focus various bits of UI
457 case IDC_FOCUS_TOOLBAR:
458 FocusToolbar(browser_);
459 break;
460 case IDC_FOCUS_LOCATION:
461 FocusLocationBar(browser_);
462 break;
463 case IDC_FOCUS_SEARCH:
464 FocusSearch(browser_);
465 break;
466 case IDC_FOCUS_MENU_BAR:
467 FocusAppMenu(browser_);
468 break;
469 case IDC_FOCUS_BOOKMARKS:
470 FocusBookmarksToolbar(browser_);
471 break;
472 case IDC_FOCUS_NEXT_PANE:
473 FocusNextPane(browser_);
474 break;
475 case IDC_FOCUS_PREVIOUS_PANE:
476 FocusPreviousPane(browser_);
477 break;
478
479 // Show various bits of UI
480 case IDC_OPEN_FILE:
481 browser_->OpenFile();
482 break;
483 case IDC_CREATE_SHORTCUTS:
484 browser_->OpenCreateShortcutsDialog();
485 break;
486 case IDC_DEV_TOOLS:
487 ToggleDevToolsWindow(browser_, DEVTOOLS_TOGGLE_ACTION_NONE);
488 break;
489 case IDC_DEV_TOOLS_CONSOLE:
490 ToggleDevToolsWindow(browser_, DEVTOOLS_TOGGLE_ACTION_SHOW_CONSOLE);
491 break;
492 case IDC_DEV_TOOLS_INSPECT:
493 ToggleDevToolsWindow(browser_, DEVTOOLS_TOGGLE_ACTION_INSPECT);
494 break;
495 case IDC_TASK_MANAGER:
496 OpenTaskManager(browser_, false);
497 break;
498 case IDC_VIEW_BACKGROUND_PAGES:
499 OpenTaskManager(browser_, true);
500 break;
501 case IDC_FEEDBACK:
502 OpenFeedbackDialog(browser_);
503 break;
504
505 case IDC_SHOW_BOOKMARK_BAR:
506 ToggleBookmarkBar(browser_);
507 break;
508 case IDC_PROFILING_ENABLED:
509 Profiling::Toggle();
510 break;
511
512 case IDC_SHOW_BOOKMARK_MANAGER:
513 ShowBookmarkManager(browser_);
514 break;
515 case IDC_SHOW_APP_MENU:
516 ShowAppMenu(browser_);
517 break;
518 case IDC_SHOW_AVATAR_MENU:
519 ShowAvatarMenu(browser_);
520 break;
521 case IDC_SHOW_HISTORY:
522 ShowHistory(browser_);
523 break;
524 case IDC_SHOW_DOWNLOADS:
525 ShowDownloads(browser_);
526 break;
527 case IDC_MANAGE_EXTENSIONS:
528 ShowExtensions(browser_);
529 break;
530 case IDC_OPTIONS:
531 ShowSettings(browser_);
532 break;
533 case IDC_EDIT_SEARCH_ENGINES:
534 ShowSearchEngineSettings(browser_);
535 break;
536 case IDC_VIEW_PASSWORDS:
537 ShowPasswordManager(browser_);
538 break;
539 case IDC_CLEAR_BROWSING_DATA:
540 ShowClearBrowsingDataDialog(browser_);
541 break;
542 case IDC_IMPORT_SETTINGS:
543 ShowImportDialog(browser_);
544 break;
545 case IDC_ABOUT:
546 ShowAboutChrome(browser_);
547 break;
548 case IDC_UPGRADE_DIALOG:
549 OpenUpdateChromeDialog(browser_);
550 break;
551 case IDC_VIEW_INCOMPATIBILITIES:
552 ShowConflicts(browser_);
553 break;
554 case IDC_HELP_PAGE_VIA_KEYBOARD:
555 ShowHelp(browser_, HELP_SOURCE_KEYBOARD);
556 break;
557 case IDC_HELP_PAGE_VIA_MENU:
558 ShowHelp(browser_, HELP_SOURCE_MENU);
559 break;
560 case IDC_SHOW_SYNC_SETUP:
561 ShowSyncSetup(browser_, SyncPromoUI::SOURCE_MENU);
562 break;
563 case IDC_TOGGLE_SPEECH_INPUT:
564 ToggleSpeechInput(browser_);
565 break;
566
567 default:
568 LOG(WARNING) << "Received Unimplemented Command: " << id;
569 break;
570 }
571}
572
573////////////////////////////////////////////////////////////////////////////////
574// BrowserCommandController, content::NotificationObserver implementation:
575
576void BrowserCommandController::Observe(
577 int type,
578 const content::NotificationSource& source,
579 const content::NotificationDetails& details) {
580 switch (type) {
581 case NOTIFICATION_PREF_CHANGED: {
582 const std::string& pref_name =
583 *content::Details<std::string>(details).ptr();
584 if (pref_name == prefs::kPrintingEnabled) {
585 UpdatePrintingState();
586 } else if (pref_name == prefs::kIncognitoModeAvailability) {
587 UpdateCommandsForIncognitoAvailability();
588 } else if (pref_name == prefs::kDevToolsDisabled) {
589 UpdateCommandsForDevTools();
590 } else if (pref_name == prefs::kEditBookmarksEnabled) {
591 UpdateCommandsForBookmarkEditing();
592 } else if (pref_name == prefs::kShowBookmarkBar) {
593 UpdateCommandsForBookmarkBar();
594 } else if (pref_name == prefs::kAllowFileSelectionDialogs) {
595 UpdateSaveAsState();
596 UpdateOpenFileState();
597 } else if (pref_name == prefs::kInManagedMode) {
598 UpdateCommandsForMultipleProfiles();
599 } else {
600 NOTREACHED();
601 }
602 break;
603 }
604 case content::NOTIFICATION_INTERSTITIAL_ATTACHED:
605 UpdateCommandsForTabState();
606 break;
607
608 case content::NOTIFICATION_INTERSTITIAL_DETACHED:
609 UpdateCommandsForTabState();
610 break;
611
612 default:
613 NOTREACHED() << "Got a notification we didn't register for.";
614 }
615}
616
617////////////////////////////////////////////////////////////////////////////////
618// BrowserCommandController, TabStripModelObserver implementation:
619
620void BrowserCommandController::TabInsertedAt(TabContents* contents,
621 int index,
622 bool foreground) {
623 AddInterstitialObservers(contents);
624}
625
626void BrowserCommandController::TabDetachedAt(TabContents* contents, int index) {
627 RemoveInterstitialObservers(contents);
628}
629
630void BrowserCommandController::TabReplacedAt(TabStripModel* tab_strip_model,
631 TabContents* old_contents,
632 TabContents* new_contents,
633 int index) {
634 RemoveInterstitialObservers(old_contents);
635 AddInterstitialObservers(new_contents);
636}
637
638////////////////////////////////////////////////////////////////////////////////
639// BrowserCommandController, TabRestoreServiceObserver implementation:
640
641void BrowserCommandController::TabRestoreServiceChanged(
642 TabRestoreService* service) {
643 command_updater_.UpdateCommandEnabled(IDC_RESTORE_TAB,
644 CanRestoreTab(browser_));
645}
646
647void BrowserCommandController::TabRestoreServiceDestroyed(
648 TabRestoreService* service) {
649 service->RemoveObserver(this);
650}
651
652////////////////////////////////////////////////////////////////////////////////
653// BrowserCommandController, ProfileSyncServiceObserver implementation:
654
655void BrowserCommandController::OnStateChanged() {
656 DCHECK(ProfileSyncServiceFactory::GetInstance()->HasProfileSyncService(
657 profile()));
658 // For unit tests, we don't have a window.
659 if (!window())
660 return;
661 const bool show_main_ui = IsShowingMainUI(window()->IsFullscreen());
662 command_updater_.UpdateCommandEnabled(IDC_SHOW_SYNC_SETUP,
663 show_main_ui && profile()->GetOriginalProfile()->IsSyncAccessible());
664}
665
666////////////////////////////////////////////////////////////////////////////////
667// BrowserCommandController, private:
668
669bool BrowserCommandController::IsShowingMainUI(bool is_fullscreen) {
670#if !defined(OS_MACOSX)
671 return browser_->is_type_tabbed() && !is_fullscreen;
672#else
673 return browser_->is_type_tabbed();
674#endif
675}
676
677void BrowserCommandController::InitCommandState() {
678 // All browser commands whose state isn't set automagically some other way
679 // (like Back & Forward with initial page load) must have their state
680 // initialized here, otherwise they will be forever disabled.
681
682 // Navigation commands
683 command_updater_.UpdateCommandEnabled(IDC_RELOAD, true);
684 command_updater_.UpdateCommandEnabled(IDC_RELOAD_IGNORING_CACHE, true);
685
686 // Window management commands
687 command_updater_.UpdateCommandEnabled(IDC_CLOSE_WINDOW, true);
688 command_updater_.UpdateCommandEnabled(IDC_NEW_TAB, true);
689 command_updater_.UpdateCommandEnabled(IDC_CLOSE_TAB, true);
690 command_updater_.UpdateCommandEnabled(IDC_DUPLICATE_TAB, true);
691 command_updater_.UpdateCommandEnabled(IDC_RESTORE_TAB, false);
692 command_updater_.UpdateCommandEnabled(IDC_EXIT, true);
693 command_updater_.UpdateCommandEnabled(IDC_DEBUG_FRAME_TOGGLE, true);
694
695 // Page-related commands
696 command_updater_.UpdateCommandEnabled(IDC_EMAIL_PAGE_LOCATION, true);
697 command_updater_.UpdateCommandEnabled(IDC_ENCODING_AUTO_DETECT, true);
698 command_updater_.UpdateCommandEnabled(IDC_ENCODING_UTF8, true);
699 command_updater_.UpdateCommandEnabled(IDC_ENCODING_UTF16LE, true);
700 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88591, true);
701 command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1252, true);
702 command_updater_.UpdateCommandEnabled(IDC_ENCODING_GBK, true);
703 command_updater_.UpdateCommandEnabled(IDC_ENCODING_GB18030, true);
704 command_updater_.UpdateCommandEnabled(IDC_ENCODING_BIG5HKSCS, true);
705 command_updater_.UpdateCommandEnabled(IDC_ENCODING_BIG5, true);
706 command_updater_.UpdateCommandEnabled(IDC_ENCODING_THAI, true);
707 command_updater_.UpdateCommandEnabled(IDC_ENCODING_KOREAN, true);
708 command_updater_.UpdateCommandEnabled(IDC_ENCODING_SHIFTJIS, true);
709 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO2022JP, true);
710 command_updater_.UpdateCommandEnabled(IDC_ENCODING_EUCJP, true);
711 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO885915, true);
712 command_updater_.UpdateCommandEnabled(IDC_ENCODING_MACINTOSH, true);
713 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88592, true);
714 command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1250, true);
715 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88595, true);
716 command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1251, true);
717 command_updater_.UpdateCommandEnabled(IDC_ENCODING_KOI8R, true);
718 command_updater_.UpdateCommandEnabled(IDC_ENCODING_KOI8U, true);
719 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88597, true);
720 command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1253, true);
721 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88594, true);
722 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO885913, true);
723 command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1257, true);
724 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88593, true);
725 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO885910, true);
726 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO885914, true);
727 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO885916, true);
728 command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1254, true);
729 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88596, true);
730 command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1256, true);
731 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88598, true);
732 command_updater_.UpdateCommandEnabled(IDC_ENCODING_ISO88598I, true);
733 command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1255, true);
734 command_updater_.UpdateCommandEnabled(IDC_ENCODING_WINDOWS1258, true);
735
736 // Zoom
737 command_updater_.UpdateCommandEnabled(IDC_ZOOM_MENU, true);
738 command_updater_.UpdateCommandEnabled(IDC_ZOOM_PLUS, true);
739 command_updater_.UpdateCommandEnabled(IDC_ZOOM_NORMAL, true);
740 command_updater_.UpdateCommandEnabled(IDC_ZOOM_MINUS, true);
741
742 // Show various bits of UI
743 UpdateOpenFileState();
744 command_updater_.UpdateCommandEnabled(IDC_CREATE_SHORTCUTS, false);
745 UpdateCommandsForDevTools();
746 command_updater_.UpdateCommandEnabled(IDC_TASK_MANAGER, CanOpenTaskManager());
747 command_updater_.UpdateCommandEnabled(IDC_SHOW_HISTORY, true);
748 command_updater_.UpdateCommandEnabled(IDC_SHOW_DOWNLOADS, true);
749 command_updater_.UpdateCommandEnabled(IDC_HELP_PAGE_VIA_KEYBOARD, true);
750 command_updater_.UpdateCommandEnabled(IDC_HELP_PAGE_VIA_MENU, true);
751 command_updater_.UpdateCommandEnabled(IDC_BOOKMARKS_MENU, true);
752
753 command_updater_.UpdateCommandEnabled(
754 IDC_SHOW_SYNC_SETUP, profile()->GetOriginalProfile()->IsSyncAccessible());
755
756 // Initialize other commands based on the window type.
757 bool normal_window = browser_->is_type_tabbed();
758
759 // Navigation commands
760 command_updater_.UpdateCommandEnabled(IDC_HOME, normal_window);
761
762 // Window management commands
763 // TODO(rohitrao): Disable fullscreen on non-Lion?
764 command_updater_.UpdateCommandEnabled(IDC_FULLSCREEN,
765 !(browser_->is_type_panel() && browser_->is_app()));
766 command_updater_.UpdateCommandEnabled(IDC_SELECT_NEXT_TAB, normal_window);
767 command_updater_.UpdateCommandEnabled(IDC_SELECT_PREVIOUS_TAB,
768 normal_window);
769 command_updater_.UpdateCommandEnabled(IDC_MOVE_TAB_NEXT, normal_window);
770 command_updater_.UpdateCommandEnabled(IDC_MOVE_TAB_PREVIOUS, normal_window);
771 command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_0, normal_window);
772 command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_1, normal_window);
773 command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_2, normal_window);
774 command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_3, normal_window);
775 command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_4, normal_window);
776 command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_5, normal_window);
777 command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_6, normal_window);
778 command_updater_.UpdateCommandEnabled(IDC_SELECT_TAB_7, normal_window);
779 command_updater_.UpdateCommandEnabled(IDC_SELECT_LAST_TAB, normal_window);
780#if defined(OS_WIN)
781 const bool metro_mode = base::win::IsMetroProcess();
782 command_updater_.UpdateCommandEnabled(IDC_METRO_SNAP_ENABLE, metro_mode);
783 command_updater_.UpdateCommandEnabled(IDC_METRO_SNAP_DISABLE, metro_mode);
784#endif
785#if defined(OS_MACOSX)
786 command_updater_.UpdateCommandEnabled(IDC_TABPOSE, normal_window);
787 command_updater_.UpdateCommandEnabled(IDC_PRESENTATION_MODE,
788 !(browser_->is_type_panel() && browser_->is_app()));
789#endif
790
791 // Clipboard commands
792 command_updater_.UpdateCommandEnabled(IDC_COPY_URL, !browser_->is_devtools());
793
794 // Find-in-page
795 command_updater_.UpdateCommandEnabled(IDC_FIND, !browser_->is_devtools());
796 command_updater_.UpdateCommandEnabled(IDC_FIND_NEXT,
797 !browser_->is_devtools());
798 command_updater_.UpdateCommandEnabled(IDC_FIND_PREVIOUS,
799 !browser_->is_devtools());
800
801 // Show various bits of UI
802 command_updater_.UpdateCommandEnabled(IDC_CLEAR_BROWSING_DATA, normal_window);
803
804 // The upgrade entry and the view incompatibility entry should always be
805 // enabled. Whether they are visible is a separate matter determined on menu
806 // show.
807 command_updater_.UpdateCommandEnabled(IDC_UPGRADE_DIALOG, true);
808 command_updater_.UpdateCommandEnabled(IDC_VIEW_INCOMPATIBILITIES, true);
809
810 // View Background Pages entry is always enabled, but is hidden if there are
811 // no background pages.
812 command_updater_.UpdateCommandEnabled(IDC_VIEW_BACKGROUND_PAGES, true);
813
814 // Toggle speech input
815 command_updater_.UpdateCommandEnabled(IDC_TOGGLE_SPEECH_INPUT, true);
816
817 // Initialize other commands whose state changes based on fullscreen mode.
818 UpdateCommandsForFullscreenMode(FULLSCREEN_DISABLED);
819
820 UpdateCommandsForContentRestrictionState();
821
822 UpdateCommandsForBookmarkEditing();
823
824 UpdateCommandsForIncognitoAvailability();
825}
826
827void BrowserCommandController::UpdateCommandsForIncognitoAvailability() {
828 IncognitoModePrefs::Availability incognito_availability =
829 IncognitoModePrefs::GetAvailability(profile()->GetPrefs());
830 command_updater_.UpdateCommandEnabled(
831 IDC_NEW_WINDOW,
832 incognito_availability != IncognitoModePrefs::FORCED);
833 command_updater_.UpdateCommandEnabled(
834 IDC_NEW_INCOGNITO_WINDOW,
835 incognito_availability != IncognitoModePrefs::DISABLED);
836
837 // Bookmark manager and settings page/subpages are forced to open in normal
838 // mode. For this reason we disable these commands when incognito is forced.
839 const bool command_enabled =
840 incognito_availability != IncognitoModePrefs::FORCED;
841 command_updater_.UpdateCommandEnabled(
842 IDC_SHOW_BOOKMARK_MANAGER,
843 browser_defaults::bookmarks_enabled && command_enabled);
844 ExtensionService* extension_service = profile()->GetExtensionService();
845 bool enable_extensions =
846 extension_service && extension_service->extensions_enabled();
847 command_updater_.UpdateCommandEnabled(IDC_MANAGE_EXTENSIONS,
848 enable_extensions && command_enabled);
849
850 const bool show_main_ui =
851 IsShowingMainUI(window() && window()->IsFullscreen());
852 command_updater_.UpdateCommandEnabled(IDC_IMPORT_SETTINGS,
853 show_main_ui && command_enabled);
854 command_updater_.UpdateCommandEnabled(IDC_OPTIONS,
855 show_main_ui && command_enabled);
856}
857
858void BrowserCommandController::UpdateCommandsForTabState() {
859 TabContents* current_tab_contents = browser_->GetActiveTabContents();
860 if (!current_tab_contents) // May be NULL during tab restore.
861 return;
862 WebContents* current_web_contents = current_tab_contents->web_contents();
863
864 // Navigation commands
865 command_updater_.UpdateCommandEnabled(IDC_BACK, CanGoBack(browser_));
866 command_updater_.UpdateCommandEnabled(IDC_FORWARD, CanGoForward(browser_));
867 command_updater_.UpdateCommandEnabled(IDC_RELOAD, CanReload(browser_));
868 command_updater_.UpdateCommandEnabled(IDC_RELOAD_IGNORING_CACHE,
869 CanReload(browser_));
870
871 // Window management commands
872 command_updater_.UpdateCommandEnabled(IDC_DUPLICATE_TAB,
873 !browser_->is_app() && CanDuplicateTab(browser_));
874
875 // Page-related commands
876 window()->SetStarredState(
877 current_tab_contents->bookmark_tab_helper()->is_starred());
878 window()->SetZoomIconState(
879 current_tab_contents->zoom_controller()->zoom_icon_state());
880 window()->SetZoomIconTooltipPercent(
881 current_tab_contents->zoom_controller()->zoom_percent());
882 command_updater_.UpdateCommandEnabled(IDC_VIEW_SOURCE,
883 CanViewSource(browser_));
884 command_updater_.UpdateCommandEnabled(IDC_EMAIL_PAGE_LOCATION,
885 CanEmailPageLocation(browser_));
886 if (browser_->is_devtools())
887 command_updater_.UpdateCommandEnabled(IDC_OPEN_FILE, false);
888
889 // Changing the encoding is not possible on Chrome-internal webpages.
890 NavigationController& nc = current_web_contents->GetController();
891 bool is_chrome_internal = HasInternalURL(nc.GetActiveEntry()) ||
892 current_web_contents->ShowingInterstitialPage();
893 command_updater_.UpdateCommandEnabled(IDC_ENCODING_MENU,
894 !is_chrome_internal && current_web_contents->IsSavable());
895
896 // Show various bits of UI
897 // TODO(pinkerton): Disable app-mode in the model until we implement it
898 // on the Mac. Be sure to remove both ifdefs. http://crbug.com/13148
899#if !defined(OS_MACOSX)
900 command_updater_.UpdateCommandEnabled(
901 IDC_CREATE_SHORTCUTS,
902 CanCreateApplicationShortcuts(browser_));
903#endif
904
905 UpdateCommandsForContentRestrictionState();
906 UpdateCommandsForBookmarkEditing();
907}
908
909void BrowserCommandController::UpdateCommandsForContentRestrictionState() {
910 int restrictions = GetContentRestrictions(browser_);
911
912 command_updater_.UpdateCommandEnabled(
913 IDC_COPY, !(restrictions & content::CONTENT_RESTRICTION_COPY));
914 command_updater_.UpdateCommandEnabled(
915 IDC_CUT, !(restrictions & content::CONTENT_RESTRICTION_CUT));
916 command_updater_.UpdateCommandEnabled(
917 IDC_PASTE, !(restrictions & content::CONTENT_RESTRICTION_PASTE));
918 UpdateSaveAsState();
919 UpdatePrintingState();
920}
921
922void BrowserCommandController::UpdateCommandsForDevTools() {
923 bool dev_tools_enabled =
924 !profile()->GetPrefs()->GetBoolean(prefs::kDevToolsDisabled);
925 command_updater_.UpdateCommandEnabled(IDC_DEV_TOOLS,
926 dev_tools_enabled);
927 command_updater_.UpdateCommandEnabled(IDC_DEV_TOOLS_CONSOLE,
928 dev_tools_enabled);
929 command_updater_.UpdateCommandEnabled(IDC_DEV_TOOLS_INSPECT,
930 dev_tools_enabled);
931}
932
933void BrowserCommandController::UpdateCommandsForBookmarkEditing() {
934 command_updater_.UpdateCommandEnabled(IDC_BOOKMARK_PAGE,
935 CanBookmarkCurrentPage(browser_));
936 command_updater_.UpdateCommandEnabled(IDC_BOOKMARK_ALL_TABS,
937 CanBookmarkAllTabs(browser_));
938 command_updater_.UpdateCommandEnabled(IDC_PIN_TO_START_SCREEN,
939 true);
940}
941
942void BrowserCommandController::UpdateCommandsForBookmarkBar() {
943 const bool show_main_ui =
944 IsShowingMainUI(window() && window()->IsFullscreen());
945 command_updater_.UpdateCommandEnabled(IDC_SHOW_BOOKMARK_BAR,
946 browser_defaults::bookmarks_enabled &&
947 !profile()->GetPrefs()->IsManagedPreference(prefs::kShowBookmarkBar) &&
948 show_main_ui);
949}
950
951void BrowserCommandController::UpdateCommandsForFullscreenMode(
952 FullScreenMode fullscreen_mode) {
953 const bool show_main_ui =
954 IsShowingMainUI(fullscreen_mode != FULLSCREEN_DISABLED);
955 bool main_not_fullscreen = show_main_ui &&
956 (fullscreen_mode == FULLSCREEN_DISABLED);
957
958 // Navigation commands
959 command_updater_.UpdateCommandEnabled(IDC_OPEN_CURRENT_URL, show_main_ui);
960
961 // Window management commands
962 command_updater_.UpdateCommandEnabled(
963 IDC_SHOW_AS_TAB,
964 !browser_->is_type_tabbed() && fullscreen_mode == FULLSCREEN_DISABLED);
965
966 // Focus various bits of UI
967 command_updater_.UpdateCommandEnabled(IDC_FOCUS_TOOLBAR, show_main_ui);
968 command_updater_.UpdateCommandEnabled(IDC_FOCUS_LOCATION, show_main_ui);
969 command_updater_.UpdateCommandEnabled(IDC_FOCUS_SEARCH, show_main_ui);
970 command_updater_.UpdateCommandEnabled(
971 IDC_FOCUS_MENU_BAR, main_not_fullscreen);
972 command_updater_.UpdateCommandEnabled(
973 IDC_FOCUS_NEXT_PANE, main_not_fullscreen);
974 command_updater_.UpdateCommandEnabled(
975 IDC_FOCUS_PREVIOUS_PANE, main_not_fullscreen);
976 command_updater_.UpdateCommandEnabled(
977 IDC_FOCUS_BOOKMARKS, main_not_fullscreen);
978
979 // Show various bits of UI
980 command_updater_.UpdateCommandEnabled(IDC_DEVELOPER_MENU, show_main_ui);
981 command_updater_.UpdateCommandEnabled(IDC_FEEDBACK, show_main_ui);
982 command_updater_.UpdateCommandEnabled(IDC_SHOW_SYNC_SETUP,
983 show_main_ui && profile()->GetOriginalProfile()->IsSyncAccessible());
984
985 // Settings page/subpages are forced to open in normal mode. We disable these
986 // commands when incognito is forced.
987 const bool options_enabled = show_main_ui &&
988 IncognitoModePrefs::GetAvailability(
989 profile()->GetPrefs()) != IncognitoModePrefs::FORCED;
990 command_updater_.UpdateCommandEnabled(IDC_OPTIONS, options_enabled);
991 command_updater_.UpdateCommandEnabled(IDC_IMPORT_SETTINGS, options_enabled);
992
993 command_updater_.UpdateCommandEnabled(IDC_EDIT_SEARCH_ENGINES, show_main_ui);
994 command_updater_.UpdateCommandEnabled(IDC_VIEW_PASSWORDS, show_main_ui);
995 command_updater_.UpdateCommandEnabled(IDC_ABOUT, show_main_ui);
996 command_updater_.UpdateCommandEnabled(IDC_SHOW_APP_MENU, show_main_ui);
997#if defined (ENABLE_PROFILING) && !defined(NO_TCMALLOC)
998 command_updater_.UpdateCommandEnabled(IDC_PROFILING_ENABLED, show_main_ui);
999#endif
1000
1001 // Disable explicit fullscreen toggling when in metro snap mode.
1002 command_updater_.UpdateCommandEnabled(
1003 IDC_FULLSCREEN,
1004 fullscreen_mode != FULLSCREEN_METRO_SNAP);
1005
1006 UpdateCommandsForBookmarkBar();
1007 UpdateCommandsForMultipleProfiles();
1008}
1009
1010void BrowserCommandController::UpdateCommandsForMultipleProfiles() {
1011 bool show_main_ui = IsShowingMainUI(window() && window()->IsFullscreen());
1012 command_updater_.UpdateCommandEnabled(IDC_SHOW_AVATAR_MENU,
1013 show_main_ui &&
1014 !profile()->IsOffTheRecord() &&
1015 ProfileManager::IsMultipleProfilesEnabled());
1016}
1017
1018void BrowserCommandController::UpdatePrintingState() {
[email protected]d53e4032012-06-29 18:58:341019 bool print_enabled = CanPrint(browser_);
1020 command_updater_.UpdateCommandEnabled(IDC_PRINT, print_enabled);
[email protected]5d98294912012-06-27 22:57:401021 command_updater_.UpdateCommandEnabled(IDC_ADVANCED_PRINT,
1022 CanAdvancedPrint(browser_));
[email protected]d53e4032012-06-29 18:58:341023 command_updater_.UpdateCommandEnabled(IDC_PRINT_TO_DESTINATION,
1024 print_enabled);
1025#if defined(OS_WIN)
1026 HMODULE metro_module = base::win::GetMetroModule();
1027 if (metro_module != NULL) {
1028 typedef void (*MetroEnablePrinting)(BOOL);
1029 MetroEnablePrinting metro_enable_printing =
1030 reinterpret_cast<MetroEnablePrinting>(
1031 ::GetProcAddress(metro_module, "MetroEnablePrinting"));
1032 if (metro_enable_printing)
1033 metro_enable_printing(print_enabled);
1034 }
1035#endif
[email protected]5d98294912012-06-27 22:57:401036}
1037
1038void BrowserCommandController::UpdateSaveAsState() {
1039 command_updater_.UpdateCommandEnabled(IDC_SAVE_PAGE, CanSavePage(browser_));
1040}
1041
1042void BrowserCommandController::UpdateOpenFileState() {
1043 bool enabled = true;
1044 PrefService* local_state = g_browser_process->local_state();
1045 if (local_state)
1046 enabled = local_state->GetBoolean(prefs::kAllowFileSelectionDialogs);
1047
1048 command_updater_.UpdateCommandEnabled(IDC_OPEN_FILE, enabled);
1049}
1050
1051void BrowserCommandController::UpdateReloadStopState(bool is_loading,
1052 bool force) {
1053 window()->UpdateReloadStopState(is_loading, force);
1054 command_updater_.UpdateCommandEnabled(IDC_STOP, is_loading);
1055}
1056
1057void BrowserCommandController::AddInterstitialObservers(TabContents* contents) {
1058 registrar_.Add(this, content::NOTIFICATION_INTERSTITIAL_ATTACHED,
1059 content::Source<WebContents>(contents->web_contents()));
1060 registrar_.Add(this, content::NOTIFICATION_INTERSTITIAL_DETACHED,
1061 content::Source<WebContents>(contents->web_contents()));
1062}
1063
1064void BrowserCommandController::RemoveInterstitialObservers(
1065 TabContents* contents) {
1066 registrar_.Remove(this, content::NOTIFICATION_INTERSTITIAL_ATTACHED,
1067 content::Source<WebContents>(contents->web_contents()));
1068 registrar_.Remove(this, content::NOTIFICATION_INTERSTITIAL_DETACHED,
1069 content::Source<WebContents>(contents->web_contents()));
1070}
1071
1072BrowserWindow* BrowserCommandController::window() {
1073 return browser_->window();
1074}
1075
1076Profile* BrowserCommandController::profile() {
1077 return browser_->profile();
1078}
1079
1080} // namespace chrome