blob: 4287c001157e61e8229bba4a18a6b49dcd4a8b16 [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]0610ab52013-12-04 03:22:5111#import "base/mac/sdk_forward_declarations.h"
[email protected]3cc55ad2013-07-17 22:17:4112#include "base/message_loop/message_loop.h"
[email protected]3853a4c2013-02-11 17:15:5713#include "base/prefs/pref_service.h"
[email protected]3268d7b72013-03-28 17:41:4314#include "base/strings/sys_string_conversions.h"
[email protected]7d791652010-12-01 16:34:4915#include "chrome/app/chrome_command_ids.h"
[email protected]dcc8fbc2013-07-12 00:54:0916#include "chrome/browser/chrome_notification_types.h"
[email protected]7d791652010-12-01 16:34:4917#include "chrome/browser/download/download_shelf.h"
[email protected]78ce3022012-09-24 01:48:4818#include "chrome/browser/extensions/tab_helper.h"
[email protected]ee6a5272013-07-15 21:14:0119#include "chrome/browser/fullscreen.h"
[email protected]f5d230b32012-12-11 02:04:1120#include "chrome/browser/password_manager/password_manager.h"
[email protected]8ecad5e2010-12-02 21:18:3321#include "chrome/browser/profiles/profile.h"
[email protected]25ebfd362013-01-16 05:41:5522#include "chrome/browser/shell_integration.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]320b3692014-01-29 21:32:3825#include "chrome/browser/ui/browser_commands_mac.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]25d0b8b72014-01-23 22:12:1228#import "chrome/browser/ui/cocoa/browser/avatar_base_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/web_applications/web_app.h"
[email protected]52a1cc32013-07-18 19:02:4149#include "chrome/common/chrome_switches.h"
[email protected]7d791652010-12-01 16:34:4950#include "chrome/common/pref_names.h"
[email protected]e620d362013-09-09 08:01:5351#include "components/autofill/core/common/password_form.h"
[email protected]8bc38d22011-10-14 20:39:2052#include "content/public/browser/native_web_keyboard_event.h"
[email protected]6c2381d2011-10-19 02:52:5353#include "content/public/browser/notification_details.h"
[email protected]684dace42012-07-01 14:30:4154#include "content/public/browser/notification_source.h"
[email protected]e8558cf22012-01-10 03:10:5155#include "content/public/browser/web_contents.h"
[email protected]f3615f02013-02-26 06:09:0656#include "content/public/browser/web_contents_view.h"
[email protected]7d791652010-12-01 16:34:4957#include "grit/chromium_strings.h"
58#include "grit/generated_resources.h"
[email protected]c051a1b2011-01-21 23:30:1759#include "ui/base/l10n/l10n_util_mac.h"
[email protected]08397d52011-02-05 01:53:3860#include "ui/gfx/rect.h"
[email protected]7d791652010-12-01 16:34:4961
[email protected]fe54b4a2012-03-28 16:11:0462#if defined(ENABLE_ONE_CLICK_SIGNIN)
63#import "chrome/browser/ui/cocoa/one_click_signin_bubble_controller.h"
[email protected]8aa690c2013-02-06 22:33:1264#import "chrome/browser/ui/cocoa/one_click_signin_dialog_controller.h"
[email protected]fe54b4a2012-03-28 16:11:0465#endif
66
[email protected]b87ee522012-05-18 15:16:5467using content::NativeWebKeyboardEvent;
[email protected]d583e3f22011-12-27 21:38:1768using content::SSLStatus;
[email protected]2a6bc3e2011-12-28 23:51:3369using content::WebContents;
[email protected]d583e3f22011-12-27 21:38:1770
[email protected]f5d230b32012-12-11 02:04:1171namespace {
72
73NSPoint GetPointForBubble(content::WebContents* web_contents,
74 int x_offset,
75 int y_offset) {
[email protected]f3615f02013-02-26 06:09:0676 NSView* view = web_contents->GetView()->GetNativeView();
[email protected]f5d230b32012-12-11 02:04:1177 NSRect bounds = [view bounds];
78 NSPoint point;
79 point.x = NSMinX(bounds) + x_offset;
80 // The view's origin is at the bottom but |rect|'s origin is at the top.
81 point.y = NSMaxY(bounds) - y_offset;
82 point = [view convertPoint:point toView:nil];
83 point = [[view window] convertBaseToScreen:point];
84 return point;
85}
86
[email protected]f5d230b32012-12-11 02:04:1187} // namespace
88
[email protected]7d791652010-12-01 16:34:4989BrowserWindowCocoa::BrowserWindowCocoa(Browser* browser,
[email protected]400eaf82011-08-22 15:47:3990 BrowserWindowController* controller)
[email protected]7d791652010-12-01 16:34:4991 : browser_(browser),
92 controller_(controller),
[email protected]6a9b53a22012-10-09 02:43:3493 initial_show_state_(ui::SHOW_STATE_DEFAULT),
[email protected]ad996342012-01-14 00:29:5994 attention_request_id_(0) {
[email protected]cfecf9432011-09-27 17:10:0895
[email protected]6a9b53a22012-10-09 02:43:3496 gfx::Rect bounds;
97 chrome::GetSavedWindowBoundsAndShowState(browser_,
98 &bounds,
99 &initial_show_state_);
[email protected]e2395da2013-01-23 22:05:35100
101 browser_->search_model()->AddObserver(this);
[email protected]7d791652010-12-01 16:34:49102}
103
104BrowserWindowCocoa::~BrowserWindowCocoa() {
[email protected]e2395da2013-01-23 22:05:35105 browser_->search_model()->RemoveObserver(this);
[email protected]7d791652010-12-01 16:34:49106}
107
108void BrowserWindowCocoa::Show() {
109 // The Browser associated with this browser window must become the active
110 // browser at the time |Show()| is called. This is the natural behaviour under
111 // Windows, but |-makeKeyAndOrderFront:| won't send |-windowDidBecomeMain:|
112 // until we return to the runloop. Therefore any calls to
[email protected]4d900252012-11-20 20:37:11113 // |chrome::FindLastActiveWithHostDesktopType| will return the previous
114 // browser instead if we don't explicitly set it here.
[email protected]7d791652010-12-01 16:34:49115 BrowserList::SetLastActive(browser_);
116
[email protected]8bc061f2011-08-31 22:46:23117 bool is_session_restore = browser_->is_session_restore();
[email protected]b5cc93c2011-09-02 02:33:42118 NSWindowAnimationBehavior saved_animation_behavior =
119 NSWindowAnimationBehaviorDefault;
[email protected]8bc061f2011-08-31 22:46:23120 bool did_save_animation_behavior = false;
121 // Turn off swishing when restoring windows.
122 if (is_session_restore &&
123 [window() respondsToSelector:@selector(animationBehavior)] &&
124 [window() respondsToSelector:@selector(setAnimationBehavior:)]) {
125 did_save_animation_behavior = true;
126 saved_animation_behavior = [window() animationBehavior];
127 [window() setAnimationBehavior:NSWindowAnimationBehaviorNone];
128 }
[email protected]400eaf82011-08-22 15:47:39129
[email protected]8bc061f2011-08-31 22:46:23130 [window() makeKeyAndOrderFront:controller_];
[email protected]400eaf82011-08-22 15:47:39131
[email protected]8bc061f2011-08-31 22:46:23132 // When creating windows from nibs it is necessary to |makeKeyAndOrderFront:|
133 // prior to |orderOut:| then |miniaturize:| when restoring windows in the
134 // minimized state.
[email protected]cfecf9432011-09-27 17:10:08135 if (initial_show_state_ == ui::SHOW_STATE_MINIMIZED) {
[email protected]400eaf82011-08-22 15:47:39136 [window() orderOut:controller_];
137 [window() miniaturize:controller_];
[email protected]85b0ac62012-02-09 01:57:43138 } else if (initial_show_state_ == ui::SHOW_STATE_FULLSCREEN) {
[email protected]320b3692014-01-29 21:32:38139 chrome::ToggleFullscreenWithChromeOrFallback(browser_);
[email protected]400eaf82011-08-22 15:47:39140 }
[email protected]cfecf9432011-09-27 17:10:08141 initial_show_state_ = ui::SHOW_STATE_DEFAULT;
[email protected]8bc061f2011-08-31 22:46:23142
143 // Restore window animation behavior.
144 if (did_save_animation_behavior)
145 [window() setAnimationBehavior:saved_animation_behavior];
[email protected]2f516c792011-09-19 22:22:09146
147 browser_->OnWindowDidShow();
[email protected]7d791652010-12-01 16:34:49148}
149
[email protected]d4db6c702011-03-28 21:49:14150void BrowserWindowCocoa::ShowInactive() {
[email protected]400eaf82011-08-22 15:47:39151 [window() orderFront:controller_];
[email protected]d4db6c702011-03-28 21:49:14152}
153
[email protected]7d412f72012-10-25 04:59:15154void BrowserWindowCocoa::Hide() {
155 // Not implemented.
156}
157
[email protected]7d791652010-12-01 16:34:49158void BrowserWindowCocoa::SetBounds(const gfx::Rect& bounds) {
[email protected]ccb5895f2011-06-09 21:16:14159 gfx::Rect real_bounds = [controller_ enforceMinWindowSize:bounds];
160
[email protected]55c87fa2011-10-15 07:28:28161 ExitFullscreen();
[email protected]ccb5895f2011-06-09 21:16:14162 NSRect cocoa_bounds = NSMakeRect(real_bounds.x(), 0,
163 real_bounds.width(),
164 real_bounds.height());
[email protected]7d791652010-12-01 16:34:49165 // Flip coordinates based on the primary screen.
166 NSScreen* screen = [[NSScreen screens] objectAtIndex:0];
167 cocoa_bounds.origin.y =
[email protected]03e0f5f1e2012-06-07 21:35:39168 NSHeight([screen frame]) - real_bounds.height() - real_bounds.y();
[email protected]7d791652010-12-01 16:34:49169
170 [window() setFrame:cocoa_bounds display:YES];
171}
172
173// Callers assume that this doesn't immediately delete the Browser object.
174// The controller implementing the window delegate methods called from
175// |-performClose:| must take precautions to ensure that.
176void BrowserWindowCocoa::Close() {
177 // If there is an overlay window, we contain a tab being dragged between
178 // windows. Don't hide the window as it makes the UI extra confused. We can
179 // still close the window, as that will happen when the drag completes.
[email protected]60f94292012-03-12 22:24:27180 if ([controller_ overlayWindow]) {
[email protected]7d791652010-12-01 16:34:49181 [controller_ deferPerformClose];
[email protected]60f94292012-03-12 22:24:27182 } else {
[email protected]5ea51972012-10-15 16:45:47183 // Using |-performClose:| can prevent the window from actually closing if
184 // a JavaScript beforeunload handler opens an alert during shutdown, as
185 // documented at <http://crbug.com/118424>. Re-implement
186 // -[NSWindow performClose:] as closely as possible to how Apple documents
187 // it.
[email protected]d1136ca2012-10-18 23:35:55188 //
189 // Before calling |-close|, hide the window immediately. |-performClose:|
190 // would do something similar, and this ensures that the window is removed
191 // from AppKit's display list. Not doing so can lead to crashes like
192 // <http://crbug.com/156101>.
[email protected]5ea51972012-10-15 16:45:47193 id<NSWindowDelegate> delegate = [window() delegate];
194 SEL window_should_close = @selector(windowShouldClose:);
195 if ([delegate respondsToSelector:window_should_close]) {
[email protected]d1136ca2012-10-18 23:35:55196 if ([delegate windowShouldClose:window()]) {
197 [window() orderOut:nil];
[email protected]5ea51972012-10-15 16:45:47198 [window() close];
[email protected]d1136ca2012-10-18 23:35:55199 }
[email protected]5ea51972012-10-15 16:45:47200 } else if ([window() respondsToSelector:window_should_close]) {
[email protected]d1136ca2012-10-18 23:35:55201 if ([window() performSelector:window_should_close withObject:window()]) {
202 [window() orderOut:nil];
[email protected]5ea51972012-10-15 16:45:47203 [window() close];
[email protected]d1136ca2012-10-18 23:35:55204 }
[email protected]5ea51972012-10-15 16:45:47205 } else {
[email protected]d1136ca2012-10-18 23:35:55206 [window() orderOut:nil];
[email protected]5ea51972012-10-15 16:45:47207 [window() close];
208 }
[email protected]60f94292012-03-12 22:24:27209 }
[email protected]7d791652010-12-01 16:34:49210}
211
212void BrowserWindowCocoa::Activate() {
213 [controller_ activate];
214}
215
216void BrowserWindowCocoa::Deactivate() {
217 // TODO(jcivelli): http://crbug.com/51364 Implement me.
218 NOTIMPLEMENTED();
219}
220
[email protected]ad996342012-01-14 00:29:59221void BrowserWindowCocoa::FlashFrame(bool flash) {
222 if (flash) {
223 attention_request_id_ = [NSApp requestUserAttention:NSInformationalRequest];
224 } else {
225 [NSApp cancelUserAttentionRequest:attention_request_id_];
226 attention_request_id_ = 0;
227 }
[email protected]7d791652010-12-01 16:34:49228}
229
[email protected]d101b0c2012-03-16 00:30:57230bool BrowserWindowCocoa::IsAlwaysOnTop() const {
231 return false;
232}
233
[email protected]46d46052013-10-11 11:27:22234void BrowserWindowCocoa::SetAlwaysOnTop(bool always_on_top) {
235 // Not implemented for browser windows.
236 NOTIMPLEMENTED();
237}
238
[email protected]7d791652010-12-01 16:34:49239bool BrowserWindowCocoa::IsActive() const {
240 return [window() isKeyWindow];
241}
242
[email protected]90556dd2012-06-07 20:26:18243gfx::NativeWindow BrowserWindowCocoa::GetNativeWindow() {
[email protected]7d791652010-12-01 16:34:49244 return window();
245}
246
247BrowserWindowTesting* BrowserWindowCocoa::GetBrowserWindowTesting() {
248 return NULL;
249}
250
251StatusBubble* BrowserWindowCocoa::GetStatusBubble() {
252 return [controller_ statusBubble];
253}
254
[email protected]7d791652010-12-01 16:34:49255void BrowserWindowCocoa::UpdateTitleBar() {
256 NSString* newTitle =
257 base::SysUTF16ToNSString(browser_->GetWindowTitleForCurrentTab());
258
[email protected]d78e615e2011-09-06 21:46:03259 pending_window_title_.reset(
260 [BrowserWindowUtils scheduleReplaceOldTitle:pending_window_title_.get()
261 withNewTitle:newTitle
262 forWindow:window()]);
[email protected]7d791652010-12-01 16:34:49263}
264
[email protected]09b29342011-06-24 19:18:48265void BrowserWindowCocoa::BookmarkBarStateChanged(
266 BookmarkBar::AnimateChangeType change_type) {
[email protected]1eeccb92012-12-06 20:31:24267 [[controller_ bookmarkBarController]
268 updateState:browser_->bookmark_bar_state()
269 changeType:change_type];
[email protected]7d791652010-12-01 16:34:49270}
271
272void BrowserWindowCocoa::UpdateDevTools() {
273 [controller_ updateDevToolsForContents:
[email protected]617ee962013-01-29 20:49:12274 browser_->tab_strip_model()->GetActiveWebContents()];
[email protected]7d791652010-12-01 16:34:49275}
276
277void BrowserWindowCocoa::UpdateLoadingAnimations(bool should_animate) {
278 // Do nothing on Mac.
279}
280
281void BrowserWindowCocoa::SetStarredState(bool is_starred) {
282 [controller_ setStarredState:is_starred ? YES : NO];
283}
284
[email protected]3917f82a2013-11-21 06:25:54285void BrowserWindowCocoa::SetTranslateIconToggled(bool is_lit) {
286 NOTIMPLEMENTED();
287}
288
[email protected]08726d5e2013-09-24 21:52:55289void BrowserWindowCocoa::OnActiveTabChanged(content::WebContents* old_contents,
290 content::WebContents* new_contents,
291 int index,
292 int reason) {
293 // TODO(pkasting): Perhaps the code in
294 // TabStripController::activateTabWithContents should move here? Or this
295 // should call that (instead of TabStripModelObserverBridge doing so)? It's
296 // not obvious to me why Mac doesn't handle tab changes in BrowserWindow the
297 // way views and GTK do.
298}
299
[email protected]5423c372012-08-22 05:50:16300void BrowserWindowCocoa::ZoomChangedForActiveTab(bool can_show_bubble) {
301 [controller_ zoomChangedForActiveTab:can_show_bubble ? YES : NO];
[email protected]6f80e932012-06-04 19:00:07302}
303
[email protected]7d791652010-12-01 16:34:49304gfx::Rect BrowserWindowCocoa::GetRestoredBounds() const {
305 // Flip coordinates based on the primary screen.
306 NSScreen* screen = [[NSScreen screens] objectAtIndex:0];
307 NSRect frame = [controller_ regularWindowFrame];
[email protected]03e0f5f1e2012-06-07 21:35:39308 gfx::Rect bounds(frame.origin.x, 0, NSWidth(frame), NSHeight(frame));
309 bounds.set_y(NSHeight([screen frame]) - NSMaxY(frame));
[email protected]7d791652010-12-01 16:34:49310 return bounds;
311}
312
[email protected]68eeede2013-05-09 06:10:57313ui::WindowShowState BrowserWindowCocoa::GetRestoredState() const {
314 if (IsMaximized())
315 return ui::SHOW_STATE_MAXIMIZED;
316 if (IsMinimized())
317 return ui::SHOW_STATE_MINIMIZED;
318 return ui::SHOW_STATE_NORMAL;
319}
320
[email protected]d479b8e22011-02-09 05:19:49321gfx::Rect BrowserWindowCocoa::GetBounds() const {
322 return GetRestoredBounds();
323}
324
[email protected]7d791652010-12-01 16:34:49325bool BrowserWindowCocoa::IsMaximized() const {
326 return [window() isZoomed];
327}
328
[email protected]400eaf82011-08-22 15:47:39329bool BrowserWindowCocoa::IsMinimized() const {
330 return [window() isMiniaturized];
331}
332
[email protected]541e3ee2011-11-22 01:31:10333void BrowserWindowCocoa::Maximize() {
334 // Zoom toggles so only call if not already maximized.
335 if (!IsMaximized())
336 [window() zoom:controller_];
337}
338
339void BrowserWindowCocoa::Minimize() {
340 [window() miniaturize:controller_];
341}
342
343void BrowserWindowCocoa::Restore() {
344 if (IsMaximized())
345 [window() zoom:controller_]; // Toggles zoom mode.
346 else if (IsMinimized())
347 [window() deminiaturize:controller_];
348}
349
[email protected]8d944b32011-10-17 06:11:53350void BrowserWindowCocoa::EnterFullscreen(
[email protected]22d74a6b2011-10-17 20:30:31351 const GURL& url, FullscreenExitBubbleType bubble_type) {
[email protected]52a1cc32013-07-18 19:02:41352 // When simplified fullscreen is enabled, always enter normal fullscreen.
353 const CommandLine* command_line = CommandLine::ForCurrentProcess();
354 if (command_line->HasSwitch(switches::kEnableSimplifiedFullscreen)) {
[email protected]750501522013-07-20 01:44:29355 if (url.is_empty())
356 [controller_ enterFullscreen];
357 else
358 [controller_ enterFullscreenForURL:url bubbleType:bubble_type];
[email protected]52a1cc32013-07-18 19:02:41359 return;
360 }
361
[email protected]34337d32013-01-29 20:29:01362 [controller_ enterPresentationModeForURL:url
363 bubbleType:bubble_type];
[email protected]55c87fa2011-10-15 07:28:28364}
365
366void BrowserWindowCocoa::ExitFullscreen() {
[email protected]22d74a6b2011-10-17 20:30:31367 [controller_ exitFullscreen];
[email protected]8d944b32011-10-17 06:11:53368}
369
370void BrowserWindowCocoa::UpdateFullscreenExitBubbleContent(
371 const GURL& url,
372 FullscreenExitBubbleType bubble_type) {
[email protected]22d74a6b2011-10-17 20:30:31373 [controller_ updateFullscreenExitBubbleURL:url bubbleType:bubble_type];
[email protected]7d791652010-12-01 16:34:49374}
375
[email protected]6a414ff2013-02-27 08:22:54376bool BrowserWindowCocoa::ShouldHideUIForFullscreen() const {
377 // On Mac, fullscreen mode has most normal things (in a slide-down panel).
378 return false;
379}
380
[email protected]7d791652010-12-01 16:34:49381bool BrowserWindowCocoa::IsFullscreen() const {
[email protected]34337d32013-01-29 20:29:01382 if ([controller_ inPresentationMode])
383 CHECK([controller_ isFullscreen]); // Presentation mode must be fullscreen.
[email protected]8d944b32011-10-17 06:11:53384 return [controller_ isFullscreen];
[email protected]7d791652010-12-01 16:34:49385}
386
387bool BrowserWindowCocoa::IsFullscreenBubbleVisible() const {
388 return false;
389}
390
391void BrowserWindowCocoa::ConfirmAddSearchProvider(
[email protected]3613347d2012-04-27 20:27:37392 TemplateURL* template_url,
[email protected]7d791652010-12-01 16:34:49393 Profile* profile) {
[email protected]464f0012011-07-07 02:12:51394 // The controller will release itself when the window closes.
395 EditSearchEngineCocoaController* editor =
396 [[EditSearchEngineCocoaController alloc] initWithProfile:profile
397 delegate:NULL
398 templateURL:template_url];
399 [NSApp beginSheet:[editor window]
400 modalForWindow:window()
401 modalDelegate:controller_
402 didEndSelector:@selector(sheetDidEnd:returnCode:context:)
403 contextInfo:NULL];
[email protected]7d791652010-12-01 16:34:49404}
405
406LocationBar* BrowserWindowCocoa::GetLocationBar() const {
407 return [controller_ locationBarBridge];
408}
409
410void BrowserWindowCocoa::SetFocusToLocationBar(bool select_all) {
411 [controller_ focusLocationBar:select_all ? YES : NO];
412}
413
414void BrowserWindowCocoa::UpdateReloadStopState(bool is_loading, bool force) {
415 [controller_ setIsLoading:is_loading force:force];
416}
417
[email protected]2e7fe4312013-08-21 17:19:48418void BrowserWindowCocoa::UpdateToolbar(content::WebContents* contents) {
419 [controller_ updateToolbarWithContents:contents];
[email protected]7d791652010-12-01 16:34:49420}
421
422void BrowserWindowCocoa::FocusToolbar() {
423 // Not needed on the Mac.
424}
425
426void BrowserWindowCocoa::FocusAppMenu() {
427 // Chrome uses the standard Mac OS X menu bar, so this isn't needed.
428}
429
430void BrowserWindowCocoa::RotatePaneFocus(bool forwards) {
431 // Not needed on the Mac.
432}
433
434void BrowserWindowCocoa::FocusBookmarksToolbar() {
435 // Not needed on the Mac.
436}
437
[email protected]822ca8c62013-04-19 00:49:15438void BrowserWindowCocoa::FocusInfobars() {
439 // Not needed on the Mac.
440}
441
[email protected]7d791652010-12-01 16:34:49442bool BrowserWindowCocoa::IsBookmarkBarVisible() const {
[email protected]a007e732011-08-05 13:32:19443 return browser_->profile()->GetPrefs()->GetBoolean(prefs::kShowBookmarkBar);
[email protected]7d791652010-12-01 16:34:49444}
445
446bool BrowserWindowCocoa::IsBookmarkBarAnimating() const {
447 return [controller_ isBookmarkBarAnimating];
448}
449
[email protected]95bf8a5b2010-12-22 16:04:07450bool BrowserWindowCocoa::IsTabStripEditable() const {
451 return ![controller_ isDragSessionActive];
452}
453
[email protected]7d791652010-12-01 16:34:49454bool BrowserWindowCocoa::IsToolbarVisible() const {
455 return browser_->SupportsWindowFeature(Browser::FEATURE_TOOLBAR) ||
456 browser_->SupportsWindowFeature(Browser::FEATURE_LOCATIONBAR);
457}
458
[email protected]b7a756d42012-01-23 18:08:17459gfx::Rect BrowserWindowCocoa::GetRootWindowResizerRect() const {
[email protected]9f8727092012-02-08 01:38:18460 if (IsDownloadShelfVisible())
461 return gfx::Rect();
[email protected]b7a756d42012-01-23 18:08:17462 NSRect tabRect = [controller_ selectedTabGrowBoxRect];
463 return gfx::Rect(NSRectToCGRect(tabRect));
464}
465
[email protected]7d791652010-12-01 16:34:49466void BrowserWindowCocoa::AddFindBar(
467 FindBarCocoaController* find_bar_cocoa_controller) {
[email protected]632983f2011-08-08 22:51:24468 [controller_ addFindBar:find_bar_cocoa_controller];
[email protected]7d791652010-12-01 16:34:49469}
470
[email protected]7d791652010-12-01 16:34:49471void BrowserWindowCocoa::ShowUpdateChromeDialog() {
[email protected]678dae82011-02-11 20:03:08472 restart_browser::RequestRestart(window());
[email protected]7d791652010-12-01 16:34:49473}
474
[email protected]7d791652010-12-01 16:34:49475void BrowserWindowCocoa::ShowBookmarkBubble(const GURL& url,
476 bool already_bookmarked) {
477 [controller_ showBookmarkBubbleForURL:url
478 alreadyBookmarked:(already_bookmarked ? YES : NO)];
479}
480
[email protected]e625b7602013-10-28 09:24:56481void BrowserWindowCocoa::ShowTranslateBubble(
482 content::WebContents* contents,
[email protected]6d37ab22013-12-03 11:18:30483 TranslateBubbleModel::ViewState view_state,
484 TranslateErrors::Type error_type) {
485 NOTIMPLEMENTED();
[email protected]e625b7602013-10-28 09:24:56486}
487
[email protected]235a0562012-03-26 22:22:35488#if defined(ENABLE_ONE_CLICK_SIGNIN)
[email protected]fe54b4a2012-03-28 16:11:04489void BrowserWindowCocoa::ShowOneClickSigninBubble(
[email protected]265c9272013-01-25 19:18:45490 OneClickSigninBubbleType type,
[email protected]dcd0249872013-12-06 23:58:45491 const base::string16& email,
492 const base::string16& error_message,
[email protected]265c9272013-01-25 19:18:45493 const StartSyncCallback& start_sync_callback) {
[email protected]02ada8bf2013-05-02 01:34:22494 WebContents* web_contents =
495 browser_->tab_strip_model()->GetActiveWebContents();
[email protected]8aa690c2013-02-06 22:33:12496 if (type == ONE_CLICK_SIGNIN_BUBBLE_TYPE_BUBBLE) {
[email protected]a8522032013-06-24 22:51:46497 base::scoped_nsobject<OneClickSigninBubbleController> bubble_controller([
498 [OneClickSigninBubbleController alloc]
499 initWithBrowserWindowController:cocoa_controller()
500 webContents:web_contents
501 errorMessage:base::SysUTF16ToNSString(error_message)
502 callback:start_sync_callback]);
[email protected]8aa690c2013-02-06 22:33:12503 [bubble_controller showWindow:nil];
504 } else {
[email protected]8aa690c2013-02-06 22:33:12505 // Deletes itself when the dialog closes.
[email protected]c28050a2013-07-10 04:56:40506 new OneClickSigninDialogController(
507 web_contents, start_sync_callback, email);
[email protected]8aa690c2013-02-06 22:33:12508 }
[email protected]235a0562012-03-26 22:22:35509}
510#endif
511
[email protected]7d791652010-12-01 16:34:49512bool BrowserWindowCocoa::IsDownloadShelfVisible() const {
513 return [controller_ isDownloadShelfVisible] != NO;
514}
515
516DownloadShelf* BrowserWindowCocoa::GetDownloadShelf() {
517 DownloadShelfController* shelfController = [controller_ downloadShelf];
518 return [shelfController bridge];
519}
520
[email protected]7d791652010-12-01 16:34:49521// We allow closing the window here since the real quit decision on Mac is made
522// in [AppController quit:].
[email protected]edfca702013-08-16 08:58:14523void BrowserWindowCocoa::ConfirmBrowserCloseWithPendingDownloads(
524 int download_count,
525 Browser::DownloadClosePreventionType dialog_type,
526 bool app_modal,
527 const base::Callback<void(bool)>& callback) {
528 callback.Run(true);
[email protected]7d791652010-12-01 16:34:49529}
530
[email protected]7d791652010-12-01 16:34:49531void BrowserWindowCocoa::UserChangedTheme() {
532 [controller_ userChangedTheme];
533}
534
535int BrowserWindowCocoa::GetExtraRenderViewHeight() const {
536 // Currently this is only used on linux.
537 return 0;
538}
539
[email protected]2a6bc3e2011-12-28 23:51:33540void BrowserWindowCocoa::WebContentsFocused(WebContents* contents) {
[email protected]7d791652010-12-01 16:34:49541 NOTIMPLEMENTED();
542}
543
[email protected]b8e681e82012-02-20 10:18:47544void BrowserWindowCocoa::ShowWebsiteSettings(
545 Profile* profile,
[email protected]36ad4aa82012-11-21 19:20:48546 content::WebContents* web_contents,
[email protected]b8e681e82012-02-20 10:18:47547 const GURL& url,
[email protected]9fb47a82013-07-05 11:34:02548 const content::SSLStatus& ssl) {
[email protected]a4ed9ed2013-07-11 23:40:13549 WebsiteSettingsUIBridge::Show(window(), profile, web_contents, url, ssl);
[email protected]b8e681e82012-02-20 10:18:47550}
551
[email protected]7d791652010-12-01 16:34:49552void BrowserWindowCocoa::ShowAppMenu() {
553 // No-op. Mac doesn't support showing the menus via alt keys.
554}
555
556bool BrowserWindowCocoa::PreHandleKeyboardEvent(
557 const NativeWebKeyboardEvent& event, bool* is_keyboard_shortcut) {
[email protected]3a1381d2011-08-26 18:12:13558 if (![BrowserWindowUtils shouldHandleKeyboardEvent:event])
[email protected]7d791652010-12-01 16:34:49559 return false;
560
[email protected]a1221aea2013-11-07 01:31:30561 if (event.type == blink::WebInputEvent::RawKeyDown &&
[email protected]d2885ba2012-08-17 10:23:12562 [controller_ handledByExtensionCommand:event.os_event])
563 return true;
564
[email protected]3a1381d2011-08-26 18:12:13565 int id = [BrowserWindowUtils getCommandId:event];
[email protected]7d791652010-12-01 16:34:49566 if (id == -1)
567 return false;
568
[email protected]5d98294912012-06-27 22:57:40569 if (browser_->command_controller()->IsReservedCommandOrKey(id, event)) {
[email protected]3a1381d2011-08-26 18:12:13570 return [BrowserWindowUtils handleKeyboardEvent:event.os_event
571 inWindow:window()];
572 }
[email protected]7d791652010-12-01 16:34:49573
[email protected]3a1381d2011-08-26 18:12:13574 DCHECK(is_keyboard_shortcut);
[email protected]7d791652010-12-01 16:34:49575 *is_keyboard_shortcut = true;
[email protected]7d791652010-12-01 16:34:49576 return false;
577}
578
579void BrowserWindowCocoa::HandleKeyboardEvent(
580 const NativeWebKeyboardEvent& event) {
[email protected]3a1381d2011-08-26 18:12:13581 if ([BrowserWindowUtils shouldHandleKeyboardEvent:event])
582 [BrowserWindowUtils handleKeyboardEvent:event.os_event inWindow:window()];
[email protected]7d791652010-12-01 16:34:49583}
584
[email protected]7d791652010-12-01 16:34:49585void BrowserWindowCocoa::Cut() {
586 [NSApp sendAction:@selector(cut:) to:nil from:nil];
587}
588
589void BrowserWindowCocoa::Copy() {
590 [NSApp sendAction:@selector(copy:) to:nil from:nil];
591}
592
593void BrowserWindowCocoa::Paste() {
594 [NSApp sendAction:@selector(paste:) to:nil from:nil];
595}
596
[email protected]7d791652010-12-01 16:34:49597void BrowserWindowCocoa::OpenTabpose() {
598 [controller_ openTabpose];
599}
600
[email protected]34337d32013-01-29 20:29:01601void BrowserWindowCocoa::EnterFullscreenWithChrome() {
[email protected]52a1cc32013-07-18 19:02:41602 // This method cannot be called if simplified fullscreen is enabled.
603 const CommandLine* command_line = CommandLine::ForCurrentProcess();
604 DCHECK(!command_line->HasSwitch(switches::kEnableSimplifiedFullscreen));
605
[email protected]ee6a5272013-07-15 21:14:01606 CHECK(chrome::mac::SupportsSystemFullscreen());
[email protected]34337d32013-01-29 20:29:01607 if ([controller_ inPresentationMode])
608 [controller_ exitPresentationMode];
609 else
610 [controller_ enterFullscreen];
[email protected]8d944b32011-10-17 06:11:53611}
612
[email protected]34337d32013-01-29 20:29:01613bool BrowserWindowCocoa::IsFullscreenWithChrome() {
[email protected]52a1cc32013-07-18 19:02:41614 // The WithChrome mode does not exist when simplified fullscreen is enabled.
615 const CommandLine* command_line = CommandLine::ForCurrentProcess();
616 if (command_line->HasSwitch(switches::kEnableSimplifiedFullscreen))
617 return false;
[email protected]34337d32013-01-29 20:29:01618 return IsFullscreen() && ![controller_ inPresentationMode];
[email protected]d3766932011-08-04 22:18:23619}
620
[email protected]34337d32013-01-29 20:29:01621bool BrowserWindowCocoa::IsFullscreenWithoutChrome() {
[email protected]52a1cc32013-07-18 19:02:41622 // Presentation mode does not exist if simplified fullscreen is enabled. The
623 // WithoutChrome mode simply maps to whether or not the window is fullscreen.
624 const CommandLine* command_line = CommandLine::ForCurrentProcess();
625 if (command_line->HasSwitch(switches::kEnableSimplifiedFullscreen))
626 return IsFullscreen();
627
[email protected]34337d32013-01-29 20:29:01628 return IsFullscreen() && [controller_ inPresentationMode];
[email protected]d3766932011-08-04 22:18:23629}
630
[email protected]588300d2011-04-28 21:06:35631WindowOpenDisposition BrowserWindowCocoa::GetDispositionForPopupBounds(
632 const gfx::Rect& bounds) {
[email protected]d82a3c9f2012-02-22 04:46:00633 // In Lion fullscreen mode, convert popups into tabs.
[email protected]ee6a5272013-07-15 21:14:01634 if (chrome::mac::SupportsSystemFullscreen() && IsFullscreen())
[email protected]d82a3c9f2012-02-22 04:46:00635 return NEW_FOREGROUND_TAB;
[email protected]588300d2011-04-28 21:06:35636 return NEW_POPUP;
637}
638
[email protected]632983f2011-08-08 22:51:24639FindBar* BrowserWindowCocoa::CreateFindBar() {
640 // We could push the AddFindBar() call into the FindBarBridge
641 // constructor or the FindBarCocoaController init, but that makes
642 // unit testing difficult, since we would also require a
643 // BrowserWindow object.
[email protected]03d5af592013-03-21 12:30:25644 FindBarBridge* bridge = new FindBarBridge(browser_);
[email protected]632983f2011-08-08 22:51:24645 AddFindBar(bridge->find_bar_cocoa_controller());
646 return bridge;
647}
648
[email protected]e41d0082013-05-16 04:37:54649web_modal::WebContentsModalDialogHost*
[email protected]7519c522013-04-02 01:07:23650 BrowserWindowCocoa::GetWebContentsModalDialogHost() {
651 return NULL;
[email protected]6a151762012-10-03 22:33:19652}
653
[email protected]78ce3022012-09-24 01:48:48654extensions::ActiveTabPermissionGranter*
655 BrowserWindowCocoa::GetActiveTabPermissionGranter() {
[email protected]852934842012-12-10 16:50:13656 WebContents* web_contents =
657 browser_->tab_strip_model()->GetActiveWebContents();
658 if (!web_contents)
[email protected]78ce3022012-09-24 01:48:48659 return NULL;
660 extensions::TabHelper* tab_helper =
[email protected]852934842012-12-10 16:50:13661 extensions::TabHelper::FromWebContents(web_contents);
[email protected]78ce3022012-09-24 01:48:48662 return tab_helper ? tab_helper->active_tab_permission_granter() : NULL;
663}
664
[email protected]165fe422013-03-27 06:34:03665void BrowserWindowCocoa::ModelChanged(const SearchModel::State& old_state,
666 const SearchModel::State& new_state) {
[email protected]e2395da2013-01-23 22:05:35667}
668
[email protected]7d791652010-12-01 16:34:49669void BrowserWindowCocoa::DestroyBrowser() {
670 [controller_ destroyBrowser];
671
672 // at this point the controller is dead (autoreleased), so
673 // make sure we don't try to reference it any more.
674}
675
676NSWindow* BrowserWindowCocoa::window() const {
677 return [controller_ window];
678}
679
[email protected]0ec4898e2011-12-30 21:09:24680void BrowserWindowCocoa::ShowAvatarBubble(WebContents* web_contents,
[email protected]2f733a02011-10-06 15:17:34681 const gfx::Rect& rect) {
[email protected]f5d230b32012-12-11 02:04:11682 NSPoint point = GetPointForBubble(web_contents, rect.right(), rect.bottom());
[email protected]2f733a02011-10-06 15:17:34683
684 // |menu| will automatically release itself on close.
685 AvatarMenuBubbleController* menu =
686 [[AvatarMenuBubbleController alloc] initWithBrowser:browser_
687 anchoredAt:point];
[email protected]51152d6d2011-11-07 01:55:12688 [[menu bubble] setAlignment:info_bubble::kAlignEdgeToAnchorEdge];
[email protected]2f733a02011-10-06 15:17:34689 [menu showWindow:nil];
690}
[email protected]7d2d08152011-10-25 22:58:47691
692void BrowserWindowCocoa::ShowAvatarBubbleFromAvatarButton() {
[email protected]25d0b8b72014-01-23 22:12:12693 AvatarBaseController* controller = [controller_ avatarButtonController];
[email protected]8d904e832013-06-17 19:19:14694 [controller showAvatarBubble:[controller buttonView]];
[email protected]7d2d08152011-10-25 22:58:47695}
[email protected]f5d230b32012-12-11 02:04:11696
697void BrowserWindowCocoa::ShowPasswordGenerationBubble(
698 const gfx::Rect& rect,
[email protected]e620d362013-09-09 08:01:53699 const autofill::PasswordForm& form,
[email protected]f5d230b32012-12-11 02:04:11700 autofill::PasswordGenerator* password_generator) {
[email protected]617ee962013-01-29 20:49:12701 WebContents* web_contents =
702 browser_->tab_strip_model()->GetActiveWebContents();
[email protected]f5d230b32012-12-11 02:04:11703 // We want to point to the middle of the rect instead of the right side.
704 NSPoint point = GetPointForBubble(web_contents,
705 rect.x() + rect.width()/2,
706 rect.bottom());
707
708 PasswordGenerationBubbleController* controller =
709 [[PasswordGenerationBubbleController alloc]
710 initWithWindow:browser_->window()->GetNativeWindow()
711 anchoredAt:point
712 renderViewHost:web_contents->GetRenderViewHost()
713 passwordManager:PasswordManager::FromWebContents(web_contents)
714 usingGenerator:password_generator
715 forForm:form];
716 [controller showWindow:nil];
717}
[email protected]dc0fd432013-08-27 15:29:21718
719int
720BrowserWindowCocoa::GetRenderViewHeightInsetWithDetachedBookmarkBar() {
721 if (browser_->bookmark_bar_state() != BookmarkBar::DETACHED)
722 return 0;
723 // TODO(sail): please make this work with cocoa, then enable
724 // BrowserTest.GetSizeForNewRenderView and
725 // WebContentsImplBrowserTest.GetSizeForNewRenderView.
726 // This function should return the extra height of the render view when
727 // detached bookmark bar is hidden.
728 // However, I (kuan) return 0 for now to retain the original behavior,
729 // because I encountered the following problem on cocoa:
730 // 1) When a navigation is requested,
731 // WebContentsImpl::CreateRenderViewForRenderManager creates the new
732 // RenderWidgetHostView at the size specified by
733 // WebContentsDelegate::GetSizeForNewRenderView implemented by Browser.
734 // 2) When the pending navigation entry is committed,
735 // WebContentsImpl::UpdateRenderViewSizeForRenderManager udpates the size
736 // of WebContentsView to the size in (1).
737 // 3) WebContentsImpl::DidNavigateMainFramePostCommit() is called, where
738 // the detached bookmark bar is hidden, resulting in relayout of tab
739 // contents area.
740 // On cocoa, (2) causes RenderWidgetHostView to resize (enlarge) further.
741 // e.g. if size in (1) is size A, and this function returns height H, height
742 // of RenderWidgetHostView after (2) becomes A.height() + H; it's supposed to
743 // stay at A.height().
744 // Then, in (3), WebContentsView and RenderWidgetHostView enlarge even
745 // further, both by another H, i.e. WebContentsView's height becomes
746 // A.height() + H and RenderWidgetHostView's height becomes A.height() + 2H.
747 // Strangely, the RenderWidgetHostView for the previous navigation entry also
748 // gets enlarged by H.
749 // I believe these "automatic" resizing are caused by setAutoresizingMask of
750 // of the cocoa view in WebContentsViewMac, which defeats the purpose of
751 // WebContentsDelegate::GetSizeForNewRenderView i.e. to prevent resizing of
752 // RenderWidgetHostView in (2) and (3).
753 return 0;
754}