Home | History | Annotate | Download | only in fullscreen
      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