blob: 22adf681b9511060067ecbeece1dca33329fb4b7 [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
Jeremy Roman2d8dfe132021-07-06 20:51:2676void PageImpl::OnFirstVisuallyNonEmptyPaint() {
77 did_first_visually_non_empty_paint_ = true;
78 delegate_.OnFirstVisuallyNonEmptyPaint(*this);
79}
80
81void PageImpl::OnThemeColorChanged(const absl::optional<SkColor>& theme_color) {
82 main_document_theme_color_ = theme_color;
83 delegate_.OnThemeColorChanged(*this);
84}
85
86void PageImpl::DidChangeBackgroundColor(SkColor background_color,
87 bool color_adjust) {
88 main_document_background_color_ = background_color;
89 delegate_.OnBackgroundColorChanged(*this);
90 if (color_adjust) {
91 // <meta name="color-scheme" content="dark"> may pass the dark canvas
92 // background before the first paint in order to avoid flashing the white
93 // background in between loading documents. If we perform a navigation
94 // within the same renderer process, we keep the content background from the
95 // previous page while rendering is blocked in the new page, but for cross
96 // process navigations we would paint the default background (typically
97 // white) while the rendering is blocked.
98 main_document_.GetRenderWidgetHost()->GetView()->SetContentBackgroundColor(
99 background_color);
100 }
101}
102
103void PageImpl::SetContentsMimeType(std::string mime_type) {
104 contents_mime_type_ = std::move(mime_type);
105}
106
Lingqi Chidcf722442021-09-02 01:47:19107void PageImpl::OnTextAutosizerPageInfoChanged(
108 blink::mojom::TextAutosizerPageInfoPtr page_info) {
109 OPTIONAL_TRACE_EVENT0("content", "PageImpl::OnTextAutosizerPageInfoChanged");
110
111 // Keep a copy of |page_info| in case we create a new RenderView before
112 // the next update, so that the PageImpl can tell the newly created RenderView
113 // about the autosizer info.
114 text_autosizer_page_info_.main_frame_width = page_info->main_frame_width;
115 text_autosizer_page_info_.main_frame_layout_width =
116 page_info->main_frame_layout_width;
117 text_autosizer_page_info_.device_scale_adjustment =
118 page_info->device_scale_adjustment;
119
120 auto remote_frames_broadcast_callback = base::BindRepeating(
121 [](const blink::mojom::TextAutosizerPageInfo& page_info,
122 RenderFrameProxyHost* proxy_host) {
123 DCHECK(proxy_host);
124 proxy_host->GetAssociatedRemoteMainFrame()->UpdateTextAutosizerPageInfo(
125 page_info.Clone());
126 },
127 text_autosizer_page_info_);
128
129 main_document_.frame_tree()
130 ->root()
131 ->render_manager()
132 ->ExecuteRemoteFramesBroadcastMethod(
133 std::move(remote_frames_broadcast_callback),
134 main_document_.GetSiteInstance());
135}
136
Matt Falkenhagenf78c2192021-07-24 02:01:43137void PageImpl::SetActivationStartTime(base::TimeTicks activation_start) {
138 DCHECK(!activation_start_time_for_prerendering_);
139 activation_start_time_for_prerendering_ = activation_start;
140}
141
142void PageImpl::ActivateForPrerendering(
143 std::set<RenderViewHostImpl*>& render_view_hosts) {
144 base::OnceClosure did_activate_render_views =
145 base::BindOnce(&PageImpl::DidActivateAllRenderViewsForPrerendering,
146 weak_factory_.GetWeakPtr());
147
148 base::RepeatingClosure barrier = base::BarrierClosure(
149 render_view_hosts.size(), std::move(did_activate_render_views));
150 for (RenderViewHostImpl* rvh : render_view_hosts) {
151 base::TimeTicks navigation_start_to_send;
152 // Only send navigation_start to the RenderViewHost for the main frame to
153 // avoid sending the info cross-origin. Only this RenderViewHost needs the
154 // info, as we expect the other RenderViewHosts are made for cross-origin
155 // iframes which have not yet loaded their document. To the renderer, it
156 // just looks like an ongoing navigation is happening in the frame and has
157 // not yet committed. These RenderViews still need to know about activation
158 // so their documents are created in the non-prerendered state once their
159 // navigation is committed.
160 if (main_document_.GetRenderViewHost() == rvh)
161 navigation_start_to_send = *activation_start_time_for_prerendering_;
162
163 rvh->ActivatePrerenderedPage(navigation_start_to_send, barrier);
164 }
165
166 // Prepare each RenderFrameHostImpl in this Page for activation.
167 // TODO(https://crbug.com/1232528): Currently we check GetPage() below because
168 // RenderFrameHostImpls may be in a different Page, if, e.g., they are in an
169 // inner WebContents. These are in a different FrameTree which might not know
170 // it is being prerendered. We should teach these FrameTrees that they are
171 // being prerendered, or ban inner FrameTrees in a prerendering page.
172 main_document_.ForEachRenderFrameHost(base::BindRepeating(
173 [](PageImpl* page, RenderFrameHostImpl* rfh) {
174 if (&rfh->GetPage() != page)
175 return;
176 rfh->RendererWillActivateForPrerendering();
177 },
178 this));
179}
180
Sreeja Kamishetty81fbeefb2021-08-12 07:21:41181void PageImpl::MaybeDispatchLoadEventsOnPrerenderActivation() {
182 DCHECK(IsPrimary());
183
Sreeja Kamishetty0be3b1b2021-08-12 17:04:15184 // Dispatch LoadProgressChanged notification on activation with the
185 // prerender last load progress value if the value is not equal to
186 // blink::kFinalLoadProgress, whose notification is dispatched during call
187 // to DidStopLoading.
188 if (load_progress() != blink::kFinalLoadProgress)
189 main_document_.DidChangeLoadProgress(load_progress());
190
Sreeja Kamishetty81fbeefb2021-08-12 07:21:41191 main_document_.ForEachRenderFrameHost(
192 base::BindRepeating([](RenderFrameHostImpl* rfh) {
193 rfh->MaybeDispatchDOMContentLoadedOnPrerenderActivation();
194 }));
195
196 if (is_on_load_completed_in_main_document())
197 main_document_.DocumentOnLoadCompleted();
198
199 main_document_.ForEachRenderFrameHost(
200 base::BindRepeating([](RenderFrameHostImpl* rfh) {
201 rfh->MaybeDispatchDidFinishLoadOnPrerenderActivation();
202 }));
203}
204
Matt Falkenhagenf78c2192021-07-24 02:01:43205void PageImpl::DidActivateAllRenderViewsForPrerendering() {
206 // Tell each RenderFrameHostImpl in this Page that activation finished.
207 main_document_.ForEachRenderFrameHost(base::BindRepeating(
208 [](PageImpl* page, RenderFrameHostImpl* rfh) {
209 if (&rfh->GetPage() != page)
210 return;
211 rfh->RendererDidActivateForPrerendering();
212 },
213 this));
214}
215
Sreeja Kamishetty1b5c1432021-06-25 11:32:59216RenderFrameHost& PageImpl::GetMainDocumentHelper() {
217 return main_document_;
218}
219
220RenderFrameHostImpl& PageImpl::GetMainDocument() const {
221 return main_document_;
222}
223
Yoshisato Yanagisawad016d62d32021-10-15 04:38:55224void PageImpl::UpdateBrowserControlsState(cc::BrowserControlsState constraints,
225 cc::BrowserControlsState current,
226 bool animate) {
227 // TODO(https://crbug.com/1154852): Asking for the LocalMainFrame interface
228 // before the RenderFrame is created is racy.
229 if (!GetMainDocument().IsRenderFrameCreated())
230 return;
231
232 GetMainDocument().GetAssociatedLocalMainFrame()->UpdateBrowserControlsState(
233 constraints, current, animate);
234}
235
Sreeja Kamishetty9e1d0e732021-05-27 18:20:09236} // namespace content