#include "content/renderer/render_frame_impl.h"
#include <algorithm>
#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include <utility>
#include <vector>
#include "base/byte_count.h"
#include "base/check_deref.h"
#include "base/command_line.h"
#include "base/containers/contains.h"
#include "base/containers/flat_map.h"
#include "base/containers/to_vector.h"
#include "base/debug/alias.h"
#include "base/debug/asan_invalid_access.h"
#include "base/debug/crash_logging.h"
#include "base/debug/dump_without_crashing.h"
#include "base/feature_list.h"
#include "base/files/file.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/raw_ref.h"
#include "base/memory/weak_ptr.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/field_trial_params.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/notreached.h"
#include "base/observer_list.h"
#include "base/process/process.h"
#include "base/run_loop.h"
#include "base/strings/strcat.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/common/task_annotator.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/single_thread_task_runner.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
#include "base/time/time.h"
#include "base/timer/elapsed_timer.h"
#include "base/trace_event/trace_event.h"
#include "base/types/optional_util.h"
#include "base/unguessable_token.h"
#include "base/uuid.h"
#include "base/values.h"
#include "build/build_config.h"
#include "cc/base/switches.h"
#include "components/history/core/browser/features.h"
#include "content/common/associated_interfaces.mojom.h"
#include "content/common/content_navigation_policy.h"
#include "content/common/content_switches_internal.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/main_frame_counter.h"
#include "content/common/navigation_client.mojom.h"
#include "content/common/navigation_gesture.h"
#include "content/common/navigation_params_utils.h"
#include "content/common/renderer_host.mojom.h"
#include "content/common/web_package/signed_exchange_utils.h"
#include "content/common/web_ui_loading_util.h"
#include "content/public/common/bindings_policy.h"
#include "content/public/common/content_constants.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/url_constants.h"
#include "content/public/common/url_utils.h"
#include "content/public/renderer/content_renderer_client.h"
#include "content/public/renderer/render_frame_observer.h"
#include "content/public/renderer/render_frame_visitor.h"
#include "content/public/renderer/render_thread.h"
#include "content/public/renderer/window_features_converter.h"
#include "content/renderer/accessibility/ax_tree_snapshotter_impl.h"
#include "content/renderer/accessibility/render_accessibility_impl.h"
#include "content/renderer/accessibility/render_accessibility_manager.h"
#include "content/renderer/agent_scheduling_group.h"
#include "content/renderer/background_resource_fetch_assets.h"
#include "content/renderer/content_security_policy_util.h"
#include "content/renderer/document_state.h"
#include "content/renderer/dom_automation_controller.h"
#include "content/renderer/effective_connection_type_helper.h"
#include "content/renderer/frame_owner_properties_converter.h"
#include "content/renderer/gpu_benchmarking_extension.h"
#include "content/renderer/local_resource_url_loader_factory.h"
#include "content/renderer/media/media_permission_dispatcher.h"
#include "content/renderer/mhtml_handle_writer.h"
#include "content/renderer/mojo/blink_interface_registry_impl.h"
#include "content/renderer/navigation_client.h"
#include "content/renderer/navigation_state.h"
#include "content/renderer/policy_container_util.h"
#include "content/renderer/render_process.h"
#include "content/renderer/render_thread_impl.h"
#include "content/renderer/renderer_blink_platform_impl.h"
#include "content/renderer/renderer_navigation_metrics_manager.h"
#include "content/renderer/service_worker/service_worker_network_provider_for_frame.h"
#include "content/renderer/service_worker/web_service_worker_provider_impl.h"
#include "content/renderer/skia_benchmarking_extension.h"
#include "content/renderer/stats_collection_controller.h"
#include "content/renderer/v8_value_converter_impl.h"
#include "content/renderer/web_ui_extension.h"
#include "content/renderer/web_ui_extension_data.h"
#include "content/renderer/worker/dedicated_worker_host_factory_client.h"
#include "crypto/sha2.h"
#include "ipc/constants.mojom.h"
#include "media/mojo/mojom/audio_processing.mojom.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
#include "mojo/public/cpp/bindings/pending_associated_remote.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "net/base/data_url.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_util.h"
#include "services/metrics/public/cpp/ukm_source_id.h"
#include "services/network/public/cpp/content_decoding_interceptor.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/not_implemented_url_loader_factory.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "services/network/public/mojom/fetch_api.mojom.h"
#include "services/network/public/mojom/restricted_cookie_manager.mojom.h"
#include "services/network/public/mojom/url_loader.mojom.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "services/network/public/mojom/url_response_head.mojom.h"
#include "services/service_manager/public/mojom/interface_provider.mojom.h"
#include "services/tracing/public/cpp/perfetto/track_name_recorder.h"
#include "services/viz/public/cpp/gpu/context_provider_command_buffer.h"
#include "third_party/abseil-cpp/absl/container/flat_hash_map.h"
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
#include "third_party/blink/public/common/chrome_debug_urls.h"
#include "third_party/blink/public/common/context_menu_data/context_menu_data.h"
#include "third_party/blink/public/common/context_menu_data/untrustworthy_context_menu_params.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/input/web_keyboard_event.h"
#include "third_party/blink/public/common/interest_group/ad_auction_constants.h"
#include "third_party/blink/public/common/loader/loader_constants.h"
#include "third_party/blink/public/common/loader/record_load_histograms.h"
#include "third_party/blink/public/common/loader/resource_type_util.h"
#include "third_party/blink/public/common/loader/url_loader_throttle.h"
#include "third_party/blink/public/common/navigation/impression.h"
#include "third_party/blink/public/common/navigation/navigation_params.h"
#include "third_party/blink/public/common/navigation/navigation_params_mojom_traits.h"
#include "third_party/blink/public/common/navigation/navigation_policy.h"
#include "third_party/blink/public/common/page_state/page_state.h"
#include "third_party/blink/public/common/renderer_preferences/renderer_preferences.h"
#include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
#include "third_party/blink/public/mojom/blob/blob.mojom.h"
#include "third_party/blink/public/mojom/blob/blob_url_store.mojom.h"
#include "third_party/blink/public/mojom/choosers/file_chooser.mojom.h"
#include "third_party/blink/public/mojom/dom_storage/storage_area.mojom.h"
#include "third_party/blink/public/mojom/fetch/fetch_api_request.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/user_activation_notification_type.mojom.h"
#include "third_party/blink/public/mojom/frame/user_activation_update_types.mojom.h"
#include "third_party/blink/public/mojom/frame/view_transition_state.mojom.h"
#include "third_party/blink/public/mojom/input/focus_type.mojom.h"
#include "third_party/blink/public/mojom/input/input_handler.mojom-shared.h"
#include "third_party/blink/public/mojom/loader/fetch_later.mojom.h"
#include "third_party/blink/public/mojom/loader/referrer.mojom.h"
#include "third_party/blink/public/mojom/loader/request_context_frame_type.mojom.h"
#include "third_party/blink/public/mojom/loader/resource_load_info.mojom.h"
#include "third_party/blink/public/mojom/navigation/navigation_params.mojom.h"
#include "third_party/blink/public/mojom/page/widget.mojom.h"
#include "third_party/blink/public/mojom/permissions/permission.mojom.h"
#include "third_party/blink/public/mojom/render_accessibility.mojom.h"
#include "third_party/blink/public/mojom/renderer_preference_watcher.mojom.h"
#include "third_party/blink/public/mojom/widget/platform_widget.mojom.h"
#include "third_party/blink/public/platform/file_path_conversion.h"
#include "third_party/blink/public/platform/modules/service_worker/web_service_worker_network_provider.h"
#include "third_party/blink/public/platform/resource_load_info_notifier_wrapper.h"
#include "third_party/blink/public/platform/scheduler/web_agent_group_scheduler.h"
#include "third_party/blink/public/platform/tracked_child_url_loader_factory_bundle.h"
#include "third_party/blink/public/platform/url_conversion.h"
#include "third_party/blink/public/platform/weak_wrapper_resource_load_info_notifier.h"
#include "third_party/blink/public/platform/web_data.h"
#include "third_party/blink/public/platform/web_dedicated_or_shared_worker_global_scope_context.h"
#include "third_party/blink/public/platform/web_http_body.h"
#include "third_party/blink/public/platform/web_media_player.h"
#include "third_party/blink/public/platform/web_media_player_source.h"
#include "third_party/blink/public/platform/web_navigation_body_loader.h"
#include "third_party/blink/public/platform/web_runtime_features.h"
#include "third_party/blink/public/platform/web_string.h"
#include "third_party/blink/public/platform/web_url.h"
#include "third_party/blink/public/platform/web_url_error.h"
#include "third_party/blink/public/platform/web_url_request_extra_data.h"
#include "third_party/blink/public/platform/web_url_request_util.h"
#include "third_party/blink/public/platform/web_url_response.h"
#include "third_party/blink/public/web/blink.h"
#include "third_party/blink/public/web/modules/media/audio/audio_device_factory.h"
#include "third_party/blink/public/web/modules/media/audio/audio_output_ipc_factory.h"
#include "third_party/blink/public/web/modules/mediastream/web_media_stream_device_observer.h"
#include "third_party/blink/public/web/web_autofill_client.h"
#include "third_party/blink/public/web/web_console_message.h"
#include "third_party/blink/public/web/web_document.h"
#include "third_party/blink/public/web/web_element_collection.h"
#include "third_party/blink/public/web/web_frame_owner_properties.h"
#include "third_party/blink/public/web/web_frame_serializer.h"
#include "third_party/blink/public/web/web_frame_widget.h"
#include "third_party/blink/public/web/web_input_method_controller.h"
#include "third_party/blink/public/web/web_link_preview_triggerer.h"
#include "third_party/blink/public/web/web_local_frame.h"
#include "third_party/blink/public/web/web_navigation_control.h"
#include "third_party/blink/public/web/web_navigation_policy.h"
#include "third_party/blink/public/web/web_navigation_timings.h"
#include "third_party/blink/public/web/web_navigation_type.h"
#include "third_party/blink/public/web/web_performance_metrics_for_nested_contexts.h"
#include "third_party/blink/public/web/web_picture_in_picture_window_options.h"
#include "third_party/blink/public/web/web_plugin.h"
#include "third_party/blink/public/web/web_plugin_container.h"
#include "third_party/blink/public/web/web_plugin_document.h"
#include "third_party/blink/public/web/web_plugin_params.h"
#include "third_party/blink/public/web/web_range.h"
#include "third_party/blink/public/web/web_remote_frame.h"
#include "third_party/blink/public/web/web_savable_resources_test_support.h"
#include "third_party/blink/public/web/web_script_source.h"
#include "third_party/blink/public/web/web_searchable_form_data.h"
#include "third_party/blink/public/web/web_security_policy.h"
#include "third_party/blink/public/web/web_serialized_script_value.h"
#include "third_party/blink/public/web/web_v8_features.h"
#include "third_party/blink/public/web/web_view.h"
#include "third_party/blink/public/web/web_widget.h"
#include "third_party/blink/public/web/web_window_features.h"
#include "third_party/perfetto/include/perfetto/tracing/track.h"
#include "ui/accessibility/ax_tree_update.h"
#include "ui/events/base_event_utils.h"
#include "url/origin.h"
#include "url/url_constants.h"
#include "url/url_util.h"
#include "v8/include/v8-isolate.h"
#include "v8/include/v8-local-handle.h"
#include "v8/include/v8-microtask-queue.h"
#if BUILDFLAG(IS_ANDROID)
#include <cpu-features.h>
#include "content/renderer/java/gin_java_bridge_dispatcher.h"
#endif
#include "mojo/public/cpp/bindings/self_owned_associated_receiver.h"
#if BUILDFLAG(IS_ARKWEB)
#include "arkweb/chromium_ext/content/renderer/render_frame_impl_before_for_include.cc"
#endif
#if BUILDFLAG(ARKWEB_CRASHPAD)
#include "arkweb/chromium_ext/content/browser/dfx/memory_monitor_render_impl.h"
#endif
#if BUILDFLAG(ARKWEB_JSHEAP_DUMP)
#include "arkweb/chromium_ext/v8/heap_dump/mojom_impl/binary_writer_render_impl.h"
#endif
using base::Time;
using blink::ContextMenuData;
using blink::WebContentDecryptionModule;
using blink::WebData;
using blink::WebDocument;
using blink::WebDocumentLoader;
using blink::WebDOMMessageEvent;
using blink::WebElement;
using blink::WebElementCollection;
using blink::WebFrame;
using blink::WebFrameLoadType;
using blink::WebFrameSerializer;
using blink::WebFrameSerializerClient;
using blink::WebHistoryItem;
using blink::WebHTTPBody;
using blink::WebInputMethodController;
using blink::WebLocalFrame;
using blink::WebMediaPlayer;
using blink::WebMediaPlayerClient;
using blink::WebMediaPlayerEncryptedMediaClient;
using blink::WebNavigationParams;
using blink::WebNavigationPolicy;
using blink::WebNavigationType;
using blink::WebNode;
using blink::WebPluginDocument;
using blink::WebPluginParams;
using blink::WebRange;
using blink::WebScriptSource;
using blink::WebSearchableFormData;
using blink::WebSecurityOrigin;
using blink::WebSecurityPolicy;
using blink::WebSerializedScriptValue;
using blink::WebServiceWorkerProvider;
using blink::WebString;
using blink::WebThreadSafeData;
using blink::WebURL;
using blink::WebURLError;
using blink::WebURLRequest;
using blink::WebURLResponse;
using blink::WebView;
using blink::mojom::SelectionMenuBehavior;
using network::mojom::ReferrerPolicy;
namespace content {
namespace {
BASE_FEATURE(kReducePageStateIpcs, base::FEATURE_ENABLED_BY_DEFAULT);
const int kExtraCharsBeforeAndAfterSelection = 100;
const size_t kMaxURLLogChars = 1024;
const char kCommitRenderFrame[] = "Navigation.CommitRenderFrame";
constexpr base::TimeDelta kDelaySecondsForContentStateSyncHidden =
base::Seconds(5);
constexpr base::TimeDelta kDelaySecondsForContentStateSync = base::Seconds(1);
using FrameMap = absl::flat_hash_map<blink::WebFrame*, RenderFrameImpl*>;
base::LazyInstance<FrameMap>::DestructorAtExit g_frame_map =
LAZY_INSTANCE_INITIALIZER;
enum class RendererBlockedURLReason {
kInvalidURL = 0,
kTooLongURL = 1,
kBadAboutURL = 2,
kMaxValue = kBadAboutURL
};
int64_t ExtractPostId(const WebHistoryItem& item) {
if (item.IsNull() || item.HttpBody().IsNull())
return -1;
return item.HttpBody().Identifier();
}
std::string TrimURL(const std::string& url) {
if (url.length() <= kMaxURLLogChars)
return url;
return url.substr(0, kMaxURLLogChars - 3) + "...";
}
ui::PageTransition GetTransitionType(ui::PageTransition default_transition,
bool replaces_current_item,
bool is_main_frame,
bool is_in_fenced_frame_tree,
WebNavigationType navigation_type) {
if (is_in_fenced_frame_tree) {
return ui::PAGE_TRANSITION_AUTO_SUBFRAME;
}
if (replaces_current_item && !is_main_frame) {
return ui::PAGE_TRANSITION_AUTO_SUBFRAME;
}
bool is_form_submit =
navigation_type == blink::kWebNavigationTypeFormSubmitted ||
navigation_type == blink::kWebNavigationTypeFormResubmittedBackForward ||
navigation_type == blink::kWebNavigationTypeFormResubmittedReload;
if (ui::PageTransitionCoreTypeIs(default_transition,
ui::PAGE_TRANSITION_LINK) &&
is_form_submit) {
return ui::PAGE_TRANSITION_FORM_SUBMIT;
}
return default_transition;
}
ui::PageTransition GetTransitionType(blink::WebDocumentLoader* document_loader,
NavigationState* navigation_state,
bool is_main_frame,
bool is_in_fenced_frame_tree) {
ui::PageTransition default_transition =
navigation_state->IsForSynchronousCommit()
? ui::PAGE_TRANSITION_LINK
: ui::PageTransitionFromInt(
navigation_state->common_params().transition);
if (!is_in_fenced_frame_tree && navigation_state->WasWithinSameDocument())
return default_transition;
return GetTransitionType(default_transition,
document_loader->ReplacesCurrentHistoryItem(),
is_main_frame, is_in_fenced_frame_tree,
document_loader->GetNavigationType());
}
bool IsValidCommitUrl(const GURL& url) {
if (!url.is_valid()) {
base::UmaHistogramEnumeration("Navigation.Renderer.BlockedForFilterURL",
RendererBlockedURLReason::kInvalidURL);
return false;
}
if (url.possibly_invalid_spec().length() > url::kMaxURLChars) {
base::UmaHistogramEnumeration("Navigation.Renderer.BlockedForFilterURL",
RendererBlockedURLReason::kTooLongURL);
return false;
}
if (url.SchemeIs(url::kAboutScheme) &&
(!url.IsAboutBlank() && !url.IsAboutSrcdoc())) {
base::UmaHistogramEnumeration("Navigation.Renderer.BlockedForFilterURL",
RendererBlockedURLReason::kBadAboutURL);
return false;
}
return true;
}
bool MaybeGetOverriddenURL(WebDocumentLoader* document_loader, GURL* output) {
DocumentState* document_state =
DocumentState::FromDocumentLoader(document_loader);
if (!document_state) {
return false;
}
if (document_state->was_load_data_with_base_url_request()) {
*output = document_state->data_url();
return true;
}
if (document_loader->HasUnreachableURL()) {
*output = document_loader->UnreachableWebURL();
return true;
}
return false;
}
bool IsTopLevelNavigation(WebFrame* frame) {
return frame->Parent() == nullptr && !frame->View()->IsFencedFrameRoot();
}
void FillNavigationParamsRequest(
const blink::mojom::CommonNavigationParams& common_params,
const blink::mojom::CommitNavigationParams& commit_params,
blink::WebNavigationParams* navigation_params) {
navigation_params->url = !commit_params.original_url.is_empty()
? commit_params.original_url
: common_params.url;
navigation_params->http_method = WebString::FromASCII(
!commit_params.original_method.empty() ? commit_params.original_method
: common_params.method);
if (common_params.referrer->url.is_valid()) {
WebString referrer = WebSecurityPolicy::GenerateReferrerHeader(
common_params.referrer->policy, common_params.url,
WebString::FromUTF8(common_params.referrer->url.spec()));
navigation_params->referrer = referrer;
navigation_params->referrer_policy = common_params.referrer->policy;
}
if (common_params.referrer->policy !=
network::mojom::ReferrerPolicy::kDefault) {
navigation_params->referrer_policy = common_params.referrer->policy;
}
if (common_params.post_data) {
navigation_params->http_body =
blink::GetWebHTTPBodyForRequestBody(*common_params.post_data);
if (!commit_params.post_content_type.empty()) {
navigation_params->http_content_type =
WebString::FromASCII(commit_params.post_content_type);
}
}
if (common_params.initiator_origin) {
navigation_params->requestor_origin =
common_params.initiator_origin.value();
}
navigation_params->initiator_origin_trial_features = {
common_params.initiator_origin_trial_features.begin(),
common_params.initiator_origin_trial_features.end()};
navigation_params->was_discarded = commit_params.was_discarded;
navigation_params->document_ukm_source_id =
commit_params.document_ukm_source_id;
navigation_params->prefetched_signed_exchanges = base::ToVector(
commit_params.prefetched_signed_exchanges, [](const auto& exchange) {
blink::WebURLResponse web_response = blink::WebURLResponse::Create(
exchange->inner_url, *exchange->inner_response,
false , -1 );
return std::make_unique<
blink::WebNavigationParams::PrefetchedSignedExchange>(
exchange->outer_url,
WebString::FromLatin1(
signed_exchange_utils::CreateHeaderIntegrityHashString(
exchange->header_integrity)),
exchange->inner_url, web_response,
std::move(exchange->loader_factory_handle));
});
navigation_params->had_transient_user_activation =
common_params.has_user_gesture;
navigation_params->force_enabled_origin_trials = base::ToVector(
commit_params.force_enabled_origin_trials, &WebString::FromASCII);
navigation_params->early_hints_preloaded_resources = base::ToVector(
commit_params.early_hints_preloaded_resources, blink::ToWebURL);
if (common_params.initiator_base_url) {
CHECK(common_params.url.IsAboutSrcdoc() ||
common_params.url.IsAboutBlank());
navigation_params->fallback_base_url =
common_params.initiator_base_url.value();
} else {
navigation_params->fallback_base_url = WebURL();
}
}
blink::mojom::CommonNavigationParamsPtr MakeCommonNavigationParams(
const WebSecurityOrigin& current_origin,
std::unique_ptr<blink::WebNavigationInfo> info,
int load_flags,
bool has_download_sandbox_flag,
bool from_ad,
bool is_history_navigation_in_new_child_frame,
network::mojom::RequestDestination request_destination) {
DCHECK(!info->url_request.RequestorOrigin().IsNull());
blink::mojom::ReferrerPtr referrer = blink::mojom::Referrer::New(
blink::WebStringToGURL(info->url_request.ReferrerString()),
info->url_request.GetReferrerPolicy());
DCHECK(info->navigation_type != blink::kWebNavigationTypeBackForward);
blink::mojom::NavigationType navigation_type =
blink::mojom::NavigationType::DIFFERENT_DOCUMENT;
if (info->navigation_type == blink::kWebNavigationTypeReload) {
if (load_flags & net::LOAD_BYPASS_CACHE)
navigation_type = blink::mojom::NavigationType::RELOAD_BYPASSING_CACHE;
else
navigation_type = blink::mojom::NavigationType::RELOAD;
}
auto source_location = network::mojom::SourceLocation::New(
info->source_location.url.Latin1(), info->source_location.line_number,
info->source_location.column_number);
const blink::WebURLRequestExtraData* url_request_extra_data =
static_cast<blink::WebURLRequestExtraData*>(
info->url_request.GetURLRequestExtraData().get());
DCHECK(url_request_extra_data);
blink::NavigationDownloadPolicy download_policy;
download_policy.ApplyDownloadFramePolicy(
info->is_opener_navigation, info->url_request.HasUserGesture(),
info->url_request.RequestorOrigin().CanAccess(current_origin),
has_download_sandbox_flag, from_ad);
std::optional<GURL> initiator_base_url;
GURL requestor_base_url(info->requestor_base_url);
if (requestor_base_url.is_valid() &&
requestor_base_url.possibly_invalid_spec().length() <=
url::kMaxURLChars) {
initiator_base_url = requestor_base_url;
}
return blink::mojom::CommonNavigationParams::New(
info->url_request.Url(), info->url_request.RequestorOrigin(),
initiator_base_url, std::move(referrer),
url_request_extra_data->transition_type(), navigation_type,
download_policy,
info->frame_load_type == WebFrameLoadType::kReplaceCurrentItem, GURL(),
info->actual_navigation_start,
base::TimeTicks::Now(),
info->url_request.HttpMethod().Latin1(),
blink::GetRequestBodyForWebURLRequest(info->url_request),
std::move(source_location), false ,
info->url_request.HasUserGesture(),
info->url_request.HasTextFragmentToken(),
info->should_check_main_world_content_security_policy,
info->initiator_origin_trial_features, info->href_translate.Latin1(),
is_history_navigation_in_new_child_frame, info->input_start,
#if BUILDFLAG(ARKWEB_NETWORK_BASE)
request_destination, ""
#else
request_destination
#endif
#if BUILDFLAG(ARKWEB_ERROR_PAGE)
, false
#endif
);
}
WebFrameLoadType NavigationTypeToLoadType(
blink::mojom::NavigationType navigation_type,
bool should_replace_current_entry) {
switch (navigation_type) {
case blink::mojom::NavigationType::RELOAD:
return WebFrameLoadType::kReload;
case blink::mojom::NavigationType::RELOAD_BYPASSING_CACHE:
return WebFrameLoadType::kReloadBypassingCache;
case blink::mojom::NavigationType::HISTORY_SAME_DOCUMENT:
case blink::mojom::NavigationType::HISTORY_DIFFERENT_DOCUMENT:
return WebFrameLoadType::kBackForward;
case blink::mojom::NavigationType::RESTORE:
case blink::mojom::NavigationType::RESTORE_WITH_POST:
return WebFrameLoadType::kRestore;
case blink::mojom::NavigationType::SAME_DOCUMENT:
case blink::mojom::NavigationType::DIFFERENT_DOCUMENT:
return should_replace_current_entry
? WebFrameLoadType::kReplaceCurrentItem
: WebFrameLoadType::kStandard;
default:
NOTREACHED();
}
}
RenderFrameImpl::CreateRenderFrameImplFunction g_create_render_frame_impl =
nullptr;
WebString ConvertRelativePathToHtmlAttribute(const base::FilePath& path) {
DCHECK(!path.IsAbsolute());
return WebString::FromUTF8(
std::string("./") +
path.NormalizePathSeparatorsTo(FILE_PATH_LITERAL('/')).AsUTF8Unsafe());
}
class RenderFrameWebFrameSerializerClient
: public blink::WebFrameSerializerClient {
public:
explicit RenderFrameWebFrameSerializerClient(
mojo::PendingRemote<mojom::FrameHTMLSerializerHandler> handler_remote)
: handler_remote_(std::move(handler_remote)) {}
void DidSerializeDataForFrame(
const std::vector<char>& data,
WebFrameSerializerClient::FrameSerializationStatus status) override {
DCHECK(handler_remote_.is_bound());
handler_remote_->DidReceiveData(std::string(data.data(), data.size()));
if (status == WebFrameSerializerClient::kCurrentFrameIsFinished) {
handler_remote_->Done();
handler_remote_.reset();
}
}
private:
mojo::Remote<mojom::FrameHTMLSerializerHandler> handler_remote_;
};
class LinkRewritingDelegate : public WebFrameSerializer::LinkRewritingDelegate {
public:
LinkRewritingDelegate(
const base::flat_map<GURL, base::FilePath>& url_to_local_path,
const base::flat_map<blink::FrameToken, base::FilePath>&
frame_token_to_local_path)
: url_to_local_path_(url_to_local_path),
frame_token_to_local_path_(frame_token_to_local_path) {}
bool RewriteFrameSource(WebFrame* frame, WebString* rewritten_link) override {
const blink::FrameToken frame_token = frame->GetFrameToken();
auto it = frame_token_to_local_path_->find(frame_token);
if (it == frame_token_to_local_path_->end()) {
return false;
}
const base::FilePath& local_path = it->second;
*rewritten_link = ConvertRelativePathToHtmlAttribute(local_path);
return true;
}
bool RewriteLink(const WebURL& url, WebString* rewritten_link) override {
auto it = url_to_local_path_->find(GURL(url));
if (it == url_to_local_path_->end()) {
return false;
}
const base::FilePath& local_path = it->second;
*rewritten_link = ConvertRelativePathToHtmlAttribute(local_path);
return true;
}
private:
const raw_ref<const base::flat_map<GURL, base::FilePath>> url_to_local_path_;
const raw_ref<const base::flat_map<blink::FrameToken, base::FilePath>>
frame_token_to_local_path_;
};
bool IsHttpPost(const blink::WebURLRequest& request) {
return request.HttpMethod().Utf8() == "POST";
}
class MHTMLHandleWriterDelegate {
public:
MHTMLHandleWriterDelegate(
const mojom::SerializeAsMHTMLParams& params,
MHTMLHandleWriter::MHTMLWriteCompleteCallback callback,
scoped_refptr<base::TaskRunner> main_thread_task_runner) {
DCHECK(params.output_handle);
if (params.output_handle->is_file_handle()) {
handle_ = std::make_unique<MHTMLFileHandleWriter>(
std::move(main_thread_task_runner), std::move(callback),
std::move(params.output_handle->get_file_handle()));
} else {
handle_ = std::make_unique<MHTMLProducerHandleWriter>(
std::move(main_thread_task_runner), std::move(callback),
std::move(params.output_handle->get_producer_handle()));
}
}
MHTMLHandleWriterDelegate(const MHTMLHandleWriterDelegate&) = delete;
MHTMLHandleWriterDelegate& operator=(const MHTMLHandleWriterDelegate&) =
delete;
void WriteContents(std::vector<WebThreadSafeData> mhtml_contents) {
base::ThreadPool::PostTask(
FROM_HERE, {base::MayBlock()},
base::BindOnce(&MHTMLHandleWriter::WriteContents, std::move(handle_),
std::move(mhtml_contents)));
}
void Finish(mojom::MhtmlSaveStatus save_status) {
base::ThreadPool::PostTask(FROM_HERE, {base::MayBlock()},
base::BindOnce(&MHTMLHandleWriter::Finish,
std::move(handle_), save_status));
}
private:
std::unique_ptr<MHTMLHandleWriter> handle_;
};
mojo::PendingRemote<blink::mojom::BlobURLToken> CloneBlobURLToken(
blink::CrossVariantMojoRemote<blink::mojom::BlobURLTokenInterfaceBase>&
blob_url_token) {
if (!blob_url_token)
return mojo::NullRemote();
mojo::PendingRemote<blink::mojom::BlobURLToken> cloned_token;
mojo::Remote<blink::mojom::BlobURLToken> token(std::move(blob_url_token));
token->Clone(cloned_token.InitWithNewPipeAndPassReceiver());
blob_url_token = token.Unbind();
return cloned_token;
}
std::unique_ptr<DocumentState> BuildDocumentState() {
std::unique_ptr<DocumentState> document_state =
std::make_unique<DocumentState>();
document_state->set_navigation_state(
NavigationState::CreateForSynchronousCommit());
return document_state;
}
std::unique_ptr<DocumentState> BuildDocumentStateFromParams(
const blink::mojom::CommonNavigationParams& common_params,
const blink::mojom::CommitNavigationParams& commit_params,
mojom::NavigationClient::CommitNavigationCallback commit_callback,
std::unique_ptr<NavigationClient> navigation_client,
int request_id,
bool was_initiated_in_this_frame) {
std::unique_ptr<DocumentState> document_state(new DocumentState());
DCHECK(!common_params.navigation_start.is_null());
DCHECK(!common_params.url.SchemeIs(url::kJavaScriptScheme));
document_state->set_is_overriding_user_agent(
commit_params.is_overriding_user_agent);
document_state->set_request_id(request_id);
document_state->set_was_load_data_with_base_url_request(
commit_params.is_load_data_with_base_url);
if (commit_params.is_load_data_with_base_url)
document_state->set_data_url(common_params.url);
document_state->set_navigation_state(
NavigationState::CreateForCrossDocumentCommit(
common_params.Clone(), commit_params.Clone(),
std::move(commit_callback), std::move(navigation_client),
was_initiated_in_this_frame));
return document_state;
}
std::optional<WebURL> ApplyFilePathAlias(const WebURL& target) {
const base::CommandLine::StringType file_url_path_alias =
base::CommandLine::ForCurrentProcess()->GetSwitchValueNative(
switches::kFileUrlPathAlias);
if (file_url_path_alias.empty()) {
return std::nullopt;
}
const auto alias_mapping =
base::SplitString(file_url_path_alias, FILE_PATH_LITERAL("="),
base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
if (alias_mapping.size() != 2) {
LOG(ERROR) << "Invalid file path alias format.";
return std::nullopt;
}
#if BUILDFLAG(IS_WIN)
std::wstring path = base::UTF16ToWide(target.GetString().Utf16());
const std::wstring file_prefix =
base::ASCIIToWide(url::kFileScheme) +
base::ASCIIToWide(url::kStandardSchemeSeparator);
#else
std::string path = target.GetString().Utf8();
const std::string file_prefix =
std::string(url::kFileScheme) + url::kStandardSchemeSeparator;
#endif
if (!base::StartsWith(path, file_prefix + alias_mapping[0],
base::CompareCase::SENSITIVE)) {
return std::nullopt;
}
base::ReplaceFirstSubstringAfterOffset(&path, 0, alias_mapping[0],
alias_mapping[1]);
#if BUILDFLAG(IS_WIN)
return blink::WebURL(GURL(base::WideToUTF8(path)));
#else
return blink::WebURL(GURL(path));
#endif
}
blink::WebNavigationTimings BuildNavigationTimings(
base::TimeTicks navigation_start,
const blink::mojom::NavigationTiming& browser_navigation_timings,
base::TimeTicks input_start) {
blink::WebNavigationTimings renderer_navigation_timings;
DCHECK(!navigation_start.is_null());
renderer_navigation_timings.navigation_start =
std::min(navigation_start, base::TimeTicks::Now());
renderer_navigation_timings.redirect_start =
browser_navigation_timings.redirect_start;
renderer_navigation_timings.redirect_end =
browser_navigation_timings.redirect_end;
renderer_navigation_timings.fetch_start =
browser_navigation_timings.fetch_start;
renderer_navigation_timings.input_start = input_start;
renderer_navigation_timings.parent_resource_timing_access =
browser_navigation_timings.parent_resource_timing_access;
return renderer_navigation_timings;
}
WebHistoryItem NavigationApiHistoryEntryPtrToWebHistoryItem(
const blink::mojom::NavigationApiHistoryEntry& entry) {
return WebHistoryItem(
WebString::FromUTF16(entry.url), WebString::FromUTF16(entry.key),
WebString::FromUTF16(entry.id), entry.item_sequence_number,
entry.document_sequence_number, WebString::FromUTF16(entry.state));
}
void FillMiscNavigationParams(
const blink::mojom::CommonNavigationParams& common_params,
blink::mojom::CommitNavigationParams& commit_params,
blink::WebNavigationParams* navigation_params) {
navigation_params->navigation_timings = BuildNavigationTimings(
common_params.navigation_start, *commit_params.navigation_timing,
common_params.input_start);
if (!commit_params.redirect_infos.empty()) {
navigation_params->navigation_timings.critical_ch_restart =
commit_params.redirect_infos.back().critical_ch_restart_time;
}
navigation_params->is_user_activated =
commit_params.was_activated == blink::mojom::WasActivatedOption::kYes;
navigation_params->has_text_fragment_token =
common_params.text_fragment_token;
navigation_params->is_browser_initiated = commit_params.is_browser_initiated;
navigation_params->is_cross_site_cross_browsing_context_group =
commit_params.is_cross_site_cross_browsing_context_group;
navigation_params->should_have_sticky_user_activation =
commit_params.should_have_sticky_user_activation;
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_ARKWEB)
navigation_params->grant_load_local_resources =
commit_params.can_load_local_resources;
#else
DCHECK(!commit_params.can_load_local_resources);
#endif
navigation_params->origin_to_commit = commit_params.origin_to_commit;
navigation_params->storage_key = std::move(commit_params.storage_key);
navigation_params->frame_policy = commit_params.frame_policy;
if (common_params.navigation_type == blink::mojom::NavigationType::RESTORE) {
navigation_params->force_fetch_cache_mode =
blink::mojom::FetchCacheMode::kDefault;
}
navigation_params->origin_agent_cluster = commit_params.origin_agent_cluster;
navigation_params->origin_agent_cluster_left_as_default =
commit_params.origin_agent_cluster_left_as_default;
navigation_params->reduced_accept_language =
WebString::FromASCII(commit_params.reduced_accept_language);
navigation_params->enabled_client_hints.reserve(
commit_params.enabled_client_hints.size());
for (auto enabled_hint : commit_params.enabled_client_hints)
navigation_params->enabled_client_hints.emplace_back(enabled_hint);
if (commit_params.http_response_code != -1)
navigation_params->http_status_code = commit_params.http_response_code;
navigation_params->modified_runtime_features =
commit_params.modified_runtime_features;
auto& entry_arrays = commit_params.navigation_api_history_entry_arrays;
navigation_params->navigation_api_back_entries.reserve(
entry_arrays->back_entries.size());
for (const auto& entry : entry_arrays->back_entries) {
navigation_params->navigation_api_back_entries.emplace_back(
NavigationApiHistoryEntryPtrToWebHistoryItem(*entry));
}
navigation_params->navigation_api_forward_entries.reserve(
entry_arrays->forward_entries.size());
for (const auto& entry : entry_arrays->forward_entries) {
navigation_params->navigation_api_forward_entries.emplace_back(
NavigationApiHistoryEntryPtrToWebHistoryItem(*entry));
}
if (entry_arrays->previous_entry) {
navigation_params->navigation_api_previous_entry =
NavigationApiHistoryEntryPtrToWebHistoryItem(
*entry_arrays->previous_entry);
}
if (commit_params.fenced_frame_properties) {
navigation_params->fenced_frame_properties =
commit_params.fenced_frame_properties;
if (commit_params.fenced_frame_properties->nested_urn_config_pairs() &&
commit_params.fenced_frame_properties->nested_urn_config_pairs()
->potentially_opaque_value.has_value()) {
const auto& nested_urn_config_pairs_value =
commit_params.fenced_frame_properties->nested_urn_config_pairs()
->potentially_opaque_value.value();
DCHECK_EQ(blink::MaxAdAuctionAdComponents(),
nested_urn_config_pairs_value.size());
navigation_params->ad_auction_components.emplace();
for (const auto& nested_urn_config_pair : nested_urn_config_pairs_value) {
const GURL& urn = nested_urn_config_pair.first;
DCHECK(urn.SchemeIs(url::kUrnScheme));
navigation_params->ad_auction_components->push_back(blink::WebURL(urn));
}
}
}
navigation_params->ancestor_or_self_has_cspee =
commit_params.ancestor_or_self_has_cspee;
navigation_params->browsing_context_group_token =
commit_params.browsing_context_group_token;
navigation_params->content_settings =
std::move(commit_params.content_settings);
navigation_params->initial_permission_statuses =
std::move(commit_params.initial_permission_statuses);
navigation_params->force_new_document_sequence_number =
commit_params.force_new_document_sequence_number;
}
std::string GetUniqueNameOfWebFrame(WebFrame* web_frame) {
if (web_frame->IsWebLocalFrame())
return RenderFrameImpl::FromWebFrame(web_frame)->unique_name();
return web_frame->ToWebRemoteFrame()->UniqueName().Utf8();
}
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();
}
void CallClientDeferMediaLoad(base::WeakPtr<RenderFrameImpl> frame,
bool has_played_media_before,
base::OnceClosure closure) {
if (!frame)
return;
GetContentClient()->renderer()->DeferMediaLoad(
frame.get(), has_played_media_before, std::move(closure));
}
void LogCommitHistograms(base::TimeTicks commit_sent,
bool is_main_frame,
const GURL& new_page_url) {
if (!base::TimeTicks::IsConsistentAcrossProcesses())
return;
const char* frame_type = is_main_frame ? "MainFrame" : "Subframe";
auto now = base::TimeTicks::Now();
base::UmaHistogramTimes(
base::StrCat({"Navigation.RendererCommitDelay.", frame_type}),
now - commit_sent);
if (auto* task = base::TaskAnnotator::CurrentTaskForThread()) {
base::UmaHistogramTimes(
base::StrCat({"Navigation.RendererCommitQueueTime.", frame_type}),
now - task->queue_time);
}
if (!RenderThreadImpl::current())
return;
base::TimeTicks run_loop_start_time =
RenderThreadImpl::current()->run_loop_start_time();
if (commit_sent < run_loop_start_time) {
base::UmaHistogramTimes(
base::StrCat({"Navigation.RendererCommitProcessWaitTime.", frame_type}),
run_loop_start_time - commit_sent);
}
static bool is_first_commit = true;
if (is_first_commit) {
is_first_commit = false;
if (run_loop_start_time <= now && new_page_url.is_valid() &&
new_page_url.SchemeIsHTTPOrHTTPS()) {
const char* const name =
is_main_frame
? "Navigation.RendererRunLoopStartToFirstCommitNavigation2."
"MainFrame"
: "Navigation.RendererRunLoopStartToFirstCommitNavigation2."
"Subframe";
const auto trace_id = perfetto::NamedTrack(
perfetto::StaticString(name),
reinterpret_cast<uintptr_t>(RenderThreadImpl::current()));
TRACE_EVENT_BEGIN("navigation", perfetto::StaticString(name), trace_id,
run_loop_start_time, "url", new_page_url);
TRACE_EVENT_END("navigation", trace_id, now);
base::UmaHistogramLongTimes(name, now - run_loop_start_time);
}
}
}
content::mojom::WindowContainerType WindowFeaturesToContainerType(
const blink::WebWindowFeatures& window_features) {
if (window_features.background) {
if (window_features.persistent)
return content::mojom::WindowContainerType::PERSISTENT;
else
return content::mojom::WindowContainerType::BACKGROUND;
} else {
return content::mojom::WindowContainerType::NORMAL;
}
}
WindowOpenDisposition NavigationPolicyToDisposition(
WebNavigationPolicy policy) {
switch (policy) {
case blink::kWebNavigationPolicyDownload:
return WindowOpenDisposition::SAVE_TO_DISK;
case blink::kWebNavigationPolicyCurrentTab:
return WindowOpenDisposition::CURRENT_TAB;
case blink::kWebNavigationPolicyNewBackgroundTab:
return WindowOpenDisposition::NEW_BACKGROUND_TAB;
case blink::kWebNavigationPolicyNewForegroundTab:
return WindowOpenDisposition::NEW_FOREGROUND_TAB;
case blink::kWebNavigationPolicyNewWindow:
return WindowOpenDisposition::NEW_WINDOW;
case blink::kWebNavigationPolicyNewPopup:
return WindowOpenDisposition::NEW_POPUP;
case blink::kWebNavigationPolicyPictureInPicture:
return WindowOpenDisposition::NEW_PICTURE_IN_PICTURE;
}
NOTREACHED() << "Unexpected WebNavigationPolicy";
}
bool ShouldNotifySubresourceResponseStarted(
const blink::RendererPreferences& pref) {
if (!base::FeatureList::IsEnabled(
features::kReduceSubresourceResponseStartedIPC)) {
return true;
}
return pref.send_subresource_notification;
}
void InitializeFrameWidgetForFrame(
WebLocalFrame& frame,
mojom::CreateFrameWidgetParamsPtr widget_params,
const bool is_for_nested_main_frame) {
CHECK(widget_params);
const bool is_main_frame = !frame.Parent();
CHECK(is_main_frame || !is_for_nested_main_frame);
const bool is_for_scalable_page =
is_main_frame && !frame.View()->IsFencedFrameRoot();
const auto frame_sink_id = viz::FrameSinkId(
RenderThread::Get()->GetClientId(), widget_params->routing_id);
auto* web_frame_widget = frame.InitializeFrameWidget(
std::move(widget_params->frame_widget_host),
std::move(widget_params->frame_widget),
std::move(widget_params->widget_host), std::move(widget_params->widget),
frame_sink_id, is_for_nested_main_frame, is_for_scalable_page,
true);
web_frame_widget->InitializeCompositing(
widget_params->visual_properties.screen_infos,
nullptr);
web_frame_widget->ApplyVisualProperties(widget_params->visual_properties);
}
mojo::ScopedDataPipeConsumerHandle FillResponseForInitialWebUI(
const GURL& url,
const url::Origin& origin,
const blink::mojom::LocalResourceLoaderConfigPtr&
local_resource_loader_config,
network::mojom::URLResponseHeadPtr* response_head,
mojo::PendingRemote<network::mojom::URLLoaderClient> client_remote) {
CHECK(local_resource_loader_config->sources.contains(origin));
const blink::mojom::LocalResourceSourcePtr& source =
local_resource_loader_config->sources[origin];
const std::map<std::string, std::string> replacement_strings(
source->replacement_strings.begin(), source->replacement_strings.end());
auto [response_body, output_size] =
webui::GetPipe(LocalResourceURLLoaderFactory::GetResource(
url, source, replacement_strings, "text/html"),
std::nullopt);
(*response_head)->content_length = output_size;
mojo::Remote<network::mojom::URLLoaderClient> client(
std::move(client_remote));
network::URLLoaderCompletionStatus status(net::OK);
status.encoded_data_length = output_size;
status.encoded_body_length = output_size;
status.decoded_body_length = output_size;
client->OnComplete(status);
return std::move(response_body);
}
}
#if BUILDFLAG(IS_ARKWEB)
#include "arkweb/chromium_ext/content/renderer/render_frame_impl_for_include.cc"
#endif
class MHTMLPartsGenerationDelegateImpl final
: public WebFrameSerializer::MHTMLPartsGenerationDelegate {
public:
explicit MHTMLPartsGenerationDelegateImpl(
mojom::SerializeAsMHTMLParamsPtr params)
: params_(std::move(params)) {
DCHECK(std::is_sorted(params_->digests_of_uris_to_skip.begin(),
params_->digests_of_uris_to_skip.end()));
DCHECK(std::ranges::adjacent_find(params_->digests_of_uris_to_skip) ==
params_->digests_of_uris_to_skip.end());
}
MHTMLPartsGenerationDelegateImpl(const MHTMLPartsGenerationDelegateImpl&) =
delete;
MHTMLPartsGenerationDelegateImpl& operator=(
const MHTMLPartsGenerationDelegateImpl&) = delete;
bool ShouldSkipResource(const WebURL& url) override {
std::string digest =
crypto::SHA256HashString(params_->salt + GURL(url).spec());
if (std::binary_search(params_->digests_of_uris_to_skip.begin(),
params_->digests_of_uris_to_skip.end(), digest)) {
return true;
}
auto pair = serialized_resources_uri_digests_.insert(digest);
bool insertion_took_place = pair.second;
DCHECK(insertion_took_place);
return false;
}
bool UseBinaryEncoding() override { return params_->mhtml_binary_encoding; }
bool RemovePopupOverlay() override {
return params_->mhtml_popup_overlay_removal;
}
std::unordered_set<std::string> TakeSerializedResourcesUriDigests() {
return std::move(serialized_resources_uri_digests_);
}
mojom::SerializeAsMHTMLParamsPtr TakeParams() { return std::move(params_); }
private:
std::vector<std::string> digests_of_uris_to_skip_;
mojom::SerializeAsMHTMLParamsPtr params_;
std::unordered_set<std::string> serialized_resources_uri_digests_;
};
RenderFrameImpl::AssertNavigationCommits::AssertNavigationCommits(
RenderFrameImpl* frame)
: AssertNavigationCommits(frame, false) {}
RenderFrameImpl::AssertNavigationCommits::AssertNavigationCommits(
RenderFrameImpl* frame,
MayReplaceInitialEmptyDocumentTag)
: AssertNavigationCommits(frame, true) {}
RenderFrameImpl::AssertNavigationCommits::~AssertNavigationCommits() {
if (frame_) {
CHECK_EQ(NavigationCommitState::kDidCommit,
frame_->navigation_commit_state_);
frame_->navigation_commit_state_ = NavigationCommitState::kNone;
}
}
RenderFrameImpl::AssertNavigationCommits::AssertNavigationCommits(
RenderFrameImpl* frame,
bool allow_transition_from_initial_empty_document)
: frame_(frame->weak_factory_.GetWeakPtr()) {
if (NavigationCommitState::kNone != frame->navigation_commit_state_) {
CHECK(allow_transition_from_initial_empty_document);
CHECK_EQ(NavigationCommitState::kInitialEmptyDocument,
frame->navigation_commit_state_);
}
frame->navigation_commit_state_ = NavigationCommitState::kWillCommit;
}
class RenderFrameImpl::MHTMLBodyLoaderClient
: public blink::WebNavigationBodyLoader::Client {
public:
MHTMLBodyLoaderClient(
RenderFrameImpl* frame,
std::unique_ptr<blink::WebNavigationParams> navigation_params,
base::OnceCallback<void(std::unique_ptr<blink::WebNavigationParams>)>
done_callback)
: frame_(frame),
navigation_params_(std::move(navigation_params)),
body_loader_(std::move(navigation_params_->body_loader)),
done_callback_(std::move(done_callback)) {
body_loader_->StartLoadingBody(this);
}
MHTMLBodyLoaderClient(const MHTMLBodyLoaderClient&) = delete;
MHTMLBodyLoaderClient& operator=(const MHTMLBodyLoaderClient&) = delete;
~MHTMLBodyLoaderClient() override {
CHECK(
committing_ ||
!frame_ ||
NavigationCommitState::kWillCommit == frame_->navigation_commit_state_);
}
void Detach() {
frame_ = nullptr;
}
void BodyDataReceived(base::span<const char> data) override {
data_.Append(base::as_bytes(data));
}
void BodyLoadingFinished(base::TimeTicks completion_time,
int64_t total_encoded_data_length,
int64_t total_encoded_body_length,
int64_t total_decoded_body_length,
const std::optional<WebURLError>& error) override {
committing_ = true;
AssertNavigationCommits assert_navigation_commits(frame_);
if (!error.has_value()) {
WebNavigationParams::FillBodyLoader(navigation_params_.get(), data_);
navigation_params_->is_static_data = false;
}
std::move(done_callback_).Run(std::move(navigation_params_));
}
private:
raw_ptr<RenderFrameImpl> frame_;
bool committing_ = false;
WebData data_;
std::unique_ptr<blink::WebNavigationParams> navigation_params_;
std::unique_ptr<blink::WebNavigationBodyLoader> body_loader_;
base::OnceCallback<void(std::unique_ptr<blink::WebNavigationParams>)>
done_callback_;
};
RenderFrameImpl::UniqueNameFrameAdapter::UniqueNameFrameAdapter(
RenderFrameImpl* render_frame)
: render_frame_(render_frame) {}
RenderFrameImpl::UniqueNameFrameAdapter::~UniqueNameFrameAdapter() {}
bool RenderFrameImpl::UniqueNameFrameAdapter::IsMainFrame() const {
return render_frame_->IsMainFrame();
}
bool RenderFrameImpl::UniqueNameFrameAdapter::IsCandidateUnique(
std::string_view name) const {
DCHECK(!name.empty());
for (blink::WebFrame* frame = GetWebFrame()->Top(); frame;
frame = frame->TraverseNext()) {
if (GetUniqueNameOfWebFrame(frame) == name)
return false;
}
return true;
}
int RenderFrameImpl::UniqueNameFrameAdapter::GetSiblingCount() const {
int sibling_count = 0;
for (blink::WebFrame* frame = GetWebFrame()->Parent()->FirstChild(); frame;
frame = frame->NextSibling()) {
if (frame == GetWebFrame())
continue;
++sibling_count;
}
return sibling_count;
}
int RenderFrameImpl::UniqueNameFrameAdapter::GetChildCount() const {
int child_count = 0;
for (blink::WebFrame* frame = GetWebFrame()->FirstChild(); frame;
frame = frame->NextSibling()) {
++child_count;
}
return child_count;
}
std::vector<std::string>
RenderFrameImpl::UniqueNameFrameAdapter::CollectAncestorNames(
BeginPoint begin_point,
bool (*should_stop)(std::string_view)) const {
std::vector<std::string> result;
for (blink::WebFrame* frame = begin_point == BeginPoint::kParentFrame
? GetWebFrame()->Parent()
: GetWebFrame();
frame; frame = frame->Parent()) {
result.push_back(GetUniqueNameOfWebFrame(frame));
if (should_stop(result.back()))
break;
}
return result;
}
std::vector<int> RenderFrameImpl::UniqueNameFrameAdapter::GetFramePosition(
BeginPoint begin_point) const {
std::vector<int> result;
blink::WebFrame* parent = begin_point == BeginPoint::kParentFrame
? GetWebFrame()->Parent()
: GetWebFrame();
blink::WebFrame* child =
begin_point == BeginPoint::kParentFrame ? GetWebFrame() : nullptr;
while (parent) {
int position_in_parent = 0;
blink::WebFrame* sibling = parent->FirstChild();
while (sibling != child) {
sibling = sibling->NextSibling();
++position_in_parent;
}
result.push_back(position_in_parent);
child = parent;
parent = parent->Parent();
}
return result;
}
blink::WebLocalFrame* RenderFrameImpl::UniqueNameFrameAdapter::GetWebFrame()
const {
return render_frame_->frame_;
}
RenderFrameImpl* RenderFrameImpl::Create(
AgentSchedulingGroup& agent_scheduling_group,
const blink::LocalFrameToken& frame_token,
int32_t routing_id,
mojo::PendingAssociatedReceiver<mojom::Frame> frame_receiver,
mojo::PendingAssociatedRemote<blink::mojom::AssociatedInterfaceProvider>
associated_interface_provider,
const base::UnguessableToken& devtools_frame_token,
bool is_for_nested_main_frame) {
DCHECK(routing_id != IPC::mojom::kRoutingIdNone);
CreateParams params(agent_scheduling_group, frame_token, routing_id,
std::move(frame_receiver),
std::move(associated_interface_provider),
devtools_frame_token, is_for_nested_main_frame);
if (g_create_render_frame_impl)
return g_create_render_frame_impl(std::move(params));
else
return new RenderFrameImpl(std::move(params));
}
RenderFrameImpl* RenderFrameImpl::CreateMainFrame(
AgentSchedulingGroup& agent_scheduling_group,
blink::WebView* web_view,
blink::WebFrame* opener,
bool is_for_nested_main_frame,
bool is_for_scalable_page,
blink::mojom::FrameReplicationStatePtr replication_state,
const base::UnguessableToken& devtools_frame_token,
mojom::CreateLocalMainFrameParamsPtr params,
#if BUILDFLAG(ARKWEB_ARKWEB_EXTENSIONS)
bool is_offscreen,
#endif
const blink::WebURL& base_url) {
DCHECK_NE(IPC::mojom::kRoutingIdNone, params->widget_params->routing_id);
RenderFrameImpl* render_frame = RenderFrameImpl::Create(
agent_scheduling_group, params->frame_token, params->routing_id,
std::move(params->frame),
std::move(params->associated_interface_provider_remote),
devtools_frame_token, is_for_nested_main_frame);
#if BUILDFLAG(ARKWEB_ARKWEB_EXTENSIONS)
if (render_frame) {
render_frame->is_offscreen_ = is_offscreen;
}
#endif
WebLocalFrame* web_frame = WebLocalFrame::CreateMainFrame(
web_view, render_frame, render_frame->blink_interface_registry_.get(),
std::move(params->interface_broker), params->frame_token,
params->document_token,
ToWebPolicyContainer(std::move(params->policy_container)), opener,
WebString::FromUTF8(replication_state->name),
replication_state->frame_policy.sandbox_flags, base_url);
if (!params->is_on_initial_empty_document)
render_frame->frame_->SetIsNotOnInitialEmptyDocument();
blink::WebFrameWidget* web_frame_widget = web_frame->InitializeFrameWidget(
std::move(params->widget_params->frame_widget_host),
std::move(params->widget_params->frame_widget),
std::move(params->widget_params->widget_host),
std::move(params->widget_params->widget),
viz::FrameSinkId(RenderThread::Get()->GetClientId(),
params->widget_params->routing_id),
is_for_nested_main_frame, is_for_scalable_page,
true);
web_frame_widget->InitializeCompositing(
params->widget_params->visual_properties.screen_infos,
nullptr);
render_frame->GetWebView()->DidAttachLocalMainFrame();
web_frame_widget->ApplyVisualProperties(
params->widget_params->visual_properties);
render_frame->in_frame_tree_ = true;
render_frame->Initialize(nullptr);
if (params->subresource_loader_factories
->IsTrackedChildPendingURLLoaderFactoryBundle()) {
render_frame->SetLoaderFactoryBundle(
base::MakeRefCounted<blink::TrackedChildURLLoaderFactoryBundle>(
base::WrapUnique(
static_cast<blink::TrackedChildPendingURLLoaderFactoryBundle*>(
params->subresource_loader_factories.release()))));
} else {
render_frame->SetLoaderFactoryBundle(
render_frame->CreateLoaderFactoryBundle(
std::move(params->subresource_loader_factories),
std::nullopt,
mojo::NullRemote(),
mojo::NullRemote(),
mojo::NullAssociatedRemote()));
}
return render_frame;
}
void RenderFrameImpl::CreateFrame(
AgentSchedulingGroup& agent_scheduling_group,
const blink::LocalFrameToken& frame_token,
int routing_id,
mojo::PendingAssociatedReceiver<mojom::Frame> frame_receiver,
mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>
browser_interface_broker,
mojo::PendingAssociatedRemote<blink::mojom::AssociatedInterfaceProvider>
associated_interface_provider,
blink::WebView* web_view,
base::optional_ref<const blink::FrameToken> previous_frame_token,
base::optional_ref<const blink::FrameToken> opener_frame_token,
base::optional_ref<const blink::FrameToken> parent_frame_token,
base::optional_ref<const blink::FrameToken> previous_sibling_frame_token,
const base::UnguessableToken& devtools_frame_token,
const std::optional<base::UnguessableToken>& navigation_metrics_token,
blink::mojom::TreeScopeType tree_scope_type,
blink::mojom::FrameReplicationStatePtr replicated_state,
mojom::CreateFrameWidgetParamsPtr widget_params,
blink::mojom::FrameOwnerPropertiesPtr frame_owner_properties,
bool is_on_initial_empty_document,
const blink::DocumentToken& document_token,
blink::mojom::PolicyContainerPtr policy_container,
bool is_for_nested_main_frame) {
base::ElapsedTimer timer;
RenderFrameImpl* render_frame = nullptr;
blink::WebLocalFrame* web_frame = nullptr;
if (!previous_frame_token) {
CHECK(parent_frame_token);
WebFrame* parent_web_frame =
WebFrame::FromFrameToken(parent_frame_token.value());
CHECK(parent_web_frame);
CHECK(parent_web_frame->IsWebRemoteFrame());
blink::WebFrame* previous_sibling_web_frame = nullptr;
if (previous_sibling_frame_token) {
previous_sibling_web_frame =
blink::WebFrame::FromFrameToken(previous_sibling_frame_token.value());
}
CHECK(!web_view);
web_view = parent_web_frame->View();
render_frame = RenderFrameImpl::Create(
agent_scheduling_group, frame_token, routing_id,
std::move(frame_receiver), std::move(associated_interface_provider),
devtools_frame_token, is_for_nested_main_frame);
render_frame->unique_name_helper_.set_propagated_name(
replicated_state->unique_name);
WebFrame* opener = nullptr;
if (opener_frame_token)
opener = WebFrame::FromFrameToken(opener_frame_token.value());
web_frame = parent_web_frame->ToWebRemoteFrame()->CreateLocalChild(
tree_scope_type, WebString::FromUTF8(replicated_state->name),
replicated_state->frame_policy, render_frame,
render_frame->blink_interface_registry_.get(),
previous_sibling_web_frame,
frame_owner_properties->To<blink::WebFrameOwnerProperties>(),
frame_token, opener, document_token,
std::move(browser_interface_broker),
ToWebPolicyContainer(std::move(policy_container)));
render_frame->in_frame_tree_ = true;
} else {
WebFrame* previous_web_frame =
WebFrame::FromFrameToken(previous_frame_token.value());
if (!previous_web_frame)
return;
if (web_view) {
CHECK(!previous_web_frame->Parent());
CHECK_NE(web_view, previous_web_frame->View());
} else {
web_view = previous_web_frame->View();
}
render_frame = RenderFrameImpl::Create(
agent_scheduling_group, frame_token, routing_id,
std::move(frame_receiver), std::move(associated_interface_provider),
devtools_frame_token, is_for_nested_main_frame);
web_frame = blink::WebLocalFrame::CreateProvisional(
render_frame, render_frame->blink_interface_registry_.get(),
std::move(browser_interface_broker), frame_token, previous_web_frame,
replicated_state->frame_policy,
WebString::FromUTF8(replicated_state->name), web_view);
DCHECK_EQ(!previous_web_frame->Parent(), !web_frame->Parent());
render_frame->unique_name_helper_.set_propagated_name(
GetUniqueNameOfWebFrame(previous_web_frame));
}
CHECK(web_view);
CHECK(render_frame);
CHECK(web_frame);
bool is_main_frame = !web_frame->Parent();
if (!is_main_frame)
DCHECK(parent_frame_token);
if (is_main_frame) {
DCHECK(widget_params);
DCHECK_NE(widget_params->routing_id, IPC::mojom::kRoutingIdNone);
InitializeFrameWidgetForFrame(*web_frame, std::move(widget_params),
is_for_nested_main_frame);
} else if (widget_params) {
DCHECK(widget_params->routing_id != IPC::mojom::kRoutingIdNone);
InitializeFrameWidgetForFrame(*web_frame, std::move(widget_params),
is_for_nested_main_frame);
}
if (!is_on_initial_empty_document) {
render_frame->frame_->SetIsNotOnInitialEmptyDocument();
}
render_frame->Initialize(web_frame->Parent());
RendererNavigationMetricsManager::Instance().AddCreateFrameEvent(
navigation_metrics_token, timer.start_time(), timer.Elapsed());
}
RenderFrame* RenderFrame::FromWebFrame(blink::WebLocalFrame* web_frame) {
return RenderFrameImpl::FromWebFrame(web_frame);
}
void RenderFrame::ForEach(RenderFrameVisitor* visitor) {
DCHECK(RenderThread::IsMainThread());
FrameMap* frames = g_frame_map.Pointer();
for (auto it = frames->begin(); it != frames->end(); ++it) {
if (!visitor->Visit(it->second))
return;
}
}
RenderFrameImpl* RenderFrameImpl::FromWebFrame(blink::WebFrame* web_frame) {
DCHECK(RenderThread::IsMainThread());
auto iter = g_frame_map.Get().find(web_frame);
if (iter != g_frame_map.Get().end())
return iter->second;
return nullptr;
}
void RenderFrameImpl::InstallCreateHook(
CreateRenderFrameImplFunction create_frame) {
DCHECK(!g_create_render_frame_impl);
g_create_render_frame_impl = create_frame;
}
blink::WebURL RenderFrameImpl::OverrideFlashEmbedWithHTML(
const blink::WebURL& url) {
return GetContentClient()->renderer()->OverrideFlashEmbedWithHTML(url);
}
RenderFrameImpl::CreateParams::CreateParams(
AgentSchedulingGroup& agent_scheduling_group,
const blink::LocalFrameToken& frame_token,
int32_t routing_id,
mojo::PendingAssociatedReceiver<mojom::Frame> frame_receiver,
mojo::PendingAssociatedRemote<blink::mojom::AssociatedInterfaceProvider>
associated_interface_provider,
const base::UnguessableToken& devtools_frame_token,
bool is_for_nested_main_frame)
: agent_scheduling_group(&agent_scheduling_group),
frame_token(frame_token),
routing_id(routing_id),
frame_receiver(std::move(frame_receiver)),
associated_interface_provider(std::move(associated_interface_provider)),
devtools_frame_token(devtools_frame_token),
is_for_nested_main_frame(is_for_nested_main_frame) {}
RenderFrameImpl::CreateParams::~CreateParams() = default;
RenderFrameImpl::CreateParams::CreateParams(CreateParams&&) = default;
RenderFrameImpl::CreateParams& RenderFrameImpl::CreateParams::operator=(
CreateParams&&) = default;
RenderFrameImpl::RenderFrameImpl(CreateParams params)
: agent_scheduling_group_(*params.agent_scheduling_group),
is_main_frame_(true),
unique_name_frame_adapter_(this),
unique_name_helper_(&unique_name_frame_adapter_),
in_frame_tree_(false),
frame_token_(params.frame_token),
process_label_id_(
tracing::TrackNameRecorder::GetInstance()->GetNewProcessLabelId()),
selection_text_offset_(0),
selection_range_(gfx::Range::InvalidRange()),
render_accessibility_manager_(
std::make_unique<RenderAccessibilityManager>(this)),
weak_wrapper_resource_load_info_notifier_(
std::make_unique<blink::WeakWrapperResourceLoadInfoNotifier>(this)),
navigation_client_impl_(nullptr),
media_factory_(
this,
base::BindRepeating(&RenderFrameImpl::RequestOverlayRoutingToken,
base::Unretained(this))),
devtools_frame_token_(params.devtools_frame_token) {
implUtils = new RenderFrameImplUtils(this);
TRACE_EVENT_WITH_FLOW0("navigation", "RenderFrameImpl::RenderFrameImpl",
TRACE_ID_LOCAL(this), TRACE_EVENT_FLAG_FLOW_OUT);
DCHECK(RenderThread::IsMainThread());
blink_interface_registry_ = std::make_unique<BlinkInterfaceRegistryImpl>(
registry_.GetWeakPtr(), associated_interfaces_.GetWeakPtr());
DCHECK(params.frame_receiver.is_valid());
pending_frame_receiver_ = std::move(params.frame_receiver);
DCHECK(params.associated_interface_provider.is_valid());
pending_associated_interface_provider_remote_ =
std::move(params.associated_interface_provider);
delayed_state_sync_timer_.SetTaskRunner(
agent_scheduling_group_->agent_group_scheduler().DefaultTaskRunner());
media_factory_.SetupMojo();
}
mojom::FrameHost* RenderFrameImpl::GetFrameHost() {
if (!frame_host_remote_.is_bound())
GetRemoteAssociatedInterfaces()->GetInterface(&frame_host_remote_);
return frame_host_remote_.get();
}
RenderFrameImpl::~RenderFrameImpl() {
TRACE_EVENT_WITH_FLOW0("navigation", "RenderFrameImpl::~RenderFrameImpl",
TRACE_ID_LOCAL(this), TRACE_EVENT_FLAG_FLOW_IN);
for (auto& observer : observers_)
observer.OnDestruct();
for (auto& observer : observers_)
observer.RenderFrameGone();
web_media_stream_device_observer_.reset();
if (initialized_ && is_main_frame_)
MainFrameCounter::DecrementCount();
tracing::TrackNameRecorder::GetInstance()->RemoveProcessLabel(
process_label_id_);
agent_scheduling_group_->RemoveFrameRoute(frame_token_);
#if BUILDFLAG(ARKWEB_DFX_TRACING)
delete implUtils;
#endif
}
void RenderFrameImpl::Initialize(blink::WebFrame* parent) {
initialized_ = true;
is_main_frame_ = !parent;
if (is_main_frame_)
MainFrameCounter::IncrementCount();
TRACE_EVENT1("navigation,rail", "RenderFrameImpl::Initialize", "frame_token",
frame_token_);
RegisterMojoInterfaces();
{
TRACE_EVENT("navigation", "ContentRendererClient::RenderFrameCreated");
GetContentClient()->renderer()->RenderFrameCreated(this);
}
auto& factory = blink::AudioOutputIPCFactory::GetInstance();
if (factory.io_task_runner()) {
factory.RegisterRemoteFactory(GetWebFrame()->GetLocalFrameToken(),
GetBrowserInterfaceBroker());
}
frame_receiver_.Bind(
std::move(pending_frame_receiver_),
GetTaskRunner(blink::TaskType::kInternalNavigationAssociated));
agent_scheduling_group_->AddFrameRoute(
frame_token_,
this, GetTaskRunner(blink::TaskType::kInternalNavigationAssociated));
#if BUILDFLAG(ARKWEB_DFX_TRACING)
implUtils->ReportRenderInitBlock();
#endif
}
void RenderFrameImpl::GetInterface(
const std::string& interface_name,
mojo::ScopedMessagePipeHandle interface_pipe) {
if (registry_.TryBindInterface(interface_name, &interface_pipe))
return;
for (auto& observer : observers_) {
observer.OnInterfaceRequestForFrame(interface_name, &interface_pipe);
if (!interface_pipe.is_valid())
return;
}
}
blink::WebFrameWidget* RenderFrameImpl::GetLocalRootWebFrameWidget() {
#if BUILDFLAG(ARKWEB_TEST)
if (web_frame_widget_test_mode){
web_frame_widget_test_mode = false;
return web_frame_widget_test;
}
#endif
return frame_->LocalRoot()->FrameWidget();
}
void RenderFrameImpl::ScriptedPrint() {
bool user_initiated = GetLocalRootWebFrameWidget()->HandlingInputEvent();
for (auto& observer : observers_)
observer.ScriptedPrint(user_initiated);
}
void RenderFrameImpl::OnAssociatedInterfaceRequest(
const std::string& interface_name,
mojo::ScopedInterfaceEndpointHandle handle) {
if (!associated_interfaces_.TryBindInterface(interface_name, &handle)) {
for (auto& observer : observers_) {
if (observer.OnAssociatedInterfaceRequestForFrame(interface_name,
&handle)) {
return;
}
}
}
}
void RenderFrameImpl::SetUpSharedMemoryForDroppedFrames(
base::ReadOnlySharedMemoryRegion dropped_frames_memory) {
TRACE_EVENT_WITH_FLOW0("navigation",
"RenderFrameImpl::SetUpSharedMemoryForDroppedFrames",
TRACE_ID_LOCAL(this),
TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
DCHECK(dropped_frames_memory.IsValid());
for (auto& observer : observers_) {
DCHECK(dropped_frames_memory.IsValid());
if (observer.SetUpDroppedFramesReporting(dropped_frames_memory)) {
break;
}
}
}
void RenderFrameImpl::BindAutoplayConfiguration(
mojo::PendingAssociatedReceiver<blink::mojom::AutoplayConfigurationClient>
receiver) {
autoplay_configuration_receiver_.reset();
autoplay_configuration_receiver_.Bind(
std::move(receiver),
GetTaskRunner(blink::TaskType::kInternalNavigationAssociated));
}
void RenderFrameImpl::BindFrameBindingsControl(
mojo::PendingAssociatedReceiver<mojom::FrameBindingsControl> receiver) {
frame_bindings_control_receiver_.Bind(
std::move(receiver),
GetTaskRunner(blink::TaskType::kInternalNavigationAssociated));
}
void RenderFrameImpl::BindNavigationClient(
mojo::PendingAssociatedReceiver<mojom::NavigationClient> receiver) {
NavigationClient* initiator_navigation_client = nullptr;
WebFrame* initiator_frame = GetWebFrame()->GetProvisionalOwnerFrame();
if (initiator_frame && initiator_frame->IsWebLocalFrame()) {
initiator_navigation_client = RenderFrameImpl::FromWebFrame(initiator_frame)
->navigation_client_impl_.get();
}
navigation_client_impl_ =
std::make_unique<NavigationClient>(this, initiator_navigation_client);
navigation_client_impl_->Bind(std::move(receiver));
}
void RenderFrameImpl::BindNavigationClientWithParams(
mojo::PendingAssociatedReceiver<mojom::NavigationClient> receiver,
blink::mojom::BeginNavigationParamsPtr begin_params,
blink::mojom::CommonNavigationParamsPtr common_params,
bool is_duplicate_navigation) {
if (navigation_client_impl_) {
navigation_client_impl_->ResetForNewNavigation(is_duplicate_navigation);
}
navigation_client_impl_ = std::make_unique<NavigationClient>(
this, std::move(begin_params), std::move(common_params));
navigation_client_impl_->Bind(std::move(receiver));
}
void RenderFrameImpl::Unload(
bool is_loading,
blink::mojom::FrameReplicationStatePtr replicated_frame_state,
const blink::RemoteFrameToken& proxy_frame_token,
blink::mojom::RemoteFrameInterfacesFromBrowserPtr remote_frame_interfaces,
blink::mojom::RemoteMainFrameInterfacesPtr remote_main_frame_interfaces,
const std::optional<base::UnguessableToken>& devtools_frame_token) {
TRACE_EVENT1("navigation,rail", "RenderFrameImpl::UnloadFrame", "frame_token",
frame_token_);
DCHECK(!base::RunLoop::IsNestedOnCurrentThread());
SendUpdateState();
auto& agent_scheduling_group = *agent_scheduling_group_;
blink::LocalFrameToken frame_token = frame_->GetLocalFrameToken();
scoped_refptr<base::SingleThreadTaskRunner> task_runner =
GetTaskRunner(blink::TaskType::kInternalPostMessageForwarding);
if (!SwapOutAndDeleteThis(
is_loading, std::move(replicated_frame_state), proxy_frame_token,
std::move(remote_frame_interfaces),
std::move(remote_main_frame_interfaces), devtools_frame_token)) {
return;
}
auto send_unload_ack = base::BindOnce(
[](AgentSchedulingGroup* agent_scheduling_group,
const blink::LocalFrameToken& frame_token) {
agent_scheduling_group->DidUnloadRenderFrame(frame_token);
},
&agent_scheduling_group, frame_token);
task_runner->PostTask(FROM_HERE, std::move(send_unload_ack));
}
void RenderFrameImpl::Delete(mojom::FrameDeleteIntention intent) {
TRACE_EVENT(
"navigation", "RenderFrameImpl::Delete", [&](perfetto::EventContext ctx) {
auto* event = ctx.event<perfetto::protos::pbzero::ChromeTrackEvent>();
auto* data = event->set_render_frame_impl_deletion();
data->set_intent(FrameDeleteIntentionToProto(intent));
});
base::ScopedUmaHistogramTimer histogram_timer("Navigation.RenderFrameDelete");
switch (intent) {
case mojom::FrameDeleteIntention::kNotMainFrame:
DCHECK(!is_main_frame_);
break;
case mojom::FrameDeleteIntention::kSpeculativeMainFrameForShutdown:
DCHECK(is_main_frame_);
if (in_frame_tree_)
return;
break;
case mojom::FrameDeleteIntention::
kSpeculativeMainFrameForNavigationCancelled:
DCHECK(is_main_frame_);
#if !BUILDFLAG(IS_ANDROID)
CHECK(!in_frame_tree_);
#else
CHECK(!in_frame_tree_);
#endif
break;
}
frame_->Detach();
}
void RenderFrameImpl::UndoCommitNavigation(
bool is_loading,
blink::mojom::FrameReplicationStatePtr replicated_frame_state,
const blink::RemoteFrameToken& proxy_frame_token,
blink::mojom::RemoteFrameInterfacesFromBrowserPtr remote_frame_interfaces,
blink::mojom::RemoteMainFrameInterfacesPtr remote_main_frame_interfaces) {
SwapOutAndDeleteThis(is_loading, std::move(replicated_frame_state),
proxy_frame_token, std::move(remote_frame_interfaces),
std::move(remote_main_frame_interfaces),
std::nullopt);
}
void RenderFrameImpl::SnapshotAccessibilityTree(
mojom::SnapshotAccessibilityTreeParamsPtr params,
SnapshotAccessibilityTreeCallback callback) {
ui::AXTreeUpdate response;
AXTreeSnapshotterImpl snapshotter(this, ui::AXMode(params->ax_mode));
snapshotter.Snapshot(params->max_nodes, params->timeout, &response);
std::move(callback).Run(response);
}
void RenderFrameImpl::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> handler_remote) {
LinkRewritingDelegate delegate(url_map, frame_token_map);
RenderFrameWebFrameSerializerClient client(std::move(handler_remote));
WebFrameSerializer::Serialize(GetWebFrame(), &client, &delegate,
save_with_empty_url);
}
void RenderFrameImpl::SetWantErrorMessageStackTrace() {
want_error_message_stack_trace_ = true;
GetAgentGroupScheduler().Isolate()->SetCaptureStackTraceForUncaughtExceptions(
true);
}
void RenderFrameImpl::NotifyObserversOfFailedProvisionalLoad() {
for (auto& observer : observers_)
observer.DidFailProvisionalLoad();
}
void RenderFrameImpl::DidMeaningfulLayout(
blink::WebMeaningfulLayout layout_type) {
for (auto& observer : observers_)
observer.DidMeaningfulLayout(layout_type);
}
RenderFrame* RenderFrameImpl::GetMainRenderFrame() {
WebFrame* main_frame = GetWebView()->MainFrame();
DCHECK(main_frame);
if (!main_frame->IsWebLocalFrame())
return nullptr;
return RenderFrame::FromWebFrame(main_frame->ToWebLocalFrame());
}
RenderAccessibility* RenderFrameImpl::GetRenderAccessibility() {
return render_accessibility_manager_->GetRenderAccessibilityImpl();
}
std::unique_ptr<AXTreeSnapshotter> RenderFrameImpl::CreateAXTreeSnapshotter(
ui::AXMode ax_mode) {
return std::make_unique<AXTreeSnapshotterImpl>(this, ax_mode);
}
blink::WebLocalFrame* RenderFrameImpl::GetWebFrame() {
DCHECK(frame_);
return frame_;
}
const blink::WebLocalFrame* RenderFrameImpl::GetWebFrame() const {
DCHECK(frame_);
return frame_;
}
blink::WebView* RenderFrameImpl::GetWebView() {
#if BUILDFLAG(ARKWEB_TEST)
if (web_view_test_mode) {
web_view_test_mode = false;
return web_view_test;
}
#endif
blink::WebView* web_view = GetWebFrame()->View();
DCHECK(web_view);
return web_view;
}
const blink::WebView* RenderFrameImpl::GetWebView() const {
const blink::WebView* web_view = GetWebFrame()->View();
DCHECK(web_view);
return web_view;
}
const blink::web_pref::WebPreferences& RenderFrameImpl::GetBlinkPreferences() {
return GetWebView()->GetWebPreferences();
}
const blink::RendererPreferences& RenderFrameImpl::GetRendererPreferences()
const {
return GetWebView()->GetRendererPreferences();
}
void RenderFrameImpl::ShowVirtualKeyboard() {
GetLocalRootWebFrameWidget()->ShowVirtualKeyboard();
}
void RenderFrameImpl::ExecuteJavaScript(const std::u16string& javascript) {
v8::HandleScope handle_scope(GetAgentGroupScheduler().Isolate());
frame_->ExecuteScript(WebScriptSource(WebString::FromUTF16(javascript)));
}
void RenderFrameImpl::BindLocalInterface(
const std::string& interface_name,
mojo::ScopedMessagePipeHandle interface_pipe) {
GetInterface(interface_name, std::move(interface_pipe));
}
blink::AssociatedInterfaceRegistry*
RenderFrameImpl::GetAssociatedInterfaceRegistry() {
return &associated_interfaces_;
}
blink::AssociatedInterfaceProvider*
RenderFrameImpl::GetRemoteAssociatedInterfaces() {
if (!remote_associated_interfaces_) {
DCHECK(pending_associated_interface_provider_remote_);
remote_associated_interfaces_ =
std::make_unique<blink::AssociatedInterfaceProvider>(
std::move(pending_associated_interface_provider_remote_),
GetTaskRunner(blink::TaskType::kInternalNavigationAssociated));
}
return remote_associated_interfaces_.get();
}
void RenderFrameImpl::SetSelectedText(const std::u16string& selection_text,
size_t offset,
const gfx::Range& range) {
GetWebFrame()->TextSelectionChanged(WebString::FromUTF16(selection_text),
static_cast<uint32_t>(offset), range);
}
void RenderFrameImpl::AddMessageToConsole(
blink::mojom::ConsoleMessageLevel level,
const std::string& message) {
AddMessageToConsoleImpl(level, message, false );
}
bool RenderFrameImpl::IsPasting() {
return GetLocalRootWebFrameWidget()->IsPasting();
}
void RenderFrameImpl::AddAutoplayFlags(const url::Origin& origin,
const int32_t flags) {
if (autoplay_flags_.first == origin) {
autoplay_flags_.second |= flags;
} else {
autoplay_flags_ = std::make_pair(origin, flags);
}
}
#if BUILDFLAG(IS_ANDROID)
void RenderFrameImpl::NotifyUpdateUserGestureCarryoverInfo() {
GetFrameHost()->UpdateUserGestureCarryoverInfo();
}
#endif
void RenderFrameImpl::NotifyResourceRedirectReceived(
const net::RedirectInfo& redirect_info,
network::mojom::URLResponseHeadPtr redirect_response) {}
void RenderFrameImpl::NotifyResourceResponseReceived(
int64_t request_id,
const url::SchemeHostPort& final_response_url,
network::mojom::URLResponseHeadPtr response_head,
network::mojom::RequestDestination request_destination,
bool is_ad_resource) {
if (!blink::IsRequestDestinationFrame(request_destination)) {
bool notify = ShouldNotifySubresourceResponseStarted(
GetWebView()->GetRendererPreferences());
UMA_HISTOGRAM_BOOLEAN(
"Renderer.ReduceSubresourceResponseIPC.DidNotifyBrowser", notify);
if (notify) {
GetFrameHost()->SubresourceResponseStarted(final_response_url,
response_head->cert_status);
}
}
DidStartResponse(final_response_url, request_id, std::move(response_head),
request_destination, is_ad_resource);
}
void RenderFrameImpl::NotifyResourceTransferSizeUpdated(
int64_t request_id,
int32_t transfer_size_diff) {
DidReceiveTransferSizeUpdate(request_id, transfer_size_diff);
}
void RenderFrameImpl::NotifyResourceLoadCompleted(
blink::mojom::ResourceLoadInfoPtr resource_load_info,
const network::URLLoaderCompletionStatus& status) {
DidCompleteResponse(resource_load_info->request_id, status);
GetFrameHost()->ResourceLoadComplete(std::move(resource_load_info));
}
void RenderFrameImpl::NotifyResourceLoadCanceled(int64_t request_id) {
DidCancelResponse(request_id);
}
void RenderFrameImpl::Clone(
mojo::PendingReceiver<blink::mojom::ResourceLoadInfoNotifier>
pending_resource_load_info_notifier) {
resource_load_info_notifier_receivers_.Add(
this, std::move(pending_resource_load_info_notifier),
agent_scheduling_group_->agent_group_scheduler().DefaultTaskRunner());
}
void RenderFrameImpl::GetInterfaceProvider(
mojo::PendingReceiver<service_manager::mojom::InterfaceProvider> receiver) {
auto task_runner = GetTaskRunner(blink::TaskType::kInternalDefault);
DCHECK(task_runner);
interface_provider_receivers_.Add(this, std::move(receiver), task_runner);
}
void RenderFrameImpl::AllowBindings(int64_t enabled_bindings_flags) {
auto new_bindings =
BindingsPolicySet::FromEnumBitmask(enabled_bindings_flags);
enabled_bindings_.PutAll(new_bindings);
if (new_bindings.Has(BindingsPolicyValue::kMojoWebUi)) {
blink::WebV8Features::AllowMojoJSForProcess();
}
}
void RenderFrameImpl::EnableMojoJsBindings(
content::mojom::ExtraMojoJsFeaturesPtr features) {
enable_mojo_js_bindings_ = true;
mojo_js_features_ = std::move(features);
blink::WebV8Features::AllowMojoJSForProcess();
}
void RenderFrameImpl::EnableMojoJsBindingsWithBroker(
mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker> broker) {
mojo_js_interface_broker_ = std::move(broker);
blink::WebV8Features::AllowMojoJSForProcess();
}
void RenderFrameImpl::BindWebUI(
mojo::PendingAssociatedReceiver<mojom::WebUI> receiver,
mojo::PendingAssociatedRemote<mojom::WebUIHost> remote) {
DCHECK(enabled_bindings_.Has(BindingsPolicyValue::kWebUi));
WebUIExtensionData::Create(this, std::move(receiver), std::move(remote));
}
void RenderFrameImpl::SetOldPageLifecycleStateFromNewPageCommitIfNeeded(
const blink::mojom::OldPageInfo* old_page_info,
const GURL& new_page_url) {
if (!old_page_info)
return;
WebLocalFrame* old_main_web_frame = WebLocalFrame::FromFrameToken(
old_page_info->frame_token_for_old_main_frame);
if (!old_main_web_frame) {
return;
}
RenderFrameImpl* old_main_render_frame =
RenderFrameImpl::FromWebFrame(old_main_web_frame);
if (!old_main_render_frame) {
return;
}
if (!IsMainFrame() && !old_main_render_frame->IsMainFrame()) {
SCOPED_CRASH_KEY_BOOL("old_page_info", "new_is_main_frame", IsMainFrame());
SCOPED_CRASH_KEY_STRING256("old_page_info", "new_url", new_page_url.spec());
SCOPED_CRASH_KEY_BOOL("old_page_info", "old_is_main_frame",
old_main_render_frame->IsMainFrame());
SCOPED_CRASH_KEY_STRING256("old_page_info", "old_url",
old_main_render_frame->GetLoadingUrl().spec());
SCOPED_CRASH_KEY_BOOL(
"old_page_info", "old_is_frozen",
old_page_info->new_lifecycle_state_for_old_page->is_frozen);
SCOPED_CRASH_KEY_BOOL("old_page_info", "old_is_in_bfcache",
old_page_info->new_lifecycle_state_for_old_page
->is_in_back_forward_cache);
SCOPED_CRASH_KEY_BOOL(
"old_page_info", "old_is_hidden",
old_page_info->new_lifecycle_state_for_old_page->visibility ==
blink::mojom::PageVisibilityState::kHidden);
SCOPED_CRASH_KEY_BOOL(
"old_page_info", "old_pagehide_dispatch",
old_page_info->new_lifecycle_state_for_old_page->pagehide_dispatch ==
blink::mojom::PagehideDispatch::kNotDispatched);
CaptureTraceForNavigationDebugScenario(
DebugScenario::kDebugNonMainFrameWithOldPageInfo);
return;
}
DCHECK_EQ(old_page_info->new_lifecycle_state_for_old_page->visibility,
blink::mojom::PageVisibilityState::kHidden);
DCHECK_NE(old_page_info->new_lifecycle_state_for_old_page->pagehide_dispatch,
blink::mojom::PagehideDispatch::kNotDispatched);
old_main_web_frame->View()->SetPageLifecycleStateFromNewPageCommit(
old_page_info->new_lifecycle_state_for_old_page->visibility,
old_page_info->new_lifecycle_state_for_old_page->pagehide_dispatch);
}
void RenderFrameImpl::CommitNavigation(
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,
std::optional<std::vector<blink::mojom::TransferrableURLLoaderPtr>>
subresource_overrides,
blink::mojom::ControllerServiceWorkerInfoPtr controller_service_worker_info,
blink::mojom::ServiceWorkerContainerInfoForClientPtr container_info,
mojo::PendingRemote<network::mojom::URLLoaderFactory>
subresource_proxying_loader_factory,
mojo::PendingRemote<network::mojom::URLLoaderFactory>
keep_alive_loader_factory,
mojo::PendingAssociatedRemote<blink::mojom::FetchLaterLoaderFactory>
fetch_later_loader_factory,
const blink::DocumentToken& document_token,
const base::UnguessableToken& devtools_navigation_token,
const base::Uuid& base_auction_nonce,
const std::optional<network::ParsedPermissionsPolicy>& permissions_policy,
blink::mojom::PolicyContainerPtr policy_container,
mojo::PendingRemote<blink::mojom::CodeCacheHost> code_cache_host,
mojo::PendingRemote<blink::mojom::CodeCacheHost>
code_cache_host_for_background,
mojom::CookieManagerInfoPtr cookie_manager_info,
mojom::StorageInfoPtr storage_info,
mojom::NavigationClient::CommitNavigationCallback commit_callback) {
LOG(INFO) << "RenderFrameImpl::CommitNavigation " << devtools_navigation_token.ToString();
RendererNavigationMetricsManager::Instance().MarkCommitStart(
commit_params->navigation_metrics_token);
if (!response_head->client_side_content_decoding_types.empty()) {
auto data_pipe_pair =
network::ContentDecodingInterceptor::CreateDataPipePair(
network::ContentDecodingInterceptor::ClientType::kCommitNavigation);
if (data_pipe_pair) {
network::ContentDecodingInterceptor::Intercept(
response_head->client_side_content_decoding_types,
url_loader_client_endpoints, response_body,
std::move(*data_pipe_pair),
base::ThreadPool::CreateSequencedTaskRunner(
{base::TaskPriority::USER_BLOCKING}));
} else {
response_body.reset();
AddMessageToConsole(blink::mojom::ConsoleMessageLevel::kError,
"Failed to decode content");
}
}
base::ElapsedTimer timer;
base::ScopedUmaHistogramTimer histogram_timer(kCommitRenderFrame);
base::ScopedUmaHistogramTimer histogram_timer_frame(base::StrCat(
{kCommitRenderFrame, IsMainFrame() ? ".MainFrame" : ".Subframe"}));
TRACE_EVENT_WITH_FLOW0("navigation", "RenderFrameImpl::CommitNavigation",
TRACE_ID_LOCAL(this),
TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
DCHECK(navigation_client_impl_);
DCHECK(!blink::IsRendererDebugURL(common_params->url));
DCHECK(!NavigationTypeUtils::IsSameDocument(common_params->navigation_type));
LogCommitHistograms(commit_params->commit_sent, is_main_frame_,
common_params->url);
if (base::FeatureList::IsEnabled(
blink::features::kRemoveCommitRedirectUrlsArray)) {
commit_params->redirects.clear();
}
bool is_new_navigation_in_outermost_main_frame_with_http_or_https = false;
if (frame_->IsOutermostMainFrame() &&
common_params->url.SchemeIsHTTPOrHTTPS()) {
switch (common_params->navigation_type) {
case blink::mojom::NavigationType::DIFFERENT_DOCUMENT:
is_new_navigation_in_outermost_main_frame_with_http_or_https = true;
break;
case blink::mojom::NavigationType::RELOAD:
case blink::mojom::NavigationType::RELOAD_BYPASSING_CACHE:
case blink::mojom::NavigationType::RESTORE:
case blink::mojom::NavigationType::RESTORE_WITH_POST:
case blink::mojom::NavigationType::HISTORY_SAME_DOCUMENT:
case blink::mojom::NavigationType::HISTORY_DIFFERENT_DOCUMENT:
case blink::mojom::NavigationType::SAME_DOCUMENT:
break;
}
}
AssertNavigationCommits assert_navigation_commits(
this, kMayReplaceInitialEmptyDocument);
base::ElapsedTimer elapsed_timer;
SetOldPageLifecycleStateFromNewPageCommitIfNeeded(
commit_params->old_page_info.get(), common_params->url);
base::TimeDelta total_lifecycle_events_processing_time_on_commit =
elapsed_timer.Elapsed();
bool was_initiated_in_this_frame =
navigation_client_impl_ &&
navigation_client_impl_->was_initiated_in_this_frame();
DCHECK(common_params->url.SchemeIs(url::kJavaScriptScheme) ||
subresource_loader_factories);
int request_id = blink::GenerateRequestId();
std::unique_ptr<DocumentState> document_state = BuildDocumentStateFromParams(
*common_params, *commit_params, std::move(commit_callback),
std::move(navigation_client_impl_), request_id,
was_initiated_in_this_frame);
#if BUILDFLAG(ARKWEB_CUSTOM_VIEWPORT_WIDTH)
bool has_cached = false;
if (blink::WebView* web_view = GetWebView()) {
has_cached = web_view->ApplyCachedViewportMetaEnabled();
}
if (IsMainFrame() && has_cached) {
document_state->set_must_reset_scroll_and_scale_state(true);
}
#endif
#if BUILDFLAG(ARKWEB_USERAGENT)
if (IsMainFrame() &&
viewport_meta_enabled_ != GetBlinkPreferences().viewport_meta_enabled &&
(common_params->navigation_type == blink::mojom::NavigationType::RELOAD ||
common_params->navigation_type ==
blink::mojom::NavigationType::RELOAD_BYPASSING_CACHE)) {
document_state->set_must_reset_scroll_and_scale_state(true);
}
viewport_meta_enabled_ = GetBlinkPreferences().viewport_meta_enabled;
#endif
bool is_client_redirect =
!!(common_params->transition & ui::PAGE_TRANSITION_CLIENT_REDIRECT);
auto navigation_params = std::make_unique<WebNavigationParams>(
document_token, devtools_navigation_token, base_auction_nonce);
navigation_params->navigation_delivery_type =
commit_params->navigation_delivery_type;
navigation_params->is_client_redirect = is_client_redirect;
FillMiscNavigationParams(*common_params, *commit_params,
navigation_params.get());
navigation_params->policy_container =
ToWebPolicyContainer(std::move(policy_container));
navigation_params->view_transition_state =
std::move(commit_params->view_transition_state);
navigation_params->navigation_timings
.total_lifecycle_events_processing_time_on_commit =
total_lifecycle_events_processing_time_on_commit;
#if BUILDFLAG(ARKWEB_CUSTOM_VIEWPORT_WIDTH)
navigation_params->custom_viewport_width = commit_params->custom_viewport_width;
#endif
if (frame_->IsOutermostMainFrame() && permissions_policy) {
navigation_params->permissions_policy_override = permissions_policy;
}
if (IsForInitialWebUI() && base::FeatureList::IsEnabled(
features::kInitialWebUISyncNavStartToCommit)) {
CHECK(subresource_loader_factories);
CHECK(subresource_loader_factories->local_resource_loader_config());
mojo::PendingRemote<network::mojom::URLLoaderClient> client_remote;
url_loader_client_endpoints = network::mojom::URLLoaderClientEndpoints::New(
mojo::NullRemote(), client_remote.InitWithNewPipeAndPassReceiver());
response_body = FillResponseForInitialWebUI(
common_params->url, commit_params->origin_to_commit,
subresource_loader_factories->local_resource_loader_config(),
&response_head, std::move(client_remote));
}
auto commit_with_params = base::BindOnce(
&RenderFrameImpl::CommitNavigationWithParams, weak_factory_.GetWeakPtr(),
common_params.Clone(), commit_params.Clone(),
std::move(subresource_loader_factories), std::move(subresource_overrides),
std::move(controller_service_worker_info), std::move(container_info),
std::move(subresource_proxying_loader_factory),
std::move(keep_alive_loader_factory),
std::move(fetch_later_loader_factory), std::move(code_cache_host),
std::move(code_cache_host_for_background), std::move(cookie_manager_info),
std::move(storage_info), std::move(document_state));
bool should_handle_data_url_as_string = false;
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(ARKWEB_NETWORK_BASE)
should_handle_data_url_as_string |=
is_main_frame_ && !commit_params->data_url_as_string.empty();
#endif
if (should_handle_data_url_as_string ||
commit_params->is_load_data_with_base_url) {
std::string mime_type, charset, data;
GURL base_url;
DecodeDataURL(*common_params, *commit_params, &mime_type, &charset, &data,
&base_url);
navigation_params->url = base_url;
WebNavigationParams::FillStaticResponse(navigation_params.get(),
WebString::FromUTF8(mime_type),
WebString::FromUTF8(charset), data);
std::move(commit_with_params).Run(std::move(navigation_params));
return;
}
FillNavigationParamsRequest(*common_params, *commit_params,
navigation_params.get());
if (!url_loader_client_endpoints &&
common_params->url.SchemeIs(url::kDataScheme)) {
std::string mime_type, charset, data;
if (!net::DataURL::Parse(common_params->url, &mime_type, &charset, &data)) {
NOTREACHED() << "Invalid URL passed: "
<< common_params->url.possibly_invalid_spec();
}
WebNavigationParams::FillStaticResponse(navigation_params.get(),
WebString::FromUTF8(mime_type),
WebString::FromUTF8(charset), data);
} else {
blink::WebNavigationBodyLoader::FillNavigationParamsResponseAndBodyLoader(
std::move(common_params), std::move(commit_params), request_id,
response_head.Clone(), std::move(response_body),
std::move(url_loader_client_endpoints),
GetTaskRunner(blink::TaskType::kInternalLoading),
CreateResourceLoadInfoNotifierWrapper(), !frame_->Parent(),
navigation_params.get(), frame_->IsAdFrame());
}
bool is_mhtml_archive = base::EqualsCaseInsensitiveASCII(
response_head->mime_type, "multipart/related") ||
base::EqualsCaseInsensitiveASCII(
response_head->mime_type, "message/rfc822");
if (is_mhtml_archive && navigation_params->body_loader) {
mhtml_body_loader_client_ =
std::make_unique<RenderFrameImpl::MHTMLBodyLoaderClient>(
this, std::move(navigation_params), std::move(commit_with_params));
navigation_commit_state_ = NavigationCommitState::kDidCommit;
return;
}
std::move(commit_with_params).Run(std::move(navigation_params));
if (is_new_navigation_in_outermost_main_frame_with_http_or_https) {
base::UmaHistogramTimes(
base::StrCat({kCommitRenderFrame,
".OutermostMainFrame.NewNavigation.IsHTTPOrHTTPS"}),
timer.Elapsed());
}
}
void RenderFrameImpl::CommitNavigationWithParams(
blink::mojom::CommonNavigationParamsPtr common_params,
blink::mojom::CommitNavigationParamsPtr commit_params,
std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
subresource_loader_factories,
std::optional<std::vector<blink::mojom::TransferrableURLLoaderPtr>>
subresource_overrides,
blink::mojom::ControllerServiceWorkerInfoPtr controller_service_worker_info,
blink::mojom::ServiceWorkerContainerInfoForClientPtr container_info,
mojo::PendingRemote<network::mojom::URLLoaderFactory>
subresource_proxying_loader_factory,
mojo::PendingRemote<network::mojom::URLLoaderFactory>
keep_alive_loader_factory,
mojo::PendingAssociatedRemote<blink::mojom::FetchLaterLoaderFactory>
fetch_later_loader_factory,
mojo::PendingRemote<blink::mojom::CodeCacheHost> code_cache_host,
mojo::PendingRemote<blink::mojom::CodeCacheHost>
code_cache_host_for_background,
mojom::CookieManagerInfoPtr cookie_manager_info,
mojom::StorageInfoPtr storage_info,
std::unique_ptr<DocumentState> document_state,
std::unique_ptr<WebNavigationParams> navigation_params) {
TRACE_EVENT_WITH_FLOW0("navigation",
"RenderFrameImpl::CommitNavigationWithParams",
TRACE_ID_LOCAL(this),
TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
base::ElapsedTimer timer;
#if BUILDFLAG(ARKWEB_ADBLOCK)
bool site_adblock_enabled = commit_params->site_adblock_enabled;
#endif
if (common_params->url.IsAboutSrcdoc()) {
WebNavigationParams::FillStaticResponse(navigation_params.get(),
"text/html", "UTF-8",
commit_params->srcdoc_value);
}
scoped_refptr<blink::ChildURLLoaderFactoryBundle> new_loader_factories =
CreateLoaderFactoryBundle(std::move(subresource_loader_factories),
std::move(subresource_overrides),
std::move(subresource_proxying_loader_factory),
std::move(keep_alive_loader_factory),
std::move(fetch_later_loader_factory));
DCHECK(new_loader_factories);
DCHECK(new_loader_factories->HasBoundDefaultFactory());
if (commit_params->is_view_source)
frame_->EnableViewSourceMode(true);
if (frame_->IsOutermostMainFrame()) {
frame_->SetNotRestoredReasons(
std::move(commit_params->not_restored_reasons));
} else {
CHECK(!commit_params->not_restored_reasons);
}
CHECK(!commit_params->lcpp_hint || frame_->IsOutermostMainFrame());
frame_->SetLCPPHint(std::move(commit_params->lcpp_hint));
mhtml_body_loader_client_.reset();
PrepareFrameForCommit(common_params->url, *commit_params);
blink::WebFrameLoadType load_type =
NavigationTypeToLoadType(common_params->navigation_type,
common_params->should_replace_current_entry);
WebHistoryItem item_for_history_navigation;
blink::mojom::CommitResult commit_status = blink::mojom::CommitResult::Ok;
if (load_type == WebFrameLoadType::kBackForward ||
load_type == WebFrameLoadType::kRestore) {
DCHECK_NE(0, commit_params->nav_entry_id);
commit_status = PrepareForHistoryNavigationCommit(
*common_params, *commit_params, &item_for_history_navigation,
&load_type);
}
if (commit_status != blink::mojom::CommitResult::Ok) {
if (frame_ && !frame_->IsLoading())
GetFrameHost()->DidStopLoading();
return;
}
navigation_params->frame_load_type = load_type;
navigation_params->history_item = item_for_history_navigation;
navigation_params->load_with_storage_access =
commit_params->load_with_storage_access;
navigation_params->visited_link_salt = commit_params->visited_link_salt;
if (!container_info) {
navigation_params->service_worker_network_provider =
ServiceWorkerNetworkProviderForFrame::CreateInvalidInstance();
} else {
navigation_params->service_worker_network_provider =
ServiceWorkerNetworkProviderForFrame::Create(
this, std::move(container_info),
std::move(controller_service_worker_info),
network::SharedURLLoaderFactory::Create(
new_loader_factories->Clone()));
}
DCHECK(!pending_loader_factories_);
pending_loader_factories_ = std::move(new_loader_factories);
pending_code_cache_host_ = std::move(code_cache_host);
pending_code_cache_host_for_background_ =
std::move(code_cache_host_for_background);
pending_cookie_manager_info_ = std::move(cookie_manager_info);
pending_storage_info_ = std::move(storage_info);
original_storage_key_ = navigation_params->storage_key;
base::WeakPtr<RenderFrameImpl> weak_self = weak_factory_.GetWeakPtr();
frame_->CommitNavigation(std::move(navigation_params),
std::move(document_state));
if (!weak_self)
return;
if (commit_params->local_surface_id) {
CHECK(frame_->FrameWidget())
<< "Only local roots should get a SurfaceID update";
frame_->FrameWidget()->ApplyLocalSurfaceIdUpdate(
*commit_params->local_surface_id);
}
if (load_type == WebFrameLoadType::kStandard &&
common_params->url.SchemeIsHTTPOrHTTPS()) {
base::UmaHistogramMicrosecondsTimes(
"Navigation.CommitNavigationWithParams.Time.IsStandardLoadType."
"IsHTTPOrHTTPS",
timer.Elapsed());
}
#if BUILDFLAG(ARKWEB_ADBLOCK)
if (is_main_frame_) {
OnUpdateAdBlockEnabledToRender(site_adblock_enabled);
}
#endif
ResetMembersUsedForDurationOfCommit();
}
void RenderFrameImpl::CommitFailedNavigation(
blink::mojom::CommonNavigationParamsPtr common_params,
blink::mojom::CommitNavigationParamsPtr commit_params,
bool has_stale_copy_in_cache,
int error_code,
int extended_error_code,
net::ResolveErrorInfo resolve_error_info,
const std::optional<std::string>& error_page_content,
std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
subresource_loader_factories,
const blink::DocumentToken& document_token,
const base::UnguessableToken& devtools_navigation_token,
blink::mojom::PolicyContainerPtr policy_container,
mojom::AlternativeErrorPageOverrideInfoPtr alternative_error_page_info,
mojom::NavigationClient::CommitFailedNavigationCallback callback) {
TRACE_EVENT1("navigation,benchmark,rail",
"RenderFrameImpl::CommitFailedNavigation", "frame_token",
frame_token_);
RendererNavigationMetricsManager::Instance().MarkCommitStart(
commit_params->navigation_metrics_token);
DCHECK(navigation_client_impl_);
DCHECK(!NavigationTypeUtils::IsSameDocument(common_params->navigation_type));
DCHECK(!common_params->initiator_base_url);
AssertNavigationCommits assert_navigation_commits(
this, kMayReplaceInitialEmptyDocument);
if (base::FeatureList::IsEnabled(
blink::features::kRemoveCommitRedirectUrlsArray)) {
commit_params->redirects.clear();
}
GetWebView()->SetHistoryListFromNavigation(
commit_params->current_history_list_index,
commit_params->current_history_list_length);
mhtml_body_loader_client_.reset();
GetContentClient()->SetActiveURL(
common_params->url, frame_->Top()->GetSecurityOrigin().ToString().Utf8());
scoped_refptr<blink::ChildURLLoaderFactoryBundle> new_loader_factories =
CreateLoaderFactoryBundle(
std::move(subresource_loader_factories),
std::nullopt ,
mojo::NullRemote() ,
mojo::NullRemote() ,
mojo::NullAssociatedRemote() );
DCHECK(new_loader_factories->HasBoundDefaultFactory());
WebURLError error(
error_code, extended_error_code, resolve_error_info,
has_stale_copy_in_cache ? WebURLError::HasCopyInCache::kTrue
: WebURLError::HasCopyInCache::kFalse,
WebURLError::IsWebSecurityViolation::kFalse, common_params->url,
WebURLError::ShouldCollapseInitiator::kFalse);
commit_params->content_settings =
blink::CreateDefaultRendererContentSettings();
auto navigation_params = std::make_unique<WebNavigationParams>(
document_token, devtools_navigation_token,
base::Uuid::GenerateRandomV4());
FillNavigationParamsRequest(*common_params, *commit_params,
navigation_params.get());
navigation_params->url = GURL(kUnreachableWebDataURL);
navigation_params->http_method = WebString::FromASCII(common_params->method);
navigation_params->error_code = error_code;
CHECK_NE(net::ERR_ABORTED, error_code);
if (commit_params->nav_entry_id == 0) {
NotifyObserversOfFailedProvisionalLoad();
}
std::string error_html;
std::string* error_html_ptr = &error_html;
if (error_code == net::ERR_HTTP_RESPONSE_CODE_FAILURE) {
DCHECK_NE(commit_params->http_response_code, -1);
#if BUILDFLAG(ARKWEB_ERROR_PAGE)
if (error_page_content && common_params->is_override_error_page) {
error_html = error_page_content.value();
error_html_ptr = nullptr;
}
#endif
GetContentClient()->renderer()->PrepareErrorPageForHttpStatusError(
this, error, navigation_params->http_method.Ascii(),
commit_params->http_response_code,
std::move(alternative_error_page_info), error_html_ptr);
} else {
if (error_page_content) {
error_html = error_page_content.value();
error_html_ptr = nullptr;
}
GetContentClient()->renderer()->PrepareErrorPage(
this, error, navigation_params->http_method.Ascii(),
std::move(alternative_error_page_info), error_html_ptr);
}
frame_->EnableViewSourceMode(false);
auto page_state =
blink::PageState::CreateFromEncodedData(commit_params->page_state);
if (page_state.IsValid())
navigation_params->history_item = WebHistoryItem(page_state);
if (!navigation_params->history_item.IsNull()) {
if (common_params->navigation_type ==
blink::mojom::NavigationType::RESTORE ||
common_params->navigation_type ==
blink::mojom::NavigationType::RESTORE_WITH_POST) {
navigation_params->frame_load_type = WebFrameLoadType::kRestore;
} else {
navigation_params->frame_load_type = WebFrameLoadType::kBackForward;
}
} else if (common_params->should_replace_current_entry) {
navigation_params->frame_load_type = WebFrameLoadType::kReplaceCurrentItem;
}
navigation_params->service_worker_network_provider =
ServiceWorkerNetworkProviderForFrame::CreateInvalidInstance();
FillMiscNavigationParams(*common_params, *commit_params,
navigation_params.get());
WebNavigationParams::FillStaticResponse(navigation_params.get(), "text/html",
"UTF-8", error_html);
navigation_params->unreachable_url = error.url();
if (base::FeatureList::IsEnabled(
blink::features::kRemoveCommitRedirectUrlsArray)) {
if (commit_params->redirect_infos.size()) {
navigation_params->pre_redirect_url_for_failed_navigations =
common_params->url;
} else {
navigation_params->pre_redirect_url_for_failed_navigations = error.url();
}
} else {
if (commit_params->redirects.size()) {
navigation_params->pre_redirect_url_for_failed_navigations =
commit_params->redirects[0];
} else {
navigation_params->pre_redirect_url_for_failed_navigations = error.url();
}
}
navigation_params->policy_container =
ToWebPolicyContainer(std::move(policy_container));
navigation_params->view_transition_state =
std::move(commit_params->view_transition_state);
std::unique_ptr<DocumentState> document_state = BuildDocumentStateFromParams(
*common_params, *commit_params, std::move(callback),
std::move(navigation_client_impl_), blink::GenerateRequestId(),
false );
#if BUILDFLAG(ARKWEB_EXT_UA)
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableNwebExUa)) {
if (IsMainFrame() &&
viewport_meta_enabled_ != GetBlinkPreferences().viewport_meta_enabled &&
(common_params->navigation_type ==
blink::mojom::NavigationType::RELOAD ||
common_params->navigation_type ==
blink::mojom::NavigationType::RELOAD_BYPASSING_CACHE)) {
document_state->set_must_reset_scroll_and_scale_state(true);
}
viewport_meta_enabled_ = GetBlinkPreferences().viewport_meta_enabled;
}
#endif
DCHECK(!pending_loader_factories_);
pending_loader_factories_ = std::move(new_loader_factories);
base::WeakPtr<RenderFrameImpl> weak_this = weak_factory_.GetWeakPtr();
frame_->CommitNavigation(std::move(navigation_params),
std::move(document_state));
if (!weak_this)
return;
ResetMembersUsedForDurationOfCommit();
}
void RenderFrameImpl::CommitSameDocumentNavigation(
blink::mojom::CommonNavigationParamsPtr common_params,
blink::mojom::CommitNavigationParamsPtr commit_params,
CommitSameDocumentNavigationCallback callback) {
RendererNavigationMetricsManager::Instance().MarkCommitStart(
commit_params->navigation_metrics_token);
DCHECK(!blink::IsRendererDebugURL(common_params->url));
DCHECK(!NavigationTypeUtils::IsReload(common_params->navigation_type));
DCHECK(!commit_params->is_view_source);
DCHECK(NavigationTypeUtils::IsSameDocument(common_params->navigation_type));
CHECK(in_frame_tree_);
if (mhtml_body_loader_client_) {
mhtml_body_loader_client_->Detach();
mhtml_body_loader_client_.reset();
}
PrepareFrameForCommit(common_params->url, *commit_params);
blink::WebFrameLoadType load_type =
NavigationTypeToLoadType(common_params->navigation_type,
common_params->should_replace_current_entry);
DocumentState* document_state =
DocumentState::FromDocumentLoader(frame_->GetDocumentLoader());
document_state->set_navigation_state(
NavigationState::CreateForSameDocumentCommitFromBrowser(
std::move(common_params), std::move(commit_params),
std::move(callback)));
NavigationState* navigation_state = document_state->navigation_state();
blink::mojom::CommitResult commit_status = blink::mojom::CommitResult::Ok;
WebHistoryItem item_for_history_navigation;
if (navigation_state->common_params().navigation_type ==
blink::mojom::NavigationType::HISTORY_SAME_DOCUMENT) {
DCHECK(blink::PageState::CreateFromEncodedData(
navigation_state->commit_params().page_state)
.IsValid());
DCHECK_NE(0, navigation_state->commit_params().nav_entry_id);
DCHECK(!navigation_state->common_params()
.is_history_navigation_in_new_child_frame);
commit_status = PrepareForHistoryNavigationCommit(
navigation_state->common_params(), navigation_state->commit_params(),
&item_for_history_navigation, &load_type);
}
if (commit_status == blink::mojom::CommitResult::Ok) {
base::WeakPtr<RenderFrameImpl> weak_this = weak_factory_.GetWeakPtr();
bool use_base_url_for_data_url =
!navigation_state->common_params().base_url_for_data_url.is_empty();
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(ARKWEB_NETWORK_BASE)
use_base_url_for_data_url |=
!navigation_state->commit_params().data_url_as_string.empty();
#endif
GURL url;
if (is_main_frame_ && use_base_url_for_data_url) {
url = navigation_state->common_params().base_url_for_data_url;
} else {
url = navigation_state->common_params().url;
}
bool is_client_redirect = !!(navigation_state->common_params().transition &
ui::PAGE_TRANSITION_CLIENT_REDIRECT);
bool started_with_transient_activation =
navigation_state->common_params().has_user_gesture;
bool is_browser_initiated =
navigation_state->commit_params().is_browser_initiated;
bool has_ua_visual_transition =
navigation_state->commit_params().has_ua_visual_transition;
std::optional<blink::scheduler::TaskAttributionId>
soft_navigation_heuristics_task_id =
navigation_state->commit_params()
.soft_navigation_heuristics_task_id;
WebSecurityOrigin initiator_origin;
if (navigation_state->common_params().initiator_origin) {
initiator_origin =
navigation_state->common_params().initiator_origin.value();
}
bool should_skip_screenshot =
navigation_state->commit_params().should_skip_screenshot;
commit_status = frame_->CommitSameDocumentNavigation(
url, load_type, item_for_history_navigation, is_client_redirect,
started_with_transient_activation, initiator_origin,
is_browser_initiated, has_ua_visual_transition,
soft_navigation_heuristics_task_id, should_skip_screenshot);
if (commit_status == blink::mojom::CommitResult::Ok) {
return;
}
if (!weak_this || document_state->navigation_state() != navigation_state) {
return;
}
}
DCHECK_NE(commit_status, blink::mojom::CommitResult::Ok);
document_state->TakeNavigationState()
->RunCommitSameDocumentNavigationCallback(commit_status);
if (frame_ && !frame_->IsLoading()) {
GetFrameHost()->DidStopLoading();
}
}
void RenderFrameImpl::UpdateSubresourceLoaderFactories(
std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
subresource_loader_factories) {
if (loader_factories_->IsHostChildURLLoaderFactoryBundle()) {
static_cast<blink::HostChildURLLoaderFactoryBundle*>(
loader_factories_.get())
->UpdateThisAndAllClones(std::move(subresource_loader_factories));
} else {
DCHECK(!subresource_loader_factories->pending_default_factory().is_valid());
DCHECK(!subresource_loader_factories->pending_isolated_world_factories()
.empty());
DCHECK_EQ(NavigationCommitState::kInitialEmptyDocument,
navigation_commit_state_);
auto partial_bundle =
base::MakeRefCounted<blink::ChildURLLoaderFactoryBundle>();
static_cast<blink::URLLoaderFactoryBundle*>(partial_bundle.get())
->Update(std::move(subresource_loader_factories));
loader_factories_->Update(partial_bundle->PassInterface());
}
background_resource_fetch_context_.reset();
}
const blink::BrowserInterfaceBrokerProxy&
RenderFrameImpl::GetBrowserInterfaceBroker() {
return frame_->GetBrowserInterfaceBroker();
}
bool RenderFrameImpl::IsPluginHandledExternally(
const blink::WebElement& plugin_element,
const blink::WebURL& url,
const blink::WebString& suggested_mime_type) {
#if BUILDFLAG(ENABLE_PLUGINS)
return GetContentClient()->renderer()->IsPluginHandledExternally(
this, plugin_element, GURL(url), suggested_mime_type.Utf8());
#else
return false;
#endif
}
bool RenderFrameImpl::IsDomStorageDisabled() const {
return GetContentClient()->renderer()->IsDomStorageDisabled();
}
v8::Local<v8::Object> RenderFrameImpl::GetScriptableObject(
const blink::WebElement& plugin_element,
v8::Isolate* isolate) {
#if BUILDFLAG(ENABLE_PLUGINS)
return GetContentClient()->renderer()->GetScriptableObject(plugin_element,
isolate);
#else
return v8::Local<v8::Object>();
#endif
}
void RenderFrameImpl::BindToFrame(blink::WebNavigationControl* frame) {
DCHECK(!frame_);
std::pair<FrameMap::iterator, bool> result =
g_frame_map.Get().emplace(frame, this);
CHECK(result.second) << "Inserting a duplicate item.";
frame_ = frame;
}
blink::WebPlugin* RenderFrameImpl::CreatePlugin(
const blink::WebPluginParams& params) {
blink::WebPlugin* plugin = nullptr;
if (GetContentClient()->renderer()->OverrideCreatePlugin(this, params,
&plugin)) {
return plugin;
}
return nullptr;
}
std::unique_ptr<blink::WebMediaPlayer> RenderFrameImpl::CreateMediaPlayer(
const blink::WebMediaPlayerSource& source,
WebMediaPlayerClient* client,
blink::MediaInspectorContext* inspector_context,
WebMediaPlayerEncryptedMediaClient* encrypted_client,
WebContentDecryptionModule* initial_cdm,
const blink::WebString& sink_id,
const cc::LayerTreeSettings* settings,
scoped_refptr<base::TaskRunner> compositor_worker_task_runner) {
DCHECK(settings);
return media_factory_.CreateMediaPlayer(
source, client, inspector_context, encrypted_client, initial_cdm, sink_id,
GetLocalRootWebFrameWidget()->GetFrameSinkId(), *settings,
agent_scheduling_group_->agent_group_scheduler().CompositorTaskRunner(),
std::move(compositor_worker_task_runner));
}
std::unique_ptr<blink::WebContentSettingsClient>
RenderFrameImpl::CreateWorkerContentSettingsClient() {
if (!frame_ || !frame_->View())
return nullptr;
return GetContentClient()->renderer()->CreateWorkerContentSettingsClient(
this);
}
#if !BUILDFLAG(IS_ANDROID)
std::unique_ptr<media::SpeechRecognitionClient>
RenderFrameImpl::CreateSpeechRecognitionClient() {
if (!frame_ || !frame_->View())
return nullptr;
return GetContentClient()->renderer()->CreateSpeechRecognitionClient(this);
}
#endif
scoped_refptr<blink::WebWorkerFetchContext>
RenderFrameImpl::CreateWorkletFetchContext() {
ServiceWorkerNetworkProviderForFrame* provider =
static_cast<ServiceWorkerNetworkProviderForFrame*>(
frame_->GetDocumentLoader()->GetServiceWorkerNetworkProvider());
DCHECK(provider);
mojo::PendingReceiver<blink::mojom::RendererPreferenceWatcher>
watcher_receiver;
GetWebView()->RegisterRendererPreferenceWatcher(
watcher_receiver.InitWithNewPipeAndPassRemote());
mojo::PendingRemote<blink::mojom::ResourceLoadInfoNotifier>
pending_resource_load_info_notifier;
resource_load_info_notifier_receivers_.Add(
this,
pending_resource_load_info_notifier.InitWithNewPipeAndPassReceiver(),
agent_scheduling_group_->agent_group_scheduler().DefaultTaskRunner());
std::vector<std::string> cors_exempt_header_list =
RenderThreadImpl::current()->cors_exempt_header_list();
std::vector<blink::WebString> web_cors_exempt_header_list(
cors_exempt_header_list.size());
std::ranges::transform(
cors_exempt_header_list, web_cors_exempt_header_list.begin(),
[](const auto& header) { return blink::WebString::FromLatin1(header); });
scoped_refptr<blink::WebDedicatedOrSharedWorkerGlobalScopeContext>
web_dedicated_or_shared_worker_global_scope_context =
blink::WebDedicatedOrSharedWorkerGlobalScopeContext::Create(
provider->context(), GetWebView()->GetRendererPreferences(),
std::move(watcher_receiver), GetLoaderFactoryBundle()->Clone(),
GetLoaderFactoryBundle()->Clone(),
mojo::NullReceiver(),
web_cors_exempt_header_list,
std::move(pending_resource_load_info_notifier));
web_dedicated_or_shared_worker_global_scope_context->SetAncestorFrameToken(
frame_->GetLocalFrameToken());
web_dedicated_or_shared_worker_global_scope_context->set_site_for_cookies(
frame_->GetDocument().SiteForCookies());
web_dedicated_or_shared_worker_global_scope_context->set_top_frame_origin(
frame_->GetDocument().TopFrameOrigin());
for (auto& observer : observers_) {
observer.WillCreateWorkerFetchContext(
web_dedicated_or_shared_worker_global_scope_context.get());
}
return web_dedicated_or_shared_worker_global_scope_context;
}
scoped_refptr<blink::WebWorkerFetchContext>
RenderFrameImpl::CreateWorkerFetchContext(
blink::WebDedicatedWorkerHostFactoryClient* factory_client) {
DCHECK(factory_client);
mojo::PendingReceiver<blink::mojom::RendererPreferenceWatcher>
watcher_receiver;
GetWebView()->RegisterRendererPreferenceWatcher(
watcher_receiver.InitWithNewPipeAndPassRemote());
mojo::PendingRemote<blink::mojom::ResourceLoadInfoNotifier>
pending_resource_load_info_notifier;
resource_load_info_notifier_receivers_.Add(
this,
pending_resource_load_info_notifier.InitWithNewPipeAndPassReceiver(),
agent_scheduling_group_->agent_group_scheduler().DefaultTaskRunner());
scoped_refptr<blink::WebDedicatedOrSharedWorkerGlobalScopeContext>
web_dedicated_or_shared_worker_global_scope_context =
static_cast<DedicatedWorkerHostFactoryClient*>(factory_client)
->CreateWorkerGlobalScopeContext(
GetWebView()->GetRendererPreferences(),
std::move(watcher_receiver),
std::move(pending_resource_load_info_notifier));
web_dedicated_or_shared_worker_global_scope_context->SetAncestorFrameToken(
frame_->GetLocalFrameToken());
web_dedicated_or_shared_worker_global_scope_context->set_site_for_cookies(
frame_->GetDocument().SiteForCookies());
web_dedicated_or_shared_worker_global_scope_context->set_top_frame_origin(
frame_->GetDocument().TopFrameOrigin());
for (auto& observer : observers_) {
observer.WillCreateWorkerFetchContext(
web_dedicated_or_shared_worker_global_scope_context.get());
}
return web_dedicated_or_shared_worker_global_scope_context;
}
std::unique_ptr<blink::WebPrescientNetworking>
RenderFrameImpl::CreatePrescientNetworking() {
return GetContentClient()->renderer()->CreatePrescientNetworking(this);
}
std::unique_ptr<blink::ResourceLoadInfoNotifierWrapper>
RenderFrameImpl::CreateResourceLoadInfoNotifierWrapper() {
return std::make_unique<blink::ResourceLoadInfoNotifierWrapper>(
weak_wrapper_resource_load_info_notifier_->AsWeakPtr(),
GetTaskRunner(blink::TaskType::kNetworking));
}
std::unique_ptr<blink::WebServiceWorkerProvider>
RenderFrameImpl::CreateServiceWorkerProvider() {
if (!frame_->GetDocumentLoader())
return nullptr;
if (!ChildThreadImpl::current())
return nullptr;
ServiceWorkerNetworkProviderForFrame* provider =
static_cast<ServiceWorkerNetworkProviderForFrame*>(
frame_->GetDocumentLoader()->GetServiceWorkerNetworkProvider());
if (!provider->context()) {
return nullptr;
}
return std::make_unique<WebServiceWorkerProviderImpl>(provider->context());
}
blink::AssociatedInterfaceProvider*
RenderFrameImpl::GetRemoteNavigationAssociatedInterfaces() {
return GetRemoteAssociatedInterfaces();
}
namespace {
struct CreateChildFrameTraceEvent {
explicit CreateChildFrameTraceEvent(
const blink::LocalFrameToken& frame_token) {
TRACE_EVENT_BEGIN("navigation,rail", "RenderFrameImpl::createChildFrame",
"frame_token", frame_token);
}
~CreateChildFrameTraceEvent() {
TRACE_EVENT_END("navigation,rail", "child_frame_token", child_frame_token);
}
blink::LocalFrameToken child_frame_token;
};
}
blink::WebLocalFrame* RenderFrameImpl::CreateChildFrame(
blink::mojom::TreeScopeType scope,
const blink::WebString& name,
const blink::WebString& fallback_name,
const blink::FramePolicy& frame_policy,
const blink::WebFrameOwnerProperties& frame_owner_properties,
blink::FrameOwnerElementType frame_owner_element_type,
blink::WebPolicyContainerBindParams policy_container_bind_params,
ukm::SourceId document_ukm_source_id,
FinishChildFrameCreationFn finish_creation) {
CreateChildFrameTraceEvent trace_event(frame_token_);
int child_routing_id;
blink::LocalFrameToken frame_token;
base::UnguessableToken devtools_frame_token;
blink::DocumentToken document_token;
if (!RenderThread::Get()->GenerateFrameRoutingID(
child_routing_id, frame_token, devtools_frame_token,
document_token)) {
return nullptr;
}
trace_event.child_frame_token = frame_token;
bool is_created_by_script = GetAgentGroupScheduler().Isolate()->InContext();
std::string frame_unique_name =
unique_name_helper_.GenerateNameForNewChildFrame(
name.IsEmpty() ? fallback_name.Utf8() : name.Utf8(),
is_created_by_script);
mojo::PendingAssociatedReceiver<mojom::Frame> pending_frame_receiver;
mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>
browser_interface_broker;
mojo::PendingAssociatedRemote<blink::mojom::AssociatedInterfaceProvider>
associated_interface_provider;
GetFrameHost()->CreateChildFrame(
frame_token, pending_frame_receiver.InitWithNewEndpointAndPassRemote(),
browser_interface_broker.InitWithNewPipeAndPassReceiver(),
blink::mojom::PolicyContainerBindParams::New(
std::move(policy_container_bind_params.receiver)),
associated_interface_provider.InitWithNewEndpointAndPassReceiver(), scope,
name.Utf8(), frame_unique_name, is_created_by_script, frame_policy,
blink::mojom::FrameOwnerProperties::From(frame_owner_properties),
frame_owner_element_type, document_ukm_source_id);
RenderFrameImpl* child_render_frame = RenderFrameImpl::Create(
*agent_scheduling_group_, frame_token, child_routing_id,
std::move(pending_frame_receiver),
std::move(associated_interface_provider), devtools_frame_token,
false);
child_render_frame->SetLoaderFactoryBundle(CloneLoaderFactories());
child_render_frame->unique_name_helper_.set_propagated_name(
frame_unique_name);
if (is_created_by_script)
child_render_frame->unique_name_helper_.Freeze();
blink::WebLocalFrame* web_frame = frame_->CreateLocalChild(
scope, child_render_frame,
child_render_frame->blink_interface_registry_.get(), frame_token);
finish_creation(web_frame, document_token,
std::move(browser_interface_broker));
child_render_frame->in_frame_tree_ = true;
child_render_frame->Initialize(GetWebFrame());
return web_frame;
}
void RenderFrameImpl::DidCreateFencedFrame(
const blink::RemoteFrameToken& frame_token) {
for (auto& observer : observers_)
observer.DidCreateFencedFrame(frame_token);
}
blink::WebFrame* RenderFrameImpl::FindFrame(const blink::WebString& name) {
if (GetBlinkPreferences().renderer_wide_named_frame_lookup) {
for (const auto& it : g_frame_map.Get()) {
WebLocalFrame* frame = it.second->GetWebFrame();
if (frame->AssignedName() == name)
return frame;
}
}
return GetContentClient()->renderer()->FindFrame(this->GetWebFrame(),
name.Utf8());
}
void RenderFrameImpl::WillDetach(blink::DetachReason detach_reason) {
if (detach_reason == blink::DetachReason::kNavigation) {
if (navigation_client_impl_ &&
ShouldQueueNavigationsWhenPendingCommitRFHExists()) {
navigation_client_impl_->ResetWithoutCancelling();
}
}
for (auto& observer : observers_)
observer.WillDetach(detach_reason);
auto& factory = blink::AudioOutputIPCFactory::GetInstance();
if (factory.io_task_runner())
factory.MaybeDeregisterRemoteFactory(GetWebFrame()->GetLocalFrameToken());
SendUpdateState();
}
void RenderFrameImpl::FrameDetached(blink::DetachReason detach_reason) {
TRACE_EVENT0("navigation", "RenderFrameImpl::FrameDetached");
base::ScopedUmaHistogramTimer histogram_timer(
"Navigation.RenderFrameImpl.FrameDetached");
auto it = g_frame_map.Get().find(frame_);
CHECK(it != g_frame_map.Get().end());
CHECK_EQ(it->second, this);
g_frame_map.Get().erase(it);
render_accessibility_manager_.reset();
frame_->Close(detach_reason);
frame_ = nullptr;
if (mhtml_body_loader_client_) {
mhtml_body_loader_client_->Detach();
mhtml_body_loader_client_.reset();
}
delete this;
}
void RenderFrameImpl::DidChangeName(const blink::WebString& name) {
if (GetWebFrame()->GetCurrentHistoryItem().IsNull()) {
unique_name_helper_.UpdateName(name.Utf8());
}
GetFrameHost()->DidChangeName(name.Utf8(), unique_name_helper_.value());
}
void RenderFrameImpl::DidMatchCSS(
const std::vector<blink::WebString>& newly_matching_selectors,
const std::vector<blink::WebString>& stopped_matching_selectors) {
for (auto& observer : observers_)
observer.DidMatchCSS(newly_matching_selectors, stopped_matching_selectors);
}
bool RenderFrameImpl::ShouldReportDetailedMessageForSourceAndSeverity(
blink::mojom::ConsoleMessageLevel log_level,
const blink::WebString& source) {
if (want_error_message_stack_trace_ &&
log_level == blink::mojom::ConsoleMessageLevel::kError) {
return true;
}
return GetContentClient()->renderer()->ShouldReportDetailedMessageForSource(
source.Utf16());
}
void RenderFrameImpl::DidAddMessageToConsole(
const blink::WebConsoleMessage& message,
const blink::WebString& source_name,
unsigned source_line,
const blink::WebString& stack_trace) {
if (ShouldReportDetailedMessageForSourceAndSeverity(message.level,
source_name)) {
for (auto& observer : observers_) {
observer.DetailedConsoleMessageAdded(
message.text.Utf16(), source_name.Utf16(), stack_trace.Utf16(),
source_line, message.level);
}
}
}
void RenderFrameImpl::DidCreateDocumentLoader(
blink::WebDocumentLoader* document_loader) {
DocumentState* document_state =
DocumentState::FromDocumentLoader(document_loader);
if (!document_state) {
document_loader->SetExtraData(BuildDocumentState());
document_loader->SetServiceWorkerNetworkProvider(
ServiceWorkerNetworkProviderForFrame::CreateInvalidInstance());
}
document_loader->SetCodeCacheHost(
std::move(pending_code_cache_host_),
std::move(pending_code_cache_host_for_background_));
}
void RenderFrameImpl::DidCommitNavigation(
blink::WebHistoryCommitType commit_type,
bool should_reset_browser_interface_broker,
const network::ParsedPermissionsPolicy& permissions_policy_header,
const blink::DocumentPolicyFeatureState& document_policy_header) {
TRACE_EVENT_WITH_FLOW0("navigation", "RenderFrameImpl::DidCommitNavigation",
TRACE_ID_LOCAL(this),
TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
CHECK_EQ(NavigationCommitState::kWillCommit, navigation_commit_state_);
navigation_commit_state_ = NavigationCommitState::kDidCommit;
WebDocumentLoader* document_loader = frame_->GetDocumentLoader();
DocumentState* document_state =
DocumentState::FromDocumentLoader(document_loader);
NavigationState* navigation_state = document_state->navigation_state();
DCHECK(!navigation_state->WasWithinSameDocument());
TRACE_EVENT2("navigation,benchmark,rail",
"RenderFrameImpl::didStartProvisionalLoad", "frame_token",
frame_token_, "url",
document_loader->GetUrl().GetString().Utf8());
#if BUILDFLAG(ARKWEB_EXT_LOG_MESSAGE)
if (IsMainFrame()) {
LOG(WARNING) << "event_message: page load start, routing_id: "
<< ", url: ***";
#if BUILDFLAG(ARKWEB_LOGGER_REPORT)
PageLoadStartLoggerReport(document_loader);
#endif
#if BUILDFLAG(ARKWEB_CRASHPAD)
if (!MemoryMonitorImpl::GetInstance()->IsInitialized()) {
GetBrowserInterfaceBroker().GetInterface(
std::move(MemoryMonitorImpl::GetInstance()->GetPendingReceiver())
);
}
MemoryMonitorImpl::GetInstance()->Trigger(document_loader->GetUrl().GetString().Utf8());
#endif
#if BUILDFLAG(ARKWEB_JSHEAP_DUMP)
if (!dfx::BinaryWriterRender::GetInstance()->IsInitialized()) {
LOG(INFO) << "HeapDump: GetInstance()->SetInitialized()\n";
dfx::BinaryWriterRender::GetInstance()->SetInitialized();
LOG(INFO) << "HeapDump: RenderFrameImpl::Initialize\n";
GetBrowserInterfaceBroker().GetInterface(std::move(
dfx::BinaryWriterRender::GetInstance()->GetPendingReceiver()));
}
#endif
}
#endif
if (pending_loader_factories_) {
SetLoaderFactoryBundle(std::move(pending_loader_factories_));
}
DCHECK(loader_factories_);
DCHECK(loader_factories_->HasBoundDefaultFactory());
if (!navigation_state->was_initiated_in_this_frame()) {
for (auto& observer : observers_)
observer.DidStartNavigation(document_loader->GetUrl(), std::nullopt);
}
for (auto& observer : observers_)
observer.ReadyToCommitNavigation(document_loader);
for (auto& observer : observers_)
observer.DidCreateNewDocument();
DVLOG(1) << "Committed provisional load: "
<< TrimURL(GetLoadingUrl().possibly_invalid_spec());
TRACE_EVENT2("navigation,rail", "RenderFrameImpl::didCommitProvisionalLoad",
"frame_token", frame_token_, "url",
GetLoadingUrl().possibly_invalid_spec());
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kWaitForDebuggerOnNavigation)) {
std::string renderer =
base::StrCat({"Renderer url=\"",
TrimURL(GetLoadingUrl().possibly_invalid_spec()), "\""});
content::WaitForDebugger(renderer);
}
GetWebFrame()->SetEmbeddingToken(base::UnguessableToken::Create());
mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
browser_interface_broker_receiver;
if (should_reset_browser_interface_broker) {
browser_interface_broker_receiver =
frame_->GetBrowserInterfaceBroker().Reset(
agent_scheduling_group_->agent_group_scheduler()
.DefaultTaskRunner());
auto& factory = blink::AudioOutputIPCFactory::GetInstance();
if (factory.io_task_runner()) {
factory.MaybeDeregisterRemoteFactory(GetWebFrame()->GetLocalFrameToken());
factory.RegisterRemoteFactory(GetWebFrame()->GetLocalFrameToken(),
frame_->GetBrowserInterfaceBroker());
}
audio_input_stream_factory_.reset();
render_accessibility_manager_->CloseConnection();
}
if (media_permission_dispatcher_)
media_permission_dispatcher_->OnNavigation();
ui::PageTransition transition =
GetTransitionType(frame_->GetDocumentLoader(), navigation_state,
IsMainFrame(), GetWebView()->IsFencedFrameRoot());
if (pending_cookie_manager_info_ &&
pending_cookie_manager_info_->origin ==
url::Origin(frame_->GetDocument().GetSecurityOrigin())) {
frame_->GetDocument().SetCookieManager(
std::move(pending_cookie_manager_info_->cookie_manager));
}
if (pending_storage_info_ &&
original_storage_key_.origin() ==
url::Origin(frame_->GetDocument().GetSecurityOrigin())) {
if (pending_storage_info_->local_storage_area) {
frame_->SetLocalStorageArea(
std::move(pending_storage_info_->local_storage_area));
}
if (pending_storage_info_->session_storage_area) {
frame_->SetSessionStorageArea(
std::move(pending_storage_info_->session_storage_area));
}
}
DidCommitNavigationInternal(
commit_type, transition, navigation_state, permissions_policy_header,
document_policy_header,
should_reset_browser_interface_broker
? mojom::DidCommitProvisionalLoadInterfaceParams::New(
std::move(browser_interface_broker_receiver))
: nullptr,
nullptr , GetWebFrame()->GetEmbeddingToken());
UpdateEncoding(frame_, frame_->View()->PageEncoding().Utf8());
NotifyObserversOfNavigationCommit(transition);
std::ignore = document_state->TakeNavigationState();
ResetMembersUsedForDurationOfCommit();
}
void RenderFrameImpl::DidCommitDocumentReplacementNavigation(
blink::WebDocumentLoader* document_loader) {
for (auto& observer : observers_)
observer.DidStartNavigation(document_loader->GetUrl(), std::nullopt);
for (auto& observer : observers_)
observer.ReadyToCommitNavigation(document_loader);
for (auto& observer : observers_)
observer.DidCreateNewDocument();
auto navigation_state = NavigationState::CreateForSynchronousCommit();
ui::PageTransition transition =
GetTransitionType(document_loader, navigation_state.get(), IsMainFrame(),
GetWebView()->IsFencedFrameRoot());
NotifyObserversOfNavigationCommit(transition);
}
void RenderFrameImpl::DidClearWindowObject() {
TRACE_EVENT_WITH_FLOW0("navigation", "RenderFrameImpl::DidClearWindowObject",
TRACE_ID_LOCAL(this),
TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
if (enabled_bindings_.Has(BindingsPolicyValue::kWebUi)) {
WebUIExtension::Install(frame_);
}
const base::CommandLine& command_line =
*base::CommandLine::ForCurrentProcess();
if (command_line.HasSwitch(switches::kDomAutomationController))
DomAutomationController::Install(this, frame_);
if (command_line.HasSwitch(switches::kStatsCollectionController))
StatsCollectionController::Install(frame_);
if (command_line.HasSwitch(switches::kEnableGpuBenchmarking)) {
GpuBenchmarking::Install(weak_factory_.GetWeakPtr());
}
if (command_line.HasSwitch(switches::kEnableSkiaBenchmarking))
SkiaBenchmarking::Install(frame_);
for (auto& observer : observers_)
observer.DidClearWindowObject();
}
void RenderFrameImpl::DidCreateDocumentElement() {
for (auto& observer : observers_)
observer.DidCreateDocumentElement();
}
void RenderFrameImpl::RunScriptsAtDocumentElementAvailable() {
if (!initialized_)
return;
GetContentClient()->renderer()->RunScriptsAtDocumentStart(this);
}
void RenderFrameImpl::DidReceiveTitle(const blink::WebString& title) {
if (!frame_->Parent() && !title.IsEmpty()) {
tracing::TrackNameRecorder::GetInstance()->UpdateProcessLabel(
process_label_id_, title.Utf8());
} else {
GURL loading_url = GetLoadingUrl();
if (!loading_url.GetHost().empty() &&
loading_url.GetScheme() != url::kFileScheme) {
std::string frame_title;
if (frame_->Parent()) {
frame_title += "Subframe: ";
}
frame_title += loading_url.DeprecatedGetOriginAsURL().spec();
tracing::TrackNameRecorder::GetInstance()->UpdateProcessLabel(
process_label_id_, frame_title);
}
}
UpdateEncoding(frame_, frame_->View()->PageEncoding().Utf8());
}
void RenderFrameImpl::DidDispatchDOMContentLoadedEvent() {
TRACE_EVENT1("navigation,benchmark,rail",
"RenderFrameImpl::DidDispatchDOMContentLoadedEvent",
"frame_token", frame_token_);
for (auto& observer : observers_)
observer.DidDispatchDOMContentLoadedEvent();
#if BUILDFLAG(ARKWEB_EXT_LOG_MESSAGE)
if (IsMainFrame()) {
LOG(WARNING) << "event_message: content load finished, routing_id: "
<< ", url: ***";
}
#endif
#if BUILDFLAG(ARKWEB_LOGGER_REPORT)
ContentLoadFailedLoggerReport();
#endif
UpdateEncoding(frame_, frame_->View()->PageEncoding().Utf8());
}
void RenderFrameImpl::RunScriptsAtDocumentReady() {
DCHECK(initialized_);
GetContentClient()->renderer()->RunScriptsAtDocumentEnd(this);
}
void RenderFrameImpl::RunScriptsAtDocumentIdle() {
GetContentClient()->renderer()->RunScriptsAtDocumentIdle(this);
}
void RenderFrameImpl::DidHandleOnloadEvents() {
for (auto& observer : observers_)
observer.DidHandleOnloadEvents();
#if BUILDFLAG(ARKWEB_EXT_LOG_MESSAGE)
if (IsMainFrame()) {
LOG(WARNING) << "event_message: page load finished, routing_id: "
<< ", url: ***";
#if BUILDFLAG(ARKWEB_LOGGER_REPORT)
PageLoadFinishedLoggerReport();
#endif
}
#endif
}
void RenderFrameImpl::DidFinishLoad() {
TRACE_EVENT1("navigation,benchmark,rail", "RenderFrameImpl::didFinishLoad",
"frame_token", frame_token_);
if (!frame_->Parent()) {
TRACE_EVENT_INSTANT1("WebCore,benchmark,rail", "LoadFinished",
TRACE_EVENT_SCOPE_PROCESS, "isOutermostMainFrame",
frame_->IsOutermostMainFrame());
}
for (auto& observer : observers_)
observer.DidFinishLoad();
}
void RenderFrameImpl::DidFinishLoadForPrinting() {
for (auto& observer : observers_)
observer.DidFinishLoadForPrinting();
}
void RenderFrameImpl::DidFinishSameDocumentNavigation(
blink::WebHistoryCommitType commit_type,
bool is_synchronously_committed,
blink::mojom::SameDocumentNavigationType same_document_navigation_type,
bool is_client_redirect,
const std::optional<blink::SameDocNavigationScreenshotDestinationToken>&
screenshot_destination,
base::UnguessableToken same_document_metrics_token) {
TRACE_EVENT1("navigation,rail",
"RenderFrameImpl::didFinishSameDocumentNavigation",
"frame_token", frame_token_);
WebDocumentLoader* document_loader = frame_->GetDocumentLoader();
DocumentState* document_state =
DocumentState::FromDocumentLoader(document_loader);
std::unique_ptr<NavigationState> navigation_state;
if (is_synchronously_committed) {
navigation_state = NavigationState::CreateForSynchronousCommit();
} else {
navigation_state = document_state->TakeNavigationState();
}
navigation_state->set_was_within_same_document(true);
ui::PageTransition transition =
GetTransitionType(document_loader, navigation_state.get(), IsMainFrame(),
GetWebView()->IsFencedFrameRoot());
auto same_document_params =
mojom::DidCommitSameDocumentNavigationParams::New();
same_document_params->same_document_navigation_type =
same_document_navigation_type;
same_document_params->is_client_redirect = is_client_redirect;
same_document_params->started_with_transient_activation =
document_loader->LastNavigationHadTransientUserActivation();
same_document_params->should_replace_current_entry =
document_loader->ReplacesCurrentHistoryItem();
same_document_params->navigation_entry_screenshot_destination =
screenshot_destination;
same_document_params->same_document_metrics_token =
same_document_metrics_token;
DidCommitNavigationInternal(
commit_type, transition, navigation_state.get(),
network::ParsedPermissionsPolicy(),
blink::DocumentPolicyFeatureState(),
nullptr,
std::move(same_document_params),
std::nullopt
);
for (auto& observer : observers_)
observer.DidFinishSameDocumentNavigation();
}
void RenderFrameImpl::DidFailAsyncSameDocumentCommit() {
DocumentState* document_state =
DocumentState::FromDocumentLoader(frame_->GetDocumentLoader());
if (auto navigation_state = document_state->TakeNavigationState()) {
navigation_state->RunCommitSameDocumentNavigationCallback(
blink::mojom::CommitResult::Aborted);
}
}
void RenderFrameImpl::WillFreezePage() {
SendUpdateState();
}
void RenderFrameImpl::DidOpenDocumentInputStream(const blink::WebURL& url) {
GURL filtered_url(url);
if (!IsValidCommitUrl(filtered_url)) {
filtered_url = GURL(kBlockedURL);
}
GetFrameHost()->DidOpenDocumentInputStream(filtered_url);
}
void RenderFrameImpl::DidSetPageLifecycleState(
blink::BFCacheStateChange bfcache_change) {
for (auto& observer : observers_)
observer.DidSetPageLifecycleState(bfcache_change);
}
void RenderFrameImpl::NotifyCurrentHistoryItemChanged() {
SendUpdateState();
}
void RenderFrameImpl::DidUpdateCurrentHistoryItem() {
StartDelayedSyncTimer();
}
void RenderFrameImpl::StartDelayedSyncTimer() {
base::TimeDelta delay;
if (send_content_state_immediately_) {
SendUpdateState();
return;
} else if (GetWebView()->GetVisibilityState() !=
blink::mojom::PageVisibilityState::kVisible)
delay = kDelaySecondsForContentStateSyncHidden;
else
delay = kDelaySecondsForContentStateSync;
if (delayed_state_sync_timer_.IsRunning()) {
if (delayed_state_sync_timer_.GetCurrentDelay() == delay)
return;
delayed_state_sync_timer_.Stop();
}
delayed_state_sync_timer_.Start(FROM_HERE, delay, this,
&RenderFrameImpl::SendUpdateState);
}
bool RenderFrameImpl::SwapOutAndDeleteThis(
bool is_loading,
blink::mojom::FrameReplicationStatePtr replicated_frame_state,
const blink::RemoteFrameToken& proxy_frame_token,
blink::mojom::RemoteFrameInterfacesFromBrowserPtr remote_frame_interfaces,
blink::mojom::RemoteMainFrameInterfacesPtr remote_main_frame_interfaces,
const std::optional<base::UnguessableToken>& devtools_frame_token) {
TRACE_EVENT1("navigation,rail", "RenderFrameImpl::SwapOutAndDeleteThis",
"frame_token", frame_token_);
DCHECK(!base::RunLoop::IsNestedOnCurrentThread());
blink::WebRemoteFrame* remote_frame = blink::WebRemoteFrame::Create(
frame_->GetTreeScopeType(), proxy_frame_token);
blink::WebView* web_view = GetWebView();
bool is_main_frame = is_main_frame_;
bool success =
frame_->Swap(remote_frame, std::move(remote_frame_interfaces->frame_host),
std::move(remote_frame_interfaces->frame_receiver),
std::move(replicated_frame_state), devtools_frame_token);
if (is_main_frame) {
DCHECK(success);
web_view->DidAttachRemoteMainFrame(
std::move(remote_main_frame_interfaces->main_frame_host),
std::move(remote_main_frame_interfaces->main_frame));
}
if (!success) {
remote_frame->Close(blink::DetachReason::kFrameDeletion);
return false;
}
if (is_loading)
remote_frame->DidStartLoading();
return true;
}
base::UnguessableToken RenderFrameImpl::GetDevToolsFrameToken() {
return devtools_frame_token_;
}
void RenderFrameImpl::AbortClientNavigation(bool for_new_navigation) {
CHECK(in_frame_tree_);
client_navigation_throttler_.DispatchOrScheduleNavigation(
base::BindOnce(&RenderFrameImpl::AbortClientNavigationImpl,
base::Unretained(this), for_new_navigation));
}
void RenderFrameImpl::AbortClientNavigationImpl(bool for_new_navigation) {
CHECK(navigation_client_impl_);
is_requesting_navigation_ = false;
if (mhtml_body_loader_client_) {
mhtml_body_loader_client_->Detach();
mhtml_body_loader_client_.reset();
}
NotifyObserversOfFailedProvisionalLoad();
if (for_new_navigation) {
navigation_client_impl_->ResetForNewNavigation(
false);
} else {
navigation_client_impl_->ResetForAbort();
}
navigation_client_impl_.reset();
}
void RenderFrameImpl::DidChangeSelection(bool is_empty_selection,
blink::SyncCondition force_sync) {
if (!GetLocalRootWebFrameWidget()->HandlingInputEvent() &&
!GetLocalRootWebFrameWidget()->HandlingSelectRange())
return;
if (is_empty_selection)
selection_text_.clear();
GetLocalRootWebFrameWidget()->UpdateTextInputState();
SyncSelectionIfRequired(force_sync);
}
void RenderFrameImpl::OnMainFrameIntersectionChanged(
const gfx::Rect& main_frame_intersection_rect) {
if (main_frame_intersection_rect != main_frame_intersection_rect_) {
main_frame_intersection_rect_ = main_frame_intersection_rect;
for (auto& observer : observers_) {
observer.OnMainFrameIntersectionChanged(main_frame_intersection_rect);
}
}
}
void RenderFrameImpl::OnMainFrameViewportRectangleChanged(
const gfx::Rect& main_frame_viewport_rect) {
if (main_frame_viewport_rect != main_frame_viewport_rect_) {
main_frame_viewport_rect_ = main_frame_viewport_rect;
for (auto& observer : observers_) {
observer.OnMainFrameViewportRectangleChanged(main_frame_viewport_rect);
}
}
}
void RenderFrameImpl::OnMainFrameAdRectangleChanged(int element_id,
const gfx::Rect& ad_rect) {
for (auto& observer : observers_) {
observer.OnMainFrameAdRectangleChanged(element_id, ad_rect);
}
}
void RenderFrameImpl::OnOverlayPopupAdDetected() {
for (auto& observer : observers_) {
observer.OnOverlayPopupAdDetected();
}
}
void RenderFrameImpl::OnLargeStickyAdDetected() {
for (auto& observer : observers_) {
observer.OnLargeStickyAdDetected();
}
}
void RenderFrameImpl::FinalizeRequest(blink::WebURLRequest& request) {
FinalizeRequestInternal(request, false,
ui::PAGE_TRANSITION_LINK);
}
std::optional<blink::WebURL> RenderFrameImpl::WillSendRequest(
const blink::WebURL& target,
const blink::WebSecurityOrigin& security_origin,
const net::SiteForCookies& site_for_cookies,
ForRedirect for_redirect,
const blink::WebURL& upstream_url) {
return WillSendRequestInternal(target, security_origin, site_for_cookies,
for_redirect, upstream_url,
ui::PAGE_TRANSITION_LINK);
}
std::optional<blink::WebURL> RenderFrameImpl::WillSendRequestInternal(
const blink::WebURL& target,
const blink::WebSecurityOrigin& security_origin,
const net::SiteForCookies& site_for_cookies,
ForRedirect for_redirect,
const blink::WebURL& upstream_url,
ui::PageTransition transition_type) {
std::optional<blink::WebURL> adjusted = ApplyFilePathAlias(target);
GURL new_url;
std::optional<url::Origin> initiator_origin =
security_origin.IsNull() ? std::optional<url::Origin>()
: std::optional<url::Origin>(security_origin);
GetContentClient()->renderer()->WillSendRequest(
frame_, transition_type, upstream_url,
adjusted.has_value() ? *adjusted : target, site_for_cookies,
base::OptionalToPtr(initiator_origin), &new_url);
if (!new_url.is_empty()) {
return WebURL(new_url);
}
return adjusted;
}
void RenderFrameImpl::FinalizeRequestInternal(
blink::WebURLRequest& request,
bool for_outermost_main_frame,
ui::PageTransition transition_type) {
if (GetWebView()->GetRendererPreferences().enable_do_not_track) {
request.SetHttpHeaderField(
blink::WebString::FromUTF8(blink::kDoNotTrackHeader), "1");
}
WebString custom_user_agent;
if (request.GetURLRequestExtraData()) {
blink::WebURLRequestExtraData* old_request_extra_data =
static_cast<blink::WebURLRequestExtraData*>(
request.GetURLRequestExtraData().get());
custom_user_agent = old_request_extra_data->custom_user_agent();
if (!custom_user_agent.IsNull()) {
if (custom_user_agent.IsEmpty())
request.ClearHttpHeaderField("User-Agent");
else
request.SetHttpHeaderField("User-Agent", custom_user_agent);
}
}
if (!request.GetURLRequestExtraData()) {
request.SetURLRequestExtraData(
base::MakeRefCounted<blink::WebURLRequestExtraData>());
}
auto* url_request_extra_data = static_cast<blink::WebURLRequestExtraData*>(
request.GetURLRequestExtraData().get());
url_request_extra_data->set_custom_user_agent(custom_user_agent);
url_request_extra_data->set_is_outermost_main_frame(IsMainFrame() &&
!IsInFencedFrameTree());
url_request_extra_data->set_transition_type(transition_type);
bool is_for_no_state_prefetch =
GetContentClient()->renderer()->IsPrefetchOnly(this);
url_request_extra_data->set_is_for_no_state_prefetch(
is_for_no_state_prefetch);
url_request_extra_data->set_allow_cross_origin_auth_prompt(
GetWebView()->GetRendererPreferences().allow_cross_origin_auth_prompt);
request.SetDownloadToNetworkCacheOnly(is_for_no_state_prefetch &&
!for_outermost_main_frame);
request.SetHasUserGesture(frame_->HasTransientUserActivation());
if (!GetWebView()->GetRendererPreferences().enable_referrers) {
request.SetReferrerString(WebString());
request.SetReferrerPolicy(network::mojom::ReferrerPolicy::kNever);
}
}
void RenderFrameImpl::DidLoadResourceFromMemoryCache(
const blink::WebURLRequest& request,
const blink::WebURLResponse& response) {
if (load_from_memory_cache_callback_) {
load_from_memory_cache_callback_.Run(
request.Url(), response.RequestId(),
base::ByteCount(response.EncodedBodyLength()),
response.MimeType().Utf8(), response.FromArchive());
} else {
for (auto& observer : observers_) {
observer.DidLoadResourceFromMemoryCache(
request.Url(), response.RequestId(),
base::ByteCount(response.EncodedBodyLength()),
response.MimeType().Utf8(), response.FromArchive());
}
}
}
void RenderFrameImpl::DidStartResponse(
const url::SchemeHostPort& final_response_url,
int request_id,
network::mojom::URLResponseHeadPtr response_head,
network::mojom::RequestDestination request_destination,
bool is_ad_resource) {
if (did_start_response_callback_) {
did_start_response_callback_.Run(final_response_url, request_id,
*response_head, request_destination,
is_ad_resource);
} else {
for (auto& observer : observers_) {
observer.DidStartResponse(final_response_url, request_id, *response_head,
request_destination, is_ad_resource);
}
}
}
void RenderFrameImpl::DidCompleteResponse(
int request_id,
const network::URLLoaderCompletionStatus& status) {
if (did_complete_response_callback_) {
did_complete_response_callback_.Run(request_id, status);
} else {
for (auto& observer : observers_) {
observer.DidCompleteResponse(request_id, status);
}
}
}
void RenderFrameImpl::DidCancelResponse(int request_id) {
if (did_cancel_response_callback_) {
did_cancel_response_callback_.Run(request_id);
} else {
for (auto& observer : observers_) {
observer.DidCancelResponse(request_id);
}
}
}
void RenderFrameImpl::DidReceiveTransferSizeUpdate(int resource_id,
int received_data_length) {
for (auto& observer : observers_) {
observer.DidReceiveTransferSizeUpdate(
resource_id, base::ByteCount(received_data_length));
}
}
void RenderFrameImpl::DidChangePerformanceTiming() {
for (auto& observer : observers_)
observer.DidChangePerformanceTiming();
}
void RenderFrameImpl::DidObserveUserInteraction(
base::TimeTicks max_event_start,
base::TimeTicks max_event_queued_main_thread,
base::TimeTicks max_event_commit_finish,
base::TimeTicks max_event_end,
uint64_t interaction_offset) {
for (auto& observer : observers_) {
observer.DidObserveUserInteraction(
max_event_start, max_event_queued_main_thread, max_event_commit_finish,
max_event_end, interaction_offset);
}
}
void RenderFrameImpl::DidChangeCpuTiming(base::TimeDelta time) {
for (auto& observer : observers_)
observer.DidChangeCpuTiming(time);
}
void RenderFrameImpl::DidObserveLoadingBehavior(
blink::LoadingBehaviorFlag behavior) {
for (auto& observer : observers_)
observer.DidObserveLoadingBehavior(behavior);
}
void RenderFrameImpl::DidObserveJavaScriptFrameworks(
const blink::JavaScriptFrameworkDetectionResult& result) {
for (auto& observer : observers_) {
observer.DidObserveJavaScriptFrameworks(result);
}
}
void RenderFrameImpl::DidObserveSubresourceLoad(
const blink::SubresourceLoadMetrics& subresource_load_metrics) {
if (subresource_load_callback_) {
subresource_load_callback_.Run(subresource_load_metrics);
} else {
for (auto& observer : observers_) {
observer.DidObserveSubresourceLoad(subresource_load_metrics);
}
}
}
void RenderFrameImpl::SetNewFeatureUsageCallback(
NewFeatureUsageCallback callback) {
new_feature_usage_callback_ = std::move(callback);
}
void RenderFrameImpl::SetSubresourceLoadCallback(
SubresourceLoadCallback callback) {
subresource_load_callback_ = std::move(callback);
}
void RenderFrameImpl::SetLoadFromMemoryCacheCallback(
LoadFromMemoryCacheCallback callback) {
load_from_memory_cache_callback_ = std::move(callback);
}
void RenderFrameImpl::SetDidStartResponseCallback(
DidStartResponseCallback callback) {
did_start_response_callback_ = std::move(callback);
}
void RenderFrameImpl::SetDidCompleteResponseCallback(
DidCompleteResponseCallback callback) {
did_complete_response_callback_ = std::move(callback);
}
base::WeakPtr<RenderFrame> RenderFrameImpl::GetRenderFrameWeakPtr() {
return GetWeakPtr();
}
void RenderFrameImpl::SetDidCancelResponseCallback(
DidCancelResponseCallback callback) {
did_cancel_response_callback_ = std::move(callback);
}
void RenderFrameImpl::DidObserveNewFeatureUsage(
const blink::UseCounterFeature& feature) {
TRACE_EVENT_WITH_FLOW0("navigation",
"RenderFrameImpl::DidObserveNewFeatureUsage",
TRACE_ID_LOCAL(this),
TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
if (new_feature_usage_callback_) {
new_feature_usage_callback_.Run(feature);
} else {
for (auto& observer : observers_) {
observer.DidObserveNewFeatureUsage(feature);
}
}
}
void RenderFrameImpl::DidObserveSoftNavigation(
blink::SoftNavigationMetricsForReporting metrics) {
for (auto& observer : observers_) {
observer.DidObserveSoftNavigation(metrics);
}
}
void RenderFrameImpl::DidObserveLayoutShift(double score,
bool after_input_or_scroll) {
for (auto& observer : observers_)
observer.DidObserveLayoutShift(score, after_input_or_scroll);
}
void RenderFrameImpl::DidCreateScriptContext(v8::Local<v8::Context> context,
int world_id) {
TRACE_EVENT_WITH_FLOW0("navigation",
"RenderFrameImpl::DidCreateScriptContext",
TRACE_ID_LOCAL(this),
TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
v8::MicrotasksScope microtasks(GetAgentGroupScheduler().Isolate(),
context->GetMicrotaskQueue(),
v8::MicrotasksScope::kDoNotRunMicrotasks);
if (((enabled_bindings_.Has(BindingsPolicyValue::kMojoWebUi)) ||
enable_mojo_js_bindings_) &&
IsMainFrame() && world_id == ISOLATED_WORLD_ID_GLOBAL) {
#if BUILDFLAG(ARKWEB_DISABLE_MOJO_JS)
LOG(WARNING) << "MojoJS ability is disabled for security reasons.";
#else
blink::WebV8Features::EnableMojoJS(context, true);
#endif
if (mojo_js_features_) {
if (mojo_js_features_->file_system_access)
blink::WebV8Features::EnableMojoJSFileSystemAccessHelper(context, true);
}
}
#if BUILDFLAG(ARKWEB_DISABLE_MOJO_JS)
else {
LOG(WARNING) << "For security reasons MojoJS is forcibly disabled.";
}
#endif
if (world_id == ISOLATED_WORLD_ID_GLOBAL &&
mojo_js_interface_broker_.is_valid()) {
blink::WebV8Features::EnableMojoJSAndUseBroker(
context, std::move(mojo_js_interface_broker_));
}
for (auto& observer : observers_)
observer.DidCreateScriptContext(context, world_id);
}
void RenderFrameImpl::WillReleaseScriptContext(v8::Local<v8::Context> context,
int world_id) {
for (auto& observer : observers_)
observer.WillReleaseScriptContext(context, world_id);
}
void RenderFrameImpl::DidChangeScrollOffset() {
StartDelayedSyncTimer();
for (auto& observer : observers_)
observer.DidChangeScrollOffset();
}
blink::WebMediaStreamDeviceObserver*
RenderFrameImpl::MediaStreamDeviceObserver() {
if (!web_media_stream_device_observer_)
InitializeMediaStreamDeviceObserver();
return web_media_stream_device_observer_.get();
}
blink::WebEncryptedMediaClient* RenderFrameImpl::EncryptedMediaClient() {
return media_factory_.EncryptedMediaClient();
}
blink::WebString RenderFrameImpl::UserAgentOverride() {
if (ShouldUseUserAgentOverride()) {
return WebString::FromUTF8(GetWebView()
->GetRendererPreferences()
.user_agent_override.ua_string_override);
}
#if BUILDFLAG(ARKWEB_USERAGENT)
if (auto ark_web_ua = ArkWebUserAgentOverride(this)) {
return *ark_web_ua;
}
#endif
return blink::WebString();
}
std::optional<blink::UserAgentMetadata>
RenderFrameImpl::UserAgentMetadataOverride() {
if (ShouldUseUserAgentOverride()) {
return GetWebView()
->GetRendererPreferences()
.user_agent_override.ua_metadata_override;
}
return std::nullopt;
}
bool RenderFrameImpl::ShouldUseUserAgentOverride() const {
auto* web_view = GetWebView();
if (web_view->MainFrame()->IsWebRemoteFrame())
return false;
const WebLocalFrame* main_frame = web_view->MainFrame()->ToWebLocalFrame();
WebDocumentLoader* document_loader = main_frame->GetDocumentLoader();
DocumentState* document_state =
document_loader ? DocumentState::FromDocumentLoader(document_loader)
: nullptr;
return document_state && document_state->is_overriding_user_agent();
}
blink::mojom::RendererAudioInputStreamFactory*
RenderFrameImpl::GetAudioInputStreamFactory() {
if (!audio_input_stream_factory_)
GetBrowserInterfaceBroker().GetInterface(
audio_input_stream_factory_.BindNewPipeAndPassReceiver(
agent_scheduling_group_->agent_group_scheduler()
.DefaultTaskRunner()));
return audio_input_stream_factory_.get();
}
bool RenderFrameImpl::AllowContentInitiatedDataUrlNavigations(
const blink::WebURL& url) {
return url.GetString() == kUnreachableWebDataURL;
}
void RenderFrameImpl::PostAccessibilityEvent(const ui::AXEvent& event) {
if (!IsAccessibilityEnabled())
return;
render_accessibility_manager_->GetRenderAccessibilityImpl()->HandleAXEvent(
event);
}
bool RenderFrameImpl::SendAccessibilitySerialization(
std::vector<ui::AXTreeUpdate> updates,
std::vector<ui::AXEvent> events,
ui::AXLocationAndScrollUpdates location_and_scroll_updates,
bool had_load_complete_messages) {
CHECK(IsAccessibilityEnabled());
return render_accessibility_manager_->GetRenderAccessibilityImpl()
->SendAccessibilitySerialization(std::move(updates), std::move(events),
std::move(location_and_scroll_updates),
had_load_complete_messages);
}
void RenderFrameImpl::AddObserver(RenderFrameObserver* observer) {
observers_.AddObserver(observer);
}
void RenderFrameImpl::RemoveObserver(RenderFrameObserver* observer) {
observer->RenderFrameGone();
observers_.RemoveObserver(observer);
}
void RenderFrameImpl::OnDroppedNavigation() {
is_requesting_navigation_ = false;
frame_->DidDropNavigation();
}
void RenderFrameImpl::WasHidden() {
frame_->WasHidden();
for (auto& observer : observers_)
observer.WasHidden();
}
void RenderFrameImpl::WasShown() {
frame_->WasShown();
for (auto& observer : observers_)
observer.WasShown();
}
void RenderFrameImpl::OnFrameVisibilityChanged(
blink::mojom::FrameVisibility render_status) {
for (auto& observer : observers_) {
observer.OnFrameVisibilityChanged(render_status);
}
}
bool RenderFrameImpl::IsMainFrame() {
return is_main_frame_;
}
bool RenderFrameImpl::IsInFencedFrameTree() const {
return GetWebFrame()->IsInFencedFrameTree();
}
bool RenderFrameImpl::IsHidden() {
CHECK(GetWebFrame()->IsProvisional() || GetLocalRootWebFrameWidget())
<< "Only provisional frames are created with no widget";
if (!GetLocalRootWebFrameWidget()) {
return true;
}
return GetLocalRootWebFrameWidget()->IsHidden();
}
bool RenderFrameImpl::IsLocalRoot() const {
return !(frame_->Parent() && frame_->Parent()->IsWebLocalFrame());
}
const RenderFrameImpl* RenderFrameImpl::GetLocalRoot() const {
return IsLocalRoot() ? this
: RenderFrameImpl::FromWebFrame(frame_->LocalRoot());
}
base::WeakPtr<RenderFrameImpl> RenderFrameImpl::GetWeakPtr() {
return weak_factory_.GetWeakPtr();
}
mojom::DidCommitProvisionalLoadParamsPtr
RenderFrameImpl::MakeDidCommitProvisionalLoadParams(
blink::WebHistoryCommitType commit_type,
ui::PageTransition transition,
NavigationState* navigation_state,
const network::ParsedPermissionsPolicy& permissions_policy_header,
const blink::DocumentPolicyFeatureState& document_policy_header,
const std::optional<base::UnguessableToken>& embedding_token,
std::optional<blink::PageState> previous_page_state) {
WebDocumentLoader* document_loader = frame_->GetDocumentLoader();
const WebURLResponse& response = document_loader->GetWebResponse();
auto params = mojom::DidCommitProvisionalLoadParams::New();
params->http_status_code = response.HttpStatusCode();
params->url_is_unreachable = document_loader->HasUnreachableURL();
params->method = "GET";
params->post_id = -1;
params->embedding_token = embedding_token;
params->navigation_token = navigation_state->commit_params().navigation_token;
#if BUILDFLAG(ARKWEB_NETWORK_BASE)
params->headers = navigation_state->common_params().headers;
#endif
if (params->navigation_token.is_empty())
params->navigation_token = base::UnguessableToken::Create();
params->did_create_new_entry =
(commit_type == blink::kWebStandardCommit) ||
(commit_type == blink::kWebHistoryInertCommit && !frame_->Parent() &&
document_loader->ReplacesCurrentHistoryItem() &&
!navigation_state->WasWithinSameDocument());
WebDocument frame_document = frame_->GetDocument();
WebSecurityOrigin frame_origin = frame_document.GetSecurityOrigin();
params->origin = frame_origin;
params->permissions_policy_header = permissions_policy_header;
params->document_policy_header = document_policy_header;
params->insecure_request_policy = frame_->GetInsecureRequestPolicy();
params->insecure_navigations_set = frame_->GetInsecureRequestToUpgrade();
params->has_potentially_trustworthy_unique_origin =
frame_origin.IsOpaque() && frame_origin.IsPotentiallyTrustworthy();
params->url = GetLoadingUrl();
if (params->url.IsAboutBlank() || params->url.IsAboutSrcdoc()) {
GURL base_url = frame_document.BaseURL();
if (base_url.is_valid() &&
base_url.possibly_invalid_spec().length() <= url::kMaxURLChars) {
params->initiator_base_url = base_url;
}
}
if (!IsValidCommitUrl(params->url)) {
params->url = GURL(kBlockedURL);
}
bool does_status_code_qualify_for_history =
base::FeatureList::IsEnabled(history::kVisitedLinksOn404) ||
response.HttpStatusCode() != 404;
params->should_update_history = !document_loader->HasUnreachableURL() &&
does_status_code_qualify_for_history;
if (previous_page_state.has_value()) {
params->previous_page_state = std::move(previous_page_state).value();
}
const WebHistoryItem& item = GetWebFrame()->GetCurrentHistoryItem();
params->page_state = GetWebFrame()->CurrentHistoryItemToPageState();
params->method = document_loader->HttpMethod().Latin1();
if (params->method == "POST")
params->post_id = ExtractPostId(item);
params->item_sequence_number = item.ItemSequenceNumber();
params->document_sequence_number = item.DocumentSequenceNumber();
params->navigation_api_key = item.GetNavigationApiKey().Utf8();
params->referrer = blink::mojom::Referrer::New(
blink::WebStringToGURL(document_loader->Referrer()),
network::mojom::ReferrerPolicy::kDefault);
DocumentState* document_state =
DocumentState::FromDocumentLoader(document_loader);
if (!frame_->Parent()) {
params->contents_mime_type =
document_loader->GetWebResponse().MimeType().Utf8();
params->transition = transition;
if (GetWebView()->IsFencedFrameRoot()) {
DCHECK(ui::PageTransitionCoreTypeIs(params->transition,
ui::PAGE_TRANSITION_AUTO_SUBFRAME));
} else {
DCHECK(ui::PageTransitionIsMainFrame(params->transition));
}
if (document_loader->IsClientRedirect()) {
params->transition = ui::PageTransitionFromInt(
params->transition | ui::PAGE_TRANSITION_CLIENT_REDIRECT);
}
params->is_overriding_user_agent =
document_state->is_overriding_user_agent();
params->history_list_was_cleared =
navigation_state->commit_params().should_clear_history_list;
} else {
if (commit_type == blink::kWebStandardCommit)
params->transition = ui::PAGE_TRANSITION_MANUAL_SUBFRAME;
else
params->transition = ui::PAGE_TRANSITION_AUTO_SUBFRAME;
DCHECK(!navigation_state->commit_params().should_clear_history_list);
params->history_list_was_cleared = false;
}
bool requires_universal_access = false;
const bool file_scheme_with_universal_access =
#if BUILDFLAG(ARKWEB_RECOURCE_SCHEME)
(params->origin.scheme() == url::kFileScheme ||
params->origin.scheme() == url::kResourcesScheme) &&
#else
params->origin.scheme() == url::kFileScheme &&
#endif
GetBlinkPreferences().allow_universal_access_from_file_urls;
if (!params->origin.opaque() && params->url.IsStandard() &&
GetBlinkPreferences().web_security_enabled) {
if (!params->origin.IsSameOriginWith(params->url)) {
if (!file_scheme_with_universal_access) {
SCOPED_CRASH_KEY_STRING256("MakeDCPLParams", "mismatched_url",
params->url.possibly_invalid_spec());
SCOPED_CRASH_KEY_STRING256("MakeDCPLParams", "mismatched_origin",
params->origin.GetDebugString());
NOTREACHED() << " url:" << params->url << " origin:" << params->origin;
} else {
requires_universal_access = true;
}
}
if (file_scheme_with_universal_access) {
base::UmaHistogramBoolean(
"Android.WebView.UniversalAccess.OriginUrlMismatchInRenderFrame",
requires_universal_access);
}
}
params->request_id = document_state->request_id();
params->unload_start =
GetWebFrame()->PerformanceMetricsForNestedContexts().UnloadStart();
params->unload_end =
GetWebFrame()->PerformanceMetricsForNestedContexts().UnloadEnd();
params->commit_navigation_start = navigation_state->commit_start_time();
params->commit_navigation_end = GetWebFrame()
->PerformanceMetricsForNestedContexts()
.CommitNavigationEnd();
params->commit_reply_sent = base::TimeTicks().Now();
return params;
}
void RenderFrameImpl::UpdateNavigationHistory(
blink::WebHistoryCommitType commit_type,
NavigationState* navigation_state) {
const blink::mojom::CommitNavigationParams& commit_params =
navigation_state->commit_params();
GetWebFrame()->UpdateCurrentHistoryItem();
GetWebFrame()->SetTargetToCurrentHistoryItem(
blink::WebString::FromUTF8(unique_name_helper_.value()));
bool is_new_navigation = commit_type == blink::kWebStandardCommit;
blink::WebView* webview = GetWebView();
if (commit_params.should_clear_history_list) {
webview->SetHistoryListFromNavigation( 0,
1);
} else if (is_new_navigation) {
DCHECK(!navigation_state->common_params().should_replace_current_entry ||
(webview->HistoryBackListCount() +
webview->HistoryForwardListCount() + 1) > 0);
if (!navigation_state->common_params().should_replace_current_entry)
webview->IncreaseHistoryListFromNavigation();
} else if (commit_params.nav_entry_id != 0 &&
!commit_params.intended_as_new_entry) {
webview->SetHistoryListFromNavigation(
navigation_state->commit_params().pending_history_list_index, {});
}
}
void RenderFrameImpl::NotifyObserversOfNavigationCommit(
ui::PageTransition transition) {
TRACE_EVENT_WITH_FLOW0("navigation",
"RenderFrameImpl::NotifyObserversOfNavigationCommit",
TRACE_ID_LOCAL(this),
TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT);
for (auto& observer : observers_)
observer.DidCommitProvisionalLoad(transition);
}
void RenderFrameImpl::UpdateStateForCommit(
blink::WebHistoryCommitType commit_type,
ui::PageTransition transition,
NavigationState* navigation_state) {
if (!base::FeatureList::IsEnabled(kReducePageStateIpcs)) {
SendUpdateState();
}
UpdateNavigationHistory(commit_type, navigation_state);
#if BUILDFLAG(ARKWEB_USERAGENT)
DocumentState* document_state =
DocumentState::FromDocumentLoader(frame_->GetDocumentLoader());
if (document_state->must_reset_scroll_and_scale_state()) {
GetWebView()->ResetScrollAndScaleState();
document_state->set_must_reset_scroll_and_scale_state(false);
}
#endif
if (!frame_->Parent()) {
RenderThreadImpl* render_thread_impl = RenderThreadImpl::current();
if (render_thread_impl) {
render_thread_impl->histogram_customizer()->RenderViewNavigatedToHost(
GetLoadingUrl().GetHost(), blink::WebView::GetWebViewCount());
}
}
if (IsLocalRoot()) {
auto& widget = CHECK_DEREF(GetLocalRootWebFrameWidget());
widget.SetZoomLevel(widget.GetZoomLevel());
}
if (!frame_->Parent() && !navigation_state->WasWithinSameDocument()) {
GetWebView()->ClearAutoplayFlags();
}
if (url::Origin(frame_->GetSecurityOrigin()) == autoplay_flags_.first) {
GetWebView()->AddAutoplayFlags(autoplay_flags_.second);
autoplay_flags_.first = url::Origin();
}
}
void RenderFrameImpl::DidCommitNavigationInternal(
blink::WebHistoryCommitType commit_type,
ui::PageTransition transition,
NavigationState* navigation_state,
const network::ParsedPermissionsPolicy& permissions_policy_header,
const blink::DocumentPolicyFeatureState& document_policy_header,
mojom::DidCommitProvisionalLoadInterfaceParamsPtr interface_params,
mojom::DidCommitSameDocumentNavigationParamsPtr same_document_params,
const std::optional<base::UnguessableToken>& embedding_token) {
DCHECK(!(same_document_params && interface_params));
std::optional<blink::PageState> previous_page_state = std::nullopt;
if (base::FeatureList::IsEnabled(kReducePageStateIpcs) &&
!GetWebFrame()->GetCurrentHistoryItem().IsNull()) {
previous_page_state = GetWebFrame()->CurrentHistoryItemToPageState();
}
UpdateStateForCommit(commit_type, transition, navigation_state);
if (GetBlinkPreferences().renderer_wide_named_frame_lookup)
GetWebFrame()->SetAllowsCrossBrowsingInstanceFrameLookup();
auto params = MakeDidCommitProvisionalLoadParams(
commit_type, transition, navigation_state, permissions_policy_header,
document_policy_header, embedding_token, std::move(previous_page_state));
if (same_document_params) {
GetFrameHost()->DidCommitSameDocumentNavigation(
std::move(params), std::move(same_document_params));
navigation_state->RunCommitSameDocumentNavigationCallback(
blink::mojom::CommitResult::Ok);
} else {
if (navigation_state->has_navigation_client()) {
navigation_state->RunCommitNavigationCallback(
std::move(params), std::move(interface_params));
} else {
GetFrameHost()->DidCommitProvisionalLoad(std::move(params),
std::move(interface_params));
}
}
if (IsMainFrame()) {
main_frame_intersection_rect_.reset();
main_frame_viewport_rect_.reset();
}
RendererNavigationMetricsManager::Instance().ProcessNavigationCommit(
navigation_state->commit_params().navigation_metrics_token,
navigation_state->common_params().url,
navigation_state->common_params().actual_navigation_start,
navigation_state->commit_params().commit_sent, IsMainFrame());
}
void RenderFrameImpl::PrepareFrameForCommit(
const GURL& url,
const blink::mojom::CommitNavigationParams& commit_params) {
is_requesting_navigation_ = false;
GetContentClient()->SetActiveURL(
url, frame_->Top()->GetSecurityOrigin().ToString().Utf8());
GetWebView()->SetHistoryListFromNavigation(
commit_params.current_history_list_index,
commit_params.current_history_list_length);
}
blink::mojom::CommitResult RenderFrameImpl::PrepareForHistoryNavigationCommit(
const blink::mojom::CommonNavigationParams& common_params,
const blink::mojom::CommitNavigationParams& commit_params,
WebHistoryItem* item_for_history_navigation,
blink::WebFrameLoadType* load_type) {
blink::mojom::NavigationType navigation_type = common_params.navigation_type;
DCHECK(navigation_type ==
blink::mojom::NavigationType::HISTORY_SAME_DOCUMENT ||
navigation_type ==
blink::mojom::NavigationType::HISTORY_DIFFERENT_DOCUMENT ||
navigation_type == blink::mojom::NavigationType::RESTORE ||
navigation_type == blink::mojom::NavigationType::RESTORE_WITH_POST);
*item_for_history_navigation = WebHistoryItem(
blink::PageState::CreateFromEncodedData(commit_params.page_state));
if (item_for_history_navigation->IsNull())
return blink::mojom::CommitResult::Aborted;
if (navigation_type == blink::mojom::NavigationType::HISTORY_SAME_DOCUMENT ||
navigation_type ==
blink::mojom::NavigationType::HISTORY_DIFFERENT_DOCUMENT) {
*load_type = blink::WebFrameLoadType::kBackForward;
} else {
*load_type = blink::WebFrameLoadType::kRestore;
}
history_subframe_unique_names_ = commit_params.subframe_unique_names;
if (navigation_type == blink::mojom::NavigationType::HISTORY_SAME_DOCUMENT) {
DCHECK(!GetWebFrame()->GetCurrentHistoryItem().IsNull());
if (GetWebFrame()->GetCurrentHistoryItem().IsNull()) {
SCOPED_CRASH_KEY_BOOL("history_no_item", "is_main_frame", IsMainFrame());
SCOPED_CRASH_KEY_NUMBER("history_no_item", "renderer_commit_state",
(int)navigation_commit_state_);
SCOPED_CRASH_KEY_NUMBER("history_no_item", "browser_history_index",
commit_params.current_history_list_index);
SCOPED_CRASH_KEY_NUMBER("history_no_item", "browser_history_len",
commit_params.current_history_list_length);
SCOPED_CRASH_KEY_NUMBER("history_no_item", "renderer_history_len",
GetWebView()->HistoryBackListCount() +
GetWebView()->HistoryForwardListCount() + 1);
base::debug::DumpWithoutCrashing();
return blink::mojom::CommitResult::RestartCrossDocument;
}
DCHECK_EQ(GetWebFrame()->GetCurrentHistoryItem().DocumentSequenceNumber(),
item_for_history_navigation->DocumentSequenceNumber());
if (GetWebFrame()->GetCurrentHistoryItem().DocumentSequenceNumber() !=
item_for_history_navigation->DocumentSequenceNumber()) {
SCOPED_CRASH_KEY_NUMBER(
"history_bad_seq", "browser_doc_seq_num",
item_for_history_navigation->DocumentSequenceNumber());
SCOPED_CRASH_KEY_NUMBER(
"history_bad_seq", "renderer_doc_seq_num",
GetWebFrame()->GetCurrentHistoryItem().DocumentSequenceNumber());
base::debug::DumpWithoutCrashing();
return blink::mojom::CommitResult::RestartCrossDocument;
}
}
return blink::mojom::CommitResult::Ok;
}
bool RenderFrameImpl::SwapIn(WebFrame* previous_web_frame) {
CHECK(!in_frame_tree_);
unique_name_helper_.set_propagated_name(
GetUniqueNameOfWebFrame(previous_web_frame));
bool is_main_frame = is_main_frame_;
if (!previous_web_frame->Swap(frame_)) {
DCHECK(!is_main_frame);
return false;
}
CHECK(GetLocalRootWebFrameWidget());
in_frame_tree_ = true;
if (is_main_frame_) {
GetWebView()->DidAttachLocalMainFrame();
}
return true;
}
void RenderFrameImpl::DidStartLoading() {
TRACE_EVENT1("navigation,rail", "RenderFrameImpl::didStartLoading",
"frame_token", frame_token_);
}
void RenderFrameImpl::DidStopLoading() {
TRACE_EVENT1("navigation,rail", "RenderFrameImpl::didStopLoading",
"frame_token", frame_token_);
history_subframe_unique_names_.clear();
GetFrameHost()->DidStopLoading();
}
void RenderFrameImpl::NotifyAccessibilityModeChange(ui::AXMode new_mode) {
for (auto& observer : observers_)
observer.AccessibilityModeChanged(new_mode);
}
void RenderFrameImpl::FocusedElementChanged(const blink::WebElement& element) {
for (auto& observer : observers_)
observer.FocusedElementChanged(element);
}
void RenderFrameImpl::BeginNavigation(
std::unique_ptr<blink::WebNavigationInfo> info) {
CHECK(in_frame_tree_);
const bool first_navigation_in_render_frame = !had_started_any_navigation_;
had_started_any_navigation_ = true;
const GURL& url = info->url_request.Url();
TRACE_EVENT2("navigation", "RenderFrameImpl::BeginNavigation", "url",
url.possibly_invalid_spec(), "navigation_type",
static_cast<int>(info->navigation_type));
bool use_archive = (info->archive_status ==
blink::WebNavigationInfo::ArchiveStatus::Present) &&
!url.SchemeIs(url::kDataScheme);
DCHECK(!(use_archive && IsMainFrame()));
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(ARKWEB_NETWORK_LOAD)
if (!url.is_empty() && !use_archive && !IsURLHandledByNetworkStack(url) &&
GetContentClient()->renderer()->HandleNavigation(
this, frame_, info->url_request, info->navigation_type,
info->navigation_policy, false )) {
return;
}
#endif
if (info->is_unfenced_top_navigation) {
OpenURL(std::move(info));
return;
}
if (IsTopLevelNavigation(frame_) &&
GetWebView()
->GetRendererPreferences()
.browser_handles_all_top_level_requests) {
OpenURL(std::move(info));
return;
}
bool is_history_navigation_in_new_child_frame = false;
if (info->is_history_navigation_in_new_child_frame && frame_->Parent() &&
!use_archive) {
RenderFrameImpl* parent = RenderFrameImpl::FromWebFrame(frame_->Parent());
auto iter = parent->history_subframe_unique_names_.find(
unique_name_helper_.value());
if (iter != parent->history_subframe_unique_names_.end()) {
bool history_item_is_about_blank = iter->second;
is_history_navigation_in_new_child_frame =
!history_item_is_about_blank || url != url::kAboutBlankURL;
parent->history_subframe_unique_names_.erase(iter);
}
}
if (is_history_navigation_in_new_child_frame) {
if (info->is_client_redirect) {
is_history_navigation_in_new_child_frame = false;
GetFrameHost()->CancelInitialHistoryLoad();
}
}
GURL old_url(frame_->GetDocumentLoader()->GetUrl());
if (IsTopLevelNavigation(frame_) && !url.SchemeIs(url::kAboutScheme) &&
!url.is_empty()) {
bool should_fork = HasWebUIScheme(url) || HasWebUIScheme(old_url) ||
enabled_bindings_.HasAny(kWebUIBindingsPolicySet);
if (should_fork) {
OpenURL(std::move(info));
return;
}
}
if (frame_->IsOutermostMainFrame() && url.is_valid() &&
url.SchemeIsHTTPOrHTTPS() &&
(base::FeatureList::IsEnabled(
blink::features::kHttpDiskCachePrewarming) ||
base::FeatureList::IsEnabled(
blink::features::kSpeculativeServiceWorkerWarmUp))) {
frame_->MaybeStartOutermostMainFrameNavigation(std::vector<WebURL>({url}));
}
if (info->navigation_policy == blink::kWebNavigationPolicyDownload) {
#if BUILDFLAG(ARKWEB_DISABLE_MOJO_JS)
LOG(INFO) << "download url from rfh";
#endif
mojo::PendingRemote<blink::mojom::BlobURLToken> blob_url_token =
CloneBlobURLToken(info->blob_url_token);
frame_->DownloadURL(info->url_request,
network::mojom::RedirectMode::kFollow,
std::move(blob_url_token));
return;
}
if (info->navigation_policy != blink::kWebNavigationPolicyCurrentTab) {
OpenURL(std::move(info));
return;
}
base::WeakPtr<RenderFrameImpl> weak_self = weak_factory_.GetWeakPtr();
base::TimeTicks renderer_before_unload_start = base::TimeTicks::Now();
if (!frame_->DispatchBeforeUnloadEvent(info->navigation_type ==
blink::kWebNavigationTypeReload) ||
!weak_self) {
return;
}
base::TimeTicks renderer_before_unload_end = base::TimeTicks::Now();
if (!info->form.IsNull()) {
for (auto& observer : observers_)
observer.WillSubmitForm(info->form);
}
if (mhtml_body_loader_client_) {
mhtml_body_loader_client_->Detach();
mhtml_body_loader_client_.reset();
}
bool should_do_synchronous_about_blank_navigation =
WebDocumentLoader::WillLoadUrlAsEmpty(url) &&
info->url_request.HttpMethod().Equals("GET") &&
frame_->IsOnInitialEmptyDocument() && first_navigation_in_render_frame &&
!is_history_navigation_in_new_child_frame &&
(IsMainFrame() || info->url_request.RequestorOrigin().IsSameOriginWith(
static_cast<WebLocalFrame*>(frame_->Parent())
->GetDocument()
.GetSecurityOrigin()));
if (should_do_synchronous_about_blank_navigation) {
for (auto& observer : observers_)
observer.DidStartNavigation(url, info->navigation_type);
SynchronouslyCommitAboutBlankForBug778318(std::move(info));
return;
}
#if BUILDFLAG(ARKWEB_LOGGER_REPORT)
if (IsMainFrame()) {
LOG_FEEDBACK(INFO) << "Begin navigation frame_token: " << frame_token_;
}
#endif
if (!frame_->WillStartNavigation(*info)) {
return;
}
for (auto& observer : observers_) {
observer.DidStartNavigation(info->url_request.Url(), info->navigation_type);
}
auto do_begin_navigation = base::BindOnce(
&RenderFrameImpl::BeginNavigationInternal, base::Unretained(this),
std::move(info), is_history_navigation_in_new_child_frame,
renderer_before_unload_start, renderer_before_unload_end);
client_navigation_throttler_.DispatchOrScheduleNavigation(
std::move(do_begin_navigation));
}
void RenderFrameImpl::SynchronouslyCommitAboutBlankForBug778318(
std::unique_ptr<blink::WebNavigationInfo> info) {
CHECK_EQ(NavigationCommitState::kInitialEmptyDocument,
navigation_commit_state_);
navigation_commit_state_ = NavigationCommitState::kNone;
AssertNavigationCommits assert_navigation_commits(this);
auto navigation_params = WebNavigationParams::CreateFromInfo(*info);
navigation_params->document_token = frame_->GetDocument().Token();
navigation_params->is_synchronous_commit_for_bug_778318 = true;
navigation_params->service_worker_network_provider =
ServiceWorkerNetworkProviderForFrame::CreateInvalidInstance();
DCHECK(IsMainFrame() || navigation_params->frame_load_type ==
WebFrameLoadType::kReplaceCurrentItem);
if (info->initiator_frame_token.has_value() &&
WebFrame::FromFrameToken(info->initiator_frame_token.value())) {
WebFrame* initiator =
WebFrame::FromFrameToken(info->initiator_frame_token.value());
DCHECK(initiator->IsWebLocalFrame());
navigation_params->referrer =
initiator->ToWebLocalFrame()->GetDocument().Url().GetString();
}
frame_->CommitNavigation(std::move(navigation_params), BuildDocumentState());
}
void RenderFrameImpl::SerializeAsMHTML(mojom::SerializeAsMHTMLParamsPtr params,
SerializeAsMHTMLCallback callback) {
TRACE_EVENT0("page-serialization", "RenderFrameImpl::SerializeAsMHTML");
const WebString mhtml_boundary =
WebString::FromUTF8(params->mhtml_boundary_marker);
DCHECK(!mhtml_boundary.IsEmpty());
std::vector<WebThreadSafeData> mhtml_contents;
auto delegate =
std::make_unique<MHTMLPartsGenerationDelegateImpl>(std::move(params));
if (IsMainFrame()) {
TRACE_EVENT0("page-serialization",
"RenderFrameImpl::SerializeAsMHTML header");
mhtml_contents.emplace_back(WebFrameSerializer::GenerateMHTMLHeader(
mhtml_boundary, GetWebFrame(), delegate.get()));
}
TRACE_EVENT0("page-serialization",
"RenderFrameImpl::SerializeAsMHTML parts serialization");
MHTMLPartsGenerationDelegateImpl* delegate_ptr = delegate.get();
WebFrameSerializer::GenerateMHTMLParts(
mhtml_boundary, GetWebFrame(), delegate_ptr,
base::BindOnce(&RenderFrameImpl::OnSerializeMHTMLComplete,
weak_factory_.GetWeakPtr(), std::move(delegate),
std::move(callback), std::move(mhtml_contents)));
}
void RenderFrameImpl::OnSerializeMHTMLComplete(
std::unique_ptr<MHTMLPartsGenerationDelegateImpl> delegate,
SerializeAsMHTMLCallback callback,
std::vector<blink::WebThreadSafeData> mhtml_contents,
blink::WebThreadSafeData frame_mhtml_data) {
TRACE_EVENT0("page-serialization",
"RenderFrameImpl::SerializeAsMHTML parts serialization");
mhtml_contents.emplace_back(frame_mhtml_data);
bool has_some_data = false;
for (const auto& c : mhtml_contents) {
if (!c.IsEmpty()) {
has_some_data = true;
break;
}
}
MHTMLHandleWriterDelegate handle_delegate(
*delegate->TakeParams(),
base::BindOnce(&RenderFrameImpl::OnWriteMHTMLComplete,
weak_factory_.GetWeakPtr(), std::move(callback),
delegate->TakeSerializedResourcesUriDigests()),
GetTaskRunner(blink::TaskType::kInternalDefault));
if (has_some_data) {
handle_delegate.WriteContents(mhtml_contents);
} else {
handle_delegate.Finish(mojom::MhtmlSaveStatus::kSuccess);
}
}
void RenderFrameImpl::OnWriteMHTMLComplete(
SerializeAsMHTMLCallback callback,
std::unordered_set<std::string> serialized_resources_uri_digests,
mojom::MhtmlSaveStatus save_status) {
TRACE_EVENT1("page-serialization", "RenderFrameImpl::OnWriteMHTMLComplete",
"frame save status", save_status);
DCHECK(RenderThread::IsMainThread())
<< "Must run in the main renderer thread";
std::vector<std::string> digests_of_new_parts(
std::make_move_iterator(serialized_resources_uri_digests.begin()),
std::make_move_iterator(serialized_resources_uri_digests.end()));
std::move(callback).Run(save_status, std::move(digests_of_new_parts));
}
#ifndef STATIC_ASSERT_ENUM
#define STATIC_ASSERT_ENUM(a, b) \
static_assert(static_cast<int>(a) == static_cast<int>(b), \
"mismatching enums: " #a)
#undef STATIC_ASSERT_ENUM
#endif
void RenderFrameImpl::RequestOverlayRoutingToken(
media::RoutingTokenCallback callback) {
std::move(callback).Run(GetWebFrame()->GetFrameToken().value());
}
void RenderFrameImpl::OpenURL(std::unique_ptr<blink::WebNavigationInfo> info) {
DCHECK(!info->url_request.RequestorOrigin().IsNull());
WebNavigationPolicy policy = info->navigation_policy;
auto params = blink::mojom::OpenURLParams::New();
params->url = info->url_request.Url();
params->initiator_origin = info->url_request.RequestorOrigin();
if (info->requestor_base_url.IsValid()) {
params->initiator_base_url = info->requestor_base_url;
}
params->actual_navigation_start = info->actual_navigation_start;
params->post_body = blink::GetRequestBodyForWebURLRequest(info->url_request);
DCHECK_EQ(!!params->post_body, IsHttpPost(info->url_request));
params->extra_headers =
blink::GetWebURLRequestHeadersAsString(info->url_request).Latin1();
params->referrer = blink::mojom::Referrer::New(
blink::WebStringToGURL(info->url_request.ReferrerString()),
info->url_request.GetReferrerPolicy());
params->disposition = NavigationPolicyToDisposition(policy);
params->triggering_event_info = info->triggering_event_info;
params->blob_url_token = CloneBlobURLToken(info->blob_url_token);
params->should_replace_current_entry =
info->frame_load_type == WebFrameLoadType::kReplaceCurrentItem &&
GetWebView()->HistoryBackListCount() +
GetWebView()->HistoryForwardListCount() + 1;
params->user_gesture = info->has_transient_user_activation;
params->is_unfenced_top_navigation = info->is_unfenced_top_navigation;
params->initiator_navigation_state_keep_alive_handle =
std::move(info->initiator_navigation_state_keep_alive_handle);
params->initiator_frame_token = info->initiator_frame_token;
params->source_location = network::mojom::SourceLocation::New();
params->impression = info->impression;
if (GetContentClient()->renderer()->AllowPopup())
params->user_gesture = true;
DCHECK(!is_main_frame_ || !frame_->HasTransientUserActivation());
if (!is_main_frame_ &&
(policy == blink::kWebNavigationPolicyNewBackgroundTab ||
policy == blink::kWebNavigationPolicyNewForegroundTab ||
policy == blink::kWebNavigationPolicyNewWindow ||
policy == blink::kWebNavigationPolicyNewPopup ||
policy == blink::kWebNavigationPolicyPictureInPicture)) {
frame_->ConsumeTransientUserActivation();
}
params->href_translate = info->href_translate.Latin1();
bool current_frame_has_download_sandbox_flag = !frame_->IsAllowedToDownload();
bool has_download_sandbox_flag =
info->initiator_frame_has_download_sandbox_flag ||
current_frame_has_download_sandbox_flag;
bool from_ad = info->initiator_frame_is_ad || frame_->IsAdFrame();
params->download_policy.ApplyDownloadFramePolicy(
info->is_opener_navigation, info->url_request.HasUserGesture(),
info->url_request.RequestorOrigin().CanAccess(
frame_->GetSecurityOrigin()),
has_download_sandbox_flag, from_ad);
params->initiator_activation_and_ad_status =
blink::GetNavigationInitiatorActivationAndAdStatus(
info->url_request.HasUserGesture(), info->initiator_frame_is_ad,
info->is_ad_script_in_stack);
params->has_rel_opener = info->has_rel_opener;
GetFrameHost()->OpenURL(std::move(params));
}
void RenderFrameImpl::SetLoaderFactoryBundle(
scoped_refptr<blink::ChildURLLoaderFactoryBundle> loader_factories) {
background_resource_fetch_context_.reset();
loader_factories_ = std::move(loader_factories);
}
blink::ChildURLLoaderFactoryBundle* RenderFrameImpl::GetLoaderFactoryBundle() {
DCHECK(loader_factories_);
return loader_factories_.get();
}
scoped_refptr<blink::ChildURLLoaderFactoryBundle>
RenderFrameImpl::CreateLoaderFactoryBundle(
std::unique_ptr<blink::PendingURLLoaderFactoryBundle> info,
std::optional<std::vector<blink::mojom::TransferrableURLLoaderPtr>>
subresource_overrides,
mojo::PendingRemote<network::mojom::URLLoaderFactory>
subresource_proxying_loader_factory,
mojo::PendingRemote<network::mojom::URLLoaderFactory>
keep_alive_loader_factory,
mojo::PendingAssociatedRemote<blink::mojom::FetchLaterLoaderFactory>
fetch_later_loader_factory) {
DCHECK(info);
info = MaybeSetUpLocalResourceLoader(std::move(info));
auto loader_factories =
base::MakeRefCounted<blink::HostChildURLLoaderFactoryBundle>(
GetTaskRunner(blink::TaskType::kInternalLoading));
loader_factories->Update(
std::make_unique<blink::ChildPendingURLLoaderFactoryBundle>(
std::move(info)));
if (subresource_overrides) {
loader_factories->UpdateSubresourceOverrides(&*subresource_overrides);
}
if (subresource_proxying_loader_factory) {
loader_factories->SetSubresourceProxyingLoaderFactory(
std::move(subresource_proxying_loader_factory));
}
if (keep_alive_loader_factory) {
loader_factories->SetKeepAliveLoaderFactory(
std::move(keep_alive_loader_factory));
}
if (base::FeatureList::IsEnabled(blink::features::kFetchLaterAPI) &&
fetch_later_loader_factory) {
loader_factories->SetFetchLaterLoaderFactory(
std::move(fetch_later_loader_factory));
}
return loader_factories;
}
void RenderFrameImpl::UpdateEncoding(WebFrame* frame,
const std::string& encoding_name) {
if (!frame->Parent()) {
GetFrameHost()->UpdateEncoding(encoding_name);
}
}
void RenderFrameImpl::SyncSelectionIfRequired(blink::SyncCondition force_sync) {
std::u16string text;
size_t offset;
gfx::Range range;
{
WebInputMethodController* controller = frame_->GetInputMethodController();
WebRange selection = controller->GetSelectionOffsets();
if (selection.IsNull())
return;
range = gfx::Range(selection.StartOffset(), selection.EndOffset());
if (controller->TextInputType() != blink::kWebTextInputTypeNone) {
if (selection.StartOffset() > kExtraCharsBeforeAndAfterSelection)
offset = selection.StartOffset() - kExtraCharsBeforeAndAfterSelection;
else
offset = 0;
size_t length =
selection.EndOffset() - offset + kExtraCharsBeforeAndAfterSelection;
#if BUILDFLAG(ARKWEB_MENU)
text = frame_->RangeAsText(WebRange(offset, length)).Utf16();
#else
WebString value = controller->TextInputInfo().value;
text = value.IsNull() ? value.Utf16()
: value.Substring(offset, length).Utf16();
#endif
} else {
offset = selection.StartOffset();
text = frame_->SelectionAsText().Utf16();
range.set_end(range.start() + text.length());
}
}
if (force_sync == blink::SyncCondition::kForced ||
selection_text_offset_ != offset || selection_range_ != range ||
selection_text_ != text) {
selection_text_ = text;
selection_text_offset_ = offset;
selection_range_ = range;
SetSelectedText(text, offset, range);
}
GetLocalRootWebFrameWidget()->UpdateSelectionBounds();
}
void RenderFrameImpl::CreateAudioInputStream(
blink::CrossVariantMojoRemote<
blink::mojom::RendererAudioInputStreamFactoryClientInterfaceBase>
client,
const base::UnguessableToken& session_id,
const media::AudioParameters& params,
bool automatic_gain_control,
uint32_t shared_memory_count,
blink::CrossVariantMojoReceiver<
media::mojom::AudioProcessorControlsInterfaceBase> controls_receiver,
const media::AudioProcessingSettings* settings) {
DCHECK_EQ(!!settings, !!controls_receiver);
media::mojom::AudioProcessingConfigPtr processing_config;
if (controls_receiver) {
DCHECK(settings);
processing_config = media::mojom::AudioProcessingConfig::New(
std::move(controls_receiver), *settings);
}
GetAudioInputStreamFactory()->CreateStream(
std::move(client), session_id, params, automatic_gain_control,
shared_memory_count, std::move(processing_config));
}
void RenderFrameImpl::AssociateInputAndOutputForAec(
const base::UnguessableToken& input_stream_id,
const std::string& output_device_id) {
GetAudioInputStreamFactory()->AssociateInputAndOutputForAec(input_stream_id,
output_device_id);
}
void RenderFrameImpl::InitializeMediaStreamDeviceObserver() {
RenderThreadImpl* render_thread = RenderThreadImpl::current();
if (!render_thread)
return;
DCHECK(!web_media_stream_device_observer_);
web_media_stream_device_observer_ =
std::make_unique<blink::WebMediaStreamDeviceObserver>(GetWebFrame());
}
void RenderFrameImpl::BeginNavigationInternal(
std::unique_ptr<blink::WebNavigationInfo> info,
bool is_history_navigation_in_new_child_frame,
base::TimeTicks renderer_before_unload_start,
base::TimeTicks renderer_before_unload_end) {
CHECK(!GetWebFrame()->IsProvisional());
is_requesting_navigation_ = true;
WebDocument frame_document = frame_->GetDocument();
if (info->frame_type == blink::mojom::RequestContextFrameType::kTopLevel) {
info->url_request.SetSiteForCookies(
net::SiteForCookies::FromUrl(info->url_request.Url()));
} else {
info->url_request.SetSiteForCookies(frame_document.SiteForCookies());
}
ui::PageTransition transition_type = GetTransitionType(
ui::PAGE_TRANSITION_LINK,
info->frame_load_type == WebFrameLoadType::kReplaceCurrentItem,
IsMainFrame(), GetWebView()->IsFencedFrameRoot(), info->navigation_type);
if (info->is_client_redirect) {
transition_type = ui::PageTransitionFromInt(
transition_type | ui::PAGE_TRANSITION_CLIENT_REDIRECT);
}
#if BUILDFLAG(ARKWEB_EXT_RECEIVE_RESPONSE)
if (info->is_triggered_by_js) {
transition_type = ui::PageTransitionFromInt(
transition_type | ui::PAGE_TRANSITION_FROM_JAVASCRIPT);
}
#endif
bool for_outermost_main_frame = frame_->IsOutermostMainFrame();
{
std::optional<blink::WebURL> adjusted_request_url = WillSendRequestInternal(
info->url_request.Url(), info->url_request.RequestorOrigin(),
info->url_request.SiteForCookies(), ForRedirect(false),
GURL(), transition_type);
if (adjusted_request_url.has_value()) {
info->url_request.SetUrl(adjusted_request_url.value());
}
}
FinalizeRequestInternal(info->url_request, for_outermost_main_frame,
transition_type);
DCHECK(info->url_request.GetURLRequestExtraData());
DCHECK_EQ(network::mojom::RequestMode::kNavigate,
info->url_request.GetMode());
DCHECK_EQ(network::mojom::CredentialsMode::kInclude,
info->url_request.GetCredentialsMode());
DCHECK_EQ(network::mojom::RedirectMode::kManual,
info->url_request.GetRedirectMode());
DCHECK(frame_->Parent() ||
info->frame_type == blink::mojom::RequestContextFrameType::kTopLevel);
DCHECK(!frame_->Parent() ||
info->frame_type == blink::mojom::RequestContextFrameType::kNested);
bool is_form_submission =
(info->navigation_type == blink::kWebNavigationTypeFormSubmitted ||
info->navigation_type ==
blink::kWebNavigationTypeFormResubmittedBackForward ||
info->navigation_type == blink::kWebNavigationTypeFormResubmittedReload);
bool was_initiated_by_link_click =
info->navigation_type == blink::kWebNavigationTypeLinkClicked;
GURL searchable_form_url;
std::string searchable_form_encoding;
if (!info->form.IsNull()) {
WebSearchableFormData web_searchable_form_data(info->form);
searchable_form_url = web_searchable_form_data.Url();
searchable_form_encoding = web_searchable_form_data.Encoding().Utf8();
}
GURL client_side_redirect_url;
if (info->is_client_redirect)
client_side_redirect_url = frame_->GetDocument().Url();
mojo::PendingRemote<blink::mojom::BlobURLToken> blob_url_token(
CloneBlobURLToken(info->blob_url_token));
int load_flags = info->url_request.GetLoadFlagsForWebUrlRequest();
std::optional<base::Value::Dict> devtools_initiator;
if (!info->devtools_initiator_info.IsNull()) {
std::optional<base::Value> devtools_initiator_value =
base::JSONReader::Read(info->devtools_initiator_info.Utf8(),
base::JSON_PARSE_CHROMIUM_EXTENSIONS);
if (devtools_initiator_value && devtools_initiator_value->is_dict()) {
devtools_initiator = std::move(*devtools_initiator_value).TakeDict();
}
}
blink::mojom::NavigationInitiatorActivationAndAdStatus
initiator_activation_and_ad_status =
blink::GetNavigationInitiatorActivationAndAdStatus(
info->url_request.HasUserGesture(), info->initiator_frame_is_ad,
info->is_ad_script_in_stack);
blink::mojom::BeginNavigationParamsPtr begin_params =
blink::mojom::BeginNavigationParams::New(
info->initiator_frame_token,
blink::GetWebURLRequestHeadersAsString(info->url_request).Latin1(),
load_flags, info->url_request.GetSkipServiceWorker(),
blink::GetRequestContextTypeForWebURLRequest(info->url_request),
blink::GetMixedContentContextTypeForWebURLRequest(info->url_request),
is_form_submission, was_initiated_by_link_click,
info->force_history_push, searchable_form_url,
searchable_form_encoding, client_side_redirect_url,
std::move(devtools_initiator),
info->url_request.TrustTokenParams()
? info->url_request.TrustTokenParams()->Clone()
: nullptr,
info->impression, renderer_before_unload_start,
renderer_before_unload_end, initiator_activation_and_ad_status,
info->is_container_initiated, info->storage_access_api_status,
info->has_rel_opener);
bool current_frame_has_download_sandbox_flag = !frame_->IsAllowedToDownload();
bool has_download_sandbox_flag =
info->initiator_frame_has_download_sandbox_flag ||
current_frame_has_download_sandbox_flag;
bool from_ad = info->initiator_frame_is_ad || frame_->IsAdFrame();
mojo::PendingRemote<blink::mojom::NavigationStateKeepAliveHandle>
initiator_navigation_state_keep_alive_handle =
std::move(info->initiator_navigation_state_keep_alive_handle);
network::mojom::RequestDestination request_destination =
blink::GetRequestDestinationForWebURLRequest(info->url_request);
blink::mojom::CommonNavigationParamsPtr common_params =
MakeCommonNavigationParams(frame_->GetSecurityOrigin(), std::move(info),
load_flags, has_download_sandbox_flag, from_ad,
is_history_navigation_in_new_child_frame,
request_destination);
bool is_duplicate_navigation = false;
base::TimeDelta nav_start_diff;
if (navigation_client_impl_ &&
navigation_client_impl_->HasBeginNavigationParams()) {
auto& prev_begin_params = navigation_client_impl_->begin_params();
auto& prev_common_params = navigation_client_impl_->common_params();
if (begin_params->was_initiated_by_link_click ==
prev_begin_params.was_initiated_by_link_click &&
common_params->url == prev_common_params.url &&
common_params->method == "GET" && prev_common_params.method == "GET" &&
common_params->initiator_origin ==
prev_common_params.initiator_origin &&
common_params->has_user_gesture ==
prev_common_params.has_user_gesture &&
common_params->referrer == prev_common_params.referrer &&
common_params->transition == prev_common_params.transition &&
common_params->should_replace_current_entry ==
prev_common_params.should_replace_current_entry &&
begin_params->headers == prev_begin_params.headers &&
begin_params->has_rel_opener == prev_begin_params.has_rel_opener) {
is_duplicate_navigation = true;
nav_start_diff = (common_params->navigation_start -
prev_common_params.navigation_start);
}
}
base::UmaHistogramBoolean(
"Navigation.RendererInitiated.IsDuplicateWithoutThresholdCheck2",
is_duplicate_navigation);
if (is_duplicate_navigation) {
bool start_diff_under_threshold =
(nav_start_diff <= features::kDuplicateNavThreshold.Get());
base::UmaHistogramBoolean(
"Navigation.RendererInitiated.DuplicateNavIsUnderThreshold2",
start_diff_under_threshold);
base::UmaHistogramTimes(
"Navigation.RendererInitiated.DuplicateNavStartTimeDiff2",
nav_start_diff);
if (start_diff_under_threshold &&
GetContentClient()->ShouldIgnoreDuplicateNavs(
common_params->url, true)) {
if (!base::FeatureList::IsEnabled(
features::kIgnoreDuplicateNavsOnlyWithUserGesture) ||
common_params->has_user_gesture) {
DVLOG(0) << "Ignoring duplicate navigation to " << common_params->url
<< " due to the short interval of " << nav_start_diff
<< " since the previous one.";
return;
}
}
}
mojo::PendingAssociatedRemote<mojom::NavigationClient>
navigation_client_remote;
BindNavigationClientWithParams(
navigation_client_remote.InitWithNewEndpointAndPassReceiver(),
begin_params.Clone(), common_params.Clone(), is_duplicate_navigation);
mojo::PendingReceiver<mojom::NavigationRendererCancellationListener>
renderer_cancellation_listener_receiver;
navigation_client_impl_->SetUpRendererInitiatedNavigation(
renderer_cancellation_listener_receiver.InitWithNewPipeAndPassRemote());
GetFrameHost()->BeginNavigation(
std::move(common_params), std::move(begin_params),
std::move(blob_url_token), std::move(navigation_client_remote),
std::move(initiator_navigation_state_keep_alive_handle),
std::move(renderer_cancellation_listener_receiver));
}
void RenderFrameImpl::DecodeDataURL(
const blink::mojom::CommonNavigationParams& common_params,
const blink::mojom::CommitNavigationParams& commit_params,
std::string* mime_type,
std::string* charset,
std::string* data,
GURL* base_url) {
GURL data_url = common_params.url;
#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(ARKWEB_NETWORK_BASE)
if (!commit_params.data_url_as_string.empty()) {
#if DCHECK_IS_ON()
{
std::string mime_type_tmp, charset_tmp, data_tmp;
DCHECK(net::DataURL::Parse(data_url, &mime_type_tmp, &charset_tmp,
&data_tmp));
DCHECK(data_tmp.empty());
}
#endif
data_url = GURL(commit_params.data_url_as_string);
if (!data_url.is_valid() || !data_url.SchemeIs(url::kDataScheme)) {
data_url = common_params.url;
}
}
#endif
if (net::DataURL::Parse(data_url, mime_type, charset, data)) {
*base_url = common_params.base_url_for_data_url.is_empty()
? common_params.url
: common_params.base_url_for_data_url;
} else {
NOTREACHED() << "Invalid URL passed: "
<< common_params.url.possibly_invalid_spec();
}
}
void RenderFrameImpl::SendUpdateState() {
delayed_state_sync_timer_.Stop();
if (GetWebFrame()->GetCurrentHistoryItem().IsNull())
return;
GetFrameHost()->UpdateState(GetWebFrame()->CurrentHistoryItemToPageState());
}
std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
RenderFrameImpl::MaybeSetUpLocalResourceLoader(
std::unique_ptr<blink::PendingURLLoaderFactoryBundle> factory_bundle) {
if (!factory_bundle->local_resource_loader_config()) {
return factory_bundle;
}
local_resource_loader_.emplace(
base::ThreadPool::CreateSequencedTaskRunner(
{base::TaskPriority::USER_BLOCKING, base::MayBlock(),
base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}),
std::move(factory_bundle->local_resource_loader_config()),
std::move(factory_bundle->pending_default_factory()));
mojo::PendingRemote<network::mojom::URLLoaderFactory> pending_remote;
local_resource_loader_
.AsyncCall(&content::LocalResourceURLLoaderFactory::Clone)
.WithArgs(pending_remote.InitWithNewPipeAndPassReceiver());
factory_bundle->pending_default_factory() = std::move(pending_remote);
return factory_bundle;
}
blink::WebURL RenderFrameImpl::LastCommittedUrlForUKM() {
return GetLoadingUrl();
}
GURL RenderFrameImpl::GetLoadingUrl() const {
WebDocumentLoader* document_loader = frame_->GetDocumentLoader();
GURL overriden_url;
if (MaybeGetOverriddenURL(document_loader, &overriden_url))
return overriden_url;
return document_loader->GetUrl();
}
media::MediaPermission* RenderFrameImpl::GetMediaPermission() {
if (!media_permission_dispatcher_) {
media_permission_dispatcher_ =
std::make_unique<MediaPermissionDispatcher>(this);
}
return media_permission_dispatcher_.get();
}
void RenderFrameImpl::RegisterMojoInterfaces() {
GetAssociatedInterfaceRegistry()
->AddInterface<blink::mojom::AutoplayConfigurationClient>(
base::BindRepeating(&RenderFrameImpl::BindAutoplayConfiguration,
weak_factory_.GetWeakPtr()));
GetAssociatedInterfaceRegistry()->AddInterface<mojom::FrameBindingsControl>(
base::BindRepeating(&RenderFrameImpl::BindFrameBindingsControl,
weak_factory_.GetWeakPtr()));
GetAssociatedInterfaceRegistry()->AddInterface<mojom::NavigationClient>(
base::BindRepeating(&RenderFrameImpl::BindNavigationClient,
weak_factory_.GetWeakPtr()));
GetAssociatedInterfaceRegistry()->AddInterface<mojom::MhtmlFileWriter>(
base::BindRepeating(&RenderFrameImpl::BindMhtmlFileWriter,
base::Unretained(this)));
GetAssociatedInterfaceRegistry()
->AddInterface<blink::mojom::RenderAccessibility>(base::BindRepeating(
&RenderAccessibilityManager::BindReceiver,
base::Unretained(render_accessibility_manager_.get())));
#if BUILDFLAG(IS_ANDROID)
GetAssociatedInterfaceRegistry()->AddInterface<mojom::GinJavaBridge>(
base::BindRepeating(&RenderFrameImpl::BindGinJavaBridge,
weak_factory_.GetWeakPtr()));
#endif
GetAssociatedInterfaceRegistry()->AddInterface<mojom::OhGinJavascriptBridge>(
base::BindRepeating(&RenderFrameImpl::BindOhGinJavascriptBridge,
weak_factory_.GetWeakPtr()));
}
#if BUILDFLAG(IS_ANDROID)
void RenderFrameImpl::BindGinJavaBridge(
mojo::PendingAssociatedReceiver<mojom::GinJavaBridge> receiver) {
mojo::MakeSelfOwnedAssociatedReceiver(
std::make_unique<GinJavaBridgeDispatcher>(this), std::move(receiver));
}
#endif
void RenderFrameImpl::BindOhGinJavascriptBridge(
mojo::PendingAssociatedReceiver<mojom::OhGinJavascriptBridge> receiver) {
mojo::MakeSelfOwnedAssociatedReceiver(
std::make_unique<NWEB::OhGinJavascriptBridgeDispatcher>(this), std::move(receiver));
}
void RenderFrameImpl::BindMhtmlFileWriter(
mojo::PendingAssociatedReceiver<mojom::MhtmlFileWriter> receiver) {
mhtml_file_writer_receiver_.reset();
mhtml_file_writer_receiver_.Bind(
std::move(receiver), GetTaskRunner(blink::TaskType::kInternalDefault));
}
scoped_refptr<network::SharedURLLoaderFactory>
RenderFrameImpl::GetURLLoaderFactory() {
if (!RenderThreadImpl::current()) {
if (url_loader_factory_override_for_test_) {
return url_loader_factory_override_for_test_;
}
for (auto* ancestor = GetWebFrame()->Parent(); ancestor;
ancestor = ancestor->Parent()) {
RenderFrameImpl* ancestor_frame = RenderFrameImpl::FromWebFrame(ancestor);
if (ancestor_frame &&
ancestor_frame->url_loader_factory_override_for_test_) {
return ancestor_frame->url_loader_factory_override_for_test_;
}
}
NOTREACHED();
}
return GetLoaderFactoryBundle();
}
blink::URLLoaderThrottleProvider*
RenderFrameImpl::GetURLLoaderThrottleProvider() {
RenderThreadImpl* render_thread = RenderThreadImpl::current();
return render_thread ? render_thread->url_loader_throttle_provider()
: nullptr;
}
scoped_refptr<blink::WebBackgroundResourceFetchAssets>
RenderFrameImpl::MaybeGetBackgroundResourceFetchAssets() {
if (!base::FeatureList::IsEnabled(
blink::features::kBackgroundResourceFetch)) {
return nullptr;
}
if (!background_resource_fetch_context_) {
if (!background_resource_fetch_task_runner_) {
background_resource_fetch_task_runner_ =
base::ThreadPool::CreateSequencedTaskRunner(
{base::TaskPriority::USER_BLOCKING});
}
background_resource_fetch_context_ =
base::MakeRefCounted<BackgroundResourceFetchAssets>(
GetLoaderFactoryBundle()->Clone(),
GetURLLoaderThrottleProvider()
? GetURLLoaderThrottleProvider()->Clone()
: nullptr,
background_resource_fetch_task_runner_,
frame_->GetLocalFrameToken());
}
return background_resource_fetch_context_;
}
void RenderFrameImpl::OnStopLoading() {
for (auto& observer : observers_)
observer.OnStop();
}
bool RenderFrameImpl::IsRequestingNavigation() {
return is_requesting_navigation_;
}
void RenderFrameImpl::LoadHTMLStringForTesting(std::string_view html,
const GURL& base_url,
const std::string& text_encoding,
const GURL& unreachable_url,
bool replace_current_item) {
AssertNavigationCommits assert_navigation_commits(
this, kMayReplaceInitialEmptyDocument);
mojo::PendingRemote<network::mojom::URLLoaderFactory>
url_loader_factory_remote;
if (url_loader_factory_override_for_test_) {
url_loader_factory_override_for_test_->Clone(
url_loader_factory_remote.InitWithNewPipeAndPassReceiver());
} else {
url_loader_factory_remote =
network::NotImplementedURLLoaderFactory::Create();
}
pending_loader_factories_ = CreateLoaderFactoryBundle(
blink::ChildPendingURLLoaderFactoryBundle::CreateFromDefaultFactoryImpl(
std::move(url_loader_factory_remote)),
std::nullopt,
{},
{},
{});
auto navigation_params = std::make_unique<WebNavigationParams>();
navigation_params->url = base_url;
WebNavigationParams::FillStaticResponse(navigation_params.get(), "text/html",
WebString::FromUTF8(text_encoding),
html);
navigation_params->unreachable_url = unreachable_url;
navigation_params->frame_load_type =
replace_current_item ? blink::WebFrameLoadType::kReplaceCurrentItem
: blink::WebFrameLoadType::kStandard;
navigation_params->service_worker_network_provider =
ServiceWorkerNetworkProviderForFrame::CreateInvalidInstance();
frame_->CommitNavigation(std::move(navigation_params), BuildDocumentState());
}
scoped_refptr<base::SingleThreadTaskRunner> RenderFrameImpl::GetTaskRunner(
blink::TaskType task_type) {
return GetWebFrame()->GetTaskRunner(task_type);
}
BindingsPolicySet RenderFrameImpl::GetEnabledBindings() {
return enabled_bindings_;
}
void RenderFrameImpl::SetAccessibilityModeForTest(ui::AXMode new_mode) {
render_accessibility_manager_->SetMode(new_mode, 1);
}
const RenderFrameMediaPlaybackOptions&
RenderFrameImpl::GetRenderFrameMediaPlaybackOptions() {
return renderer_media_playback_options_;
}
void RenderFrameImpl::SetRenderFrameMediaPlaybackOptions(
const RenderFrameMediaPlaybackOptions& opts) {
renderer_media_playback_options_ = opts;
}
void RenderFrameImpl::SetAllowsCrossBrowsingInstanceFrameLookup() {
GetWebFrame()->SetAllowsCrossBrowsingInstanceFrameLookup();
}
bool RenderFrameImpl::IsAccessibilityEnabled() const {
return render_accessibility_manager_->GetAccessibilityMode().has_mode(
ui::AXMode::kWebContents);
}
std::unique_ptr<blink::WebSocketHandshakeThrottle>
RenderFrameImpl::CreateWebSocketHandshakeThrottle() {
if (!websocket_handshake_throttle_provider_) {
websocket_handshake_throttle_provider_ =
GetContentClient()
->renderer()
->CreateWebSocketHandshakeThrottleProvider();
if (!websocket_handshake_throttle_provider_)
return nullptr;
}
return websocket_handshake_throttle_provider_->CreateThrottle(
frame_->GetLocalFrameToken(),
GetTaskRunner(blink::TaskType::kInternalDefault));
}
void RenderFrameImpl::AddMessageToConsoleImpl(
blink::mojom::ConsoleMessageLevel level,
const std::string& message,
bool discard_duplicates) {
blink::WebConsoleMessage wcm(level, WebString::FromUTF8(message));
frame_->AddMessageToConsole(wcm, discard_duplicates);
}
void RenderFrameImpl::SetURLLoaderFactoryOverrideForTest(
scoped_refptr<network::SharedURLLoaderFactory> factory) {
url_loader_factory_override_for_test_ = std::move(factory);
}
scoped_refptr<blink::ChildURLLoaderFactoryBundle>
RenderFrameImpl::CloneLoaderFactories() {
auto pending_bundle = base::WrapUnique(
static_cast<blink::TrackedChildPendingURLLoaderFactoryBundle*>(
GetLoaderFactoryBundle()->Clone().release()));
return base::MakeRefCounted<blink::TrackedChildURLLoaderFactoryBundle>(
std::move(pending_bundle));
}
blink::scheduler::WebAgentGroupScheduler&
RenderFrameImpl::GetAgentGroupScheduler() {
return agent_scheduling_group_->agent_group_scheduler();
}
url::Origin RenderFrameImpl::GetSecurityOriginOfTopFrame() {
return frame_->Top()->GetSecurityOrigin();
}
base::WeakPtr<media::DecoderFactory> RenderFrameImpl::GetMediaDecoderFactory() {
return media_factory_.GetDecoderFactory();
}
gfx::Rect RenderFrameImpl::ConvertViewportToWindow(const gfx::Rect& rect) {
return GetLocalRootWebFrameWidget()->BlinkSpaceToEnclosedDIPs(rect);
}
float RenderFrameImpl::GetDeviceScaleFactor() {
return GetLocalRootWebFrameWidget()->GetScreenInfo().device_scale_factor;
}
bool RenderFrameImpl::DeferMediaLoad(bool has_played_media_before,
base::OnceClosure closure) {
if (frame_->GetDocument().IsPrerendering()) {
frame_->GetDocument().AddPostPrerenderingActivationStep(
base::BindOnce(CallClientDeferMediaLoad, weak_factory_.GetWeakPtr(),
has_played_media_before, std::move(closure)));
return true;
}
return GetContentClient()->renderer()->DeferMediaLoad(
this, has_played_media_before, std::move(closure));
}
WebView* RenderFrameImpl::CreateNewWindow(
const WebURLRequest& request,
const blink::WebWindowFeatures& features,
const WebString& frame_name,
const gfx::Rect& requested_screen_rect,
WebNavigationPolicy policy,
network::mojom::WebSandboxFlags sandbox_flags,
const blink::SessionStorageNamespaceId& session_storage_namespace_id,
bool& consumed_user_gesture,
const std::optional<blink::Impression>& impression,
const std::optional<blink::WebPictureInPictureWindowOptions>& pip_options,
const blink::WebURL& base_url) {
consumed_user_gesture = false;
mojom::CreateNewWindowParamsPtr params = mojom::CreateNewWindowParams::New();
params->allow_popup = false;
if (GetContentClient()->renderer()->AllowPopup())
params->allow_popup = true;
#if BUILDFLAG(ARKWEB_MULTI_WINDOW)
GetNewWindowWebView(request.Url(), policy, params->allow_popup, features);
#endif
params->window_container_type = WindowFeaturesToContainerType(features);
params->session_storage_namespace_id = session_storage_namespace_id;
if (!features.noopener) {
params->clone_from_session_storage_namespace_id =
GetWebView()->GetSessionStorageNamespaceId();
}
const std::string& frame_name_utf8 = frame_name.Utf8(
WebString::UTF8ConversionMode::kStrictReplacingErrorsWithFFFD);
params->frame_name = frame_name_utf8;
params->opener_suppressed = features.noopener;
params->disposition = NavigationPolicyToDisposition(policy);
if (!request.IsNull()) {
params->target_url = request.Url();
if (params->target_url.is_empty() ||
params->target_url.SchemeIs(url::kJavaScriptScheme)) {
params->target_url = GURL(url::kAboutBlankURL);
}
params->referrer = blink::mojom::Referrer::New(
blink::WebStringToGURL(request.ReferrerString()),
request.GetReferrerPolicy());
}
params->features = ConvertWebWindowFeaturesToMojoWindowFeatures(features);
params->is_form_submission = request.IsFormSubmission();
params->consumes_user_activation =
GetWebFrame()->HasTransientUserActivation();
params->form_submission_post_data =
blink::GetRequestBodyForWebURLRequest(request);
params->form_submission_post_content_type = request.HttpContentType().Utf8();
params->impression = impression;
if (pip_options) {
CHECK_EQ(policy, blink::kWebNavigationPolicyPictureInPicture);
auto pip_mojom_opts = blink::mojom::PictureInPictureWindowOptions::New();
pip_mojom_opts->width = pip_options->width;
pip_mojom_opts->height = pip_options->height;
pip_mojom_opts->disallow_return_to_opener =
pip_options->disallow_return_to_opener;
pip_mojom_opts->prefer_initial_window_placement =
pip_options->prefer_initial_window_placement;
pip_mojom_opts->initial_position = pip_options->initial_position;
params->pip_options = std::move(pip_mojom_opts);
}
params->download_policy.ApplyDownloadFramePolicy(
false, request.HasUserGesture(),
true,
!GetWebFrame()->IsAllowedToDownload(), GetWebFrame()->IsAdFrame());
params->initiator_activation_and_ad_status =
blink::GetNavigationInitiatorActivationAndAdStatus(
request.HasUserGesture(), GetWebFrame()->IsAdFrame(),
GetWebFrame()->IsAdScriptInStack());
bool is_background_tab =
params->disposition == WindowOpenDisposition::NEW_BACKGROUND_TAB;
mojo::PendingAssociatedReceiver<mojom::Frame> pending_frame_receiver;
params->frame_remote =
pending_frame_receiver.InitWithNewEndpointAndPassRemote();
mojo::PendingAssociatedReceiver<blink::mojom::PageBroadcast>
page_broadcast_receiver;
params->page_broadcast_remote =
page_broadcast_receiver.InitWithNewEndpointAndPassRemote();
mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>
browser_interface_broker;
params->main_frame_interface_broker =
browser_interface_broker.InitWithNewPipeAndPassReceiver();
mojo::PendingAssociatedRemote<blink::mojom::AssociatedInterfaceProvider>
associated_interface_provider;
params->associated_interface_provider =
associated_interface_provider.InitWithNewEndpointAndPassReceiver();
mojo::PendingAssociatedRemote<blink::mojom::WidgetHost> widget_host;
params->widget_host = widget_host.InitWithNewEndpointAndPassReceiver();
mojo::PendingAssociatedReceiver<blink::mojom::Widget> widget;
params->widget = widget.InitWithNewEndpointAndPassRemote();
mojo::PendingAssociatedRemote<blink::mojom::FrameWidgetHost>
frame_widget_host;
params->frame_widget_host =
frame_widget_host.InitWithNewEndpointAndPassReceiver();
mojo::PendingAssociatedReceiver<blink::mojom::FrameWidget> frame_widget;
params->frame_widget = frame_widget.InitWithNewEndpointAndPassRemote();
mojom::CreateNewWindowStatus status;
mojom::CreateNewWindowReplyPtr reply;
auto* frame_host = GetFrameHost();
if (!frame_host->CreateNewWindow(std::move(params), &status, &reply)) {
return nullptr;
}
if (status == mojom::CreateNewWindowStatus::kBlocked)
return nullptr;
if (status == mojom::CreateNewWindowStatus::kReuse) {
if (!request.IsNull() && request.Url().ProtocolIs(url::kJavaScriptScheme)) {
return nullptr;
}
return GetWebView();
}
consumed_user_gesture = GetWebFrame()->ConsumeTransientUserActivation(
blink::UserActivationUpdateSource::kBrowser);
if (status == mojom::CreateNewWindowStatus::kIgnore)
return nullptr;
DCHECK(reply);
DCHECK_NE(IPC::mojom::kRoutingIdNone, reply->main_frame_route_id);
DCHECK_NE(IPC::mojom::kRoutingIdNone, reply->widget_routing_id);
bool never_composited = false;
mojom::CreateViewParamsPtr view_params = mojom::CreateViewParams::New();
view_params->opener_frame_token = GetWebFrame()->GetFrameToken();
view_params->window_was_opened_by_another_window = true;
view_params->renderer_preferences = GetWebView()->GetRendererPreferences();
view_params->web_preferences = GetWebView()->GetWebPreferences();
view_params->replication_state = blink::mojom::FrameReplicationState::New();
view_params->replication_state->frame_policy.sandbox_flags = sandbox_flags;
view_params->replication_state->name = frame_name_utf8;
view_params->devtools_main_frame_token = reply->devtools_main_frame_token;
view_params->browsing_context_group_token =
reply->browsing_context_group_token;
view_params->color_provider_colors = reply->color_provider_colors;
auto widget_params = mojom::CreateFrameWidgetParams::New();
widget_params->routing_id = reply->widget_routing_id;
widget_params->visual_properties = reply->visual_properties;
widget_params->widget_host = std::move(widget_host);
widget_params->widget = std::move(widget);
widget_params->frame_widget_host = std::move(frame_widget_host);
widget_params->frame_widget = std::move(frame_widget);
auto main_frame_params = mojom::CreateLocalMainFrameParams::New();
main_frame_params->frame_token = reply->main_frame_token;
main_frame_params->routing_id = reply->main_frame_route_id;
main_frame_params->frame = std::move(pending_frame_receiver);
main_frame_params->interface_broker = std::move(browser_interface_broker);
main_frame_params->document_token = reply->document_token;
main_frame_params->policy_container = std::move(reply->policy_container);
main_frame_params->associated_interface_provider_remote =
std::move(associated_interface_provider);
main_frame_params->widget_params = std::move(widget_params);
main_frame_params->subresource_loader_factories =
base::WrapUnique(static_cast<blink::PendingURLLoaderFactoryBundle*>(
CloneLoaderFactories()->Clone().release()));
view_params->main_frame =
mojom::CreateMainFrameUnion::NewLocalParams(std::move(main_frame_params));
view_params->blink_page_broadcast = std::move(page_broadcast_receiver);
view_params->session_storage_namespace_id =
reply->cloned_session_storage_namespace_id;
DCHECK(!view_params->session_storage_namespace_id.empty())
<< "Session storage namespace must be populated.";
view_params->hidden = is_background_tab;
view_params->never_composited = never_composited;
WebView* web_view = agent_scheduling_group_->CreateWebView(
std::move(view_params),
true, base_url);
if (reply->widget_screen_rect.has_value() &&
reply->window_screen_rect.has_value()) {
CHECK(base::FeatureList::IsEnabled(blink::features::kCombineNewWindowIPCs));
web_view->MainFrameWidget()->SetScreenRects(*reply->widget_screen_rect,
*reply->window_screen_rect);
} else {
web_view->MainFrameWidget()->SetScreenRects(requested_screen_rect,
requested_screen_rect);
}
web_view->MainFrameWidget()->ApplyVisualProperties(reply->visual_properties);
if (reply->wait_for_debugger) {
web_view->MainFrame()
->ToWebLocalFrame()
->LocalRoot()
->FrameWidget()
->WaitForDebuggerWhenShown();
}
return web_view;
}
std::unique_ptr<blink::WebLinkPreviewTriggerer>
RenderFrameImpl::CreateLinkPreviewTriggerer() {
return GetContentClient()->renderer()->CreateLinkPreviewTriggerer();
}
base::ScopedClosureRunner
RenderFrameImpl::CreateScopedClientNavigationThrottler() {
return client_navigation_throttler_.DeferNavigations();
}
bool RenderFrameImpl::IsForInitialWebUI() const {
#if !BUILDFLAG(IS_ANDROID)
static const bool is_for_initial_webui =
base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kRendererForInitialWebUI);
return is_for_initial_webui;
#else
return false;
#endif
}
void RenderFrameImpl::ResetMembersUsedForDurationOfCommit() {
pending_loader_factories_ = nullptr;
pending_code_cache_host_.reset();
pending_cookie_manager_info_.reset();
pending_storage_info_.reset();
is_requesting_navigation_ = false;
}
#if BUILDFLAG(ARKWEB_TEST)
void RenderFrameImpl::SetLocalRootWebFrameWidgetForTest(blink::WebFrameWidget* widget) {
web_frame_widget_test_mode = true;
web_frame_widget_test = widget;
}
void RenderFrameImpl::SetWebViewForTest(blink::WebView* web_view) {
web_view_test_mode = true;
web_view_test = web_view;
}
#endif
}