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