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/cocoa/browser_window_cocoa.h" 6 7#include "base/bind.h" 8#include "base/command_line.h" 9#include "base/logging.h" 10#include "base/mac/mac_util.h" 11#import "base/mac/sdk_forward_declarations.h" 12#include "base/message_loop/message_loop.h" 13#include "base/prefs/pref_service.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/tab_helper.h" 19#include "chrome/browser/fullscreen.h" 20#include "chrome/browser/profiles/profile.h" 21#include "chrome/browser/shell_integration.h" 22#include "chrome/browser/signin/signin_header_helper.h" 23#include "chrome/browser/translate/chrome_translate_client.h" 24#include "chrome/browser/ui/browser.h" 25#include "chrome/browser/ui/browser_command_controller.h" 26#include "chrome/browser/ui/browser_commands_mac.h" 27#include "chrome/browser/ui/browser_list.h" 28#include "chrome/browser/ui/browser_window_state.h" 29#import "chrome/browser/ui/cocoa/browser/edit_search_engine_cocoa_controller.h" 30#import "chrome/browser/ui/cocoa/browser_window_controller.h" 31#import "chrome/browser/ui/cocoa/browser_window_utils.h" 32#import "chrome/browser/ui/cocoa/chrome_event_processing_window.h" 33#import "chrome/browser/ui/cocoa/download/download_shelf_controller.h" 34#include "chrome/browser/ui/cocoa/find_bar/find_bar_bridge.h" 35#import "chrome/browser/ui/cocoa/info_bubble_view.h" 36#import "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h" 37#import "chrome/browser/ui/cocoa/nsmenuitem_additions.h" 38#import "chrome/browser/ui/cocoa/profiles/avatar_base_controller.h" 39#import "chrome/browser/ui/cocoa/profiles/avatar_menu_bubble_controller.h" 40#include "chrome/browser/ui/cocoa/restart_browser.h" 41#include "chrome/browser/ui/cocoa/status_bubble_mac.h" 42#include "chrome/browser/ui/cocoa/task_manager_mac.h" 43#import "chrome/browser/ui/cocoa/toolbar/toolbar_controller.h" 44#import "chrome/browser/ui/cocoa/web_dialog_window_controller.h" 45#import "chrome/browser/ui/cocoa/website_settings/website_settings_bubble_controller.h" 46#include "chrome/browser/ui/fullscreen/fullscreen_controller.h" 47#include "chrome/browser/ui/search/search_model.h" 48#include "chrome/browser/ui/tabs/tab_strip_model.h" 49#include "chrome/browser/web_applications/web_app.h" 50#include "chrome/common/chrome_switches.h" 51#include "chrome/common/pref_names.h" 52#include "components/translate/core/browser/language_state.h" 53#include "content/public/browser/native_web_keyboard_event.h" 54#include "content/public/browser/notification_details.h" 55#include "content/public/browser/notification_source.h" 56#include "content/public/browser/web_contents.h" 57#include "ui/base/l10n/l10n_util_mac.h" 58#include "ui/gfx/rect.h" 59 60#if defined(ENABLE_ONE_CLICK_SIGNIN) 61#import "chrome/browser/ui/cocoa/one_click_signin_bubble_controller.h" 62#import "chrome/browser/ui/cocoa/one_click_signin_dialog_controller.h" 63#endif 64 65using content::NativeWebKeyboardEvent; 66using content::SSLStatus; 67using content::WebContents; 68 69namespace { 70 71NSPoint GetPointForBubble(content::WebContents* web_contents, 72 int x_offset, 73 int y_offset) { 74 NSView* view = web_contents->GetNativeView(); 75 NSRect bounds = [view bounds]; 76 NSPoint point; 77 point.x = NSMinX(bounds) + x_offset; 78 // The view's origin is at the bottom but |rect|'s origin is at the top. 79 point.y = NSMaxY(bounds) - y_offset; 80 point = [view convertPoint:point toView:nil]; 81 point = [[view window] convertBaseToScreen:point]; 82 return point; 83} 84 85} // namespace 86 87BrowserWindowCocoa::BrowserWindowCocoa(Browser* browser, 88 BrowserWindowController* controller) 89 : browser_(browser), 90 controller_(controller), 91 initial_show_state_(ui::SHOW_STATE_DEFAULT), 92 attention_request_id_(0) { 93 94 gfx::Rect bounds; 95 chrome::GetSavedWindowBoundsAndShowState(browser_, 96 &bounds, 97 &initial_show_state_); 98 99 browser_->search_model()->AddObserver(this); 100} 101 102BrowserWindowCocoa::~BrowserWindowCocoa() { 103 browser_->search_model()->RemoveObserver(this); 104} 105 106void BrowserWindowCocoa::Show() { 107 // The Browser associated with this browser window must become the active 108 // browser at the time |Show()| is called. This is the natural behaviour under 109 // Windows, but |-makeKeyAndOrderFront:| won't send |-windowDidBecomeMain:| 110 // until we return to the runloop. Therefore any calls to 111 // |chrome::FindLastActiveWithHostDesktopType| will return the previous 112 // browser instead if we don't explicitly set it here. 113 BrowserList::SetLastActive(browser_); 114 115 bool is_session_restore = browser_->is_session_restore(); 116 NSWindowAnimationBehavior saved_animation_behavior = 117 NSWindowAnimationBehaviorDefault; 118 bool did_save_animation_behavior = false; 119 // Turn off swishing when restoring windows. 120 if (is_session_restore && 121 [window() respondsToSelector:@selector(animationBehavior)] && 122 [window() respondsToSelector:@selector(setAnimationBehavior:)]) { 123 did_save_animation_behavior = true; 124 saved_animation_behavior = [window() animationBehavior]; 125 [window() setAnimationBehavior:NSWindowAnimationBehaviorNone]; 126 } 127 128 { 129 TRACE_EVENT0("ui", "BrowserWindowCocoa::Show makeKeyAndOrderFront"); 130 // This call takes up a substantial part of startup time, and an even more 131 // substantial part of startup time when any CALayers are part of the 132 // window's NSView heirarchy. 133 [window() makeKeyAndOrderFront:controller_]; 134 } 135 136 // When creating windows from nibs it is necessary to |makeKeyAndOrderFront:| 137 // prior to |orderOut:| then |miniaturize:| when restoring windows in the 138 // minimized state. 139 if (initial_show_state_ == ui::SHOW_STATE_MINIMIZED) { 140 [window() orderOut:controller_]; 141 [window() miniaturize:controller_]; 142 } else if (initial_show_state_ == ui::SHOW_STATE_FULLSCREEN) { 143 chrome::ToggleFullscreenWithChromeOrFallback(browser_); 144 } 145 initial_show_state_ = ui::SHOW_STATE_DEFAULT; 146 147 // Restore window animation behavior. 148 if (did_save_animation_behavior) 149 [window() setAnimationBehavior:saved_animation_behavior]; 150 151 browser_->OnWindowDidShow(); 152} 153 154void BrowserWindowCocoa::ShowInactive() { 155 [window() orderFront:controller_]; 156} 157 158void BrowserWindowCocoa::Hide() { 159 // Not implemented. 160} 161 162void BrowserWindowCocoa::SetBounds(const gfx::Rect& bounds) { 163 gfx::Rect real_bounds = [controller_ enforceMinWindowSize:bounds]; 164 165 ExitFullscreen(); 166 NSRect cocoa_bounds = NSMakeRect(real_bounds.x(), 0, 167 real_bounds.width(), 168 real_bounds.height()); 169 // Flip coordinates based on the primary screen. 170 NSScreen* screen = [[NSScreen screens] objectAtIndex:0]; 171 cocoa_bounds.origin.y = 172 NSHeight([screen frame]) - real_bounds.height() - real_bounds.y(); 173 174 [window() setFrame:cocoa_bounds display:YES]; 175} 176 177// Callers assume that this doesn't immediately delete the Browser object. 178// The controller implementing the window delegate methods called from 179// |-performClose:| must take precautions to ensure that. 180void BrowserWindowCocoa::Close() { 181 // If there is an overlay window, we contain a tab being dragged between 182 // windows. Don't hide the window as it makes the UI extra confused. We can 183 // still close the window, as that will happen when the drag completes. 184 if ([controller_ overlayWindow]) { 185 [controller_ deferPerformClose]; 186 } else { 187 // Using |-performClose:| can prevent the window from actually closing if 188 // a JavaScript beforeunload handler opens an alert during shutdown, as 189 // documented at <http://crbug.com/118424>. Re-implement 190 // -[NSWindow performClose:] as closely as possible to how Apple documents 191 // it. 192 // 193 // Before calling |-close|, hide the window immediately. |-performClose:| 194 // would do something similar, and this ensures that the window is removed 195 // from AppKit's display list. Not doing so can lead to crashes like 196 // <http://crbug.com/156101>. 197 id<NSWindowDelegate> delegate = [window() delegate]; 198 SEL window_should_close = @selector(windowShouldClose:); 199 if ([delegate respondsToSelector:window_should_close]) { 200 if ([delegate windowShouldClose:window()]) { 201 [window() orderOut:nil]; 202 [window() close]; 203 } 204 } else if ([window() respondsToSelector:window_should_close]) { 205 if ([window() performSelector:window_should_close withObject:window()]) { 206 [window() orderOut:nil]; 207 [window() close]; 208 } 209 } else { 210 [window() orderOut:nil]; 211 [window() close]; 212 } 213 } 214} 215 216void BrowserWindowCocoa::Activate() { 217 [controller_ activate]; 218} 219 220void BrowserWindowCocoa::Deactivate() { 221 // TODO(jcivelli): http://crbug.com/51364 Implement me. 222 NOTIMPLEMENTED(); 223} 224 225void BrowserWindowCocoa::FlashFrame(bool flash) { 226 if (flash) { 227 attention_request_id_ = [NSApp requestUserAttention:NSInformationalRequest]; 228 } else { 229 [NSApp cancelUserAttentionRequest:attention_request_id_]; 230 attention_request_id_ = 0; 231 } 232} 233 234bool BrowserWindowCocoa::IsAlwaysOnTop() const { 235 return false; 236} 237 238void BrowserWindowCocoa::SetAlwaysOnTop(bool always_on_top) { 239 // Not implemented for browser windows. 240 NOTIMPLEMENTED(); 241} 242 243bool BrowserWindowCocoa::IsActive() const { 244 return [window() isKeyWindow]; 245} 246 247gfx::NativeWindow BrowserWindowCocoa::GetNativeWindow() { 248 return window(); 249} 250 251BrowserWindowTesting* BrowserWindowCocoa::GetBrowserWindowTesting() { 252 return NULL; 253} 254 255StatusBubble* BrowserWindowCocoa::GetStatusBubble() { 256 return [controller_ statusBubble]; 257} 258 259void BrowserWindowCocoa::UpdateTitleBar() { 260 NSString* newTitle = 261 base::SysUTF16ToNSString(browser_->GetWindowTitleForCurrentTab()); 262 263 pending_window_title_.reset( 264 [BrowserWindowUtils scheduleReplaceOldTitle:pending_window_title_.get() 265 withNewTitle:newTitle 266 forWindow:window()]); 267} 268 269void BrowserWindowCocoa::BookmarkBarStateChanged( 270 BookmarkBar::AnimateChangeType change_type) { 271 [[controller_ bookmarkBarController] 272 updateState:browser_->bookmark_bar_state() 273 changeType:change_type]; 274} 275 276void BrowserWindowCocoa::UpdateDevTools() { 277 [controller_ updateDevToolsForContents: 278 browser_->tab_strip_model()->GetActiveWebContents()]; 279} 280 281void BrowserWindowCocoa::UpdateLoadingAnimations(bool should_animate) { 282 // Do nothing on Mac. 283} 284 285void BrowserWindowCocoa::SetStarredState(bool is_starred) { 286 [controller_ setStarredState:is_starred]; 287} 288 289void BrowserWindowCocoa::SetTranslateIconToggled(bool is_lit) { 290 [controller_ setCurrentPageIsTranslated:is_lit]; 291} 292 293void BrowserWindowCocoa::OnActiveTabChanged(content::WebContents* old_contents, 294 content::WebContents* new_contents, 295 int index, 296 int reason) { 297 // TODO(pkasting): Perhaps the code in 298 // TabStripController::activateTabWithContents should move here? Or this 299 // should call that (instead of TabStripModelObserverBridge doing so)? It's 300 // not obvious to me why Mac doesn't handle tab changes in BrowserWindow the 301 // way views and GTK do. 302} 303 304void BrowserWindowCocoa::ZoomChangedForActiveTab(bool can_show_bubble) { 305 [controller_ zoomChangedForActiveTab:can_show_bubble ? YES : NO]; 306} 307 308gfx::Rect BrowserWindowCocoa::GetRestoredBounds() const { 309 // Flip coordinates based on the primary screen. 310 NSScreen* screen = [[NSScreen screens] objectAtIndex:0]; 311 NSRect frame = [controller_ regularWindowFrame]; 312 gfx::Rect bounds(frame.origin.x, 0, NSWidth(frame), NSHeight(frame)); 313 bounds.set_y(NSHeight([screen frame]) - NSMaxY(frame)); 314 return bounds; 315} 316 317ui::WindowShowState BrowserWindowCocoa::GetRestoredState() const { 318 if (IsMaximized()) 319 return ui::SHOW_STATE_MAXIMIZED; 320 if (IsMinimized()) 321 return ui::SHOW_STATE_MINIMIZED; 322 return ui::SHOW_STATE_NORMAL; 323} 324 325gfx::Rect BrowserWindowCocoa::GetBounds() const { 326 return GetRestoredBounds(); 327} 328 329bool BrowserWindowCocoa::IsMaximized() const { 330 return [window() isZoomed]; 331} 332 333bool BrowserWindowCocoa::IsMinimized() const { 334 return [window() isMiniaturized]; 335} 336 337void BrowserWindowCocoa::Maximize() { 338 // Zoom toggles so only call if not already maximized. 339 if (!IsMaximized()) 340 [window() zoom:controller_]; 341} 342 343void BrowserWindowCocoa::Minimize() { 344 [window() miniaturize:controller_]; 345} 346 347void BrowserWindowCocoa::Restore() { 348 if (IsMaximized()) 349 [window() zoom:controller_]; // Toggles zoom mode. 350 else if (IsMinimized()) 351 [window() deminiaturize:controller_]; 352} 353 354// See browser_window_controller.h for a detailed explanation of the logic in 355// this method. 356void BrowserWindowCocoa::EnterFullscreen(const GURL& url, 357 FullscreenExitBubbleType bubble_type) { 358 if (browser_->fullscreen_controller()->IsWindowFullscreenForTabOrPending()) { 359 [controller_ enterWebContentFullscreenForURL:url bubbleType:bubble_type]; 360 return; 361 } 362 363 if (url.is_empty()) { 364 [controller_ enterPresentationMode]; 365 } else { 366 [controller_ enterExtensionFullscreenForURL:url bubbleType:bubble_type]; 367 } 368} 369 370void BrowserWindowCocoa::ExitFullscreen() { 371 [controller_ exitAnyFullscreen]; 372} 373 374void BrowserWindowCocoa::UpdateFullscreenExitBubbleContent( 375 const GURL& url, 376 FullscreenExitBubbleType bubble_type) { 377 [controller_ updateFullscreenExitBubbleURL:url bubbleType:bubble_type]; 378} 379 380bool BrowserWindowCocoa::ShouldHideUIForFullscreen() const { 381 // On Mac, fullscreen mode has most normal things (in a slide-down panel). 382 return false; 383} 384 385bool BrowserWindowCocoa::IsFullscreen() const { 386 return [controller_ isInAnyFullscreenMode]; 387} 388 389bool BrowserWindowCocoa::IsFullscreenBubbleVisible() const { 390 return false; 391} 392 393void BrowserWindowCocoa::ConfirmAddSearchProvider( 394 TemplateURL* template_url, 395 Profile* profile) { 396 // The controller will release itself when the window closes. 397 EditSearchEngineCocoaController* editor = 398 [[EditSearchEngineCocoaController alloc] initWithProfile:profile 399 delegate:NULL 400 templateURL:template_url]; 401 [NSApp beginSheet:[editor window] 402 modalForWindow:window() 403 modalDelegate:controller_ 404 didEndSelector:@selector(sheetDidEnd:returnCode:context:) 405 contextInfo:NULL]; 406} 407 408LocationBar* BrowserWindowCocoa::GetLocationBar() const { 409 return [controller_ locationBarBridge]; 410} 411 412void BrowserWindowCocoa::SetFocusToLocationBar(bool select_all) { 413 [controller_ focusLocationBar:select_all ? YES : NO]; 414} 415 416void BrowserWindowCocoa::UpdateReloadStopState(bool is_loading, bool force) { 417 [controller_ setIsLoading:is_loading force:force]; 418} 419 420void BrowserWindowCocoa::UpdateToolbar(content::WebContents* contents) { 421 [controller_ updateToolbarWithContents:contents]; 422} 423 424void BrowserWindowCocoa::FocusToolbar() { 425 // Not needed on the Mac. 426} 427 428void BrowserWindowCocoa::FocusAppMenu() { 429 // Chrome uses the standard Mac OS X menu bar, so this isn't needed. 430} 431 432void BrowserWindowCocoa::RotatePaneFocus(bool forwards) { 433 // Not needed on the Mac. 434} 435 436void BrowserWindowCocoa::FocusBookmarksToolbar() { 437 // Not needed on the Mac. 438} 439 440void BrowserWindowCocoa::FocusInfobars() { 441 // Not needed on the Mac. 442} 443 444bool BrowserWindowCocoa::IsBookmarkBarVisible() const { 445 return browser_->profile()->GetPrefs()->GetBoolean( 446 bookmarks::prefs::kShowBookmarkBar); 447} 448 449bool BrowserWindowCocoa::IsBookmarkBarAnimating() const { 450 return [controller_ isBookmarkBarAnimating]; 451} 452 453bool BrowserWindowCocoa::IsTabStripEditable() const { 454 return ![controller_ isDragSessionActive]; 455} 456 457bool BrowserWindowCocoa::IsToolbarVisible() const { 458 return browser_->SupportsWindowFeature(Browser::FEATURE_TOOLBAR) || 459 browser_->SupportsWindowFeature(Browser::FEATURE_LOCATIONBAR); 460} 461 462gfx::Rect BrowserWindowCocoa::GetRootWindowResizerRect() const { 463 if (IsDownloadShelfVisible()) 464 return gfx::Rect(); 465 NSRect tabRect = [controller_ selectedTabGrowBoxRect]; 466 return gfx::Rect(NSRectToCGRect(tabRect)); 467} 468 469void BrowserWindowCocoa::AddFindBar( 470 FindBarCocoaController* find_bar_cocoa_controller) { 471 [controller_ addFindBar:find_bar_cocoa_controller]; 472} 473 474void BrowserWindowCocoa::ShowUpdateChromeDialog() { 475 restart_browser::RequestRestart(window()); 476} 477 478void BrowserWindowCocoa::ShowBookmarkBubble(const GURL& url, 479 bool already_bookmarked) { 480 [controller_ showBookmarkBubbleForURL:url 481 alreadyBookmarked:(already_bookmarked ? YES : NO)]; 482} 483 484void BrowserWindowCocoa::ShowBookmarkAppBubble( 485 const WebApplicationInfo& web_app_info, 486 const std::string& extension_id) { 487 NOTIMPLEMENTED(); 488} 489 490void BrowserWindowCocoa::ShowTranslateBubble( 491 content::WebContents* contents, 492 translate::TranslateStep step, 493 translate::TranslateErrors::Type error_type, 494 bool is_user_gesture) { 495 ChromeTranslateClient* chrome_translate_client = 496 ChromeTranslateClient::FromWebContents(contents); 497 translate::LanguageState& language_state = 498 chrome_translate_client->GetLanguageState(); 499 language_state.SetTranslateEnabled(true); 500 501 [controller_ showTranslateBubbleForWebContents:contents 502 step:step 503 errorType:error_type]; 504} 505 506#if defined(ENABLE_ONE_CLICK_SIGNIN) 507void BrowserWindowCocoa::ShowOneClickSigninBubble( 508 OneClickSigninBubbleType type, 509 const base::string16& email, 510 const base::string16& error_message, 511 const StartSyncCallback& start_sync_callback) { 512 WebContents* web_contents = 513 browser_->tab_strip_model()->GetActiveWebContents(); 514 if (type == ONE_CLICK_SIGNIN_BUBBLE_TYPE_BUBBLE) { 515 base::scoped_nsobject<OneClickSigninBubbleController> bubble_controller([ 516 [OneClickSigninBubbleController alloc] 517 initWithBrowserWindowController:cocoa_controller() 518 webContents:web_contents 519 errorMessage:base::SysUTF16ToNSString(error_message) 520 callback:start_sync_callback]); 521 [bubble_controller showWindow:nil]; 522 } else { 523 // Deletes itself when the dialog closes. 524 new OneClickSigninDialogController( 525 web_contents, start_sync_callback, email); 526 } 527} 528#endif 529 530bool BrowserWindowCocoa::IsDownloadShelfVisible() const { 531 return [controller_ isDownloadShelfVisible] != NO; 532} 533 534DownloadShelf* BrowserWindowCocoa::GetDownloadShelf() { 535 [controller_ createAndAddDownloadShelf]; 536 DownloadShelfController* shelfController = [controller_ downloadShelf]; 537 return [shelfController bridge]; 538} 539 540// We allow closing the window here since the real quit decision on Mac is made 541// in [AppController quit:]. 542void BrowserWindowCocoa::ConfirmBrowserCloseWithPendingDownloads( 543 int download_count, 544 Browser::DownloadClosePreventionType dialog_type, 545 bool app_modal, 546 const base::Callback<void(bool)>& callback) { 547 callback.Run(true); 548} 549 550void BrowserWindowCocoa::UserChangedTheme() { 551 [controller_ userChangedTheme]; 552} 553 554int BrowserWindowCocoa::GetExtraRenderViewHeight() const { 555 // Currently this is only used on linux. 556 return 0; 557} 558 559void BrowserWindowCocoa::WebContentsFocused(WebContents* contents) { 560 NOTIMPLEMENTED(); 561} 562 563void BrowserWindowCocoa::ShowWebsiteSettings( 564 Profile* profile, 565 content::WebContents* web_contents, 566 const GURL& url, 567 const content::SSLStatus& ssl) { 568 WebsiteSettingsUIBridge::Show(window(), profile, web_contents, url, ssl); 569} 570 571void BrowserWindowCocoa::ShowAppMenu() { 572 // No-op. Mac doesn't support showing the menus via alt keys. 573} 574 575bool BrowserWindowCocoa::PreHandleKeyboardEvent( 576 const NativeWebKeyboardEvent& event, bool* is_keyboard_shortcut) { 577 if (![BrowserWindowUtils shouldHandleKeyboardEvent:event]) 578 return false; 579 580 if (event.type == blink::WebInputEvent::RawKeyDown && 581 [controller_ 582 handledByExtensionCommand:event.os_event 583 priority:ui::AcceleratorManager::kHighPriority]) 584 return true; 585 586 int id = [BrowserWindowUtils getCommandId:event]; 587 if (id == -1) 588 return false; 589 590 if (browser_->command_controller()->IsReservedCommandOrKey(id, event)) { 591 return [BrowserWindowUtils handleKeyboardEvent:event.os_event 592 inWindow:window()]; 593 } 594 595 DCHECK(is_keyboard_shortcut); 596 *is_keyboard_shortcut = true; 597 return false; 598} 599 600void BrowserWindowCocoa::HandleKeyboardEvent( 601 const NativeWebKeyboardEvent& event) { 602 if ([BrowserWindowUtils shouldHandleKeyboardEvent:event]) 603 [BrowserWindowUtils handleKeyboardEvent:event.os_event inWindow:window()]; 604} 605 606void BrowserWindowCocoa::Cut() { 607 [NSApp sendAction:@selector(cut:) to:nil from:nil]; 608} 609 610void BrowserWindowCocoa::Copy() { 611 [NSApp sendAction:@selector(copy:) to:nil from:nil]; 612} 613 614void BrowserWindowCocoa::Paste() { 615 [NSApp sendAction:@selector(paste:) to:nil from:nil]; 616} 617 618void BrowserWindowCocoa::EnterFullscreenWithChrome() { 619 CHECK(chrome::mac::SupportsSystemFullscreen()); 620 [controller_ enterFullscreenWithChrome]; 621} 622 623void BrowserWindowCocoa::EnterFullscreenWithoutChrome() { 624 [controller_ enterPresentationMode]; 625} 626 627bool BrowserWindowCocoa::IsFullscreenWithChrome() { 628 return IsFullscreen() && ![controller_ inPresentationMode]; 629} 630 631bool BrowserWindowCocoa::IsFullscreenWithoutChrome() { 632 return IsFullscreen() && [controller_ inPresentationMode]; 633} 634 635WindowOpenDisposition BrowserWindowCocoa::GetDispositionForPopupBounds( 636 const gfx::Rect& bounds) { 637 // When using Cocoa's System Fullscreen mode, convert popups into tabs. 638 if ([controller_ isInAppKitFullscreen]) 639 return NEW_FOREGROUND_TAB; 640 return NEW_POPUP; 641} 642 643FindBar* BrowserWindowCocoa::CreateFindBar() { 644 // We could push the AddFindBar() call into the FindBarBridge 645 // constructor or the FindBarCocoaController init, but that makes 646 // unit testing difficult, since we would also require a 647 // BrowserWindow object. 648 FindBarBridge* bridge = new FindBarBridge(browser_); 649 AddFindBar(bridge->find_bar_cocoa_controller()); 650 return bridge; 651} 652 653web_modal::WebContentsModalDialogHost* 654 BrowserWindowCocoa::GetWebContentsModalDialogHost() { 655 return NULL; 656} 657 658extensions::ActiveTabPermissionGranter* 659 BrowserWindowCocoa::GetActiveTabPermissionGranter() { 660 WebContents* web_contents = 661 browser_->tab_strip_model()->GetActiveWebContents(); 662 if (!web_contents) 663 return NULL; 664 extensions::TabHelper* tab_helper = 665 extensions::TabHelper::FromWebContents(web_contents); 666 return tab_helper ? tab_helper->active_tab_permission_granter() : NULL; 667} 668 669void BrowserWindowCocoa::ModelChanged(const SearchModel::State& old_state, 670 const SearchModel::State& new_state) { 671} 672 673void BrowserWindowCocoa::DestroyBrowser() { 674 [controller_ destroyBrowser]; 675 676 // at this point the controller is dead (autoreleased), so 677 // make sure we don't try to reference it any more. 678} 679 680NSWindow* BrowserWindowCocoa::window() const { 681 return [controller_ window]; 682} 683 684void BrowserWindowCocoa::ShowAvatarBubble(WebContents* web_contents, 685 const gfx::Rect& rect) { 686 NSPoint point = GetPointForBubble(web_contents, rect.right(), rect.bottom()); 687 688 // |menu| will automatically release itself on close. 689 AvatarMenuBubbleController* menu = 690 [[AvatarMenuBubbleController alloc] initWithBrowser:browser_ 691 anchoredAt:point]; 692 [[menu bubble] setAlignment:info_bubble::kAlignEdgeToAnchorEdge]; 693 [menu showWindow:nil]; 694} 695 696void BrowserWindowCocoa::ShowAvatarBubbleFromAvatarButton( 697 AvatarBubbleMode mode, 698 const signin::ManageAccountsParams& manage_accounts_params) { 699 AvatarBaseController* controller = [controller_ avatarButtonController]; 700 NSView* anchor = [controller buttonView]; 701 if ([anchor isHiddenOrHasHiddenAncestor]) 702 anchor = [[controller_ toolbarController] wrenchButton]; 703 [controller showAvatarBubbleAnchoredAt:anchor 704 withMode:mode 705 withServiceType:manage_accounts_params.service_type]; 706} 707 708int 709BrowserWindowCocoa::GetRenderViewHeightInsetWithDetachedBookmarkBar() { 710 if (browser_->bookmark_bar_state() != BookmarkBar::DETACHED) 711 return 0; 712 return 40; 713} 714 715void BrowserWindowCocoa::ExecuteExtensionCommand( 716 const extensions::Extension* extension, 717 const extensions::Command& command) { 718 [cocoa_controller() executeExtensionCommand:extension->id() command:command]; 719} 720