blob: 5123171ed1f90bd7601494ff2215ef31da6a4e61 [file] [log] [blame]
// 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.
#include <set>
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "build/build_config.h"
#include "chrome/browser/ui/exclusive_access/exclusive_access_controller_base.h"
#include "components/content_settings/core/common/content_settings.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
class GURL;
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, 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 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.
// Content-fullscreen (for macOS only):
// First, the browser window will not be fullscreened. Second, the WebContents's
// view will not be displayed in the browser window but rather in a
// separate window, SeparateFullscreenWindow, which will be fullscreened and
// moved to a new space. This enables the user to have both the browser window
// and the fullscreen content displayed separately at the same time.
// This class implements fullscreen behaviour.
class FullscreenController : public ExclusiveAccessControllerBase {
explicit FullscreenController(ExclusiveAccessManager* manager);
~FullscreenController() override;
// 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;
// Returns true if Flash is providing the "exit from fullscreen" message.
bool IsPrivilegedFullscreenForTab() 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 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 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;
// 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;
// Enter tab-initiated fullscreen mode. FullscreenController will decide
// whether to also fullscreen the browser window. See 'FullscreenWithinTab
// Note'.
// |web_contents| represents the tab that requests to be fullscreen.
// |origin| represents the origin of the requesting frame inside the
// WebContents. If empty, then the |web_contents|'s latest committed URL
// origin will be used.
void EnterFullscreenModeForTab(content::WebContents* web_contents,
const GURL& origin);
// Leave a tab-initiated fullscreen mode.
// |web_contents| represents the tab that requests to no longer be fullscreen.
void ExitFullscreenModeForTab(content::WebContents* web_contents);
// Platform Fullscreen ///////////////////////////////////////////////////////
// Overrde 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 ExitExclusiveAccessToPreviousState() override;
GURL GetURLForExclusiveAccessBubble() const override;
void ExitExclusiveAccessIfNecessary() override;
// Callbacks /////////////////////////////////////////////////////////////////
// Called by Browser::WindowFullscreenStateWillChange.
void WindowFullscreenStateWillChange();
// Called by Browser::WindowFullscreenStateChanged.
void WindowFullscreenStateChanged();
void set_is_tab_fullscreen_for_testing(bool is_tab_fullscreen) {
is_tab_fullscreen_for_testing_ = is_tab_fullscreen;
friend class FullscreenControllerTest;
enum FullscreenInternalOption {
// Posts a task to call NotifyFullscreenChange.
void PostFullscreenChangeNotification(bool is_fullscreen);
void NotifyFullscreenChange(bool is_fullscreen);
// Notifies the tab that it has been forced out of fullscreen mode if
// necessary.
void NotifyTabExclusiveAccessLost() override;
void RecordBubbleReshowsHistogram(int bubble_reshow_count) override;
void ToggleFullscreenModeInternal(FullscreenInternalOption option);
void EnterFullscreenModeInternal(FullscreenInternalOption option);
void ExitFullscreenModeInternal();
void SetFullscreenedTab(content::WebContents* tab, const GURL& origin);
void SetPrivilegedFullscreenForTesting(bool is_privileged);
// 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.
GURL GetRequestingOrigin() const;
GURL GetEmbeddingOrigin() const;
// If a tab is fullscreen, the |fullscreen_origin_| should be used as the
// origin with regards to fullscreen. The |fullscreened_tab_| url should be
// used as the embedder url.
GURL fullscreened_origin_;
// The URL of the extension which trigerred "browser fullscreen" mode.
GURL extension_caused_fullscreen_;
enum PriorFullscreenState {
// 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 the site has entered into fullscreen.
bool tab_fullscreen_;
// True if this controller has toggled into tab OR browser fullscreen.
bool toggled_into_fullscreen_;
// Set in OnTabDeactivated(). Used to see if we're in the middle of
// deactivation of a tab.
content::WebContents* deactivated_contents_;
// Used in testing to confirm proper behavior for specific, privileged
// fullscreen cases.
bool is_privileged_fullscreen_for_testing_;
// Used in testing to set the state to tab fullscreen.
bool is_tab_fullscreen_for_testing_;
base::WeakPtrFactory<FullscreenController> ptr_factory_;