Harkiran Bolaria | 8dec6f9 | 2021-12-07 14:57:12 | [diff] [blame] | 1 | // Copyright (c) 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/browsing_context_state.h" |
| 6 | |
Harkiran Bolaria | 2912a6b3 | 2022-02-22 16:43:45 | [diff] [blame] | 7 | #include "content/browser/renderer_host/frame_tree_node.h" |
| 8 | #include "content/browser/renderer_host/render_view_host_impl.h" |
| 9 | #include "content/common/content_navigation_policy.h" |
Harkiran Bolaria | 5ce2763 | 2022-01-20 15:05:05 | [diff] [blame] | 10 | #include "services/network/public/cpp/web_sandbox_flags.h" |
| 11 | #include "services/network/public/mojom/web_sandbox_flags.mojom.h" |
| 12 | |
Harkiran Bolaria | 8dec6f9 | 2021-12-07 14:57:12 | [diff] [blame] | 13 | namespace features { |
| 14 | const base::Feature kNewBrowsingContextStateOnBrowsingContextGroupSwap{ |
| 15 | "NewBrowsingContextStateOnBrowsingContextGroupSwap", |
| 16 | base::FEATURE_DISABLED_BY_DEFAULT}; |
| 17 | |
| 18 | BrowsingContextStateImplementationType GetBrowsingContextMode() { |
| 19 | if (base::FeatureList::IsEnabled( |
| 20 | kNewBrowsingContextStateOnBrowsingContextGroupSwap)) { |
| 21 | return BrowsingContextStateImplementationType:: |
| 22 | kSwapForCrossBrowsingInstanceNavigations; |
| 23 | } |
| 24 | |
| 25 | return BrowsingContextStateImplementationType:: |
| 26 | kLegacyOneToOneWithFrameTreeNode; |
| 27 | } |
| 28 | } // namespace features |
| 29 | |
| 30 | namespace content { |
| 31 | |
Harkiran Bolaria | 4eacb3a | 2021-12-13 20:03:47 | [diff] [blame] | 32 | BrowsingContextState::BrowsingContextState( |
| 33 | blink::mojom::FrameReplicationStatePtr replication_state) |
| 34 | : replication_state_(std::move(replication_state)) {} |
Harkiran Bolaria | 8dec6f9 | 2021-12-07 14:57:12 | [diff] [blame] | 35 | |
| 36 | BrowsingContextState::~BrowsingContextState() = default; |
Harkiran Bolaria | 4eacb3a | 2021-12-13 20:03:47 | [diff] [blame] | 37 | |
Harkiran Bolaria | 5ce2763 | 2022-01-20 15:05:05 | [diff] [blame] | 38 | RenderFrameProxyHost* BrowsingContextState::GetRenderFrameProxyHost( |
| 39 | SiteInstanceGroup* site_instance_group) const { |
| 40 | auto it = proxy_hosts_.find(site_instance_group->GetId()); |
| 41 | if (it != proxy_hosts_.end()) |
| 42 | return it->second.get(); |
| 43 | return nullptr; |
| 44 | } |
| 45 | |
Harkiran Bolaria | d22a1dca | 2022-02-22 17:01:12 | [diff] [blame^] | 46 | size_t BrowsingContextState::GetProxyCount() { |
| 47 | return proxy_hosts_.size(); |
| 48 | } |
| 49 | |
Harkiran Bolaria | 5ce2763 | 2022-01-20 15:05:05 | [diff] [blame] | 50 | bool BrowsingContextState::UpdateFramePolicyHeaders( |
| 51 | network::mojom::WebSandboxFlags sandbox_flags, |
| 52 | const blink::ParsedPermissionsPolicy& parsed_header) { |
| 53 | bool changed = false; |
| 54 | if (replication_state_->permissions_policy_header != parsed_header) { |
| 55 | replication_state_->permissions_policy_header = parsed_header; |
| 56 | changed = true; |
| 57 | } |
| 58 | // TODO(iclelland): Kill the renderer if sandbox flags is not a subset of the |
| 59 | // currently effective sandbox flags from the frame. https://crbug.com/740556 |
| 60 | network::mojom::WebSandboxFlags updated_flags = |
| 61 | sandbox_flags | replication_state_->frame_policy.sandbox_flags; |
| 62 | if (replication_state_->active_sandbox_flags != updated_flags) { |
| 63 | replication_state_->active_sandbox_flags = updated_flags; |
| 64 | changed = true; |
| 65 | } |
| 66 | // Notify any proxies if the policies have been changed. |
| 67 | if (changed) { |
| 68 | for (const auto& pair : proxy_hosts_) { |
| 69 | pair.second->GetAssociatedRemoteFrame()->DidSetFramePolicyHeaders( |
| 70 | replication_state_->active_sandbox_flags, |
| 71 | replication_state_->permissions_policy_header); |
| 72 | } |
| 73 | } |
| 74 | return changed; |
| 75 | } |
| 76 | |
| 77 | bool BrowsingContextState::CommitFramePolicy( |
| 78 | const blink::FramePolicy& new_frame_policy) { |
| 79 | // Documents create iframes, iframes host new documents. Both are associated |
| 80 | // with sandbox flags. They are required to be stricter or equal to their |
| 81 | // owner when they change, as we go down. |
| 82 | // TODO(https://crbug.com/1262061). Enforce the invariant mentioned above, |
| 83 | // once the interactions with fenced frame has been tested and clarified. |
| 84 | |
| 85 | bool did_change_flags = new_frame_policy.sandbox_flags != |
| 86 | replication_state_->frame_policy.sandbox_flags; |
| 87 | bool did_change_container_policy = |
| 88 | new_frame_policy.container_policy != |
| 89 | replication_state_->frame_policy.container_policy; |
| 90 | bool did_change_required_document_policy = |
| 91 | new_frame_policy.required_document_policy != |
| 92 | replication_state_->frame_policy.required_document_policy; |
| 93 | DCHECK_EQ(new_frame_policy.is_fenced, |
| 94 | replication_state_->frame_policy.is_fenced); |
| 95 | |
Harkiran Bolaria | 4eacb3a | 2021-12-13 20:03:47 | [diff] [blame] | 96 | if (did_change_flags) { |
| 97 | replication_state_->frame_policy.sandbox_flags = |
| 98 | new_frame_policy.sandbox_flags; |
| 99 | } |
| 100 | if (did_change_container_policy) { |
| 101 | replication_state_->frame_policy.container_policy = |
| 102 | new_frame_policy.container_policy; |
| 103 | } |
| 104 | if (did_change_required_document_policy) { |
| 105 | replication_state_->frame_policy.required_document_policy = |
| 106 | new_frame_policy.required_document_policy; |
| 107 | } |
Harkiran Bolaria | e352143 | 2021-12-14 11:27:43 | [diff] [blame] | 108 | |
Harkiran Bolaria | 5ce2763 | 2022-01-20 15:05:05 | [diff] [blame] | 109 | UpdateFramePolicyHeaders(new_frame_policy.sandbox_flags, |
| 110 | replication_state_->permissions_policy_header); |
| 111 | return did_change_flags || did_change_container_policy || |
| 112 | did_change_required_document_policy; |
Harkiran Bolaria | 7fdb4c64 | 2021-12-20 12:47:00 | [diff] [blame] | 113 | } |
| 114 | |
Harkiran Bolaria | e352143 | 2021-12-14 11:27:43 | [diff] [blame] | 115 | void BrowsingContextState::SetCurrentOrigin( |
| 116 | const url::Origin& origin, |
| 117 | bool is_potentially_trustworthy_unique_origin) { |
| 118 | if (origin.IsSameOriginWith(replication_state_->origin) && |
| 119 | replication_state_->has_potentially_trustworthy_unique_origin == |
| 120 | is_potentially_trustworthy_unique_origin) { |
| 121 | return; |
| 122 | } |
| 123 | |
| 124 | for (const auto& pair : proxy_hosts_) { |
| 125 | pair.second->GetAssociatedRemoteFrame()->SetReplicatedOrigin( |
| 126 | origin, is_potentially_trustworthy_unique_origin); |
| 127 | } |
| 128 | |
| 129 | replication_state_->origin = origin; |
| 130 | replication_state_->has_potentially_trustworthy_unique_origin = |
| 131 | is_potentially_trustworthy_unique_origin; |
| 132 | } |
| 133 | |
| 134 | void BrowsingContextState::SetInsecureRequestPolicy( |
| 135 | blink::mojom::InsecureRequestPolicy policy) { |
| 136 | if (policy == replication_state_->insecure_request_policy) |
| 137 | return; |
| 138 | for (const auto& pair : proxy_hosts_) { |
| 139 | pair.second->GetAssociatedRemoteFrame()->EnforceInsecureRequestPolicy( |
| 140 | policy); |
| 141 | } |
| 142 | replication_state_->insecure_request_policy = policy; |
| 143 | } |
| 144 | |
| 145 | void BrowsingContextState::SetInsecureNavigationsSet( |
| 146 | const std::vector<uint32_t>& insecure_navigations_set) { |
| 147 | DCHECK(std::is_sorted(insecure_navigations_set.begin(), |
| 148 | insecure_navigations_set.end())); |
| 149 | if (insecure_navigations_set == replication_state_->insecure_navigations_set) |
| 150 | return; |
| 151 | for (const auto& pair : proxy_hosts_) { |
| 152 | pair.second->GetAssociatedRemoteFrame()->EnforceInsecureNavigationsSet( |
| 153 | insecure_navigations_set); |
| 154 | } |
| 155 | replication_state_->insecure_navigations_set = insecure_navigations_set; |
| 156 | } |
| 157 | |
| 158 | void BrowsingContextState::OnSetHadStickyUserActivationBeforeNavigation( |
| 159 | bool value) { |
| 160 | for (const auto& pair : proxy_hosts_) { |
| 161 | pair.second->GetAssociatedRemoteFrame() |
| 162 | ->SetHadStickyUserActivationBeforeNavigation(value); |
| 163 | } |
| 164 | replication_state_->has_received_user_gesture_before_nav = value; |
| 165 | } |
| 166 | |
| 167 | void BrowsingContextState::SetIsAdSubframe(bool is_ad_subframe) { |
| 168 | if (is_ad_subframe == replication_state_->is_ad_subframe) |
| 169 | return; |
| 170 | |
| 171 | replication_state_->is_ad_subframe = is_ad_subframe; |
| 172 | for (const auto& pair : proxy_hosts_) { |
| 173 | pair.second->GetAssociatedRemoteFrame()->SetReplicatedIsAdSubframe( |
| 174 | is_ad_subframe); |
| 175 | } |
| 176 | } |
| 177 | |
Harkiran Bolaria | e182a594 | 2021-12-20 17:23:31 | [diff] [blame] | 178 | void BrowsingContextState::ActiveFrameCountIsZero( |
Sharon Yang | a2fe85e | 2022-02-09 21:38:29 | [diff] [blame] | 179 | SiteInstanceGroup* site_instance_group) { |
| 180 | // |site_instance_group| no longer contains any active RenderFrameHosts, so we |
| 181 | // don't need to maintain a proxy there anymore. |
| 182 | RenderFrameProxyHost* proxy = GetRenderFrameProxyHost(site_instance_group); |
Harkiran Bolaria | e182a594 | 2021-12-20 17:23:31 | [diff] [blame] | 183 | CHECK(proxy); |
| 184 | |
Sharon Yang | a2fe85e | 2022-02-09 21:38:29 | [diff] [blame] | 185 | DeleteRenderFrameProxyHost(site_instance_group); |
Harkiran Bolaria | e182a594 | 2021-12-20 17:23:31 | [diff] [blame] | 186 | } |
| 187 | |
| 188 | void BrowsingContextState::RenderProcessGone( |
Sharon Yang | a2fe85e | 2022-02-09 21:38:29 | [diff] [blame] | 189 | SiteInstanceGroup* site_instance_group, |
Harkiran Bolaria | e182a594 | 2021-12-20 17:23:31 | [diff] [blame] | 190 | const ChildProcessTerminationInfo& info) { |
Sharon Yang | a2fe85e | 2022-02-09 21:38:29 | [diff] [blame] | 191 | GetRenderFrameProxyHost(site_instance_group) |
| 192 | ->SetRenderFrameProxyCreated(false); |
Harkiran Bolaria | e182a594 | 2021-12-20 17:23:31 | [diff] [blame] | 193 | } |
| 194 | |
| 195 | void BrowsingContextState::DeleteRenderFrameProxyHost( |
Sharon Yang | a2fe85e | 2022-02-09 21:38:29 | [diff] [blame] | 196 | SiteInstanceGroup* site_instance_group) { |
| 197 | site_instance_group->RemoveObserver(this); |
| 198 | proxy_hosts_.erase(site_instance_group->GetId()); |
Harkiran Bolaria | e182a594 | 2021-12-20 17:23:31 | [diff] [blame] | 199 | } |
| 200 | |
Harkiran Bolaria | 5ce2763 | 2022-01-20 15:05:05 | [diff] [blame] | 201 | void BrowsingContextState::SendFramePolicyUpdatesToProxies( |
| 202 | SiteInstance* parent_site_instance, |
| 203 | const blink::FramePolicy& frame_policy) { |
| 204 | // Notify all of the frame's proxies about updated policies, excluding |
| 205 | // the parent process since it already knows the latest state. |
| 206 | for (const auto& pair : proxy_hosts_) { |
| 207 | if (pair.second->GetSiteInstance() != parent_site_instance) { |
| 208 | pair.second->GetAssociatedRemoteFrame()->DidUpdateFramePolicy( |
| 209 | frame_policy); |
| 210 | } |
| 211 | } |
| 212 | } |
| 213 | |
Harkiran Bolaria | 2912a6b3 | 2022-02-22 16:43:45 | [diff] [blame] | 214 | RenderFrameProxyHost* BrowsingContextState::CreateRenderFrameProxyHost( |
| 215 | SiteInstance* site_instance, |
| 216 | const scoped_refptr<RenderViewHostImpl>& rvh, |
| 217 | FrameTreeNode* frame_tree_node) { |
| 218 | if (features::GetBrowsingContextMode() == |
| 219 | features::BrowsingContextStateImplementationType:: |
| 220 | kLegacyOneToOneWithFrameTreeNode) { |
| 221 | DCHECK_EQ(this, |
| 222 | frame_tree_node->current_frame_host()->browsing_context_state()); |
| 223 | } |
| 224 | |
| 225 | auto site_instance_group_id = |
| 226 | static_cast<SiteInstanceImpl*>(site_instance)->group()->GetId(); |
| 227 | CHECK(proxy_hosts_.find(site_instance_group_id) == proxy_hosts_.end()) |
| 228 | << "A proxy already existed for this SiteInstanceGroup."; |
| 229 | RenderFrameProxyHost* proxy_host = |
| 230 | new RenderFrameProxyHost(site_instance, std::move(rvh), frame_tree_node); |
| 231 | proxy_hosts_[site_instance_group_id] = base::WrapUnique(proxy_host); |
| 232 | static_cast<SiteInstanceImpl*>(site_instance)->group()->AddObserver(this); |
| 233 | |
| 234 | TRACE_EVENT_INSTANT( |
| 235 | "navigation", "BrowsingContextState::CreateRenderFrameProxyHost", |
| 236 | perfetto::protos::pbzero::ChromeTrackEvent::kRenderFrameProxyHost, |
| 237 | *proxy_host); |
| 238 | return proxy_host; |
| 239 | } |
| 240 | |
Harkiran Bolaria | 8dec6f9 | 2021-12-07 14:57:12 | [diff] [blame] | 241 | } // namespace content |