blob: 7b7afb42805448ba4f5cd3ff3abadbad26da2f42 [file] [log] [blame]
Sreeja Kamishetty9e1d0e732021-05-27 18:20:091// Copyright 2021 The Chromium Authors. All rights reserved.
2// 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"
Dominic Farolino5c606c12021-12-18 09:40:148#include "base/i18n/character_encoding.h"
Lingqi Chidcf722442021-09-02 01:47:199#include "base/trace_event/optional_trace_event.h"
Jeremy Roman4bd173d2021-06-17 00:05:4410#include "content/browser/manifest/manifest_manager_host.h"
Dave Tapuska9c9afe82021-06-22 19:07:4511#include "content/browser/renderer_host/frame_tree_node.h"
Jeremy Roman2d8dfe132021-07-06 20:51:2612#include "content/browser/renderer_host/page_delegate.h"
Julie Jeongeun Kim9e204512021-06-24 07:28:5413#include "content/browser/renderer_host/render_frame_host_delegate.h"
Sreeja Kamishetty9e1d0e732021-05-27 18:20:0914#include "content/browser/renderer_host/render_frame_host_impl.h"
Lingqi Chidcf722442021-09-02 01:47:1915#include "content/browser/renderer_host/render_frame_proxy_host.h"
Jeremy Roman2d8dfe132021-07-06 20:51:2616#include "content/browser/renderer_host/render_view_host_delegate.h"
Matt Falkenhagenf78c2192021-07-24 02:01:4317#include "content/browser/renderer_host/render_view_host_impl.h"
Jeremy Roman2d8dfe132021-07-06 20:51:2618#include "content/public/browser/render_view_host.h"
Sreeja Kamishetty0be3b1b2021-08-12 17:04:1519#include "third_party/blink/public/common/loader/loader_constants.h"
Jeremy Roman2d8dfe132021-07-06 20:51:2620#include "third_party/perfetto/include/perfetto/tracing/traced_value.h"
Sreeja Kamishetty9e1d0e732021-05-27 18:20:0921
22namespace content {
Jeremy Roman2d8dfe132021-07-06 20:51:2623
24PageImpl::PageImpl(RenderFrameHostImpl& rfh, PageDelegate& delegate)
Lingqi Chidcf722442021-09-02 01:47:1925 : main_document_(rfh),
26 delegate_(delegate),
27 text_autosizer_page_info_({0, 0, 1.f}) {}
Sreeja Kamishetty9e1d0e732021-05-27 18:20:0928
Sreeja Kamishetty1b5c1432021-06-25 11:32:5929PageImpl::~PageImpl() {
30 // As SupportsUserData is a base class of PageImpl, Page members will be
31 // destroyed before running ~SupportsUserData, which would delete the
32 // associated PageUserData objects. Avoid this by calling ClearAllUserData
33 // explicitly here to ensure that the PageUserData destructors can access
34 // associated Page object.
35 ClearAllUserData();
36}
Sreeja Kamishetty9e1d0e732021-05-27 18:20:0937
Julie Jeongeun Kim9e204512021-06-24 07:28:5438const absl::optional<GURL>& PageImpl::GetManifestUrl() const {
Sreeja Kamishetty7c91ab22021-06-03 13:29:5239 return manifest_url_;
40}
41
Jeremy Roman4bd173d2021-06-17 00:05:4442void PageImpl::GetManifest(GetManifestCallback callback) {
43 ManifestManagerHost* manifest_manager_host =
44 ManifestManagerHost::GetOrCreateForCurrentDocument(&main_document_);
45 manifest_manager_host->GetManifest(std::move(callback));
46}
47
Dave Tapuska9c9afe82021-06-22 19:07:4548bool PageImpl::IsPrimary() {
Dominic Farolino4bc10ee2021-08-31 00:37:3649 // TODO(1244137): Check for portals as well, once they are migrated to MPArch.
50 if (main_document_.IsFencedFrameRoot())
51 return false;
52
Dave Tapuska9c9afe82021-06-22 19:07:4553 return main_document_.lifecycle_state() ==
Khushalc5eaf222021-06-30 20:15:4854 RenderFrameHostImpl::LifecycleStateImpl::kActive;
Dave Tapuska9c9afe82021-06-22 19:07:4555}
56
Julie Jeongeun Kim9e204512021-06-24 07:28:5457void PageImpl::UpdateManifestUrl(const GURL& manifest_url) {
58 manifest_url_ = manifest_url;
59
60 // If |main_document_| is not active, the notification is sent on the page
61 // activation.
62 if (!main_document_.IsActive())
63 return;
64
65 main_document_.delegate()->OnManifestUrlChanged(*this);
66}
67
Jeremy Roman2d8dfe132021-07-06 20:51:2668void PageImpl::WriteIntoTrace(perfetto::TracedValue context) {
69 auto dict = std::move(context).WriteDictionary();
70 dict.Add("main_document", main_document_);
71}
72
Miyoung Shinfa182e472021-09-03 12:39:3273base::WeakPtr<Page> PageImpl::GetWeakPtr() {
74 return weak_factory_.GetWeakPtr();
75}
76
Yao Xiaoc7224362022-02-16 08:21:4077base::WeakPtr<PageImpl> PageImpl::GetWeakPtrImpl() {
78 return weak_factory_.GetWeakPtr();
79}
80
Kevin McNee3183a7792021-11-09 21:03:3681bool PageImpl::IsPageScaleFactorOne() {
82 return page_scale_factor_ == 1.f;
83}
84
Jeremy Roman2d8dfe132021-07-06 20:51:2685void PageImpl::OnFirstVisuallyNonEmptyPaint() {
86 did_first_visually_non_empty_paint_ = true;
87 delegate_.OnFirstVisuallyNonEmptyPaint(*this);
88}
89
90void PageImpl::OnThemeColorChanged(const absl::optional<SkColor>& theme_color) {
91 main_document_theme_color_ = theme_color;
92 delegate_.OnThemeColorChanged(*this);
93}
94
95void PageImpl::DidChangeBackgroundColor(SkColor background_color,
96 bool color_adjust) {
97 main_document_background_color_ = background_color;
98 delegate_.OnBackgroundColorChanged(*this);
99 if (color_adjust) {
100 // <meta name="color-scheme" content="dark"> may pass the dark canvas
101 // background before the first paint in order to avoid flashing the white
102 // background in between loading documents. If we perform a navigation
103 // within the same renderer process, we keep the content background from the
104 // previous page while rendering is blocked in the new page, but for cross
105 // process navigations we would paint the default background (typically
106 // white) while the rendering is blocked.
107 main_document_.GetRenderWidgetHost()->GetView()->SetContentBackgroundColor(
108 background_color);
109 }
110}
111
Michael Bai19f17a302021-12-08 04:08:33112void PageImpl::DidInferColorScheme(
113 blink::mojom::PreferredColorScheme color_scheme) {
114 main_document_inferred_color_scheme_ = color_scheme;
115 delegate_.DidInferColorScheme(*this);
116}
117
Jeremy Roman2d8dfe132021-07-06 20:51:26118void PageImpl::SetContentsMimeType(std::string mime_type) {
119 contents_mime_type_ = std::move(mime_type);
120}
121
Lingqi Chidcf722442021-09-02 01:47:19122void PageImpl::OnTextAutosizerPageInfoChanged(
123 blink::mojom::TextAutosizerPageInfoPtr page_info) {
124 OPTIONAL_TRACE_EVENT0("content", "PageImpl::OnTextAutosizerPageInfoChanged");
125
126 // Keep a copy of |page_info| in case we create a new RenderView before
127 // the next update, so that the PageImpl can tell the newly created RenderView
128 // about the autosizer info.
129 text_autosizer_page_info_.main_frame_width = page_info->main_frame_width;
130 text_autosizer_page_info_.main_frame_layout_width =
131 page_info->main_frame_layout_width;
132 text_autosizer_page_info_.device_scale_adjustment =
133 page_info->device_scale_adjustment;
134
135 auto remote_frames_broadcast_callback = base::BindRepeating(
136 [](const blink::mojom::TextAutosizerPageInfo& page_info,
137 RenderFrameProxyHost* proxy_host) {
138 DCHECK(proxy_host);
139 proxy_host->GetAssociatedRemoteMainFrame()->UpdateTextAutosizerPageInfo(
140 page_info.Clone());
141 },
142 text_autosizer_page_info_);
143
144 main_document_.frame_tree()
145 ->root()
146 ->render_manager()
147 ->ExecuteRemoteFramesBroadcastMethod(
148 std::move(remote_frames_broadcast_callback),
149 main_document_.GetSiteInstance());
150}
151
Matt Falkenhagenf78c2192021-07-24 02:01:43152void PageImpl::SetActivationStartTime(base::TimeTicks activation_start) {
153 DCHECK(!activation_start_time_for_prerendering_);
154 activation_start_time_for_prerendering_ = activation_start;
155}
156
157void PageImpl::ActivateForPrerendering(
158 std::set<RenderViewHostImpl*>& render_view_hosts) {
159 base::OnceClosure did_activate_render_views =
160 base::BindOnce(&PageImpl::DidActivateAllRenderViewsForPrerendering,
161 weak_factory_.GetWeakPtr());
162
163 base::RepeatingClosure barrier = base::BarrierClosure(
164 render_view_hosts.size(), std::move(did_activate_render_views));
165 for (RenderViewHostImpl* rvh : render_view_hosts) {
166 base::TimeTicks navigation_start_to_send;
167 // Only send navigation_start to the RenderViewHost for the main frame to
168 // avoid sending the info cross-origin. Only this RenderViewHost needs the
169 // info, as we expect the other RenderViewHosts are made for cross-origin
170 // iframes which have not yet loaded their document. To the renderer, it
171 // just looks like an ongoing navigation is happening in the frame and has
172 // not yet committed. These RenderViews still need to know about activation
173 // so their documents are created in the non-prerendered state once their
174 // navigation is committed.
175 if (main_document_.GetRenderViewHost() == rvh)
176 navigation_start_to_send = *activation_start_time_for_prerendering_;
177
178 rvh->ActivatePrerenderedPage(navigation_start_to_send, barrier);
179 }
180
181 // Prepare each RenderFrameHostImpl in this Page for activation.
182 // TODO(https://crbug.com/1232528): Currently we check GetPage() below because
183 // RenderFrameHostImpls may be in a different Page, if, e.g., they are in an
184 // inner WebContents. These are in a different FrameTree which might not know
185 // it is being prerendered. We should teach these FrameTrees that they are
186 // being prerendered, or ban inner FrameTrees in a prerendering page.
Lingqi Chi2cfb83bb52022-01-12 13:15:37187 main_document_.ForEachRenderFrameHostIncludingSpeculative(base::BindRepeating(
Matt Falkenhagenf78c2192021-07-24 02:01:43188 [](PageImpl* page, RenderFrameHostImpl* rfh) {
189 if (&rfh->GetPage() != page)
190 return;
191 rfh->RendererWillActivateForPrerendering();
192 },
193 this));
194}
195
Sreeja Kamishetty81fbeefb2021-08-12 07:21:41196void PageImpl::MaybeDispatchLoadEventsOnPrerenderActivation() {
197 DCHECK(IsPrimary());
198
Sreeja Kamishetty0be3b1b2021-08-12 17:04:15199 // Dispatch LoadProgressChanged notification on activation with the
200 // prerender last load progress value if the value is not equal to
201 // blink::kFinalLoadProgress, whose notification is dispatched during call
202 // to DidStopLoading.
203 if (load_progress() != blink::kFinalLoadProgress)
204 main_document_.DidChangeLoadProgress(load_progress());
205
Sreeja Kamishetty49783302022-01-28 17:52:25206 // Dispatch PrimaryMainDocumentElementAvailable before dispatching following
207 // load complete events.
208 if (is_main_document_element_available())
209 main_document_.MainDocumentElementAvailable(uses_temporary_zoom_level());
Sreeja Kamishettycd5560912021-11-22 11:54:53210
Sreeja Kamishetty81fbeefb2021-08-12 07:21:41211 main_document_.ForEachRenderFrameHost(
212 base::BindRepeating([](RenderFrameHostImpl* rfh) {
213 rfh->MaybeDispatchDOMContentLoadedOnPrerenderActivation();
214 }));
215
216 if (is_on_load_completed_in_main_document())
217 main_document_.DocumentOnLoadCompleted();
218
219 main_document_.ForEachRenderFrameHost(
220 base::BindRepeating([](RenderFrameHostImpl* rfh) {
221 rfh->MaybeDispatchDidFinishLoadOnPrerenderActivation();
222 }));
223}
224
Matt Falkenhagenf78c2192021-07-24 02:01:43225void PageImpl::DidActivateAllRenderViewsForPrerendering() {
226 // Tell each RenderFrameHostImpl in this Page that activation finished.
227 main_document_.ForEachRenderFrameHost(base::BindRepeating(
228 [](PageImpl* page, RenderFrameHostImpl* rfh) {
229 if (&rfh->GetPage() != page)
230 return;
231 rfh->RendererDidActivateForPrerendering();
232 },
233 this));
234}
235
Sreeja Kamishetty1b5c1432021-06-25 11:32:59236RenderFrameHost& PageImpl::GetMainDocumentHelper() {
237 return main_document_;
238}
239
240RenderFrameHostImpl& PageImpl::GetMainDocument() const {
241 return main_document_;
242}
243
Yoshisato Yanagisawad016d62d32021-10-15 04:38:55244void PageImpl::UpdateBrowserControlsState(cc::BrowserControlsState constraints,
245 cc::BrowserControlsState current,
246 bool animate) {
247 // TODO(https://crbug.com/1154852): Asking for the LocalMainFrame interface
248 // before the RenderFrame is created is racy.
249 if (!GetMainDocument().IsRenderFrameCreated())
250 return;
251
252 GetMainDocument().GetAssociatedLocalMainFrame()->UpdateBrowserControlsState(
253 constraints, current, animate);
254}
255
Dominic Farolino5c606c12021-12-18 09:40:14256void PageImpl::UpdateEncoding(const std::string& encoding_name) {
257 if (encoding_name == last_reported_encoding_)
258 return;
259 last_reported_encoding_ = encoding_name;
260
261 canonical_encoding_ =
262 base::GetCanonicalEncodingNameByAliasName(encoding_name);
263}
264
Sreeja Kamishetty9e1d0e732021-05-27 18:20:09265} // namespace content