summaryrefslogtreecommitdiff
path: root/chromium/content/browser/frame_host/navigation_request.cc
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2020-10-29 10:46:47 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2020-11-02 12:02:10 +0000
commit99677208ff3b216fdfec551fbe548da5520cd6fb (patch)
tree476a4865c10320249360e859d8fdd3e01833b03a /chromium/content/browser/frame_host/navigation_request.cc
parentc30a6232df03e1efbd9f3b226777b07e087a1122 (diff)
downloadqtwebengine-chromium-99677208ff3b216fdfec551fbe548da5520cd6fb.tar.gz
BASELINE: Update Chromium to 86.0.4240.124
Change-Id: Ide0ff151e94cd665ae6521a446995d34a9d1d644 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/content/browser/frame_host/navigation_request.cc')
-rw-r--r--chromium/content/browser/frame_host/navigation_request.cc755
1 files changed, 447 insertions, 308 deletions
diff --git a/chromium/content/browser/frame_host/navigation_request.cc b/chromium/content/browser/frame_host/navigation_request.cc
index 5757ad84edb..2c8589e2d7d 100644
--- a/chromium/content/browser/frame_host/navigation_request.cc
+++ b/chromium/content/browser/frame_host/navigation_request.cc
@@ -23,6 +23,7 @@
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/system/sys_info.h"
+#include "base/trace_event/trace_conversion_helper.h"
#include "build/build_config.h"
#include "content/browser/appcache/appcache_navigation_handle.h"
#include "content/browser/appcache/chrome_appcache_service.h"
@@ -101,8 +102,10 @@
#include "net/url_request/redirect_info.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
#include "services/network/public/cpp/content_security_policy/content_security_policy.h"
+#include "services/network/public/cpp/cross_origin_embedder_policy.h"
#include "services/network/public/cpp/cross_origin_resource_policy.h"
#include "services/network/public/cpp/features.h"
+#include "services/network/public/cpp/ip_address_space_util.h"
#include "services/network/public/cpp/is_potentially_trustworthy.h"
#include "services/network/public/cpp/resource_request_body.h"
#include "services/network/public/cpp/url_loader_completion_status.h"
@@ -120,6 +123,7 @@
#include "third_party/blink/public/mojom/web_feature/web_feature.mojom.h"
#include "third_party/blink/public/platform/resource_request_blocked_reason.h"
#include "third_party/blink/public/platform/web_mixed_content_context_type.h"
+#include "url/origin.h"
#include "url/url_constants.h"
namespace content {
@@ -276,15 +280,12 @@ void AddAdditionalRequestHeaders(
if (!url.SchemeIsHTTPOrHTTPS())
return;
- bool is_reload =
- navigation_type == mojom::NavigationType::RELOAD ||
- navigation_type == mojom::NavigationType::RELOAD_BYPASSING_CACHE ||
- navigation_type == mojom::NavigationType::RELOAD_ORIGINAL_REQUEST_URL;
+ bool is_reload = NavigationTypeUtils::IsReload(navigation_type);
blink::mojom::RendererPreferences render_prefs =
frame_tree_node->render_manager()
->current_host()
->GetDelegate()
- ->GetRendererPrefs(browser_context);
+ ->GetRendererPrefs();
UpdateAdditionalHeadersForBrowserInitiatedRequest(headers, browser_context,
is_reload, render_prefs);
@@ -313,8 +314,8 @@ void AddAdditionalRequestHeaders(
origin_header_value.Serialize());
}
- if (base::FeatureList::IsEnabled(features::kDocumentPolicy)) {
- const blink::DocumentPolicy::FeatureState& required_policy =
+ if (base::FeatureList::IsEnabled(features::kDocumentPolicyNegotiation)) {
+ const blink::DocumentPolicyFeatureState& required_policy =
frame_tree_node->effective_frame_policy().required_document_policy;
if (!required_policy.empty()) {
base::Optional<std::string> policy_header =
@@ -480,7 +481,8 @@ void RecordReadyToCommitMetrics(
{
ChildProcessSecurityPolicyImpl* policy =
ChildProcessSecurityPolicyImpl::GetInstance();
- GURL process_lock = policy->GetOriginLock(new_rfh->GetProcess()->GetID());
+ ProcessLock process_lock =
+ policy->GetProcessLock(new_rfh->GetProcess()->GetID());
UMA_HISTOGRAM_BOOLEAN("Navigation.IsLockedProcess",
!process_lock.is_empty());
if (common_params.url.SchemeIsHTTPOrHTTPS()) {
@@ -547,13 +549,6 @@ void RecordReadyToCommitMetrics(
}
}
-// Use this to get a new unique ID for a NavigationHandle during construction.
-// The returned ID is guaranteed to be nonzero (zero is the "no ID" indicator).
-int64_t CreateUniqueHandleID() {
- static int64_t unique_id_counter = 0;
- return ++unique_id_counter;
-}
-
// Given an net::IPAddress and a CSP set, this function calculates the
// IPAddressSpace which should be associated with the document this navigation
// eventually commits into.
@@ -574,16 +569,7 @@ network::mojom::IPAddressSpace CalculateIPAddressSpace(
return network::mojom::IPAddressSpace::kPublic;
// Otherwise, calculate the address space via the provided IP address.
- if (!ip.IsValid())
- return network::mojom::IPAddressSpace::kUnknown;
-
- if (ip.IsLoopback())
- return network::mojom::IPAddressSpace::kLocal;
-
- if (!ip.IsPubliclyRoutable())
- return network::mojom::IPAddressSpace::kPrivate;
-
- return network::mojom::IPAddressSpace::kPublic;
+ return network::IPAddressToIPAddressSpace(ip);
}
// Convert the navigation type to the appropriate cross-document one.
@@ -646,8 +632,9 @@ class ScopedNavigationRequestCrashKeys {
void EnterChildTraceEvent(const char* name, NavigationRequest* request) {
// Tracing no longer outputs the end event name, so we can simply pass an
// empty string here.
- TRACE_EVENT_NESTABLE_ASYNC_END0("navigation", "", request);
- TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("navigation", name, request);
+ TRACE_EVENT_NESTABLE_ASYNC_END0("navigation", "", request->GetNavigationId());
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("navigation", name,
+ request->GetNavigationId());
}
// Start a new nested async event with the given name and args.
@@ -658,9 +645,9 @@ void EnterChildTraceEvent(const char* name,
ArgType arg_value) {
// Tracing no longer outputs the end event name, so we can simply pass an
// empty string here.
- TRACE_EVENT_NESTABLE_ASYNC_END0("navigation", "", request);
- TRACE_EVENT_NESTABLE_ASYNC_BEGIN1("navigation", name, request, arg_name,
- arg_value);
+ TRACE_EVENT_NESTABLE_ASYNC_END0("navigation", "", request->GetNavigationId());
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(
+ "navigation", name, request->GetNavigationId(), arg_name, arg_value);
}
network::mojom::RequestDestination GetDestinationFromFrameTreeNode(
@@ -692,76 +679,53 @@ network::mojom::RequestDestination GetDestinationFromFrameTreeNode(
}
}
-// This function implements the COOP matching algorithm as detailed in [1].
-// Note that COEP is also provided since the COOP enum does not have a
-// "same-origin + COEP" value.
-// [1] https://gist.github.com/annevk/6f2dd8c79c77123f39797f6bdac43f3e
-bool CrossOriginOpenerPolicyMatch(
- network::mojom::CrossOriginOpenerPolicyValue initiator_coop,
- network::mojom::CrossOriginEmbedderPolicyValue initiator_coep,
- const url::Origin& initiator_origin,
- network::mojom::CrossOriginOpenerPolicyValue destination_coop,
- network::mojom::CrossOriginEmbedderPolicyValue destination_coep,
- const url::Origin& destination_origin) {
- if (initiator_coop != destination_coop)
- return false;
- if (initiator_coop ==
- network::mojom::CrossOriginOpenerPolicyValue::kUnsafeNone) {
- return true;
- }
- if (initiator_coop ==
- network::mojom::CrossOriginOpenerPolicyValue::kSameOrigin &&
- initiator_coep != destination_coep) {
- return false;
- }
- if (!initiator_origin.IsSameOriginWith(destination_origin))
- return false;
- return true;
-}
+url::Origin GetOriginForURLLoaderFactoryUnchecked(
+ NavigationRequest* navigation_request) {
+ DCHECK(navigation_request);
-// This function returns whether the BrowsingInstance should change following
-// COOP rules defined in:
-// https://gist.github.com/annevk/6f2dd8c79c77123f39797f6bdac43f3e#changes-to-navigation
-bool ShouldSwapBrowsingInstanceForCrossOriginOpenerPolicy(
- network::mojom::CrossOriginOpenerPolicyValue initiator_coop,
- network::mojom::CrossOriginEmbedderPolicyValue initiator_coep,
- const url::Origin& initiator_origin,
- bool is_initiator_aboutblank,
- network::mojom::CrossOriginOpenerPolicyValue destination_coop,
- network::mojom::CrossOriginEmbedderPolicyValue destination_coep,
- const url::Origin& destination_origin) {
- using network::mojom::CrossOriginEmbedderPolicyValue;
- using network::mojom::CrossOriginOpenerPolicyValue;
+ // Check if this is loadDataWithBaseUrl (which needs special treatment).
+ auto& common_params = navigation_request->common_params();
+ if (NavigationRequest::IsLoadDataWithBaseURL(common_params)) {
+ // A (potentially attacker-controlled) renderer process should not be able
+ // to use loadDataWithBaseUrl code path to initiate fetches on behalf of a
+ // victim origin (fetches controlled by attacker-provided
+ // |common_params.url| data: URL in a victim's origin from the
+ // attacker-provided |common_params.base_url_for_data_url|). Browser
+ // process should verify that |common_params.base_url_for_data_url| is empty
+ // for all renderer-initiated navigations (e.g. see
+ // VerifyBeginNavigationCommonParams), but as a defense-in-depth this is
+ // also asserted below.
+ CHECK(navigation_request->browser_initiated());
- if (!base::FeatureList::IsEnabled(
- network::features::kCrossOriginOpenerPolicy))
- return false;
-
- // If policies match there is no reason to switch BrowsingInstances.
- if (CrossOriginOpenerPolicyMatch(initiator_coop, initiator_coep,
- initiator_origin, destination_coop,
- destination_coep, destination_origin)) {
- return false;
+ // loadDataWithBaseUrl submits a data: |common_params.url| (which has a
+ // opaque origin), but commits that URL as if it came from
+ // |common_params.base_url_for_data_url|. See also
+ // https://crbug.com/976253.
+ return url::Origin::Create(common_params.base_url_for_data_url);
}
- // "same-origin-allow-popups" is used to stay in the same BrowsingInstance
- // despite COOP mismatch. This case is defined in the spec [1] as follow.
- // ```
- // If the result of matching currentCOOP, currentOrigin, potentialCOOP, and
- // potentialOrigin is false and one of the following is false:
- // - doc is the initial about:blank document
- // - currentCOOP is "same-origin-allow-popups"
- // - potentialCOOP is "unsafe-none"
- // Then create a new browsing context group.
- // ```
- // [1]
- // https://gist.github.com/annevk/6f2dd8c79c77123f39797f6bdac43f3e#changes-to-navigation
- if (is_initiator_aboutblank &&
- initiator_coop == CrossOriginOpenerPolicyValue::kSameOriginAllowPopups &&
- destination_coop == CrossOriginOpenerPolicyValue::kUnsafeNone) {
- return false;
+ // MHTML frames should commit as a opaque origin (and should not be able to
+ // make network requests on behalf of the real origin).
+ //
+ // TODO(lukasza): Cover MHTML main frames here.
+ if (navigation_request->IsForMhtmlSubframe())
+ return url::Origin();
+
+ // Srcdoc subframes need to inherit their origin from their parent frame.
+ if (navigation_request->GetURL().IsAboutSrcdoc()) {
+ // Srcdoc navigations in main frames should be blocked before this function
+ // is called. This should guarantee existence of a parent here.
+ RenderFrameHostImpl* parent =
+ navigation_request->frame_tree_node()->parent();
+ DCHECK(parent);
+ return parent->GetLastCommittedOrigin();
}
- return true;
+
+ // In cases not covered above, URLLoaderFactory should be associated with the
+ // origin of |common_params.url| and/or |common_params.initiator_origin|.
+ return url::Origin::Resolve(
+ common_params.url,
+ common_params.initiator_origin.value_or(url::Origin()));
}
} // namespace
@@ -796,7 +760,9 @@ std::unique_ptr<NavigationRequest> NavigationRequest::CreateBrowserInitiated(
GURL() /* client_side_redirect_url */,
base::nullopt /* devtools_initiator_info */,
false /* force_ignore_site_for_cookies */,
- nullptr /* trust_token_params */, impression);
+ nullptr /* trust_token_params */, impression,
+ base::TimeTicks() /* renderer_before_unload_start */,
+ base::TimeTicks() /* renderer_before_unload_end */);
// Shift-Reload forces bypassing caches and service workers.
if (common_params->navigation_type ==
@@ -912,7 +878,12 @@ std::unique_ptr<NavigationRequest> NavigationRequest::CreateRendererInitiated(
GURL() /* base_url_override_for_web_bundle */,
frame_tree_node->pending_frame_policy(),
std::vector<std::string>() /* force_enabled_origin_trials */,
- false /* origin_isolation_restricted */);
+ false /* origin_isolated */,
+ std::vector<
+ network::mojom::WebClientHintsType>() /* enabled_client_hints */,
+ false /* is_cross_browsing_instance */,
+ std::vector<std::string>() /* forced_content_security_policies */,
+ nullptr /* old_page_info */);
// CreateRendererInitiated() should only be triggered when the navigation is
// initiated by a frame in the same process.
@@ -965,11 +936,12 @@ std::unique_ptr<NavigationRequest> NavigationRequest::CreateForCommit(
is_same_document ? mojom::NavigationType::SAME_DOCUMENT
: mojom::NavigationType::DIFFERENT_DOCUMENT,
NavigationDownloadPolicy(), params.should_replace_current_entry,
- params.base_url, params.base_url, PREVIEWS_UNSPECIFIED,
- base::TimeTicks::Now(), params.method, nullptr,
- network::mojom::SourceLocation::New(),
+ params.base_url, params.base_url,
+ blink::PreviewsTypes::PREVIEWS_UNSPECIFIED, base::TimeTicks::Now(),
+ params.method, nullptr, network::mojom::SourceLocation::New(),
false /* started_from_context_menu */,
- params.gesture == NavigationGestureUser, CreateInitiatorCSPInfo(),
+ params.gesture == NavigationGestureUser,
+ false /* has_text_fragment_token */, CreateInitiatorCSPInfo(),
std::vector<int>() /* initiator_origin_trial_features */,
std::string() /* href_translate */,
false /* is_history_navigation_in_new_child_frame */,
@@ -1000,7 +972,12 @@ std::unique_ptr<NavigationRequest> NavigationRequest::CreateForCommit(
GURL() /* base_url_override_for_web_bundle */,
frame_tree_node->pending_frame_policy(),
std::vector<std::string>() /* force_enabled_origin_trials */,
- false /* origin_isolation_restricted */
+ false /* origin_isolated */,
+ std::vector<
+ network::mojom::WebClientHintsType>() /* enabled_client_hints */,
+ false /* is_cross_browsing_instance */,
+ std::vector<std::string>() /* forced_content_security_policies */,
+ nullptr /* old_page_info */
);
mojom::BeginNavigationParamsPtr begin_params =
mojom::BeginNavigationParams::New();
@@ -1023,6 +1000,10 @@ std::unique_ptr<NavigationRequest> NavigationRequest::CreateForCommit(
return navigation_request;
}
+// static class variable used to generate unique navigation ids for
+// NavigationRequest.
+int64_t NavigationRequest::unique_id_counter_ = 0;
+
NavigationRequest::NavigationRequest(
FrameTreeNode* frame_tree_node,
mojom::CommonNavigationParamsPtr common_params,
@@ -1047,7 +1028,12 @@ NavigationRequest::NavigationRequest(
navigation_ui_data_(std::move(navigation_ui_data)),
state_(NOT_STARTED),
restore_type_(entry ? entry->restore_type() : RestoreType::NONE),
- reload_type_(entry ? entry->reload_type() : ReloadType::NONE),
+ // Some navigations, such as renderer-initiated subframe navigations,
+ // won't have a NavigationEntryImpl. Set |reload_type_| if applicable
+ // for them.
+ reload_type_(
+ entry ? entry->reload_type()
+ : NavigationTypeToReloadType(common_params_->navigation_type)),
nav_entry_id_(entry ? entry->GetUniqueID() : 0),
is_view_source_(false),
bindings_(FrameNavigationEntry::kInvalidBindings),
@@ -1072,6 +1058,7 @@ NavigationRequest::NavigationRequest(
frame_tree_node->current_frame_host()->GetRoutingID())),
initiator_routing_id_(initiator_routing_id),
client_security_state_(network::mojom::ClientSecurityState::New()),
+ coop_status_(frame_tree_node, common_params_->initiator_origin),
previous_page_load_ukm_source_id_(
frame_tree_node_->current_frame_host()->GetPageUkmSourceId()) {
DCHECK(browser_initiated_ || common_params_->initiator_origin.has_value());
@@ -1080,11 +1067,11 @@ NavigationRequest::NavigationRequest(
DCHECK((IsInMainFrame() && browser_initiated) ||
commit_params_->frame_policy.has_value());
- TRACE_EVENT_NESTABLE_ASYNC_BEGIN2(
- "navigation", "NavigationRequest", this, "frame_tree_node",
- frame_tree_node_->frame_tree_node_id(), "url",
- common_params_->url.possibly_invalid_spec());
- TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("navigation", "Initializing", this);
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN1("navigation", "NavigationRequest",
+ navigation_id_, "navigation_request",
+ base::trace_event::ToTracedValue(this));
+ TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("navigation", "Initializing",
+ navigation_id_);
NavigationControllerImpl* controller = GetNavigationController();
if (frame_entry) {
@@ -1121,13 +1108,24 @@ NavigationRequest::NavigationRequest(
dest_site_instance_ = frame_entry->site_instance();
bindings_ = frame_entry->bindings();
- // Handle history subframe navigations that require a source_site_instance
- // but do not have one set yet. This can happen when navigation entries
- // are restored from PageState objects. The serialized state does not
- // contain a SiteInstance so we need to use the initiator_origin to
- // get an appropriate source SiteInstance.
- if (common_params_->is_history_navigation_in_new_child_frame)
+ // Handle history subframe and restore navigations that require a
+ // |source_site_instance| but do not have one set yet. This can happen
+ // when navigation entries are restored from PageState objects, because
+ // the serialized state does not contain a SiteInstance so we need to use
+ // the |initiator_origin| to get an appropriate source SiteInstance.
+ //
+ // History subframe and restore navigations are the only cases where
+ // SetSourceSiteInstanceToInitiatorIfNeeded needs to be called (i.e. the
+ // only cases that may have no |source_site_instance_| even though
+ // RequiresInitiatorBasedSourceSiteInstance returns true). We verify that
+ // other cases which require a |source_site_instance_| indeed have one
+ // with a DCHECK below.
+ if (common_params_->is_history_navigation_in_new_child_frame ||
+ common_params_->navigation_type == mojom::NavigationType::RESTORE ||
+ common_params_->navigation_type ==
+ mojom::NavigationType::RESTORE_WITH_POST) {
SetSourceSiteInstanceToInitiatorIfNeeded();
+ }
}
isolation_info_ = entry->isolation_info();
is_view_source_ = entry->IsViewSourceMode();
@@ -1139,7 +1137,8 @@ NavigationRequest::NavigationRequest(
// TODO(acolwell): Move this below so it can be enforced on all paths.
// This requires auditing same-document and other navigations that don't
// have |from_begin_navigation_| or |entry| set.
- DCHECK(!RequiresSourceSiteInstance() || source_site_instance_);
+ DCHECK(!RequiresInitiatorBasedSourceSiteInstance() ||
+ source_site_instance_);
}
// Let the NTP override the navigation params and pretend that this is a
@@ -1241,8 +1240,9 @@ NavigationRequest::~NavigationRequest() {
// Close the last child event. Tracing no longer outputs the end event name,
// so we can simply pass an empty string here.
- TRACE_EVENT_NESTABLE_ASYNC_END0("navigation", "", this);
- TRACE_EVENT_NESTABLE_ASYNC_END0("navigation", "NavigationRequest", this);
+ TRACE_EVENT_NESTABLE_ASYNC_END0("navigation", "", navigation_id_);
+ TRACE_EVENT_NESTABLE_ASYNC_END0("navigation", "NavigationRequest",
+ navigation_id_);
if (loading_mem_tracker_)
loading_mem_tracker_->Cancel();
ResetExpectedProcess();
@@ -1381,26 +1381,6 @@ void NavigationRequest::BeginNavigation() {
return;
}
- // Try to inherit the current page COOP/COEP to have a relevant speculative
- // RFH. The heuristic for inheriting is to have the most conservative approach
- // towards BrowsingInstance switching. Every same-origin navigation should
- // yield a no swap decision. This is done to work with the renderer crash
- // optimization that instantly commits the speculative RenderFrameHost.
- network::mojom::CrossOriginOpenerPolicyValue coop;
- network::mojom::CrossOriginEmbedderPolicyValue coep;
- RenderFrameHostImpl* current_rfh = frame_tree_node_->current_frame_host();
-
- bool inherit_coop =
- current_rfh->has_committed_any_navigation() ||
- current_rfh->cross_origin_opener_policy().value ==
- network::mojom::CrossOriginOpenerPolicyValue::kSameOrigin;
- coop = inherit_coop
- ? current_rfh->cross_origin_opener_policy().value
- : network::mojom::CrossOriginOpenerPolicyValue::kUnsafeNone;
- coep = current_rfh->cross_origin_embedder_policy().value;
-
- UpdateCoopStatus(coop, coep);
-
if (!NeedsUrlLoader()) {
// The types of pages that don't need a URL Loader should never get served
// from the BackForwardCache.
@@ -1496,12 +1476,13 @@ void NavigationRequest::StartNavigation(bool is_for_commit) {
DCHECK(!IsNavigationStarted());
SetState(WILL_START_REQUEST);
- navigation_handle_id_ = CreateUniqueHandleID();
+ is_navigation_started_ = true;
modified_request_headers_.Clear();
removed_request_headers_.clear();
- throttle_runner_ = base::WrapUnique(new NavigationThrottleRunner(this));
+ throttle_runner_ =
+ base::WrapUnique(new NavigationThrottleRunner(this, navigation_id_));
#if defined(OS_ANDROID)
navigation_handle_proxy_ = std::make_unique<NavigationHandleProxy>(this);
@@ -1562,8 +1543,8 @@ void NavigationRequest::ResetForCrossDocumentRestart() {
// Reset the state of the NavigationRequest, and the navigation_handle_id.
StopCommitTimeout();
SetState(NOT_STARTED);
+ is_navigation_started_ = false;
processing_navigation_throttle_ = false;
- navigation_handle_id_ = 0;
#if defined(OS_ANDROID)
if (navigation_handle_proxy_)
@@ -1611,7 +1592,7 @@ void NavigationRequest::ResetStateForSiteInstanceChange() {
}
void NavigationRequest::RegisterSubresourceOverride(
- mojom::TransferrableURLLoaderPtr transferrable_loader) {
+ blink::mojom::TransferrableURLLoaderPtr transferrable_loader) {
if (!transferrable_loader)
return;
if (!subresource_overrides_)
@@ -1639,6 +1620,21 @@ NavigationRequest::TakeClientSecurityState() {
return std::move(client_security_state_);
}
+void NavigationRequest::SetRequiredCSP(
+ network::mojom::ContentSecurityPolicyPtr csp) {
+ DCHECK(!required_csp_);
+ required_csp_ = std::move(csp);
+ if (required_csp_) {
+ const std::string& header_value = required_csp_->header->header_value;
+ DCHECK(net::HttpUtil::IsValidHeaderValue(header_value));
+ SetRequestHeader("Sec-Required-CSP", header_value);
+ }
+}
+
+network::mojom::ContentSecurityPolicyPtr NavigationRequest::TakeRequiredCSP() {
+ return std::move(required_csp_);
+}
+
void NavigationRequest::CreateCoepReporter(
StoragePartition* storage_partition) {
const auto& coep = client_security_state_->cross_origin_embedder_policy;
@@ -1652,37 +1648,6 @@ NavigationRequest::TakeCoepReporter() {
return std::move(coep_reporter_);
}
-void NavigationRequest::CreateCoopReporter(
- StoragePartition* storage_partition) {
- // If the flag for reporting is off, we simply don't create anything.
- // Since this is the only place we create COOP reporters this ensure reporting
- // is completely off.
- // Note that "popup inheritance" also instantiate a reporter, but only if we
- // created one here first.
- if (!base::FeatureList::IsEnabled(
- network::features::kCrossOriginOpenerPolicyReporting)) {
- return;
- }
-
- // If the page does not have any reporting endpoints, skip creating a
- // reporter.
- if (!render_frame_host_->cross_origin_opener_policy().reporting_endpoint &&
- !render_frame_host_->cross_origin_opener_policy()
- .report_only_reporting_endpoint) {
- return;
- }
-
- coop_reporter_ = std::make_unique<CrossOriginOpenerPolicyReporter>(
- storage_partition, frame_tree_node_->current_frame_host(),
- common_params_->url, render_frame_host_->cross_origin_opener_policy(),
- render_frame_host_->cross_origin_embedder_policy());
-}
-
-std::unique_ptr<CrossOriginOpenerPolicyReporter>
-NavigationRequest::TakeCoopReporter() {
- return std::move(coop_reporter_);
-}
-
ukm::SourceId NavigationRequest::GetPreviousPageUkmSourceId() {
return previous_page_load_ukm_source_id_;
}
@@ -1790,13 +1755,30 @@ void NavigationRequest::OnRequestRedirected(
return;
}
- SanitizeCoopHeaders();
+ // TODO(clamy): When we are able to compute the origin of a response in the
+ // browser process, we should use the computed origin instead of extracting it
+ // from the response URL.
+ const base::Optional<network::mojom::BlockedByResponseReason>
+ coop_requires_blocking = coop_status_.EnforceCOOP(
+ response_head_.get(), url::Origin::Create(common_params_->url),
+ common_params_->url, common_params_->referrer->url);
+ if (coop_requires_blocking) {
+ OnRequestFailedInternal(
+ network::URLLoaderCompletionStatus(*coop_requires_blocking),
+ false /* skip_throttles */, base::nullopt /* error_page_content */,
+ false /* collapse_frame */);
+ // DO NOT ADD CODE after this. The previous call to
+ // OnRequestFailedInternal has destroyed the NavigationRequest.
+ return;
+ }
- if (const auto blocked_reason = IsBlockedByResponse()) {
- OnRequestFailedInternal(network::URLLoaderCompletionStatus(*blocked_reason),
- false /* skip_throttles */,
- base::nullopt /* error_page_content */,
- false /* collapse_frame */);
+ const base::Optional<network::mojom::BlockedByResponseReason>
+ coep_requires_blocking = EnforceCOEP();
+ if (coep_requires_blocking) {
+ OnRequestFailedInternal(
+ network::URLLoaderCompletionStatus(*coep_requires_blocking),
+ false /* skip_throttles */, base::nullopt /* error_page_content */,
+ false /* collapse_frame */);
// DO NOT ADD CODE after this. The previous call to
// OnRequestFailedInternal has destroyed the NavigationRequest.
return;
@@ -1870,13 +1852,6 @@ void NavigationRequest::OnRequestRedirected(
return;
}
- if (base::FeatureList::IsEnabled(
- network::features::kCrossOriginOpenerPolicy)) {
- UpdateCoopStatus(
- response_head_->parsed_headers->cross_origin_opener_policy.value,
- response_head_->parsed_headers->cross_origin_embedder_policy.value);
- }
-
// Compute the SiteInstance to use for the redirect and pass its
// RenderProcessHost if it has a process. Keep a reference if it has a
// process, so that the SiteInstance and its associated process aren't deleted
@@ -2022,7 +1997,20 @@ void NavigationRequest::DetermineOriginIsolationEndResult(
break;
}
- commit_params_->origin_isolation_restricted =
+ // This needs to be computed separately from origin.opaque() because, per
+ // https://crbug.com/1041376, we don't have a notion of the true origin yet.
+ const bool is_opaque_origin_because_sandbox =
+ (ComputeSandboxFlagsToCommit() &
+ network::mojom::WebSandboxFlags::kOrigin) ==
+ network::mojom::WebSandboxFlags::kOrigin;
+
+ // The origin_isolated navigation commit parameter communicates to the
+ // renderer about origin isolation, so it should be true for opaque origin
+ // cases (e.g., for data: URLs). origin_isolation_end_result_ shouldn't be
+ // modified since it's used for warnings and use counters, i.e. things that
+ // don't apply to this sort of "automatic" origin isolation.
+ commit_params_->origin_isolated =
+ is_opaque_origin_because_sandbox || origin.opaque() ||
origin_isolation_end_result_ ==
OptInOriginIsolationEndResult::kRequestedViaOriginPolicyAndIsolated ||
origin_isolation_end_result_ ==
@@ -2198,13 +2186,30 @@ void NavigationRequest::OnResponseStarted(
}
}
- SanitizeCoopHeaders();
+ // TODO(clamy): When we are able to compute the origin of a response in the
+ // browser process, we should use the computed origin instead of extracting it
+ // from the response URL.
+ const base::Optional<network::mojom::BlockedByResponseReason>
+ coop_requires_blocking = coop_status_.EnforceCOOP(
+ response_head_.get(), url::Origin::Create(common_params_->url),
+ common_params_->url, common_params_->referrer->url);
+ if (coop_requires_blocking) {
+ OnRequestFailedInternal(
+ network::URLLoaderCompletionStatus(*coop_requires_blocking),
+ false /* skip_throttles */, base::nullopt /* error_page_content */,
+ false /* collapse_frame */);
+ // DO NOT ADD CODE after this. The previous call to
+ // OnRequestFailedInternal has destroyed the NavigationRequest.
+ return;
+ }
- if (const auto blocked_reason = IsBlockedByResponse()) {
- OnRequestFailedInternal(network::URLLoaderCompletionStatus(*blocked_reason),
- false /* skip_throttles */,
- base::nullopt /* error_page_content */,
- false /* collapse_frame */);
+ const base::Optional<network::mojom::BlockedByResponseReason>
+ coep_requires_blocking = EnforceCOEP();
+ if (coep_requires_blocking) {
+ OnRequestFailedInternal(
+ network::URLLoaderCompletionStatus(*coep_requires_blocking),
+ false /* skip_throttles */, base::nullopt /* error_page_content */,
+ false /* collapse_frame */);
// DO NOT ADD CODE after this. The previous call to
// OnRequestFailedInternal has destroyed the NavigationRequest.
return;
@@ -2269,23 +2274,6 @@ void NavigationRequest::OnResponseStarted(
}
}
- if (base::FeatureList::IsEnabled(
- network::features::kCrossOriginOpenerPolicy)) {
- UpdateCoopStatus(
- response_head_->parsed_headers->cross_origin_opener_policy.value,
- response_head_->parsed_headers->cross_origin_embedder_policy.value);
-
- RenderFrameHostImpl* current_rfh = frame_tree_node_->current_frame_host();
- if (coop_status_.require_browsing_instance_swap &&
- coop_status_.had_opener_before_browsing_instance_swap &&
- current_rfh->coop_reporter()) {
- current_rfh->coop_reporter()->QueueOpenerBreakageReport(
- current_rfh->coop_reporter()->GetNextDocumentUrlForReporting(
- GetRedirectChain(), GetInitiatorRoutingId()),
- true /* is_reported_from_document */, false /* is_report_only */);
- }
- }
-
// Select an appropriate renderer to commit the navigation.
if (IsServedFromBackForwardCache()) {
NavigationControllerImpl* controller = GetNavigationController();
@@ -2318,13 +2306,10 @@ void NavigationRequest::OnResponseStarted(
if (render_frame_host_) {
DetermineOriginIsolationEndResult(opt_in_isolation);
- // TODO(pmeuleman, ahemery): Only set COOP and COEP values on
- // RenderFrameHost when the navigation commits. In the meantime, keep them
- // in NavigationRequest.
+ // TODO(pmeuleman, ahemery): Only set COEP values on RenderFrameHost when
+ // the navigation commits. In the meantime, keep them in NavigationRequest.
render_frame_host_->set_cross_origin_embedder_policy(
cross_origin_embedder_policy);
- render_frame_host_->set_cross_origin_opener_policy(
- response_head_->parsed_headers->cross_origin_opener_policy);
}
client_security_state_->cross_origin_embedder_policy =
cross_origin_embedder_policy;
@@ -2503,7 +2488,7 @@ void NavigationRequest::OnRequestFailedInternal(
// anymore from now while the error page is being loaded.
loader_.reset();
- common_params_->previews_state = PREVIEWS_OFF;
+ common_params_->previews_state = blink::PreviewsTypes::PREVIEWS_OFF;
if (status.ssl_info.has_value())
ssl_info_ = status.ssl_info;
@@ -2710,14 +2695,16 @@ void NavigationRequest::OnStartChecksComplete(
}
if (IsSchemeSupportedForAppCache(common_params_->url)) {
- if (navigating_frame_host->GetRenderViewHost()
- ->GetWebkitPreferences()
+ if (navigating_frame_host->GetOrCreateWebPreferences()
.application_cache_enabled) {
- // The final process id won't be available until
- // NavigationRequest::ReadyToCommitNavigation.
- appcache_handle_ = std::make_unique<AppCacheNavigationHandle>(
- static_cast<ChromeAppCacheService*>(partition->GetAppCacheService()),
- ChildProcessHost::kInvalidUniqueID);
+ auto* appcache_service =
+ static_cast<ChromeAppCacheService*>(partition->GetAppCacheService());
+ if (appcache_service) {
+ // The final process id won't be available until
+ // NavigationRequest::ReadyToCommitNavigation.
+ appcache_handle_ = std::make_unique<AppCacheNavigationHandle>(
+ appcache_service, ChildProcessHost::kInvalidUniqueID);
+ }
}
}
@@ -2875,7 +2862,7 @@ void NavigationRequest::OnRedirectChecksComplete(
browser_context->GetClientHintsControllerDelegate();
if (client_hints_delegate) {
net::HttpRequestHeaders client_hints_extra_headers;
- PersistAcceptCHAfterNagivationRequestRedirect(
+ ParseAndPersistAcceptCHForNagivation(
commit_params_->redirects.back(),
commit_params_->redirect_response.back()->parsed_headers,
browser_context, client_hints_delegate, frame_tree_node_);
@@ -3058,6 +3045,39 @@ void NavigationRequest::CommitErrorPage(
error_page_content);
}
+void NavigationRequest::AddOldPageInfoToCommitParamsIfNeeded() {
+ // Add the routing ID and the updated lifecycle state of the old page if we
+ // need to run pagehide and visibilitychange handlers of the old page
+ // when we commit the new page.
+ auto* old_frame_host =
+ frame_tree_node_->render_manager()->current_frame_host();
+ if (!GetRenderFrameHost()
+ ->ShouldDispatchPagehideAndVisibilitychangeDuringCommit(
+ old_frame_host, GetURL())) {
+ return;
+ }
+ DCHECK(!IsSameDocument());
+ // The pagehide event's "persisted" property depends on whether the old page
+ // will be put into the back-forward cache or not. As we won't freeze the
+ // page until after the commit finished, there is no way to know for sure
+ // whether the page will actually be persisted or not after commit, but we
+ // will send our best guess by checking if the page can be persisted at this
+ // point.
+ bool can_store_old_page_in_bfcache =
+ frame_tree_node_->frame_tree()
+ ->controller()
+ ->GetBackForwardCache()
+ .CanPotentiallyStorePageLater(old_frame_host);
+ commit_params_->old_page_info = mojom::OldPageInfo::New();
+ commit_params_->old_page_info->routing_id_for_old_main_frame =
+ old_frame_host->GetRoutingID();
+ auto* page_lifecycle_state_manager =
+ old_frame_host->render_view_host()->GetPageLifecycleStateManager();
+ commit_params_->old_page_info->new_lifecycle_state_for_old_page =
+ page_lifecycle_state_manager->SetPagehideDispatchDuringNewPageCommit(
+ can_store_old_page_in_bfcache /* persisted */);
+}
+
void NavigationRequest::CommitNavigation() {
UpdateCommitNavigationParamsHistory();
DCHECK(NeedsUrlLoader() == !!response_head_ ||
@@ -3065,11 +3085,27 @@ void NavigationRequest::CommitNavigation() {
DCHECK(!common_params_->url.SchemeIs(url::kJavaScriptScheme));
DCHECK(!IsRendererDebugURL(common_params_->url));
+ AddOldPageInfoToCommitParamsIfNeeded();
+
if (IsServedFromBackForwardCache()) {
+ // Navigations served from the back-forward cache must be a history
+ // navigation, and thus should have a valid |pending_history_list_offset|
+ // value. We will pass that value and the |current_history_list_length|
+ // value to update the history offset and length information saved in the
+ // renderer, which might be stale.
+ DCHECK_GE(commit_params_->pending_history_list_offset, 0);
+
+ auto page_restore_params = blink::mojom::PageRestoreParams::New();
+ page_restore_params->navigation_start = NavigationStart();
+ page_restore_params->pending_history_list_offset =
+ commit_params_->pending_history_list_offset;
+ page_restore_params->current_history_list_length =
+ commit_params_->current_history_list_length;
+
NavigationControllerImpl* controller = GetNavigationController();
std::unique_ptr<BackForwardCacheImpl::Entry> restored_bfcache_entry =
- controller->GetBackForwardCache().RestoreEntry(nav_entry_id_,
- NavigationStart());
+ controller->GetBackForwardCache().RestoreEntry(
+ nav_entry_id_, std::move(page_restore_params));
if (!restored_bfcache_entry) {
// The only time restored_bfcache_entry can be nullptr here, is if the
@@ -3122,7 +3158,31 @@ void NavigationRequest::CommitNavigation() {
sandbox_flags_to_commit_ = ComputeSandboxFlagsToCommit();
CreateCoepReporter(render_frame_host_->GetProcess()->GetStoragePartition());
- CreateCoopReporter(render_frame_host_->GetProcess()->GetStoragePartition());
+ coop_status_.UpdateReporterStoragePartition(
+ render_frame_host_->GetProcess()->GetStoragePartition());
+
+ BrowserContext* browser_context =
+ frame_tree_node_->navigator().GetController()->GetBrowserContext();
+ ClientHintsControllerDelegate* client_hints_delegate =
+ browser_context->GetClientHintsControllerDelegate();
+ if (client_hints_delegate) {
+ base::Optional<std::vector<network::mojom::WebClientHintsType>>
+ opt_in_hints_from_response;
+ if (response()) {
+ opt_in_hints_from_response = ParseAndPersistAcceptCHForNagivation(
+ common_params_->url, response()->parsed_headers, browser_context,
+ client_hints_delegate, frame_tree_node_);
+ }
+ commit_params_->enabled_client_hints = LookupAcceptCHForCommit(
+ common_params_->url, client_hints_delegate, frame_tree_node_);
+
+ // We may need to add hints that were parsed this time in case they were
+ // not permitted to persist in legacy accept-ch-lifetime mode.
+ if (opt_in_hints_from_response) {
+ for (auto hint : opt_in_hints_from_response.value())
+ commit_params_->enabled_client_hints.push_back(hint);
+ }
+ }
blink::mojom::ServiceWorkerContainerInfoForClientPtr
service_worker_container_info;
@@ -3156,6 +3216,12 @@ void NavigationRequest::CommitNavigation() {
}
}
+ if (!IsSameDocument() && !render_frame_host_->GetParent()) {
+ commit_params_->is_cross_browsing_instance =
+ !render_frame_host_->GetSiteInstance()->IsRelatedSiteInstance(
+ GetStartingSiteInstance());
+ }
+
auto common_params = common_params_->Clone();
auto commit_params = commit_params_.Clone();
auto response_head = response_head_.Clone();
@@ -3179,6 +3245,18 @@ void NavigationRequest::CommitNavigation() {
// if it wasn't done in RenderProcessHostImpl::GetProcessHostForSiteInstance.
RenderProcessHostImpl::NotifySpareManagerAboutRecentlyUsedBrowserContext(
render_frame_host_->GetSiteInstance()->GetBrowserContext());
+
+ if (coop_status().header_ignored_due_to_insecure_context()) {
+ render_frame_host_->AddMessageToConsole(
+ blink::mojom::ConsoleMessageLevel::kError,
+ "The Cross-Origin-Opener-Policy header has been ignored, because the "
+ "origin was untrustworthy. It was defined either in the final response "
+ "or a redirect. Please deliver the response using the HTTPS protocol. "
+ "You can also use the 'localhost' origin instead. "
+ "See https://www.w3.org/TR/powerful-features/"
+ "#potentially-trustworthy-origin and "
+ "https://html.spec.whatwg.org/#the-cross-origin-opener-policy-header.");
+ }
}
void NavigationRequest::ResetExpectedProcess() {
@@ -3952,6 +4030,16 @@ void NavigationRequest::DidCommitNavigation(
common_params_->url = params.url;
did_replace_entry_ = did_replace_entry;
should_update_history_ = params.should_update_history;
+ // A same document navigation with the same url, and no user-gesture is
+ // typically the result of 'history.replaceState().' As the page is
+ // controlling this, the user doesn't really think of this as a navigation
+ // and it doesn't make sense to log this in history. Logging this in history
+ // would lead to lots of visits to a particular page, which impacts the
+ // visit count.
+ if (should_update_history_ && IsSameDocument() && !HasUserGesture() &&
+ params.url == previous_url) {
+ should_update_history_ = false;
+ }
previous_url_ = previous_url;
navigation_type_ = navigation_type;
@@ -3972,7 +4060,7 @@ void NavigationRequest::DidCommitNavigation(
// The renderer already knows locally about it because we sent an empty name
// at frame creation time. The renderer has now committed the page and we can
// safely enforce the empty name on the browser side.
- if (coop_status().require_browsing_instance_swap) {
+ if (coop_status().require_browsing_instance_swap()) {
std::string name, unique_name;
// "COOP swaps" only affect main frames, that have an empty unique name.
DCHECK(frame_tree_node_->unique_name().empty());
@@ -4089,6 +4177,24 @@ void NavigationRequest::ReadyToCommitNavigation(bool is_error) {
: empty_csp);
commit_params_->ip_address_space = ip_address_space;
client_security_state_->ip_address_space = ip_address_space;
+
+ // TODO(crbug.com/986744): Check whether this is the correct way of
+ // detecting a secure context, amend if not. The current origin being
+ // trustworthy is a necessary condition for secure contexts, but it might
+ // not be sufficient.
+ client_security_state_->is_web_secure_context =
+ network::IsOriginPotentiallyTrustworthy(
+ url::Origin::Create(common_params_->url));
+
+ if (base::FeatureList::IsEnabled(
+ network::features::kBlockInsecurePrivateNetworkRequests)) {
+ client_security_state_->private_network_request_policy =
+ GetContentClient()->browser()->GetPrivateNetworkRequestPolicy(
+ frame_tree_node_->navigator()
+ .GetController()
+ ->GetBrowserContext(),
+ common_params_->url);
+ }
}
if (appcache_handle_) {
@@ -4129,6 +4235,66 @@ bool NavigationRequest::IsWaitingToCommit() {
return state_ == READY_TO_COMMIT;
}
+// static
+bool NavigationRequest::IsLoadDataWithBaseURL(const GURL& url,
+ const GURL& base_url) {
+ return url.SchemeIs(url::kDataScheme) && !base_url.is_empty();
+}
+
+// static
+bool NavigationRequest::IsLoadDataWithBaseURL(
+ const mojom::CommonNavigationParams& common_params) {
+ return IsLoadDataWithBaseURL(common_params.url,
+ common_params.base_url_for_data_url);
+}
+
+url::Origin NavigationRequest::GetOriginForURLLoaderFactory() {
+ // Calculate an approximation (sandbox/csp is ignored - see
+ // https://crbug.com/1041376) of the origin that will be committed because of
+ // |this| NavigationRequest.
+ url::Origin result = GetOriginForURLLoaderFactoryUnchecked(this);
+
+ // Note that GetRenderFrameHost() only allows to retrieve the RenderFrameHost
+ // once it has been set for this navigation. This will happens either at
+ // WillProcessResponse time for regular navigations or at WillFailRequest time
+ // for error pages.
+ RenderFrameHostImpl* target_frame = GetRenderFrameHost();
+ DCHECK(target_frame);
+
+ // Check that |result| origin is allowed to be accessed from the process that
+ // is the target of this navigation.
+ if (target_frame->ShouldBypassSecurityChecksForErrorPage(this))
+ return result;
+ int process_id = target_frame->GetProcess()->GetID();
+ auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
+ CHECK(policy->CanAccessDataForOrigin(process_id, result));
+ return result;
+}
+
+void NavigationRequest::AsValueInto(
+ base::trace_event::TracedValue* traced_value) {
+ traced_value->SetPointer("this", this);
+ traced_value->SetInteger("navigation_id", navigation_id_);
+ traced_value->SetInteger("frame_tree_node",
+ frame_tree_node_->frame_tree_node_id());
+ traced_value->SetString("url", common_params_->url.possibly_invalid_spec());
+ traced_value->SetBoolean("browser_initiated", browser_initiated_);
+ traced_value->SetBoolean("from_begin_navigation", from_begin_navigation_);
+ traced_value->SetBoolean("is_for_commit", is_for_commit_);
+ traced_value->SetInteger("reload_type", static_cast<int>(reload_type_));
+ traced_value->SetInteger("navigation_type",
+ static_cast<int>(common_params_->navigation_type));
+ traced_value->SetInteger("state", static_cast<int>(state_));
+
+ if (IsServedFromBackForwardCache()) {
+ traced_value->SetBoolean("bf cached", true);
+ rfh_restored_from_back_forward_cache_->AsValueInto(traced_value);
+ }
+
+ if (state_ >= WILL_PROCESS_RESPONSE)
+ GetRenderFrameHost()->AsValueInto(traced_value);
+}
+
void NavigationRequest::RenderProcessBlockedStateChanged(bool blocked) {
if (blocked)
StopCommitTimeout();
@@ -4316,7 +4482,7 @@ bool NavigationRequest::HasPrefetchedAlternativeSubresourceSignedExchange() {
}
int64_t NavigationRequest::GetNavigationId() {
- return navigation_handle_id_;
+ return navigation_id_;
}
const GURL& NavigationRequest::GetURL() {
@@ -4577,31 +4743,59 @@ bool NavigationRequest::GetIsOverridingUserAgent() {
return entry_overrides_ua_;
}
+void NavigationRequest::ForceCSPForResponse(const std::string& csp) {
+ commit_params_->forced_content_security_policies.push_back(csp);
+}
+
// static
NavigationRequest* NavigationRequest::From(NavigationHandle* handle) {
return static_cast<NavigationRequest*>(handle);
}
+// static
+ReloadType NavigationRequest::NavigationTypeToReloadType(
+ mojom::NavigationType type) {
+ if (type == mojom::NavigationType::RELOAD)
+ return ReloadType::NORMAL;
+ if (type == mojom::NavigationType::RELOAD_BYPASSING_CACHE)
+ return ReloadType::BYPASSING_CACHE;
+ if (type == mojom::NavigationType::RELOAD_ORIGINAL_REQUEST_URL)
+ return ReloadType::ORIGINAL_REQUEST_URL;
+ return ReloadType::NONE;
+}
+
bool NavigationRequest::IsNavigationStarted() const {
- return navigation_handle_id_;
+ return is_navigation_started_;
}
-bool NavigationRequest::RequiresSourceSiteInstance() const {
+bool NavigationRequest::RequiresInitiatorBasedSourceSiteInstance() const {
const bool is_data_or_about =
common_params_->url.SchemeIs(url::kDataScheme) ||
common_params_->url.IsAboutBlank();
+
const bool has_valid_initiator =
common_params_->initiator_origin &&
common_params_->initiator_origin->GetTupleOrPrecursorTupleIfOpaque()
.IsValid();
- return is_data_or_about && has_valid_initiator && !dest_site_instance_;
+
+ // If renderer-initiated navigation of a main frame |has_valid_initiator| but
+ // has no |initiator_routing_id_|, then it means that the opener was
+ // suppressed (and therefore that a source SiteInstance is not needed). Note
+ // that |initiator_routing_id| is always MSG_ROUTING_NONE during
+ // browser-initiated navigations (including session restore or history
+ // navigations).
+ const bool was_opener_suppressed =
+ has_valid_initiator && frame_tree_node()->IsMainFrame() &&
+ initiator_routing_id_.frame_routing_id == MSG_ROUTING_NONE &&
+ !browser_initiated_;
+
+ return is_data_or_about && has_valid_initiator && !was_opener_suppressed &&
+ !dest_site_instance_;
}
void NavigationRequest::SetSourceSiteInstanceToInitiatorIfNeeded() {
- if (source_site_instance_ || !RequiresSourceSiteInstance() ||
- !common_params_->initiator_origin.has_value()) {
+ if (source_site_instance_ || !RequiresInitiatorBasedSourceSiteInstance())
return;
- }
const auto tuple =
common_params_->initiator_origin->GetTupleOrPrecursorTupleIfOpaque();
@@ -4647,44 +4841,27 @@ void NavigationRequest::ForceEnableOriginTrials(
}
base::Optional<network::mojom::BlockedByResponseReason>
-NavigationRequest::IsBlockedByResponse() {
- if (base::FeatureList::IsEnabled(
- network::features::kCrossOriginOpenerPolicy)) {
- // Popups with a sandboxing flag, inherited from their opener, are not
- // allowed to navigate to a document with a Cross-Origin-Opener-Policy that
- // is not "unsafe-none". This ensures a COOP document does not inherit any
- // property from an opener.
- // https://gist.github.com/annevk/6f2dd8c79c77123f39797f6bdac43f3e
- if (response_head_->parsed_headers->cross_origin_opener_policy.value !=
- network::mojom::CrossOriginOpenerPolicyValue::kUnsafeNone &&
- (frame_tree_node_->pending_frame_policy().sandbox_flags !=
- network::mojom::WebSandboxFlags::kNone)) {
- return network::mojom::BlockedByResponseReason::
- kCoopSandboxedIFrameCannotNavigateToCoopPage;
- }
- }
-
- if (base::FeatureList::IsEnabled(
+NavigationRequest::EnforceCOEP() {
+ if (!base::FeatureList::IsEnabled(
network::features::kCrossOriginEmbedderPolicy)) {
- // https://mikewest.github.io/corpp/#integration-html
- auto* parent_frame = GetParentFrame();
- if (!parent_frame) {
- return base::nullopt;
- }
- const auto& url = common_params_->url;
- // Some special URLs not loaded using the network are inheriting the
- // Cross-Origin-Embedder-Policy header from their parent.
- if (url.SchemeIsBlob() || url.SchemeIs(url::kDataScheme)) {
- return base::nullopt;
- }
- return network::CrossOriginResourcePolicy::IsNavigationBlocked(
- url, redirect_chain_[0], parent_frame->GetLastCommittedOrigin(),
- *response_head_, parent_frame->GetLastCommittedOrigin(),
- parent_frame->cross_origin_embedder_policy(),
- parent_frame->coep_reporter());
+ return base::nullopt;
}
-
- return base::nullopt;
+ // https://html.spec.whatwg.org/#check-a-navigation-response's-adherence-to-its-embedder-policy
+ auto* parent_frame = GetParentFrame();
+ if (!parent_frame) {
+ return base::nullopt;
+ }
+ const auto& url = common_params_->url;
+ // Some special URLs not loaded using the network are inheriting the
+ // Cross-Origin-Embedder-Policy header from their parent.
+ if (url.SchemeIsBlob() || url.SchemeIs(url::kDataScheme)) {
+ return base::nullopt;
+ }
+ return network::CrossOriginResourcePolicy::IsNavigationBlocked(
+ url, redirect_chain_[0], parent_frame->GetLastCommittedOrigin(),
+ *response_head_, parent_frame->GetLastCommittedOrigin(),
+ parent_frame->cross_origin_embedder_policy(),
+ parent_frame->coep_reporter());
}
std::unique_ptr<PeakGpuMemoryTracker>
@@ -4775,10 +4952,6 @@ NavigationRequest::ComputeSandboxFlagsToCommit() {
return out;
}
-const CrossOriginOpenerPolicyStatus& NavigationRequest::coop_status() const {
- return coop_status_;
-}
-
void NavigationRequest::CheckStateTransition(NavigationState state) const {
#if DCHECK_IS_ON()
// See
@@ -4845,38 +5018,4 @@ void NavigationRequest::SetState(NavigationState state) {
state_ = state;
}
-void NavigationRequest::SanitizeCoopHeaders() {
- // We blank out the COOP headers in a number of situations.
- // - When the COOP flag is not enabled.
- // - When the headers were not sent over HTTPS.
- // - For subframes.
- if (!base::FeatureList::IsEnabled(
- network::features::kCrossOriginOpenerPolicy) ||
- !IsOriginSecure(common_params_->url) || !IsInMainFrame()) {
- response_head_->parsed_headers->cross_origin_opener_policy =
- network::CrossOriginOpenerPolicy();
- }
-}
-
-void NavigationRequest::UpdateCoopStatus(
- network::mojom::CrossOriginOpenerPolicyValue coop,
- network::mojom::CrossOriginEmbedderPolicyValue coep) {
- RenderFrameHostImpl* current_rfh = frame_tree_node_->current_frame_host();
-
- bool cross_origin_policy_swap =
- IsInMainFrame() && !common_params_->url.IsAboutBlank() &&
- ShouldSwapBrowsingInstanceForCrossOriginOpenerPolicy(
- current_rfh->cross_origin_opener_policy().value,
- current_rfh->cross_origin_embedder_policy().value,
- current_rfh->GetLastCommittedOrigin(),
- !current_rfh->has_committed_any_navigation(), coop, coep,
- url::Origin::Create(common_params_->url));
-
- if (cross_origin_policy_swap) {
- coop_status_.require_browsing_instance_swap = true;
- if (frame_tree_node_->opener())
- coop_status_.had_opener_before_browsing_instance_swap = true;
- }
-}
-
} // namespace content