blob: 5142a85b0dcd734d54350cf56946b40051ebf203 [file] [log] [blame]
Avi Drissman4e1b7bc32022-09-15 14:03:501// Copyright 2021 The Chromium Authors
Sreeja Kamishetty9e1d0e732021-05-27 18:20:092// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "content/browser/renderer_host/page_impl.h"
6
Matt Falkenhagenf78c2192021-07-24 02:01:437#include "base/barrier_closure.h"
Sky Malice3774b002022-10-21 19:18:408#include "base/feature_list.h"
Dominic Farolino5c606c12021-12-18 09:40:149#include "base/i18n/character_encoding.h"
Lingqi Chidcf722442021-09-02 01:47:1910#include "base/trace_event/optional_trace_event.h"
Sky Malice3774b002022-10-21 19:18:4011#include "cc/base/features.h"
Jeremy Roman4bd173d2021-06-17 00:05:4412#include "content/browser/manifest/manifest_manager_host.h"
Dave Tapuska9c9afe82021-06-22 19:07:4513#include "content/browser/renderer_host/frame_tree_node.h"
Jeremy Roman2d8dfe132021-07-06 20:51:2614#include "content/browser/renderer_host/page_delegate.h"
Julie Jeongeun Kim9e204512021-06-24 07:28:5415#include "content/browser/renderer_host/render_frame_host_delegate.h"
Sreeja Kamishetty9e1d0e732021-05-27 18:20:0916#include "content/browser/renderer_host/render_frame_host_impl.h"
Lingqi Chidcf722442021-09-02 01:47:1917#include "content/browser/renderer_host/render_frame_proxy_host.h"
Jeremy Roman2d8dfe132021-07-06 20:51:2618#include "content/browser/renderer_host/render_view_host_delegate.h"
Matt Falkenhagenf78c2192021-07-24 02:01:4319#include "content/browser/renderer_host/render_view_host_impl.h"
Jeremy Roman2d8dfe132021-07-06 20:51:2620#include "content/public/browser/render_view_host.h"
Sreeja Kamishetty0be3b1b2021-08-12 17:04:1521#include "third_party/blink/public/common/loader/loader_constants.h"
Julie Jeongeun Kim33ef6a22022-03-22 09:46:1122#include "third_party/blink/public/mojom/manifest/manifest.mojom.h"
Jeremy Roman2d8dfe132021-07-06 20:51:2623#include "third_party/perfetto/include/perfetto/tracing/traced_value.h"
Sreeja Kamishetty9e1d0e732021-05-27 18:20:0924
25namespace content {
Jeremy Roman2d8dfe132021-07-06 20:51:2626
27PageImpl::PageImpl(RenderFrameHostImpl& rfh, PageDelegate& delegate)
Lingqi Chidcf722442021-09-02 01:47:1928 : main_document_(rfh),
29 delegate_(delegate),
30 text_autosizer_page_info_({0, 0, 1.f}) {}
Sreeja Kamishetty9e1d0e732021-05-27 18:20:0931
Sreeja Kamishetty1b5c1432021-06-25 11:32:5932PageImpl::~PageImpl() {
33 // As SupportsUserData is a base class of PageImpl, Page members will be
34 // destroyed before running ~SupportsUserData, which would delete the
35 // associated PageUserData objects. Avoid this by calling ClearAllUserData
36 // explicitly here to ensure that the PageUserData destructors can access
37 // associated Page object.
38 ClearAllUserData();
39}
Sreeja Kamishetty9e1d0e732021-05-27 18:20:0940
Julie Jeongeun Kim9e204512021-06-24 07:28:5441const absl::optional<GURL>& PageImpl::GetManifestUrl() const {
Sreeja Kamishetty7c91ab22021-06-03 13:29:5242 return manifest_url_;
43}
44
Jeremy Roman4bd173d2021-06-17 00:05:4445void PageImpl::GetManifest(GetManifestCallback callback) {
46 ManifestManagerHost* manifest_manager_host =
Julie Jeongeun Kim33ef6a22022-03-22 09:46:1147 ManifestManagerHost::GetOrCreateForPage(*this);
Jeremy Roman4bd173d2021-06-17 00:05:4448 manifest_manager_host->GetManifest(std::move(callback));
49}
50
Dave Tapuska9c9afe82021-06-22 19:07:4551bool PageImpl::IsPrimary() {
Dominic Farolino4bc10ee2021-08-31 00:37:3652 // TODO(1244137): Check for portals as well, once they are migrated to MPArch.
Ali Hijazid87307d2022-11-07 20:15:0353 if (main_document_->IsFencedFrameRoot())
Dominic Farolino4bc10ee2021-08-31 00:37:3654 return false;
55
Ali Hijazid87307d2022-11-07 20:15:0356 return main_document_->lifecycle_state() ==
Khushalc5eaf222021-06-30 20:15:4857 RenderFrameHostImpl::LifecycleStateImpl::kActive;
Dave Tapuska9c9afe82021-06-22 19:07:4558}
59
Julie Jeongeun Kim9e204512021-06-24 07:28:5460void PageImpl::UpdateManifestUrl(const GURL& manifest_url) {
61 manifest_url_ = manifest_url;
62
63 // If |main_document_| is not active, the notification is sent on the page
64 // activation.
Ali Hijazid87307d2022-11-07 20:15:0365 if (!main_document_->IsActive())
Julie Jeongeun Kim9e204512021-06-24 07:28:5466 return;
67
Ali Hijazid87307d2022-11-07 20:15:0368 main_document_->delegate()->OnManifestUrlChanged(*this);
Julie Jeongeun Kim9e204512021-06-24 07:28:5469}
70
Jeremy Roman2d8dfe132021-07-06 20:51:2671void PageImpl::WriteIntoTrace(perfetto::TracedValue context) {
72 auto dict = std::move(context).WriteDictionary();
Ali Hijazid87307d2022-11-07 20:15:0373 dict.Add("main_document", *main_document_);
Jeremy Roman2d8dfe132021-07-06 20:51:2674}
75
Miyoung Shinfa182e472021-09-03 12:39:3276base::WeakPtr<Page> PageImpl::GetWeakPtr() {
77 return weak_factory_.GetWeakPtr();
78}
79
Yao Xiaoc7224362022-02-16 08:21:4080base::WeakPtr<PageImpl> PageImpl::GetWeakPtrImpl() {
81 return weak_factory_.GetWeakPtr();
82}
83
Kevin McNee3183a7792021-11-09 21:03:3684bool PageImpl::IsPageScaleFactorOne() {
Kevin McNeec4325ba2022-04-08 23:18:2385 return GetPageScaleFactor() == 1.f;
Kevin McNee3183a7792021-11-09 21:03:3686}
87
Jeremy Roman2d8dfe132021-07-06 20:51:2688void PageImpl::OnFirstVisuallyNonEmptyPaint() {
89 did_first_visually_non_empty_paint_ = true;
Ali Hijazid87307d2022-11-07 20:15:0390 delegate_->OnFirstVisuallyNonEmptyPaint(*this);
Jeremy Roman2d8dfe132021-07-06 20:51:2691}
92
93void PageImpl::OnThemeColorChanged(const absl::optional<SkColor>& theme_color) {
94 main_document_theme_color_ = theme_color;
Ali Hijazid87307d2022-11-07 20:15:0395 delegate_->OnThemeColorChanged(*this);
Jeremy Roman2d8dfe132021-07-06 20:51:2696}
97
98void PageImpl::DidChangeBackgroundColor(SkColor background_color,
99 bool color_adjust) {
100 main_document_background_color_ = background_color;
Ali Hijazid87307d2022-11-07 20:15:03101 delegate_->OnBackgroundColorChanged(*this);
Jeremy Roman2d8dfe132021-07-06 20:51:26102 if (color_adjust) {
103 // <meta name="color-scheme" content="dark"> may pass the dark canvas
104 // background before the first paint in order to avoid flashing the white
105 // background in between loading documents. If we perform a navigation
106 // within the same renderer process, we keep the content background from the
107 // previous page while rendering is blocked in the new page, but for cross
108 // process navigations we would paint the default background (typically
109 // white) while the rendering is blocked.
Ali Hijazid87307d2022-11-07 20:15:03110 main_document_->GetRenderWidgetHost()->GetView()->SetContentBackgroundColor(
Jeremy Roman2d8dfe132021-07-06 20:51:26111 background_color);
112 }
113}
114
Michael Bai19f17a302021-12-08 04:08:33115void PageImpl::DidInferColorScheme(
116 blink::mojom::PreferredColorScheme color_scheme) {
117 main_document_inferred_color_scheme_ = color_scheme;
Ali Hijazid87307d2022-11-07 20:15:03118 delegate_->DidInferColorScheme(*this);
Michael Bai19f17a302021-12-08 04:08:33119}
120
Julie Jeongeun Kimd4597df12022-11-11 02:44:51121void PageImpl::NotifyPageBecameCurrent() {
122 if (!IsPrimary())
123 return;
124 delegate_->NotifyPageBecamePrimary(*this);
125}
126
Jeremy Roman2d8dfe132021-07-06 20:51:26127void PageImpl::SetContentsMimeType(std::string mime_type) {
128 contents_mime_type_ = std::move(mime_type);
129}
130
Lingqi Chidcf722442021-09-02 01:47:19131void PageImpl::OnTextAutosizerPageInfoChanged(
132 blink::mojom::TextAutosizerPageInfoPtr page_info) {
133 OPTIONAL_TRACE_EVENT0("content", "PageImpl::OnTextAutosizerPageInfoChanged");
134
Dave Tapuska2cf1f532022-08-10 15:30:49135 // Keep a copy of `page_info` in case we create a new `blink::WebView` before
136 // the next update, so that the PageImpl can tell the newly created
137 // `blink::WebView` about the autosizer info.
Lingqi Chidcf722442021-09-02 01:47:19138 text_autosizer_page_info_.main_frame_width = page_info->main_frame_width;
139 text_autosizer_page_info_.main_frame_layout_width =
140 page_info->main_frame_layout_width;
141 text_autosizer_page_info_.device_scale_adjustment =
142 page_info->device_scale_adjustment;
143
144 auto remote_frames_broadcast_callback = base::BindRepeating(
145 [](const blink::mojom::TextAutosizerPageInfo& page_info,
146 RenderFrameProxyHost* proxy_host) {
147 DCHECK(proxy_host);
148 proxy_host->GetAssociatedRemoteMainFrame()->UpdateTextAutosizerPageInfo(
149 page_info.Clone());
150 },
151 text_autosizer_page_info_);
152
Ali Hijazid87307d2022-11-07 20:15:03153 main_document_->frame_tree()
Lingqi Chidcf722442021-09-02 01:47:19154 ->root()
155 ->render_manager()
156 ->ExecuteRemoteFramesBroadcastMethod(
157 std::move(remote_frames_broadcast_callback),
Ali Hijazid87307d2022-11-07 20:15:03158 main_document_->GetSiteInstance());
Lingqi Chidcf722442021-09-02 01:47:19159}
160
Matt Falkenhagenf78c2192021-07-24 02:01:43161void PageImpl::SetActivationStartTime(base::TimeTicks activation_start) {
162 DCHECK(!activation_start_time_for_prerendering_);
163 activation_start_time_for_prerendering_ = activation_start;
164}
165
166void PageImpl::ActivateForPrerendering(
Dave Tapuskac3e58352022-09-28 19:05:27167 StoredPage::RenderViewHostImplSafeRefSet& render_view_hosts) {
Matt Falkenhagenf78c2192021-07-24 02:01:43168 base::OnceClosure did_activate_render_views =
169 base::BindOnce(&PageImpl::DidActivateAllRenderViewsForPrerendering,
170 weak_factory_.GetWeakPtr());
171
172 base::RepeatingClosure barrier = base::BarrierClosure(
173 render_view_hosts.size(), std::move(did_activate_render_views));
Dave Tapuskac3e58352022-09-28 19:05:27174 for (const auto& rvh : render_view_hosts) {
Matt Falkenhagenf78c2192021-07-24 02:01:43175 base::TimeTicks navigation_start_to_send;
176 // Only send navigation_start to the RenderViewHost for the main frame to
177 // avoid sending the info cross-origin. Only this RenderViewHost needs the
178 // info, as we expect the other RenderViewHosts are made for cross-origin
179 // iframes which have not yet loaded their document. To the renderer, it
180 // just looks like an ongoing navigation is happening in the frame and has
181 // not yet committed. These RenderViews still need to know about activation
182 // so their documents are created in the non-prerendered state once their
183 // navigation is committed.
Ali Hijazid87307d2022-11-07 20:15:03184 if (main_document_->GetRenderViewHost() == &*rvh)
Matt Falkenhagenf78c2192021-07-24 02:01:43185 navigation_start_to_send = *activation_start_time_for_prerendering_;
186
Hiroki Nakagawaab53cd22022-04-13 19:18:02187 auto params = blink::mojom::PrerenderPageActivationParams::New();
188 params->was_user_activated =
Ali Hijazid87307d2022-11-07 20:15:03189 main_document_->frame_tree_node()
190 ->has_received_user_gesture_before_nav()
Hiroki Nakagawaab53cd22022-04-13 19:18:02191 ? blink::mojom::WasActivatedOption::kYes
192 : blink::mojom::WasActivatedOption::kNo;
193 params->activation_start = navigation_start_to_send;
194 rvh->ActivatePrerenderedPage(std::move(params), barrier);
Matt Falkenhagenf78c2192021-07-24 02:01:43195 }
196
197 // Prepare each RenderFrameHostImpl in this Page for activation.
198 // TODO(https://crbug.com/1232528): Currently we check GetPage() below because
199 // RenderFrameHostImpls may be in a different Page, if, e.g., they are in an
200 // inner WebContents. These are in a different FrameTree which might not know
201 // it is being prerendered. We should teach these FrameTrees that they are
202 // being prerendered, or ban inner FrameTrees in a prerendering page.
Ali Hijazid87307d2022-11-07 20:15:03203 main_document_->ForEachRenderFrameHostIncludingSpeculative(
Daniel Cheng982f2b22022-08-25 23:46:16204 [this](RenderFrameHostImpl* rfh) {
205 if (&rfh->GetPage() != this)
Matt Falkenhagenf78c2192021-07-24 02:01:43206 return;
207 rfh->RendererWillActivateForPrerendering();
Daniel Cheng982f2b22022-08-25 23:46:16208 });
Matt Falkenhagenf78c2192021-07-24 02:01:43209}
210
Sreeja Kamishetty81fbeefb2021-08-12 07:21:41211void PageImpl::MaybeDispatchLoadEventsOnPrerenderActivation() {
212 DCHECK(IsPrimary());
213
Sreeja Kamishetty0be3b1b2021-08-12 17:04:15214 // Dispatch LoadProgressChanged notification on activation with the
215 // prerender last load progress value if the value is not equal to
216 // blink::kFinalLoadProgress, whose notification is dispatched during call
217 // to DidStopLoading.
218 if (load_progress() != blink::kFinalLoadProgress)
Ali Hijazid87307d2022-11-07 20:15:03219 main_document_->DidChangeLoadProgress(load_progress());
Sreeja Kamishetty0be3b1b2021-08-12 17:04:15220
Sreeja Kamishetty49783302022-01-28 17:52:25221 // Dispatch PrimaryMainDocumentElementAvailable before dispatching following
222 // load complete events.
223 if (is_main_document_element_available())
Ali Hijazid87307d2022-11-07 20:15:03224 main_document_->MainDocumentElementAvailable(uses_temporary_zoom_level());
Sreeja Kamishettycd5560912021-11-22 11:54:53225
Ali Hijazid87307d2022-11-07 20:15:03226 main_document_->ForEachRenderFrameHost(
Daniel Cheng982f2b22022-08-25 23:46:16227 &RenderFrameHostImpl::MaybeDispatchDOMContentLoadedOnPrerenderActivation);
Sreeja Kamishetty81fbeefb2021-08-12 07:21:41228
229 if (is_on_load_completed_in_main_document())
Ali Hijazid87307d2022-11-07 20:15:03230 main_document_->DocumentOnLoadCompleted();
Sreeja Kamishetty81fbeefb2021-08-12 07:21:41231
Ali Hijazid87307d2022-11-07 20:15:03232 main_document_->ForEachRenderFrameHost(
Daniel Cheng982f2b22022-08-25 23:46:16233 &RenderFrameHostImpl::MaybeDispatchDidFinishLoadOnPrerenderActivation);
Sreeja Kamishetty81fbeefb2021-08-12 07:21:41234}
235
Matt Falkenhagenf78c2192021-07-24 02:01:43236void PageImpl::DidActivateAllRenderViewsForPrerendering() {
237 // Tell each RenderFrameHostImpl in this Page that activation finished.
Ali Hijazid87307d2022-11-07 20:15:03238 main_document_->ForEachRenderFrameHost([this](RenderFrameHostImpl* rfh) {
Daniel Cheng982f2b22022-08-25 23:46:16239 if (&rfh->GetPage() != this)
240 return;
241 rfh->RendererDidActivateForPrerendering();
242 });
Matt Falkenhagenf78c2192021-07-24 02:01:43243}
244
Sreeja Kamishetty1b5c1432021-06-25 11:32:59245RenderFrameHost& PageImpl::GetMainDocumentHelper() {
Ali Hijazid87307d2022-11-07 20:15:03246 return *main_document_;
Sreeja Kamishetty1b5c1432021-06-25 11:32:59247}
248
249RenderFrameHostImpl& PageImpl::GetMainDocument() const {
Ali Hijazid87307d2022-11-07 20:15:03250 return *main_document_;
Sreeja Kamishetty1b5c1432021-06-25 11:32:59251}
252
Yoshisato Yanagisawad016d62d32021-10-15 04:38:55253void PageImpl::UpdateBrowserControlsState(cc::BrowserControlsState constraints,
254 cc::BrowserControlsState current,
255 bool animate) {
256 // TODO(https://crbug.com/1154852): Asking for the LocalMainFrame interface
257 // before the RenderFrame is created is racy.
Nasko Oskov8b04f402022-05-26 23:29:56258 if (!GetMainDocument().IsRenderFrameLive())
Yoshisato Yanagisawad016d62d32021-10-15 04:38:55259 return;
260
Sky Malice3774b002022-10-21 19:18:40261 if (base::FeatureList::IsEnabled(
262 features::kUpdateBrowserControlsWithoutProxy)) {
263 GetMainDocument().GetRenderWidgetHost()->UpdateBrowserControlsState(
264 constraints, current, animate);
265 } else {
266 GetMainDocument().GetAssociatedLocalMainFrame()->UpdateBrowserControlsState(
267 constraints, current, animate);
268 }
Yoshisato Yanagisawad016d62d32021-10-15 04:38:55269}
270
Kevin McNeec4325ba2022-04-08 23:18:23271float PageImpl::GetPageScaleFactor() const {
272 return GetMainDocument().GetPageScaleFactor();
273}
274
Dominic Farolino5c606c12021-12-18 09:40:14275void PageImpl::UpdateEncoding(const std::string& encoding_name) {
276 if (encoding_name == last_reported_encoding_)
277 return;
278 last_reported_encoding_ = encoding_name;
279
280 canonical_encoding_ =
281 base::GetCanonicalEncodingNameByAliasName(encoding_name);
282}
283
Yoshisato Yanagisawa8ae0d112022-04-20 01:49:30284void PageImpl::NotifyVirtualKeyboardOverlayRect(
285 const gfx::Rect& keyboard_rect) {
286 // TODO(https://crbug.com/1317002): send notification to outer frames if
287 // needed.
David Bokand6e44055b2022-09-21 03:58:08288 DCHECK_EQ(virtual_keyboard_mode(),
289 ui::mojom::VirtualKeyboardMode::kOverlaysContent);
Yoshisato Yanagisawa8ae0d112022-04-20 01:49:30290 GetMainDocument().GetAssociatedLocalFrame()->NotifyVirtualKeyboardOverlayRect(
291 keyboard_rect);
292}
293
David Bokand6e44055b2022-09-21 03:58:08294void PageImpl::SetVirtualKeyboardMode(ui::mojom::VirtualKeyboardMode mode) {
295 if (virtual_keyboard_mode_ == mode)
296 return;
297
298 virtual_keyboard_mode_ = mode;
299
Ali Hijazid87307d2022-11-07 20:15:03300 delegate_->OnVirtualKeyboardModeChanged(*this);
David Bokand6e44055b2022-09-21 03:58:08301}
302
Yoshisato Yanagisawa668f8442022-04-20 04:45:58303base::flat_map<std::string, std::string> PageImpl::GetKeyboardLayoutMap() {
304 return GetMainDocument().GetRenderWidgetHost()->GetKeyboardLayoutMap();
305}
306
Camillia Smith Barnes574d4d42023-01-10 18:57:47307bool PageImpl::IsSelectURLAllowed(const url::Origin& origin) {
308 int& count = select_url_count_[origin];
309 if (count >=
310 blink::features::
311 kSharedStorageMaxAllowedSelectURLCallsPerOriginPerPageLoad.Get()) {
312 return false;
313 }
314
315 ++count;
316 return true;
317}
318
Sreeja Kamishetty9e1d0e732021-05-27 18:20:09319} // namespace content