| // 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_exclusion.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/observer_list.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 "ui/display/types/display_constants.h" |
| |
| class GURL; |
| class PopunderPreventer; |
| |
| namespace content { |
| class WebContents; |
| class RenderFrameHost; |
| } |
| |
| // 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. |
| // |
| // 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); |
| |
| // 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 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'. |
| // Writes the display ID that tab is tab-fullscreen on or transitioning to to |
| // `display_id`. Only writes when the function returns true and display_id is |
| // non-null. |
| bool IsFullscreenForTabOrPending(const content::WebContents* web_contents, |
| int64_t* display_id = nullptr) 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, |
| const int64_t display_id = display::kInvalidDisplayId); |
| |
| // 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 ExitExclusiveAccessToPreviousState() override; |
| GURL GetURLForExclusiveAccessBubble() 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 FullscreenTransititionCompleted(); |
| |
| // 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 RecordBubbleReshowsHistogram(int bubble_reshow_count) override; |
| |
| void ToggleFullscreenModeInternal(FullscreenInternalOption option, |
| content::RenderFrameHost* requesting_frame, |
| const int64_t display_id); |
| void EnterFullscreenModeInternal(FullscreenInternalOption option, |
| content::RenderFrameHost* requesting_frame, |
| int64_t display_id); |
| void ExitFullscreenModeInternal(); |
| void SetFullscreenedTab(content::WebContents* tab, const GURL& origin); |
| |
| // 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; |
| |
| // 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. |
| GURL requesting_origin_; |
| |
| // The URL of the extension which trigerred "browser fullscreen" mode. |
| GURL extension_caused_fullscreen_; |
| |
| 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. |
| // This field is not a raw_ptr<> because it was filtered by the rewriter for: |
| // #addr-of |
| RAW_PTR_EXCLUSION 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 persisent popunders. |
| std::unique_ptr<PopunderPreventer> popunder_preventer_; |
| |
| base::ObserverList<FullscreenObserver> observer_list_; |
| |
| base::WeakPtrFactory<FullscreenController> ptr_factory_{this}; |
| }; |
| |
| #endif // CHROME_BROWSER_UI_EXCLUSIVE_ACCESS_FULLSCREEN_CONTROLLER_H_ |