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 265 266 267 268 269 270
|
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_UI_EXCLUSIVE_ACCESS_FULLSCREEN_CONTROLLER_H_
#define CHROME_BROWSER_UI_EXCLUSIVE_ACCESS_FULLSCREEN_CONTROLLER_H_
#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/task/cancelable_task_tracker.h"
#include "base/time/time.h"
#include "chrome/browser/ui/exclusive_access/exclusive_access_controller_base.h"
#include "chrome/browser/ui/exclusive_access/fullscreen_observer.h"
#include "components/content_settings/core/common/content_settings.h"
#include "content/public/browser/fullscreen_types.h"
#include "ui/display/types/display_constants.h"
#include "url/origin.h"
class PopunderPreventer;
namespace content {
class WebContents;
class RenderFrameHost;
} // namespace content
// There are two different kinds of fullscreen mode - "tab fullscreen" and
// "browser fullscreen". "Tab fullscreen" refers to a renderer-initiated
// fullscreen mode (eg: from an extension 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.
//
// 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 screen-captured or the
// content fullscreen feature is active.
//
// 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 behaviour.
class FullscreenController : public ExclusiveAccessControllerBase {
public:
explicit FullscreenController(ExclusiveAccessManager* manager);
FullscreenController(const FullscreenController&) = delete;
FullscreenController& operator=(const FullscreenController&) = delete;
~FullscreenController() override;
void AddObserver(FullscreenObserver* observer);
void RemoveObserver(FullscreenObserver* observer);
static int64_t GetDisplayId(const content::WebContents& web_contents);
// 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;
// Toggle in or out of browser fullscreen mode. Certain windows will block
// `user_initiated` requests; see `CanUserEnterFullscreen()` for details.
void ToggleBrowserFullscreenMode(bool user_initiated);
// 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/Extension 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 browser window is fullscreen because of extension
// initiated fullscreen.
bool IsExtensionFullscreenOrPending() const;
// Returns true if controller has entered fullscreen mode.
bool IsControllerInitiatedFullscreen() const;
// Returns true if the site has entered fullscreen.
bool IsTabFullscreen() const;
// Returns fullscreen state information about the given `web_contents`.
content::FullscreenState GetFullscreenState(
const content::WebContents* web_contents) const;
// Returns true if |web_contents| is in fullscreen mode as a screen-captured
// tab. See 'FullscreenWithinTab Note'.
bool IsFullscreenWithinTab(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;
// Returns whether entering fullscreen with |EnterFullscreenModeForTab()| is
// allowed.
bool CanEnterFullscreenModeForTab(content::RenderFrameHost* requesting_frame);
// Enter tab-initiated fullscreen mode. FullscreenController decides whether
// to also fullscreen the browser window. See 'FullscreenWithinTab Note'.
// `requesting_frame` is the specific content frame requesting fullscreen.
// Sites with the Window Management permission may request fullscreen on a
// particular display. In that case, `display_id` is the display's id;
// otherwise, display::kInvalidDisplayId indicates no display is specified.
// `CanEnterFullscreenModeForTab()` must return true on entry.
void EnterFullscreenModeForTab(
content::RenderFrameHost* requesting_frame,
const int64_t display_id = display::kInvalidDisplayId);
// Leave a tab-initiated fullscreen mode.
// |web_contents| represents the tab that requests to no longer be fullscreen.
void ExitFullscreenModeForTab(content::WebContents* web_contents);
base::WeakPtr<FullscreenController> GetWeakPtr() {
return ptr_factory_.GetWeakPtr();
}
// Called when fullscreen tabs open popups, to track potential popunders.
void FullscreenTabOpeningPopup(content::WebContents* opener,
content::WebContents* popup);
// Platform Fullscreen ///////////////////////////////////////////////////////
// Override from ExclusiveAccessControllerBase.
void OnTabDeactivated(content::WebContents* web_contents) override;
void OnTabDetachedFromView(content::WebContents* web_contents) override;
void OnTabClosing(content::WebContents* web_contents) override;
bool HandleUserPressedEscape() override;
void HandleUserHeldEscape() override;
void HandleUserReleasedEscapeEarly() override;
bool RequiresPressAndHoldEscToExit() const override;
void ExitExclusiveAccessToPreviousState() override;
url::Origin GetOriginForExclusiveAccessBubble() const override;
void ExitExclusiveAccessIfNecessary() override;
// Callbacks /////////////////////////////////////////////////////////////////
// Called by Browser::WindowFullscreenStateChanged. This is called immediately
// as fullscreen mode is toggled.
void WindowFullscreenStateChanged();
// Called by BrowserView::FullscreenStateChanged. This is called after
// fullscreen mode is toggled and after the transition animation completes.
void FullscreenTransitionCompleted();
// Runs the given closure unless a fullscreen transition is currently in
// progress. If a transition is in progress, the execution of the closure is
// deferred and run after the transition is complete.
void RunOrDeferUntilTransitionIsComplete(base::OnceClosure callback);
void set_is_tab_fullscreen_for_testing(bool is_tab_fullscreen) {
is_tab_fullscreen_for_testing_ = is_tab_fullscreen;
}
private:
friend class ExclusiveAccessTest;
enum FullscreenInternalOption { BROWSER, TAB };
// Posts a task to notify observers of the fullscreen state change.
void PostFullscreenChangeNotification();
void NotifyFullscreenChange();
// Notifies the tab that it has been forced out of fullscreen mode if
// necessary.
void NotifyTabExclusiveAccessLost() override;
void ToggleFullscreenModeInternal(FullscreenInternalOption option,
content::RenderFrameHost* requesting_frame,
const int64_t display_id,
bool user_initiated);
void EnterFullscreenModeInternal(FullscreenInternalOption option,
content::RenderFrameHost* requesting_frame,
int64_t display_id);
void ExitFullscreenModeInternal();
// Returns true if |web_contents| was toggled into/out of fullscreen mode as a
// screen-captured tab or as a content-fullscreen tab.
// See 'FullscreenWithinTab Note'.
bool MaybeToggleFullscreenWithinTab(content::WebContents* web_contents,
bool enter_fullscreen);
// Helper methods that should be used in a TAB context.
url::Origin GetRequestingOrigin() const;
url::Origin GetEmbeddingOrigin() const;
// This is recorded when the web page requests to go fullscreen, even if the
// fullscreen state doesn't change.
void RecordMetricsOnFullscreenApiRequested(
content::RenderFrameHost* requesting_frame);
// This is recorded after entering fullscreen.
void RecordMetricsOnEnteringFullscreen();
// The origin of the specific frame requesting fullscreen, which may not match
// the exclusive_access_tab()'s origin, if an embedded frame made the request.
url::Origin requesting_origin_;
// The URL of the extension which triggered "browser fullscreen" mode,
// std::nullopt if it is not in extension fullscreen.
std::optional<GURL> extension_url_;
enum PriorFullscreenState {
STATE_INVALID,
STATE_NORMAL,
STATE_BROWSER_FULLSCREEN,
};
// The state before entering tab fullscreen mode via webkitRequestFullScreen.
// When not in tab fullscreen, it is STATE_INVALID.
PriorFullscreenState state_prior_to_tab_fullscreen_ = STATE_INVALID;
// The display that the window was on before entering tab fullscreen mode.
int64_t display_id_prior_to_tab_fullscreen_ = display::kInvalidDisplayId;
// Stores the target display when tab fullscreen is being entered.
int64_t tab_fullscreen_target_display_id_ = display::kInvalidDisplayId;
// True if the site has entered into fullscreen.
bool tab_fullscreen_ = false;
// True if this controller has toggled into tab OR browser fullscreen.
bool toggled_into_fullscreen_ = false;
// True if the transition to / from fullscreen has started, but not completed.
bool started_fullscreen_transition_ = false;
// This closure will be called after the transition to / from fullscreen
// is completed.
base::OnceClosure fullscreen_transition_complete_callback_;
// Set in OnTabDeactivated(). Used to see if we're in the middle of
// deactivation of a tab.
raw_ptr<content::WebContents> deactivated_contents_ = nullptr;
// Used in testing to set the state to tab fullscreen.
bool is_tab_fullscreen_for_testing_ = false;
// Tracks related popups that lost activation or were shown without activation
// during content fullscreen sessions. This also activates the popups when
// fullscreen exits, to prevent sites from creating persistent popunders.
std::unique_ptr<PopunderPreventer> popunder_preventer_;
base::ObserverList<FullscreenObserver> observer_list_;
// Recorded when the controller switches to fullscreen or when the fullscreen
// window state changes, which ever comes first.
std::optional<base::TimeTicks> fullscreen_start_time_;
// This is used for accessing HistoryService.
base::CancelableTaskTracker task_tracker_;
base::WeakPtrFactory<FullscreenController> ptr_factory_{this};
};
#endif // CHROME_BROWSER_UI_EXCLUSIVE_ACCESS_FULLSCREEN_CONTROLLER_H_
|