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.
5 #include "chrome/browser/ui/cocoa/browser_window_cocoa.h"
8 #include "base/command_line.h"
9 #include "base/logging.h"
10 #import "base/mac/sdk_forward_declarations.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/prefs/pref_service.h"
13 #include "base/strings/string_util.h"
14 #include "base/strings/sys_string_conversions.h"
15 #include "chrome/app/chrome_command_ids.h"
16 #include "chrome/browser/chrome_notification_types.h"
17 #include "chrome/browser/download/download_shelf.h"
18 #include "chrome/browser/extensions/extension_util.h"
19 #include "chrome/browser/extensions/tab_helper.h"
20 #include "chrome/browser/fullscreen.h"
21 #include "chrome/browser/profiles/profile.h"
22 #include "chrome/browser/shell_integration.h"
23 #include "chrome/browser/signin/chrome_signin_helper.h"
24 #include "chrome/browser/translate/chrome_translate_client.h"
25 #include "chrome/browser/ui/browser.h"
26 #include "chrome/browser/ui/browser_command_controller.h"
27 #include "chrome/browser/ui/browser_commands_mac.h"
28 #include "chrome/browser/ui/browser_list.h"
29 #include "chrome/browser/ui/browser_window_state.h"
30 #import "chrome/browser/ui/cocoa/browser/edit_search_engine_cocoa_controller.h"
31 #import "chrome/browser/ui/cocoa/browser_window_controller.h"
32 #import "chrome/browser/ui/cocoa/browser_window_utils.h"
33 #import "chrome/browser/ui/cocoa/chrome_event_processing_window.h"
34 #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_sheet_controller.h"
35 #import "chrome/browser/ui/cocoa/download/download_shelf_controller.h"
36 #import "chrome/browser/ui/cocoa/extensions/browser_actions_controller.h"
37 #include "chrome/browser/ui/cocoa/find_bar/find_bar_bridge.h"
38 #import "chrome/browser/ui/cocoa/info_bubble_view.h"
39 #include "chrome/browser/ui/cocoa/key_equivalent_constants.h"
40 #import "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h"
41 #import "chrome/browser/ui/cocoa/nsmenuitem_additions.h"
42 #import "chrome/browser/ui/cocoa/profiles/avatar_base_controller.h"
43 #import "chrome/browser/ui/cocoa/profiles/avatar_menu_bubble_controller.h"
44 #include "chrome/browser/ui/cocoa/restart_browser.h"
45 #include "chrome/browser/ui/cocoa/status_bubble_mac.h"
46 #include "chrome/browser/ui/cocoa/task_manager_mac.h"
47 #import "chrome/browser/ui/cocoa/toolbar/toolbar_controller.h"
48 #import "chrome/browser/ui/cocoa/web_dialog_window_controller.h"
49 #import "chrome/browser/ui/cocoa/website_settings/website_settings_bubble_controller.h"
50 #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h"
51 #include "chrome/browser/ui/search/search_model.h"
52 #include "chrome/browser/ui/tabs/tab_strip_model.h"
53 #include "chrome/browser/web_applications/web_app.h"
54 #include "chrome/common/chrome_switches.h"
55 #include "chrome/common/pref_names.h"
56 #include "chrome/grit/generated_resources.h"
57 #include "components/translate/core/browser/language_state.h"
58 #include "content/public/browser/native_web_keyboard_event.h"
59 #include "content/public/browser/notification_details.h"
60 #include "content/public/browser/notification_service.h"
61 #include "content/public/browser/notification_source.h"
62 #include "content/public/browser/web_contents.h"
63 #include "extensions/browser/extension_registry.h"
64 #include "extensions/browser/extension_system.h"
65 #include "extensions/common/constants.h"
66 #include "ui/base/l10n/l10n_util_mac.h"
67 #include "ui/events/keycodes/keyboard_codes.h"
68 #include "ui/gfx/geometry/rect.h"
70 #if defined(ENABLE_ONE_CLICK_SIGNIN)
71 #import "chrome/browser/ui/cocoa/one_click_signin_bubble_controller.h"
72 #import "chrome/browser/ui/cocoa/one_click_signin_dialog_controller.h"
75 using content::NativeWebKeyboardEvent;
76 using content::SSLStatus;
77 using content::WebContents;
81 // These UI constants are used in BrowserWindowCocoa::ShowBookmarkAppBubble.
82 // Used for defining the layout of the NSAlert and NSTextField within the
84 const int kAppTextFieldVerticalSpacing = 2;
85 const int kAppTextFieldWidth = 200;
86 const int kAppTextFieldHeight = 22;
87 const int kBookmarkAppBubbleViewWidth = 200;
88 const int kBookmarkAppBubbleViewHeight = 46;
90 const int kIconPreviewTargetSize = 128;
92 base::string16 TrimText(NSString* controlText) {
93 base::string16 text = base::SysNSStringToUTF16(controlText);
94 base::TrimWhitespace(text, base::TRIM_ALL, &text);
100 @interface TextRequiringDelegate : NSObject<NSTextFieldDelegate> {
102 // Disable |control_| when text changes to just whitespace or empty string.
105 - (id)initWithControl:(NSControl*)control text:(NSString*)text;
106 - (void)controlTextDidChange:(NSNotification*)notification;
109 @interface TextRequiringDelegate ()
110 - (void)validateText:(NSString*)text;
113 @implementation TextRequiringDelegate
114 - (id)initWithControl:(NSControl*)control text:(NSString*)text {
115 if ((self = [super init])) {
117 [self validateText:text];
122 - (void)controlTextDidChange:(NSNotification*)notification {
123 [self validateText:[[notification object] stringValue]];
126 - (void)validateText:(NSString*)text {
127 [control_ setEnabled:TrimText(text).empty() ? NO : YES];
131 BrowserWindowCocoa::BrowserWindowCocoa(Browser* browser,
132 BrowserWindowController* controller)
134 controller_(controller),
135 initial_show_state_(ui::SHOW_STATE_DEFAULT),
136 attention_request_id_(0) {
139 chrome::GetSavedWindowBoundsAndShowState(browser_,
141 &initial_show_state_);
143 browser_->search_model()->AddObserver(this);
146 BrowserWindowCocoa::~BrowserWindowCocoa() {
147 browser_->search_model()->RemoveObserver(this);
150 void BrowserWindowCocoa::Show() {
151 // The Browser associated with this browser window must become the active
152 // browser at the time |Show()| is called. This is the natural behaviour under
153 // Windows, but |-makeKeyAndOrderFront:| won't send |-windowDidBecomeMain:|
154 // until we return to the runloop. Therefore any calls to
155 // |chrome::FindLastActiveWithHostDesktopType| will return the previous
156 // browser instead if we don't explicitly set it here.
157 BrowserList::SetLastActive(browser_);
159 bool is_session_restore = browser_->is_session_restore();
160 NSWindowAnimationBehavior saved_animation_behavior =
161 NSWindowAnimationBehaviorDefault;
162 bool did_save_animation_behavior = false;
163 // Turn off swishing when restoring windows or showing an app.
164 if ((is_session_restore || browser_->is_app()) &&
165 [window() respondsToSelector:@selector(animationBehavior)] &&
166 [window() respondsToSelector:@selector(setAnimationBehavior:)]) {
167 did_save_animation_behavior = true;
168 saved_animation_behavior = [window() animationBehavior];
169 [window() setAnimationBehavior:NSWindowAnimationBehaviorNone];
173 TRACE_EVENT0("ui", "BrowserWindowCocoa::Show Activate");
174 // This call takes up a substantial part of startup time, and an even more
175 // substantial part of startup time when any CALayers are part of the
176 // window's NSView heirarchy.
180 // When creating windows from nibs it is necessary to |makeKeyAndOrderFront:|
181 // prior to |orderOut:| then |miniaturize:| when restoring windows in the
183 if (initial_show_state_ == ui::SHOW_STATE_MINIMIZED) {
184 [window() orderOut:controller_];
185 [window() miniaturize:controller_];
186 } else if (initial_show_state_ == ui::SHOW_STATE_FULLSCREEN) {
187 chrome::ToggleFullscreenWithToolbarOrFallback(browser_);
189 initial_show_state_ = ui::SHOW_STATE_DEFAULT;
191 // Restore window animation behavior.
192 if (did_save_animation_behavior)
193 [window() setAnimationBehavior:saved_animation_behavior];
195 browser_->OnWindowDidShow();
198 void BrowserWindowCocoa::ShowInactive() {
199 [window() orderFront:controller_];
202 void BrowserWindowCocoa::Hide() {
203 [window() orderOut:controller_];
206 void BrowserWindowCocoa::SetBounds(const gfx::Rect& bounds) {
207 gfx::Rect real_bounds = [controller_ enforceMinWindowSize:bounds];
210 NSRect cocoa_bounds = NSMakeRect(real_bounds.x(), 0,
212 real_bounds.height());
213 // Flip coordinates based on the primary screen.
214 NSScreen* screen = [[NSScreen screens] objectAtIndex:0];
215 cocoa_bounds.origin.y =
216 NSHeight([screen frame]) - real_bounds.height() - real_bounds.y();
218 [window() setFrame:cocoa_bounds display:YES];
221 // Callers assume that this doesn't immediately delete the Browser object.
222 // The controller implementing the window delegate methods called from
223 // |-performClose:| must take precautions to ensure that.
224 void BrowserWindowCocoa::Close() {
225 // If there is an overlay window, we contain a tab being dragged between
226 // windows. Don't hide the window as it makes the UI extra confused. We can
227 // still close the window, as that will happen when the drag completes.
228 if ([controller_ overlayWindow]) {
229 [controller_ deferPerformClose];
231 // Using |-performClose:| can prevent the window from actually closing if
232 // a JavaScript beforeunload handler opens an alert during shutdown, as
233 // documented at <http://crbug.com/118424>. Re-implement
234 // -[NSWindow performClose:] as closely as possible to how Apple documents
237 // Before calling |-close|, hide the window immediately. |-performClose:|
238 // would do something similar, and this ensures that the window is removed
239 // from AppKit's display list. Not doing so can lead to crashes like
240 // <http://crbug.com/156101>.
241 id<NSWindowDelegate> delegate = [window() delegate];
242 SEL window_should_close = @selector(windowShouldClose:);
243 if ([delegate respondsToSelector:window_should_close]) {
244 if ([delegate windowShouldClose:window()]) {
245 [window() orderOut:nil];
248 } else if ([window() respondsToSelector:window_should_close]) {
249 if ([window() performSelector:window_should_close withObject:window()]) {
250 [window() orderOut:nil];
254 [window() orderOut:nil];
260 void BrowserWindowCocoa::Activate() {
261 [controller_ activate];
264 void BrowserWindowCocoa::Deactivate() {
265 // TODO(jcivelli): http://crbug.com/51364 Implement me.
269 void BrowserWindowCocoa::FlashFrame(bool flash) {
271 attention_request_id_ = [NSApp requestUserAttention:NSInformationalRequest];
273 [NSApp cancelUserAttentionRequest:attention_request_id_];
274 attention_request_id_ = 0;
278 bool BrowserWindowCocoa::IsAlwaysOnTop() const {
282 void BrowserWindowCocoa::SetAlwaysOnTop(bool always_on_top) {
283 // Not implemented for browser windows.
287 bool BrowserWindowCocoa::IsActive() const {
288 return [window() isKeyWindow];
291 gfx::NativeWindow BrowserWindowCocoa::GetNativeWindow() const {
295 StatusBubble* BrowserWindowCocoa::GetStatusBubble() {
296 return [controller_ statusBubble];
299 void BrowserWindowCocoa::UpdateTitleBar() {
301 base::SysUTF16ToNSString(browser_->GetWindowTitleForCurrentTab());
303 pending_window_title_.reset(
304 [BrowserWindowUtils scheduleReplaceOldTitle:pending_window_title_.get()
305 withNewTitle:newTitle
306 forWindow:window()]);
309 void BrowserWindowCocoa::BookmarkBarStateChanged(
310 BookmarkBar::AnimateChangeType change_type) {
311 [[controller_ bookmarkBarController]
312 updateState:browser_->bookmark_bar_state()
313 changeType:change_type];
316 void BrowserWindowCocoa::UpdateDevTools() {
317 [controller_ updateDevToolsForContents:
318 browser_->tab_strip_model()->GetActiveWebContents()];
321 void BrowserWindowCocoa::UpdateLoadingAnimations(bool should_animate) {
322 // Do nothing on Mac.
325 void BrowserWindowCocoa::SetStarredState(bool is_starred) {
326 [controller_ setStarredState:is_starred];
329 void BrowserWindowCocoa::SetTranslateIconToggled(bool is_lit) {
330 [controller_ setCurrentPageIsTranslated:is_lit];
333 void BrowserWindowCocoa::OnActiveTabChanged(content::WebContents* old_contents,
334 content::WebContents* new_contents,
337 [controller_ onActiveTabChanged:old_contents to:new_contents];
338 // TODO(pkasting): Perhaps the code in
339 // TabStripController::activateTabWithContents should move here? Or this
340 // should call that (instead of TabStripModelObserverBridge doing so)? It's
341 // not obvious to me why Mac doesn't handle tab changes in BrowserWindow the
342 // way views and GTK do.
343 // See http://crbug.com/340720 for discussion.
346 void BrowserWindowCocoa::ZoomChangedForActiveTab(bool can_show_bubble) {
347 [controller_ zoomChangedForActiveTab:can_show_bubble ? YES : NO];
350 gfx::Rect BrowserWindowCocoa::GetRestoredBounds() const {
351 // Flip coordinates based on the primary screen.
352 NSScreen* screen = [[NSScreen screens] objectAtIndex:0];
353 NSRect frame = [controller_ regularWindowFrame];
354 gfx::Rect bounds(frame.origin.x, 0, NSWidth(frame), NSHeight(frame));
355 bounds.set_y(NSHeight([screen frame]) - NSMaxY(frame));
359 ui::WindowShowState BrowserWindowCocoa::GetRestoredState() const {
361 return ui::SHOW_STATE_MAXIMIZED;
363 return ui::SHOW_STATE_MINIMIZED;
364 return ui::SHOW_STATE_NORMAL;
367 gfx::Rect BrowserWindowCocoa::GetBounds() const {
368 return GetRestoredBounds();
371 bool BrowserWindowCocoa::IsMaximized() const {
372 // -isZoomed returns YES if the window's frame equals the rect returned by
373 // -windowWillUseStandardFrame:defaultFrame:, even if the window is in the
374 // dock, so have to explicitly check for miniaturization state first.
375 return ![window() isMiniaturized] && [window() isZoomed];
378 bool BrowserWindowCocoa::IsMinimized() const {
379 return [window() isMiniaturized];
382 void BrowserWindowCocoa::Maximize() {
383 // Zoom toggles so only call if not already maximized.
385 [window() zoom:controller_];
388 void BrowserWindowCocoa::Minimize() {
389 [window() miniaturize:controller_];
392 void BrowserWindowCocoa::Restore() {
394 [window() zoom:controller_]; // Toggles zoom mode.
395 else if (IsMinimized())
396 [window() deminiaturize:controller_];
399 // See browser_window_controller.h for a detailed explanation of the logic in
401 void BrowserWindowCocoa::EnterFullscreen(const GURL& url,
402 ExclusiveAccessBubbleType bubble_type,
404 if (browser_->exclusive_access_manager()
405 ->fullscreen_controller()
406 ->IsWindowFullscreenForTabOrPending())
407 [controller_ enterWebContentFullscreenForURL:url bubbleType:bubble_type];
408 else if (!url.is_empty())
409 [controller_ enterExtensionFullscreenForURL:url bubbleType:bubble_type];
411 [controller_ enterBrowserFullscreenWithToolbar:with_toolbar];
414 void BrowserWindowCocoa::ExitFullscreen() {
415 [controller_ exitAnyFullscreen];
418 void BrowserWindowCocoa::UpdateExclusiveAccessExitBubbleContent(
420 ExclusiveAccessBubbleType bubble_type) {
421 [controller_ updateFullscreenExitBubbleURL:url bubbleType:bubble_type];
424 bool BrowserWindowCocoa::ShouldHideUIForFullscreen() const {
425 // On Mac, fullscreen mode has most normal things (in a slide-down panel).
429 bool BrowserWindowCocoa::IsFullscreen() const {
430 return [controller_ isInAnyFullscreenMode];
433 bool BrowserWindowCocoa::IsFullscreenBubbleVisible() const {
437 bool BrowserWindowCocoa::SupportsFullscreenWithToolbar() const {
438 return chrome::mac::SupportsSystemFullscreen();
441 void BrowserWindowCocoa::UpdateFullscreenWithToolbar(bool with_toolbar) {
442 [controller_ updateFullscreenWithToolbar:with_toolbar];
445 bool BrowserWindowCocoa::IsFullscreenWithToolbar() const {
446 return IsFullscreen() && ![controller_ inPresentationMode];
449 void BrowserWindowCocoa::ConfirmAddSearchProvider(
450 TemplateURL* template_url,
452 // The controller will release itself when the window closes.
453 EditSearchEngineCocoaController* editor =
454 [[EditSearchEngineCocoaController alloc] initWithProfile:profile
456 templateURL:template_url];
457 [NSApp beginSheet:[editor window]
458 modalForWindow:window()
459 modalDelegate:controller_
460 didEndSelector:@selector(sheetDidEnd:returnCode:context:)
464 LocationBar* BrowserWindowCocoa::GetLocationBar() const {
465 return [controller_ locationBarBridge];
468 void BrowserWindowCocoa::SetFocusToLocationBar(bool select_all) {
469 [controller_ focusLocationBar:select_all ? YES : NO];
472 void BrowserWindowCocoa::UpdateReloadStopState(bool is_loading, bool force) {
473 [controller_ setIsLoading:is_loading force:force];
476 void BrowserWindowCocoa::UpdateToolbar(content::WebContents* contents) {
477 [controller_ updateToolbarWithContents:contents];
480 void BrowserWindowCocoa::ResetToolbarTabState(content::WebContents* contents) {
481 [controller_ resetTabState:contents];
484 void BrowserWindowCocoa::FocusToolbar() {
485 // Not needed on the Mac.
488 ToolbarActionsBar* BrowserWindowCocoa::GetToolbarActionsBar() {
489 if ([controller_ hasToolbar])
490 return [[[controller_ toolbarController] browserActionsController]
495 void BrowserWindowCocoa::ToolbarSizeChanged(bool is_animating) {
496 // Not needed on the Mac.
499 void BrowserWindowCocoa::FocusAppMenu() {
500 // Chrome uses the standard Mac OS X menu bar, so this isn't needed.
503 void BrowserWindowCocoa::RotatePaneFocus(bool forwards) {
504 // Not needed on the Mac.
507 void BrowserWindowCocoa::FocusBookmarksToolbar() {
508 // Not needed on the Mac.
511 void BrowserWindowCocoa::FocusInfobars() {
512 // Not needed on the Mac.
515 bool BrowserWindowCocoa::IsBookmarkBarVisible() const {
516 return browser_->profile()->GetPrefs()->GetBoolean(
517 bookmarks::prefs::kShowBookmarkBar);
520 bool BrowserWindowCocoa::IsBookmarkBarAnimating() const {
521 return [controller_ isBookmarkBarAnimating];
524 bool BrowserWindowCocoa::IsTabStripEditable() const {
525 return ![controller_ isDragSessionActive];
528 bool BrowserWindowCocoa::IsToolbarVisible() const {
529 return browser_->SupportsWindowFeature(Browser::FEATURE_TOOLBAR) ||
530 browser_->SupportsWindowFeature(Browser::FEATURE_LOCATIONBAR);
533 gfx::Rect BrowserWindowCocoa::GetRootWindowResizerRect() const {
534 if (IsDownloadShelfVisible())
536 NSRect tabRect = [controller_ selectedTabGrowBoxRect];
537 return gfx::Rect(NSRectToCGRect(tabRect));
540 void BrowserWindowCocoa::AddFindBar(
541 FindBarCocoaController* find_bar_cocoa_controller) {
542 [controller_ addFindBar:find_bar_cocoa_controller];
545 void BrowserWindowCocoa::ShowUpdateChromeDialog() {
546 restart_browser::RequestRestart(window());
549 void BrowserWindowCocoa::ShowBookmarkBubble(const GURL& url,
550 bool already_bookmarked) {
551 [controller_ showBookmarkBubbleForURL:url
552 alreadyBookmarked:(already_bookmarked ? YES : NO)];
555 void BrowserWindowCocoa::ShowBookmarkAppBubble(
556 const WebApplicationInfo& web_app_info,
557 const ShowBookmarkAppBubbleCallback& callback) {
558 base::scoped_nsobject<NSAlert> alert([[NSAlert alloc] init]);
559 [alert setMessageText:l10n_util::GetNSString(
560 IDS_ADD_TO_APPLICATIONS_BUBBLE_TITLE)];
561 [alert setAlertStyle:NSInformationalAlertStyle];
563 NSButton* continue_button =
564 [alert addButtonWithTitle:l10n_util::GetNSString(IDS_OK)];
565 [continue_button setKeyEquivalent:kKeyEquivalentReturn];
566 NSButton* cancel_button =
567 [alert addButtonWithTitle:l10n_util::GetNSString(IDS_CANCEL)];
568 [cancel_button setKeyEquivalent:kKeyEquivalentEscape];
570 base::scoped_nsobject<NSButton> open_as_window_checkbox(
571 [[NSButton alloc] initWithFrame:NSZeroRect]);
572 [open_as_window_checkbox setButtonType:NSSwitchButton];
573 [open_as_window_checkbox
574 setTitle:l10n_util::GetNSString(IDS_BOOKMARK_APP_BUBBLE_OPEN_AS_WINDOW)];
575 [open_as_window_checkbox setState:web_app_info.open_as_window];
576 [open_as_window_checkbox sizeToFit];
578 base::scoped_nsobject<NSTextField> app_title([[NSTextField alloc]
579 initWithFrame:NSMakeRect(0, kAppTextFieldHeight +
580 kAppTextFieldVerticalSpacing,
581 kAppTextFieldWidth, kAppTextFieldHeight)]);
582 NSString* original_title = SysUTF16ToNSString(web_app_info.title);
583 [[app_title cell] setWraps:NO];
584 [[app_title cell] setScrollable:YES];
585 [app_title setStringValue:original_title];
586 base::scoped_nsobject<TextRequiringDelegate> delegate(
587 [[TextRequiringDelegate alloc] initWithControl:continue_button
588 text:[app_title stringValue]]);
589 [app_title setDelegate:delegate];
591 base::scoped_nsobject<NSView> view([[NSView alloc]
592 initWithFrame:NSMakeRect(0, 0, kBookmarkAppBubbleViewWidth,
593 kBookmarkAppBubbleViewHeight)]);
595 // When CanHostedAppsOpenInWindows() returns false, do not show the open as
596 // window checkbox to avoid confusing users.
597 if (extensions::util::CanHostedAppsOpenInWindows())
598 [view addSubview:open_as_window_checkbox];
599 [view addSubview:app_title];
600 [alert setAccessoryView:view];
602 // Find the image with target size.
603 // Assumes that the icons are sorted in ascending order of size.
604 if (!web_app_info.icons.empty()) {
605 for (const WebApplicationInfo::IconInfo& info : web_app_info.icons) {
606 if (info.width == kIconPreviewTargetSize &&
607 info.height == kIconPreviewTargetSize) {
608 gfx::Image icon_image = gfx::Image::CreateFrom1xBitmap(info.data);
609 [alert setIcon:icon_image.ToNSImage()];
615 NSInteger response = [alert runModal];
617 // Prevent |app_title| from accessing |delegate| after it's destroyed.
618 [app_title setDelegate:nil];
620 if (response == NSAlertFirstButtonReturn) {
621 WebApplicationInfo updated_info = web_app_info;
622 updated_info.open_as_window = [open_as_window_checkbox state] == NSOnState;
623 updated_info.title = TrimText([app_title stringValue]);
625 callback.Run(true, updated_info);
629 callback.Run(false, web_app_info);
632 void BrowserWindowCocoa::ShowTranslateBubble(
633 content::WebContents* contents,
634 translate::TranslateStep step,
635 translate::TranslateErrors::Type error_type,
636 bool is_user_gesture) {
637 ChromeTranslateClient* chrome_translate_client =
638 ChromeTranslateClient::FromWebContents(contents);
639 translate::LanguageState& language_state =
640 chrome_translate_client->GetLanguageState();
641 language_state.SetTranslateEnabled(true);
643 [controller_ showTranslateBubbleForWebContents:contents
645 errorType:error_type];
648 bool BrowserWindowCocoa::ShowSessionCrashedBubble() {
652 bool BrowserWindowCocoa::IsProfileResetBubbleSupported() const {
656 GlobalErrorBubbleViewBase* BrowserWindowCocoa::ShowProfileResetBubble(
657 const base::WeakPtr<ProfileResetGlobalError>& global_error) {
662 #if defined(ENABLE_ONE_CLICK_SIGNIN)
663 void BrowserWindowCocoa::ShowOneClickSigninBubble(
664 OneClickSigninBubbleType type,
665 const base::string16& email,
666 const base::string16& error_message,
667 const StartSyncCallback& start_sync_callback) {
668 WebContents* web_contents =
669 browser_->tab_strip_model()->GetActiveWebContents();
670 if (type == ONE_CLICK_SIGNIN_BUBBLE_TYPE_BUBBLE) {
671 base::scoped_nsobject<OneClickSigninBubbleController> bubble_controller([
672 [OneClickSigninBubbleController alloc]
673 initWithBrowserWindowController:cocoa_controller()
674 webContents:web_contents
675 errorMessage:base::SysUTF16ToNSString(error_message)
676 callback:start_sync_callback]);
677 [bubble_controller showWindow:nil];
679 // Deletes itself when the dialog closes.
680 new OneClickSigninDialogController(
681 web_contents, start_sync_callback, email);
686 bool BrowserWindowCocoa::IsDownloadShelfVisible() const {
687 return [controller_ isDownloadShelfVisible] != NO;
690 DownloadShelf* BrowserWindowCocoa::GetDownloadShelf() {
691 [controller_ createAndAddDownloadShelf];
692 DownloadShelfController* shelfController = [controller_ downloadShelf];
693 return [shelfController bridge];
696 // We allow closing the window here since the real quit decision on Mac is made
697 // in [AppController quit:].
698 void BrowserWindowCocoa::ConfirmBrowserCloseWithPendingDownloads(
700 Browser::DownloadClosePreventionType dialog_type,
702 const base::Callback<void(bool)>& callback) {
706 void BrowserWindowCocoa::UserChangedTheme() {
707 [controller_ userChangedTheme];
710 void BrowserWindowCocoa::ShowWebsiteSettings(
712 content::WebContents* web_contents,
714 const content::SSLStatus& ssl) {
715 WebsiteSettingsUIBridge::Show(window(), profile, web_contents, url, ssl);
718 void BrowserWindowCocoa::ShowAppMenu() {
719 // No-op. Mac doesn't support showing the menus via alt keys.
722 bool BrowserWindowCocoa::PreHandleKeyboardEvent(
723 const NativeWebKeyboardEvent& event, bool* is_keyboard_shortcut) {
724 // Handle ESC to dismiss permission bubbles, but still forward it
725 // to the window afterwards.
726 if (event.windowsKeyCode == ui::VKEY_ESCAPE)
727 [controller_ dismissPermissionBubble];
729 if (![BrowserWindowUtils shouldHandleKeyboardEvent:event])
732 if (event.type == blink::WebInputEvent::RawKeyDown &&
734 handledByExtensionCommand:event.os_event
735 priority:ui::AcceleratorManager::kHighPriority])
738 int id = [BrowserWindowUtils getCommandId:event];
742 if (browser_->command_controller()->IsReservedCommandOrKey(id, event)) {
743 return [BrowserWindowUtils handleKeyboardEvent:event.os_event
747 DCHECK(is_keyboard_shortcut);
748 *is_keyboard_shortcut = true;
752 void BrowserWindowCocoa::HandleKeyboardEvent(
753 const NativeWebKeyboardEvent& event) {
754 if ([BrowserWindowUtils shouldHandleKeyboardEvent:event])
755 [BrowserWindowUtils handleKeyboardEvent:event.os_event inWindow:window()];
758 void BrowserWindowCocoa::CutCopyPaste(int command_id) {
759 if (command_id == IDC_CUT)
760 [NSApp sendAction:@selector(cut:) to:nil from:nil];
761 else if (command_id == IDC_COPY)
762 [NSApp sendAction:@selector(copy:) to:nil from:nil];
764 [NSApp sendAction:@selector(paste:) to:nil from:nil];
767 WindowOpenDisposition BrowserWindowCocoa::GetDispositionForPopupBounds(
768 const gfx::Rect& bounds) {
769 // When using Cocoa's System Fullscreen mode, convert popups into tabs.
770 if ([controller_ isInAppKitFullscreen])
771 return NEW_FOREGROUND_TAB;
775 FindBar* BrowserWindowCocoa::CreateFindBar() {
776 // We could push the AddFindBar() call into the FindBarBridge
777 // constructor or the FindBarCocoaController init, but that makes
778 // unit testing difficult, since we would also require a
779 // BrowserWindow object.
780 FindBarBridge* bridge = new FindBarBridge(browser_);
781 AddFindBar(bridge->find_bar_cocoa_controller());
785 web_modal::WebContentsModalDialogHost*
786 BrowserWindowCocoa::GetWebContentsModalDialogHost() {
787 DCHECK([controller_ window]);
788 ConstrainedWindowSheetController* sheet_controller =
789 [ConstrainedWindowSheetController
790 controllerForParentWindow:[controller_ window]];
791 DCHECK(sheet_controller);
792 return [sheet_controller dialogHost];
795 extensions::ActiveTabPermissionGranter*
796 BrowserWindowCocoa::GetActiveTabPermissionGranter() {
797 WebContents* web_contents =
798 browser_->tab_strip_model()->GetActiveWebContents();
801 extensions::TabHelper* tab_helper =
802 extensions::TabHelper::FromWebContents(web_contents);
803 return tab_helper ? tab_helper->active_tab_permission_granter() : NULL;
806 void BrowserWindowCocoa::ModelChanged(const SearchModel::State& old_state,
807 const SearchModel::State& new_state) {
810 void BrowserWindowCocoa::DestroyBrowser() {
811 [controller_ destroyBrowser];
813 // at this point the controller is dead (autoreleased), so
814 // make sure we don't try to reference it any more.
817 NSWindow* BrowserWindowCocoa::window() const {
818 return [controller_ window];
821 void BrowserWindowCocoa::ShowAvatarBubbleFromAvatarButton(
822 AvatarBubbleMode mode,
823 const signin::ManageAccountsParams& manage_accounts_params) {
824 AvatarBaseController* controller = [controller_ avatarButtonController];
825 NSView* anchor = [controller buttonView];
826 if ([anchor isHiddenOrHasHiddenAncestor])
827 anchor = [[controller_ toolbarController] wrenchButton];
828 [controller showAvatarBubbleAnchoredAt:anchor
830 withServiceType:manage_accounts_params.service_type];
834 BrowserWindowCocoa::GetRenderViewHeightInsetWithDetachedBookmarkBar() {
835 if (browser_->bookmark_bar_state() != BookmarkBar::DETACHED)
840 void BrowserWindowCocoa::ExecuteExtensionCommand(
841 const extensions::Extension* extension,
842 const extensions::Command& command) {
843 [cocoa_controller() executeExtensionCommand:extension->id() command:command];
846 ExclusiveAccessContext* BrowserWindowCocoa::GetExclusiveAccessContext() {
850 Profile* BrowserWindowCocoa::GetProfile() {
851 return browser_->profile();
854 WebContents* BrowserWindowCocoa::GetActiveWebContents() {
855 return browser_->tab_strip_model()->GetActiveWebContents();
858 void BrowserWindowCocoa::UnhideDownloadShelf() {
859 GetDownloadShelf()->Unhide();
862 void BrowserWindowCocoa::HideDownloadShelf() {
863 GetDownloadShelf()->Hide();
864 StatusBubble* statusBubble = GetStatusBubble();
866 statusBubble->Hide();