• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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