blob: ce4287ffe15c84ab0ae0aa905d6a41498d222e19 [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"
Lingqi Chidcf722442021-09-02 01:47:198#include "base/trace_event/optional_trace_event.h"
Jeremy Roman4bd173d2021-06-17 00:05:449#include "content/browser/manifest/manifest_manager_host.h"
Dave Tapuska9c9afe82021-06-22 19:07:4510#include "content/browser/renderer_host/frame_tree_node.h"
Jeremy Roman2d8dfe132021-07-06 20:51:2611#include "content/browser/renderer_host/page_delegate.h"
Julie Jeongeun Kim9e204512021-06-24 07:28:5412#include "content/browser/renderer_host/render_frame_host_delegate.h"
Sreeja Kamishetty9e1d0e732021-05-27 18:20:0913#include "content/browser/renderer_host/render_frame_host_impl.h"
Lingqi Chidcf722442021-09-02 01:47:1914#include "content/browser/renderer_host/render_frame_proxy_host.h"
Jeremy Roman2d8dfe132021-07-06 20:51:2615#include "content/browser/renderer_host/render_view_host_delegate.h"
Matt Falkenhagenf78c2192021-07-24 02:01:4316#include "content/browser/renderer_host/render_view_host_impl.h"
Jeremy Roman2d8dfe132021-07-06 20:51:2617#include "content/public/browser/render_view_host.h"
Sreeja Kamishetty0be3b1b2021-08-12 17:04:1518#include "third_party/blink/public/common/loader/loader_constants.h"
Jeremy Roman2d8dfe132021-07-06 20:51:2619#include "third_party/perfetto/include/perfetto/tracing/traced_value.h"
Sreeja Kamishetty9e1d0e732021-05-27 18:20:0920
21namespace content {
Jeremy Roman2d8dfe132021-07-06 20:51:2622
23PageImpl::PageImpl(RenderFrameHostImpl& rfh, PageDelegate& delegate)
Lingqi Chidcf722442021-09-02 01:47:1924 : main_document_(rfh),
25 delegate_(delegate),
26 text_autosizer_page_info_({0, 0, 1.f}) {}
Sreeja Kamishetty9e1d0e732021-05-27 18:20:0927
Sreeja Kamishetty1b5c1432021-06-25 11:32:5928PageImpl::~PageImpl() {
29 // As SupportsUserData is a base class of PageImpl, Page members will be
30 // destroyed before running ~SupportsUserData, which would delete the
31 // associated PageUserData objects. Avoid this by calling ClearAllUserData
32 // explicitly here to ensure that the PageUserData destructors can access
33 // associated Page object.
34 ClearAllUserData();
35}
Sreeja Kamishetty9e1d0e732021-05-27 18:20:0936
Julie Jeongeun Kim9e204512021-06-24 07:28:5437const absl::optional<GURL>& PageImpl::GetManifestUrl() const {
Sreeja Kamishetty7c91ab22021-06-03 13:29:5238 return manifest_url_;
39}
40
Jeremy Roman4bd173d2021-06-17 00:05:4441void PageImpl::GetManifest(GetManifestCallback callback) {
42 ManifestManagerHost* manifest_manager_host =
43 ManifestManagerHost::GetOrCreateForCurrentDocument(&main_document_);
44 manifest_manager_host->GetManifest(std::move(callback));
45}
46
Dave Tapuska9c9afe82021-06-22 19:07:4547bool PageImpl::IsPrimary() {
Dominic Farolino4bc10ee2021-08-31 00:37:3648 // TODO(1244137): Check for portals as well, once they are migrated to MPArch.
49 if (main_document_.IsFencedFrameRoot())
50 return false;
51
Dave Tapuska9c9afe82021-06-22 19:07:4552 return main_document_.lifecycle_state() ==
Khushalc5eaf222021-06-30 20:15:4853 RenderFrameHostImpl::LifecycleStateImpl::kActive;
Dave Tapuska9c9afe82021-06-22 19:07:4554}
55
Julie Jeongeun Kim9e204512021-06-24 07:28:5456void PageImpl::UpdateManifestUrl(const GURL& manifest_url) {
57 manifest_url_ = manifest_url;
58
59 // If |main_document_| is not active, the notification is sent on the page
60 // activation.
61 if (!main_document_.IsActive())
62 return;
63
64 main_document_.delegate()->OnManifestUrlChanged(*this);
65}
66
Jeremy Roman2d8dfe132021-07-06 20:51:2667void PageImpl::WriteIntoTrace(perfetto::TracedValue context) {
68 auto dict = std::move(context).WriteDictionary();
69 dict.Add("main_document", main_document_);
70}
71
Miyoung Shinfa182e472021-09-03 12:39:3272base::WeakPtr<Page> PageImpl::GetWeakPtr() {
73 return weak_factory_.GetWeakPtr();
74}
75
Kevin McNee3183a7792021-11-09 21:03:3676bool PageImpl::IsPageScaleFactorOne() {
77 return page_scale_factor_ == 1.f;
78}
79
Jeremy Roman2d8dfe132021-07-06 20:51:2680void PageImpl::OnFirstVisuallyNonEmptyPaint() {
81 did_first_visually_non_empty_paint_ = true;
82 delegate_.OnFirstVisuallyNonEmptyPaint(*this);
83}
84
85void PageImpl::OnThemeColorChanged(const absl::optional<SkColor>& theme_color) {
86 main_document_theme_color_ = theme_color;
87 delegate_.OnThemeColorChanged(*this);
88}
89
90void PageImpl::DidChangeBackgroundColor(SkColor background_color,
91 bool color_adjust) {
92 main_document_background_color_ = background_color;
93 delegate_.OnBackgroundColorChanged(*this);
94 if (color_adjust) {
95 // <meta name="color-scheme" content="dark"> may pass the dark canvas
96 // background before the first paint in order to avoid flashing the white
97 // background in between loading documents. If we perform a navigation
98 // within the same renderer process, we keep the content background from the
99 // previous page while rendering is blocked in the new page, but for cross
100 // process navigations we would paint the default background (typically
101 // white) while the rendering is blocked.
102 main_document_.GetRenderWidgetHost()->GetView()->SetContentBackgroundColor(
103 background_color);
104 }
105}
106
Michael Bai19f17a302021-12-08 04:08:33107void PageImpl::DidInferColorScheme(
108 blink::mojom::PreferredColorScheme color_scheme) {
109 main_document_inferred_color_scheme_ = color_scheme;
110 delegate_.DidInferColorScheme(*this);
111}
112
Jeremy Roman2d8dfe132021-07-06 20:51:26113void PageImpl::SetContentsMimeType(std::string mime_type) {
114 contents_mime_type_ = std::move(mime_type);
115}
116
Lingqi Chidcf722442021-09-02 01:47:19117void PageImpl::OnTextAutosizerPageInfoChanged(
118 blink::mojom::TextAutosizerPageInfoPtr page_info) {
119 OPTIONAL_TRACE_EVENT0("content", "PageImpl::OnTextAutosizerPageInfoChanged");
120
121 // Keep a copy of |page_info| in case we create a new RenderView before
122 // the next update, so that the PageImpl can tell the newly created RenderView
123 // about the autosizer info.
124 text_autosizer_page_info_.main_frame_width = page_info->main_frame_width;
125 text_autosizer_page_info_.main_frame_layout_width =
126 page_info->main_frame_layout_width;
127 text_autosizer_page_info_.device_scale_adjustment =
128 page_info->device_scale_adjustment;
129
130 auto remote_frames_broadcast_callback = base::BindRepeating(
131 [](const blink::mojom::TextAutosizerPageInfo& page_info,
132 RenderFrameProxyHost* proxy_host) {
133 DCHECK(proxy_host);
134 proxy_host->GetAssociatedRemoteMainFrame()->UpdateTextAutosizerPageInfo(
135 page_info.Clone());
136 },
137 text_autosizer_page_info_);
138
139 main_document_.frame_tree()
140 ->root()
141 ->render_manager()
142 ->ExecuteRemoteFramesBroadcastMethod(
143 std::move(remote_frames_broadcast_callback),
144 main_document_.GetSiteInstance());
145}
146
Matt Falkenhagenf78c2192021-07-24 02:01:43147void PageImpl::SetActivationStartTime(base::TimeTicks activation_start) {
148 DCHECK(!activation_start_time_for_prerendering_);
149 activation_start_time_for_prerendering_ = activation_start;
150}
151
152void PageImpl::ActivateForPrerendering(
153 std::set<RenderViewHostImpl*>& render_view_hosts) {
154 base::OnceClosure did_activate_render_views =
155 base::BindOnce(&PageImpl::DidActivateAllRenderViewsForPrerendering,
156 weak_factory_.GetWeakPtr());
157
158 base::RepeatingClosure barrier = base::BarrierClosure(
159 render_view_hosts.size(), std::move(did_activate_render_views));
160 for (RenderViewHostImpl* rvh : render_view_hosts) {
161 base::TimeTicks navigation_start_to_send;
162 // Only send navigation_start to the RenderViewHost for the main frame to
163 // avoid sending the info cross-origin. Only this RenderViewHost needs the
164 // info, as we expect the other RenderViewHosts are made for cross-origin
165 // iframes which have not yet loaded their document. To the renderer, it
166 // just looks like an ongoing navigation is happening in the frame and has
167 // not yet committed. These RenderViews still need to know about activation
168 // so their documents are created in the non-prerendered state once their
169 // navigation is committed.
170 if (main_document_.GetRenderViewHost() == rvh)
171 navigation_start_to_send = *activation_start_time_for_prerendering_;
172
173 rvh->ActivatePrerenderedPage(navigation_start_to_send, barrier);
174 }
175
176 // Prepare each RenderFrameHostImpl in this Page for activation.
177 // TODO(https://crbug.com/1232528): Currently we check GetPage() below because
178 // RenderFrameHostImpls may be in a different Page, if, e.g., they are in an
179 // inner WebContents. These are in a different FrameTree which might not know
180 // it is being prerendered. We should teach these FrameTrees that they are
181 // being prerendered, or ban inner FrameTrees in a prerendering page.
182 main_document_.ForEachRenderFrameHost(base::BindRepeating(
183 [](PageImpl* page, RenderFrameHostImpl* rfh) {
184 if (&rfh->GetPage() != page)
185 return;
186 rfh->RendererWillActivateForPrerendering();
187 },
188 this));
189}
190
Sreeja Kamishetty81fbeefb2021-08-12 07:21:41191void PageImpl::MaybeDispatchLoadEventsOnPrerenderActivation() {
192 DCHECK(IsPrimary());
193
Sreeja Kamishetty0be3b1b2021-08-12 17:04:15194 // Dispatch LoadProgressChanged notification on activation with the
195 // prerender last load progress value if the value is not equal to
196 // blink::kFinalLoadProgress, whose notification is dispatched during call
197 // to DidStopLoading.
198 if (load_progress() != blink::kFinalLoadProgress)
199 main_document_.DidChangeLoadProgress(load_progress());
200
Sreeja Kamishettycd5560912021-11-22 11:54:53201 // Dispatch DocumentAvailableInMainFrame before dispatching following load
202 // complete events.
203 if (is_document_available_in_main_document())
204 main_document_.DocumentAvailableInMainFrame(uses_temporary_zoom_level());
205
Sreeja Kamishetty81fbeefb2021-08-12 07:21:41206 main_document_.ForEachRenderFrameHost(
207 base::BindRepeating([](RenderFrameHostImpl* rfh) {
208 rfh->MaybeDispatchDOMContentLoadedOnPrerenderActivation();
209 }));
210
211 if (is_on_load_completed_in_main_document())
212 main_document_.DocumentOnLoadCompleted();
213
214 main_document_.ForEachRenderFrameHost(
215 base::BindRepeating([](RenderFrameHostImpl* rfh) {
216 rfh->MaybeDispatchDidFinishLoadOnPrerenderActivation();
217 }));
218}
219
Matt Falkenhagenf78c2192021-07-24 02:01:43220void PageImpl::DidActivateAllRenderViewsForPrerendering() {
221 // Tell each RenderFrameHostImpl in this Page that activation finished.
222 main_document_.ForEachRenderFrameHost(base::BindRepeating(
223 [](PageImpl* page, RenderFrameHostImpl* rfh) {
224 if (&rfh->GetPage() != page)
225 return;
226 rfh->RendererDidActivateForPrerendering();
227 },
228 this));
229}
230
Sreeja Kamishetty1b5c1432021-06-25 11:32:59231RenderFrameHost& PageImpl::GetMainDocumentHelper() {
232 return main_document_;
233}
234
235RenderFrameHostImpl& PageImpl::GetMainDocument() const {
236 return main_document_;
237}
238
Yoshisato Yanagisawad016d62d32021-10-15 04:38:55239void PageImpl::UpdateBrowserControlsState(cc::BrowserControlsState constraints,
240 cc::BrowserControlsState current,
241 bool animate) {
242 // TODO(https://crbug.com/1154852): Asking for the LocalMainFrame interface
243 // before the RenderFrame is created is racy.
244 if (!GetMainDocument().IsRenderFrameCreated())
245 return;
246
247 GetMainDocument().GetAssociatedLocalMainFrame()->UpdateBrowserControlsState(
248 constraints, current, animate);
249}
250
Sreeja Kamishetty9e1d0e732021-05-27 18:20:09251} // namespace content