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