1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CHROME_BROWSER_UI_COCOA_BROWSER_WINDOW_CONTROLLER_H_
6#define CHROME_BROWSER_UI_COCOA_BROWSER_WINDOW_CONTROLLER_H_
7
8// A class acting as the Objective-C controller for the Browser
9// object. Handles interactions between Cocoa and the cross-platform
10// code. Each window has a single toolbar and, by virtue of being a
11// TabWindowController, a tab strip along the top.
12
13#import <Cocoa/Cocoa.h>
14
15#include "base/mac/scoped_nsobject.h"
16#include "base/memory/scoped_ptr.h"
17#import "chrome/browser/ui/cocoa/bookmarks/bookmark_bar_controller.h"
18#import "chrome/browser/ui/cocoa/bookmarks/bookmark_bubble_controller.h"
19#import "chrome/browser/ui/cocoa/browser_command_executor.h"
20#import "chrome/browser/ui/cocoa/fullscreen_exit_bubble_controller.h"
21#import "chrome/browser/ui/cocoa/tabs/tab_strip_controller.h"
22#import "chrome/browser/ui/cocoa/tabs/tab_window_controller.h"
23#import "chrome/browser/ui/cocoa/themed_window.h"
24#import "chrome/browser/ui/cocoa/url_drop_target.h"
25#import "chrome/browser/ui/cocoa/view_resizer.h"
26#include "ui/gfx/rect.h"
27
28@class AvatarButtonController;
29class Browser;
30class BrowserWindow;
31class BrowserWindowCocoa;
32@class DevToolsController;
33@class DownloadShelfController;
34class ExtensionKeybindingRegistryCocoa;
35@class FindBarCocoaController;
36@class FullscreenWindow;
37@class InfoBarContainerController;
38class LocationBarViewMac;
39@class OverlayableContentsController;
40@class PresentationModeController;
41class StatusBubbleMac;
42@class TabStripController;
43@class TabStripView;
44@class ToolbarController;
45
46namespace content {
47class WebContents;
48}
49
50@interface BrowserWindowController :
51  TabWindowController<NSUserInterfaceValidations,
52                      BookmarkBarControllerDelegate,
53                      BrowserCommandExecutor,
54                      ViewResizer,
55                      TabStripControllerDelegate> {
56 @private
57  // The ordering of these members is important as it determines the order in
58  // which they are destroyed. |browser_| needs to be destroyed last as most of
59  // the other objects hold weak references to it or things it owns
60  // (tab/toolbar/bookmark models, profiles, etc).
61  scoped_ptr<Browser> browser_;
62  NSWindow* savedRegularWindow_;
63  scoped_ptr<BrowserWindowCocoa> windowShim_;
64  base::scoped_nsobject<ToolbarController> toolbarController_;
65  base::scoped_nsobject<TabStripController> tabStripController_;
66  base::scoped_nsobject<FindBarCocoaController> findBarCocoaController_;
67  base::scoped_nsobject<InfoBarContainerController> infoBarContainerController_;
68  base::scoped_nsobject<DownloadShelfController> downloadShelfController_;
69  base::scoped_nsobject<BookmarkBarController> bookmarkBarController_;
70  base::scoped_nsobject<DevToolsController> devToolsController_;
71  base::scoped_nsobject<OverlayableContentsController>
72      overlayableContentsController_;
73  base::scoped_nsobject<PresentationModeController> presentationModeController_;
74  base::scoped_nsobject<FullscreenExitBubbleController>
75      fullscreenExitBubbleController_;
76
77  // Strong. StatusBubble is a special case of a strong reference that
78  // we don't wrap in a scoped_ptr because it is acting the same
79  // as an NSWindowController in that it wraps a window that must
80  // be shut down before our destructors are called.
81  StatusBubbleMac* statusBubble_;
82
83  BookmarkBubbleController* bookmarkBubbleController_;  // Weak.
84  BOOL initializing_;  // YES while we are currently in initWithBrowser:
85  BOOL ownsBrowser_;  // Only ever NO when testing
86
87  // The total amount by which we've grown the window up or down (to display a
88  // bookmark bar and/or download shelf), respectively; reset to 0 when moved
89  // away from the bottom/top or resized (or zoomed).
90  CGFloat windowTopGrowth_;
91  CGFloat windowBottomGrowth_;
92
93  // YES only if we're shrinking the window from an apparent zoomed state (which
94  // we'll only do if we grew it to the zoomed state); needed since we'll then
95  // restrict the amount of shrinking by the amounts specified above. Reset to
96  // NO on growth.
97  BOOL isShrinkingFromZoomed_;
98
99  // The raw accumulated zoom value and the actual zoom increments made for an
100  // an in-progress pinch gesture.
101  CGFloat totalMagnifyGestureAmount_;
102  NSInteger currentZoomStepDelta_;
103
104  // The view controller that manages the incognito badge or the multi-profile
105  // avatar icon. The view is always in the view hierarchy, but will be hidden
106  // unless it's appropriate to show it.
107  base::scoped_nsobject<AvatarButtonController> avatarButtonController_;
108
109  // Lazily created view which draws the background for the floating set of bars
110  // in presentation mode (for window types having a floating bar; it remains
111  // nil for those which don't).
112  base::scoped_nsobject<NSView> floatingBarBackingView_;
113
114  // The borderless window used in fullscreen mode.  Lion reuses the original
115  // window in fullscreen mode, so this is always nil on Lion.
116  base::scoped_nsobject<NSWindow> fullscreenWindow_;
117
118  // Tracks whether presentation mode was entered from fullscreen mode or
119  // directly from normal windowed mode.  Used to determine what to do when
120  // exiting presentation mode.
121  BOOL enteredPresentationModeFromFullscreen_;
122
123  // True between -windowWillEnterFullScreen and -windowDidEnterFullScreen.
124  // Only used on Lion and higher.
125  BOOL enteringFullscreen_;
126
127  // True between |-setPresentationMode:url:bubbleType:| and
128  // -windowDidEnterFullScreen. Only used on Lion and higher.
129  BOOL enteringPresentationMode_;
130
131  // The size of the original (non-fullscreen) window.  This is saved just
132  // before entering fullscreen mode and is only valid when |-isFullscreen|
133  // returns YES.
134  NSRect savedRegularWindowFrame_;
135
136  // The proportion of the floating bar which is shown (in presentation mode).
137  CGFloat floatingBarShownFraction_;
138
139  // Various UI elements/events may want to ensure that the floating bar is
140  // visible (in presentation mode), e.g., because of where the mouse is or
141  // where keyboard focus is. Whenever an object requires bar visibility, it has
142  // itself added to |barVisibilityLocks_|. When it no longer requires bar
143  // visibility, it has itself removed.
144  base::scoped_nsobject<NSMutableSet> barVisibilityLocks_;
145
146  // Bar visibility locks and releases only result (when appropriate) in changes
147  // in visible state when the following is |YES|.
148  BOOL barVisibilityUpdatesEnabled_;
149
150  // When going fullscreen for a tab, we need to store the URL and the
151  // fullscreen type, since we can't show the bubble until
152  // -windowDidEnterFullScreen: gets called.
153  GURL fullscreenUrl_;
154  FullscreenExitBubbleType fullscreenBubbleType_;
155
156  // The Extension Command Registry used to determine which keyboard events to
157  // handle.
158  scoped_ptr<ExtensionKeybindingRegistryCocoa> extension_keybinding_registry_;
159
160  // The number of overlapped views being shown.
161  NSUInteger overlappedViewCount_;
162}
163
164// A convenience class method which gets the |BrowserWindowController| for a
165// given window. This method returns nil if no window in the chain has a BWC.
166+ (BrowserWindowController*)browserWindowControllerForWindow:(NSWindow*)window;
167
168// A convenience class method which gets the |BrowserWindowController| for a
169// given view.  This is the controller for the window containing |view|, if it
170// is a BWC, or the first controller in the parent-window chain that is a
171// BWC. This method returns nil if no window in the chain has a BWC.
172+ (BrowserWindowController*)browserWindowControllerForView:(NSView*)view;
173
174// Helper method used to update the "Signin" menu item to reflect the current
175// signed in state. Class-level function as it's still required even when there
176// are no open browser windows.
177+ (void)updateSigninItem:(id)signinItem
178              shouldShow:(BOOL)showSigninMenuItem
179          currentProfile:(Profile*)profile;
180
181// Load the browser window nib and do any Cocoa-specific initialization.
182// Takes ownership of |browser|.
183- (id)initWithBrowser:(Browser*)browser;
184
185// Call to make the browser go away from other places in the cross-platform
186// code.
187- (void)destroyBrowser;
188
189// Ensure bounds for the window abide by the minimum window size.
190- (gfx::Rect)enforceMinWindowSize:(gfx::Rect)bounds;
191
192// Access the C++ bridge between the NSWindow and the rest of Chromium.
193- (BrowserWindow*)browserWindow;
194
195// Return a weak pointer to the toolbar controller.
196- (ToolbarController*)toolbarController;
197
198// Return a weak pointer to the tab strip controller.
199- (TabStripController*)tabStripController;
200
201// Return a weak pointer to the find bar controller.
202- (FindBarCocoaController*)findBarCocoaController;
203
204// Access the ObjC controller that contains the infobars.
205- (InfoBarContainerController*)infoBarContainerController;
206
207// Access the C++ bridge object representing the status bubble for the window.
208- (StatusBubbleMac*)statusBubble;
209
210// Access the C++ bridge object representing the location bar.
211- (LocationBarViewMac*)locationBarBridge;
212
213// Returns a weak pointer to the floating bar backing view;
214- (NSView*)floatingBarBackingView;
215
216// Returns a weak pointer to the overlayable contents controller.
217- (OverlayableContentsController*)overlayableContentsController;
218
219// Access the Profile object that backs this Browser.
220- (Profile*)profile;
221
222// Access the avatar button controller.
223- (AvatarButtonController*)avatarButtonController;
224
225// Updates the toolbar (and transitively the location bar) with the states of
226// the specified |tab|.  If |shouldRestore| is true, we're switching
227// (back?) to this tab and should restore any previous location bar state
228// (such as user editing) as well.
229- (void)updateToolbarWithContents:(content::WebContents*)tab
230               shouldRestoreState:(BOOL)shouldRestore;
231
232// Sets whether or not the current page in the frontmost tab is bookmarked.
233- (void)setStarredState:(BOOL)isStarred;
234
235// Happens when the zoom level is changed in the active tab, the active tab is
236// changed, or a new browser window or tab is created. |canShowBubble| denotes
237// whether it would be appropriate to show a zoom bubble or not.
238- (void)zoomChangedForActiveTab:(BOOL)canShowBubble;
239
240// Return the rect, in WebKit coordinates (flipped), of the window's grow box
241// in the coordinate system of the content area of the currently selected tab.
242- (NSRect)selectedTabGrowBoxRect;
243
244// Called to tell the selected tab to update its loading state.
245// |force| is set if the update is due to changing tabs, as opposed to
246// the page-load finishing.  See comment in reload_button.h.
247- (void)setIsLoading:(BOOL)isLoading force:(BOOL)force;
248
249// Brings this controller's window to the front.
250- (void)activate;
251
252// Make the location bar the first responder, if possible.
253- (void)focusLocationBar:(BOOL)selectAll;
254
255// Make the (currently-selected) tab contents the first responder, if possible.
256- (void)focusTabContents;
257
258// Returns the frame of the regular (non-fullscreened) window (even if the
259// window is currently in fullscreen mode).  The frame is returned in Cocoa
260// coordinates (origin in bottom-left).
261- (NSRect)regularWindowFrame;
262
263// Whether or not to show the avatar, which is either the incognito guy or the
264// user's profile avatar.
265- (BOOL)shouldShowAvatar;
266
267- (BOOL)isBookmarkBarVisible;
268
269// Returns YES if the bookmark bar is currently animating.
270- (BOOL)isBookmarkBarAnimating;
271
272- (BookmarkBarController*)bookmarkBarController;
273
274- (DevToolsController*)devToolsController;
275
276- (BOOL)isDownloadShelfVisible;
277
278// Lazily creates the download shelf in visible state if it doesn't exist yet.
279- (DownloadShelfController*)downloadShelf;
280
281// Retains the given FindBarCocoaController and adds its view to this
282// browser window.  Must only be called once per
283// BrowserWindowController.
284- (void)addFindBar:(FindBarCocoaController*)findBarCocoaController;
285
286// The user changed the theme.
287- (void)userChangedTheme;
288
289// Executes the command in the context of the current browser.
290// |command| is an integer value containing one of the constants defined in the
291// "chrome/app/chrome_command_ids.h" file.
292- (void)executeCommand:(int)command;
293
294// Consults the Command Registry to see if this |event| needs to be handled as
295// an extension command and returns YES if so (NO otherwise).
296- (BOOL)handledByExtensionCommand:(NSEvent*)event;
297
298// Delegate method for the status bubble to query its base frame.
299- (NSRect)statusBubbleBaseFrame;
300
301// Show the bookmark bubble (e.g. user just clicked on the STAR)
302- (void)showBookmarkBubbleForURL:(const GURL&)url
303               alreadyBookmarked:(BOOL)alreadyBookmarked;
304
305// Shows or hides the docked web inspector depending on |contents|'s state.
306- (void)updateDevToolsForContents:(content::WebContents*)contents;
307
308// Gets the current theme provider.
309- (ui::ThemeProvider*)themeProvider;
310
311// Gets the window style.
312- (ThemedWindowStyle)themedWindowStyle;
313
314// Returns the pattern phase for |alignment|. If the window does not have a tab
315// strip, the phase for THEME_PATTERN_ALIGN_WITH_FRAME is always returned.
316- (NSPoint)themePatternPhaseForAlignment:(ThemePatternAlignment)alignment;
317
318// Return the point to which a bubble window's arrow should point, in window
319// coordinates.
320- (NSPoint)bookmarkBubblePoint;
321
322// Called when the Add Search Engine dialog is closed.
323- (void)sheetDidEnd:(NSWindow*)sheet
324         returnCode:(NSInteger)code
325            context:(void*)context;
326
327// Called when the find bar visibility changes. This is used to update the
328// allowOverlappingViews state.
329- (void)onFindBarVisibilityChanged;
330
331// Called when an overlapped view is shown. This is used to update the
332// allowOverlappingViews state. Currently used for history overlay and
333// confirm bubble.
334- (void)onOverlappedViewShown;
335
336// Called when a history overlay is hidden. This is used to update the
337// allowOverlappingViews state. Currently used for history overlay and
338// confirm bubble.
339- (void)onOverlappedViewHidden;
340
341@end  // @interface BrowserWindowController
342
343
344// Methods having to do with the window type (normal/popup/app, and whether the
345// window has various features; fullscreen and presentation mode methods are
346// separate).
347@interface BrowserWindowController(WindowType)
348
349// Determines whether this controller's window supports a given feature (i.e.,
350// whether a given feature is or can be shown in the window).
351// TODO(viettrungluu): |feature| is really should be |Browser::Feature|, but I
352// don't want to include browser.h (and you can't forward declare enums).
353- (BOOL)supportsWindowFeature:(int)feature;
354
355// Called to check whether or not this window has a normal title bar (YES if it
356// does, NO otherwise). (E.g., normal browser windows do not, pop-ups do.)
357- (BOOL)hasTitleBar;
358
359// Called to check whether or not this window has a toolbar (YES if it does, NO
360// otherwise). (E.g., normal browser windows do, pop-ups do not.)
361- (BOOL)hasToolbar;
362
363// Called to check whether or not this window has a location bar (YES if it
364// does, NO otherwise). (E.g., normal browser windows do, pop-ups may or may
365// not.)
366- (BOOL)hasLocationBar;
367
368// Called to check whether or not this window can have bookmark bar (YES if it
369// does, NO otherwise). (E.g., normal browser windows may, pop-ups may not.)
370- (BOOL)supportsBookmarkBar;
371
372// Called to check if this controller's window is a tabbed window (e.g., not a
373// pop-up window). Returns YES if it is, NO otherwise.
374// Note: The |-has...| methods are usually preferred, so this method is largely
375// deprecated.
376- (BOOL)isTabbedWindow;
377
378@end  // @interface BrowserWindowController(WindowType)
379
380
381// Methods having to do with fullscreen and presentation mode.
382@interface BrowserWindowController(Fullscreen)
383
384// Toggles fullscreen mode.  Meant to be called by Lion windows when they enter
385// or exit Lion fullscreen mode.  Must not be called on Snow Leopard or earlier.
386- (void)handleLionToggleFullscreen;
387
388// Enters (or exits) fullscreen mode.  This method is safe to call on all OS
389// versions.
390- (void)enterFullscreen;
391- (void)exitFullscreen;
392
393// Updates the contents of the fullscreen exit bubble with |url| and
394// |bubbleType|.
395- (void)updateFullscreenExitBubbleURL:(const GURL&)url
396                           bubbleType:(FullscreenExitBubbleType)bubbleType;
397
398// Returns fullscreen state.  This method is safe to call on all OS versions.
399- (BOOL)isFullscreen;
400
401// Enters (or exits) presentation mode.  Also enters fullscreen mode if this
402// window is not already fullscreen.  This method is safe to call on all OS
403// versions.
404- (void)enterPresentationModeForURL:(const GURL&)url
405                         bubbleType:(FullscreenExitBubbleType)bubbleType;
406- (void)exitPresentationMode;
407
408// For simplified fullscreen: Enters fullscreen for a tab at a URL. The |url|
409// is guaranteed to be non-empty; see -enterFullscreen for the user-initiated
410// fullscreen mode. Called on Snow Leopard and Lion+.
411- (void)enterFullscreenForURL:(const GURL&)url
412                   bubbleType:(FullscreenExitBubbleType)bubbleType;
413
414// Returns presentation mode state.  This method is safe to call on all OS
415// versions.
416- (BOOL)inPresentationMode;
417
418// Resizes the fullscreen window to fit the screen it's currently on.  Called by
419// the PresentationModeController when there is a change in monitor placement or
420// resolution.
421- (void)resizeFullscreenWindow;
422
423// Gets or sets the fraction of the floating bar (presentation mode overlay)
424// that is shown.  0 is completely hidden, 1 is fully shown.
425- (CGFloat)floatingBarShownFraction;
426- (void)setFloatingBarShownFraction:(CGFloat)fraction;
427
428// Query/lock/release the requirement that the tab strip/toolbar/attached
429// bookmark bar bar cluster is visible (e.g., when one of its elements has
430// focus). This is required for the floating bar in presentation mode, but
431// should also be called when not in presentation mode; see the comments for
432// |barVisibilityLocks_| for more details. Double locks/releases by the same
433// owner are ignored. If |animate:| is YES, then an animation may be performed,
434// possibly after a small delay if |delay:| is YES. If |animate:| is NO,
435// |delay:| will be ignored. In the case of multiple calls, later calls have
436// precedence with the rule that |animate:NO| has precedence over |animate:YES|,
437// and |delay:NO| has precedence over |delay:YES|.
438- (BOOL)isBarVisibilityLockedForOwner:(id)owner;
439- (void)lockBarVisibilityForOwner:(id)owner
440                    withAnimation:(BOOL)animate
441                            delay:(BOOL)delay;
442- (void)releaseBarVisibilityForOwner:(id)owner
443                       withAnimation:(BOOL)animate
444                               delay:(BOOL)delay;
445
446// Returns YES if any of the views in the floating bar currently has focus.
447- (BOOL)floatingBarHasFocus;
448
449// Opens the tabpose window.
450- (void)openTabpose;
451
452@end  // @interface BrowserWindowController(Fullscreen)
453
454
455// Methods which are either only for testing, or only public for testing.
456@interface BrowserWindowController (TestingAPI)
457
458// Put the incognito badge or multi-profile avatar on the browser and adjust the
459// tab strip accordingly.
460- (void)installAvatar;
461
462// Allows us to initWithBrowser withOUT taking ownership of the browser.
463- (id)initWithBrowser:(Browser*)browser takeOwnership:(BOOL)ownIt;
464
465// Adjusts the window height by the given amount.  If the window spans from the
466// top of the current workspace to the bottom of the current workspace, the
467// height is not adjusted.  If growing the window by the requested amount would
468// size the window to be taller than the current workspace, the window height is
469// capped to be equal to the height of the current workspace.  If the window is
470// partially offscreen, its height is not adjusted at all.  This function
471// prefers to grow the window down, but will grow up if needed.  Calls to this
472// function should be followed by a call to |layoutSubviews|.
473// Returns if the window height was changed.
474- (BOOL)adjustWindowHeightBy:(CGFloat)deltaH;
475
476// Return an autoreleased NSWindow suitable for fullscreen use.
477- (NSWindow*)createFullscreenWindow;
478
479// Resets any saved state about window growth (due to showing the bookmark bar
480// or the download shelf), so that future shrinking will occur from the bottom.
481- (void)resetWindowGrowthState;
482
483// Computes by how far in each direction, horizontal and vertical, the
484// |source| rect doesn't fit into |target|.
485- (NSSize)overflowFrom:(NSRect)source
486                    to:(NSRect)target;
487
488// The fullscreen exit bubble controller, or nil if the bubble isn't showing.
489- (FullscreenExitBubbleController*)fullscreenExitBubbleController;
490
491// Gets the rect, in window base coordinates, that the omnibox popup should be
492// positioned relative to.
493- (NSRect)omniboxPopupAnchorRect;
494
495@end  // @interface BrowserWindowController (TestingAPI)
496
497
498#endif  // CHROME_BROWSER_UI_COCOA_BROWSER_WINDOW_CONTROLLER_H_
499