blob: a0f805634ff17f8e5377f83663aa814e604388bf [file] [log] [blame]
[email protected]3a80ea332012-01-09 19:53:291// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]7d791652010-12-01 16:34:492// 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
[email protected]a932d9e2011-09-29 01:14:347#include "base/bind.h"
[email protected]7d791652010-12-01 16:34:498#include "base/command_line.h"
9#include "base/logging.h"
[email protected]d82a3c9f2012-02-22 04:46:0010#include "base/mac/mac_util.h"
[email protected]3cc55ad2013-07-17 22:17:4111#include "base/message_loop/message_loop.h"
[email protected]3853a4c2013-02-11 17:15:5712#include "base/prefs/pref_service.h"
[email protected]3268d7b72013-03-28 17:41:4313#include "base/strings/sys_string_conversions.h"
[email protected]7d791652010-12-01 16:34:4914#include "chrome/app/chrome_command_ids.h"
[email protected]dcc8fbc2013-07-12 00:54:0915#include "chrome/browser/chrome_notification_types.h"
[email protected]7d791652010-12-01 16:34:4916#include "chrome/browser/download/download_shelf.h"
[email protected]78ce3022012-09-24 01:48:4817#include "chrome/browser/extensions/tab_helper.h"
[email protected]ee6a5272013-07-15 21:14:0118#include "chrome/browser/fullscreen.h"
[email protected]f5d230b32012-12-11 02:04:1119#include "chrome/browser/password_manager/password_manager.h"
[email protected]8ecad5e2010-12-02 21:18:3320#include "chrome/browser/profiles/profile.h"
[email protected]25ebfd362013-01-16 05:41:5521#include "chrome/browser/shell_integration.h"
[email protected]03020ff2012-11-29 12:08:1722#include "chrome/browser/ui/bookmarks/bookmark_utils.h"
[email protected]7d791652010-12-01 16:34:4923#include "chrome/browser/ui/browser.h"
[email protected]5d98294912012-06-27 22:57:4024#include "chrome/browser/ui/browser_command_controller.h"
[email protected]3f32b9b2012-07-09 16:59:2825#include "chrome/browser/ui/browser_commands.h"
[email protected]7d791652010-12-01 16:34:4926#include "chrome/browser/ui/browser_list.h"
[email protected]1f0b50b2012-06-22 20:37:1627#include "chrome/browser/ui/browser_window_state.h"
[email protected]7d2d08152011-10-25 22:58:4728#import "chrome/browser/ui/cocoa/browser/avatar_button_controller.h"
[email protected]2f733a02011-10-06 15:17:3429#import "chrome/browser/ui/cocoa/browser/avatar_menu_bubble_controller.h"
[email protected]464f0012011-07-07 02:12:5130#import "chrome/browser/ui/cocoa/browser/edit_search_engine_cocoa_controller.h"
[email protected]f5d230b32012-12-11 02:04:1131#import "chrome/browser/ui/cocoa/browser/password_generation_bubble_controller.h"
[email protected]7d791652010-12-01 16:34:4932#import "chrome/browser/ui/cocoa/browser_window_controller.h"
[email protected]3a1381d2011-08-26 18:12:1333#import "chrome/browser/ui/cocoa/browser_window_utils.h"
[email protected]7d791652010-12-01 16:34:4934#import "chrome/browser/ui/cocoa/chrome_event_processing_window.h"
[email protected]7d791652010-12-01 16:34:4935#import "chrome/browser/ui/cocoa/download/download_shelf_controller.h"
[email protected]632983f2011-08-08 22:51:2436#include "chrome/browser/ui/cocoa/find_bar/find_bar_bridge.h"
[email protected]51152d6d2011-11-07 01:55:1237#import "chrome/browser/ui/cocoa/info_bubble_view.h"
[email protected]7d791652010-12-01 16:34:4938#import "chrome/browser/ui/cocoa/location_bar/location_bar_view_mac.h"
[email protected]a7d83ca2011-03-06 14:41:0739#import "chrome/browser/ui/cocoa/nsmenuitem_additions.h"
[email protected]7d791652010-12-01 16:34:4940#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"
[email protected]8450c4f2011-01-19 22:16:2243#import "chrome/browser/ui/cocoa/toolbar/toolbar_controller.h"
[email protected]684dace42012-07-01 14:30:4144#import "chrome/browser/ui/cocoa/web_dialog_window_controller.h"
[email protected]5436c8fd2012-07-02 11:30:4645#import "chrome/browser/ui/cocoa/website_settings_bubble_controller.h"
[email protected]e2395da2013-01-23 22:05:3546#include "chrome/browser/ui/search/search_model.h"
[email protected]617ee962013-01-29 20:49:1247#include "chrome/browser/ui/tabs/tab_strip_model.h"
[email protected]25ebfd362013-01-16 05:41:5548#include "chrome/browser/ui/web_applications/web_app_ui.h"
49#include "chrome/browser/web_applications/web_app.h"
[email protected]52a1cc32013-07-18 19:02:4150#include "chrome/common/chrome_switches.h"
[email protected]7d791652010-12-01 16:34:4951#include "chrome/common/pref_names.h"
[email protected]e620d362013-09-09 08:01:5352#include "components/autofill/core/common/password_form.h"
[email protected]8bc38d22011-10-14 20:39:2053#include "content/public/browser/native_web_keyboard_event.h"
[email protected]6c2381d2011-10-19 02:52:5354#include "content/public/browser/notification_details.h"
[email protected]684dace42012-07-01 14:30:4155#include "content/public/browser/notification_source.h"
[email protected]e8558cf22012-01-10 03:10:5156#include "content/public/browser/web_contents.h"
[email protected]f3615f02013-02-26 06:09:0657#include "content/public/browser/web_contents_view.h"
[email protected]7d791652010-12-01 16:34:4958#include "grit/chromium_strings.h"
59#include "grit/generated_resources.h"
[email protected]c051a1b2011-01-21 23:30:1760#include "ui/base/l10n/l10n_util_mac.h"
[email protected]08397d52011-02-05 01:53:3861#include "ui/gfx/rect.h"
[email protected]7d791652010-12-01 16:34:4962
[email protected]fe54b4a2012-03-28 16:11:0463#if defined(ENABLE_ONE_CLICK_SIGNIN)
64#import "chrome/browser/ui/cocoa/one_click_signin_bubble_controller.h"
[email protected]8aa690c2013-02-06 22:33:1265#import "chrome/browser/ui/cocoa/one_click_signin_dialog_controller.h"
[email protected]fe54b4a2012-03-28 16:11:0466#endif
67
[email protected]b87ee522012-05-18 15:16:5468using content::NativeWebKeyboardEvent;
[email protected]d583e3f22011-12-27 21:38:1769using content::SSLStatus;
[email protected]2a6bc3e2011-12-28 23:51:3370using content::WebContents;
[email protected]d583e3f22011-12-27 21:38:1771
[email protected]400eaf82011-08-22 15:47:3972// 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
76enum {
77 NSWindowAnimationBehaviorDefault = 0,
78 NSWindowAnimationBehaviorNone = 2,
79 NSWindowAnimationBehaviorDocumentWindow = 3,
80 NSWindowAnimationBehaviorUtilityWindow = 4,
81 NSWindowAnimationBehaviorAlertPanel = 5
82};
83typedef 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
[email protected]f5d230b32012-12-11 02:04:1192namespace {
93
94NSPoint GetPointForBubble(content::WebContents* web_contents,
95 int x_offset,
96 int y_offset) {
[email protected]f3615f02013-02-26 06:09:0697 NSView* view = web_contents->GetView()->GetNativeView();
[email protected]f5d230b32012-12-11 02:04:1198 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
[email protected]b5ff7ab2013-03-01 07:48:53108void CreateShortcuts(const ShellIntegration::ShortcutInfo& shortcut_info) {
109 // creation_locations will be ignored by CreatePlatformShortcuts on Mac.
110 ShellIntegration::ShortcutLocations creation_locations;
[email protected]cf610e62013-07-03 04:42:17111 web_app::CreateShortcuts(shortcut_info, creation_locations,
[email protected]a705c7ee72013-07-26 08:01:54112 web_app::SHORTCUT_CREATION_BY_USER);
[email protected]b5ff7ab2013-03-01 07:48:53113}
114
[email protected]f5d230b32012-12-11 02:04:11115} // namespace
116
[email protected]7d791652010-12-01 16:34:49117BrowserWindowCocoa::BrowserWindowCocoa(Browser* browser,
[email protected]400eaf82011-08-22 15:47:39118 BrowserWindowController* controller)
[email protected]7d791652010-12-01 16:34:49119 : browser_(browser),
120 controller_(controller),
[email protected]6a9b53a22012-10-09 02:43:34121 initial_show_state_(ui::SHOW_STATE_DEFAULT),
[email protected]ad996342012-01-14 00:29:59122 attention_request_id_(0) {
[email protected]cfecf9432011-09-27 17:10:08123
[email protected]6a9b53a22012-10-09 02:43:34124 gfx::Rect bounds;
125 chrome::GetSavedWindowBoundsAndShowState(browser_,
126 &bounds,
127 &initial_show_state_);
[email protected]e2395da2013-01-23 22:05:35128
129 browser_->search_model()->AddObserver(this);
[email protected]7d791652010-12-01 16:34:49130}
131
132BrowserWindowCocoa::~BrowserWindowCocoa() {
[email protected]e2395da2013-01-23 22:05:35133 browser_->search_model()->RemoveObserver(this);
[email protected]7d791652010-12-01 16:34:49134}
135
136void BrowserWindowCocoa::Show() {
137 // The Browser associated with this browser window must become the active
138 // browser at the time |Show()| is called. This is the natural behaviour under
139 // Windows, but |-makeKeyAndOrderFront:| won't send |-windowDidBecomeMain:|
140 // until we return to the runloop. Therefore any calls to
[email protected]4d900252012-11-20 20:37:11141 // |chrome::FindLastActiveWithHostDesktopType| will return the previous
142 // browser instead if we don't explicitly set it here.
[email protected]7d791652010-12-01 16:34:49143 BrowserList::SetLastActive(browser_);
144
[email protected]8bc061f2011-08-31 22:46:23145 bool is_session_restore = browser_->is_session_restore();
[email protected]b5cc93c2011-09-02 02:33:42146 NSWindowAnimationBehavior saved_animation_behavior =
147 NSWindowAnimationBehaviorDefault;
[email protected]8bc061f2011-08-31 22:46:23148 bool did_save_animation_behavior = false;
149 // Turn off swishing when restoring windows.
150 if (is_session_restore &&
151 [window() respondsToSelector:@selector(animationBehavior)] &&
152 [window() respondsToSelector:@selector(setAnimationBehavior:)]) {
153 did_save_animation_behavior = true;
154 saved_animation_behavior = [window() animationBehavior];
155 [window() setAnimationBehavior:NSWindowAnimationBehaviorNone];
156 }
[email protected]400eaf82011-08-22 15:47:39157
[email protected]8bc061f2011-08-31 22:46:23158 [window() makeKeyAndOrderFront:controller_];
[email protected]400eaf82011-08-22 15:47:39159
[email protected]8bc061f2011-08-31 22:46:23160 // When creating windows from nibs it is necessary to |makeKeyAndOrderFront:|
161 // prior to |orderOut:| then |miniaturize:| when restoring windows in the
162 // minimized state.
[email protected]cfecf9432011-09-27 17:10:08163 if (initial_show_state_ == ui::SHOW_STATE_MINIMIZED) {
[email protected]400eaf82011-08-22 15:47:39164 [window() orderOut:controller_];
165 [window() miniaturize:controller_];
[email protected]85b0ac62012-02-09 01:57:43166 } else if (initial_show_state_ == ui::SHOW_STATE_FULLSCREEN) {
[email protected]3f32b9b2012-07-09 16:59:28167 chrome::ToggleFullscreenMode(browser_);
[email protected]400eaf82011-08-22 15:47:39168 }
[email protected]cfecf9432011-09-27 17:10:08169 initial_show_state_ = ui::SHOW_STATE_DEFAULT;
[email protected]8bc061f2011-08-31 22:46:23170
171 // Restore window animation behavior.
172 if (did_save_animation_behavior)
173 [window() setAnimationBehavior:saved_animation_behavior];
[email protected]2f516c792011-09-19 22:22:09174
175 browser_->OnWindowDidShow();
[email protected]7d791652010-12-01 16:34:49176}
177
[email protected]d4db6c702011-03-28 21:49:14178void BrowserWindowCocoa::ShowInactive() {
[email protected]400eaf82011-08-22 15:47:39179 [window() orderFront:controller_];
[email protected]d4db6c702011-03-28 21:49:14180}
181
[email protected]7d412f72012-10-25 04:59:15182void BrowserWindowCocoa::Hide() {
183 // Not implemented.
184}
185
[email protected]7d791652010-12-01 16:34:49186void BrowserWindowCocoa::SetBounds(const gfx::Rect& bounds) {
[email protected]ccb5895f2011-06-09 21:16:14187 gfx::Rect real_bounds = [controller_ enforceMinWindowSize:bounds];
188
[email protected]55c87fa2011-10-15 07:28:28189 ExitFullscreen();
[email protected]ccb5895f2011-06-09 21:16:14190 NSRect cocoa_bounds = NSMakeRect(real_bounds.x(), 0,
191 real_bounds.width(),
192 real_bounds.height());
[email protected]7d791652010-12-01 16:34:49193 // Flip coordinates based on the primary screen.
194 NSScreen* screen = [[NSScreen screens] objectAtIndex:0];
195 cocoa_bounds.origin.y =
[email protected]03e0f5f1e2012-06-07 21:35:39196 NSHeight([screen frame]) - real_bounds.height() - real_bounds.y();
[email protected]7d791652010-12-01 16:34:49197
198 [window() setFrame:cocoa_bounds display:YES];
199}
200
201// Callers assume that this doesn't immediately delete the Browser object.
202// The controller implementing the window delegate methods called from
203// |-performClose:| must take precautions to ensure that.
204void BrowserWindowCocoa::Close() {
205 // If there is an overlay window, we contain a tab being dragged between
206 // windows. Don't hide the window as it makes the UI extra confused. We can
207 // still close the window, as that will happen when the drag completes.
[email protected]60f94292012-03-12 22:24:27208 if ([controller_ overlayWindow]) {
[email protected]7d791652010-12-01 16:34:49209 [controller_ deferPerformClose];
[email protected]60f94292012-03-12 22:24:27210 } else {
[email protected]5ea51972012-10-15 16:45:47211 // Using |-performClose:| can prevent the window from actually closing if
212 // a JavaScript beforeunload handler opens an alert during shutdown, as
213 // documented at <http://crbug.com/118424>. Re-implement
214 // -[NSWindow performClose:] as closely as possible to how Apple documents
215 // it.
[email protected]d1136ca2012-10-18 23:35:55216 //
217 // Before calling |-close|, hide the window immediately. |-performClose:|
218 // would do something similar, and this ensures that the window is removed
219 // from AppKit's display list. Not doing so can lead to crashes like
220 // <http://crbug.com/156101>.
[email protected]5ea51972012-10-15 16:45:47221 id<NSWindowDelegate> delegate = [window() delegate];
222 SEL window_should_close = @selector(windowShouldClose:);
223 if ([delegate respondsToSelector:window_should_close]) {
[email protected]d1136ca2012-10-18 23:35:55224 if ([delegate windowShouldClose:window()]) {
225 [window() orderOut:nil];
[email protected]5ea51972012-10-15 16:45:47226 [window() close];
[email protected]d1136ca2012-10-18 23:35:55227 }
[email protected]5ea51972012-10-15 16:45:47228 } else if ([window() respondsToSelector:window_should_close]) {
[email protected]d1136ca2012-10-18 23:35:55229 if ([window() performSelector:window_should_close withObject:window()]) {
230 [window() orderOut:nil];
[email protected]5ea51972012-10-15 16:45:47231 [window() close];
[email protected]d1136ca2012-10-18 23:35:55232 }
[email protected]5ea51972012-10-15 16:45:47233 } else {
[email protected]d1136ca2012-10-18 23:35:55234 [window() orderOut:nil];
[email protected]5ea51972012-10-15 16:45:47235 [window() close];
236 }
[email protected]60f94292012-03-12 22:24:27237 }
[email protected]7d791652010-12-01 16:34:49238}
239
240void BrowserWindowCocoa::Activate() {
241 [controller_ activate];
242}
243
244void BrowserWindowCocoa::Deactivate() {
245 // TODO(jcivelli): http://crbug.com/51364 Implement me.
246 NOTIMPLEMENTED();
247}
248
[email protected]ad996342012-01-14 00:29:59249void BrowserWindowCocoa::FlashFrame(bool flash) {
250 if (flash) {
251 attention_request_id_ = [NSApp requestUserAttention:NSInformationalRequest];
252 } else {
253 [NSApp cancelUserAttentionRequest:attention_request_id_];
254 attention_request_id_ = 0;
255 }
[email protected]7d791652010-12-01 16:34:49256}
257
[email protected]d101b0c2012-03-16 00:30:57258bool BrowserWindowCocoa::IsAlwaysOnTop() const {
259 return false;
260}
261
[email protected]46d46052013-10-11 11:27:22262void BrowserWindowCocoa::SetAlwaysOnTop(bool always_on_top) {
263 // Not implemented for browser windows.
264 NOTIMPLEMENTED();
265}
266
[email protected]7d791652010-12-01 16:34:49267bool BrowserWindowCocoa::IsActive() const {
268 return [window() isKeyWindow];
269}
270
[email protected]90556dd2012-06-07 20:26:18271gfx::NativeWindow BrowserWindowCocoa::GetNativeWindow() {
[email protected]7d791652010-12-01 16:34:49272 return window();
273}
274
275BrowserWindowTesting* BrowserWindowCocoa::GetBrowserWindowTesting() {
276 return NULL;
277}
278
279StatusBubble* BrowserWindowCocoa::GetStatusBubble() {
280 return [controller_ statusBubble];
281}
282
[email protected]7d791652010-12-01 16:34:49283void BrowserWindowCocoa::UpdateTitleBar() {
284 NSString* newTitle =
285 base::SysUTF16ToNSString(browser_->GetWindowTitleForCurrentTab());
286
[email protected]d78e615e2011-09-06 21:46:03287 pending_window_title_.reset(
288 [BrowserWindowUtils scheduleReplaceOldTitle:pending_window_title_.get()
289 withNewTitle:newTitle
290 forWindow:window()]);
[email protected]7d791652010-12-01 16:34:49291}
292
[email protected]09b29342011-06-24 19:18:48293void BrowserWindowCocoa::BookmarkBarStateChanged(
294 BookmarkBar::AnimateChangeType change_type) {
[email protected]1eeccb92012-12-06 20:31:24295 [[controller_ bookmarkBarController]
296 updateState:browser_->bookmark_bar_state()
297 changeType:change_type];
[email protected]7d791652010-12-01 16:34:49298}
299
300void BrowserWindowCocoa::UpdateDevTools() {
301 [controller_ updateDevToolsForContents:
[email protected]617ee962013-01-29 20:49:12302 browser_->tab_strip_model()->GetActiveWebContents()];
[email protected]7d791652010-12-01 16:34:49303}
304
305void BrowserWindowCocoa::UpdateLoadingAnimations(bool should_animate) {
306 // Do nothing on Mac.
307}
308
309void BrowserWindowCocoa::SetStarredState(bool is_starred) {
310 [controller_ setStarredState:is_starred ? YES : NO];
311}
312
[email protected]08726d5e2013-09-24 21:52:55313void BrowserWindowCocoa::OnActiveTabChanged(content::WebContents* old_contents,
314 content::WebContents* new_contents,
315 int index,
316 int reason) {
317 // TODO(pkasting): Perhaps the code in
318 // TabStripController::activateTabWithContents should move here? Or this
319 // should call that (instead of TabStripModelObserverBridge doing so)? It's
320 // not obvious to me why Mac doesn't handle tab changes in BrowserWindow the
321 // way views and GTK do.
322}
323
[email protected]5423c372012-08-22 05:50:16324void BrowserWindowCocoa::ZoomChangedForActiveTab(bool can_show_bubble) {
325 [controller_ zoomChangedForActiveTab:can_show_bubble ? YES : NO];
[email protected]6f80e932012-06-04 19:00:07326}
327
[email protected]7d791652010-12-01 16:34:49328gfx::Rect BrowserWindowCocoa::GetRestoredBounds() const {
329 // Flip coordinates based on the primary screen.
330 NSScreen* screen = [[NSScreen screens] objectAtIndex:0];
331 NSRect frame = [controller_ regularWindowFrame];
[email protected]03e0f5f1e2012-06-07 21:35:39332 gfx::Rect bounds(frame.origin.x, 0, NSWidth(frame), NSHeight(frame));
333 bounds.set_y(NSHeight([screen frame]) - NSMaxY(frame));
[email protected]7d791652010-12-01 16:34:49334 return bounds;
335}
336
[email protected]68eeede2013-05-09 06:10:57337ui::WindowShowState BrowserWindowCocoa::GetRestoredState() const {
338 if (IsMaximized())
339 return ui::SHOW_STATE_MAXIMIZED;
340 if (IsMinimized())
341 return ui::SHOW_STATE_MINIMIZED;
342 return ui::SHOW_STATE_NORMAL;
343}
344
[email protected]d479b8e22011-02-09 05:19:49345gfx::Rect BrowserWindowCocoa::GetBounds() const {
346 return GetRestoredBounds();
347}
348
[email protected]7d791652010-12-01 16:34:49349bool BrowserWindowCocoa::IsMaximized() const {
350 return [window() isZoomed];
351}
352
[email protected]400eaf82011-08-22 15:47:39353bool BrowserWindowCocoa::IsMinimized() const {
354 return [window() isMiniaturized];
355}
356
[email protected]541e3ee2011-11-22 01:31:10357void BrowserWindowCocoa::Maximize() {
358 // Zoom toggles so only call if not already maximized.
359 if (!IsMaximized())
360 [window() zoom:controller_];
361}
362
363void BrowserWindowCocoa::Minimize() {
364 [window() miniaturize:controller_];
365}
366
367void BrowserWindowCocoa::Restore() {
368 if (IsMaximized())
369 [window() zoom:controller_]; // Toggles zoom mode.
370 else if (IsMinimized())
371 [window() deminiaturize:controller_];
372}
373
[email protected]8d944b32011-10-17 06:11:53374void BrowserWindowCocoa::EnterFullscreen(
[email protected]22d74a6b2011-10-17 20:30:31375 const GURL& url, FullscreenExitBubbleType bubble_type) {
[email protected]52a1cc32013-07-18 19:02:41376 // When simplified fullscreen is enabled, always enter normal fullscreen.
377 const CommandLine* command_line = CommandLine::ForCurrentProcess();
378 if (command_line->HasSwitch(switches::kEnableSimplifiedFullscreen)) {
[email protected]750501522013-07-20 01:44:29379 if (url.is_empty())
380 [controller_ enterFullscreen];
381 else
382 [controller_ enterFullscreenForURL:url bubbleType:bubble_type];
[email protected]52a1cc32013-07-18 19:02:41383 return;
384 }
385
[email protected]34337d32013-01-29 20:29:01386 [controller_ enterPresentationModeForURL:url
387 bubbleType:bubble_type];
[email protected]55c87fa2011-10-15 07:28:28388}
389
390void BrowserWindowCocoa::ExitFullscreen() {
[email protected]22d74a6b2011-10-17 20:30:31391 [controller_ exitFullscreen];
[email protected]8d944b32011-10-17 06:11:53392}
393
394void BrowserWindowCocoa::UpdateFullscreenExitBubbleContent(
395 const GURL& url,
396 FullscreenExitBubbleType bubble_type) {
[email protected]22d74a6b2011-10-17 20:30:31397 [controller_ updateFullscreenExitBubbleURL:url bubbleType:bubble_type];
[email protected]7d791652010-12-01 16:34:49398}
399
[email protected]6a414ff2013-02-27 08:22:54400bool BrowserWindowCocoa::ShouldHideUIForFullscreen() const {
401 // On Mac, fullscreen mode has most normal things (in a slide-down panel).
402 return false;
403}
404
[email protected]7d791652010-12-01 16:34:49405bool BrowserWindowCocoa::IsFullscreen() const {
[email protected]34337d32013-01-29 20:29:01406 if ([controller_ inPresentationMode])
407 CHECK([controller_ isFullscreen]); // Presentation mode must be fullscreen.
[email protected]8d944b32011-10-17 06:11:53408 return [controller_ isFullscreen];
[email protected]7d791652010-12-01 16:34:49409}
410
411bool BrowserWindowCocoa::IsFullscreenBubbleVisible() const {
412 return false;
413}
414
415void BrowserWindowCocoa::ConfirmAddSearchProvider(
[email protected]3613347d2012-04-27 20:27:37416 TemplateURL* template_url,
[email protected]7d791652010-12-01 16:34:49417 Profile* profile) {
[email protected]464f0012011-07-07 02:12:51418 // The controller will release itself when the window closes.
419 EditSearchEngineCocoaController* editor =
420 [[EditSearchEngineCocoaController alloc] initWithProfile:profile
421 delegate:NULL
422 templateURL:template_url];
423 [NSApp beginSheet:[editor window]
424 modalForWindow:window()
425 modalDelegate:controller_
426 didEndSelector:@selector(sheetDidEnd:returnCode:context:)
427 contextInfo:NULL];
[email protected]7d791652010-12-01 16:34:49428}
429
430LocationBar* BrowserWindowCocoa::GetLocationBar() const {
431 return [controller_ locationBarBridge];
432}
433
434void BrowserWindowCocoa::SetFocusToLocationBar(bool select_all) {
435 [controller_ focusLocationBar:select_all ? YES : NO];
436}
437
438void BrowserWindowCocoa::UpdateReloadStopState(bool is_loading, bool force) {
439 [controller_ setIsLoading:is_loading force:force];
440}
441
[email protected]2e7fe4312013-08-21 17:19:48442void BrowserWindowCocoa::UpdateToolbar(content::WebContents* contents) {
443 [controller_ updateToolbarWithContents:contents];
[email protected]7d791652010-12-01 16:34:49444}
445
446void BrowserWindowCocoa::FocusToolbar() {
447 // Not needed on the Mac.
448}
449
450void BrowserWindowCocoa::FocusAppMenu() {
451 // Chrome uses the standard Mac OS X menu bar, so this isn't needed.
452}
453
454void BrowserWindowCocoa::RotatePaneFocus(bool forwards) {
455 // Not needed on the Mac.
456}
457
458void BrowserWindowCocoa::FocusBookmarksToolbar() {
459 // Not needed on the Mac.
460}
461
[email protected]822ca8c62013-04-19 00:49:15462void BrowserWindowCocoa::FocusInfobars() {
463 // Not needed on the Mac.
464}
465
[email protected]7d791652010-12-01 16:34:49466bool BrowserWindowCocoa::IsBookmarkBarVisible() const {
[email protected]a007e732011-08-05 13:32:19467 return browser_->profile()->GetPrefs()->GetBoolean(prefs::kShowBookmarkBar);
[email protected]7d791652010-12-01 16:34:49468}
469
470bool BrowserWindowCocoa::IsBookmarkBarAnimating() const {
471 return [controller_ isBookmarkBarAnimating];
472}
473
[email protected]95bf8a5b2010-12-22 16:04:07474bool BrowserWindowCocoa::IsTabStripEditable() const {
475 return ![controller_ isDragSessionActive];
476}
477
[email protected]7d791652010-12-01 16:34:49478bool BrowserWindowCocoa::IsToolbarVisible() const {
479 return browser_->SupportsWindowFeature(Browser::FEATURE_TOOLBAR) ||
480 browser_->SupportsWindowFeature(Browser::FEATURE_LOCATIONBAR);
481}
482
[email protected]b7a756d42012-01-23 18:08:17483gfx::Rect BrowserWindowCocoa::GetRootWindowResizerRect() const {
[email protected]9f8727092012-02-08 01:38:18484 if (IsDownloadShelfVisible())
485 return gfx::Rect();
[email protected]b7a756d42012-01-23 18:08:17486 NSRect tabRect = [controller_ selectedTabGrowBoxRect];
487 return gfx::Rect(NSRectToCGRect(tabRect));
488}
489
[email protected]7d791652010-12-01 16:34:49490// This is called from Browser, which in turn is called directly from
491// a menu option. All we do here is set a preference. The act of
492// setting the preference sends notifications to all windows who then
493// know what to do.
494void BrowserWindowCocoa::ToggleBookmarkBar() {
[email protected]03020ff2012-11-29 12:08:17495 chrome::ToggleBookmarkBarWhenVisible(browser_->profile());
[email protected]7d791652010-12-01 16:34:49496}
497
498void BrowserWindowCocoa::AddFindBar(
499 FindBarCocoaController* find_bar_cocoa_controller) {
[email protected]632983f2011-08-08 22:51:24500 [controller_ addFindBar:find_bar_cocoa_controller];
[email protected]7d791652010-12-01 16:34:49501}
502
[email protected]7d791652010-12-01 16:34:49503void BrowserWindowCocoa::ShowUpdateChromeDialog() {
[email protected]678dae82011-02-11 20:03:08504 restart_browser::RequestRestart(window());
[email protected]7d791652010-12-01 16:34:49505}
506
[email protected]7d791652010-12-01 16:34:49507void BrowserWindowCocoa::ShowBookmarkBubble(const GURL& url,
508 bool already_bookmarked) {
509 [controller_ showBookmarkBubbleForURL:url
510 alreadyBookmarked:(already_bookmarked ? YES : NO)];
511}
512
[email protected]235a0562012-03-26 22:22:35513#if defined(ENABLE_ONE_CLICK_SIGNIN)
[email protected]fe54b4a2012-03-28 16:11:04514void BrowserWindowCocoa::ShowOneClickSigninBubble(
[email protected]265c9272013-01-25 19:18:45515 OneClickSigninBubbleType type,
[email protected]0cf5d282013-04-12 18:33:12516 const string16& email,
[email protected]62e86372013-05-01 15:59:25517 const string16& error_message,
[email protected]265c9272013-01-25 19:18:45518 const StartSyncCallback& start_sync_callback) {
[email protected]02ada8bf2013-05-02 01:34:22519 WebContents* web_contents =
520 browser_->tab_strip_model()->GetActiveWebContents();
[email protected]8aa690c2013-02-06 22:33:12521 if (type == ONE_CLICK_SIGNIN_BUBBLE_TYPE_BUBBLE) {
[email protected]a8522032013-06-24 22:51:46522 base::scoped_nsobject<OneClickSigninBubbleController> bubble_controller([
523 [OneClickSigninBubbleController alloc]
524 initWithBrowserWindowController:cocoa_controller()
525 webContents:web_contents
526 errorMessage:base::SysUTF16ToNSString(error_message)
527 callback:start_sync_callback]);
[email protected]8aa690c2013-02-06 22:33:12528 [bubble_controller showWindow:nil];
529 } else {
[email protected]8aa690c2013-02-06 22:33:12530 // Deletes itself when the dialog closes.
[email protected]c28050a2013-07-10 04:56:40531 new OneClickSigninDialogController(
532 web_contents, start_sync_callback, email);
[email protected]8aa690c2013-02-06 22:33:12533 }
[email protected]235a0562012-03-26 22:22:35534}
535#endif
536
[email protected]7d791652010-12-01 16:34:49537bool BrowserWindowCocoa::IsDownloadShelfVisible() const {
538 return [controller_ isDownloadShelfVisible] != NO;
539}
540
541DownloadShelf* BrowserWindowCocoa::GetDownloadShelf() {
542 DownloadShelfController* shelfController = [controller_ downloadShelf];
543 return [shelfController bridge];
544}
545
[email protected]7d791652010-12-01 16:34:49546// We allow closing the window here since the real quit decision on Mac is made
547// in [AppController quit:].
[email protected]edfca702013-08-16 08:58:14548void BrowserWindowCocoa::ConfirmBrowserCloseWithPendingDownloads(
549 int download_count,
550 Browser::DownloadClosePreventionType dialog_type,
551 bool app_modal,
552 const base::Callback<void(bool)>& callback) {
553 callback.Run(true);
[email protected]7d791652010-12-01 16:34:49554}
555
[email protected]7d791652010-12-01 16:34:49556void BrowserWindowCocoa::UserChangedTheme() {
557 [controller_ userChangedTheme];
558}
559
560int BrowserWindowCocoa::GetExtraRenderViewHeight() const {
561 // Currently this is only used on linux.
562 return 0;
563}
564
[email protected]2a6bc3e2011-12-28 23:51:33565void BrowserWindowCocoa::WebContentsFocused(WebContents* contents) {
[email protected]7d791652010-12-01 16:34:49566 NOTIMPLEMENTED();
567}
568
[email protected]b8e681e82012-02-20 10:18:47569void BrowserWindowCocoa::ShowWebsiteSettings(
570 Profile* profile,
[email protected]36ad4aa82012-11-21 19:20:48571 content::WebContents* web_contents,
[email protected]b8e681e82012-02-20 10:18:47572 const GURL& url,
[email protected]9fb47a82013-07-05 11:34:02573 const content::SSLStatus& ssl) {
[email protected]a4ed9ed2013-07-11 23:40:13574 WebsiteSettingsUIBridge::Show(window(), profile, web_contents, url, ssl);
[email protected]b8e681e82012-02-20 10:18:47575}
576
[email protected]7d791652010-12-01 16:34:49577void BrowserWindowCocoa::ShowAppMenu() {
578 // No-op. Mac doesn't support showing the menus via alt keys.
579}
580
581bool BrowserWindowCocoa::PreHandleKeyboardEvent(
582 const NativeWebKeyboardEvent& event, bool* is_keyboard_shortcut) {
[email protected]3a1381d2011-08-26 18:12:13583 if (![BrowserWindowUtils shouldHandleKeyboardEvent:event])
[email protected]7d791652010-12-01 16:34:49584 return false;
585
[email protected]d2885ba2012-08-17 10:23:12586 if (event.type == WebKit::WebInputEvent::RawKeyDown &&
587 [controller_ handledByExtensionCommand:event.os_event])
588 return true;
589
[email protected]3a1381d2011-08-26 18:12:13590 int id = [BrowserWindowUtils getCommandId:event];
[email protected]7d791652010-12-01 16:34:49591 if (id == -1)
592 return false;
593
[email protected]5d98294912012-06-27 22:57:40594 if (browser_->command_controller()->IsReservedCommandOrKey(id, event)) {
[email protected]3a1381d2011-08-26 18:12:13595 return [BrowserWindowUtils handleKeyboardEvent:event.os_event
596 inWindow:window()];
597 }
[email protected]7d791652010-12-01 16:34:49598
[email protected]3a1381d2011-08-26 18:12:13599 DCHECK(is_keyboard_shortcut);
[email protected]7d791652010-12-01 16:34:49600 *is_keyboard_shortcut = true;
[email protected]7d791652010-12-01 16:34:49601 return false;
602}
603
604void BrowserWindowCocoa::HandleKeyboardEvent(
605 const NativeWebKeyboardEvent& event) {
[email protected]3a1381d2011-08-26 18:12:13606 if ([BrowserWindowUtils shouldHandleKeyboardEvent:event])
607 [BrowserWindowUtils handleKeyboardEvent:event.os_event inWindow:window()];
[email protected]7d791652010-12-01 16:34:49608}
609
[email protected]7d791652010-12-01 16:34:49610void BrowserWindowCocoa::ShowCreateChromeAppShortcutsDialog(
[email protected]1c321ee2012-05-21 03:02:34611 Profile* profile, const extensions::Extension* app) {
[email protected]25ebfd362013-01-16 05:41:55612 // Normally we would show a dialog, but since we always create the app
613 // shortcut in /Applications there are no options for the user to choose.
[email protected]4fd2ab52013-02-05 23:20:50614 web_app::UpdateShortcutInfoAndIconForApp(*app, profile,
[email protected]b5ff7ab2013-03-01 07:48:53615 base::Bind(&CreateShortcuts));
[email protected]7d791652010-12-01 16:34:49616}
617
618void BrowserWindowCocoa::Cut() {
619 [NSApp sendAction:@selector(cut:) to:nil from:nil];
620}
621
622void BrowserWindowCocoa::Copy() {
623 [NSApp sendAction:@selector(copy:) to:nil from:nil];
624}
625
626void BrowserWindowCocoa::Paste() {
627 [NSApp sendAction:@selector(paste:) to:nil from:nil];
628}
629
[email protected]7d791652010-12-01 16:34:49630void BrowserWindowCocoa::OpenTabpose() {
631 [controller_ openTabpose];
632}
633
[email protected]34337d32013-01-29 20:29:01634void BrowserWindowCocoa::EnterFullscreenWithChrome() {
[email protected]52a1cc32013-07-18 19:02:41635 // This method cannot be called if simplified fullscreen is enabled.
636 const CommandLine* command_line = CommandLine::ForCurrentProcess();
637 DCHECK(!command_line->HasSwitch(switches::kEnableSimplifiedFullscreen));
638
[email protected]ee6a5272013-07-15 21:14:01639 CHECK(chrome::mac::SupportsSystemFullscreen());
[email protected]34337d32013-01-29 20:29:01640 if ([controller_ inPresentationMode])
641 [controller_ exitPresentationMode];
642 else
643 [controller_ enterFullscreen];
[email protected]8d944b32011-10-17 06:11:53644}
645
[email protected]34337d32013-01-29 20:29:01646bool BrowserWindowCocoa::IsFullscreenWithChrome() {
[email protected]52a1cc32013-07-18 19:02:41647 // The WithChrome mode does not exist when simplified fullscreen is enabled.
648 const CommandLine* command_line = CommandLine::ForCurrentProcess();
649 if (command_line->HasSwitch(switches::kEnableSimplifiedFullscreen))
650 return false;
[email protected]34337d32013-01-29 20:29:01651 return IsFullscreen() && ![controller_ inPresentationMode];
[email protected]d3766932011-08-04 22:18:23652}
653
[email protected]34337d32013-01-29 20:29:01654bool BrowserWindowCocoa::IsFullscreenWithoutChrome() {
[email protected]52a1cc32013-07-18 19:02:41655 // Presentation mode does not exist if simplified fullscreen is enabled. The
656 // WithoutChrome mode simply maps to whether or not the window is fullscreen.
657 const CommandLine* command_line = CommandLine::ForCurrentProcess();
658 if (command_line->HasSwitch(switches::kEnableSimplifiedFullscreen))
659 return IsFullscreen();
660
[email protected]34337d32013-01-29 20:29:01661 return IsFullscreen() && [controller_ inPresentationMode];
[email protected]d3766932011-08-04 22:18:23662}
663
[email protected]588300d2011-04-28 21:06:35664WindowOpenDisposition BrowserWindowCocoa::GetDispositionForPopupBounds(
665 const gfx::Rect& bounds) {
[email protected]d82a3c9f2012-02-22 04:46:00666 // In Lion fullscreen mode, convert popups into tabs.
[email protected]ee6a5272013-07-15 21:14:01667 if (chrome::mac::SupportsSystemFullscreen() && IsFullscreen())
[email protected]d82a3c9f2012-02-22 04:46:00668 return NEW_FOREGROUND_TAB;
[email protected]588300d2011-04-28 21:06:35669 return NEW_POPUP;
670}
671
[email protected]632983f2011-08-08 22:51:24672FindBar* BrowserWindowCocoa::CreateFindBar() {
673 // We could push the AddFindBar() call into the FindBarBridge
674 // constructor or the FindBarCocoaController init, but that makes
675 // unit testing difficult, since we would also require a
676 // BrowserWindow object.
[email protected]03d5af592013-03-21 12:30:25677 FindBarBridge* bridge = new FindBarBridge(browser_);
[email protected]632983f2011-08-08 22:51:24678 AddFindBar(bridge->find_bar_cocoa_controller());
679 return bridge;
680}
681
[email protected]e41d0082013-05-16 04:37:54682web_modal::WebContentsModalDialogHost*
[email protected]7519c522013-04-02 01:07:23683 BrowserWindowCocoa::GetWebContentsModalDialogHost() {
684 return NULL;
[email protected]6a151762012-10-03 22:33:19685}
686
[email protected]78ce3022012-09-24 01:48:48687extensions::ActiveTabPermissionGranter*
688 BrowserWindowCocoa::GetActiveTabPermissionGranter() {
[email protected]852934842012-12-10 16:50:13689 WebContents* web_contents =
690 browser_->tab_strip_model()->GetActiveWebContents();
691 if (!web_contents)
[email protected]78ce3022012-09-24 01:48:48692 return NULL;
693 extensions::TabHelper* tab_helper =
[email protected]852934842012-12-10 16:50:13694 extensions::TabHelper::FromWebContents(web_contents);
[email protected]78ce3022012-09-24 01:48:48695 return tab_helper ? tab_helper->active_tab_permission_granter() : NULL;
696}
697
[email protected]165fe422013-03-27 06:34:03698void BrowserWindowCocoa::ModelChanged(const SearchModel::State& old_state,
699 const SearchModel::State& new_state) {
[email protected]e2395da2013-01-23 22:05:35700}
701
[email protected]7d791652010-12-01 16:34:49702void BrowserWindowCocoa::DestroyBrowser() {
703 [controller_ destroyBrowser];
704
705 // at this point the controller is dead (autoreleased), so
706 // make sure we don't try to reference it any more.
707}
708
709NSWindow* BrowserWindowCocoa::window() const {
710 return [controller_ window];
711}
712
[email protected]0ec4898e2011-12-30 21:09:24713void BrowserWindowCocoa::ShowAvatarBubble(WebContents* web_contents,
[email protected]2f733a02011-10-06 15:17:34714 const gfx::Rect& rect) {
[email protected]f5d230b32012-12-11 02:04:11715 NSPoint point = GetPointForBubble(web_contents, rect.right(), rect.bottom());
[email protected]2f733a02011-10-06 15:17:34716
717 // |menu| will automatically release itself on close.
718 AvatarMenuBubbleController* menu =
719 [[AvatarMenuBubbleController alloc] initWithBrowser:browser_
720 anchoredAt:point];
[email protected]51152d6d2011-11-07 01:55:12721 [[menu bubble] setAlignment:info_bubble::kAlignEdgeToAnchorEdge];
[email protected]2f733a02011-10-06 15:17:34722 [menu showWindow:nil];
723}
[email protected]7d2d08152011-10-25 22:58:47724
725void BrowserWindowCocoa::ShowAvatarBubbleFromAvatarButton() {
[email protected]8d904e832013-06-17 19:19:14726 AvatarButtonController* controller = [controller_ avatarButtonController];
727 [controller showAvatarBubble:[controller buttonView]];
[email protected]7d2d08152011-10-25 22:58:47728}
[email protected]f5d230b32012-12-11 02:04:11729
730void BrowserWindowCocoa::ShowPasswordGenerationBubble(
731 const gfx::Rect& rect,
[email protected]e620d362013-09-09 08:01:53732 const autofill::PasswordForm& form,
[email protected]f5d230b32012-12-11 02:04:11733 autofill::PasswordGenerator* password_generator) {
[email protected]617ee962013-01-29 20:49:12734 WebContents* web_contents =
735 browser_->tab_strip_model()->GetActiveWebContents();
[email protected]f5d230b32012-12-11 02:04:11736 // We want to point to the middle of the rect instead of the right side.
737 NSPoint point = GetPointForBubble(web_contents,
738 rect.x() + rect.width()/2,
739 rect.bottom());
740
741 PasswordGenerationBubbleController* controller =
742 [[PasswordGenerationBubbleController alloc]
743 initWithWindow:browser_->window()->GetNativeWindow()
744 anchoredAt:point
745 renderViewHost:web_contents->GetRenderViewHost()
746 passwordManager:PasswordManager::FromWebContents(web_contents)
747 usingGenerator:password_generator
748 forForm:form];
749 [controller showWindow:nil];
750}
[email protected]dc0fd432013-08-27 15:29:21751
752int
753BrowserWindowCocoa::GetRenderViewHeightInsetWithDetachedBookmarkBar() {
754 if (browser_->bookmark_bar_state() != BookmarkBar::DETACHED)
755 return 0;
756 // TODO(sail): please make this work with cocoa, then enable
757 // BrowserTest.GetSizeForNewRenderView and
758 // WebContentsImplBrowserTest.GetSizeForNewRenderView.
759 // This function should return the extra height of the render view when
760 // detached bookmark bar is hidden.
761 // However, I (kuan) return 0 for now to retain the original behavior,
762 // because I encountered the following problem on cocoa:
763 // 1) When a navigation is requested,
764 // WebContentsImpl::CreateRenderViewForRenderManager creates the new
765 // RenderWidgetHostView at the size specified by
766 // WebContentsDelegate::GetSizeForNewRenderView implemented by Browser.
767 // 2) When the pending navigation entry is committed,
768 // WebContentsImpl::UpdateRenderViewSizeForRenderManager udpates the size
769 // of WebContentsView to the size in (1).
770 // 3) WebContentsImpl::DidNavigateMainFramePostCommit() is called, where
771 // the detached bookmark bar is hidden, resulting in relayout of tab
772 // contents area.
773 // On cocoa, (2) causes RenderWidgetHostView to resize (enlarge) further.
774 // e.g. if size in (1) is size A, and this function returns height H, height
775 // of RenderWidgetHostView after (2) becomes A.height() + H; it's supposed to
776 // stay at A.height().
777 // Then, in (3), WebContentsView and RenderWidgetHostView enlarge even
778 // further, both by another H, i.e. WebContentsView's height becomes
779 // A.height() + H and RenderWidgetHostView's height becomes A.height() + 2H.
780 // Strangely, the RenderWidgetHostView for the previous navigation entry also
781 // gets enlarged by H.
782 // I believe these "automatic" resizing are caused by setAutoresizingMask of
783 // of the cocoa view in WebContentsViewMac, which defeats the purpose of
784 // WebContentsDelegate::GetSizeForNewRenderView i.e. to prevent resizing of
785 // RenderWidgetHostView in (2) and (3).
786 return 0;
787}