blob: 1d14e843f56eca5ee1f522ad8d3785cbd222135a [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"
Jeremy Roman4bd173d2021-06-17 00:05:448#include "content/browser/manifest/manifest_manager_host.h"
Dave Tapuska9c9afe82021-06-22 19:07:459#include "content/browser/renderer_host/frame_tree_node.h"
Jeremy Roman2d8dfe132021-07-06 20:51:2610#include "content/browser/renderer_host/page_delegate.h"
Julie Jeongeun Kim9e204512021-06-24 07:28:5411#include "content/browser/renderer_host/render_frame_host_delegate.h"
Sreeja Kamishetty9e1d0e732021-05-27 18:20:0912#include "content/browser/renderer_host/render_frame_host_impl.h"
Jeremy Roman2d8dfe132021-07-06 20:51:2613#include "content/browser/renderer_host/render_view_host_delegate.h"
Matt Falkenhagenf78c2192021-07-24 02:01:4314#include "content/browser/renderer_host/render_view_host_impl.h"
Jeremy Roman2d8dfe132021-07-06 20:51:2615#include "content/public/browser/render_view_host.h"
Sreeja Kamishetty0be3b1b2021-08-12 17:04:1516#include "third_party/blink/public/common/loader/loader_constants.h"
Jeremy Roman2d8dfe132021-07-06 20:51:2617#include "third_party/perfetto/include/perfetto/tracing/traced_value.h"
Sreeja Kamishetty9e1d0e732021-05-27 18:20:0918
19namespace content {
Jeremy Roman2d8dfe132021-07-06 20:51:2620
21PageImpl::PageImpl(RenderFrameHostImpl& rfh, PageDelegate& delegate)
22 : main_document_(rfh), delegate_(delegate) {}
Sreeja Kamishetty9e1d0e732021-05-27 18:20:0923
Sreeja Kamishetty1b5c1432021-06-25 11:32:5924PageImpl::~PageImpl() {
25 // As SupportsUserData is a base class of PageImpl, Page members will be
26 // destroyed before running ~SupportsUserData, which would delete the
27 // associated PageUserData objects. Avoid this by calling ClearAllUserData
28 // explicitly here to ensure that the PageUserData destructors can access
29 // associated Page object.
30 ClearAllUserData();
31}
Sreeja Kamishetty9e1d0e732021-05-27 18:20:0932
Julie Jeongeun Kim9e204512021-06-24 07:28:5433const absl::optional<GURL>& PageImpl::GetManifestUrl() const {
Sreeja Kamishetty7c91ab22021-06-03 13:29:5234 return manifest_url_;
35}
36
Jeremy Roman4bd173d2021-06-17 00:05:4437void PageImpl::GetManifest(GetManifestCallback callback) {
38 ManifestManagerHost* manifest_manager_host =
39 ManifestManagerHost::GetOrCreateForCurrentDocument(&main_document_);
40 manifest_manager_host->GetManifest(std::move(callback));
41}
42
Dave Tapuska9c9afe82021-06-22 19:07:4543bool PageImpl::IsPrimary() {
Dominic Farolino4bc10ee2021-08-31 00:37:3644 // TODO(1244137): Check for portals as well, once they are migrated to MPArch.
45 if (main_document_.IsFencedFrameRoot())
46 return false;
47
Dave Tapuska9c9afe82021-06-22 19:07:4548 return main_document_.lifecycle_state() ==
Khushalc5eaf222021-06-30 20:15:4849 RenderFrameHostImpl::LifecycleStateImpl::kActive;
Dave Tapuska9c9afe82021-06-22 19:07:4550}
51
Julie Jeongeun Kim9e204512021-06-24 07:28:5452void PageImpl::UpdateManifestUrl(const GURL& manifest_url) {
53 manifest_url_ = manifest_url;
54
55 // If |main_document_| is not active, the notification is sent on the page
56 // activation.
57 if (!main_document_.IsActive())
58 return;
59
60 main_document_.delegate()->OnManifestUrlChanged(*this);
61}
62
Jeremy Roman2d8dfe132021-07-06 20:51:2663void PageImpl::WriteIntoTrace(perfetto::TracedValue context) {
64 auto dict = std::move(context).WriteDictionary();
65 dict.Add("main_document", main_document_);
66}
67
68void PageImpl::OnFirstVisuallyNonEmptyPaint() {
69 did_first_visually_non_empty_paint_ = true;
70 delegate_.OnFirstVisuallyNonEmptyPaint(*this);
71}
72
73void PageImpl::OnThemeColorChanged(const absl::optional<SkColor>& theme_color) {
74 main_document_theme_color_ = theme_color;
75 delegate_.OnThemeColorChanged(*this);
76}
77
78void PageImpl::DidChangeBackgroundColor(SkColor background_color,
79 bool color_adjust) {
80 main_document_background_color_ = background_color;
81 delegate_.OnBackgroundColorChanged(*this);
82 if (color_adjust) {
83 // <meta name="color-scheme" content="dark"> may pass the dark canvas
84 // background before the first paint in order to avoid flashing the white
85 // background in between loading documents. If we perform a navigation
86 // within the same renderer process, we keep the content background from the
87 // previous page while rendering is blocked in the new page, but for cross
88 // process navigations we would paint the default background (typically
89 // white) while the rendering is blocked.
90 main_document_.GetRenderWidgetHost()->GetView()->SetContentBackgroundColor(
91 background_color);
92 }
93}
94
95void PageImpl::SetContentsMimeType(std::string mime_type) {
96 contents_mime_type_ = std::move(mime_type);
97}
98
Matt Falkenhagenf78c2192021-07-24 02:01:4399void PageImpl::SetActivationStartTime(base::TimeTicks activation_start) {
100 DCHECK(!activation_start_time_for_prerendering_);
101 activation_start_time_for_prerendering_ = activation_start;
102}
103
104void PageImpl::ActivateForPrerendering(
105 std::set<RenderViewHostImpl*>& render_view_hosts) {
106 base::OnceClosure did_activate_render_views =
107 base::BindOnce(&PageImpl::DidActivateAllRenderViewsForPrerendering,
108 weak_factory_.GetWeakPtr());
109
110 base::RepeatingClosure barrier = base::BarrierClosure(
111 render_view_hosts.size(), std::move(did_activate_render_views));
112 for (RenderViewHostImpl* rvh : render_view_hosts) {
113 base::TimeTicks navigation_start_to_send;
114 // Only send navigation_start to the RenderViewHost for the main frame to
115 // avoid sending the info cross-origin. Only this RenderViewHost needs the
116 // info, as we expect the other RenderViewHosts are made for cross-origin
117 // iframes which have not yet loaded their document. To the renderer, it
118 // just looks like an ongoing navigation is happening in the frame and has
119 // not yet committed. These RenderViews still need to know about activation
120 // so their documents are created in the non-prerendered state once their
121 // navigation is committed.
122 if (main_document_.GetRenderViewHost() == rvh)
123 navigation_start_to_send = *activation_start_time_for_prerendering_;
124
125 rvh->ActivatePrerenderedPage(navigation_start_to_send, barrier);
126 }
127
128 // Prepare each RenderFrameHostImpl in this Page for activation.
129 // TODO(https://crbug.com/1232528): Currently we check GetPage() below because
130 // RenderFrameHostImpls may be in a different Page, if, e.g., they are in an
131 // inner WebContents. These are in a different FrameTree which might not know
132 // it is being prerendered. We should teach these FrameTrees that they are
133 // being prerendered, or ban inner FrameTrees in a prerendering page.
134 main_document_.ForEachRenderFrameHost(base::BindRepeating(
135 [](PageImpl* page, RenderFrameHostImpl* rfh) {
136 if (&rfh->GetPage() != page)
137 return;
138 rfh->RendererWillActivateForPrerendering();
139 },
140 this));
141}
142
Sreeja Kamishetty81fbeefb2021-08-12 07:21:41143void PageImpl::MaybeDispatchLoadEventsOnPrerenderActivation() {
144 DCHECK(IsPrimary());
145
Sreeja Kamishetty0be3b1b2021-08-12 17:04:15146 // Dispatch LoadProgressChanged notification on activation with the
147 // prerender last load progress value if the value is not equal to
148 // blink::kFinalLoadProgress, whose notification is dispatched during call
149 // to DidStopLoading.
150 if (load_progress() != blink::kFinalLoadProgress)
151 main_document_.DidChangeLoadProgress(load_progress());
152
Sreeja Kamishetty81fbeefb2021-08-12 07:21:41153 main_document_.ForEachRenderFrameHost(
154 base::BindRepeating([](RenderFrameHostImpl* rfh) {
155 rfh->MaybeDispatchDOMContentLoadedOnPrerenderActivation();
156 }));
157
158 if (is_on_load_completed_in_main_document())
159 main_document_.DocumentOnLoadCompleted();
160
161 main_document_.ForEachRenderFrameHost(
162 base::BindRepeating([](RenderFrameHostImpl* rfh) {
163 rfh->MaybeDispatchDidFinishLoadOnPrerenderActivation();
164 }));
165}
166
Matt Falkenhagenf78c2192021-07-24 02:01:43167void PageImpl::DidActivateAllRenderViewsForPrerendering() {
168 // Tell each RenderFrameHostImpl in this Page that activation finished.
169 main_document_.ForEachRenderFrameHost(base::BindRepeating(
170 [](PageImpl* page, RenderFrameHostImpl* rfh) {
171 if (&rfh->GetPage() != page)
172 return;
173 rfh->RendererDidActivateForPrerendering();
174 },
175 this));
176}
177
Sreeja Kamishetty1b5c1432021-06-25 11:32:59178RenderFrameHost& PageImpl::GetMainDocumentHelper() {
179 return main_document_;
180}
181
182RenderFrameHostImpl& PageImpl::GetMainDocument() const {
183 return main_document_;
184}
185
Sreeja Kamishetty9e1d0e732021-05-27 18:20:09186} // namespace content