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