#include "content/browser/renderer_host/navigation_request.h"
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "base/auto_reset.h"
#include "base/command_line.h"
#include "base/containers/contains.h"
#include "base/containers/cxx20_erase.h"
#include "base/debug/alias.h"
#include "base/debug/dump_without_crashing.h"
#include "base/feature_list.h"
#include "base/files/file_path.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/field_trial_params.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/user_metrics.h"
#include "base/no_destructor.h"
#include "base/notreached.h"
#include "base/rand_util.h"
#include "base/state_transitions.h"
#include "base/strings/strcat.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/system/sys_info.h"
#include "base/task/sequenced_task_runner.h"
#include "base/time/time.h"
#include "base/timer/elapsed_timer.h"
#include "base/trace_event/trace_conversion_helper.h"
#include "base/types/optional_util.h"
#include "base/types/pass_key.h"
#include "build/build_config.h"
#include "build/buildflag.h"
#include "build/chromeos_buildflags.h"
#include "content/browser/blob_storage/chrome_blob_storage_context.h"
#include "content/browser/browsing_topics/header_util.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/client_hints/client_hints.h"
#include "content/browser/devtools/devtools_instrumentation.h"
#include "content/browser/devtools/network_service_devtools_observer.h"
#include "content/browser/download/download_manager_impl.h"
#include "content/browser/fenced_frame/fenced_frame_url_mapping.h"
#include "content/browser/loader/browser_initiated_resource_request.h"
#include "content/browser/loader/cached_navigation_url_loader.h"
#include "content/browser/loader/navigation_early_hints_manager.h"
#include "content/browser/loader/navigation_url_loader.h"
#include "content/browser/loader/object_navigation_fallback_body_loader.h"
#include "content/browser/navigation_or_document_handle.h"
#include "content/browser/network/cross_origin_embedder_policy_reporter.h"
#include "content/browser/network/cross_origin_opener_policy_reporter.h"
#include "content/browser/network_service_instance_impl.h"
#include "content/browser/origin_agent_cluster_isolation_state.h"
#include "content/browser/origin_trials/origin_trials_utils.h"
#include "content/browser/preloading/prerender/prerender_host_registry.h"
#include "content/browser/process_lock.h"
#include "content/browser/reduce_accept_language/reduce_accept_language_utils.h"
#include "content/browser/renderer_host/back_forward_cache_impl.h"
#include "content/browser/renderer_host/concurrent_navigations_commit_deferring_condition.h"
#include "content/browser/renderer_host/cookie_utils.h"
#include "content/browser/renderer_host/debug_urls.h"
#include "content/browser/renderer_host/frame_tree.h"
#include "content/browser/renderer_host/frame_tree_node.h"
#include "content/browser/renderer_host/local_network_access_util.h"
#include "content/browser/renderer_host/navigation_controller_impl.h"
#include "content/browser/renderer_host/navigation_request_info.h"
#include "content/browser/renderer_host/navigator.h"
#include "content/browser/renderer_host/navigator_delegate.h"
#include "content/browser/renderer_host/render_frame_host_csp_context.h"
#include "content/browser/renderer_host/render_frame_host_delegate.h"
#include "content/browser/renderer_host/render_frame_host_impl.h"
#include "content/browser/renderer_host/render_frame_proxy_host.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/renderer_host/render_view_host_delegate.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/renderer_host/subframe_history_navigation_throttle.h"
#include "content/browser/runtime_feature_state/runtime_feature_state_document_data.h"
#include "content/browser/scoped_active_url.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
#include "content/browser/service_worker/service_worker_main_resource_handle.h"
#include "content/browser/site_info.h"
#include "content/browser/site_instance_impl.h"
#include "content/browser/storage_partition_impl.h"
#include "content/browser/url_loader_factory_params_helper.h"
#include "content/browser/web_package/prefetched_signed_exchange_cache.h"
#include "content/browser/web_package/subresource_web_bundle_navigation_info.h"
#include "content/common/content_constants_internal.h"
#include "content/common/content_navigation_policy.h"
#include "content/common/debug_utils.h"
#include "content/common/features.h"
#include "content/common/navigation_params_utils.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/child_process_host.h"
#include "content/public/browser/client_hints_controller_delegate.h"
#include "content/public/browser/commit_deferring_condition.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/cookie_access_details.h"
#include "content/public/browser/global_request_id.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_ui_data.h"
#include "content/public/browser/network_service_instance.h"
#include "content/public/browser/origin_trials_controller_delegate.h"
#include "content/public/browser/peak_gpu_memory_tracker.h"
#include "content/public/browser/reduce_accept_language_controller_delegate.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/site_isolation_policy.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/weak_document_ptr.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/network_service_util.h"
#include "content/public/common/origin_util.h"
#include "content/public/common/url_constants.h"
#include "content/public/common/url_utils.h"
#include "mojo/public/cpp/system/data_pipe.h"
#include "net/base/filename_util.h"
#include "net/base/ip_endpoint.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "net/base/url_util.h"
#include "net/cookies/canonical_cookie.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_status_code.h"
#include "net/url_request/redirect_info.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
#include "services/network/public/cpp/client_hints.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/header_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/supports_loading_mode/supports_loading_mode_parser.h"
#include "services/network/public/cpp/url_loader_completion_status.h"
#include "services/network/public/cpp/web_sandbox_flags.h"
#include "services/network/public/mojom/fetch_api.mojom.h"
#include "services/network/public/mojom/supports_loading_mode.mojom.h"
#include "services/network/public/mojom/url_response_head.mojom-forward.h"
#include "services/network/public/mojom/url_response_head.mojom-shared.h"
#include "services/network/public/mojom/url_response_head.mojom.h"
#include "services/network/public/mojom/web_client_hints_types.mojom-shared.h"
#include "services/network/public/mojom/web_client_hints_types.mojom.h"
#include "services/network/public/mojom/web_sandbox_flags.mojom.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/blob/blob_utils.h"
#include "third_party/blink/public/common/chrome_debug_urls.h"
#include "third_party/blink/public/common/client_hints/client_hints.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/fenced_frame/fenced_frame_utils.h"
#include "third_party/blink/public/common/fenced_frame/redacted_fenced_frame_config.h"
#include "third_party/blink/public/common/frame/fenced_frame_permissions_policies.h"
#include "third_party/blink/public/common/frame/fenced_frame_sandbox_flags.h"
#include "third_party/blink/public/common/frame/frame_owner_element_type.h"
#include "third_party/blink/public/common/navigation/navigation_params_mojom_traits.h"
#include "third_party/blink/public/common/navigation/navigation_policy.h"
#include "third_party/blink/public/common/origin_trials/trial_token_validator.h"
#include "third_party/blink/public/common/permissions_policy/document_policy.h"
#include "third_party/blink/public/common/permissions_policy/permissions_policy_features.h"
#include "third_party/blink/public/common/permissions_policy/policy_helper_public.h"
#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
#include "third_party/blink/public/common/runtime_feature_state/runtime_feature_state_context.h"
#include "third_party/blink/public/common/security/address_space_feature.h"
#include "third_party/blink/public/common/user_agent/user_agent_metadata.h"
#include "third_party/blink/public/common/web_preferences/web_preferences.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom.h"
#include "third_party/blink/public/mojom/loader/mixed_content.mojom.h"
#include "third_party/blink/public/mojom/loader/transferrable_url_loader.mojom.h"
#include "third_party/blink/public/mojom/navigation/navigation_params.mojom-shared.h"
#include "third_party/blink/public/mojom/navigation/navigation_params.mojom.h"
#include "third_party/blink/public/mojom/navigation/prefetched_signed_exchange_info.mojom.h"
#include "third_party/blink/public/mojom/runtime_feature_state/runtime_feature_state.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_provider.mojom.h"
#include "third_party/blink/public/mojom/storage_key/ancestor_chain_bit.mojom.h"
#include "third_party/blink/public/mojom/timing/resource_timing.mojom-forward.h"
#include "third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom.h"
#include "third_party/blink/public/platform/resource_request_blocked_reason.h"
#include "ui/compositor/compositor_lock.h"
#include "url/origin.h"
#include "url/url_constants.h"
#if BUILDFLAG(IS_ANDROID)
#include "ui/android/window_android.h"
#include "ui/android/window_android_compositor.h"
#endif
#if defined(OHOS_RENDERER_ANR_DUMP)
#include "content/public/browser/web_contents_delegate.h"
#endif
#if BUILDFLAG(IS_OHOS_PRPP)
#include "mojo/public/cpp/bindings/callback_helpers.h"
#endif
#if defined(OHOS_LOGGER_REPORT)
#include "url/ohos/log_utils.h"
#include "content/public/browser/web_contents.h"
#include "content/browser/web_contents/web_contents_impl.h"
#endif
namespace content {
namespace {
constexpr base::TimeDelta kDefaultCommitTimeout = base::Seconds(30);
base::TimeDelta g_commit_timeout = kDefaultCommitTimeout;
#if BUILDFLAG(IS_ANDROID)
constexpr base::TimeDelta kCompositorLockTimeout = base::Milliseconds(150);
#endif
#if BUILDFLAG(IS_OHOS_PRPP)
const std::string ORIGIN = "origin.DEFAULT";
#endif
BASE_FEATURE(kHistoryNavigationDoNotUseCacheAblationStudy,
"HistoryNavigationDoNotUseCacheAblationStudy",
base::FEATURE_DISABLED_BY_DEFAULT);
constexpr base::FeatureParam<double> kDoNotUseCacheProbability{
&kHistoryNavigationDoNotUseCacheAblationStudy, "probability", 0.0};
const char kIsolatedAppCSP[] =
"base-uri 'none';"
"default-src 'self';"
"object-src 'none';"
"frame-src 'self' https: blob: data:;"
"connect-src 'self' https:;"
"script-src 'self' 'wasm-unsafe-eval';"
"img-src 'self' https: blob: data:;"
"media-src 'self' https: blob: data:;"
"font-src 'self' blob: data:;"
"require-trusted-types-for 'script';";
enum class UserAgentStringType {
kFullVersion,
kReducedVersion,
kOverriden,
kMaxValue = kOverriden
};
void UpdateLoadFlagsWithCacheFlags(int* load_flags,
blink::mojom::NavigationType navigation_type,
bool is_post) {
switch (navigation_type) {
case blink::mojom::NavigationType::RELOAD:
case blink::mojom::NavigationType::RELOAD_ORIGINAL_REQUEST_URL:
*load_flags |= net::LOAD_VALIDATE_CACHE;
break;
case blink::mojom::NavigationType::RELOAD_BYPASSING_CACHE:
*load_flags |= net::LOAD_BYPASS_CACHE;
break;
case blink::mojom::NavigationType::RESTORE:
*load_flags |= net::LOAD_SKIP_CACHE_VALIDATION;
break;
case blink::mojom::NavigationType::RESTORE_WITH_POST:
*load_flags |=
net::LOAD_ONLY_FROM_CACHE | net::LOAD_SKIP_CACHE_VALIDATION;
break;
case blink::mojom::NavigationType::SAME_DOCUMENT:
case blink::mojom::NavigationType::DIFFERENT_DOCUMENT:
if (is_post)
*load_flags |= net::LOAD_VALIDATE_CACHE;
break;
case blink::mojom::NavigationType::HISTORY_SAME_DOCUMENT:
case blink::mojom::NavigationType::HISTORY_DIFFERENT_DOCUMENT:
if (is_post) {
*load_flags |=
net::LOAD_ONLY_FROM_CACHE | net::LOAD_SKIP_CACHE_VALIDATION;
} else if (base::FeatureList::IsEnabled(
kHistoryNavigationDoNotUseCacheAblationStudy) &&
base::RandDouble() < kDoNotUseCacheProbability.Get()) {
*load_flags |= net::LOAD_BYPASS_CACHE;
} else {
*load_flags |= net::LOAD_SKIP_CACHE_VALIDATION;
}
break;
}
}
bool IsSecureFrame(RenderFrameHostImpl* frame) {
while (frame) {
if (!network::IsOriginPotentiallyTrustworthy(
frame->GetLastCommittedOrigin()))
return false;
frame = frame->GetParent();
}
return true;
}
bool NeedsHTTPOrigin(net::HttpRequestHeaders* headers,
const std::string& method) {
if (method == "GET" || method == "HEAD")
return false;
return true;
}
bool DoesHeaderContainClientHint(
const net::HttpRequestHeaders& headers,
const network::mojom::WebClientHintsType hint) {
std::string header = network::GetClientHintToNameMap().at(hint);
std::string value;
return headers.GetHeader(header, &value) && value == "?1";
}
std::string ComputeUserAgentValue(const net::HttpRequestHeaders& headers,
const std::string& user_agent_override,
content::BrowserContext* context) {
if (!user_agent_override.empty()) {
base::UmaHistogramEnumeration("Navigation.UserAgentStringType",
UserAgentStringType::kOverriden);
return user_agent_override;
}
const bool full = DoesHeaderContainClientHint(
headers, network::mojom::WebClientHintsType::kFullUserAgent);
if (full) {
base::UmaHistogramEnumeration("Navigation.UserAgentStringType",
UserAgentStringType::kFullVersion);
return GetContentClient()->browser()->GetFullUserAgent();
}
const bool reduced = DoesHeaderContainClientHint(
headers, network::mojom::WebClientHintsType::kUAReduced);
base::UmaHistogramEnumeration("Navigation.UserAgentStringType",
reduced ? UserAgentStringType::kReducedVersion
: UserAgentStringType::kFullVersion);
return reduced ? GetContentClient()->browser()->GetReducedUserAgent()
: GetContentClient()->browser()->GetUserAgentBasedOnPolicy(
context);
}
void AddAdditionalRequestHeaders(
net::HttpRequestHeaders* headers,
const GURL& url,
blink::mojom::NavigationType navigation_type,
ui::PageTransition transition,
BrowserContext* browser_context,
const std::string& method,
const std::string& user_agent_override,
const absl::optional<url::Origin>& initiator_origin,
blink::mojom::Referrer* referrer,
FrameTreeNode* frame_tree_node) {
if (!url.SchemeIsHTTPOrHTTPS())
return;
bool is_reload = NavigationTypeUtils::IsReload(navigation_type);
blink::RendererPreferences render_prefs =
frame_tree_node->current_frame_host()
->render_view_host()
->GetDelegate()
->GetRendererPrefs();
UpdateAdditionalHeadersForBrowserInitiatedRequest(
headers, browser_context, is_reload, render_prefs,
false);
headers->SetHeaderIfMissing("Upgrade-Insecure-Requests", "1");
headers->SetHeaderIfMissing(
net::HttpRequestHeaders::kUserAgent,
ComputeUserAgentValue(*headers, user_agent_override, browser_context));
if (!render_prefs.enable_referrers) {
*referrer =
blink::mojom::Referrer(GURL(), network::mojom::ReferrerPolicy::kNever);
}
if (NeedsHTTPOrigin(headers, method)) {
url::Origin origin_header_value = initiator_origin.value_or(url::Origin());
origin_header_value = Referrer::SanitizeOriginForRequest(
url, origin_header_value, referrer->policy);
headers->SetHeader(net::HttpRequestHeaders::kOrigin,
origin_header_value.Serialize());
}
if (base::FeatureList::IsEnabled(features::kDocumentPolicyNegotiation)) {
const blink::DocumentPolicyFeatureState& required_policy =
frame_tree_node->effective_frame_policy().required_document_policy;
if (!required_policy.empty()) {
absl::optional<std::string> policy_header =
blink::DocumentPolicy::Serialize(required_policy);
DCHECK(policy_header);
headers->SetHeader("Sec-Required-Document-Policy", policy_header.value());
}
}
if (frame_tree_node->frame_tree().is_prerendering()) {
headers->SetHeader("Sec-Purpose", "prefetch;prerender");
headers->SetHeader("Purpose", "prefetch");
}
}
bool ShouldPropagateUserActivation(const url::Origin& previous_origin,
const url::Origin& new_origin) {
if ((previous_origin.scheme() != "http" &&
previous_origin.scheme() != "https") ||
(new_origin.scheme() != "http" && new_origin.scheme() != "https")) {
return false;
}
if (previous_origin.host() == new_origin.host())
return true;
std::string previous_domain =
net::registry_controlled_domains::GetDomainAndRegistry(
previous_origin,
net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
std::string new_domain =
net::registry_controlled_domains::GetDomainAndRegistry(
new_origin,
net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
return !previous_domain.empty() && previous_domain == new_domain;
}
#define LOG_NAVIGATION_TIMING_HISTOGRAM(histogram, transition, is_background, \
duration) \
do { \
const base::TimeDelta kMinTime = base::Milliseconds(1); \
const base::TimeDelta kMaxTime = base::Minutes(3); \
const int kBuckets = 50; \
UMA_HISTOGRAM_CUSTOM_TIMES("Navigation." histogram, duration, kMinTime, \
kMaxTime, kBuckets); \
if (transition & ui::PAGE_TRANSITION_FORWARD_BACK) { \
UMA_HISTOGRAM_CUSTOM_TIMES("Navigation." histogram ".BackForward", \
duration, kMinTime, kMaxTime, kBuckets); \
} else if (ui::PageTransitionCoreTypeIs(transition, \
ui::PAGE_TRANSITION_RELOAD)) { \
UMA_HISTOGRAM_CUSTOM_TIMES("Navigation." histogram ".Reload", duration, \
kMinTime, kMaxTime, kBuckets); \
} else if (ui::PageTransitionIsNewNavigation(transition)) { \
UMA_HISTOGRAM_CUSTOM_TIMES("Navigation." histogram ".NewNavigation", \
duration, kMinTime, kMaxTime, kBuckets); \
} else { \
NOTREACHED() << "Invalid page transition: " << transition; \
} \
if (is_background.has_value()) { \
if (is_background.value()) { \
UMA_HISTOGRAM_CUSTOM_TIMES("Navigation." histogram \
".BackgroundProcessPriority", \
duration, kMinTime, kMaxTime, kBuckets); \
} else { \
UMA_HISTOGRAM_CUSTOM_TIMES("Navigation." histogram \
".ForegroundProcessPriority", \
duration, kMinTime, kMaxTime, kBuckets); \
} \
} \
} while (0)
void RecordStartToCommitMetrics(base::TimeTicks navigation_start_time,
ui::PageTransition transition,
const base::TimeTicks& ready_to_commit_time,
absl::optional<bool> is_background,
bool is_same_process,
bool is_main_frame) {
base::TimeTicks now = base::TimeTicks::Now();
base::TimeDelta delta = now - navigation_start_time;
LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit", transition, is_background,
delta);
if (is_main_frame) {
LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit.MainFrame", transition,
is_background, delta);
} else {
LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit.Subframe", transition,
is_background, delta);
}
if (is_same_process) {
LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit.SameProcess", transition,
is_background, delta);
if (is_main_frame) {
LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit.SameProcess.MainFrame",
transition, is_background, delta);
} else {
LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit.SameProcess.Subframe",
transition, is_background, delta);
}
} else {
LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit.CrossProcess", transition,
is_background, delta);
if (is_main_frame) {
LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit.CrossProcess.MainFrame",
transition, is_background, delta);
} else {
LOG_NAVIGATION_TIMING_HISTOGRAM("StartToCommit.CrossProcess.Subframe",
transition, is_background, delta);
}
}
if (!ready_to_commit_time.is_null()) {
LOG_NAVIGATION_TIMING_HISTOGRAM("ReadyToCommitUntilCommit2", transition,
is_background, now - ready_to_commit_time);
}
}
void RecordReadyToCommitMetrics(
RenderFrameHostImpl* old_rfh,
RenderFrameHostImpl* new_rfh,
const blink::mojom::CommonNavigationParams& common_params,
base::TimeTicks ready_to_commit_time,
NavigationRequest::OriginAgentClusterEndResult
origin_agent_cluster_end_result,
bool did_receive_early_hints_before_cross_origin_redirect) {
bool is_main_frame = !new_rfh->GetParent();
bool is_same_process =
old_rfh->GetProcess()->GetID() == new_rfh->GetProcess()->GetID();
if (is_main_frame) {
bool is_same_browsing_instance =
old_rfh->GetSiteInstance()->IsRelatedSiteInstance(
new_rfh->GetSiteInstance());
UMA_HISTOGRAM_BOOLEAN("Navigation.IsSameBrowsingInstance",
is_same_browsing_instance);
}
{
bool is_same_site_instance =
old_rfh->GetSiteInstance() == new_rfh->GetSiteInstance();
UMA_HISTOGRAM_BOOLEAN("Navigation.IsSameSiteInstance",
is_same_site_instance);
if (is_main_frame) {
UMA_HISTOGRAM_BOOLEAN("Navigation.IsSameSiteInstance.MainFrame",
is_same_site_instance);
} else {
UMA_HISTOGRAM_BOOLEAN("Navigation.IsSameSiteInstance.Subframe",
is_same_site_instance);
}
}
{
ProcessLock process_lock = new_rfh->GetProcess()->GetProcessLock();
UMA_HISTOGRAM_BOOLEAN("Navigation.IsLockedProcess",
process_lock.is_locked_to_site());
if (common_params.url.SchemeIsHTTPOrHTTPS()) {
UMA_HISTOGRAM_BOOLEAN("Navigation.IsLockedProcess.HTTPOrHTTPS",
process_lock.is_locked_to_site());
}
}
{
UMA_HISTOGRAM_BOOLEAN(
"Navigation.RequiresDedicatedProcess",
new_rfh->GetSiteInstance()->RequiresDedicatedProcess());
if (common_params.url.SchemeIsHTTPOrHTTPS()) {
UMA_HISTOGRAM_BOOLEAN(
"Navigation.RequiresDedicatedProcess.HTTPOrHTTPS",
new_rfh->GetSiteInstance()->RequiresDedicatedProcess());
}
}
{
constexpr absl::optional<bool> kIsBackground = absl::nullopt;
base::TimeDelta delta =
ready_to_commit_time - common_params.navigation_start;
ui::PageTransition transition =
ui::PageTransitionFromInt(common_params.transition);
LOG_NAVIGATION_TIMING_HISTOGRAM("TimeToReadyToCommit2", transition,
kIsBackground, delta);
if (is_main_frame) {
LOG_NAVIGATION_TIMING_HISTOGRAM("TimeToReadyToCommit2.MainFrame",
transition, kIsBackground, delta);
} else {
LOG_NAVIGATION_TIMING_HISTOGRAM("TimeToReadyToCommit2.Subframe",
transition, kIsBackground, delta);
}
if (is_same_process) {
LOG_NAVIGATION_TIMING_HISTOGRAM("TimeToReadyToCommit2.SameProcess",
transition, kIsBackground, delta);
} else {
LOG_NAVIGATION_TIMING_HISTOGRAM("TimeToReadyToCommit2.CrossProcess",
transition, kIsBackground, delta);
}
if (did_receive_early_hints_before_cross_origin_redirect) {
LOG_NAVIGATION_TIMING_HISTOGRAM(
"TimeToReadyToCommit2.CrossOriginRedirectAfterEarlyHints", transition,
kIsBackground, delta);
}
}
{
UMA_HISTOGRAM_ENUMERATION("Navigation.OriginAgentCluster.Result",
origin_agent_cluster_end_result);
}
{
base::UmaHistogramBoolean("Navigation.IsGuest",
new_rfh->GetSiteInstance()->IsGuest());
if (new_rfh->GetSiteInstance()->IsGuest()) {
base::UmaHistogramBoolean("Navigation.Guest.IsHTTPOrHTTPS",
common_params.url.SchemeIsHTTPOrHTTPS());
base::UmaHistogramBoolean("Navigation.Guest.IsMainFrame", is_main_frame);
}
}
}
blink::mojom::NavigationType ConvertToCrossDocumentType(
blink::mojom::NavigationType type) {
switch (type) {
case blink::mojom::NavigationType::SAME_DOCUMENT:
return blink::mojom::NavigationType::DIFFERENT_DOCUMENT;
case blink::mojom::NavigationType::HISTORY_SAME_DOCUMENT:
return blink::mojom::NavigationType::HISTORY_DIFFERENT_DOCUMENT;
case blink::mojom::NavigationType::RELOAD:
case blink::mojom::NavigationType::RELOAD_BYPASSING_CACHE:
case blink::mojom::NavigationType::RELOAD_ORIGINAL_REQUEST_URL:
case blink::mojom::NavigationType::RESTORE:
case blink::mojom::NavigationType::RESTORE_WITH_POST:
case blink::mojom::NavigationType::HISTORY_DIFFERENT_DOCUMENT:
case blink::mojom::NavigationType::DIFFERENT_DOCUMENT:
return type;
}
}
base::debug::CrashKeyString* GetNavigationRequestUrlCrashKey() {
static auto* crash_key = base::debug::AllocateCrashKeyString(
"navigation_request_url", base::debug::CrashKeySize::Size256);
return crash_key;
}
base::debug::CrashKeyString* GetNavigationRequestInitiatorCrashKey() {
static auto* crash_key = base::debug::AllocateCrashKeyString(
"navigation_request_initiator", base::debug::CrashKeySize::Size64);
return crash_key;
}
base::debug::CrashKeyString* GetNavigationRequestIsSameDocumentCrashKey() {
static auto* crash_key = base::debug::AllocateCrashKeyString(
"navigation_request_is_same_document", base::debug::CrashKeySize::Size64);
return crash_key;
}
void EnterChildTraceEvent(const char* name, NavigationRequest* request) {
TRACE_EVENT_NESTABLE_ASYNC_END0("navigation", "", request->GetNavigationId());
TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("navigation", name,
request->GetNavigationId());
}
template <typename ArgType>
void EnterChildTraceEvent(const char* name,
NavigationRequest* request,
const char* arg_name,
ArgType 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(
FrameTreeNode* frame_tree_node) {
if (frame_tree_node->IsInFencedFrameTree())
return network::mojom::RequestDestination::kFencedframe;
if (frame_tree_node->IsMainFrame()) {
if (frame_tree_node->frame_tree().IsPortal()) {
return network::mojom::RequestDestination::kIframe;
}
return network::mojom::RequestDestination::kDocument;
}
switch (frame_tree_node->frame_owner_element_type()) {
case blink::FrameOwnerElementType::kObject:
return network::mojom::RequestDestination::kObject;
case blink::FrameOwnerElementType::kEmbed:
return network::mojom::RequestDestination::kEmbed;
case blink::FrameOwnerElementType::kIframe:
return network::mojom::RequestDestination::kIframe;
case blink::FrameOwnerElementType::kFrame:
return network::mojom::RequestDestination::kFrame;
case blink::FrameOwnerElementType::kPortal:
case blink::FrameOwnerElementType::kNone:
NOTREACHED();
return network::mojom::RequestDestination::kDocument;
case blink::FrameOwnerElementType::kFencedframe:
NOTREACHED();
return network::mojom::RequestDestination::kFencedframe;
}
}
std::pair<url::Origin, std::string>
GetOriginForURLLoaderFactoryUncheckedWithDebugInfo(
NavigationRequest* navigation_request) {
DCHECK(navigation_request);
const blink::mojom::CommonNavigationParams& common_params =
navigation_request->common_params();
if (navigation_request->DidEncounterError()) {
return std::make_pair(
url::Origin::Create(common_params.url).DeriveNewOpaqueOrigin(),
"error");
}
if (navigation_request->IsLoadDataWithBaseURL()) {
CHECK(navigation_request->browser_initiated() ||
NavigationTypeUtils::IsHistory(
navigation_request->common_params().navigation_type));
return std::make_pair(
url::Origin::Create(common_params.base_url_for_data_url),
"load_data_with_base_url");
}
if (navigation_request->GetURL().IsAboutSrcdoc()) {
RenderFrameHostImpl* parent =
navigation_request->frame_tree_node()->parent();
DCHECK(parent);
return std::make_pair(parent->GetLastCommittedOrigin(), "about_srcdoc");
}
if (common_params.url.SchemeIs(url::kUuidInPackageScheme) &&
navigation_request->GetWebBundleURL().is_valid()) {
return std::make_pair(
url::Origin::Resolve(
common_params.url,
url::Origin::Create(navigation_request->GetWebBundleURL())),
"web_bundle");
}
return std::make_pair(
url::Origin::Resolve(
common_params.url,
common_params.initiator_origin.value_or(url::Origin())),
"url_or_initiator");
}
url::Origin GetOriginForURLLoaderFactoryUnchecked(
NavigationRequest* navigation_request) {
return GetOriginForURLLoaderFactoryUncheckedWithDebugInfo(navigation_request)
.first;
}
bool CoepBlockIframe(network::mojom::CrossOriginEmbedderPolicyValue parent_coep,
network::mojom::CrossOriginEmbedderPolicyValue child_coep,
bool is_credentialless) {
return !is_credentialless &&
(network::CompatibleWithCrossOriginIsolated(parent_coep) &&
!network::CompatibleWithCrossOriginIsolated(child_coep));
}
int EstimateHistoryOffset(NavigationController& controller,
bool should_replace_current_entry) {
if (should_replace_current_entry)
return 0;
int current_index = controller.GetLastCommittedEntryIndex();
int pending_index = controller.GetPendingEntryIndex();
if (current_index == -1 || pending_index == -1)
return 1;
return pending_index - current_index;
}
bool IsDocumentToCommitAnonymous(FrameTreeNode* frame,
bool is_synchronous_about_blank_navigation) {
if (frame->IsFencedFrameRoot())
return false;
RenderFrameHostImpl* current_document = frame->current_frame_host();
RenderFrameHostImpl* parent_document = frame->parent();
if (is_synchronous_about_blank_navigation)
return current_document->IsCredentialless();
bool parent_is_credentialless =
parent_document && parent_document->IsCredentialless();
return parent_is_credentialless || frame->Credentialless();
}
const GURL& GetLastLoadingURLInRendererForNavigationReplacement(
RenderFrameHostImpl* rfh) {
if (rfh->IsErrorDocument() ||
rfh->was_loaded_from_load_data_with_base_url()) {
return rfh->GetLastCommittedURL();
}
return rfh->last_document_url_in_renderer();
}
bool IsOptedInFencedFrame(const net::HttpResponseHeaders& http_headers) {
network::mojom::SupportsLoadingModePtr result =
network::ParseSupportsLoadingMode(http_headers);
return !result.is_null() &&
base::Contains(result->supported_modes,
network::mojom::LoadingMode::kFencedFrame);
}
void RemoveOriginTrialHintsFromAcceptCH(
const GURL& url,
ClientHintsControllerDelegate* delegate,
const network::mojom::URLResponseHead* response,
std::vector<network::mojom::WebClientHintsType>& client_hints,
FrameTreeNode* frame_tree_node) {
if (!response || response->parsed_headers->accept_ch)
return;
std::vector<network::mojom::WebClientHintsType> hints_to_remove = {
network::mojom::WebClientHintsType::kUAReduced,
network::mojom::WebClientHintsType::kFullUserAgent};
bool need_update_storage = false;
for (const auto& hint : hints_to_remove) {
if (base::Contains(client_hints, hint)) {
base::Erase(client_hints, hint);
need_update_storage = true;
}
}
if (need_update_storage) {
DCHECK(frame_tree_node);
PersistAcceptCH(url::Origin::Create(url), *frame_tree_node, delegate,
client_hints);
}
}
void PersistOriginTrialsFromHeaders(
const url::Origin& origin,
const url::Origin& partition_origin,
const network::mojom::URLResponseHead* response,
BrowserContext* browser_context) {
if (!base::FeatureList::IsEnabled(features::kPersistentOriginTrials))
return;
if (origin.opaque())
return;
if (!response || !response->headers)
return;
OriginTrialsControllerDelegate* origin_trials_delegate =
browser_context->GetOriginTrialsControllerDelegate();
if (!origin_trials_delegate)
return;
std::vector<std::string> tokens =
GetOriginTrialHeaderValues(response->headers.get());
origin_trials_delegate->PersistTrialsFromTokens(origin, partition_origin,
tokens, base::Time::Now());
}
absl::optional<std::string> GetTopicsHeaderValueForNavigationRequest(
FrameTreeNode* frame_tree_node,
const GURL& url) {
if (!frame_tree_node->browsing_topics()) {
return absl::nullopt;
}
RenderFrameHostImpl* rfh = frame_tree_node->current_frame_host();
if (rfh->is_main_frame()) {
return absl::nullopt;
}
if (rfh->IsNestedWithinFencedFrame()) {
return absl::nullopt;
}
if (!rfh->GetPage().IsPrimary()) {
return absl::nullopt;
}
if (!static_cast<RenderFrameHostImpl*>(rfh->GetMainFrame())
->IsOutermostMainFrame()) {
return absl::nullopt;
}
url::Origin origin = url::Origin::Create(url);
if (origin.opaque()) {
return absl::nullopt;
}
if (!network::IsOriginPotentiallyTrustworthy(origin)) {
return absl::nullopt;
}
const blink::PermissionsPolicy* parent_policy =
rfh->GetParent()->permissions_policy();
DCHECK(parent_policy);
if (!parent_policy->IsFeatureEnabledForOrigin(
blink::mojom::PermissionsPolicyFeature::kBrowsingTopics, origin) ||
!parent_policy->IsFeatureEnabledForOrigin(
blink::mojom::PermissionsPolicyFeature::
kBrowsingTopicsBackwardCompatible,
origin)) {
return absl::nullopt;
}
std::vector<blink::mojom::EpochTopicPtr> topics;
bool topics_eligible = GetContentClient()->browser()->HandleTopicsWebApi(
origin, rfh->GetMainFrame(),
browsing_topics::ApiCallerSource::kIframeAttribute,
true,
false, topics);
if (!topics_eligible) {
return absl::nullopt;
}
return DeriveTopicsHeaderValue(topics);
}
}
NavigationRequest::PrerenderActivationNavigationState::
PrerenderActivationNavigationState() = default;
NavigationRequest::PrerenderActivationNavigationState::
~PrerenderActivationNavigationState() = default;
std::unique_ptr<NavigationRequest> NavigationRequest::CreateBrowserInitiated(
FrameTreeNode* frame_tree_node,
blink::mojom::CommonNavigationParamsPtr common_params,
blink::mojom::CommitNavigationParamsPtr commit_params,
bool was_opener_suppressed,
const blink::LocalFrameToken* initiator_frame_token,
int initiator_process_id,
const std::string& extra_headers,
FrameNavigationEntry* frame_entry,
NavigationEntryImpl* entry,
bool is_form_submission,
std::unique_ptr<NavigationUIData> navigation_ui_data,
const absl::optional<blink::Impression>& impression,
bool is_pdf,
bool is_embedder_initiated_fenced_frame_navigation,
absl::optional<std::u16string> embedder_shared_storage_context) {
return Create(
frame_tree_node, std::move(common_params), std::move(commit_params),
true, was_opener_suppressed, initiator_frame_token,
initiator_process_id, extra_headers, frame_entry, entry,
is_form_submission, std::move(navigation_ui_data), impression,
blink::mojom::NavigationInitiatorActivationAndAdStatus::
kDidNotStartWithTransientActivation,
is_pdf, is_embedder_initiated_fenced_frame_navigation,
false, embedder_shared_storage_context);
}
std::unique_ptr<NavigationRequest> NavigationRequest::Create(
FrameTreeNode* frame_tree_node,
blink::mojom::CommonNavigationParamsPtr common_params,
blink::mojom::CommitNavigationParamsPtr commit_params,
bool browser_initiated,
bool was_opener_suppressed,
const blink::LocalFrameToken* initiator_frame_token,
int initiator_process_id,
const std::string& extra_headers,
FrameNavigationEntry* frame_entry,
NavigationEntryImpl* entry,
bool is_form_submission,
std::unique_ptr<NavigationUIData> navigation_ui_data,
const absl::optional<blink::Impression>& impression,
blink::mojom::NavigationInitiatorActivationAndAdStatus
initiator_activation_and_ad_status,
bool is_pdf,
bool is_embedder_initiated_fenced_frame_navigation,
bool is_container_initiated,
absl::optional<std::u16string> embedder_shared_storage_context) {
TRACE_EVENT1("navigation", "NavigationRequest::Create", "browser_initiated",
browser_initiated);
common_params->request_destination =
GetDestinationFromFrameTreeNode(frame_tree_node);
absl::optional<network::ResourceRequest::WebBundleTokenParams>
web_bundle_token_params;
if (frame_entry && frame_entry->subresource_web_bundle_navigation_info()) {
auto* bundle_info = frame_entry->subresource_web_bundle_navigation_info();
web_bundle_token_params =
absl::make_optional(network::ResourceRequest::WebBundleTokenParams(
bundle_info->bundle_url(), bundle_info->token(),
bundle_info->render_process_id()));
}
auto navigation_params = blink::mojom::BeginNavigationParams::New(
base::OptionalFromPtr(initiator_frame_token), extra_headers,
net::LOAD_NORMAL, false ,
blink::mojom::RequestContextType::LOCATION,
blink::mojom::MixedContentContextType::kBlockable, is_form_submission,
false ,
blink::mojom::ForceHistoryPush::kNo, GURL() ,
std::string() ,
GURL() ,
absl::nullopt ,
nullptr , impression,
base::TimeTicks() ,
base::TimeTicks() ,
std::move(web_bundle_token_params), initiator_activation_and_ad_status,
is_container_initiated, false ,
false );
if (common_params->navigation_type ==
blink::mojom::NavigationType::RELOAD_BYPASSING_CACHE) {
navigation_params->load_flags |= net::LOAD_BYPASS_CACHE;
navigation_params->skip_service_worker = true;
}
base::WeakPtr<RenderFrameHostImpl> rfh_restored_from_back_forward_cache =
nullptr;
if (entry) {
auto restored_entry = frame_tree_node->navigator()
.controller()
.GetBackForwardCache()
.GetOrEvictEntry(entry->GetUniqueID());
if (restored_entry.has_value()) {
if (frame_tree_node->IsMainFrame()) {
rfh_restored_from_back_forward_cache =
restored_entry.value()->render_frame_host()->GetWeakPtr();
} else {
CaptureTraceForNavigationDebugScenario(
DebugScenario::
kDebugBackForwardCacheEntryExistsOnSubframeHistoryNav);
}
}
}
scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory;
if (frame_entry) {
blob_url_loader_factory = frame_entry->blob_url_loader_factory();
if (common_params->url.SchemeIsBlob() && !blob_url_loader_factory) {
blob_url_loader_factory =
ChromeBlobStorageContext::URLLoaderFactoryForUrl(
frame_tree_node->navigator()
.controller()
.GetBrowserContext()
->GetStoragePartition(frame_entry->site_instance()),
common_params->url);
}
}
std::unique_ptr<NavigationRequest> navigation_request(new NavigationRequest(
frame_tree_node, std::move(common_params), std::move(navigation_params),
std::move(commit_params), browser_initiated,
false ,
false , frame_entry, entry,
std::move(navigation_ui_data), std::move(blob_url_loader_factory),
mojo::NullAssociatedRemote(),
nullptr ,
rfh_restored_from_back_forward_cache, initiator_process_id,
was_opener_suppressed, is_pdf,
is_embedder_initiated_fenced_frame_navigation,
mojo::NullReceiver() ,
embedder_shared_storage_context));
return navigation_request;
}
std::unique_ptr<NavigationRequest> NavigationRequest::CreateRendererInitiated(
FrameTreeNode* frame_tree_node,
NavigationEntryImpl* entry,
blink::mojom::CommonNavigationParamsPtr common_params,
blink::mojom::BeginNavigationParamsPtr begin_params,
int current_history_list_offset,
int current_history_list_length,
bool override_user_agent,
scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
mojo::PendingAssociatedRemote<mojom::NavigationClient> navigation_client,
scoped_refptr<PrefetchedSignedExchangeCache>
prefetched_signed_exchange_cache,
mojo::PendingReceiver<mojom::NavigationRendererCancellationListener>
renderer_cancellation_listener) {
TRACE_EVENT0("navigation", "NavigationRequest::CreateRendererInitiated");
DCHECK(NavigationTypeUtils::IsReload(common_params->navigation_type) ||
common_params->navigation_type ==
blink::mojom::NavigationType::DIFFERENT_DOCUMENT);
common_params->request_destination =
GetDestinationFromFrameTreeNode(frame_tree_node);
const bool load_with_storage_access =
begin_params->has_storage_access &&
common_params->initiator_origin.has_value() &&
common_params->initiator_origin->IsSameOriginWith(common_params->url) &&
begin_params->initiator_frame_token.has_value() &&
begin_params->initiator_frame_token ==
frame_tree_node->current_frame_host()->GetFrameToken();
blink::mojom::CommitNavigationParamsPtr commit_params =
blink::mojom::CommitNavigationParams::New(
absl::nullopt,
blink::StorageKey(), blink::StorageKey(), override_user_agent,
std::vector<GURL>(),
std::vector<network::mojom::URLResponseHeadPtr>(),
std::vector<net::RedirectInfo>(),
std::string(), common_params->url,
common_params->method,
false,
std::string(),
0,
base::flat_map<std::string, bool>(),
false,
-1, current_history_list_offset,
current_history_list_length,
false,
false,
false,
blink::mojom::NavigationTiming::New(),
blink::mojom::WasActivatedOption::kUnknown,
base::UnguessableToken::Create(),
std::vector<blink::mojom::PrefetchedSignedExchangeInfoPtr>(),
#if BUILDFLAG(IS_ANDROID)
std::string(),
#endif
false,
ukm::kInvalidSourceId,
frame_tree_node->pending_frame_policy(),
std::vector<std::string>(),
false,
true,
std::vector<network::mojom::WebClientHintsType>(),
false,
false,
nullptr, -1,
blink::mojom::NavigationApiHistoryEntryArrays::New(),
std::vector<GURL>(),
base::TimeTicks(), std::string(),
false,
frame_tree_node->AncestorOrSelfHasCSPEE(),
std::string(),
network::mojom::NavigationDeliveryType::kDefault,
absl::nullopt,
absl::nullopt,
base::flat_map<::blink::mojom::RuntimeFeatureState, bool>(),
absl::nullopt,
nullptr,
load_with_storage_access
#ifdef OHOS_ARKWEB_ADBLOCK
,
false
#endif
);
int initiator_process_id =
frame_tree_node->current_frame_host()->GetProcess()->GetID();
std::unique_ptr<NavigationRequest> navigation_request(new NavigationRequest(
frame_tree_node, std::move(common_params), std::move(begin_params),
std::move(commit_params),
false,
true,
false,
nullptr,
entry,
nullptr,
std::move(blob_url_loader_factory), std::move(navigation_client),
std::move(prefetched_signed_exchange_cache),
nullptr,
initiator_process_id,
false, false,
false,
std::move(renderer_cancellation_listener)));
return navigation_request;
}
std::unique_ptr<NavigationRequest>
NavigationRequest::CreateForSynchronousRendererCommit(
FrameTreeNode* frame_tree_node,
RenderFrameHostImpl* render_frame_host,
bool is_same_document,
const GURL& url,
const url::Origin& origin,
const absl::optional<GURL>& initiator_base_url,
const net::IsolationInfo& isolation_info_for_subresources,
blink::mojom::ReferrerPtr referrer,
const ui::PageTransition& transition,
bool should_replace_current_entry,
const std::string& method,
bool has_transient_activation,
bool is_overriding_user_agent,
const std::vector<GURL>& redirects,
const GURL& original_url,
std::unique_ptr<CrossOriginEmbedderPolicyReporter> coep_reporter,
std::unique_ptr<SubresourceWebBundleNavigationInfo>
subresource_web_bundle_navigation_info,
int http_response_code) {
TRACE_EVENT0("navigation", "NavigationRequest::CreateForSynchronousRendererCommit");
blink::mojom::CommonNavigationParamsPtr common_params =
blink::mojom::CommonNavigationParams::New(
url,
origin, initiator_base_url, std::move(referrer), transition,
is_same_document ? blink::mojom::NavigationType::SAME_DOCUMENT
: blink::mojom::NavigationType::DIFFERENT_DOCUMENT,
blink::NavigationDownloadPolicy(), should_replace_current_entry,
GURL() , base::TimeTicks::Now(),
method , nullptr ,
network::mojom::SourceLocation::New(),
false , has_transient_activation,
false ,
network::mojom::CSPDisposition::CHECK,
std::vector<int>() ,
std::string() ,
false ,
base::TimeTicks::Now() ,
network::mojom::RequestDestination::kEmpty);
blink::mojom::CommitNavigationParamsPtr commit_params =
blink::mojom::CommitNavigationParams::New(
absl::nullopt,
blink::StorageKey(), blink::StorageKey(), is_overriding_user_agent,
redirects,
std::vector<network::mojom::URLResponseHeadPtr>(),
std::vector<net::RedirectInfo>(),
std::string(), original_url,
method,
false,
std::string(),
0,
base::flat_map<std::string, bool>(),
false,
-1,
-1,
-1,
false,
false,
false,
blink::mojom::NavigationTiming::New(),
blink::mojom::WasActivatedOption::kUnknown,
base::UnguessableToken::Create(),
std::vector<blink::mojom::PrefetchedSignedExchangeInfoPtr>(),
#if BUILDFLAG(IS_ANDROID)
std::string(),
#endif
false,
ukm::kInvalidSourceId,
frame_tree_node->pending_frame_policy(),
std::vector<std::string>(),
false,
true,
std::vector<network::mojom::WebClientHintsType>(),
false,
false,
nullptr, http_response_code,
blink::mojom::NavigationApiHistoryEntryArrays::New(),
std::vector<GURL>(),
base::TimeTicks(), std::string(),
false,
frame_tree_node->AncestorOrSelfHasCSPEE(),
std::string(),
network::mojom::NavigationDeliveryType::kDefault,
absl::nullopt,
absl::nullopt,
base::flat_map<::blink::mojom::RuntimeFeatureState, bool>(),
absl::nullopt,
nullptr,
false
#ifdef OHOS_ARKWEB_ADBLOCK
,
false
#endif
);
blink::mojom::BeginNavigationParamsPtr begin_params =
blink::mojom::BeginNavigationParams::New();
std::unique_ptr<NavigationRequest> navigation_request(new NavigationRequest(
frame_tree_node, std::move(common_params), std::move(begin_params),
std::move(commit_params), false ,
false ,
true ,
nullptr , nullptr ,
nullptr , nullptr ,
mojo::NullAssociatedRemote(),
nullptr ,
nullptr ,
ChildProcessHost::kInvalidUniqueID ,
false , false ));
absl::optional<base::UnguessableToken> nonce =
render_frame_host->ComputeNonce(
navigation_request->is_credentialless(),
navigation_request->ComputeFencedFrameNonce());
url::Origin top_level_origin =
render_frame_host->ComputeTopFrameOrigin(origin);
if (nonce) {
navigation_request->commit_params_->storage_key =
blink::StorageKey::CreateWithNonce(origin, *nonce);
} else {
net::SchemefulSite top_level_site(top_level_origin);
blink::mojom::AncestorChainBit ancestor_chain_bit =
blink::mojom::AncestorChainBit::kSameSite;
if (render_frame_host->ComputeSiteForCookies().IsNull() ||
net::SchemefulSite(origin) != top_level_site ||
!top_level_site.opaque() || origin.opaque()) {
ancestor_chain_bit = blink::mojom::AncestorChainBit::kCrossSite;
}
navigation_request->commit_params_->storage_key =
blink::StorageKey::Create(origin, top_level_site, ancestor_chain_bit);
}
navigation_request->commit_params_->session_storage_key =
frame_tree_node->frame_tree().GetSessionStorageKey(
navigation_request->commit_params_->storage_key);
if (subresource_web_bundle_navigation_info) {
navigation_request->begin_params_->web_bundle_token =
absl::make_optional(network::ResourceRequest::WebBundleTokenParams(
subresource_web_bundle_navigation_info->bundle_url(),
subresource_web_bundle_navigation_info->token(),
subresource_web_bundle_navigation_info->render_process_id()));
}
navigation_request->render_frame_host_ = render_frame_host->GetSafeRef();
navigation_request->coep_reporter_ = std::move(coep_reporter);
navigation_request->isolation_info_for_subresources_ =
isolation_info_for_subresources;
navigation_request->associated_rfh_type_ =
AssociatedRenderFrameHostType::CURRENT;
navigation_request->StartNavigation();
DCHECK(navigation_request->IsNavigationStarted());
return navigation_request;
}
int64_t NavigationRequest::unique_id_counter_ = 0;
NavigationRequest::NavigationRequest(
FrameTreeNode* frame_tree_node,
blink::mojom::CommonNavigationParamsPtr common_params,
blink::mojom::BeginNavigationParamsPtr begin_params,
blink::mojom::CommitNavigationParamsPtr commit_params,
bool browser_initiated,
bool from_begin_navigation,
bool is_synchronous_renderer_commit,
const FrameNavigationEntry* frame_entry,
NavigationEntryImpl* entry,
std::unique_ptr<NavigationUIData> navigation_ui_data,
scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
mojo::PendingAssociatedRemote<mojom::NavigationClient> navigation_client,
scoped_refptr<PrefetchedSignedExchangeCache>
prefetched_signed_exchange_cache,
base::WeakPtr<RenderFrameHostImpl> rfh_restored_from_back_forward_cache,
int initiator_process_id,
bool was_opener_suppressed,
bool is_pdf,
bool is_embedder_initiated_fenced_frame_navigation,
mojo::PendingReceiver<mojom::NavigationRendererCancellationListener>
renderer_cancellation_listener,
absl::optional<std::u16string> embedder_shared_storage_context)
: frame_tree_node_(frame_tree_node),
is_synchronous_renderer_commit_(is_synchronous_renderer_commit),
common_params_(std::move(common_params)),
begin_params_(std::move(begin_params)),
commit_params_(std::move(commit_params)),
navigation_ui_data_(std::move(navigation_ui_data)),
blob_url_loader_factory_(std::move(blob_url_loader_factory)),
restore_type_(entry ? entry->restore_type() : RestoreType::kNotRestored),
reload_type_(
entry ? entry->reload_type()
: NavigationTypeToReloadType(common_params_->navigation_type)),
nav_entry_id_(entry ? entry->GetUniqueID() : 0),
from_begin_navigation_(from_begin_navigation),
site_info_(
frame_tree_node_->navigator().controller().GetBrowserContext()),
navigation_entry_offset_(
EstimateHistoryOffset(frame_tree_node_->navigator().controller(),
common_params_->should_replace_current_entry)),
prefetched_signed_exchange_cache_(
std::move(prefetched_signed_exchange_cache)),
rfh_restored_from_back_forward_cache_(
rfh_restored_from_back_forward_cache),
is_back_forward_cache_restore_(!!rfh_restored_from_back_forward_cache),
previous_render_frame_host_id_(
frame_tree_node->current_frame_host()->GetGlobalId()),
initiator_frame_token_(begin_params_->initiator_frame_token),
initiator_process_id_(initiator_process_id),
was_opener_suppressed_(was_opener_suppressed),
is_credentialless_(
IsDocumentToCommitAnonymous(frame_tree_node,
is_synchronous_renderer_commit)),
previous_page_ukm_source_id_(
frame_tree_node_->current_frame_host()->GetPageUkmSourceId()),
is_pdf_(is_pdf),
is_embedder_initiated_fenced_frame_navigation_(
is_embedder_initiated_fenced_frame_navigation),
is_embedder_initiated_fenced_frame_opaque_url_navigation_(
is_embedder_initiated_fenced_frame_navigation
? blink::IsValidUrnUuidURL(common_params_->url)
: false),
is_target_fenced_frame_root_originating_from_opaque_url_(
is_embedder_initiated_fenced_frame_navigation
? is_embedder_initiated_fenced_frame_opaque_url_navigation_
: frame_tree_node->current_frame_host()
->is_fenced_frame_root_originating_from_opaque_url()),
fenced_frame_properties_(
is_embedder_initiated_fenced_frame_navigation
? absl::make_optional(FencedFrameProperties())
: absl::nullopt),
embedder_shared_storage_context_(embedder_shared_storage_context) {
CHECK(!common_params_->initiator_base_url ||
!common_params_->initiator_base_url->is_empty());
DCHECK(!blink::IsRendererDebugURL(common_params_->url));
DCHECK(common_params_->method == "POST" || !common_params_->post_data);
DCHECK_EQ(common_params_->url, commit_params_->original_url);
DCHECK(!common_params_->should_replace_current_entry ||
!NavigationTypeUtils::IsReload(common_params_->navigation_type));
DCHECK(IsInOutermostMainFrame() ||
common_params_->base_url_for_data_url.is_empty());
#if BUILDFLAG(IS_ANDROID)
DCHECK(IsInOutermostMainFrame() ||
commit_params_->data_url_as_string.empty());
#endif
CHECK(!rfh_restored_from_back_forward_cache.WasInvalidated());
CheckSoftNavigationHeuristicsInvariants();
ScopedCrashKeys crash_keys(*this);
ComputeDownloadPolicy();
runtime_feature_state_context_ = blink::RuntimeFeatureStateContext();
if (GetURL().SchemeIs(url::kAboutScheme) && !GetURL().IsAboutBlank() &&
!GetURL().IsAboutSrcdoc()) {
NOTREACHED();
base::debug::DumpWithoutCrashing();
}
TRACE_EVENT1("navigation", "NavigationRequest::NavigationRequest",
"navigation_request", this);
TRACE_EVENT_NESTABLE_ASYNC_BEGIN1("navigation", "NavigationRequest",
navigation_id_, "navigation_request", this);
TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("navigation", "Initializing",
navigation_id_);
if (GetInitiatorFrameToken().has_value()) {
RenderFrameHostImpl* initiator_rfh = RenderFrameHostImpl::FromFrameToken(
GetInitiatorProcessID(), GetInitiatorFrameToken().value());
if (initiator_rfh)
initiator_document_ = initiator_rfh->GetWeakDocumentPtr();
}
if (begin_params_->is_container_initiated) {
commit_params_->navigation_timing->parent_resource_timing_access =
GetParentFrame()->GetLastCommittedOrigin().IsSameOriginWith(GetURL())
? blink::mojom::ParentResourceTimingAccess::
kReportWithResponseDetails
: blink::mojom::ParentResourceTimingAccess::
kReportWithoutResponseDetails;
}
navigation_or_document_handle_ =
NavigationOrDocumentHandle::CreateForNavigation(*this);
policy_container_builder_.emplace(
GetParentFrame(),
initiator_frame_token_.has_value() ? &*initiator_frame_token_ : nullptr,
frame_entry);
NavigationControllerImpl* controller = GetNavigationController();
if (frame_entry) {
frame_entry_item_sequence_number_ = frame_entry->item_sequence_number();
frame_entry_document_sequence_number_ =
frame_entry->document_sequence_number();
}
common_params_->referrer = Referrer::SanitizeForRequest(
common_params_->url, *common_params_->referrer);
if (IsInPrimaryMainFrame()) {
loading_mem_tracker_ =
PeakGpuMemoryTracker::Create(PeakGpuMemoryTracker::Usage::PAGE_LOAD);
}
if (frame_tree_node_->IsInFencedFrameTree()) {
commit_params_->frame_policy.sandbox_flags |=
blink::kFencedFrameForcedSandboxFlags;
}
if (from_begin_navigation_) {
source_site_instance_ =
frame_tree_node->current_frame_host()->GetSiteInstance();
DCHECK(navigation_client.is_valid());
SetNavigationClient(std::move(navigation_client));
if (renderer_cancellation_listener.is_valid()) {
renderer_cancellation_listener_.Bind(
std::move(renderer_cancellation_listener),
GetUIThreadTaskRunner({BrowserTaskType::kNavigationNetworkResponse}));
}
} else if (entry) {
DCHECK(!navigation_client.is_valid());
if (frame_entry) {
source_site_instance_ = frame_entry->source_site_instance();
dest_site_instance_ = frame_entry->site_instance();
bindings_ = frame_entry->bindings();
if (common_params_->is_history_navigation_in_new_child_frame ||
common_params_->navigation_type ==
blink::mojom::NavigationType::RESTORE ||
common_params_->navigation_type ==
blink::mojom::NavigationType::RESTORE_WITH_POST ||
was_opener_suppressed) {
SetSourceSiteInstanceToInitiatorIfNeeded();
}
}
isolation_info_ = entry->isolation_info();
DCHECK(!RequiresInitiatorBasedSourceSiteInstance() ||
source_site_instance_);
}
if (source_site_instance_) {
bool is_renderer_initiated = !browser_initiated;
Referrer referrer(*common_params_->referrer);
ui::PageTransition transition =
ui::PageTransitionFromInt(common_params_->transition);
GetContentClient()->browser()->OverrideNavigationParams(
source_site_instance_.get(), &transition, &is_renderer_initiated,
&referrer, &common_params_->initiator_origin);
common_params_->transition = transition;
common_params_->referrer =
blink::mojom::Referrer::New(referrer.url, referrer.policy);
browser_initiated = !is_renderer_initiated;
}
commit_params_->is_browser_initiated = browser_initiated;
UpdateLoadFlagsWithCacheFlags(&begin_params_->load_flags,
common_params_->navigation_type,
common_params_->method == "POST");
if (entry) {
if (frame_tree_node->IsOutermostMainFrame() &&
entry->back_forward_cache_metrics()) {
entry->back_forward_cache_metrics()
->MainFrameDidStartNavigationToDocument();
}
if (entry == controller->GetPendingEntry())
pending_entry_ref_ = controller->ReferencePendingEntry();
DCHECK_EQ(is_overriding_user_agent(), entry->GetIsOverridingUserAgent());
}
net::HttpRequestHeaders headers;
if (!is_synchronous_renderer_commit) {
BrowserContext* browser_context = controller->GetBrowserContext();
ClientHintsControllerDelegate* client_hints_delegate =
browser_context->GetClientHintsControllerDelegate();
if ((CheckAboutSrcDoc() != AboutSrcDocCheckResult::BLOCK_REQUEST) &&
client_hints_delegate) {
net::HttpRequestHeaders client_hints_headers;
AddNavigationRequestClientHintsHeaders(
GetTentativeOriginAtRequestTime(), &client_hints_headers,
browser_context, client_hints_delegate, is_overriding_user_agent(),
frame_tree_node_, commit_params_->frame_policy.container_policy,
common_params_->url);
headers.MergeFrom(client_hints_headers);
}
if (auto reduce_accept_lang_utils =
ReduceAcceptLanguageUtils::Create(browser_context);
reduce_accept_lang_utils && !devtools_accept_language_override_) {
net::HttpRequestHeaders accept_language_headers;
absl::optional<std::string> reduced_accept_language =
reduce_accept_lang_utils.value()
.AddNavigationRequestAcceptLanguageHeaders(
url::Origin::Create(common_params_->url), frame_tree_node_,
&accept_language_headers);
commit_params_->reduced_accept_language =
reduced_accept_language.value_or("");
headers.MergeFrom(accept_language_headers);
}
headers.AddHeadersFromString(begin_params_->headers);
AddAdditionalRequestHeaders(
&headers, common_params_->url, common_params_->navigation_type,
ui::PageTransitionFromInt(common_params_->transition),
controller->GetBrowserContext(), common_params_->method,
GetUserAgentOverride(), common_params_->initiator_origin,
common_params_->referrer.get(), frame_tree_node);
if (begin_params_->is_form_submission) {
if (!commit_params_->post_content_type.empty()) {
headers.SetHeaderIfMissing(net::HttpRequestHeaders::kContentType,
commit_params_->post_content_type);
}
headers.GetHeader(net::HttpRequestHeaders::kContentType,
&commit_params_->post_content_type);
}
absl::optional<std::string> topics_header_value =
GetTopicsHeaderValueForNavigationRequest(frame_tree_node,
common_params_->url);
topics_eligible_ = topics_header_value.has_value();
if (topics_eligible_) {
headers.SetHeader(kBrowsingTopicsRequestHeaderKey, *topics_header_value);
}
}
begin_params_->headers = headers.ToString();
#if BUILDFLAG(IS_ANDROID)
RenderWidgetHostImpl* host = RenderWidgetHostImpl::From(
frame_tree_node_->current_frame_host()->GetRenderWidgetHost());
if (NeedsUrlLoader() && IsInPrimaryMainFrame() && host &&
!host->is_hidden() && host->GetView() &&
host->GetView()->GetNativeView() &&
host->GetView()->GetNativeView()->GetWindowAndroid()) {
ui::WindowAndroidCompositor* compositor =
host->GetView()->GetNativeView()->GetWindowAndroid()->GetCompositor();
if (compositor) {
compositor_lock_ = compositor->GetCompositorLock(kCompositorLockTimeout);
}
}
navigation_handle_proxy_ = std::make_unique<NavigationHandleProxy>(this);
#endif
if (base::FeatureList::IsEnabled(features::kNavigationRequestPreconnect) &&
NeedsUrlLoader() && common_params_->url.SchemeIsHTTPOrHTTPS()) {
BrowserContext* browser_context =
frame_tree_node_->navigator().controller().GetBrowserContext();
if (GetContentClient()->browser()->ShouldPreconnectNavigation(
browser_context)) {
auto* storage_partition =
frame_tree_node_->current_frame_host()->GetStoragePartition();
storage_partition->GetNetworkContext()->PreconnectSockets(
1, common_params_->url, true,
GetIsolationInfo().network_anonymization_key());
}
}
if (GetURL().is_valid() && OriginCanAccessServiceWorkers(GetURL()) &&
reload_type_ != ReloadType::BYPASSING_CACHE &&
base::FeatureList::IsEnabled(kSpeculativeServiceWorkerStartup)) {
if (ServiceWorkerContext* context =
frame_tree_node_->navigator()
.controller()
.GetBrowserContext()
->GetStoragePartition(site_info_.storage_partition_config())
->GetServiceWorkerContext()) {
const blink::StorageKey key = blink::StorageKey::CreateFirstParty(
GetTentativeOriginAtRequestTime());
if (context->MaybeHasRegistrationForStorageKey(key)) {
context->StartServiceWorkerForNavigationHint(GetURL(), key,
base::DoNothing());
}
}
}
if (IsBackForwardCacheEnabled() && !IsServedFromBackForwardCache() && entry &&
BackForwardCacheMetrics::IsCrossDocumentMainFrameHistoryNavigation(
this)) {
entry->UpdateBackForwardCacheNotRestoredReasons(this);
auto* metrics = entry->back_forward_cache_metrics();
DCHECK(metrics);
if (base::FeatureList::IsEnabled(
blink::features::kBackForwardCacheSendNotRestoredReasons)) {
commit_params_->not_restored_reasons =
metrics->GetWebExposedNotRestoredReasons();
}
}
if (common_params_->navigation_type ==
blink::mojom::NavigationType::SAME_DOCUMENT &&
GetInitiatorOrigin() &&
!GetInitiatorOrigin()->IsSameOriginWith(
GetTentativeOriginAtRequestTime())) {
GetContentClient()->browser()->LogWebFeatureForCurrentPage(
frame_tree_node_->current_frame_host(),
blink::mojom::WebFeature::kSameDocumentCrossOriginInitiator);
}
}
NavigationRequest::~NavigationRequest() {
#if DCHECK_IS_ON()
DCHECK(is_safe_to_delete_);
#endif
TRACE_EVENT_NESTABLE_ASYNC_END0("navigation", "", navigation_id_);
TRACE_EVENT_NESTABLE_ASYNC_END0("navigation", "NavigationRequest",
navigation_id_);
if (NavigationRequest* request = frame_tree_node_->navigation_request()) {
if (request->IsQueued() && request != this &&
!request->restarting_back_forward_cached_navigation_) {
if (!request->ShouldQueueDueToExistingPendingCommitRFH()) {
request->PostResumeCommitTask();
}
}
}
if (loading_mem_tracker_)
loading_mem_tracker_->Cancel();
ResetExpectedProcess();
if (!HasCommitted()) {
if (state_ >= WILL_START_NAVIGATION) {
devtools_instrumentation::OnNavigationRequestFailed(
*this, network::URLLoaderCompletionStatus(net::ERR_ABORTED));
}
if (pending_navigation_api_key_) {
frame_tree_node_->current_frame_host()
->GetAssociatedLocalFrame()
->TraverseCancelled(
*pending_navigation_api_key_,
blink::mojom::TraverseCancelledReason::kAbortedBeforeCommit);
}
for (auto& throttle : subframe_history_navigation_throttles_) {
if (throttle) {
throttle->Cancel();
}
}
subframe_history_navigation_throttles_.clear();
}
pending_entry_ref_.reset();
#if BUILDFLAG(IS_ANDROID)
if (navigation_visible_to_embedder_)
navigation_handle_proxy_->DidFinish();
#endif
if (is_deferred_on_fenced_frame_url_mapping_) {
CHECK(NeedFencedFrameURLMapping());
GetFencedFrameURLMap().RemoveObserverForURN(common_params_->url, this);
}
if (IsNavigationStarted()) {
GetDelegate()->DidFinishNavigation(this);
ProcessOriginAgentClusterEndResult();
if (IsInMainFrame()) {
TRACE_EVENT_NESTABLE_ASYNC_END2(
"navigation", "Navigation StartToCommit",
TRACE_ID_WITH_SCOPE("StartToCommit", TRACE_ID_LOCAL(this)), "URL",
common_params_->url.spec(), "Net Error Code", net_error_);
}
if (IsPrerenderedPageActivation()) {
GetPrerenderHostRegistry().OnActivationFinished(
prerender_frame_tree_node_id_.value());
}
if (IsServedFromBackForwardCache()) {
auto bfcache_entry =
GetNavigationController()->GetBackForwardCache().GetOrEvictEntry(
nav_entry_id());
if (bfcache_entry.has_value()) {
RenderFrameHostImpl* rfh = RenderFrameHostImpl::FromID(
bfcache_entry.value()->render_frame_host()->GetGlobalId());
if (rfh && rfh->IsInBackForwardCache()) {
rfh->EvictFromBackForwardCacheWithReason(
BackForwardCacheMetrics::NotRestoredReason::
kNavigationCancelledWhileRestoring);
}
}
}
}
}
void NavigationRequest::RegisterCommitDeferringConditionForTesting(
std::unique_ptr<CommitDeferringCondition> condition) {
commit_deferrer_->AddConditionForTesting(std::move(condition));
}
bool NavigationRequest::IsCommitDeferringConditionDeferredForTesting() {
if (!commit_deferrer_)
return false;
return commit_deferrer_->GetDeferringConditionForTesting();
}
CommitDeferringCondition*
NavigationRequest::GetCommitDeferringConditionForTesting() {
if (!commit_deferrer_)
return nullptr;
return commit_deferrer_->GetDeferringConditionForTesting();
}
void NavigationRequest::BeginNavigation() {
EnterChildTraceEvent("BeginNavigation", this);
DCHECK(!loader_);
DCHECK(!HasRenderFrameHost());
ScopedCrashKeys crash_keys(*this);
if (begin_navigation_callback_for_testing_) {
std::move(begin_navigation_callback_for_testing_).Run();
}
if (MaybeStartPrerenderingActivationChecks()) {
return;
}
MaybeAssignInvalidPrerenderFrameTreeNodeId();
bool is_fenced_frame = frame_tree_node_->IsFencedFrameRoot();
if (is_fenced_frame) {
DCHECK(!frame_tree_node_->csp_attribute());
if (GetParentFrameOrOuterDocument()->required_csp()) {
GURL sanitized_blocked_url =
common_params_->url.DeprecatedGetOriginAsURL();
AddDeferredConsoleMessage(
blink::mojom::ConsoleMessageLevel::kError,
base::StringPrintf(
"Refused to frame '%s' as a fenced frame because "
"CSP Embedded Enforcement is specified by the embedder",
sanitized_blocked_url.spec().c_str()));
StartNavigation();
OnRequestFailedInternal(
network::URLLoaderCompletionStatus(net::ERR_BLOCKED_BY_CSP),
false , absl::nullopt ,
false );
return;
}
}
if (NeedFencedFrameURLMapping()) {
if (!is_fenced_frame) {
DCHECK(!frame_tree_node_->IsMainFrame());
DCHECK(blink::features::IsAllowURNsInIframeEnabled());
AddDeferredConsoleMessage(
blink::mojom::ConsoleMessageLevel::kWarning,
"FLEDGE will deprecate supporting iframes to render the winning ad. "
"Please use fenced frames instead. See "
"https://developer.chrome.com/en/docs/privacy-sandbox/fenced-frame/"
"#examples");
}
UMA_HISTOGRAM_BOOLEAN(
"Navigation.BrowserMappedUrnUuidInIframeOrFencedFrame",
!is_fenced_frame);
FencedFrameURLMapping& fenced_frame_urls_map = GetFencedFrameURLMap();
is_deferred_on_fenced_frame_url_mapping_ = true;
fenced_frame_url_mapping_start_time_ = base::TimeTicks::Now();
fenced_frame_urls_map.ConvertFencedFrameURNToURL(common_params_->url,
this);
return;
}
BeginNavigationImpl();
}
bool NavigationRequest::MaybeStartPrerenderingActivationChecks() {
int candidate_prerender_frame_tree_node_id =
GetPrerenderHostRegistry().FindPotentialHostToActivate(*this);
if (candidate_prerender_frame_tree_node_id ==
RenderFrameHost::kNoFrameTreeNodeId) {
return false;
}
commit_deferrer_ = CommitDeferringConditionRunner::Create(
*this,
CommitDeferringCondition::NavigationType::kPrerenderedPageActivation,
candidate_prerender_frame_tree_node_id);
is_potentially_prerendered_page_activation_for_testing_ = true;
base::SequencedTaskRunner::GetCurrentDefault()->PostNonNestableTask(
FROM_HERE,
base::BindOnce(&NavigationRequest::RunCommitDeferringConditions,
weak_factory_.GetWeakPtr()));
return true;
}
void NavigationRequest::OnPrerenderingActivationChecksComplete(
CommitDeferringCondition::NavigationType navigation_type,
absl::optional<int> candidate_prerender_frame_tree_node_id) {
DCHECK_LT(state_, WILL_START_NAVIGATION);
DCHECK(candidate_prerender_frame_tree_node_id.has_value());
DCHECK(!prerender_frame_tree_node_id_.has_value());
prerender_frame_tree_node_id_ =
GetPrerenderHostRegistry().ReserveHostToActivate(
*this, candidate_prerender_frame_tree_node_id.value());
if (prerender_frame_tree_node_id_.value() !=
RenderFrameHost::kNoFrameTreeNodeId) {
DCHECK_EQ(prerender_frame_tree_node_id_.value(),
candidate_prerender_frame_tree_node_id.value());
}
is_potentially_prerendered_page_activation_for_testing_ = false;
commit_deferrer_.reset();
CHECK(!NeedFencedFrameURLMapping());
BeginNavigationImpl();
}
FencedFrameURLMapping& NavigationRequest::GetFencedFrameURLMap() {
bool is_fenced_frame_root =
frame_tree_node_->current_frame_host()->IsFencedFrameRoot();
FrameTreeNode* node_to_use = frame_tree_node_->frame_tree()
.root()
->render_manager()
->GetOuterDelegateNode();
if (!is_fenced_frame_root) {
node_to_use = frame_tree_node_;
}
DCHECK(node_to_use);
return node_to_use->current_frame_host()->GetPage().fenced_frame_urls_map();
}
bool NavigationRequest::NeedFencedFrameURLMapping() {
if (frame_tree_node_->IsFencedFrameRoot()) {
return is_embedder_initiated_fenced_frame_opaque_url_navigation_;
} else if (!frame_tree_node_->IsMainFrame() &&
blink::features::IsAllowURNsInIframeEnabled()) {
is_embedder_initiated_fenced_frame_navigation_ =
blink::IsValidUrnUuidURL(common_params_->url);
return is_embedder_initiated_fenced_frame_navigation_;
}
return false;
}
void NavigationRequest::OnFencedFrameURLMappingComplete(
const absl::optional<FencedFrameProperties>& properties) {
is_deferred_on_fenced_frame_url_mapping_ = false;
if (!properties.has_value()) {
if (!frame_tree_node_->IsFencedFrameRoot()) {
BeginNavigationImpl();
return;
}
StartNavigation();
OnRequestFailedInternal(
network::URLLoaderCompletionStatus(net::ERR_INVALID_URL),
false , absl::nullopt ,
false );
return;
}
if (properties->on_navigate_callback_) {
properties->on_navigate_callback_.Run();
}
CHECK(properties->mapped_url_.has_value());
const GURL& mapped_url_value =
properties->mapped_url_->GetValueIgnoringVisibility();
common_params_->url = mapped_url_value;
commit_params_->original_url = mapped_url_value;
fenced_frame_properties_ = properties;
DCHECK(fenced_frame_properties_);
fenced_frame_properties_->embedder_shared_storage_context_ =
embedder_shared_storage_context_;
embedder_shared_storage_context_ = absl::nullopt;
if (!frame_tree_node_->IsFencedFrameRoot()) {
CHECK(blink::features::IsAllowURNsInIframeEnabled());
fenced_frame_properties_->partition_nonce_ = absl::nullopt;
}
if (fenced_frame_properties_->shared_storage_budget_metadata_) {
base::TimeDelta time_spent_in_fenced_frame_url_mapping =
base::TimeTicks::Now() - fenced_frame_url_mapping_start_time_;
base::UmaHistogramTimes(
"Storage.SharedStorage.Timing.UrlMappingDuringNavigation",
time_spent_in_fenced_frame_url_mapping);
}
BeginNavigationImpl();
}
void NavigationRequest::BeginNavigationImpl() {
base::ElapsedTimer timer;
SetState(WILL_START_NAVIGATION);
#ifdef OHOS_LOG_MESSAGE
if (frame_tree_node_->IsMainFrame()) {
LOG(INFO) << "event_message: start a navigation url domain: "
<< (common_params_ ? GetDomainAndRegistry(common_params_->url,
net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES) : "")
<< " is_browser_initiated_: " << commit_params_->is_browser_initiated
<< " was_redirected_: " << was_redirected_ << " " << devtools_navigation_token_;
}
#endif
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_OHOS)
base::WeakPtr<NavigationRequest> this_ptr(weak_factory_.GetWeakPtr());
bool should_override_url_loading = false;
if (!GetContentClient()->browser()->ShouldOverrideUrlLoading(
frame_tree_node_->frame_tree_node_id(),
commit_params_->is_browser_initiated, commit_params_->original_url,
commit_params_->original_method, common_params_->has_user_gesture,
false, frame_tree_node_->IsOutermostMainFrame(),
ui::PageTransitionFromInt(common_params_->transition),
&should_override_url_loading)) {
return;
}
if (!this_ptr)
return;
if (should_override_url_loading) {
OnRequestFailedInternal(
network::URLLoaderCompletionStatus(net::ERR_ABORTED),
false , absl::nullopt ,
false );
return;
}
#endif
net::Error net_error = CheckContentSecurityPolicy(
false ,
false , false );
if (net_error != net::OK) {
StartNavigation();
OnRequestFailedInternal(network::URLLoaderCompletionStatus(net_error),
false ,
absl::nullopt ,
false );
return;
}
if (CheckCredentialedSubresource() ==
CredentialedSubresourceCheckResult::BLOCK_REQUEST) {
StartNavigation();
OnRequestFailedInternal(
network::URLLoaderCompletionStatus(net::ERR_ABORTED),
false , absl::nullopt ,
false );
return;
}
StartNavigation();
if (CheckAboutSrcDoc() == AboutSrcDocCheckResult::BLOCK_REQUEST) {
OnRequestFailedInternal(
network::URLLoaderCompletionStatus(net::ERR_INVALID_URL),
true , absl::nullopt ,
false );
return;
}
if (!post_commit_error_page_html_.empty()) {
OnRequestFailedInternal(
network::URLLoaderCompletionStatus(net_error_),
true ,
post_commit_error_page_html_ ,
false );
return;
}
if (IsForMhtmlSubframe())
is_mhtml_or_subframe_ = true;
SetupCSPEmbeddedEnforcement();
if (!NeedsUrlLoader()) {
DCHECK(!IsServedFromBackForwardCache());
DCHECK(!IsPrerenderedPageActivation());
EnterChildTraceEvent("ResponseStarted", this);
if (CheckCSPEmbeddedEnforcement() ==
CSPEmbeddedEnforcementResult::BLOCK_RESPONSE) {
NOTREACHED();
base::debug::DumpWithoutCrashing();
}
ComputePoliciesToCommit();
if (IsSameDocument()) {
render_frame_host_ = frame_tree_node_->current_frame_host()->GetSafeRef();
} else {
if (!CheckResponseAdherenceToCoep(common_params_->url)) {
OnRequestFailedInternal(network::URLLoaderCompletionStatus(
network::mojom::BlockedByResponseReason::
kCoepFrameResourceNeedsCoepHeader),
false ,
absl::nullopt ,
false );
return;
}
const url::Origin origin = GetOriginForURLLoaderFactoryUnchecked(this);
const net::SchemefulSite site = net::SchemefulSite(origin);
coop_status_.EnforceCOOP(
policy_container_builder_->FinalPolicies().cross_origin_opener_policy,
origin, net::NetworkAnonymizationKey::CreateSameSite(site));
if (auto result =
frame_tree_node_->render_manager()->GetFrameHostForNavigation(
this, &browsing_context_group_swap_);
result.has_value()) {
render_frame_host_ = result.value()->GetSafeRef();
} else {
switch (result.error()) {
case GetFrameHostForNavigationFailed::kCouldNotReinitializeMainFrame:
break;
case GetFrameHostForNavigationFailed::kBlockedByPendingCommit:
break;
}
}
CHECK(Navigator::CheckWebUIRendererDoesNotDisplayNormalURL(
&*render_frame_host_.value(), GetUrlInfo(),
false));
}
if (HasRenderFrameHost()) {
auto* site_instance = render_frame_host_.value()->GetSiteInstance();
if (!site_instance->HasSite() &&
SiteInstanceImpl::ShouldAssignSiteForUrlInfo(GetUrlInfo())) {
site_instance->ConvertToDefaultOrSetSite(GetUrlInfo());
}
}
WillCommitWithoutUrlLoader();
return;
}
base::UmaHistogramTimes(
base::StrCat({"Navigation.BeginNavigationImpl.",
IsInMainFrame() ? "MainFrame" : "Subframe"}),
timer.Elapsed());
WillStartRequest();
}
void NavigationRequest::SetWaitingForRendererResponse() {
EnterChildTraceEvent("WaitingForRendererResponse", this);
SetState(WAITING_FOR_RENDERER_RESPONSE);
}
bool NavigationRequest::ShouldAddCookieChangeListener() {
return BackForwardCacheImpl::AllowStoringPagesWithCacheControlNoStore() &&
!IsPageActivation() && !IsSameDocument() && IsInPrimaryMainFrame() &&
common_params_->url.SchemeIsHTTPOrHTTPS();
}
void NavigationRequest::StartNavigation() {
DCHECK(frame_tree_node_->navigation_request() == this ||
is_synchronous_renderer_commit_);
FrameTreeNode* frame_tree_node = frame_tree_node_;
MaybeAssignInvalidPrerenderFrameTreeNodeId();
starting_site_instance_ =
frame_tree_node->current_frame_host()->GetSiteInstance();
site_info_ = GetSiteInfoForCommonParamsURL();
if (ShouldAddCookieChangeListener()) {
cookie_change_listener_ =
std::make_unique<RenderFrameHostImpl::CookieChangeListener>(
GetStoragePartitionWithCurrentSiteInfo(), common_params_->url);
}
redirect_chain_.clear();
if (!begin_params_->client_side_redirect_url.is_empty()) {
redirect_chain_.push_back(begin_params_->client_side_redirect_url);
} else if (!commit_params_->redirects.empty()) {
for (const auto& url : commit_params_->redirects)
redirect_chain_.push_back(url);
}
if (!is_synchronous_renderer_commit_) {
if (!common_params_->base_url_for_data_url.is_empty()) {
redirect_chain_.push_back(common_params_->base_url_for_data_url);
} else {
redirect_chain_.push_back(common_params_->url);
}
}
if (common_params_->transition & ui::PAGE_TRANSITION_CLIENT_REDIRECT) {
sanitized_referrer_ = blink::mojom::Referrer::New(
redirect_chain_[0], Referrer::SanitizeForRequest(
common_params_->url, *common_params_->referrer)
->policy);
} else {
sanitized_referrer_ = Referrer::SanitizeForRequest(
common_params_->url, *common_params_->referrer);
}
if (commit_params_->should_clear_history_list) {
common_params_->should_replace_current_entry = false;
} else if (
ShouldReplaceCurrentEntryForSameUrlNavigation() ||
ShouldReplaceCurrentEntryForNavigationFromInitialEmptyDocumentOrEntry()) {
common_params_->should_replace_current_entry = true;
}
if (associated_rfh_type_ != AssociatedRenderFrameHostType::NONE) {
RenderFrameHostImpl* navigating_frame_host =
associated_rfh_type_ == AssociatedRenderFrameHostType::SPECULATIVE
? frame_tree_node_->render_manager()->speculative_frame_host()
: frame_tree_node_->current_frame_host();
SetExpectedProcess(navigating_frame_host->GetProcess());
}
DCHECK(!IsNavigationStarted());
SetState(WILL_START_REQUEST);
is_navigation_started_ = true;
modified_request_headers_.Clear();
removed_request_headers_.clear();
throttle_runner_ = std::make_unique<NavigationThrottleRunner>(
this, navigation_id_, IsInPrimaryMainFrame());
if (!IsPrerenderedPageActivation()) {
commit_deferrer_ = CommitDeferringConditionRunner::Create(
*this, CommitDeferringCondition::NavigationType::kOther,
absl::nullopt);
}
navigation_visible_to_embedder_ = true;
#if BUILDFLAG(IS_ANDROID)
navigation_handle_proxy_->DidStart();
#endif
if (IsInMainFrame()) {
DCHECK(!common_params_->navigation_start.is_null());
DCHECK(!blink::IsRendererDebugURL(common_params_->url));
TRACE_EVENT_NESTABLE_ASYNC_BEGIN_WITH_TIMESTAMP1(
"navigation", "Navigation StartToCommit",
TRACE_ID_WITH_SCOPE("StartToCommit", TRACE_ID_LOCAL(this)),
common_params_->navigation_start, "Initial URL",
common_params_->url.spec());
}
if (IsSameDocument()) {
EnterChildTraceEvent("Same document", this);
}
{
#if DCHECK_IS_ON()
DCHECK(is_safe_to_delete_);
base::AutoReset<bool> resetter(&is_safe_to_delete_, false);
#endif
base::AutoReset<bool> resetter2(&ua_change_requires_reload_, false);
GetDelegate()->DidStartNavigation(this);
}
if (rfh_restored_from_back_forward_cache_ &&
rfh_restored_from_back_forward_cache_->is_overriding_user_agent() !=
commit_params_->is_overriding_user_agent) {
rfh_restored_from_back_forward_cache_->EvictFromBackForwardCacheWithReason(
BackForwardCacheMetrics::NotRestoredReason::kUserAgentOverrideDiffers);
}
}
void NavigationRequest::ResetForCrossDocumentRestart() {
DCHECK(IsSameDocument());
if (common_params_->navigation_type ==
blink::mojom::NavigationType::HISTORY_SAME_DOCUMENT) {
CaptureTraceForNavigationDebugScenario(
DebugScenario::kDebugSameDocNavigationDocIdMismatch);
}
DCHECK(!loader_);
#if BUILDFLAG(IS_ANDROID)
if (navigation_visible_to_embedder_)
navigation_handle_proxy_->DidFinish();
#endif
if (IsNavigationStarted()) {
GetDelegate()->DidFinishNavigation(this);
if (IsInMainFrame()) {
TRACE_EVENT_NESTABLE_ASYNC_END2(
"navigation", "Navigation StartToCommit",
TRACE_ID_WITH_SCOPE("StartToCommit", TRACE_ID_LOCAL(this)), "URL",
common_params_->url.spec(), "Net Error Code", net_error_);
}
}
StopCommitTimeout();
SetState(NOT_STARTED);
is_navigation_started_ = false;
processing_navigation_throttle_ = false;
navigation_visible_to_embedder_ = false;
#if BUILDFLAG(IS_ANDROID)
if (navigation_visible_to_embedder_) {
navigation_handle_proxy_.reset();
navigation_handle_proxy_ = std::make_unique<NavigationHandleProxy>(this);
}
#endif
DCHECK(HasRenderFrameHost());
render_frame_host_ = absl::nullopt;
common_params_->navigation_type =
ConvertToCrossDocumentType(common_params_->navigation_type);
navigation_handle_timing_ = NavigationHandleTiming();
policy_container_builder_->ResetForCrossDocumentRestart();
commit_params_->soft_navigation_heuristics_task_id = absl::nullopt;
CheckSoftNavigationHeuristicsInvariants();
}
void NavigationRequest::ResetStateForSiteInstanceChange() {
DCHECK(dest_site_instance_);
bindings_ = FrameNavigationEntry::kInvalidBindings;
blink::PageState page_state =
blink::PageState::CreateFromEncodedData(commit_params_->page_state);
if (page_state.IsValid())
commit_params_->page_state =
blink::PageState::CreateFromURL(GetURL()).ToEncodedData();
frame_entry_item_sequence_number_ = -1;
frame_entry_document_sequence_number_ = -1;
}
void NavigationRequest::RegisterSubresourceOverride(
blink::mojom::TransferrableURLLoaderPtr transferrable_loader) {
if (!transferrable_loader)
return;
if (!subresource_overrides_)
subresource_overrides_.emplace();
subresource_overrides_->push_back(std::move(transferrable_loader));
}
mojom::NavigationClient* NavigationRequest::GetCommitNavigationClient() {
if (commit_navigation_client_ && commit_navigation_client_.is_bound())
return commit_navigation_client_.get();
commit_navigation_client_ =
GetRenderFrameHost()->GetNavigationClientFromInterfaceProvider();
HandleInterfaceDisconnection(commit_navigation_client_);
return commit_navigation_client_.get();
}
void NavigationRequest::SetRequiredCSP(
network::mojom::ContentSecurityPolicyPtr csp) {
DCHECK(!required_csp_);
required_csp_ = std::move(csp);
if (required_csp_)
SetRequestHeader("Sec-Required-CSP", required_csp_->header->header_value);
}
network::mojom::ContentSecurityPolicyPtr NavigationRequest::TakeRequiredCSP() {
return std::move(required_csp_);
}
const PolicyContainerPolicies*
NavigationRequest::GetInitiatorPolicyContainerPolicies() const {
return policy_container_builder_->InitiatorPolicies();
}
const blink::DocumentToken& NavigationRequest::GetDocumentToken() const {
DCHECK(!IsSameDocument());
DCHECK_GE(state_, READY_TO_COMMIT);
return *document_token_;
}
const PolicyContainerPolicies& NavigationRequest::GetPolicyContainerPolicies()
const {
DCHECK_GE(state_, READY_TO_COMMIT);
return policy_container_builder_->FinalPolicies();
}
blink::mojom::PolicyContainerPtr
NavigationRequest::CreatePolicyContainerForBlink() {
DCHECK_GE(state_, READY_TO_COMMIT);
return policy_container_builder_->CreatePolicyContainerForBlink();
}
scoped_refptr<PolicyContainerHost> NavigationRequest::GetPolicyContainerHost() {
DCHECK_GE(state_, READY_TO_COMMIT);
CHECK(policy_container_builder_);
return policy_container_builder_->GetPolicyContainerHost();
}
scoped_refptr<PolicyContainerHost>
NavigationRequest::TakePolicyContainerHost() {
DCHECK_GE(state_, READY_TO_COMMIT);
scoped_refptr<PolicyContainerHost> host =
std::move(*policy_container_builder_).TakePolicyContainerHost();
policy_container_builder_ = absl::nullopt;
return host;
}
void NavigationRequest::CreateCoepReporter(
StoragePartition* storage_partition) {
DCHECK(!isolation_info_for_subresources_.IsEmpty());
const PolicyContainerPolicies& policies =
policy_container_builder_->FinalPolicies();
coep_reporter_ = std::make_unique<CrossOriginEmbedderPolicyReporter>(
static_cast<StoragePartitionImpl*>(storage_partition)->GetWeakPtr(),
common_params_->url,
policies.cross_origin_embedder_policy.reporting_endpoint,
policies.cross_origin_embedder_policy.report_only_reporting_endpoint,
GetRenderFrameHost()->GetFrameToken().value(),
isolation_info_for_subresources_.network_anonymization_key());
}
std::unique_ptr<CrossOriginEmbedderPolicyReporter>
NavigationRequest::TakeCoepReporter() {
return std::move(coep_reporter_);
}
ukm::SourceId NavigationRequest::GetPreviousPageUkmSourceId() {
return previous_page_ukm_source_id_;
}
void NavigationRequest::OnRequestRedirected(
const net::RedirectInfo& redirect_info,
const net::NetworkAnonymizationKey& network_anonymization_key,
network::mojom::URLResponseHeadPtr response_head) {
ScopedCrashKeys crash_keys(*this);
DCHECK(!auth_challenge_info_);
DCHECK(response_head);
DCHECK(response_head->parsed_headers);
response_head_ = std::move(response_head);
ssl_info_ = response_head_->ssl_info;
commit_params_->page_state = std::string();
commit_params_->not_restored_reasons = nullptr;
RecordAddressSpaceFeature();
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_OHOS)
base::WeakPtr<NavigationRequest> this_ptr(weak_factory_.GetWeakPtr());
bool should_override_url_loading = false;
if (!GetContentClient()->browser()->ShouldOverrideUrlLoading(
frame_tree_node_->frame_tree_node_id(),
commit_params_->is_browser_initiated, redirect_info.new_url,
redirect_info.new_method,
false, true, frame_tree_node_->IsOutermostMainFrame(),
ui::PageTransitionFromInt(common_params_->transition),
&should_override_url_loading)) {
return;
}
if (!this_ptr)
return;
if (should_override_url_loading) {
net_error_ = net::ERR_ABORTED;
common_params_->url = redirect_info.new_url;
common_params_->method = redirect_info.new_method;
UpdateStateFollowingRedirect(GURL(redirect_info.new_referrer));
frame_tree_node_->ResetNavigationRequest(
NavigationDiscardReason::kCancelled);
return;
}
#endif
if (!ChildProcessSecurityPolicyImpl::GetInstance()->CanRedirectToURL(
redirect_info.new_url)) {
DVLOG(1) << "Denied redirect for "
<< redirect_info.new_url.possibly_invalid_spec();
OnRequestFailedInternal(
network::URLLoaderCompletionStatus(net::ERR_ABORTED),
false , absl::nullopt ,
false );
return;
}
if (!commit_params_->is_browser_initiated && GetSourceSiteInstance() &&
!ChildProcessSecurityPolicyImpl::GetInstance()->CanRequestURL(
GetSourceSiteInstance()->GetProcess()->GetID(),
redirect_info.new_url)) {
DVLOG(1) << "Denied unauthorized redirect for "
<< redirect_info.new_url.possibly_invalid_spec();
OnRequestFailedInternal(
network::URLLoaderCompletionStatus(net::ERR_ABORTED),
false , absl::nullopt ,
false );
return;
}
const absl::optional<network::mojom::BlockedByResponseReason>
coop_requires_blocking =
coop_status_.SanitizeResponse(response_head_.get());
if (coop_requires_blocking) {
OnRequestFailedInternal(
network::URLLoaderCompletionStatus(*coop_requires_blocking),
false , absl::nullopt ,
false );
return;
}
const url::Origin origin = GetOriginForURLLoaderFactoryUnchecked(this);
coop_status_.EnforceCOOP(
response()->parsed_headers->cross_origin_opener_policy, origin,
network_anonymization_key);
const absl::optional<network::mojom::BlockedByResponseReason>
coep_requires_blocking = EnforceCOEP();
if (coep_requires_blocking) {
OnRequestFailedInternal(
network::URLLoaderCompletionStatus(*coep_requires_blocking),
false , absl::nullopt ,
false );
return;
}
if (redirect_info.new_method != "POST")
common_params_->post_data.reset();
const bool is_first_response = commit_params_->redirects.empty();
UpdateNavigationHandleTimingsOnResponseReceived(is_first_response);
if (commit_params_->navigation_timing->redirect_start.is_null()) {
commit_params_->navigation_timing->redirect_start =
commit_params_->navigation_timing->fetch_start;
}
#if BUILDFLAG(IS_OHOS)
TRACE_EVENT1("navigation", "PAGE_LOAD_TIME",
"redirectStart", commit_params_->navigation_timing->redirect_start);
#endif
commit_params_->navigation_timing->redirect_end = base::TimeTicks::Now();
commit_params_->navigation_timing->fetch_start = base::TimeTicks::Now();
#if BUILDFLAG(IS_OHOS)
TRACE_EVENT1("navigation", "PAGE_LOAD_TIME",
"redirectEnd", commit_params_->navigation_timing->redirect_end);
TRACE_EVENT1("navigation", "PAGE_LOAD_TIME",
"fetchStart", commit_params_->navigation_timing->fetch_start);
#endif
commit_params_->redirect_response.push_back(response_head_.Clone());
commit_params_->redirect_infos.push_back(redirect_info);
const bool is_same_origin_redirect =
url::Origin::Create(common_params_->url)
.IsSameOriginWith(redirect_info.new_url);
if (!is_same_origin_redirect &&
commit_params_->navigation_timing->parent_resource_timing_access ==
blink::mojom::ParentResourceTimingAccess::
kReportWithResponseDetails) {
commit_params_->navigation_timing->parent_resource_timing_access =
blink::mojom::ParentResourceTimingAccess::kReportWithoutResponseDetails;
}
did_receive_early_hints_before_cross_origin_redirect_ |=
did_create_early_hints_manager_params_ && !is_same_origin_redirect;
commit_params_->load_with_storage_access =
commit_params_->load_with_storage_access && is_same_origin_redirect;
commit_params_->redirects.push_back(common_params_->url);
common_params_->url = redirect_info.new_url;
common_params_->method = redirect_info.new_method;
common_params_->referrer->url = GURL(redirect_info.new_referrer);
common_params_->referrer = Referrer::SanitizeForRequest(
common_params_->url, *common_params_->referrer);
commit_params_->redirect_infos.back().new_referrer =
common_params_->referrer->url.spec();
if (ShouldAddCookieChangeListener()) {
cookie_change_listener_ =
std::make_unique<RenderFrameHostImpl::CookieChangeListener>(
GetStoragePartitionWithCurrentSiteInfo(), common_params_->url);
} else {
cookie_change_listener_.reset();
}
net::Error net_error =
CheckContentSecurityPolicy(true ,
redirect_info.insecure_scheme_was_upgraded,
false );
if (net_error != net::OK) {
OnRequestFailedInternal(
network::URLLoaderCompletionStatus(net_error), false ,
absl::nullopt , false );
return;
}
if (CheckCredentialedSubresource() ==
CredentialedSubresourceCheckResult::BLOCK_REQUEST) {
OnRequestFailedInternal(
network::URLLoaderCompletionStatus(net::ERR_ABORTED),
false , absl::nullopt ,
false );
return;
}
scoped_refptr<SiteInstance> site_instance =
frame_tree_node_->render_manager()->GetSiteInstanceForNavigationRequest(
this, &browsing_context_group_swap_);
speculative_site_instance_ =
site_instance->HasProcess() ? site_instance : nullptr;
if (!site_instance->HasProcess()) {
RenderProcessHostImpl::NotifySpareManagerAboutRecentlyUsedBrowserContext(
site_instance->GetBrowserContext());
}
RenderProcessHost* expected_process =
site_instance->HasProcess() ? site_instance->GetProcess() : nullptr;
#ifdef OHOS_ARKWEB_ADBLOCK
if (frame_tree_node_->IsMainFrame() &&
common_params_->url.SchemeIsHTTPOrHTTPS()) {
LOG(INFO) << "[AdBlock] Redirect to ***"
<< ", try to get adblock switch from UI.";
GetContentClient()->browser()->UpdateAdBlockEnabledForSite(
frame_tree_node_->current_frame_host(), common_params_->url);
}
#endif
WillRedirectRequest(common_params_->referrer->url, expected_process);
}
base::WeakPtr<NavigationRequest> NavigationRequest::GetWeakPtr() {
return weak_factory_.GetWeakPtr();
}
base::SafeRef<NavigationHandle> NavigationRequest::GetSafeRef() {
return weak_factory_.GetSafeRef();
}
bool NavigationRequest::ExistingDocumentWasDiscarded() const {
return commit_params_->was_discarded;
}
void NavigationRequest::CheckForIsolationOptIn(const GURL& url) {
if (!IsOriginAgentClusterOptInRequested() &&
!IsOriginAgentClusterOptOutRequested())
return;
auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
url::Origin origin = url::Origin::Create(url);
auto* browser_context =
frame_tree_node_->navigator().controller().GetBrowserContext();
if (policy->UpdateOriginIsolationOptInListIfNecessary(browser_context,
origin)) {
frame_tree_node_->navigator()
.GetDelegate()
->RegisterExistingOriginAsHavingDefaultIsolation(
origin, this );
}
}
void NavigationRequest::AddSameProcessOriginAgentClusterStateIfNecessary(
const IsolationContext& isolation_context,
const GURL& url) {
bool is_opt_in_requested =
IsOriginAgentClusterOptInRequested() &&
!SiteIsolationPolicy::IsProcessIsolationForOriginAgentClusterEnabled();
bool is_opt_out_requested = IsOriginAgentClusterOptOutRequested();
if (!is_opt_in_requested && !is_opt_out_requested)
return;
bool should_isolate_origin = is_opt_in_requested;
url::Origin origin = url::Origin::Create(url);
auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
policy->AddOriginIsolationStateForBrowsingInstance(
isolation_context, origin,
should_isolate_origin ,
false );
}
bool NavigationRequest::IsOriginAgentClusterOptInRequested() {
if (state_ < WILL_PROCESS_RESPONSE)
return false;
if (!response())
return false;
if (!SiteIsolationPolicy::IsOriginAgentClusterEnabled())
return false;
return response_head_->parsed_headers->origin_agent_cluster ==
network::mojom::OriginAgentClusterValue::kTrue;
}
bool NavigationRequest::IsOriginAgentClusterOptOutRequested() {
if (state_ < WILL_PROCESS_RESPONSE)
return false;
if (!response())
return false;
if (!SiteIsolationPolicy::AreOriginAgentClustersEnabledByDefault(
frame_tree_node_->navigator().controller().GetBrowserContext())) {
return false;
}
return response_head_->parsed_headers->origin_agent_cluster ==
network::mojom::OriginAgentClusterValue::kFalse;
}
bool NavigationRequest::IsIsolationImplied() {
if (!SiteIsolationPolicy::AreOriginAgentClustersEnabledByDefault(
frame_tree_node_->navigator().controller().GetBrowserContext())) {
return false;
}
return !response() || response_head_->parsed_headers->origin_agent_cluster ==
network::mojom::OriginAgentClusterValue::kAbsent;
}
void NavigationRequest::DetermineOriginAgentClusterEndResult() {
DCHECK(state_ == WILL_PROCESS_RESPONSE ||
state_ == WILL_COMMIT_WITHOUT_URL_LOADER ||
state_ == WILL_FAIL_REQUEST || state_ == CANCELING);
auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
url::Origin origin = GetOriginToCommit().value();
const IsolationContext& isolation_context =
GetRenderFrameHost()->GetSiteInstance()->GetIsolationContext();
bool is_requested = IsOriginAgentClusterOptInRequested();
bool expects_origin_agent_cluster = is_requested || IsIsolationImplied();
bool requires_origin_keyed_process =
is_requested &&
SiteIsolationPolicy::IsProcessIsolationForOriginAgentClusterEnabled();
OriginAgentClusterIsolationState requested_isolation_state =
expects_origin_agent_cluster
? OriginAgentClusterIsolationState::CreateForOriginAgentCluster(
requires_origin_keyed_process)
: OriginAgentClusterIsolationState::CreateNonIsolated();
const bool got_origin_agent_cluster =
policy
->DetermineOriginAgentClusterIsolation(isolation_context, origin,
requested_isolation_state)
.is_origin_agent_cluster();
if (SiteIsolationPolicy::AreOriginAgentClustersEnabledByDefault(
frame_tree_node_->navigator().controller().GetBrowserContext())) {
bool was_explicitly_requested =
response_head_ &&
response_head_->parsed_headers->origin_agent_cluster ==
network::mojom::OriginAgentClusterValue::kTrue;
bool was_explicitly_not_requested =
response_head_ &&
response_head_->parsed_headers->origin_agent_cluster ==
network::mojom::OriginAgentClusterValue::kFalse;
if (got_origin_agent_cluster) {
if (was_explicitly_requested) {
origin_agent_cluster_end_result_ =
OriginAgentClusterEndResult::kExplicitlyRequestedAndOriginKeyed;
} else if (was_explicitly_not_requested) {
origin_agent_cluster_end_result_ =
OriginAgentClusterEndResult::kExplicitlyNotRequestedButOriginKeyed;
} else {
origin_agent_cluster_end_result_ =
OriginAgentClusterEndResult::kNotExplicitlyRequestedAndOriginKeyed;
}
} else {
if (was_explicitly_requested) {
origin_agent_cluster_end_result_ =
OriginAgentClusterEndResult::kExplicitlyRequestedButNotOriginKeyed;
} else if (was_explicitly_not_requested) {
origin_agent_cluster_end_result_ = OriginAgentClusterEndResult::
kExplicitlyNotRequestedAndNotOriginKeyed;
} else {
origin_agent_cluster_end_result_ = OriginAgentClusterEndResult::
kNotExplicitlyRequestedButNotOriginKeyed;
}
}
} else {
if (is_requested) {
origin_agent_cluster_end_result_ =
got_origin_agent_cluster
? OriginAgentClusterEndResult::kRequestedAndOriginKeyed
: OriginAgentClusterEndResult::kRequestedButNotOriginKeyed;
} else {
origin_agent_cluster_end_result_ =
got_origin_agent_cluster
? OriginAgentClusterEndResult::kNotRequestedButOriginKeyed
: OriginAgentClusterEndResult::kNotRequestedAndNotOriginKeyed;
}
}
const bool is_opaque_origin_because_sandbox =
(policy_container_builder_->FinalPolicies().sandbox_flags &
network::mojom::WebSandboxFlags::kOrigin) ==
network::mojom::WebSandboxFlags::kOrigin;
commit_params_->origin_agent_cluster = is_opaque_origin_because_sandbox ||
origin.opaque() ||
got_origin_agent_cluster;
commit_params_->origin_agent_cluster_left_as_default =
!response_head_ || response_head_->parsed_headers->origin_agent_cluster ==
network::mojom::OriginAgentClusterValue::kAbsent;
}
void NavigationRequest::ProcessOriginAgentClusterEndResult() {
if (!HasCommitted() || IsErrorPage() || IsSameDocument())
return;
if (origin_agent_cluster_end_result_ ==
OriginAgentClusterEndResult::kRequestedAndOriginKeyed ||
origin_agent_cluster_end_result_ ==
OriginAgentClusterEndResult::kRequestedButNotOriginKeyed ||
origin_agent_cluster_end_result_ ==
OriginAgentClusterEndResult::kExplicitlyRequestedAndOriginKeyed ||
origin_agent_cluster_end_result_ ==
OriginAgentClusterEndResult::kExplicitlyRequestedButNotOriginKeyed) {
GetContentClient()->browser()->LogWebFeatureForCurrentPage(
GetRenderFrameHost(),
blink::mojom::WebFeature::kOriginAgentClusterHeader);
}
const url::Origin origin = url::Origin::Create(GetURL());
if (origin_agent_cluster_end_result_ ==
OriginAgentClusterEndResult::kRequestedButNotOriginKeyed ||
origin_agent_cluster_end_result_ ==
OriginAgentClusterEndResult::kExplicitlyRequestedButNotOriginKeyed) {
GetRenderFrameHost()->AddMessageToConsole(
blink::mojom::ConsoleMessageLevel::kWarning,
base::StringPrintf(
"The page requested an origin-keyed agent cluster using the "
"Origin-Agent-Cluster header, but could not be origin-keyed since "
"the origin '%s' had previously been placed in a site-keyed agent "
"cluster. Update your headers to uniformly request origin-keying "
"for all pages on the origin.",
origin.Serialize().c_str()));
}
if (origin_agent_cluster_end_result_ ==
OriginAgentClusterEndResult::kNotRequestedButOriginKeyed ||
origin_agent_cluster_end_result_ ==
OriginAgentClusterEndResult::kExplicitlyNotRequestedButOriginKeyed) {
GetRenderFrameHost()->AddMessageToConsole(
blink::mojom::ConsoleMessageLevel::kWarning,
base::StringPrintf(
"The page did not request an origin-keyed agent cluster, but was "
"put in one anyway because the origin '%s' had previously been "
"placed in an origin-keyed agent cluster. Update your headers to "
"uniformly request origin-keying for all pages on the origin.",
origin.Serialize().c_str()));
}
}
void NavigationRequest::PopulateDocumentTokenForCrossDocumentNavigation() {
DCHECK(!IsSameDocument());
DCHECK_GE(state_, READY_TO_COMMIT);
const auto* token_to_reuse =
GetRenderFrameHost()->GetDocumentTokenForCrossDocumentNavigationReuse(
{});
document_token_.emplace(token_to_reuse ? *token_to_reuse
: blink::DocumentToken());
}
bool NavigationRequest::HasCommittingOrigin(const url::Origin& origin) {
if (state() < WILL_PROCESS_RESPONSE)
return false;
return origin == url::Origin::Create(GetURL());
}
bool NavigationRequest::ShouldRequestSiteIsolationForCOOP() {
if (!SiteIsolationPolicy::IsSiteIsolationForCOOPEnabled())
return false;
if (state_ < WILL_PROCESS_RESPONSE)
return false;
if (!IsInMainFrame())
return false;
url::Origin origin(url::Origin::Create(site_info_.process_lock_url()));
if (!IsolatedOriginUtil::IsValidIsolatedOrigin(origin))
return false;
bool should_header_value_trigger_isolation = false;
switch (coop_status_.current_coop().value) {
case network::mojom::CrossOriginOpenerPolicyValue::kSameOrigin:
case network::mojom::CrossOriginOpenerPolicyValue::kSameOriginPlusCoep:
case network::mojom::CrossOriginOpenerPolicyValue::kSameOriginAllowPopups:
case network::mojom::CrossOriginOpenerPolicyValue::kRestrictProperties:
case network::mojom::CrossOriginOpenerPolicyValue::
kRestrictPropertiesPlusCoep:
should_header_value_trigger_isolation = true;
break;
case network::mojom::CrossOriginOpenerPolicyValue::kUnsafeNone:
should_header_value_trigger_isolation = false;
break;
}
if (!should_header_value_trigger_isolation)
return false;
DCHECK(!site_info_.does_site_request_dedicated_process_for_coop());
if (site_info_.RequiresDedicatedProcess(
GetStartingSiteInstance()->GetIsolationContext())) {
bool is_already_isolated_due_to_coop =
ChildProcessSecurityPolicyImpl::GetInstance()->IsIsolatedSiteFromSource(
origin,
ChildProcessSecurityPolicy::IsolatedOriginSource::WEB_TRIGGERED);
return is_already_isolated_due_to_coop;
}
return true;
}
UrlInfo NavigationRequest::GetUrlInfo() {
uint32_t isolation_flags = UrlInfo::OriginIsolationRequest::kNone;
if (IsOriginAgentClusterOptInRequested() || IsIsolationImplied())
isolation_flags |= UrlInfo::OriginIsolationRequest::kOriginAgentCluster;
if (IsOriginAgentClusterOptInRequested() &&
SiteIsolationPolicy::IsProcessIsolationForOriginAgentClusterEnabled()) {
isolation_flags |=
UrlInfo::OriginIsolationRequest::kRequiresOriginKeyedProcess;
}
auto isolation_request =
static_cast<UrlInfo::OriginIsolationRequest>(isolation_flags);
auto web_exposed_isolation_info = ComputeWebExposedIsolationInfo();
UrlInfoInit url_info_init(GetURL());
url_info_init.WithOriginIsolationRequest(isolation_request)
.WithCOOPSiteIsolation(ShouldRequestSiteIsolationForCOOP())
.WithWebExposedIsolationInfo(web_exposed_isolation_info)
.WithIsPdf(is_pdf_);
auto common_coop_origin = ComputeCommonCoopOrigin();
if (common_coop_origin.has_value()) {
url_info_init.WithCommonCoopOrigin(common_coop_origin.value());
}
SiteInstanceImpl* current_instance =
frame_tree_node_->current_frame_host()->GetSiteInstance();
if (current_instance->IsGuest()) {
url_info_init.WithStoragePartitionConfig(
current_instance->GetStoragePartitionConfig());
}
RenderFrameHostImpl* parent = GetParentFrameOrOuterDocument();
if (parent) {
url_info_init.WithStoragePartitionConfig(
parent->GetSiteInstance()->GetStoragePartitionConfig());
}
if (GetWebBundleURL().is_valid()) {
url_info_init.WithOrigin(
url::Origin::Resolve(GetURL(), url::Origin::Create(GetWebBundleURL())));
} else if (IsLoadDataWithBaseURL()) {
url_info_init.WithOrigin(
url::Origin::Create(common_params().base_url_for_data_url));
} else if (GetURL().IsAboutBlank() && GetInitiatorOrigin().has_value()) {
url_info_init.WithOrigin(*GetInitiatorOrigin());
} else {
DCHECK(!url_info_init.origin().has_value());
}
if (SiteIsolationPolicy::AreIsolatedSandboxedIframesEnabled() &&
!GetURL().IsAboutBlank()) {
bool has_origin_restricted_sandbox_flag = false;
if (policy_container_builder_->HasComputedPolicies()) {
has_origin_restricted_sandbox_flag =
(policy_container_builder_->FinalPolicies().sandbox_flags &
network::mojom::WebSandboxFlags::kOrigin) ==
network::mojom::WebSandboxFlags::kOrigin;
} else {
has_origin_restricted_sandbox_flag =
(commit_params_->frame_policy.sandbox_flags &
network::mojom::WebSandboxFlags::kOrigin) ==
network::mojom::WebSandboxFlags::kOrigin;
}
if (has_origin_restricted_sandbox_flag) {
const IsolationContext& isolation_context =
current_instance->GetIsolationContext();
if (SiteInfo::Create(isolation_context, UrlInfo(url_info_init))
.RequiresDedicatedProcess(isolation_context)) {
url_info_init.WithSandbox(true);
if (blink::features::kIsolateSandboxedIframesGroupingParam.Get() ==
blink::features::IsolateSandboxedIframesGrouping::kPerDocument) {
url_info_init.WithUniqueSandboxId(navigation_id_);
}
}
}
}
return UrlInfo(url_info_init);
}
const GURL& NavigationRequest::GetOriginalRequestURL() {
if (IsLoadDataWithBaseURL())
return GetURL();
DCHECK(!redirect_chain_.empty());
return redirect_chain_[0];
}
GURL NavigationRequest::GetWebBundleURL() {
if (!begin_params_->web_bundle_token)
return GURL();
return begin_params_->web_bundle_token->bundle_url;
}
std::unique_ptr<SubresourceWebBundleNavigationInfo>
NavigationRequest::GetSubresourceWebBundleNavigationInfo() {
if (!begin_params_->web_bundle_token)
return nullptr;
return std::make_unique<SubresourceWebBundleNavigationInfo>(
begin_params_->web_bundle_token->bundle_url,
begin_params_->web_bundle_token->token,
begin_params_->web_bundle_token->render_process_id);
}
void NavigationRequest::OnResponseStarted(
network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
network::mojom::URLResponseHeadPtr response_head,
mojo::ScopedDataPipeConsumerHandle response_body,
GlobalRequestID request_id,
bool is_download,
net::NetworkAnonymizationKey network_anonymization_key,
absl::optional<SubresourceLoaderParams> subresource_loader_params,
EarlyHints early_hints) {
if (is_download) {
download_policy().RecordHistogram();
}
ScopedCrashKeys crash_keys(*this);
loader_.reset();
if (is_download)
RecordDownloadUseCountersPrePolicyCheck();
is_download_ = is_download && download_policy().IsDownloadAllowed();
if (is_download_)
RecordDownloadUseCountersPostPolicyCheck();
request_id_ = request_id;
DCHECK(IsNavigationStarted());
DCHECK(response_head);
DCHECK(response_head->parsed_headers);
EnterChildTraceEvent("OnResponseStarted", this);
SetState(WILL_PROCESS_RESPONSE);
response_head_ = std::move(response_head);
response_body_ = std::move(response_body);
ssl_info_ = response_head_->ssl_info;
auth_challenge_info_ = response_head_->auth_challenge_info;
was_resource_hints_received_ = early_hints.was_resource_hints_received;
early_hints_manager_ = std::move(early_hints.manager);
RecordAddressSpaceFeature();
bool is_mhtml_archive = response_head_->mime_type == "multipart/related" ||
response_head_->mime_type == "message/rfc822";
if (is_mhtml_archive)
is_mhtml_or_subframe_ = true;
if (CheckCSPEmbeddedEnforcement() ==
CSPEmbeddedEnforcementResult::BLOCK_RESPONSE) {
OnRequestFailedInternal(
network::URLLoaderCompletionStatus(net::ERR_BLOCKED_BY_CSP),
true , absl::nullopt ,
false );
return;
}
if (!response_head_->timing_allow_passed) {
commit_params_->navigation_timing->parent_resource_timing_access =
blink::mojom::ParentResourceTimingAccess::kDoNotReport;
}
MaybeInjectIsolatedAppHeaders();
{
const absl::optional<network::mojom::BlockedByResponseReason>
coop_requires_blocking =
coop_status_.SanitizeResponse(response_head_.get());
if (coop_requires_blocking) {
OnRequestFailedInternal(
network::URLLoaderCompletionStatus(*coop_requires_blocking),
false , absl::nullopt ,
false );
return;
}
policy_container_builder_->SetCrossOriginOpenerPolicy(
response_head_->parsed_headers->cross_origin_opener_policy);
}
ComputePoliciesToCommit();
{
const PolicyContainerPolicies& policies =
policy_container_builder_->FinalPolicies();
const url::Origin origin =
GetOriginForURLLoaderFactoryBeforeResponse(policies.sandbox_flags);
coop_status_.EnforceCOOP(policies.cross_origin_opener_policy, origin,
network_anonymization_key);
}
CheckForIsolationOptIn(GetURL());
response_should_be_rendered_ =
!is_download &&
(!response_head_->headers.get() ||
(response_head_->headers->response_code() != net::HTTP_NO_CONTENT &&
response_head_->headers->response_code() != net::HTTP_RESET_CONTENT &&
!ShouldRenderFallbackContentForResponse(*response_head_->headers)));
if (!response_should_be_rendered_)
net_error_ = net::ERR_ABORTED;
const bool is_first_response = commit_params_->redirects.empty();
UpdateNavigationHandleTimingsOnResponseReceived(is_first_response);
commit_params_->http_response_code =
response_head_->headers ? response_head_->headers->response_code()
: -1 ;
commit_params_->navigation_timing->fetch_start =
std::max(commit_params_->navigation_timing->fetch_start,
response_head_->load_timing.service_worker_ready_time);
if (commit_params_->was_activated ==
blink::mojom::WasActivatedOption::kUnknown) {
commit_params_->was_activated = blink::mojom::WasActivatedOption::kNo;
if (!commit_params_->is_browser_initiated &&
(frame_tree_node_->HasStickyUserActivation() ||
frame_tree_node_->has_received_user_gesture_before_nav()) &&
ShouldPropagateUserActivation(
frame_tree_node_->current_origin(),
url::Origin::Create(common_params_->url))) {
commit_params_->was_activated = blink::mojom::WasActivatedOption::kYes;
} else if (((common_params_->has_user_gesture &&
!commit_params_->is_browser_initiated) ||
common_params_->started_from_context_menu) &&
ShouldPropagateUserActivation(
url::Origin::Create(sanitized_referrer_->url),
url::Origin::Create(common_params_->url))) {
commit_params_->was_activated = blink::mojom::WasActivatedOption::kYes;
}
}
if (is_mhtml_archive && !IsInMainFrame() && response_should_be_rendered_) {
OnRequestFailedInternal(
network::URLLoaderCompletionStatus(net::ERR_BLOCKED_BY_RESPONSE),
false , absl::nullopt ,
false );
return;
}
const absl::optional<network::mojom::BlockedByResponseReason>
coep_requires_blocking = EnforceCOEP();
if (coep_requires_blocking) {
OnRequestFailedInternal(
network::URLLoaderCompletionStatus(*coep_requires_blocking),
false , absl::nullopt ,
false );
return;
}
const auto& url = common_params_->url;
const bool should_enforce_fenced_frame_opt_in =
response_should_be_rendered_ && response_head_->headers &&
frame_tree_node_->IsInFencedFrameTree() &&
!(url.IsAboutBlank() || url.SchemeIsBlob() ||
url.SchemeIs(url::kDataScheme));
if (should_enforce_fenced_frame_opt_in &&
!IsOptedInFencedFrame(*response_head_->headers)) {
blink::RecordFencedFrameCreationOutcome(
blink::FencedFrameCreationOutcome::kResponseHeaderNotOptIn);
AddDeferredConsoleMessage(
blink::mojom::ConsoleMessageLevel::kError,
"Supports-Loading-Mode HTTP response header 'fenced-frame' is required "
"to load the fenced frame root and its nested iframes.");
OnRequestFailedInternal(
network::URLLoaderCompletionStatus(net::ERR_BLOCKED_BY_RESPONSE),
false , absl::nullopt ,
false );
return;
}
if (!CheckResponseAdherenceToCoep(url)) {
OnRequestFailedInternal(network::URLLoaderCompletionStatus(
network::mojom::BlockedByResponseReason::
kCoepFrameResourceNeedsCoepHeader),
false ,
absl::nullopt ,
false );
return;
}
SelectFrameHostForOnResponseStarted(std::move(url_loader_client_endpoints),
is_download,
std::move(subresource_loader_params));
}
void NavigationRequest::SelectFrameHostForOnResponseStarted(
network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
bool is_download,
absl::optional<SubresourceLoaderParams> subresource_loader_params) {
ScopedCrashKeys crash_keys(*this);
if (IsServedFromBackForwardCache()) {
CHECK(!restarting_back_forward_cached_navigation_);
NavigationControllerImpl* controller = GetNavigationController();
auto entry =
controller->GetBackForwardCache().GetOrEvictEntry(nav_entry_id_);
if (!rfh_restored_from_back_forward_cache_ ||
(!entry.has_value() &&
entry.error() == BackForwardCacheImpl::kEntryIneligibleAndEvicted)) {
return;
}
CHECK(entry.has_value() && entry.value());
CHECK(entry.value()->render_frame_host());
render_frame_host_ = entry.value()->render_frame_host()->GetSafeRef();
} else if (IsPrerenderedPageActivation()) {
DCHECK(IsInMainFrame());
render_frame_host_ = GetPrerenderHostRegistry()
.GetRenderFrameHostForReservedHost(
prerender_frame_tree_node_id_.value())
->GetSafeRef();
} else if (response_should_be_rendered_) {
if (auto result =
frame_tree_node_->render_manager()->GetFrameHostForNavigation(
this, &browsing_context_group_swap_);
result.has_value()) {
render_frame_host_ = result.value()->GetSafeRef();
} else {
switch (result.error()) {
case GetFrameHostForNavigationFailed::kCouldNotReinitializeMainFrame:
break;
case GetFrameHostForNavigationFailed::kBlockedByPendingCommit:
DCHECK(ShouldQueueDueToExistingPendingCommitRFH());
resume_commit_closure_ = base::BindOnce(
&NavigationRequest::SelectFrameHostForOnResponseStarted,
weak_factory_.GetWeakPtr(),
std::move(url_loader_client_endpoints), is_download,
std::move(subresource_loader_params));
return;
}
}
DCHECK_NE(AssociatedRenderFrameHostType::NONE, associated_rfh_type_);
if (!Navigator::CheckWebUIRendererDoesNotDisplayNormalURL(
GetRenderFrameHost(), GetUrlInfo(),
false)) {
CHECK(false);
}
} else {
render_frame_host_ = absl::nullopt;
}
if (!HasRenderFrameHost()) {
DCHECK(!response_should_be_rendered_);
}
if (!commit_params_->is_browser_initiated && HasRenderFrameHost() &&
GetRenderFrameHost()->GetProcess() !=
frame_tree_node_->current_frame_host()->GetProcess()) {
if (!frame_tree_node_->navigator()
.GetDelegate()
->ShouldAllowRendererInitiatedCrossProcessNavigation(
frame_tree_node_->IsOutermostMainFrame())) {
net_error_ = net::ERR_ABORTED;
frame_tree_node_->ResetNavigationRequest(
NavigationDiscardReason::kCancelled);
return;
}
}
proxy_server_ = response_head_->proxy_server;
url_loader_client_endpoints_ = std::move(url_loader_client_endpoints);
subresource_loader_params_ = std::move(subresource_loader_params);
if (common_params_->url.IsAboutBlank()) {
if (!WasServerRedirect()) {
DVLOG(1) << "about:blank should only go through the network stack "
<< "when an extension redirects to it.";
base::debug::DumpWithoutCrashing();
}
} else {
if (!SiteInstanceImpl::ShouldAssignSiteForUrlInfo(GetUrlInfo())) {
DVLOG(1) << "This URL was unexpectedly loaded through the network stack: "
<< common_params_->url;
base::debug::DumpWithoutCrashing();
}
}
if (HasRenderFrameHost()) {
SiteInstanceImpl* instance = GetRenderFrameHost()->GetSiteInstance();
if (!instance->HasSite() &&
SiteInstanceImpl::ShouldAssignSiteForUrlInfo(GetUrlInfo())) {
instance->ConvertToDefaultOrSetSite(GetUrlInfo());
}
GetRenderFrameHost()->GetProcess()->SetIsUsed();
const IsolationContext& isolation_context = instance->GetIsolationContext();
AddSameProcessOriginAgentClusterStateIfNecessary(isolation_context,
GetURL());
const url::Origin origin =
IsLoadDataWithBaseURL()
? url::Origin::Create(common_params_->base_url_for_data_url)
: url::Origin::Create(common_params_->url);
ChildProcessSecurityPolicyImpl::GetInstance()
->AddDefaultIsolatedOriginIfNeeded(
isolation_context, origin,
false );
NavigationEntryImpl* nav_entry =
frame_tree_node_->navigator().controller().GetLastCommittedEntry();
if (nav_entry && !nav_entry->GetURL().IsAboutBlank() &&
!SiteInstance::ShouldAssignSiteForURL(nav_entry->GetURL()) &&
SiteInstanceImpl::ShouldAssignSiteForUrlInfo(GetUrlInfo())) {
scoped_refptr<FrameNavigationEntry> frame_entry =
nav_entry->root_node()->frame_entry;
scoped_refptr<SiteInstanceImpl> new_site_instance =
base::WrapRefCounted<SiteInstanceImpl>(static_cast<SiteInstanceImpl*>(
instance->GetRelatedSiteInstance(frame_entry->url()).get()));
nav_entry->AddOrUpdateFrameEntry(
frame_tree_node_, NavigationEntryImpl::UpdatePolicy::kReplace,
frame_entry->item_sequence_number(),
frame_entry->document_sequence_number(),
frame_entry->navigation_api_key(), new_site_instance.get(),
frame_entry->source_site_instance(), frame_entry->url(),
frame_entry->committed_origin(), frame_entry->referrer(),
frame_entry->initiator_origin(), frame_entry->initiator_base_url(),
frame_entry->redirect_chain(), frame_entry->page_state(),
frame_entry->method(), frame_entry->post_id(),
frame_entry->blob_url_loader_factory(),
frame_entry->subresource_web_bundle_navigation_info()
? frame_entry->subresource_web_bundle_navigation_info()->Clone()
: nullptr,
frame_entry->policy_container_policies()
? frame_entry->policy_container_policies()->ClonePtr()
: nullptr);
}
}
devtools_instrumentation::OnNavigationResponseReceived(*this,
*response_head_);
if (is_download && (response_head_->headers.get() &&
(response_head_->headers->response_code() / 100 != 2))) {
OnRequestFailedInternal(
network::URLLoaderCompletionStatus(net::ERR_INVALID_RESPONSE),
false , absl::nullopt ,
false );
return;
}
net::Error net_error = CheckContentSecurityPolicy(
was_redirected_ ,
false , true );
DCHECK_NE(net_error, net::ERR_BLOCKED_BY_CLIENT);
if (net_error != net::OK) {
OnRequestFailedInternal(network::URLLoaderCompletionStatus(net_error),
false ,
absl::nullopt ,
false );
return;
}
if (HasRenderFrameHost() &&
!CheckPermissionsPoliciesForFencedFrames(GetOriginToCommit().value())) {
OnRequestFailedInternal(
network::URLLoaderCompletionStatus(net::ERR_ABORTED),
false , absl::nullopt ,
false );
return;
}
WillProcessResponse();
}
void NavigationRequest::OnRequestFailed(
const network::URLLoaderCompletionStatus& status) {
DCHECK_NE(status.error_code, net::OK);
OnRequestFailedInternal(
status, false ,
absl::nullopt ,
status.should_collapse_initiator );
}
absl::optional<NavigationEarlyHintsManagerParams>
NavigationRequest::CreateNavigationEarlyHintsManagerParams(
const network::mojom::EarlyHints& early_hints) {
CHECK(!HasRenderFrameHost());
CHECK(loader_);
CHECK_LT(state_, WILL_PROCESS_RESPONSE);
CHECK(!IsSameDocument());
CHECK(IsInMainFrame());
DCHECK(!IsPageActivation());
auto result = frame_tree_node_->render_manager()->GetFrameHostForNavigation(
this, &browsing_context_group_swap_);
if (!result.has_value()) {
return absl::nullopt;
}
RenderProcessHost* process = result.value()->GetProcess();
if (!process->GetBrowserContext())
return absl::nullopt;
network::mojom::WebSandboxFlags sandbox_flags =
commit_params_->frame_policy.sandbox_flags;
const url::Origin tentative_origin =
GetOriginForURLLoaderFactoryBeforeResponse(sandbox_flags);
mojo::PendingRemote<network::mojom::CookieAccessObserver> cookie_observer;
Clone(cookie_observer.InitWithNewPipeAndPassReceiver());
mojo::PendingRemote<network::mojom::TrustTokenAccessObserver>
trust_token_observer;
Clone(trust_token_observer.InitWithNewPipeAndPassReceiver());
network::mojom::URLLoaderFactoryParamsPtr url_loader_factory_params =
URLLoaderFactoryParamsHelper::CreateForEarlyHintsPreload(
process, tentative_origin, *this, early_hints,
std::move(cookie_observer), std::move(trust_token_observer));
net::IsolationInfo isolation_info = url_loader_factory_params->isolation_info;
mojo::Remote<network::mojom::URLLoaderFactory> loader_factory;
process->CreateURLLoaderFactory(loader_factory.BindNewPipeAndPassReceiver(),
std::move(url_loader_factory_params));
did_create_early_hints_manager_params_ = true;
return NavigationEarlyHintsManagerParams(
tentative_origin, std::move(isolation_info), std::move(loader_factory));
}
void NavigationRequest::OnRequestFailedInternal(
const network::URLLoaderCompletionStatus& status,
bool skip_throttles,
const absl::optional<std::string>& error_page_content,
bool collapse_frame) {
CheckStateTransition(WILL_FAIL_REQUEST);
DCHECK(!(status.error_code == net::ERR_ABORTED &&
error_page_content.has_value()));
ScopedCrashKeys crash_keys(*this);
loader_.reset();
ssl_info_ = status.ssl_info;
devtools_instrumentation::OnNavigationRequestFailed(*this, status);
EnterChildTraceEvent("OnRequestFailed", this, "error", status.error_code);
SetState(WILL_FAIL_REQUEST);
processing_navigation_throttle_ = false;
pending_entry_ref_.reset();
net_error_ = static_cast<net::Error>(status.error_code);
extended_error_code_ = status.extended_error_code;
resolve_error_info_ = status.resolve_error_info;
if (MaybeCancelFailedNavigation())
return;
if (collapse_frame) {
DCHECK_EQ(net::ERR_BLOCKED_BY_CLIENT, status.error_code);
frame_tree_node_->SetCollapsed(true);
}
is_mhtml_or_subframe_ = false;
ComputePoliciesToCommitForError();
coop_status_.EnforceCOOP(
policy_container_builder_->FinalPolicies().cross_origin_opener_policy,
url::Origin(), net::NetworkAnonymizationKey::CreateTransient());
switch (ComputeErrorPageProcess()) {
case ErrorPageProcess::kCurrentProcess:
CHECK(!IsSameDocument());
break;
case ErrorPageProcess::kIsolatedProcess:
ResetExpectedProcess();
[[fallthrough]];
case ErrorPageProcess::kDestinationProcess:
common_params_->navigation_type =
ConvertToCrossDocumentType(common_params_->navigation_type);
break;
case ErrorPageProcess::kNotErrorPage:
case ErrorPageProcess::kPostCommitErrorPage:
NOTREACHED();
break;
}
RenderFrameHostImpl* render_frame_host = nullptr;
if (auto result =
frame_tree_node_->render_manager()->GetFrameHostForNavigation(
this, &browsing_context_group_swap_);
result.has_value()) {
render_frame_host = result.value();
} else {
switch (result.error()) {
case GetFrameHostForNavigationFailed::kCouldNotReinitializeMainFrame:
break;
case GetFrameHostForNavigationFailed::kBlockedByPendingCommit:
break;
}
}
CHECK(!HasRenderFrameHost() || GetRenderFrameHost() == render_frame_host);
render_frame_host_ = render_frame_host->GetSafeRef();
SetAssociatedRFHType(
GetRenderFrameHost() ==
frame_tree_node_->render_manager()->current_frame_host()
? AssociatedRenderFrameHostType::CURRENT
: AssociatedRenderFrameHostType::SPECULATIVE);
SiteInstanceImpl* instance = GetRenderFrameHost()->GetSiteInstance();
if (!instance->HasSite())
instance->ConvertToDefaultOrSetSite(GetUrlInfo());
GetRenderFrameHost()->GetProcess()->SetIsUsed();
if (frame_tree_node_->IsErrorPageIsolationEnabled()) {
if (!Navigator::CheckWebUIRendererDoesNotDisplayNormalURL(
GetRenderFrameHost(), GetUrlInfo(),
false)) {
CHECK(false);
}
}
has_stale_copy_in_cache_ = status.exists_in_cache;
if (skip_throttles) {
CommitErrorPage(error_page_content);
} else {
WillFailRequest();
}
}
NavigationRequest::ErrorPageProcess
NavigationRequest::ComputeErrorPageProcess() {
if (net_error_ == net::OK) {
return ErrorPageProcess::kNotErrorPage;
}
if (state_ < NavigationRequest::CANCELING) {
CHECK(!post_commit_error_page_html_.empty());
return ErrorPageProcess::kPostCommitErrorPage;
}
if (frame_tree_node_->IsErrorPageIsolationEnabled())
return ErrorPageProcess::kIsolatedProcess;
if (net_error_ == net::ERR_UNKNOWN_URL_SCHEME &&
frame_tree_node_->current_frame_host()->GetSiteInstance()->IsGuest()) {
return ErrorPageProcess::kCurrentProcess;
}
if (net::IsRequestBlockedError(net_error_) && !browser_initiated()) {
return ErrorPageProcess::kCurrentProcess;
}
return ErrorPageProcess::kDestinationProcess;
}
#ifdef OHOS_EX_UA
void NavigationRequest::RemoveUserAgentHeaderForDevTools(bool devtools_useragent_override) {
if (devtools_useragent_override && base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableNwebExUa)) {
modified_request_headers_.RemoveHeader(net::HttpRequestHeaders::kUserAgent);
}
}
#endif
void NavigationRequest::OnStartChecksComplete(
NavigationThrottle::ThrottleCheckResult result) {
DCHECK(result.action() != NavigationThrottle::DEFER);
DCHECK(result.action() != NavigationThrottle::BLOCK_RESPONSE);
if (on_start_checks_complete_closure_)
std::move(on_start_checks_complete_closure_).Run();
if (result.action() == NavigationThrottle::CANCEL_AND_IGNORE ||
result.action() == NavigationThrottle::CANCEL ||
result.action() == NavigationThrottle::BLOCK_REQUEST ||
result.action() == NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE) {
#if DCHECK_IS_ON()
if (result.action() == NavigationThrottle::BLOCK_REQUEST) {
DCHECK(net::IsRequestBlockedError(result.net_error_code()));
}
else if (result.action() == NavigationThrottle::CANCEL_AND_IGNORE) {
DCHECK_EQ(result.net_error_code(), net::ERR_ABORTED);
}
#endif
bool collapse_frame =
result.action() == NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE;
GetUIThreadTaskRunner({})->PostTask(
FROM_HERE, base::BindOnce(&NavigationRequest::OnRequestFailedInternal,
weak_factory_.GetWeakPtr(),
network::URLLoaderCompletionStatus(
result.net_error_code()),
true ,
result.error_page_content(), collapse_frame));
return;
}
StoragePartition* partition = GetStoragePartitionWithCurrentSiteInfo();
DCHECK(partition);
DCHECK(!loader_);
bool can_create_service_worker =
(frame_tree_node_->pending_frame_policy().sandbox_flags &
network::mojom::WebSandboxFlags::kOrigin) !=
network::mojom::WebSandboxFlags::kOrigin;
if (can_create_service_worker) {
ServiceWorkerContextWrapper* service_worker_context =
static_cast<ServiceWorkerContextWrapper*>(
partition->GetServiceWorkerContext());
service_worker_handle_ = std::make_unique<ServiceWorkerMainResourceHandle>(
service_worker_context,
base::BindRepeating(&NavigationRequest::OnServiceWorkerAccessed,
weak_factory_.GetWeakPtr()));
}
commit_params_->navigation_timing->fetch_start = base::TimeTicks::Now();
#if BUILDFLAG(IS_OHOS)
TRACE_EVENT1("navigation", "PAGE_LOAD_TIME",
"fetchStart", commit_params_->navigation_timing->fetch_start);
#endif
std::unique_ptr<NavigationUIData> navigation_ui_data;
if (navigation_ui_data_)
navigation_ui_data = navigation_ui_data_->Clone();
bool report_raw_headers = false;
absl::optional<std::vector<net::SourceStream::SourceType>>
devtools_accepted_stream_types;
devtools_instrumentation::ApplyNetworkRequestOverrides(
frame_tree_node_, begin_params_.get(), &report_raw_headers,
&devtools_accepted_stream_types, &devtools_user_agent_override_,
&devtools_accept_language_override_);
devtools_instrumentation::OnNavigationRequestWillBeSent(*this);
net::HttpRequestHeaders headers;
headers.AddHeadersFromString(begin_params_->headers);
#ifdef OHOS_EX_UA
RemoveUserAgentHeaderForDevTools(devtools_user_agent_override_);
#endif
headers.MergeFrom(TakeModifiedRequestHeaders());
begin_params_->headers = headers.ToString();
std::vector<std::unique_ptr<NavigationLoaderInterceptor>> interceptor;
net::HttpRequestHeaders cors_exempt_headers;
std::swap(cors_exempt_headers, cors_exempt_request_headers_);
network::mojom::ClientSecurityStatePtr client_security_state = nullptr;
RenderFrameHostImpl* parent = GetParentFrame();
if (parent) {
client_security_state = parent->BuildClientSecurityState();
if (!base::FeatureList::IsEnabled(
features::kBlockInsecurePrivateNetworkRequestsForNavigations)) {
client_security_state->local_network_request_policy =
client_security_state->is_web_secure_context
? network::mojom::LocalNetworkRequestPolicy::kAllow
: network::mojom::LocalNetworkRequestPolicy::kWarn;
}
}
auto loader_type = NavigationURLLoader::LoaderType::kRegular;
network::mojom::URLResponseHeadPtr cached_response_head = nullptr;
if (IsServedFromBackForwardCache()) {
if (restarting_back_forward_cached_navigation_) {
return;
}
if (!rfh_restored_from_back_forward_cache_ ||
rfh_restored_from_back_forward_cache_
->is_evicted_from_back_forward_cache()) {
SCOPED_CRASH_KEY_BOOL("NoRestoredRFH", "rfh_exists",
!!rfh_restored_from_back_forward_cache_);
SCOPED_CRASH_KEY_BOOL("NoRestoredRFH", "is_main_frame",
frame_tree_node_->IsMainFrame());
SCOPED_CRASH_KEY_BOOL("NoRestoredRFH", "is_outermost_main_frame",
frame_tree_node_->IsOutermostMainFrame());
SCOPED_CRASH_KEY_BOOL("NoRestoredRFH", "is_ftn_nav_req",
(frame_tree_node_->navigation_request() == this));
BackForwardCacheImpl& back_forward_cache =
frame_tree_node_->frame_tree().controller().GetBackForwardCache();
SCOPED_CRASH_KEY_NUMBER("NoRestoredRFH", "bfcache_entries_size",
back_forward_cache.GetEntries().size());
CaptureTraceForNavigationDebugScenario(
DebugScenario::kDebugNoRestoredRFHOnNonRestartedNavigation);
return;
}
loader_type = NavigationURLLoader::LoaderType::kNoopForBackForwardCache;
cached_response_head =
rfh_restored_from_back_forward_cache_->last_response_head()->Clone();
} else if (IsPrerenderedPageActivation()) {
loader_type = NavigationURLLoader::LoaderType::kNoopForPrerender;
DCHECK(prerender_frame_tree_node_id_.has_value());
const network::mojom::URLResponseHeadPtr& last_response_head =
GetPrerenderHostRegistry()
.GetRenderFrameHostForReservedHost(*prerender_frame_tree_node_id_)
->last_response_head();
DCHECK(last_response_head);
cached_response_head = last_response_head->Clone();
}
network::mojom::WebSandboxFlags sandbox_flags =
commit_params_->frame_policy.sandbox_flags;
compositor_lock_.reset();
BrowserContext* browser_context =
frame_tree_node_->navigator().controller().GetBrowserContext();
loader_ = NavigationURLLoader::Create(
browser_context, partition,
std::make_unique<NavigationRequestInfo>(
common_params_->Clone(), begin_params_.Clone(), sandbox_flags,
GetIsolationInfo(),
frame_tree_node_->current_frame_host()->IsInPrimaryMainFrame(),
frame_tree_node_->IsOutermostMainFrame(),
frame_tree_node_->IsMainFrame(),
IsSecureFrame(frame_tree_node_->parent()),
frame_tree_node_->frame_tree_node_id(), report_raw_headers,
upgrade_if_insecure_,
blob_url_loader_factory_ ? blob_url_loader_factory_->Clone()
: nullptr,
devtools_navigation_token(),
frame_tree_node_->current_frame_host()->devtools_frame_token(),
std::move(cors_exempt_headers), std::move(client_security_state),
devtools_accepted_stream_types, is_pdf_, initiator_document_,
GetPreviousRenderFrameHostId(), allow_cookies_from_browser_),
std::move(navigation_ui_data), service_worker_handle_.get(),
std::move(prefetched_signed_exchange_cache_), this, loader_type,
CreateCookieAccessObserver(), CreateTrustTokenAccessObserver(),
static_cast<StoragePartitionImpl*>(partition)
->CreateURLLoaderNetworkObserverForNavigationRequest(*this),
NetworkServiceDevToolsObserver::MakeSelfOwned(frame_tree_node_),
std::move(cached_response_head), std::move(interceptor));
DCHECK(!HasRenderFrameHost());
base::UmaHistogramTimes(
base::StrCat({"Navigation.WillStartRequestToLoaderStart.",
IsInMainFrame() ? "MainFrame" : "Subframe"}),
base::TimeTicks::Now() - will_start_request_time_);
loader_->Start();
}
void NavigationRequest::OnServiceWorkerAccessed(
const GURL& scope,
AllowServiceWorkerResult allowed) {
GetDelegate()->OnServiceWorkerAccessed(this, scope, allowed);
}
network::mojom::WebSandboxFlags NavigationRequest::SandboxFlagsInherited() {
return commit_params_->frame_policy.sandbox_flags;
}
network::mojom::WebSandboxFlags NavigationRequest::SandboxFlagsToCommit() {
DCHECK_GE(state_, WILL_PROCESS_RESPONSE);
DCHECK(!IsSameDocument());
DCHECK(!IsPageActivation());
return policy_container_builder_->FinalPolicies().sandbox_flags;
}
void NavigationRequest::MaybeAddResourceTimingEntryForCancelledNavigation() {
if (!base::FeatureList::IsEnabled(
features::kResourceTimingForCancelledNavigationInFrame)) {
return;
}
if (!response()) {
return;
}
network::URLLoaderCompletionStatus status;
status.encoded_data_length = response()->encoded_data_length;
status.completion_time = base::TimeTicks::Now();
AddResourceTimingEntryForFailedSubframeNavigation(status);
}
void NavigationRequest::AddResourceTimingEntryForFailedSubframeNavigation(
const network::URLLoaderCompletionStatus& status) {
DCHECK(response());
if (commit_params().navigation_timing->parent_resource_timing_access ==
blink::mojom::ParentResourceTimingAccess::kDoNotReport) {
return;
}
network::mojom::URLResponseHeadPtr response_head = response()->Clone();
bool allow_response_details =
commit_params().navigation_timing->parent_resource_timing_access ==
blink::mojom::ParentResourceTimingAccess::kReportWithResponseDetails;
GetParentFrame()->AddResourceTimingEntryForFailedSubframeNavigation(
frame_tree_node(), common_params().navigation_start,
commit_params().navigation_timing->redirect_end,
commit_params().original_url, common_params().url,
std::move(response_head), allow_response_details, status);
}
void NavigationRequest::OnRedirectChecksComplete(
NavigationThrottle::ThrottleCheckResult result) {
DCHECK(result.action() != NavigationThrottle::DEFER);
DCHECK(result.action() != NavigationThrottle::BLOCK_RESPONSE);
DCHECK(!IsPageActivation());
bool collapse_frame =
result.action() == NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE;
if (result.action() == NavigationThrottle::CANCEL_AND_IGNORE ||
result.action() == NavigationThrottle::CANCEL) {
DCHECK(result.action() == NavigationThrottle::CANCEL ||
result.net_error_code() == net::ERR_ABORTED);
OnRequestFailedInternal(
network::URLLoaderCompletionStatus(result.net_error_code()),
true , result.error_page_content(), collapse_frame);
return;
}
if (result.action() == NavigationThrottle::BLOCK_REQUEST ||
result.action() == NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE) {
DCHECK(net::IsRequestBlockedError(result.net_error_code()));
OnRequestFailedInternal(
network::URLLoaderCompletionStatus(result.net_error_code()),
true , result.error_page_content(), collapse_frame);
return;
}
devtools_instrumentation::OnNavigationRequestWillBeSent(*this);
net::HttpRequestHeaders modified_headers = TakeModifiedRequestHeaders();
std::vector<std::string> removed_headers = TakeRemovedRequestHeaders();
if (topics_eligible_) {
topics_eligible_ = false;
removed_headers.push_back(kBrowsingTopicsRequestHeaderKey);
HandleTopicsEligibleResponse(
*commit_params_->redirect_response.back().get()->headers.get(),
url::Origin::Create(commit_params_->redirects.back()),
*frame_tree_node_->current_frame_host(),
browsing_topics::ApiCallerSource::kIframeAttribute);
}
absl::optional<std::string> topics_header_value =
GetTopicsHeaderValueForNavigationRequest(frame_tree_node_,
common_params_->url);
topics_eligible_ = topics_header_value.has_value();
if (topics_eligible_) {
modified_headers.SetHeader(kBrowsingTopicsRequestHeaderKey,
*topics_header_value);
}
for (const auto& elem : network::GetClientHintToNameMap()) {
const auto& header = elem.second;
removed_headers.push_back(header);
}
BrowserContext* browser_context =
frame_tree_node_->navigator().controller().GetBrowserContext();
ClientHintsControllerDelegate* client_hints_delegate =
browser_context->GetClientHintsControllerDelegate();
if (client_hints_delegate) {
net::HttpRequestHeaders client_hints_extra_headers;
const url::Origin& source_origin =
url::Origin::Create(commit_params_->redirects.back());
const network::mojom::URLResponseHead* response_head =
commit_params_->redirect_response.back().get();
ParseAndPersistAcceptCHForNavigation(
source_origin, response_head->parsed_headers,
response_head->headers.get(), browser_context, client_hints_delegate,
frame_tree_node_);
if (response_head->headers && response_head->headers->response_code() !=
net::HTTP_TEMPORARY_REDIRECT) {
std::vector<network::mojom::WebClientHintsType> client_hints =
LookupAcceptCHForCommit(source_origin, client_hints_delegate,
frame_tree_node_,
commit_params_->redirects.back());
RemoveOriginTrialHintsFromAcceptCH(commit_params_->redirects.back(),
client_hints_delegate, response_head,
client_hints, frame_tree_node_);
}
AddNavigationRequestClientHintsHeaders(
GetTentativeOriginAtRequestTime(), &client_hints_extra_headers,
browser_context, client_hints_delegate, is_overriding_user_agent(),
frame_tree_node_, commit_params_->frame_policy.container_policy,
common_params_->url);
modified_headers.MergeFrom(client_hints_extra_headers);
if (!devtools_user_agent_override_) {
modified_headers.SetHeader(
net::HttpRequestHeaders::kUserAgent,
ComputeUserAgentValue(modified_headers, GetUserAgentOverride(),
browser_context));
}
}
if (auto reduce_accept_lang_utils =
ReduceAcceptLanguageUtils::Create(browser_context);
reduce_accept_lang_utils && !devtools_accept_language_override_) {
const network::mojom::URLResponseHead* response_head =
commit_params_->redirect_response.back().get();
if (response_head->headers && response_head->headers->response_code() !=
net::HTTP_TEMPORARY_REDIRECT) {
const url::Origin& source_origin =
url::Origin::Create(commit_params_->redirects.back());
absl::optional<std::string> persisted_language =
reduce_accept_lang_utils.value().LookupReducedAcceptLanguage(
source_origin, frame_tree_node_);
reduce_accept_lang_utils.value().RemoveOriginTrialReducedAcceptLanguage(
persisted_language.value_or(""), source_origin, response_head,
frame_tree_node_);
}
net::HttpRequestHeaders accept_language_headers;
absl::optional<std::string> reduced_accept_language =
reduce_accept_lang_utils.value()
.AddNavigationRequestAcceptLanguageHeaders(
url::Origin::Create(common_params_->url), frame_tree_node_,
&accept_language_headers);
commit_params_->reduced_accept_language =
reduced_accept_language.value_or("");
modified_headers.MergeFrom(accept_language_headers);
removed_headers.push_back(net::HttpRequestHeaders::kAcceptLanguage);
}
net::HttpRequestHeaders cors_exempt_headers;
std::swap(cors_exempt_headers, cors_exempt_request_headers_);
loader_->FollowRedirect(std::move(removed_headers),
std::move(modified_headers),
std::move(cors_exempt_headers));
}
void NavigationRequest::OnFailureChecksComplete(
NavigationThrottle::ThrottleCheckResult result) {
DCHECK(result.action() != NavigationThrottle::DEFER);
net::Error old_net_error = net_error_;
ErrorPageProcess old_error_page_process = ComputeErrorPageProcess();
net_error_ = result.net_error_code();
CHECK_EQ(old_error_page_process, ComputeErrorPageProcess())
<< " Unsupported error code change in WillFailRequest(): from "
<< old_net_error << " to " << net_error_;
if (MaybeCancelFailedNavigation())
return;
CommitErrorPage(result.error_page_content());
}
void NavigationRequest::OnWillProcessResponseChecksComplete(
NavigationThrottle::ThrottleCheckResult result) {
DCHECK(result.action() != NavigationThrottle::DEFER);
if (result.action() == NavigationThrottle::PROCEED) {
if (is_download_) {
auto resource_request = std::make_unique<network::ResourceRequest>();
resource_request->url = common_params_->url;
resource_request->method = common_params_->method;
resource_request->request_initiator = common_params_->initiator_origin;
resource_request->referrer = common_params_->referrer->url;
resource_request->has_user_gesture = common_params_->has_user_gesture;
resource_request->mode = network::mojom::RequestMode::kNavigate;
resource_request->transition_type = common_params_->transition;
resource_request->trusted_params =
network::ResourceRequest::TrustedParams();
resource_request->trusted_params->isolation_info = GetIsolationInfo();
BrowserContext* browser_context =
frame_tree_node_->navigator().controller().GetBrowserContext();
DownloadManagerImpl* download_manager = static_cast<DownloadManagerImpl*>(
browser_context->GetDownloadManager());
#ifdef OHOS_ARKWEB_ADBLOCK
frame_tree_node_->set_adblock_enabled(
frame_tree_node_->is_adblock_enabled_last_committed());
#endif
download_manager->InterceptNavigation(
std::move(resource_request), redirect_chain_, response_head_.Clone(),
std::move(response_body_), std::move(url_loader_client_endpoints_),
ssl_info_.has_value() ? ssl_info_->cert_status : 0,
frame_tree_node_->frame_tree_node_id(),
from_download_cross_origin_redirect_);
OnRequestFailedInternal(
network::URLLoaderCompletionStatus(net::ERR_ABORTED),
false , absl::nullopt ,
false );
return;
}
if (response()->headers &&
ShouldRenderFallbackContentForResponse(*response()->headers)) {
ObjectNavigationFallbackBodyLoader::CreateAndStart(
*this, std::move(response_body_),
std::move(url_loader_client_endpoints_),
base::BindOnce(&NavigationRequest::OnRequestFailedInternal,
weak_factory_.GetWeakPtr(),
network::URLLoaderCompletionStatus(net::ERR_ABORTED),
false ,
absl::nullopt ,
false ));
return;
}
}
if (result.action() == NavigationThrottle::CANCEL_AND_IGNORE ||
result.action() == NavigationThrottle::CANCEL ||
!response_should_be_rendered_) {
MaybeAddResourceTimingEntryForCancelledNavigation();
render_frame_host_ = absl::nullopt;
if (!response_should_be_rendered_) {
OnRequestFailedInternal(
network::URLLoaderCompletionStatus(net::ERR_ABORTED),
true , absl::nullopt ,
false );
return;
}
DCHECK(result.action() == NavigationThrottle::CANCEL ||
result.net_error_code() == net::ERR_ABORTED);
OnRequestFailedInternal(
network::URLLoaderCompletionStatus(result.net_error_code()),
true , result.error_page_content(),
false );
return;
}
if (result.action() == NavigationThrottle::BLOCK_RESPONSE) {
DCHECK_EQ(net::ERR_BLOCKED_BY_RESPONSE, result.net_error_code());
render_frame_host_ = absl::nullopt;
OnRequestFailedInternal(
network::URLLoaderCompletionStatus(result.net_error_code()),
true , result.error_page_content(),
false );
return;
}
DCHECK_EQ(result.action(), NavigationThrottle::PROCEED);
if (IsPrerenderedPageActivation()) {
DCHECK(!commit_deferrer_);
CommitNavigation();
return;
};
RunCommitDeferringConditions();
}
void NavigationRequest::OnWillCommitWithoutUrlLoaderChecksComplete(
NavigationThrottle::ThrottleCheckResult result) {
DCHECK(result.action() == NavigationThrottle::CANCEL_AND_IGNORE ||
result.action() == NavigationThrottle::PROCEED);
if (result.action() == NavigationThrottle::CANCEL_AND_IGNORE) {
OnRequestFailedInternal(
network::URLLoaderCompletionStatus(result.net_error_code()),
true, result.error_page_content(),
false);
return;
}
CommitNavigation();
}
void NavigationRequest::RunCommitDeferringConditions() {
commit_deferrer_->RegisterDeferringConditions(*this);
commit_deferrer_->ProcessChecks();
}
void NavigationRequest::OnCommitDeferringConditionChecksComplete(
CommitDeferringCondition::NavigationType navigation_type,
absl::optional<int> candidate_prerender_frame_tree_node_id) {
switch (navigation_type) {
case CommitDeferringCondition::NavigationType::kPrerenderedPageActivation:
OnPrerenderingActivationChecksComplete(
navigation_type, candidate_prerender_frame_tree_node_id);
return;
case CommitDeferringCondition::NavigationType::kOther:
DCHECK_LT(state_, READY_TO_COMMIT);
CommitNavigation();
return;
}
}
void NavigationRequest::CommitErrorPage(
const absl::optional<std::string>& error_page_content) {
DCHECK(!IsSameDocument());
DetermineOriginAgentClusterEndResult();
UpdateCommitNavigationParamsHistory();
common_params_->should_replace_current_entry =
ShouldReplaceCurrentEntryForFailedNavigation();
DCHECK(!commit_params_->origin_to_commit);
commit_params_->origin_to_commit = GetOriginToCommit();
DCHECK(commit_params_->origin_to_commit->opaque());
common_params_->initiator_base_url = absl::nullopt;
if (request_navigation_client_.is_bound()) {
if (GetRenderFrameHost() == frame_tree_node()->current_frame_host()) {
commit_navigation_client_ = std::move(request_navigation_client_);
} else {
IgnoreInterfaceDisconnection();
}
}
if (topics_eligible_) {
topics_eligible_ = false;
}
base::WeakPtr<NavigationRequest> weak_self(weak_factory_.GetWeakPtr());
ReadyToCommitNavigation(true );
if (!weak_self) {
return;
}
PopulateDocumentTokenForCrossDocumentNavigation();
isolation_info_for_subresources_ = net::IsolationInfo::CreateTransient();
GetRenderFrameHost()->FailedNavigation(
this, *common_params_, *commit_params_, has_stale_copy_in_cache_,
net_error_, extended_error_code_, error_page_content, *document_token_);
SendDeferredConsoleMessages();
}
void NavigationRequest::AddOldPageInfoToCommitParamsIfNeeded() {
auto* old_frame_host =
frame_tree_node_->render_manager()->current_frame_host();
if (!GetRenderFrameHost()
->ShouldDispatchPagehideAndVisibilitychangeDuringCommit(
old_frame_host, GetUrlInfo())) {
return;
}
DCHECK(!IsSameDocument());
bool can_store_old_page_in_bfcache =
frame_tree_node_->frame_tree()
.controller()
.GetBackForwardCache()
.GetFutureBackForwardCacheEligibilityPotential(old_frame_host)
.CanStore();
commit_params_->old_page_info = blink::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 );
}
void NavigationRequest::CommitNavigation() {
DCHECK_GE(state_, WILL_PROCESS_RESPONSE);
CHECK(!HasWebUI());
CheckSoftNavigationHeuristicsInvariants();
if (!CoopCoepSanityCheck())
return;
DetermineOriginAgentClusterEndResult();
UpdateCommitNavigationParamsHistory();
DCHECK(NeedsUrlLoader() == !!response_head_ ||
(was_redirected_ && common_params_->url.IsAboutBlank()));
DCHECK(!common_params_->url.SchemeIs(url::kJavaScriptScheme));
DCHECK(!blink::IsRendererDebugURL(common_params_->url));
AddOldPageInfoToCommitParamsIfNeeded();
url::Origin origin =
(common_params_->url.SchemeIs(url::kUuidInPackageScheme) &&
GetWebBundleURL().is_valid())
? url::Origin::Create(GetWebBundleURL())
: GetOriginToCommit().value();
url::Origin origin_to_commit = GetOriginToCommit().value();
isolation_info_for_subresources_ =
GetRenderFrameHost()->ComputeIsolationInfoForSubresourcesForPendingCommit(
origin, is_credentialless(), ComputeFencedFrameNonce());
DCHECK(!isolation_info_for_subresources_.IsEmpty());
if (GetURL().IsAboutSrcdoc() &&
(!common_params().initiator_origin ||
origin_to_commit.GetTupleOrPrecursorTupleIfOpaque() !=
common_params()
.initiator_origin->GetTupleOrPrecursorTupleIfOpaque())) {
common_params_->initiator_base_url = absl::nullopt;
}
absl::optional<base::UnguessableToken> nonce =
GetRenderFrameHost()->ComputeNonce(is_credentialless(),
ComputeFencedFrameNonce());
commit_params_->storage_key = GetRenderFrameHost()->CalculateStorageKey(
GetOriginToCommit().value(), base::OptionalToPtr(nonce));
commit_params_->session_storage_key =
frame_tree_node()->frame_tree().GetSessionStorageKey(
commit_params_->storage_key);
if (topics_eligible_) {
topics_eligible_ = false;
if (response()) {
HandleTopicsEligibleResponse(
*response()->headers.get(), url::Origin::Create(common_params_->url),
*GetRenderFrameHost(),
browsing_topics::ApiCallerSource::kIframeAttribute);
}
}
RenderFrameHostImpl* old_frame_host =
frame_tree_node_->render_manager()->current_frame_host();
if (!NavigationTypeUtils::IsSameDocument(common_params_->navigation_type)) {
old_frame_host->RecordNavigationSuddenTerminationHandlers();
}
if (IsServedFromBackForwardCache() || IsPrerenderedPageActivation()) {
CommitPageActivation();
return;
}
base::WeakPtr<NavigationRequest> weak_self(weak_factory_.GetWeakPtr());
ReadyToCommitNavigation(false );
if (!weak_self)
return;
DCHECK(GetRenderFrameHost() == old_frame_host ||
GetRenderFrameHost() ==
frame_tree_node_->render_manager()->speculative_frame_host());
if (request_navigation_client_.is_bound()) {
if (GetRenderFrameHost() == frame_tree_node()->current_frame_host()) {
commit_navigation_client_ = std::move(request_navigation_client_);
} else {
IgnoreInterfaceDisconnection();
}
}
CreateCoepReporter(GetRenderFrameHost()->GetProcess()->GetStoragePartition());
coop_status_.UpdateReporterStoragePartition(
GetRenderFrameHost()->GetProcess()->GetStoragePartition());
BrowserContext* browser_context =
frame_tree_node_->navigator().controller().GetBrowserContext();
ClientHintsControllerDelegate* client_hints_delegate =
browser_context->GetClientHintsControllerDelegate();
if (client_hints_delegate) {
absl::optional<std::vector<network::mojom::WebClientHintsType>>
opt_in_hints_from_response;
if (response()) {
opt_in_hints_from_response = ParseAndPersistAcceptCHForNavigation(
url::Origin::Create(common_params_->url), response()->parsed_headers,
response()->headers.get(), browser_context, client_hints_delegate,
frame_tree_node_);
}
commit_params_->enabled_client_hints = LookupAcceptCHForCommit(
GetOriginToCommit().value(), client_hints_delegate, frame_tree_node_,
common_params_->url);
RemoveOriginTrialHintsFromAcceptCH(
common_params_->url, client_hints_delegate, response(),
commit_params_->enabled_client_hints, frame_tree_node_);
}
url::Origin partition_origin = origin;
bool is_top_level = frame_tree_node()->GetParentOrOuterDocument() == nullptr;
if (!is_top_level) {
partition_origin = frame_tree_node()
->GetParentOrOuterDocument()
->GetOutermostMainFrame()
->GetLastCommittedOrigin();
}
PersistOriginTrialsFromHeaders(origin, partition_origin, response(),
browser_context);
if (auto reduce_accept_lang_utils =
ReduceAcceptLanguageUtils::Create(browser_context);
reduce_accept_lang_utils && !devtools_accept_language_override_) {
if (commit_params_->reduced_accept_language.empty()) {
commit_params_->reduced_accept_language =
reduce_accept_lang_utils.value()
.LookupReducedAcceptLanguage(GetOriginToCommit().value(),
frame_tree_node_)
.value_or("");
}
reduce_accept_lang_utils.value().RemoveOriginTrialReducedAcceptLanguage(
commit_params_->reduced_accept_language, GetOriginToCommit().value(),
response(), frame_tree_node_);
}
commit_params_->should_have_sticky_user_activation =
!frame_tree_node_->IsMainFrame() &&
old_frame_host->HasStickyUserActivation() &&
net::SchemefulSite(old_frame_host->GetLastCommittedOrigin()) ==
net::SchemefulSite(origin_to_commit);
commit_params_->document_ukm_source_id = ukm::UkmRecorder::GetNewSourceID();
blink::mojom::ServiceWorkerContainerInfoForClientPtr
service_worker_container_info;
if (service_worker_handle_) {
DCHECK(coep_reporter());
mojo::PendingRemote<network::mojom::CrossOriginEmbedderPolicyReporter>
reporter_remote;
coep_reporter()->Clone(reporter_remote.InitWithNewPipeAndPassReceiver());
service_worker_handle_->OnBeginNavigationCommit(
GetRenderFrameHost()->GetGlobalId(),
policy_container_builder_->FinalPolicies(), std::move(reporter_remote),
&service_worker_container_info, commit_params_->document_ukm_source_id);
}
using WebSandboxFlags = network::mojom::WebSandboxFlags;
const bool embedder_allows_top_navigation_explicitly =
((commit_params_->frame_policy.sandbox_flags != WebSandboxFlags::kNone) &&
(commit_params_->frame_policy.sandbox_flags &
WebSandboxFlags::kTopNavigation) == WebSandboxFlags::kNone);
const bool is_same_origin_to_top =
GetOriginToCommit() ==
GetRenderFrameHost()->GetMainFrame()->GetLastCommittedOrigin();
if (is_same_origin_to_top) {
policy_container_builder_->SetAllowTopNavigationWithoutUserGesture(true);
} else if (!IsInMainFrame() && !embedder_allows_top_navigation_explicitly) {
policy_container_builder_->SetAllowTopNavigationWithoutUserGesture(false);
}
if (!IsSameDocument()) {
commit_params_->navigation_api_history_entry_arrays =
GetNavigationController()->GetNavigationApiHistoryEntryVectors(
frame_tree_node_, this);
PopulateDocumentTokenForCrossDocumentNavigation();
}
if (early_hints_manager_) {
commit_params_->early_hints_preloaded_resources =
early_hints_manager_->TakePreloadedResourceURLs();
}
if (response_head_) {
commit_params_->navigation_delivery_type =
response_head_->navigation_delivery_type;
}
commit_params_->modified_runtime_features =
runtime_feature_state_context_.GetFeatureOverrides();
auto common_params = common_params_->Clone();
auto commit_params = commit_params_.Clone();
auto response_head = response_head_.Clone();
if (subresource_loader_params_ &&
!subresource_loader_params_->prefetched_signed_exchanges.empty()) {
commit_params->prefetched_signed_exchanges =
std::move(subresource_loader_params_->prefetched_signed_exchanges);
}
#ifdef OHOS_ARKWEB_ADBLOCK
LOG(DEBUG) << "[Adblock] CommitNavigation url : ***";
bool adblock_enabled = frame_tree_node_->is_adblock_enabled();
frame_tree_node_->set_adblock_enabled_last_committed(adblock_enabled);
if (frame_tree_node_->IsMainFrame()) {
commit_params->site_adblock_enabled = adblock_enabled;
}
#endif
GetRenderFrameHost()->CommitNavigation(
this, std::move(common_params), std::move(commit_params),
std::move(response_head), std::move(response_body_),
std::move(url_loader_client_endpoints_),
std::move(subresource_loader_params_), std::move(subresource_overrides_),
std::move(service_worker_container_info), document_token_,
devtools_navigation_token_
#if BUILDFLAG(IS_OHOS_PRPP)
,
addr_web_handle_
#endif
);
UpdateNavigationHandleTimingsOnCommitSent();
RenderProcessHostImpl::NotifySpareManagerAboutRecentlyUsedBrowserContext(
GetRenderFrameHost()->GetSiteInstance()->GetBrowserContext());
SendDeferredConsoleMessages();
}
void NavigationRequest::CommitPageActivation() {
DCHECK_NE(IsServedFromBackForwardCache(), IsPrerenderedPageActivation());
NavigationControllerImpl* controller = GetNavigationController();
if (IsServedFromBackForwardCache()) {
std::unique_ptr<BackForwardCacheImpl::Entry> activated_entry;
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;
activated_entry = controller->GetBackForwardCache().RestoreEntry(
nav_entry_id_, std::move(page_restore_params));
DCHECK(activated_entry || restarting_back_forward_cached_navigation_);
if (!activated_entry)
return;
activated_entry->render_frame_host()->ForEachRenderFrameHostWithAction(
[this, &activated_entry](RenderFrameHostImpl* rfh) {
auto entry_arrays =
rfh->frame_tree()
->controller()
.GetNavigationApiHistoryEntryVectors(
rfh->frame_tree_node(),
activated_entry->render_frame_host() == rfh ? this
: nullptr);
rfh->GetAssociatedLocalFrame()
->SetNavigationApiHistoryEntriesForRestore(
std::move(entry_arrays));
return RenderFrameHost::FrameIterationAction::kContinue;
});
base::WeakPtr<NavigationRequest> weak_self(weak_factory_.GetWeakPtr());
ReadyToCommitNavigation(false );
if (!weak_self)
return;
activated_entry->SetViewTransitionState(
std::exchange(commit_params_->view_transition_state, {}));
DCHECK(activated_entry);
frame_tree_node_->render_manager()->RestorePage(
activated_entry->TakeStoredPage());
} else {
PrerenderTriggerType trigger_type =
GetPrerenderHostRegistry().GetPrerenderTriggerType(
prerender_frame_tree_node_id());
const std::string embedder_histogram_suffix =
GetPrerenderHostRegistry().GetPrerenderEmbedderHistogramSuffix(
prerender_frame_tree_node_id());
std::unique_ptr<StoredPage> stored_page =
GetPrerenderHostRegistry().ActivateReservedHost(
prerender_frame_tree_node_id_.value(), *this);
if (!stored_page) {
NOTIMPLEMENTED()
<< "The prerendered page was cancelled during activation";
return;
}
RenderFrameHostImpl* rfh = stored_page->render_frame_host();
set_prerender_trigger_type(trigger_type);
set_prerender_embedder_histogram_suffix(embedder_histogram_suffix);
common_params_->url = rfh->GetLastCommittedURL();
redirect_chain_.clear();
redirect_chain_.push_back(rfh->GetLastCommittedURL());
base::WeakPtr<NavigationRequest> weak_self(weak_factory_.GetWeakPtr());
ReadyToCommitNavigation(false );
if (!weak_self)
return;
DCHECK(stored_page);
stored_page->SetViewTransitionState(
std::exchange(commit_params_->view_transition_state, {}));
frame_tree_node_->render_manager()->ActivatePrerender(
std::move(stored_page));
}
GetRenderFrameHost()->DidCommitPageActivation(
this, IsPrerenderedPageActivation()
? MakeDidCommitProvisionalLoadParamsForPrerenderActivation()
: MakeDidCommitProvisionalLoadParamsForBFCacheRestore());
}
void NavigationRequest::SetExpectedProcess(
RenderProcessHost* expected_process) {
if (expected_process &&
expected_process->GetID() == expected_render_process_host_id_) {
return;
}
ResetExpectedProcess();
if (expected_process == nullptr)
return;
expected_render_process_host_id_ = expected_process->GetID();
expected_process->AddObserver(this);
RenderProcessHostImpl::AddExpectedNavigationToSite(
frame_tree_node()->navigator().controller().GetBrowserContext(),
expected_process, site_info_);
}
void NavigationRequest::ResetExpectedProcess() {
if (expected_render_process_host_id_ == ChildProcessHost::kInvalidUniqueID) {
return;
}
RenderProcessHost* process =
RenderProcessHost::FromID(expected_render_process_host_id_);
if (process) {
RenderProcessHostImpl::RemoveExpectedNavigationToSite(
frame_tree_node()->navigator().controller().GetBrowserContext(),
process, site_info_);
process->RemoveObserver(this);
}
expected_render_process_host_id_ = ChildProcessHost::kInvalidUniqueID;
}
void NavigationRequest::RenderProcessHostDestroyed(RenderProcessHost* host) {
DCHECK_EQ(host->GetID(), expected_render_process_host_id_);
ResetExpectedProcess();
}
void NavigationRequest::RenderProcessExited(
RenderProcessHost* host,
const ChildProcessTerminationInfo& info) {}
void NavigationRequest::UpdateNavigationHandleTimingsOnResponseReceived(
bool is_first_response) {
base::TimeTicks loader_callback_time = base::TimeTicks::Now();
if (is_first_response) {
DCHECK(navigation_handle_timing_.first_request_start_time.is_null());
DCHECK(navigation_handle_timing_.first_response_start_time.is_null());
DCHECK(navigation_handle_timing_.first_loader_callback_time.is_null());
navigation_handle_timing_.first_request_start_time =
response_head_->load_timing.send_start;
navigation_handle_timing_.first_response_start_time =
response_head_->load_timing.receive_headers_start;
navigation_handle_timing_.first_loader_callback_time = loader_callback_time;
}
navigation_handle_timing_.final_request_start_time =
response_head_->load_timing.send_start;
navigation_handle_timing_.final_response_start_time =
response_head_->load_timing.receive_headers_start;
navigation_handle_timing_.final_non_informational_response_start_time =
response_head_->load_timing.receive_non_informational_headers_start;
navigation_handle_timing_.final_loader_callback_time = loader_callback_time;
if (is_first_response) {
DCHECK(
navigation_handle_timing_.early_hints_for_first_request_time.is_null());
navigation_handle_timing_.early_hints_for_first_request_time =
response_head_->load_timing.first_early_hints_time;
}
navigation_handle_timing_.early_hints_for_final_request_time =
response_head_->load_timing.first_early_hints_time;
DCHECK(navigation_handle_timing_.navigation_commit_sent_time.is_null());
}
void NavigationRequest::UpdateNavigationHandleTimingsOnCommitSent() {
DCHECK(navigation_handle_timing_.navigation_commit_sent_time.is_null());
navigation_handle_timing_.navigation_commit_sent_time =
base::TimeTicks::Now();
}
void NavigationRequest::UpdateSiteInfo(
RenderProcessHost* post_redirect_process) {
int post_redirect_process_id = post_redirect_process
? post_redirect_process->GetID()
: ChildProcessHost::kInvalidUniqueID;
SiteInfo new_site_info = GetSiteInfoForCommonParamsURL();
if (new_site_info == site_info_ &&
post_redirect_process_id == expected_render_process_host_id_) {
return;
}
ResetExpectedProcess();
site_info_ = new_site_info;
SetExpectedProcess(post_redirect_process);
}
bool NavigationRequest::IsAllowedByCSPDirective(
const std::vector<network::mojom::ContentSecurityPolicyPtr>& policies,
network::CSPContext* context,
network::mojom::CSPDirectiveName directive,
bool has_followed_redirect,
bool url_upgraded_after_redirect,
bool is_response_check,
bool is_opaque_fenced_frame,
network::CSPContext::CheckCSPDisposition disposition) {
GURL url;
if (url_upgraded_after_redirect &&
disposition ==
network::CSPContext::CheckCSPDisposition::CHECK_REPORT_ONLY_CSP &&
common_params_->url.SchemeIs(url::kHttpsScheme)) {
GURL::Replacements replacements;
replacements.SetSchemeStr(url::kHttpScheme);
url = common_params_->url.ReplaceComponents(replacements);
} else if (common_params_->url.SchemeIs(url::kUuidInPackageScheme) &&
begin_params_->web_bundle_token.has_value()) {
url = begin_params_->web_bundle_token->bundle_url;
} else {
url = common_params_->url;
}
return context->IsAllowedByCsp(
policies, directive, url, commit_params_->original_url,
has_followed_redirect, is_response_check, common_params_->source_location,
disposition, begin_params_->is_form_submission, is_opaque_fenced_frame);
}
net::Error NavigationRequest::CheckCSPDirectives(
RenderFrameHostCSPContext parent_context,
const PolicyContainerPolicies* parent_policies,
RenderFrameHostCSPContext initiator_context,
const PolicyContainerPolicies* initiator_policies,
bool has_followed_redirect,
bool url_upgraded_after_redirect,
bool is_response_check,
network::CSPContext::CheckCSPDisposition disposition) {
net::Error error = net::OK;
if (initiator_policies) {
if (begin_params_->is_form_submission && !is_response_check &&
!IsAllowedByCSPDirective(
initiator_policies->content_security_policies, &initiator_context,
network::mojom::CSPDirectiveName::FormAction, has_followed_redirect,
url_upgraded_after_redirect, is_response_check,
false, disposition)) {
error = net::ERR_ABORTED;
}
if (base::FeatureList::IsEnabled(
features::kExperimentalContentSecurityPolicyFeatures)) {
if (!IsAllowedByCSPDirective(
initiator_policies->content_security_policies, &initiator_context,
network::mojom::CSPDirectiveName::NavigateTo,
has_followed_redirect, url_upgraded_after_redirect,
is_response_check, false,
disposition)) {
error = net::ERR_ABORTED;
}
}
}
if (parent_policies) {
if (!IsAllowedByCSPDirective(
parent_policies->content_security_policies, &parent_context,
frame_tree_node_->IsFencedFrameRoot()
? network::mojom::CSPDirectiveName::FencedFrameSrc
: network::mojom::CSPDirectiveName::FrameSrc,
has_followed_redirect, url_upgraded_after_redirect,
is_response_check,
is_target_fenced_frame_root_originating_from_opaque_url_,
disposition)) {
error = net::ERR_BLOCKED_BY_CSP;
}
}
return error;
}
net::Error NavigationRequest::CheckContentSecurityPolicy(
bool has_followed_redirect,
bool url_upgraded_after_redirect,
bool is_response_check) {
DCHECK(policy_container_builder_.has_value());
if (common_params_->url.SchemeIs(url::kAboutScheme))
return net::OK;
if (IsSameDocument())
return net::OK;
if (common_params_->should_check_main_world_csp ==
network::mojom::CSPDisposition::DO_NOT_CHECK) {
return net::OK;
}
RenderFrameHostImpl* parent = frame_tree_node()->parent();
const PolicyContainerPolicies* parent_policies =
policy_container_builder_->ParentPolicies();
DCHECK(!parent == !parent_policies);
bool set_parent_for_nested_frame_tree =
!parent &&
(frame_tree_node()->frame_tree().IsPortal() ||
frame_tree_node()->IsFencedFrameRoot()) &&
frame_tree_node()->render_manager()->GetOuterDelegateNode();
if (set_parent_for_nested_frame_tree) {
parent = frame_tree_node()
->render_manager()
->GetOuterDelegateNode()
->current_frame_host()
->GetParent();
parent_policies = &parent->policy_container_host()->policies();
}
const PolicyContainerPolicies* initiator_policies =
policy_container_builder_->InitiatorPolicies();
RenderFrameHostCSPContext parent_context(parent);
RenderFrameHostCSPContext initiator_context(
GetInitiatorDocumentRenderFrameHost());
net::Error report_only_csp_status = CheckCSPDirectives(
parent_context, parent_policies, initiator_context, initiator_policies,
has_followed_redirect, url_upgraded_after_redirect, is_response_check,
network::CSPContext::CHECK_REPORT_ONLY_CSP);
if (!has_followed_redirect && !frame_tree_node()->IsMainFrame()) {
DCHECK(parent_policies);
if (parent_policies && network::ShouldUpgradeInsecureRequest(
parent_policies->content_security_policies)) {
upgrade_if_insecure_ = true;
network::UpgradeInsecureRequest(&common_params_->url);
common_params_->referrer = Referrer::SanitizeForRequest(
common_params_->url, *common_params_->referrer);
commit_params_->original_url = common_params_->url;
}
}
net::Error enforced_csp_status = CheckCSPDirectives(
parent_context, parent_policies, initiator_context, initiator_policies,
has_followed_redirect, url_upgraded_after_redirect, is_response_check,
network::CSPContext::CHECK_ENFORCED_CSP);
if (enforced_csp_status != net::OK)
return enforced_csp_status;
return report_only_csp_status;
}
NavigationRequest::CredentialedSubresourceCheckResult
NavigationRequest::CheckCredentialedSubresource() const {
if (frame_tree_node_->IsOutermostMainFrame())
return CredentialedSubresourceCheckResult::ALLOW_REQUEST;
if (!common_params_->url.has_username() &&
!common_params_->url.has_password())
return CredentialedSubresourceCheckResult::ALLOW_REQUEST;
RenderFrameHostImpl* parent = frame_tree_node_->GetParentOrOuterDocument();
DCHECK(parent);
const GURL& parent_url = parent->GetLastCommittedURL();
if (url::IsSameOriginWith(parent_url, common_params_->url) &&
parent_url.username() == common_params_->url.username() &&
parent_url.password() == common_params_->url.password()) {
return CredentialedSubresourceCheckResult::ALLOW_REQUEST;
}
#ifdef OHOS_DEVTOOLS
const char* console_message = "Subresource requests whose URLs contain embedded credentials (e.g. "
"`https://user:pass@host/`) are blocked.";
#else
const char* console_message = "Subresource requests whose URLs contain embedded credentials (e.g. "
"`https://user:pass@host/`) are blocked. See "
"https://www.chromestatus.com/feature/5669008342777856 for more "
"details.";
#endif
parent->AddMessageToConsole(blink::mojom::ConsoleMessageLevel::kWarning,
console_message);
return CredentialedSubresourceCheckResult::BLOCK_REQUEST;
}
NavigationRequest::AboutSrcDocCheckResult NavigationRequest::CheckAboutSrcDoc()
const {
if (!common_params_->url.IsAboutSrcdoc())
return AboutSrcDocCheckResult::ALLOW_REQUEST;
if (frame_tree_node_->IsMainFrame())
return AboutSrcDocCheckResult::BLOCK_REQUEST;
return AboutSrcDocCheckResult::ALLOW_REQUEST;
}
void NavigationRequest::SetupCSPEmbeddedEnforcement() {
if (IsInMainFrame())
return;
if (IsForMhtmlSubframe())
return;
network::mojom::ContentSecurityPolicyPtr frame_csp_attribute =
frame_tree_node()->csp_attribute()
? frame_tree_node()->csp_attribute()->Clone()
: nullptr;
if (frame_csp_attribute) {
const GURL& url = GetURL();
frame_csp_attribute->self_origin = network::mojom::CSPSource::New(
url.scheme(), url.host(), url.EffectiveIntPort(), "", false, false);
}
const network::mojom::ContentSecurityPolicy* parent_required_csp =
frame_tree_node()->parent()->required_csp();
std::vector<network::mojom::ContentSecurityPolicyPtr> frame_csp;
frame_csp.push_back(std::move(frame_csp_attribute));
std::string error_message;
if (network::IsValidRequiredCSPAttr(frame_csp, parent_required_csp,
error_message)) {
SetRequiredCSP(std::move(frame_csp[0]));
return;
}
if (frame_csp[0]) {
GetParentFrame()->AddMessageToConsole(
blink::mojom::ConsoleMessageLevel::kError,
base::StringPrintf("The frame 'csp' attribute ('%s') is invalid and "
"will be discarded: %s",
frame_csp[0]->header->header_value.c_str(),
error_message.c_str()));
}
if (parent_required_csp) {
SetRequiredCSP(parent_required_csp->Clone());
}
}
NavigationRequest::CSPEmbeddedEnforcementResult
NavigationRequest::CheckCSPEmbeddedEnforcement() {
if (IsInMainFrame())
return CSPEmbeddedEnforcementResult::ALLOW_RESPONSE;
if (IsSameDocument())
return CSPEmbeddedEnforcementResult::ALLOW_RESPONSE;
if (!required_csp_)
return CSPEmbeddedEnforcementResult::ALLOW_RESPONSE;
const network::mojom::AllowCSPFromHeaderValue* allow_csp_from =
response() ? response()->parsed_headers->allow_csp_from.get() : nullptr;
if (network::AllowsBlanketEnforcementOfRequiredCSP(
GetParentFrame()->GetLastCommittedOrigin(), GetURL(), allow_csp_from,
required_csp_)) {
policy_container_builder_->AddContentSecurityPolicy(required_csp_->Clone());
return CSPEmbeddedEnforcementResult::ALLOW_RESPONSE;
}
if (!response()) {
CHECK(IsForMhtmlSubframe());
return CSPEmbeddedEnforcementResult::ALLOW_RESPONSE;
}
std::string sanitized_blocked_url =
GetRedirectChain().front().DeprecatedGetOriginAsURL().spec();
if (allow_csp_from && allow_csp_from->is_error_message()) {
AddDeferredConsoleMessage(
blink::mojom::ConsoleMessageLevel::kError,
base::StringPrintf("The value of the 'Allow-CSP-From' response header "
"returned by %s is invalid: %s",
sanitized_blocked_url.c_str(),
allow_csp_from->get_error_message().c_str()));
}
if (network::Subsumes(*required_csp_,
response()->parsed_headers->content_security_policy)) {
return CSPEmbeddedEnforcementResult::ALLOW_RESPONSE;
}
AddDeferredConsoleMessage(
blink::mojom::ConsoleMessageLevel::kError,
base::StringPrintf(
"Refused to display '%s' in a frame. The embedder requires it to "
"enforce the following Content Security Policy: '%s'. However, the "
"frame neither accepts that policy using the Allow-CSP-From header "
"nor delivers a Content Security Policy which is at least as strong "
"as that one.",
sanitized_blocked_url.c_str(),
required_csp_->header->header_value.c_str()));
return CSPEmbeddedEnforcementResult::BLOCK_RESPONSE;
}
void NavigationRequest::UpdateCommitNavigationParamsHistory() {
NavigationController& navigation_controller =
frame_tree_node_->navigator().controller();
commit_params_->current_history_list_offset =
navigation_controller.GetCurrentEntryIndex();
commit_params_->current_history_list_length =
navigation_controller.GetEntryCount();
}
void NavigationRequest::RendererRequestedNavigationCancellationForTesting() {
OnNavigationClientDisconnected(0, "");
}
void NavigationRequest::OnNavigationClientDisconnected(
uint32_t reason,
const std::string& description) {
if (reason == mojom::NavigationClient::kResetForSwap) {
return;
}
if (!IsWaitingToCommit()) {
frame_tree_node_->navigator().CancelNavigation(
frame_tree_node_, NavigationDiscardReason::kCancelled);
} else if (GetRenderFrameHost() ==
frame_tree_node_->render_manager()->current_frame_host() ||
!GetRenderFrameHost()->IsRenderFrameLive()) {
FrameTreeNode* frame_tree_node = frame_tree_node_;
GetRenderFrameHost()->NavigationRequestCancelled(this);
frame_tree_node->render_manager()->DiscardSpeculativeRFHIfUnused(
NavigationDiscardReason::kCancelled);
}
}
void NavigationRequest::HandleInterfaceDisconnection(
mojo::AssociatedRemote<mojom::NavigationClient>& navigation_client) {
navigation_client.set_disconnect_with_reason_handler(
base::BindOnce(&NavigationRequest::OnNavigationClientDisconnected,
base::Unretained(this)));
}
void NavigationRequest::IgnoreInterfaceDisconnection() {
return request_navigation_client_.set_disconnect_handler(base::DoNothing());
}
void NavigationRequest::IgnoreCommitInterfaceDisconnection() {
return commit_navigation_client_.set_disconnect_handler(base::DoNothing());
}
bool NavigationRequest::IsSameDocument() const {
return NavigationTypeUtils::IsSameDocument(common_params_->navigation_type);
}
void NavigationRequest::RecordDownloadUseCountersPrePolicyCheck() {
RenderFrameHost* rfh = frame_tree_node_->current_frame_host();
GetContentClient()->browser()->LogWebFeatureForCurrentPage(
rfh, blink::mojom::WebFeature::kDownloadPrePolicyCheck);
if (download_policy().IsType(
blink::NavigationDownloadType::kOpenerCrossOrigin)) {
rfh->AddMessageToConsole(
blink::mojom::ConsoleMessageLevel::kError,
base::StringPrintf(
"Navigating a cross-origin opener to a download (%s) is "
"deprecated, see "
"https://www.chromestatus.com/feature/5742188281462784.",
common_params_->url.spec().c_str()));
GetContentClient()->browser()->LogWebFeatureForCurrentPage(
rfh, blink::mojom::WebFeature::kOpenerNavigationDownloadCrossOrigin);
}
if (download_policy().IsType(blink::NavigationDownloadType::kSandbox)) {
GetContentClient()->browser()->LogWebFeatureForCurrentPage(
rfh, blink::mojom::WebFeature::kDownloadInSandbox);
}
if (download_policy().IsType(blink::NavigationDownloadType::kNoGesture)) {
GetContentClient()->browser()->LogWebFeatureForCurrentPage(
rfh, blink::mojom::WebFeature::kDownloadWithoutUserGesture);
}
if (download_policy().IsType(
blink::NavigationDownloadType::kAdFrameNoGesture)) {
GetContentClient()->browser()->LogWebFeatureForCurrentPage(
rfh, blink::mojom::WebFeature::kDownloadInAdFrameWithoutUserGesture);
}
if (download_policy().IsType(blink::NavigationDownloadType::kAdFrame)) {
GetContentClient()->browser()->LogWebFeatureForCurrentPage(
rfh, blink::mojom::WebFeature::kDownloadInAdFrame);
}
}
void NavigationRequest::RecordDownloadUseCountersPostPolicyCheck() {
DCHECK(is_download_);
RenderFrameHost* rfh = frame_tree_node_->current_frame_host();
GetContentClient()->browser()->LogWebFeatureForCurrentPage(
rfh, blink::mojom::WebFeature::kDownloadPostPolicyCheck);
}
void NavigationRequest::OnNavigationEventProcessed(
NavigationThrottleRunner::Event event,
NavigationThrottle::ThrottleCheckResult result) {
DCHECK_NE(NavigationThrottle::DEFER, result.action());
switch (event) {
case NavigationThrottleRunner::Event::WillStartRequest:
OnWillStartRequestProcessed(result);
return;
case NavigationThrottleRunner::Event::WillRedirectRequest:
OnWillRedirectRequestProcessed(result);
return;
case NavigationThrottleRunner::Event::WillFailRequest:
OnWillFailRequestProcessed(result);
return;
case NavigationThrottleRunner::Event::WillProcessResponse:
OnWillProcessResponseProcessed(result);
return;
case NavigationThrottleRunner::Event::WillCommitWithoutUrlLoader:
OnWillCommitWithoutUrlLoaderProcessed(result);
return;
default:
NOTREACHED();
}
NOTREACHED();
}
void NavigationRequest::OnWillStartRequestProcessed(
NavigationThrottle::ThrottleCheckResult result) {
DCHECK_EQ(WILL_START_REQUEST, state_);
DCHECK_NE(NavigationThrottle::BLOCK_RESPONSE, result.action());
DCHECK(processing_navigation_throttle_);
processing_navigation_throttle_ = false;
if (result.action() != NavigationThrottle::PROCEED)
SetState(CANCELING);
if (complete_callback_for_testing_ &&
std::move(complete_callback_for_testing_).Run(result)) {
return;
}
OnStartChecksComplete(result);
}
void NavigationRequest::OnWillRedirectRequestProcessed(
NavigationThrottle::ThrottleCheckResult result) {
DCHECK_EQ(WILL_REDIRECT_REQUEST, state_);
DCHECK_NE(NavigationThrottle::BLOCK_RESPONSE, result.action());
DCHECK(processing_navigation_throttle_);
processing_navigation_throttle_ = false;
if (result.action() == NavigationThrottle::PROCEED) {
if (GetDelegate()) {
#if DCHECK_IS_ON()
DCHECK(is_safe_to_delete_);
base::AutoReset<bool> resetter(&is_safe_to_delete_, false);
#endif
#ifdef OHOS_NWEB_EX
base::AutoReset<bool> resetter2(&ua_change_requires_reload_, false);
#endif
GetDelegate()->DidRedirectNavigation(this);
}
} else {
SetState(CANCELING);
}
if (complete_callback_for_testing_ &&
std::move(complete_callback_for_testing_).Run(result)) {
return;
}
OnRedirectChecksComplete(result);
}
void NavigationRequest::OnWillFailRequestProcessed(
NavigationThrottle::ThrottleCheckResult result) {
DCHECK_EQ(WILL_FAIL_REQUEST, state_);
DCHECK_NE(NavigationThrottle::BLOCK_RESPONSE, result.action());
DCHECK(processing_navigation_throttle_);
processing_navigation_throttle_ = false;
if (result.action() == NavigationThrottle::PROCEED) {
result = NavigationThrottle::ThrottleCheckResult(
NavigationThrottle::PROCEED, net_error_);
} else {
SetState(CANCELING);
}
if (complete_callback_for_testing_ &&
std::move(complete_callback_for_testing_).Run(result)) {
return;
}
OnFailureChecksComplete(result);
}
void NavigationRequest::OnWillProcessResponseProcessed(
NavigationThrottle::ThrottleCheckResult result) {
DCHECK_EQ(WILL_PROCESS_RESPONSE, state_);
DCHECK_NE(NavigationThrottle::BLOCK_REQUEST, result.action());
DCHECK_NE(NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE, result.action());
DCHECK(processing_navigation_throttle_);
processing_navigation_throttle_ = false;
if (result.action() != NavigationThrottle::PROCEED) {
SetState(CANCELING);
}
if (complete_callback_for_testing_ &&
std::move(complete_callback_for_testing_).Run(result)) {
return;
}
OnWillProcessResponseChecksComplete(result);
}
void NavigationRequest::OnWillCommitWithoutUrlLoaderProcessed(
NavigationThrottle::ThrottleCheckResult result) {
DCHECK_EQ(WILL_COMMIT_WITHOUT_URL_LOADER, state_);
DCHECK(result.action() == NavigationThrottle::CANCEL_AND_IGNORE ||
result.action() == NavigationThrottle::PROCEED);
DCHECK(processing_navigation_throttle_);
processing_navigation_throttle_ = false;
if (complete_callback_for_testing_ &&
std::move(complete_callback_for_testing_).Run(result)) {
return;
}
OnWillCommitWithoutUrlLoaderChecksComplete(result);
}
NavigatorDelegate* NavigationRequest::GetDelegate() const {
return frame_tree_node()->navigator().GetDelegate();
}
void NavigationRequest::Resume(NavigationThrottle* resuming_throttle) {
DCHECK(resuming_throttle);
EnterChildTraceEvent("Resume", this);
throttle_runner_->ResumeProcessingNavigationEvent(resuming_throttle);
}
void NavigationRequest::CancelDeferredNavigation(
NavigationThrottle* cancelling_throttle,
NavigationThrottle::ThrottleCheckResult result) {
DCHECK(cancelling_throttle);
DCHECK_EQ(cancelling_throttle, throttle_runner_->GetDeferringThrottle());
CancelDeferredNavigationInternal(result);
}
void NavigationRequest::RegisterThrottleForTesting(
std::unique_ptr<NavigationThrottle> navigation_throttle) {
DCHECK(!IsPageActivation())
<< "Attempted to register a NavigationThrottle for an activating "
"navigation which will not work.";
throttle_runner_->AddThrottle(std::move(navigation_throttle));
}
bool NavigationRequest::IsDeferredForTesting() {
return throttle_runner_->GetDeferringThrottle() != nullptr;
}
bool NavigationRequest::IsMhtmlOrSubframe() {
DCHECK(state_ >= WILL_PROCESS_RESPONSE ||
state_ == WILL_START_REQUEST && !NeedsUrlLoader());
return is_mhtml_or_subframe_;
}
bool NavigationRequest::IsForMhtmlSubframe() const {
return frame_tree_node_->parent() && frame_tree_node_->frame_tree()
.root()
->current_frame_host()
->is_mhtml_document();
}
void NavigationRequest::CancelDeferredNavigationInternal(
NavigationThrottle::ThrottleCheckResult result) {
DCHECK(processing_navigation_throttle_);
DCHECK(result.action() == NavigationThrottle::CANCEL_AND_IGNORE ||
result.action() == NavigationThrottle::CANCEL ||
result.action() == NavigationThrottle::BLOCK_RESPONSE ||
result.action() == NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE);
DCHECK(result.action() != NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE ||
state_ == WILL_START_REQUEST || state_ == WILL_REDIRECT_REQUEST);
EnterChildTraceEvent("CancelDeferredNavigation", this);
NavigationState old_state = state_;
SetState(CANCELING);
if (complete_callback_for_testing_ &&
std::move(complete_callback_for_testing_).Run(result)) {
return;
}
switch (old_state) {
case WILL_START_REQUEST:
OnStartChecksComplete(result);
return;
case WILL_REDIRECT_REQUEST:
OnRedirectChecksComplete(result);
return;
case WILL_FAIL_REQUEST:
OnFailureChecksComplete(result);
return;
case WILL_PROCESS_RESPONSE:
OnWillProcessResponseChecksComplete(result);
return;
case WILL_COMMIT_WITHOUT_URL_LOADER:
OnWillCommitWithoutUrlLoaderChecksComplete(result);
return;
default:
NOTREACHED();
}
}
void NavigationRequest::WillStartRequest() {
EnterChildTraceEvent("WillStartRequest", this);
DCHECK_EQ(state_, WILL_START_REQUEST);
will_start_request_time_ = base::TimeTicks::Now();
if (IsSelfReferentialURL()) {
SetState(CANCELING);
DVLOG(1) << "Cancelling self-referential request for " << GetURL();
if (complete_callback_for_testing_ &&
std::move(complete_callback_for_testing_)
.Run(NavigationThrottle::CANCEL)) {
return;
}
OnWillProcessResponseChecksComplete(NavigationThrottle::CANCEL);
return;
}
if (!IsPageActivation())
throttle_runner_->RegisterNavigationThrottles();
if (!navigation_ui_data_) {
navigation_ui_data_ = GetDelegate()->GetNavigationUIData(this);
}
processing_navigation_throttle_ = true;
throttle_runner_->ProcessNavigationEvent(
NavigationThrottleRunner::Event::WillStartRequest);
}
void NavigationRequest::WillRedirectRequest(
const GURL& new_referrer_url,
RenderProcessHost* post_redirect_process) {
EnterChildTraceEvent("WillRedirectRequest", this, "url",
common_params_->url.possibly_invalid_spec());
UpdateStateFollowingRedirect(new_referrer_url);
UpdateSiteInfo(post_redirect_process);
if (IsSelfReferentialURL()) {
SetState(CANCELING);
if (complete_callback_for_testing_ &&
std::move(complete_callback_for_testing_)
.Run(NavigationThrottle::CANCEL)) {
return;
}
OnWillProcessResponseChecksComplete(NavigationThrottle::CANCEL);
return;
}
throttle_runner_->ProcessNavigationEvent(
NavigationThrottleRunner::Event::WillRedirectRequest);
}
void NavigationRequest::WillFailRequest() {
EnterChildTraceEvent("WillFailRequest", this);
SetState(WILL_FAIL_REQUEST);
processing_navigation_throttle_ = true;
throttle_runner_->ProcessNavigationEvent(
NavigationThrottleRunner::Event::WillFailRequest);
}
void NavigationRequest::WillProcessResponse() {
EnterChildTraceEvent("WillProcessResponse", this);
DCHECK_EQ(state_, WILL_PROCESS_RESPONSE);
processing_navigation_throttle_ = true;
throttle_runner_->ProcessNavigationEvent(
NavigationThrottleRunner::Event::WillProcessResponse);
}
void NavigationRequest::WillCommitWithoutUrlLoader() {
EnterChildTraceEvent("WillCommitWithoutUrlLoader", this);
throttle_runner_->RegisterNavigationThrottlesForCommitWithoutUrlLoader();
SetState(WILL_COMMIT_WITHOUT_URL_LOADER);
processing_navigation_throttle_ = true;
throttle_runner_->ProcessNavigationEvent(
NavigationThrottleRunner::Event::WillCommitWithoutUrlLoader);
}
bool NavigationRequest::IsSelfReferentialURL() {
if (common_params_->url.SchemeIs(url::kAboutScheme))
return false;
if (browser_initiated())
return false;
if (common_params_->method == "POST")
return false;
bool found_self_reference = false;
for (RenderFrameHost* rfh = frame_tree_node()->parent(); rfh;
rfh = rfh->GetParent()) {
if (rfh->GetLastCommittedURL().EqualsIgnoringRef(common_params_->url)) {
if (found_self_reference)
return true;
found_self_reference = true;
}
}
return false;
}
void NavigationRequest::DidCommitNavigation(
const mojom::DidCommitProvisionalLoadParams& params,
bool navigation_entry_committed,
bool did_replace_entry,
const GURL& previous_main_frame_url) {
common_params_->url = params.url;
did_replace_entry_ = did_replace_entry;
should_update_history_ = params.should_update_history;
if ((should_update_history_ && IsSameDocument() && !HasUserGesture() &&
params.url == previous_main_frame_url) ||
!GetRenderFrameHost()->GetPage().IsPrimary() ||
frame_tree_node()->frame_tree().IsPortal()) {
should_update_history_ = false;
}
previous_main_frame_url_ = previous_main_frame_url;
if (DidEncounterError()) {
EnterChildTraceEvent("DidCommitNavigation: error page", this);
SetState(DID_COMMIT_ERROR_PAGE);
} else {
EnterChildTraceEvent("DidCommitNavigation", this);
SetState(DID_COMMIT);
}
navigation_or_document_handle_->OnNavigationCommitted(*this);
StopCommitTimeout();
bool should_clear_browsing_instance_name =
browsing_context_group_swap().ShouldClearWindowName() ||
(commit_params().is_cross_site_cross_browsing_context_group &&
base::FeatureList::IsEnabled(
features::kClearCrossSiteCrossBrowsingContextGroupWindowName));
if (should_clear_browsing_instance_name) {
std::string name, unique_name;
if (features::GetBrowsingContextMode() ==
features::BrowsingContextStateImplementationType::
kLegacyOneToOneWithFrameTreeNode) {
DCHECK(frame_tree_node_->unique_name().empty());
GetRenderFrameHost()->browsing_context_state()->SetFrameName(name,
unique_name);
}
}
if (!IsSameDocument() && state_ != DID_COMMIT_ERROR_PAGE) {
ui::PageTransition transition =
ui::PageTransitionFromInt(common_params_->transition);
absl::optional<bool> is_background =
GetRenderFrameHost()->GetProcess()->IsProcessBackgrounded();
RecordStartToCommitMetrics(
common_params_->navigation_start, transition, ready_to_commit_time_,
is_background, is_same_process_, frame_tree_node_->IsMainFrame());
}
DCHECK(!frame_tree_node_->IsMainFrame() || navigation_entry_committed)
<< "Only subframe navigations can get here without changing the "
<< "NavigationEntry";
subframe_entry_committed_ = navigation_entry_committed;
if (state_ != DID_COMMIT_ERROR_PAGE &&
(!frame_tree_node()->IsMainFrame() ||
frame_tree_node()->IsFencedFrameRoot())) {
DCHECK(!IsSameDocument() || !frame_tree_node()->is_collapsed());
frame_tree_node()->SetCollapsed(false);
}
if (service_worker_handle_) {
service_worker_handle_->OnEndNavigationCommit();
}
if (topics_url_loader_service_bind_context_) {
DCHECK(!IsSameDocument());
topics_url_loader_service_bind_context_->OnDidCommitNavigation(
GetRenderFrameHost()->GetWeakDocumentPtr());
}
UnblockPendingSubframeNavigationRequestsIfNeeded();
}
SiteInfo NavigationRequest::GetSiteInfoForCommonParamsURL() {
UrlInfo url_info = GetUrlInfo();
return SiteInfo::Create(starting_site_instance_->GetIsolationContext(),
url_info);
}
void NavigationRequest::UpdateStateFollowingRedirect(
const GURL& new_referrer_url) {
CHECK(!blink::IsRendererDebugURL(common_params_->url));
runtime_feature_state_context_ = blink::RuntimeFeatureStateContext();
if (!(common_params_->transition & ui::PAGE_TRANSITION_CLIENT_REDIRECT)) {
sanitized_referrer_->url = new_referrer_url;
sanitized_referrer_ =
Referrer::SanitizeForRequest(common_params_->url, *sanitized_referrer_);
}
common_params_->referrer = sanitized_referrer_.Clone();
was_redirected_ = true;
redirect_chain_.push_back(common_params_->url);
SetState(WILL_REDIRECT_REQUEST);
processing_navigation_throttle_ = true;
#if BUILDFLAG(IS_ANDROID)
navigation_handle_proxy_->DidRedirect();
#endif
}
void NavigationRequest::SetNavigationClient(
mojo::PendingAssociatedRemote<mojom::NavigationClient> navigation_client) {
DCHECK(from_begin_navigation_ ||
common_params_->is_history_navigation_in_new_child_frame);
DCHECK(!request_navigation_client_);
if (!navigation_client.is_valid())
return;
request_navigation_client_.reset();
request_navigation_client_.Bind(std::move(navigation_client));
HandleInterfaceDisconnection(request_navigation_client_);
}
bool NavigationRequest::NeedsUrlLoader() {
bool is_mhtml_subframe_loaded_from_achive =
IsForMhtmlSubframe() &&
!common_params_->url.SchemeIs(url::kDataScheme);
return IsURLHandledByNetworkStack(common_params_->url) && !IsSameDocument() &&
!is_mhtml_subframe_loaded_from_achive;
}
void NavigationRequest::UpdateLocalNetworkRequestPolicy() {
DCHECK(!IsSameDocument());
DCHECK(!IsPageActivation());
if (GetSocketAddress().address().IsZero()) {
web_features_to_log_.push_back(
blink::mojom::WebFeature::kPrivateNetworkAccessNullIpAddress);
}
ContentBrowserClient* client = GetContentClient()->browser();
BrowserContext* context =
frame_tree_node_->navigator().controller().GetBrowserContext();
url::Origin origin = GetOriginToCommit().value();
if (client->ShouldAllowInsecureLocalNetworkRequests(context, origin)) {
local_network_request_policy_ =
network::mojom::LocalNetworkRequestPolicy::kAllow;
LOG(INFO) << "NavigationRequest::UpdateLocalNetworkRequestPolicy local_network_request_policy_ "
<< static_cast<int>(local_network_request_policy_);
return;
}
const PolicyContainerPolicies& policies =
policy_container_builder_->FinalPolicies();
if (!policies.is_web_secure_context &&
base::FeatureList::IsEnabled(
features::kBlockInsecurePrivateNetworkRequestsDeprecationTrial) &&
response_head_ && response_head_->headers &&
blink::TrialTokenValidator().RequestEnablesDeprecatedFeature(
common_params_->url, response_head_->headers.get(),
"PrivateNetworkAccessNonSecureContextsAllowed", base::Time::Now())) {
web_features_to_log_.push_back(
blink::mojom::WebFeature::
kPrivateNetworkAccessNonSecureContextsAllowedDeprecationTrial);
local_network_request_policy_ =
network::mojom::LocalNetworkRequestPolicy::kAllow;
LOG(INFO) << "NavigationRequest::UpdateLocalNetworkRequestPolicy local_network_request_policy_ "
<< static_cast<int>(local_network_request_policy_);
return;
}
local_network_request_policy_ = DerivePrivateNetworkRequestPolicy(
policies, PrivateNetworkRequestContext::kSubresource);
LOG(INFO) << "NavigationRequest::UpdateLocalNetworkRequestPolicy local_network_request_policy_ "
<< static_cast<int>(local_network_request_policy_);
}
std::vector<blink::mojom::WebFeature>
NavigationRequest::TakeWebFeaturesToLog() {
std::vector<blink::mojom::WebFeature> result;
result.swap(web_features_to_log_);
return result;
}
void NavigationRequest::ReadyToCommitNavigation(bool is_error) {
EnterChildTraceEvent("ReadyToCommitNavigation", this);
if (!GetRenderFrameHost()->IsRenderFrameLive()) {
OnNavigationClientDisconnected(0, "");
return;
}
frame_tree_node_->TransferNavigationRequestOwnership(GetRenderFrameHost());
if (GetRenderFrameHost()->lifecycle_state() ==
RenderFrameHostImpl::LifecycleStateImpl::kSpeculative) {
DCHECK(!IsSameDocument() && !IsPageActivation());
GetRenderFrameHost()->SetLifecycleState(
RenderFrameHostImpl::LifecycleStateImpl::kPendingCommit);
}
common_params_->source_location = network::mojom::SourceLocation::New();
SetState(READY_TO_COMMIT);
ready_to_commit_time_ = base::TimeTicks::Now();
RestartCommitTimeout();
if (!IsSameDocument()) {
MaybeRegisterOriginForUnpartitionedSessionStorageAccess();
}
if (!IsSameDocument() && !IsPageActivation())
UpdateLocalNetworkRequestPolicy();
RenderFrameHostImpl* previous_render_frame_host =
frame_tree_node_->current_frame_host();
if (!IsSameDocument() && !is_error) {
is_same_process_ = GetRenderFrameHost()->GetProcess()->GetID() ==
previous_render_frame_host->GetProcess()->GetID();
RecordReadyToCommitMetrics(
previous_render_frame_host, GetRenderFrameHost(), *common_params_.get(),
ready_to_commit_time_, origin_agent_cluster_end_result_,
did_receive_early_hints_before_cross_origin_redirect_);
}
same_origin_ = (previous_render_frame_host->GetLastCommittedOrigin() ==
GetOriginToCommit());
SetExpectedProcess(GetRenderFrameHost()->GetProcess());
commit_params_->is_load_data_with_base_url = IsLoadDataWithBaseURL();
browser_side_origin_to_commit_with_debug_info_ =
GetOriginToCommitWithDebugInfo();
if (!IsSameDocument()) {
#if DCHECK_IS_ON()
DCHECK(is_safe_to_delete_);
base::AutoReset<bool> resetter(&is_safe_to_delete_, false);
#endif
GetDelegate()->ReadyToCommitNavigation(this);
}
if (IsInPrimaryMainFrame()) {
NavigationEntry* entry = GetNavigationEntry();
if (entry && entry->IsViewSourceMode()) {
GetRenderFrameHost()->GetAssociatedLocalFrame()->EnableViewSourceMode();
}
}
if (is_embedder_initiated_fenced_frame_navigation_) {
if (fenced_frame_properties_->mapped_url_.has_value()) {
fenced_frame_properties_->UpdateMappedURL(GetURL());
}
}
const auto& computed_fenced_frame_properties = ComputeFencedFrameProperties();
if (computed_fenced_frame_properties.has_value()) {
if (!computed_fenced_frame_properties->mapped_url_.has_value() ||
url::Origin::Create(common_params_->url)
.IsSameOriginWith(computed_fenced_frame_properties->mapped_url_
->GetValueIgnoringVisibility())) {
commit_params_->fenced_frame_properties =
computed_fenced_frame_properties->RedactFor(
content::FencedFrameEntity::kContent);
}
}
if (ready_to_commit_callback_for_testing_)
std::move(ready_to_commit_callback_for_testing_).Run();
}
bool NavigationRequest::IsWaitingToCommit() {
return state_ == READY_TO_COMMIT;
}
bool NavigationRequest::WasResourceHintsReceived() {
DCHECK_GE(state_, WILL_PROCESS_RESPONSE)
<< "Should only be called after the response started";
return was_resource_hints_received_;
}
bool NavigationRequest::IsPdf() {
return is_pdf_;
}
bool NavigationRequest::IsLoadDataWithBaseURL() const {
return IsInPrimaryMainFrame() && !DidEncounterError() &&
common_params_->url.SchemeIs(url::kDataScheme) &&
common_params_->base_url_for_data_url.is_valid();
}
url::Origin NavigationRequest::GetTentativeOriginAtRequestTime() {
DCHECK_LT(state_, WILL_PROCESS_RESPONSE);
return GetOriginForURLLoaderFactoryBeforeResponse(
commit_params_->frame_policy.sandbox_flags);
}
absl::optional<url::Origin> NavigationRequest::GetOriginToCommit() {
return GetOriginToCommitWithDebugInfo().first;
}
std::pair<absl::optional<url::Origin>, std::string>
NavigationRequest::GetOriginToCommitWithDebugInfo() {
return GetOriginForURLLoaderFactoryAfterResponseWithDebugInfo();
}
url::Origin NavigationRequest::GetOriginForURLLoaderFactoryBeforeResponse(
network::mojom::WebSandboxFlags sandbox_flags) {
return GetOriginForURLLoaderFactoryBeforeResponseWithDebugInfo(sandbox_flags)
.first;
}
std::pair<url::Origin, std::string>
NavigationRequest::GetOriginForURLLoaderFactoryBeforeResponseWithDebugInfo(
network::mojom::WebSandboxFlags sandbox_flags) {
std::pair<url::Origin, std::string> origin_and_debug_info =
GetOriginForURLLoaderFactoryUncheckedWithDebugInfo(this);
bool use_opaque_origin =
(sandbox_flags & network::mojom::WebSandboxFlags::kOrigin) ==
network::mojom::WebSandboxFlags::kOrigin;
if (use_opaque_origin) {
origin_and_debug_info.second += ", sandbox_flags";
}
#ifdef OHOS_NETWORK_LOAD
bool find_custom_scheme = false;
std::string scheme = origin_and_debug_info.first.GetURL().scheme();
for (size_t index = 0; index < url::GetCustomScheme().size(); index++) {
if (scheme == url::GetCustomScheme()[index]) {
find_custom_scheme = true;
}
}
if (!origin_and_debug_info.first.GetURL().IsStandard() && !find_custom_scheme) {
#else
if (!origin_and_debug_info.first.GetURL().IsStandard()) {
#endif
use_opaque_origin = true;
origin_and_debug_info.second += ", cef_nonstandard";
}
if (use_opaque_origin) {
origin_and_debug_info =
std::make_pair(origin_and_debug_info.first.DeriveNewOpaqueOrigin(),
origin_and_debug_info.second);
}
return origin_and_debug_info;
}
absl::optional<url::Origin>
NavigationRequest::GetOriginForURLLoaderFactoryAfterResponse() {
return GetOriginForURLLoaderFactoryAfterResponseWithDebugInfo().first;
}
std::pair<absl::optional<url::Origin>, std::string>
NavigationRequest::GetOriginForURLLoaderFactoryAfterResponseWithDebugInfo() {
DCHECK_GE(state_, WILL_PROCESS_RESPONSE);
if (!GetRenderFrameHost())
return std::make_pair(absl::nullopt, "no_commit");
if (IsSameDocument() || IsPageActivation())
return std::make_pair(GetRenderFrameHost()->GetLastCommittedOrigin(),
"same_doc_or_page_activation");
std::pair<url::Origin, std::string> origin_with_debug_info =
GetOriginForURLLoaderFactoryBeforeResponseWithDebugInfo(
SandboxFlagsToCommit());
if (origin_with_debug_info.first.opaque() &&
origin_with_debug_info.second.find("cef_nonstandard") !=
std::string::npos) {
return origin_with_debug_info;
}
DCHECK(!IsMhtmlOrSubframe() || origin_with_debug_info.first.opaque());
if (GetRenderFrameHost()->ShouldBypassSecurityChecksForErrorPage(this))
return origin_with_debug_info;
if (IsForMhtmlSubframe())
return origin_with_debug_info;
int process_id = GetRenderFrameHost()->GetProcess()->GetID();
auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
CHECK(
policy->CanAccessDataForOrigin(process_id, origin_with_debug_info.first));
return origin_with_debug_info;
}
void NavigationRequest::WriteIntoTrace(
perfetto::TracedProto<TraceProto> ctx) const {
ctx->set_navigation_id(navigation_id_);
ctx->set_has_committed(HasCommitted());
ctx->set_is_error_page(IsErrorPage());
ctx.Set(TraceProto::kFrameTreeNode, frame_tree_node_);
if (state_ >= WILL_PROCESS_RESPONSE)
ctx.Set(TraceProto::kRenderFrameHost, GetRenderFrameHost());
perfetto::TracedDictionary dict = std::move(ctx).AddDebugAnnotations();
dict.Add("url", common_params_->url);
dict.Add("net_error", net_error_);
dict.Add("browser_initiated", commit_params_->is_browser_initiated);
dict.Add("from_begin_navigation", from_begin_navigation_);
dict.Add("is_synchronous_renderer_commit", is_synchronous_renderer_commit_);
dict.Add("reload_type", reload_type_);
dict.Add("state", state_);
dict.Add("navigation_type", common_params_->navigation_type);
if (IsServedFromBackForwardCache()) {
dict.Add("served_from_bfcache", true);
dict.Add("rfh_restored_from_bfcache",
rfh_restored_from_back_forward_cache_);
}
if (prerender_frame_tree_node_id_.has_value()) {
dict.Add("prerender_frame_tree_node_id",
prerender_frame_tree_node_id_.value());
}
}
bool NavigationRequest::SetNavigationTimeout(base::TimeDelta timeout) {
DCHECK_EQ(state_, WILL_REDIRECT_REQUEST);
if (loader_)
return loader_->SetNavigationTimeout(timeout);
return false;
}
void NavigationRequest::SetAllowCookiesFromBrowser(
bool allow_cookies_from_browser) {
allow_cookies_from_browser_ = allow_cookies_from_browser;
}
void NavigationRequest::RenderProcessBlockedStateChanged(bool blocked) {
if (blocked)
StopCommitTimeout();
else
RestartCommitTimeout();
}
void NavigationRequest::StopCommitTimeout() {
commit_timeout_timer_.Stop();
render_process_blocked_state_changed_subscription_ = {};
GetRenderFrameHost()->GetRenderWidgetHost()->RendererIsResponsive();
}
void NavigationRequest::RestartCommitTimeout() {
commit_timeout_timer_.Stop();
if (state_ >= DID_COMMIT)
return;
RenderProcessHost* renderer_host =
GetRenderFrameHost()->GetRenderWidgetHost()->GetProcess();
if (!render_process_blocked_state_changed_subscription_) {
render_process_blocked_state_changed_subscription_ =
renderer_host->RegisterBlockStateChangedCallback(base::BindRepeating(
&NavigationRequest::RenderProcessBlockedStateChanged,
base::Unretained(this)));
}
if (!renderer_host->IsBlocked()) {
commit_timeout_timer_.Start(
FROM_HERE, g_commit_timeout,
base::BindOnce(&NavigationRequest::OnCommitTimeout,
weak_factory_.GetWeakPtr()));
}
}
void NavigationRequest::OnCommitTimeout() {
DCHECK_EQ(READY_TO_COMMIT, state_);
render_process_blocked_state_changed_subscription_ = {};
GetRenderFrameHost()->GetRenderWidgetHost()->RendererIsUnresponsive(
base::BindRepeating(&NavigationRequest::RestartCommitTimeout,
weak_factory_.GetWeakPtr())
#if defined(OHOS_RENDERER_ANR_DUMP)
,
content::RenderProcessNotRespondingReason::kRendererAnrNavigationTimeout
#endif
);
}
void NavigationRequest::SetCommitTimeoutForTesting(
const base::TimeDelta& timeout) {
if (timeout.is_zero())
g_commit_timeout = kDefaultCommitTimeout;
else
g_commit_timeout = timeout;
}
void NavigationRequest::SetPrerenderActivationNavigationState(
std::unique_ptr<NavigationEntryImpl> prerender_navigation_entry,
const blink::mojom::FrameReplicationState& replication_state) {
DCHECK(IsPrerenderedPageActivation());
if (!prerender_navigation_state_) {
prerender_navigation_state_.emplace();
}
prerender_navigation_state_->prerender_navigation_entry =
std::move(prerender_navigation_entry);
prerender_navigation_state_->prerender_main_frame_replication_state =
replication_state;
}
void NavigationRequest::RemoveRequestHeader(const std::string& header_name) {
DCHECK(state_ == WILL_REDIRECT_REQUEST);
removed_request_headers_.push_back(header_name);
}
void NavigationRequest::SetRequestHeader(const std::string& header_name,
const std::string& header_value) {
DCHECK(state_ == WILL_START_REQUEST || state_ == WILL_REDIRECT_REQUEST);
modified_request_headers_.SetHeader(header_name, header_value);
}
void NavigationRequest::SetCorsExemptRequestHeader(
const std::string& header_name,
const std::string& header_value) {
DCHECK(state_ == WILL_START_REQUEST || state_ == WILL_REDIRECT_REQUEST);
cors_exempt_request_headers_.SetHeader(header_name, header_value);
}
const net::HttpResponseHeaders* NavigationRequest::GetResponseHeaders() {
return response_head_.get() ? response_head_->headers.get() : nullptr;
}
mojom::DidCommitProvisionalLoadParamsPtr
NavigationRequest::MakeDidCommitProvisionalLoadParamsForActivation() {
mojom::DidCommitProvisionalLoadParamsPtr params =
GetRenderFrameHost()->TakeLastCommitParams();
CHECK(params);
if (IsPrerenderedPageActivation()) {
switch (params->http_status_code) {
case net::HTTP_OK:
case net::HTTP_CREATED:
case net::HTTP_ACCEPTED:
case net::HTTP_NON_AUTHORITATIVE_INFORMATION:
break;
default:
NOTREACHED();
}
} else {
DCHECK_EQ(params->http_status_code, net::HTTP_OK);
}
DCHECK_EQ(params->url_is_unreachable, false);
DCHECK_EQ(params->post_id, -1);
params->navigation_token = commit_params().navigation_token;
DCHECK_EQ(params->url, common_params().url);
params->should_update_history = true;
DCHECK_EQ(params->method, common_params().method);
params->item_sequence_number = frame_entry_item_sequence_number_;
params->document_sequence_number = frame_entry_document_sequence_number_;
params->transition = ui::PageTransitionFromInt(common_params().transition);
params->history_list_was_cleared = false;
params->request_id = GetGlobalRequestID().request_id;
return params;
}
mojom::DidCommitProvisionalLoadParamsPtr
NavigationRequest::MakeDidCommitProvisionalLoadParamsForBFCacheRestore() {
mojom::DidCommitProvisionalLoadParamsPtr params =
MakeDidCommitProvisionalLoadParamsForActivation();
params->did_create_new_entry = false;
params->page_state =
blink::PageState::CreateFromEncodedData(commit_params().page_state);
return params;
}
mojom::DidCommitProvisionalLoadParamsPtr
NavigationRequest::MakeDidCommitProvisionalLoadParamsForPrerenderActivation() {
DCHECK(IsPrerenderedPageActivation());
mojom::DidCommitProvisionalLoadParamsPtr params =
MakeDidCommitProvisionalLoadParamsForActivation();
params->did_create_new_entry = true;
params->page_state = prerender_navigation_state_->prerender_navigation_entry
->GetFrameEntry(frame_tree_node())
->page_state();
params->insecure_request_policy =
prerender_navigation_state_->prerender_main_frame_replication_state
.insecure_request_policy;
return params;
}
bool NavigationRequest::IsExternalProtocol() {
return !GetContentClient()->browser()->IsHandledURL(common_params_->url);
}
bool NavigationRequest::IsSignedExchangeInnerResponse() {
return response() && response()->is_signed_exchange_inner_response;
}
net::IPEndPoint NavigationRequest::GetSocketAddress() {
DCHECK_GE(state_, WILL_PROCESS_RESPONSE);
return response() ? response()->remote_endpoint : net::IPEndPoint();
}
bool NavigationRequest::HasCommitted() const {
return state_ == DID_COMMIT || state_ == DID_COMMIT_ERROR_PAGE;
}
bool NavigationRequest::IsErrorPage() const {
return state_ == DID_COMMIT_ERROR_PAGE;
}
bool NavigationRequest::DidEncounterError() const {
return net_error_ != net::OK;
}
net::HttpResponseInfo::ConnectionInfo NavigationRequest::GetConnectionInfo() {
return response() ? response()->connection_info
: net::HttpResponseInfo::ConnectionInfo();
}
bool NavigationRequest::IsInMainFrame() const {
return frame_tree_node()->IsMainFrame();
}
RenderFrameHostImpl* NavigationRequest::GetParentFrame() {
return IsInMainFrame() ? nullptr : frame_tree_node()->parent();
}
RenderFrameHostImpl* NavigationRequest::GetParentFrameOrOuterDocument() {
return frame_tree_node()->GetParentOrOuterDocument();
}
bool NavigationRequest::IsInPrimaryMainFrame() const {
return GetNavigatingFrameType() == FrameType::kPrimaryMainFrame;
}
bool NavigationRequest::IsInOutermostMainFrame() {
return !GetParentFrameOrOuterDocument();
}
bool NavigationRequest::IsInPrerenderedMainFrame() const {
return GetNavigatingFrameType() == FrameType::kPrerenderMainFrame;
}
bool NavigationRequest::IsPrerenderedPageActivation() const {
CHECK(prerender_frame_tree_node_id_.has_value());
return prerender_frame_tree_node_id_ != RenderFrameHost::kNoFrameTreeNodeId;
}
bool NavigationRequest::IsInFencedFrameTree() const {
return frame_tree_node()->IsInFencedFrameTree();
}
FrameType NavigationRequest::GetNavigatingFrameType() const {
return frame_tree_node()->GetFrameType();
}
int NavigationRequest::GetFrameTreeNodeId() {
return frame_tree_node()->frame_tree_node_id();
}
bool NavigationRequest::WasResponseCached() {
return response() && response()->was_fetched_via_cache;
}
bool NavigationRequest::HasPrefetchedAlternativeSubresourceSignedExchange() {
return !commit_params_->prefetched_signed_exchanges.empty();
}
int64_t NavigationRequest::GetNavigationId() {
return navigation_id_;
}
ukm::SourceId NavigationRequest::GetNextPageUkmSourceId() {
if (rfh_restored_from_back_forward_cache_)
return rfh_restored_from_back_forward_cache_->GetPageUkmSourceId();
if (IsSameDocument() || !IsInMainFrame() || IsInFencedFrameTree())
return previous_page_ukm_source_id_;
return ukm::ConvertToSourceId(navigation_id_,
ukm::SourceIdObj::Type::NAVIGATION_ID);
}
const GURL& NavigationRequest::GetURL() {
return common_params().url;
}
SiteInstanceImpl* NavigationRequest::GetStartingSiteInstance() {
return starting_site_instance_.get();
}
SiteInstanceImpl* NavigationRequest::GetSourceSiteInstance() {
return source_site_instance_.get();
}
bool NavigationRequest::IsRendererInitiated() {
return !commit_params_->is_browser_initiated;
}
blink::mojom::NavigationInitiatorActivationAndAdStatus
NavigationRequest::GetNavigationInitiatorActivationAndAdStatus() {
return begin_params_->initiator_activation_and_ad_status;
}
bool NavigationRequest::IsSameOrigin() {
DCHECK(HasCommitted());
return same_origin_;
}
bool NavigationRequest::WasServerRedirect() {
return was_redirected_;
}
const std::vector<GURL>& NavigationRequest::GetRedirectChain() {
return redirect_chain_;
}
base::TimeTicks NavigationRequest::NavigationStart() {
return common_params().navigation_start;
}
base::TimeTicks NavigationRequest::NavigationInputStart() {
return common_params().input_start;
}
const NavigationHandleTiming& NavigationRequest::GetNavigationHandleTiming() {
return navigation_handle_timing_;
}
bool NavigationRequest::IsPost() {
return common_params().method == "POST";
}
const blink::mojom::Referrer& NavigationRequest::GetReferrer() {
return *sanitized_referrer_;
}
void NavigationRequest::SetReferrer(blink::mojom::ReferrerPtr referrer) {
DCHECK(state_ == WILL_START_REQUEST || state_ == WILL_REDIRECT_REQUEST);
sanitized_referrer_ =
Referrer::SanitizeForRequest(common_params_->url, *referrer);
common_params_->referrer = sanitized_referrer_.Clone();
}
bool NavigationRequest::HasUserGesture() {
return common_params().has_user_gesture;
}
ui::PageTransition NavigationRequest::GetPageTransition() {
return ui::PageTransitionFromInt(common_params().transition);
}
NavigationUIData* NavigationRequest::GetNavigationUIData() {
return navigation_ui_data_.get();
}
net::Error NavigationRequest::GetNetErrorCode() {
return net_error_;
}
RenderFrameHostImpl* NavigationRequest::GetRenderFrameHost() const {
if (!is_synchronous_renderer_commit()) {
CHECK_GE(state_, WILL_PROCESS_RESPONSE)
<< "This accessor should only be called after a RenderFrameHost has "
"been picked for this navigation.";
}
static_assert(WILL_FAIL_REQUEST > WILL_PROCESS_RESPONSE,
"WillFailRequest state should come after WillProcessResponse");
if (HasRenderFrameHost()) {
return &*render_frame_host_.value();
}
return nullptr;
}
NavigationRequest::AssociatedRenderFrameHostType
NavigationRequest::GetAssociatedRFHType() const {
CHECK(state_ < READY_TO_COMMIT || state_ == WILL_FAIL_REQUEST)
<< "Use GetRenderFrameHost() instead when the final RenderFrameHost "
"for the navigation has been picked";
return associated_rfh_type_;
}
void NavigationRequest::SetAssociatedRFHType(
AssociatedRenderFrameHostType type) {
if (associated_rfh_type_ != AssociatedRenderFrameHostType::NONE &&
type == AssociatedRenderFrameHostType::NONE) {
ResetExpectedProcess();
}
associated_rfh_type_ = type;
}
const net::HttpRequestHeaders& NavigationRequest::GetRequestHeaders() {
if (!request_headers_) {
request_headers_.emplace();
request_headers_->AddHeadersFromString(begin_params_->headers);
}
return *request_headers_;
}
const absl::optional<net::SSLInfo>& NavigationRequest::GetSSLInfo() {
return ssl_info_;
}
const absl::optional<net::AuthChallengeInfo>&
NavigationRequest::GetAuthChallengeInfo() {
return auth_challenge_info_;
}
net::ResolveErrorInfo NavigationRequest::GetResolveErrorInfo() {
return resolve_error_info_;
}
net::IsolationInfo NavigationRequest::GetIsolationInfo() {
if (isolation_info_)
return isolation_info_.value();
return frame_tree_node_->current_frame_host()
->ComputeIsolationInfoForNavigation(
common_params_->url, is_credentialless(), ComputeFencedFrameNonce());
}
bool NavigationRequest::HasSubframeNavigationEntryCommitted() {
DCHECK(!frame_tree_node_->IsMainFrame());
DCHECK(state_ == DID_COMMIT || state_ == DID_COMMIT_ERROR_PAGE);
return subframe_entry_committed_;
}
bool NavigationRequest::DidReplaceEntry() {
DCHECK(state_ == DID_COMMIT || state_ == DID_COMMIT_ERROR_PAGE);
return did_replace_entry_;
}
bool NavigationRequest::ShouldUpdateHistory() {
DCHECK(state_ == DID_COMMIT || state_ == DID_COMMIT_ERROR_PAGE);
return should_update_history_;
}
const GURL& NavigationRequest::GetPreviousPrimaryMainFrameURL() {
DCHECK(IsInPrimaryMainFrame() ||
GetParentFrame() && GetParentFrame()->GetPage().IsPrimary());
return GetPreviousMainFrameURL();
}
const GURL& NavigationRequest::GetPreviousMainFrameURL() const {
DCHECK(state_ == DID_COMMIT || state_ == DID_COMMIT_ERROR_PAGE);
return previous_main_frame_url_;
}
bool NavigationRequest::WasStartedFromContextMenu() {
return common_params().started_from_context_menu;
}
const GURL& NavigationRequest::GetSearchableFormURL() {
return begin_params().searchable_form_url;
}
const std::string& NavigationRequest::GetSearchableFormEncoding() {
return begin_params().searchable_form_encoding;
}
ReloadType NavigationRequest::GetReloadType() {
return reload_type_;
}
RestoreType NavigationRequest::GetRestoreType() {
return restore_type_;
}
const GURL& NavigationRequest::GetBaseURLForDataURL() {
return common_params().base_url_for_data_url;
}
const GlobalRequestID& NavigationRequest::GetGlobalRequestID() {
DCHECK_GE(state_, WILL_PROCESS_RESPONSE);
return request_id_;
}
bool NavigationRequest::IsDownload() {
return is_download_;
}
bool NavigationRequest::IsFormSubmission() {
return begin_params().is_form_submission;
}
bool NavigationRequest::WasInitiatedByLinkClick() {
return begin_params().was_initiated_by_link_click;
}
const std::string& NavigationRequest::GetHrefTranslate() {
return common_params().href_translate;
}
const absl::optional<blink::Impression>& NavigationRequest::GetImpression() {
return begin_params().impression;
}
const absl::optional<blink::LocalFrameToken>&
NavigationRequest::GetInitiatorFrameToken() {
return initiator_frame_token_;
}
int NavigationRequest::GetInitiatorProcessID() {
return initiator_process_id_;
}
const absl::optional<url::Origin>& NavigationRequest::GetInitiatorOrigin() {
return common_params().initiator_origin;
}
const absl::optional<GURL>& NavigationRequest::GetInitiatorBaseUrl() {
return common_params().initiator_base_url;
}
const std::vector<std::string>& NavigationRequest::GetDnsAliases() {
static const base::NoDestructor<std::vector<std::string>> emptyvector_result;
return response_head_ ? response_head_->dns_aliases : *emptyvector_result;
}
bool NavigationRequest::IsSameProcess() {
return is_same_process_;
}
NavigationEntry* NavigationRequest::GetNavigationEntry() {
if (nav_entry_id_ == 0)
return nullptr;
return GetNavigationController()->GetEntryWithUniqueIDIncludingPending(
nav_entry_id_);
}
int NavigationRequest::GetNavigationEntryOffset() {
return navigation_entry_offset_;
}
const net::ProxyServer& NavigationRequest::GetProxyServer() {
return proxy_server_;
}
GlobalRenderFrameHostId NavigationRequest::GetPreviousRenderFrameHostId() {
return previous_render_frame_host_id_;
}
int NavigationRequest::GetExpectedRenderProcessHostId() {
DCHECK_LT(state_, READY_TO_COMMIT);
return expected_render_process_host_id_;
}
bool NavigationRequest::IsServedFromBackForwardCache() {
const NavigationRequest& request = *this;
return request.IsServedFromBackForwardCache();
}
void NavigationRequest::SetIsOverridingUserAgent(bool override_ua) {
if (is_synchronous_renderer_commit_)
return;
DCHECK(!ua_change_requires_reload_);
commit_params_->is_overriding_user_agent = override_ua;
net::HttpRequestHeaders headers;
headers.AddHeadersFromString(begin_params_->headers);
BrowserContext* browser_context =
frame_tree_node_->navigator().controller().GetBrowserContext();
ClientHintsControllerDelegate* client_hints_delegate =
browser_context->GetClientHintsControllerDelegate();
if (client_hints_delegate) {
UpdateNavigationRequestClientUaHeaders(
GetTentativeOriginAtRequestTime(), client_hints_delegate,
is_overriding_user_agent(), frame_tree_node_, &headers,
common_params_->url);
}
headers.SetHeader(
net::HttpRequestHeaders::kUserAgent,
ComputeUserAgentValue(headers, GetUserAgentOverride(), browser_context));
begin_params_->headers = headers.ToString();
request_headers_.reset();
}
void NavigationRequest::SetSilentlyIgnoreErrors() {
silently_ignore_errors_ = true;
}
NavigationRequest* NavigationRequest::From(NavigationHandle* handle) {
return static_cast<NavigationRequest*>(handle);
}
ReloadType NavigationRequest::NavigationTypeToReloadType(
blink::mojom::NavigationType type) {
if (type == blink::mojom::NavigationType::RELOAD)
return ReloadType::NORMAL;
if (type == blink::mojom::NavigationType::RELOAD_BYPASSING_CACHE)
return ReloadType::BYPASSING_CACHE;
if (type == blink::mojom::NavigationType::RELOAD_ORIGINAL_REQUEST_URL)
return ReloadType::ORIGINAL_REQUEST_URL;
return ReloadType::NONE;
}
bool NavigationRequest::IsNavigationStarted() const {
return is_navigation_started_;
}
bool NavigationRequest::RequiresInitiatorBasedSourceSiteInstance() const {
if (commit_params_->is_browser_initiated &&
!common_params().started_from_context_menu) {
return false;
}
const bool is_data_or_about_or_empty =
common_params_->url.SchemeIs(url::kDataScheme) ||
common_params_->url.IsAboutBlank() || common_params_->url.is_empty();
const bool has_valid_initiator =
common_params_->initiator_origin &&
common_params_->initiator_origin->GetTupleOrPrecursorTupleIfOpaque()
.IsValid();
return is_data_or_about_or_empty && has_valid_initiator &&
!dest_site_instance_;
}
void NavigationRequest::SetSourceSiteInstanceToInitiatorIfNeeded() {
if (source_site_instance_ || !RequiresInitiatorBasedSourceSiteInstance())
return;
const auto tuple =
common_params_->initiator_origin->GetTupleOrPrecursorTupleIfOpaque();
source_site_instance_ = static_cast<SiteInstanceImpl*>(
frame_tree_node_->current_frame_host()
->GetSiteInstance()
->GetRelatedSiteInstance(tuple.GetURL())
.get());
}
void NavigationRequest::RestartBackForwardCachedNavigation() {
TRACE_EVENT0("navigation",
"NavigationRequest::RestartBackForwardCachedNavigation");
CHECK(IsServedFromBackForwardCache());
restarting_back_forward_cached_navigation_ = true;
GetUIThreadTaskRunner({})->PostTask(
FROM_HERE,
base::BindOnce(&NavigationRequest::RestartBackForwardCachedNavigationImpl,
weak_factory_.GetWeakPtr()));
loader_.reset();
}
void NavigationRequest::RestartBackForwardCachedNavigationImpl() {
TRACE_EVENT0("navigation",
"NavigationRequest::RestartBackForwardCachedNavigationImpl");
CHECK(IsServedFromBackForwardCache());
if (RenderFrameHostImpl* rfh = rfh_restored_from_back_forward_cache()) {
CHECK_EQ(rfh->frame_tree_node()->navigation_request(), this);
}
NavigationControllerImpl* controller = GetNavigationController();
int nav_index = controller->GetEntryIndexWithUniqueID(nav_entry_id());
if (nav_index == -1)
return;
controller->GoToIndex(nav_index);
}
void NavigationRequest::ForceEnableOriginTrials(
const std::vector<std::string>& trials) {
DCHECK(!HasCommitted());
commit_params_->force_enabled_origin_trials = trials;
}
network::CrossOriginEmbedderPolicy
NavigationRequest::ComputeCrossOriginEmbedderPolicy() {
const auto& url = common_params_->url;
RenderFrameHostImpl* const parent =
GetNavigatingFrameType() == FrameType::kFencedFrameRoot
? GetParentFrameOrOuterDocument()
: GetParentFrame();
bool is_fenced_frame_from_local_scheme =
GetNavigatingFrameType() == FrameType::kFencedFrameRoot &&
(url.SchemeIsBlob() || url.SchemeIs(url::kDataScheme));
if (parent && (GetContentClient()
->browser()
->ShouldInheritCrossOriginEmbedderPolicyImplicitly(url) ||
is_fenced_frame_from_local_scheme)) {
return parent->cross_origin_embedder_policy();
}
const GURL& top_level_creation_url = GetParentFrameOrOuterDocument()
? GetParentFrameOrOuterDocument()
->GetOutermostMainFrame()
->GetLastCommittedURL()
: url;
if (network::IsUrlPotentiallyTrustworthy(top_level_creation_url)) {
if (response_head_) {
return response_head_->parsed_headers->cross_origin_embedder_policy;
}
}
return network::CrossOriginEmbedderPolicy();
}
bool NavigationRequest::CheckResponseAdherenceToCoep(const GURL& url) {
const auto& coep =
policy_container_builder_->FinalPolicies().cross_origin_embedder_policy;
RenderFrameHostImpl* const parent =
GetNavigatingFrameType() == FrameType::kFencedFrameRoot
? GetParentFrameOrOuterDocument()
: GetParentFrame();
if (!parent)
return true;
const auto& parent_coep = parent->cross_origin_embedder_policy();
CrossOriginEmbedderPolicyReporter* parent_coep_reporter =
parent->coep_reporter();
if (CoepBlockIframe(parent_coep.report_only_value, coep.value,
is_credentialless())) {
if (parent_coep_reporter) {
parent_coep_reporter->QueueNavigationReport(redirect_chain_[0],
true);
}
}
if (!CoepBlockIframe(parent_coep.value, coep.value, is_credentialless()))
return true;
if (parent_coep_reporter) {
parent_coep_reporter->QueueNavigationReport(redirect_chain_[0],
false);
}
return false;
}
absl::optional<network::mojom::BlockedByResponseReason>
NavigationRequest::EnforceCOEP() {
RenderFrameHostImpl* const parent_frame =
GetNavigatingFrameType() == FrameType::kFencedFrameRoot
? GetParentFrameOrOuterDocument()
: GetParentFrame();
if (!parent_frame) {
return absl::nullopt;
}
if (is_credentialless()) {
return absl::nullopt;
}
const auto& url = common_params_->url;
if (url.SchemeIsBlob() || url.SchemeIs(url::kDataScheme)) {
return absl::nullopt;
}
return network::CrossOriginResourcePolicy::IsNavigationBlocked(
url, redirect_chain_[0], parent_frame->GetLastCommittedOrigin(),
*response_head_, request_destination(),
parent_frame->cross_origin_embedder_policy(),
parent_frame->coep_reporter());
}
bool NavigationRequest::CoopCoepSanityCheck() {
if (IsSameDocument()) {
return true;
}
if (is_credentialless_) {
return true;
}
const PolicyContainerPolicies& policies =
policy_container_builder_->FinalPolicies();
network::mojom::CrossOriginOpenerPolicyValue coop_value =
GetParentFrameOrOuterDocument()
? GetRenderFrameHost()
->GetOutermostMainFrame()
->cross_origin_opener_policy()
.value
: policies.cross_origin_opener_policy.value;
if (coop_value ==
network::mojom::CrossOriginOpenerPolicyValue::kSameOriginPlusCoep &&
!CompatibleWithCrossOriginIsolated(
policies.cross_origin_embedder_policy)) {
NOTREACHED();
base::debug::DumpWithoutCrashing();
return false;
}
return true;
}
bool NavigationRequest::IsFencedFrameRequiredPolicyFeatureAllowed(
const url::Origin& origin,
const blink::mojom::PermissionsPolicyFeature feature) {
const blink::PermissionsPolicyFeatureList& feature_list =
blink::GetPermissionsPolicyFeatureList();
if (GetParentFrameOrOuterDocument()
->permissions_policy()
->GetAllowlistForFeatureIfExists(feature) &&
!GetParentFrameOrOuterDocument()
->permissions_policy()
->IsFeatureEnabledForOrigin(feature, origin)) {
return false;
}
auto policy_iter = std::find_if(
commit_params_->frame_policy.container_policy.begin(),
commit_params_->frame_policy.container_policy.end(),
[feature](const blink::ParsedPermissionsPolicyDeclaration& d) {
return d.feature == feature;
});
if (policy_iter == commit_params_->frame_policy.container_policy.end()) {
return feature_list.at(feature) ==
blink::PermissionsPolicyFeatureDefault::EnableForAll;
}
return policy_iter->Contains(origin);
}
bool NavigationRequest::CheckPermissionsPoliciesForFencedFrames(
const url::Origin& origin) {
if (!frame_tree_node_->IsFencedFrameRoot())
return true;
for (const blink::mojom::PermissionsPolicyFeature feature :
blink::kFencedFrameOpaqueAdsDefaultAllowedFeatures) {
if (!IsFencedFrameRequiredPolicyFeatureAllowed(origin, feature)) {
const blink::PermissionsPolicyFeatureToNameMap& feature_to_name_map =
blink::GetPermissionsPolicyFeatureToNameMap();
const std::string feature_string(feature_to_name_map.at(feature));
frame_tree_node_->current_frame_host()->AddMessageToConsole(
blink::mojom::ConsoleMessageLevel::kError,
base::StringPrintf(
"Refused to frame '%s' as a fenced frame because permissions "
"policy '%s' is not allowed for the frame's origin.",
origin.Serialize().c_str(), feature_string.c_str()));
return false;
}
}
return true;
}
std::unique_ptr<PeakGpuMemoryTracker>
NavigationRequest::TakePeakGpuMemoryTracker() {
return std::move(loading_mem_tracker_);
}
std::unique_ptr<NavigationEarlyHintsManager>
NavigationRequest::TakeEarlyHintsManager() {
return std::move(early_hints_manager_);
}
network::mojom::ClientSecurityStatePtr
NavigationRequest::BuildClientSecurityState() {
auto client_security_state = network::mojom::ClientSecurityState::New();
const PolicyContainerPolicies& policies =
policy_container_builder_->FinalPolicies();
client_security_state->is_web_secure_context = policies.is_web_secure_context;
client_security_state->ip_address_space = policies.ip_address_space;
client_security_state->cross_origin_embedder_policy =
policies.cross_origin_embedder_policy;
client_security_state->local_network_request_policy =
local_network_request_policy_;
return client_security_state;
}
std::string NavigationRequest::GetUserAgentOverride() {
return is_overriding_user_agent() ? frame_tree_node_->navigator()
.GetDelegate()
->GetUserAgentOverride()
.ua_string_override
: std::string();
}
NavigationControllerImpl* NavigationRequest::GetNavigationController() {
return &frame_tree_node_->navigator().controller();
}
PrerenderHostRegistry& NavigationRequest::GetPrerenderHostRegistry() {
return *frame_tree_node_->current_frame_host()
->delegate()
->GetPrerenderHostRegistry();
}
mojo::PendingRemote<network::mojom::CookieAccessObserver>
NavigationRequest::CreateCookieAccessObserver() {
mojo::PendingRemote<network::mojom::CookieAccessObserver> remote;
cookie_observers_.Add(this, remote.InitWithNewPipeAndPassReceiver());
return remote;
}
mojo::PendingRemote<network::mojom::TrustTokenAccessObserver>
NavigationRequest::CreateTrustTokenAccessObserver() {
mojo::PendingRemote<network::mojom::TrustTokenAccessObserver> remote;
trust_token_observers_.Add(this, remote.InitWithNewPipeAndPassReceiver());
return remote;
}
void NavigationRequest::OnCookiesAccessed(
std::vector<network::mojom::CookieAccessDetailsPtr> details_vector) {
for (auto& details : details_vector) {
EmitCookieWarningsAndMetrics(frame_tree_node()->current_frame_host(),
details);
CookieAccessDetails allowed;
CookieAccessDetails blocked;
SplitCookiesIntoAllowedAndBlocked(details, &allowed, &blocked);
if (!allowed.cookie_list.empty()) {
GetDelegate()->OnCookiesAccessed(this, allowed);
}
if (!blocked.cookie_list.empty()) {
GetDelegate()->OnCookiesAccessed(this, blocked);
}
if (allowed.type == CookieAccessDetails::Type::kChange) {
uint64_t cookie_modification_count = allowed.cookie_list.size();
uint64_t http_only_cookie_modification_count = 0u;
for (net::CanonicalCookie& cookie : allowed.cookie_list) {
if (cookie.IsHttpOnly()) {
http_only_cookie_modification_count++;
}
}
if (cookie_change_listener_) {
cookie_change_listener_->RemoveNavigationCookieModificationCount(
base::PassKey<NavigationRequest>(), cookie_modification_count,
http_only_cookie_modification_count);
}
}
}
}
void NavigationRequest::Clone(
mojo::PendingReceiver<network::mojom::CookieAccessObserver> observer) {
cookie_observers_.Add(this, std::move(observer));
}
std::vector<mojo::PendingReceiver<network::mojom::CookieAccessObserver>>
NavigationRequest::TakeCookieObservers() {
return cookie_observers_.TakeReceivers();
}
void NavigationRequest::OnTrustTokensAccessed(
network::mojom::TrustTokenAccessDetailsPtr details) {
GetDelegate()->OnTrustTokensAccessed(this, TrustTokenAccessDetails(details));
}
void NavigationRequest::Clone(
mojo::PendingReceiver<network::mojom::TrustTokenAccessObserver> observer) {
trust_token_observers_.Add(this, std::move(observer));
}
std::vector<mojo::PendingReceiver<network::mojom::TrustTokenAccessObserver>>
NavigationRequest::TakeTrustTokenObservers() {
return trust_token_observers_.TakeReceivers();
}
RenderFrameHostImpl* NavigationRequest::GetInitiatorDocumentRenderFrameHost() {
return static_cast<RenderFrameHostImpl*>(
initiator_document_.AsRenderFrameHostIfValid());
}
void NavigationRequest::RecordAddressSpaceFeature() {
DCHECK(response_head_);
DCHECK(policy_container_builder_);
RenderFrameHostImpl* initiator_render_frame_host =
GetInitiatorDocumentRenderFrameHost();
if (!initiator_render_frame_host) {
return;
}
const PolicyContainerPolicies* initiator_policies =
policy_container_builder_->InitiatorPolicies();
DCHECK(initiator_policies);
if (!initiator_policies) {
base::debug::DumpWithoutCrashing();
return;
}
absl::optional<blink::mojom::WebFeature> optional_feature =
blink::AddressSpaceFeature(blink::FetchType::kNavigation,
initiator_policies->ip_address_space,
initiator_policies->is_web_secure_context,
response_head_->response_address_space);
if (!optional_feature.has_value()) {
return;
}
ContentBrowserClient* client = GetContentClient()->browser();
client->LogWebFeatureForCurrentPage(initiator_render_frame_host,
*optional_feature);
client->LogWebFeatureForCurrentPage(
initiator_render_frame_host,
IsInOutermostMainFrame()
? blink::mojom::WebFeature::kPrivateNetworkAccessFetchedTopFrame
: blink::mojom::WebFeature::kPrivateNetworkAccessFetchedSubFrame);
}
void NavigationRequest::ComputePoliciesToCommit() {
const auto& url = common_params_->url;
network::mojom::IPAddressSpace response_address_space =
CalculateIPAddressSpace(url, response_head_.get(),
GetContentClient()->browser());
policy_container_builder_->SetIPAddressSpace(response_address_space);
if (!devtools_instrumentation::ShouldBypassCSP(*this)) {
if (response_head_) {
policy_container_builder_->AddContentSecurityPolicies(
mojo::Clone(response_head_->parsed_headers->content_security_policy));
}
BrowserContext* browser_context =
frame_tree_node()->navigator().controller().GetBrowserContext();
if (SiteIsolationPolicy::ShouldUrlUseApplicationIsolationLevel(
browser_context, GetURL())) {
policy_container_builder_->AddContentSecurityPolicies(
network::ParseContentSecurityPolicies(
kIsolatedAppCSP,
network::mojom::ContentSecurityPolicyType::kEnforce,
network::mojom::ContentSecurityPolicySource::kHTTP, GetURL()));
}
}
policy_container_builder_->SetIsOriginPotentiallyTrustworthy(
network::IsOriginPotentiallyTrustworthy(
GetOriginForURLLoaderFactoryUnchecked(this)));
policy_container_builder_->SetCrossOriginEmbedderPolicy(
ComputeCrossOriginEmbedderPolicy());
DCHECK(commit_params_);
DCHECK(!HasCommitted());
DCHECK(!IsErrorPage());
policy_container_builder_->ComputePolicies(
url, IsMhtmlOrSubframe(), commit_params_->frame_policy.sandbox_flags,
is_credentialless());
}
void NavigationRequest::ComputePoliciesToCommitForError() {
CHECK(!IsMhtmlOrSubframe());
policy_container_builder_->ComputePoliciesForError();
}
void NavigationRequest::CheckStateTransition(NavigationState state) const {
#if DCHECK_IS_ON()
static const base::NoDestructor<base::StateTransitions<NavigationState>>
transitions(base::StateTransitions<NavigationState>({
{NOT_STARTED, {
WAITING_FOR_RENDERER_RESPONSE,
WILL_START_NAVIGATION,
WILL_START_REQUEST,
}},
{WAITING_FOR_RENDERER_RESPONSE, {
WILL_START_NAVIGATION,
WILL_START_REQUEST,
}},
{WILL_START_NAVIGATION, {
WILL_START_REQUEST,
WILL_FAIL_REQUEST,
}},
{WILL_START_REQUEST, {
WILL_REDIRECT_REQUEST,
WILL_PROCESS_RESPONSE,
WILL_COMMIT_WITHOUT_URL_LOADER,
READY_TO_COMMIT,
DID_COMMIT,
CANCELING,
WILL_FAIL_REQUEST,
DID_COMMIT_ERROR_PAGE,
}},
{WILL_REDIRECT_REQUEST, {
WILL_REDIRECT_REQUEST,
WILL_PROCESS_RESPONSE,
CANCELING,
WILL_FAIL_REQUEST,
}},
{WILL_PROCESS_RESPONSE, {
READY_TO_COMMIT,
CANCELING,
WILL_FAIL_REQUEST,
}},
{WILL_COMMIT_WITHOUT_URL_LOADER, {
READY_TO_COMMIT,
CANCELING,
WILL_FAIL_REQUEST,
}},
{READY_TO_COMMIT, {
NOT_STARTED,
DID_COMMIT,
DID_COMMIT_ERROR_PAGE,
}},
{CANCELING, {
READY_TO_COMMIT,
WILL_FAIL_REQUEST,
}},
{WILL_FAIL_REQUEST, {
READY_TO_COMMIT,
CANCELING,
WILL_FAIL_REQUEST,
}},
{DID_COMMIT, {}},
{DID_COMMIT_ERROR_PAGE, {}},
}));
DCHECK_STATE_TRANSITION(transitions, state_, state);
#endif
}
void NavigationRequest::SetState(NavigationState state) {
CheckStateTransition(state);
state_ = state;
}
bool NavigationRequest::MaybeCancelFailedNavigation() {
if (net::ERR_ABORTED == net_error_ ||
silently_ignore_errors_ ||
(net::ERR_BLOCKED_BY_CLIENT == net_error_ &&
silently_ignore_blocked_by_client_)) {
frame_tree_node_->ResetNavigationRequest(
NavigationDiscardReason::kCancelled);
return true;
}
if (frame_tree_node()->frame_owner_element_type() ==
blink::FrameOwnerElementType::kObject) {
RenderFallbackContentForObjectTag();
frame_tree_node_->ResetNavigationRequest(
NavigationDiscardReason::kCancelled);
return true;
}
return false;
}
bool NavigationRequest::ShouldRenderFallbackContentForResponse(
const net::HttpResponseHeaders& http_headers) const {
return frame_tree_node()->frame_owner_element_type() ==
blink::FrameOwnerElementType::kObject &&
!network::IsSuccessfulStatus(http_headers.response_code());
}
bool NavigationRequest::ShouldReplaceCurrentEntryForSameUrlNavigation() const {
DCHECK_LE(state_, WILL_START_NAVIGATION);
if (common_params_->url !=
GetLastLoadingURLInRendererForNavigationReplacement(
frame_tree_node_->current_frame_host())) {
return false;
}
if (IsLoadDataWithBaseURL()) {
return false;
}
if (!frame_tree_node_->navigator().controller().GetEntryCount())
return false;
if (begin_params_->force_history_push ==
blink::mojom::ForceHistoryPush::kYes) {
return false;
}
if (common_params_->navigation_type !=
blink::mojom::NavigationType::DIFFERENT_DOCUMENT) {
return false;
}
if (begin_params_->is_form_submission)
return false;
if (!frame_tree_node_->current_frame_host()->IsErrorDocument() &&
common_params_->initiator_origin &&
!common_params_->initiator_origin->IsSameOriginWith(
frame_tree_node_->current_origin())) {
return false;
}
return true;
}
bool NavigationRequest::
ShouldReplaceCurrentEntryForNavigationFromInitialEmptyDocumentOrEntry()
const {
DCHECK_LE(state_, WILL_START_NAVIGATION);
if (!frame_tree_node_->navigator().controller().GetEntryCount())
return false;
if (common_params_->navigation_type !=
blink::mojom::NavigationType::SAME_DOCUMENT &&
common_params_->navigation_type !=
blink::mojom::NavigationType::DIFFERENT_DOCUMENT) {
return false;
}
if (frame_tree_node_->navigator()
.controller()
.GetLastCommittedEntry()
->IsInitialEntry()) {
return true;
}
return frame_tree_node_->is_on_initial_empty_document() &&
frame_tree_node_->GetParentOrOuterDocument();
}
bool NavigationRequest::ShouldReplaceCurrentEntryForFailedNavigation() const {
DCHECK(state_ == CANCELING || state_ == WILL_FAIL_REQUEST);
if (common_params_->should_replace_current_entry)
return true;
if (!frame_tree_node_->navigator().controller().GetEntryCount())
return false;
auto page_state =
blink::PageState::CreateFromEncodedData(commit_params_->page_state);
if (page_state.IsValid())
return false;
bool is_reload_or_history =
NavigationTypeUtils::IsReload(common_params_->navigation_type) ||
NavigationTypeUtils::IsHistory(common_params_->navigation_type);
return is_reload_or_history ||
(common_params_->url ==
GetLastLoadingURLInRendererForNavigationReplacement(
frame_tree_node_->current_frame_host()));
}
const absl::optional<FencedFrameProperties>&
NavigationRequest::ComputeFencedFrameProperties() const {
if (fenced_frame_properties_) {
return fenced_frame_properties_;
}
return frame_tree_node_->GetFencedFrameProperties();
}
const absl::optional<base::UnguessableToken>
NavigationRequest::ComputeFencedFrameNonce() const {
const absl::optional<FencedFrameProperties>&
computed_fenced_frame_properties = ComputeFencedFrameProperties();
if (!computed_fenced_frame_properties.has_value()) {
return absl::nullopt;
}
if (!computed_fenced_frame_properties->partition_nonce_.has_value()) {
CHECK(blink::features::IsAllowURNsInIframeEnabled());
return absl::nullopt;
}
return computed_fenced_frame_properties->partition_nonce_
->GetValueIgnoringVisibility();
}
const absl::optional<blink::FencedFrame::DeprecatedFencedFrameMode>
NavigationRequest::ComputeDeprecatedFencedFrameMode() const {
const absl::optional<FencedFrameProperties>&
computed_fenced_frame_properties = ComputeFencedFrameProperties();
if (!computed_fenced_frame_properties.has_value()) {
return absl::nullopt;
}
return computed_fenced_frame_properties->mode_;
}
void NavigationRequest::RenderFallbackContentForObjectTag() {
DCHECK_EQ(blink::FrameOwnerElementType::kObject,
frame_tree_node_->frame_owner_element_type());
if (RenderFrameProxyHost* proxy =
frame_tree_node_->render_manager()->GetProxyToParent()) {
if (proxy->is_render_frame_proxy_live()) {
proxy->GetAssociatedRemoteFrame()->RenderFallbackContent();
}
} else {
frame_tree_node_->current_frame_host()
->GetAssociatedLocalFrame()
->RenderFallbackContent();
}
}
absl::optional<base::UnguessableToken>
NavigationRequest::GetNavigationTokenForDeferringSubframes() {
DCHECK(IsInMainFrame());
if (!base::FeatureList::IsEnabled(
blink::features::kNavigateEventCancelableTraversals)) {
return absl::nullopt;
}
if (!IsSameDocument() ||
!NavigationTypeUtils::IsHistory(common_params_->navigation_type)) {
return absl::nullopt;
}
RenderFrameHostImpl* current_frame_host =
frame_tree_node_->current_frame_host();
if (!current_frame_host->has_navigate_event_handler()) {
return absl::nullopt;
}
if (commit_params_->is_browser_initiated &&
!current_frame_host->IsHistoryUserActivationActive()) {
return absl::nullopt;
}
return commit_params_->navigation_token;
}
void NavigationRequest::AddDeferredSubframeNavigationThrottle(
base::WeakPtr<SubframeHistoryNavigationThrottle> throttle) {
DCHECK(IsInMainFrame());
subframe_history_navigation_throttles_.push_back(throttle);
}
void NavigationRequest::UnblockPendingSubframeNavigationRequestsIfNeeded() {
base::WeakPtr<NavigationRequest> self = GetWeakPtr();
for (auto& throttle : subframe_history_navigation_throttles_) {
if (throttle) {
throttle->Resume();
if (!self) {
return;
}
}
}
subframe_history_navigation_throttles_.clear();
}
bool NavigationRequest::IsServedFromBackForwardCache() const {
return is_back_forward_cache_restore_;
}
bool NavigationRequest::IsPageActivation() const {
return const_cast<NavigationRequest*>(this)->IsPrerenderedPageActivation() ||
IsServedFromBackForwardCache();
}
std::unique_ptr<NavigationEntryImpl>
NavigationRequest::TakePrerenderNavigationEntry() {
DCHECK(IsPrerenderedPageActivation());
return std::move(prerender_navigation_state_->prerender_navigation_entry);
}
bool NavigationRequest::IsWaitingForBeforeUnload() {
return state_ < WILL_START_NAVIGATION;
}
void NavigationRequest::AddDeferredConsoleMessage(
blink::mojom::ConsoleMessageLevel level,
std::string message) {
DCHECK_LE(state_, READY_TO_COMMIT);
console_messages_.push_back(ConsoleMessage{level, std::move(message)});
}
void NavigationRequest::SendDeferredConsoleMessages() {
for (auto& message : console_messages_) {
GetRenderFrameHost()->AddMessageToConsole(message.level,
std::move(message.message));
}
console_messages_.clear();
}
absl::optional<WebExposedIsolationInfo>
NavigationRequest::ComputeWebExposedIsolationInfo() {
if (!frame_tree_node_->IsOutermostMainFrame()) {
return frame_tree_node_->current_frame_host()
->GetMainFrame()
->GetSiteInstance()
->GetWebExposedIsolationInfo();
}
if (common_params_->url.IsAboutBlank())
return absl::nullopt;
if (state_ < WILL_PROCESS_RESPONSE)
return absl::nullopt;
if ((coop_status().current_coop().value !=
network::mojom::CrossOriginOpenerPolicyValue::kSameOriginPlusCoep) &&
(coop_status().current_coop().value !=
network::mojom::CrossOriginOpenerPolicyValue::
kRestrictPropertiesPlusCoep)) {
return WebExposedIsolationInfo::CreateNonIsolated();
}
const GURL& url = common_params().url;
url::Origin origin = url::Origin::Create(url);
return SiteIsolationPolicy::ShouldUrlUseApplicationIsolationLevel(
GetNavigationController()->GetBrowserContext(), url)
? WebExposedIsolationInfo::CreateIsolatedApplication(origin)
: WebExposedIsolationInfo::CreateIsolated(origin);
}
absl::optional<url::Origin> NavigationRequest::ComputeCommonCoopOrigin() {
if (!frame_tree_node_->IsOutermostMainFrame()) {
return frame_tree_node_->current_frame_host()
->GetMainFrame()
->GetSiteInstance()
->GetCommonCoopOrigin();
}
if ((coop_status().current_coop().value ==
network::mojom::CrossOriginOpenerPolicyValue::kSameOrigin) ||
(coop_status().current_coop().value ==
network::mojom::CrossOriginOpenerPolicyValue::kSameOriginPlusCoep) ||
(coop_status().current_coop().value ==
network::mojom::CrossOriginOpenerPolicyValue::kRestrictProperties) ||
(coop_status().current_coop().value ==
network::mojom::CrossOriginOpenerPolicyValue::
kRestrictPropertiesPlusCoep)) {
if (!policy_container_builder_->HasComputedPolicies()) {
return GetTentativeOriginAtRequestTime();
}
return url::Origin::Create(common_params().url);
}
return absl::nullopt;
}
void NavigationRequest::MaybeAssignInvalidPrerenderFrameTreeNodeId() {
if (!prerender_frame_tree_node_id_.has_value()) {
prerender_frame_tree_node_id_ = RenderFrameHost::kNoFrameTreeNodeId;
}
}
void NavigationRequest::MaybeInjectIsolatedAppHeaders() {
BrowserContext* browser_context =
frame_tree_node()->navigator().controller().GetBrowserContext();
if (!SiteIsolationPolicy::ShouldUrlUseApplicationIsolationLevel(
browser_context, GetURL())) {
return;
}
network::CrossOriginOpenerPolicy coop;
coop.value =
network::mojom::CrossOriginOpenerPolicyValue::kSameOriginPlusCoep;
coop.soap_by_default_value =
network::mojom::CrossOriginOpenerPolicyValue::kSameOriginPlusCoep;
response()->parsed_headers->cross_origin_opener_policy = coop;
network::CrossOriginEmbedderPolicy coep;
coep.value = network::mojom::CrossOriginEmbedderPolicyValue::kRequireCorp;
response()->parsed_headers->cross_origin_embedder_policy = coep;
response()->headers->SetHeader(
network::CrossOriginResourcePolicy::kHeaderName, "same-origin");
}
void NavigationRequest::RendererCancellationWindowEnded() {
renderer_cancellation_window_ended_ = true;
renderer_cancellation_listener_.reset();
if (renderer_cancellation_window_ended_callback_) {
std::move(renderer_cancellation_window_ended_callback_).Run();
}
}
bool NavigationRequest::ShouldWaitForRendererCancellationWindowToEnd() {
return renderer_cancellation_listener_.is_bound() &&
!renderer_cancellation_window_ended_;
}
NavigationRequest::ScopedCrashKeys::ScopedCrashKeys(
NavigationRequest& navigation_request)
: initiator_origin_(
GetNavigationRequestInitiatorCrashKey(),
base::OptionalToPtr(navigation_request.GetInitiatorOrigin())),
url_(GetNavigationRequestUrlCrashKey(), navigation_request.GetURL()),
is_same_document_(
GetNavigationRequestIsSameDocumentCrashKey(),
navigation_request.IsSameDocument() ? "same-doc" : "cross-doc") {}
NavigationRequest::ScopedCrashKeys::~ScopedCrashKeys() = default;
PrerenderTriggerType NavigationRequest::GetPrerenderTriggerType() {
DCHECK(prerender_trigger_type_.has_value());
return prerender_trigger_type_.value();
}
std::string NavigationRequest::GetPrerenderEmbedderHistogramSuffix() {
return prerender_embedder_histogram_suffix_;
}
#if BUILDFLAG(IS_ANDROID)
const base::android::JavaRef<jobject>&
NavigationRequest::GetJavaNavigationHandle() {
return navigation_handle_proxy_->java_navigation_handle();
}
#endif
void NavigationRequest::SetViewTransitionState(
blink::ViewTransitionState view_transition_state) {
commit_params_->view_transition_state = std::move(view_transition_state);
}
blink::RuntimeFeatureStateContext&
NavigationRequest::GetMutableRuntimeFeatureStateContext() {
DCHECK_LE(state_, NavigationState::READY_TO_COMMIT);
return runtime_feature_state_context_;
}
const blink::RuntimeFeatureStateContext&
NavigationRequest::GetRuntimeFeatureStateContext() {
return runtime_feature_state_context_;
}
void NavigationRequest::ComputeDownloadPolicy() {
if (GetNavigationEntry() && GetNavigationEntry()->IsViewSourceMode()) {
download_policy().SetDisallowed(blink::NavigationDownloadType::kViewSource);
}
if ((commit_params_->frame_policy.sandbox_flags &
network::mojom::WebSandboxFlags::kDownloads) ==
network::mojom::WebSandboxFlags::kDownloads) {
download_policy().SetDisallowed(blink::NavigationDownloadType::kSandbox);
}
}
bool NavigationRequest::ShouldQueueDueToExistingPendingCommitRFH() const {
CHECK_EQ(this, frame_tree_node_->navigation_request());
CHECK(state_ < READY_TO_COMMIT || state_ == WILL_FAIL_REQUEST);
if (RenderFrameHostImpl* speculative_rfh =
frame_tree_node_->render_manager()->speculative_frame_host()) {
return speculative_rfh->HasPendingCommitForCrossDocumentNavigation();
}
return false;
}
void NavigationRequest::PostResumeCommitTask() {
DCHECK(ShouldAvoidRedundantNavigationCancellations());
DCHECK(!ShouldQueueDueToExistingPendingCommitRFH());
if (resume_commit_closure_) {
base::SequencedTaskRunner::GetCurrentDefault()->PostNonNestableTask(
FROM_HERE, std::move(resume_commit_closure_));
}
}
void NavigationRequest::
MaybeRegisterOriginForUnpartitionedSessionStorageAccess() {
if (!common_params_ || !response_head_ || !response_head_->headers ||
!GetRenderFrameHost()->IsOutermostMainFrame()) {
return;
}
if (!blink::TrialTokenValidator().RequestEnablesDeprecatedFeature(
common_params_->url, response_head_->headers.get(),
"DisableThirdPartySessionStoragePartitioningAfterGeneralPartitioning",
base::Time::Now())) {
frame_tree_node()
->frame_tree()
.UnregisterOriginForUnpartitionedSessionStorageAccess(
url::Origin::Create(common_params_->url));
return;
}
frame_tree_node()
->frame_tree()
.RegisterOriginForUnpartitionedSessionStorageAccess(
url::Origin::Create(common_params_->url));
}
void NavigationRequest::CheckSoftNavigationHeuristicsInvariants() {
if (!commit_params_->soft_navigation_heuristics_task_id) {
return;
}
DCHECK(IsSameDocument());
DCHECK(IsInMainFrame());
DCHECK(!frame_tree_node()->IsFencedFrameRoot());
}
StoragePartition* NavigationRequest::GetStoragePartitionWithCurrentSiteInfo() {
return frame_tree_node_->navigator()
.controller()
.GetBrowserContext()
->GetStoragePartition(site_info_.storage_partition_config());
}
bool NavigationRequest::GetIsThirdPartyCookiesUserBypassEnabled() {
if (IsInMainFrame()) {
blink::RuntimeFeatureStateContext state_context =
GetRuntimeFeatureStateContext();
return state_context.IsThirdPartyCookiesUserBypassEnabled();
}
return GetParentFrame()->GetIsThirdPartyCookiesUserBypassEnabled();
}
void NavigationRequest::CreateWebUIIfNeeded(RenderFrameHostImpl* frame_host) {
TRACE_EVENT1("content", "NavigationRequest::CreateWebUI", "url", GetURL());
WebUI::TypeID new_web_ui_type =
WebUIControllerFactoryRegistry::GetInstance()->GetWebUIType(
frame_tree_node_->navigator().controller().GetBrowserContext(),
GetURL());
if (new_web_ui_type == WebUI::kNoWebUI) {
return;
}
CHECK(!web_ui_);
if (frame_host && frame_host->web_ui()) {
CHECK_EQ(new_web_ui_type, frame_host->web_ui_type());
return;
}
web_ui_ = std::make_unique<WebUIImpl>(this);
std::unique_ptr<WebUIController> controller(
WebUIControllerFactoryRegistry::GetInstance()
->CreateWebUIControllerForURL(web_ui_.get(), GetURL()));
if (bindings() != FrameNavigationEntry::kInvalidBindings &&
bindings() != web_ui_->GetBindings()) {
RecordAction(base::UserMetricsAction("ProcessSwapBindingsMismatch_RVHM"));
base::WeakPtr<NavigationRequest> self = GetWeakPtr();
controller.reset();
web_ui_.reset();
CHECK(self);
return;
}
web_ui_->SetController(std::move(controller));
}
#if BUILDFLAG(IS_OHOS_PRPP)
network::mojom::NetworkContext* NavigationRequest::GetNetworkContext() const
{
if (!common_params_) {
LOG(DEBUG) << "PRPPreload.NavigationRequest::GetNetworkContext, no common_params";
return nullptr;
}
if (common_params_->url.spec() == "about:blank") {
LOG(DEBUG) << "PRPPreload.NavigationRequest::GetNetworkContext, blank page not need";
return nullptr;
}
if (!frame_tree_node_) {
LOG(DEBUG) << "PRPPreload.NavigationRequest::GetNetworkContext, no frame_tree_node";
return nullptr;
}
if (!frame_tree_node_->IsMainFrame()) {
LOG(DEBUG) << "PRPPreload.NavigationRequest::GetNetworkContext, not main frame";
return nullptr;
}
if (!frame_tree_node_->current_frame_host()) {
LOG(DEBUG) << "PRPPreload.NavigationRequest::GetNetworkContext, no current_frame_host";
return nullptr;
}
if (!frame_tree_node_->current_frame_host()->GetStoragePartition()) {
LOG(DEBUG) << "PRPPreload.NavigationRequest::GetNetworkContext, no storage_partition";
return nullptr;
}
return frame_tree_node_->current_frame_host()->GetStoragePartition()->GetNetworkContext();
}
using StartPageCallback__ = base::OnceCallback<void(const std::string&)>;
void NavigationRequest::StartPage(const net::NetworkAnonymizationKey& networkAnonymizationKey,
uint64_t addr_web_handle)
{
network::mojom::NetworkContext* network_context = GetNetworkContext();
if (!network_context) {
return;
}
addr_web_handle_ = addr_web_handle;
network_context->StartPage(common_params_->url.spec(), networkAnonymizationKey, addr_web_handle_,
mojo::WrapCallbackWithDefaultInvokeIfNotRun(base::BindOnce(&NavigationRequest::OnGetIsolation,
weak_factory_.GetWeakPtr()), ORIGIN));
}
void NavigationRequest::OnGetIsolation(const std::string& origin)
{
if (origin.starts_with(ORIGIN)) {
LOG(DEBUG) << "PRPPreload.NavigationRequest::OnGetIsolation, canceled";
return;
}
network::mojom::NetworkContext* network_context = GetNetworkContext();
if (!network_context) {
return;
}
url::Origin url_origin = url::Origin::Create(GURL(origin));
net::IsolationInfo prp_isolation =
frame_tree_node_->current_frame_host()->ComputeIsolationInfoForSubresourcesForPendingCommit(
url_origin, is_credentialless(), ComputeFencedFrameNonce());
network::mojom::URLLoaderFactoryParamsPtr params = network::mojom::URLLoaderFactoryParams::New();
if (params) {
params->isolation_info = prp_isolation;
params->main_url = common_params_->url.spec();
network_context->SetURLLoaderFactoryParam(std::move(params));
}
}
#endif
}