1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef CHROME_BROWSER_UI_FULLSCREEN_FULLSCREEN_CONTROLLER_H_
6 #define CHROME_BROWSER_UI_FULLSCREEN_FULLSCREEN_CONTROLLER_H_
10 #include "base/basictypes.h"
11 #include "base/memory/weak_ptr.h"
12 #include "chrome/browser/ui/fullscreen/fullscreen_exit_bubble_type.h"
13 #include "components/content_settings/core/common/content_settings.h"
14 #include "content/public/browser/notification_observer.h"
15 #include "content/public/browser/notification_registrar.h"
26 // There are two different kinds of fullscreen mode - "tab fullscreen" and
27 // "browser fullscreen". "Tab fullscreen" refers to a renderer-initiated
28 // fullscreen mode (eg: from a Flash plugin or via the JS fullscreen API),
29 // whereas "browser fullscreen" refers to the user putting the browser itself
30 // into fullscreen mode from the UI. The difference is that tab fullscreen has
31 // implications for how the contents of the tab render (eg: a video element may
32 // grow to consume the whole tab), whereas browser fullscreen mode doesn't.
33 // Therefore if a user forces an exit from tab fullscreen, we need to notify the
34 // tab so it can stop rendering in its fullscreen mode.
36 // For Flash, FullscreenController will auto-accept all permission requests for
37 // fullscreen and/or mouse lock, since the assumption is that the plugin handles
40 // FullscreenWithinTab Note:
41 // All fullscreen widgets are displayed within the tab contents area, and
42 // FullscreenController will expand the browser window so that the tab contents
43 // area fills the entire screen. However, special behavior applies when a tab is
44 // being screen-captured. First, the browser window will not be
45 // fullscreened. This allows the user to retain control of their desktop to work
46 // in other browser tabs or applications while the fullscreen view is displayed
47 // on a remote screen. Second, FullscreenController will auto-resize fullscreen
48 // widgets to that of the capture video resolution when they are hidden (e.g.,
49 // when a user has switched to another tab). This is both a performance and
50 // quality improvement since scaling and letterboxing steps can be skipped in
51 // the capture pipeline.
53 // This class implements fullscreen and mouselock behaviour.
54 class FullscreenController : public content::NotificationObserver {
56 explicit FullscreenController(Browser* browser);
57 virtual ~FullscreenController();
59 // Browser/User Fullscreen ///////////////////////////////////////////////////
61 // Returns true if the window is currently fullscreen and was initially
62 // transitioned to fullscreen by a browser (i.e., not tab-initiated) mode
64 bool IsFullscreenForBrowser() const;
66 void ToggleBrowserFullscreenMode();
68 // Extension API implementation uses this method to toggle fullscreen mode.
69 // The extension's name is displayed in the full screen bubble UI to attribute
70 // the cause of the full screen state change.
71 void ToggleBrowserFullscreenModeWithExtension(const GURL& extension_url);
73 // Tab/HTML/Flash Fullscreen /////////////////////////////////////////////////
75 // Returns true if the browser window has/will fullscreen because of
76 // tab-initiated fullscreen. The window may still be transitioning, and
77 // BrowserWindow::IsFullscreen() may still return false.
78 bool IsWindowFullscreenForTabOrPending() const;
80 // Returns true if the tab is/will be in fullscreen mode. Note: This does NOT
81 // indicate whether the browser window is/will be fullscreened as well. See
82 // 'FullscreenWithinTab Note'.
83 bool IsFullscreenForTabOrPending(
84 const content::WebContents* web_contents) const;
86 // True if fullscreen was entered because of tab fullscreen (was not
87 // previously in user-initiated fullscreen).
88 bool IsFullscreenCausedByTab() const;
90 // Enter or leave tab-initiated fullscreen mode. FullscreenController will
91 // decide whether to also fullscreen the browser window. See
92 // 'FullscreenWithinTab Note'.
93 void ToggleFullscreenModeForTab(content::WebContents* web_contents,
94 bool enter_fullscreen);
96 // Platform Fullscreen ///////////////////////////////////////////////////////
98 // Returns whether we are currently in a Metro snap view.
99 bool IsInMetroSnapMode();
102 // API that puts the window into a mode suitable for rendering when Chrome
103 // is rendered in a 20% screen-width Metro snap view on Windows 8.
104 void SetMetroSnapMode(bool enable);
107 #if defined(OS_MACOSX)
108 void ToggleBrowserFullscreenWithChrome();
111 // Mouse Lock ////////////////////////////////////////////////////////////////
113 bool IsMouseLockRequested() const;
114 bool IsMouseLocked() const;
116 void RequestToLockMouse(content::WebContents* web_contents,
118 bool last_unlocked_by_target);
120 // Callbacks /////////////////////////////////////////////////////////////////
122 // Called by Browser::TabDeactivated.
123 void OnTabDeactivated(content::WebContents* web_contents);
125 // Called by Browser::ActiveTabChanged.
126 void OnTabDetachedFromView(content::WebContents* web_contents);
128 // Called by Browser::TabClosingAt.
129 void OnTabClosing(content::WebContents* web_contents);
131 // Called by Browser::WindowFullscreenStateChanged.
132 void WindowFullscreenStateChanged();
134 // Called by Browser::PreHandleKeyboardEvent.
135 bool HandleUserPressedEscape();
137 // Called by platform FullscreenExitBubble.
138 void ExitTabOrBrowserFullscreenToPreviousState();
139 void OnAcceptFullscreenPermission();
140 void OnDenyFullscreenPermission();
142 // Called by Browser::LostMouseLock.
143 void LostMouseLock();
145 // content::NotificationObserver:
146 virtual void Observe(int type,
147 const content::NotificationSource& source,
148 const content::NotificationDetails& details) OVERRIDE;
150 // Bubble Content ////////////////////////////////////////////////////////////
152 GURL GetFullscreenExitBubbleURL() const;
153 FullscreenExitBubbleType GetFullscreenExitBubbleType() const;
156 friend class FullscreenControllerTest;
158 enum MouseLockState {
159 MOUSELOCK_NOT_REQUESTED,
160 // The page requests to lock the mouse and the user hasn't responded to the
163 // Mouse lock has been allowed by the user.
165 // Mouse lock has been silently accepted, no notification to user.
166 MOUSELOCK_ACCEPTED_SILENTLY
169 enum FullscreenInternalOption {
171 #if defined(OS_MACOSX)
177 void UpdateNotificationRegistrations();
179 // Posts a task to call NotifyFullscreenChange.
180 void PostFullscreenChangeNotification(bool is_fullscreen);
181 // Sends a NOTIFICATION_FULLSCREEN_CHANGED notification.
182 void NotifyFullscreenChange(bool is_fullscreen);
183 // Notifies the tab that it has been forced out of fullscreen and mouse lock
184 // mode if necessary.
185 void NotifyTabOfExitIfNecessary();
186 void NotifyMouseLockChange();
188 void ToggleFullscreenModeInternal(FullscreenInternalOption option);
189 void EnterFullscreenModeInternal(FullscreenInternalOption option);
190 void ExitFullscreenModeInternal();
191 void SetFullscreenedTab(content::WebContents* tab);
192 void SetMouseLockTab(content::WebContents* tab);
194 // Make the current tab exit fullscreen mode or mouse lock if it is in it.
195 void ExitTabFullscreenOrMouseLockIfNecessary();
196 void UpdateFullscreenExitBubbleContent();
198 ContentSetting GetFullscreenSetting(const GURL& url) const;
199 ContentSetting GetMouseLockSetting(const GURL& url) const;
201 bool IsPrivilegedFullscreenForTab() const;
202 void SetPrivilegedFullscreenForTesting(bool is_privileged);
203 // Returns true if |web_contents| was toggled into/out of fullscreen mode as a
204 // screen-captured tab. See 'FullscreenWithinTab Note'.
205 bool MaybeToggleFullscreenForCapturedTab(content::WebContents* web_contents,
206 bool enter_fullscreen);
207 // Returns true if |web_contents| is in fullscreen mode as a screen-captured
208 // tab. See 'FullscreenWithinTab Note'.
209 bool IsFullscreenForCapturedTab(const content::WebContents* web_contents)
213 Browser* const browser_;
214 BrowserWindow* const window_;
215 Profile* const profile_;
217 // If there is currently a tab in fullscreen mode (entered via
218 // webkitRequestFullScreen), this is its WebContents.
219 // Assign using SetFullscreenedTab().
220 content::WebContents* fullscreened_tab_;
222 // The URL of the extension which trigerred "browser fullscreen" mode.
223 GURL extension_caused_fullscreen_;
225 enum PriorFullscreenState {
228 STATE_BROWSER_FULLSCREEN_NO_CHROME,
229 #if defined(OS_MACOSX)
230 STATE_BROWSER_FULLSCREEN_WITH_CHROME,
233 // The state before entering tab fullscreen mode via webkitRequestFullScreen.
234 // When not in tab fullscreen, it is STATE_INVALID.
235 PriorFullscreenState state_prior_to_tab_fullscreen_;
236 // True if tab fullscreen has been allowed, either by settings or by user
237 // clicking the allow button on the fullscreen infobar.
238 bool tab_fullscreen_accepted_;
240 // True if this controller has toggled into tab OR browser fullscreen.
241 bool toggled_into_fullscreen_;
243 // WebContents for current tab requesting or currently in mouse lock.
244 // Assign using SetMouseLockTab().
245 content::WebContents* mouse_lock_tab_;
247 MouseLockState mouse_lock_state_;
249 content::NotificationRegistrar registrar_;
251 // Used to verify that calls we expect to reenter by calling
252 // WindowFullscreenStateChanged do so.
253 bool reentrant_window_state_change_call_check_;
255 // Used in testing to confirm proper behavior for specific, privileged
257 bool is_privileged_fullscreen_for_testing_;
259 base::WeakPtrFactory<FullscreenController> ptr_factory_;
261 DISALLOW_COPY_AND_ASSIGN(FullscreenController);
264 #endif // CHROME_BROWSER_UI_FULLSCREEN_FULLSCREEN_CONTROLLER_H_