| // Copyright 2021 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef CONTENT_BROWSER_RENDERER_HOST_PAGE_IMPL_H_ |
| #define CONTENT_BROWSER_RENDERER_HOST_PAGE_IMPL_H_ |
| |
| #include <memory> |
| #include <optional> |
| #include <set> |
| #include <vector> |
| |
| #include "base/memory/raw_ref.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/time/time.h" |
| #include "cc/input/browser_controls_state.h" |
| #include "content/browser/fenced_frame/fenced_frame_url_mapping.h" |
| #include "content/browser/renderer_host/stored_page.h" |
| #include "content/browser/shared_storage/shared_storage_saved_query_data.h" |
| #include "content/common/content_export.h" |
| #include "content/common/navigation_client.mojom.h" |
| #include "content/public/browser/page.h" |
| #include "net/base/schemeful_site.h" |
| #include "services/metrics/public/cpp/ukm_source.h" |
| #include "services/metrics/public/cpp/ukm_source_id.h" |
| #include "third_party/blink/public/common/features.h" |
| #include "third_party/blink/public/common/shared_storage/shared_storage_utils.h" |
| #include "third_party/blink/public/mojom/css/preferred_color_scheme.mojom.h" |
| #include "third_party/blink/public/mojom/favicon/favicon_url.mojom.h" |
| #include "third_party/blink/public/mojom/frame/text_autosizer_page_info.mojom.h" |
| #include "third_party/skia/include/core/SkColor.h" |
| #include "ui/base/ime/mojom/virtual_keyboard_types.mojom.h" |
| #include "url/gurl.h" |
| |
| namespace cc { |
| struct BrowserControlsOffsetTagsInfo; |
| } // namespace cc |
| |
| namespace viz { |
| class PeakGpuMemoryTracker; |
| } // namespace viz |
| |
| namespace content { |
| |
| class NavigationRequest; |
| class PageDelegate; |
| class RenderFrameHostImpl; |
| |
| // This implements the Page interface that is exposed to embedders of content, |
| // and adds things only visible to content. |
| |
| // Please refer to content/public/browser/page.h for more details. |
| class CONTENT_EXPORT PageImpl : public Page { |
| public: |
| enum class ActivationType { |
| kPrerendering, |
| kPreview, |
| }; |
| PageImpl(RenderFrameHostImpl& rfh, PageDelegate& delegate); |
| |
| ~PageImpl() override; |
| |
| using base::SupportsUserData::ClearAllUserData; |
| |
| // Page implementation. |
| const std::optional<GURL>& GetManifestUrl() const override; |
| void GetManifest(GetManifestCallback callback) override; |
| bool IsPrimary() const override; |
| void WriteIntoTrace(perfetto::TracedValue context) override; |
| base::WeakPtr<Page> GetWeakPtr() override; |
| bool IsPageScaleFactorOne() override; |
| const std::string& GetContentsMimeType() const override; |
| void SetResizableForTesting(std::optional<bool> resizable) override; |
| std::optional<bool> GetResizable() override; |
| |
| // Setter for the `window.setResizable(bool)` API's value defining whether the |
| // window can be resized or not. `std::nullopt` means the value is not set. |
| void SetResizable(std::optional<bool> resizable); |
| |
| base::WeakPtr<PageImpl> GetWeakPtrImpl(); |
| |
| virtual void UpdateManifestUrl(const GURL& manifest_url); |
| |
| RenderFrameHostImpl& GetMainDocument() const; |
| |
| bool is_on_load_completed_in_main_document() const { |
| return is_on_load_completed_in_main_document_; |
| } |
| void set_is_on_load_completed_in_main_document(bool completed) { |
| is_on_load_completed_in_main_document_ = completed; |
| } |
| |
| bool did_first_contentful_paint_in_main_document() const { |
| return did_first_contentful_paint_in_main_document_; |
| } |
| void set_did_first_contentful_paint_in_main_document() { |
| did_first_contentful_paint_in_main_document_ = true; |
| } |
| |
| bool is_main_document_element_available() const { |
| return is_main_document_element_available_; |
| } |
| void set_is_main_document_element_available(bool completed) { |
| is_main_document_element_available_ = completed; |
| } |
| |
| bool uses_temporary_zoom_level() const { return uses_temporary_zoom_level_; } |
| void set_uses_temporary_zoom_level(bool level) { |
| uses_temporary_zoom_level_ = level; |
| } |
| |
| void OnFirstVisuallyNonEmptyPaint(); |
| bool did_first_visually_non_empty_paint() const { |
| return did_first_visually_non_empty_paint_; |
| } |
| |
| const std::vector<blink::mojom::FaviconURLPtr>& favicon_urls() const { |
| return favicon_urls_; |
| } |
| void set_favicon_urls(std::vector<blink::mojom::FaviconURLPtr> favicon_urls) { |
| favicon_urls_ = std::move(favicon_urls); |
| } |
| |
| void OnThemeColorChanged(const std::optional<SkColor>& theme_color); |
| |
| void DidChangeBackgroundColor(SkColor4f background_color, bool color_adjust); |
| |
| // Notifies the page's color scheme was inferred. |
| void DidInferColorScheme(blink::mojom::PreferredColorScheme color_scheme); |
| |
| void NotifyPageBecameCurrent(); |
| |
| std::optional<SkColor> theme_color() const { |
| return main_document_theme_color_; |
| } |
| |
| std::optional<SkColor> background_color() const { |
| return main_document_background_color_; |
| } |
| |
| std::optional<blink::mojom::PreferredColorScheme> inferred_color_scheme() |
| const { |
| return main_document_inferred_color_scheme_; |
| } |
| |
| void SetContentsMimeType(std::string mime_type); |
| |
| void OnTextAutosizerPageInfoChanged( |
| blink::mojom::TextAutosizerPageInfoPtr page_info); |
| |
| blink::mojom::TextAutosizerPageInfo text_autosizer_page_info() const { |
| return text_autosizer_page_info_; |
| } |
| |
| FencedFrameURLMapping& fenced_frame_urls_map() { |
| return fenced_frame_urls_map_; |
| } |
| |
| void set_last_main_document_source_id(ukm::SourceId id) { |
| last_main_document_source_id_ = id; |
| } |
| ukm::SourceId last_main_document_source_id() const { |
| return last_main_document_source_id_; |
| } |
| |
| // Sets the start time of the prerender activation navigation for this page. |
| // TODO(falken): Plumb NavigationRequest to |
| // RenderFrameHostManager::CommitPending and remove this. |
| void SetActivationStartTime(base::TimeTicks activation_start); |
| |
| // Called during the activation navigation. Sends an IPC to the RenderViews in |
| // the renderers, instructing them to transition their documents from |
| // prerendered to activated. Tells the corresponding RenderFrameHostImpls that |
| // the renderer will be activating their documents. |
| void Activate( |
| ActivationType type, |
| StoredPage::RenderViewHostImplSafeRefSet& render_view_hosts_to_activate, |
| std::optional<blink::ViewTransitionState> view_transition_state, |
| base::OnceCallback<void(base::TimeTicks)> completion_callback); |
| |
| // Prerender2: |
| // Dispatches load events that were deferred to be dispatched after |
| // activation. Please note that this should only be called on prerender |
| // activation. |
| void MaybeDispatchLoadEventsOnPrerenderActivation(); |
| |
| // Hide or show the browser controls for the given Page, based on allowed |
| // states, desired state and whether the transition should be animated or |
| // not. |
| void UpdateBrowserControlsState( |
| cc::BrowserControlsState constraints, |
| cc::BrowserControlsState current, |
| bool animate, |
| const std::optional<cc::BrowserControlsOffsetTagsInfo>& offset_tags_info); |
| |
| float GetPageScaleFactor() const; |
| |
| void set_load_progress(double load_progress) { |
| load_progress_ = load_progress; |
| } |
| double load_progress() const { return load_progress_; } |
| |
| void NotifyVirtualKeyboardOverlayRect(const gfx::Rect& keyboard_rect); |
| |
| void SetVirtualKeyboardMode(ui::mojom::VirtualKeyboardMode mode); |
| ui::mojom::VirtualKeyboardMode virtual_keyboard_mode() const { |
| return virtual_keyboard_mode_; |
| } |
| |
| const std::string& GetEncoding() { return canonical_encoding_; } |
| void UpdateEncoding(const std::string& encoding_name); |
| |
| // Returns the keyboard layout mapping. |
| base::flat_map<std::string, std::string> GetKeyboardLayoutMap(); |
| |
| // Retrieves the index from `select_url_saved_query_index_results_` for the |
| // given key, or a special value indicating the status of the query. The key |
| // is a tuple of (`origin`, `script_url`, `operation_name`, `query_name`). |
| // |
| // - New Query: If no entry exists for the key, initializes a new entry with |
| // an index of -1 (indicating pending) and returns -2. |
| // - Pending Query: If an entry exists but the index is -1, adds the provided |
| // `callback` to the list of callbacks for this query and returns -1. |
| // - Completed Query: If an entry exists and the index is nonnegative, returns |
| // the index. |
| int32_t GetSavedQueryResultIndexOrStoreCallback( |
| const url::Origin& origin, |
| const GURL& script_url, |
| const std::string& operation_name, |
| const std::u16string& query_name, |
| base::OnceCallback<void(uint32_t)> callback); |
| |
| // Updates `select_url_saved_query_index_results_` for the given key as |
| // follows. The key is a tuple of (`origin`, `script_url`, `operation_name`, |
| // `query_name`). |
| // - The index is of the entry is set to `index`. |
| // - If the entry has any callbacks, runs them in order. |
| // |
| // Precondition: The entry exists and its index has value -1. |
| void SetSavedQueryResultIndexAndRunCallbacks( |
| const url::Origin& origin, |
| const GURL& script_url, |
| const std::string& operation_name, |
| const std::u16string& query_name, |
| uint32_t index); |
| |
| // Returns whether a pending call to `sharedStorage.selectURL()` has |
| // sufficient budget for `site`, debiting `select_url_overall_budget_` and |
| // `select_url_per_site_budget_[site]` if so and if |
| // `blink::features::kSharedStorageSelectURLLimit` is enabled. If |
| // `blink::features::kSharedStorageSelectURLLimit` is disabled, always returns |
| // `blink::SharedStorageSelectUrlBudgetStatus::kSufficientBudget`. If there is |
| // insufficient budget, the returned enum value specifies which budget was |
| // insufficient. |
| blink::SharedStorageSelectUrlBudgetStatus CheckAndMaybeDebitSelectURLBudgets( |
| const net::SchemefulSite& site, |
| double bits_to_charge); |
| |
| // See documentation for |credentialless_iframes_nonce_|. |
| const base::UnguessableToken& credentialless_iframes_nonce() const { |
| return credentialless_iframes_nonce_; |
| } |
| |
| // Take ownership of the loading memory tracker from the NavigationRequest |
| // that navigated to this page. |
| void TakeLoadingMemoryTracker(NavigationRequest* request); |
| // If we have a loading memory tracker, close it as loading has stopped. It |
| // will asynchronously receive the statistics from the GPU process, and update |
| // UMA stats. |
| void ResetLoadingMemoryTracker(); |
| // If we have a loading memory tracker, cancel it as loading hasn't stopped |
| // and the page is being navigated away from. UMA stats will not be recorded. |
| void CancelLoadingMemoryTracker(); |
| |
| bool is_overriding_user_agent() { return is_overriding_user_agent_; } |
| void set_is_overriding_user_agent(bool is_overriding_user_agent) { |
| is_overriding_user_agent_ = is_overriding_user_agent; |
| } |
| |
| // Use to set and release |last_commit_params_|, see documentation of the |
| // member for more details. This is only called for outermost pages. |
| void SetLastCommitParams( |
| mojom::DidCommitProvisionalLoadParamsPtr commit_params); |
| mojom::DidCommitProvisionalLoadParamsPtr TakeLastCommitParams(); |
| |
| private: |
| void DidActivateAllRenderViewsForPrerenderingOrPreview( |
| base::OnceCallback<void(base::TimeTicks)> completion_callback); |
| |
| // This method is needed to ensure that PageImpl can both implement a Page's |
| // method and define a new GetMainDocument(). Please refer to page.h for more |
| // details. |
| RenderFrameHost& GetMainDocumentHelper() override; |
| |
| // True if we've received a notification that the onload() handler has |
| // run for the main document. |
| bool is_on_load_completed_in_main_document_ = false; |
| |
| // True if the main document had done a first contentful paint. |
| bool did_first_contentful_paint_in_main_document_ = false; |
| |
| // True if we've received a notification that the window.document element |
| // became available for the main document. |
| bool is_main_document_element_available_ = false; |
| |
| // True if plugin zoom level is set for the main document. |
| bool uses_temporary_zoom_level_ = false; |
| |
| // Overall load progress of this Page. Initial load progress value is 0.0 |
| // before the load has begun. |
| double load_progress_ = 0.0; |
| |
| // Web application manifest URL for this page. |
| // See https://w3c.github.io/manifest/#web-application-manifest. |
| // |
| // This is non-nullopt when the page gets an update of the manifest URL. It |
| // can be the empty URL when the manifest url is removed and a non-empty |
| // URL when it has a valid URL for the manifest. If this is non-nullopt, |
| // WebContentsObserver::DidUpdateWebManifestURL() will be called |
| // (either immediately on document load, or on activation in the case |
| // of a prerendered page). |
| // |
| // nullopt indicates that the page did not get an update of the |
| // manifest URL, and DidUpdateWebManifestURL() will not be called. |
| std::optional<GURL> manifest_url_; |
| |
| // Candidate favicon URLs. Each page may have a collection and will be |
| // displayed when active (i.e., upon activation for prerendering). |
| std::vector<blink::mojom::FaviconURLPtr> favicon_urls_; |
| |
| // Whether the first visually non-empty paint has occurred. |
| bool did_first_visually_non_empty_paint_ = false; |
| |
| // Stores the value set by `window.setResizable(bool)` API for whether the |
| // window can be resized or not. `std::nullopt` means the value is not set. |
| std::optional<bool> resizable_ = std::nullopt; |
| |
| // The theme color for the underlying document as specified |
| // by theme-color meta tag. |
| std::optional<SkColor> main_document_theme_color_; |
| |
| // The background color for the underlying document as computed by CSS. |
| std::optional<SkColor> main_document_background_color_; |
| |
| // The inferred color scheme of the document. |
| std::optional<blink::mojom::PreferredColorScheme> |
| main_document_inferred_color_scheme_; |
| |
| // Contents MIME type for the main document. It can be used to check whether |
| // we can do something for special contents. |
| std::string contents_mime_type_; |
| |
| // Fenced frames: |
| // Any fenced frames created within this page will access this map. |
| FencedFrameURLMapping fenced_frame_urls_map_; |
| |
| // If `blink::features::kSharedStorageSelectURLLimit` is enabled, the number |
| // of bits of entropy remaining in this pageload's overall budget for calls to |
| // `sharedStorage.selectURL()`. Calls from all sites on this page are |
| // charged to this budget. `select_url_overall_budget_` is not renewed until |
| // `this` is destroyed, and it does not rely on any assumptions about when |
| // specifically `this` is destroyed (e.g. during navigation or not). |
| std::optional<double> select_url_overall_budget_; |
| |
| // If `blink::features::kSharedStorageSelectURLLimit` is enabled, the maximum |
| // number of bits of entropy in a single site's budget. |
| std::optional<double> select_url_max_bits_per_site_; |
| |
| // A map of sites to the number bits of entropy remaining in the site's |
| // budget for calls to `sharedStorage.selectURL()` during this pageload. |
| // `select_url_per_site_budget_` is not cleared until `this` is destroyed, |
| // and it does not rely on any assumptions about when specifically `this` is |
| // destroyed (e.g. during navigation or not). Used only if |
| // `blink::features::kSharedStorageSelectURLLimit` is enabled. |
| base::flat_map<net::SchemefulSite, double> select_url_per_site_budget_; |
| |
| // A map of tuples (origin, worklet script URL, operation name, query name) to |
| // the index returned for the corresponding `sharedStorage.selectURL()` query. |
| base::flat_map<std::tuple<url::Origin, GURL, std::string, std::u16string>, |
| SharedStorageSavedQueryData> |
| select_url_saved_query_index_results_; |
| |
| // This class is owned by the main RenderFrameHostImpl and it's safe to keep a |
| // reference to it. |
| const raw_ref<RenderFrameHostImpl> main_document_; |
| |
| // SourceId of the navigation in this page's main frame. Note that a same |
| // document navigation is the only case where this source id can change, since |
| // all other navigations create a new PageImpl instance. |
| ukm::SourceId last_main_document_source_id_ = ukm::kInvalidSourceId; |
| |
| // This page is owned by the RenderFrameHostImpl, which in turn does not |
| // outlive the delegate (the contents). |
| const raw_ref<PageDelegate> delegate_; |
| |
| // Stores information from the main frame's renderer that needs to be shared |
| // with OOPIF renderers. |
| blink::mojom::TextAutosizerPageInfo text_autosizer_page_info_; |
| |
| // Prerender2: The start time of the activation navigation for prerendering, |
| // which is passed to the renderer process, and will be accessible in the |
| // prerendered page as PerformanceNavigationTiming.activationStart. Set after |
| // navigation commit. |
| // TODO(b:291867362): Plumb NavigationRequest to |
| // RenderFrameHostManager::CommitPending and remove this. |
| std::optional<base::TimeTicks> activation_start_time_; |
| |
| // The resizing mode requested by Blink for the virtual keyboard. |
| ui::mojom::VirtualKeyboardMode virtual_keyboard_mode_ = |
| ui::mojom::VirtualKeyboardMode::kUnset; |
| |
| // The last reported character encoding, not canonicalized. |
| std::string last_reported_encoding_; |
| // The canonicalized character encoding. |
| std::string canonical_encoding_; |
| |
| // Nonce to be used for initializing the storage key and the network isolation |
| // key of credentialless iframes which are children of this page's main |
| // document. |
| const base::UnguessableToken credentialless_iframes_nonce_ = |
| base::UnguessableToken::Create(); |
| |
| // This is only set for primary pages. |
| // Created by NavigationRequest; ownership is maintained until the frame has |
| // stopped loading, or we navigate away from the page before it finishes |
| // loading. |
| std::unique_ptr<viz::PeakGpuMemoryTracker> loading_memory_tracker_; |
| |
| // Whether the page is overriding the user agent or not. |
| bool is_overriding_user_agent_ = false; |
| |
| // This is used to re-commit when restoring a page from the BackForwardCache |
| // or when activating a prerendered page, with the same params as the original |
| // navigation. |
| mojom::DidCommitProvisionalLoadParamsPtr last_commit_params_; |
| |
| base::WeakPtrFactory<PageImpl> weak_factory_{this}; |
| }; |
| |
| } // namespace content |
| |
| #endif // CONTENT_BROWSER_RENDERER_HOST_PAGE_IMPL_H_ |