#include "content/browser/renderer_host/render_frame_host_impl.h"
#include <cstdint>
#include <memory>
#include <tuple>
#include <unordered_map>
#include <utility>
#include "base/command_line.h"
#include "base/containers/contains.h"
#include "base/containers/cxx20_erase.h"
#include "base/debug/crash_logging.h"
#include "base/debug/dump_without_crashing.h"
#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/lazy_instance.h"
#include "base/memory/memory_pressure_monitor.h"
#include "base/memory/ptr_util.h"
#include "base/memory/raw_ptr.h"
#include "base/metrics/field_trial_params.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/metrics_hashes.h"
#include "base/metrics/user_metrics.h"
#include "base/no_destructor.h"
#include "base/numerics/safe_conversions.h"
#include "base/process/kill.h"
#include "base/ranges/algorithm.h"
#include "base/state_transitions.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
#include "base/syslog_logging.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/single_thread_task_runner.h"
#include "base/task/thread_pool.h"
#include "base/threading/sequence_bound.h"
#include "base/time/time.h"
#include "base/timer/elapsed_timer.h"
#include "base/trace_event/optional_trace_event.h"
#include "base/types/optional_util.h"
#include "build/build_config.h"
#include "components/download/public/common/download_url_parameters.h"
#include "content/browser/about_url_loader_factory.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
#include "content/browser/accessibility/render_accessibility_host.h"
#include "content/browser/bad_message.h"
#include "content/browser/bluetooth/web_bluetooth_service_impl.h"
#include "content/browser/broadcast_channel/broadcast_channel_provider.h"
#include "content/browser/broadcast_channel/broadcast_channel_service.h"
#include "content/browser/browser_main_loop.h"
#include "content/browser/browsing_topics/browsing_topics_url_loader_service.h"
#include "content/browser/can_commit_status.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/code_cache/generated_code_cache_context.h"
#include "content/browser/data_url_loader_factory.h"
#include "content/browser/devtools/devtools_instrumentation.h"
#include "content/browser/dom_storage/dom_storage_context_wrapper.h"
#include "content/browser/download/data_url_blob_reader.h"
#include "content/browser/feature_observer.h"
#include "content/browser/fenced_frame/fenced_frame.h"
#include "content/browser/fenced_frame/fenced_frame_reporter.h"
#include "content/browser/fenced_frame/fenced_frame_url_mapping.h"
#include "content/browser/file_system/file_system_manager_impl.h"
#include "content/browser/file_system/file_system_url_loader_factory.h"
#include "content/browser/file_system_access/file_system_access_manager_impl.h"
#include "content/browser/font_access/font_access_manager.h"
#include "content/browser/generic_sensor/sensor_provider_proxy_impl.h"
#include "content/browser/geolocation/geolocation_service_impl.h"
#include "content/browser/idle/idle_manager_impl.h"
#include "content/browser/installedapp/installed_app_provider_impl.h"
#include "content/browser/interest_group/ad_auction_document_data.h"
#include "content/browser/loader/file_url_loader_factory.h"
#include "content/browser/loader/keep_alive_url_loader_service.h"
#include "content/browser/loader/navigation_early_hints_manager.h"
#include "content/browser/loader/prefetch_url_loader_service.h"
#include "content/browser/loader/resource_cache_manager.h"
#include "content/browser/log_console_message.h"
#include "content/browser/media/media_interface_proxy.h"
#include "content/browser/media/webaudio/audio_context_manager_impl.h"
#include "content/browser/navigation_or_document_handle.h"
#include "content/browser/navigation_subresource_loader_params.h"
#include "content/browser/network/cross_origin_embedder_policy_reporter.h"
#include "content/browser/network/cross_origin_opener_policy_reporter.h"
#include "content/browser/permissions/permission_controller_impl.h"
#include "content/browser/permissions/permission_service_context.h"
#include "content/browser/portal/portal.h"
#include "content/browser/preloading/prerender/prerender_final_status.h"
#include "content/browser/preloading/prerender/prerender_host_registry.h"
#include "content/browser/preloading/prerender/prerender_metrics.h"
#include "content/browser/presentation/presentation_service_impl.h"
#include "content/browser/process_lock.h"
#include "content/browser/push_messaging/push_messaging_manager.h"
#include "content/browser/renderer_host/agent_scheduling_group_host.h"
#include "content/browser/renderer_host/back_forward_cache_disable.h"
#include "content/browser/renderer_host/back_forward_cache_impl.h"
#include "content/browser/renderer_host/close_listener_host.h"
#include "content/browser/renderer_host/code_cache_host_impl.h"
#include "content/browser/renderer_host/cookie_utils.h"
#include "content/browser/renderer_host/dip_util.h"
#include "content/browser/renderer_host/frame_tree.h"
#include "content/browser/renderer_host/frame_tree_node.h"
#include "content/browser/renderer_host/input/input_injector_impl.h"
#include "content/browser/renderer_host/input/input_router.h"
#include "content/browser/renderer_host/input/timeout_monitor.h"
#include "content/browser/renderer_host/ipc_utils.h"
#include "content/browser/renderer_host/local_network_access_util.h"
#include "content/browser/renderer_host/media/peer_connection_tracker_host.h"
#include "content/browser/renderer_host/navigation_controller_impl.h"
#include "content/browser/renderer_host/navigation_entry_impl.h"
#include "content/browser/renderer_host/navigation_request.h"
#include "content/browser/renderer_host/navigator.h"
#include "content/browser/renderer_host/page_factory.h"
#include "content/browser/renderer_host/pending_beacon_host.h"
#include "content/browser/renderer_host/pending_beacon_service.h"
#include "content/browser/renderer_host/render_frame_host_delegate.h"
#include "content/browser/renderer_host/render_frame_host_owner.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/render_widget_host_factory.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/browser/renderer_host/render_widget_host_view_child_frame.h"
#include "content/browser/renderer_host/view_transition_opt_in_state.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_container_host.h"
#include "content/browser/service_worker/service_worker_object_host.h"
#include "content/browser/site_info.h"
#include "content/browser/sms/webotp_service.h"
#include "content/browser/speech/speech_synthesis_impl.h"
#include "content/browser/storage_partition_impl.h"
#include "content/browser/url_loader_factory_params_helper.h"
#include "content/browser/usb/web_usb_service_impl.h"
#include "content/browser/web_exposed_isolation_info.h"
#include "content/browser/web_package/prefetched_signed_exchange_cache.h"
#include "content/browser/web_package/subresource_web_bundle_navigation_info.h"
#include "content/browser/webauth/authenticator_impl.h"
#include "content/browser/webauth/webauth_request_security_checker.h"
#include "content/browser/webid/federated_auth_request_impl.h"
#include "content/browser/webid/flags.h"
#include "content/browser/websockets/websocket_connector_impl.h"
#include "content/browser/webtransport/web_transport_connector_impl.h"
#include "content/browser/webui/url_data_manager_backend.h"
#include "content/browser/webui/web_ui_controller_factory_registry.h"
#include "content/browser/worker_host/dedicated_worker_host.h"
#include "content/browser/worker_host/dedicated_worker_host_factory_impl.h"
#include "content/browser/worker_host/dedicated_worker_hosts_for_document.h"
#include "content/common/associated_interfaces.mojom.h"
#include "content/common/content_navigation_policy.h"
#include "content/common/debug_utils.h"
#include "content/common/features.h"
#include "content/common/frame.mojom.h"
#include "content/common/frame_messages.mojom.h"
#include "content/common/navigation_client.mojom.h"
#include "content/common/navigation_params_utils.h"
#include "content/public/browser/active_url_message_filter.h"
#include "content/public/browser/ax_event_notification_details.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/context_menu_params.h"
#include "content/public/browser/disallow_activation_reason.h"
#include "content/public/browser/document_ref.h"
#include "content/public/browser/document_service_internal.h"
#include "content/public/browser/download_manager.h"
#include "content/public/browser/global_routing_id.h"
#include "content/public/browser/peak_gpu_memory_tracker.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/shared_cors_origin_access_list.h"
#include "content/public/browser/site_isolation_policy.h"
#include "content/public/browser/sms_fetcher.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/weak_document_ptr.h"
#include "content/public/browser/web_ui_url_loader_factory.h"
#include "content/public/common/alternative_error_page_override_info.mojom.h"
#include "content/public/common/bindings_policy.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/extra_mojo_js_features.mojom.h"
#include "content/public/common/isolated_world_ids.h"
#include "content/public/common/network_service_util.h"
#include "content/public/common/origin_util.h"
#include "content/public/common/page_visibility_state.h"
#include "content/public/common/referrer.h"
#include "content/public/common/referrer_type_converters.h"
#include "content/public/common/url_constants.h"
#include "content/public/common/url_utils.h"
#include "media/base/media_switches.h"
#include "media/learning/common/value.h"
#include "media/media_buildflags.h"
#include "media/mojo/mojom/remoting.mojom.h"
#include "media/mojo/services/video_decode_perf_history.h"
#include "media/render_frame_audio_output_stream_factory.h"
#include "mojo/public/cpp/bindings/message.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "mojo/public/cpp/bindings/struct_ptr.h"
#include "mojo/public/cpp/system/data_pipe.h"
#if BUILDFLAG(IS_OHOS)
#include "mojo/public/cpp/system/platform_handle.h"
#endif
#include "net/base/schemeful_site.h"
#include "net/net_buildflags.h"
#include "ppapi/buildflags/buildflags.h"
#include "render_frame_host_impl.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
#include "services/network/public/cpp/cors/origin_access_list.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/is_potentially_trustworthy.h"
#include "services/network/public/cpp/network_service_buildflags.h"
#include "services/network/public/cpp/not_implemented_url_loader_factory.h"
#include "services/network/public/cpp/simple_url_loader.h"
#include "services/network/public/cpp/web_sandbox_flags.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "services/network/public/mojom/web_sandbox_flags.mojom-shared.h"
#include "services/service_manager/public/cpp/interface_provider.h"
#include "storage/browser/blob/blob_url_store_impl.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
#include "third_party/blink/public/common/chrome_debug_urls.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/features_generated.h"
#include "third_party/blink/public/common/fenced_frame/fenced_frame_utils.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/frame/frame_policy.h"
#include "third_party/blink/public/common/loader/inter_process_time_ticks_converter.h"
#include "third_party/blink/public/common/loader/resource_type_util.h"
#include "third_party/blink/public/common/messaging/transferable_message.h"
#include "third_party/blink/public/common/navigation/navigation_params_mojom_traits.h"
#include "third_party/blink/public/common/permissions/permission_utils.h"
#include "third_party/blink/public/common/permissions_policy/document_policy.h"
#include "third_party/blink/public/common/permissions_policy/permissions_policy.h"
#include "third_party/blink/public/common/privacy_budget/identifiability_study_document_created.h"
#include "third_party/blink/public/common/privacy_budget/identifiability_study_settings.h"
#include "third_party/blink/public/common/runtime_feature_state/runtime_feature_state_context.h"
#include "third_party/blink/public/common/scheduler/web_scheduler_tracked_feature.h"
#include "third_party/blink/public/common/storage_key/storage_key.h"
#include "third_party/blink/public/mojom/back_forward_cache_not_restored_reasons.mojom.h"
#include "third_party/blink/public/mojom/broadcastchannel/broadcast_channel.mojom.h"
#include "third_party/blink/public/mojom/devtools/inspector_issue.mojom.h"
#include "third_party/blink/public/mojom/frame/frame.mojom.h"
#include "third_party/blink/public/mojom/frame/frame_owner_properties.mojom.h"
#include "third_party/blink/public/mojom/frame/fullscreen.mojom.h"
#include "third_party/blink/public/mojom/frame/media_player_action.mojom.h"
#include "third_party/blink/public/mojom/frame/text_autosizer_page_info.mojom.h"
#include "third_party/blink/public/mojom/loader/resource_load_info.mojom.h"
#include "third_party/blink/public/mojom/loader/transferrable_url_loader.mojom.h"
#include "third_party/blink/public/mojom/navigation/navigation_params.mojom.h"
#include "third_party/blink/public/mojom/opengraph/metadata.mojom.h"
#include "third_party/blink/public/mojom/permissions/permission_status.mojom.h"
#include "third_party/blink/public/mojom/scroll/scroll_into_view_params.mojom.h"
#include "third_party/blink/public/mojom/service_worker/service_worker_object.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.h"
#include "third_party/blink/public/mojom/window_features/window_features.mojom.h"
#include "ui/accessibility/ax_action_handler_registry.h"
#include "ui/accessibility/ax_common.h"
#include "ui/accessibility/ax_tree_update.h"
#include "ui/display/screen.h"
#include "ui/events/event_constants.h"
#include "url/gurl.h"
#include "url/origin.h"
#include "url/url_constants.h"
#if BUILDFLAG(IS_ANDROID)
#include "content/browser/android/content_url_loader_factory.h"
#include "content/browser/android/java_interfaces_impl.h"
#include "content/browser/renderer_host/render_frame_host_android.h"
#include "content/public/browser/android/java_interfaces.h"
#include "content/public/browser/authenticator_request_client_delegate.h"
#else
#include "content/browser/hid/hid_service.h"
#include "content/browser/host_zoom_map_impl.h"
#include "content/browser/serial/serial_service.h"
#endif
#if BUILDFLAG(IS_CHROMEOS)
#include "content/browser/smart_card/smart_card_service.h"
#endif
#if BUILDFLAG(IS_MAC)
#include "content/browser/renderer_host/popup_menu_helper_mac.h"
#endif
#if BUILDFLAG(ENABLE_PPAPI)
#include "content/browser/renderer_host/render_frame_host_impl_ppapi_support.h"
#endif
#if BUILDFLAG(USE_EXTERNAL_POPUP_MENU)
#include "content/browser/renderer_host/render_view_host_delegate_view.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 features {
BASE_FEATURE(kDisableFrameNameUpdateOnNonCurrentRenderFrameHost,
"DisableFrameNameUpdateOnNonCurrentRenderFrameHost",
base::FEATURE_ENABLED_BY_DEFAULT);
BASE_FEATURE(kEvictOnAXEvents,
"EvictOnAXEvents",
#if BUILDFLAG(IS_ANDROID)
base::FEATURE_ENABLED_BY_DEFAULT
#else
base::FEATURE_DISABLED_BY_DEFAULT
#endif
);
BASE_FEATURE(kUnblockSpeechSynthesisForBFCache,
"UnblockSpeechSynthesisForBFCache",
base::FEATURE_DISABLED_BY_DEFAULT);
}
namespace content {
#if defined(AX_FAIL_FAST_BUILD)
int RenderFrameHostImpl::max_accessibility_resets_ = 0;
#else
int RenderFrameHostImpl::max_accessibility_resets_ = 4;
#endif
class RenderFrameHostOrProxy {
public:
RenderFrameHostOrProxy(RenderFrameHostImpl* frame,
RenderFrameProxyHost* proxy) {
DCHECK(!frame || !proxy)
<< "Both frame and proxy can't be non-null at the same time";
if (proxy) {
frame_or_proxy_ = proxy;
return;
}
if (frame) {
frame_or_proxy_ = frame;
return;
}
}
explicit operator bool() { return frame_or_proxy_.index() > 0; }
FrameTreeNode* GetFrameTreeNode() {
if (auto* proxy = GetProxy()) {
return proxy->frame_tree_node();
} else if (auto* frame = GetFrame()) {
return frame->frame_tree_node();
}
return nullptr;
}
RenderFrameHostImpl* GetCurrentFrameHost() {
if (auto* proxy = GetProxy()) {
return proxy->frame_tree_node()->current_frame_host();
} else if (auto* frame = GetFrame()) {
return frame;
}
return nullptr;
}
private:
RenderFrameProxyHost* GetProxy() {
if (auto** proxy = absl::get_if<RenderFrameProxyHost*>(&frame_or_proxy_)) {
return *proxy;
}
return nullptr;
}
RenderFrameHostImpl* GetFrame() {
if (auto** frame = absl::get_if<RenderFrameHostImpl*>(&frame_or_proxy_)) {
return *frame;
}
return nullptr;
}
absl::variant<absl::monostate, RenderFrameHostImpl*, RenderFrameProxyHost*>
frame_or_proxy_;
};
namespace {
constexpr int kUnloadTimeoutInMSec = 500;
constexpr base::TimeDelta kUnloadTimeout =
base::Milliseconds(kUnloadTimeoutInMSec);
constexpr int kSubframeProcessShutdownDelayInMSec = 2 * 1000;
static_assert(kSubframeProcessShutdownDelayInMSec + kUnloadTimeoutInMSec <
RenderProcessHostImpl::kKeepAliveHandleFactoryTimeoutInMSec,
"The maximum process shutdown delay should not exceed the "
"keepalive timeout. This has security implications, see "
"https://crbug.com/1177674.");
#if BUILDFLAG(IS_ANDROID)
const void* const kRenderFrameHostAndroidKey = &kRenderFrameHostAndroidKey;
#endif
BASE_FEATURE(kRenderAccessibilityHostAvoidCopying,
"RenderAccessibilityHostAvoidCopying",
base::FEATURE_ENABLED_BY_DEFAULT);
int g_next_accessibility_reset_token = 1;
bool g_allow_injecting_javascript = false;
const char kDotGoogleDotCom[] = ".google.com";
typedef std::unordered_map<GlobalRenderFrameHostId,
RenderFrameHostImpl*,
GlobalRenderFrameHostIdHasher>
RoutingIDFrameMap;
base::LazyInstance<RoutingIDFrameMap>::DestructorAtExit g_routing_id_frame_map =
LAZY_INSTANCE_INITIALIZER;
typedef std::unordered_set<GlobalRenderFrameHostId,
GlobalRenderFrameHostIdHasher>
RoutingIDIsolatableSandboxedIframesSet;
base::LazyInstance<RoutingIDIsolatableSandboxedIframesSet>::DestructorAtExit
g_routing_id_isolatable_sandboxed_iframes_set = LAZY_INSTANCE_INITIALIZER;
using TokenFrameMap = std::unordered_map<blink::LocalFrameToken,
RenderFrameHostImpl*,
blink::LocalFrameToken::Hasher>;
base::LazyInstance<TokenFrameMap>::Leaky g_token_frame_map =
LAZY_INSTANCE_INITIALIZER;
auto& GetDocumentTokenMap() {
static base::NoDestructor<std::unordered_map<
blink::DocumentToken, RenderFrameHostImpl*, blink::DocumentToken::Hasher>>
map;
return *map;
}
BackForwardCacheMetrics::NotRestoredReason
RendererEvictionReasonToNotRestoredReason(
blink::mojom::RendererEvictionReason reason) {
switch (reason) {
case blink::mojom::RendererEvictionReason::kJavaScriptExecution:
return BackForwardCacheMetrics::NotRestoredReason::kJavaScriptExecution;
case blink::mojom::RendererEvictionReason::
kNetworkRequestDatapipeDrainedAsBytesConsumer:
return BackForwardCacheMetrics::NotRestoredReason::
kNetworkRequestDatapipeDrainedAsBytesConsumer;
case blink::mojom::RendererEvictionReason::kNetworkRequestRedirected:
return BackForwardCacheMetrics::NotRestoredReason::
kNetworkRequestRedirected;
case blink::mojom::RendererEvictionReason::kNetworkRequestTimeout:
return BackForwardCacheMetrics::NotRestoredReason::kNetworkRequestTimeout;
case blink::mojom::RendererEvictionReason::kNetworkExceedsBufferLimit:
return BackForwardCacheMetrics::NotRestoredReason::
kNetworkExceedsBufferLimit;
}
NOTREACHED();
return BackForwardCacheMetrics::NotRestoredReason::kUnknown;
}
class ScopedCommitStateResetter {
public:
explicit ScopedCommitStateResetter(RenderFrameHostImpl* render_frame_host)
: render_frame_host_(render_frame_host) {}
~ScopedCommitStateResetter() {
if (!disabled_) {
render_frame_host_->set_nav_entry_id(0);
}
}
void disable() { disabled_ = true; }
private:
raw_ptr<RenderFrameHostImpl> render_frame_host_;
bool disabled_ = false;
};
void GrantFileAccess(int child_id,
const std::vector<base::FilePath>& file_paths) {
ChildProcessSecurityPolicyImpl* policy =
ChildProcessSecurityPolicyImpl::GetInstance();
for (const auto& file : file_paths) {
if (!policy->CanReadFile(child_id, file))
policy->GrantReadFile(child_id, file);
}
}
#if BUILDFLAG(ENABLE_MEDIA_REMOTING)
class RemoterFactoryImpl final : public media::mojom::RemoterFactory {
public:
RemoterFactoryImpl(int process_id, int routing_id)
: process_id_(process_id), routing_id_(routing_id) {}
RemoterFactoryImpl(const RemoterFactoryImpl&) = delete;
RemoterFactoryImpl& operator=(const RemoterFactoryImpl&) = delete;
private:
void Create(mojo::PendingRemote<media::mojom::RemotingSource> source,
mojo::PendingReceiver<media::mojom::Remoter> receiver) final {
if (auto* host = RenderFrameHostImpl::FromID(process_id_, routing_id_)) {
GetContentClient()->browser()->CreateMediaRemoter(host, std::move(source),
std::move(receiver));
}
}
const int process_id_;
const int routing_id_;
};
#endif
RenderFrameHostOrProxy LookupRenderFrameHostOrProxy(int process_id,
int routing_id) {
RenderFrameHostImpl* rfh =
RenderFrameHostImpl::FromID(process_id, routing_id);
RenderFrameProxyHost* proxy = nullptr;
if (!rfh)
proxy = RenderFrameProxyHost::FromID(process_id, routing_id);
return RenderFrameHostOrProxy(rfh, proxy);
}
RenderFrameHostOrProxy LookupRenderFrameHostOrProxy(
int process_id,
const blink::FrameToken& frame_token) {
if (frame_token.Is<blink::LocalFrameToken>()) {
auto it = g_token_frame_map.Get().find(
frame_token.GetAs<blink::LocalFrameToken>());
if (it == g_token_frame_map.Get().end() ||
process_id != it->second->GetProcess()->GetID()) {
return RenderFrameHostOrProxy(nullptr, nullptr);
}
return RenderFrameHostOrProxy(it->second, nullptr);
}
DCHECK(frame_token.Is<blink::RemoteFrameToken>());
return RenderFrameHostOrProxy(
nullptr, RenderFrameProxyHost::FromFrameToken(
process_id, frame_token.GetAs<blink::RemoteFrameToken>()));
}
void LogRendererKillCrashKeys(const SiteInfo& site_info) {
static auto* const site_info_key = base::debug::AllocateCrashKeyString(
"current_site_info", base::debug::CrashKeySize::Size256);
base::debug::SetCrashKeyString(site_info_key, site_info.GetDebugString());
}
void LogCanCommitOriginAndUrlFailureReason(const std::string& failure_reason) {
static auto* const failure_reason_key = base::debug::AllocateCrashKeyString(
"rfhi_can_commit_failure_reason", base::debug::CrashKeySize::Size64);
base::debug::SetCrashKeyString(failure_reason_key, failure_reason);
}
std::unique_ptr<blink::PendingURLLoaderFactoryBundle> CloneFactoryBundle(
scoped_refptr<blink::URLLoaderFactoryBundle> bundle) {
return base::WrapUnique(static_cast<blink::PendingURLLoaderFactoryBundle*>(
bundle->Clone().release()));
}
void StartDownload(
std::unique_ptr<download::DownloadUrlParameters> parameters,
scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
RenderProcessHost* render_process_host =
RenderProcessHost::FromID(parameters->render_process_host_id());
if (!render_process_host)
return;
BrowserContext* browser_context = render_process_host->GetBrowserContext();
DownloadManager* download_manager = browser_context->GetDownloadManager();
parameters->set_download_source(download::DownloadSource::FROM_RENDERER);
download_manager->DownloadUrl(std::move(parameters),
std::move(blob_url_loader_factory));
}
void OnDataURLRetrieved(
std::unique_ptr<download::DownloadUrlParameters> parameters,
GURL data_url) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (!data_url.is_valid())
return;
parameters->set_url(std::move(data_url));
StartDownload(std::move(parameters), nullptr);
}
network::mojom::TrustTokenOperationPolicyVerdict
DetermineWhetherToForbidTrustTokenOperation(
const RenderFrameHostImpl* frame,
const blink::mojom::CommitNavigationParams& commit_params,
const url::Origin& subframe_origin,
absl::optional<blink::FencedFrame::DeprecatedFencedFrameMode>
fenced_frame_mode_for_navigation,
const network::mojom::TrustTokenOperationType& operation) {
std::unique_ptr<blink::PermissionsPolicy> subframe_policy;
if (frame->IsFencedFrameRoot()) {
CHECK(fenced_frame_mode_for_navigation);
subframe_policy = blink::PermissionsPolicy::CreateForFencedFrame(
subframe_origin, fenced_frame_mode_for_navigation.value());
} else {
if (!frame->GetParent())
return network::mojom::TrustTokenOperationPolicyVerdict::
kPotentiallyPermit;
const blink::PermissionsPolicy* parent_policy =
frame->GetParent()->permissions_policy();
blink::ParsedPermissionsPolicy container_policy =
commit_params.frame_policy.container_policy;
subframe_policy = blink::PermissionsPolicy::CreateFromParentPolicy(
parent_policy, container_policy, subframe_origin);
}
switch (operation) {
case network::mojom::TrustTokenOperationType::kRedemption:
case network::mojom::TrustTokenOperationType::kSigning:
if (subframe_policy->IsFeatureEnabled(
blink::mojom::PermissionsPolicyFeature::kTrustTokenRedemption)) {
return network::mojom::TrustTokenOperationPolicyVerdict::
kPotentiallyPermit;
}
return network::mojom::TrustTokenOperationPolicyVerdict::kForbid;
case network::mojom::TrustTokenOperationType::kIssuance:
if (subframe_policy->IsFeatureEnabled(
blink::mojom::PermissionsPolicyFeature::
kPrivateStateTokenIssuance)) {
return network::mojom::TrustTokenOperationPolicyVerdict::
kPotentiallyPermit;
}
return network::mojom::TrustTokenOperationPolicyVerdict::kForbid;
}
return network::mojom::TrustTokenOperationPolicyVerdict::kForbid;
}
network::mojom::TrustTokenOperationPolicyVerdict
DetermineAfterCommitWhetherToForbidTrustTokenOperation(
RenderFrameHostImpl& impl,
const network::mojom::TrustTokenOperationType& operation) {
switch (operation) {
case network::mojom::TrustTokenOperationType::kRedemption:
case network::mojom::TrustTokenOperationType::kSigning:
if (impl.IsFeatureEnabled(
blink::mojom::PermissionsPolicyFeature::kTrustTokenRedemption)) {
return network::mojom::TrustTokenOperationPolicyVerdict::
kPotentiallyPermit;
}
return network::mojom::TrustTokenOperationPolicyVerdict::kForbid;
case network::mojom::TrustTokenOperationType::kIssuance:
if (impl.IsFeatureEnabled(blink::mojom::PermissionsPolicyFeature::
kPrivateStateTokenIssuance)) {
return network::mojom::TrustTokenOperationPolicyVerdict::
kPotentiallyPermit;
}
return network::mojom::TrustTokenOperationPolicyVerdict::kForbid;
}
return network::mojom::TrustTokenOperationPolicyVerdict::kForbid;
}
bool VerifyThatBrowserAndRendererCalculatedOriginsToCommitMatch(
NavigationRequest* navigation_request,
const mojom::DidCommitProvisionalLoadParams& params) {
DCHECK(navigation_request);
DCHECK(!navigation_request->IsSameDocument());
DCHECK(!navigation_request->IsPageActivation());
if (navigation_request->state() < NavigationRequest::WILL_PROCESS_RESPONSE)
return true;
const url::Origin& renderer_side_origin = params.origin;
std::pair<absl::optional<url::Origin>, std::string>
browser_side_origin_and_debug_info =
navigation_request->GetOriginToCommitWithDebugInfo();
if (renderer_side_origin.scheme() == url::kContentScheme &&
browser_side_origin_and_debug_info.first->opaque()) {
return true;
}
bool origins_match = (browser_side_origin_and_debug_info.first.value() ==
renderer_side_origin);
if (renderer_side_origin.opaque() &&
browser_side_origin_and_debug_info.first->opaque()) {
origins_match = (renderer_side_origin.GetTupleOrPrecursorTupleIfOpaque() ==
browser_side_origin_and_debug_info.first
->GetTupleOrPrecursorTupleIfOpaque());
}
if (!origins_match) {
NavigationRequest::ScopedCrashKeys navigation_request_crash_keys(
*navigation_request);
SCOPED_CRASH_KEY_STRING256(
"", "browser_origin",
browser_side_origin_and_debug_info.first->GetDebugString());
SCOPED_CRASH_KEY_STRING256("", "browser_debug_info",
browser_side_origin_and_debug_info.second);
SCOPED_CRASH_KEY_STRING256(
"", "browser_ready_to_commit_origin",
navigation_request->browser_side_origin_to_commit_with_debug_info()
.first->GetDebugString());
SCOPED_CRASH_KEY_STRING256(
"", "browser_ready_to_commit_debug_info",
navigation_request->browser_side_origin_to_commit_with_debug_info()
.second);
SCOPED_CRASH_KEY_STRING256("", "renderer_origin",
renderer_side_origin.GetDebugString());
SCOPED_CRASH_KEY_STRING256("", "renderer_debug_info",
params.origin_calculation_debug_info);
CaptureTraceForNavigationDebugScenario(
DebugScenario::kDebugBrowserVsRendererOriginToCommit);
base::debug::DumpWithoutCrashing();
DCHECK_EQ(browser_side_origin_and_debug_info.first.value(),
renderer_side_origin)
<< "; navigation_request->GetURL() = " << navigation_request->GetURL();
return false;
}
return true;
}
enum class VerifyDidCommitParamsDifference {
kIntendedAsNewEntry = 0,
kMethod = 1,
kURLIsUnreachable = 2,
kBaseURL = 3,
kPostID = 4,
kIsOverridingUserAgent = 5,
kHTTPStatusCode = 6,
kShouldUpdateHistory = 7,
kGesture = 8,
kShouldReplaceCurrentEntry = 9,
kURL = 10,
kDidCreateNewEntry = 11,
kTransition = 12,
kHistoryListWasCleared = 13,
kOrigin = 14,
kMaxValue = kOrigin,
};
enum class RendererLoadType {
kStandard,
kBackForward,
kReload,
kReplaceCurrentItem,
};
enum class SSLSubresourceResponseType {
kIgnored = 0,
kProcessed = 1,
kMaxValue = kProcessed,
};
bool ValidateCSPAttribute(const std::string& value) {
static const size_t kMaxLengthCSPAttribute = 4096;
if (!base::IsStringASCII(value))
return false;
if (value.length() > kMaxLengthCSPAttribute ||
value.find('\n') != std::string::npos ||
value.find('\r') != std::string::npos) {
return false;
}
return true;
}
perfetto::protos::pbzero::FrameDeleteIntention FrameDeleteIntentionToProto(
mojom::FrameDeleteIntention intent) {
using ProtoLevel = perfetto::protos::pbzero::FrameDeleteIntention;
switch (intent) {
case mojom::FrameDeleteIntention::kNotMainFrame:
return ProtoLevel::FRAME_DELETE_INTENTION_NOT_MAIN_FRAME;
case mojom::FrameDeleteIntention::kSpeculativeMainFrameForShutdown:
return ProtoLevel::
FRAME_DELETE_INTENTION_SPECULATIVE_MAIN_FRAME_FOR_SHUTDOWN;
case mojom::FrameDeleteIntention::
kSpeculativeMainFrameForNavigationCancelled:
return ProtoLevel::
FRAME_DELETE_INTENTION_SPECULATIVE_MAIN_FRAME_FOR_NAVIGATION_CANCELLED;
}
NOTREACHED();
return ProtoLevel::FRAME_DELETE_INTENTION_NOT_MAIN_FRAME;
}
void WriteRenderFrameImplDeletion(perfetto::EventContext& ctx,
RenderFrameHostImpl* rfh,
mojom::FrameDeleteIntention intent) {
auto* event = ctx.event<perfetto::protos::pbzero::ChromeTrackEvent>();
auto* data = event->set_render_frame_impl_deletion();
data->set_has_pending_commit(rfh->HasPendingCommitNavigation());
data->set_has_pending_cross_document_commit(
rfh->HasPendingCommitForCrossDocumentNavigation());
data->set_frame_tree_node_id(rfh->GetFrameTreeNodeId());
data->set_intent(FrameDeleteIntentionToProto(intent));
}
base::TimeDelta GetSubframeProcessShutdownDelay(
BrowserContext* browser_context) {
static constexpr base::TimeDelta kZeroDelay;
if (!base::FeatureList::IsEnabled(features::kSubframeShutdownDelay))
return kZeroDelay;
const auto* const memory_monitor = base::MemoryPressureMonitor::Get();
if (memory_monitor &&
memory_monitor->GetCurrentPressureLevel() >=
base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE) {
return kZeroDelay;
}
return base::Milliseconds(kSubframeProcessShutdownDelayInMSec);
}
GURL GetLastDocumentURL(
NavigationRequest* request,
const mojom::DidCommitProvisionalLoadParams& params,
bool last_document_is_error_document,
const RenderFrameHostImpl::RendererURLInfo& renderer_url_info) {
if (request->DidEncounterError() ||
(request->IsSameDocument() && last_document_is_error_document)) {
return GURL(kUnreachableWebDataURL);
}
if (request->IsLoadDataWithBaseURL()) {
return request->common_params().base_url_for_data_url;
}
if (renderer_url_info.was_loaded_from_load_data_with_base_url &&
request->IsSameDocument()) {
return renderer_url_info.last_document_url;
}
return params.url;
}
bool IsAvoidUnnecessaryBeforeUnloadCheckSyncEnabled() {
const bool is_feature_enabled = base::FeatureList::IsEnabled(
features::kAvoidUnnecessaryBeforeUnloadCheckSync);
#if BUILDFLAG(IS_ANDROID)
return is_feature_enabled &&
GetContentClient()
->browser()
->SupportsAvoidUnnecessaryBeforeUnloadCheckSync();
#else
return is_feature_enabled;
#endif
}
bool IsAvoidUnnecessaryBeforeUnloadCheckPostTaskEnabled() {
return !IsAvoidUnnecessaryBeforeUnloadCheckSyncEnabled();
}
bool IsWindowManagementGranted(RenderFrameHost* host) {
content::PermissionController* permission_controller =
host->GetBrowserContext()->GetPermissionController();
DCHECK(permission_controller);
return permission_controller->GetPermissionStatusForCurrentDocument(
blink::PermissionType::WINDOW_MANAGEMENT, host) ==
blink::mojom::PermissionStatus::GRANTED;
}
bool IsOpenGraphMetadataValid(const blink::mojom::OpenGraphMetadata* metadata) {
return !metadata->image || metadata->image->SchemeIsHTTPOrHTTPS();
}
void ForwardOpenGraphMetadataIfValid(
base::OnceCallback<void(blink::mojom::OpenGraphMetadataPtr)> callback,
blink::mojom::OpenGraphMetadataPtr metadata) {
if (IsOpenGraphMetadataValid(metadata.get()))
std::move(callback).Run(std::move(metadata));
else
std::move(callback).Run({});
}
blink::mojom::LocalFrame::JavaScriptExecuteRequestForTestsCallback
CreateJavaScriptExecuteRequestForTestsCallback(
RenderFrameHost::JavaScriptResultCallback callback) {
if (!callback)
return base::NullCallback();
return base::BindOnce(
[](RenderFrameHost::JavaScriptResultCallback callback,
blink::mojom::JavaScriptExecutionResultType type, base::Value value) {
if (type == blink::mojom::JavaScriptExecutionResultType::kSuccess)
std::move(callback).Run(value.Clone());
else
std::move(callback).Run(base::Value());
},
std::move(callback));
}
bool ValidateUnfencedTopNavigation(
RenderFrameHostImpl* render_frame_host,
GURL& url,
int initiator_process_id,
const scoped_refptr<network::ResourceRequestBody>& post_body,
bool user_gesture) {
render_frame_host->GetSiteInstance()->GetProcess()->FilterURL(
false, &url);
if ((render_frame_host->frame_tree_node()->GetDeprecatedFencedFrameMode() !=
blink::FencedFrame::DeprecatedFencedFrameMode::kOpaqueAds) ||
render_frame_host->IsSandboxed(
network::mojom::WebSandboxFlags::kTopNavigationByUserActivation)) {
bad_message::ReceivedBadMessage(
initiator_process_id,
bad_message::RFHI_UNFENCED_TOP_IPC_OUTSIDE_FENCED_FRAME);
return false;
}
if (url.SchemeIs(url::kJavaScriptScheme)) {
render_frame_host->AddMessageToConsole(
blink::mojom::ConsoleMessageLevel::kError,
"The frame attempting navigation must be in the same fenced "
"frame tree as the target if navigating to a javascript: url");
return false;
}
if (url.SchemeIs(url::kBlobScheme)) {
render_frame_host->AddMessageToConsole(
blink::mojom::ConsoleMessageLevel::kError,
"_unfencedTop may not be used with a blob: url");
return false;
}
if (post_body) {
render_frame_host->AddMessageToConsole(
blink::mojom::ConsoleMessageLevel::kError,
"_unfencedTop may not be used to send POST requests");
return false;
}
if (!user_gesture) {
render_frame_host->AddMessageToConsole(
blink::mojom::ConsoleMessageLevel::kError,
"The frame attempting navigation of the top-level window is "
"sandboxed with the 'allow-top-navigation-by-user-activation' "
"flag, but has no user activation (aka gesture). See "
"https://www.chromestatus.com/feature/5629582019395584.");
return false;
}
return true;
}
void RecordIdentifiabilityDocumentCreatedMetrics(
const ukm::SourceId document_ukm_source_id,
ukm::UkmRecorder* ukm_recorder,
ukm::SourceId navigation_source_id,
bool is_cross_origin_frame,
bool is_cross_site_frame,
bool is_main_frame) {
if (blink::IdentifiabilityStudySettings::Get()->IsActive()) {
blink::IdentifiabilityStudyDocumentCreated(document_ukm_source_id)
.SetNavigationSourceId(navigation_source_id)
.SetIsMainFrame(is_main_frame)
.SetIsCrossOriginFrame(is_cross_origin_frame)
.SetIsCrossSiteFrame(is_cross_site_frame)
.Record(ukm_recorder);
}
}
bool PopupInheritCOOP(const RenderFrameHostImpl* opener) {
return opener->GetLastCommittedOrigin() ==
opener->GetMainFrame()->GetLastCommittedOrigin();
}
bool CoopSuppressOpener(const RenderFrameHostImpl* opener) {
switch (opener->GetMainFrame()->cross_origin_opener_policy().value) {
case network::mojom::CrossOriginOpenerPolicyValue::kUnsafeNone:
case network::mojom::CrossOriginOpenerPolicyValue::kSameOriginAllowPopups:
return false;
case network::mojom::CrossOriginOpenerPolicyValue::kRestrictProperties:
case network::mojom::CrossOriginOpenerPolicyValue::
kRestrictPropertiesPlusCoep:
case network::mojom::CrossOriginOpenerPolicyValue::kSameOrigin:
case network::mojom::CrossOriginOpenerPolicyValue::kSameOriginPlusCoep:
return !PopupInheritCOOP(opener);
}
}
}
class RenderFrameHostImpl::SubresourceLoaderFactoriesConfig {
public:
static SubresourceLoaderFactoriesConfig ForLastCommittedNavigation(
RenderFrameHostImpl& frame) {
SubresourceLoaderFactoriesConfig result;
result.origin_ = frame.GetLastCommittedOrigin();
result.isolation_info_ = frame.GetIsolationInfoForSubresources();
result.client_security_state_ = frame.BuildClientSecurityState();
if (frame.coep_reporter_) {
frame.coep_reporter_->Clone(
result.coep_reporter_.BindNewPipeAndPassReceiver());
}
result.trust_token_redemption_policy_ =
DetermineAfterCommitWhetherToForbidTrustTokenOperation(
frame, network::mojom::TrustTokenOperationType::kRedemption);
result.trust_token_issuance_policy_ =
DetermineAfterCommitWhetherToForbidTrustTokenOperation(
frame, network::mojom::TrustTokenOperationType::kIssuance);
result.ukm_source_id_ =
ukm::SourceIdObj::FromInt64(frame.GetPageUkmSourceId());
if (frame.GetIsThirdPartyCookiesUserBypassEnabled()) {
result.cookie_setting_overrides_.Put(
net::CookieSettingOverride::kForceThirdPartyByUser);
}
return result;
}
static SubresourceLoaderFactoriesConfig ForPendingNavigation(
NavigationRequest& navigation_request) {
SubresourceLoaderFactoriesConfig result;
#if BUILDFLAG(IS_OHOS_PRPP)
result.main_url_ = navigation_request.common_params().url;
result.addr_web_handle_ = navigation_request.GetAddrWebHandle();
#endif
result.origin_ = navigation_request.GetOriginToCommit().value();
result.client_security_state_ =
navigation_request.BuildClientSecurityState();
result.ukm_source_id_ = ukm::SourceIdObj::FromInt64(
navigation_request.GetNextPageUkmSourceId());
if (navigation_request.DidEncounterError()) {
result.isolation_info_ = net::IsolationInfo::CreateTransient();
result.trust_token_redemption_policy_ =
network::mojom::TrustTokenOperationPolicyVerdict::kForbid;
result.trust_token_issuance_policy_ =
network::mojom::TrustTokenOperationPolicyVerdict::kForbid;
} else {
result.isolation_info_ =
navigation_request.isolation_info_for_subresources();
if (navigation_request.coep_reporter()) {
navigation_request.coep_reporter()->Clone(
result.coep_reporter_.BindNewPipeAndPassReceiver());
}
result.trust_token_redemption_policy_ =
DetermineWhetherToForbidTrustTokenOperation(
navigation_request.GetRenderFrameHost(),
navigation_request.commit_params(), result.origin(),
navigation_request.ComputeDeprecatedFencedFrameMode(),
network::mojom::TrustTokenOperationType::kRedemption);
result.trust_token_issuance_policy_ =
DetermineWhetherToForbidTrustTokenOperation(
navigation_request.GetRenderFrameHost(),
navigation_request.commit_params(), result.origin(),
navigation_request.ComputeDeprecatedFencedFrameMode(),
network::mojom::TrustTokenOperationType::kIssuance);
if (navigation_request.GetIsThirdPartyCookiesUserBypassEnabled()) {
result.cookie_setting_overrides_.Put(
net::CookieSettingOverride::kForceThirdPartyByUser);
}
}
return result;
}
static SubresourceLoaderFactoriesConfig ForPendingOrLastCommittedNavigation(
RenderFrameHostImpl& frame) {
NavigationRequest* navigation_request =
frame.FindLatestNavigationRequestThatIsStillCommitting();
return navigation_request ? ForPendingNavigation(*navigation_request)
: ForLastCommittedNavigation(frame);
}
~SubresourceLoaderFactoriesConfig() = default;
SubresourceLoaderFactoriesConfig(SubresourceLoaderFactoriesConfig&&) =
default;
SubresourceLoaderFactoriesConfig& operator=(
SubresourceLoaderFactoriesConfig&&) = default;
SubresourceLoaderFactoriesConfig(const SubresourceLoaderFactoriesConfig&) =
delete;
SubresourceLoaderFactoriesConfig& operator=(
const SubresourceLoaderFactoriesConfig&) = delete;
const url::Origin& origin() const { return origin_; }
#if BUILDFLAG(IS_OHOS_PRPP)
const GURL& main_url() const { return main_url_; }
uint64_t addr_web_handle() const { return addr_web_handle_; }
#endif
const net::IsolationInfo& isolation_info() const { return isolation_info_; }
network::mojom::ClientSecurityStatePtr GetClientSecurityState() const {
return mojo::Clone(client_security_state_);
}
mojo::PendingRemote<network::mojom::CrossOriginEmbedderPolicyReporter>
GetCoepReporter() const {
mojo::PendingRemote<network::mojom::CrossOriginEmbedderPolicyReporter> p;
if (coep_reporter_) {
coep_reporter_->Clone(p.InitWithNewPipeAndPassReceiver());
}
return p;
}
const network::mojom::TrustTokenOperationPolicyVerdict&
trust_token_redemption_policy() const {
return trust_token_redemption_policy_;
}
const network::mojom::TrustTokenOperationPolicyVerdict&
trust_token_issuance_policy() const {
return trust_token_issuance_policy_;
}
const ukm::SourceIdObj& ukm_source_id() const { return ukm_source_id_; }
const net::CookieSettingOverrides& cookie_setting_overrides() const {
return cookie_setting_overrides_;
}
private:
SubresourceLoaderFactoriesConfig() = default;
#if BUILDFLAG(IS_OHOS_PRPP)
GURL main_url_;
uint64_t addr_web_handle_;
#endif
url::Origin origin_;
net::IsolationInfo isolation_info_;
network::mojom::ClientSecurityStatePtr client_security_state_;
mojo::Remote<network::mojom::CrossOriginEmbedderPolicyReporter>
coep_reporter_;
network::mojom::TrustTokenOperationPolicyVerdict trust_token_issuance_policy_;
network::mojom::TrustTokenOperationPolicyVerdict
trust_token_redemption_policy_;
ukm::SourceIdObj ukm_source_id_;
net::CookieSettingOverrides cookie_setting_overrides_;
};
struct PendingNavigation {
blink::mojom::CommonNavigationParamsPtr common_params;
blink::mojom::BeginNavigationParamsPtr begin_navigation_params;
scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory;
mojo::PendingAssociatedRemote<mojom::NavigationClient> navigation_client;
mojo::PendingReceiver<mojom::NavigationRendererCancellationListener>
renderer_cancellation_listener;
PendingNavigation(
blink::mojom::CommonNavigationParamsPtr common_params,
blink::mojom::BeginNavigationParamsPtr begin_navigation_params,
scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
mojo::PendingAssociatedRemote<mojom::NavigationClient> navigation_client,
mojo::PendingReceiver<mojom::NavigationRendererCancellationListener>
renderer_cancellation_listener);
};
PendingNavigation::PendingNavigation(
blink::mojom::CommonNavigationParamsPtr common_params,
blink::mojom::BeginNavigationParamsPtr begin_navigation_params,
scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
mojo::PendingAssociatedRemote<mojom::NavigationClient> navigation_client,
mojo::PendingReceiver<mojom::NavigationRendererCancellationListener>
renderer_cancellation_listener)
: common_params(std::move(common_params)),
begin_navigation_params(std::move(begin_navigation_params)),
blob_url_loader_factory(std::move(blob_url_loader_factory)),
navigation_client(std::move(navigation_client)),
renderer_cancellation_listener(
std::move(renderer_cancellation_listener)) {}
RenderFrameHost* RenderFrameHost::FromID(const GlobalRenderFrameHostId& id) {
return RenderFrameHostImpl::FromID(id);
}
RenderFrameHost* RenderFrameHost::FromID(int render_process_id,
int render_frame_id) {
return RenderFrameHostImpl::FromID(
GlobalRenderFrameHostId(render_process_id, render_frame_id));
}
RenderFrameHost* RenderFrameHost::FromFrameToken(
int process_id,
const blink::LocalFrameToken& token) {
return RenderFrameHostImpl::FromFrameToken(process_id, token);
}
void RenderFrameHost::AllowInjectingJavaScript() {
g_allow_injecting_javascript = true;
}
RenderFrameHostImpl* RenderFrameHostImpl::FromID(GlobalRenderFrameHostId id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
RoutingIDFrameMap* frames = g_routing_id_frame_map.Pointer();
auto it = frames->find(id);
return it == frames->end() ? nullptr : it->second;
}
RenderFrameHostImpl* RenderFrameHostImpl::FromID(int render_process_id,
int render_frame_id) {
return RenderFrameHostImpl::FromID(
GlobalRenderFrameHostId(render_process_id, render_frame_id));
}
RenderFrameHostImpl* RenderFrameHostImpl::FromFrameToken(
int process_id,
const blink::LocalFrameToken& frame_token,
mojo::ReportBadMessageCallback* process_mismatch_callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
auto it = g_token_frame_map.Get().find(frame_token);
if (it == g_token_frame_map.Get().end())
return nullptr;
if (it->second->GetProcess()->GetID() != process_id) {
if (process_mismatch_callback) {
SYSLOG(WARNING)
<< "Denying illegal RenderFrameHost::FromFrameToken request.";
std::move(*process_mismatch_callback)
.Run(
"Unknown LocalFrame made RenderFrameHost::FromFrameToken "
"request.");
}
return nullptr;
}
return it->second;
}
RenderFrameHostImpl* RenderFrameHostImpl::FromDocumentToken(
int process_id,
const blink::DocumentToken& document_token,
mojo::ReportBadMessageCallback* process_mismatch_callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
const auto it = GetDocumentTokenMap().find(document_token);
if (it == GetDocumentTokenMap().end())
return nullptr;
if (it->second->GetProcess()->GetID() != process_id) {
if (process_mismatch_callback) {
SYSLOG(WARNING)
<< "Denying illegal RenderFrameHost::FromDocumentToken request.";
std::move(*process_mismatch_callback)
.Run("process ID does not match requested DocumentToken");
}
return nullptr;
}
return it->second;
}
RenderFrameHost* RenderFrameHost::FromAXTreeID(const ui::AXTreeID& ax_tree_id) {
return RenderFrameHostImpl::FromAXTreeID(ax_tree_id);
}
RenderFrameHostImpl* RenderFrameHostImpl::FromAXTreeID(
ui::AXTreeID ax_tree_id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
ui::AXActionHandlerRegistry::FrameID frame_id =
ui::AXActionHandlerRegistry::GetInstance()->GetFrameID(ax_tree_id);
return RenderFrameHostImpl::FromID(frame_id.first, frame_id.second);
}
RenderFrameHostImpl* RenderFrameHostImpl::FromOverlayRoutingToken(
const base::UnguessableToken& token) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
auto it = g_token_frame_map.Get().find(blink::LocalFrameToken(token));
return it == g_token_frame_map.Get().end() ? nullptr : it->second;
}
void RenderFrameHostImpl::ClearAllPrefetchedSignedExchangeCache() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
RoutingIDFrameMap* frames = g_routing_id_frame_map.Pointer();
for (auto it : *frames)
it.second->ClearPrefetchedSignedExchangeCache();
}
RenderFrameHostImpl::CodeCacheHostReceiverHandler&
GetCodeCacheHostReceiverHandler() {
static base::NoDestructor<RenderFrameHostImpl::CodeCacheHostReceiverHandler>
instance;
return *instance;
}
void RenderFrameHostImpl::SetCodeCacheHostReceiverHandlerForTesting(
CodeCacheHostReceiverHandler handler) {
GetCodeCacheHostReceiverHandler() = handler;
}
const char* RenderFrameHostImpl::LifecycleStateImplToString(
RenderFrameHostImpl::LifecycleStateImpl state) {
using LifecycleStateImpl = RenderFrameHostImpl::LifecycleStateImpl;
switch (state) {
case LifecycleStateImpl::kSpeculative:
return "Speculative";
case LifecycleStateImpl::kPrerendering:
return "Prerendering";
case LifecycleStateImpl::kPendingCommit:
return "PendingCommit";
case LifecycleStateImpl::kActive:
return "Active";
case LifecycleStateImpl::kInBackForwardCache:
return "InBackForwardCache";
case LifecycleStateImpl::kRunningUnloadHandlers:
return "RunningUnloadHandlers";
case LifecycleStateImpl::kReadyToBeDeleted:
return "ReadyToBeDeleted";
}
}
RenderFrameHostImpl::RenderFrameHostImpl(
SiteInstance* site_instance,
scoped_refptr<RenderViewHostImpl> render_view_host,
RenderFrameHostDelegate* delegate,
FrameTree* frame_tree,
FrameTreeNode* frame_tree_node,
int32_t routing_id,
mojo::PendingAssociatedRemote<mojom::Frame> frame_remote,
const blink::LocalFrameToken& frame_token,
const blink::DocumentToken& document_token,
base::UnguessableToken devtools_frame_token,
bool renderer_initiated_creation_of_main_frame,
LifecycleStateImpl lifecycle_state,
scoped_refptr<BrowsingContextState> browsing_context_state,
blink::FrameOwnerElementType frame_owner_element_type,
RenderFrameHostImpl* parent,
FencedFrameStatus fenced_frame_status)
: render_view_host_(std::move(render_view_host)),
delegate_(delegate),
site_instance_(static_cast<SiteInstanceImpl*>(site_instance)),
agent_scheduling_group_(
site_instance_->GetOrCreateAgentSchedulingGroup().GetSafeRef()),
frame_tree_(frame_tree),
frame_tree_node_(frame_tree_node),
owner_(frame_tree_node),
browsing_context_state_(std::move(browsing_context_state)),
frame_owner_element_type_(frame_owner_element_type),
parent_(parent),
depth_(parent_ ? parent_->GetFrameDepth() + 1 : 0),
last_committed_site_info_(site_instance_->GetBrowserContext()),
routing_id_(routing_id),
beforeunload_timeout_delay_(kUnloadTimeout),
frame_(std::move(frame_remote)),
waiting_for_init_(renderer_initiated_creation_of_main_frame),
frame_token_(frame_token),
keep_alive_handle_factory_(
agent_scheduling_group_->GetProcess(),
RenderProcessHostImpl::kKeepAliveHandleFactoryTimeout),
subframe_unload_timeout_(kUnloadTimeout),
media_device_id_salt_base_(
BrowserContext::CreateRandomMediaDeviceIDSalt()),
document_associated_data_(absl::in_place, *this, document_token),
lifecycle_state_(lifecycle_state),
inner_tree_main_frame_tree_node_id_(
FrameTreeNode::kFrameTreeNodeInvalidId),
code_cache_host_receivers_(
GetProcess()->GetStoragePartition()->GetGeneratedCodeCacheContext()),
fenced_frame_status_(fenced_frame_status),
devtools_frame_token_(devtools_frame_token) {
TRACE_EVENT_BEGIN("navigation", "RenderFrameHostImpl",
perfetto::Track::FromPointer(this),
"render_frame_host_when_created", this);
TRACE_EVENT_BEGIN(
"navigation",
perfetto::StaticString{LifecycleStateImplToString(lifecycle_state_)},
perfetto::Track::FromPointer(this));
DCHECK_NE(routing_id_, MSG_ROUTING_NONE);
DCHECK(delegate_);
DCHECK(lifecycle_state_ == LifecycleStateImpl::kSpeculative ||
lifecycle_state_ == LifecycleStateImpl::kPrerendering ||
lifecycle_state_ == LifecycleStateImpl::kActive);
DCHECK(!waiting_for_init_ || !parent_);
GetAgentSchedulingGroup().AddRoute(routing_id_, this);
g_routing_id_frame_map.Get().emplace(
GlobalRenderFrameHostId(GetProcess()->GetID(), routing_id_), this);
g_token_frame_map.Get().insert(std::make_pair(frame_token_, this));
site_instance_->group()->AddObserver(this);
auto* process = GetProcess();
process->RegisterRenderFrameHost(GetGlobalId());
GetSiteInstance()->group()->IncrementActiveFrameCount();
if (parent_) {
CHECK_EQ(parent_->GetStoragePartition(), GetStoragePartition());
set_nav_entry_id(parent_->nav_entry_id());
}
if (frame_tree_->is_prerendering()) {
mojo_binder_policy_applier_ =
MojoBinderPolicyApplier::CreateForSameOriginPrerendering(base::BindOnce(
&RenderFrameHostImpl::CancelPrerenderingByMojoBinderPolicy,
base::Unretained(this)));
broker_.ApplyMojoBinderPolicies(mojo_binder_policy_applier_.get());
}
if (lifecycle_state_ != LifecycleStateImpl::kSpeculative) {
DCHECK(frame_tree_node_->is_on_initial_empty_document());
}
InitializePolicyContainerHost(renderer_initiated_creation_of_main_frame);
InitializeLocalNetworkRequestPolicy();
unload_event_monitor_timeout_ =
std::make_unique<TimeoutMonitor>(base::BindRepeating(
&RenderFrameHostImpl::OnUnloaded, weak_ptr_factory_.GetWeakPtr()));
beforeunload_timeout_ = std::make_unique<TimeoutMonitor>(
base::BindRepeating(&RenderFrameHostImpl::BeforeUnloadTimeout,
weak_ptr_factory_.GetWeakPtr()));
const bool setup_local_render_widget_host =
is_main_frame() || RequiresProxyToParent();
if (setup_local_render_widget_host) {
if (is_main_frame()) {
DCHECK(GetLocalRenderWidgetHost());
} else {
int32_t widget_routing_id =
site_instance->GetProcess()->GetNextRoutingID();
DCHECK_EQ(nullptr, GetLocalRenderWidgetHost());
owned_render_widget_host_ = RenderWidgetHostFactory::Create(
frame_tree_, frame_tree_->render_widget_delegate(),
site_instance_->group()->GetSafeRef(), widget_routing_id,
true,
false);
}
if (is_main_frame())
GetLocalRenderWidgetHost()->SetIntersectsViewport(true);
GetLocalRenderWidgetHost()->SetFrameDepth(depth_);
}
DCHECK_EQ(setup_local_render_widget_host, is_local_root());
ResetPermissionsPolicy();
virtual_browsing_context_group_ = CrossOriginOpenerPolicyAccessReportManager::
NextVirtualBrowsingContextGroup();
soap_by_default_virtual_browsing_context_group_ =
CrossOriginOpenerPolicyAccessReportManager::
NextVirtualBrowsingContextGroup();
idle_manager_ = std::make_unique<IdleManagerImpl>(this);
}
RenderFrameHostImpl::~RenderFrameHostImpl() {
SCOPED_CRASH_KEY_STRING256("Bug1407526", "lifecycle",
LifecycleStateImplToString(lifecycle_state()));
TRACE_EVENT("navigation", "~RenderFrameHostImpl()",
ChromeTrackEvent::kRenderFrameHost, this);
if (check_deletion_for_bug_1276535_) {
base::debug::DumpWithoutCrashing();
}
g_routing_id_frame_map.Get().erase(
GlobalRenderFrameHostId(GetProcess()->GetID(), routing_id_));
g_routing_id_isolatable_sandboxed_iframes_set.Get().erase(GetGlobalId());
ResetChildren();
ResetOwnedNavigationRequests(
NavigationDiscardReason::kRenderFrameHostDestruction);
base::WeakPtr<RenderFrameHostImpl> self = GetWeakPtr();
ClearWebUI();
CHECK(self);
SetLastCommittedSiteInfo(UrlInfo());
g_token_frame_map.Get().erase(frame_token_);
auto* process = GetProcess();
SCOPED_CRASH_KEY_BOOL("Bug1407526", "si_exists", !!site_instance_);
SCOPED_CRASH_KEY_BOOL("Bug1407526", "sig_exists", !!site_instance_->group());
SCOPED_CRASH_KEY_BOOL("Bug1407526", "process_exists", !!process);
site_instance_->group()->RemoveObserver(this);
process->UnregisterRenderFrameHost(GetGlobalId());
const bool was_created = is_render_frame_created();
SCOPED_CRASH_KEY_BOOL("Bug1407526", "was_created", !!was_created);
SCOPED_CRASH_KEY_BOOL("Bug1407526", "delegate_exists", !!delegate_);
render_frame_state_ = RenderFrameState::kDeleted;
if (was_created)
delegate_->RenderFrameDeleted(this);
if (is_audible_) {
OnAudibleStateChanged(false);
}
document_associated_data_.reset();
GetSiteInstance()->group()->DecrementActiveFrameCount();
if (was_created && render_view_host_->GetMainRenderFrameHost() != this) {
CHECK(IsPendingDeletion() || IsInBackForwardCache() ||
lifecycle_state() == LifecycleStateImpl::kPrerendering ||
lifecycle_state() == LifecycleStateImpl::kSpeculative)
<< lifecycle_state();
}
GetAgentSchedulingGroup().RemoveRoute(routing_id_);
unload_event_monitor_timeout_.reset();
browser_accessibility_manager_.reset();
if (owned_render_widget_host_)
owned_render_widget_host_->ShutdownAndDestroyWidget(false);
ResourceCacheManager* resource_cache_manager =
GetStoragePartition()->GetResourceCacheManager();
if (resource_cache_manager) {
resource_cache_manager->RenderFrameHostBecameIneligible(*this);
}
render_view_host_.reset();
RenderFrameHostImpl* beforeunload_initiator = GetBeforeUnloadInitiator();
if (beforeunload_initiator && beforeunload_initiator != this) {
base::TimeTicks approx_renderer_start_time = send_before_unload_start_time_;
beforeunload_initiator->ProcessBeforeUnloadCompletedFromFrame(
true, false, this,
true, approx_renderer_start_time,
base::TimeTicks::Now(), false);
}
if (prefetched_signed_exchange_cache_)
prefetched_signed_exchange_cache_->RecordHistograms();
TRACE_EVENT_END("navigation", perfetto::Track::FromPointer(this));
TRACE_EVENT_END("navigation", perfetto::Track::FromPointer(this));
}
int RenderFrameHostImpl::GetRoutingID() const {
return routing_id_;
}
const blink::LocalFrameToken& RenderFrameHostImpl::GetFrameToken() const {
return frame_token_;
}
const base::UnguessableToken& RenderFrameHostImpl::GetReportingSource() {
DCHECK(!document_associated_data_->reporting_source().is_empty());
return document_associated_data_->reporting_source();
}
ui::AXTreeID RenderFrameHostImpl::GetAXTreeID() {
return ax_tree_id();
}
const blink::LocalFrameToken& RenderFrameHostImpl::GetTopFrameToken() {
RenderFrameHostImpl* frame = this;
while (frame->parent_) {
frame = frame->parent_;
}
return frame->GetFrameToken();
}
void RenderFrameHostImpl::AudioContextPlaybackStarted(int audio_context_id) {
delegate_->AudioContextPlaybackStarted(this, audio_context_id);
}
void RenderFrameHostImpl::AudioContextPlaybackStopped(int audio_context_id) {
delegate_->AudioContextPlaybackStopped(this, audio_context_id);
}
void RenderFrameHostImpl::DidEnterBackForwardCache() {
TRACE_EVENT0("navigation", "RenderFrameHostImpl::EnterBackForwardCache");
DCHECK(IsBackForwardCacheEnabled());
DCHECK(IsInPrimaryMainFrame());
DidEnterBackForwardCacheInternal();
StartBackForwardCacheEvictionTimer();
for (FrameTreeNode* node : FrameTree::SubtreeAndInnerTreeNodes(
this,
true)) {
if (RenderFrameHostImpl* rfh = node->current_frame_host())
rfh->DidEnterBackForwardCacheInternal();
}
}
void RenderFrameHostImpl::DidEnterBackForwardCacheInternal() {
DCHECK_EQ(lifecycle_state(), LifecycleStateImpl::kActive);
SetLifecycleState(LifecycleStateImpl::kInBackForwardCache);
if (inner_tree_main_frame_tree_node_id_ !=
FrameTreeNode::kFrameTreeNodeInvalidId) {
return;
}
for (auto& entry : service_worker_container_hosts_) {
if (base::WeakPtr<ServiceWorkerContainerHost> host = entry.second)
host->OnEnterBackForwardCache();
}
DedicatedWorkerHostsForDocument::GetOrCreateForCurrentDocument(this)
->OnEnterBackForwardCache();
#if BUILDFLAG(IS_P2P_ENABLED)
GetProcess()->PauseSocketManagerForRenderFrameHost(GetGlobalId());
#endif
#if BUILDFLAG(IS_OHOS)
if (delegate_) {
delegate_->OnRenderFrameHostEnterBackForwardCache(GetGlobalId());
}
#endif
if (auto* permission_service_context =
PermissionServiceContext::GetForCurrentDocument(this)) {
permission_service_context->StoreStatusAtBFCacheEntry();
}
}
void RenderFrameHostImpl::WillLeaveBackForwardCache() {
TRACE_EVENT0("navigation", "RenderFrameHostImpl::LeaveBackForwardCache");
DCHECK(IsBackForwardCacheEnabled());
DCHECK(IsOutermostMainFrame());
if (back_forward_cache_eviction_timer_.IsRunning())
back_forward_cache_eviction_timer_.Stop();
WillLeaveBackForwardCacheInternal();
for (FrameTreeNode* node : FrameTree::SubtreeAndInnerTreeNodes(
this,
true)) {
if (RenderFrameHostImpl* rfh = node->current_frame_host())
rfh->WillLeaveBackForwardCacheInternal();
}
}
void RenderFrameHostImpl::WillLeaveBackForwardCacheInternal() {
DCHECK_EQ(lifecycle_state(), LifecycleStateImpl::kInBackForwardCache);
DCHECK(!back_forward_cache_eviction_timer_.IsRunning());
if (inner_tree_main_frame_tree_node_id_ !=
FrameTreeNode::kFrameTreeNodeInvalidId) {
return;
}
for (auto& entry : service_worker_container_hosts_) {
if (base::WeakPtr<ServiceWorkerContainerHost> host = entry.second)
host->OnRestoreFromBackForwardCache();
}
DedicatedWorkerHostsForDocument::GetOrCreateForCurrentDocument(this)
->OnRestoreFromBackForwardCache();
#if BUILDFLAG(IS_P2P_ENABLED)
GetProcess()->ResumeSocketManagerForRenderFrameHost(GetGlobalId());
#endif
#if BUILDFLAG(IS_OHOS)
if (delegate_) {
delegate_->OnRenderFrameHostLeaveBackForwardCache(GetGlobalId());
}
#endif
}
mojom::DidCommitProvisionalLoadParamsPtr
RenderFrameHostImpl::TakeLastCommitParams() {
return std::move(last_commit_params_);
}
void RenderFrameHostImpl::StartBackForwardCacheEvictionTimer() {
DCHECK(IsInBackForwardCache());
#ifdef OHOS_BFCACHE
base::TimeDelta evict_after =
GetBackForwardCache().ArkWebGetTimeToLiveInBackForwardCache();
#else
base::TimeDelta evict_after =
BackForwardCacheImpl::GetTimeToLiveInBackForwardCache();
#endif
back_forward_cache_eviction_timer_.SetTaskRunner(
GetBackForwardCache().GetTaskRunner());
back_forward_cache_eviction_timer_.Start(
FROM_HERE, evict_after,
base::BindOnce(&RenderFrameHostImpl::EvictFromBackForwardCacheWithReason,
weak_ptr_factory_.GetWeakPtr(),
BackForwardCacheMetrics::NotRestoredReason::kTimeout));
}
void RenderFrameHostImpl::DisableBackForwardCache(
BackForwardCache::DisabledReason reason,
absl::optional<ukm::SourceId> source_id) {
back_forward_cache_disabled_reasons_[reason].insert(source_id);
MaybeEvictFromBackForwardCache();
}
void RenderFrameHostImpl::DisableProactiveBrowsingInstanceSwapForTesting() {
DCHECK(IsInPrimaryMainFrame());
has_test_disabled_proactive_browsing_instance_swap_ = true;
}
void RenderFrameHostImpl::OnGrantedMediaStreamAccess() {
was_granted_media_access_ = true;
MaybeEvictFromBackForwardCache();
}
void RenderFrameHostImpl::OnPortalActivated(
std::unique_ptr<Portal> predecessor,
mojo::PendingAssociatedRemote<blink::mojom::Portal> pending_portal,
mojo::PendingAssociatedReceiver<blink::mojom::PortalClient> client_receiver,
blink::TransferableMessage data,
uint64_t trace_id,
base::OnceCallback<void(blink::mojom::PortalActivateResult)> callback) {
auto it = portals_.insert(std::move(predecessor)).first;
TRACE_EVENT_WITH_FLOW0("navigation", "RenderFrameHostImpl::OnPortalActivated",
TRACE_ID_GLOBAL(trace_id),
TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
GetAssociatedLocalMainFrame()->OnPortalActivated(
(*it)->portal_token(), std::move(pending_portal),
std::move(client_receiver), std::move(data), trace_id,
base::BindOnce(
[](base::OnceCallback<void(blink::mojom::PortalActivateResult)>
callback,
blink::mojom::PortalActivateResult result) {
switch (result) {
case blink::mojom::PortalActivateResult::kPredecessorWillUnload:
case blink::mojom::PortalActivateResult::kPredecessorWasAdopted:
break;
case blink::mojom::PortalActivateResult::
kRejectedDueToPredecessorNavigation:
case blink::mojom::PortalActivateResult::
kRejectedDueToPortalNotReady:
case blink::mojom::PortalActivateResult::
kRejectedDueToErrorInPortal:
case blink::mojom::PortalActivateResult::kDisconnected:
case blink::mojom::PortalActivateResult::kNotImplemented:
case blink::mojom::PortalActivateResult::kAbortedDueToBug:
mojo::ReportBadMessage(
"Unexpected PortalActivateResult from renderer");
result = blink::mojom::PortalActivateResult::kAbortedDueToBug;
break;
}
std::move(callback).Run(result);
},
std::move(callback)));
}
void RenderFrameHostImpl::OnPortalCreatedForTesting(
std::unique_ptr<Portal> portal) {
portals_.insert(std::move(portal));
}
Portal* RenderFrameHostImpl::FindPortalByToken(
const blink::PortalToken& portal_token) {
auto it = base::ranges::find(portals_, portal_token, &Portal::portal_token);
return it == portals_.end() ? nullptr : it->get();
}
std::vector<Portal*> RenderFrameHostImpl::GetPortals() const {
std::vector<Portal*> result;
for (const auto& portal : portals_)
result.push_back(portal.get());
return result;
}
void RenderFrameHostImpl::DestroyPortal(Portal* portal) {
auto it = portals_.find(portal);
CHECK(it != portals_.end());
std::unique_ptr<Portal> owned_portal(std::move(*it));
portals_.erase(it);
}
void RenderFrameHostImpl::ForwardMessageFromHost(
blink::TransferableMessage message,
const url::Origin& source_origin) {
DCHECK_EQ(source_origin, GetLastCommittedOrigin());
GetAssociatedLocalMainFrame()->ForwardMessageFromHost(std::move(message),
source_origin);
}
SiteInstanceImpl* RenderFrameHostImpl::GetSiteInstance() const {
return site_instance_.get();
}
RenderProcessHost* RenderFrameHostImpl::GetProcess() const {
return agent_scheduling_group_->GetProcess();
}
AgentSchedulingGroupHost& RenderFrameHostImpl::GetAgentSchedulingGroup() {
return *agent_scheduling_group_;
}
RenderFrameHostImpl* RenderFrameHostImpl::GetParent() const {
return parent_;
}
PageImpl& RenderFrameHostImpl::GetPage() {
return *GetMainFrame()->document_associated_data_->owned_page();
}
const PageImpl& RenderFrameHostImpl::GetPage() const {
return *GetMainFrame()->document_associated_data_->owned_page();
}
bool RenderFrameHostImpl::IsDescendantOfWithinFrameTree(
RenderFrameHostImpl* ancestor) {
if (!ancestor || !ancestor->child_count())
return false;
for (RenderFrameHostImpl* current = GetParent(); current;
current = current->GetParent()) {
if (current == ancestor)
return true;
}
return false;
}
bool RenderFrameHostImpl::IsFencedFrameRoot() const {
return fenced_frame_status_ == FencedFrameStatus::kFencedFrameRoot;
}
bool RenderFrameHostImpl::IsNestedWithinFencedFrame() const {
switch (fenced_frame_status_) {
case FencedFrameStatus::kNotNestedInFencedFrame:
return false;
case FencedFrameStatus::kFencedFrameRoot:
return true;
case FencedFrameStatus::kIframeNestedWithinFencedFrame:
return true;
}
}
void RenderFrameHostImpl::ForEachRenderFrameHostWithAction(
base::FunctionRef<FrameIterationAction(RenderFrameHost*)> on_frame) {
ForEachRenderFrameHostWithAction(
[on_frame](RenderFrameHostImpl* rfh) { return on_frame(rfh); });
}
void RenderFrameHostImpl::ForEachRenderFrameHost(
base::FunctionRef<void(RenderFrameHost*)> on_frame) {
ForEachRenderFrameHost(
[on_frame](RenderFrameHostImpl* rfh) { on_frame(rfh); });
}
void RenderFrameHostImpl::ForEachRenderFrameHostWithAction(
base::FunctionRef<FrameIterationAction(RenderFrameHostImpl*)> on_frame) {
ForEachRenderFrameHostImpl(on_frame, false);
}
void RenderFrameHostImpl::ForEachRenderFrameHost(
base::FunctionRef<void(RenderFrameHostImpl*)> on_frame) {
ForEachRenderFrameHostWithAction([on_frame](RenderFrameHostImpl* rfh) {
on_frame(rfh);
return FrameIterationAction::kContinue;
});
}
void RenderFrameHostImpl::ForEachRenderFrameHostIncludingSpeculativeWithAction(
base::FunctionRef<FrameIterationAction(RenderFrameHostImpl*)> on_frame) {
ForEachRenderFrameHostImpl(on_frame, true);
}
void RenderFrameHostImpl::ForEachRenderFrameHostIncludingSpeculative(
base::FunctionRef<void(RenderFrameHostImpl*)> on_frame) {
ForEachRenderFrameHostIncludingSpeculativeWithAction(
[on_frame](RenderFrameHostImpl* rfh) {
on_frame(rfh);
return FrameIterationAction::kContinue;
});
}
void RenderFrameHostImpl::ForEachRenderFrameHostImpl(
base::FunctionRef<FrameIterationAction(RenderFrameHostImpl*)> on_frame,
bool include_speculative) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (!include_speculative &&
(lifecycle_state() == LifecycleStateImpl::kSpeculative ||
lifecycle_state() == LifecycleStateImpl::kPendingCommit)) {
return;
}
bool skip_children_of_starting_frame = false;
switch (on_frame(this)) {
case FrameIterationAction::kContinue:
break;
case FrameIterationAction::kSkipChildren:
skip_children_of_starting_frame = true;
break;
case FrameIterationAction::kStop:
return;
}
if (include_speculative && frame_tree_node()->current_frame_host() == this) {
RenderFrameHostImpl* speculative_frame_host =
frame_tree_node()->render_manager()->speculative_frame_host();
if (speculative_frame_host) {
DCHECK_EQ(speculative_frame_host->child_count(), 0U);
switch (on_frame(speculative_frame_host)) {
case FrameIterationAction::kContinue:
case FrameIterationAction::kSkipChildren:
break;
case FrameIterationAction::kStop:
return;
}
}
}
if (skip_children_of_starting_frame)
return;
FrameTree::NodeRange ftn_range = FrameTree::SubtreeAndInnerTreeNodes(this);
FrameTree::NodeIterator it = ftn_range.begin();
const FrameTree::NodeIterator end = ftn_range.end();
while (it != end) {
FrameTreeNode* node = *it;
RenderFrameHostImpl* frame_host = node->current_frame_host();
if (frame_host) {
switch (on_frame(frame_host)) {
case FrameIterationAction::kContinue:
++it;
break;
case FrameIterationAction::kSkipChildren:
it.AdvanceSkippingChildren();
break;
case FrameIterationAction::kStop:
return;
}
}
if (include_speculative) {
RenderFrameHostImpl* speculative_frame_host =
node->render_manager()->speculative_frame_host();
if (speculative_frame_host) {
DCHECK_EQ(speculative_frame_host->child_count(), 0U);
switch (on_frame(speculative_frame_host)) {
case FrameIterationAction::kContinue:
case FrameIterationAction::kSkipChildren:
break;
case FrameIterationAction::kStop:
return;
}
}
}
}
}
int RenderFrameHostImpl::GetFrameTreeNodeId() const {
return frame_tree_node_->frame_tree_node_id();
}
const base::UnguessableToken& RenderFrameHostImpl::GetDevToolsFrameToken() {
return devtools_frame_token();
}
absl::optional<base::UnguessableToken>
RenderFrameHostImpl::GetEmbeddingToken() {
return embedding_token_;
}
const std::string& RenderFrameHostImpl::GetFrameName() {
return browsing_context_state_->frame_name();
}
bool RenderFrameHostImpl::IsFrameDisplayNone() {
return frame_tree_node()->frame_owner_properties().is_display_none;
}
const absl::optional<gfx::Size>& RenderFrameHostImpl::GetFrameSize() {
return frame_size_;
}
size_t RenderFrameHostImpl::GetFrameDepth() {
return depth_;
}
bool RenderFrameHostImpl::IsCrossProcessSubframe() {
if (is_main_frame() || GetSiteInstance() == parent_->GetSiteInstance())
return false;
return GetSiteInstance()->GetProcess() !=
parent_->GetSiteInstance()->GetProcess();
}
bool RenderFrameHostImpl::RequiresProxyToParent() {
if (is_main_frame())
return false;
return GetSiteInstance() != parent_->GetSiteInstance();
}
WebExposedIsolationLevel RenderFrameHostImpl::GetWebExposedIsolationLevel() {
DCHECK_EQ(GetSiteInstance()->GetSiteInfo().web_exposed_isolation_info(),
GetProcess()->GetProcessLock().GetWebExposedIsolationInfo());
return GetProcess()->GetWebExposedIsolationLevel();
}
const GURL& RenderFrameHostImpl::GetLastCommittedURL() const {
return last_committed_url_;
}
const url::Origin& RenderFrameHostImpl::GetLastCommittedOrigin() const {
return last_committed_origin_;
}
const GURL& RenderFrameHostImpl::GetInheritedBaseUrl() const {
return inherited_base_url_;
}
const net::NetworkIsolationKey& RenderFrameHostImpl::GetNetworkIsolationKey() {
DCHECK(!isolation_info_.IsEmpty());
return isolation_info_.network_isolation_key();
}
const net::IsolationInfo&
RenderFrameHostImpl::GetIsolationInfoForSubresources() {
DCHECK(!isolation_info_.IsEmpty());
return isolation_info_;
}
net::IsolationInfo
RenderFrameHostImpl::GetPendingIsolationInfoForSubresources() {
auto config =
SubresourceLoaderFactoriesConfig::ForPendingOrLastCommittedNavigation(
*this);
DCHECK(!config.isolation_info().IsEmpty());
return config.isolation_info();
}
void RenderFrameHostImpl::GetCanonicalUrl(
base::OnceCallback<void(const absl::optional<GURL>&)> callback) {
if (IsRenderFrameLive()) {
auto validate_and_forward =
[](base::OnceCallback<void(const absl::optional<GURL>&)> callback,
const absl::optional<GURL>& url) {
if (url && url->is_valid() && url->SchemeIsHTTPOrHTTPS()) {
std::move(callback).Run(url);
} else {
std::move(callback).Run(absl::nullopt);
}
};
GetAssociatedLocalFrame()->GetCanonicalUrlForSharing(
base::BindOnce(validate_and_forward, std::move(callback)));
} else {
std::move(callback).Run(absl::nullopt);
}
}
void RenderFrameHostImpl::GetOpenGraphMetadata(
base::OnceCallback<void(blink::mojom::OpenGraphMetadataPtr)> callback) {
if (IsRenderFrameLive()) {
GetAssociatedLocalFrame()->GetOpenGraphMetadata(
base::BindOnce(&ForwardOpenGraphMetadataIfValid, std::move(callback)));
} else {
std::move(callback).Run({});
}
}
bool RenderFrameHostImpl::IsErrorDocument() {
DCHECK_NE(lifecycle_state(), LifecycleStateImpl::kSpeculative);
DCHECK_NE(lifecycle_state(), LifecycleStateImpl::kPendingCommit);
return is_error_document_;
}
DocumentRef RenderFrameHostImpl::GetDocumentRef() {
return DocumentRef(document_associated_data_->weak_factory().GetSafeRef());
}
WeakDocumentPtr RenderFrameHostImpl::GetWeakDocumentPtr() {
return WeakDocumentPtr(
document_associated_data_->weak_factory().GetWeakPtr());
}
void RenderFrameHostImpl::GetSerializedHtmlWithLocalLinks(
const base::flat_map<GURL, base::FilePath>& url_map,
const base::flat_map<blink::FrameToken, base::FilePath>& frame_token_map,
bool save_with_empty_url,
mojo::PendingRemote<mojom::FrameHTMLSerializerHandler> serializer_handler) {
if (!IsRenderFrameLive())
return;
GetMojomFrameInRenderer()->GetSerializedHtmlWithLocalLinks(
url_map, frame_token_map, save_with_empty_url,
std::move(serializer_handler));
}
void RenderFrameHostImpl::SetWantErrorMessageStackTrace() {
GetMojomFrameInRenderer()->SetWantErrorMessageStackTrace();
}
void RenderFrameHostImpl::ExecuteMediaPlayerActionAtLocation(
const gfx::Point& location,
const blink::mojom::MediaPlayerAction& action) {
auto media_player_action = blink::mojom::MediaPlayerAction::New();
media_player_action->type = action.type;
media_player_action->enable = action.enable;
gfx::PointF point_in_view = GetView()->TransformRootPointToViewCoordSpace(
gfx::PointF(location.x(), location.y()));
GetAssociatedLocalFrame()->MediaPlayerActionAt(
gfx::Point(point_in_view.x(), point_in_view.y()),
std::move(media_player_action));
}
bool RenderFrameHostImpl::CreateNetworkServiceDefaultFactory(
mojo::PendingReceiver<network::mojom::URLLoaderFactory>
default_factory_receiver) {
auto subresource_loader_factories_config =
SubresourceLoaderFactoriesConfig::ForLastCommittedNavigation(*this);
return CreateNetworkServiceDefaultFactoryAndObserve(
CreateURLLoaderFactoryParamsForMainWorld(
subresource_loader_factories_config,
"RFHI::CreateNetworkServiceDefaultFactory"),
subresource_loader_factories_config.ukm_source_id(),
std::move(default_factory_receiver));
}
std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
RenderFrameHostImpl::CreateSubresourceLoaderFactoriesForInitialEmptyDocument() {
DCHECK(!GetParent());
DCHECK_EQ(GURL(), last_committed_url_);
auto subresource_loader_factories =
std::make_unique<blink::PendingURLLoaderFactoryBundle>();
switch (lifecycle_state()) {
case RenderFrameHostImpl::LifecycleStateImpl::kInBackForwardCache:
case RenderFrameHostImpl::LifecycleStateImpl::kPendingCommit:
case RenderFrameHostImpl::LifecycleStateImpl::kReadyToBeDeleted:
case RenderFrameHostImpl::LifecycleStateImpl::kRunningUnloadHandlers:
NOTREACHED();
break;
case RenderFrameHostImpl::LifecycleStateImpl::kSpeculative:
break;
case RenderFrameHostImpl::LifecycleStateImpl::kActive:
case RenderFrameHostImpl::LifecycleStateImpl::kPrerendering:
CreateNetworkServiceDefaultFactory(
subresource_loader_factories->pending_default_factory()
.InitWithNewPipeAndPassReceiver());
recreate_default_url_loader_factory_after_network_service_crash_ = true;
break;
}
return subresource_loader_factories;
}
void RenderFrameHostImpl::MarkIsolatedWorldsAsRequiringSeparateURLLoaderFactory(
const base::flat_set<url::Origin>& isolated_world_origins,
bool push_to_renderer_now) {
size_t old_size =
isolated_worlds_requiring_separate_url_loader_factory_.size();
isolated_worlds_requiring_separate_url_loader_factory_.insert(
isolated_world_origins.begin(), isolated_world_origins.end());
size_t new_size =
isolated_worlds_requiring_separate_url_loader_factory_.size();
bool insertion_took_place = (old_size != new_size);
if (push_to_renderer_now && insertion_took_place) {
auto config =
SubresourceLoaderFactoriesConfig::ForPendingOrLastCommittedNavigation(
*this);
std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
subresource_loader_factories =
std::make_unique<blink::PendingURLLoaderFactoryBundle>();
subresource_loader_factories->pending_isolated_world_factories() =
CreateURLLoaderFactoriesForIsolatedWorlds(config,
isolated_world_origins);
GetMojomFrameInRenderer()->UpdateSubresourceLoaderFactories(
std::move(subresource_loader_factories));
}
}
bool RenderFrameHostImpl::IsSandboxed(network::mojom::WebSandboxFlags flags) {
return static_cast<int>(active_sandbox_flags()) & static_cast<int>(flags);
}
blink::web_pref::WebPreferences
RenderFrameHostImpl::GetOrCreateWebPreferences() {
return delegate()->GetOrCreateWebPreferences();
}
blink::PendingURLLoaderFactoryBundle::OriginMap
RenderFrameHostImpl::CreateURLLoaderFactoriesForIsolatedWorlds(
const SubresourceLoaderFactoriesConfig& config,
const base::flat_set<url::Origin>& isolated_world_origins) {
blink::PendingURLLoaderFactoryBundle::OriginMap result;
for (const url::Origin& isolated_world_origin : isolated_world_origins) {
network::mojom::URLLoaderFactoryParamsPtr factory_params =
URLLoaderFactoryParamsHelper::CreateForIsolatedWorld(
this, isolated_world_origin, config.origin(),
config.isolation_info(), config.GetClientSecurityState(),
config.trust_token_issuance_policy(),
config.trust_token_redemption_policy(),
config.cookie_setting_overrides());
mojo::PendingRemote<network::mojom::URLLoaderFactory> factory_remote;
CreateNetworkServiceDefaultFactoryAndObserve(
std::move(factory_params),
ukm::kInvalidSourceIdObj,
factory_remote.InitWithNewPipeAndPassReceiver());
result[isolated_world_origin] = std::move(factory_remote);
}
return result;
}
gfx::NativeView RenderFrameHostImpl::GetNativeView() {
RenderWidgetHostView* view = render_view_host_->GetWidget()->GetView();
if (!view)
return nullptr;
return view->GetNativeView();
}
void RenderFrameHostImpl::AddMessageToConsole(
blink::mojom::ConsoleMessageLevel level,
const std::string& message) {
AddMessageToConsoleImpl(level, message, false);
}
void RenderFrameHostImpl::ExecuteJavaScriptMethod(
const std::u16string& object_name,
const std::u16string& method_name,
base::Value::List arguments,
JavaScriptResultCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
CHECK(CanExecuteJavaScript());
AssertNonSpeculativeFrame();
const bool wants_result = !callback.is_null();
GetAssociatedLocalFrame()->JavaScriptMethodExecuteRequest(
object_name, method_name, std::move(arguments), wants_result,
std::move(callback));
}
void RenderFrameHostImpl::ExecuteJavaScript(const std::u16string& javascript,
JavaScriptResultCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
CHECK(CanExecuteJavaScript());
AssertNonSpeculativeFrame();
const bool wants_result = !callback.is_null();
GetAssociatedLocalFrame()->JavaScriptExecuteRequest(javascript, wants_result,
std::move(callback));
}
#if BUILDFLAG(IS_OHOS)
void RenderFrameHostImpl::ExecuteJavaScriptExt(const int fd,
const uint64_t scriptLength,
JavaScriptResultCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
CHECK(CanExecuteJavaScript());
AssertNonSpeculativeFrame();
const bool wants_result = !callback.is_null();
MojoPlatformHandle platform_handle;
platform_handle.struct_size = sizeof(platform_handle);
platform_handle.type = MOJO_PLATFORM_HANDLE_TYPE_FILE_DESCRIPTOR;
platform_handle.value = static_cast<uint64_t>(fd);
MojoHandle handle;
MojoWrapPlatformHandle(&platform_handle, nullptr, &handle);
GetAssociatedLocalFrame()->JavaScriptExecuteRequestExt(
mojo::ScopedHandle(mojo::Handle(handle)), scriptLength, wants_result, std::move(callback));
}
void RenderFrameHostImpl::SendAccessibilityEvent(int64_t accessibilityId,
int32_t eventType,
const std::string& argument) {
RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>(
render_view_host_->GetWidget()->GetView());
if (view) {
view->SendAccessibilityEvent(accessibilityId, eventType, argument);
}
}
#endif
void RenderFrameHostImpl::ExecuteJavaScriptInIsolatedWorld(
const std::u16string& javascript,
JavaScriptResultCallback callback,
int32_t world_id) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK_GT(world_id, ISOLATED_WORLD_ID_GLOBAL);
DCHECK_LE(world_id, ISOLATED_WORLD_ID_MAX);
AssertNonSpeculativeFrame();
const bool wants_result = !callback.is_null();
GetAssociatedLocalFrame()->JavaScriptExecuteRequestInIsolatedWorld(
javascript, wants_result, world_id, std::move(callback));
}
void RenderFrameHostImpl::ExecuteJavaScriptForTests(
const std::u16string& javascript,
JavaScriptResultCallback callback,
int32_t world_id) {
ExecuteJavaScriptForTests(
javascript, false,
false, world_id,
CreateJavaScriptExecuteRequestForTestsCallback(std::move(callback)));
}
void RenderFrameHostImpl::ExecuteJavaScriptWithUserGestureForTests(
const std::u16string& javascript,
JavaScriptResultCallback callback,
int32_t world_id) {
ExecuteJavaScriptForTests(
javascript, true,
false, world_id,
CreateJavaScriptExecuteRequestForTestsCallback(std::move(callback)));
}
void RenderFrameHostImpl::ExecuteJavaScriptForTests(
const std::u16string& javascript,
bool has_user_gesture,
bool resolve_promises,
int32_t world_id,
JavaScriptResultAndTypeCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
AssertNonSpeculativeFrame();
if (has_user_gesture && owner_) {
owner_->UpdateUserActivationState(
blink::mojom::UserActivationUpdateType::kNotifyActivation,
blink::mojom::UserActivationNotificationType::kTest);
}
GetAssociatedLocalFrame()->JavaScriptExecuteRequestForTests(
javascript, has_user_gesture, resolve_promises, world_id,
std::move(callback));
}
void RenderFrameHostImpl::ExecutePluginActionAtLocalLocation(
const gfx::Point& local_location,
blink::mojom::PluginActionType plugin_action) {
GetAssociatedLocalFrame()->PluginActionAt(local_location, plugin_action);
}
void RenderFrameHostImpl::CopyImageAt(int x, int y) {
gfx::PointF point_in_view =
GetView()->TransformRootPointToViewCoordSpace(gfx::PointF(x, y));
GetAssociatedLocalFrame()->CopyImageAt(
gfx::Point(point_in_view.x(), point_in_view.y()));
}
void RenderFrameHostImpl::SaveImageAt(int x, int y) {
gfx::PointF point_in_view =
GetView()->TransformRootPointToViewCoordSpace(gfx::PointF(x, y));
GetAssociatedLocalFrame()->SaveImageAt(
gfx::Point(point_in_view.x(), point_in_view.y()));
}
RenderViewHost* RenderFrameHostImpl::GetRenderViewHost() const {
return render_view_host_.get();
}
service_manager::InterfaceProvider* RenderFrameHostImpl::GetRemoteInterfaces() {
DCHECK(IsRenderFrameLive());
return remote_interfaces_.get();
}
blink::AssociatedInterfaceProvider*
RenderFrameHostImpl::GetRemoteAssociatedInterfaces() {
if (!remote_associated_interfaces_) {
mojo::AssociatedRemote<blink::mojom::AssociatedInterfaceProvider>
remote_interfaces;
if (GetAgentSchedulingGroup().GetChannel()) {
GetAgentSchedulingGroup().GetRemoteRouteProvider()->GetRoute(
GetRoutingID(), remote_interfaces.BindNewEndpointAndPassReceiver());
} else {
std::ignore = remote_interfaces.BindNewEndpointAndPassDedicatedReceiver();
}
remote_associated_interfaces_ =
std::make_unique<blink::AssociatedInterfaceProvider>(
remote_interfaces.Unbind());
}
return remote_associated_interfaces_.get();
}
PageVisibilityState RenderFrameHostImpl::GetVisibilityState() {
RenderFrameHostImpl* frame = this;
while (frame) {
if (frame->GetLocalRenderWidgetHost())
break;
frame = frame->GetParent();
}
if (!frame)
return PageVisibilityState::kHidden;
PageVisibilityState visibility_state = GetRenderWidgetHost()->is_hidden()
? PageVisibilityState::kHidden
: PageVisibilityState::kVisible;
GetContentClient()->browser()->OverridePageVisibilityState(this,
&visibility_state);
return visibility_state;
}
bool RenderFrameHostImpl::Send(IPC::Message* message) {
return GetAgentSchedulingGroup().Send(message);
}
bool RenderFrameHostImpl::OnMessageReceived(const IPC::Message& msg) {
if (!is_render_frame_created())
return false;
ScopedActiveURL scoped_active_url(this);
if (delegate_->OnMessageReceived(this, msg))
return true;
return false;
}
void RenderFrameHostImpl::OnAssociatedInterfaceRequest(
const std::string& interface_name,
mojo::ScopedInterfaceEndpointHandle handle) {
NOTREACHED();
}
std::string RenderFrameHostImpl::ToDebugString() {
return "RFHI:" +
render_view_host_->GetDelegate()->GetCreatorLocation().ToString();
}
void RenderFrameHostImpl::AccessibilityPerformAction(
const ui::AXActionData& action_data) {
if (IsInactiveAndDisallowActivation(
DisallowActivationReasonId::kAXPerformAction) ||
!render_accessibility_)
return;
if (action_data.action == ax::mojom::Action::kHitTest) {
AccessibilityHitTest(action_data.target_point,
action_data.hit_test_event_to_fire,
action_data.request_id, {});
return;
}
if (action_data.action == ax::mojom::Action::kFocus) {
RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>(
render_view_host_->GetWidget()->GetView());
if (view)
view->SetLastPointerType(ui::EventPointerType::kTouch);
}
render_accessibility_->PerformAction(action_data);
}
bool RenderFrameHostImpl::AccessibilityViewHasFocus() {
RenderWidgetHostView* view = render_view_host_->GetWidget()->GetView();
if (view)
return view->HasFocus();
return false;
}
void RenderFrameHostImpl::AccessibilityViewSetFocus() {
if (IsInactiveAndDisallowActivation(DisallowActivationReasonId::kAXSetFocus))
return;
RenderWidgetHostView* view = render_view_host_->GetWidget()->GetView();
if (view)
view->Focus();
}
gfx::Rect RenderFrameHostImpl::AccessibilityGetViewBounds() {
RenderWidgetHostView* view = render_view_host_->GetWidget()->GetView();
if (view)
return view->GetViewBounds();
return gfx::Rect();
}
float RenderFrameHostImpl::AccessibilityGetDeviceScaleFactor() {
return GetScaleFactorForView(GetView());
}
void RenderFrameHostImpl::AccessibilityReset() {
if (!render_accessibility_)
return;
accessibility_reset_token_ = g_next_accessibility_reset_token++;
render_accessibility_->Reset(accessibility_reset_token_);
}
void RenderFrameHostImpl::AccessibilityFatalError() {
CHECK(!BrowserAccessibilityManager::IsFailFastMode());
browser_accessibility_manager_.reset();
if (accessibility_reset_token_ || !render_accessibility_)
return;
accessibility_fatal_error_count_++;
if (accessibility_fatal_error_count_ > max_accessibility_resets_) {
render_accessibility_->FatalError();
} else {
if (accessibility_fatal_error_count_ == 1) {
base::debug::DumpWithoutCrashing();
}
AccessibilityReset();
}
}
gfx::AcceleratedWidget
RenderFrameHostImpl::AccessibilityGetAcceleratedWidget() {
DCHECK(AccessibilityIsRootFrame());
if (!IsActive())
return gfx::kNullAcceleratedWidget;
RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>(
render_view_host_->GetWidget()->GetView());
if (view)
return view->AccessibilityGetAcceleratedWidget();
return gfx::kNullAcceleratedWidget;
}
gfx::NativeViewAccessible
RenderFrameHostImpl::AccessibilityGetNativeViewAccessible() {
if (base::FeatureList::IsEnabled(features::kEvictOnAXEvents) &&
base::FeatureList::IsEnabled(
features::kEnableBackForwardCacheForScreenReader) &&
IsInactiveAndDisallowActivation(
DisallowActivationReasonId::kAXGetNativeView)) {
return nullptr;
}
RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>(
render_view_host_->GetWidget()->GetView());
if (view)
return view->AccessibilityGetNativeViewAccessible();
return nullptr;
}
gfx::NativeViewAccessible
RenderFrameHostImpl::AccessibilityGetNativeViewAccessibleForWindow() {
if (IsInactiveAndDisallowActivation(
DisallowActivationReasonId::kAXGetNativeViewForWindow))
return nullptr;
RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>(
render_view_host_->GetWidget()->GetView());
if (view)
return view->AccessibilityGetNativeViewAccessibleForWindow();
return nullptr;
}
void RenderFrameHostImpl::AccessibilityHitTest(
const gfx::Point& point_in_frame_pixels,
const ax::mojom::Event& opt_event_to_fire,
int opt_request_id,
base::OnceCallback<void(ui::AXPlatformTreeManager* hit_manager,
ui::AXNodeID hit_node_id)> opt_callback) {
if (IsInactiveAndDisallowActivation(DisallowActivationReasonId::kAXHitTest) ||
!render_accessibility_) {
if (opt_callback)
std::move(opt_callback).Run(nullptr, 0);
return;
}
render_accessibility_->HitTest(
point_in_frame_pixels, opt_event_to_fire, opt_request_id,
base::BindOnce(&RenderFrameHostImpl::AccessibilityHitTestCallback,
weak_ptr_factory_.GetWeakPtr(), opt_request_id,
opt_event_to_fire, std::move(opt_callback)));
}
bool RenderFrameHostImpl::AccessibilityIsRootFrame() const {
return !GetParentOrOuterDocumentOrEmbedderExcludingProspectiveOwners();
}
RenderFrameHostImpl* RenderFrameHostImpl::AccessibilityRenderFrameHost() {
return this;
}
WebContentsAccessibility*
RenderFrameHostImpl::AccessibilityGetWebContentsAccessibility() {
DCHECK(AccessibilityIsRootFrame());
auto* view = static_cast<RenderWidgetHostViewBase*>(GetView());
if (!view)
return nullptr;
return view->GetWebContentsAccessibility();
}
void RenderFrameHostImpl::InitializePolicyContainerHost(
bool renderer_initiated_creation_of_main_frame) {
if (lifecycle_state_ == LifecycleStateImpl::kSpeculative) {
return;
}
CHECK(owner_);
if (parent_) {
SetPolicyContainerHost(parent_->policy_container_host()->Clone());
} else if (GetParentOrOuterDocument()) {
const PolicyContainerPolicies& parent_policies =
GetParentOrOuterDocument()->policy_container_host()->policies();
SetPolicyContainerHost(
base::MakeRefCounted<PolicyContainerHost>(PolicyContainerPolicies(
network::mojom::ReferrerPolicy::kDefault,
network::mojom::IPAddressSpace::kUnknown,
false,
std::vector<network::mojom::ContentSecurityPolicyPtr>(),
parent_policies.cross_origin_opener_policy,
parent_policies.cross_origin_embedder_policy,
network::mojom::WebSandboxFlags::kNone,
false,
true)));
} else if (owner_->GetOpener()) {
SetPolicyContainerHost(owner_->GetOpener()
->current_frame_host()
->policy_container_host()
->Clone());
} else {
PolicyContainerPolicies policies;
DCHECK(IsOutermostMainFrame());
if (!renderer_initiated_creation_of_main_frame &&
lifecycle_state_ != LifecycleStateImpl::kPrerendering) {
policies.ip_address_space = network::mojom::IPAddressSpace::kLoopback;
}
SetPolicyContainerHost(
base::MakeRefCounted<PolicyContainerHost>(std::move(policies)));
}
network::mojom::WebSandboxFlags sandbox_flags_to_commit =
browsing_context_state_->effective_frame_policy().sandbox_flags;
for (const auto& csp :
policy_container_host_->policies().content_security_policies) {
sandbox_flags_to_commit |= csp->sandbox;
}
policy_container_host_->set_sandbox_flags(sandbox_flags_to_commit);
if (owner_->Credentialless()) {
policy_container_host_->SetIsCredentialless();
}
}
void RenderFrameHostImpl::SetPolicyContainerHost(
scoped_refptr<PolicyContainerHost> policy_container_host) {
policy_container_host_ = std::move(policy_container_host);
policy_container_host_->AssociateWithFrameToken(GetFrameToken(),
GetProcess()->GetID());
CHECK(parent_ || !IsCredentialless());
}
void RenderFrameHostImpl::InitializeLocalNetworkRequestPolicy() {
if (!policy_container_host_) {
DCHECK_EQ(lifecycle_state_, LifecycleStateImpl::kSpeculative);
return;
}
local_network_request_policy_ = DerivePrivateNetworkRequestPolicy(
policy_container_host_->policies(),
PrivateNetworkRequestContext::kSubresource);
}
void RenderFrameHostImpl::RenderProcessGone(
SiteInstanceGroup* site_instance_group,
const ChildProcessTerminationInfo& info) {
DCHECK_EQ(site_instance_->group(), site_instance_group);
if (IsInBackForwardCache()) {
EvictFromBackForwardCacheWithReason(
info.status == base::TERMINATION_STATUS_PROCESS_CRASHED
? BackForwardCacheMetrics::NotRestoredReason::
kRendererProcessCrashed
: BackForwardCacheMetrics::NotRestoredReason::
kRendererProcessKilled);
}
CancelPrerendering(PrerenderCancellationReason(
info.status == base::TERMINATION_STATUS_PROCESS_CRASHED
? PrerenderFinalStatus::kRendererProcessCrashed
: PrerenderFinalStatus::kRendererProcessKilled));
if (owned_render_widget_host_)
owned_render_widget_host_->RendererExited();
ResetOwnedNavigationRequests(NavigationDiscardReason::kRenderProcessGone);
ResetLoadingState();
pending_navigate_.reset();
set_nav_entry_id(0);
if (is_audible_)
OnAudibleStateChanged(false);
++renderer_exit_count_;
if (base::FeatureList::IsEnabled(features::kCrashReporting))
MaybeGenerateCrashReport(info.status, info.exit_code);
GetProcess()
->GetStoragePartition()
->GetNetworkContext()
->SendReportsAndRemoveSource(GetReportingSource());
ResetChildren();
RenderFrameDeleted();
SetLastCommittedUrl(GURL());
SetInheritedBaseUrl(GURL());
renderer_url_info_ = RendererURLInfo();
must_be_replaced_ = true;
has_committed_any_navigation_ = false;
#if BUILDFLAG(IS_ANDROID)
for (base::IDMap<std::unique_ptr<ExtractSmartClipDataCallback>>::iterator
iter(&smart_clip_callbacks_);
!iter.IsAtEnd(); iter.Advance()) {
std::move(*iter.GetCurrentValue())
.Run(std::u16string(), std::u16string(), gfx::Rect());
}
smart_clip_callbacks_.Clear();
#endif
remote_associated_interfaces_.reset();
has_before_unload_handler_ = false;
has_unload_handler_ = false;
has_pagehide_handler_ = false;
has_visibilitychange_handler_ = false;
has_navigate_event_handler_ = false;
if (IsPendingDeletion()) {
if (lifecycle_state() != LifecycleStateImpl::kReadyToBeDeleted)
SetLifecycleState(LifecycleStateImpl::kReadyToBeDeleted);
DCHECK(children_.empty());
PendingDeletionCheckCompleted();
return;
}
if (lifecycle_state_ == LifecycleStateImpl::kSpeculative) {
CHECK(owner_);
owner_->GetRenderFrameHostManager()
.CleanupSpeculativeRfhForRenderProcessGone();
}
}
void RenderFrameHostImpl::PerformAction(const ui::AXActionData& data) {
AccessibilityPerformAction(data);
}
bool RenderFrameHostImpl::RequiresPerformActionPointInPixels() const {
return true;
}
bool RenderFrameHostImpl::CreateRenderFrame(
const absl::optional<blink::FrameToken>& previous_frame_token,
const absl::optional<blink::FrameToken>& opener_frame_token,
const absl::optional<blink::FrameToken>& parent_frame_token,
const absl::optional<blink::FrameToken>& previous_sibling_frame_token) {
TRACE_EVENT0("navigation", "RenderFrameHostImpl::CreateRenderFrame");
DCHECK(!IsRenderFrameLive()) << "Creating frame twice";
if (!GetAgentSchedulingGroup().Init())
return false;
DCHECK(GetProcess()->IsInitializedAndNotDead());
mojom::CreateFrameParamsPtr params = mojom::CreateFrameParams::New();
BindBrowserInterfaceBrokerReceiver(
params->interface_broker.InitWithNewPipeAndPassReceiver());
params->routing_id = routing_id_;
params->previous_frame_token = previous_frame_token;
params->opener_frame_token = opener_frame_token;
params->parent_frame_token = parent_frame_token;
params->previous_sibling_frame_token = previous_sibling_frame_token;
params->tree_scope_type = frame_tree_node()->tree_scope_type();
params->replication_state =
browsing_context_state_->current_replication_state().Clone();
params->frame_token = frame_token_;
params->devtools_frame_token = devtools_frame_token();
BindAssociatedInterfaceProviderReceiver(
params->associated_interface_provider_remote
.InitWithNewEndpointAndPassReceiver());
params->document_token = document_associated_data_->token();
if (policy_container_host())
params->policy_container =
policy_container_host()->CreatePolicyContainerForBlink();
params->replication_state->frame_policy =
frame_tree_node()->pending_frame_policy();
NavigationRequest* navigation_request =
frame_tree_node()->navigation_request();
bool should_clear_browsing_instance_name =
navigation_request &&
(navigation_request->browsing_context_group_swap()
.ShouldClearWindowName() ||
(navigation_request->commit_params()
.is_cross_site_cross_browsing_context_group &&
base::FeatureList::IsEnabled(
features::kClearCrossSiteCrossBrowsingContextGroupWindowName)));
if (should_clear_browsing_instance_name) {
params->replication_state->name = "";
DCHECK(params->replication_state->unique_name.empty());
}
params->frame_owner_properties =
frame_tree_node()->frame_owner_properties().Clone();
params->is_on_initial_empty_document =
frame_tree_node()->is_on_initial_empty_document();
if (owned_render_widget_host_) {
DCHECK(parent_);
DCHECK(parent_frame_token);
RenderWidgetHostView* rwhv = RenderWidgetHostViewChildFrame::Create(
owned_render_widget_host_.get(),
parent_->GetRenderWidgetHost()->GetScreenInfos());
DCHECK(!rwhv->IsShowing());
}
if (auto* rwh = GetLocalRenderWidgetHost()) {
params->widget_params = rwh->BindAndGenerateCreateFrameWidgetParams();
}
mojo::PendingAssociatedRemote<mojom::Frame> pending_frame_remote;
params->frame = pending_frame_remote.InitWithNewEndpointAndPassReceiver();
SetMojomFrameRemote(std::move(pending_frame_remote));
DCHECK(params->previous_frame_token || params->parent_frame_token);
GetAgentSchedulingGroup().CreateFrame(std::move(params));
if (previous_frame_token &&
previous_frame_token->Is<blink::RemoteFrameToken>()) {
RenderFrameProxyHost* proxy = RenderFrameProxyHost::FromFrameToken(
GetProcess()->GetID(),
previous_frame_token->GetAs<blink::RemoteFrameToken>());
CHECK(proxy);
proxy->SetRenderFrameProxyCreated(true);
}
RenderFrameCreated();
return true;
}
void RenderFrameHostImpl::SetMojomFrameRemote(
mojo::PendingAssociatedRemote<mojom::Frame> frame_remote) {
DCHECK(!frame_);
frame_.Bind(std::move(frame_remote));
}
void RenderFrameHostImpl::DeleteRenderFrame(
mojom::FrameDeleteIntention intent) {
TRACE_EVENT("navigation", "RenderFrameHostImpl::DeleteRenderFrame",
[&](perfetto::EventContext ctx) {
WriteRenderFrameImplDeletion(ctx, this, intent);
});
if (IsPendingDeletion())
return;
if (IsRenderFrameLive()) {
GetMojomFrameInRenderer()->Delete(intent);
if (!is_main_frame() && IsActive()) {
base::TimeDelta subframe_shutdown_timeout =
frame_tree_->IsBeingDestroyed()
? base::TimeDelta()
: GetSubframeProcessShutdownDelay(
GetSiteInstance()->GetBrowserContext());
const base::TimeDelta unload_handler_timeout =
has_unload_handlers() ? subframe_unload_timeout_ : base::TimeDelta();
if (!subframe_shutdown_timeout.is_zero() ||
!unload_handler_timeout.is_zero()) {
GetProcess()->DelayProcessShutdown(subframe_shutdown_timeout,
unload_handler_timeout,
site_instance_->GetSiteInfo());
}
subframe_unload_timer_.Start(FROM_HERE, subframe_unload_timeout_, this,
&RenderFrameHostImpl::OnUnloadTimeout);
}
}
if (lifecycle_state() == LifecycleStateImpl::kSpeculative) {
DCHECK(!has_unload_handlers());
return;
}
SetLifecycleState(ShouldWaitForUnloadHandlers()
? LifecycleStateImpl::kRunningUnloadHandlers
: LifecycleStateImpl::kReadyToBeDeleted);
}
void RenderFrameHostImpl::RenderFrameCreated() {
CHECK_NE(render_frame_state_, RenderFrameState::kDeleting);
CHECK(!frame_tree_->IsBeingDestroyed());
DCHECK_NE(render_frame_state_, RenderFrameState::kCreated);
const RenderFrameState old_render_frame_state = render_frame_state_;
render_frame_state_ = RenderFrameState::kCreated;
if (old_render_frame_state == RenderFrameState::kDeleted) {
DCHECK(is_main_frame());
DCHECK_EQ(lifecycle_state(), LifecycleStateImpl::kActive);
GetPage().NotifyPageBecameCurrent();
}
if (GetLocalRenderWidgetHost()) {
#if BUILDFLAG(IS_ANDROID) || defined(OHOS_EX_FORCE_ZOOM)
GetLocalRenderWidgetHost()->SetForceEnableZoom(
delegate_->GetOrCreateWebPreferences().force_enable_zoom);
#endif
GetLocalRenderWidgetHost()->RendererWidgetCreated(
true);
}
SetUpMojoConnection();
delegate_->RenderFrameCreated(this);
if (enabled_bindings_)
GetFrameBindingsControl()->AllowBindings(enabled_bindings_);
if (web_ui_ && enabled_bindings_ & BINDINGS_POLICY_WEB_UI)
web_ui_->SetUpMojoConnection();
}
void RenderFrameHostImpl::RenderFrameDeleted() {
CHECK_NE(render_frame_state_, RenderFrameState::kDeleting);
bool was_created = is_render_frame_created();
render_frame_state_ = RenderFrameState::kDeleting;
render_frame_scoped_weak_ptr_factory_.InvalidateWeakPtrs();
if (was_created) {
delegate_->RenderFrameDeleted(this);
}
TearDownMojoConnection();
#if !BUILDFLAG(IS_ANDROID)
HostZoomMap* host_zoom_map = HostZoomMap::Get(GetSiteInstance());
host_zoom_map->ClearTemporaryZoomLevel(GetGlobalId());
#endif
if (web_ui_) {
web_ui_->RenderFrameDeleted();
web_ui_->TearDownMojoConnection();
}
render_frame_state_ = RenderFrameState::kDeleted;
}
void RenderFrameHostImpl::SwapIn() {
GetAssociatedLocalFrame()->SwapInImmediately();
}
void RenderFrameHostImpl::Init() {
DCHECK(is_main_frame());
DCHECK(waiting_for_init_);
waiting_for_init_ = false;
GetLocalRenderWidgetHost()->Init();
ForEachRenderFrameHostIncludingSpeculative(
[this](RenderFrameHostImpl* render_frame_host) {
DCHECK_EQ(render_frame_host->frame_tree(), frame_tree());
if (render_frame_host->IsRenderFrameLive())
render_frame_host->frame_->ResumeBlockedRequests();
});
if (pending_navigate_) {
std::unique_ptr<PendingNavigation> pending_navigation =
std::move(pending_navigate_);
frame_tree_node()->navigator().OnBeginNavigation(
frame_tree_node(), std::move(pending_navigation->common_params),
std::move(pending_navigation->begin_navigation_params),
std::move(pending_navigation->blob_url_loader_factory),
std::move(pending_navigation->navigation_client),
EnsurePrefetchedSignedExchangeCache(),
std::move(pending_navigation->renderer_cancellation_listener));
}
}
RenderFrameProxyHost* RenderFrameHostImpl::GetProxyToParent() {
if (is_main_frame())
return nullptr;
return browsing_context_state_->GetRenderFrameProxyHost(
GetParent()->GetSiteInstance()->group());
}
RenderFrameProxyHost* RenderFrameHostImpl::GetProxyToOuterDelegate() {
CHECK(lifecycle_state_ == LifecycleStateImpl::kActive ||
lifecycle_state_ == LifecycleStateImpl::kPrerendering);
DCHECK(is_main_frame());
CHECK(owner_);
return owner_->GetRenderFrameHostManager().GetProxyToOuterDelegate();
}
void RenderFrameHostImpl::DidChangeReferrerPolicy(
network::mojom::ReferrerPolicy referrer_policy) {
if (!IsActive())
return;
DCHECK(owner_);
owner_->DidChangeReferrerPolicy(referrer_policy);
}
void RenderFrameHostImpl::PropagateEmbeddingTokenToParentFrame() {
if (!embedding_token_)
return;
RenderFrameProxyHost* target_render_frame_proxy = nullptr;
if (RequiresProxyToParent()) {
target_render_frame_proxy = GetProxyToParent();
DCHECK(target_render_frame_proxy);
} else if (is_main_frame()) {
target_render_frame_proxy = GetProxyToOuterDelegate();
}
if (target_render_frame_proxy &&
target_render_frame_proxy->is_render_frame_proxy_live()) {
target_render_frame_proxy->GetAssociatedRemoteFrame()->SetEmbeddingToken(
embedding_token_.value());
}
}
void RenderFrameHostImpl::OnAudibleStateChanged(bool is_audible) {
DCHECK_NE(is_audible_, is_audible);
if (is_audible) {
DCHECK_NE(lifecycle_state(), LifecycleStateImpl::kPrerendering);
GetProcess()->OnMediaStreamAdded();
} else {
GetProcess()->OnMediaStreamRemoved();
}
is_audible_ = is_audible;
delegate_->OnFrameAudioStateChanged(this, is_audible_);
}
void RenderFrameHostImpl::DidAddMessageToConsole(
blink::mojom::ConsoleMessageLevel log_level,
const std::u16string& message,
uint32_t line_no,
const absl::optional<std::u16string>& source_id,
const absl::optional<std::u16string>& untrusted_stack_trace) {
std::u16string updated_source_id;
if (source_id.has_value())
updated_source_id = *source_id;
if (delegate_->DidAddMessageToConsole(this, log_level, message, line_no,
updated_source_id,
untrusted_stack_trace)) {
return;
}
const bool is_web_ui = HasWebUIScheme(GetMainFrame()->GetLastCommittedURL());
if (is_web_ui) {
DCHECK_EQ(GetMainFrame(), GetOutermostMainFrame())
<< "The mainframe and outermost mainframe should be the same in WebUI.";
}
const bool is_builtin_component =
is_web_ui ||
GetContentClient()->browser()->IsBuiltinComponent(
GetProcess()->GetBrowserContext(), GetLastCommittedOrigin());
const bool is_off_the_record =
GetSiteInstance()->GetBrowserContext()->IsOffTheRecord();
LogConsoleMessage(log_level, message, line_no, is_builtin_component,
is_off_the_record, updated_source_id);
}
void RenderFrameHostImpl::FrameSizeChanged(const gfx::Size& frame_size) {
frame_size_ = frame_size;
delegate_->FrameSizeChanged(this, frame_size);
}
void RenderFrameHostImpl::RendererDidActivateForPrerendering() {
if (mojo_binder_policy_applier_) {
mojo_binder_policy_applier_->GrantAll();
broker_.ReleaseMojoBinderPolicies();
mojo_binder_policy_applier_.reset();
}
}
void RenderFrameHostImpl::SetCrossOriginOpenerPolicyReporter(
std::unique_ptr<CrossOriginOpenerPolicyReporter> coop_reporter) {
coop_access_report_manager_.set_coop_reporter(std::move(coop_reporter));
}
bool RenderFrameHostImpl::IsCredentialless() const {
return policy_container_host_->policies().is_credentialless;
}
bool RenderFrameHostImpl::IsLastCrossDocumentNavigationStartedByUser() const {
return last_cross_document_navigation_started_by_user_;
}
void RenderFrameHostImpl::OnCreateChildFrame(
int new_routing_id,
mojo::PendingAssociatedRemote<mojom::Frame> frame_remote,
mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
browser_interface_broker_receiver,
blink::mojom::PolicyContainerBindParamsPtr policy_container_bind_params,
mojo::PendingAssociatedReceiver<blink::mojom::AssociatedInterfaceProvider>
associated_interface_provider_receiver,
blink::mojom::TreeScopeType scope,
const std::string& frame_name,
const std::string& frame_unique_name,
bool is_created_by_script,
const blink::LocalFrameToken& frame_token,
const base::UnguessableToken& devtools_frame_token,
const blink::DocumentToken& document_token,
const blink::FramePolicy& frame_policy,
const blink::mojom::FrameOwnerProperties& frame_owner_properties,
blink::FrameOwnerElementType owner_type,
ukm::SourceId document_ukm_source_id) {
DCHECK(!frame_unique_name.empty());
DCHECK(browser_interface_broker_receiver.is_valid());
DCHECK(policy_container_bind_params->receiver.is_valid());
DCHECK(associated_interface_provider_receiver.is_valid());
DCHECK(devtools_frame_token);
if (!is_render_frame_created())
return;
if (lifecycle_state() != LifecycleStateImpl::kPrerendering) {
if (IsInactiveAndDisallowActivation(
DisallowActivationReasonId::kCreateChildFrame))
return;
}
FrameTreeNode* new_frame_tree_node = frame_tree_->AddFrame(
this, GetProcess()->GetID(), new_routing_id, std::move(frame_remote),
std::move(browser_interface_broker_receiver),
std::move(policy_container_bind_params),
std::move(associated_interface_provider_receiver), scope, frame_name,
frame_unique_name, is_created_by_script, frame_token,
devtools_frame_token, document_token, frame_policy,
frame_owner_properties, was_discarded_, owner_type,
false);
new_frame_tree_node->current_frame_host()->RecordDocumentCreatedUkmEvent(
GetLastCommittedOrigin(), document_ukm_source_id, ukm::UkmRecorder::Get(),
true);
}
void RenderFrameHostImpl::CreateChildFrame(
int new_routing_id,
mojo::PendingAssociatedRemote<mojom::Frame> frame_remote,
mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
browser_interface_broker_receiver,
blink::mojom::PolicyContainerBindParamsPtr policy_container_bind_params,
mojo::PendingAssociatedReceiver<blink::mojom::AssociatedInterfaceProvider>
associated_interface_provider_receiver,
blink::mojom::TreeScopeType scope,
const std::string& frame_name,
const std::string& frame_unique_name,
bool is_created_by_script,
const blink::FramePolicy& frame_policy,
blink::mojom::FrameOwnerPropertiesPtr frame_owner_properties,
blink::FrameOwnerElementType owner_type,
ukm::SourceId document_ukm_source_id) {
blink::LocalFrameToken frame_token;
base::UnguessableToken devtools_frame_token;
blink::DocumentToken document_token;
if (!static_cast<RenderProcessHostImpl*>(GetProcess())
->TakeFrameTokensForFrameRoutingID(new_routing_id, frame_token,
devtools_frame_token,
document_token)) {
bad_message::ReceivedBadMessage(
GetProcess(), bad_message::RFH_CREATE_CHILD_FRAME_TOKENS_NOT_FOUND);
return;
}
if (frame_policy.sandbox_flags !=
(frame_policy.sandbox_flags | active_sandbox_flags())) {
bad_message::ReceivedBadMessage(
GetProcess(), bad_message::RFH_CREATE_CHILD_FRAME_SANDBOX_FLAGS);
return;
}
OnCreateChildFrame(new_routing_id, std::move(frame_remote),
std::move(browser_interface_broker_receiver),
std::move(policy_container_bind_params),
std::move(associated_interface_provider_receiver), scope,
frame_name, frame_unique_name, is_created_by_script,
frame_token, devtools_frame_token, document_token,
frame_policy, *frame_owner_properties, owner_type,
document_ukm_source_id);
}
void RenderFrameHostImpl::DidNavigate(
const mojom::DidCommitProvisionalLoadParams& params,
NavigationRequest* navigation_request,
bool was_within_same_document) {
SetLastCommittedUrl(params.url);
SetLastCommittedOrigin(params.origin);
if (!navigation_request->IsSameDocument() &&
(!navigation_request->is_synchronous_renderer_commit() ||
!navigation_request->GetURL().IsAboutBlank())) {
navigation_request->frame_tree_node()->set_not_on_initial_empty_document();
}
url::Origin origin =
(params.url.SchemeIs(url::kUuidInPackageScheme) &&
navigation_request->GetWebBundleURL().is_valid())
? url::Origin::Create(navigation_request->GetWebBundleURL())
: GetLastCommittedOrigin();
isolation_info_ = ComputeIsolationInfoInternal(
origin, isolation_info_.request_type(),
navigation_request->is_credentialless(),
navigation_request->ComputeFencedFrameNonce());
if (!navigation_request->DidEncounterError())
last_successful_url_ = params.url;
renderer_url_info_.last_document_url = GetLastDocumentURL(
navigation_request, params, is_error_document_, renderer_url_info_);
last_http_method_ = params.method;
last_post_id_ = params.post_id;
last_http_status_code_ = params.http_status_code;
last_committed_common_params_has_user_gesture_ =
navigation_request->common_params().has_user_gesture;
if (!was_within_same_document) {
last_cross_document_navigation_started_by_user_ =
!navigation_request->IsRendererInitiated() ||
(navigation_request->begin_params()
.initiator_activation_and_ad_status !=
blink::mojom::NavigationInitiatorActivationAndAdStatus::
kDidNotStartWithTransientActivation);
}
bool did_create_new_document =
!navigation_request->IsPageActivation() && !was_within_same_document;
if (did_create_new_document)
DidCommitNewDocument(params, navigation_request);
if (!navigation_request->IsSameDocument()) {
browsing_context_state_->UpdateFramePolicyHeaders(
active_sandbox_flags(), permissions_policy_header_);
}
}
void RenderFrameHostImpl::SetLastCommittedOrigin(const url::Origin& origin) {
last_committed_origin_ = origin;
}
void RenderFrameHostImpl::SetInheritedBaseUrl(const GURL& inherited_base_url) {
if (blink::features::IsNewBaseUrlInheritanceBehaviorEnabled()) {
inherited_base_url_ = inherited_base_url;
}
}
void RenderFrameHostImpl::SetLastCommittedOriginForTesting(
const url::Origin& origin) {
SetLastCommittedOrigin(origin);
}
const url::Origin& RenderFrameHostImpl::ComputeTopFrameOrigin(
const url::Origin& frame_origin) const {
if (is_main_frame()) {
return frame_origin;
}
DCHECK(parent_);
RenderFrameHostImpl* host = parent_;
while (host->parent_) {
host = host->parent_;
}
return host->GetLastCommittedOrigin();
}
void RenderFrameHostImpl::SetStorageKey(const blink::StorageKey& storage_key) {
storage_key_ = storage_key;
}
net::IsolationInfo RenderFrameHostImpl::ComputeIsolationInfoForNavigation(
const GURL& destination) {
return ComputeIsolationInfoForNavigation(
destination, IsCredentialless(),
absl::nullopt);
}
net::IsolationInfo RenderFrameHostImpl::ComputeIsolationInfoForNavigation(
const GURL& destination,
bool is_credentialless,
absl::optional<base::UnguessableToken> fenced_frame_nonce_for_navigation) {
net::IsolationInfo::RequestType request_type =
is_main_frame() ? net::IsolationInfo::RequestType::kMainFrame
: net::IsolationInfo::RequestType::kSubFrame;
return ComputeIsolationInfoInternal(url::Origin::Create(destination),
request_type, is_credentialless,
fenced_frame_nonce_for_navigation);
}
net::IsolationInfo
RenderFrameHostImpl::ComputeIsolationInfoForSubresourcesForPendingCommit(
const url::Origin& main_world_origin,
bool is_credentialless,
absl::optional<base::UnguessableToken> fenced_frame_nonce_for_navigation) {
return ComputeIsolationInfoInternal(
main_world_origin, net::IsolationInfo::RequestType::kOther,
is_credentialless, fenced_frame_nonce_for_navigation);
}
net::SiteForCookies RenderFrameHostImpl::ComputeSiteForCookies() {
return isolation_info_.site_for_cookies();
}
net::IsolationInfo RenderFrameHostImpl::ComputeIsolationInfoInternal(
const url::Origin& frame_origin,
net::IsolationInfo::RequestType request_type,
bool is_credentialless,
absl::optional<base::UnguessableToken> fenced_frame_nonce_for_navigation) {
url::Origin top_frame_origin = ComputeTopFrameOrigin(frame_origin);
net::SchemefulSite top_frame_site = net::SchemefulSite(top_frame_origin);
net::SiteForCookies candidate_site_for_cookies(top_frame_site);
std::set<net::SchemefulSite> party_context;
const RenderFrameHostImpl* initial_rfh = this;
if (request_type != net::IsolationInfo::RequestType::kOther)
initial_rfh = this->parent_;
for (const RenderFrameHostImpl* rfh = initial_rfh; rfh; rfh = rfh->parent_) {
const url::Origin& cur_origin =
rfh == this ? frame_origin : rfh->last_committed_origin_;
net::SchemefulSite cur_site = net::SchemefulSite(cur_origin);
if (top_frame_site != cur_site) {
party_context.insert(cur_site);
}
candidate_site_for_cookies.CompareWithFrameTreeSiteAndRevise(cur_site);
}
if (GetContentClient()
->browser()
->ShouldTreatURLSchemeAsFirstPartyWhenTopLevel(
top_frame_origin.scheme(),
GURL::SchemeIsCryptographic(frame_origin.scheme()))) {
candidate_site_for_cookies = net::SiteForCookies(top_frame_site);
}
absl::optional<base::UnguessableToken> nonce =
ComputeNonce(is_credentialless, fenced_frame_nonce_for_navigation);
return net::IsolationInfo::Create(request_type, top_frame_origin,
frame_origin, candidate_site_for_cookies,
std::move(party_context), nonce);
}
absl::optional<base::UnguessableToken> RenderFrameHostImpl::ComputeNonce(
bool is_credentialless,
absl::optional<base::UnguessableToken> fenced_frame_nonce_for_navigation) {
if (is_credentialless) {
RenderFrameHostImpl* main_rfh = this;
while (main_rfh->parent_ && !main_rfh->IsFencedFrameRoot()) {
main_rfh = main_rfh->parent_;
}
return main_rfh->credentialless_iframes_nonce();
}
if (fenced_frame_nonce_for_navigation.has_value()) {
return fenced_frame_nonce_for_navigation;
}
return frame_tree_node_->GetFencedFrameNonce();
}
bool RenderFrameHostImpl::IsThirdPartyStoragePartitioningEnabled(
RenderFrameHostImpl* main_frame_for_storage_partitioning) {
if (main_frame_for_storage_partitioning == this) {
return false;
}
RuntimeFeatureStateDocumentData* rfs_document_data_for_storage_key =
RuntimeFeatureStateDocumentData::GetForCurrentDocument(
main_frame_for_storage_partitioning);
DCHECK(rfs_document_data_for_storage_key);
if (rfs_document_data_for_storage_key->runtime_feature_state_read_context()
.IsDisableThirdPartyStoragePartitioningEnabled()) {
return false;
}
if (!GetContentClient()->browser()->IsThirdPartyStoragePartitioningAllowed(
GetBrowserContext(),
main_frame_for_storage_partitioning->GetLastCommittedOrigin())) {
return false;
}
return blink::StorageKey::IsThirdPartyStoragePartitioningEnabled();
}
blink::StorageKey RenderFrameHostImpl::CalculateStorageKey(
const url::Origin& new_rfh_origin,
const base::UnguessableToken* nonce) {
if (nonce) {
return blink::StorageKey::CreateWithNonce(new_rfh_origin, *nonce);
}
if (base::FeatureList::IsEnabled(
features::kShouldAllowFirstPartyStorageKeyOverrideFromEmbedder) &&
GetContentClient()->browser()->ShouldUseFirstPartyStorageKey(
new_rfh_origin)) {
return blink::StorageKey::CreateFirstParty(new_rfh_origin);
}
std::vector<RenderFrameHostImpl*> ancestor_chain;
RenderFrameHostImpl* current = this;
while (current) {
ancestor_chain.push_back(current);
current = current->parent_;
}
auto origin = [&](RenderFrameHostImpl* rfh) {
return rfh == this ? new_rfh_origin : rfh->GetLastCommittedOrigin();
};
bool ignore_top_level_extension =
!is_main_frame() &&
GetBrowserContext()
->GetSharedCorsOriginAccessList()
->GetOriginAccessList()
.CheckAccessState(origin(ancestor_chain.end()[-1]),
origin(ancestor_chain.end()[-2]).GetURL()) ==
network::cors::OriginAccessList::AccessState::kAllowed;
if (ignore_top_level_extension) {
ancestor_chain.pop_back();
}
net::SchemefulSite top_level_site(origin(ancestor_chain.back()));
blink::mojom::AncestorChainBit ancestor_chain_bit =
blink::mojom::AncestorChainBit::kSameSite;
if (!new_rfh_origin.opaque() && !top_level_site.opaque()) {
for (auto* ancestor : ancestor_chain) {
if (top_level_site != net::SchemefulSite(origin(ancestor))) {
ancestor_chain_bit = blink::mojom::AncestorChainBit::kCrossSite;
break;
}
}
} else {
ancestor_chain_bit = blink::mojom::AncestorChainBit::kCrossSite;
}
bool is_third_party_storage_partitioning_allowed =
IsThirdPartyStoragePartitioningEnabled(ancestor_chain.back());
return blink::StorageKey::Create(new_rfh_origin, top_level_site,
ancestor_chain_bit,
is_third_party_storage_partitioning_allowed);
}
void RenderFrameHostImpl::SetOriginDependentStateOfNewFrame(
RenderFrameHostImpl* creator_frame) {
DCHECK(!has_committed_any_navigation_);
DCHECK(GetLastCommittedOrigin().opaque());
url::Origin creator_origin =
creator_frame ? creator_frame->GetLastCommittedOrigin() : url::Origin();
bool new_frame_should_be_sandboxed =
network::mojom::WebSandboxFlags::kOrigin ==
(browsing_context_state_->active_sandbox_flags() &
network::mojom::WebSandboxFlags::kOrigin);
url::Origin new_frame_origin = new_frame_should_be_sandboxed
? creator_origin.DeriveNewOpaqueOrigin()
: creator_origin;
isolation_info_ = ComputeIsolationInfoInternal(
new_frame_origin, net::IsolationInfo::RequestType::kOther,
IsCredentialless(),
absl::nullopt);
SetLastCommittedOrigin(new_frame_origin);
if (creator_frame) {
RuntimeFeatureStateDocumentData* rfs_document_data_from_creator =
RuntimeFeatureStateDocumentData::GetForCurrentDocument(creator_frame);
DCHECK(rfs_document_data_from_creator);
RuntimeFeatureStateDocumentData::CreateForCurrentDocument(
this,
rfs_document_data_from_creator->runtime_feature_state_read_context());
} else {
RuntimeFeatureStateDocumentData::CreateForCurrentDocument(
this, blink::RuntimeFeatureStateContext());
}
SetStorageKey(CalculateStorageKey(
new_frame_origin, base::OptionalToPtr(isolation_info_.nonce())));
if (GetContentClient()->browser()->ShouldAllowInsecureLocalNetworkRequests(
GetBrowserContext(), new_frame_origin)) {
local_network_request_policy_ =
network::mojom::LocalNetworkRequestPolicy::kAllow;
}
ResetPermissionsPolicy();
}
FrameTreeNode* RenderFrameHostImpl::AddChild(
std::unique_ptr<FrameTreeNode> child,
int frame_routing_id,
mojo::PendingAssociatedRemote<mojom::Frame> frame_remote,
const blink::LocalFrameToken& frame_token,
const blink::DocumentToken& document_token,
base::UnguessableToken devtools_frame_token,
const blink::FramePolicy& frame_policy,
std::string frame_name,
std::string frame_unique_name) {
DCHECK(lifecycle_state_ == LifecycleStateImpl::kActive ||
lifecycle_state_ == LifecycleStateImpl::kPrerendering);
child->render_manager()->InitChild(
GetSiteInstance(), frame_routing_id, std::move(frame_remote), frame_token,
document_token, devtools_frame_token, frame_policy, frame_name,
frame_unique_name);
CHECK(owner_);
owner_->GetRenderFrameHostManager().CreateProxiesForChildFrame(child.get());
child->current_frame_host()->SetOriginDependentStateOfNewFrame(this);
children_.push_back(std::move(child));
return children_.back().get();
}
void RenderFrameHostImpl::RemoveChild(FrameTreeNode* child) {
for (auto iter = children_.begin(); iter != children_.end(); ++iter) {
if (iter->get() == child) {
std::unique_ptr<FrameTreeNode> node_to_delete(std::move(*iter));
children_.erase(iter);
node_to_delete->current_frame_host()->DeleteRenderFrame(
mojom::FrameDeleteIntention::kNotMainFrame);
RenderFrameHostImpl* speculative_frame_host =
node_to_delete->render_manager()->speculative_frame_host();
if (speculative_frame_host) {
if (speculative_frame_host->lifecycle_state() ==
LifecycleStateImpl::kPendingCommit) {
speculative_frame_host->DeleteRenderFrame(
mojom::FrameDeleteIntention::kNotMainFrame);
} else {
}
}
node_to_delete.reset();
PendingDeletionCheckCompleted();
return;
}
}
}
void RenderFrameHostImpl::ResetChildren() {
std::vector<std::unique_ptr<FrameTreeNode>> children;
children.swap(children_);
for (auto& child : children)
child->current_frame_host()->DeleteRenderFrame(
mojom::FrameDeleteIntention::kNotMainFrame);
}
void RenderFrameHostImpl::SetLastCommittedUrl(const GURL& url) {
last_committed_url_ = url;
}
void RenderFrameHostImpl::Detach() {
if (lifecycle_state() == LifecycleStateImpl::kSpeculative ||
lifecycle_state() == LifecycleStateImpl::kPendingCommit) {
return;
}
if (!parent_) {
bad_message::ReceivedBadMessage(GetProcess(),
bad_message::RFH_DETACH_MAIN_FRAME);
return;
}
if (is_waiting_for_unload_ack_) {
parent_->RemoveChild(GetFrameTreeNodeForUnload());
return;
}
if (do_not_delete_for_testing_)
return;
if (IsPendingDeletion()) {
if (lifecycle_state() != LifecycleStateImpl::kReadyToBeDeleted)
SetLifecycleState(LifecycleStateImpl::kReadyToBeDeleted);
PendingDeletionCheckCompleted();
return;
}
SetLifecycleState(LifecycleStateImpl::kReadyToBeDeleted);
StartPendingDeletionOnSubtree(PendingDeletionReason::kFrameDetach);
frame_tree()->FrameUnloading(GetFrameTreeNodeForUnload());
PendingDeletionCheckCompletedOnSubtree();
}
void RenderFrameHostImpl::DidFailLoadWithError(const GURL& url,
int32_t error_code) {
TRACE_EVENT("navigation", "RenderFrameHostImpl::DidFailLoadWithError",
ChromeTrackEvent::kRenderFrameHost, *this, "error", error_code);
if (!GetParentOrOuterDocument() &&
CancelPrerendering(
PrerenderCancellationReason(PrerenderFinalStatus::kDidFailLoad))) {
return;
}
GURL validated_url(url);
GetProcess()->FilterURL(false, &validated_url);
delegate_->DidFailLoadWithError(this, validated_url, error_code);
}
void RenderFrameHostImpl::DidFocusFrame() {
TRACE_EVENT("navigation", "RenderFrameHostImpl::DidFocusFrame",
ChromeTrackEvent::kRenderFrameHost, *this,
ChromeTrackEvent::kSiteInstanceGroup,
*GetSiteInstance()->group());
if (!IsActive())
return;
DCHECK(owner_);
owner_->SetFocusedFrame(GetSiteInstance()->group());
}
void RenderFrameHostImpl::DidCallFocus() {
if (!IsActive())
return;
delegate_->DidCallFocus();
}
void RenderFrameHostImpl::CancelInitialHistoryLoad() {
NOTIMPLEMENTED();
}
void RenderFrameHostImpl::DidChangeBackForwardCacheDisablingFeatures(
BackForwardCacheBlockingDetails details) {
renderer_reported_bfcache_blocking_details_ = std::move(details);
#if BUILDFLAG(IS_OHOS)
if (GetBackForwardCacheDisablingFeatures().Has(blink::scheduler::WebSchedulerTrackedFeature::kEnableCacheNativeEmbed)) {
LOG(INFO) << "NativeEmbed BFCache, render frame host received NativeEmbed feature, render frame host global id = " \
<< GetGlobalId();
}
#endif
MaybeEvictFromBackForwardCache();
if (back_forward_cache_disabling_features_callback_for_testing_) {
back_forward_cache_disabling_features_callback_for_testing_.Run(
GetBackForwardCacheDisablingFeatures());
}
}
using BackForwardCacheDisablingFeatureHandle =
RenderFrameHostImpl::BackForwardCacheDisablingFeatureHandle;
BackForwardCacheDisablingFeatureHandle::
BackForwardCacheDisablingFeatureHandle() {
feature_ = BackForwardCacheDisablingFeature::kDummy;
}
BackForwardCacheDisablingFeatureHandle::BackForwardCacheDisablingFeatureHandle(
BackForwardCacheDisablingFeatureHandle&& other) = default;
BackForwardCacheDisablingFeatureHandle::BackForwardCacheDisablingFeatureHandle(
RenderFrameHostImpl* render_frame_host,
BackForwardCacheDisablingFeature feature)
: render_frame_host_(render_frame_host->GetWeakPtr()), feature_(feature) {
CHECK(render_frame_host_);
render_frame_host_->OnBackForwardCacheDisablingFeatureUsed(feature_);
}
void RenderFrameHostImpl::OnBackForwardCacheDisablingFeatureUsed(
BackForwardCacheDisablingFeature feature) {
++browser_reported_bfcache_disabling_features_counts_[feature];
MaybeEvictFromBackForwardCache();
}
void RenderFrameHostImpl::OnBackForwardCacheDisablingStickyFeatureUsed(
BackForwardCacheDisablingFeature feature) {
OnBackForwardCacheDisablingFeatureUsed(feature);
}
void RenderFrameHostImpl::OnBackForwardCacheDisablingFeatureRemoved(
BackForwardCacheDisablingFeature feature) {
auto it = browser_reported_bfcache_disabling_features_counts_.find(feature);
DCHECK(it->second >= 1);
if (it->second == 1) {
browser_reported_bfcache_disabling_features_counts_.erase(it);
} else {
--it->second;
}
}
RenderFrameHostImpl::BackForwardCacheDisablingFeatures
RenderFrameHostImpl::GetBackForwardCacheDisablingFeatures() const {
BackForwardCacheDisablingFeatures features;
for (const auto& details : GetBackForwardCacheBlockingDetails()) {
features.Put(static_cast<blink::scheduler::WebSchedulerTrackedFeature>(
details->feature));
}
return features;
}
RenderFrameHostImpl::BackForwardCacheBlockingDetails
RenderFrameHostImpl::GetBackForwardCacheBlockingDetails() const {
BackForwardCacheBlockingDetails combined_details_list =
DedicatedWorkerHostsForDocument::GetOrCreateForCurrentDocument(
const_cast<RenderFrameHostImpl*>(this))
->GetBackForwardCacheBlockingDetails();
for (const auto& details : renderer_reported_bfcache_blocking_details_) {
combined_details_list.push_back(details.Clone());
}
for (const auto& it : browser_reported_bfcache_disabling_features_counts_) {
auto details_ptr = blink::mojom::BlockingDetails::New();
details_ptr->feature = static_cast<uint32_t>(it.first);
combined_details_list.push_back(std::move(details_ptr));
}
return combined_details_list;
}
RenderFrameHostImpl::BackForwardCacheDisablingFeatureHandle
RenderFrameHostImpl::RegisterBackForwardCacheDisablingNonStickyFeature(
BackForwardCacheDisablingFeature feature) {
return BackForwardCacheDisablingFeatureHandle(this, feature);
}
bool RenderFrameHostImpl::IsFrozen() {
return lifecycle_state() == LifecycleStateImpl::kInBackForwardCache;
}
void RenderFrameHostImpl::DidCommitProvisionalLoad(
mojom::DidCommitProvisionalLoadParamsPtr params,
mojom::DidCommitProvisionalLoadInterfaceParamsPtr interface_params) {
if (!MaybeInterceptCommitCallback(nullptr, ¶ms, &interface_params))
return;
DCHECK(params);
DidCommitNavigation(nullptr, std::move(params), std::move(interface_params));
}
void RenderFrameHostImpl::DidCommitPageActivation(
NavigationRequest* committing_navigation_request,
mojom::DidCommitProvisionalLoadParamsPtr params) {
DCHECK(committing_navigation_request->IsPageActivation());
DCHECK(is_main_frame());
auto request = navigation_requests_.find(committing_navigation_request);
CHECK(request != navigation_requests_.end());
base::TimeTicks navigation_start =
committing_navigation_request->NavigationStart();
bool is_prerender_page_activation =
committing_navigation_request->IsPrerenderedPageActivation();
std::unique_ptr<NavigationRequest> owned_request = std::move(request->second);
navigation_requests_.erase(committing_navigation_request);
blink::mojom::FrameReplicationState prerender_main_frame_replication_state;
PrerenderTriggerType prerender_trigger_type;
std::string prerender_embedder_histogram_suffix;
if (is_prerender_page_activation) {
prerender_main_frame_replication_state =
owned_request->prerender_main_frame_replication_state();
prerender_trigger_type = owned_request->GetPrerenderTriggerType();
prerender_embedder_histogram_suffix =
owned_request->GetPrerenderEmbedderHistogramSuffix();
}
#if DCHECK_IS_ON()
ForEachRenderFrameHost([](RenderFrameHostImpl* rfh) {
if (rfh->is_main_frame())
return;
for (const auto& pair : rfh->navigation_requests_)
DCHECK_EQ(pair.first->nav_entry_id(), 0);
});
#endif
DidCommitNavigationInternal(std::move(owned_request), std::move(params),
nullptr);
if (is_prerender_page_activation)
GetPage().MaybeDispatchLoadEventsOnPrerenderActivation();
DidStopLoading();
if (is_prerender_page_activation) {
base::TimeDelta delta = base::TimeTicks::Now() - navigation_start;
RecordPrerenderActivationTime(delta, prerender_trigger_type,
prerender_embedder_histogram_suffix);
DCHECK(prerender_main_frame_replication_state ==
frame_tree()->root()->current_replication_state());
}
}
void RenderFrameHostImpl::StartLoadingForAsyncNavigationApiCommit() {
LoadingState previous_frame_tree_loading_state =
frame_tree()->LoadingTree()->GetLoadingState();
loading_state_ = LoadingState::LOADING_UI_REQUESTED;
frame_tree_node()->DidStartLoading(previous_frame_tree_loading_state);
}
void RenderFrameHostImpl::DidCommitSameDocumentNavigation(
mojom::DidCommitProvisionalLoadParamsPtr params,
mojom::DidCommitSameDocumentNavigationParamsPtr same_document_params) {
TRACE_EVENT("navigation",
"RenderFrameHostImpl::DidCommitSameDocumentNavigation",
ChromeTrackEvent::kRenderFrameHost, this, "url",
params->url.possibly_invalid_spec());
SCOPED_UMA_HISTOGRAM_TIMER(
"Navigation.DidCommitSameDocumentNavigation.Duration");
ScopedActiveURL scoped_active_url(params->url,
GetMainFrame()->GetLastCommittedOrigin());
ScopedCommitStateResetter commit_state_resetter(this);
if (lifecycle_state() != LifecycleStateImpl::kPrerendering &&
IsInactiveAndDisallowActivation(
DisallowActivationReasonId::kCommitSameDocumentNavigation)) {
return;
}
auto request_entry =
same_document_navigation_requests_.find(params->navigation_token);
bool is_browser_initiated =
(request_entry != same_document_navigation_requests_.end());
std::unique_ptr<NavigationRequest> request =
is_browser_initiated ? std::move(request_entry->second) : nullptr;
same_document_navigation_requests_.erase(params->navigation_token);
if (!MaybeInterceptCommitCallback(request.get(), ¶ms, nullptr)) {
return;
}
if (!DidCommitNavigationInternal(std::move(request), std::move(params),
std::move(same_document_params))) {
return;
}
commit_state_resetter.disable();
}
void RenderFrameHostImpl::DidOpenDocumentInputStream(const GURL& url) {
if (!ValidateURLAndOrigin(url, last_committed_origin_,
true,
nullptr)) {
return;
}
GURL filtered_url(url);
GetProcess()->FilterURL(false, &filtered_url);
renderer_url_info_.last_document_url = filtered_url;
if (owner_) {
owner_->DidOpenDocumentInputStream();
}
}
RenderWidgetHostImpl* RenderFrameHostImpl::GetRenderWidgetHost() {
RenderFrameHostImpl* frame = this;
while (frame) {
if (frame->GetLocalRenderWidgetHost())
return frame->GetLocalRenderWidgetHost();
frame = frame->GetParent();
}
NOTREACHED();
return nullptr;
}
RenderWidgetHostView* RenderFrameHostImpl::GetView() {
return GetRenderWidgetHost()->GetView();
}
GlobalRenderFrameHostId RenderFrameHostImpl::GetGlobalId() const {
return GlobalRenderFrameHostId(GetProcess()->GetID(), GetRoutingID());
}
bool RenderFrameHostImpl::HasPendingCommitNavigation() const {
return HasPendingCommitForCrossDocumentNavigation() ||
!same_document_navigation_requests_.empty();
}
bool RenderFrameHostImpl::HasPendingCommitForCrossDocumentNavigation() const {
return !navigation_requests_.empty();
}
NavigationRequest* RenderFrameHostImpl::GetSameDocumentNavigationRequest(
const base::UnguessableToken& token) {
auto request = same_document_navigation_requests_.find(token);
return (request == same_document_navigation_requests_.end())
? nullptr
: request->second.get();
}
void RenderFrameHostImpl::ResetOwnedNavigationRequests(
NavigationDiscardReason reason) {
#ifdef OHOS_LOGGER_REPORT
LOG_FEEDBACK(INFO) << "current lifecycle state: " << static_cast<int>(lifecycle_state_);
#endif
if (ShouldQueueNavigationsWhenPendingCommitRFHExists() &&
lifecycle_state_ == LifecycleStateImpl::kPendingCommit) {
CHECK(reason == NavigationDiscardReason::kRenderProcessGone ||
reason == NavigationDiscardReason::kWillRemoveFrame);
}
std::map<NavigationRequest*, std::unique_ptr<NavigationRequest>>
navigation_requests;
navigation_requests_.swap(navigation_requests);
base::flat_map<base::UnguessableToken, std::unique_ptr<NavigationRequest>>
same_document_navigation_requests;
same_document_navigation_requests_.swap(same_document_navigation_requests);
}
void RenderFrameHostImpl::SetNavigationRequest(
std::unique_ptr<NavigationRequest> navigation_request) {
DCHECK(navigation_request);
if (NavigationTypeUtils::IsSameDocument(
navigation_request->common_params().navigation_type)) {
loading_state_ = LoadingState::LOADING_WITHOUT_UI;
same_document_navigation_requests_[navigation_request->commit_params()
.navigation_token] =
std::move(navigation_request);
return;
}
loading_state_ = LoadingState::LOADING_UI_REQUESTED;
navigation_requests_[navigation_request.get()] =
std::move(navigation_request);
}
const scoped_refptr<NavigationOrDocumentHandle>&
RenderFrameHostImpl::GetNavigationOrDocumentHandle() {
if (!document_associated_data_->navigation_or_document_handle()) {
document_associated_data_->set_navigation_or_document_handle(
NavigationOrDocumentHandle::CreateForDocument(GetGlobalId()));
}
return document_associated_data_->navigation_or_document_handle();
}
void RenderFrameHostImpl::Unload(RenderFrameProxyHost* proxy, bool is_loading) {
TRACE_EVENT_NESTABLE_ASYNC_BEGIN1("navigation", "RenderFrameHostImpl::Unload",
TRACE_ID_LOCAL(this), "render_frame_host",
this);
if (IsPendingDeletion()) {
NOTREACHED() << "RFH should be in default state when calling Unload.";
return;
}
if (unload_event_monitor_timeout_ && !do_not_delete_for_testing_) {
unload_event_monitor_timeout_->Start(kUnloadTimeout);
}
is_waiting_for_unload_ack_ = true;
if (proxy) {
SetLifecycleState(LifecycleStateImpl::kRunningUnloadHandlers);
if (IsRenderFrameLive()) {
GetMojomFrameInRenderer()->Unload(
is_loading,
proxy->frame_tree_node()->current_replication_state().Clone(),
proxy->GetFrameToken(), proxy->CreateAndBindRemoteFrameInterfaces(),
proxy->CreateAndBindRemoteMainFrameInterfaces());
proxy->SetRenderFrameProxyCreated(true);
}
} else {
CHECK(ShouldCreateNewHostForSameSiteSubframe());
SetLifecycleState(LifecycleStateImpl::kReadyToBeDeleted);
}
if (web_ui())
web_ui()->RenderFrameHostUnloading();
StartPendingDeletionOnSubtree(PendingDeletionReason::kSwappedOut);
PendingDeletionCheckCompletedOnSubtree();
}
void RenderFrameHostImpl::UndoCommitNavigation(RenderFrameProxyHost& proxy,
bool is_loading) {
TRACE_EVENT("navigation", "RenderFrameHostImpl::UndoCommitNavigation",
"render_frame_host", this);
DCHECK_EQ(lifecycle_state_, LifecycleStateImpl::kPendingCommit);
if (IsRenderFrameLive()) {
proxy.TearDownMojoConnection();
GetMojomFrameInRenderer()->UndoCommitNavigation(
is_loading,
proxy.frame_tree_node()->current_replication_state().Clone(),
proxy.GetFrameToken(), proxy.CreateAndBindRemoteFrameInterfaces(),
proxy.CreateAndBindRemoteMainFrameInterfaces());
}
SetLifecycleState(LifecycleStateImpl::kReadyToBeDeleted);
}
void RenderFrameHostImpl::MaybeDispatchDidFinishLoadOnPrerenderActivation() {
if (!document_associated_data_
->pending_did_finish_load_url_for_prerendering())
return;
delegate_->OnDidFinishLoad(
this, *document_associated_data_
->pending_did_finish_load_url_for_prerendering());
document_associated_data_
->reset_pending_did_finish_load_url_for_prerendering();
}
void RenderFrameHostImpl::MaybeDispatchDOMContentLoadedOnPrerenderActivation() {
if (!document_associated_data_->dom_content_loaded())
return;
delegate_->DOMContentLoaded(this);
}
void RenderFrameHostImpl::SwapOuterDelegateFrame(RenderFrameProxyHost* proxy) {
GetMojomFrameInRenderer()->Unload(
false,
browsing_context_state_->current_replication_state().Clone(),
proxy->GetFrameToken(), proxy->CreateAndBindRemoteFrameInterfaces(),
proxy->CreateAndBindRemoteMainFrameInterfaces());
}
void RenderFrameHostImpl::DetachFromProxy() {
if (IsPendingDeletion())
return;
DeleteRenderFrame(mojom::FrameDeleteIntention::kNotMainFrame);
StartPendingDeletionOnSubtree(PendingDeletionReason::kFrameDetach);
#if BUILDFLAG(IS_OHOS)
if (!frame_tree()) {
return;
}
#endif
frame_tree()->FrameUnloading(GetFrameTreeNodeForUnload());
PendingDeletionCheckCompletedOnSubtree();
}
void RenderFrameHostImpl::ProcessBeforeUnloadCompleted(
bool proceed,
bool treat_as_final_completion_callback,
const base::TimeTicks& renderer_before_unload_start_time,
const base::TimeTicks& renderer_before_unload_end_time,
bool for_legacy) {
TRACE_EVENT_NESTABLE_ASYNC_END1(
"navigation", "RenderFrameHostImpl BeforeUnload", TRACE_ID_LOCAL(this),
"render_frame_host", this);
RenderFrameHostImpl* initiator = GetBeforeUnloadInitiator();
if (!initiator)
return;
initiator->ProcessBeforeUnloadCompletedFromFrame(
proceed, treat_as_final_completion_callback, this,
false, renderer_before_unload_start_time,
renderer_before_unload_end_time, for_legacy);
}
RenderFrameHostImpl* RenderFrameHostImpl::GetBeforeUnloadInitiator() {
for (RenderFrameHostImpl* frame = this; frame; frame = frame->GetParent()) {
if (frame->is_waiting_for_beforeunload_completion_)
return frame;
}
return nullptr;
}
void RenderFrameHostImpl::ProcessBeforeUnloadCompletedFromFrame(
bool proceed,
bool treat_as_final_completion_callback,
RenderFrameHostImpl* frame,
bool is_frame_being_destroyed,
const base::TimeTicks& renderer_before_unload_start_time,
const base::TimeTicks& renderer_before_unload_end_time,
bool for_legacy) {
if (!proceed || treat_as_final_completion_callback) {
beforeunload_pending_replies_.clear();
} else {
beforeunload_pending_replies_.erase(frame);
if (!beforeunload_pending_replies_.empty())
return;
}
DCHECK(!send_before_unload_start_time_.is_null());
base::TimeTicks before_unload_end_time = renderer_before_unload_end_time;
base::TimeDelta browser_to_renderer_ipc_time_delta;
if (!renderer_before_unload_start_time.is_null() &&
!renderer_before_unload_end_time.is_null()) {
base::TimeTicks before_unload_completed_time = base::TimeTicks::Now();
if (!base::TimeTicks::IsConsistentAcrossProcesses() && !for_legacy) {
blink::InterProcessTimeTicksConverter converter(
blink::LocalTimeTicks::FromTimeTicks(send_before_unload_start_time_),
blink::LocalTimeTicks::FromTimeTicks(before_unload_completed_time),
blink::RemoteTimeTicks::FromTimeTicks(
renderer_before_unload_start_time),
blink::RemoteTimeTicks::FromTimeTicks(
renderer_before_unload_end_time));
const base::TimeTicks browser_before_unload_start_time =
converter
.ToLocalTimeTicks(blink::RemoteTimeTicks::FromTimeTicks(
renderer_before_unload_start_time))
.ToTimeTicks();
const base::TimeTicks browser_before_unload_end_time =
converter
.ToLocalTimeTicks(blink::RemoteTimeTicks::FromTimeTicks(
renderer_before_unload_end_time))
.ToTimeTicks();
before_unload_end_time = browser_before_unload_end_time;
browser_to_renderer_ipc_time_delta =
browser_before_unload_start_time - send_before_unload_start_time_;
} else {
browser_to_renderer_ipc_time_delta =
(renderer_before_unload_start_time - send_before_unload_start_time_);
}
if (for_legacy) {
base::UmaHistogramTimes(
"Navigation.OnBeforeUnloadLegacyPostTaskTime",
before_unload_completed_time - renderer_before_unload_end_time);
DCHECK(browser_to_renderer_ipc_time_delta.is_zero());
} else {
base::UmaHistogramTimes(
"Navigation.OnBeforeUnloadBrowserToRendererIpcTime",
browser_to_renderer_ipc_time_delta);
}
base::TimeDelta on_before_unload_overhead_time =
(before_unload_completed_time - send_before_unload_start_time_) -
(renderer_before_unload_end_time - renderer_before_unload_start_time);
base::UmaHistogramTimes("Navigation.OnBeforeUnloadOverheadTime",
on_before_unload_overhead_time);
frame_tree_node_->navigator().LogBeforeUnloadTime(
renderer_before_unload_start_time, renderer_before_unload_end_time,
send_before_unload_start_time_, for_legacy);
}
is_waiting_for_beforeunload_completion_ = false;
has_shown_beforeunload_dialog_ = false;
if (beforeunload_timeout_)
beforeunload_timeout_->Stop();
send_before_unload_start_time_ = base::TimeTicks();
base::OnceClosure task = base::BindOnce(
[](base::WeakPtr<RenderFrameHostImpl> self,
const base::TimeTicks& before_unload_end_time, bool proceed,
bool unload_ack_is_for_navigation) {
if (!self)
return;
FrameTreeNode* frame = self->frame_tree_node();
if (unload_ack_is_for_navigation) {
frame->navigator().BeforeUnloadCompleted(frame, proceed,
before_unload_end_time);
} else {
frame->render_manager()->BeforeUnloadCompleted(proceed);
}
},
weak_ptr_factory_.GetWeakPtr(),
before_unload_end_time - browser_to_renderer_ipc_time_delta, proceed,
unload_ack_is_for_navigation_);
if (is_frame_being_destroyed) {
DCHECK(proceed);
base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE, std::move(task));
} else {
std::move(task).Run();
}
if (!proceed)
frame_tree_->DidCancelLoading();
}
bool RenderFrameHostImpl::IsWaitingForUnloadACK() const {
return page_close_state_ == PageCloseState::kRunningUnloadHandlers ||
is_waiting_for_unload_ack_;
}
bool RenderFrameHostImpl::BeforeUnloadTimedOut() const {
return beforeunload_timeout_ &&
(send_before_unload_start_time_ != base::TimeTicks()) &&
(base::TimeTicks::Now() - send_before_unload_start_time_) >
beforeunload_timeout_delay_;
}
void RenderFrameHostImpl::OnUnloadACK() {
if (unload_ack_callback_ && unload_ack_callback_.Run()) {
return;
}
RenderFrameHostOwner* owner =
IsPendingDeletion() ? GetFrameTreeNodeForUnload() : owner_;
if (!is_main_frame() &&
owner->GetRenderFrameHostManager().is_attaching_inner_delegate()) {
RenderFrameDeleted();
return;
}
if (!is_waiting_for_unload_ack_)
return;
if (do_not_delete_for_testing_)
return;
DCHECK_EQ(LifecycleStateImpl::kRunningUnloadHandlers, lifecycle_state());
SetLifecycleState(LifecycleStateImpl::kReadyToBeDeleted);
PendingDeletionCheckCompleted();
}
void RenderFrameHostImpl::OnUnloaded() {
DCHECK(is_waiting_for_unload_ack_);
TRACE_EVENT_NESTABLE_ASYNC_END0("navigation", "RenderFrameHostImpl::Unload",
TRACE_ID_LOCAL(this));
if (unload_event_monitor_timeout_)
unload_event_monitor_timeout_->Stop();
base::WeakPtr<RenderFrameHostImpl> self = GetWeakPtr();
ClearWebUI();
if (!self) {
return;
}
bool deleted =
GetFrameTreeNodeForUnload()->render_manager()->DeleteFromPendingList(
this);
CHECK(deleted);
}
void RenderFrameHostImpl::DisableUnloadTimerForTesting() {
unload_event_monitor_timeout_.reset();
}
bool RenderFrameHostImpl::IsBackForwardCacheEvictionTimeRunningForTesting()
const {
return back_forward_cache_eviction_timer_.IsRunning();
}
void RenderFrameHostImpl::SetSubframeUnloadTimeoutForTesting(
const base::TimeDelta& timeout) {
subframe_unload_timeout_ = timeout;
}
#if BUILDFLAG(IS_ANDROID)
void RenderFrameHostImpl::RequestSmartClipExtract(
ExtractSmartClipDataCallback callback,
gfx::Rect rect) {
int32_t callback_id = smart_clip_callbacks_.Add(
std::make_unique<ExtractSmartClipDataCallback>(std::move(callback)));
GetAssociatedLocalFrame()->ExtractSmartClipData(
rect, base::BindOnce(&RenderFrameHostImpl::OnSmartClipDataExtracted,
base::Unretained(this), callback_id));
}
void RenderFrameHostImpl::OnSmartClipDataExtracted(int32_t callback_id,
const std::u16string& text,
const std::u16string& html,
const gfx::Rect& clip_rect) {
std::move(*smart_clip_callbacks_.Lookup(callback_id))
.Run(text, html, clip_rect);
smart_clip_callbacks_.Remove(callback_id);
}
#endif
#if BUILDFLAG(IS_OHOS)
void RenderFrameHostImpl::GetImageFromCache(const std::string& url,
ImageCacheCallback callback) {
GetAssociatedLocalFrame()->GetImageFromCache(url, std::move(callback));
}
#endif
void RenderFrameHostImpl::RunModalAlertDialog(
const std::u16string& alert_message,
bool disable_third_party_subframe_suppresion,
RunModalAlertDialogCallback response_callback) {
auto dialog_closed_callback = base::BindOnce(
[](RunModalAlertDialogCallback response_callback, bool success,
const std::u16string& response) {
std::move(response_callback).Run();
},
std::move(response_callback));
RunJavaScriptDialog(alert_message, std::u16string(),
JAVASCRIPT_DIALOG_TYPE_ALERT,
disable_third_party_subframe_suppresion,
std::move(dialog_closed_callback));
}
void RenderFrameHostImpl::RunModalConfirmDialog(
const std::u16string& alert_message,
bool disable_third_party_subframe_suppresion,
RunModalConfirmDialogCallback response_callback) {
auto dialog_closed_callback = base::BindOnce(
[](RunModalConfirmDialogCallback response_callback, bool success,
const std::u16string& response) {
std::move(response_callback).Run(success);
},
std::move(response_callback));
RunJavaScriptDialog(alert_message, std::u16string(),
JAVASCRIPT_DIALOG_TYPE_CONFIRM,
disable_third_party_subframe_suppresion,
std::move(dialog_closed_callback));
}
void RenderFrameHostImpl::RunModalPromptDialog(
const std::u16string& alert_message,
const std::u16string& default_value,
bool disable_third_party_subframe_suppresion,
RunModalPromptDialogCallback response_callback) {
RunJavaScriptDialog(
alert_message, default_value, JAVASCRIPT_DIALOG_TYPE_PROMPT,
disable_third_party_subframe_suppresion, std::move(response_callback));
}
void RenderFrameHostImpl::RunJavaScriptDialog(
const std::u16string& message,
const std::u16string& default_prompt,
JavaScriptDialogType dialog_type,
bool disable_third_party_subframe_suppresion,
JavaScriptDialogCallback ipc_response_callback) {
if (!IsActive() || !GetPage().IsPrimary() || IsNestedWithinFencedFrame() ||
frame_tree()->delegate()->IsPortal()) {
std::move(ipc_response_callback).Run(false, std::u16string());
return;
}
GetProcess()->SetBlocked(true);
delegate_->RunJavaScriptDialog(
this, message, default_prompt, dialog_type,
disable_third_party_subframe_suppresion,
base::BindOnce(&RenderFrameHostImpl::JavaScriptDialogClosed,
weak_ptr_factory_.GetWeakPtr(),
std::move(ipc_response_callback)));
}
void RenderFrameHostImpl::RunBeforeUnloadConfirm(
bool is_reload,
RunBeforeUnloadConfirmCallback ipc_response_callback) {
TRACE_EVENT1("navigation", "RenderFrameHostImpl::OnRunBeforeUnloadConfirm",
"render_frame_host", this);
if (!IsActive() || !GetPage().IsPrimary() || IsNestedWithinFencedFrame() ||
frame_tree()->delegate()->IsPortal()) {
std::move(ipc_response_callback).Run(false);
return;
}
RenderFrameHostImpl* beforeunload_initiator = GetBeforeUnloadInitiator();
if (beforeunload_initiator) {
if (beforeunload_initiator->beforeunload_dialog_request_cancels_unload_) {
std::move(ipc_response_callback).Run(false);
return;
}
if (beforeunload_initiator->has_shown_beforeunload_dialog_) {
std::move(ipc_response_callback).Run(true);
return;
}
beforeunload_initiator->has_shown_beforeunload_dialog_ = true;
} else {
}
GetProcess()->SetBlocked(true);
for (RenderFrameHostImpl* frame = this; frame; frame = frame->GetParent()) {
if (frame->beforeunload_timeout_)
frame->beforeunload_timeout_->Stop();
}
auto ipc_callback_wrapper = base::BindOnce(
[](RunBeforeUnloadConfirmCallback response_callback, bool success,
const std::u16string& response) {
std::move(response_callback).Run(success);
},
std::move(ipc_response_callback));
auto dialog_closed_callback = base::BindOnce(
&RenderFrameHostImpl::JavaScriptDialogClosed,
weak_ptr_factory_.GetWeakPtr(), std::move(ipc_callback_wrapper));
delegate_->RunBeforeUnloadConfirm(this, is_reload,
std::move(dialog_closed_callback));
}
void RenderFrameHostImpl::MaybeStartOutermostMainFrameNavigation(
const std::vector<GURL>& urls) {
const bool kStartupEnabled =
base::FeatureList::IsEnabled(kSpeculativeServiceWorkerStartup);
const bool kWarmUpEnabled =
base::FeatureList::IsEnabled(
blink::features::kSpeculativeServiceWorkerWarmUp) &&
!blink::features::kSpeculativeServiceWorkerWarmUpDryRun.Get();
if (!kStartupEnabled && !kWarmUpEnabled) {
return;
}
TRACE_EVENT0("navigation",
"RenderFrameHostImpl::MaybeStartOutermostMainFrameNavigation");
ServiceWorkerContextWrapper* context =
GetStoragePartition()->GetServiceWorkerContext();
if (!context) {
return;
}
for (const auto& url : urls) {
GURL filtered_url(url);
GetProcess()->FilterURL(false, &filtered_url);
if (filtered_url.spec() == kBlockedURL) {
continue;
}
if (!OriginCanAccessServiceWorkers(filtered_url)) {
continue;
}
const blink::StorageKey key =
blink::StorageKey::CreateFirstParty(url::Origin::Create(filtered_url));
if (!context->MaybeHasRegistrationForStorageKey(key)) {
continue;
}
if (kStartupEnabled) {
context->StartServiceWorkerForNavigationHint(filtered_url, key,
base::DoNothing());
}
if (kWarmUpEnabled) {
context->WarmUpServiceWorker(filtered_url, key, base::DoNothing());
}
}
}
void RenderFrameHostImpl::UpdateFaviconURL(
std::vector<blink::mojom::FaviconURLPtr> favicon_urls) {
DCHECK(!GetParent());
GetPage().set_favicon_urls(std::move(favicon_urls));
delegate_->UpdateFaviconURL(this, GetPage().favicon_urls());
}
float RenderFrameHostImpl::GetPageScaleFactor() const {
DCHECK(!GetParent());
return page_scale_factor_;
}
void RenderFrameHostImpl::ScaleFactorChanged(float scale) {
DCHECK(!GetParent());
page_scale_factor_ = scale;
delegate_->OnPageScaleFactorChanged(GetPage());
}
void RenderFrameHostImpl::ContentsPreferredSizeChanged(
const gfx::Size& pref_size) {
if (IsInactiveAndDisallowActivation(
DisallowActivationReasonId::kContentsPreferredSizeChanged)) {
return;
}
if (GetParentOrOuterDocument())
return;
delegate_->UpdateWindowPreferredSize(pref_size);
}
void RenderFrameHostImpl::TextAutosizerPageInfoChanged(
blink::mojom::TextAutosizerPageInfoPtr page_info) {
GetPage().OnTextAutosizerPageInfoChanged(std::move(page_info));
}
void RenderFrameHostImpl::FocusPage() {
render_view_host_->OnFocus();
}
void RenderFrameHostImpl::TakeFocus(bool reverse) {
DCHECK(is_main_frame());
if (IsInactiveAndDisallowActivation(
DisallowActivationReasonId::kDispatchLoad)) {
return;
}
RenderFrameHostImpl* parent_or_outer_document =
GetParentOrOuterDocumentOrEmbedder();
if (parent_or_outer_document) {
RenderFrameProxyHost* proxy_host = GetProxyToOuterDelegate();
DCHECK(proxy_host);
parent_or_outer_document->DidFocusFrame();
parent_or_outer_document->AdvanceFocus(
reverse ? blink::mojom::FocusType::kBackward
: blink::mojom::FocusType::kForward,
proxy_host);
return;
}
render_view_host_->OnTakeFocus(reverse);
}
void RenderFrameHostImpl::UpdateTargetURL(
const GURL& url,
blink::mojom::LocalMainFrameHost::UpdateTargetURLCallback callback) {
if (!IsActive()) {
std::move(callback).Run();
return;
}
delegate_->UpdateTargetURL(this, url);
std::move(callback).Run();
}
void RenderFrameHostImpl::RequestClose() {
if (!IsOutermostMainFrame()) {
bad_message::ReceivedBadMessage(
GetProcess(), bad_message::RFH_WINDOW_CLOSE_ON_NON_OUTERMOST_FRAME);
return;
}
ClosePageIgnoringUnloadEvents(ClosePageSource::kRenderer);
}
bool RenderFrameHostImpl::HasStickyUserActivation() const {
return user_activation_state_.HasBeenActive();
}
bool RenderFrameHostImpl::IsActiveUserActivation() const {
return user_activation_state_.IsActive();
}
void RenderFrameHostImpl::ClearUserActivation() {
user_activation_state_.Clear();
history_user_activation_state_.Clear();
}
void RenderFrameHostImpl::ConsumeTransientUserActivation() {
user_activation_state_.ConsumeIfActive();
}
void RenderFrameHostImpl::ActivateUserActivation(
blink::mojom::UserActivationNotificationType notification_type,
bool sticky_only) {
if (sticky_only) {
user_activation_state_.SetHasBeenActive();
} else {
user_activation_state_.Activate(notification_type);
history_user_activation_state_.Activate();
}
}
bool RenderFrameHostImpl::IsHistoryUserActivationActive() const {
return history_user_activation_state_.IsActive();
}
void RenderFrameHostImpl::ConsumeHistoryUserActivation() {
history_user_activation_state_.Consume();
}
void RenderFrameHostImpl::ClosePage(ClosePageSource source) {
DCHECK(is_main_frame());
DCHECK(IsOutermostMainFrame() || frame_tree()->delegate()->IsPortal());
if (!IsInPrimaryMainFrame() && source == ClosePageSource::kRenderer) {
return;
}
page_close_state_ = PageCloseState::kRunningUnloadHandlers;
if (IsRenderFrameLive() && !IsPageReadyToBeClosed()) {
close_timeout_ = std::make_unique<TimeoutMonitor>(
base::BindRepeating(&RenderFrameHostImpl::ClosePageTimeout,
weak_ptr_factory_.GetWeakPtr(), source));
close_timeout_->Start(kUnloadTimeout);
GetAssociatedLocalMainFrame()->ClosePage(
base::BindOnce(&RenderFrameHostImpl::ClosePageIgnoringUnloadEvents,
weak_ptr_factory_.GetWeakPtr(), source));
} else {
ClosePageIgnoringUnloadEvents(source);
}
}
void RenderFrameHostImpl::ClosePageIgnoringUnloadEvents(
ClosePageSource source) {
if (close_timeout_) {
close_timeout_->Stop();
close_timeout_.reset();
}
if (!IsInPrimaryMainFrame() && source == ClosePageSource::kRenderer) {
page_close_state_ = PageCloseState::kNotClosing;
return;
}
page_close_state_ = PageCloseState::kReadyToBeClosed;
delegate_->Close();
}
bool RenderFrameHostImpl::IsPageReadyToBeClosed() {
DCHECK(IsInPrimaryMainFrame());
return page_close_state_ == PageCloseState::kReadyToBeClosed ||
delegate_->IsJavaScriptDialogShowing() || BeforeUnloadTimedOut();
}
void RenderFrameHostImpl::ClosePageTimeout(ClosePageSource source) {
if (delegate_->ShouldIgnoreUnresponsiveRenderer()) {
return;
}
ClosePageIgnoringUnloadEvents(source);
}
void RenderFrameHostImpl::ShowCreatedWindow(
const blink::LocalFrameToken& opener_frame_token,
WindowOpenDisposition disposition,
blink::mojom::WindowFeaturesPtr window_features,
bool user_gesture,
ShowCreatedWindowCallback callback) {
RenderFrameHostImpl* opener_frame_host =
FromFrameToken(GetProcess()->GetID(), opener_frame_token);
if (!opener_frame_host) {
std::move(callback).Run();
return;
}
opener_frame_host->delegate()->ShowCreatedWindow(
opener_frame_host, GetRenderWidgetHost()->GetRoutingID(), disposition,
*window_features, user_gesture);
std::move(callback).Run();
}
void RenderFrameHostImpl::SetWindowRect(const gfx::Rect& bounds,
SetWindowRectCallback callback) {
if (lifecycle_state_ == LifecycleStateImpl::kPrerendering) {
local_main_frame_host_receiver_.ReportBadMessage(
"SetWindowRect called during prerendering.");
return;
}
if (GetParentOrOuterDocument()) {
local_main_frame_host_receiver_.ReportBadMessage(
"SetWindowRect called from child frame.");
return;
}
delegate_->SetWindowRect(bounds);
std::move(callback).Run();
}
void RenderFrameHostImpl::DidFirstVisuallyNonEmptyPaint() {
DCHECK(is_main_frame());
GetPage().OnFirstVisuallyNonEmptyPaint();
}
void RenderFrameHostImpl::DownloadURL(
blink::mojom::DownloadURLParamsPtr blink_parameters) {
if (CancelPrerendering(
PrerenderCancellationReason(PrerenderFinalStatus::kDownload))) {
return;
}
if (!VerifyDownloadUrlParams(GetProcess(), *blink_parameters)) {
return;
}
net::NetworkTrafficAnnotationTag traffic_annotation =
net::DefineNetworkTrafficAnnotation("renderer_initiated_download", R"(
semantics {
sender: "Download from Renderer"
description:
"The frame has either navigated to a URL that was determined to be "
"a download via one of the renderer's classification mechanisms, "
"or WebView has requested a <canvas> or <img> element at a "
"specific location be to downloaded."
trigger:
"The user navigated to a destination that was categorized as a "
"download, or WebView triggered saving a <canvas> or <img> tag."
data: "Only the URL we are attempting to download."
destination: WEBSITE
}
policy {
cookies_allowed: YES
cookies_store: "user"
setting: "This feature cannot be disabled by settings."
chrome_policy {
DownloadRestrictions {
DownloadRestrictions: 3
}
}
})");
std::unique_ptr<download::DownloadUrlParameters> parameters(
new download::DownloadUrlParameters(blink_parameters->url,
GetProcess()->GetID(), GetRoutingID(),
traffic_annotation));
parameters->set_content_initiated(!blink_parameters->is_context_menu_save);
parameters->set_has_user_gesture(blink_parameters->has_user_gesture);
parameters->set_suggested_name(
blink_parameters->suggested_name.value_or(std::u16string()));
parameters->set_prompt(blink_parameters->is_context_menu_save);
parameters->set_cross_origin_redirects(
blink_parameters->cross_origin_redirects);
parameters->set_referrer(
blink_parameters->referrer ? blink_parameters->referrer->url : GURL());
parameters->set_referrer_policy(Referrer::ReferrerPolicyForUrlRequest(
blink_parameters->referrer ? blink_parameters->referrer->policy
: network::mojom::ReferrerPolicy::kDefault));
parameters->set_initiator(
blink_parameters->initiator_origin.value_or(url::Origin()));
parameters->set_download_source(download::DownloadSource::FROM_RENDERER);
if (blink_parameters->data_url_blob) {
DataURLBlobReader::ReadDataURLFromBlob(
std::move(blink_parameters->data_url_blob),
base::BindOnce(&OnDataURLRetrieved, std::move(parameters)));
return;
}
scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory;
if (blink_parameters->blob_url_token) {
blob_url_loader_factory =
ChromeBlobStorageContext::URLLoaderFactoryForToken(
GetStoragePartition(), std::move(blink_parameters->blob_url_token));
}
StartDownload(std::move(parameters), std::move(blob_url_loader_factory));
}
void RenderFrameHostImpl::ReportNoBinderForInterface(const std::string& error) {
broker_receiver_.ReportBadMessage(error + " for the frame/document scope");
}
ukm::SourceId RenderFrameHostImpl::GetPageUkmSourceId() {
RenderFrameHostImpl* main_frame =
IsNestedWithinFencedFrame() ? GetOutermostMainFrame() : GetMainFrame();
int64_t navigation_id =
main_frame->last_committed_cross_document_navigation_id_;
if (navigation_id == -1)
return ukm::kInvalidSourceId;
return ukm::ConvertToSourceId(navigation_id,
ukm::SourceIdType::NAVIGATION_ID);
}
BrowserContext* RenderFrameHostImpl::GetBrowserContext() {
return GetProcess()->GetBrowserContext();
}
void RenderFrameHostImpl::ReportInspectorIssue(
blink::mojom::InspectorIssueInfoPtr info) {
devtools_instrumentation::BuildAndReportBrowserInitiatedIssue(
this, std::move(info));
}
void RenderFrameHostImpl::WriteIntoTrace(
perfetto::TracedProto<TraceProto> proto) const {
proto.Set(TraceProto::kRenderFrameHostId, GetGlobalId());
proto->set_frame_tree_node_id(GetFrameTreeNodeId());
proto->set_lifecycle_state(LifecycleStateToProto());
proto->set_frame_type(GetFrameTypeProto());
proto->set_origin(GetLastCommittedOrigin().GetDebugString());
proto->set_url(GetLastCommittedURL().possibly_invalid_spec());
proto.Set(TraceProto::kProcess, GetProcess());
proto.Set(TraceProto::kSiteInstance, GetSiteInstance());
if (auto* parent = GetParent()) {
proto.Set(TraceProto::kParent, parent);
} else if (auto* outer_document = GetParentOrOuterDocument()) {
proto.Set(TraceProto::kOuterDocument, outer_document);
outer_document->WriteIntoTrace(proto.WriteNestedMessage(
perfetto::protos::pbzero::RenderFrameHost::kOuterDocument));
} else if (auto* embedder = GetParentOrOuterDocumentOrEmbedder()) {
proto.Set(TraceProto::kEmbedder, embedder);
embedder->WriteIntoTrace(proto.WriteNestedMessage(
perfetto::protos::pbzero::RenderFrameHost::kEmbedder));
}
proto.Set(TraceProto::kBrowsingContextState, browsing_context_state_);
}
perfetto::protos::pbzero::RenderFrameHost::LifecycleState
RenderFrameHostImpl::LifecycleStateToProto() const {
using RFHProto = perfetto::protos::pbzero::RenderFrameHost;
switch (lifecycle_state()) {
case LifecycleStateImpl::kSpeculative:
return RFHProto::SPECULATIVE;
case LifecycleStateImpl::kPendingCommit:
return RFHProto::PENDING_COMMIT;
case LifecycleStateImpl::kPrerendering:
return RFHProto::PRERENDERING;
case LifecycleStateImpl::kActive:
return RFHProto::ACTIVE;
case LifecycleStateImpl::kInBackForwardCache:
return RFHProto::IN_BACK_FORWARD_CACHE;
case LifecycleStateImpl::kRunningUnloadHandlers:
return RFHProto::RUNNING_UNLOAD_HANDLERS;
case LifecycleStateImpl::kReadyToBeDeleted:
return RFHProto::READY_TO_BE_DELETED;
}
return RFHProto::UNSPECIFIED;
}
perfetto::protos::pbzero::FrameTreeNodeInfo::FrameType
RenderFrameHostImpl::GetFrameTypeProto() const {
using RFHProto = perfetto::protos::pbzero::FrameTreeNodeInfo;
if (GetParent()) {
return RFHProto::SUBFRAME;
}
if (GetPage().IsPrimary()) {
return RFHProto::PRIMARY_MAIN_FRAME;
}
if (lifecycle_state() == LifecycleStateImpl::kPrerendering) {
return RFHProto::PRERENDER_MAIN_FRAME;
}
if (IsFencedFrameRoot()) {
return RFHProto::FENCED_FRAME_ROOT;
}
return RFHProto::UNSPECIFIED_FRAME_TYPE;
}
StoragePartitionImpl* RenderFrameHostImpl::GetStoragePartition() {
return static_cast<StoragePartitionImpl*>(
GetProcess()->GetStoragePartition());
}
void RenderFrameHostImpl::RequestTextSurroundingSelection(
blink::mojom::LocalFrame::GetTextSurroundingSelectionCallback callback,
int max_length) {
DCHECK(!callback.is_null());
GetAssociatedLocalFrame()->GetTextSurroundingSelection(max_length,
std::move(callback));
}
bool RenderFrameHostImpl::HasCommittingNavigationRequestForOrigin(
const url::Origin& origin,
NavigationRequest* navigation_request_to_exclude) {
for (const auto& it : navigation_requests_) {
NavigationRequest* request = it.first;
if (request != navigation_request_to_exclude &&
request->HasCommittingOrigin(origin)) {
return true;
}
}
return false;
}
void RenderFrameHostImpl::SendInterventionReport(const std::string& id,
const std::string& message) {
GetAssociatedLocalFrame()->SendInterventionReport(id, message);
}
WebUI* RenderFrameHostImpl::GetWebUI() {
return web_ui();
}
void RenderFrameHostImpl::AllowBindings(int bindings_flags) {
if (GetProcess()->IsForGuestsOnly()) {
NOTREACHED() << "Never grant bindings to a guest process.";
return;
}
TRACE_EVENT2("navigation", "RenderFrameHostImpl::AllowBindings",
"render_frame_host", this, "bindings_flags", bindings_flags);
int webui_bindings = bindings_flags & kWebUIBindingsPolicyMask;
if (webui_bindings != BINDINGS_POLICY_NONE &&
!RenderProcessHost::run_renderer_in_process() &&
base::FeatureList::IsEnabled(kEnsureAllowBindingsIsAlwaysForWebUI)) {
ProcessLock process_lock = GetProcess()->GetProcessLock();
if (!process_lock.is_locked_to_site() ||
!base::Contains(URLDataManagerBackend::GetWebUISchemes(),
process_lock.lock_url().scheme())) {
SCOPED_CRASH_KEY_STRING256("AllowBindings", "process_lock",
process_lock.ToString());
NOTREACHED() << "Calling AllowBindings for a process not locked to WebUI:"
<< process_lock;
base::debug::DumpWithoutCrashing();
}
}
if (web_ui_)
CHECK_EQ(web_ui_->GetBindings(), webui_bindings);
if (webui_bindings && GetProcess()->IsInitializedAndNotDead() &&
!ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
GetProcess()->GetID())) {
if (GetProcess()->GetActiveViewCount() > 1 &&
!base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kSingleProcess))
return;
}
if (webui_bindings) {
ChildProcessSecurityPolicyImpl::GetInstance()->GrantWebUIBindings(
GetProcess()->GetID(), webui_bindings);
}
enabled_bindings_ |= bindings_flags;
if (is_render_frame_created()) {
GetFrameBindingsControl()->AllowBindings(enabled_bindings_);
if (web_ui_ && enabled_bindings_ & BINDINGS_POLICY_WEB_UI)
web_ui_->SetUpMojoConnection();
}
}
int RenderFrameHostImpl::GetEnabledBindings() {
return enabled_bindings_;
}
void RenderFrameHostImpl::SetWebUIProperty(const std::string& name,
const std::string& value) {
if (GetParentOrOuterDocument())
return;
if (enabled_bindings_ & BINDINGS_POLICY_WEB_UI)
web_ui_->SetProperty(name, value);
else
ReceivedBadMessage(GetProcess(), bad_message::RVH_WEB_UI_BINDINGS_MISMATCH);
}
void RenderFrameHostImpl::DisableBeforeUnloadHangMonitorForTesting() {
beforeunload_timeout_.reset();
}
bool RenderFrameHostImpl::IsBeforeUnloadHangMonitorDisabledForTesting() {
return !beforeunload_timeout_;
}
void RenderFrameHostImpl::DoNotDeleteForTesting() {
do_not_delete_for_testing_ = true;
}
void RenderFrameHostImpl::ResumeDeletionForTesting() {
do_not_delete_for_testing_ = false;
}
void RenderFrameHostImpl::DetachForTesting() {
do_not_delete_for_testing_ = false;
RenderFrameHostImpl::Detach();
}
bool RenderFrameHostImpl::IsFeatureEnabled(
blink::mojom::PermissionsPolicyFeature feature) {
return permissions_policy_ && permissions_policy_->IsFeatureEnabledForOrigin(
feature, GetLastCommittedOrigin());
}
const blink::PermissionsPolicy* RenderFrameHostImpl::GetPermissionsPolicy() {
return permissions_policy_.get();
}
const blink::ParsedPermissionsPolicy&
RenderFrameHostImpl::GetPermissionsPolicyHeader() {
return permissions_policy_header_;
}
void RenderFrameHostImpl::ViewSource() {
delegate_->ViewSource(this);
}
void RenderFrameHostImpl::FlushNetworkAndNavigationInterfacesForTesting(
bool do_nothing_if_no_network_service_connection) {
if (do_nothing_if_no_network_service_connection &&
!network_service_disconnect_handler_holder_) {
return;
}
DCHECK(network_service_disconnect_handler_holder_);
network_service_disconnect_handler_holder_.FlushForTesting();
DCHECK(IsRenderFrameLive());
DCHECK(frame_);
frame_.FlushForTesting();
}
void RenderFrameHostImpl::PrepareForInnerWebContentsAttach(
PrepareForInnerWebContentsAttachCallback callback) {
CHECK(owner_);
owner_->GetRenderFrameHostManager().PrepareForInnerDelegateAttach(
std::move(callback));
}
void RenderFrameHostImpl::UpdateSubresourceLoaderFactories() {
if (!frame_)
return;
if (!recreate_default_url_loader_factory_after_network_service_crash_ &&
isolated_worlds_requiring_separate_url_loader_factory_.empty()) {
return;
}
SCOPED_CRASH_KEY_STRING256("rfhi-uslf", "frame->ToDebugString",
ToDebugString());
auto subresource_loader_factories_config =
SubresourceLoaderFactoriesConfig::ForPendingOrLastCommittedNavigation(
*this);
mojo::PendingRemote<network::mojom::URLLoaderFactory> default_factory_remote;
bool bypass_redirect_checks = false;
if (recreate_default_url_loader_factory_after_network_service_crash_) {
DCHECK(!IsOutOfProcessNetworkService() ||
network_service_disconnect_handler_holder_.is_bound());
bypass_redirect_checks = CreateNetworkServiceDefaultFactoryAndObserve(
CreateURLLoaderFactoryParamsForMainWorld(
subresource_loader_factories_config,
"RFHI::UpdateSubresourceLoaderFactories"),
subresource_loader_factories_config.ukm_source_id(),
default_factory_remote.InitWithNewPipeAndPassReceiver());
}
std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
subresource_loader_factories =
std::make_unique<blink::PendingURLLoaderFactoryBundle>(
std::move(default_factory_remote),
blink::PendingURLLoaderFactoryBundle::SchemeMap(),
CreateURLLoaderFactoriesForIsolatedWorlds(
subresource_loader_factories_config,
isolated_worlds_requiring_separate_url_loader_factory_),
bypass_redirect_checks);
GetMojomFrameInRenderer()->UpdateSubresourceLoaderFactories(
std::move(subresource_loader_factories));
}
blink::FrameOwnerElementType RenderFrameHostImpl::GetFrameOwnerElementType() {
return frame_owner_element_type_;
}
bool RenderFrameHostImpl::HasTransientUserActivation() {
return user_activation_state_.IsActive();
}
void RenderFrameHostImpl::NotifyUserActivation(
blink::mojom::UserActivationNotificationType notification_type) {
GetAssociatedLocalFrame()->NotifyUserActivation(notification_type);
}
void RenderFrameHostImpl::DidAccessInitialMainDocument() {
frame_tree_->DidAccessInitialMainDocument();
}
void RenderFrameHostImpl::DidChangeName(const std::string& name,
const std::string& unique_name) {
if ((IsInBackForwardCache() || IsPendingDeletion()) &&
base::FeatureList::IsEnabled(
features::kDisableFrameNameUpdateOnNonCurrentRenderFrameHost)) {
return;
}
if (GetParent() != nullptr) {
DCHECK(!unique_name.empty());
}
TRACE_EVENT2("navigation", "RenderFrameHostImpl::OnDidChangeName",
"render_frame_host", this, "name", name);
std::string old_name = browsing_context_state_->frame_name();
browsing_context_state_->SetFrameName(name, unique_name);
if (old_name.empty() && !name.empty())
frame_tree_node_->render_manager()->CreateProxiesForNewNamedFrame(
browsing_context_state_);
delegate_->DidChangeName(this, name);
}
void RenderFrameHostImpl::EnforceInsecureRequestPolicy(
blink::mojom::InsecureRequestPolicy policy) {
browsing_context_state_->SetInsecureRequestPolicy(policy);
}
void RenderFrameHostImpl::EnforceInsecureNavigationsSet(
const std::vector<uint32_t>& set) {
browsing_context_state_->SetInsecureNavigationsSet(set);
}
void RenderFrameHostImpl::AddDocumentService(
internal::DocumentServiceBase* document_service,
base::PassKey<internal::DocumentServiceBase>) {
document_associated_data_->services().push_back(document_service);
}
void RenderFrameHostImpl::RemoveDocumentService(
internal::DocumentServiceBase* document_service,
base::PassKey<internal::DocumentServiceBase>) {
if (document_service == last_web_bluetooth_service_for_testing_) {
last_web_bluetooth_service_for_testing_ = nullptr;
}
base::Erase(document_associated_data_->services(), document_service);
}
FrameTreeNode* RenderFrameHostImpl::FindAndVerifyChild(
int32_t child_frame_routing_id,
bad_message::BadMessageReason reason) {
auto child_frame_or_proxy = LookupRenderFrameHostOrProxy(
GetProcess()->GetID(), child_frame_routing_id);
return FindAndVerifyChildInternal(child_frame_or_proxy, reason);
}
FrameTreeNode* RenderFrameHostImpl::FindAndVerifyChild(
const blink::FrameToken& child_frame_token,
bad_message::BadMessageReason reason) {
auto child_frame_or_proxy =
LookupRenderFrameHostOrProxy(GetProcess()->GetID(), child_frame_token);
return FindAndVerifyChildInternal(child_frame_or_proxy, reason);
}
FrameTreeNode* RenderFrameHostImpl::FindAndVerifyChildInternal(
RenderFrameHostOrProxy child_frame_or_proxy,
bad_message::BadMessageReason reason) {
if (!child_frame_or_proxy)
return nullptr;
if (&child_frame_or_proxy.GetFrameTreeNode()->frame_tree() != frame_tree()) {
return nullptr;
}
if (child_frame_or_proxy.GetFrameTreeNode()->parent() != this) {
bad_message::ReceivedBadMessage(GetProcess(), reason);
return nullptr;
}
return child_frame_or_proxy.GetFrameTreeNode();
}
void RenderFrameHostImpl::UpdateTitle(
const absl::optional<::std::u16string>& title,
base::i18n::TextDirection title_direction) {
if (!is_main_frame())
return;
std::u16string received_title;
if (title.has_value())
received_title = title.value();
if (received_title.length() > blink::mojom::kMaxTitleChars) {
mojo::ReportBadMessage("Renderer sent too many characters in title.");
return;
}
delegate_->UpdateTitle(this, received_title, title_direction);
}
void RenderFrameHostImpl::DidInferColorScheme(
blink::mojom::PreferredColorScheme color_scheme) {
if (is_main_frame()) {
GetPage().DidInferColorScheme(color_scheme);
}
}
void RenderFrameHostImpl::UpdateEncoding(const std::string& encoding_name) {
if (!is_main_frame()) {
mojo::ReportBadMessage("Renderer sent updated encoding for a subframe.");
return;
}
GetPage().UpdateEncoding(encoding_name);
}
void RenderFrameHostImpl::FullscreenStateChanged(
bool is_fullscreen,
blink::mojom::FullscreenOptionsPtr options) {
if (IsInactiveAndDisallowActivation(
DisallowActivationReasonId::kFullScreenStateChanged))
return;
delegate_->FullscreenStateChanged(this, is_fullscreen, std::move(options));
}
void RenderFrameHostImpl::RegisterProtocolHandler(const std::string& scheme,
const GURL& url,
bool user_gesture) {
delegate_->RegisterProtocolHandler(this, scheme, url, user_gesture);
}
void RenderFrameHostImpl::UnregisterProtocolHandler(const std::string& scheme,
const GURL& url,
bool user_gesture) {
delegate_->UnregisterProtocolHandler(this, scheme, url, user_gesture);
}
void RenderFrameHostImpl::DidDisplayInsecureContent() {
frame_tree_->controller().ssl_manager()->DidDisplayMixedContent();
}
void RenderFrameHostImpl::DidContainInsecureFormAction() {
frame_tree_->controller().ssl_manager()->DidContainInsecureFormAction();
}
void RenderFrameHostImpl::MainDocumentElementAvailable(
bool uses_temporary_zoom_level) {
if (!is_main_frame()) {
bad_message::ReceivedBadMessage(
GetProcess(), bad_message::RFH_INVALID_CALL_FROM_NOT_MAIN_FRAME);
return;
}
GetPage().set_is_main_document_element_available(true);
GetPage().set_uses_temporary_zoom_level(uses_temporary_zoom_level);
if (!IsInPrimaryMainFrame())
return;
delegate_->PrimaryMainDocumentElementAvailable();
if (base::FeatureList::IsEnabled(blink::features::kFullscreenPopupWindows) &&
fullscreen_document_on_document_element_ready_ &&
(*fullscreen_document_on_document_element_ready_) == GetDocumentToken()) {
fullscreen_document_on_document_element_ready_ = absl::nullopt;
fullscreen_request_token_.Activate();
GetAssociatedLocalFrame()->RequestFullscreenDocumentElement();
}
if (!uses_temporary_zoom_level)
return;
#if !BUILDFLAG(IS_ANDROID)
HostZoomMapImpl* host_zoom_map =
static_cast<HostZoomMapImpl*>(HostZoomMap::Get(GetSiteInstance()));
host_zoom_map->SetTemporaryZoomLevel(GetGlobalId(),
host_zoom_map->GetDefaultZoomLevel());
#endif
}
void RenderFrameHostImpl::SetNeedsOcclusionTracking(bool needs_tracking) {
if (IsInactiveAndDisallowActivation(
DisallowActivationReasonId::kSetNeedsOcclusionTracking))
return;
RenderFrameProxyHost* proxy = GetProxyToParent();
if (!proxy) {
bad_message::ReceivedBadMessage(GetProcess(),
bad_message::RFH_NO_PROXY_TO_PARENT);
return;
}
if (proxy->is_render_frame_proxy_live()) {
proxy->GetAssociatedRemoteFrame()->SetNeedsOcclusionTracking(
needs_tracking);
}
}
void RenderFrameHostImpl::SetVirtualKeyboardMode(
ui::mojom::VirtualKeyboardMode mode) {
if (GetOutermostMainFrame() != this) {
bad_message::ReceivedBadMessage(
GetProcess(),
bad_message::RFHI_SET_OVERLAYS_CONTENT_NOT_OUTERMOST_FRAME);
return;
}
GetPage().SetVirtualKeyboardMode(mode);
}
#if BUILDFLAG(IS_ANDROID)
void RenderFrameHostImpl::UpdateUserGestureCarryoverInfo() {
if (!IsActive())
return;
delegate_->UpdateUserGestureCarryoverInfo();
}
#endif
void RenderFrameHostImpl::VisibilityChanged(
blink::mojom::FrameVisibility visibility) {
visibility_ = visibility;
}
void RenderFrameHostImpl::DidChangeThemeColor(
absl::optional<SkColor> theme_color) {
DCHECK(is_main_frame());
GetPage().OnThemeColorChanged(theme_color);
}
void RenderFrameHostImpl::DidChangeBackgroundColor(
const SkColor4f& background_color,
bool color_adjust) {
DCHECK(is_main_frame());
GetPage().DidChangeBackgroundColor(background_color, color_adjust);
}
#if defined(OHOS_EX_FREE_COPY)
void RenderFrameHostImpl::NotifyContextMenuWillShow() {
delegate_->NotifyContextMenuWillShow();
}
#endif
void RenderFrameHostImpl::SetCommitCallbackInterceptorForTesting(
CommitCallbackInterceptor* interceptor) {
DCHECK(!commit_callback_interceptor_ || !interceptor);
commit_callback_interceptor_ = interceptor;
}
void RenderFrameHostImpl::SetCreateNewPopupCallbackForTesting(
const CreateNewPopupWidgetCallbackForTesting& callback) {
DCHECK(!create_new_popup_widget_callback_ || !callback);
create_new_popup_widget_callback_ = callback;
}
void RenderFrameHostImpl::SetUnloadACKCallbackForTesting(
const UnloadACKCallbackForTesting& callback) {
DCHECK(!unload_ack_callback_ || !callback);
unload_ack_callback_ = callback;
}
const net::HttpResponseHeaders* RenderFrameHostImpl::GetLastResponseHeaders() {
DCHECK_NE(lifecycle_state(), LifecycleStateImpl::kSpeculative);
DCHECK_NE(lifecycle_state(), LifecycleStateImpl::kPendingCommit);
return last_response_head_ ? last_response_head_->headers.get() : nullptr;
}
void RenderFrameHostImpl::DidBlockNavigation(
const GURL& blocked_url,
const GURL& initiator_url,
blink::mojom::NavigationBlockedReason reason) {
GURL validated_blocked_url = blocked_url;
GURL validated_initiator_url = initiator_url;
RenderProcessHost* process = GetProcess();
process->FilterURL(false, &validated_blocked_url);
process->FilterURL(false, &validated_initiator_url);
DCHECK_NE(lifecycle_state(), LifecycleStateImpl::kPrerendering);
delegate_->OnDidBlockNavigation(validated_blocked_url,
validated_initiator_url, reason);
}
void RenderFrameHostImpl::DidChangeLoadProgress(double load_progress) {
if (!is_main_frame())
return;
if (load_progress < GetPage().load_progress())
return;
GetPage().set_load_progress(load_progress);
if (IsInPrimaryMainFrame())
delegate_->DidChangeLoadProgressForPrimaryMainFrame();
}
void RenderFrameHostImpl::DidFinishLoad(const GURL& validated_url) {
if (lifecycle_state() == LifecycleStateImpl::kPrerendering) {
document_associated_data_->set_pending_did_finish_load_url_for_prerendering(
validated_url);
return;
}
delegate_->OnDidFinishLoad(this, validated_url);
}
void RenderFrameHostImpl::DispatchLoad() {
TRACE_EVENT1("navigation", "RenderFrameHostImpl::DispatchLoad",
"render_frame_host", this);
if (lifecycle_state() != LifecycleStateImpl::kPrerendering) {
if (IsInactiveAndDisallowActivation(
DisallowActivationReasonId::kDispatchLoad))
return;
}
DCHECK(lifecycle_state() == LifecycleStateImpl::kActive ||
lifecycle_state() == LifecycleStateImpl::kPrerendering);
RenderFrameProxyHost* proxy = GetProxyToParent();
if (!proxy) {
bad_message::ReceivedBadMessage(GetProcess(),
bad_message::RFH_NO_PROXY_TO_PARENT);
return;
}
if (proxy->is_render_frame_proxy_live())
proxy->GetAssociatedRemoteFrame()->DispatchLoadEventForFrameOwner();
}
void RenderFrameHostImpl::GoToEntryAtOffset(
int32_t offset,
bool has_user_gesture,
absl::optional<blink::scheduler::TaskAttributionId>
soft_navigation_heuristics_task_id) {
OPTIONAL_TRACE_EVENT2("content", "RenderFrameHostImpl::GoToEntryAtOffset",
"render_frame_host", this, "offset", offset);
if (Navigator::ShouldIgnoreIncomingRendererRequest(
frame_tree_->root()->navigation_request(), has_user_gesture)) {
return;
}
if (delegate_->IsAllowedToGoToEntryAtOffset(offset)) {
frame_tree_->controller().GoToOffsetFromRenderer(
offset, this, soft_navigation_heuristics_task_id);
}
}
void RenderFrameHostImpl::NavigateToNavigationApiKey(
const std::string& key,
bool has_user_gesture,
absl::optional<blink::scheduler::TaskAttributionId> task_id) {
if (Navigator::ShouldIgnoreIncomingRendererRequest(
frame_tree_->root()->navigation_request(), has_user_gesture)) {
return;
}
frame_tree_->controller().NavigateToNavigationApiKey(this, task_id, key);
}
void RenderFrameHostImpl::NavigateEventHandlerPresenceChanged(bool present) {
DCHECK_NE(has_navigate_event_handler_, present);
has_navigate_event_handler_ = present;
}
void RenderFrameHostImpl::HandleAccessibilityFindInPageResult(
blink::mojom::FindInPageResultAXParamsPtr params) {
if (lifecycle_state() != LifecycleStateImpl::kActive)
return;
BrowserAccessibilityManager* manager =
GetOrCreateBrowserAccessibilityManager();
if (manager) {
manager->OnFindInPageResult(params->request_id, params->match_index,
params->start_id, params->start_offset,
params->end_id, params->end_offset);
}
}
void RenderFrameHostImpl::HandleAccessibilityFindInPageTermination() {
if (lifecycle_state() != LifecycleStateImpl::kActive)
return;
BrowserAccessibilityManager* manager =
GetOrCreateBrowserAccessibilityManager();
if (manager)
manager->OnFindInPageTermination();
}
void RenderFrameHostImpl::DocumentOnLoadCompleted() {
if (!is_main_frame()) {
bad_message::ReceivedBadMessage(
GetProcess(), bad_message::RFH_INVALID_CALL_FROM_NOT_MAIN_FRAME);
return;
}
GetPage().set_is_on_load_completed_in_main_document(true);
if (!IsInPrimaryMainFrame())
return;
delegate_->DocumentOnLoadCompleted(this);
}
void RenderFrameHostImpl::ForwardResourceTimingToParent(
blink::mojom::ResourceTimingInfoPtr timing) {
if (lifecycle_state() != LifecycleStateImpl::kPrerendering) {
if (IsInactiveAndDisallowActivation(
DisallowActivationReasonId::kForwardResourceTimingToParent))
return;
}
DCHECK(lifecycle_state() == LifecycleStateImpl::kActive ||
lifecycle_state() == LifecycleStateImpl::kPrerendering);
RenderFrameProxyHost* proxy = GetProxyToParent();
if (!proxy) {
bad_message::ReceivedBadMessage(GetProcess(),
bad_message::RFH_NO_PROXY_TO_PARENT);
return;
}
if (proxy->is_render_frame_proxy_live()) {
proxy->GetAssociatedRemoteFrame()->AddResourceTimingFromChild(
std::move(timing));
}
}
bool RenderFrameHostImpl::Reload() {
CHECK(IsActive());
return owner_->Reload();
}
void RenderFrameHostImpl::SendAccessibilityEventsToManager(
const AXEventNotificationDetails& details) {
if (!browser_accessibility_manager_)
return;
DCHECK(delegate_->GetAccessibilityMode().has_mode(ui::AXMode::kNativeAPIs));
if (!browser_accessibility_manager_->OnAccessibilityEvents(details)) {
AccessibilityFatalError();
}
}
bool RenderFrameHostImpl::IsInactiveAndDisallowActivation(uint64_t reason) {
TRACE_EVENT1("navigation",
"RenderFrameHostImpl::IsInactiveAndDisallowActivation",
"render_frame_host", this);
switch (lifecycle_state_) {
case LifecycleStateImpl::kRunningUnloadHandlers:
case LifecycleStateImpl::kReadyToBeDeleted:
return true;
case LifecycleStateImpl::kInBackForwardCache: {
if (!base::FeatureList::IsEnabled(features::kEvictOnAXEvents))
DCHECK_NE(reason, kAXEvent);
BackForwardCacheCanStoreDocumentResult can_store_flat;
can_store_flat.NoDueToDisallowActivation(reason);
EvictFromBackForwardCacheWithFlattenedReasons(can_store_flat);
}
return true;
case LifecycleStateImpl::kPrerendering:
DCHECK_NE(reason, DisallowActivationReasonId::kIndexedDBEvent);
CancelPrerendering(
PrerenderCancellationReason::BuildForDisallowActivationState(reason));
return true;
case LifecycleStateImpl::kSpeculative:
bad_message::ReceivedBadMessage(
GetProcess(), bad_message::RFH_INACTIVE_CHECK_FROM_SPECULATIVE_RFH);
return false;
case LifecycleStateImpl::kPendingCommit:
bad_message::ReceivedBadMessage(
GetProcess(),
bad_message::RFH_INACTIVE_CHECK_FROM_PENDING_COMMIT_RFH);
return false;
case LifecycleStateImpl::kActive:
return false;
}
}
bool RenderFrameHostImpl::IsInactiveAndDisallowActivationForAXEvents(
const std::vector<ui::AXEvent>& events) {
DCHECK(base::FeatureList::IsEnabled(features::kEvictOnAXEvents));
if (lifecycle_state_ != LifecycleStateImpl::kInBackForwardCache) {
return IsInactiveAndDisallowActivation(
DisallowActivationReasonId::kAXEvent);
}
BackForwardCacheCanStoreDocumentResult can_store_flat;
can_store_flat.NoDueToAXEvents(events);
EvictFromBackForwardCacheWithFlattenedReasons(can_store_flat);
return true;
}
void RenderFrameHostImpl::EvictFromBackForwardCache(
blink::mojom::RendererEvictionReason reason) {
EvictFromBackForwardCacheWithReason(
RendererEvictionReasonToNotRestoredReason(reason));
}
void RenderFrameHostImpl::EvictFromBackForwardCacheWithReason(
BackForwardCacheMetrics::NotRestoredReason reason) {
DCHECK_NE(reason,
BackForwardCacheMetrics::NotRestoredReason::kIgnoreEventAndEvict);
BackForwardCacheCanStoreDocumentResult flattened_reasons;
flattened_reasons.No(reason);
EvictFromBackForwardCacheWithFlattenedReasons(flattened_reasons);
}
void RenderFrameHostImpl::EvictFromBackForwardCacheWithFlattenedReasons(
BackForwardCacheCanStoreDocumentResult can_store_flat) {
auto can_store =
BackForwardCacheImpl::CreateEvictionBackForwardCacheCanStoreTreeResult(
*this, can_store_flat);
EvictFromBackForwardCacheWithFlattenedAndTreeReasons(can_store);
}
void RenderFrameHostImpl::EvictFromBackForwardCacheWithFlattenedAndTreeReasons(
BackForwardCacheCanStoreDocumentResultWithTree& can_store) {
TRACE_EVENT2("navigation", "RenderFrameHostImpl::EvictFromBackForwardCache",
"can_store", can_store.flattened_reasons.ToString(), "rfh",
static_cast<void*>(this));
TRACE_EVENT("navigation",
"RenderFrameHostImpl::"
"EvictFromBackForwardCacheWithFlattenedAndTreeReasons",
ChromeTrackEvent::kBackForwardCacheCanStoreDocumentResult,
can_store.flattened_reasons);
LOG(INFO) << "RenderFrameHostImpl::" << __func__ << " the value of can_stored flattened_reasons is: "
<< can_store.flattened_reasons.ToString();
DCHECK(IsBackForwardCacheEnabled());
RenderFrameHostImpl* top_document = GetOutermostMainFrame();
if (top_document->is_evicted_from_back_forward_cache_)
return;
bool in_back_forward_cache = IsInBackForwardCache();
BackForwardCacheMetrics* metrics = top_document->GetBackForwardCacheMetrics();
if (in_back_forward_cache && metrics) {
metrics->SetNotRestoredReasons(can_store);
}
if (!in_back_forward_cache) {
TRACE_EVENT0("navigation", "BackForwardCache_EvictAfterDocumentRestored");
BackForwardCacheMetrics::RecordEvictedAfterDocumentRestored(
BackForwardCacheMetrics::EvictedAfterDocumentRestoredReason::
kByJavaScript);
CaptureTraceForNavigationDebugScenario(
DebugScenario::kDebugBackForwardCacheEvictRestoreRace);
top_document->frame_tree()->controller().Reload(ReloadType::NORMAL, false);
return;
}
NavigationRequest* in_flight_navigation_request =
top_document->frame_tree_node()->navigation_request();
bool is_navigation_to_evicted_frame_in_flight =
(in_flight_navigation_request &&
in_flight_navigation_request->rfh_restored_from_back_forward_cache() ==
top_document);
if (is_navigation_to_evicted_frame_in_flight) {
in_flight_navigation_request->RestartBackForwardCachedNavigation();
}
top_document->is_evicted_from_back_forward_cache_ = true;
GetBackForwardCache().PostTaskToDestroyEvictedFrames();
}
void RenderFrameHostImpl::
UseDummyStickyBackForwardCacheDisablingFeatureForTesting() {
OnBackForwardCacheDisablingFeatureUsed(
BackForwardCacheDisablingFeature::kDummy);
}
bool RenderFrameHostImpl::HasSeenRecentXrOverlaySetup() {
static constexpr base::TimeDelta kMaxInterval = base::Seconds(1);
base::TimeDelta delta = base::TimeTicks::Now() - last_xr_overlay_setup_time_;
DVLOG(2) << __func__ << ": return " << (delta <= kMaxInterval);
return delta <= kMaxInterval;
}
void RenderFrameHostImpl::SetIsXrOverlaySetup() {
DVLOG(2) << __func__;
last_xr_overlay_setup_time_ = base::TimeTicks::Now();
}
void RenderFrameHostImpl::EnterFullscreen(
blink::mojom::FullscreenOptionsPtr options,
EnterFullscreenCallback callback) {
const bool had_fullscreen_token = fullscreen_request_token_.IsActive();
if (!IsActive() || !GetPage().IsPrimary()) {
std::move(callback).Run(false);
return;
}
if (!delegate_->HasSeenRecentScreenOrientationChange() &&
!WindowManagementAllowsFullscreen() && !HasSeenRecentXrOverlaySetup() &&
#if defined(OHOS_CUSTOM_VIDEO_PLAYER)
!options->is_custom_media_player &&
#endif
!GetContentClient()
->browser()
->CanEnterFullscreenWithoutUserActivation()) {
CHECK(owner_);
const bool consumed_activation = owner_->UpdateUserActivationState(
blink::mojom::UserActivationUpdateType::kConsumeTransientActivation,
blink::mojom::UserActivationNotificationType::kNone);
const bool consumed_token = fullscreen_request_token_.ConsumeIfActive();
if (!consumed_activation && !consumed_token) {
DLOG(ERROR) << "Cannot enter fullscreen because there is no transient "
<< "user activation, orientation change, XR overlay, nor "
<< "capability delegation.";
std::move(callback).Run(false);
return;
}
}
if (!delegate_->CanEnterFullscreenMode(this, *options)) {
std::move(callback).Run(false);
return;
}
const display::Screen* screen = display::Screen::GetScreen();
display::Display display;
if (screen && screen->GetNumDisplays() > 1 &&
screen->GetDisplayWithDisplayId(options->display_id, &display) &&
IsWindowManagementGranted(this)) {
transient_allow_popup_.Activate();
}
std::move(callback).Run(true);
std::set<SiteInstance*> notified_instances;
notified_instances.insert(GetSiteInstance());
for (RenderFrameHostImpl* rfh = this; rfh->GetParent();
rfh = rfh->GetParent()) {
SiteInstance* parent_site_instance = rfh->GetParent()->GetSiteInstance();
if (base::Contains(notified_instances, parent_site_instance))
continue;
RenderFrameProxyHost* child_proxy =
rfh->browsing_context_state()->GetRenderFrameProxyHost(
static_cast<SiteInstanceImpl*>(parent_site_instance)->group());
if (child_proxy->is_render_frame_proxy_live()) {
child_proxy->GetAssociatedRemoteFrame()->WillEnterFullscreen(
options.Clone());
notified_instances.insert(parent_site_instance);
}
}
if (had_fullscreen_token && !GetView()->HasFocus())
GetView()->Focus();
delegate_->EnterFullscreenMode(this, *options);
delegate_->FullscreenStateChanged(this, true,
std::move(options));
render_view_host_->GetWidget()->SynchronizeVisualProperties();
}
void RenderFrameHostImpl::ExitFullscreen() {
delegate_->ExitFullscreenMode(true);
render_view_host_->GetWidget()->SynchronizeVisualProperties();
}
void RenderFrameHostImpl::SuddenTerminationDisablerChanged(
bool present,
blink::mojom::SuddenTerminationDisablerType disabler_type) {
switch (disabler_type) {
case blink::mojom::SuddenTerminationDisablerType::kBeforeUnloadHandler:
DCHECK_NE(has_before_unload_handler_, present);
if (IsNestedWithinFencedFrame()) {
bad_message::ReceivedBadMessage(
GetProcess(),
bad_message::RFH_BEFOREUNLOAD_HANDLER_NOT_ALLOWED_IN_FENCED_FRAME);
return;
}
has_before_unload_handler_ = present;
break;
case blink::mojom::SuddenTerminationDisablerType::kPageHideHandler:
DCHECK_NE(has_pagehide_handler_, present);
has_pagehide_handler_ = present;
break;
case blink::mojom::SuddenTerminationDisablerType::kUnloadHandler:
DCHECK_NE(has_unload_handler_, present);
if (IsNestedWithinFencedFrame()) {
bad_message::ReceivedBadMessage(
GetProcess(),
bad_message::RFH_UNLOAD_HANDLER_NOT_ALLOWED_IN_FENCED_FRAME);
return;
}
has_unload_handler_ = present;
break;
case blink::mojom::SuddenTerminationDisablerType::kVisibilityChangeHandler:
DCHECK_NE(has_visibilitychange_handler_, present);
has_visibilitychange_handler_ = present;
break;
}
}
bool RenderFrameHostImpl::GetSuddenTerminationDisablerState(
blink::mojom::SuddenTerminationDisablerType disabler_type) {
if (do_not_delete_for_testing_ &&
disabler_type !=
blink::mojom::SuddenTerminationDisablerType::kBeforeUnloadHandler) {
return true;
}
switch (disabler_type) {
case blink::mojom::SuddenTerminationDisablerType::kBeforeUnloadHandler:
return has_before_unload_handler_;
case blink::mojom::SuddenTerminationDisablerType::kPageHideHandler:
return has_pagehide_handler_;
case blink::mojom::SuddenTerminationDisablerType::kUnloadHandler:
return has_unload_handler_;
case blink::mojom::SuddenTerminationDisablerType::kVisibilityChangeHandler:
return has_visibilitychange_handler_;
}
}
void RenderFrameHostImpl::DidDispatchDOMContentLoadedEvent() {
document_associated_data_->MarkDomContentLoaded();
if (lifecycle_state() == LifecycleStateImpl::kPrerendering)
return;
delegate_->DOMContentLoaded(this);
}
void RenderFrameHostImpl::FocusedElementChanged(
bool is_editable_element,
bool is_richly_editable_element,
const gfx::Rect& bounds_in_frame_widget,
blink::mojom::FocusType focus_type) {
if (!GetView())
return;
has_focused_editable_element_ = is_editable_element;
has_focused_richly_editable_element_ = is_richly_editable_element;
delegate_->OnFocusedElementChangedInFrame(
this,
gfx::Rect(GetView()->TransformPointToRootCoordSpace(
bounds_in_frame_widget.origin()),
bounds_in_frame_widget.size()),
focus_type);
}
void RenderFrameHostImpl::TextSelectionChanged(const std::u16string& text,
uint32_t offset,
const gfx::Range& range) {
RecordAction(base::UserMetricsAction("TextSelectionChanged"));
has_selection_ = !text.empty();
GetRenderWidgetHost()->SelectionChanged(text, offset, range);
}
void RenderFrameHostImpl::DidReceiveUserActivation() {
delegate_->DidReceiveUserActivation(this);
}
void RenderFrameHostImpl::MaybeIsolateForUserActivation() {
if (GetMainFrame()
->GetSiteInstance()
->GetSiteInfo()
.does_site_request_dedicated_process_for_coop()) {
DCHECK(base::FeatureList::IsEnabled(
features::kSiteIsolationForCrossOriginOpenerPolicy));
bool is_same_origin_activation =
GetParent() ? GetMainFrame()->GetLastCommittedOrigin().IsSameOriginWith(
GetLastCommittedOrigin())
: true;
if (is_same_origin_activation) {
SiteInstance::StartIsolatingSite(
GetSiteInstance()->GetBrowserContext(),
GetMainFrame()->GetLastCommittedURL(),
ChildProcessSecurityPolicy::IsolatedOriginSource::WEB_TRIGGERED,
SiteIsolationPolicy::ShouldPersistIsolatedCOOPSites());
}
}
}
void RenderFrameHostImpl::UpdateUserActivationState(
blink::mojom::UserActivationUpdateType update_type,
blink::mojom::UserActivationNotificationType notification_type) {
if (lifecycle_state() != LifecycleStateImpl::kActive)
return;
CHECK(owner_);
owner_->UpdateUserActivationState(update_type, notification_type);
}
void RenderFrameHostImpl::DidConsumeHistoryUserActivation() {
if (owner_) {
owner_->DidConsumeHistoryUserActivation();
}
}
void RenderFrameHostImpl::HadStickyUserActivationBeforeNavigationChanged(
bool value) {
browsing_context_state_->OnSetHadStickyUserActivationBeforeNavigation(value);
}
void RenderFrameHostImpl::ScrollRectToVisibleInParentFrame(
const gfx::RectF& rect_to_scroll,
blink::mojom::ScrollIntoViewParamsPtr params) {
if (IsInactiveAndDisallowActivation(
DisallowActivationReasonId::kDispatchLoad)) {
return;
}
RenderFrameProxyHost* proxy = nullptr;
if (IsFencedFrameRoot()) {
if (!params->for_focused_editable) {
local_frame_host_receiver_.ReportBadMessage(
"ScrollRectToVisibleInParentFrame can only be used for "
"is_for_editable from a fenced frame");
return;
}
proxy = GetProxyToOuterDelegate();
} else {
proxy = GetProxyToParent();
}
if (!proxy)
return;
proxy->ScrollRectToVisible(rect_to_scroll, std::move(params));
}
void RenderFrameHostImpl::BubbleLogicalScrollInParentFrame(
blink::mojom::ScrollDirection direction,
ui::ScrollGranularity granularity) {
if (IsInactiveAndDisallowActivation(
DisallowActivationReasonId::kDispatchLoad)) {
return;
}
RenderFrameProxyHost* proxy =
IsFencedFrameRoot() ? GetProxyToOuterDelegate() : GetProxyToParent();
if (!proxy) {
bad_message::ReceivedBadMessage(GetProcess(),
bad_message::RFH_NO_PROXY_TO_PARENT);
return;
}
if (proxy->is_render_frame_proxy_live()) {
proxy->GetAssociatedRemoteFrame()->BubbleLogicalScroll(direction,
granularity);
}
}
void RenderFrameHostImpl::ShowPopupMenu(
mojo::PendingRemote<blink::mojom::PopupMenuClient> popup_client,
const gfx::Rect& bounds,
int32_t item_height,
double font_size,
int32_t selected_item,
std::vector<blink::mojom::MenuItemPtr> menu_items,
bool right_aligned,
bool allow_multiple_selection) {
#if BUILDFLAG(USE_EXTERNAL_POPUP_MENU)
if (!IsActive()) {
if (lifecycle_state() == LifecycleStateImpl::kPrerendering) {
bad_message::ReceivedBadMessage(
GetProcess(), bad_message::RFH_POPUP_REQUEST_WHILE_PRERENDERING);
}
return;
}
if (delegate()->ShowPopupMenu(this, bounds)) {
return;
}
auto* view = render_view_host()->delegate_->GetDelegateView();
if (!view)
return;
gfx::Point original_point(bounds.x(), bounds.y());
gfx::Point transformed_point =
static_cast<RenderWidgetHostViewBase*>(GetView())
->TransformPointToRootCoordSpace(original_point);
gfx::Rect transformed_bounds(transformed_point.x(), transformed_point.y(),
bounds.width(), bounds.height());
view->ShowPopupMenu(this, std::move(popup_client), transformed_bounds,
item_height, font_size, selected_item,
std::move(menu_items), right_aligned,
allow_multiple_selection);
#endif
}
#if defined(OHOS_CLIPBOARD)
void RenderFrameHostImpl::MouseSelectMenuShow(bool show) {
if (delegate_) {
delegate_->MouseSelectMenuShow(show);
}
}
void RenderFrameHostImpl::ChangeVisibilityOfQuickMenu() {
if (delegate_) {
delegate_->ChangeVisibilityOfQuickMenu();
}
}
#endif
#ifdef OHOS_AI
void RenderFrameHostImpl::CloseImageOverlaySelection() {
if (delegate_) {
delegate_->CloseImageOverlaySelection();
}
}
#endif
void RenderFrameHostImpl::ShowContextMenu(
mojo::PendingAssociatedRemote<blink::mojom::ContextMenuClient>
context_menu_client,
const blink::UntrustworthyContextMenuParams& params) {
if (IsInactiveAndDisallowActivation(
DisallowActivationReasonId::kShowContextMenu))
return;
ContextMenuParams validated_params(params);
validated_params.page_url = GetOutermostMainFrame()->GetLastCommittedURL();
validated_params.frame_url = GetLastCommittedURL();
validated_params.frame_origin = GetLastCommittedOrigin();
validated_params.is_subframe = !!GetParentOrOuterDocument();
RenderProcessHost* process = GetProcess();
process->FilterURL(true, &validated_params.link_url);
process->FilterURL(true, &validated_params.src_url);
process->FilterURL(false, &validated_params.page_url);
process->FilterURL(true, &validated_params.frame_url);
gfx::Point original_point(validated_params.x, validated_params.y);
gfx::Point transformed_point =
static_cast<RenderWidgetHostViewBase*>(GetView())
->TransformPointToRootCoordSpace(original_point);
validated_params.x = transformed_point.x();
validated_params.y = transformed_point.y();
#ifdef OHOS_EX_TOPCONTROLS
if (GetView()) {
validated_params.y += GetView()->GetTopControlsOffset();
}
#endif
if (validated_params.selection_start_offset < 0) {
bad_message::ReceivedBadMessage(
GetProcess(), bad_message::RFH_NEGATIVE_SELECTION_START_OFFSET);
return;
}
delegate_->ShowContextMenu(*this, std::move(context_menu_client),
validated_params);
}
void RenderFrameHostImpl::DidLoadResourceFromMemoryCache(
const GURL& url,
const std::string& http_method,
const std::string& mime_type,
network::mojom::RequestDestination request_destination,
bool include_credentials) {
delegate_->DidLoadResourceFromMemoryCache(this, url, http_method, mime_type,
request_destination,
include_credentials);
}
void RenderFrameHostImpl::DidChangeFrameOwnerProperties(
const blink::FrameToken& child_frame_token,
blink::mojom::FrameOwnerPropertiesPtr properties) {
auto* child =
FindAndVerifyChild(child_frame_token, bad_message::RFH_OWNER_PROPERTY);
if (!child)
return;
bool has_display_none_property_changed =
properties->is_display_none !=
child->frame_owner_properties().is_display_none;
child->set_frame_owner_properties(*properties);
child->render_manager()->OnDidUpdateFrameOwnerProperties(*properties);
if (has_display_none_property_changed) {
delegate_->DidChangeDisplayState(child->current_frame_host(),
properties->is_display_none);
}
}
void RenderFrameHostImpl::DidChangeOpener(
const absl::optional<blink::LocalFrameToken>& opener_frame_token) {
if (!owner_)
return;
owner_->GetRenderFrameHostManager().DidChangeOpener(
opener_frame_token, GetSiteInstance()->group());
}
void RenderFrameHostImpl::DidChangeIframeAttributes(
const blink::FrameToken& child_frame_token,
blink::mojom::IframeAttributesPtr attributes) {
if (attributes->parsed_csp_attribute &&
!ValidateCSPAttribute(
attributes->parsed_csp_attribute->header->header_value)) {
bad_message::ReceivedBadMessage(GetProcess(),
bad_message::RFH_CSP_ATTRIBUTE);
return;
}
if (attributes->browsing_topics &&
!base::FeatureList::IsEnabled(blink::features::kBrowsingTopics)) {
bad_message::ReceivedBadMessage(
GetProcess(),
bad_message::RFH_RECEIVED_INVALID_BROWSING_TOPICS_ATTRIBUTE);
return;
}
auto* child = FindAndVerifyChild(
child_frame_token, bad_message::RFH_DID_CHANGE_IFRAME_ATTRIBUTE);
if (!child)
return;
child->SetAttributes(std::move(attributes));
}
void RenderFrameHostImpl::DidChangeFramePolicy(
const blink::FrameToken& child_frame_token,
const blink::FramePolicy& frame_policy) {
FrameTreeNode* child = FindAndVerifyChild(
child_frame_token, bad_message::RFH_SANDBOX_FLAGS);
if (!child)
return;
child->SetPendingFramePolicy(frame_policy);
if (child->current_frame_host()->GetSiteInstance() != GetSiteInstance()) {
child->current_frame_host()
->GetAssociatedLocalFrame()
->DidUpdateFramePolicy(frame_policy);
}
}
void RenderFrameHostImpl::CapturePaintPreviewOfSubframe(
const gfx::Rect& clip_rect,
const base::UnguessableToken& guid) {
if (IsInactiveAndDisallowActivation(
DisallowActivationReasonId::kCapturePaintPreview))
return;
if (IsOutermostMainFrame()) {
bad_message::ReceivedBadMessage(
GetProcess(), bad_message::RFH_SUBFRAME_CAPTURE_ON_MAIN_FRAME);
return;
}
delegate()->CapturePaintPreviewOfCrossProcessSubframe(clip_rect, guid, this);
}
void RenderFrameHostImpl::SetCloseListener(
mojo::PendingRemote<blink::mojom::CloseListener> listener) {
CloseListenerHost::GetOrCreateForCurrentDocument(this)->SetListener(
std::move(listener));
}
void RenderFrameHostImpl::BindBrowserInterfaceBrokerReceiver(
mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker> receiver) {
DCHECK(receiver.is_valid());
if (frame_tree()->is_prerendering()) {
DCHECK(mojo_binder_policy_applier_)
<< "prerendering pages should have a policy applier";
mojo_binder_policy_applier_->DropDeferredBinders();
}
broker_receiver_.Bind(std::move(receiver));
broker_receiver_.SetFilter(
std::make_unique<internal::ActiveUrlMessageFilter>(this));
}
void RenderFrameHostImpl::BindAssociatedInterfaceProviderReceiver(
mojo::PendingAssociatedReceiver<blink::mojom::AssociatedInterfaceProvider>
receiver) {
DCHECK(receiver.is_valid());
associated_interface_provider_receiver_.Bind(std::move(receiver));
}
void RenderFrameHostImpl::BindDomOperationControllerHostReceiver(
mojo::PendingAssociatedReceiver<mojom::DomAutomationControllerHost>
receiver) {
DCHECK(receiver.is_valid());
dom_automation_controller_receiver_.reset();
dom_automation_controller_receiver_.Bind(std::move(receiver));
dom_automation_controller_receiver_.SetFilter(
CreateMessageFilterForAssociatedReceiver(
mojom::DomAutomationControllerHost::Name_));
}
void RenderFrameHostImpl::SetKeepAliveTimeoutForTesting(
base::TimeDelta timeout) {
keep_alive_handle_factory_.set_timeout(timeout);
}
void RenderFrameHostImpl::UpdateState(const blink::PageState& state) {
OPTIONAL_TRACE_EVENT1("content", "RenderFrameHostImpl::UpdateState",
"render_frame_host", this);
if (!CanAccessFilesOfPageState(state)) {
bad_message::ReceivedBadMessage(
GetProcess(), bad_message::RFH_CAN_ACCESS_FILES_OF_PAGE_STATE);
return;
}
frame_tree_->controller().UpdateStateForFrame(this, state);
}
void RenderFrameHostImpl::OpenURL(blink::mojom::OpenURLParamsPtr params) {
GURL validated_url;
scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory;
if (!VerifyOpenURLParams(this, GetProcess(), params, &validated_url,
&blob_url_loader_factory)) {
return;
}
if (params->is_unfenced_top_navigation) {
GURL validated_params_url = params->url;
if (!ValidateUnfencedTopNavigation(this, validated_params_url,
GetProcess()->GetID(), params->post_body,
params->user_gesture)) {
return;
}
TRACE_EVENT1("navigation", "RenderFrameHostImpl::OpenURL(_unfencedTop)",
"url", validated_params_url.possibly_invalid_spec());
RenderFrameHostImpl* target_frame = GetOutermostMainFrame();
bool should_replace_current_entry = false;
blink::NavigationDownloadPolicy download_policy;
target_frame->frame_tree_node()->navigator().NavigateFromFrameProxy(
target_frame, validated_params_url,
base::OptionalToPtr(params->initiator_frame_token),
GetProcess()->GetID(), params->initiator_origin,
params->initiator_base_url, GetSiteInstance(), content::Referrer(),
ui::PAGE_TRANSITION_LINK, should_replace_current_entry, download_policy,
"GET",
nullptr, params->extra_headers,
nullptr,
network::mojom::SourceLocation::New(), false,
params->is_form_submission, params->impression,
params->initiator_activation_and_ad_status, base::TimeTicks::Now(),
false,
true,
true);
return;
}
TRACE_EVENT1("navigation", "RenderFrameHostImpl::OpenURL", "url",
validated_url.possibly_invalid_spec());
RenderFrameHostOwner* owner = owner_;
if (!owner) {
return;
}
owner->GetCurrentNavigator().RequestOpenURL(
this, validated_url, base::OptionalToPtr(params->initiator_frame_token),
GetProcess()->GetID(), params->initiator_origin,
params->initiator_base_url, params->post_body, params->extra_headers,
params->referrer.To<content::Referrer>(), params->disposition,
params->should_replace_current_entry, params->user_gesture,
params->triggering_event_info, params->href_translate,
std::move(blob_url_loader_factory), params->impression);
}
void RenderFrameHostImpl::GetAssociatedInterface(
const std::string& name,
mojo::PendingAssociatedReceiver<blink::mojom::AssociatedInterface>
receiver) {
DCHECK(associated_registry_);
if (mojo_binder_policy_applier_ &&
!mojo_binder_policy_applier_->ApplyPolicyToAssociatedBinder(name)) {
return;
}
mojo::ScopedInterfaceEndpointHandle handle = receiver.PassHandle();
if (associated_registry_->TryBindInterface(name, &handle))
return;
}
void RenderFrameHostImpl::DidStopLoading() {
TRACE_EVENT("navigation", "RenderFrameHostImpl::DidStopLoading",
ChromeTrackEvent::kRenderFrameHost, this);
if (did_stop_loading_callback_)
std::move(did_stop_loading_callback_).Run();
if (!is_loading()) {
return;
}
was_discarded_ = false;
loading_state_ = LoadingState::NONE;
if (loading_mem_tracker_)
loading_mem_tracker_.reset();
if (!IsPendingDeletion() && !IsInBackForwardCache()) {
DCHECK(owner_);
owner_->DidStopLoading();
}
}
void RenderFrameHostImpl::GetSavableResourceLinksCallback(
blink::mojom::GetSavableResourceLinksReplyPtr reply) {
if (!reply) {
delegate_->SavableResourceLinksError(this);
return;
}
delegate_->SavableResourceLinksResponse(this, reply->resources_list,
std::move(reply->referrer),
reply->subframes);
}
void RenderFrameHostImpl::DomOperationResponse(const std::string& json_string) {
delegate_->DomOperationResponse(this, json_string);
}
std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
RenderFrameHostImpl::CreateCrossOriginPrefetchLoaderFactoryBundle() {
auto subresource_loader_factories_config =
SubresourceLoaderFactoriesConfig::ForLastCommittedNavigation(*this);
network::mojom::URLLoaderFactoryParamsPtr factory_params =
URLLoaderFactoryParamsHelper::CreateForPrefetch(
this, subresource_loader_factories_config.GetClientSecurityState(),
subresource_loader_factories_config.cookie_setting_overrides());
mojo::PendingRemote<network::mojom::URLLoaderFactory> pending_default_factory;
bool bypass_redirect_checks = false;
bypass_redirect_checks = CreateNetworkServiceDefaultFactoryAndObserve(
std::move(factory_params),
subresource_loader_factories_config.ukm_source_id(),
pending_default_factory.InitWithNewPipeAndPassReceiver());
return std::make_unique<blink::PendingURLLoaderFactoryBundle>(
std::move(pending_default_factory),
blink::PendingURLLoaderFactoryBundle::SchemeMap(),
CreateURLLoaderFactoriesForIsolatedWorlds(
subresource_loader_factories_config,
isolated_worlds_requiring_separate_url_loader_factory_),
bypass_redirect_checks);
}
base::WeakPtr<RenderFrameHostImpl> RenderFrameHostImpl::GetWeakPtr() {
return weak_ptr_factory_.GetWeakPtr();
}
base::SafeRef<RenderFrameHostImpl> RenderFrameHostImpl::GetSafeRef() const {
return weak_ptr_factory_.GetSafeRef();
}
#if BUILDFLAG(IS_OHOS)
void RenderFrameHostImpl::GetCreateNewWindow(
const GURL& target_url,
WindowOpenDisposition disposition,
bool allow_popup,
GetCreateNewWindowCallback callback) {
#if defined(OHOS_MULTI_WINDOW)
bool effective_transient_activation_state =
allow_popup || frame_tree_node_->HasTransientUserActivation();
GetContentClient()->browser()->CanCreateWindow(
this, target_url, disposition, effective_transient_activation_state,
std::move(callback));
#endif
}
void RenderFrameHostImpl::GenerateCodeCache(const std::string& url,
const std::string& script,
const std::shared_ptr<oh_code_cache::CacheOptions>& cacheOptions,
CodeCacheCallback callback) {
auto options = blink::mojom::CacheOptions::New();
for (auto header : cacheOptions->response_headers_) {
options->response_headers.insert(std::make_pair(header.first, header.second));
}
GetAssociatedLocalFrame()->GenerateCodeCache(url, script, std::move(options), std::move(callback));
}
#endif
void RenderFrameHostImpl::CreateNewWindow(
mojom::CreateNewWindowParamsPtr params,
CreateNewWindowCallback callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
TRACE_EVENT2("navigation", "RenderFrameHostImpl::CreateNewWindow",
"render_frame_host", this, "url", params->target_url);
if (params->disposition == WindowOpenDisposition::NEW_PICTURE_IN_PICTURE &&
GetParentOrOuterDocumentOrEmbedder()) {
frame_host_associated_receiver_.ReportBadMessage(
"Only top-most frames can open picture-in-picture windows.");
return;
}
bool no_javascript_access = false;
GetProcess()->FilterURL(false, ¶ms->target_url);
bool effective_transient_activation_state =
params->allow_popup || HasTransientUserActivation() ||
(transient_allow_popup_.IsActive() &&
params->disposition == WindowOpenDisposition::NEW_POPUP);
bool can_create_window =
IsActive() && is_render_frame_created() &&
GetContentClient()->browser()->CanCreateWindow(
this, GetLastCommittedURL(),
GetOutermostMainFrame()->GetLastCommittedURL(),
last_committed_origin_, params->window_container_type,
params->target_url, params->referrer.To<Referrer>(),
params->frame_name, params->disposition, *params->features,
effective_transient_activation_state, params->opener_suppressed,
&no_javascript_access);
if (!can_create_window) {
std::move(callback).Run(mojom::CreateNewWindowStatus::kBlocked, nullptr);
return;
}
CHECK(owner_);
bool was_consumed = owner_->UpdateUserActivationState(
blink::mojom::UserActivationUpdateType::kConsumeTransientActivation,
blink::mojom::UserActivationNotificationType::kNone);
if (!GetOrCreateWebPreferences().supports_multiple_windows) {
if (params->target_url == GURL(kBlockedURL)) {
std::move(callback).Run(mojom::CreateNewWindowStatus::kIgnore, nullptr);
} else {
std::move(callback).Run(mojom::CreateNewWindowStatus::kReuse, nullptr);
}
return;
}
StoragePartition* storage_partition = GetStoragePartition();
DOMStorageContextWrapper* dom_storage_context =
static_cast<DOMStorageContextWrapper*>(
storage_partition->GetDOMStorageContext());
scoped_refptr<SessionStorageNamespaceImpl> cloned_namespace;
if (!params->clone_from_session_storage_namespace_id.empty()) {
cloned_namespace = SessionStorageNamespaceImpl::CloneFrom(
dom_storage_context, params->session_storage_namespace_id,
params->clone_from_session_storage_namespace_id);
} else {
cloned_namespace = SessionStorageNamespaceImpl::Create(
dom_storage_context, params->session_storage_namespace_id);
}
if (IsCredentialless() || IsNestedWithinFencedFrame() ||
CoopSuppressOpener(this)) {
params->opener_suppressed = true;
params->frame_name.clear();
}
RenderFrameHostImpl* top_level_opener = GetMainFrame();
int popup_virtual_browsing_context_group =
params->opener_suppressed
? CrossOriginOpenerPolicyAccessReportManager::
NextVirtualBrowsingContextGroup()
: top_level_opener->virtual_browsing_context_group();
int popup_soap_by_default_virtual_browsing_context_group =
params->opener_suppressed
? CrossOriginOpenerPolicyAccessReportManager::
NextVirtualBrowsingContextGroup()
: top_level_opener->soap_by_default_virtual_browsing_context_group();
bool is_new_browsing_instance =
params->opener_suppressed || no_javascript_access;
DCHECK(IsRenderFrameLive());
FrameTree* new_frame_tree =
delegate_->CreateNewWindow(this, *params, is_new_browsing_instance,
was_consumed, cloned_namespace.get());
transient_allow_popup_.Deactivate();
if (is_new_browsing_instance || !new_frame_tree) {
std::move(callback).Run(mojom::CreateNewWindowStatus::kIgnore, nullptr);
return;
}
DCHECK(!params->opener_suppressed);
RenderFrameHostImpl* new_main_rfh =
new_frame_tree->root()->current_frame_host();
new_main_rfh->virtual_browsing_context_group_ =
popup_virtual_browsing_context_group;
new_main_rfh->soap_by_default_virtual_browsing_context_group_ =
popup_soap_by_default_virtual_browsing_context_group;
if (PopupInheritCOOP(this) &&
GetMainFrame()->coop_access_report_manager()->coop_reporter()) {
new_main_rfh->SetCrossOriginOpenerPolicyReporter(
std::make_unique<CrossOriginOpenerPolicyReporter>(
GetProcess()->GetStoragePartition(), GetLastCommittedURL(),
params->referrer->url, new_main_rfh->cross_origin_opener_policy(),
GetReportingSource(), isolation_info_.network_anonymization_key()));
}
mojo::PendingAssociatedRemote<mojom::Frame> pending_frame_remote;
mojo::PendingAssociatedReceiver<mojom::Frame> pending_frame_receiver =
pending_frame_remote.InitWithNewEndpointAndPassReceiver();
new_main_rfh->SetMojomFrameRemote(std::move(pending_frame_remote));
mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>
browser_interface_broker;
new_main_rfh->BindBrowserInterfaceBrokerReceiver(
browser_interface_broker.InitWithNewPipeAndPassReceiver());
mojo::PendingAssociatedRemote<blink::mojom::AssociatedInterfaceProvider>
pending_associated_interface_provider;
new_main_rfh->BindAssociatedInterfaceProviderReceiver(
pending_associated_interface_provider
.InitWithNewEndpointAndPassReceiver());
mojo::PendingAssociatedRemote<blink::mojom::PageBroadcast> page_broadcast;
mojo::PendingAssociatedReceiver<blink::mojom::PageBroadcast>
page_broadcast_receiver =
page_broadcast.InitWithNewEndpointAndPassReceiver();
auto widget_params =
new_main_rfh->GetLocalRenderWidgetHost()
->BindAndGenerateCreateFrameWidgetParamsForNewWindow();
new_main_rfh->render_view_host()->BindPageBroadcast(
std::move(page_broadcast));
bool wait_for_debugger =
devtools_instrumentation::ShouldWaitForDebuggerInWindowOpen();
mojom::CreateNewWindowReplyPtr reply = mojom::CreateNewWindowReply::New(
new_main_rfh->GetFrameToken(), new_main_rfh->GetRoutingID(),
std::move(pending_frame_receiver), std::move(widget_params),
std::move(page_broadcast_receiver), std::move(browser_interface_broker),
std::move(pending_associated_interface_provider), cloned_namespace->id(),
new_main_rfh->GetDevToolsFrameToken(), wait_for_debugger,
new_main_rfh->GetDocumentToken(),
new_main_rfh->policy_container_host()->CreatePolicyContainerForBlink());
std::move(callback).Run(mojom::CreateNewWindowStatus::kSuccess,
std::move(reply));
if (new_main_rfh->waiting_for_init_)
new_main_rfh->GetMojomFrameInRenderer()->BlockRequests();
new_main_rfh->render_view_host()->RenderViewCreated(new_main_rfh);
}
void RenderFrameHostImpl::SendPrivateAggregationRequestsForFencedFrameEvent(
const std::string& event_type) {
if (!base::FeatureList::IsEnabled(blink::features::kPrivateAggregationApi) ||
!blink::features::kPrivateAggregationApiEnabledInFledge.Get() ||
(!blink::features::kPrivateAggregationApiFledgeExtensionsEnabled.Get() &&
!base::FeatureList::IsEnabled(
blink::features::
kPrivateAggregationApiFledgeExtensionsLocalTestingOverride))) {
mojo::ReportBadMessage(
"FLEDGE extensions must be enabled to use reportEvent() for private "
"aggregation events.");
return;
}
if (base::StartsWith(event_type, blink::kFencedFrameReservedPAEventPrefix)) {
mojo::ReportBadMessage("Reserved events cannot be triggered manually.");
return;
}
const absl::optional<FencedFrameProperties>& fenced_frame_properties =
frame_tree_node_->GetFencedFrameProperties();
if (!fenced_frame_properties.has_value() ||
!fenced_frame_properties->fenced_frame_reporter_) {
mojo::ReportBadMessage(
"This frame had reporting metadata registered in its renderer process"
"but not in its browser process. The reporting metadata should be"
"consistent between the two.");
return;
}
if (!fenced_frame_properties->mapped_url_.has_value() ||
!GetLastCommittedOrigin().IsSameOriginWith(
url::Origin::Create(fenced_frame_properties->mapped_url_
->GetValueIgnoringVisibility()))) {
mojo::ReportBadMessage(
"This frame is cross-origin to the mapped url of its fenced frame "
"config, so the renderer should not be able to call reportEvent.");
return;
}
fenced_frame_properties->fenced_frame_reporter_
->SendPrivateAggregationRequestsForEvent(event_type);
}
void RenderFrameHostImpl::CreatePortal(
mojo::PendingAssociatedReceiver<blink::mojom::Portal> pending_receiver,
mojo::PendingAssociatedRemote<blink::mojom::PortalClient> client,
blink::mojom::RemoteFrameInterfacesFromRendererPtr remote_frame_interfaces,
CreatePortalCallback callback) {
if (!Portal::IsEnabled()) {
frame_host_associated_receiver_.ReportBadMessage(
"blink.mojom.Portal can only be used if the Portals feature is "
"enabled.");
return;
}
if (GetLifecycleState() == RenderFrameHost::LifecycleState::kPrerendering) {
frame_host_associated_receiver_.ReportBadMessage(
"RenderFrameHostImpl::CreatePortal cannot be called when the RFH is "
"being prerendered.");
return;
}
if (!is_main_frame() || IsFencedFrameRoot()) {
frame_host_associated_receiver_.ReportBadMessage(
"RFHI::CreatePortal called in a nested browsing context");
return;
}
if (active_sandbox_flags() != network::mojom::WebSandboxFlags::kNone) {
frame_host_associated_receiver_.ReportBadMessage(
"RFHI::CreatePortal called in a sandboxed browsing context");
return;
}
if (!GetLastCommittedURL().SchemeIsHTTPOrHTTPS()) {
frame_host_associated_receiver_.ReportBadMessage(
"Portal creation is restricted to the HTTP family.");
return;
}
auto portal = std::make_unique<Portal>(this);
portal->Bind(std::move(pending_receiver), std::move(client));
auto it = portals_.insert(std::move(portal)).first;
RenderFrameProxyHost* proxy_host =
(*it)->CreateProxyAndAttachPortal(std::move(remote_frame_interfaces));
if (!proxy_host) {
frame_host_associated_receiver_.ReportBadMessage(
"Trying to attach a portal that has already been attached.");
return;
}
const blink::mojom::FrameReplicationState& initial_replicated_state =
proxy_host->frame_tree_node()->current_replication_state();
DCHECK(initial_replicated_state.origin.opaque());
std::move(callback).Run(initial_replicated_state.Clone(),
(*it)->portal_token(), proxy_host->GetFrameToken(),
(*it)->GetDevToolsFrameToken());
}
void RenderFrameHostImpl::AdoptPortal(
const blink::PortalToken& portal_token,
blink::mojom::RemoteFrameInterfacesFromRendererPtr remote_frame_interfaces,
AdoptPortalCallback callback) {
Portal* portal = FindPortalByToken(portal_token);
if (!portal) {
frame_host_associated_receiver_.ReportBadMessage(
"Unknown portal_token when adopting portal.");
return;
}
DCHECK_EQ(portal->owner_render_frame_host(), this);
RenderFrameProxyHost* proxy_host =
portal->CreateProxyAndAttachPortal(std::move(remote_frame_interfaces));
if (!proxy_host) {
frame_host_associated_receiver_.ReportBadMessage(
"Trying to attach a portal that has already been attached.");
return;
}
viz::FrameSinkId frame_sink_id = proxy_host->frame_tree_node()
->render_manager()
->GetRenderWidgetHostView()
->GetFrameSinkId();
proxy_host->GetAssociatedRemoteFrame()->SetFrameSinkId(frame_sink_id);
std::move(callback).Run(
proxy_host->frame_tree_node()->current_replication_state().Clone(),
proxy_host->GetFrameToken(), portal->GetDevToolsFrameToken());
}
std::vector<FencedFrame*> RenderFrameHostImpl::GetFencedFrames() const {
std::vector<FencedFrame*> result;
for (const std::unique_ptr<FencedFrame>& fenced_frame : fenced_frames_)
result.push_back(fenced_frame.get());
return result;
}
void RenderFrameHostImpl::DestroyFencedFrame(FencedFrame& fenced_frame) {
auto it = base::ranges::find_if(fenced_frames_,
base::MatchesUniquePtr(&fenced_frame));
CHECK(it != fenced_frames_.end());
fenced_frames_.erase(it);
}
void RenderFrameHostImpl::CreateFencedFrame(
mojo::PendingAssociatedReceiver<blink::mojom::FencedFrameOwnerHost>
pending_receiver,
blink::mojom::RemoteFrameInterfacesFromRendererPtr remote_frame_interfaces,
const blink::RemoteFrameToken& frame_token,
const base::UnguessableToken& devtools_frame_token) {
if (GetLifecycleState() == RenderFrameHost::LifecycleState::kPrerendering) {
bad_message::ReceivedBadMessage(GetProcess(),
bad_message::FF_CREATE_WHILE_PRERENDERING);
return;
}
if (!blink::features::IsFencedFramesEnabled()) {
bad_message::ReceivedBadMessage(
GetProcess(), bad_message::RFH_FENCED_FRAME_MOJO_WHEN_DISABLED);
return;
}
if (IsSandboxed(blink::kFencedFrameMandatoryUnsandboxedFlags)) {
bad_message::ReceivedBadMessage(
GetProcess(), bad_message::RFH_CREATE_FENCED_FRAME_IN_SANDBOXED_FRAME);
return;
}
if (RenderFrameProxyHost::IsFrameTokenInUse(frame_token)) {
bad_message::ReceivedBadMessage(
GetProcess(), bad_message::RFHI_CREATE_FENCED_FRAME_BAD_FRAME_TOKEN);
return;
}
for (FrameTreeNode* node :
GetOutermostMainFrame()->frame_tree()->NodesIncludingInnerTreeNodes()) {
if (node->current_frame_host()->devtools_frame_token() ==
devtools_frame_token) {
bad_message::ReceivedBadMessage(
GetProcess(),
bad_message::RFHI_CREATE_FENCED_FRAME_BAD_DEVTOOLS_FRAME_TOKEN);
return;
}
}
if (IsInactiveAndDisallowActivation(
DisallowActivationReasonId::kCreateFencedFrame)) {
return;
}
fenced_frames_.push_back(std::make_unique<FencedFrame>(
weak_ptr_factory_.GetSafeRef(), was_discarded_));
FencedFrame* fenced_frame = fenced_frames_.back().get();
RenderFrameProxyHost* proxy_host =
fenced_frame->InitInnerFrameTreeAndReturnProxyToOuterFrameTree(
std::move(remote_frame_interfaces), frame_token,
devtools_frame_token);
fenced_frame->Bind(std::move(pending_receiver));
const blink::mojom::FrameReplicationState& initial_replicated_state =
proxy_host->frame_tree_node()->current_replication_state();
DCHECK(initial_replicated_state.origin.opaque());
}
void RenderFrameHostImpl::SendFencedFrameReportingBeacon(
const std::string& event_data,
const std::string& event_type,
const std::vector<blink::FencedFrame::ReportingDestination>& destinations) {
for (const blink::FencedFrame::ReportingDestination& destination :
destinations) {
SendFencedFrameReportingBeaconInternal(event_data, event_type, destination,
true);
}
}
void RenderFrameHostImpl::MaybeSendFencedFrameReportingBeacon(
NavigationRequest& navigation_request) {
if (!IsOutermostMainFrame()) {
return;
}
if (navigation_request.GetNavigationInitiatorActivationAndAdStatus() ==
blink::mojom::NavigationInitiatorActivationAndAdStatus::
kDidNotStartWithTransientActivation) {
return;
}
if (!navigation_request.GetInitiatorFrameToken().has_value()) {
return;
}
RenderFrameHostImpl* initiator_rfh = RenderFrameHostImpl::FromFrameToken(
navigation_request.GetInitiatorProcessID(),
navigation_request.GetInitiatorFrameToken().value());
if (!initiator_rfh) {
return;
}
const absl::optional<FencedFrameProperties>& properties =
initiator_rfh->frame_tree_node()->GetFencedFrameProperties();
if (!properties.has_value() || !properties->fenced_frame_reporter_) {
return;
}
absl::optional<AutomaticBeaconInfo> info =
properties->automatic_beacon_info();
if (!info) {
return;
}
if (!properties->mapped_url_.has_value() ||
!initiator_rfh->GetLastCommittedOrigin().IsSameOriginWith(
url::Origin::Create(
properties->mapped_url_->GetValueIgnoringVisibility()))) {
return;
}
for (blink::FencedFrame::ReportingDestination destination :
info->destinations) {
initiator_rfh->SendFencedFrameReportingBeaconInternal(
info->data, blink::kFencedFrameTopNavigationBeaconType, destination,
false, navigation_request.GetNavigationId());
}
}
void RenderFrameHostImpl::SendFencedFrameReportingBeaconInternal(
const std::string& event_data,
const std::string& event_type,
blink::FencedFrame::ReportingDestination destination,
bool from_renderer,
absl::optional<int64_t> navigation_id) {
if (!IsActive()) {
return;
}
const absl::optional<FencedFrameProperties>& fenced_frame_properties =
frame_tree_node_->GetFencedFrameProperties();
if (fenced_frame_properties.has_value() &&
fenced_frame_properties->is_ad_component_) {
if (from_renderer) {
AddMessageToConsole(
blink::mojom::ConsoleMessageLevel::kError,
"This frame is an ad component. It is not allowed to call "
"fence.reportEvent.");
return;
}
CHECK_EQ(event_type, blink::kFencedFrameTopNavigationBeaconType);
}
if (!fenced_frame_properties.has_value() ||
!fenced_frame_properties->fenced_frame_reporter_) {
mojo::ReportBadMessage(
"This frame has no fenced frame reporter registered in the browser.");
return;
}
if (!fenced_frame_properties->mapped_url_.has_value() ||
!GetLastCommittedOrigin().IsSameOriginWith(
url::Origin::Create(fenced_frame_properties->mapped_url_
->GetValueIgnoringVisibility()))) {
mojo::ReportBadMessage(
"This frame is cross-origin to the mapped url of its fenced frame "
"config, so the renderer should not be able to call reportEvent.");
return;
}
if (event_data.length() > blink::kFencedFrameMaxBeaconLength) {
mojo::ReportBadMessage(
"The data provided to SendFencedFrameReportingBeacon() exceeds the "
"maximum length, which is 64KB.");
return;
}
std::string error_message;
if (!fenced_frame_properties->fenced_frame_reporter_->SendReport(
event_type, event_data, destination,
this, error_message, navigation_id)) {
AddMessageToConsole(blink::mojom::ConsoleMessageLevel::kError,
error_message);
}
}
void RenderFrameHostImpl::SetFencedFrameAutomaticBeaconReportEventData(
const std::string& event_data,
const std::vector<blink::FencedFrame::ReportingDestination>& destinations) {
if (event_data.length() > blink::kFencedFrameMaxBeaconLength) {
mojo::ReportBadMessage(
"The data provided to SetFencedFrameAutomaticBeaconReportEventData() "
"exceeds the maximum length, which is 64KB.");
return;
}
if (!IsActive()) {
return;
}
CHECK(owner_);
owner_->SetFencedFrameAutomaticBeaconReportEventData(event_data,
destinations);
}
void RenderFrameHostImpl::OnViewTransitionOptInChanged(
blink::mojom::ViewTransitionSameOriginOptIn view_transition_opt_in) {
ViewTransitionOptInState::GetOrCreateForCurrentDocument(this)
->set_same_origin_opt_in(view_transition_opt_in);
}
void RenderFrameHostImpl::CreateNewPopupWidget(
mojo::PendingAssociatedReceiver<blink::mojom::PopupWidgetHost>
blink_popup_widget_host,
mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost> blink_widget_host,
mojo::PendingAssociatedRemote<blink::mojom::Widget> blink_widget) {
if (!IsActive()) {
if (lifecycle_state() == LifecycleStateImpl::kPrerendering) {
bad_message::ReceivedBadMessage(
GetProcess(), bad_message::RFH_POPUP_REQUEST_WHILE_PRERENDERING);
}
return;
}
int32_t widget_route_id = GetProcess()->GetNextRoutingID();
RenderWidgetHostImpl* widget = delegate_->CreateNewPopupWidget(
site_instance_->group()->GetSafeRef(), widget_route_id,
std::move(blink_popup_widget_host), std::move(blink_widget_host),
std::move(blink_widget));
if (!widget)
return;
widget->RendererWidgetCreated(false);
if (create_new_popup_widget_callback_)
create_new_popup_widget_callback_.Run(widget);
}
void RenderFrameHostImpl::GetKeepAliveHandleFactory(
mojo::PendingReceiver<blink::mojom::KeepAliveHandleFactory> receiver) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
if (GetProcess()->AreRefCountsDisabled())
return;
keep_alive_handle_factory_.Bind(std::move(receiver));
}
void RenderFrameHostImpl::DidChangeSrcDoc(
const blink::FrameToken& child_frame_token,
const std::string& srcdoc_value) {
auto* child =
FindAndVerifyChild(child_frame_token, bad_message::RFH_OWNER_PROPERTY);
if (!child)
return;
child->SetSrcdocValue(srcdoc_value);
}
void RenderFrameHostImpl::ReceivedDelegatedCapability(
blink::mojom::DelegatedCapability delegated_capability) {
if (delegated_capability ==
blink::mojom::DelegatedCapability::kFullscreenRequest) {
fullscreen_request_token_.Activate();
}
}
void RenderFrameHostImpl::BeginNavigation(
blink::mojom::CommonNavigationParamsPtr unvalidated_common_params,
blink::mojom::BeginNavigationParamsPtr begin_params,
mojo::PendingRemote<blink::mojom::BlobURLToken> blob_url_token,
mojo::PendingAssociatedRemote<mojom::NavigationClient> navigation_client,
mojo::PendingRemote<blink::mojom::PolicyContainerHostKeepAliveHandle>
initiator_policy_container_host_keep_alive_handle,
mojo::PendingReceiver<mojom::NavigationRendererCancellationListener>
renderer_cancellation_listener) {
TRACE_EVENT("navigation", "RenderFrameHostImpl::BeginNavigation",
ChromeTrackEvent::kRenderFrameHost, this, "url",
unvalidated_common_params->url.possibly_invalid_spec());
if (lifecycle_state() != LifecycleStateImpl::kPrerendering) {
if (IsInactiveAndDisallowActivation(
DisallowActivationReasonId::kBeginNavigation)) {
return;
}
}
DCHECK(owner_);
if (owner_->GetRenderFrameHostManager().is_attaching_inner_delegate()) {
return;
}
DCHECK(navigation_client.is_valid());
blink::mojom::CommonNavigationParamsPtr validated_common_params =
unvalidated_common_params.Clone();
if (!VerifyBeginNavigationCommonParams(*this, &*validated_common_params)) {
return;
}
int initiator_process_id = GetProcess()->GetID();
if (!VerifyNavigationInitiator(this, begin_params->initiator_frame_token,
initiator_process_id)) {
return;
}
if (begin_params->is_container_initiated) {
if (!GetParent() ||
(initiator_process_id != GetParent()->GetProcess()->GetID())) {
mojo::ReportBadMessage(
"container initiated navigation from non-parent process");
return;
}
}
if (begin_params->trust_token_params) {
if (IsFencedFrameRoot()) {
mojo::ReportBadMessage(
"RFHI: Private State Token params in fenced frame nav");
return;
}
if (!GetParent()) {
mojo::ReportBadMessage(
"RFHI: Private State Token params in main frame nav");
return;
}
RenderFrameHostImpl* parent = GetParent();
bool is_right_operation_policy_enabled = false;
const network::mojom::TrustTokenOperationType& operation =
begin_params->trust_token_params->operation;
switch (operation) {
case network::mojom::TrustTokenOperationType::kRedemption:
case network::mojom::TrustTokenOperationType::kSigning:
is_right_operation_policy_enabled = parent->IsFeatureEnabled(
blink::mojom::PermissionsPolicyFeature::kTrustTokenRedemption);
break;
case network::mojom::TrustTokenOperationType::kIssuance:
is_right_operation_policy_enabled = parent->IsFeatureEnabled(
blink::mojom::PermissionsPolicyFeature::kPrivateStateTokenIssuance);
break;
}
if (!is_right_operation_policy_enabled) {
mojo::ReportBadMessage(
"RFHI: Mandatory Private State Tokens Permissions Policy feature "
"is absent");
return;
}
}
if (begin_params->web_bundle_token &&
!validated_common_params->url.SchemeIs(url::kUuidInPackageScheme)) {
bad_message::ReceivedBadMessage(
GetProcess(), bad_message::WEB_BUNDLE_INVALID_NAVIGATION_URL);
return;
}
if (begin_params->is_fullscreen_requested) {
if (!is_initial_empty_document()) {
bad_message::ReceivedBadMessage(
GetProcess(),
bad_message::RFHI_FULLSCREEN_NAV_INVALID_INITIAL_DOCUMENT);
return;
}
if (!IsOutermostMainFrame()) {
bad_message::ReceivedBadMessage(
GetProcess(),
bad_message::RFHI_FULLSCREEN_NAV_NOT_OUTERMOST_MAIN_FRAME);
return;
}
RenderFrameHostImpl* initiator_render_frame_host =
begin_params->initiator_frame_token
? RenderFrameHostImpl::FromFrameToken(
initiator_process_id,
begin_params->initiator_frame_token.value())
: nullptr;
if (!initiator_render_frame_host ||
!IsWindowManagementGranted(initiator_render_frame_host)) {
begin_params->is_fullscreen_requested = false;
}
}
GetProcess()->FilterURL(true, &begin_params->searchable_form_url);
if (unvalidated_common_params->url.SchemeIsBlob() &&
!validated_common_params->url.SchemeIsBlob()) {
blob_url_token = mojo::NullRemote();
}
if (blob_url_token && !validated_common_params->url.SchemeIsBlob()) {
mojo::ReportBadMessage("Blob URL Token, but not a blob: URL");
return;
}
scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory;
if (blob_url_token) {
blob_url_loader_factory =
ChromeBlobStorageContext::URLLoaderFactoryForToken(
GetStoragePartition(), std::move(blob_url_token));
}
if (validated_common_params->url.SchemeIsBlob() && !blob_url_loader_factory) {
blob_url_loader_factory = ChromeBlobStorageContext::URLLoaderFactoryForUrl(
GetStoragePartition(), validated_common_params->url);
}
if (waiting_for_init_) {
pending_navigate_ = std::make_unique<PendingNavigation>(
std::move(validated_common_params), std::move(begin_params),
std::move(blob_url_loader_factory), std::move(navigation_client),
std::move(renderer_cancellation_listener));
return;
}
owner_->GetCurrentNavigator().OnBeginNavigation(
frame_tree_node(), std::move(validated_common_params),
std::move(begin_params), std::move(blob_url_loader_factory),
std::move(navigation_client), EnsurePrefetchedSignedExchangeCache(),
std::move(renderer_cancellation_listener));
}
void RenderFrameHostImpl::SubresourceResponseStarted(
const url::SchemeHostPort& final_response_url,
net::CertStatus cert_status) {
OPTIONAL_TRACE_EVENT1("content",
"RenderFrameHostImpl::SubresourceResponseStarted",
"url", final_response_url.GetURL());
bool was_processed =
frame_tree_->controller().ssl_manager()->DidStartResourceResponse(
final_response_url, cert_status);
UMA_HISTOGRAM_ENUMERATION("SSL.Experimental.SubresourceResponse",
was_processed
? SSLSubresourceResponseType::kProcessed
: SSLSubresourceResponseType::kIgnored);
}
void RenderFrameHostImpl::ResourceLoadComplete(
blink::mojom::ResourceLoadInfoPtr resource_load_info) {
GlobalRequestID global_request_id;
const bool is_frame_request =
blink::IsRequestDestinationFrame(resource_load_info->request_destination);
if (main_frame_request_ids_.first == resource_load_info->request_id) {
global_request_id = main_frame_request_ids_.second;
} else if (is_frame_request) {
deferred_main_frame_load_info_ = std::move(resource_load_info);
return;
}
delegate_->ResourceLoadComplete(this, global_request_id,
std::move(resource_load_info));
}
void RenderFrameHostImpl::HandleAXEvents(
const ui::AXTreeID& tree_id,
blink::mojom::AXUpdatesAndEventsPtr updates_and_events,
int32_t reset_token) {
TRACE_EVENT0("accessibility", "RenderFrameHostImpl::HandleAXEvents");
SCOPED_UMA_HISTOGRAM_TIMER("Accessibility.Performance.HandleAXEvents");
if (tree_id != GetAXTreeID()) {
if (!accessibility_testing_callback_.is_null()) {
accessibility_testing_callback_.Run(this, ax::mojom::Event::kNone, 0);
}
return;
}
if (accessibility_reset_token_ != reset_token) {
return;
}
accessibility_reset_token_ = 0;
ui::AXMode accessibility_mode = delegate_->GetAccessibilityMode();
if (accessibility_mode.is_mode_off()) {
return;
}
if (base::FeatureList::IsEnabled(features::kEvictOnAXEvents)) {
if (IsInactiveAndDisallowActivationForAXEvents(updates_and_events->events))
return;
} else {
if (!IsInBackForwardCache() &&
IsInactiveAndDisallowActivation(DisallowActivationReasonId::kAXEvent)) {
return;
}
}
GetOrCreateBrowserAccessibilityManager();
AXEventNotificationDetails details;
details.ax_tree_id = tree_id;
if (base::FeatureList::IsEnabled(kRenderAccessibilityHostAvoidCopying)) {
details.events = std::move(updates_and_events->events);
details.updates = std::move(updates_and_events->updates);
for (auto& update : details.updates) {
if (update.has_tree_data) {
DCHECK_EQ(tree_id, update.tree_data.tree_id);
ax_tree_data_ = update.tree_data;
update.tree_data = GetAXTreeData();
}
}
} else {
details.events = updates_and_events->events;
details.updates.resize(updates_and_events->updates.size());
for (size_t i = 0; i < updates_and_events->updates.size(); ++i) {
details.updates[i] = updates_and_events->updates[i];
if (updates_and_events->updates[i].has_tree_data) {
DCHECK_EQ(tree_id, updates_and_events->updates[i].tree_data.tree_id);
ax_tree_data_ = updates_and_events->updates[i].tree_data;
details.updates[i].tree_data = GetAXTreeData();
}
}
}
if (needs_ax_root_id_) {
DCHECK(!details.updates.empty());
DCHECK_NE(ui::kInvalidAXNodeID, details.updates[0].root_id);
needs_ax_root_id_ = false;
}
SendAccessibilityEventsToManager(details);
delegate_->AccessibilityEventReceived(details);
if (!accessibility_testing_callback_.is_null()) {
if (details.events.empty()) {
accessibility_testing_callback_.Run(this, ax::mojom::Event::kNone, 0);
} else {
for (auto& event : details.events) {
if (static_cast<int>(event.event_type) < 0)
continue;
accessibility_testing_callback_.Run(this, event.event_type, event.id);
}
}
}
}
void RenderFrameHostImpl::HandleAXLocationChanges(
const ui::AXTreeID& tree_id,
std::vector<blink::mojom::LocationChangesPtr> changes) {
if (tree_id != GetAXTreeID()) {
return;
}
if (accessibility_reset_token_ ||
IsInactiveAndDisallowActivation(
DisallowActivationReasonId::kAXLocationChange))
return;
BrowserAccessibilityManager* manager =
GetOrCreateBrowserAccessibilityManager();
if (manager)
manager->OnLocationChanges(changes);
std::vector<AXLocationChangeNotificationDetails> details;
details.reserve(changes.size());
for (auto& change : changes) {
AXLocationChangeNotificationDetails detail;
detail.id = change->id;
detail.ax_tree_id = GetAXTreeID();
detail.new_location = change->new_location;
details.push_back(detail);
}
delegate_->AccessibilityLocationChangesReceived(details);
}
media::MediaMetricsProvider::RecordAggregateWatchTimeCallback
RenderFrameHostImpl::GetRecordAggregateWatchTimeCallback() {
return delegate_->GetRecordAggregateWatchTimeCallback(
GetOutermostMainFrame()->GetLastCommittedURL());
}
void RenderFrameHostImpl::ResetWaitingState() {
DCHECK(!IsInBackForwardCache());
DCHECK(!IsPendingDeletion());
if (is_waiting_for_beforeunload_completion_) {
is_waiting_for_beforeunload_completion_ = false;
if (beforeunload_timeout_)
beforeunload_timeout_->Stop();
has_shown_beforeunload_dialog_ = false;
beforeunload_pending_replies_.clear();
}
send_before_unload_start_time_ = base::TimeTicks();
page_close_state_ = PageCloseState::kNotClosing;
}
CanCommitStatus RenderFrameHostImpl::CanCommitOriginAndUrl(
const url::Origin& origin,
const GURL& url,
bool is_same_document_navigation,
bool is_pdf,
bool is_sandboxed) {
if (blink::IsRendererDebugURL(url)) {
LogCanCommitOriginAndUrlFailureReason("is_renderer_debug_url");
return CanCommitStatus::CANNOT_COMMIT_URL;
}
if (!Navigator::CheckWebUIRendererDoesNotDisplayNormalURL(
this, UrlInfo(UrlInfoInit(url).WithOrigin(origin).WithIsPdf(is_pdf)),
true)) {
return CanCommitStatus::CANNOT_COMMIT_URL;
}
if (!is_main_frame()) {
RenderFrameHostImpl* main_frame = GetMainFrame();
if (main_frame->is_mhtml_document()) {
if (IsSameSiteInstance(main_frame))
return CanCommitStatus::CAN_COMMIT_ORIGIN_AND_URL;
static auto* const oopif_in_mhtml_page_key =
base::debug::AllocateCrashKeyString(
"oopif_in_mhtml_page", base::debug::CrashKeySize::Size32);
base::debug::SetCrashKeyString(
oopif_in_mhtml_page_key,
is_mhtml_document() ? "is_mhtml_doc" : "not_mhtml_doc");
LogCanCommitOriginAndUrlFailureReason("oopif_in_mhtml_page");
return CanCommitStatus::CANNOT_COMMIT_URL;
}
}
if (is_same_document_navigation && origin != GetLastCommittedOrigin()) {
LogCanCommitOriginAndUrlFailureReason("cross_origin_same_document");
return CanCommitStatus::CANNOT_COMMIT_ORIGIN;
}
if (!GetContentClient()->browser()->CanCommitURL(GetProcess(), url)) {
LogCanCommitOriginAndUrlFailureReason(
"content_client_disallowed_commit_url");
return CanCommitStatus::CANNOT_COMMIT_URL;
}
auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
const CanCommitStatus can_commit_status = policy->CanCommitOriginAndUrl(
GetProcess()->GetID(), GetSiteInstance()->GetIsolationContext(),
UrlInfo(
UrlInfoInit(url)
.WithOrigin(origin)
.WithStoragePartitionConfig(
GetSiteInstance()->GetSiteInfo().storage_partition_config())
.WithWebExposedIsolationInfo(
GetSiteInstance()->GetWebExposedIsolationInfo())
.WithSandbox(is_sandboxed)));
if (can_commit_status != CanCommitStatus::CAN_COMMIT_ORIGIN_AND_URL) {
LogCanCommitOriginAndUrlFailureReason("cpspi_disallowed_commit");
return can_commit_status;
}
const auto origin_tuple_or_precursor_tuple =
origin.GetTupleOrPrecursorTupleIfOpaque();
if (origin_tuple_or_precursor_tuple.IsValid()) {
if (blink::IsRendererDebugURL(origin_tuple_or_precursor_tuple.GetURL())) {
LogCanCommitOriginAndUrlFailureReason(
"origin_or_precursor_is_renderer_debug_url");
return CanCommitStatus::CANNOT_COMMIT_ORIGIN;
}
if (!origin.opaque() && !GetContentClient()->browser()->CanCommitURL(
GetProcess(), origin.GetURL())) {
LogCanCommitOriginAndUrlFailureReason(
"content_client_disallowed_commit_origin");
return CanCommitStatus::CANNOT_COMMIT_ORIGIN;
}
}
return CanCommitStatus::CAN_COMMIT_ORIGIN_AND_URL;
}
bool RenderFrameHostImpl::CanSubframeCommitOriginAndUrl(
NavigationRequest* navigation_request) {
DCHECK(navigation_request);
DCHECK(!is_main_frame());
const int nav_entry_id = navigation_request->nav_entry_id();
if (nav_entry_id == 0)
return true;
const int last_nav_entry_index = navigation_request->frame_tree_node()
->navigator()
.controller()
.GetLastCommittedEntryIndex();
const int dest_nav_entry_index = navigation_request->frame_tree_node()
->navigator()
.controller()
.GetEntryIndexWithUniqueID(nav_entry_id);
if (dest_nav_entry_index <= 0 || dest_nav_entry_index == last_nav_entry_index)
return true;
NavigationEntryImpl* dest_nav_entry =
navigation_request->frame_tree_node()
->navigator()
.controller()
.GetEntryAtIndex(dest_nav_entry_index);
auto dest_main_frame_fne = dest_nav_entry->root_node()->frame_entry;
int64_t dest_main_frame_dsn = dest_main_frame_fne->document_sequence_number();
int64_t actual_main_frame_dsn = navigation_request->frame_tree_node()
->navigator()
.controller()
.GetLastCommittedEntry()
->root_node()
->frame_entry->document_sequence_number();
if (dest_main_frame_dsn != actual_main_frame_dsn)
return false;
url::Origin dest_top_origin =
dest_main_frame_fne->committed_origin().value_or(
GetMainFrame()->GetLastCommittedOrigin());
const GURL& dest_top_url = dest_nav_entry->GetURL();
const bool is_top_pdf =
GetMainFrame()->GetSiteInstance()->GetSiteInfo().is_pdf();
const bool is_top_sandboxed =
GetMainFrame()->GetSiteInstance()->GetSiteInfo().is_sandboxed();
return GetMainFrame()->CanCommitOriginAndUrl(
dest_top_origin, dest_top_url,
true , is_top_pdf,
is_top_sandboxed) == CanCommitStatus::CAN_COMMIT_ORIGIN_AND_URL;
}
void RenderFrameHostImpl::Stop() {
TRACE_EVENT1("navigation", "RenderFrameHostImpl::Stop", "render_frame_host",
this);
if (!IsRenderFrameLive())
return;
GetAssociatedLocalFrame()->StopLoading();
}
void RenderFrameHostImpl::DispatchBeforeUnload(BeforeUnloadType type,
bool is_reload) {
bool for_navigation =
type == BeforeUnloadType::BROWSER_INITIATED_NAVIGATION ||
type == BeforeUnloadType::RENDERER_INITIATED_NAVIGATION;
bool for_inner_delegate_attach =
type == BeforeUnloadType::INNER_DELEGATE_ATTACH;
DCHECK(for_navigation || for_inner_delegate_attach || !is_reload);
DCHECK(type == BeforeUnloadType::BROWSER_INITIATED_NAVIGATION ||
type == BeforeUnloadType::RENDERER_INITIATED_NAVIGATION ||
type == BeforeUnloadType::INNER_DELEGATE_ATTACH ||
IsOutermostMainFrame());
CHECK(owner_);
if (!for_navigation) {
owner_->CancelNavigation();
}
bool check_subframes_only =
type == BeforeUnloadType::RENDERER_INITIATED_NAVIGATION;
if (!ShouldDispatchBeforeUnload(check_subframes_only)) {
DCHECK(!for_navigation);
base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE,
base::BindOnce(&RenderFrameHostManager::BeforeUnloadCompleted,
owner_->GetRenderFrameHostManager().GetWeakPtr(),
true));
return;
}
TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(
"navigation", "RenderFrameHostImpl BeforeUnload", TRACE_ID_LOCAL(this),
"render_frame_host", this);
if (is_waiting_for_beforeunload_completion_) {
unload_ack_is_for_navigation_ =
unload_ack_is_for_navigation_ && for_navigation;
} else {
is_waiting_for_beforeunload_completion_ = true;
beforeunload_dialog_request_cancels_unload_ = false;
unload_ack_is_for_navigation_ = for_navigation;
send_before_unload_start_time_ = base::TimeTicks::Now();
if (delegate_->IsJavaScriptDialogShowing()) {
SimulateBeforeUnloadCompleted(type != BeforeUnloadType::DISCARD);
} else {
if (beforeunload_timeout_)
beforeunload_timeout_->Start(beforeunload_timeout_delay_);
beforeunload_pending_replies_.clear();
beforeunload_dialog_request_cancels_unload_ =
(type == BeforeUnloadType::DISCARD);
CheckOrDispatchBeforeUnloadForSubtree(
check_subframes_only,
true, is_reload,
nullptr);
}
}
}
bool RenderFrameHostImpl::CheckOrDispatchBeforeUnloadForSubtree(
bool subframes_only,
bool send_ipc,
bool is_reload,
bool* no_dispatch_because_avoid_unnecessary_sync) {
if (IsFencedFrameRoot())
return false;
bool found_beforeunload = false;
bool run_beforeunload_for_legacy = false;
ForEachRenderFrameHostWithAction(
[this, subframes_only, send_ipc, is_reload, &found_beforeunload,
&run_beforeunload_for_legacy](
RenderFrameHostImpl* rfh) -> FrameIterationAction {
return CheckOrDispatchBeforeUnloadForFrame(
subframes_only, send_ipc, is_reload, &found_beforeunload,
&run_beforeunload_for_legacy, rfh);
});
if (run_beforeunload_for_legacy) {
DCHECK(send_ipc);
beforeunload_pending_replies_.insert(this);
SendBeforeUnload(is_reload, GetWeakPtr(), true);
} else if (no_dispatch_because_avoid_unnecessary_sync &&
!found_beforeunload && !subframes_only && IsRenderFrameLive() &&
IsAvoidUnnecessaryBeforeUnloadCheckSyncEnabled()) {
*no_dispatch_because_avoid_unnecessary_sync = true;
}
return found_beforeunload;
}
RenderFrameHost::FrameIterationAction
RenderFrameHostImpl::CheckOrDispatchBeforeUnloadForFrame(
bool subframes_only,
bool send_ipc,
bool is_reload,
bool* found_beforeunload,
bool* run_beforeunload_for_legacy,
RenderFrameHostImpl* rfh) {
if (&GetPage() != &rfh->GetPage())
return FrameIterationAction::kSkipChildren;
if (subframes_only && rfh->GetSiteInstance() == GetSiteInstance())
return FrameIterationAction::kContinue;
if (!rfh->IsRenderFrameLive())
return FrameIterationAction::kContinue;
const bool run_beforeunload_for_legacy_frame =
rfh == this && !rfh->has_before_unload_handler_ &&
!IsAvoidUnnecessaryBeforeUnloadCheckSyncEnabled();
const bool should_run_beforeunload =
rfh->has_before_unload_handler_ || run_beforeunload_for_legacy_frame;
if (!should_run_beforeunload)
return FrameIterationAction::kContinue;
*found_beforeunload = true;
if (!send_ipc)
return FrameIterationAction::kStop;
while (!rfh->is_local_root() && rfh != this)
rfh = rfh->GetParent();
if (base::Contains(beforeunload_pending_replies_, rfh))
return FrameIterationAction::kContinue;
bool has_same_site_ancestor = false;
for (auto* added_rfh : beforeunload_pending_replies_) {
if (rfh->IsDescendantOfWithinFrameTree(added_rfh) &&
rfh->GetSiteInstance() == added_rfh->GetSiteInstance()) {
has_same_site_ancestor = true;
break;
}
}
if (has_same_site_ancestor)
return FrameIterationAction::kContinue;
if (run_beforeunload_for_legacy_frame &&
IsAvoidUnnecessaryBeforeUnloadCheckPostTaskEnabled()) {
*run_beforeunload_for_legacy = true;
return FrameIterationAction::kContinue;
}
*run_beforeunload_for_legacy = false;
beforeunload_pending_replies_.insert(rfh);
SendBeforeUnload(is_reload, rfh->GetWeakPtr(), false);
return FrameIterationAction::kContinue;
}
void RenderFrameHostImpl::SimulateBeforeUnloadCompleted(bool proceed) {
DCHECK(is_waiting_for_beforeunload_completion_);
base::TimeTicks approx_renderer_start_time = send_before_unload_start_time_;
base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE,
base::BindOnce(&RenderFrameHostImpl::ProcessBeforeUnloadCompleted,
weak_ptr_factory_.GetWeakPtr(), proceed,
true,
approx_renderer_start_time, base::TimeTicks::Now(),
false));
}
bool RenderFrameHostImpl::ShouldDispatchBeforeUnload(
bool check_subframes_only,
bool* no_dispatch_because_avoid_unnecessary_sync) {
return CheckOrDispatchBeforeUnloadForSubtree(
check_subframes_only, false, false,
no_dispatch_because_avoid_unnecessary_sync);
}
void RenderFrameHostImpl::SetBeforeUnloadTimeoutDelayForTesting(
const base::TimeDelta& timeout) {
beforeunload_timeout_delay_ = timeout;
}
void RenderFrameHostImpl::StartPendingDeletionOnSubtree(
RenderFrameHostImpl::PendingDeletionReason pending_deletion_reason) {
DCHECK(IsPendingDeletion());
if (pending_deletion_reason == PendingDeletionReason::kFrameDetach ||
!ShouldAvoidRedundantNavigationCancellations()) {
NavigationDiscardReason reason = NavigationDiscardReason::kWillRemoveFrame;
GetFrameTreeNodeForUnload()->CancelNavigation();
GetFrameTreeNodeForUnload()
->GetRenderFrameHostManager()
.DiscardSpeculativeRFH(reason);
ResetOwnedNavigationRequests(reason);
} else {
CHECK(pending_deletion_reason == PendingDeletionReason::kSwappedOut ||
ShouldAvoidRedundantNavigationCancellations());
ResetNavigationsUsingSwappedOutRFH();
}
for (auto& subframe : children_) {
subframe->ResetAllNavigationsForFrameDetach();
}
for (std::unique_ptr<FrameTreeNode>& child_frame : children_) {
for (FrameTreeNode* node : frame_tree()->SubtreeNodes(child_frame.get())) {
RenderFrameHostImpl* child = node->current_frame_host();
if (child->IsPendingDeletion())
continue;
RenderFrameHostImpl* local_ancestor = child;
for (auto* rfh = child->parent_.get(); rfh != parent_;
rfh = rfh->parent_) {
if (rfh->GetSiteInstance() == child->GetSiteInstance())
local_ancestor = rfh;
}
local_ancestor->DeleteRenderFrame(
mojom::FrameDeleteIntention::kNotMainFrame);
if (local_ancestor != child) {
child->SetLifecycleState(
child->ShouldWaitForUnloadHandlers()
? LifecycleStateImpl::kRunningUnloadHandlers
: LifecycleStateImpl::kReadyToBeDeleted);
}
node->frame_tree().FrameUnloading(node);
}
}
}
void RenderFrameHostImpl::PendingDeletionCheckCompleted() {
if (lifecycle_state() == LifecycleStateImpl::kReadyToBeDeleted &&
children_.empty()) {
check_deletion_for_bug_1276535_ = false;
if (is_waiting_for_unload_ack_) {
OnUnloaded();
} else {
parent_->RemoveChild(GetFrameTreeNodeForUnload());
}
}
}
void RenderFrameHostImpl::PendingDeletionCheckCompletedOnSubtree() {
if (children_.empty()) {
PendingDeletionCheckCompleted();
return;
}
base::WeakPtr<RenderFrameHostImpl> self = GetWeakPtr();
check_deletion_for_bug_1276535_ = true;
std::vector<base::WeakPtr<RenderFrameHostImpl>> weak_children;
for (std::unique_ptr<FrameTreeNode>& child : children_) {
RenderFrameHostImpl* child_rfh = child->current_frame_host();
CHECK(child_rfh);
weak_children.push_back(child_rfh->GetWeakPtr());
}
for (base::WeakPtr<RenderFrameHostImpl>& child_rfh : weak_children) {
if (child_rfh) {
child_rfh->PendingDeletionCheckCompletedOnSubtree();
}
}
if (self) {
check_deletion_for_bug_1276535_ = false;
}
}
void RenderFrameHostImpl::ResetNavigationsUsingSwappedOutRFH() {
ResetOwnedNavigationRequests(
NavigationDiscardReason::kRenderFrameHostDestruction);
const NavigationRequest* navigation_request =
frame_tree_node_->navigation_request();
if (navigation_request &&
navigation_request->state() >= NavigationRequest::WILL_PROCESS_RESPONSE &&
navigation_request->GetRenderFrameHost() == this) {
frame_tree_node_->ResetNavigationRequest(
NavigationDiscardReason::kRenderFrameHostDestruction);
}
}
void RenderFrameHostImpl::OnUnloadTimeout() {
DCHECK(IsPendingDeletion());
parent_->RemoveChild(GetFrameTreeNodeForUnload());
}
void RenderFrameHostImpl::SetFocusedFrame() {
GetAssociatedLocalFrame()->Focus();
}
void RenderFrameHostImpl::AdvanceFocus(blink::mojom::FocusType type,
RenderFrameProxyHost* source_proxy) {
DCHECK(!source_proxy ||
(source_proxy->GetProcess()->GetID() == GetProcess()->GetID()));
absl::optional<blink::RemoteFrameToken> frame_token;
if (source_proxy)
frame_token = source_proxy->GetFrameToken();
GetAssociatedLocalFrame()->AdvanceFocusInFrame(type, frame_token);
}
void RenderFrameHostImpl::JavaScriptDialogClosed(
JavaScriptDialogCallback dialog_closed_callback,
bool success,
const std::u16string& user_input) {
GetProcess()->SetBlocked(false);
std::move(dialog_closed_callback).Run(success, user_input);
for (RenderFrameHostImpl* frame = this; frame; frame = frame->GetParent()) {
if (frame->is_waiting_for_beforeunload_completion_ &&
frame->beforeunload_timeout_) {
frame->beforeunload_timeout_->Start(beforeunload_timeout_delay_);
}
}
}
bool RenderFrameHostImpl::ShouldDispatchPagehideAndVisibilitychangeDuringCommit(
RenderFrameHostImpl* old_frame_host,
const UrlInfo& dest_url_info) {
DCHECK(old_frame_host);
if (old_frame_host->GetSiteInstance()->IsRelatedSiteInstance(
GetSiteInstance())) {
return false;
}
if (old_frame_host->GetProcess() != GetProcess()) {
return false;
}
if (!old_frame_host->IsNavigationSameSite(dest_url_info)) {
return false;
}
DCHECK(is_main_frame());
DCHECK_NE(old_frame_host, this);
DCHECK_NE(old_frame_host->GetSiteInstance(), GetSiteInstance());
return true;
}
void RenderFrameHostImpl::SendAllPendingBeaconsOnNavigation() {
if (auto* pending_beacon_host =
PendingBeaconHost::GetForCurrentDocument(this)) {
pending_beacon_host->SendAllOnNavigation();
}
for (auto& child : children_) {
child->current_frame_host()->SendAllPendingBeaconsOnNavigation();
}
}
bool RenderFrameHostImpl::is_initial_empty_document() const {
return frame_tree_node_->is_on_initial_empty_document();
}
uint32_t RenderFrameHostImpl::FindSuddenTerminationHandlers(bool same_origin) {
uint32_t navigation_termination = 0;
ForEachRenderFrameHostWithAction([this, same_origin, &navigation_termination](
RenderFrameHost* rfh) {
if (same_origin &&
GetLastCommittedOrigin() != rfh->GetLastCommittedOrigin()) {
return FrameIterationAction::kSkipChildren;
}
if (rfh->GetSuddenTerminationDisablerState(
blink::mojom::SuddenTerminationDisablerType::kUnloadHandler)) {
navigation_termination = navigation_termination |
NavigationSuddenTerminationDisablerType::kUnload;
return FrameIterationAction::kStop;
}
return FrameIterationAction::kContinue;
});
return navigation_termination;
}
void RenderFrameHostImpl::RecordNavigationSuddenTerminationHandlers() {
uint32_t navigation_termination =
is_main_frame() ? NavigationSuddenTerminationDisablerType::kMainFrame : 0;
if (is_initial_empty_document()) {
navigation_termination |=
NavigationSuddenTerminationDisablerType::kInitialEmptyDocument;
}
if (!GetLastCommittedURL().SchemeIsHTTPOrHTTPS()) {
navigation_termination |= NavigationSuddenTerminationDisablerType::kNotHttp;
}
base::UmaHistogramExactLinear(
"Navigation.SuddenTerminationDisabler.AllOrigins",
navigation_termination |
FindSuddenTerminationHandlers(false),
NavigationSuddenTerminationDisablerType::kMaxValue * 2);
base::UmaHistogramExactLinear(
"Navigation.SuddenTerminationDisabler.SameOrigin",
navigation_termination |
FindSuddenTerminationHandlers(true),
NavigationSuddenTerminationDisablerType::kMaxValue * 2);
}
void RenderFrameHostImpl::CommitNavigation(
NavigationRequest* navigation_request,
blink::mojom::CommonNavigationParamsPtr common_params,
blink::mojom::CommitNavigationParamsPtr commit_params,
network::mojom::URLResponseHeadPtr response_head,
mojo::ScopedDataPipeConsumerHandle response_body,
network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
absl::optional<SubresourceLoaderParams> subresource_loader_params,
absl::optional<std::vector<blink::mojom::TransferrableURLLoaderPtr>>
subresource_overrides,
blink::mojom::ServiceWorkerContainerInfoForClientPtr container_info,
const absl::optional<blink::DocumentToken>& document_token,
const base::UnguessableToken& devtools_navigation_token
#if BUILDFLAG(IS_OHOS_PRPP)
,
uint64_t addr_web_handle
#endif
) {
TRACE_EVENT2("navigation", "RenderFrameHostImpl::CommitNavigation",
"navigation_request", navigation_request, "url",
common_params->url);
DCHECK(!blink::IsRendererDebugURL(common_params->url));
DCHECK(navigation_request);
DCHECK_EQ(this, navigation_request->GetRenderFrameHost());
AssertBrowserContextShutdownHasntStarted();
bool is_same_document =
NavigationTypeUtils::IsSameDocument(common_params->navigation_type);
bool is_mhtml_subframe = navigation_request->IsForMhtmlSubframe();
DCHECK((response_head && url_loader_client_endpoints) ||
common_params->url.SchemeIs(url::kDataScheme) || is_same_document ||
!IsURLHandledByNetworkStack(common_params->url) || is_mhtml_subframe);
if (!is_main_frame()) {
RenderFrameHostImpl* root = GetMainFrame();
if (root->is_mhtml_document_) {
bool loaded_from_outside_the_archive =
response_head || url_loader_client_endpoints;
CHECK(!loaded_from_outside_the_archive ||
common_params->url.SchemeIs(url::kDataScheme));
CHECK(navigation_request->IsForMhtmlSubframe());
CHECK_EQ(GetSiteInstance(), root->GetSiteInstance());
CHECK_EQ(GetProcess(), root->GetProcess());
} else {
DCHECK(!navigation_request->IsForMhtmlSubframe());
}
}
bool is_srcdoc = common_params->url.IsAboutSrcdoc();
if (is_srcdoc) {
commit_params->srcdoc_value =
navigation_request->frame_tree_node()->srcdoc_value();
CHECK(!is_main_frame());
CHECK(GetSiteInstance() == parent_->GetSiteInstance() ||
!parent_->GetSiteInstance()->GetSiteInfo().is_sandboxed() &&
GetSiteInstance()->GetSiteInfo().is_sandboxed());
}
auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
const ProcessLock process_lock =
ProcessLock::FromSiteInfo(GetSiteInstance()->GetSiteInfo());
if (!process_lock.is_error_page() && common_params->url.IsStandard() &&
!is_mhtml_subframe &&
!policy->CanAccessDataForOrigin(
GetProcess()->GetID(), url::Origin::Create(common_params->url))) {
SCOPED_CRASH_KEY_STRING64("CommitNavigation", "lock_url",
process_lock.ToString());
SCOPED_CRASH_KEY_STRING64(
"CommitNavigation", "commit_origin",
common_params->url.DeprecatedGetOriginAsURL().spec());
SCOPED_CRASH_KEY_BOOL("CommitNavigation", "is_main_frame", is_main_frame());
SCOPED_CRASH_KEY_BOOL("CommitNavigation", "is_outermost_frame",
IsOutermostMainFrame());
NOTREACHED() << "Commiting in incompatible process for URL: "
<< process_lock.lock_url() << " lock vs "
<< common_params->url.DeprecatedGetOriginAsURL();
base::debug::DumpWithoutCrashing();
}
const bool is_first_navigation = !has_committed_any_navigation_;
has_committed_any_navigation_ = true;
if (!is_same_document) {
subresource_web_bundle_navigation_info_ =
navigation_request->GetSubresourceWebBundleNavigationInfo();
}
UpdatePermissionsForNavigation(navigation_request);
ResetWaitingState();
if (commit_params->is_view_source && IsActive()) {
DCHECK(!GetParentOrOuterDocument());
GetAssociatedLocalFrame()->EnableViewSourceMode();
}
network::mojom::URLResponseHeadPtr head =
response_head ? std::move(response_head)
: network::mojom::URLResponseHead::New();
std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
subresource_loader_factories;
mojo::PendingRemote<blink::mojom::ResourceCache> resource_cache_remote;
if (!is_same_document || is_first_navigation) {
recreate_default_url_loader_factory_after_network_service_crash_ = false;
subresource_loader_factories =
std::make_unique<blink::PendingURLLoaderFactoryBundle>();
BrowserContext* browser_context = GetSiteInstance()->GetBrowserContext();
auto subresource_loader_factories_config =
SubresourceLoaderFactoriesConfig::ForPendingNavigation(
*navigation_request);
const std::string& effective_scheme =
subresource_loader_factories_config.origin()
.GetTupleOrPrecursorTupleIfOpaque()
.scheme();
ContentBrowserClient::NonNetworkURLLoaderFactoryMap non_network_factories;
mojo::PendingRemote<network::mojom::URLLoaderFactory>
pending_default_factory;
const auto& webui_schemes = URLDataManagerBackend::GetWebUISchemes();
if (base::Contains(webui_schemes, effective_scheme)) {
mojo::PendingRemote<network::mojom::URLLoaderFactory> factory_for_webui;
auto factory_receiver =
factory_for_webui.InitWithNewPipeAndPassReceiver();
GetContentClient()->browser()->WillCreateURLLoaderFactory(
browser_context, this, GetProcess()->GetID(),
ContentBrowserClient::URLLoaderFactoryType::kDocumentSubResource,
subresource_loader_factories_config.origin(),
absl::nullopt,
subresource_loader_factories_config.ukm_source_id(),
&factory_receiver, nullptr,
nullptr,
nullptr, nullptr);
mojo::Remote<network::mojom::URLLoaderFactory> direct_factory_for_webui(
CreateWebUIURLLoaderFactory(this, effective_scheme, {}));
direct_factory_for_webui->Clone(std::move(factory_receiver));
if ((enabled_bindings_ & kWebUIBindingsPolicyMask) &&
!GetContentClient()->browser()->IsWebUIAllowedToMakeNetworkRequests(
subresource_loader_factories_config.origin())) {
pending_default_factory = std::move(factory_for_webui);
non_network_factories[url::kAboutScheme] =
AboutURLLoaderFactory::Create();
} else {
subresource_loader_factories->pending_scheme_specific_factories()
.emplace(effective_scheme, std::move(factory_for_webui));
}
}
if (navigation_request->IsMhtmlOrSubframe()) {
pending_default_factory =
network::NotImplementedURLLoaderFactory::Create();
}
if (!pending_default_factory) {
recreate_default_url_loader_factory_after_network_service_crash_ = true;
bool bypass_redirect_checks =
CreateNetworkServiceDefaultFactoryAndObserve(
CreateURLLoaderFactoryParamsForMainWorld(
subresource_loader_factories_config,
"RFHI::CommitNavigation"),
subresource_loader_factories_config.ukm_source_id(),
pending_default_factory.InitWithNewPipeAndPassReceiver());
subresource_loader_factories->set_bypass_redirect_checks(
bypass_redirect_checks);
}
DCHECK(pending_default_factory);
subresource_loader_factories->pending_default_factory() =
std::move(pending_default_factory);
if (effective_scheme == url::kFileScheme) {
base::TaskPriority file_factory_priority =
base::TaskPriority::USER_BLOCKING;
non_network_factories.emplace(
url::kFileScheme,
FileURLLoaderFactory::Create(
browser_context->GetPath(),
browser_context->GetSharedCorsOriginAccessList(),
file_factory_priority));
}
#if BUILDFLAG(IS_ANDROID)
if (effective_scheme == url::kContentScheme) {
non_network_factories.emplace(url::kContentScheme,
ContentURLLoaderFactory::Create());
}
#endif
#ifdef OHOS_HAP_DECOMPRESSED
if (effective_scheme == url::kResourcesScheme) {
base::TaskPriority file_factory_priority =
base::TaskPriority::USER_BLOCKING;
non_network_factories.emplace(
url::kResourcesScheme,
FileURLLoaderFactory::Create(
browser_context->GetPath(),
browser_context->GetSharedCorsOriginAccessList(),
file_factory_priority));
}
#endif
auto* partition = GetStoragePartition();
non_network_factories.emplace(
url::kFileSystemScheme,
CreateFileSystemURLLoaderFactory(
GetProcess()->GetID(), GetFrameTreeNodeId(),
partition->GetFileSystemContext(), partition->GetPartitionDomain(),
commit_params->storage_key));
non_network_factories.emplace(url::kDataScheme,
DataURLLoaderFactory::Create());
GetContentClient()
->browser()
->RegisterNonNetworkSubresourceURLLoaderFactories(
GetProcess()->GetID(), routing_id_,
subresource_loader_factories_config.origin(),
&non_network_factories);
for (auto& factory : non_network_factories) {
const std::string& scheme = factory.first;
mojo::PendingRemote<network::mojom::URLLoaderFactory>
original_pending_factory = std::move(factory.second);
if (!original_pending_factory)
continue;
mojo::PendingRemote<network::mojom::URLLoaderFactory>
pending_factory_proxy;
mojo::PendingReceiver<network::mojom::URLLoaderFactory> factory_receiver =
pending_factory_proxy.InitWithNewPipeAndPassReceiver();
WillCreateURLLoaderFactory(
subresource_loader_factories_config.origin(), &factory_receiver,
subresource_loader_factories_config.ukm_source_id());
mojo::Remote<network::mojom::URLLoaderFactory> remote(
std::move(original_pending_factory));
remote->Clone(std::move(factory_receiver));
subresource_loader_factories->pending_scheme_specific_factories().emplace(
scheme, std::move(pending_factory_proxy));
}
subresource_loader_factories->pending_isolated_world_factories() =
CreateURLLoaderFactoriesForIsolatedWorlds(
subresource_loader_factories_config,
isolated_worlds_requiring_separate_url_loader_factory_);
ResourceCacheManager* resource_cache_manager =
partition->GetResourceCacheManager();
if (resource_cache_manager) {
resource_cache_manager
->MaybeInitializeResourceCacheRemoteOnCommitNavigation(
resource_cache_remote, *navigation_request);
}
}
DCHECK(is_same_document || !is_first_navigation || is_srcdoc ||
subresource_loader_factories);
if (is_same_document) {
DCHECK_EQ(navigation_request->frame_tree_node()->current_frame_host(),
this);
const base::UnguessableToken& navigation_token =
commit_params->navigation_token;
DCHECK(GetSameDocumentNavigationRequest(navigation_token));
bool should_replace_current_entry =
common_params->should_replace_current_entry;
GetMojomFrameInRenderer()->CommitSameDocumentNavigation(
std::move(common_params), std::move(commit_params),
base::BindOnce(&RenderFrameHostImpl::OnSameDocumentCommitProcessed,
base::Unretained(this), navigation_token,
should_replace_current_entry));
} else {
blink::mojom::ControllerServiceWorkerInfoPtr controller;
mojo::PendingAssociatedRemote<blink::mojom::ServiceWorkerObject>
remote_object;
blink::mojom::ServiceWorkerState sent_state;
if (subresource_loader_params &&
subresource_loader_params->controller_service_worker_info) {
controller =
std::move(subresource_loader_params->controller_service_worker_info);
if (controller->object_info) {
controller->object_info->receiver =
remote_object.InitWithNewEndpointAndPassReceiver();
sent_state = controller->object_info->state;
}
}
std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
factory_bundle_for_prefetch;
mojo::PendingRemote<network::mojom::URLLoaderFactory>
prefetch_loader_factory;
if (subresource_loader_factories) {
auto bundle = base::MakeRefCounted<blink::URLLoaderFactoryBundle>(
std::move(subresource_loader_factories));
subresource_loader_factories = CloneFactoryBundle(bundle);
factory_bundle_for_prefetch = CloneFactoryBundle(bundle);
}
if (factory_bundle_for_prefetch) {
if (prefetched_signed_exchange_cache_) {
prefetched_signed_exchange_cache_->RecordHistograms();
prefetched_signed_exchange_cache_.reset();
}
auto* storage_partition = GetStoragePartition();
storage_partition->GetPrefetchURLLoaderService()->GetFactory(
prefetch_loader_factory.InitWithNewPipeAndPassReceiver(),
navigation_request->frame_tree_node()->frame_tree_node_id(),
std::move(factory_bundle_for_prefetch),
weak_ptr_factory_.GetWeakPtr(),
EnsurePrefetchedSignedExchangeCache());
}
mojo::PendingRemote<network::mojom::URLLoaderFactory> topics_loader_factory;
if (base::FeatureList::IsEnabled(blink::features::kBrowsingTopics)) {
std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
factory_bundle_for_topics;
if (subresource_loader_factories) {
auto bundle = base::MakeRefCounted<blink::URLLoaderFactoryBundle>(
std::move(subresource_loader_factories));
subresource_loader_factories = CloneFactoryBundle(bundle);
factory_bundle_for_topics = CloneFactoryBundle(bundle);
}
if (factory_bundle_for_topics) {
auto* storage_partition = GetStoragePartition();
base::WeakPtr<BrowsingTopicsURLLoaderService::BindContext>
bind_context =
storage_partition->GetBrowsingTopicsURLLoaderService()
->GetFactory(
topics_loader_factory.InitWithNewPipeAndPassReceiver(),
std::move(factory_bundle_for_topics));
navigation_request->set_topics_url_loader_service_bind_context(
bind_context);
}
}
mojo::PendingRemote<network::mojom::URLLoaderFactory>
keep_alive_loader_factory;
if (base::FeatureList::IsEnabled(
blink::features::kKeepAliveInBrowserMigration)) {
std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
factory_bundle_for_keep_alive;
if (subresource_loader_factories) {
auto bundle = base::MakeRefCounted<blink::URLLoaderFactoryBundle>(
std::move(subresource_loader_factories));
subresource_loader_factories = CloneFactoryBundle(bundle);
factory_bundle_for_keep_alive = CloneFactoryBundle(bundle);
}
if (factory_bundle_for_keep_alive) {
GetStoragePartition()->GetKeepAliveURLLoaderService()->BindFactory(
keep_alive_loader_factory.InitWithNewPipeAndPassReceiver(),
std::move(factory_bundle_for_keep_alive),
navigation_request->GetPolicyContainerHost());
}
}
mojom::NavigationClient* navigation_client =
navigation_request->GetCommitNavigationClient();
if (!GetParent() &&
navigation_request->frame_tree_node()->current_frame_host() == this) {
if (NavigationEntryImpl* last_committed_entry =
NavigationEntryImpl::FromNavigationEntry(
navigation_request->frame_tree_node()
->frame_tree()
.controller()
.GetLastCommittedEntry())) {
if (last_committed_entry->back_forward_cache_metrics()) {
last_committed_entry->back_forward_cache_metrics()
->RecordFeatureUsage(this);
}
}
}
blink::mojom::PolicyContainerPtr policy_container =
navigation_request->CreatePolicyContainerForBlink();
auto isolation_info = GetSiteInstance()->GetWebExposedIsolationInfo();
RenderFrameHostImpl* parent_frame_host = GetParentOrOuterDocument();
absl::optional<blink::ParsedPermissionsPolicy> manifest_policy;
if (!parent_frame_host && isolation_info.is_isolated_application()) {
if (auto isolated_web_app_permissions_policy =
GetContentClient()
->browser()
->GetPermissionsPolicyForIsolatedWebApp(
GetBrowserContext(), isolation_info.origin())) {
manifest_policy = std::move(isolated_web_app_permissions_policy);
}
}
SendCommitNavigation(
navigation_client, navigation_request, std::move(common_params),
std::move(commit_params), std::move(head), std::move(response_body),
std::move(url_loader_client_endpoints),
std::move(subresource_loader_factories),
std::move(subresource_overrides), std::move(controller),
std::move(container_info), std::move(prefetch_loader_factory),
std::move(topics_loader_factory), std::move(keep_alive_loader_factory),
std::move(resource_cache_remote), manifest_policy,
std::move(policy_container), *document_token,
devtools_navigation_token);
navigation_request->frame_tree_node()
->navigator()
.LogCommitNavigationSent();
if (remote_object.is_valid()) {
subresource_loader_params->controller_service_worker_object_host
->AddRemoteObjectPtrAndUpdateState(std::move(remote_object),
sent_state);
}
}
}
void RenderFrameHostImpl::FailedNavigation(
NavigationRequest* navigation_request,
const blink::mojom::CommonNavigationParams& common_params,
const blink::mojom::CommitNavigationParams& commit_params,
bool has_stale_copy_in_cache,
int error_code,
int extended_error_code,
const absl::optional<std::string>& error_page_content,
const blink::DocumentToken& document_token) {
TRACE_EVENT2("navigation", "RenderFrameHostImpl::FailedNavigation",
"navigation_request", navigation_request, "error", error_code);
DCHECK(navigation_request);
UpdatePermissionsForNavigation(navigation_request);
ResetWaitingState();
std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
subresource_loader_factories;
mojo::PendingRemote<network::mojom::URLLoaderFactory> default_factory_remote;
bool bypass_redirect_checks = CreateNetworkServiceDefaultFactoryAndObserve(
CreateURLLoaderFactoryParamsForMainWorld(
SubresourceLoaderFactoriesConfig::ForPendingNavigation(
*navigation_request),
"RFHI::FailedNavigation"),
ukm::kInvalidSourceIdObj,
default_factory_remote.InitWithNewPipeAndPassReceiver());
subresource_loader_factories =
std::make_unique<blink::PendingURLLoaderFactoryBundle>(
std::move(default_factory_remote),
blink::PendingURLLoaderFactoryBundle::SchemeMap(),
blink::PendingURLLoaderFactoryBundle::OriginMap(),
bypass_redirect_checks);
recreate_default_url_loader_factory_after_network_service_crash_ = true;
mojom::NavigationClient* navigation_client =
navigation_request->GetCommitNavigationClient();
blink::mojom::PolicyContainerPtr policy_container =
navigation_request->CreatePolicyContainerForBlink();
SendCommitFailedNavigation(navigation_client, navigation_request,
common_params.Clone(), commit_params.Clone(),
has_stale_copy_in_cache, error_code,
extended_error_code, error_page_content,
std::move(subresource_loader_factories),
document_token, std::move(policy_container));
has_committed_any_navigation_ = true;
DCHECK(navigation_request && navigation_request->IsNavigationStarted() &&
navigation_request->DidEncounterError());
}
void RenderFrameHostImpl::AddResourceTimingEntryForFailedSubframeNavigation(
FrameTreeNode* child_frame,
base::TimeTicks start_time,
base::TimeTicks redirect_time,
const GURL& initial_url,
const GURL& final_url,
network::mojom::URLResponseHeadPtr response_head,
bool allow_response_details,
const network::URLLoaderCompletionStatus& completion_status) {
uint32_t status_code = 0;
std::string mime_type;
std::string normalized_server_timing;
response_head->headers->GetNormalizedHeader("Server-Timing",
&normalized_server_timing);
if (allow_response_details) {
status_code = response_head->headers->response_code();
mime_type = response_head->mime_type;
}
absl::optional<blink::FrameToken> child_token_in_parent =
child_frame->GetRenderFrameHostManager()
.GetFrameTokenForSiteInstanceGroup(GetSiteInstance()->group());
if (!child_token_in_parent) {
return;
}
GetAssociatedLocalFrame()->AddResourceTimingEntryForFailedSubframeNavigation(
child_token_in_parent.value(), initial_url, start_time, redirect_time,
response_head->request_start, response_head->response_start, status_code,
mime_type, response_head->load_timing, response_head->connection_info,
response_head->alpn_negotiated_protocol,
base::Contains(url::GetSecureSchemes(),
url::Origin::Create(final_url).scheme()),
response_head->is_validated, normalized_server_timing, completion_status);
}
void RenderFrameHostImpl::HandleRendererDebugURL(const GURL& url) {
DCHECK(blink::IsRendererDebugURL(url));
GetAssociatedLocalFrame()->HandleRendererDebugURL(url);
GetProcess()->SetIsUsed();
}
void RenderFrameHostImpl::CreateBroadcastChannelProvider(
mojo::PendingAssociatedReceiver<blink::mojom::BroadcastChannelProvider>
receiver) {
auto* storage_partition_impl =
static_cast<StoragePartitionImpl*>(GetStoragePartition());
auto* broadcast_channel_service =
storage_partition_impl->GetBroadcastChannelService();
broadcast_channel_service->AddAssociatedReceiver(
std::make_unique<BroadcastChannelProvider>(broadcast_channel_service,
storage_key()),
std::move(receiver));
}
void RenderFrameHostImpl::BindBlobUrlStoreAssociatedReceiver(
mojo::PendingAssociatedReceiver<blink::mojom::BlobURLStore> receiver) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
auto* storage_partition_impl =
static_cast<StoragePartitionImpl*>(GetStoragePartition());
storage_partition_impl->GetBlobUrlRegistry()->AddReceiver(
storage_key(), std::move(receiver));
}
void RenderFrameHostImpl::BindBlobUrlStoreReceiver(
mojo::PendingReceiver<blink::mojom::BlobURLStore> receiver) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
auto* storage_partition_impl =
static_cast<StoragePartitionImpl*>(GetStoragePartition());
storage_partition_impl->GetBlobUrlRegistry()->AddReceiver(
storage_key(), std::move(receiver));
}
bool RenderFrameHostImpl::IsFocused() {
if (!GetMainFrame()->GetRenderWidgetHost()->is_focused() ||
!frame_tree_->GetFocusedFrame())
return false;
RenderFrameHostImpl* focused_rfh =
frame_tree_->GetFocusedFrame()->current_frame_host();
return focused_rfh == this ||
focused_rfh->IsDescendantOfWithinFrameTree(this);
}
void RenderFrameHostImpl::SetWebUI(NavigationRequest& request) {
std::unique_ptr<WebUIImpl> new_web_ui = request.TakeWebUI();
CHECK(new_web_ui);
CHECK(!web_ui_);
DCHECK(!GetSiteInstance()->GetSiteInfo().is_error_page());
WebUI::TypeID new_web_ui_type =
WebUIControllerFactoryRegistry::GetInstance()->GetWebUIType(
GetSiteInstance()->GetBrowserContext(), request.GetURL());
CHECK_NE(new_web_ui_type, WebUI::kNoWebUI);
web_ui_ = std::move(new_web_ui);
web_ui_->SetRenderFrameHost(this);
DCHECK(!GetProcess()->IsForGuestsOnly());
web_ui_type_ = new_web_ui_type;
for (const auto& scheme : web_ui_->GetRequestableSchemes()) {
ChildProcessSecurityPolicyImpl::GetInstance()->GrantRequestScheme(
GetProcess()->GetID(), scheme);
}
DCHECK_EQ(BINDINGS_POLICY_NONE, GetEnabledBindings());
AllowBindings(web_ui_->GetBindings());
}
void RenderFrameHostImpl::ClearWebUI() {
web_ui_type_ = WebUI::kNoWebUI;
web_ui_.reset();
}
const mojo::Remote<blink::mojom::ImageDownloader>&
RenderFrameHostImpl::GetMojoImageDownloader() {
if (!mojo_image_downloader_.is_bound() && GetRemoteInterfaces()) {
GetRemoteInterfaces()->GetInterface(
mojo_image_downloader_.BindNewPipeAndPassReceiver());
}
return mojo_image_downloader_;
}
const mojo::AssociatedRemote<blink::mojom::FindInPage>&
RenderFrameHostImpl::GetFindInPage() {
if (!find_in_page_)
GetRemoteAssociatedInterfaces()->GetInterface(&find_in_page_);
return find_in_page_;
}
const mojo::AssociatedRemote<blink::mojom::LocalFrame>&
RenderFrameHostImpl::GetAssociatedLocalFrame() {
if (!local_frame_)
GetRemoteAssociatedInterfaces()->GetInterface(&local_frame_);
return local_frame_;
}
blink::mojom::LocalMainFrame*
RenderFrameHostImpl::GetAssociatedLocalMainFrame() {
DCHECK(is_main_frame());
if (!local_main_frame_)
GetRemoteAssociatedInterfaces()->GetInterface(&local_main_frame_);
return local_main_frame_.get();
}
const mojo::Remote<blink::mojom::HighPriorityLocalFrame>&
RenderFrameHostImpl::GetHighPriorityLocalFrame() {
if (!high_priority_local_frame_.is_bound()) {
GetRemoteInterfaces()->GetInterface(
high_priority_local_frame_.BindNewPipeAndPassReceiver());
}
return high_priority_local_frame_;
}
const mojo::AssociatedRemote<mojom::FrameBindingsControl>&
RenderFrameHostImpl::GetFrameBindingsControl() {
if (!frame_bindings_control_)
GetRemoteAssociatedInterfaces()->GetInterface(&frame_bindings_control_);
return frame_bindings_control_;
}
void RenderFrameHostImpl::ResetLoadingState() {
if (is_loading()) {
if (IsPendingDeletion() || IsInBackForwardCache()) {
loading_state_ = LoadingState::NONE;
} else {
DidStopLoading();
}
}
}
void RenderFrameHostImpl::ClearFocusedElement() {
has_focused_editable_element_ = false;
GetAssociatedLocalFrame()->ClearFocusedElement();
}
void RenderFrameHostImpl::BindDevToolsAgent(
mojo::PendingAssociatedRemote<blink::mojom::DevToolsAgentHost> host,
mojo::PendingAssociatedReceiver<blink::mojom::DevToolsAgent> receiver) {
GetAssociatedLocalFrame()->BindDevToolsAgent(std::move(host),
std::move(receiver));
}
bool RenderFrameHostImpl::IsSameSiteInstance(
RenderFrameHostImpl* other_render_frame_host) {
CHECK_EQ(GetSiteInstance()->GetBrowserContext(),
other_render_frame_host->GetSiteInstance()->GetBrowserContext());
return GetSiteInstance() == other_render_frame_host->GetSiteInstance();
}
void RenderFrameHostImpl::UpdateAccessibilityMode() {
if (!IsRenderFrameLive())
return;
ui::AXMode ax_mode = delegate_->GetAccessibilityMode();
if (ax_mode.has_mode(ui::AXMode::kScreenReader) &&
!BackForwardCacheImpl::IsScreenReaderAllowed()) {
BackForwardCache::DisableForRenderFrameHost(
this, BackForwardCacheDisable::DisabledReason(
BackForwardCacheDisable::DisabledReasonId::kScreenReader));
}
if (ax_mode.has_mode(ui::AXMode::kWebContents)) {
if (!render_accessibility_) {
GetRemoteAssociatedInterfaces()->GetInterface(&render_accessibility_);
DCHECK(render_accessibility_);
}
render_accessibility_->SetMode(ax_mode);
} else {
render_accessibility_.reset();
}
if (!ax_mode.has_mode(ui::kAXModeBasic.flags()) &&
browser_accessibility_manager_) {
browser_accessibility_manager_->DetachFromParentManager();
browser_accessibility_manager_.reset();
}
}
void RenderFrameHostImpl::SnapshotDocumentForViewTransition(
blink::mojom::LocalFrame::SnapshotDocumentForViewTransitionCallback
callback) {
DCHECK(IsRenderFrameLive());
GetAssociatedLocalFrame()->SnapshotDocumentForViewTransition(
std::move(callback));
}
#if BUILDFLAG(ENABLE_PPAPI)
RenderFrameHostImplPpapiSupport& RenderFrameHostImpl::GetPpapiSupport() {
if (!ppapi_support_) {
ppapi_support_ = std::make_unique<RenderFrameHostImplPpapiSupport>(*this);
}
return *ppapi_support_;
}
#endif
void RenderFrameHostImpl::RequestAXTreeSnapshot(
AXTreeSnapshotCallback callback,
mojom::SnapshotAccessibilityTreeParamsPtr params) {
if (!IsRenderFrameLive())
return;
GetMojomFrameInRenderer()->SnapshotAccessibilityTree(
std::move(params),
base::BindOnce(&RenderFrameHostImpl::RequestAXTreeSnapshotCallback,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}
void RenderFrameHostImpl::GetSavableResourceLinksFromRenderer() {
if (!IsRenderFrameLive())
return;
GetAssociatedLocalFrame()->GetSavableResourceLinks(
base::BindOnce(&RenderFrameHostImpl::GetSavableResourceLinksCallback,
weak_ptr_factory_.GetWeakPtr()));
}
void RenderFrameHostImpl::SetAccessibilityCallbackForTesting(
const AccessibilityCallbackForTesting& callback) {
accessibility_testing_callback_ = callback;
}
void RenderFrameHostImpl::UpdateAXTreeData() {
ui::AXMode accessibility_mode = delegate_->GetAccessibilityMode();
if (accessibility_mode.is_mode_off() ||
IsInactiveAndDisallowActivation(
DisallowActivationReasonId::kAXUpdateTree)) {
return;
}
if (needs_ax_root_id_)
return;
if (ax_defer_scope_count_ > 0) {
ax_update_deferred_ = true;
return;
}
AXEventNotificationDetails detail;
detail.ax_tree_id = GetAXTreeID();
detail.updates.resize(1);
detail.updates[0].has_tree_data = true;
detail.updates[0].tree_data = GetAXTreeData();
SendAccessibilityEventsToManager(detail);
delegate_->AccessibilityEventReceived(detail);
}
RenderFrameHostImpl::UpdateAXFocusDeferScope::UpdateAXFocusDeferScope(
RenderFrameHostImpl& rfh)
: rfh_(rfh.GetSafeRef()) {
++rfh_->ax_defer_scope_count_;
}
RenderFrameHostImpl::UpdateAXFocusDeferScope::~UpdateAXFocusDeferScope() {
DCHECK_GE(rfh_->ax_defer_scope_count_, 1);
--rfh_->ax_defer_scope_count_;
if (!rfh_->ax_defer_scope_count_ && rfh_->ax_update_deferred_) {
rfh_->ax_update_deferred_ = false;
rfh_->UpdateAXTreeData();
}
}
BrowserAccessibilityManager*
RenderFrameHostImpl::GetOrCreateBrowserAccessibilityManager() {
ui::AXMode accessibility_mode = delegate_->GetAccessibilityMode();
if (!accessibility_mode.has_mode(ui::AXMode::kNativeAPIs)) {
DCHECK(!browser_accessibility_manager_);
return nullptr;
}
if (browser_accessibility_manager_ ||
no_create_browser_accessibility_manager_for_testing_)
return browser_accessibility_manager_.get();
browser_accessibility_manager_.reset(
BrowserAccessibilityManager::Create(this));
return browser_accessibility_manager_.get();
}
void RenderFrameHostImpl::ActivateFindInPageResultForAccessibility(
int request_id) {
BrowserAccessibilityManager* manager =
GetOrCreateBrowserAccessibilityManager();
if (manager)
manager->ActivateFindInPageResult(request_id);
}
void RenderFrameHostImpl::InsertVisualStateCallback(
VisualStateCallback callback) {
GetRenderWidgetHost()->InsertVisualStateCallback(std::move(callback));
}
bool RenderFrameHostImpl::IsLastCommitIPAddressPubliclyRoutable() const {
net::IPEndPoint ip_end_point =
last_response_head().get() ? last_response_head().get()->remote_endpoint
: net::IPEndPoint();
return ip_end_point.address().IsPubliclyRoutable();
}
bool RenderFrameHostImpl::IsRenderFrameLive() {
bool is_live =
GetProcess()->IsInitializedAndNotDead() && is_render_frame_created();
DCHECK(!is_live || render_view_host_->IsRenderViewLive());
return is_live;
}
RenderFrameHost::LifecycleState RenderFrameHostImpl::GetLifecycleState() {
return GetLifecycleStateFromImpl(lifecycle_state());
}
bool RenderFrameHostImpl::IsInLifecycleState(LifecycleState state) {
if (lifecycle_state() == LifecycleStateImpl::kSpeculative)
return false;
return state == GetLifecycleState();
}
RenderFrameHost::LifecycleState RenderFrameHostImpl::GetLifecycleStateFromImpl(
LifecycleStateImpl state) {
switch (state) {
case LifecycleStateImpl::kSpeculative:
NOTREACHED();
return LifecycleState::kPendingCommit;
case LifecycleStateImpl::kPendingCommit:
return LifecycleState::kPendingCommit;
case LifecycleStateImpl::kPrerendering:
return LifecycleState::kPrerendering;
case LifecycleStateImpl::kActive:
return LifecycleState::kActive;
case LifecycleStateImpl::kInBackForwardCache:
return LifecycleState::kInBackForwardCache;
case LifecycleStateImpl::kRunningUnloadHandlers:
return LifecycleState::kPendingDeletion;
case LifecycleStateImpl::kReadyToBeDeleted:
return LifecycleState::kPendingDeletion;
}
}
bool RenderFrameHostImpl::IsActive() {
if (has_pending_lifecycle_state_update_)
return false;
return lifecycle_state() == LifecycleStateImpl::kActive;
}
size_t RenderFrameHostImpl::GetProxyCount() {
if (!IsActive())
return 0;
return browsing_context_state_->GetProxyCount();
}
bool RenderFrameHostImpl::HasSelection() {
return has_selection_;
}
FrameTreeNode* RenderFrameHostImpl::PreviousSibling() const {
return GetSibling(-1);
}
FrameTreeNode* RenderFrameHostImpl::NextSibling() const {
return GetSibling(1);
}
FrameTreeNode* RenderFrameHostImpl::GetSibling(int relative_offset) const {
if (!parent_ || !parent_->child_count())
return nullptr;
for (size_t i = 0; i < parent_->child_count(); ++i) {
if (parent_->child_at(i)->frame_tree_node_id() != GetFrameTreeNodeId()) {
continue;
}
if (relative_offset < 0 && base::checked_cast<size_t>(-relative_offset) > i)
return nullptr;
if (i + relative_offset >= parent_->child_count())
return nullptr;
return parent_->child_at(i + relative_offset);
}
NOTREACHED() << "FrameTreeNode not found in its parent's children.";
return nullptr;
}
RenderFrameHostImpl* RenderFrameHostImpl::GetMainFrame() {
return const_cast<RenderFrameHostImpl*>(std::as_const(*this).GetMainFrame());
}
const RenderFrameHostImpl* RenderFrameHostImpl::GetMainFrame() const {
const RenderFrameHostImpl* main_frame = this;
while (const RenderFrameHostImpl* parent = main_frame->GetParent()) {
main_frame = parent;
}
return main_frame;
}
bool RenderFrameHostImpl::IsInPrimaryMainFrame() {
return !GetParent() && GetPage().IsPrimary();
}
RenderFrameHostImpl* RenderFrameHostImpl::GetOutermostMainFrame() {
RenderFrameHostImpl* current = this;
while (RenderFrameHostImpl* parent_or_outer_doc =
current->GetParentOrOuterDocument()) {
current = parent_or_outer_doc;
}
return current;
}
bool RenderFrameHostImpl::CanAccessFilesOfPageState(
const blink::PageState& state) {
return ChildProcessSecurityPolicyImpl::GetInstance()->CanReadAllFiles(
GetProcess()->GetID(), state.GetReferencedFiles());
}
void RenderFrameHostImpl::GrantFileAccessFromPageState(
const blink::PageState& state) {
GrantFileAccess(GetProcess()->GetID(), state.GetReferencedFiles());
}
void RenderFrameHostImpl::SetHasPendingLifecycleStateUpdate() {
DCHECK(!has_pending_lifecycle_state_update_);
for (auto& child : children_)
child->current_frame_host()->SetHasPendingLifecycleStateUpdate();
has_pending_lifecycle_state_update_ = true;
}
void RenderFrameHostImpl::GrantFileAccessFromResourceRequestBody(
const network::ResourceRequestBody& body) {
GrantFileAccess(GetProcess()->GetID(), body.GetReferencedFiles());
}
void RenderFrameHostImpl::UpdatePermissionsForNavigation(
NavigationRequest* request) {
if (!GetProcess()->IsForGuestsOnly()) {
ChildProcessSecurityPolicyImpl::GetInstance()->GrantCommitURL(
GetProcess()->GetID(), request->common_params().url);
if (request->IsLoadDataWithBaseURL()) {
ChildProcessSecurityPolicyImpl::GetInstance()->GrantCommitURL(
GetProcess()->GetID(),
request->common_params().base_url_for_data_url);
}
}
blink::PageState page_state = blink::PageState::CreateFromEncodedData(
request->commit_params().page_state);
if (page_state.IsValid())
GrantFileAccessFromPageState(page_state);
if (request->common_params().post_data)
GrantFileAccessFromResourceRequestBody(*request->common_params().post_data);
}
bool RenderFrameHostImpl::WindowManagementAllowsFullscreen() {
return IsWindowManagementGranted(this) &&
delegate_->IsTransientAllowFullscreenActive();
}
mojo::AssociatedRemote<mojom::NavigationClient>
RenderFrameHostImpl::GetNavigationClientFromInterfaceProvider() {
mojo::AssociatedRemote<mojom::NavigationClient> navigation_client_remote;
GetRemoteAssociatedInterfaces()->GetInterface(&navigation_client_remote);
return navigation_client_remote;
}
void RenderFrameHostImpl::NavigationRequestCancelled(
NavigationRequest* navigation_request) {
navigation_requests_.erase(navigation_request);
}
NavigationRequest*
RenderFrameHostImpl::FindLatestNavigationRequestThatIsStillCommitting() {
NavigationRequest* found_request = nullptr;
for (const auto& it : navigation_requests_) {
NavigationRequest* candidate = it.first;
DCHECK_EQ(candidate, it.second.get());
if (candidate->state() < NavigationRequest::READY_TO_COMMIT)
continue;
if (candidate->state() >= NavigationRequest::DID_COMMIT)
continue;
if (!found_request ||
found_request->NavigationStart() < candidate->NavigationStart()) {
found_request = candidate;
}
}
return found_request;
}
network::mojom::URLLoaderFactoryParamsPtr
RenderFrameHostImpl::CreateURLLoaderFactoryParamsForMainWorld(
const SubresourceLoaderFactoriesConfig& config,
base::StringPiece debug_tag) {
return URLLoaderFactoryParamsHelper::CreateForFrame(
this, config.origin(), config.isolation_info(),
config.GetClientSecurityState(), config.GetCoepReporter(), GetProcess(),
config.trust_token_issuance_policy(),
config.trust_token_redemption_policy(), config.cookie_setting_overrides(),
debug_tag
#if BUILDFLAG(IS_OHOS_PRPP)
,
config.main_url(),
config.addr_web_handle()
#endif
);
}
bool RenderFrameHostImpl::CreateNetworkServiceDefaultFactoryAndObserve(
network::mojom::URLLoaderFactoryParamsPtr params,
ukm::SourceIdObj ukm_source_id,
mojo::PendingReceiver<network::mojom::URLLoaderFactory>
default_factory_receiver) {
bool bypass_redirect_checks = CreateNetworkServiceDefaultFactoryInternal(
std::move(params), ukm_source_id, std::move(default_factory_receiver));
if (IsOutOfProcessNetworkService() &&
(!network_service_disconnect_handler_holder_ ||
!network_service_disconnect_handler_holder_.is_connected())) {
network_service_disconnect_handler_holder_.reset();
StoragePartition* storage_partition = GetStoragePartition();
network::mojom::URLLoaderFactoryParamsPtr monitoring_factory_params =
network::mojom::URLLoaderFactoryParams::New();
monitoring_factory_params->process_id = GetProcess()->GetID();
monitoring_factory_params->debug_tag = "RFHI - monitoring_factory_params";
monitoring_factory_params->request_initiator_origin_lock =
url::Origin::Create(
GURL("https://monitoring.url.loader.factory.invalid"));
storage_partition->GetNetworkContext()->CreateURLLoaderFactory(
network_service_disconnect_handler_holder_.BindNewPipeAndPassReceiver(),
std::move(monitoring_factory_params));
network_service_disconnect_handler_holder_.set_disconnect_handler(
base::BindOnce(&RenderFrameHostImpl::UpdateSubresourceLoaderFactories,
weak_ptr_factory_.GetWeakPtr()));
}
return bypass_redirect_checks;
}
bool RenderFrameHostImpl::CreateNetworkServiceDefaultFactoryInternal(
network::mojom::URLLoaderFactoryParamsPtr params,
ukm::SourceIdObj ukm_source_id,
mojo::PendingReceiver<network::mojom::URLLoaderFactory>
default_factory_receiver) {
DCHECK(params->request_initiator_origin_lock.has_value());
const url::Origin& request_initiator =
params->request_initiator_origin_lock.value();
bool bypass_redirect_checks = false;
WillCreateURLLoaderFactory(
request_initiator, &default_factory_receiver, ukm_source_id,
¶ms->header_client, &bypass_redirect_checks,
¶ms->disable_secure_dns, ¶ms->factory_override);
GetProcess()->CreateURLLoaderFactory(std::move(default_factory_receiver),
std::move(params));
return bypass_redirect_checks;
}
void RenderFrameHostImpl::WillCreateURLLoaderFactory(
const url::Origin& request_initiator,
mojo::PendingReceiver<network::mojom::URLLoaderFactory>* factory_receiver,
ukm::SourceIdObj ukm_source_id,
mojo::PendingRemote<network::mojom::TrustedURLLoaderHeaderClient>*
header_client,
bool* bypass_redirect_checks,
bool* disable_secure_dns,
network::mojom::URLLoaderFactoryOverridePtr* factory_override) {
GetContentClient()->browser()->WillCreateURLLoaderFactory(
GetBrowserContext(), this, GetProcess()->GetID(),
ContentBrowserClient::URLLoaderFactoryType::kDocumentSubResource,
request_initiator, absl::nullopt, ukm_source_id,
factory_receiver, header_client, bypass_redirect_checks,
disable_secure_dns, factory_override);
devtools_instrumentation::WillCreateURLLoaderFactory(
this, false, false, factory_receiver,
factory_override);
}
bool RenderFrameHostImpl::CanExecuteJavaScript() {
if (g_allow_injecting_javascript)
return true;
return !GetLastCommittedURL().is_valid() ||
GetLastCommittedURL().SchemeIs(kChromeDevToolsScheme) ||
ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
GetProcess()->GetID()) ||
(GetLastCommittedURL().spec() == url::kAboutBlankURL);
}
int RenderFrameHost::GetFrameTreeNodeIdForRoutingId(int process_id,
int routing_id) {
auto frame_or_proxy = LookupRenderFrameHostOrProxy(process_id, routing_id);
if (frame_or_proxy)
return frame_or_proxy.GetFrameTreeNode()->frame_tree_node_id();
return kNoFrameTreeNodeId;
}
int RenderFrameHost::GetFrameTreeNodeIdForFrameToken(
int process_id,
const ::blink::FrameToken& frame_token) {
auto frame_or_proxy = LookupRenderFrameHostOrProxy(process_id, frame_token);
if (frame_or_proxy)
return frame_or_proxy.GetFrameTreeNode()->frame_tree_node_id();
return kNoFrameTreeNodeId;
}
RenderFrameHost* RenderFrameHost::FromPlaceholderToken(
int render_process_id,
const blink::RemoteFrameToken& placeholder_frame_token) {
RenderFrameProxyHost* rfph = RenderFrameProxyHost::FromFrameToken(
render_process_id, placeholder_frame_token);
FrameTreeNode* node = rfph ? rfph->frame_tree_node() : nullptr;
return node ? node->current_frame_host() : nullptr;
}
ui::AXTreeID RenderFrameHostImpl::GetParentAXTreeID() {
auto* parent = GetParentOrOuterDocumentOrEmbedderExcludingProspectiveOwners();
if (!parent) {
DCHECK(AccessibilityIsRootFrame())
<< "Child frame requires a parent, root=" << GetLastCommittedURL();
return ui::AXTreeIDUnknown();
}
DCHECK(!AccessibilityIsRootFrame())
<< "Root frame must not have a parent, root=" << GetLastCommittedURL()
<< " parent=" << parent->GetLastCommittedURL();
return parent->GetAXTreeID();
}
ui::AXTreeID RenderFrameHostImpl::GetFocusedAXTreeID() {
if (!AccessibilityIsRootFrame())
return ui::AXTreeIDUnknown();
RenderFrameHostImpl* focused_frame = delegate_->GetFocusedFrame();
if (focused_frame)
return focused_frame->GetAXTreeID();
return ui::AXTreeIDUnknown();
}
ui::AXTreeData RenderFrameHostImpl::GetAXTreeData() {
ax_tree_data_.tree_id = GetAXTreeID();
ax_tree_data_.parent_tree_id = GetParentAXTreeID();
ax_tree_data_.focused_tree_id = GetFocusedAXTreeID();
return ax_tree_data_;
}
void RenderFrameHostImpl::AccessibilityHitTestCallback(
int request_id,
ax::mojom::Event event_to_fire,
base::OnceCallback<void(ui::AXPlatformTreeManager* hit_manager,
ui::AXNodeID hit_node_id)> opt_callback,
blink::mojom::HitTestResponsePtr hit_test_response) {
if (!hit_test_response) {
if (opt_callback)
std::move(opt_callback).Run(nullptr, 0);
return;
}
auto frame_or_proxy = LookupRenderFrameHostOrProxy(
GetProcess()->GetID(), hit_test_response->hit_frame_token);
RenderFrameHostImpl* hit_frame = frame_or_proxy.GetCurrentFrameHost();
if (!hit_frame || hit_frame->IsInactiveAndDisallowActivation(
DisallowActivationReasonId::kAXHitTestCallback)) {
if (opt_callback)
std::move(opt_callback).Run(nullptr, 0);
return;
}
if (hit_frame->GetFrameToken() == frame_token_) {
if (opt_callback) {
std::move(opt_callback)
.Run(hit_frame->browser_accessibility_manager(),
hit_test_response->hit_node_id);
}
return;
}
hit_frame->AccessibilityHitTest(
hit_test_response->hit_frame_transformed_point, event_to_fire, request_id,
std::move(opt_callback));
}
void RenderFrameHostImpl::RequestAXTreeSnapshotCallback(
AXTreeSnapshotCallback callback,
const ui::AXTreeUpdate& snapshot) {
ui::AXTreeUpdate dst_snapshot;
CopyAXTreeUpdate(snapshot, &dst_snapshot);
std::move(callback).Run(dst_snapshot);
}
void RenderFrameHostImpl::CopyAXTreeUpdate(const ui::AXTreeUpdate& snapshot,
ui::AXTreeUpdate* snapshot_copy) {
snapshot_copy->root_id = snapshot.root_id;
snapshot_copy->nodes.resize(snapshot.nodes.size());
for (size_t i = 0; i < snapshot.nodes.size(); ++i)
snapshot_copy->nodes[i] = snapshot.nodes[i];
if (snapshot.has_tree_data) {
ax_tree_data_ = snapshot.tree_data;
snapshot_copy->tree_data = GetAXTreeData();
snapshot_copy->has_tree_data = true;
}
}
void RenderFrameHostImpl::CreatePaymentManager(
mojo::PendingReceiver<payments::mojom::PaymentManager> receiver) {
if (!IsFeatureEnabled(blink::mojom::PermissionsPolicyFeature::kPayment)) {
mojo::ReportBadMessage("Permissions policy blocks Payment");
return;
}
GetProcess()->CreatePaymentManagerForOrigin(GetLastCommittedOrigin(),
std::move(receiver));
OnBackForwardCacheDisablingStickyFeatureUsed(
BackForwardCacheDisablingFeature::kPaymentManager);
}
WebBluetoothServiceImpl*
RenderFrameHostImpl::GetWebBluetoothServiceForTesting() {
if (!document_associated_data_ || !last_web_bluetooth_service_for_testing_)
return nullptr;
return last_web_bluetooth_service_for_testing_;
}
void RenderFrameHostImpl::CreateWebBluetoothService(
mojo::PendingReceiver<blink::mojom::WebBluetoothService> receiver) {
BackForwardCache::DisableForRenderFrameHost(
this, BackForwardCacheDisable::DisabledReason(
BackForwardCacheDisable::DisabledReasonId::kWebBluetooth));
last_web_bluetooth_service_for_testing_ =
WebBluetoothServiceImpl::Create(this, std::move(receiver));
}
void RenderFrameHostImpl::CreateWebUsbService(
mojo::PendingReceiver<blink::mojom::WebUsbService> receiver) {
if (!base::FeatureList::IsEnabled(features::kWebUsb)) {
return;
}
if (!IsFeatureEnabled(blink::mojom::PermissionsPolicyFeature::kUsb)) {
mojo::ReportBadMessage("Permissions policy blocks access to USB.");
return;
}
if (GetOutermostMainFrame()->GetLastCommittedOrigin().opaque()) {
mojo::ReportBadMessage(
"WebUSB is not allowed when the top-level document has an opaque "
"origin.");
return;
}
BackForwardCache::DisableForRenderFrameHost(
this, BackForwardCacheDisable::DisabledReason(
BackForwardCacheDisable::DisabledReasonId::kWebUSB));
WebUsbServiceImpl::Create(*this, std::move(receiver));
}
void RenderFrameHostImpl::ResetPermissionsPolicy() {
if (IsFencedFrameRoot()) {
const absl::optional<FencedFrameProperties>& properties =
frame_tree_node()->GetFencedFrameProperties();
permissions_policy_ = blink::PermissionsPolicy::CreateForFencedFrame(
last_committed_origin_,
properties.has_value() &&
properties->mode_ ==
blink::FencedFrame::DeprecatedFencedFrameMode::kOpaqueAds);
return;
}
RenderFrameHostImpl* parent_frame_host = GetParent();
auto isolation_info = GetSiteInstance()->GetWebExposedIsolationInfo();
if (!parent_frame_host && isolation_info.is_isolated_application()) {
if (auto isolated_web_app_permissions_policy =
GetContentClient()
->browser()
->GetPermissionsPolicyForIsolatedWebApp(
GetBrowserContext(), isolation_info.origin())) {
permissions_policy_ = blink::PermissionsPolicy::CreateFromParsedPolicy(
*isolated_web_app_permissions_policy, last_committed_origin_);
return;
}
}
const blink::PermissionsPolicy* parent_policy =
parent_frame_host ? parent_frame_host->permissions_policy() : nullptr;
blink::ParsedPermissionsPolicy container_policy =
browsing_context_state_->effective_frame_policy().container_policy;
permissions_policy_ = blink::PermissionsPolicy::CreateFromParentPolicy(
parent_policy, container_policy, last_committed_origin_);
}
void RenderFrameHostImpl::CreateAudioInputStreamFactory(
mojo::PendingReceiver<blink::mojom::RendererAudioInputStreamFactory>
receiver) {
BrowserMainLoop* browser_main_loop = BrowserMainLoop::GetInstance();
DCHECK(browser_main_loop);
MediaStreamManager* msm = browser_main_loop->media_stream_manager();
audio_service_audio_input_stream_factory_.emplace(std::move(receiver), msm,
this);
}
void RenderFrameHostImpl::CreateAudioOutputStreamFactory(
mojo::PendingReceiver<blink::mojom::RendererAudioOutputStreamFactory>
receiver) {
media::AudioSystem* audio_system =
BrowserMainLoop::GetInstance()->audio_system();
MediaStreamManager* media_stream_manager =
BrowserMainLoop::GetInstance()->media_stream_manager();
bool restricted_mode = frame_tree()->is_prerendering();
if (restricted_mode) {
audio_service_audio_output_stream_factory_.emplace(
this, audio_system, media_stream_manager, std::move(receiver),
base::BindOnce(
base::IgnoreResult(&RenderFrameHostImpl::CancelPrerendering),
base::Unretained(this),
PrerenderCancellationReason(
PrerenderFinalStatus::kAudioOutputDeviceRequested)));
} else {
audio_service_audio_output_stream_factory_.emplace(
this, audio_system, media_stream_manager, std::move(receiver),
absl::nullopt);
}
}
void RenderFrameHostImpl::GetFeatureObserver(
mojo::PendingReceiver<blink::mojom::FeatureObserver> receiver) {
if (!feature_observer_) {
auto* client = GetContentClient()->browser()->GetFeatureObserverClient();
if (!client)
return;
feature_observer_ = std::make_unique<FeatureObserver>(
client, GlobalRenderFrameHostId(GetProcess()->GetID(), routing_id_));
}
feature_observer_->GetFeatureObserver(std::move(receiver));
}
void RenderFrameHostImpl::BindRenderAccessibilityHost(
mojo::PendingReceiver<blink::mojom::RenderAccessibilityHost> receiver) {
DCHECK(GetAXTreeID().token());
ui::AXTreeID ax_tree_id = GetAXTreeID();
if (!render_accessibility_host_ ||
ax_tree_id != render_accessibility_host_ax_tree_id_) {
render_accessibility_host_ = base::SequenceBound<RenderAccessibilityHost>(
base::FeatureList::IsEnabled(
features::kRenderAccessibilityHostDeserializationOffMainThread)
? base::ThreadPool::CreateSequencedTaskRunner({})
: base::SequencedTaskRunner::GetCurrentDefault(),
render_frame_scoped_weak_ptr_factory_.GetWeakPtr(), ax_tree_id);
}
render_accessibility_host_ax_tree_id_ = ax_tree_id;
render_accessibility_host_.AsyncCall(&RenderAccessibilityHost::Bind)
.WithArgs(std::move(receiver));
}
void RenderFrameHostImpl::BindNonAssociatedLocalFrameHost(
mojo::PendingReceiver<blink::mojom::NonAssociatedLocalFrameHost> receiver) {
non_associated_local_frame_host_receiver_.Bind(std::move(receiver));
}
bool RenderFrameHostImpl::CancelPrerendering(
const PrerenderCancellationReason& reason) {
FrameTreeNode* outermost_frame =
GetOutermostMainFrameOrEmbedder()->frame_tree_node();
if (outermost_frame->GetFrameType() != FrameType::kPrerenderMainFrame)
return false;
return delegate_->GetPrerenderHostRegistry()->CancelHost(
outermost_frame->frame_tree_node_id(), reason);
}
void RenderFrameHostImpl::CancelPrerenderingByMojoBinderPolicy(
const std::string& interface_name) {
FrameTreeNode* outermost_frame =
GetOutermostMainFrameOrEmbedder()->frame_tree_node();
PrerenderHost* prerender_host =
delegate_->GetPrerenderHostRegistry()->FindNonReservedHostById(
outermost_frame->frame_tree_node_id());
if (!prerender_host)
return;
bool canceled = CancelPrerendering(
PrerenderCancellationReason::BuildForMojoBinderPolicy(interface_name));
DCHECK(canceled);
}
void RenderFrameHostImpl::RendererWillActivateForPrerendering() {
if (audio_service_audio_output_stream_factory_) {
audio_service_audio_output_stream_factory_->ReleaseRestriction();
}
DCHECK(mojo_binder_policy_applier_)
<< "prerendering pages should have a policy applier";
mojo_binder_policy_applier_->PrepareToGrantAll();
}
void RenderFrameHostImpl::BindMediaInterfaceFactoryReceiver(
mojo::PendingReceiver<media::mojom::InterfaceFactory> receiver) {
MediaInterfaceProxy::GetOrCreateForCurrentDocument(this)->Bind(
std::move(receiver));
}
void RenderFrameHostImpl::BindMediaMetricsProviderReceiver(
mojo::PendingReceiver<media::mojom::MediaMetricsProvider> receiver) {
media::VideoDecodePerfHistory::SaveCallback save_stats_cb;
if (GetSiteInstance()->GetBrowserContext()->GetVideoDecodePerfHistory()) {
save_stats_cb = GetSiteInstance()
->GetBrowserContext()
->GetVideoDecodePerfHistory()
->GetSaveCallback();
}
auto is_shutting_down_cb = base::BindRepeating(
[]() { return GetContentClient()->browser()->IsShuttingDown(); });
media::MediaMetricsProvider::Create(
GetProcess()->GetBrowserContext()->IsOffTheRecord()
? media::MediaMetricsProvider::BrowsingMode::kIncognito
: media::MediaMetricsProvider::BrowsingMode::kNormal,
IsOutermostMainFrame()
? media::MediaMetricsProvider::FrameStatus::kTopFrame
: media::MediaMetricsProvider::FrameStatus::kNotTopFrame,
GetPage().last_main_document_source_id(),
media::learning::FeatureValue(GetLastCommittedOrigin().host()),
std::move(save_stats_cb),
base::BindRepeating(
[](base::WeakPtr<RenderFrameHostImpl> frame)
-> media::learning::LearningSession* {
if (!base::FeatureList::IsEnabled(media::kMediaLearningFramework) ||
!frame) {
return nullptr;
}
return frame->GetProcess()
->GetBrowserContext()
->GetLearningSession();
},
weak_ptr_factory_.GetWeakPtr()),
base::BindRepeating(
&RenderFrameHostImpl::GetRecordAggregateWatchTimeCallback,
base::Unretained(this)),
std::move(is_shutting_down_cb), std::move(receiver));
}
#if BUILDFLAG(ENABLE_MEDIA_REMOTING)
void RenderFrameHostImpl::BindMediaRemoterFactoryReceiver(
mojo::PendingReceiver<media::mojom::RemoterFactory> receiver) {
mojo::MakeSelfOwnedReceiver(
std::make_unique<RemoterFactoryImpl>(GetProcess()->GetID(), routing_id_),
std::move(receiver));
}
#endif
void RenderFrameHostImpl::CreateWebSocketConnector(
mojo::PendingReceiver<blink::mojom::WebSocketConnector> receiver) {
mojo::MakeSelfOwnedReceiver(std::make_unique<WebSocketConnectorImpl>(
GetProcess()->GetID(), routing_id_,
last_committed_origin_, isolation_info_),
std::move(receiver));
}
void RenderFrameHostImpl::CreateWebTransportConnector(
mojo::PendingReceiver<blink::mojom::WebTransportConnector> receiver) {
mojo::MakeSelfOwnedReceiver(
std::make_unique<WebTransportConnectorImpl>(
GetProcess()->GetID(), weak_ptr_factory_.GetWeakPtr(),
last_committed_origin_, isolation_info_.network_anonymization_key()),
std::move(receiver));
}
void RenderFrameHostImpl::CreateNotificationService(
mojo::PendingReceiver<blink::mojom::NotificationService> receiver) {
GetProcess()->CreateNotificationService(
GetGlobalId(),
RenderProcessHost::NotificationServiceCreatorType::kDocument,
storage_key(), std::move(receiver));
}
void RenderFrameHostImpl::CreateInstalledAppProvider(
mojo::PendingReceiver<blink::mojom::InstalledAppProvider> receiver) {
InstalledAppProviderImpl::Create(*this, std::move(receiver));
}
void RenderFrameHostImpl::CreateCodeCacheHostWithKeys(
mojo::PendingReceiver<blink::mojom::CodeCacheHost> receiver,
const net::NetworkIsolationKey& nik,
const blink::StorageKey& storage_key) {
code_cache_host_receivers_.Add(GetProcess()->GetID(), nik, storage_key,
std::move(receiver),
GetCodeCacheHostReceiverHandler());
}
void RenderFrameHostImpl::CreateCodeCacheHost(
mojo::PendingReceiver<blink::mojom::CodeCacheHost> receiver) {
CreateCodeCacheHostWithKeys(std::move(receiver), GetNetworkIsolationKey(),
storage_key());
}
void RenderFrameHostImpl::CreateDedicatedWorkerHostFactory(
mojo::PendingReceiver<blink::mojom::DedicatedWorkerHostFactory> receiver) {
int worker_process_id = GetProcess()->GetID();
base::WeakPtr<CrossOriginEmbedderPolicyReporter> coep_reporter;
if (coep_reporter_) {
coep_reporter = coep_reporter_->GetWeakPtr();
}
mojo::MakeSelfOwnedReceiver(
std::make_unique<DedicatedWorkerHostFactoryImpl>(
worker_process_id,
GetGlobalId(),
absl::nullopt,
GetGlobalId(), storage_key(),
isolation_info_, BuildClientSecurityState(),
coep_reporter,
coep_reporter),
std::move(receiver));
}
#if BUILDFLAG(IS_ANDROID)
void RenderFrameHostImpl::BindNFCReceiver(
mojo::PendingReceiver<device::mojom::NFC> receiver) {
delegate_->GetNFC(this, std::move(receiver));
}
#endif
#if !BUILDFLAG(IS_ANDROID)
void RenderFrameHostImpl::BindSerialService(
mojo::PendingReceiver<blink::mojom::SerialService> receiver) {
if (!IsFeatureEnabled(blink::mojom::PermissionsPolicyFeature::kSerial)) {
mojo::ReportBadMessage("Permissions policy blocks access to Serial.");
return;
}
if (IsNestedWithinFencedFrame()) {
mojo::ReportBadMessage("Web Serial is not allowed in fences frames.");
return;
}
if (GetOutermostMainFrame()->GetLastCommittedOrigin().opaque()) {
mojo::ReportBadMessage(
"Web Serial is not allowed when the top-level document has an opaque "
"origin.");
return;
}
SerialService::GetOrCreateForCurrentDocument(this)->Bind(std::move(receiver));
}
void RenderFrameHostImpl::GetHidService(
mojo::PendingReceiver<blink::mojom::HidService> receiver) {
HidService::Create(this, std::move(receiver));
}
#endif
#if BUILDFLAG(IS_CHROMEOS)
void RenderFrameHostImpl::GetSmartCardService(
mojo::PendingReceiver<blink::mojom::SmartCardService> receiver) {
SmartCardService::Create(this, std::move(receiver));
}
#endif
IdleManagerImpl* RenderFrameHostImpl::GetIdleManager() {
return idle_manager_.get();
}
void RenderFrameHostImpl::BindIdleManager(
mojo::PendingReceiver<blink::mojom::IdleManager> receiver) {
if (!IsFeatureEnabled(
blink::mojom::PermissionsPolicyFeature::kIdleDetection)) {
mojo::ReportBadMessage(
"Permissions policy blocks access to IdleDetection.");
return;
}
idle_manager_->CreateService(std::move(receiver));
OnBackForwardCacheDisablingStickyFeatureUsed(
BackForwardCacheDisablingFeature::kIdleManager);
}
void RenderFrameHostImpl::GetPresentationService(
mojo::PendingReceiver<blink::mojom::PresentationService> receiver) {
if (!presentation_service_)
presentation_service_ = PresentationServiceImpl::Create(this);
presentation_service_->Bind(std::move(receiver));
}
PresentationServiceImpl&
RenderFrameHostImpl::GetPresentationServiceForTesting() {
DCHECK(presentation_service_);
return *presentation_service_.get();
}
void RenderFrameHostImpl::GetSpeechSynthesis(
mojo::PendingReceiver<blink::mojom::SpeechSynthesis> receiver) {
if (!speech_synthesis_impl_) {
speech_synthesis_impl_ = std::make_unique<SpeechSynthesisImpl>(
GetProcess()->GetBrowserContext(), this);
}
speech_synthesis_impl_->AddReceiver(std::move(receiver));
if (!base::FeatureList::IsEnabled(
features::kUnblockSpeechSynthesisForBFCache)) {
OnBackForwardCacheDisablingFeatureUsed(
BackForwardCacheDisablingFeature::kSpeechSynthesis);
}
}
void RenderFrameHostImpl::GetSensorProvider(
mojo::PendingReceiver<device::mojom::SensorProvider> receiver) {
SensorProviderProxyImpl::GetOrCreateForCurrentDocument(this)->Bind(
std::move(receiver));
}
void RenderFrameHostImpl::BindCacheStorage(
mojo::PendingReceiver<blink::mojom::CacheStorage> receiver) {
BindCacheStorageInternal(
std::move(receiver),
storage::BucketLocator::ForDefaultBucket(storage_key()));
}
void RenderFrameHostImpl::BindCacheStorageInternal(
mojo::PendingReceiver<blink::mojom::CacheStorage> receiver,
const storage::BucketLocator& bucket_locator) {
mojo::PendingRemote<network::mojom::CrossOriginEmbedderPolicyReporter>
coep_reporter_remote;
if (coep_reporter_) {
coep_reporter_->Clone(
coep_reporter_remote.InitWithNewPipeAndPassReceiver());
}
GetProcess()->BindCacheStorage(cross_origin_embedder_policy(),
std::move(coep_reporter_remote),
bucket_locator, std::move(receiver));
}
void RenderFrameHostImpl::BindInputInjectorReceiver(
mojo::PendingReceiver<mojom::InputInjector> receiver) {
InputInjectorImpl::Create(weak_ptr_factory_.GetWeakPtr(),
std::move(receiver));
}
void RenderFrameHostImpl::BindWebOTPServiceReceiver(
mojo::PendingReceiver<blink::mojom::WebOTPService> receiver) {
auto* fetcher = SmsFetcher::Get(GetProcess()->GetBrowserContext());
if (WebOTPService::Create(fetcher, this, std::move(receiver)))
document_used_web_otp_ = true;
}
void RenderFrameHostImpl::BindFederatedAuthRequestReceiver(
mojo::PendingReceiver<blink::mojom::FederatedAuthRequest> receiver) {
FederatedAuthRequestImpl::Create(this, std::move(receiver));
}
void RenderFrameHostImpl::BindRestrictedCookieManager(
mojo::PendingReceiver<network::mojom::RestrictedCookieManager> receiver) {
BindRestrictedCookieManagerWithOrigin(
std::move(receiver), GetIsolationInfoForSubresources(),
GetLastCommittedOrigin(), GetCookieSettingOverrides());
}
void RenderFrameHostImpl::BindRestrictedCookieManagerWithOrigin(
mojo::PendingReceiver<network::mojom::RestrictedCookieManager> receiver,
const net::IsolationInfo& isolation_info,
const url::Origin& origin,
net::CookieSettingOverrides cookie_setting_overrides) {
GetStoragePartition()->CreateRestrictedCookieManager(
network::mojom::RestrictedCookieManagerRole::SCRIPT, origin,
isolation_info,
false, GetProcess()->GetID(), GetRoutingID(),
cookie_setting_overrides, std::move(receiver),
CreateCookieAccessObserver());
}
void RenderFrameHostImpl::BindTrustTokenQueryAnswerer(
mojo::PendingReceiver<network::mojom::TrustTokenQueryAnswerer> receiver) {
auto top_frame_origin = ComputeTopFrameOrigin(GetLastCommittedOrigin());
if ((top_frame_origin.scheme() != url::kHttpScheme &&
top_frame_origin.scheme() != url::kHttpsScheme) ||
!network::IsOriginPotentiallyTrustworthy(top_frame_origin)) {
mojo::ReportBadMessage(
"Attempted to get a TrustTokenQueryAnswerer for a non-trustworthy or "
"non-HTTP/HTTPS top-frame origin.");
return;
}
if (!base::FeatureList::IsEnabled(network::features::kPrivateStateTokens) &&
!base::FeatureList::IsEnabled(network::features::kFledgePst)) {
mojo::ReportBadMessage(
"Attempted to get a TrustTokenQueryAnswerer with Private State Tokens "
"disabled.");
return;
}
GetProcess()->GetStoragePartition()->CreateTrustTokenQueryAnswerer(
std::move(receiver), ComputeTopFrameOrigin(GetLastCommittedOrigin()));
}
void RenderFrameHostImpl::GetAudioContextManager(
mojo::PendingReceiver<blink::mojom::AudioContextManager> receiver) {
AudioContextManagerImpl::Create(this, std::move(receiver));
}
void RenderFrameHostImpl::GetFileSystemManager(
mojo::PendingReceiver<blink::mojom::FileSystemManager> receiver) {
GetIOThreadTaskRunner({})->PostTask(
FROM_HERE, base::BindOnce(&FileSystemManagerImpl::BindReceiver,
base::Unretained(file_system_manager_.get()),
storage_key(), std::move(receiver)));
}
void RenderFrameHostImpl::GetGeolocationService(
mojo::PendingReceiver<blink::mojom::GeolocationService> receiver) {
if (!geolocation_service_) {
auto* geolocation_context = delegate_->GetGeolocationContext();
if (!geolocation_context)
return;
geolocation_service_ =
std::make_unique<GeolocationServiceImpl>(geolocation_context, this);
}
geolocation_service_->Bind(std::move(receiver));
}
void RenderFrameHostImpl::GetPendingBeaconHost(
mojo::PendingReceiver<blink::mojom::PendingBeaconHost> receiver) {
PendingBeaconHost::CreateForCurrentDocument(
this, GetStoragePartition()->GetURLLoaderFactoryForBrowserProcess(),
PendingBeaconService::GetInstance());
PendingBeaconHost* pbh = PendingBeaconHost::GetForCurrentDocument(this);
pbh->SetReceiver(std::move(receiver));
}
void RenderFrameHostImpl::GetDeviceInfoService(
mojo::PendingReceiver<blink::mojom::DeviceAPIService> receiver) {
GetContentClient()->browser()->CreateDeviceInfoService(this,
std::move(receiver));
}
void RenderFrameHostImpl::GetManagedConfigurationService(
mojo::PendingReceiver<blink::mojom::ManagedConfigurationService> receiver) {
GetContentClient()->browser()->CreateManagedConfigurationService(
this, std::move(receiver));
}
void RenderFrameHostImpl::GetFontAccessManager(
mojo::PendingReceiver<blink::mojom::FontAccessManager> receiver) {
GetStoragePartition()->GetFontAccessManager()->BindReceiver(
GetGlobalId(), std::move(receiver));
}
void RenderFrameHostImpl::GetFileSystemAccessManager(
mojo::PendingReceiver<blink::mojom::FileSystemAccessManager> receiver) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
auto* manager = GetStoragePartition()->GetFileSystemAccessManager();
manager->BindReceiver(
FileSystemAccessManagerImpl::BindingContext(
storage_key(), GetLastCommittedURL(), GetGlobalId()),
std::move(receiver));
}
void RenderFrameHostImpl::CreateLockManager(
mojo::PendingReceiver<blink::mojom::LockManager> receiver) {
GetProcess()->CreateLockManager(storage_key(), std::move(receiver));
}
void RenderFrameHostImpl::CreateIDBFactory(
mojo::PendingReceiver<blink::mojom::IDBFactory> receiver) {
GetProcess()->BindIndexedDB(storage_key(), GetGlobalId(),
std::move(receiver));
}
void RenderFrameHostImpl::CreateBucketManagerHost(
mojo::PendingReceiver<blink::mojom::BucketManagerHost> receiver) {
GetProcess()->BindBucketManagerHost(weak_ptr_factory_.GetWeakPtr(),
std::move(receiver));
}
void RenderFrameHostImpl::CreatePermissionService(
mojo::PendingReceiver<blink::mojom::PermissionService> receiver) {
PermissionServiceContext::GetOrCreateForCurrentDocument(this)->CreateService(
std::move(receiver));
}
void RenderFrameHostImpl::GetWebAuthenticationService(
mojo::PendingReceiver<blink::mojom::Authenticator> receiver) {
#if !BUILDFLAG(IS_ANDROID)
AuthenticatorImpl::Create(this, std::move(receiver));
#else
GetJavaInterfaces()->GetInterface(std::move(receiver));
#endif
}
void RenderFrameHostImpl::GetPushMessaging(
mojo::PendingReceiver<blink::mojom::PushMessaging> receiver) {
if (!push_messaging_manager_) {
auto* rph = GetProcess();
push_messaging_manager_ = std::make_unique<PushMessagingManager>(
*rph, routing_id_,
base::WrapRefCounted(GetStoragePartition()->GetServiceWorkerContext()));
}
push_messaging_manager_->AddPushMessagingReceiver(std::move(receiver));
}
void RenderFrameHostImpl::GetVirtualAuthenticatorManager(
mojo::PendingReceiver<blink::test::mojom::VirtualAuthenticatorManager>
receiver) {
#if !BUILDFLAG(IS_ANDROID)
if (!IsActive()) {
return;
}
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableWebAuthDeprecatedMojoTestingApi)) {
CHECK(owner_);
owner_->GetVirtualAuthenticatorManager(std::move(receiver));
}
#endif
}
bool IsInitialSynchronousAboutBlankCommit(const GURL& url,
bool is_initial_empty_document) {
return url.SchemeIs(url::kAboutScheme) && url != GURL(url::kAboutSrcdocURL) &&
is_initial_empty_document;
}
std::unique_ptr<NavigationRequest>
RenderFrameHostImpl::CreateNavigationRequestForSynchronousRendererCommit(
const GURL& url,
const url::Origin& origin,
const absl::optional<GURL>& initiator_base_url,
blink::mojom::ReferrerPtr referrer,
const ui::PageTransition& transition,
bool should_replace_current_entry,
bool has_user_gesture,
const std::vector<GURL>& redirects,
const GURL& original_request_url,
bool is_same_document,
bool is_same_document_history_api_navigation) {
DCHECK(IsInitialSynchronousAboutBlankCommit(
url, frame_tree_node_->is_on_initial_empty_document()) ||
is_same_document);
DCHECK(!is_same_document_history_api_navigation || is_same_document);
DCHECK(!IsPendingDeletion());
DCHECK(!IsInBackForwardCache());
CHECK(owner_);
net::IsolationInfo isolation_info = ComputeIsolationInfoInternal(
origin, net::IsolationInfo::RequestType::kOther, IsCredentialless(),
absl::nullopt);
std::unique_ptr<CrossOriginEmbedderPolicyReporter> coep_reporter;
if (!is_same_document) {
auto* storage_partition =
static_cast<StoragePartitionImpl*>(GetProcess()->GetStoragePartition());
coep_reporter = std::make_unique<CrossOriginEmbedderPolicyReporter>(
storage_partition->GetWeakPtr(), url,
cross_origin_embedder_policy().reporting_endpoint,
cross_origin_embedder_policy().report_only_reporting_endpoint,
GetReportingSource(), isolation_info.network_anonymization_key());
}
std::unique_ptr<SubresourceWebBundleNavigationInfo>
subresource_web_bundle_navigation_info;
if (is_same_document && subresource_web_bundle_navigation_info_) {
subresource_web_bundle_navigation_info =
subresource_web_bundle_navigation_info_->Clone();
}
std::string method = "GET";
if (is_same_document && !is_same_document_history_api_navigation) {
method = last_http_method_;
}
int http_status_code = is_same_document ? last_http_status_code_ : 0;
bool is_overriding_user_agent = is_same_document && is_overriding_user_agent_;
return owner_->CreateNavigationRequestForSynchronousRendererCommit(
this, is_same_document, url, origin, initiator_base_url, isolation_info,
std::move(referrer), transition, should_replace_current_entry, method,
has_user_gesture, is_overriding_user_agent, redirects,
original_request_url, std::move(coep_reporter),
std::move(subresource_web_bundle_navigation_info), http_status_code);
}
void RenderFrameHostImpl::BeforeUnloadTimeout() {
if (delegate_->ShouldIgnoreUnresponsiveRenderer()) {
return;
}
SimulateBeforeUnloadCompleted(true);
}
void RenderFrameHostImpl::SetLastCommittedSiteInfo(const UrlInfo& url_info) {
BrowserContext* browser_context = GetSiteInstance()->GetBrowserContext();
SiteInfo site_info =
url_info.url.is_empty()
? SiteInfo(browser_context)
: SiteInfo::Create(GetSiteInstance()->GetIsolationContext(),
url_info);
if (last_committed_site_info_ == site_info)
return;
if (!last_committed_site_info_.site_url().is_empty()) {
RenderProcessHostImpl::RemoveFrameWithSite(browser_context, GetProcess(),
last_committed_site_info_);
}
last_committed_site_info_ = site_info;
if (!last_committed_site_info_.site_url().is_empty()) {
RenderProcessHostImpl::AddFrameWithSite(browser_context, GetProcess(),
last_committed_site_info_);
}
}
#if BUILDFLAG(IS_ANDROID)
base::android::ScopedJavaLocalRef<jobject>
RenderFrameHostImpl::GetJavaRenderFrameHost() {
RenderFrameHostAndroid* render_frame_host_android =
static_cast<RenderFrameHostAndroid*>(
GetUserData(kRenderFrameHostAndroidKey));
if (!render_frame_host_android) {
render_frame_host_android = new RenderFrameHostAndroid(this);
SetUserData(kRenderFrameHostAndroidKey,
base::WrapUnique(render_frame_host_android));
}
return render_frame_host_android->GetJavaObject();
}
service_manager::InterfaceProvider* RenderFrameHostImpl::GetJavaInterfaces() {
if (!java_interfaces_) {
mojo::PendingRemote<service_manager::mojom::InterfaceProvider> provider;
BindInterfaceRegistryForRenderFrameHost(
provider.InitWithNewPipeAndPassReceiver(), this);
java_interfaces_ = std::make_unique<service_manager::InterfaceProvider>(
base::SingleThreadTaskRunner::GetCurrentDefault());
java_interfaces_->Bind(std::move(provider));
}
return java_interfaces_.get();
}
#endif
void RenderFrameHostImpl::ForEachImmediateLocalRoot(
base::FunctionRef<void(RenderFrameHostImpl*)> func_ref) {
ForEachRenderFrameHostWithAction([func_ref, this](RenderFrameHostImpl* rfh) {
if (rfh->is_local_root() && rfh != this) {
func_ref(rfh);
return FrameIterationAction::kSkipChildren;
}
return FrameIterationAction::kContinue;
});
}
void RenderFrameHostImpl::SetVisibilityForChildViews(bool visible) {
ForEachImmediateLocalRoot([visible](RenderFrameHostImpl* frame_host) {
if (auto* view = frame_host->GetView())
return visible ? view->Show() : view->Hide();
});
}
mojom::Frame* RenderFrameHostImpl::GetMojomFrameInRenderer() {
DCHECK(frame_);
return frame_.get();
}
bool RenderFrameHostImpl::ShouldBypassSecurityChecksForErrorPage(
NavigationRequest* navigation_request,
bool* should_commit_error_page) {
if (should_commit_error_page)
*should_commit_error_page = false;
if (SiteIsolationPolicy::IsErrorPageIsolationEnabled(is_main_frame())) {
if (GetSiteInstance()->GetSiteInfo().is_error_page()) {
if (should_commit_error_page)
*should_commit_error_page = true;
return true;
}
} else {
if (navigation_request &&
net::IsRequestBlockedError(navigation_request->GetNetErrorCode())) {
return true;
}
}
return false;
}
void RenderFrameHostImpl::SetAudioOutputDeviceIdForGlobalMediaControls(
std::string hashed_device_id) {
audio_service_audio_output_stream_factory_
->SetAuthorizedDeviceIdForGlobalMediaControls(
std::move(hashed_device_id));
}
std::unique_ptr<mojo::MessageFilter>
RenderFrameHostImpl::CreateMessageFilterForAssociatedReceiver(
const char* interface_name) {
return CreateMessageFilterForAssociatedReceiverInternal(
interface_name,
BackForwardCacheImpl::GetChannelAssociatedMessageHandlingPolicy());
}
network::mojom::ClientSecurityStatePtr
RenderFrameHostImpl::BuildClientSecurityState() const {
if (!policy_container_host_) {
DCHECK_EQ(lifecycle_state_, LifecycleStateImpl::kSpeculative);
network::CrossOriginEmbedderPolicy coep;
coep.value = network::mojom::CrossOriginEmbedderPolicyValue::kRequireCorp;
return network::mojom::ClientSecurityState::New(
std::move(coep),
false,
network::mojom::IPAddressSpace::kUnknown,
network::mojom::LocalNetworkRequestPolicy::kBlock);
}
auto client_security_state = network::mojom::ClientSecurityState::New();
const PolicyContainerPolicies& policies = policy_container_host_->policies();
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->local_network_request_policy =
local_network_request_policy_;
client_security_state->cross_origin_embedder_policy =
policies.cross_origin_embedder_policy;
return client_security_state;
}
network::mojom::ClientSecurityStatePtr
RenderFrameHostImpl::BuildClientSecurityStateForWorkers() const {
auto client_security_state = BuildClientSecurityState();
client_security_state->local_network_request_policy =
DerivePrivateNetworkRequestPolicy(
client_security_state->ip_address_space,
client_security_state->is_web_secure_context,
PrivateNetworkRequestContext::kWorker);
return client_security_state;
}
bool RenderFrameHostImpl::IsNavigationSameSite(
const UrlInfo& dest_url_info) const {
if (!WebExposedIsolationInfo::AreCompatible(
GetSiteInstance()->GetWebExposedIsolationInfo(),
dest_url_info.web_exposed_isolation_info)) {
return false;
}
return GetSiteInstance()->IsNavigationSameSite(
last_successful_url(), GetLastCommittedOrigin(), IsOutermostMainFrame(),
dest_url_info);
}
bool RenderFrameHostImpl::ValidateDidCommitParams(
NavigationRequest* navigation_request,
mojom::DidCommitProvisionalLoadParams* params,
bool is_same_document_navigation) {
DCHECK(params);
RenderProcessHost* process = GetProcess();
bool should_commit_error_page = false;
bool bypass_checks_for_error_page = ShouldBypassSecurityChecksForErrorPage(
navigation_request, &should_commit_error_page);
if (should_commit_error_page &&
(navigation_request && !navigation_request->DidEncounterError())) {
DEBUG_ALIAS_FOR_ORIGIN(origin_debug_alias, params->origin);
bad_message::ReceivedBadMessage(
process, bad_message::RFH_ERROR_PROCESS_NON_ERROR_COMMIT);
return false;
}
if (bypass_checks_for_error_page && !params->origin.opaque()) {
DEBUG_ALIAS_FOR_ORIGIN(origin_debug_alias, params->origin);
bad_message::ReceivedBadMessage(
process, bad_message::RFH_ERROR_PROCESS_NON_UNIQUE_ORIGIN_COMMIT);
return false;
}
if (!bypass_checks_for_error_page &&
!ValidateURLAndOrigin(params->url, params->origin,
is_same_document_navigation, navigation_request)) {
return false;
}
process->FilterURL(false, ¶ms->url);
process->FilterURL(true, ¶ms->referrer->url);
if (!CanAccessFilesOfPageState(params->page_state)) {
bad_message::ReceivedBadMessage(
process, bad_message::RFH_CAN_ACCESS_FILES_OF_PAGE_STATE);
return false;
}
bool is_page_activation =
navigation_request && navigation_request->IsPageActivation();
DCHECK(!is_page_activation || embedding_token_.has_value());
if (!is_page_activation) {
if (!is_same_document_navigation && !params->embedding_token.has_value()) {
bad_message::ReceivedBadMessage(process,
bad_message::RFH_MISSING_EMBEDDING_TOKEN);
return false;
} else if (is_same_document_navigation &&
params->embedding_token.has_value()) {
bad_message::ReceivedBadMessage(
process, bad_message::RFH_UNEXPECTED_EMBEDDING_TOKEN);
return false;
}
}
if (!blink::DocumentPolicy::IsPolicyCompatible(
browsing_context_state_->effective_frame_policy()
.required_document_policy,
params->document_policy_header)) {
bad_message::ReceivedBadMessage(
process, bad_message::RFH_BAD_DOCUMENT_POLICY_HEADER);
return false;
}
if (is_same_document_navigation &&
lifecycle_state() == LifecycleStateImpl::kPendingCommit) {
bad_message::ReceivedBadMessage(process,
bad_message::NI_IN_PAGE_NAVIGATION);
return false;
}
if (is_same_document_navigation) {
CHECK(owner_);
if (owner_->GetCurrentNavigator()
.controller()
.has_post_commit_error_entry()) {
bad_message::ReceivedBadMessage(
process, bad_message::NC_SAME_DOCUMENT_POST_COMMIT_ERROR);
return false;
}
}
if (navigation_request && !is_main_frame()) {
if (!CanSubframeCommitOriginAndUrl(navigation_request)) {
bad_message::ReceivedBadMessage(
process,
bad_message::RFHI_SUBFRAME_NAV_WOULD_CHANGE_MAINFRAME_ORIGIN);
return false;
}
}
return true;
}
bool RenderFrameHostImpl::ValidateURLAndOrigin(
const GURL& url,
const url::Origin& origin,
bool is_same_document_navigation,
NavigationRequest* navigation_request) {
if (origin.scheme() == url::kFileScheme) {
auto prefs = GetOrCreateWebPreferences();
if (prefs.allow_universal_access_from_file_urls)
return true;
}
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableWebSecurity)) {
return true;
}
DCHECK(navigation_request || is_same_document_navigation ||
frame_tree_node_->is_on_initial_empty_document());
RenderProcessHost* process = GetProcess();
if ((navigation_request && navigation_request->IsLoadDataWithBaseURL()) ||
(is_same_document_navigation &&
renderer_url_info_.was_loaded_from_load_data_with_base_url)) {
if (!process->GetProcessLock().is_locked_to_site())
return true;
}
bool is_pdf = navigation_request && navigation_request->GetUrlInfo().is_pdf;
bool is_sandboxed =
navigation_request && navigation_request->GetUrlInfo().is_sandboxed;
switch (CanCommitOriginAndUrl(origin, url, is_same_document_navigation,
is_pdf, is_sandboxed)) {
case CanCommitStatus::CAN_COMMIT_ORIGIN_AND_URL:
break;
case CanCommitStatus::CANNOT_COMMIT_URL:
DLOG(ERROR) << "CANNOT_COMMIT_URL url '" << url << "'"
<< " origin '" << origin << "'"
<< " lock '" << process->GetProcessLock().ToString() << "'";
VLOG(1) << "Blocked URL " << url.spec();
LogCannotCommitUrlCrashKeys(url, is_same_document_navigation,
navigation_request);
bad_message::ReceivedBadMessage(process,
bad_message::RFH_CAN_COMMIT_URL_BLOCKED);
return false;
case CanCommitStatus::CANNOT_COMMIT_ORIGIN:
DLOG(ERROR) << "CANNOT_COMMIT_ORIGIN url '" << url << "'"
<< " origin '" << origin << "'"
<< " lock '" << process->GetProcessLock().ToString() << "'";
DEBUG_ALIAS_FOR_ORIGIN(origin_debug_alias, origin);
LogCannotCommitOriginCrashKeys(url, origin, process->GetProcessLock(),
is_same_document_navigation,
navigation_request);
bad_message::ReceivedBadMessage(
process, bad_message::RFH_INVALID_ORIGIN_ON_COMMIT);
return false;
}
return true;
}
blink::mojom::ReferrerPtr GetReferrerForDidCommitParams(
NavigationRequest* request) {
if (request->DidEncounterError()) {
return request->common_params().referrer.Clone();
}
return request->GetReferrer().Clone();
}
void RenderFrameHost::LogSandboxedIframesIsolationMetrics() {
RoutingIDIsolatableSandboxedIframesSet* oopsifs =
g_routing_id_isolatable_sandboxed_iframes_set.Pointer();
base::UmaHistogramCounts1000("SiteIsolation.IsolatableSandboxedIframes",
oopsifs->size());
{
std::set<SiteInfo> sandboxed_site_infos;
std::set<url::SchemeHostPort> sandboxed_origins;
for (auto rfh_global_id : *oopsifs) {
auto* rfhi = RenderFrameHostImpl::FromID(rfh_global_id);
DCHECK(rfhi->GetLastCommittedOrigin().opaque());
sandboxed_origins.insert(
rfhi->GetLastCommittedOrigin().GetTupleOrPrecursorTupleIfOpaque());
sandboxed_site_infos.insert(rfhi->GetSiteInstance()->GetSiteInfo());
}
base::UmaHistogramCounts1000(
"SiteIsolation.IsolatableSandboxedIframes.UniqueOrigins",
sandboxed_origins.size());
base::UmaHistogramCounts1000(
"SiteIsolation.IsolatableSandboxedIframes.UniqueSites",
sandboxed_site_infos.size());
}
std::set<RenderProcessHost*> sandboxed_rphs;
for (auto rfh_global_id : *oopsifs) {
auto* rfhi = FromID(rfh_global_id);
DCHECK(rfhi);
auto* site_instance =
static_cast<SiteInstanceImpl*>(rfhi->GetSiteInstance());
DCHECK(site_instance->HasProcess());
if (site_instance->GetSiteInfo().is_sandboxed())
sandboxed_rphs.insert(site_instance->GetProcess());
}
DCHECK(SiteIsolationPolicy::AreIsolatedSandboxedIframesEnabled() ||
sandboxed_rphs.size() == 0);
base::UmaHistogramCounts1000(
"Memory.RenderProcessHost.Count.SandboxedIframeOverhead",
sandboxed_rphs.size());
}
void RenderFrameHostImpl::UpdateIsolatableSandboxedIframeTracking(
NavigationRequest* navigation_request) {
RoutingIDIsolatableSandboxedIframesSet* oopsifs =
g_routing_id_isolatable_sandboxed_iframes_set.Pointer();
GlobalRenderFrameHostId global_id = GetGlobalId();
DCHECK(policy_container_host_);
bool frame_is_isolatable =
IsSandboxed(network::mojom::WebSandboxFlags::kOrigin);
if (frame_is_isolatable) {
GURL url = GetLastCommittedURL();
if (url.IsAboutBlank() || url.is_empty()) {
frame_is_isolatable = false;
} else {
RenderFrameHost* frame_owner = GetParent();
FrameTreeNode* opener = navigation_request->frame_tree_node()->opener();
if (!frame_owner && opener)
frame_owner = opener->current_frame_host();
if (!frame_owner) {
frame_is_isolatable = false;
} else if (GetSiteInstance()->GetSiteInfo().is_sandboxed()) {
DCHECK(frame_is_isolatable);
} else if (frame_owner->GetSiteInstance() != GetSiteInstance()) {
frame_is_isolatable = false;
}
}
}
if (frame_is_isolatable)
oopsifs->insert(global_id);
else
oopsifs->erase(global_id);
}
bool RenderFrameHostImpl::DidCommitNavigationInternal(
std::unique_ptr<NavigationRequest> navigation_request,
mojom::DidCommitProvisionalLoadParamsPtr params,
mojom::DidCommitSameDocumentNavigationParamsPtr same_document_params) {
const bool is_same_document_navigation = !!same_document_params;
DCHECK_EQ(ui::PageTransitionIsMainFrame(params->transition),
!GetParent() && !IsFencedFrameRoot());
if (navigation_request &&
navigation_request->commit_params().navigation_token !=
params->navigation_token) {
LogCannotCommitUrlCrashKeys(params->url, is_same_document_navigation,
navigation_request.get());
base::debug::DumpWithoutCrashing();
}
const bool is_synchronous_about_blank_commit =
IsInitialSynchronousAboutBlankCommit(
params->url, frame_tree_node_->is_on_initial_empty_document());
if (!navigation_request && !is_synchronous_about_blank_commit &&
!is_same_document_navigation) {
LogCannotCommitUrlCrashKeys(params->url, is_same_document_navigation,
navigation_request.get());
bad_message::ReceivedBadMessage(
GetProcess(),
bad_message::RFH_NO_MATCHING_NAVIGATION_REQUEST_ON_COMMIT);
return false;
}
if (!ValidateDidCommitParams(navigation_request.get(), params.get(),
is_same_document_navigation)) {
return false;
}
if (navigation_request &&
navigation_request->common_params().url != params->url &&
is_same_document_navigation) {
same_document_navigation_requests_[navigation_request->commit_params()
.navigation_token] =
std::move(navigation_request);
}
if (!is_loading()) {
LoadingState previous_frame_tree_loading_state =
frame_tree()->LoadingTree()->GetLoadingState();
loading_state_ = is_same_document_navigation
? LoadingState::LOADING_WITHOUT_UI
: LoadingState::LOADING_UI_REQUESTED;
CHECK(owner_);
owner_->DidStartLoading(previous_frame_tree_loading_state);
}
if (navigation_request)
was_discarded_ = navigation_request->commit_params().was_discarded;
if (navigation_request) {
params->referrer = GetReferrerForDidCommitParams(navigation_request.get());
} else {
params->referrer->policy = policy_container_host_->referrer_policy();
}
if (!navigation_request) {
DCHECK(is_synchronous_about_blank_commit || is_same_document_navigation);
std::vector<GURL> redirects;
if (is_same_document_navigation &&
same_document_params->is_client_redirect) {
redirects.push_back(GetLastCommittedURL());
}
redirects.push_back(params->url);
bool started_with_transient_activation =
(is_same_document_navigation &&
same_document_params->started_with_transient_activation);
bool should_replace_current_entry =
is_same_document_navigation
? same_document_params->should_replace_current_entry
: true;
navigation_request = CreateNavigationRequestForSynchronousRendererCommit(
params->url, params->origin, params->initiator_base_url,
params->referrer.Clone(), params->transition,
should_replace_current_entry, started_with_transient_activation,
redirects, params->url, is_same_document_navigation,
same_document_params &&
same_document_params->same_document_navigation_type ==
blink::mojom::SameDocumentNavigationType::kHistoryApi);
}
DCHECK(navigation_request);
DCHECK(navigation_request->IsNavigationStarted());
VerifyThatBrowserAndRendererCalculatedDidCommitParamsMatch(
navigation_request.get(), *params, same_document_params.Clone());
navigation_request->set_transition(params->transition);
SetLastCommittedSiteInfo(navigation_request->DidEncounterError()
? UrlInfo()
: navigation_request->GetUrlInfo());
isolation_info_ = navigation_request->isolation_info_for_subresources();
bool created_new_document =
!is_same_document_navigation && !navigation_request->IsPageActivation();
bool navigated_to_new_document =
created_new_document && navigation_request->IsWaitingToCommit();
if (navigated_to_new_document) {
TRACE_EVENT("content", "DidCommitProvisionalLoad_StateResetForNewDocument",
ChromeTrackEvent::kRenderFrameHost, this);
last_committed_cross_document_navigation_id_ =
navigation_request->GetNavigationId();
if (ShouldResetDocumentAssociatedDataAtCommit()) {
DCHECK_NE(lifecycle_state(), LifecycleStateImpl::kSpeculative);
GetStoragePartition()->GetNetworkContext()->SendReportsAndRemoveSource(
GetReportingSource());
document_associated_data_.emplace(*this,
navigation_request->GetDocumentToken());
} else {
CHECK_EQ(document_associated_data_->token(),
navigation_request->GetDocumentToken());
}
const absl::optional<FencedFrameProperties>& fenced_frame_properties =
navigation_request->ComputeFencedFrameProperties();
if (fenced_frame_properties &&
(frame_tree_node()->IsFencedFrameRoot() ||
!frame_tree_node()->IsInFencedFrameTree())) {
if (fenced_frame_properties->nested_urn_config_pairs_.has_value()) {
GetPage().fenced_frame_urls_map().ImportPendingAdComponents(
fenced_frame_properties->nested_urn_config_pairs_
->GetValueIgnoringVisibility());
}
if (fenced_frame_properties->ad_auction_data_.has_value()) {
AdAuctionDocumentData::CreateForCurrentDocument(
this,
fenced_frame_properties->ad_auction_data_
->GetValueIgnoringVisibility()
.interest_group_owner,
fenced_frame_properties->ad_auction_data_
->GetValueIgnoringVisibility()
.interest_group_name);
}
}
for (auto& receiver : navigation_request->TakeCookieObservers()) {
cookie_observers_.Add(this, std::move(receiver));
}
for (auto& receiver : navigation_request->TakeTrustTokenObservers()) {
trust_token_observers_.Add(this, std::move(receiver));
}
document_used_web_otp_ = false;
const ukm::SourceId document_ukm_source_id =
navigation_request->commit_params().document_ukm_source_id;
ukm::UkmRecorder* ukm_recorder = ukm::UkmRecorder::Get();
if (navigation_request->IsInPrimaryMainFrame() &&
document_ukm_source_id != ukm::kInvalidSourceId) {
ukm_recorder->UpdateSourceURL(document_ukm_source_id, params->url);
}
RecordDocumentCreatedUkmEvent(params->origin, document_ukm_source_id,
ukm_recorder);
cookie_change_listener_ = navigation_request->TakeCookieChangeListener();
}
if (!is_same_document_navigation) {
DCHECK_EQ(navigation_request->is_overriding_user_agent() && is_main_frame(),
params->is_overriding_user_agent);
if (navigation_request->IsPrerenderedPageActivation()) {
GetPage().SetActivationStartTime(navigation_request->NavigationStart());
}
} else {
DCHECK_EQ(is_overriding_user_agent_, params->is_overriding_user_agent);
}
if (is_main_frame()) {
document_associated_data_->owned_page()->set_last_main_document_source_id(
ukm::ConvertToSourceId(navigation_request->GetNavigationId(),
ukm::SourceIdType::NAVIGATION_ID));
}
NavigationRequest* raw_navigation_request = navigation_request.get();
raw_navigation_request->frame_tree_node()->navigator().DidNavigate(
this, *params, std::move(navigation_request),
is_same_document_navigation);
committed_speculative_rfh_before_navigation_commit_ = false;
last_commit_params_ = std::move(params);
return true;
}
bool RenderFrameHostImpl::ShouldResetDocumentAssociatedDataAtCommit() const {
return lifecycle_state() != LifecycleStateImpl::kPendingCommit &&
!committed_speculative_rfh_before_navigation_commit_;
}
void RenderFrameHostImpl::DidCommitNewDocument(
const mojom::DidCommitProvisionalLoadParams& params,
NavigationRequest* navigation_request) {
DCHECK(!navigation_request->IsSameDocument());
DCHECK(!navigation_request->IsPageActivation());
const GURL& request_url = navigation_request->common_params().url;
if (request_url.IsAboutBlank() || request_url.IsAboutSrcdoc()) {
const absl::optional<::GURL>& initiator_base_url =
navigation_request->common_params().initiator_base_url;
SetInheritedBaseUrl(initiator_base_url ? initiator_base_url.value()
: GURL::EmptyGURL());
} else {
SetInheritedBaseUrl(GURL::EmptyGURL());
}
navigation_id_ = navigation_request->GetNavigationId();
credentialless_iframes_nonce_ = base::UnguessableToken::Create();
if (navigation_request->GetFencedFrameProperties()) {
frame_tree_node()->set_fenced_frame_properties(
navigation_request->GetFencedFrameProperties());
}
ResetPermissionsPolicy();
permissions_policy_header_ = params.permissions_policy_header;
auto isolation_info = GetSiteInstance()->GetWebExposedIsolationInfo();
if (isolation_info.is_isolated_application() && IsOutermostMainFrame()) {
permissions_policy_->SetHeaderPolicyForIsolatedApp(
params.permissions_policy_header);
} else {
permissions_policy_->SetHeaderPolicy(params.permissions_policy_header);
}
document_policy_ = blink::DocumentPolicy::CreateWithHeaderPolicy({
params.document_policy_header,
{},
});
has_before_unload_handler_ = false;
has_unload_handler_ = false;
has_pagehide_handler_ = false;
has_visibilitychange_handler_ = false;
has_navigate_event_handler_ = false;
DCHECK(params.embedding_token.has_value());
SetEmbeddingToken(params.embedding_token.value());
renderer_reported_bfcache_blocking_details_.clear();
browser_reported_bfcache_disabling_features_counts_.clear();
TakeNewDocumentPropertiesFromNavigation(navigation_request);
if (parent_) {
if (GetMainFrame()->GetLastCommittedOrigin().IsSameOriginWith(
params.origin)) {
policy_container_host_->set_cross_origin_opener_policy(
GetMainFrame()->cross_origin_opener_policy());
} else {
policy_container_host_->set_cross_origin_opener_policy(
network::CrossOriginOpenerPolicy());
}
}
CrossOriginOpenerPolicyAccessReportManager::InstallAccessMonitorsIfNeeded(
navigation_request->frame_tree_node());
media_device_id_salt_base_ = BrowserContext::CreateRandomMediaDeviceIDSalt();
accessibility_fatal_error_count_ = 0;
UpdateIsolatableSandboxedIframeTracking(navigation_request);
RuntimeFeatureStateDocumentData::CreateForCurrentDocument(
this, navigation_request->GetRuntimeFeatureStateContext());
}
void RenderFrameHostImpl::TakeNewDocumentPropertiesFromNavigation(
NavigationRequest* navigation_request) {
is_error_document_ = navigation_request->DidEncounterError();
std::unique_ptr<CrossOriginOpenerPolicyReporter> coop_reporter =
navigation_request->coop_status().TakeCoopReporter();
if (coop_reporter)
coop_reporter->set_reporting_source(GetReportingSource());
SetCrossOriginOpenerPolicyReporter(std::move(coop_reporter));
virtual_browsing_context_group_ =
navigation_request->coop_status().virtual_browsing_context_group();
soap_by_default_virtual_browsing_context_group_ =
navigation_request->coop_status()
.soap_by_default_virtual_browsing_context_group();
required_csp_ = navigation_request->TakeRequiredCSP();
is_fenced_frame_root_originating_from_opaque_url_ =
navigation_request
->is_target_fenced_frame_root_originating_from_opaque_url();
RuntimeFeatureStateDocumentData::CreateForCurrentDocument(
this, navigation_request->GetRuntimeFeatureStateContext());
const blink::StorageKey& provisional_storage_key =
navigation_request->commit_params().storage_key;
url::Origin origin = GetLastCommittedOrigin();
blink::StorageKey storage_key_to_commit = CalculateStorageKey(
origin, base::OptionalToPtr(provisional_storage_key.nonce()));
SetStorageKey(storage_key_to_commit);
coep_reporter_ = navigation_request->TakeCoepReporter();
if (coep_reporter_) {
coep_reporter_->set_reporting_source(GetReportingSource());
mojo::PendingRemote<blink::mojom::ReportingObserver> remote;
mojo::PendingReceiver<blink::mojom::ReportingObserver> receiver =
remote.InitWithNewPipeAndPassReceiver();
coep_reporter_->BindObserver(std::move(remote));
base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE,
base::BindOnce(&RenderFrameHostImpl::BindReportingObserver,
weak_ptr_factory_.GetWeakPtr(), std::move(receiver)));
}
is_mhtml_document_ = navigation_request->IsWaitingToCommit() &&
navigation_request->IsMhtmlOrSubframe();
is_overriding_user_agent_ =
navigation_request->is_overriding_user_agent() && is_main_frame();
renderer_url_info_.was_loaded_from_load_data_with_base_url =
navigation_request->IsLoadDataWithBaseURL();
if (loading_mem_tracker_) {
loading_mem_tracker_->Cancel();
}
loading_mem_tracker_ = navigation_request->TakePeakGpuMemoryTracker();
early_hints_manager_ = navigation_request->TakeEarlyHintsManager();
fullscreen_document_on_document_element_ready_.reset();
if (navigation_request->begin_params().is_fullscreen_requested) {
fullscreen_document_on_document_element_ready_ =
navigation_request->GetDocumentToken();
}
#ifdef OHOS_BUGFIX_CRASH
if (fullscreen_document_on_document_element_ready_ && !IsOutermostMainFrame()) {
LOG(INFO) << "fullscreen element is ready, while document is not main frame";
#ifdef OHOS_LOGGER_REPORT
LOG_FEEDBACK(INFO) << "fullscreen element is ready, while document is not main frame";
#endif
return;
}
#else
CHECK(!fullscreen_document_on_document_element_ready_ ||
IsOutermostMainFrame());
#endif
if (!navigation_request->IsWaitingToCommit()) {
return;
}
local_network_request_policy_ =
navigation_request->local_network_request_policy();
reporting_endpoints_.clear();
DCHECK(navigation_request);
if (GURL::SchemeIsCryptographic(origin.scheme()) &&
navigation_request->response() &&
navigation_request->response()->parsed_headers->reporting_endpoints) {
GetStoragePartition()->GetNetworkContext()->SetDocumentReportingEndpoints(
GetReportingSource(), origin, isolation_info_,
*(navigation_request->response()->parsed_headers->reporting_endpoints));
}
SetPolicyContainerHost(navigation_request->TakePolicyContainerHost());
if (navigation_request->response())
last_response_head_ = navigation_request->response()->Clone();
}
void RenderFrameHostImpl::OnSameDocumentCommitProcessed(
const base::UnguessableToken& navigation_token,
bool should_replace_current_entry,
blink::mojom::CommitResult result) {
auto request = same_document_navigation_requests_.find(navigation_token);
if (request == same_document_navigation_requests_.end()) {
DCHECK_EQ(result, blink::mojom::CommitResult::Ok);
return;
}
if (result == blink::mojom::CommitResult::RestartCrossDocument) {
CHECK(owner_);
owner_->RestartNavigationAsCrossDocument(std::move(request->second));
return;
}
DCHECK_EQ(result, blink::mojom::CommitResult::Aborted);
same_document_navigation_requests_.erase(navigation_token);
}
void RenderFrameHostImpl::MaybeGenerateCrashReport(
base::TerminationStatus status,
int exit_code) {
if (!last_committed_url_.SchemeIsHTTPOrHTTPS())
return;
if (!is_main_frame() && !IsCrossProcessSubframe())
return;
DCHECK(is_local_root());
std::string reason;
switch (status) {
case base::TERMINATION_STATUS_ABNORMAL_TERMINATION:
break;
case base::TERMINATION_STATUS_PROCESS_CRASHED:
if (exit_code == RESULT_CODE_HUNG)
reason = "unresponsive";
break;
case base::TERMINATION_STATUS_PROCESS_WAS_KILLED:
if (exit_code == RESULT_CODE_HUNG)
reason = "unresponsive";
else
return;
break;
case base::TERMINATION_STATUS_OOM:
#if BUILDFLAG(IS_CHROMEOS)
case base::TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM:
#endif
#if BUILDFLAG(IS_ANDROID)
case base::TERMINATION_STATUS_OOM_PROTECTED:
#endif
reason = "oom";
break;
default:
return;
}
base::Value::Dict body;
if (!reason.empty())
body.Set("reason", reason);
GetProcess()->GetStoragePartition()->GetNetworkContext()->QueueReport(
"crash", "default", last_committed_url_,
GetReportingSource(), isolation_info_.network_anonymization_key(),
absl::nullopt , std::move(body));
}
void RenderFrameHostImpl::SendCommitNavigation(
mojom::NavigationClient* navigation_client,
NavigationRequest* navigation_request,
blink::mojom::CommonNavigationParamsPtr common_params,
blink::mojom::CommitNavigationParamsPtr commit_params,
network::mojom::URLResponseHeadPtr response_head,
mojo::ScopedDataPipeConsumerHandle response_body,
network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
subresource_loader_factories,
absl::optional<std::vector<blink::mojom::TransferrableURLLoaderPtr>>
subresource_overrides,
blink::mojom::ControllerServiceWorkerInfoPtr controller,
blink::mojom::ServiceWorkerContainerInfoForClientPtr container_info,
mojo::PendingRemote<network::mojom::URLLoaderFactory>
prefetch_loader_factory,
mojo::PendingRemote<network::mojom::URLLoaderFactory> topics_loader_factory,
mojo::PendingRemote<network::mojom::URLLoaderFactory>
keep_alive_loader_factory,
mojo::PendingRemote<blink::mojom::ResourceCache> resource_cache_remote,
const absl::optional<blink::ParsedPermissionsPolicy>& permissions_policy,
blink::mojom::PolicyContainerPtr policy_container,
const blink::DocumentToken& document_token,
const base::UnguessableToken& devtools_navigation_token) {
TRACE_EVENT0("navigation", "RenderFrameHostImpl::SendCommitNavigation");
base::ElapsedTimer timer;
DCHECK_EQ(net::OK, navigation_request->GetNetErrorCode());
DCHECK(!commit_params->origin_to_commit);
IncreaseCommitNavigationCounter();
mojo::PendingRemote<blink::mojom::CodeCacheHost> code_cache_host;
mojom::CookieManagerInfoPtr cookie_manager_info;
mojom::StorageInfoPtr storage_info;
auto& code_cache_storage_key = commit_params->storage_key;
CreateCodeCacheHostWithKeys(
code_cache_host.InitWithNewPipeAndPassReceiver(),
navigation_request->isolation_info_for_subresources()
.network_isolation_key(),
code_cache_storage_key);
url::Origin origin_to_commit =
navigation_request->GetOriginToCommit().value();
if (common_params->url.SchemeIsHTTPOrHTTPS() && !origin_to_commit.opaque() &&
navigation_request->isolation_info_for_subresources()
.frame_origin()
.value() == origin_to_commit) {
cookie_manager_info = mojom::CookieManagerInfo::New();
cookie_manager_info->origin = origin_to_commit;
auto subresource_loader_factories_config =
SubresourceLoaderFactoriesConfig::ForPendingNavigation(
*navigation_request);
BindRestrictedCookieManagerWithOrigin(
cookie_manager_info->cookie_manager.InitWithNewPipeAndPassReceiver(),
navigation_request->isolation_info_for_subresources(), origin_to_commit,
subresource_loader_factories_config.cookie_setting_overrides());
if (!RenderProcessHostImpl::HasDomStorageBinderForTesting()) {
storage_info = mojom::StorageInfo::New();
auto* partition = GetStoragePartition();
int process_id = GetProcess()->GetID();
partition->OpenLocalStorageForProcess(
process_id, commit_params->storage_key,
storage_info->local_storage_area.InitWithNewPipeAndPassReceiver());
const std::string& namespace_id =
navigation_request->frame_tree_node()
->frame_tree()
.controller()
.GetSessionStorageNamespace(
GetSiteInstance()->GetStoragePartitionConfig())
->id();
partition->BindSessionStorageAreaForProcess(
process_id,
navigation_request->frame_tree_node()
->frame_tree()
.GetSessionStorageKey(commit_params->storage_key),
namespace_id,
storage_info->session_storage_area.InitWithNewPipeAndPassReceiver());
}
}
not_restored_reasons_for_testing_ =
commit_params->not_restored_reasons.Clone();
MaybeSendFencedFrameReportingBeacon(*navigation_request);
if (common_params->initiator_base_url &&
(!blink::features::IsNewBaseUrlInheritanceBehaviorEnabled() ||
(!common_params->url.IsAboutBlank() &&
!common_params->url.IsAboutSrcdoc()))) {
SCOPED_CRASH_KEY_BOOL(
"new_base_url", "new_base_url_enabled",
blink::features::IsNewBaseUrlInheritanceBehaviorEnabled());
SCOPED_CRASH_KEY_BOOL("new_base_url", "url_is_empty",
common_params->initiator_base_url->is_empty());
base::debug::DumpWithoutCrashing();
}
commit_params->commit_sent = base::TimeTicks::Now();
navigation_client->CommitNavigation(
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_factories), std::move(subresource_overrides),
std::move(controller), std::move(container_info),
std::move(prefetch_loader_factory), std::move(topics_loader_factory),
std::move(keep_alive_loader_factory), document_token,
devtools_navigation_token, permissions_policy,
std::move(policy_container), std::move(code_cache_host),
std::move(resource_cache_remote), std::move(cookie_manager_info),
std::move(storage_info),
BuildCommitNavigationCallback(navigation_request));
base::UmaHistogramTimes(
base::StrCat({"Navigation.SendCommitNavigationTime.",
IsOutermostMainFrame() ? "MainFrame" : "Subframe"}),
timer.Elapsed());
}
void RenderFrameHostImpl::SendCommitFailedNavigation(
mojom::NavigationClient* navigation_client,
NavigationRequest* navigation_request,
blink::mojom::CommonNavigationParamsPtr common_params,
blink::mojom::CommitNavigationParamsPtr commit_params,
bool has_stale_copy_in_cache,
int32_t error_code,
int32_t extended_error_code,
const absl::optional<std::string>& error_page_content,
std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
subresource_loader_factories,
const blink::DocumentToken& document_token,
blink::mojom::PolicyContainerPtr policy_container) {
DCHECK(commit_params->origin_to_commit);
DCHECK(navigation_client && navigation_request);
DCHECK_NE(GURL(), common_params->url);
DCHECK_NE(net::OK, error_code);
IncreaseCommitNavigationCounter();
navigation_client->CommitFailedNavigation(
std::move(common_params), std::move(commit_params),
has_stale_copy_in_cache, error_code, extended_error_code,
navigation_request->GetResolveErrorInfo(), error_page_content,
std::move(subresource_loader_factories), document_token,
std::move(policy_container),
GetContentClient()->browser()->GetAlternativeErrorPageOverrideInfo(
navigation_request->GetURL(), this, GetBrowserContext(), error_code),
BuildCommitFailedNavigationCallback(navigation_request));
}
void RenderFrameHostImpl::DidCommitNavigation(
NavigationRequest* committing_navigation_request,
mojom::DidCommitProvisionalLoadParamsPtr params,
mojom::DidCommitProvisionalLoadInterfaceParamsPtr interface_params) {
DCHECK(params);
DCHECK(!IsInBackForwardCache());
std::unique_ptr<NavigationRequest> request;
if (committing_navigation_request) {
committing_navigation_request->IgnoreCommitInterfaceDisconnection();
if (!MaybeInterceptCommitCallback(committing_navigation_request, ¶ms,
&interface_params)) {
return;
}
auto find_request =
navigation_requests_.find(committing_navigation_request);
CHECK(find_request != navigation_requests_.end());
request = std::move(find_request->second);
navigation_requests_.erase(committing_navigation_request);
if (request->IsNavigationStarted()) {
main_frame_request_ids_ = {params->request_id,
request->GetGlobalRequestID()};
if (deferred_main_frame_load_info_)
ResourceLoadComplete(std::move(deferred_main_frame_load_info_));
}
}
ScopedActiveURL scoped_active_url(params->url,
frame_tree()->root()->current_origin());
ScopedCommitStateResetter commit_state_resetter(this);
RenderProcessHost* process = GetProcess();
TRACE_EVENT("navigation", "RenderFrameHostImpl::DidCommitProvisionalLoad",
ChromeTrackEvent::kRenderFrameHost, this, "params", params);
if (is_waiting_for_beforeunload_completion_ &&
unload_ack_is_for_navigation_ && !GetParent()) {
base::TimeTicks approx_renderer_start_time = send_before_unload_start_time_;
ProcessBeforeUnloadCompleted(
true, true,
approx_renderer_start_time, base::TimeTicks::Now(),
false);
}
if (IsPendingDeletion())
return;
if (interface_params) {
if (broker_receiver_.is_bound()) {
broker_receiver_.reset();
}
BindBrowserInterfaceBrokerReceiver(
std::move(interface_params->browser_interface_broker_receiver));
} else {
if (!frame_tree_node_->is_on_initial_empty_document()) {
broker_receiver_.reset();
bad_message::ReceivedBadMessage(
process, bad_message::RFH_INTERFACE_PROVIDER_MISSING);
return;
}
}
if (!DidCommitNavigationInternal(std::move(request), std::move(params),
nullptr)) {
return;
}
commit_state_resetter.disable();
if (is_main_frame() && GetView()) {
RenderWidgetHostImpl::From(GetView()->GetRenderWidgetHost())->DidNavigate();
}
EnsureDescendantsAreUnloading();
}
mojom::NavigationClient::CommitNavigationCallback
RenderFrameHostImpl::BuildCommitNavigationCallback(
NavigationRequest* navigation_request) {
DCHECK(navigation_request);
return base::BindOnce(&RenderFrameHostImpl::DidCommitNavigation,
weak_ptr_factory_.GetWeakPtr(), navigation_request);
}
mojom::NavigationClient::CommitFailedNavigationCallback
RenderFrameHostImpl::BuildCommitFailedNavigationCallback(
NavigationRequest* navigation_request) {
DCHECK(navigation_request);
return base::BindOnce(&RenderFrameHostImpl::DidCommitNavigation,
weak_ptr_factory_.GetWeakPtr(), navigation_request);
}
void RenderFrameHostImpl::SendBeforeUnload(
bool is_reload,
base::WeakPtr<RenderFrameHostImpl> rfh,
bool for_legacy) {
auto before_unload_closure = base::BindOnce(
[](base::WeakPtr<RenderFrameHostImpl> impl, bool for_legacy, bool proceed,
base::TimeTicks renderer_before_unload_start_time,
base::TimeTicks renderer_before_unload_end_time) {
if (!impl)
return;
impl->ProcessBeforeUnloadCompleted(
proceed, false,
renderer_before_unload_start_time, renderer_before_unload_end_time,
for_legacy);
},
rfh, for_legacy);
if (for_legacy) {
if (frame_tree_node_->navigation_request()) {
base::UmaHistogramTimes(
"Navigation.NavigationStartToBeforeUnloadForLegacy",
base::TimeTicks::Now() - frame_tree_node_->navigation_request()
->common_params()
.navigation_start);
}
base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE,
base::BindOnce(
[](blink::mojom::LocalFrame::BeforeUnloadCallback callback,
base::TimeTicks start_time, base::TimeTicks end_time) {
std::move(callback).Run(true, start_time, end_time);
},
std::move(before_unload_closure), send_before_unload_start_time_,
base::TimeTicks::Now()));
return;
}
if (base::FeatureList::IsEnabled(features::kHighPriorityBeforeUnload)) {
rfh->GetHighPriorityLocalFrame()->DispatchBeforeUnload(
is_reload, std::move(before_unload_closure));
} else {
rfh->GetAssociatedLocalFrame()->BeforeUnload(
is_reload, std::move(before_unload_closure));
}
}
void RenderFrameHostImpl::AddServiceWorkerContainerHost(
const std::string& uuid,
base::WeakPtr<content::ServiceWorkerContainerHost> host) {
if (IsInBackForwardCache()) {
EvictFromBackForwardCacheWithReason(
BackForwardCacheMetrics::NotRestoredReason::
kEnteredBackForwardCacheBeforeServiceWorkerHostAdded);
}
DCHECK(!base::Contains(service_worker_container_hosts_, uuid));
last_committed_service_worker_host_ = host;
service_worker_container_hosts_[uuid] = std::move(host);
}
void RenderFrameHostImpl::RemoveServiceWorkerContainerHost(
const std::string& uuid) {
DCHECK(!service_worker_container_hosts_.empty());
DCHECK(base::Contains(service_worker_container_hosts_, uuid));
service_worker_container_hosts_.erase(uuid);
}
base::WeakPtr<ServiceWorkerContainerHost>
RenderFrameHostImpl::GetLastCommittedServiceWorkerHost() {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
return last_committed_service_worker_host_;
}
bool RenderFrameHostImpl::MaybeInterceptCommitCallback(
NavigationRequest* navigation_request,
mojom::DidCommitProvisionalLoadParamsPtr* params,
mojom::DidCommitProvisionalLoadInterfaceParamsPtr* interface_params) {
if (commit_callback_interceptor_) {
return commit_callback_interceptor_->WillProcessDidCommitNavigation(
navigation_request, params, interface_params);
}
return true;
}
void RenderFrameHostImpl::PostMessageEvent(
const absl::optional<blink::RemoteFrameToken>& source_token,
const std::u16string& source_origin,
const std::u16string& target_origin,
blink::TransferableMessage message) {
DCHECK(is_render_frame_created());
if (message.delegated_capability != blink::mojom::DelegatedCapability::kNone)
ReceivedDelegatedCapability(message.delegated_capability);
message.parent_task_id = absl::nullopt;
GetAssociatedLocalFrame()->PostMessageEvent(
source_token, source_origin, target_origin, std::move(message));
}
bool RenderFrameHostImpl::IsTestRenderFrameHost() const {
return false;
}
scoped_refptr<PrefetchedSignedExchangeCache>
RenderFrameHostImpl::EnsurePrefetchedSignedExchangeCache() {
if (!prefetched_signed_exchange_cache_) {
prefetched_signed_exchange_cache_ =
base::MakeRefCounted<PrefetchedSignedExchangeCache>();
}
return prefetched_signed_exchange_cache_;
}
void RenderFrameHostImpl::ClearPrefetchedSignedExchangeCache() {
if (prefetched_signed_exchange_cache_)
prefetched_signed_exchange_cache_->Clear();
}
RenderWidgetHostImpl* RenderFrameHostImpl::GetLocalRenderWidgetHost() const {
if (is_main_frame())
return render_view_host_->GetWidget();
else
return owned_render_widget_host_.get();
}
void RenderFrameHostImpl::EnsureDescendantsAreUnloading() {
std::vector<FrameTreeNode*> frame_to_remove;
std::vector<RenderFrameHostImpl*> rfh_to_be_checked = {this};
while (!rfh_to_be_checked.empty()) {
RenderFrameHostImpl* document = rfh_to_be_checked.back();
rfh_to_be_checked.pop_back();
for (auto& iframe : document->children_) {
if (iframe->current_frame_host()->IsPendingDeletion()) {
rfh_to_be_checked.push_back(iframe->current_frame_host());
} else {
frame_to_remove.push_back(iframe.get());
}
}
}
for (FrameTreeNode* child : frame_to_remove) {
child->parent()->RemoveChild(child);
}
}
void RenderFrameHostImpl::AddMessageToConsoleImpl(
blink::mojom::ConsoleMessageLevel level,
const std::string& message,
bool discard_duplicates) {
GetAssociatedLocalFrame()->AddMessageToConsole(level, message,
discard_duplicates);
}
void RenderFrameHostImpl::LogCannotCommitUrlCrashKeys(
const GURL& url,
bool is_same_document_navigation,
NavigationRequest* navigation_request) {
LogRendererKillCrashKeys(GetSiteInstance()->GetSiteInfo());
auto bool_to_crash_key = [](bool b) { return b ? "true" : "false"; };
static auto* const navigation_url_key = base::debug::AllocateCrashKeyString(
"navigation_url", base::debug::CrashKeySize::Size256);
base::debug::SetCrashKeyString(navigation_url_key, url.spec());
static auto* const is_same_document_key = base::debug::AllocateCrashKeyString(
"is_same_document", base::debug::CrashKeySize::Size32);
base::debug::SetCrashKeyString(
is_same_document_key, bool_to_crash_key(is_same_document_navigation));
static auto* const is_main_frame_key = base::debug::AllocateCrashKeyString(
"is_main_frame", base::debug::CrashKeySize::Size32);
base::debug::SetCrashKeyString(is_main_frame_key,
bool_to_crash_key(is_main_frame()));
static auto* const is_outermost_frame_key =
base::debug::AllocateCrashKeyString("is_outermost_frame",
base::debug::CrashKeySize::Size32);
base::debug::SetCrashKeyString(is_outermost_frame_key,
bool_to_crash_key(IsOutermostMainFrame()));
static auto* const is_cross_process_subframe_key =
base::debug::AllocateCrashKeyString("is_cross_process_subframe",
base::debug::CrashKeySize::Size32);
base::debug::SetCrashKeyString(is_cross_process_subframe_key,
bool_to_crash_key(IsCrossProcessSubframe()));
static auto* const is_local_root_key = base::debug::AllocateCrashKeyString(
"is_local_root", base::debug::CrashKeySize::Size32);
base::debug::SetCrashKeyString(is_local_root_key,
bool_to_crash_key(is_local_root()));
static auto* const site_lock_key = base::debug::AllocateCrashKeyString(
"site_lock", base::debug::CrashKeySize::Size256);
base::debug::SetCrashKeyString(
site_lock_key,
ProcessLock::FromSiteInfo(GetSiteInstance()->GetSiteInfo()).ToString());
static auto* const process_lock_key = base::debug::AllocateCrashKeyString(
"process_lock", base::debug::CrashKeySize::Size256);
base::debug::SetCrashKeyString(process_lock_key,
GetProcess()->GetProcessLock().ToString());
if (!GetSiteInstance()->IsDefaultSiteInstance()) {
static auto* const original_url_origin_key =
base::debug::AllocateCrashKeyString("original_url_origin",
base::debug::CrashKeySize::Size256);
base::debug::SetCrashKeyString(
original_url_origin_key,
GetSiteInstance()->original_url().DeprecatedGetOriginAsURL().spec());
}
static auto* const is_mhtml_document_key =
base::debug::AllocateCrashKeyString("is_mhtml_document",
base::debug::CrashKeySize::Size32);
base::debug::SetCrashKeyString(is_mhtml_document_key,
bool_to_crash_key(is_mhtml_document()));
static auto* const last_committed_url_origin_key =
base::debug::AllocateCrashKeyString("last_committed_url_origin",
base::debug::CrashKeySize::Size256);
base::debug::SetCrashKeyString(
last_committed_url_origin_key,
GetLastCommittedURL().DeprecatedGetOriginAsURL().spec());
static auto* const last_successful_url_origin_key =
base::debug::AllocateCrashKeyString("last_successful_url_origin",
base::debug::CrashKeySize::Size256);
base::debug::SetCrashKeyString(
last_successful_url_origin_key,
last_successful_url().DeprecatedGetOriginAsURL().spec());
if (navigation_request && navigation_request->IsNavigationStarted()) {
static auto* const is_renderer_initiated_key =
base::debug::AllocateCrashKeyString("is_renderer_initiated",
base::debug::CrashKeySize::Size32);
base::debug::SetCrashKeyString(
is_renderer_initiated_key,
bool_to_crash_key(navigation_request->IsRendererInitiated()));
static auto* const is_server_redirect_key =
base::debug::AllocateCrashKeyString("is_server_redirect",
base::debug::CrashKeySize::Size32);
base::debug::SetCrashKeyString(
is_server_redirect_key,
bool_to_crash_key(navigation_request->WasServerRedirect()));
static auto* const is_form_submission_key =
base::debug::AllocateCrashKeyString("is_form_submission",
base::debug::CrashKeySize::Size32);
base::debug::SetCrashKeyString(
is_form_submission_key,
bool_to_crash_key(navigation_request->IsFormSubmission()));
static auto* const is_error_page_key = base::debug::AllocateCrashKeyString(
"is_error_page", base::debug::CrashKeySize::Size32);
base::debug::SetCrashKeyString(
is_error_page_key,
bool_to_crash_key(navigation_request->IsErrorPage()));
static auto* const from_begin_navigation_key =
base::debug::AllocateCrashKeyString("from_begin_navigation",
base::debug::CrashKeySize::Size32);
base::debug::SetCrashKeyString(
from_begin_navigation_key,
bool_to_crash_key(navigation_request->from_begin_navigation()));
static auto* const net_error_key = base::debug::AllocateCrashKeyString(
"net_error", base::debug::CrashKeySize::Size32);
base::debug::SetCrashKeyString(
net_error_key,
base::NumberToString(navigation_request->GetNetErrorCode()));
static auto* const initiator_origin_key =
base::debug::AllocateCrashKeyString("initiator_origin",
base::debug::CrashKeySize::Size64);
base::debug::SetCrashKeyString(
initiator_origin_key,
navigation_request->GetInitiatorOrigin()
? navigation_request->GetInitiatorOrigin()->GetDebugString()
: "none");
static auto* const starting_site_instance_key =
base::debug::AllocateCrashKeyString("starting_site_instance",
base::debug::CrashKeySize::Size256);
base::debug::SetCrashKeyString(starting_site_instance_key,
navigation_request->GetStartingSiteInstance()
->GetSiteInfo()
.GetDebugString());
BrowsingContextGroupSwap ignored_bcg_swap_info =
BrowsingContextGroupSwap::CreateDefault();
scoped_refptr<SiteInstance> dest_instance =
navigation_request->frame_tree_node()
->render_manager()
->GetSiteInstanceForNavigationRequest(navigation_request,
&ignored_bcg_swap_info);
static auto* const does_recomputed_site_instance_match_key =
base::debug::AllocateCrashKeyString(
"does_recomputed_site_instance_match",
base::debug::CrashKeySize::Size32);
base::debug::SetCrashKeyString(
does_recomputed_site_instance_match_key,
bool_to_crash_key(dest_instance == GetSiteInstance()));
}
}
int64_t CalculatePostID(
const std::string& method,
const scoped_refptr<network::ResourceRequestBody>& request_body,
int64_t last_post_id,
bool is_same_document) {
if (method != "POST")
return -1;
if (is_same_document)
return last_post_id;
return request_body ? request_body->identifier() : -1;
}
const std::string CalculateMethod(
const std::string& nav_request_method,
const std::string& last_http_method,
bool is_same_document,
bool is_same_document_history_api_navigation) {
DCHECK(is_same_document || !is_same_document_history_api_navigation);
if (is_same_document_history_api_navigation)
return "GET";
if (is_same_document)
return last_http_method;
return nav_request_method;
}
int CalculateHTTPStatusCode(NavigationRequest* request,
int last_http_status_code) {
if (request->IsSameDocument() || request->IsPrerenderedPageActivation())
return last_http_status_code;
if (request->IsServedFromBackForwardCache())
return 200;
const int request_response_code = request->commit_params().http_response_code;
if (request_response_code == -1)
return 0;
return request_response_code;
}
RendererLoadType CalculateRendererLoadType(NavigationRequest* request,
bool should_replace_current_entry,
const GURL& previous_document_url) {
const bool is_history =
NavigationTypeUtils::IsHistory(request->common_params().navigation_type);
const bool is_reload =
NavigationTypeUtils::IsReload(request->common_params().navigation_type);
const bool has_valid_page_state = blink::PageState::CreateFromEncodedData(
request->commit_params().page_state)
.IsValid();
const bool is_error_document = request->DidEncounterError();
bool will_be_classified_as_back_forward_navigation = false;
if (is_error_document) {
will_be_classified_as_back_forward_navigation = has_valid_page_state;
} else {
will_be_classified_as_back_forward_navigation = is_history;
}
if (will_be_classified_as_back_forward_navigation) {
return RendererLoadType::kBackForward;
}
if (!is_error_document && is_reload) {
return RendererLoadType::kReload;
}
return should_replace_current_entry ? RendererLoadType::kReplaceCurrentItem
: RendererLoadType::kStandard;
}
bool CalculateDidCreateNewEntry(NavigationRequest* request,
bool should_replace_current_entry,
RendererLoadType renderer_load_type) {
if (renderer_load_type == RendererLoadType::kStandard)
return true;
if (renderer_load_type == RendererLoadType::kBackForward)
return false;
return request->IsInMainFrame() && should_replace_current_entry &&
!request->IsSameDocument();
}
ui::PageTransition CalculateTransition(
NavigationRequest* request,
RendererLoadType renderer_load_type,
const mojom::DidCommitProvisionalLoadParams& params,
bool is_in_fenced_frame_tree) {
if (is_in_fenced_frame_tree) {
ui::PageTransition transition = ui::PAGE_TRANSITION_AUTO_SUBFRAME;
if (request->IsInMainFrame() && !request->DidEncounterError() &&
request->common_params().transition &
ui::PAGE_TRANSITION_CLIENT_REDIRECT) {
transition =
ui::PageTransitionFromInt(ui::PAGE_TRANSITION_AUTO_SUBFRAME |
ui::PAGE_TRANSITION_CLIENT_REDIRECT);
}
return transition;
}
if (request->IsSameDocument())
return params.transition;
if (request->IsInMainFrame()) {
ui::PageTransition supplied_transition =
ui::PageTransitionFromInt(request->common_params().transition);
if (ui::PageTransitionCoreTypeIs(supplied_transition,
ui::PAGE_TRANSITION_LINK) &&
request->common_params().post_data) {
return ui::PAGE_TRANSITION_FORM_SUBMIT;
}
return supplied_transition;
}
if (renderer_load_type == RendererLoadType::kStandard)
return ui::PAGE_TRANSITION_MANUAL_SUBFRAME;
return ui::PAGE_TRANSITION_AUTO_SUBFRAME;
}
GURL CalculateLoadingURL(
NavigationRequest* request,
const mojom::DidCommitProvisionalLoadParams& params,
const RenderFrameHostImpl::RendererURLInfo& last_renderer_url_info,
bool last_document_is_error_document,
const GURL& last_committed_url) {
if (params.url.IsAboutBlank() && params.url.ref_piece() == "blocked") {
return params.url;
}
if (!request->common_params().url.is_valid()) {
return GURL(url::kAboutBlankURL);
}
if (request->IsSameDocument() &&
(last_document_is_error_document ||
last_renderer_url_info.was_loaded_from_load_data_with_base_url)) {
return last_committed_url;
}
return request->common_params().url;
}
bool ShouldVerify(const std::string& param) {
#if DCHECK_IS_ON()
return true;
#else
if (param != "should_replace_current_entry" &&
param != "url_is_unreachable") {
return true;
}
return GetFieldTrialParamByFeatureAsBool(features::kVerifyDidCommitParams,
param, false);
#endif
}
void LogVerifyDidCommitParamsDifference(
VerifyDidCommitParamsDifference difference) {
UMA_HISTOGRAM_ENUMERATION("Navigation.VerifyDidCommitParams", difference);
}
std::string GetURLTypeForCrashKey(const GURL& url) {
if (url == kUnreachableWebDataURL)
return "error";
if (url == kBlockedURL)
return "blocked";
if (url.IsAboutBlank())
return "about:blank";
if (url.IsAboutSrcdoc())
return "about:srcdoc";
if (url.is_empty())
return "empty";
if (!url.is_valid())
return "invalid";
return url.scheme();
}
std::string GetURLRelationForCrashKey(
const GURL& actual_url,
const GURL& predicted_url,
const blink::mojom::CommonNavigationParams& common_params,
const GURL& last_committed_url,
const RenderFrameHostImpl::RendererURLInfo& renderer_url_info) {
if (actual_url == predicted_url)
return "as predicted";
if (actual_url == last_committed_url)
return "last committed";
if (actual_url == common_params.url)
return "common params URL";
if (actual_url == common_params.base_url_for_data_url)
return "base URL";
if (actual_url == renderer_url_info.last_document_url)
return "last document URL";
return "unknown";
}
void RenderFrameHostImpl::
VerifyThatBrowserAndRendererCalculatedDidCommitParamsMatch(
NavigationRequest* request,
const mojom::DidCommitProvisionalLoadParams& params,
const mojom::DidCommitSameDocumentNavigationParamsPtr
same_document_params) {
#if !DCHECK_IS_ON()
if (!base::FeatureList::IsEnabled(features::kVerifyDidCommitParams))
return;
#endif
const bool is_error_document =
(request->DidEncounterError() ||
(is_error_document_ && request->IsSameDocument()));
const bool browser_url_is_unreachable = is_error_document;
const bool is_same_document_navigation = !!same_document_params;
const bool is_same_document_history_api_navigation =
same_document_params &&
same_document_params->same_document_navigation_type ==
blink::mojom::SameDocumentNavigationType::kHistoryApi;
DCHECK_EQ(is_same_document_navigation, request->IsSameDocument());
const int64_t browser_post_id =
CalculatePostID(params.method, request->common_params().post_data,
last_post_id_, is_same_document_navigation);
const std::string& browser_method = CalculateMethod(
request->common_params().method, last_http_method_,
is_same_document_navigation, is_same_document_history_api_navigation);
const bool browser_is_overriding_user_agent =
is_same_document_navigation
? is_overriding_user_agent_
: (request->commit_params().is_overriding_user_agent &&
request->frame_tree_node()->IsMainFrame());
const int browser_http_status_code =
CalculateHTTPStatusCode(request, last_http_status_code_);
const bool browser_should_update_history =
!browser_url_is_unreachable && browser_http_status_code != 404;
const bool should_replace_current_entry =
request->common_params().should_replace_current_entry;
const GURL browser_url =
CalculateLoadingURL(request, params, renderer_url_info_,
is_error_document_, last_committed_url_);
const RendererLoadType renderer_load_type =
CalculateRendererLoadType(request, should_replace_current_entry,
renderer_url_info_.last_document_url);
const bool browser_did_create_new_entry =
request->is_synchronous_renderer_commit()
? params.did_create_new_entry
: CalculateDidCreateNewEntry(request, should_replace_current_entry,
renderer_load_type);
const ui::PageTransition browser_transition = CalculateTransition(
request, renderer_load_type, params, IsNestedWithinFencedFrame());
const bool browser_history_list_was_cleared =
request->commit_params().should_clear_history_list;
const bool everything_except_origin_matches =
((!ShouldVerify("method") || browser_method == params.method) &&
(!ShouldVerify("url_is_unreachable") ||
browser_url_is_unreachable == params.url_is_unreachable) &&
(!ShouldVerify("post_id") || browser_post_id == params.post_id) &&
(!ShouldVerify("is_overriding_user_agent") ||
browser_is_overriding_user_agent == params.is_overriding_user_agent) &&
(!ShouldVerify("http_status_code") ||
browser_http_status_code == params.http_status_code) &&
(!ShouldVerify("should_update_history") ||
browser_should_update_history == params.should_update_history) &&
(!ShouldVerify("url") || browser_url == params.url) &&
(!ShouldVerify("did_create_new_entry") ||
browser_did_create_new_entry == params.did_create_new_entry) &&
(!ShouldVerify("transition") ||
ui::PageTransitionTypeIncludingQualifiersIs(browser_transition,
params.transition)) &&
(!ShouldVerify("history_list_was_cleared") ||
browser_history_list_was_cleared == params.history_list_was_cleared));
if (everything_except_origin_matches &&
(!ShouldVerify("origin") ||
request->state() < NavigationRequest::WILL_PROCESS_RESPONSE ||
request->GetOriginToCommit() == params.origin)) {
return;
}
SCOPED_CRASH_KEY_BOOL(
"VerifyDidCommit", "prev_ldwb",
renderer_url_info_.was_loaded_from_load_data_with_base_url);
SCOPED_CRASH_KEY_STRING32(
"VerifyDidCommit", "base_url_fdu_type",
GetURLTypeForCrashKey(request->common_params().base_url_for_data_url));
#if BUILDFLAG(IS_ANDROID)
SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "data_url_empty",
request->commit_params().data_url_as_string.empty());
#endif
SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "intended_as_new_entry",
request->commit_params().intended_as_new_entry);
SCOPED_CRASH_KEY_STRING32("VerifyDidCommit", "method_browser",
browser_method);
SCOPED_CRASH_KEY_STRING32("VerifyDidCommit", "method_renderer",
params.method);
SCOPED_CRASH_KEY_STRING32("VerifyDidCommit", "original_method",
request->commit_params().original_method);
SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "method_post_browser",
browser_method == "POST");
SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "method_post_renderer",
params.method == "POST");
SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "original_method_post",
request->commit_params().original_method == "POST");
SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "unreachable_browser",
browser_url_is_unreachable);
SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "unreachable_renderer",
params.url_is_unreachable);
SCOPED_CRASH_KEY_NUMBER("VerifyDidCommit", "post_id_browser",
browser_post_id);
SCOPED_CRASH_KEY_NUMBER("VerifyDidCommit", "post_id_renderer",
params.post_id);
SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "post_id_matches",
browser_post_id == params.post_id);
SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "post_id_-1_browser",
browser_post_id == -1);
SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "post_id_-1_renderer",
params.post_id == -1);
SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "override_ua_browser",
browser_is_overriding_user_agent);
SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "override_ua_renderer",
params.is_overriding_user_agent);
SCOPED_CRASH_KEY_NUMBER("VerifyDidCommit", "code_browser",
browser_http_status_code);
SCOPED_CRASH_KEY_NUMBER("VerifyDidCommit", "code_renderer",
params.http_status_code);
SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "suh_browser",
browser_should_update_history);
SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "suh_renderer",
params.should_update_history);
SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "gesture",
request->common_params().has_user_gesture);
SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "replace",
should_replace_current_entry);
SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "create_browser",
browser_did_create_new_entry);
SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "create_renderer",
params.did_create_new_entry);
SCOPED_CRASH_KEY_NUMBER("VerifyDidCommit", "transition_browser",
browser_transition);
SCOPED_CRASH_KEY_NUMBER("VerifyDidCommit", "transition_renderer",
params.transition);
SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "cleared_browser",
browser_history_list_was_cleared);
SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "cleared_renderer",
params.history_list_was_cleared);
SCOPED_CRASH_KEY_STRING256("VerifyDidCommit", "url_browser",
browser_url.possibly_invalid_spec());
SCOPED_CRASH_KEY_STRING256("VerifyDidCommit", "url_renderer",
params.url.possibly_invalid_spec());
SCOPED_CRASH_KEY_STRING32(
"VerifyDidCommit", "url_relation",
GetURLRelationForCrashKey(params.url, browser_url,
request->common_params(), GetLastCommittedURL(),
renderer_url_info_));
SCOPED_CRASH_KEY_STRING32("VerifyDidCommit", "url_browser_type",
GetURLTypeForCrashKey(browser_url));
SCOPED_CRASH_KEY_STRING32("VerifyDidCommit", "url_renderer_type",
GetURLTypeForCrashKey(params.url));
SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "is_same_document",
is_same_document_navigation);
SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "is_history_api",
is_same_document_history_api_navigation);
SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "renderer_initiated",
request->IsRendererInitiated());
SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "is_subframe",
!request->frame_tree_node()->IsMainFrame());
SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "is_form_submission",
request->IsFormSubmission());
SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "is_error_document",
is_error_document);
SCOPED_CRASH_KEY_NUMBER("VerifyDidCommit", "net_error",
request->GetNetErrorCode());
SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "is_server_redirect",
request->WasServerRedirect());
SCOPED_CRASH_KEY_NUMBER("VerifyDidCommit", "redirects_size",
request->GetRedirectChain().size());
SCOPED_CRASH_KEY_NUMBER("VerifyDidCommit", "entry_offset",
request->GetNavigationEntryOffset());
SCOPED_CRASH_KEY_NUMBER(
"VerifyDidCommit", "entry_count",
request->frame_tree_node()->frame_tree().controller().GetEntryCount());
SCOPED_CRASH_KEY_NUMBER("VerifyDidCommit", "last_committed_index",
request->frame_tree_node()
->frame_tree()
.controller()
.GetLastCommittedEntryIndex());
SCOPED_CRASH_KEY_BOOL(
"VerifyDidCommit", "is_reload",
NavigationTypeUtils::IsReload(request->common_params().navigation_type));
SCOPED_CRASH_KEY_BOOL(
"VerifyDidCommit", "is_restore",
NavigationTypeUtils::IsRestore(request->common_params().navigation_type));
SCOPED_CRASH_KEY_BOOL(
"VerifyDidCommit", "is_history",
NavigationTypeUtils::IsHistory(request->common_params().navigation_type));
SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "has_valid_page_state",
blink::PageState::CreateFromEncodedData(
request->commit_params().page_state)
.IsValid());
SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "has_gesture",
request->HasUserGesture());
SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "was_click",
request->WasInitiatedByLinkClick());
SCOPED_CRASH_KEY_STRING256("VerifyDidCommit", "original_req_url",
request->commit_params().original_url.spec());
SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "original_same_doc",
request->commit_params().original_url.EqualsIgnoringRef(
GetLastCommittedURL()));
SCOPED_CRASH_KEY_BOOL(
"VerifyDidCommit", "on_initial_empty_doc",
request->frame_tree_node()->is_on_initial_empty_document());
SCOPED_CRASH_KEY_STRING256("VerifyDidCommit", "last_committed_url",
GetLastCommittedURL().spec());
SCOPED_CRASH_KEY_STRING256("VerifyDidCommit", "last_document_url",
renderer_url_info_.last_document_url.spec());
SCOPED_CRASH_KEY_STRING32("VerifyDidCommit", "last_url_type",
GetURLTypeForCrashKey(GetLastCommittedURL()));
SCOPED_CRASH_KEY_STRING256("VerifyDidCommit", "last_method",
last_http_method_);
SCOPED_CRASH_KEY_NUMBER("VerifyDidCommit", "last_code",
last_http_status_code_);
bool has_original_url =
GetSiteInstance() && !GetSiteInstance()->IsDefaultSiteInstance();
SCOPED_CRASH_KEY_STRING256(
"VerifyDidCommit", "si_url",
has_original_url
? GetSiteInstance()->original_url().possibly_invalid_spec()
: "");
SCOPED_CRASH_KEY_BOOL("VerifyDidCommit", "has_si_url", has_original_url);
DCHECK_EQ(browser_method, params.method);
DCHECK_EQ(browser_url_is_unreachable, params.url_is_unreachable);
DCHECK_EQ(browser_post_id, params.post_id);
DCHECK_EQ(browser_is_overriding_user_agent, params.is_overriding_user_agent);
DCHECK_EQ(browser_http_status_code, params.http_status_code);
DCHECK_EQ(browser_should_update_history, params.should_update_history);
DCHECK_EQ(browser_url, params.url);
DCHECK_EQ(browser_did_create_new_entry, params.did_create_new_entry);
DCHECK(ui::PageTransitionTypeIncludingQualifiersIs(browser_transition,
params.transition));
DCHECK_EQ(browser_history_list_was_cleared, params.history_list_was_cleared);
if (browser_method != params.method) {
LogVerifyDidCommitParamsDifference(
VerifyDidCommitParamsDifference::kMethod);
}
if (browser_url_is_unreachable != params.url_is_unreachable) {
LogVerifyDidCommitParamsDifference(
VerifyDidCommitParamsDifference::kURLIsUnreachable);
}
if (browser_post_id != params.post_id) {
LogVerifyDidCommitParamsDifference(
VerifyDidCommitParamsDifference::kPostID);
}
if (browser_is_overriding_user_agent != params.is_overriding_user_agent) {
LogVerifyDidCommitParamsDifference(
VerifyDidCommitParamsDifference::kIsOverridingUserAgent);
}
if (browser_http_status_code != params.http_status_code) {
LogVerifyDidCommitParamsDifference(
VerifyDidCommitParamsDifference::kHTTPStatusCode);
}
if (browser_should_update_history != params.should_update_history) {
LogVerifyDidCommitParamsDifference(
VerifyDidCommitParamsDifference::kShouldUpdateHistory);
}
if (browser_url != params.url) {
LogVerifyDidCommitParamsDifference(VerifyDidCommitParamsDifference::kURL);
}
if (browser_did_create_new_entry != params.did_create_new_entry) {
LogVerifyDidCommitParamsDifference(
VerifyDidCommitParamsDifference::kDidCreateNewEntry);
}
if (!ui::PageTransitionTypeIncludingQualifiersIs(browser_transition,
params.transition)) {
LogVerifyDidCommitParamsDifference(
VerifyDidCommitParamsDifference::kTransition);
}
if (browser_history_list_was_cleared != params.history_list_was_cleared) {
LogVerifyDidCommitParamsDifference(
VerifyDidCommitParamsDifference::kHistoryListWasCleared);
}
if (!VerifyThatBrowserAndRendererCalculatedOriginsToCommitMatch(request,
params)) {
LogVerifyDidCommitParamsDifference(
VerifyDidCommitParamsDifference::kOrigin);
}
if (!everything_except_origin_matches) {
#if !BUILDFLAG(IS_ANDROID)
base::debug::DumpWithoutCrashing();
#endif
}
}
BackForwardCacheImpl& RenderFrameHostImpl::GetBackForwardCache() {
return GetOutermostMainFrame()
->frame_tree()
->controller()
.GetBackForwardCache();
}
FrameTreeNode* RenderFrameHostImpl::GetFrameTreeNodeForUnload() {
DCHECK(IsPendingDeletion());
return frame_tree_node_;
}
void RenderFrameHostImpl::MaybeEvictFromBackForwardCache() {
if (!IsInBackForwardCache())
return;
RenderFrameHostImpl* outermost_main_frame = GetOutermostMainFrame();
BackForwardCacheCanStoreDocumentResultWithTree bfcache_eligibility =
GetBackForwardCache().GetCurrentBackForwardCacheEligibility(
outermost_main_frame);
TRACE_EVENT("navigation",
"RenderFrameHostImpl::MaybeEvictFromBackForwardCache",
"render_frame_host", this, "bfcache_eligibility",
bfcache_eligibility.flattened_reasons.ToString());
if (bfcache_eligibility.CanStore())
return;
EvictFromBackForwardCacheWithFlattenedAndTreeReasons(bfcache_eligibility);
}
void RenderFrameHostImpl::LogCannotCommitOriginCrashKeys(
const GURL& url,
const url::Origin& origin,
const ProcessLock& process_lock,
bool is_same_document_navigation,
NavigationRequest* navigation_request) {
LogRendererKillCrashKeys(GetSiteInstance()->GetSiteInfo());
auto bool_to_crash_key = [](bool b) { return b ? "true" : "false"; };
static auto* const target_url_key = base::debug::AllocateCrashKeyString(
"target_url", base::debug::CrashKeySize::Size256);
base::debug::SetCrashKeyString(target_url_key, url.spec());
static auto* const target_origin_key = base::debug::AllocateCrashKeyString(
"target_origin", base::debug::CrashKeySize::Size256);
base::debug::SetCrashKeyString(target_origin_key, origin.GetDebugString());
const url::Origin url_origin = url::Origin::Resolve(url, origin);
const auto target_url_origin_tuple_or_precursor_tuple =
url_origin.GetTupleOrPrecursorTupleIfOpaque();
static auto* const target_url_origin_tuple_key =
base::debug::AllocateCrashKeyString("target_url_origin_tuple",
base::debug::CrashKeySize::Size256);
base::debug::SetCrashKeyString(
target_url_origin_tuple_key,
target_url_origin_tuple_or_precursor_tuple.Serialize());
const auto target_origin_tuple_or_precursor_tuple =
origin.GetTupleOrPrecursorTupleIfOpaque();
static auto* const target_origin_tuple_key =
base::debug::AllocateCrashKeyString("target_origin_tuple",
base::debug::CrashKeySize::Size256);
base::debug::SetCrashKeyString(
target_origin_tuple_key,
target_origin_tuple_or_precursor_tuple.Serialize());
static auto* const last_committed_url_key =
base::debug::AllocateCrashKeyString("last_committed_url",
base::debug::CrashKeySize::Size256);
base::debug::SetCrashKeyString(last_committed_url_key,
GetLastCommittedURL().spec());
static auto* const last_committed_origin_key =
base::debug::AllocateCrashKeyString("last_committed_origin",
base::debug::CrashKeySize::Size256);
base::debug::SetCrashKeyString(last_committed_origin_key,
GetLastCommittedOrigin().GetDebugString());
static auto* const process_lock_key = base::debug::AllocateCrashKeyString(
"process_lock", base::debug::CrashKeySize::Size256);
base::debug::SetCrashKeyString(process_lock_key, process_lock.ToString());
static auto* const is_same_document_key = base::debug::AllocateCrashKeyString(
"is_same_document", base::debug::CrashKeySize::Size32);
base::debug::SetCrashKeyString(
is_same_document_key, bool_to_crash_key(is_same_document_navigation));
static auto* const is_subframe_key = base::debug::AllocateCrashKeyString(
"is_subframe", base::debug::CrashKeySize::Size32);
base::debug::SetCrashKeyString(is_subframe_key,
bool_to_crash_key(GetMainFrame() != this));
static auto* const lifecycle_state_key = base::debug::AllocateCrashKeyString(
"lifecycle_state", base::debug::CrashKeySize::Size32);
base::debug::SetCrashKeyString(lifecycle_state_key,
LifecycleStateImplToString(lifecycle_state()));
static auto* const is_active_key = base::debug::AllocateCrashKeyString(
"is_active", base::debug::CrashKeySize::Size32);
base::debug::SetCrashKeyString(is_active_key, bool_to_crash_key(IsActive()));
static auto* const is_cross_process_subframe_key =
base::debug::AllocateCrashKeyString("is_cross_process_subframe",
base::debug::CrashKeySize::Size32);
base::debug::SetCrashKeyString(is_cross_process_subframe_key,
bool_to_crash_key(IsCrossProcessSubframe()));
static auto* const is_local_root_key = base::debug::AllocateCrashKeyString(
"is_local_root", base::debug::CrashKeySize::Size32);
base::debug::SetCrashKeyString(is_local_root_key,
bool_to_crash_key(is_local_root()));
if (navigation_request && navigation_request->IsNavigationStarted()) {
static auto* const is_renderer_initiated_key =
base::debug::AllocateCrashKeyString("is_renderer_initiated",
base::debug::CrashKeySize::Size32);
base::debug::SetCrashKeyString(
is_renderer_initiated_key,
bool_to_crash_key(navigation_request->IsRendererInitiated()));
static auto* const is_server_redirect_key =
base::debug::AllocateCrashKeyString("is_server_redirect",
base::debug::CrashKeySize::Size32);
base::debug::SetCrashKeyString(
is_server_redirect_key,
bool_to_crash_key(navigation_request->WasServerRedirect()));
static auto* const is_form_submission_key =
base::debug::AllocateCrashKeyString("is_form_submission",
base::debug::CrashKeySize::Size32);
base::debug::SetCrashKeyString(
is_form_submission_key,
bool_to_crash_key(navigation_request->IsFormSubmission()));
static auto* const is_error_page_key = base::debug::AllocateCrashKeyString(
"is_error_page", base::debug::CrashKeySize::Size32);
base::debug::SetCrashKeyString(
is_error_page_key,
bool_to_crash_key(navigation_request->IsErrorPage()));
static auto* const initiator_origin_key =
base::debug::AllocateCrashKeyString("initiator_origin",
base::debug::CrashKeySize::Size64);
base::debug::SetCrashKeyString(
initiator_origin_key,
navigation_request->GetInitiatorOrigin()
? navigation_request->GetInitiatorOrigin()->GetDebugString()
: "none");
static auto* const starting_site_instance_key =
base::debug::AllocateCrashKeyString("starting_site_instance",
base::debug::CrashKeySize::Size256);
base::debug::SetCrashKeyString(starting_site_instance_key,
navigation_request->GetStartingSiteInstance()
->GetSiteInfo()
.GetDebugString());
}
}
void RenderFrameHostImpl::EnableMojoJsBindings(
content::mojom::ExtraMojoJsFeaturesPtr features) {
DCHECK_NE(WebUI::kNoWebUI,
WebUIControllerFactoryRegistry::GetInstance()->GetWebUIType(
GetSiteInstance()->GetBrowserContext(),
site_instance_->GetSiteInfo().site_url()));
GetFrameBindingsControl()->EnableMojoJsBindings(std::move(features));
}
void RenderFrameHostImpl::EnableMojoJsBindingsWithBroker(
mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker> broker) {
DCHECK(GetWebUI());
GetFrameBindingsControl()->EnableMojoJsBindingsWithBroker(std::move(broker));
}
bool RenderFrameHostImpl::IsOutermostMainFrame() const {
return !GetParentOrOuterDocument();
}
void RenderFrameHostImpl::SetIsLoadingForRendererDebugURL() {
LoadingState previous_frame_tree_loading_state =
frame_tree()->LoadingTree()->GetLoadingState();
loading_state_ = LoadingState::LOADING_UI_REQUESTED;
owner_->DidStartLoading(previous_frame_tree_loading_state);
}
BackForwardCacheMetrics* RenderFrameHostImpl::GetBackForwardCacheMetrics() {
NavigationEntryImpl* navigation_entry =
frame_tree()->controller().GetEntryWithUniqueID(nav_entry_id());
if (!navigation_entry)
return nullptr;
return navigation_entry->back_forward_cache_metrics();
}
bool RenderFrameHostImpl::IsBackForwardCacheDisabled() const {
return back_forward_cache_disabled_reasons_.size();
}
bool RenderFrameHostImpl::IsDOMContentLoaded() {
return document_associated_data_->dom_content_loaded();
}
void RenderFrameHostImpl::UpdateIsAdFrame(bool is_ad_frame) {
browsing_context_state_->SetIsAdFrame(is_ad_frame);
}
#if BUILDFLAG(IS_ANDROID)
std::pair<blink::mojom::AuthenticatorStatus, bool>
RenderFrameHostImpl::PerformGetAssertionWebAuthSecurityChecks(
const std::string& relying_party_id,
const url::Origin& effective_origin,
bool is_payment_credential_get_assertion,
const blink::mojom::RemoteDesktopClientOverridePtr&
remote_desktop_client_override) {
bool is_cross_origin = true;
WebAuthRequestSecurityChecker::RequestType request_type =
is_payment_credential_get_assertion
? WebAuthRequestSecurityChecker::RequestType::
kGetPaymentCredentialAssertion
: WebAuthRequestSecurityChecker::RequestType::kGetAssertion;
blink::mojom::AuthenticatorStatus status =
GetWebAuthRequestSecurityChecker()->ValidateAncestorOrigins(
effective_origin, request_type, &is_cross_origin);
if (status != blink::mojom::AuthenticatorStatus::SUCCESS) {
return std::make_pair(status, is_cross_origin);
}
if (!GetContentClient()
->browser()
->GetWebAuthenticationDelegate()
->IsSecurityLevelAcceptableForWebAuthn(this, effective_origin)) {
return std::make_pair(blink::mojom::AuthenticatorStatus::CERTIFICATE_ERROR,
is_cross_origin);
}
status = GetWebAuthRequestSecurityChecker()->ValidateDomainAndRelyingPartyID(
effective_origin, relying_party_id, request_type,
remote_desktop_client_override);
return std::make_pair(status, is_cross_origin);
}
blink::mojom::AuthenticatorStatus
RenderFrameHostImpl::PerformMakeCredentialWebAuthSecurityChecks(
const std::string& relying_party_id,
const url::Origin& effective_origin,
bool is_payment_credential_creation,
const blink::mojom::RemoteDesktopClientOverridePtr&
remote_desktop_client_override) {
bool is_cross_origin;
WebAuthRequestSecurityChecker::RequestType request_type =
is_payment_credential_creation
? WebAuthRequestSecurityChecker::RequestType::kMakePaymentCredential
: WebAuthRequestSecurityChecker::RequestType::kMakeCredential;
blink::mojom::AuthenticatorStatus status =
GetWebAuthRequestSecurityChecker()->ValidateAncestorOrigins(
effective_origin, request_type, &is_cross_origin);
if (status != blink::mojom::AuthenticatorStatus::SUCCESS) {
return status;
}
if (!GetContentClient()
->browser()
->GetWebAuthenticationDelegate()
->IsSecurityLevelAcceptableForWebAuthn(this, effective_origin)) {
return blink::mojom::AuthenticatorStatus::CERTIFICATE_ERROR;
}
status = GetWebAuthRequestSecurityChecker()->ValidateDomainAndRelyingPartyID(
effective_origin, relying_party_id, request_type,
remote_desktop_client_override);
if (status != blink::mojom::AuthenticatorStatus::SUCCESS) {
return status;
}
return blink::mojom::AuthenticatorStatus::SUCCESS;
}
#endif
const blink::DocumentToken& RenderFrameHostImpl::GetDocumentToken() const {
DCHECK_NE(LifecycleStateImpl::kPendingCommit, lifecycle_state());
DCHECK_NE(LifecycleStateImpl::kSpeculative, lifecycle_state());
return GetDocumentTokenIgnoringSafetyRestrictions();
}
const blink::DocumentToken*
RenderFrameHostImpl::GetDocumentTokenForCrossDocumentNavigationReuse(
base::PassKey<NavigationRequest>) {
if (ShouldResetDocumentAssociatedDataAtCommit()) {
return nullptr;
}
return &document_associated_data_->token();
}
void RenderFrameHostImpl::ReinitializeDocumentAssociatedDataForReuseAfterCrash(
base::PassKey<RenderFrameHostManager>) {
DCHECK(is_main_frame());
DCHECK_EQ(RenderFrameState::kDeleted, render_frame_state_);
document_associated_data_.emplace(*this, blink::DocumentToken());
}
void RenderFrameHostImpl::ReinitializeDocumentAssociatedDataForTesting() {
document_associated_data_.emplace(*this, blink::DocumentToken());
}
void RenderFrameHostImpl::IsClipboardPasteContentAllowed(
const ui::ClipboardFormatType& data_type,
ClipboardPasteData clipboard_paste_data,
IsClipboardPasteContentAllowedCallback callback) {
delegate_->IsClipboardPasteContentAllowed(GetLastCommittedURL(), data_type,
std::move(clipboard_paste_data),
std::move(callback));
}
RenderFrameHostImpl* RenderFrameHostImpl::GetParentOrOuterDocument() const {
return frame_tree_node()->GetParentOrOuterDocumentHelper(
false, true);
}
RenderFrameHostImpl* RenderFrameHostImpl::GetParentOrOuterDocumentOrEmbedder()
const {
return frame_tree_node()->GetParentOrOuterDocumentHelper(
true, true);
}
RenderFrameHostImpl* RenderFrameHostImpl::GetOutermostMainFrameOrEmbedder() {
RenderFrameHostImpl* current = this;
while (RenderFrameHostImpl* parent =
current->GetParentOrOuterDocumentOrEmbedder()) {
current = parent;
}
return current;
}
RenderFrameHostImpl* RenderFrameHostImpl::
GetParentOrOuterDocumentOrEmbedderExcludingProspectiveOwners() const {
return frame_tree_node()->GetParentOrOuterDocumentHelper(
true, false);
}
RenderFrameHostImpl* RenderFrameHostImpl::
GetOutermostMainFrameOrEmbedderExcludingProspectiveOwners() {
RenderFrameHostImpl* current = this;
while (
RenderFrameHostImpl* parent =
current
->GetParentOrOuterDocumentOrEmbedderExcludingProspectiveOwners()) {
current = parent;
}
return current;
}
scoped_refptr<WebAuthRequestSecurityChecker>
RenderFrameHostImpl::GetWebAuthRequestSecurityChecker() {
if (!webauth_request_security_checker_)
webauth_request_security_checker_ =
base::MakeRefCounted<WebAuthRequestSecurityChecker>(this);
return webauth_request_security_checker_;
}
bool RenderFrameHostImpl::IsInBackForwardCache() const {
return lifecycle_state() == LifecycleStateImpl::kInBackForwardCache;
}
bool RenderFrameHostImpl::IsPendingDeletion() const {
return lifecycle_state() == LifecycleStateImpl::kRunningUnloadHandlers ||
lifecycle_state() == LifecycleStateImpl::kReadyToBeDeleted;
}
void RenderFrameHostImpl::SetLifecycleState(LifecycleStateImpl new_state) {
TRACE_EVENT2("content", "RenderFrameHostImpl::SetLifecycleState",
"render_frame_host", this, "new_state",
LifecycleStateImplToString(new_state));
TRACE_EVENT_END("navigation", perfetto::Track::FromPointer(this));
TRACE_EVENT_BEGIN(
"navigation",
perfetto::StaticString{LifecycleStateImplToString(new_state)},
perfetto::Track::FromPointer(this));
#if DCHECK_IS_ON()
static const base::NoDestructor<base::StateTransitions<LifecycleStateImpl>>
allowed_transitions(
base::StateTransitions<LifecycleStateImpl>({
{LifecycleStateImpl::kSpeculative,
{LifecycleStateImpl::kActive,
LifecycleStateImpl::kPendingCommit}},
{LifecycleStateImpl::kPendingCommit,
{LifecycleStateImpl::kPrerendering, LifecycleStateImpl::kActive,
LifecycleStateImpl::kReadyToBeDeleted}},
{LifecycleStateImpl::kPrerendering,
{LifecycleStateImpl::kActive,
LifecycleStateImpl::kRunningUnloadHandlers,
LifecycleStateImpl::kReadyToBeDeleted}},
{LifecycleStateImpl::kActive,
{LifecycleStateImpl::kInBackForwardCache,
LifecycleStateImpl::kRunningUnloadHandlers,
LifecycleStateImpl::kReadyToBeDeleted}},
{LifecycleStateImpl::kInBackForwardCache,
{LifecycleStateImpl::kActive,
LifecycleStateImpl::kReadyToBeDeleted}},
{LifecycleStateImpl::kRunningUnloadHandlers,
{LifecycleStateImpl::kReadyToBeDeleted}},
{LifecycleStateImpl::kReadyToBeDeleted, {}},
}));
DCHECK_STATE_TRANSITION(allowed_transitions,
lifecycle_state_,
new_state);
#endif
if (new_state == LifecycleStateImpl::kActive) {
if (lifecycle_state_ == LifecycleStateImpl::kPendingCommit ||
lifecycle_state_ == LifecycleStateImpl::kSpeculative) {
DCHECK(children_.empty());
}
if (GetOutermostMainFrameOrEmbedder() == this &&
(lifecycle_state() == LifecycleStateImpl::kInBackForwardCache ||
lifecycle_state() == LifecycleStateImpl::kPrerendering)) {
FrameTree::NodeRange node_range = FrameTree::SubtreeAndInnerTreeNodes(
this,
true);
FrameTree::NodeIterator node_iter = node_range.begin();
while (node_iter != node_range.end()) {
FrameTreeNode* ftn = *node_iter;
if (ftn->IsOutermostMainFrame()) {
DCHECK(ftn->current_frame_host()->lifecycle_state() !=
LifecycleStateImpl::kInBackForwardCache);
node_iter.AdvanceSkippingChildren();
} else {
RenderFrameHostImpl* rfh = ftn->current_frame_host();
DCHECK_EQ(rfh->lifecycle_state(), lifecycle_state_);
rfh->SetLifecycleState(new_state);
++node_iter;
}
}
}
}
if (lifecycle_state() == LifecycleStateImpl::kInBackForwardCache)
was_restored_from_back_forward_cache_for_debugging_ = true;
if (new_state == LifecycleStateImpl::kPendingCommit ||
new_state == LifecycleStateImpl::kPrerendering) {
DCHECK(children_.empty());
}
LifecycleStateImpl old_state = lifecycle_state_;
lifecycle_state_ = new_state;
if (has_pending_lifecycle_state_update_) {
DCHECK(lifecycle_state() == LifecycleStateImpl::kInBackForwardCache ||
IsPendingDeletion() ||
old_state == LifecycleStateImpl::kPrerendering)
<< "Transitioned to unexpected state with resetting "
"|has_pending_lifecycle_state_update_|\n ";
has_pending_lifecycle_state_update_ = false;
}
if (old_state != LifecycleStateImpl::kSpeculative) {
LifecycleState old_lifecycle_state = GetLifecycleStateFromImpl(old_state);
LifecycleState new_lifecycle_state = GetLifecycleState();
if (old_lifecycle_state != new_lifecycle_state) {
delegate_->RenderFrameHostStateChanged(this, old_lifecycle_state,
new_lifecycle_state);
}
}
if (new_state == LifecycleStateImpl::kActive &&
old_state == LifecycleStateImpl::kInBackForwardCache) {
if (auto* permission_service_context =
PermissionServiceContext::GetForCurrentDocument(this)) {
permission_service_context->NotifyPermissionStatusChangedIfNeeded();
}
}
}
void RenderFrameHostImpl::RecordDocumentCreatedUkmEvent(
const url::Origin& origin,
const ukm::SourceId document_ukm_source_id,
ukm::UkmRecorder* ukm_recorder,
bool only_record_identifiability_metric) {
DCHECK(ukm_recorder);
if (document_ukm_source_id == ukm::kInvalidSourceId)
return;
bool is_cross_origin_frame =
!IsOutermostMainFrame() &&
!GetOutermostMainFrame()->GetLastCommittedOrigin().IsSameOriginWith(
origin);
bool is_cross_site_frame =
!IsOutermostMainFrame() &&
(net::SchemefulSite(origin) !=
net::SchemefulSite(GetOutermostMainFrame()->GetLastCommittedOrigin()));
bool is_main_frame = IsOutermostMainFrame();
ukm::SourceId navigation_ukm_source_id = GetPageUkmSourceId();
RecordIdentifiabilityDocumentCreatedMetrics(
document_ukm_source_id, ukm_recorder, navigation_ukm_source_id,
is_cross_origin_frame, is_cross_site_frame, is_main_frame);
if (only_record_identifiability_metric)
return;
ukm::builders::DocumentCreated(document_ukm_source_id)
.SetNavigationSourceId(navigation_ukm_source_id)
.SetIsMainFrame(is_main_frame)
.SetIsCrossOriginFrame(is_cross_origin_frame)
.SetIsCrossSiteFrame(is_cross_site_frame)
.Record(ukm_recorder);
}
void RenderFrameHostImpl::BindReportingObserver(
mojo::PendingReceiver<blink::mojom::ReportingObserver> receiver) {
GetAssociatedLocalFrame()->BindReportingObserver(std::move(receiver));
}
mojo::PendingRemote<network::mojom::URLLoaderNetworkServiceObserver>
RenderFrameHostImpl::CreateURLLoaderNetworkObserver() {
return GetStoragePartition()->CreateURLLoaderNetworkObserverForFrame(
GetProcess()->GetID(), GetRoutingID());
}
PeerConnectionTrackerHost& RenderFrameHostImpl::GetPeerConnectionTrackerHost() {
return *PeerConnectionTrackerHost::GetOrCreateForCurrentDocument(this);
}
void RenderFrameHostImpl::BindPeerConnectionTrackerHost(
mojo::PendingReceiver<blink::mojom::PeerConnectionTrackerHost> receiver) {
GetPeerConnectionTrackerHost().BindReceiver(std::move(receiver));
}
void RenderFrameHostImpl::EnableWebRtcEventLogOutput(int lid,
int output_period_ms) {
GetPeerConnectionTrackerHost().StartEventLog(lid, output_period_ms);
}
void RenderFrameHostImpl::DisableWebRtcEventLogOutput(int lid) {
GetPeerConnectionTrackerHost().StopEventLog(lid);
}
bool RenderFrameHostImpl::IsDocumentOnLoadCompletedInMainFrame() {
return GetPage().is_on_load_completed_in_main_document();
}
const std::vector<blink::mojom::FaviconURLPtr>&
RenderFrameHostImpl::FaviconURLs() {
return GetPage().favicon_urls();
}
mojo::PendingRemote<network::mojom::CookieAccessObserver>
RenderFrameHostImpl::CreateCookieAccessObserver() {
mojo::PendingRemote<network::mojom::CookieAccessObserver> remote;
cookie_observers_.Add(this, remote.InitWithNewPipeAndPassReceiver());
return remote;
}
mojo::PendingRemote<network::mojom::TrustTokenAccessObserver>
RenderFrameHostImpl::CreateTrustTokenAccessObserver() {
mojo::PendingRemote<network::mojom::TrustTokenAccessObserver> remote;
trust_token_observers_.Add(this, remote.InitWithNewPipeAndPassReceiver());
return remote;
}
#if BUILDFLAG(ENABLE_MDNS)
void RenderFrameHostImpl::CreateMdnsResponder(
mojo::PendingReceiver<network::mojom::MdnsResponder> receiver) {
GetStoragePartition()->GetNetworkContext()->CreateMdnsResponder(
std::move(receiver));
}
#endif
void RenderFrameHostImpl::Clone(
mojo::PendingReceiver<network::mojom::CookieAccessObserver> observer) {
cookie_observers_.Add(this, std::move(observer));
}
void RenderFrameHostImpl::Clone(
mojo::PendingReceiver<network::mojom::TrustTokenAccessObserver> observer) {
trust_token_observers_.Add(this, std::move(observer));
}
void RenderFrameHostImpl::OnCookiesAccessed(
std::vector<network::mojom::CookieAccessDetailsPtr> details_vector) {
for (auto& details : details_vector) {
EmitCookieWarningsAndMetrics(this, details);
CookieAccessDetails allowed;
CookieAccessDetails blocked;
SplitCookiesIntoAllowedAndBlocked(details, &allowed, &blocked);
if (!allowed.cookie_list.empty()) {
delegate_->OnCookiesAccessed(this, allowed);
}
if (!blocked.cookie_list.empty()) {
delegate_->OnCookiesAccessed(this, blocked);
}
}
}
void RenderFrameHostImpl::OnTrustTokensAccessed(
network::mojom::TrustTokenAccessDetailsPtr details) {
delegate_->OnTrustTokensAccessed(this, TrustTokenAccessDetails(details));
}
void RenderFrameHostImpl::SetEmbeddingToken(
const base::UnguessableToken& embedding_token) {
if (embedding_token_ == embedding_token)
return;
embedding_token_ = embedding_token;
const ui::AXTreeID old_id = GetAXTreeID();
ui::AXTreeID ax_tree_id = ui::AXTreeID::FromToken(embedding_token);
DCHECK_NE(old_id, ax_tree_id);
SetAXTreeID(ax_tree_id);
needs_ax_root_id_ = true;
ui::AXActionHandlerRegistry::GetInstance()->SetFrameIDForAXTreeID(
ui::AXActionHandlerRegistry::FrameID(GetProcess()->GetID(), routing_id_),
ax_tree_id);
if (IsInPrimaryMainFrame())
delegate_->AXTreeIDForMainFrameHasChanged();
PropagateEmbeddingTokenToParentFrame();
RenderFrameHostImpl* outermost = GetOutermostMainFrameOrEmbedder();
DCHECK(outermost);
DCHECK(lifecycle_state_ != LifecycleStateImpl::kPrerendering ||
outermost->GetFocusedAXTreeID() != GetAXTreeID());
if (outermost != this &&
lifecycle_state_ != LifecycleStateImpl::kPrerendering) {
outermost->UpdateAXTreeData();
}
if (browser_accessibility_manager_) {
browser_accessibility_manager_->DetachFromParentManager();
browser_accessibility_manager_.reset();
}
}
bool RenderFrameHostImpl::DocumentUsedWebOTP() {
return document_used_web_otp_;
}
void RenderFrameHostImpl::SetFrameTreeNode(FrameTreeNode& frame_tree_node) {
devtools_instrumentation::WillSwapFrameTreeNode(*frame_tree_node_,
frame_tree_node);
frame_tree_node_ = &frame_tree_node;
SetFrameTree(frame_tree_node_->frame_tree());
switch (features::GetBrowsingContextMode()) {
case (features::BrowsingContextStateImplementationType::
kLegacyOneToOneWithFrameTreeNode):
browsing_context_state_ = frame_tree_node_->render_manager()
->current_frame_host()
->browsing_context_state();
break;
case (features::BrowsingContextStateImplementationType::
kSwapForCrossBrowsingInstanceNavigations):
break;
}
}
void RenderFrameHostImpl::SetFrameTree(FrameTree& frame_tree) {
DCHECK_EQ(&frame_tree_node_->frame_tree(), &frame_tree);
frame_tree_ = &frame_tree;
render_view_host()->SetFrameTree(frame_tree);
if (owned_render_widget_host_) {
owned_render_widget_host_->SetFrameTree(frame_tree);
}
}
void RenderFrameHostImpl::SetPolicyContainerForEarlyCommitAfterCrash(
scoped_refptr<PolicyContainerHost> policy_container_host) {
DCHECK_EQ(lifecycle_state(), LifecycleStateImpl::kSpeculative);
DCHECK(!policy_container_host_);
SetPolicyContainerHost(std::move(policy_container_host));
}
void RenderFrameHostImpl::OnDidRunInsecureContent(const GURL& security_origin,
const GURL& target_url) {
OPTIONAL_TRACE_EVENT2("content", "RenderFrameHostImpl::DidRunInsecureContent",
"security_origin", security_origin, "target_url",
target_url);
RecordAction(base::UserMetricsAction("SSL.RanInsecureContent"));
if (base::EndsWith(security_origin.spec(), kDotGoogleDotCom,
base::CompareCase::INSENSITIVE_ASCII)) {
RecordAction(base::UserMetricsAction("SSL.RanInsecureContentGoogle"));
}
frame_tree_->controller().ssl_manager()->DidRunMixedContent(security_origin);
}
void RenderFrameHostImpl::OnDidRunContentWithCertificateErrors() {
OPTIONAL_TRACE_EVENT0(
"content", "RenderFrameHostImpl::OnDidRunContentWithCertificateErrors");
DCHECK_NE(lifecycle_state(), LifecycleStateImpl::kSpeculative);
if (lifecycle_state() != LifecycleStateImpl::kPendingCommit &&
IsInactiveAndDisallowActivation(
DisallowActivationReasonId::kCertificateErrors)) {
return;
}
if (IsNestedWithinFencedFrame()) {
GetParentOrOuterDocument()->OnDidRunContentWithCertificateErrors();
return;
}
frame_tree_->controller().ssl_manager()->DidRunContentWithCertErrors(
GetMainFrame()->GetLastCommittedOrigin().GetURL());
}
void RenderFrameHostImpl::OnDidDisplayContentWithCertificateErrors() {
OPTIONAL_TRACE_EVENT0(
"content",
"RenderFrameHostImpl::OnDidDisplayContentWithCertificateErrors");
frame_tree_->controller().ssl_manager()->DidDisplayContentWithCertErrors();
}
void RenderFrameHostImpl::IncreaseCommitNavigationCounter() {
if (commit_navigation_sent_counter_ < std::numeric_limits<int>::max())
++commit_navigation_sent_counter_;
else
commit_navigation_sent_counter_ = 0;
}
bool RenderFrameHostImpl::ShouldWaitForUnloadHandlers() const {
return has_unload_handlers() && !IsInBackForwardCache();
}
void RenderFrameHostImpl::AssertNonSpeculativeFrame() const {
if (LIKELY(lifecycle_state() != LifecycleStateImpl::kSpeculative))
return;
NOTREACHED();
base::debug::DumpWithoutCrashing();
}
void RenderFrameHostImpl::AssertBrowserContextShutdownHasntStarted() {
if (LIKELY(!GetBrowserContext()->ShutdownStarted()))
return;
std::string debug_string = ToDebugString();
SCOPED_CRASH_KEY_STRING256("shutdown", "frame->ToDebugString", debug_string);
NOTREACHED() << "BrowserContext->ShutdownStarted() without first closing all "
<< "WebContents; debug_string = " << debug_string;
base::debug::DumpWithoutCrashing();
}
blink::StorageKey RenderFrameHostImpl::GetBucketStorageKey() {
return storage_key_;
}
blink::mojom::PermissionStatus RenderFrameHostImpl::GetPermissionStatus(
blink::PermissionType permission_type) {
return GetBrowserContext()
->GetPermissionController()
->GetPermissionStatusForCurrentDocument(permission_type, this);
}
void RenderFrameHostImpl::BindCacheStorageForBucket(
const storage::BucketInfo& bucket,
mojo::PendingReceiver<blink::mojom::CacheStorage> receiver) {
BindCacheStorageInternal(std::move(receiver), bucket.ToBucketLocator());
}
void RenderFrameHostImpl::GetSandboxedFileSystemForBucket(
const storage::BucketInfo& bucket,
blink::mojom::BucketHost::GetDirectoryCallback callback) {
GetStoragePartition()->GetFileSystemAccessManager()->GetSandboxedFileSystem(
FileSystemAccessManagerImpl::BindingContext(
storage_key(), GetLastCommittedURL(), GetGlobalId()),
bucket.ToBucketLocator(), std::move(callback));
}
GlobalRenderFrameHostId RenderFrameHostImpl::GetAssociatedRenderFrameHostId()
const {
return GetGlobalId();
}
RenderFrameHostImpl::DocumentAssociatedData::DocumentAssociatedData(
RenderFrameHostImpl& document,
const blink::DocumentToken& token)
: token_(token), weak_factory_(&document) {
auto [_, inserted] = GetDocumentTokenMap().insert({token_, &document});
CHECK(inserted);
if (!document.GetParent()) {
PageDelegate* page_delegate = document.frame_tree()->page_delegate();
DCHECK(page_delegate);
owned_page_ = PageFactory::Create(document, *page_delegate);
}
}
RenderFrameHostImpl::DocumentAssociatedData::~DocumentAssociatedData() {
while (!services_.empty()) {
services_.back()->WillBeDestroyed(
DocumentServiceDestructionReason::kEndOfDocumentLifetime);
services_.back()->ResetAndDeleteThis();
}
ClearAllUserData();
CHECK_EQ(1u, GetDocumentTokenMap().erase(token_));
}
void RenderFrameHostImpl::DocumentAssociatedData::
set_navigation_or_document_handle(
scoped_refptr<NavigationOrDocumentHandle> handle) {
navigation_or_document_handle_ = std::move(handle);
}
std::ostream& operator<<(std::ostream& o,
const RenderFrameHostImpl::LifecycleStateImpl& s) {
return o << RenderFrameHostImpl::LifecycleStateImplToString(s);
}
net::CookieSettingOverrides RenderFrameHostImpl::GetCookieSettingOverrides() {
DCHECK_NE(lifecycle_state(), LifecycleStateImpl::kSpeculative);
DCHECK_NE(lifecycle_state(), LifecycleStateImpl::kPendingCommit);
auto subresource_loader_factories_config =
SubresourceLoaderFactoriesConfig::ForLastCommittedNavigation(*this);
return subresource_loader_factories_config.cookie_setting_overrides();
}
RenderFrameHostImpl::CookieChangeListener::CookieChangeListener(
StoragePartition* storage_partition,
GURL& url) {
DCHECK(storage_partition);
auto* cookie_manager = storage_partition->GetCookieManagerForBrowserProcess();
cookie_manager->AddCookieChangeListener(
url, absl::nullopt,
cookie_change_listener_receiver_.BindNewPipeAndPassRemote());
}
RenderFrameHostImpl::CookieChangeListener::~CookieChangeListener() = default;
void RenderFrameHostImpl::CookieChangeListener::OnCookieChange(
const net::CookieChangeInfo& change) {
cookie_change_info_.cookie_modification_count_++;
if (change.cookie.IsHttpOnly()) {
cookie_change_info_.http_only_cookie_modification_count_++;
}
}
RenderFrameHostImpl::CookieChangeListener::CookieChangeInfo
RenderFrameHostImpl::GetCookieChangeInfo() {
return cookie_change_listener_ ? cookie_change_listener_->cookie_change_info()
: CookieChangeListener::CookieChangeInfo{};
}
bool RenderFrameHostImpl::GetIsThirdPartyCookiesUserBypassEnabled() {
auto* document_data =
RuntimeFeatureStateDocumentData::GetForCurrentDocument(GetMainFrame());
if (!document_data) {
return false;
}
blink::RuntimeFeatureStateReadContext read_context =
document_data->runtime_feature_state_read_context();
return read_context.IsThirdPartyCookiesUserBypassEnabled();
}
void RenderFrameHostImpl::SetResourceCacheRemote(
mojo::PendingRemote<blink::mojom::ResourceCache> pending_remote) {
GetMojomFrameInRenderer()->SetResourceCache(std::move(pending_remote));
}
#ifdef OHOS_DRAG_DROP
void RenderFrameHostImpl::OnClearContextMenu() {
if (IsInactiveAndDisallowActivation(DisallowActivationReasonId::kShowContextMenu))
return;
delegate_->ClearContextMenu();
}
#endif
#ifdef OHOS_ARKWEB_ADBLOCK
void RenderFrameHostImpl::UpdateAdBlockEnabledToRender(
bool site_adblock_enabled) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
FrameTreeNode* tree_node = frame_tree_node();
if (!tree_node->IsMainFrame()) {
return;
}
RenderFrameHostImpl* pending_frame_host =
tree_node->render_manager()->speculative_frame_host();
if (pending_frame_host && pending_frame_host->frame_) {
LOG(INFO) << "[AdBlock] Speculative update adblock site switch:"
<< site_adblock_enabled;
pending_frame_host->frame_->OnUpdateAdBlockEnabledToRender(
site_adblock_enabled);
}
RenderFrameHostImpl* current_frame_host = tree_node->current_frame_host();
if (current_frame_host && current_frame_host->frame_) {
LOG(INFO) << "[AdBlock] Update adblock site switch:"
<< site_adblock_enabled;
current_frame_host->frame_->OnUpdateAdBlockEnabledToRender(
site_adblock_enabled);
}
}
#endif
}