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_FULLSCREEN_FULLSCREEN_CONTROLLER_H_ 6 #define CHROME_BROWSER_UI_FULLSCREEN_FULLSCREEN_CONTROLLER_H_ 7 8 #include <set> 9 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 "chrome/common/content_settings.h" 14 #include "content/public/browser/notification_observer.h" 15 #include "content/public/browser/notification_registrar.h" 16 17 class Browser; 18 class BrowserWindow; 19 class GURL; 20 class Profile; 21 22 namespace content { 23 class WebContents; 24 } 25 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. 35 // 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 38 // this for us. 39 // 40 // FullscreenWithinTab Note: 41 // When the browser is configured as such, all fullscreen widgets are displayed 42 // within the tab contents area, and FullscreenController will expand the 43 // browser window so that the tab contents area fills the entire 44 // screen. However, special behavior applies when a tab is being 45 // screen-captured. First, the browser window will not be fullscreened. This 46 // allows the user to retain control of their desktop to work in other browser 47 // tabs or applications while the fullscreen view is displayed on a remote 48 // screen. Second, FullscreenController will auto-resize fullscreen widgets to 49 // that of the capture video resolution when they are hidden (e.g., when a user 50 // has switched to another tab). This is both a performance and quality 51 // improvement since scaling and letterboxing steps can be skipped in the 52 // capture pipeline. 53 54 // This class implements fullscreen and mouselock behaviour. 55 class FullscreenController : public content::NotificationObserver { 56 public: 57 explicit FullscreenController(Browser* browser); 58 virtual ~FullscreenController(); 59 60 // Browser/User Fullscreen /////////////////////////////////////////////////// 61 62 // Returns true if the window is currently fullscreen and was initially 63 // transitioned to fullscreen by a browser (i.e., not tab-initiated) mode 64 // transition. 65 bool IsFullscreenForBrowser() const; 66 67 void ToggleBrowserFullscreenMode(); 68 69 // Extension API implementation uses this method to toggle fullscreen mode. 70 // The extension's name is displayed in the full screen bubble UI to attribute 71 // the cause of the full screen state change. 72 void ToggleBrowserFullscreenModeWithExtension(const GURL& extension_url); 73 74 // Tab/HTML/Flash Fullscreen ///////////////////////////////////////////////// 75 76 // Returns true if the browser window has/will fullscreen because of 77 // tab-initiated fullscreen. The window may still be transitioning, and 78 // BrowserWindow::IsFullscreen() may still return false. 79 bool IsWindowFullscreenForTabOrPending() const; 80 81 // Returns true if the tab is/will be in fullscreen mode. Note: This does NOT 82 // indicate whether the browser window is/will be fullscreened as well. See 83 // 'FullscreenWithinTab Note'. 84 bool IsFullscreenForTabOrPending( 85 const content::WebContents* web_contents) const; 86 87 // True if fullscreen was entered because of tab fullscreen (was not 88 // previously in user-initiated fullscreen). 89 bool IsFullscreenCausedByTab() const; 90 91 // Enter or leave tab-initiated fullscreen mode. FullscreenController will 92 // decide whether to also fullscreen the browser window. See 93 // 'FullscreenWithinTab Note'. 94 void ToggleFullscreenModeForTab(content::WebContents* web_contents, 95 bool enter_fullscreen); 96 97 // Platform Fullscreen /////////////////////////////////////////////////////// 98 99 // Returns whether we are currently in a Metro snap view. 100 bool IsInMetroSnapMode(); 101 102 #if defined(OS_WIN) 103 // API that puts the window into a mode suitable for rendering when Chrome 104 // is rendered in a 20% screen-width Metro snap view on Windows 8. 105 void SetMetroSnapMode(bool enable); 106 #endif 107 108 #if defined(OS_MACOSX) 109 void ToggleBrowserFullscreenWithChrome(); 110 #endif 111 112 // Mouse Lock //////////////////////////////////////////////////////////////// 113 114 bool IsMouseLockRequested() const; 115 bool IsMouseLocked() const; 116 117 void RequestToLockMouse(content::WebContents* web_contents, 118 bool user_gesture, 119 bool last_unlocked_by_target); 120 121 // Callbacks ///////////////////////////////////////////////////////////////// 122 123 // Called by Browser::TabDeactivated. 124 void OnTabDeactivated(content::WebContents* web_contents); 125 126 // Called by Browser::ActiveTabChanged. 127 void OnTabDetachedFromView(content::WebContents* web_contents); 128 129 // Called by Browser::TabClosingAt. 130 void OnTabClosing(content::WebContents* web_contents); 131 132 // Called by Browser::WindowFullscreenStateChanged. 133 void WindowFullscreenStateChanged(); 134 135 // Called by Browser::PreHandleKeyboardEvent. 136 bool HandleUserPressedEscape(); 137 138 // Called by platform FullscreenExitBubble. 139 void ExitTabOrBrowserFullscreenToPreviousState(); 140 void OnAcceptFullscreenPermission(); 141 void OnDenyFullscreenPermission(); 142 143 // Called by Browser::LostMouseLock. 144 void LostMouseLock(); 145 146 // content::NotificationObserver: 147 virtual void Observe(int type, 148 const content::NotificationSource& source, 149 const content::NotificationDetails& details) OVERRIDE; 150 151 // Bubble Content //////////////////////////////////////////////////////////// 152 153 GURL GetFullscreenExitBubbleURL() const; 154 FullscreenExitBubbleType GetFullscreenExitBubbleType() const; 155 156 private: 157 friend class FullscreenControllerTest; 158 159 enum MouseLockState { 160 MOUSELOCK_NOT_REQUESTED, 161 // The page requests to lock the mouse and the user hasn't responded to the 162 // request. 163 MOUSELOCK_REQUESTED, 164 // Mouse lock has been allowed by the user. 165 MOUSELOCK_ACCEPTED, 166 // Mouse lock has been silently accepted, no notification to user. 167 MOUSELOCK_ACCEPTED_SILENTLY 168 }; 169 170 enum FullscreenInternalOption { 171 BROWSER, 172 #if defined(OS_MACOSX) 173 BROWSER_WITH_CHROME, 174 #endif 175 TAB 176 }; 177 178 void UpdateNotificationRegistrations(); 179 180 // Posts a task to call NotifyFullscreenChange. 181 void PostFullscreenChangeNotification(bool is_fullscreen); 182 // Sends a NOTIFICATION_FULLSCREEN_CHANGED notification. 183 void NotifyFullscreenChange(bool is_fullscreen); 184 // Notifies the tab that it has been forced out of fullscreen and mouse lock 185 // mode if necessary. 186 void NotifyTabOfExitIfNecessary(); 187 void NotifyMouseLockChange(); 188 189 void ToggleFullscreenModeInternal(FullscreenInternalOption option); 190 void EnterFullscreenModeInternal(FullscreenInternalOption option); 191 void ExitFullscreenModeInternal(); 192 void SetFullscreenedTab(content::WebContents* tab); 193 void SetMouseLockTab(content::WebContents* tab); 194 195 // Make the current tab exit fullscreen mode or mouse lock if it is in it. 196 void ExitTabFullscreenOrMouseLockIfNecessary(); 197 void UpdateFullscreenExitBubbleContent(); 198 199 ContentSetting GetFullscreenSetting(const GURL& url) const; 200 ContentSetting GetMouseLockSetting(const GURL& url) const; 201 202 bool IsPrivilegedFullscreenForTab() const; 203 void SetPrivilegedFullscreenForTesting(bool is_privileged); 204 // Returns true if fullscreen-within-tab has been enabled for the 205 // |browser_|. See 'FullscreenWithinTab Note'. 206 bool IsFullscreenWithinTabPossible() const; 207 // Returns true if |web_contents| was toggled into/out of fullscreen mode as a 208 // screen-captured tab. See 'FullscreenWithinTab Note'. 209 bool MaybeToggleFullscreenForCapturedTab(content::WebContents* web_contents, 210 bool enter_fullscreen); 211 // Returns true if |web_contents| is in fullscreen mode as a screen-captured 212 // tab. See 'FullscreenWithinTab Note'. 213 bool IsFullscreenForCapturedTab(const content::WebContents* web_contents) 214 const; 215 void UnlockMouse(); 216 217 Browser* const browser_; 218 BrowserWindow* const window_; 219 Profile* const profile_; 220 221 // If there is currently a tab in fullscreen mode (entered via 222 // webkitRequestFullScreen), this is its WebContents. 223 // Assign using SetFullscreenedTab(). 224 content::WebContents* fullscreened_tab_; 225 226 // The URL of the extension which trigerred "browser fullscreen" mode. 227 GURL extension_caused_fullscreen_; 228 229 enum PriorFullscreenState { 230 STATE_INVALID, 231 STATE_NORMAL, 232 STATE_BROWSER_FULLSCREEN_NO_CHROME, 233 #if defined(OS_MACOSX) 234 STATE_BROWSER_FULLSCREEN_WITH_CHROME, 235 #endif 236 }; 237 // The state before entering tab fullscreen mode via webkitRequestFullScreen. 238 // When not in tab fullscreen, it is STATE_INVALID. 239 PriorFullscreenState state_prior_to_tab_fullscreen_; 240 // True if tab fullscreen has been allowed, either by settings or by user 241 // clicking the allow button on the fullscreen infobar. 242 bool tab_fullscreen_accepted_; 243 244 // True if this controller has toggled into tab OR browser fullscreen. 245 bool toggled_into_fullscreen_; 246 247 // WebContents for current tab requesting or currently in mouse lock. 248 // Assign using SetMouseLockTab(). 249 content::WebContents* mouse_lock_tab_; 250 251 MouseLockState mouse_lock_state_; 252 253 content::NotificationRegistrar registrar_; 254 255 // Used to verify that calls we expect to reenter by calling 256 // WindowFullscreenStateChanged do so. 257 bool reentrant_window_state_change_call_check_; 258 259 // Used in testing to confirm proper behavior for specific, privileged 260 // fullscreen cases. 261 bool is_privileged_fullscreen_for_testing_; 262 263 base::WeakPtrFactory<FullscreenController> ptr_factory_; 264 265 DISALLOW_COPY_AND_ASSIGN(FullscreenController); 266 }; 267 268 #endif // CHROME_BROWSER_UI_FULLSCREEN_FULLSCREEN_CONTROLLER_H_ 269