Check USB device path access when prompting users to select a device.
[chromium-blink-merge.git] / chrome / browser / ui / cocoa / browser_window_cocoa.mm
blob9f4617085848f50cb61f91907d41067b276e216b
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.
5 #include "chrome/browser/ui/cocoa/browser_window_cocoa.h"
7 #include "base/bind.h"
8 #include "base/command_line.h"
9 #include "base/logging.h"
10 #import "base/mac/sdk_forward_declarations.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/prefs/pref_service.h"
13 #include "base/strings/string_util.h"
14 #include "base/strings/sys_string_conversions.h"
15 #include "chrome/app/chrome_command_ids.h"
16 #include "chrome/browser/chrome_notification_types.h"
17 #include "chrome/browser/download/download_shelf.h"
18 #include "chrome/browser/extensions/tab_helper.h"
19 #include "chrome/browser/fullscreen.h"
20 #include "chrome/browser/profiles/profile.h"
21 #include "chrome/browser/shell_integration.h"
22 #include "chrome/browser/signin/signin_header_helper.h"
23 #include "chrome/browser/translate/chrome_translate_client.h"
24 #include "chrome/browser/ui/browser.h"
25 #include "chrome/browser/ui/browser_command_controller.h"
26 #include "chrome/browser/ui/browser_commands_mac.h"
27 #include "chrome/browser/ui/browser_list.h"
28 #include "chrome/browser/ui/browser_window_state.h"
29 #import "chrome/browser/ui/cocoa/browser/edit_search_engine_cocoa_controller.h"
30 #import "chrome/browser/ui/cocoa/browser_window_controller.h"
31 #import "chrome/browser/ui/cocoa/browser_window_utils.h"
32 #import "chrome/browser/ui/cocoa/chrome_event_processing_window.h"
33 #import "chrome/browser/ui/cocoa/download/download_shelf_controller.h"
34 #include "chrome/browser/ui/cocoa/find_bar/find_bar_bridge.h"
35 #import "chrome/browser/ui/cocoa/info_bubble_view.h"
36 #include "chrome/browser/ui/cocoa/key_equivalent_constants.h"
37 #import "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h"
38 #import "chrome/browser/ui/cocoa/nsmenuitem_additions.h"
39 #import "chrome/browser/ui/cocoa/profiles/avatar_base_controller.h"
40 #import "chrome/browser/ui/cocoa/profiles/avatar_menu_bubble_controller.h"
41 #include "chrome/browser/ui/cocoa/restart_browser.h"
42 #include "chrome/browser/ui/cocoa/status_bubble_mac.h"
43 #include "chrome/browser/ui/cocoa/task_manager_mac.h"
44 #import "chrome/browser/ui/cocoa/toolbar/toolbar_controller.h"
45 #import "chrome/browser/ui/cocoa/web_dialog_window_controller.h"
46 #import "chrome/browser/ui/cocoa/website_settings/website_settings_bubble_controller.h"
47 #include "chrome/browser/ui/exclusive_access/fullscreen_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 "chrome/grit/generated_resources.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/notification_service.h"
59 #include "content/public/browser/web_contents.h"
60 #include "extensions/browser/extension_registry.h"
61 #include "extensions/browser/extension_system.h"
62 #include "extensions/common/constants.h"
63 #include "ui/base/l10n/l10n_util_mac.h"
64 #include "ui/gfx/geometry/rect.h"
66 #if defined(ENABLE_ONE_CLICK_SIGNIN)
67 #import "chrome/browser/ui/cocoa/one_click_signin_bubble_controller.h"
68 #import "chrome/browser/ui/cocoa/one_click_signin_dialog_controller.h"
69 #endif
71 using content::NativeWebKeyboardEvent;
72 using content::SSLStatus;
73 using content::WebContents;
75 namespace {
77 // These UI constants are used in BrowserWindowCocoa::ShowBookmarkAppBubble.
78 // Used for defining the layout of the NSAlert and NSTextField within the
79 // accessory view.
80 const int kAppTextFieldVerticalSpacing = 2;
81 const int kAppTextFieldWidth = 200;
82 const int kAppTextFieldHeight = 22;
83 const int kBookmarkAppBubbleViewWidth = 200;
84 const int kBookmarkAppBubbleViewHeight = 46;
86 const int kIconPreviewTargetSize = 128;
88 base::string16 TrimText(NSString* controlText) {
89   base::string16 text = base::SysNSStringToUTF16(controlText);
90   base::TrimWhitespace(text, base::TRIM_ALL, &text);
91   return text;
94 }  // namespace
96 @interface TextRequiringDelegate : NSObject<NSTextFieldDelegate> {
97  @private
98   // Disable |control_| when text changes to just whitespace or empty string.
99   NSControl* control_;
101 - (id)initWithControl:(NSControl*)control text:(NSString*)text;
102 - (void)controlTextDidChange:(NSNotification*)notification;
103 @end
105 @interface TextRequiringDelegate ()
106 - (void)validateText:(NSString*)text;
107 @end
109 @implementation TextRequiringDelegate
110 - (id)initWithControl:(NSControl*)control text:(NSString*)text {
111   if ((self = [super init])) {
112     control_ = control;
113     [self validateText:text];
114   }
115   return self;
118 - (void)controlTextDidChange:(NSNotification*)notification {
119   [self validateText:[[notification object] stringValue]];
122 - (void)validateText:(NSString*)text {
123   [control_ setEnabled:TrimText(text).empty() ? NO : YES];
125 @end
127 BrowserWindowCocoa::BrowserWindowCocoa(Browser* browser,
128                                        BrowserWindowController* controller)
129   : browser_(browser),
130     controller_(controller),
131     initial_show_state_(ui::SHOW_STATE_DEFAULT),
132     attention_request_id_(0) {
134   gfx::Rect bounds;
135   chrome::GetSavedWindowBoundsAndShowState(browser_,
136                                            &bounds,
137                                            &initial_show_state_);
139   browser_->search_model()->AddObserver(this);
142 BrowserWindowCocoa::~BrowserWindowCocoa() {
143   browser_->search_model()->RemoveObserver(this);
146 void BrowserWindowCocoa::Show() {
147   // The Browser associated with this browser window must become the active
148   // browser at the time |Show()| is called. This is the natural behaviour under
149   // Windows, but |-makeKeyAndOrderFront:| won't send |-windowDidBecomeMain:|
150   // until we return to the runloop. Therefore any calls to
151   // |chrome::FindLastActiveWithHostDesktopType| will return the previous
152   // browser instead if we don't explicitly set it here.
153   BrowserList::SetLastActive(browser_);
155   bool is_session_restore = browser_->is_session_restore();
156   NSWindowAnimationBehavior saved_animation_behavior =
157       NSWindowAnimationBehaviorDefault;
158   bool did_save_animation_behavior = false;
159   // Turn off swishing when restoring windows or showing an app.
160   if ((is_session_restore || browser_->is_app()) &&
161       [window() respondsToSelector:@selector(animationBehavior)] &&
162       [window() respondsToSelector:@selector(setAnimationBehavior:)]) {
163     did_save_animation_behavior = true;
164     saved_animation_behavior = [window() animationBehavior];
165     [window() setAnimationBehavior:NSWindowAnimationBehaviorNone];
166   }
168   {
169     TRACE_EVENT0("ui", "BrowserWindowCocoa::Show makeKeyAndOrderFront");
170     // This call takes up a substantial part of startup time, and an even more
171     // substantial part of startup time when any CALayers are part of the
172     // window's NSView heirarchy.
173     [window() makeKeyAndOrderFront:controller_];
174   }
176   // When creating windows from nibs it is necessary to |makeKeyAndOrderFront:|
177   // prior to |orderOut:| then |miniaturize:| when restoring windows in the
178   // minimized state.
179   if (initial_show_state_ == ui::SHOW_STATE_MINIMIZED) {
180     [window() orderOut:controller_];
181     [window() miniaturize:controller_];
182   } else if (initial_show_state_ == ui::SHOW_STATE_FULLSCREEN) {
183     chrome::ToggleFullscreenWithToolbarOrFallback(browser_);
184   }
185   initial_show_state_ = ui::SHOW_STATE_DEFAULT;
187   // Restore window animation behavior.
188   if (did_save_animation_behavior)
189     [window() setAnimationBehavior:saved_animation_behavior];
191   browser_->OnWindowDidShow();
194 void BrowserWindowCocoa::ShowInactive() {
195   [window() orderFront:controller_];
198 void BrowserWindowCocoa::Hide() {
199   [window() orderOut:controller_];
202 void BrowserWindowCocoa::SetBounds(const gfx::Rect& bounds) {
203   gfx::Rect real_bounds = [controller_ enforceMinWindowSize:bounds];
205   ExitFullscreen();
206   NSRect cocoa_bounds = NSMakeRect(real_bounds.x(), 0,
207                                    real_bounds.width(),
208                                    real_bounds.height());
209   // Flip coordinates based on the primary screen.
210   NSScreen* screen = [[NSScreen screens] objectAtIndex:0];
211   cocoa_bounds.origin.y =
212       NSHeight([screen frame]) - real_bounds.height() - real_bounds.y();
214   [window() setFrame:cocoa_bounds display:YES];
217 // Callers assume that this doesn't immediately delete the Browser object.
218 // The controller implementing the window delegate methods called from
219 // |-performClose:| must take precautions to ensure that.
220 void BrowserWindowCocoa::Close() {
221   // If there is an overlay window, we contain a tab being dragged between
222   // windows. Don't hide the window as it makes the UI extra confused. We can
223   // still close the window, as that will happen when the drag completes.
224   if ([controller_ overlayWindow]) {
225     [controller_ deferPerformClose];
226   } else {
227     // Using |-performClose:| can prevent the window from actually closing if
228     // a JavaScript beforeunload handler opens an alert during shutdown, as
229     // documented at <http://crbug.com/118424>. Re-implement
230     // -[NSWindow performClose:] as closely as possible to how Apple documents
231     // it.
232     //
233     // Before calling |-close|, hide the window immediately. |-performClose:|
234     // would do something similar, and this ensures that the window is removed
235     // from AppKit's display list. Not doing so can lead to crashes like
236     // <http://crbug.com/156101>.
237     id<NSWindowDelegate> delegate = [window() delegate];
238     SEL window_should_close = @selector(windowShouldClose:);
239     if ([delegate respondsToSelector:window_should_close]) {
240       if ([delegate windowShouldClose:window()]) {
241         [window() orderOut:nil];
242         [window() close];
243       }
244     } else if ([window() respondsToSelector:window_should_close]) {
245       if ([window() performSelector:window_should_close withObject:window()]) {
246         [window() orderOut:nil];
247         [window() close];
248       }
249     } else {
250       [window() orderOut:nil];
251       [window() close];
252     }
253   }
256 void BrowserWindowCocoa::Activate() {
257   [controller_ activate];
260 void BrowserWindowCocoa::Deactivate() {
261   // TODO(jcivelli): http://crbug.com/51364 Implement me.
262   NOTIMPLEMENTED();
265 void BrowserWindowCocoa::FlashFrame(bool flash) {
266   if (flash) {
267     attention_request_id_ = [NSApp requestUserAttention:NSInformationalRequest];
268   } else {
269     [NSApp cancelUserAttentionRequest:attention_request_id_];
270     attention_request_id_ = 0;
271   }
274 bool BrowserWindowCocoa::IsAlwaysOnTop() const {
275   return false;
278 void BrowserWindowCocoa::SetAlwaysOnTop(bool always_on_top) {
279   // Not implemented for browser windows.
280   NOTIMPLEMENTED();
283 bool BrowserWindowCocoa::IsActive() const {
284   return [window() isKeyWindow];
287 gfx::NativeWindow BrowserWindowCocoa::GetNativeWindow() const {
288   return window();
291 StatusBubble* BrowserWindowCocoa::GetStatusBubble() {
292   return [controller_ statusBubble];
295 void BrowserWindowCocoa::UpdateTitleBar() {
296   NSString* newTitle =
297       base::SysUTF16ToNSString(browser_->GetWindowTitleForCurrentTab());
299   pending_window_title_.reset(
300       [BrowserWindowUtils scheduleReplaceOldTitle:pending_window_title_.get()
301                                      withNewTitle:newTitle
302                                         forWindow:window()]);
305 void BrowserWindowCocoa::BookmarkBarStateChanged(
306     BookmarkBar::AnimateChangeType change_type) {
307   [[controller_ bookmarkBarController]
308       updateState:browser_->bookmark_bar_state()
309        changeType:change_type];
312 void BrowserWindowCocoa::UpdateDevTools() {
313   [controller_ updateDevToolsForContents:
314       browser_->tab_strip_model()->GetActiveWebContents()];
317 void BrowserWindowCocoa::UpdateLoadingAnimations(bool should_animate) {
318   // Do nothing on Mac.
321 void BrowserWindowCocoa::SetStarredState(bool is_starred) {
322   [controller_ setStarredState:is_starred];
325 void BrowserWindowCocoa::SetTranslateIconToggled(bool is_lit) {
326   [controller_ setCurrentPageIsTranslated:is_lit];
329 void BrowserWindowCocoa::OnActiveTabChanged(content::WebContents* old_contents,
330                                             content::WebContents* new_contents,
331                                             int index,
332                                             int reason) {
333   // TODO(pkasting): Perhaps the code in
334   // TabStripController::activateTabWithContents should move here?  Or this
335   // should call that (instead of TabStripModelObserverBridge doing so)?  It's
336   // not obvious to me why Mac doesn't handle tab changes in BrowserWindow the
337   // way views and GTK do.
340 void BrowserWindowCocoa::ZoomChangedForActiveTab(bool can_show_bubble) {
341   [controller_ zoomChangedForActiveTab:can_show_bubble ? YES : NO];
344 gfx::Rect BrowserWindowCocoa::GetRestoredBounds() const {
345   // Flip coordinates based on the primary screen.
346   NSScreen* screen = [[NSScreen screens] objectAtIndex:0];
347   NSRect frame = [controller_ regularWindowFrame];
348   gfx::Rect bounds(frame.origin.x, 0, NSWidth(frame), NSHeight(frame));
349   bounds.set_y(NSHeight([screen frame]) - NSMaxY(frame));
350   return bounds;
353 ui::WindowShowState BrowserWindowCocoa::GetRestoredState() const {
354   if (IsMaximized())
355     return ui::SHOW_STATE_MAXIMIZED;
356   if (IsMinimized())
357     return ui::SHOW_STATE_MINIMIZED;
358   return ui::SHOW_STATE_NORMAL;
361 gfx::Rect BrowserWindowCocoa::GetBounds() const {
362   return GetRestoredBounds();
365 bool BrowserWindowCocoa::IsMaximized() const {
366   // -isZoomed returns YES if the window's frame equals the rect returned by
367   // -windowWillUseStandardFrame:defaultFrame:, even if the window is in the
368   // dock, so have to explicitly check for miniaturization state first.
369   return ![window() isMiniaturized] && [window() isZoomed];
372 bool BrowserWindowCocoa::IsMinimized() const {
373   return [window() isMiniaturized];
376 void BrowserWindowCocoa::Maximize() {
377   // Zoom toggles so only call if not already maximized.
378   if (!IsMaximized())
379     [window() zoom:controller_];
382 void BrowserWindowCocoa::Minimize() {
383   [window() miniaturize:controller_];
386 void BrowserWindowCocoa::Restore() {
387   if (IsMaximized())
388     [window() zoom:controller_];  // Toggles zoom mode.
389   else if (IsMinimized())
390     [window() deminiaturize:controller_];
393 // See browser_window_controller.h for a detailed explanation of the logic in
394 // this method.
395 void BrowserWindowCocoa::EnterFullscreen(const GURL& url,
396                                          ExclusiveAccessBubbleType bubble_type,
397                                          bool with_toolbar) {
398   if (browser_->exclusive_access_manager()
399           ->fullscreen_controller()
400           ->IsWindowFullscreenForTabOrPending())
401     [controller_ enterWebContentFullscreenForURL:url bubbleType:bubble_type];
402   else if (!url.is_empty())
403     [controller_ enterExtensionFullscreenForURL:url bubbleType:bubble_type];
404   else
405     [controller_ enterBrowserFullscreenWithToolbar:with_toolbar];
408 void BrowserWindowCocoa::ExitFullscreen() {
409   [controller_ exitAnyFullscreen];
412 void BrowserWindowCocoa::UpdateExclusiveAccessExitBubbleContent(
413     const GURL& url,
414     ExclusiveAccessBubbleType bubble_type) {
415   [controller_ updateFullscreenExitBubbleURL:url bubbleType:bubble_type];
418 bool BrowserWindowCocoa::ShouldHideUIForFullscreen() const {
419   // On Mac, fullscreen mode has most normal things (in a slide-down panel).
420   return false;
423 bool BrowserWindowCocoa::IsFullscreen() const {
424   return [controller_ isInAnyFullscreenMode];
427 bool BrowserWindowCocoa::IsFullscreenBubbleVisible() const {
428   return false;
431 bool BrowserWindowCocoa::SupportsFullscreenWithToolbar() const {
432   return chrome::mac::SupportsSystemFullscreen();
435 void BrowserWindowCocoa::UpdateFullscreenWithToolbar(bool with_toolbar) {
436   [controller_ updateFullscreenWithToolbar:with_toolbar];
439 bool BrowserWindowCocoa::IsFullscreenWithToolbar() const {
440   return IsFullscreen() && ![controller_ inPresentationMode];
443 void BrowserWindowCocoa::ConfirmAddSearchProvider(
444     TemplateURL* template_url,
445     Profile* profile) {
446   // The controller will release itself when the window closes.
447   EditSearchEngineCocoaController* editor =
448       [[EditSearchEngineCocoaController alloc] initWithProfile:profile
449                                                       delegate:NULL
450                                                    templateURL:template_url];
451   [NSApp beginSheet:[editor window]
452      modalForWindow:window()
453       modalDelegate:controller_
454      didEndSelector:@selector(sheetDidEnd:returnCode:context:)
455         contextInfo:NULL];
458 LocationBar* BrowserWindowCocoa::GetLocationBar() const {
459   return [controller_ locationBarBridge];
462 void BrowserWindowCocoa::SetFocusToLocationBar(bool select_all) {
463   [controller_ focusLocationBar:select_all ? YES : NO];
466 void BrowserWindowCocoa::UpdateReloadStopState(bool is_loading, bool force) {
467   [controller_ setIsLoading:is_loading force:force];
470 void BrowserWindowCocoa::UpdateToolbar(content::WebContents* contents) {
471   [controller_ updateToolbarWithContents:contents];
474 void BrowserWindowCocoa::ResetToolbarTabState(content::WebContents* contents) {
475   [controller_ resetTabState:contents];
478 void BrowserWindowCocoa::FocusToolbar() {
479   // Not needed on the Mac.
482 void BrowserWindowCocoa::ToolbarSizeChanged(bool is_animating) {
483   // Not needed on the Mac.
486 void BrowserWindowCocoa::FocusAppMenu() {
487   // Chrome uses the standard Mac OS X menu bar, so this isn't needed.
490 void BrowserWindowCocoa::RotatePaneFocus(bool forwards) {
491   // Not needed on the Mac.
494 void BrowserWindowCocoa::FocusBookmarksToolbar() {
495   // Not needed on the Mac.
498 void BrowserWindowCocoa::FocusInfobars() {
499   // Not needed on the Mac.
502 bool BrowserWindowCocoa::IsBookmarkBarVisible() const {
503   return browser_->profile()->GetPrefs()->GetBoolean(
504       bookmarks::prefs::kShowBookmarkBar);
507 bool BrowserWindowCocoa::IsBookmarkBarAnimating() const {
508   return [controller_ isBookmarkBarAnimating];
511 bool BrowserWindowCocoa::IsTabStripEditable() const {
512   return ![controller_ isDragSessionActive];
515 bool BrowserWindowCocoa::IsToolbarVisible() const {
516   return browser_->SupportsWindowFeature(Browser::FEATURE_TOOLBAR) ||
517          browser_->SupportsWindowFeature(Browser::FEATURE_LOCATIONBAR);
520 gfx::Rect BrowserWindowCocoa::GetRootWindowResizerRect() const {
521   if (IsDownloadShelfVisible())
522     return gfx::Rect();
523   NSRect tabRect = [controller_ selectedTabGrowBoxRect];
524   return gfx::Rect(NSRectToCGRect(tabRect));
527 void BrowserWindowCocoa::AddFindBar(
528     FindBarCocoaController* find_bar_cocoa_controller) {
529   [controller_ addFindBar:find_bar_cocoa_controller];
532 void BrowserWindowCocoa::ShowUpdateChromeDialog() {
533   restart_browser::RequestRestart(window());
536 void BrowserWindowCocoa::ShowBookmarkBubble(const GURL& url,
537                                             bool already_bookmarked) {
538   [controller_ showBookmarkBubbleForURL:url
539                       alreadyBookmarked:(already_bookmarked ? YES : NO)];
542 void BrowserWindowCocoa::ShowBookmarkAppBubble(
543     const WebApplicationInfo& web_app_info,
544     const ShowBookmarkAppBubbleCallback& callback) {
545   base::scoped_nsobject<NSAlert> alert([[NSAlert alloc] init]);
546   [alert setMessageText:l10n_util::GetNSString(
547       IDS_ADD_TO_APPLICATIONS_BUBBLE_TITLE)];
548   [alert setAlertStyle:NSInformationalAlertStyle];
550   NSButton* continue_button =
551       [alert addButtonWithTitle:l10n_util::GetNSString(IDS_OK)];
552   [continue_button setKeyEquivalent:kKeyEquivalentReturn];
553   NSButton* cancel_button =
554       [alert addButtonWithTitle:l10n_util::GetNSString(IDS_CANCEL)];
555   [cancel_button setKeyEquivalent:kKeyEquivalentEscape];
557   base::scoped_nsobject<NSButton> open_as_window_checkbox(
558       [[NSButton alloc] initWithFrame:NSZeroRect]);
559   [open_as_window_checkbox setButtonType:NSSwitchButton];
560   [open_as_window_checkbox
561       setTitle:l10n_util::GetNSString(IDS_BOOKMARK_APP_BUBBLE_OPEN_AS_WINDOW)];
562   [open_as_window_checkbox setState:web_app_info.open_as_window];
563   [open_as_window_checkbox sizeToFit];
565   base::scoped_nsobject<NSTextField> app_title([[NSTextField alloc]
566       initWithFrame:NSMakeRect(0, kAppTextFieldHeight +
567                                       kAppTextFieldVerticalSpacing,
568                                kAppTextFieldWidth, kAppTextFieldHeight)]);
569   NSString* original_title = SysUTF16ToNSString(web_app_info.title);
570   [[app_title cell] setWraps:NO];
571   [[app_title cell] setScrollable:YES];
572   [app_title setStringValue:original_title];
573   base::scoped_nsobject<TextRequiringDelegate> delegate(
574       [[TextRequiringDelegate alloc] initWithControl:continue_button
575                                                 text:[app_title stringValue]]);
576   [app_title setDelegate:delegate];
578   base::scoped_nsobject<NSView> view([[NSView alloc]
579       initWithFrame:NSMakeRect(0, 0, kBookmarkAppBubbleViewWidth,
580                                kBookmarkAppBubbleViewHeight)]);
581   [view addSubview:open_as_window_checkbox];
582   [view addSubview:app_title];
583   [alert setAccessoryView:view];
585   // Find the image with target size.
586   // Assumes that the icons are sorted in ascending order of size.
587   if (!web_app_info.icons.empty()) {
588     for (const WebApplicationInfo::IconInfo& info : web_app_info.icons) {
589       if (info.width == kIconPreviewTargetSize &&
590           info.height == kIconPreviewTargetSize) {
591         gfx::Image icon_image = gfx::Image::CreateFrom1xBitmap(info.data);
592         [alert setIcon:icon_image.ToNSImage()];
593         break;
594       }
595     }
596   }
598   NSInteger response = [alert runModal];
600   // Prevent |app_title| from accessing |delegate| after it's destroyed.
601   [app_title setDelegate:nil];
603   if (response == NSAlertFirstButtonReturn) {
604     WebApplicationInfo updated_info = web_app_info;
605     updated_info.open_as_window = [open_as_window_checkbox state] == NSOnState;
606     updated_info.title = TrimText([app_title stringValue]);
608     callback.Run(true, updated_info);
609     return;
610   }
612   callback.Run(false, web_app_info);
615 void BrowserWindowCocoa::ShowTranslateBubble(
616     content::WebContents* contents,
617     translate::TranslateStep step,
618     translate::TranslateErrors::Type error_type,
619     bool is_user_gesture) {
620   ChromeTranslateClient* chrome_translate_client =
621       ChromeTranslateClient::FromWebContents(contents);
622   translate::LanguageState& language_state =
623       chrome_translate_client->GetLanguageState();
624   language_state.SetTranslateEnabled(true);
626   [controller_ showTranslateBubbleForWebContents:contents
627                                             step:step
628                                        errorType:error_type];
631 bool BrowserWindowCocoa::ShowSessionCrashedBubble() {
632   return false;
635 bool BrowserWindowCocoa::IsProfileResetBubbleSupported() const {
636   return false;
639 GlobalErrorBubbleViewBase* BrowserWindowCocoa::ShowProfileResetBubble(
640     const base::WeakPtr<ProfileResetGlobalError>& global_error) {
641   NOTREACHED();
642   return nullptr;
645 #if defined(ENABLE_ONE_CLICK_SIGNIN)
646 void BrowserWindowCocoa::ShowOneClickSigninBubble(
647     OneClickSigninBubbleType type,
648     const base::string16& email,
649     const base::string16& error_message,
650     const StartSyncCallback& start_sync_callback) {
651   WebContents* web_contents =
652         browser_->tab_strip_model()->GetActiveWebContents();
653   if (type == ONE_CLICK_SIGNIN_BUBBLE_TYPE_BUBBLE) {
654     base::scoped_nsobject<OneClickSigninBubbleController> bubble_controller([
655             [OneClickSigninBubbleController alloc]
656         initWithBrowserWindowController:cocoa_controller()
657                             webContents:web_contents
658                            errorMessage:base::SysUTF16ToNSString(error_message)
659                                callback:start_sync_callback]);
660     [bubble_controller showWindow:nil];
661   } else {
662     // Deletes itself when the dialog closes.
663     new OneClickSigninDialogController(
664         web_contents, start_sync_callback, email);
665   }
667 #endif
669 bool BrowserWindowCocoa::IsDownloadShelfVisible() const {
670   return [controller_ isDownloadShelfVisible] != NO;
673 DownloadShelf* BrowserWindowCocoa::GetDownloadShelf() {
674   [controller_ createAndAddDownloadShelf];
675   DownloadShelfController* shelfController = [controller_ downloadShelf];
676   return [shelfController bridge];
679 // We allow closing the window here since the real quit decision on Mac is made
680 // in [AppController quit:].
681 void BrowserWindowCocoa::ConfirmBrowserCloseWithPendingDownloads(
682       int download_count,
683       Browser::DownloadClosePreventionType dialog_type,
684       bool app_modal,
685       const base::Callback<void(bool)>& callback) {
686   callback.Run(true);
689 void BrowserWindowCocoa::UserChangedTheme() {
690   [controller_ userChangedTheme];
693 void BrowserWindowCocoa::WebContentsFocused(WebContents* contents) {
694   NOTIMPLEMENTED();
697 void BrowserWindowCocoa::ShowWebsiteSettings(
698     Profile* profile,
699     content::WebContents* web_contents,
700     const GURL& url,
701     const content::SSLStatus& ssl) {
702   WebsiteSettingsUIBridge::Show(window(), profile, web_contents, url, ssl);
705 void BrowserWindowCocoa::ShowAppMenu() {
706   // No-op. Mac doesn't support showing the menus via alt keys.
709 bool BrowserWindowCocoa::PreHandleKeyboardEvent(
710     const NativeWebKeyboardEvent& event, bool* is_keyboard_shortcut) {
711   if (![BrowserWindowUtils shouldHandleKeyboardEvent:event])
712     return false;
714   if (event.type == blink::WebInputEvent::RawKeyDown &&
715       [controller_
716           handledByExtensionCommand:event.os_event
717                            priority:ui::AcceleratorManager::kHighPriority])
718     return true;
720   int id = [BrowserWindowUtils getCommandId:event];
721   if (id == -1)
722     return false;
724   if (browser_->command_controller()->IsReservedCommandOrKey(id, event)) {
725       return [BrowserWindowUtils handleKeyboardEvent:event.os_event
726                                             inWindow:window()];
727   }
729   DCHECK(is_keyboard_shortcut);
730   *is_keyboard_shortcut = true;
731   return false;
734 void BrowserWindowCocoa::HandleKeyboardEvent(
735     const NativeWebKeyboardEvent& event) {
736   if ([BrowserWindowUtils shouldHandleKeyboardEvent:event])
737     [BrowserWindowUtils handleKeyboardEvent:event.os_event inWindow:window()];
740 void BrowserWindowCocoa::Cut() {
741   [NSApp sendAction:@selector(cut:) to:nil from:nil];
744 void BrowserWindowCocoa::Copy() {
745   [NSApp sendAction:@selector(copy:) to:nil from:nil];
748 void BrowserWindowCocoa::Paste() {
749   [NSApp sendAction:@selector(paste:) to:nil from:nil];
752 WindowOpenDisposition BrowserWindowCocoa::GetDispositionForPopupBounds(
753     const gfx::Rect& bounds) {
754   // When using Cocoa's System Fullscreen mode, convert popups into tabs.
755   if ([controller_ isInAppKitFullscreen])
756     return NEW_FOREGROUND_TAB;
757   return NEW_POPUP;
760 FindBar* BrowserWindowCocoa::CreateFindBar() {
761   // We could push the AddFindBar() call into the FindBarBridge
762   // constructor or the FindBarCocoaController init, but that makes
763   // unit testing difficult, since we would also require a
764   // BrowserWindow object.
765   FindBarBridge* bridge = new FindBarBridge(browser_);
766   AddFindBar(bridge->find_bar_cocoa_controller());
767   return bridge;
770 web_modal::WebContentsModalDialogHost*
771     BrowserWindowCocoa::GetWebContentsModalDialogHost() {
772   return NULL;
775 extensions::ActiveTabPermissionGranter*
776     BrowserWindowCocoa::GetActiveTabPermissionGranter() {
777   WebContents* web_contents =
778       browser_->tab_strip_model()->GetActiveWebContents();
779   if (!web_contents)
780     return NULL;
781   extensions::TabHelper* tab_helper =
782       extensions::TabHelper::FromWebContents(web_contents);
783   return tab_helper ? tab_helper->active_tab_permission_granter() : NULL;
786 void BrowserWindowCocoa::ModelChanged(const SearchModel::State& old_state,
787                                       const SearchModel::State& new_state) {
790 void BrowserWindowCocoa::DestroyBrowser() {
791   [controller_ destroyBrowser];
793   // at this point the controller is dead (autoreleased), so
794   // make sure we don't try to reference it any more.
797 NSWindow* BrowserWindowCocoa::window() const {
798   return [controller_ window];
801 void BrowserWindowCocoa::ShowAvatarBubbleFromAvatarButton(
802     AvatarBubbleMode mode,
803     const signin::ManageAccountsParams& manage_accounts_params) {
804   AvatarBaseController* controller = [controller_ avatarButtonController];
805   NSView* anchor = [controller buttonView];
806   if ([anchor isHiddenOrHasHiddenAncestor])
807     anchor = [[controller_ toolbarController] wrenchButton];
808   [controller showAvatarBubbleAnchoredAt:anchor
809                                 withMode:mode
810                          withServiceType:manage_accounts_params.service_type];
814 BrowserWindowCocoa::GetRenderViewHeightInsetWithDetachedBookmarkBar() {
815   if (browser_->bookmark_bar_state() != BookmarkBar::DETACHED)
816     return 0;
817   return 40;
820 void BrowserWindowCocoa::ExecuteExtensionCommand(
821     const extensions::Extension* extension,
822     const extensions::Command& command) {
823   [cocoa_controller() executeExtensionCommand:extension->id() command:command];
826 ExclusiveAccessContext* BrowserWindowCocoa::GetExclusiveAccessContext() {
827   return this;
830 Profile* BrowserWindowCocoa::GetProfile() {
831   return browser_->profile();
834 WebContents* BrowserWindowCocoa::GetActiveWebContents() {
835   return browser_->tab_strip_model()->GetActiveWebContents();
838 void BrowserWindowCocoa::UnhideDownloadShelf() {
839   GetDownloadShelf()->Unhide();
842 void BrowserWindowCocoa::HideDownloadShelf() {
843   GetDownloadShelf()->Hide();
844   StatusBubble* statusBubble = GetStatusBubble();
845   if (statusBubble)
846     statusBubble->Hide();