summaryrefslogtreecommitdiffstats
path: root/chrome/browser/ui/fullscreen/fullscreen_controller.h
blob: f9fff193c79d4d7c029b88ac5dedb0032d0c0e4a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_UI_FULLSCREEN_FULLSCREEN_CONTROLLER_H_
#define CHROME_BROWSER_UI_FULLSCREEN_FULLSCREEN_CONTROLLER_H_

#include <set>

#include "base/basictypes.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/ui/fullscreen/fullscreen_exit_bubble_type.h"
#include "chrome/common/content_settings.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"

class Browser;
class BrowserWindow;
class GURL;
class Profile;

namespace content {
class WebContents;
}

// There are two different kinds of fullscreen mode - "tab fullscreen" and
// "browser fullscreen". "Tab fullscreen" refers to a renderer-initiated
// fullscreen mode (eg: from a Flash plugin or via the JS fullscreen API),
// whereas "browser fullscreen" refers to the user putting the browser itself
// into fullscreen mode from the UI. The difference is that tab fullscreen has
// implications for how the contents of the tab render (eg: a video element may
// grow to consume the whole tab), whereas browser fullscreen mode doesn't.
// Therefore if a user forces an exit from tab fullscreen, we need to notify the
// tab so it can stop rendering in its fullscreen mode.
//
// For Flash, FullscreenController will auto-accept all permission requests for
// fullscreen and/or mouse lock, since the assumption is that the plugin handles
// this for us.
//
// FullscreenWithinTab Note:
// All fullscreen widgets are displayed within the tab contents area, and
// FullscreenController will expand the browser window so that the tab contents
// area fills the entire screen. However, special behavior applies when a tab is
// being screen-captured. First, the browser window will not be
// fullscreened. This allows the user to retain control of their desktop to work
// in other browser tabs or applications while the fullscreen view is displayed
// on a remote screen. Second, FullscreenController will auto-resize fullscreen
// widgets to that of the capture video resolution when they are hidden (e.g.,
// when a user has switched to another tab). This is both a performance and
// quality improvement since scaling and letterboxing steps can be skipped in
// the capture pipeline.

// This class implements fullscreen and mouselock behaviour.
class FullscreenController : public content::NotificationObserver {
 public:
  explicit FullscreenController(Browser* browser);
  virtual ~FullscreenController();

  // Browser/User Fullscreen ///////////////////////////////////////////////////

  // Returns true if the window is currently fullscreen and was initially
  // transitioned to fullscreen by a browser (i.e., not tab-initiated) mode
  // transition.
  bool IsFullscreenForBrowser() const;

  void ToggleBrowserFullscreenMode();

  // Extension API implementation uses this method to toggle fullscreen mode.
  // The extension's name is displayed in the full screen bubble UI to attribute
  // the cause of the full screen state change.
  void ToggleBrowserFullscreenModeWithExtension(const GURL& extension_url);

  // Tab/HTML/Flash Fullscreen /////////////////////////////////////////////////

  // Returns true if the browser window has/will fullscreen because of
  // tab-initiated fullscreen. The window may still be transitioning, and
  // BrowserWindow::IsFullscreen() may still return false.
  bool IsWindowFullscreenForTabOrPending() const;

  // Returns true if the tab is/will be in fullscreen mode. Note: This does NOT
  // indicate whether the browser window is/will be fullscreened as well. See
  // 'FullscreenWithinTab Note'.
  bool IsFullscreenForTabOrPending(
      const content::WebContents* web_contents) const;

  // True if fullscreen was entered because of tab fullscreen (was not
  // previously in user-initiated fullscreen).
  bool IsFullscreenCausedByTab() const;

  // Enter or leave tab-initiated fullscreen mode. FullscreenController will
  // decide whether to also fullscreen the browser window. See
  // 'FullscreenWithinTab Note'.
  void ToggleFullscreenModeForTab(content::WebContents* web_contents,
                                  bool enter_fullscreen);

  // Platform Fullscreen ///////////////////////////////////////////////////////

  // Returns whether we are currently in a Metro snap view.
  bool IsInMetroSnapMode();

#if defined(OS_WIN)
  // API that puts the window into a mode suitable for rendering when Chrome
  // is rendered in a 20% screen-width Metro snap view on Windows 8.
  void SetMetroSnapMode(bool enable);
#endif

#if defined(OS_MACOSX)
  void ToggleBrowserFullscreenWithChrome();
#endif

  // Mouse Lock ////////////////////////////////////////////////////////////////

  bool IsMouseLockRequested() const;
  bool IsMouseLocked() const;

  void RequestToLockMouse(content::WebContents* web_contents,
                          bool user_gesture,
                          bool last_unlocked_by_target);

  // Callbacks /////////////////////////////////////////////////////////////////

  // Called by Browser::TabDeactivated.
  void OnTabDeactivated(content::WebContents* web_contents);

  // Called by Browser::ActiveTabChanged.
  void OnTabDetachedFromView(content::WebContents* web_contents);

  // Called by Browser::TabClosingAt.
  void OnTabClosing(content::WebContents* web_contents);

  // Called by Browser::WindowFullscreenStateChanged.
  void WindowFullscreenStateChanged();

  // Called by Browser::PreHandleKeyboardEvent.
  bool HandleUserPressedEscape();

  // Called by platform FullscreenExitBubble.
  void ExitTabOrBrowserFullscreenToPreviousState();
  void OnAcceptFullscreenPermission();
  void OnDenyFullscreenPermission();

  // Called by Browser::LostMouseLock.
  void LostMouseLock();

  // content::NotificationObserver:
  virtual void Observe(int type,
                       const content::NotificationSource& source,
                       const content::NotificationDetails& details) OVERRIDE;

  // Bubble Content ////////////////////////////////////////////////////////////

  GURL GetFullscreenExitBubbleURL() const;
  FullscreenExitBubbleType GetFullscreenExitBubbleType() const;

 private:
  friend class FullscreenControllerTest;

  enum MouseLockState {
    MOUSELOCK_NOT_REQUESTED,
    // The page requests to lock the mouse and the user hasn't responded to the
    // request.
    MOUSELOCK_REQUESTED,
    // Mouse lock has been allowed by the user.
    MOUSELOCK_ACCEPTED,
    // Mouse lock has been silently accepted, no notification to user.
    MOUSELOCK_ACCEPTED_SILENTLY
  };

  enum FullscreenInternalOption {
    BROWSER,
#if defined(OS_MACOSX)
    BROWSER_WITH_CHROME,
#endif
    TAB
  };

  void UpdateNotificationRegistrations();

  // Posts a task to call NotifyFullscreenChange.
  void PostFullscreenChangeNotification(bool is_fullscreen);
  // Sends a NOTIFICATION_FULLSCREEN_CHANGED notification.
  void NotifyFullscreenChange(bool is_fullscreen);
  // Notifies the tab that it has been forced out of fullscreen and mouse lock
  // mode if necessary.
  void NotifyTabOfExitIfNecessary();
  void NotifyMouseLockChange();

  void ToggleFullscreenModeInternal(FullscreenInternalOption option);
  void EnterFullscreenModeInternal(FullscreenInternalOption option);
  void ExitFullscreenModeInternal();
  void SetFullscreenedTab(content::WebContents* tab);
  void SetMouseLockTab(content::WebContents* tab);

  // Make the current tab exit fullscreen mode or mouse lock if it is in it.
  void ExitTabFullscreenOrMouseLockIfNecessary();
  void UpdateFullscreenExitBubbleContent();

  ContentSetting GetFullscreenSetting(const GURL& url) const;
  ContentSetting GetMouseLockSetting(const GURL& url) const;

  bool IsPrivilegedFullscreenForTab() const;
  void SetPrivilegedFullscreenForTesting(bool is_privileged);
  // Returns true if |web_contents| was toggled into/out of fullscreen mode as a
  // screen-captured tab. See 'FullscreenWithinTab Note'.
  bool MaybeToggleFullscreenForCapturedTab(content::WebContents* web_contents,
                                           bool enter_fullscreen);
  // Returns true if |web_contents| is in fullscreen mode as a screen-captured
  // tab. See 'FullscreenWithinTab Note'.
  bool IsFullscreenForCapturedTab(const content::WebContents* web_contents)
      const;
  void UnlockMouse();

  Browser* const browser_;
  BrowserWindow* const window_;
  Profile* const profile_;

  // If there is currently a tab in fullscreen mode (entered via
  // webkitRequestFullScreen), this is its WebContents.
  // Assign using SetFullscreenedTab().
  content::WebContents* fullscreened_tab_;

  // The URL of the extension which trigerred "browser fullscreen" mode.
  GURL extension_caused_fullscreen_;

  enum PriorFullscreenState {
    STATE_INVALID,
    STATE_NORMAL,
    STATE_BROWSER_FULLSCREEN_NO_CHROME,
#if defined(OS_MACOSX)
    STATE_BROWSER_FULLSCREEN_WITH_CHROME,
#endif
  };
  // The state before entering tab fullscreen mode via webkitRequestFullScreen.
  // When not in tab fullscreen, it is STATE_INVALID.
  PriorFullscreenState state_prior_to_tab_fullscreen_;
  // True if tab fullscreen has been allowed, either by settings or by user
  // clicking the allow button on the fullscreen infobar.
  bool tab_fullscreen_accepted_;

  // True if this controller has toggled into tab OR browser fullscreen.
  bool toggled_into_fullscreen_;

  // WebContents for current tab requesting or currently in mouse lock.
  // Assign using SetMouseLockTab().
  content::WebContents* mouse_lock_tab_;

  MouseLockState mouse_lock_state_;

  content::NotificationRegistrar registrar_;

  // Used to verify that calls we expect to reenter by calling
  // WindowFullscreenStateChanged do so.
  bool reentrant_window_state_change_call_check_;

  // Used in testing to confirm proper behavior for specific, privileged
  // fullscreen cases.
  bool is_privileged_fullscreen_for_testing_;

  base::WeakPtrFactory<FullscreenController> ptr_factory_;

  DISALLOW_COPY_AND_ASSIGN(FullscreenController);
};

#endif  // CHROME_BROWSER_UI_FULLSCREEN_FULLSCREEN_CONTROLLER_H_