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 "base/basictypes.h"
9#include "base/memory/weak_ptr.h"
10#include "chrome/browser/ui/fullscreen/fullscreen_exit_bubble_type.h"
11#include "chrome/common/content_settings.h"
12#include "content/public/browser/notification_observer.h"
13#include "content/public/browser/notification_registrar.h"
14
15class Browser;
16class BrowserWindow;
17class GURL;
18class Profile;
19
20namespace content {
21class WebContents;
22}
23
24// There are two different kinds of fullscreen mode - "tab fullscreen" and
25// "browser fullscreen". "Tab fullscreen" refers to when a tab enters
26// fullscreen mode via the JS fullscreen API, and "browser fullscreen" refers
27// to the user putting the browser itself into fullscreen mode from the UI. The
28// difference is that tab fullscreen has implications for how the contents of
29// the tab render (eg: a video element may grow to consume the whole tab),
30// whereas browser fullscreen mode doesn't. Therefore if a user forces an exit
31// from tab fullscreen, we need to notify the tab so it can stop rendering in
32// its fullscreen mode.
33
34// This class implements fullscreen and mouselock behaviour.
35class FullscreenController : public content::NotificationObserver {
36 public:
37  explicit FullscreenController(Browser* browser);
38  virtual ~FullscreenController();
39
40  // Browser/User Fullscreen ///////////////////////////////////////////////////
41
42  // Returns true if the window is currently fullscreen and was initially
43  // transitioned to fullscreen by a browser (vs tab) mode transition.
44  bool IsFullscreenForBrowser() const;
45
46  void ToggleFullscreenMode();
47
48  // Tab/HTML Fullscreen ///////////////////////////////////////////////////////
49
50  // Returns true if fullscreen has been caused by a tab.
51  // The window may still be transitioning, and window_->IsFullscreen()
52  // may still return false.
53  bool IsFullscreenForTabOrPending() const;
54  bool IsFullscreenForTabOrPending(
55      const content::WebContents* web_contents) const;
56  // True if fullscreen was entered because of tab fullscreen (was not
57  // previously in browser fullscreen).
58  bool IsFullscreenCausedByTab() const;
59
60  void ToggleFullscreenModeForTab(content::WebContents* web_contents,
61                                  bool enter_fullscreen);
62
63  // Extension API implementation uses this method to toggle fullscreen mode.
64  // The extension's name is displayed in the full screen bubble UI to attribute
65  // the cause of the full screen state change.
66  void ToggleFullscreenModeWithExtension(const GURL& extension_url);
67
68  // Platform Fullscreen ///////////////////////////////////////////////////////
69
70  // Returns whether we are currently in a Metro snap view.
71  bool IsInMetroSnapMode();
72
73#if defined(OS_WIN)
74  // API that puts the window into a mode suitable for rendering when Chrome
75  // is rendered in a 20% screen-width Metro snap view on Windows 8.
76  void SetMetroSnapMode(bool enable);
77#endif
78
79#if defined(OS_MACOSX)
80  void ToggleFullscreenWithChrome();
81#endif
82
83  // Mouse Lock ////////////////////////////////////////////////////////////////
84
85  bool IsMouseLockRequested() const;
86  bool IsMouseLocked() const;
87
88  void RequestToLockMouse(content::WebContents* web_contents,
89                          bool user_gesture,
90                          bool last_unlocked_by_target);
91
92  // Callbacks /////////////////////////////////////////////////////////////////
93
94  // Called by Browser::TabDeactivated.
95  void OnTabDeactivated(content::WebContents* web_contents);
96
97  // Called by Browser::TabClosingAt.
98  void OnTabClosing(content::WebContents* web_contents);
99
100  // Called by Browser::WindowFullscreenStateChanged.
101  void WindowFullscreenStateChanged();
102
103  // Called by Browser::PreHandleKeyboardEvent.
104  bool HandleUserPressedEscape();
105
106  // Called by platform FullscreenExitBubble.
107  void ExitTabOrBrowserFullscreenToPreviousState();
108  void OnAcceptFullscreenPermission();
109  void OnDenyFullscreenPermission();
110
111  // Called by Browser::LostMouseLock.
112  void LostMouseLock();
113
114  // content::NotificationObserver:
115  virtual void Observe(int type,
116                       const content::NotificationSource& source,
117                       const content::NotificationDetails& details) OVERRIDE;
118
119  // Bubble Content ////////////////////////////////////////////////////////////
120
121  GURL GetFullscreenExitBubbleURL() const;
122  FullscreenExitBubbleType GetFullscreenExitBubbleType() const;
123
124 private:
125  enum MouseLockState {
126    MOUSELOCK_NOT_REQUESTED,
127    // The page requests to lock the mouse and the user hasn't responded to the
128    // request.
129    MOUSELOCK_REQUESTED,
130    // Mouse lock has been allowed by the user.
131    MOUSELOCK_ACCEPTED,
132    // Mouse lock has been silently accepted, no notification to user.
133    MOUSELOCK_ACCEPTED_SILENTLY
134  };
135
136  enum FullscreenInternalOption {
137    BROWSER,
138#if defined(OS_MACOSX)
139    BROWSER_WITH_CHROME,
140#endif
141    TAB
142  };
143
144  void UpdateNotificationRegistrations();
145
146  // Posts a task to call NotifyFullscreenChange.
147  void PostFullscreenChangeNotification(bool is_fullscreen);
148  // Sends a NOTIFICATION_FULLSCREEN_CHANGED notification.
149  void NotifyFullscreenChange(bool is_fullscreen);
150  // Notifies the tab that it has been forced out of fullscreen and mouse lock
151  // mode if necessary.
152  void NotifyTabOfExitIfNecessary();
153  void NotifyMouseLockChange();
154
155  void ToggleFullscreenModeInternal(FullscreenInternalOption option);
156  void EnterFullscreenModeInternal(FullscreenInternalOption option);
157  void ExitFullscreenModeInternal();
158  void SetFullscreenedTab(content::WebContents* tab);
159  void SetMouseLockTab(content::WebContents* tab);
160
161  // Make the current tab exit fullscreen mode or mouse lock if it is in it.
162  void ExitTabFullscreenOrMouseLockIfNecessary();
163  void UpdateFullscreenExitBubbleContent();
164
165  ContentSetting GetFullscreenSetting(const GURL& url) const;
166  ContentSetting GetMouseLockSetting(const GURL& url) const;
167
168  base::WeakPtrFactory<FullscreenController> ptr_factory_;
169
170  Browser* browser_;
171  BrowserWindow* window_;
172  Profile* profile_;
173
174  // If there is currently a tab in fullscreen mode (entered via
175  // webkitRequestFullScreen), this is its WebContents.
176  // Assign using SetFullscreenedTab().
177  content::WebContents* fullscreened_tab_;
178
179  // The URL of the extension which trigerred "browser fullscreen" mode.
180  GURL extension_caused_fullscreen_;
181
182  enum PriorFullscreenState {
183    STATE_INVALID,
184    STATE_NORMAL,
185    STATE_BROWSER_FULLSCREEN_NO_CHROME,
186#if defined(OS_MACOSX)
187    STATE_BROWSER_FULLSCREEN_WITH_CHROME,
188#endif
189  };
190  // The state before entering tab fullscreen mode via webkitRequestFullScreen.
191  // When not in tab fullscreen, it is STATE_INVALID.
192  PriorFullscreenState state_prior_to_tab_fullscreen_;
193  // True if tab fullscreen has been allowed, either by settings or by user
194  // clicking the allow button on the fullscreen infobar.
195  bool tab_fullscreen_accepted_;
196
197  // True if this controller has toggled into tab OR browser fullscreen.
198  bool toggled_into_fullscreen_;
199
200  // WebContents for current tab requesting or currently in mouse lock.
201  // Assign using SetMouseLockTab().
202  content::WebContents* mouse_lock_tab_;
203
204  MouseLockState mouse_lock_state_;
205
206  content::NotificationRegistrar registrar_;
207
208  // Used to verify that calls we expect to reenter by calling
209  // WindowFullscreenStateChanged do so.
210  bool reentrant_window_state_change_call_check_;
211
212  DISALLOW_COPY_AND_ASSIGN(FullscreenController);
213};
214
215#endif  // CHROME_BROWSER_UI_FULLSCREEN_FULLSCREEN_CONTROLLER_H_
216