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