|  | // Copyright 2013 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include "content/renderer/render_frame_impl.h" | 
|  |  | 
|  | #include <algorithm> | 
|  | #include <map> | 
|  | #include <string> | 
|  | #include <utility> | 
|  | #include <vector> | 
|  |  | 
|  | #include "base/auto_reset.h" | 
|  | #include "base/bind.h" | 
|  | #include "base/bind_helpers.h" | 
|  | #include "base/command_line.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/guid.h" | 
|  | #include "base/i18n/char_iterator.h" | 
|  | #include "base/json/json_reader.h" | 
|  | #include "base/logging.h" | 
|  | #include "base/macros.h" | 
|  | #include "base/memory/ptr_util.h" | 
|  | #include "base/memory/shared_memory.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/optional.h" | 
|  | #include "base/process/process.h" | 
|  | #include "base/stl_util.h" | 
|  | #include "base/strings/string16.h" | 
|  | #include "base/strings/string_piece.h" | 
|  | #include "base/strings/string_split.h" | 
|  | #include "base/strings/string_util.h" | 
|  | #include "base/strings/utf_string_conversions.h" | 
|  | #include "base/task/post_task.h" | 
|  | #include "base/task_runner_util.h" | 
|  | #include "base/threading/thread_task_runner_handle.h" | 
|  | #include "base/time/time.h" | 
|  | #include "base/trace_event/trace_event.h" | 
|  | #include "build/build_config.h" | 
|  | #include "cc/base/switches.h" | 
|  | #include "content/common/accessibility_messages.h" | 
|  | #include "content/common/associated_interfaces.mojom.h" | 
|  | #include "content/common/content_constants_internal.h" | 
|  | #include "content/common/content_security_policy/content_security_policy.h" | 
|  | #include "content/common/content_security_policy_header.h" | 
|  | #include "content/common/edit_command.h" | 
|  | #include "content/common/frame_messages.h" | 
|  | #include "content/common/frame_owner_properties.h" | 
|  | #include "content/common/frame_replication_state.h" | 
|  | #include "content/common/input_messages.h" | 
|  | #include "content/common/navigation_gesture.h" | 
|  | #include "content/common/navigation_params.h" | 
|  | #include "content/common/page_messages.h" | 
|  | #include "content/common/possibly_associated_wrapper_shared_url_loader_factory.h" | 
|  | #include "content/common/renderer_host.mojom.h" | 
|  | #include "content/common/savable_subframe.h" | 
|  | #include "content/common/service_worker/service_worker_types.h" | 
|  | #include "content/common/swapped_out_messages.h" | 
|  | #include "content/common/view_messages.h" | 
|  | #include "content/public/common/bind_interface_helpers.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/context_menu_params.h" | 
|  | #include "content/public/common/favicon_url.h" | 
|  | #include "content/public/common/isolated_world_ids.h" | 
|  | #include "content/public/common/mime_handler_view_mode.h" | 
|  | #include "content/public/common/navigation_policy.h" | 
|  | #include "content/public/common/page_state.h" | 
|  | #include "content/public/common/service_manager_connection.h" | 
|  | #include "content/public/common/url_constants.h" | 
|  | #include "content/public/common/url_loader_throttle.h" | 
|  | #include "content/public/common/url_utils.h" | 
|  | #include "content/public/renderer/browser_plugin_delegate.h" | 
|  | #include "content/public/renderer/content_renderer_client.h" | 
|  | #include "content/public/renderer/context_menu_client.h" | 
|  | #include "content/public/renderer/document_state.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/renderer_ppapi_host.h" | 
|  | #include "content/renderer/accessibility/aom_content_ax_tree.h" | 
|  | #include "content/renderer/accessibility/render_accessibility_impl.h" | 
|  | #include "content/renderer/browser_plugin/browser_plugin.h" | 
|  | #include "content/renderer/browser_plugin/browser_plugin_manager.h" | 
|  | #include "content/renderer/compositor/layer_tree_view.h" | 
|  | #include "content/renderer/content_security_policy_util.h" | 
|  | #include "content/renderer/context_menu_params_builder.h" | 
|  | #include "content/renderer/crash_helpers.h" | 
|  | #include "content/renderer/dom_automation_controller.h" | 
|  | #include "content/renderer/effective_connection_type_helper.h" | 
|  | #include "content/renderer/external_popup_menu.h" | 
|  | #include "content/renderer/frame_owner_properties.h" | 
|  | #include "content/renderer/gpu_benchmarking_extension.h" | 
|  | #include "content/renderer/history_entry.h" | 
|  | #include "content/renderer/history_serialization.h" | 
|  | #include "content/renderer/image_downloader/image_downloader_impl.h" | 
|  | #include "content/renderer/ime_event_guard.h" | 
|  | #include "content/renderer/input/frame_input_handler_impl.h" | 
|  | #include "content/renderer/input/input_target_client_impl.h" | 
|  | #include "content/renderer/input/widget_input_handler_manager.h" | 
|  | #include "content/renderer/installedapp/related_apps_fetcher.h" | 
|  | #include "content/renderer/internal_document_state_data.h" | 
|  | #include "content/renderer/loader/navigation_body_loader.h" | 
|  | #include "content/renderer/loader/request_extra_data.h" | 
|  | #include "content/renderer/loader/resource_dispatcher.h" | 
|  | #include "content/renderer/loader/tracked_child_url_loader_factory_bundle.h" | 
|  | #include "content/renderer/loader/web_url_loader_impl.h" | 
|  | #include "content/renderer/loader/web_url_request_util.h" | 
|  | #include "content/renderer/loader/web_worker_fetch_context_impl.h" | 
|  | #include "content/renderer/low_memory_mode_controller.h" | 
|  | #include "content/renderer/manifest/manifest_change_notifier.h" | 
|  | #include "content/renderer/manifest/manifest_manager.h" | 
|  | #include "content/renderer/media/audio/audio_device_factory.h" | 
|  | #include "content/renderer/media/audio/audio_output_ipc_factory.h" | 
|  | #include "content/renderer/media/audio/audio_renderer_sink_cache.h" | 
|  | #include "content/renderer/media/media_permission_dispatcher.h" | 
|  | #include "content/renderer/media/stream/media_stream_device_observer.h" | 
|  | #include "content/renderer/media/stream/user_media_client_impl.h" | 
|  | #include "content/renderer/media/webrtc/rtc_peer_connection_handler.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/pepper/pepper_audio_controller.h" | 
|  | #include "content/renderer/pepper/plugin_instance_throttler_impl.h" | 
|  | #include "content/renderer/push_messaging/push_messaging_client.h" | 
|  | #include "content/renderer/render_frame_proxy.h" | 
|  | #include "content/renderer/render_process.h" | 
|  | #include "content/renderer/render_thread_impl.h" | 
|  | #include "content/renderer/render_view_impl.h" | 
|  | #include "content/renderer/render_widget_fullscreen_pepper.h" | 
|  | #include "content/renderer/renderer_blink_platform_impl.h" | 
|  | #include "content/renderer/renderer_webapplicationcachehost_impl.h" | 
|  | #include "content/renderer/resource_timing_info_conversions.h" | 
|  | #include "content/renderer/savable_resources.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 "media/blink/webmediaplayer_util.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_util.h" | 
|  | #include "ppapi/buildflags/buildflags.h" | 
|  | #include "services/network/public/cpp/features.h" | 
|  | #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h" | 
|  | #include "services/network/public/mojom/request_context_frame_type.mojom.h" | 
|  | #include "services/service_manager/public/cpp/connector.h" | 
|  | #include "services/service_manager/public/cpp/interface_provider.h" | 
|  | #include "services/service_manager/public/mojom/interface_provider.mojom.h" | 
|  | #include "services/ws/public/cpp/gpu/context_provider_command_buffer.h" | 
|  | #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" | 
|  | #include "third_party/blink/public/common/features.h" | 
|  | #include "third_party/blink/public/common/frame/sandbox_flags.h" | 
|  | #include "third_party/blink/public/common/frame/user_activation_update_type.h" | 
|  | #include "third_party/blink/public/common/service_worker/service_worker_utils.h" | 
|  | #include "third_party/blink/public/mojom/choosers/file_chooser.mojom.h" | 
|  | #include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom.h" | 
|  | #include "third_party/blink/public/mojom/permissions/permission.mojom.h" | 
|  | #include "third_party/blink/public/platform/file_path_conversion.h" | 
|  | #include "third_party/blink/public/platform/interface_provider.h" | 
|  | #include "third_party/blink/public/platform/modules/service_worker/web_service_worker_network_provider.h" | 
|  | #include "third_party/blink/public/platform/url_conversion.h" | 
|  | #include "third_party/blink/public/platform/web_data.h" | 
|  | #include "third_party/blink/public/platform/web_focus_type.h" | 
|  | #include "third_party/blink/public/platform/web_http_body.h" | 
|  | #include "third_party/blink/public/platform/web_keyboard_event.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_point.h" | 
|  | #include "third_party/blink/public/platform/web_runtime_features.h" | 
|  | #include "third_party/blink/public/platform/web_scroll_into_view_params.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_response.h" | 
|  | #include "third_party/blink/public/platform/web_vector.h" | 
|  | #include "third_party/blink/public/web/blink.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_context_features.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_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_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_scoped_user_gesture.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_settings.h" | 
|  | #include "third_party/blink/public/web/web_surrounding_text.h" | 
|  | #include "third_party/blink/public/web/web_user_gesture_indicator.h" | 
|  | #include "third_party/blink/public/web/web_view.h" | 
|  | #include "third_party/blink/public/web/web_widget.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.h" | 
|  |  | 
|  | #if BUILDFLAG(ENABLE_PLUGINS) | 
|  | #include "content/renderer/pepper/pepper_browser_connection.h" | 
|  | #include "content/renderer/pepper/pepper_plugin_instance_impl.h" | 
|  | #include "content/renderer/pepper/pepper_plugin_registry.h" | 
|  | #include "content/renderer/pepper/pepper_webplugin_impl.h" | 
|  | #include "content/renderer/pepper/plugin_module.h" | 
|  | #endif | 
|  |  | 
|  | #if defined(OS_WIN) | 
|  | #include "base/debug/invalid_access_win.h" | 
|  | #include "base/process/kill.h" | 
|  | #elif defined(OS_POSIX) | 
|  | #include <signal.h> | 
|  | #endif | 
|  |  | 
|  | #if defined(OS_ANDROID) | 
|  | #include <cpu-features.h> | 
|  |  | 
|  | #include "content/renderer/java/gin_java_bridge_dispatcher.h" | 
|  | #include "third_party/blink/public/platform/web_float_point.h" | 
|  | #endif | 
|  |  | 
|  | using base::Time; | 
|  | using base::TimeDelta; | 
|  | using blink::WebContentDecryptionModule; | 
|  | using blink::WebContextMenuData; | 
|  | using blink::WebData; | 
|  | using blink::WebDocument; | 
|  | using blink::WebDocumentLoader; | 
|  | using blink::WebDOMEvent; | 
|  | using blink::WebDOMMessageEvent; | 
|  | using blink::WebElement; | 
|  | using blink::WebElementCollection; | 
|  | using blink::WebExternalPopupMenu; | 
|  | using blink::WebExternalPopupMenuClient; | 
|  | using blink::WebFrame; | 
|  | using blink::WebFrameLoadType; | 
|  | using blink::WebFrameSerializer; | 
|  | using blink::WebFrameSerializerClient; | 
|  | using blink::WebHistoryItem; | 
|  | using blink::WebHTTPBody; | 
|  | using blink::WebLayerTreeView; | 
|  | 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::WebPoint; | 
|  | using blink::WebPopupMenuInfo; | 
|  | using blink::WebRange; | 
|  | using blink::WebRect; | 
|  | using blink::WebScriptSource; | 
|  | using blink::WebSearchableFormData; | 
|  | using blink::WebSecurityOrigin; | 
|  | using blink::WebSecurityPolicy; | 
|  | using blink::WebSerializedScriptValue; | 
|  | using blink::WebServiceWorkerProvider; | 
|  | using blink::WebSettings; | 
|  | using blink::WebString; | 
|  | using blink::WebThreadSafeData; | 
|  | using blink::WebURL; | 
|  | using blink::WebURLError; | 
|  | using blink::WebURLRequest; | 
|  | using blink::WebURLResponse; | 
|  | using blink::WebUserGestureIndicator; | 
|  | using blink::WebVector; | 
|  | using blink::WebView; | 
|  | using blink::mojom::SelectionMenuBehavior; | 
|  | using network::mojom::ReferrerPolicy; | 
|  |  | 
|  | #if defined(OS_ANDROID) | 
|  | using blink::WebFloatPoint; | 
|  | using blink::WebFloatRect; | 
|  | #endif | 
|  |  | 
|  | namespace content { | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | const int kExtraCharsBeforeAndAfterSelection = 100; | 
|  |  | 
|  | // Maximum number of burst download requests allowed. | 
|  | const int kBurstDownloadLimit = 10; | 
|  |  | 
|  | const PreviewsState kDisabledPreviewsBits = | 
|  | PREVIEWS_OFF | PREVIEWS_NO_TRANSFORM; | 
|  |  | 
|  | // Print up to |kMaxSecurityWarningMessages| console messages per frame about | 
|  | // certificates or TLS versions that will be distrusted in future. | 
|  | const uint32_t kMaxSecurityWarningMessages = 10; | 
|  |  | 
|  | typedef std::map<int, RenderFrameImpl*> RoutingIDFrameMap; | 
|  | static base::LazyInstance<RoutingIDFrameMap>::DestructorAtExit | 
|  | g_routing_id_frame_map = LAZY_INSTANCE_INITIALIZER; | 
|  |  | 
|  | typedef std::map<blink::WebFrame*, RenderFrameImpl*> FrameMap; | 
|  | base::LazyInstance<FrameMap>::DestructorAtExit g_frame_map = | 
|  | LAZY_INSTANCE_INITIALIZER; | 
|  |  | 
|  | int64_t ExtractPostId(const WebHistoryItem& item) { | 
|  | if (item.IsNull() || item.HttpBody().IsNull()) | 
|  | return -1; | 
|  |  | 
|  | return item.HttpBody().Identifier(); | 
|  | } | 
|  |  | 
|  | // Calculates transition type based on navigation parameters. Used | 
|  | // during navigation, before WebDocumentLoader is available. | 
|  | ui::PageTransition GetTransitionType(ui::PageTransition default_transition, | 
|  | bool replaces_current_item, | 
|  | bool is_main_frame, | 
|  | WebNavigationType navigation_type) { | 
|  | if (replaces_current_item && !is_main_frame) { | 
|  | // Subframe navigations that don't add session history items must be | 
|  | // marked with AUTO_SUBFRAME. See also DidFailProvisionalLoad for how we | 
|  | // handle loading of error pages. | 
|  | return ui::PAGE_TRANSITION_AUTO_SUBFRAME; | 
|  | } | 
|  | bool is_form_submit = | 
|  | navigation_type == blink::kWebNavigationTypeFormSubmitted || | 
|  | navigation_type == blink::kWebNavigationTypeFormResubmitted; | 
|  | if (ui::PageTransitionCoreTypeIs(default_transition, | 
|  | ui::PAGE_TRANSITION_LINK) && | 
|  | is_form_submit) { | 
|  | return ui::PAGE_TRANSITION_FORM_SUBMIT; | 
|  | } | 
|  | return default_transition; | 
|  | } | 
|  |  | 
|  | // Calculates transition type for the specific document loaded using | 
|  | // WebDocumentLoader. Used while loading subresources. | 
|  | ui::PageTransition GetTransitionType(blink::WebDocumentLoader* document_loader, | 
|  | bool is_main_frame, | 
|  | bool loading) { | 
|  | NavigationState* navigation_state = | 
|  | NavigationState::FromDocumentLoader(document_loader); | 
|  | ui::PageTransition default_transition = | 
|  | navigation_state->IsContentInitiated() | 
|  | ? ui::PAGE_TRANSITION_LINK | 
|  | : navigation_state->common_params().transition; | 
|  | if (navigation_state->WasWithinSameDocument()) | 
|  | return default_transition; | 
|  | if (loading || document_loader->GetResponse().IsNull()) { | 
|  | return GetTransitionType( | 
|  | default_transition, document_loader->ReplacesCurrentHistoryItem(), | 
|  | is_main_frame, document_loader->GetNavigationType()); | 
|  | } | 
|  | return default_transition; | 
|  | } | 
|  |  | 
|  | void GetRedirectChain(WebDocumentLoader* document_loader, | 
|  | std::vector<GURL>* result) { | 
|  | WebVector<WebURL> urls; | 
|  | document_loader->RedirectChain(urls); | 
|  | result->reserve(urls.size()); | 
|  | for (size_t i = 0; i < urls.size(); ++i) { | 
|  | result->push_back(urls[i]); | 
|  | } | 
|  | } | 
|  |  | 
|  | // Gets URL that should override the default getter for this data source | 
|  | // (if any), storing it in |output|. Returns true if there is an override URL. | 
|  | bool MaybeGetOverriddenURL(WebDocumentLoader* document_loader, GURL* output) { | 
|  | DocumentState* document_state = | 
|  | DocumentState::FromDocumentLoader(document_loader); | 
|  |  | 
|  | // If load was from a data URL, then the saved data URL, not the history | 
|  | // URL, should be the URL of the data source. | 
|  | if (document_state->was_load_data_with_base_url_request()) { | 
|  | *output = document_state->data_url(); | 
|  | return true; | 
|  | } | 
|  |  | 
|  | // WebDocumentLoader has unreachable URL means that the frame is loaded | 
|  | // through blink::WebFrame::loadData(), and the base URL will be in the | 
|  | // redirect chain. However, we never visited the baseURL. So in this case, we | 
|  | // should use the unreachable URL as the original URL. | 
|  | if (document_loader->HasUnreachableURL()) { | 
|  | *output = document_loader->UnreachableURL(); | 
|  | return true; | 
|  | } | 
|  |  | 
|  | return false; | 
|  | } | 
|  |  | 
|  | // Returns the original request url. If there is no redirect, the original | 
|  | // url is the same as document loader's OriginalUrl(). If the WebDocumentLoader | 
|  | // belongs to a frame was loaded by loadData, the original url will be | 
|  | // it's UnreachableURL(). | 
|  | GURL GetOriginalRequestURL(WebDocumentLoader* document_loader) { | 
|  | GURL overriden_url; | 
|  | if (MaybeGetOverriddenURL(document_loader, &overriden_url)) | 
|  | return overriden_url; | 
|  |  | 
|  | std::vector<GURL> redirects; | 
|  | GetRedirectChain(document_loader, &redirects); | 
|  | if (!redirects.empty()) | 
|  | return redirects.at(0); | 
|  |  | 
|  | return document_loader->OriginalUrl(); | 
|  | } | 
|  |  | 
|  | // Returns false unless this is a top-level navigation. | 
|  | bool IsTopLevelNavigation(WebFrame* frame) { | 
|  | return frame->Parent() == nullptr; | 
|  | } | 
|  |  | 
|  | void FillNavigationParamsRequest( | 
|  | const CommonNavigationParams& common_params, | 
|  | const CommitNavigationParams& commit_params, | 
|  | blink::WebNavigationParams* navigation_params) { | 
|  | // Use the original navigation url to start with. We'll replay the redirects | 
|  | // afterwards and will eventually arrive to the final url. | 
|  | navigation_params->url = !commit_params.original_url.is_empty() | 
|  | ? commit_params.original_url | 
|  | : common_params.url; | 
|  | navigation_params->http_method = WebString::FromLatin1( | 
|  | !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 = | 
|  | GetWebHTTPBodyForRequestBody(*common_params.post_data); | 
|  | if (!commit_params.post_content_type.empty()) { | 
|  | navigation_params->http_content_type = | 
|  | WebString::FromASCII(commit_params.post_content_type); | 
|  | } | 
|  | } | 
|  |  | 
|  | navigation_params->previews_state = | 
|  | static_cast<WebURLRequest::PreviewsState>(common_params.previews_state); | 
|  | navigation_params->origin_policy = | 
|  | WebString::FromUTF8(common_params.origin_policy); | 
|  |  | 
|  | // Set the request initiator origin, which is supplied by the browser | 
|  | // process. It is present in cases such as navigating a frame in a different | 
|  | // process, which is routed through RenderFrameProxy and the origin is | 
|  | // required to correctly compute the effective origin in which the | 
|  | // navigation will commit. | 
|  | if (common_params.initiator_origin) { | 
|  | navigation_params->requestor_origin = | 
|  | common_params.initiator_origin.value(); | 
|  | } | 
|  |  | 
|  | navigation_params->was_discarded = commit_params.was_discarded; | 
|  | #if defined(OS_ANDROID) | 
|  | navigation_params->had_transient_activation = common_params.has_user_gesture; | 
|  | #endif | 
|  | } | 
|  |  | 
|  | CommonNavigationParams MakeCommonNavigationParams( | 
|  | const WebSecurityOrigin& current_origin, | 
|  | std::unique_ptr<blink::WebNavigationInfo> info, | 
|  | int load_flags, | 
|  | bool has_download_sandbox_flag, | 
|  | bool from_ad) { | 
|  | // A valid RequestorOrigin is always expected to be present. | 
|  | DCHECK(!info->url_request.RequestorOrigin().IsNull()); | 
|  |  | 
|  | Referrer referrer( | 
|  | GURL(info->url_request.HttpHeaderField(WebString::FromUTF8("Referer")) | 
|  | .Latin1()), | 
|  | info->url_request.GetReferrerPolicy()); | 
|  |  | 
|  | // No history-navigation is expected to happen. | 
|  | DCHECK(info->navigation_type != blink::kWebNavigationTypeBackForward); | 
|  |  | 
|  | // Determine the navigation type. No same-document navigation is expected | 
|  | // because it is loaded immediately by the FrameLoader. | 
|  | FrameMsg_Navigate_Type::Value navigation_type = | 
|  | FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT; | 
|  | if (info->navigation_type == blink::kWebNavigationTypeReload) { | 
|  | if (load_flags & net::LOAD_BYPASS_CACHE) | 
|  | navigation_type = FrameMsg_Navigate_Type::RELOAD_BYPASSING_CACHE; | 
|  | else | 
|  | navigation_type = FrameMsg_Navigate_Type::RELOAD; | 
|  | } | 
|  |  | 
|  | base::Optional<SourceLocation> source_location; | 
|  | if (!info->source_location.url.IsNull()) { | 
|  | source_location = SourceLocation(info->source_location.url.Latin1(), | 
|  | info->source_location.line_number, | 
|  | info->source_location.column_number); | 
|  | } | 
|  |  | 
|  | CSPDisposition should_check_main_world_csp = | 
|  | info->should_check_main_world_content_security_policy == | 
|  | blink::kWebContentSecurityPolicyDispositionCheck | 
|  | ? CSPDisposition::CHECK | 
|  | : CSPDisposition::DO_NOT_CHECK; | 
|  |  | 
|  | const RequestExtraData* extra_data = | 
|  | static_cast<RequestExtraData*>(info->url_request.GetExtraData()); | 
|  | DCHECK(extra_data); | 
|  |  | 
|  | NavigationDownloadPolicy download_policy; | 
|  | RenderFrameImpl::MaybeSetDownloadFramePolicy( | 
|  | info->is_opener_navigation, info->url_request, current_origin, | 
|  | has_download_sandbox_flag, | 
|  | info->blocking_downloads_in_sandbox_without_user_activation_enabled, | 
|  | from_ad, &download_policy); | 
|  |  | 
|  | return CommonNavigationParams( | 
|  | info->url_request.Url(), info->url_request.RequestorOrigin(), referrer, | 
|  | extra_data->transition_type(), navigation_type, download_policy, | 
|  | info->frame_load_type == WebFrameLoadType::kReplaceCurrentItem, GURL(), | 
|  | GURL(), static_cast<PreviewsState>(info->url_request.GetPreviewsState()), | 
|  | base::TimeTicks::Now(), info->url_request.HttpMethod().Latin1(), | 
|  | GetRequestBodyForWebURLRequest(info->url_request), source_location, | 
|  | false /* started_from_context_menu */, info->url_request.HasUserGesture(), | 
|  | InitiatorCSPInfo(should_check_main_world_csp, | 
|  | BuildContentSecurityPolicyList(info->initiator_csp), | 
|  | info->initiator_csp.self_source.has_value() | 
|  | ? base::Optional<CSPSource>(BuildCSPSource( | 
|  | info->initiator_csp.self_source.value())) | 
|  | : base::nullopt), | 
|  | info->href_translate.Latin1(), info->input_start); | 
|  | } | 
|  |  | 
|  | WebFrameLoadType NavigationTypeToLoadType( | 
|  | FrameMsg_Navigate_Type::Value navigation_type, | 
|  | bool should_replace_current_entry, | 
|  | bool has_valid_page_state) { | 
|  | switch (navigation_type) { | 
|  | case FrameMsg_Navigate_Type::RELOAD: | 
|  | case FrameMsg_Navigate_Type::RELOAD_ORIGINAL_REQUEST_URL: | 
|  | return WebFrameLoadType::kReload; | 
|  |  | 
|  | case FrameMsg_Navigate_Type::RELOAD_BYPASSING_CACHE: | 
|  | return WebFrameLoadType::kReloadBypassingCache; | 
|  |  | 
|  | case FrameMsg_Navigate_Type::HISTORY_SAME_DOCUMENT: | 
|  | case FrameMsg_Navigate_Type::HISTORY_DIFFERENT_DOCUMENT: | 
|  | return WebFrameLoadType::kBackForward; | 
|  |  | 
|  | case FrameMsg_Navigate_Type::RESTORE: | 
|  | case FrameMsg_Navigate_Type::RESTORE_WITH_POST: | 
|  | if (has_valid_page_state) | 
|  | return WebFrameLoadType::kBackForward; | 
|  | // If there is no valid page state, fall through to the default case. | 
|  | FALLTHROUGH; | 
|  |  | 
|  | case FrameMsg_Navigate_Type::SAME_DOCUMENT: | 
|  | case FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT: | 
|  | return should_replace_current_entry | 
|  | ? WebFrameLoadType::kReplaceCurrentItem | 
|  | : WebFrameLoadType::kStandard; | 
|  |  | 
|  | default: | 
|  | NOTREACHED(); | 
|  | return WebFrameLoadType::kStandard; | 
|  | } | 
|  | } | 
|  |  | 
|  | 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()); | 
|  | } | 
|  |  | 
|  | // Implementation of WebFrameSerializer::LinkRewritingDelegate that responds | 
|  | // based on the payload of FrameMsg_GetSerializedHtmlWithLocalLinks. | 
|  | class LinkRewritingDelegate : public WebFrameSerializer::LinkRewritingDelegate { | 
|  | public: | 
|  | LinkRewritingDelegate( | 
|  | const std::map<GURL, base::FilePath>& url_to_local_path, | 
|  | const std::map<int, base::FilePath>& frame_routing_id_to_local_path) | 
|  | : url_to_local_path_(url_to_local_path), | 
|  | frame_routing_id_to_local_path_(frame_routing_id_to_local_path) {} | 
|  |  | 
|  | bool RewriteFrameSource(WebFrame* frame, WebString* rewritten_link) override { | 
|  | int routing_id = RenderFrame::GetRoutingIdForWebFrame(frame); | 
|  | auto it = frame_routing_id_to_local_path_.find(routing_id); | 
|  | if (it == frame_routing_id_to_local_path_.end()) | 
|  | return false;  // This can happen because of https://crbug.com/541354. | 
|  |  | 
|  | 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(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 std::map<GURL, base::FilePath>& url_to_local_path_; | 
|  | const std::map<int, base::FilePath>& frame_routing_id_to_local_path_; | 
|  | }; | 
|  |  | 
|  | // Implementation of WebFrameSerializer::MHTMLPartsGenerationDelegate that | 
|  | // 1. Bases shouldSkipResource and getContentID responses on contents of | 
|  | //    SerializeAsMHTMLParams. | 
|  | // 2. Stores digests of urls of serialized resources (i.e. urls reported via | 
|  | //    shouldSkipResource) into |serialized_resources_uri_digests| passed | 
|  | //    to the constructor. | 
|  | class MHTMLPartsGenerationDelegate | 
|  | : public WebFrameSerializer::MHTMLPartsGenerationDelegate { | 
|  | public: | 
|  | MHTMLPartsGenerationDelegate( | 
|  | const mojom::SerializeAsMHTMLParams& params, | 
|  | std::unordered_set<std::string>* serialized_resources_uri_digests) | 
|  | : params_(params), | 
|  | serialized_resources_uri_digests_(serialized_resources_uri_digests) { | 
|  | DCHECK(serialized_resources_uri_digests_); | 
|  | // Digests must be sorted for binary search. | 
|  | DCHECK(std::is_sorted(params_.digests_of_uris_to_skip.begin(), | 
|  | params_.digests_of_uris_to_skip.end())); | 
|  | // URLs are not duplicated. | 
|  | DCHECK(std::adjacent_find(params_.digests_of_uris_to_skip.begin(), | 
|  | params_.digests_of_uris_to_skip.end()) == | 
|  | params_.digests_of_uris_to_skip.end()); | 
|  | } | 
|  |  | 
|  | bool ShouldSkipResource(const WebURL& url) override { | 
|  | std::string digest = | 
|  | crypto::SHA256HashString(params_.salt + GURL(url).spec()); | 
|  |  | 
|  | // Skip if the |url| already covered by serialization of an *earlier* frame. | 
|  | if (std::binary_search(params_.digests_of_uris_to_skip.begin(), | 
|  | params_.digests_of_uris_to_skip.end(), digest)) | 
|  | return true; | 
|  |  | 
|  | // Let's record |url| as being serialized for the *current* frame. | 
|  | auto pair = serialized_resources_uri_digests_->insert(digest); | 
|  | bool insertion_took_place = pair.second; | 
|  | DCHECK(insertion_took_place);  // Blink should dedupe within a frame. | 
|  |  | 
|  | return false; | 
|  | } | 
|  |  | 
|  | bool UseBinaryEncoding() override { return params_.mhtml_binary_encoding; } | 
|  |  | 
|  | bool RemovePopupOverlay() override { | 
|  | return params_.mhtml_popup_overlay_removal; | 
|  | } | 
|  |  | 
|  | bool UsePageProblemDetectors() override { | 
|  | return params_.mhtml_problem_detection; | 
|  | } | 
|  |  | 
|  | private: | 
|  | const mojom::SerializeAsMHTMLParams& params_; | 
|  | std::unordered_set<std::string>* serialized_resources_uri_digests_; | 
|  |  | 
|  | DISALLOW_COPY_AND_ASSIGN(MHTMLPartsGenerationDelegate); | 
|  | }; | 
|  |  | 
|  | bool IsHttpPost(const blink::WebURLRequest& request) { | 
|  | return request.HttpMethod().Utf8() == "POST"; | 
|  | } | 
|  |  | 
|  | // Delegate responsible for determining the handle writing implementation by | 
|  | // instantiating an MHTMLHandleWriter on the heap respective to the passed in | 
|  | // MHTMLSerializationParams. This transfers ownership of the handle to the | 
|  | // new MHTMLHandleWriter. | 
|  | class MHTMLHandleWriterDelegate { | 
|  | public: | 
|  | MHTMLHandleWriterDelegate( | 
|  | mojom::SerializeAsMHTMLParams& params, | 
|  | MHTMLHandleWriter::MHTMLWriteCompleteCallback callback, | 
|  | scoped_refptr<base::TaskRunner> main_thread_task_runner) { | 
|  | // Handle must be instantiated. | 
|  | DCHECK(params.output_handle); | 
|  |  | 
|  | if (params.output_handle->is_file_handle()) { | 
|  | handle_ = new MHTMLFileHandleWriter( | 
|  | std::move(main_thread_task_runner), std::move(callback), | 
|  | std::move(params.output_handle->get_file_handle())); | 
|  | } else { | 
|  | handle_ = new MHTMLProducerHandleWriter( | 
|  | std::move(main_thread_task_runner), std::move(callback), | 
|  | std::move(params.output_handle->get_producer_handle())); | 
|  | } | 
|  | } | 
|  |  | 
|  | void WriteContents(std::vector<WebThreadSafeData> mhtml_contents) { | 
|  | // Using base::Unretained is safe, as calls to WriteContents() always | 
|  | // deletes |handle| upon Finish(). | 
|  | base::PostTaskWithTraits( | 
|  | FROM_HERE, {base::MayBlock()}, | 
|  | base::BindOnce(&MHTMLHandleWriter::WriteContents, | 
|  | base::Unretained(handle_), std::move(mhtml_contents))); | 
|  | } | 
|  |  | 
|  | // Within the context of the delegate, only for premature write finish. | 
|  | void Finish(mojom::MhtmlSaveStatus save_status) { | 
|  | base::PostTaskWithTraits( | 
|  | FROM_HERE, {base::MayBlock()}, | 
|  | base::BindOnce(&MHTMLHandleWriter::Finish, base::Unretained(handle_), | 
|  | save_status)); | 
|  | } | 
|  |  | 
|  | private: | 
|  | MHTMLHandleWriter* handle_; | 
|  |  | 
|  | DISALLOW_COPY_AND_ASSIGN(MHTMLHandleWriterDelegate); | 
|  | }; | 
|  |  | 
|  | FaviconURL::IconType ToFaviconType(blink::WebIconURL::Type type) { | 
|  | switch (type) { | 
|  | case blink::WebIconURL::kTypeFavicon: | 
|  | return FaviconURL::IconType::kFavicon; | 
|  | case blink::WebIconURL::kTypeTouch: | 
|  | return FaviconURL::IconType::kTouchIcon; | 
|  | case blink::WebIconURL::kTypeTouchPrecomposed: | 
|  | return FaviconURL::IconType::kTouchPrecomposedIcon; | 
|  | case blink::WebIconURL::kTypeInvalid: | 
|  | return FaviconURL::IconType::kInvalid; | 
|  | } | 
|  | NOTREACHED(); | 
|  | return FaviconURL::IconType::kInvalid; | 
|  | } | 
|  |  | 
|  | std::vector<gfx::Size> ConvertToFaviconSizes( | 
|  | const blink::WebVector<blink::WebSize>& web_sizes) { | 
|  | std::vector<gfx::Size> result; | 
|  | result.reserve(web_sizes.size()); | 
|  | for (const blink::WebSize& web_size : web_sizes) | 
|  | result.push_back(gfx::Size(web_size)); | 
|  | return result; | 
|  | } | 
|  |  | 
|  | // Use this for histograms with dynamically generated names, which otherwise | 
|  | // can't use the UMA_HISTOGRAM_MEMORY_MB macro without code duplication. | 
|  | void RecordSuffixedMemoryMBHistogram(base::StringPiece name, | 
|  | base::StringPiece suffix, | 
|  | int sample_mb) { | 
|  | std::string name_with_suffix; | 
|  | name.CopyToString(&name_with_suffix); | 
|  | suffix.AppendToString(&name_with_suffix); | 
|  | base::UmaHistogramMemoryMB(name_with_suffix, sample_mb); | 
|  | } | 
|  |  | 
|  | void RecordSuffixedRendererMemoryMetrics( | 
|  | const RenderThreadImpl::RendererMemoryMetrics& memory_metrics, | 
|  | base::StringPiece suffix) { | 
|  | RecordSuffixedMemoryMBHistogram("Memory.Experimental.Renderer.PartitionAlloc", | 
|  | suffix, | 
|  | memory_metrics.partition_alloc_kb / 1024); | 
|  | RecordSuffixedMemoryMBHistogram("Memory.Experimental.Renderer.BlinkGC", | 
|  | suffix, memory_metrics.blink_gc_kb / 1024); | 
|  | RecordSuffixedMemoryMBHistogram("Memory.Experimental.Renderer.Malloc", suffix, | 
|  | memory_metrics.malloc_mb); | 
|  | RecordSuffixedMemoryMBHistogram("Memory.Experimental.Renderer.Discardable", | 
|  | suffix, memory_metrics.discardable_kb / 1024); | 
|  | RecordSuffixedMemoryMBHistogram( | 
|  | "Memory.Experimental.Renderer.V8MainThreadIsolate", suffix, | 
|  | memory_metrics.v8_main_thread_isolate_mb); | 
|  | RecordSuffixedMemoryMBHistogram("Memory.Experimental.Renderer.TotalAllocated", | 
|  | suffix, memory_metrics.total_allocated_mb); | 
|  | RecordSuffixedMemoryMBHistogram( | 
|  | "Memory.Experimental.Renderer.NonDiscardableTotalAllocated", suffix, | 
|  | memory_metrics.non_discardable_total_allocated_mb); | 
|  | RecordSuffixedMemoryMBHistogram( | 
|  | "Memory.Experimental.Renderer.TotalAllocatedPerRenderView", suffix, | 
|  | memory_metrics.total_allocated_per_render_view_mb); | 
|  | } | 
|  |  | 
|  | // See also LOG_NAVIGATION_TIMING_HISTOGRAM in NavigationHandleImpl. | 
|  | void RecordReadyToCommitUntilCommitHistogram(base::TimeDelta delay, | 
|  | ui::PageTransition transition) { | 
|  | UMA_HISTOGRAM_TIMES("Navigation.Renderer.ReadyToCommitUntilCommit", delay); | 
|  | if (transition & ui::PAGE_TRANSITION_FORWARD_BACK) { | 
|  | UMA_HISTOGRAM_TIMES( | 
|  | "Navigation.Renderer.ReadyToCommitUntilCommit.BackForward", delay); | 
|  | } else if (ui::PageTransitionCoreTypeIs(transition, | 
|  | ui::PAGE_TRANSITION_RELOAD)) { | 
|  | UMA_HISTOGRAM_TIMES("Navigation.Renderer.ReadyToCommitUntilCommit.Reload", | 
|  | delay); | 
|  | } else if (ui::PageTransitionIsNewNavigation(transition)) { | 
|  | UMA_HISTOGRAM_TIMES( | 
|  | "Navigation.Renderer.ReadyToCommitUntilCommit.NewNavigation", delay); | 
|  | } else { | 
|  | NOTREACHED() << "Invalid page transition: " << transition; | 
|  | } | 
|  | } | 
|  |  | 
|  | blink::mojom::BlobURLTokenPtrInfo CloneBlobURLToken( | 
|  | mojo::MessagePipeHandle handle) { | 
|  | if (!handle.is_valid()) | 
|  | return nullptr; | 
|  | blink::mojom::BlobURLTokenPtrInfo result; | 
|  | blink::mojom::BlobURLTokenPtr token( | 
|  | blink::mojom::BlobURLTokenPtrInfo(mojo::ScopedMessagePipeHandle(handle), | 
|  | blink::mojom::BlobURLToken::Version_)); | 
|  | token->Clone(MakeRequest(&result)); | 
|  | ignore_result(token.PassInterface().PassHandle().release()); | 
|  | return result; | 
|  | } | 
|  |  | 
|  | // Creates a fully functional DocumentState in the case where we do not have | 
|  | // navigation parameters available. | 
|  | std::unique_ptr<DocumentState> BuildDocumentState() { | 
|  | std::unique_ptr<DocumentState> document_state = | 
|  | std::make_unique<DocumentState>(); | 
|  | InternalDocumentStateData::FromDocumentState(document_state.get()) | 
|  | ->set_navigation_state(NavigationState::CreateContentInitiated()); | 
|  | return document_state; | 
|  | } | 
|  |  | 
|  | // Creates a fully functional DocumentState in the case where we have | 
|  | // navigation parameters available in the RenderFrameImpl. | 
|  | std::unique_ptr<DocumentState> BuildDocumentStateFromParams( | 
|  | const CommonNavigationParams& common_params, | 
|  | const CommitNavigationParams& commit_params, | 
|  | base::TimeTicks time_commit_requested, | 
|  | mojom::FrameNavigationControl::CommitNavigationCallback commit_callback, | 
|  | mojom::NavigationClient::CommitNavigationCallback | 
|  | per_navigation_mojo_interface_commit_callback, | 
|  | const network::ResourceResponseHead* head, | 
|  | std::unique_ptr<NavigationClient> navigation_client, | 
|  | int request_id, | 
|  | bool was_initiated_in_this_frame) { | 
|  | std::unique_ptr<DocumentState> document_state(new DocumentState()); | 
|  | InternalDocumentStateData* internal_data = | 
|  | InternalDocumentStateData::FromDocumentState(document_state.get()); | 
|  |  | 
|  | DCHECK(!common_params.navigation_start.is_null()); | 
|  | DCHECK(!common_params.url.SchemeIs(url::kJavaScriptScheme)); | 
|  |  | 
|  | if (common_params.navigation_type == FrameMsg_Navigate_Type::RESTORE) { | 
|  | // We're doing a load of a page that was restored from the last session. | 
|  | // By default this prefers the cache over loading | 
|  | // (LOAD_SKIP_CACHE_VALIDATION) which can result in stale data for pages | 
|  | // that are set to expire. We explicitly override that by setting the | 
|  | // policy here so that as necessary we load from the network. | 
|  | // | 
|  | // TODO(davidben): Remove this in favor of passing a cache policy to the | 
|  | // loadHistoryItem call in OnNavigate. That requires not overloading | 
|  | // UseProtocolCachePolicy to mean both "normal load" and "determine cache | 
|  | // policy based on load type, etc". | 
|  | internal_data->set_cache_policy_override( | 
|  | blink::mojom::FetchCacheMode::kDefault); | 
|  | } | 
|  |  | 
|  | internal_data->set_is_overriding_user_agent( | 
|  | commit_params.is_overriding_user_agent); | 
|  | internal_data->set_must_reset_scroll_and_scale_state( | 
|  | common_params.navigation_type == | 
|  | FrameMsg_Navigate_Type::RELOAD_ORIGINAL_REQUEST_URL); | 
|  | internal_data->set_previews_state(common_params.previews_state); | 
|  | internal_data->set_request_id(request_id); | 
|  | document_state->set_can_load_local_resources( | 
|  | commit_params.can_load_local_resources); | 
|  |  | 
|  | if (head) { | 
|  | if (head->headers) | 
|  | internal_data->set_http_status_code(head->headers->response_code()); | 
|  | else if (common_params.url.SchemeIs(url::kDataScheme)) | 
|  | internal_data->set_http_status_code(200); | 
|  | document_state->set_was_fetched_via_spdy(head->was_fetched_via_spdy); | 
|  | document_state->set_was_alpn_negotiated(head->was_alpn_negotiated); | 
|  | document_state->set_alpn_negotiated_protocol( | 
|  | head->alpn_negotiated_protocol); | 
|  | document_state->set_was_alternate_protocol_available( | 
|  | head->was_alternate_protocol_available); | 
|  | document_state->set_connection_info(head->connection_info); | 
|  | internal_data->set_effective_connection_type( | 
|  | head->effective_connection_type); | 
|  | } | 
|  |  | 
|  | bool load_data = !common_params.base_url_for_data_url.is_empty() && | 
|  | !common_params.history_url_for_data_url.is_empty() && | 
|  | common_params.url.SchemeIs(url::kDataScheme); | 
|  | document_state->set_was_load_data_with_base_url_request(load_data); | 
|  | if (load_data) | 
|  | document_state->set_data_url(common_params.url); | 
|  |  | 
|  | InternalDocumentStateData::FromDocumentState(document_state.get()) | 
|  | ->set_navigation_state(NavigationState::CreateBrowserInitiated( | 
|  | common_params, commit_params, time_commit_requested, | 
|  | std::move(commit_callback), | 
|  | std::move(per_navigation_mojo_interface_commit_callback), | 
|  | std::move(navigation_client), was_initiated_in_this_frame)); | 
|  | return document_state; | 
|  | } | 
|  |  | 
|  | void ApplyFilePathAlias(blink::WebURLRequest* request) { | 
|  | const base::CommandLine::StringType file_url_path_alias = | 
|  | base::CommandLine::ForCurrentProcess()->GetSwitchValueNative( | 
|  | switches::kFileUrlPathAlias); | 
|  | if (file_url_path_alias.empty()) | 
|  | return; | 
|  |  | 
|  | 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; | 
|  | } | 
|  |  | 
|  | #if defined(OS_WIN) | 
|  | base::string16 path = request->Url().GetString().Utf16(); | 
|  | const base::string16 file_prefix = | 
|  | base::ASCIIToUTF16(url::kFileScheme) + | 
|  | base::ASCIIToUTF16(url::kStandardSchemeSeparator); | 
|  | #else | 
|  | std::string path = request->Url().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; | 
|  | } | 
|  |  | 
|  | base::ReplaceFirstSubstringAfterOffset(&path, 0, alias_mapping[0], | 
|  | alias_mapping[1]); | 
|  | request->SetUrl(blink::WebURL(GURL(path))); | 
|  | } | 
|  |  | 
|  | // Packs all navigation timings sent by the browser to a blink understandable | 
|  | // format, blink::WebNavigationTimings. | 
|  | blink::WebNavigationTimings BuildNavigationTimings( | 
|  | base::TimeTicks navigation_start, | 
|  | const NavigationTiming& browser_navigation_timings, | 
|  | base::TimeTicks input_start) { | 
|  | blink::WebNavigationTimings renderer_navigation_timings; | 
|  |  | 
|  | // Sanitizes the navigation_start timestamp for browser-initiated navigations, | 
|  | // where the browser possibly has a better notion of start time than the | 
|  | // renderer. In the case of cross-process navigations, this carries over the | 
|  | // time of finishing the onbeforeunload handler of the previous page. | 
|  | // TimeTicks is sometimes not monotonic across processes, and because | 
|  | // |browser_navigation_start| is likely before this process existed, | 
|  | // InterProcessTimeTicksConverter won't help. The timestamp is sanitized by | 
|  | // clamping it to now. | 
|  | 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; | 
|  |  | 
|  | return renderer_navigation_timings; | 
|  | } | 
|  |  | 
|  | // Fills navigation data sent by the browser to a blink understandable | 
|  | // format, blink::WebNavigationParams. | 
|  | void FillMiscNavigationParams(const CommonNavigationParams& common_params, | 
|  | const CommitNavigationParams& commit_params, | 
|  | blink::WebNavigationParams* navigation_params) { | 
|  | navigation_params->navigation_timings = BuildNavigationTimings( | 
|  | common_params.navigation_start, commit_params.navigation_timing, | 
|  | common_params.input_start); | 
|  |  | 
|  | navigation_params->is_user_activated = | 
|  | commit_params.was_activated == WasActivatedOption::kYes; | 
|  |  | 
|  | if (commit_params.origin_to_commit) { | 
|  | navigation_params->origin_to_commit = | 
|  | commit_params.origin_to_commit.value(); | 
|  | } | 
|  | } | 
|  |  | 
|  | }  // namespace | 
|  |  | 
|  | // This class uses existing WebNavigationBodyLoader to read the whole response | 
|  | // body into in-memory buffer, and then creates another body loader with static | 
|  | // data so that we can parse mhtml archive synchronously. This is a workaround | 
|  | // for the fact that we need the whole archive to determine the document's mime | 
|  | // type and construct a right document instance. | 
|  | class RenderFrameImpl::MHTMLBodyLoaderClient | 
|  | : public blink::WebNavigationBodyLoader::Client { | 
|  | public: | 
|  | // Once the body is read, fills |navigation_params| with the new body loader | 
|  | // and calls |done_callbcak|. | 
|  | MHTMLBodyLoaderClient( | 
|  | std::unique_ptr<blink::WebNavigationParams> navigation_params, | 
|  | base::OnceCallback<void(std::unique_ptr<blink::WebNavigationParams>)> | 
|  | done_callback) | 
|  | : navigation_params_(std::move(navigation_params)), | 
|  | done_callback_(std::move(done_callback)) { | 
|  | body_loader_ = std::move(navigation_params_->body_loader); | 
|  | body_loader_->StartLoadingBody(this, false /* use_isolated_code_cache */); | 
|  | } | 
|  |  | 
|  | ~MHTMLBodyLoaderClient() override {} | 
|  |  | 
|  | void BodyCodeCacheReceived(base::span<const uint8_t>) override {} | 
|  |  | 
|  | void BodyDataReceived(base::span<const char> data) override { | 
|  | data_.Append(data.data(), data.size()); | 
|  | } | 
|  |  | 
|  | void BodyLoadingFinished(base::TimeTicks completion_time, | 
|  | int64_t total_encoded_data_length, | 
|  | int64_t total_encoded_body_length, | 
|  | int64_t total_decoded_body_length, | 
|  | bool should_report_corb_blocking, | 
|  | const base::Optional<WebURLError>& error) override { | 
|  | if (!error.has_value()) { | 
|  | WebNavigationParams::FillBodyLoader(navigation_params_.get(), data_); | 
|  | // Clear |is_static_data| flag to avoid the special behavior it triggers, | 
|  | // e.g. skipping content disposition check. We want this load to be | 
|  | // regular, just like with an original body loader. | 
|  | navigation_params_->is_static_data = false; | 
|  | } | 
|  | std::move(done_callback_).Run(std::move(navigation_params_)); | 
|  | } | 
|  |  | 
|  | private: | 
|  | 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_; | 
|  |  | 
|  | DISALLOW_COPY_AND_ASSIGN(MHTMLBodyLoaderClient); | 
|  | }; | 
|  |  | 
|  | class RenderFrameImpl::FrameURLLoaderFactory | 
|  | : public blink::WebURLLoaderFactory { | 
|  | public: | 
|  | explicit FrameURLLoaderFactory(base::WeakPtr<RenderFrameImpl> frame) | 
|  | : frame_(std::move(frame)) {} | 
|  |  | 
|  | ~FrameURLLoaderFactory() override = default; | 
|  |  | 
|  | std::unique_ptr<blink::WebURLLoader> CreateURLLoader( | 
|  | const WebURLRequest& request, | 
|  | std::unique_ptr<blink::scheduler::WebResourceLoadingTaskRunnerHandle> | 
|  | task_runner_handle) override { | 
|  | // This should not be called if the frame is detached. | 
|  | DCHECK(frame_); | 
|  |  | 
|  | mojom::KeepAliveHandlePtr keep_alive_handle; | 
|  | if (request.GetKeepalive()) { | 
|  | frame_->GetFrameHost()->IssueKeepAliveHandle( | 
|  | mojo::MakeRequest(&keep_alive_handle)); | 
|  | } | 
|  | return std::make_unique<WebURLLoaderImpl>( | 
|  | RenderThreadImpl::current()->resource_dispatcher(), | 
|  | std::move(task_runner_handle), frame_->GetLoaderFactoryBundle(), | 
|  | std::move(keep_alive_handle)); | 
|  | } | 
|  |  | 
|  | private: | 
|  | base::WeakPtr<RenderFrameImpl> frame_; | 
|  |  | 
|  | DISALLOW_COPY_AND_ASSIGN(FrameURLLoaderFactory); | 
|  | }; | 
|  |  | 
|  | // The following methods are outside of the anonymous namespace to ensure that | 
|  | // the corresponding symbols get emmitted even on symbol_level 1. | 
|  | NOINLINE void ExhaustMemory() { | 
|  | volatile void* ptr = nullptr; | 
|  | do { | 
|  | ptr = malloc(0x10000000); | 
|  | base::debug::Alias(&ptr); | 
|  | } while (ptr); | 
|  | } | 
|  |  | 
|  | #if defined(ADDRESS_SANITIZER) | 
|  | NOINLINE void MaybeTriggerAsanError(const GURL& url) { | 
|  | // NOTE(rogerm): We intentionally perform an invalid heap access here in | 
|  | //     order to trigger an Address Sanitizer (ASAN) error report. | 
|  | if (url == kChromeUICrashHeapOverflowURL) { | 
|  | LOG(ERROR) << "Intentionally causing ASAN heap overflow" | 
|  | << " because user navigated to " << url.spec(); | 
|  | base::debug::AsanHeapOverflow(); | 
|  | } else if (url == kChromeUICrashHeapUnderflowURL) { | 
|  | LOG(ERROR) << "Intentionally causing ASAN heap underflow" | 
|  | << " because user navigated to " << url.spec(); | 
|  | base::debug::AsanHeapUnderflow(); | 
|  | } else if (url == kChromeUICrashUseAfterFreeURL) { | 
|  | LOG(ERROR) << "Intentionally causing ASAN heap use-after-free" | 
|  | << " because user navigated to " << url.spec(); | 
|  | base::debug::AsanHeapUseAfterFree(); | 
|  | #if defined(OS_WIN) | 
|  | } else if (url == kChromeUICrashCorruptHeapBlockURL) { | 
|  | LOG(ERROR) << "Intentionally causing ASAN corrupt heap block" | 
|  | << " because user navigated to " << url.spec(); | 
|  | base::debug::AsanCorruptHeapBlock(); | 
|  | } else if (url == kChromeUICrashCorruptHeapURL) { | 
|  | LOG(ERROR) << "Intentionally causing ASAN corrupt heap" | 
|  | << " because user navigated to " << url.spec(); | 
|  | base::debug::AsanCorruptHeap(); | 
|  | #endif  // OS_WIN | 
|  | } | 
|  | } | 
|  | #endif  // ADDRESS_SANITIZER | 
|  |  | 
|  | // Returns true if the URL is a debug URL, false otherwise. These URLs do not | 
|  | // commit, though they are intentionally left in the address bar above the | 
|  | // effect they cause (e.g., a sad tab). | 
|  | void HandleChromeDebugURL(const GURL& url) { | 
|  | DCHECK(IsRendererDebugURL(url) && !url.SchemeIs(url::kJavaScriptScheme)); | 
|  | if (url == kChromeUIBadCastCrashURL) { | 
|  | LOG(ERROR) << "Intentionally crashing (with bad cast)" | 
|  | << " because user navigated to " << url.spec(); | 
|  | internal::BadCastCrashIntentionally(); | 
|  | } else if (url == kChromeUICrashURL) { | 
|  | LOG(ERROR) << "Intentionally crashing (with null pointer dereference)" | 
|  | << " because user navigated to " << url.spec(); | 
|  | internal::CrashIntentionally(); | 
|  | } else if (url == kChromeUIDumpURL) { | 
|  | // This URL will only correctly create a crash dump file if content is | 
|  | // hosted in a process that has correctly called | 
|  | // base::debug::SetDumpWithoutCrashingFunction.  Refer to the documentation | 
|  | // of base::debug::DumpWithoutCrashing for more details. | 
|  | base::debug::DumpWithoutCrashing(); | 
|  | #if defined(OS_WIN) || defined(OS_POSIX) | 
|  | } else if (url == kChromeUIKillURL) { | 
|  | LOG(ERROR) << "Intentionally terminating current process because user" | 
|  | " navigated to " | 
|  | << url.spec(); | 
|  | // Simulate termination such that the base::GetTerminationStatus() API will | 
|  | // return TERMINATION_STATUS_PROCESS_WAS_KILLED. | 
|  | #if defined(OS_WIN) | 
|  | base::Process::TerminateCurrentProcessImmediately( | 
|  | base::win::kProcessKilledExitCode); | 
|  | #elif defined(OS_POSIX) | 
|  | PCHECK(kill(base::Process::Current().Pid(), SIGTERM) == 0); | 
|  | #endif | 
|  | #endif  // defined(OS_WIN) || defined(OS_POSIX) | 
|  | } else if (url == kChromeUIHangURL) { | 
|  | LOG(ERROR) << "Intentionally hanging ourselves with sleep infinite loop" | 
|  | << " because user navigated to " << url.spec(); | 
|  | for (;;) { | 
|  | base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(1)); | 
|  | } | 
|  | } else if (url == kChromeUIShorthangURL) { | 
|  | LOG(ERROR) << "Intentionally sleeping renderer for 20 seconds" | 
|  | << " because user navigated to " << url.spec(); | 
|  | base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(20)); | 
|  | } else if (url == kChromeUIMemoryExhaustURL) { | 
|  | LOG(ERROR) | 
|  | << "Intentionally exhausting renderer memory because user navigated to " | 
|  | << url.spec(); | 
|  | ExhaustMemory(); | 
|  | } else if (url == kChromeUICheckCrashURL) { | 
|  | LOG(ERROR) << "Intentionally causing CHECK because user navigated to " | 
|  | << url.spec(); | 
|  | CHECK(false); | 
|  | } | 
|  |  | 
|  | #if defined(OS_WIN) | 
|  | if (url == kChromeUIHeapCorruptionCrashURL) { | 
|  | LOG(ERROR) | 
|  | << "Intentionally causing heap corruption because user navigated to " | 
|  | << url.spec(); | 
|  | base::debug::win::TerminateWithHeapCorruption(); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | #if DCHECK_IS_ON() | 
|  | if (url == kChromeUICrashDcheckURL) { | 
|  | LOG(ERROR) << "Intentionally causing DCHECK because user navigated to " | 
|  | << url.spec(); | 
|  |  | 
|  | DCHECK(false) << "Intentional DCHECK."; | 
|  | } | 
|  | #endif | 
|  |  | 
|  | #if defined(ADDRESS_SANITIZER) | 
|  | MaybeTriggerAsanError(url); | 
|  | #endif  // ADDRESS_SANITIZER | 
|  | } | 
|  |  | 
|  | const std::string& UniqueNameForWebFrame(blink::WebFrame* frame) { | 
|  | return frame->IsWebLocalFrame() | 
|  | ? RenderFrameImpl::FromWebFrame(frame)->unique_name() | 
|  | : RenderFrameProxy::FromWebFrame(frame->ToWebRemoteFrame()) | 
|  | ->unique_name(); | 
|  | } | 
|  |  | 
|  | 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( | 
|  | base::StringPiece name) const { | 
|  | // This method is currently O(N), where N = number of frames in the tree. | 
|  | DCHECK(!name.empty()); | 
|  |  | 
|  | for (blink::WebFrame* frame = GetWebFrame()->Top(); frame; | 
|  | frame = frame->TraverseNext()) { | 
|  | if (UniqueNameForWebFrame(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<base::StringPiece> | 
|  | RenderFrameImpl::UniqueNameFrameAdapter::CollectAncestorNames( | 
|  | BeginPoint begin_point, | 
|  | bool (*should_stop)(base::StringPiece)) const { | 
|  | std::vector<base::StringPiece> result; | 
|  | for (blink::WebFrame* frame = begin_point == BeginPoint::kParentFrame | 
|  | ? GetWebFrame()->Parent() | 
|  | : GetWebFrame(); | 
|  | frame; frame = frame->Parent()) { | 
|  | result.push_back(UniqueNameForWebFrame(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_; | 
|  | } | 
|  |  | 
|  | // static | 
|  | RenderFrameImpl* RenderFrameImpl::Create( | 
|  | RenderViewImpl* render_view, | 
|  | int32_t routing_id, | 
|  | service_manager::mojom::InterfaceProviderPtr interface_provider, | 
|  | blink::mojom::DocumentInterfaceBrokerPtr document_interface_broker_content, | 
|  | const base::UnguessableToken& devtools_frame_token) { | 
|  | DCHECK(routing_id != MSG_ROUTING_NONE); | 
|  | CreateParams params(render_view, routing_id, std::move(interface_provider), | 
|  | std::move(document_interface_broker_content), | 
|  | devtools_frame_token); | 
|  |  | 
|  | if (g_create_render_frame_impl) | 
|  | return g_create_render_frame_impl(std::move(params)); | 
|  | else | 
|  | return new RenderFrameImpl(std::move(params)); | 
|  | } | 
|  |  | 
|  | // static | 
|  | RenderFrame* RenderFrame::FromRoutingID(int routing_id) { | 
|  | return RenderFrameImpl::FromRoutingID(routing_id); | 
|  | } | 
|  |  | 
|  | // static | 
|  | RenderFrameImpl* RenderFrameImpl::FromRoutingID(int routing_id) { | 
|  | DCHECK(RenderThread::IsMainThread()); | 
|  | auto iter = g_routing_id_frame_map.Get().find(routing_id); | 
|  | if (iter != g_routing_id_frame_map.Get().end()) | 
|  | return iter->second; | 
|  | return nullptr; | 
|  | } | 
|  |  | 
|  | // static | 
|  | RenderFrameImpl* RenderFrameImpl::CreateMainFrame( | 
|  | RenderViewImpl* render_view, | 
|  | int32_t routing_id, | 
|  | service_manager::mojom::InterfaceProviderPtr interface_provider, | 
|  | blink::mojom::DocumentInterfaceBrokerPtr document_interface_broker_content, | 
|  | blink::mojom::DocumentInterfaceBrokerPtr document_interface_broker_blink, | 
|  | int32_t widget_routing_id, | 
|  | bool hidden, | 
|  | const ScreenInfo& screen_info, | 
|  | CompositorDependencies* compositor_deps, | 
|  | blink::WebFrame* opener, | 
|  | const base::UnguessableToken& devtools_frame_token, | 
|  | const FrameReplicationState& replicated_state, | 
|  | bool has_committed_real_load) { | 
|  | // A main frame RenderFrame must have a RenderWidget. | 
|  | DCHECK_NE(MSG_ROUTING_NONE, widget_routing_id); | 
|  |  | 
|  | RenderFrameImpl* render_frame = RenderFrameImpl::Create( | 
|  | render_view, routing_id, std::move(interface_provider), | 
|  | std::move(document_interface_broker_content), devtools_frame_token); | 
|  | render_frame->InitializeBlameContext(nullptr); | 
|  | WebLocalFrame* web_frame = WebLocalFrame::CreateMainFrame( | 
|  | render_view->webview(), render_frame, | 
|  | render_frame->blink_interface_registry_.get(), | 
|  | document_interface_broker_blink.PassInterface().PassHandle(), opener, | 
|  | // This conversion is a little sad, as this often comes from a | 
|  | // WebString... | 
|  | WebString::FromUTF8(replicated_state.name), | 
|  | replicated_state.frame_policy.sandbox_flags, | 
|  | replicated_state.opener_feature_state); | 
|  | if (has_committed_real_load) | 
|  | render_frame->frame_->SetCommittedFirstRealLoad(); | 
|  |  | 
|  | // The RenderViewImpl and its RenderWidget already exist by the time we get | 
|  | // here. | 
|  | // TODO(crbug.com/419087): We probably want to create the RenderWidget here | 
|  | // though (when we make the WebFrameWidget?). | 
|  | RenderWidget* render_widget = render_view->GetWidget(); | 
|  |  | 
|  | // Non-owning pointer that is self-referencing and destroyed by calling | 
|  | // Close(). The RenderViewImpl has a RenderWidget already, but not a | 
|  | // WebFrameWidget, which is now attached here. | 
|  | auto* web_frame_widget = blink::WebFrameWidget::CreateForMainFrame( | 
|  | render_view->GetWidget(), web_frame); | 
|  | render_view->AttachWebFrameWidget(web_frame_widget); | 
|  | // TODO(crbug.com/419087): This was added in 6ccadf770766e89c3 to prevent an | 
|  | // empty ScreenInfo, but the WebView has already been created and initialized | 
|  | // by RenderViewImpl, so this is surely redundant? | 
|  | render_widget->UpdateWebViewWithDeviceScaleFactor(); | 
|  |  | 
|  | // The WebFrame created here was already attached to the Page as its | 
|  | // main frame, and the WebFrameWidget has been initialized, so we can call | 
|  | // WebViewImpl's DidAttachLocalMainFrame(). | 
|  | render_view->webview()->DidAttachLocalMainFrame(render_widget); | 
|  |  | 
|  | render_frame->render_widget_ = render_widget; | 
|  | render_frame->in_frame_tree_ = true; | 
|  | render_frame->Initialize(); | 
|  |  | 
|  | return render_frame; | 
|  | } | 
|  |  | 
|  | // static | 
|  | void RenderFrameImpl::CreateFrame( | 
|  | int routing_id, | 
|  | service_manager::mojom::InterfaceProviderPtr interface_provider, | 
|  | blink::mojom::DocumentInterfaceBrokerPtr document_interface_broker_content, | 
|  | blink::mojom::DocumentInterfaceBrokerPtr document_interface_broker_blink, | 
|  | int previous_routing_id, | 
|  | int opener_routing_id, | 
|  | int parent_routing_id, | 
|  | int previous_sibling_routing_id, | 
|  | const base::UnguessableToken& devtools_frame_token, | 
|  | const FrameReplicationState& replicated_state, | 
|  | CompositorDependencies* compositor_deps, | 
|  | const mojom::CreateFrameWidgetParams& widget_params, | 
|  | const FrameOwnerProperties& frame_owner_properties, | 
|  | bool has_committed_real_load) { | 
|  | // TODO(danakj): Split this method into two pieces. The first block makes a | 
|  | // WebLocalFrame and collects the RenderView and RenderFrame for it. The | 
|  | // second block uses that to make/setup a RenderWidget, if needed. | 
|  | RenderViewImpl* render_view = nullptr; | 
|  | RenderFrameImpl* render_frame = nullptr; | 
|  | blink::WebLocalFrame* web_frame = nullptr; | 
|  | if (previous_routing_id == MSG_ROUTING_NONE) { | 
|  | // TODO(alexmos): This path is currently used only: | 
|  | // 1) When recreating a RenderFrame after a crash. | 
|  | // 2) In tests that issue this IPC directly. | 
|  | // These two cases should be cleaned up to also pass a previous_routing_id, | 
|  | // which would allow removing this branch altogether.  See | 
|  | // https://crbug.com/756790. | 
|  |  | 
|  | RenderFrameProxy* parent_proxy = | 
|  | RenderFrameProxy::FromRoutingID(parent_routing_id); | 
|  | // If the browser is sending a valid parent routing id, it should already | 
|  | // be created and registered. | 
|  | CHECK(parent_proxy); | 
|  | blink::WebRemoteFrame* parent_web_frame = parent_proxy->web_frame(); | 
|  |  | 
|  | blink::WebFrame* previous_sibling_web_frame = nullptr; | 
|  | RenderFrameProxy* previous_sibling_proxy = | 
|  | RenderFrameProxy::FromRoutingID(previous_sibling_routing_id); | 
|  | if (previous_sibling_proxy) | 
|  | previous_sibling_web_frame = previous_sibling_proxy->web_frame(); | 
|  |  | 
|  | render_view = parent_proxy->render_view(); | 
|  | // Create the RenderFrame and WebLocalFrame, linking the two. | 
|  | render_frame = RenderFrameImpl::Create( | 
|  | parent_proxy->render_view(), routing_id, std::move(interface_provider), | 
|  | std::move(document_interface_broker_content), devtools_frame_token); | 
|  | render_frame->InitializeBlameContext(FromRoutingID(parent_routing_id)); | 
|  | render_frame->unique_name_helper_.set_propagated_name( | 
|  | replicated_state.unique_name); | 
|  | web_frame = parent_web_frame->CreateLocalChild( | 
|  | replicated_state.scope, WebString::FromUTF8(replicated_state.name), | 
|  | replicated_state.frame_policy, render_frame, | 
|  | render_frame->blink_interface_registry_.get(), | 
|  | document_interface_broker_blink.PassInterface().PassHandle(), | 
|  | previous_sibling_web_frame, | 
|  | ConvertFrameOwnerPropertiesToWebFrameOwnerProperties( | 
|  | frame_owner_properties), | 
|  | replicated_state.frame_owner_element_type, | 
|  | ResolveOpener(opener_routing_id)); | 
|  |  | 
|  | // The RenderFrame is created and inserted into the frame tree in the above | 
|  | // call to createLocalChild. | 
|  | render_frame->in_frame_tree_ = true; | 
|  | } else { | 
|  | RenderFrameProxy* proxy = | 
|  | RenderFrameProxy::FromRoutingID(previous_routing_id); | 
|  | // The remote frame could've been detached while the remote-to-local | 
|  | // navigation was being initiated in the browser process. Drop the | 
|  | // navigation and don't create the frame in that case.  See | 
|  | // https://crbug.com/526304. | 
|  | if (!proxy) | 
|  | return; | 
|  |  | 
|  | // This path is creating a local frame. It may or may not be a local root, | 
|  | // depending if the frame's parent is local or remote. It may also be the | 
|  | // main frame, as in the case where a navigation to the current process' | 
|  | // origin replaces a remote main frame (the proxy's web_frame()) with a | 
|  | // local one. | 
|  | const bool proxy_is_main_frame = !proxy->web_frame()->Parent(); | 
|  |  | 
|  | render_view = proxy->render_view(); | 
|  | render_frame = RenderFrameImpl::Create( | 
|  | render_view, routing_id, std::move(interface_provider), | 
|  | std::move(document_interface_broker_content), devtools_frame_token); | 
|  | render_frame->InitializeBlameContext(nullptr); | 
|  | render_frame->previous_routing_id_ = previous_routing_id; | 
|  | proxy->set_provisional_frame_routing_id(routing_id); | 
|  | web_frame = blink::WebLocalFrame::CreateProvisional( | 
|  | render_frame, render_frame->blink_interface_registry_.get(), | 
|  | document_interface_broker_blink.PassInterface().PassHandle(), | 
|  | proxy->web_frame(), replicated_state.frame_policy); | 
|  | // The new |web_frame| is a main frame iff the proxy's frame was. | 
|  | DCHECK_EQ(proxy_is_main_frame, !web_frame->Parent()); | 
|  | } | 
|  |  | 
|  | DCHECK(render_view); | 
|  | DCHECK(render_frame); | 
|  | DCHECK(web_frame); | 
|  |  | 
|  | const bool is_main_frame = !web_frame->Parent(); | 
|  |  | 
|  | // Child frames require there to be a |parent_routing_id| present, for the | 
|  | // remote parent frame. Though it is only used if the |previous_routing_id| | 
|  | // is not given, which happens in some corner cases. | 
|  | if (!is_main_frame) | 
|  | DCHECK_NE(parent_routing_id, MSG_ROUTING_NONE); | 
|  |  | 
|  | // We now have a WebLocalFrame for the new frame. The next step is to set | 
|  | // up a RenderWidget for it, if it is needed. | 
|  | // | 
|  | // If there is no widget routing id, then the new frame is not a local root, | 
|  | // and does not need a RenderWidget. In that case we'll do nothing. Otherwise | 
|  | // it does. | 
|  | if (is_main_frame) { | 
|  | // For a main frame, we use the RenderWidget already attached to the | 
|  | // RenderView (this is being changed by https://crbug.com/419087). | 
|  |  | 
|  | // Main frames are always local roots, so they should always have a routing | 
|  | // id. Surprisingly, this routing id is *not* used though, as the routing id | 
|  | // on the existing RenderWidget is not changed. (I don't know why.) | 
|  | // TODO(crbug.com/888105): It's a bug that the RenderWidget is not using | 
|  | // this routing id. | 
|  | DCHECK_NE(widget_params.routing_id, MSG_ROUTING_NONE); | 
|  |  | 
|  | // The RenderViewImpl and its RenderWidget already exist by the time we | 
|  | // get here (we get them from the RenderFrameProxy). | 
|  | // TODO(crbug.com/419087): We probably want to create the RenderWidget | 
|  | // here though (when we make the WebFrameWidget?). | 
|  | RenderWidget* render_widget = render_view->GetWidget(); | 
|  |  | 
|  | // Non-owning pointer that is self-referencing and destroyed by calling | 
|  | // Close(). The RenderViewImpl has a RenderWidget already, but not a | 
|  | // WebFrameWidget, which is now attached here. | 
|  | auto* web_frame_widget = blink::WebFrameWidget::CreateForMainFrame( | 
|  | render_view->GetWidget(), web_frame); | 
|  | render_view->AttachWebFrameWidget(web_frame_widget); | 
|  | // TODO(crbug.com/419087): This was added in 6ccadf770766e89c3 to prevent | 
|  | // an empty ScreenInfo, but the WebView has already been created and | 
|  | // initialized by RenderViewImpl, so this is surely redundant? It will be | 
|  | // pulling the device scale factor off the WebView itself. | 
|  | render_widget->UpdateWebViewWithDeviceScaleFactor(); | 
|  |  | 
|  | // Note that we do *not* call WebViewImpl's DidAttachLocalMainFrame() here | 
|  | // yet because this frame is provisional and not attached to the Page yet. | 
|  | // We will tell WebViewImpl about it once it is swapped in. | 
|  |  | 
|  | // It may be questionable, since we create un-frozen RenderWidgets at this | 
|  | // point for subframes, but we don't un-freeze the main frame's RenderWidget | 
|  | // here, instead deferring until the non-provisional frame is swapped in. | 
|  | // But we do need to start the creating compositor resources in parallel to | 
|  | // the navigation being done with the provisional frame, so we inform the | 
|  | // frozen RenderWidget to get prepared. We must abort this if we are no | 
|  | // longer planning to un-freeze the RenderWidget (ie in FrameDetached). | 
|  | render_widget->WarmupCompositor(); | 
|  |  | 
|  | render_frame->render_widget_ = render_widget; | 
|  | } else if (widget_params.routing_id != MSG_ROUTING_NONE) { | 
|  | // This frame is a child local root, so we require a separate RenderWidget | 
|  | // for it from any other frames in the frame tree. Each local root defines | 
|  | // a separate context/coordinate space/world for compositing, painting, | 
|  | // input, etc. And each local root has a RenderWidget which provides | 
|  | // such services independent from other RenderWidgets. | 
|  | // Notably, we do not attempt to reuse the main frame's RenderWidget (if the | 
|  | // main frame in this frame tree is local) as that RenderWidget is | 
|  | // functioning in a different local root. Because this is a child local | 
|  | // root, it implies there is some remote frame ancestor between this frame | 
|  | // and the main frame, thus its coordinate space etc is not known relative | 
|  | // to the main frame. | 
|  |  | 
|  | // TODO(crbug.com/419087): This is grabbing something off the view's | 
|  | // widget but if the main frame is remote this widget would not be valid? | 
|  | const ScreenInfo& screen_info_from_main_frame = | 
|  | render_view->GetWidget()->GetWebScreenInfo(); | 
|  |  | 
|  | // Makes a new RenderWidget for the child local root. It provides the | 
|  | // local root with a new compositing, painting, and input coordinate | 
|  | // space/context. | 
|  | scoped_refptr<RenderWidget> render_widget = RenderWidget::CreateForFrame( | 
|  | widget_params.routing_id, compositor_deps, screen_info_from_main_frame, | 
|  | blink::kWebDisplayModeUndefined, | 
|  | /*is_frozen=*/false, widget_params.hidden, | 
|  | /*never_visible=*/false, /*widget_request=*/nullptr); | 
|  |  | 
|  | // Non-owning pointer that is self-referencing and destroyed by calling | 
|  | // Close(). We use the new RenderWidget as the client for this | 
|  | // WebFrameWidget, *not* the RenderWidget of the MainFrame, which is | 
|  | // accessible from the RenderViewImpl. | 
|  | auto* web_frame_widget = blink::WebFrameWidget::CreateForChildLocalRoot( | 
|  | render_widget.get(), web_frame); | 
|  |  | 
|  | // Adds a reference on RenderWidget, making it self-referencing. So it | 
|  | // will not be destroyed by scoped_refptr unless Close() has been called | 
|  | // and run. | 
|  | render_widget->InitForChildLocalRoot(web_frame_widget); | 
|  | // TODO(crbug.com/419087): This was added in 6ccadf770766e89c3 to prevent | 
|  | // an empty ScreenInfo, but the WebView has already been created and | 
|  | // initialized by RenderViewImpl, so this is surely redundant? It will be | 
|  | // pulling the device scale factor off the WebView itself. | 
|  | render_widget->UpdateWebViewWithDeviceScaleFactor(); | 
|  |  | 
|  | render_frame->render_widget_ = std::move(render_widget); | 
|  | } | 
|  |  | 
|  | if (has_committed_real_load) | 
|  | render_frame->frame_->SetCommittedFirstRealLoad(); | 
|  |  | 
|  | render_frame->Initialize(); | 
|  | } | 
|  |  | 
|  | // static | 
|  | RenderFrame* RenderFrame::FromWebFrame(blink::WebLocalFrame* web_frame) { | 
|  | return RenderFrameImpl::FromWebFrame(web_frame); | 
|  | } | 
|  |  | 
|  | // static | 
|  | 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; | 
|  | } | 
|  | } | 
|  |  | 
|  | // static | 
|  | int RenderFrame::GetRoutingIdForWebFrame(blink::WebFrame* web_frame) { | 
|  | if (!web_frame) | 
|  | return MSG_ROUTING_NONE; | 
|  | if (web_frame->IsWebRemoteFrame()) { | 
|  | return RenderFrameProxy::FromWebFrame(web_frame->ToWebRemoteFrame()) | 
|  | ->routing_id(); | 
|  | } | 
|  | return RenderFrameImpl::FromWebFrame(web_frame)->GetRoutingID(); | 
|  | } | 
|  |  | 
|  | // static | 
|  | 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; | 
|  | } | 
|  |  | 
|  | // static | 
|  | void RenderFrameImpl::InstallCreateHook( | 
|  | CreateRenderFrameImplFunction create_frame) { | 
|  | DCHECK(!g_create_render_frame_impl); | 
|  | g_create_render_frame_impl = create_frame; | 
|  | } | 
|  |  | 
|  | // static | 
|  | blink::WebFrame* RenderFrameImpl::ResolveOpener(int opener_frame_routing_id) { | 
|  | if (opener_frame_routing_id == MSG_ROUTING_NONE) | 
|  | return nullptr; | 
|  |  | 
|  | // Opener routing ID could refer to either a RenderFrameProxy or a | 
|  | // RenderFrame, so need to check both. | 
|  | RenderFrameProxy* opener_proxy = | 
|  | RenderFrameProxy::FromRoutingID(opener_frame_routing_id); | 
|  | if (opener_proxy) | 
|  | return opener_proxy->web_frame(); | 
|  |  | 
|  | RenderFrameImpl* opener_frame = | 
|  | RenderFrameImpl::FromRoutingID(opener_frame_routing_id); | 
|  | if (opener_frame) | 
|  | return opener_frame->GetWebFrame(); | 
|  |  | 
|  | return nullptr; | 
|  | } | 
|  |  | 
|  | // static | 
|  | void RenderFrameImpl::MaybeSetDownloadFramePolicy( | 
|  | bool is_opener_navigation, | 
|  | const blink::WebURLRequest& request, | 
|  | const blink::WebSecurityOrigin& current_origin, | 
|  | bool has_download_sandbox_flag, | 
|  | bool blocking_downloads_in_sandbox_without_user_activation_enabled, | 
|  | bool from_ad, | 
|  | NavigationDownloadPolicy* download_policy) { | 
|  | // Disallow downloads on an opener if the requestor is cross origin. | 
|  | // See crbug.com/632514. | 
|  | if (is_opener_navigation && | 
|  | !request.RequestorOrigin().CanAccess(current_origin)) { | 
|  | download_policy->SetDisallowed(NavigationDownloadType::kOpenerCrossOrigin); | 
|  | } | 
|  | if (has_download_sandbox_flag && !request.HasUserGesture()) { | 
|  | if (blocking_downloads_in_sandbox_without_user_activation_enabled) { | 
|  | download_policy->SetDisallowed(NavigationDownloadType::kSandboxNoGesture); | 
|  | } else { | 
|  | download_policy->SetAllowed(NavigationDownloadType::kSandboxNoGesture); | 
|  | } | 
|  | } | 
|  | if (from_ad) { | 
|  | if (!request.HasUserGesture()) { | 
|  | if (base::FeatureList::IsEnabled( | 
|  | blink::features:: | 
|  | kBlockingDownloadsInAdFrameWithoutUserActivation)) { | 
|  | download_policy->SetDisallowed( | 
|  | NavigationDownloadType::kAdFrameNoGesture); | 
|  | } else { | 
|  | download_policy->SetAllowed(NavigationDownloadType::kAdFrameNoGesture); | 
|  | } | 
|  | } else { | 
|  | download_policy->SetAllowed(NavigationDownloadType::kAdFrameGesture); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | blink::WebURL RenderFrameImpl::OverrideFlashEmbedWithHTML( | 
|  | const blink::WebURL& url) { | 
|  | return GetContentClient()->renderer()->OverrideFlashEmbedWithHTML(url); | 
|  | } | 
|  |  | 
|  | // RenderFrameImpl::CreateParams -------------------------------------------- | 
|  |  | 
|  | RenderFrameImpl::CreateParams::CreateParams( | 
|  | RenderViewImpl* render_view, | 
|  | int32_t routing_id, | 
|  | service_manager::mojom::InterfaceProviderPtr interface_provider, | 
|  | blink::mojom::DocumentInterfaceBrokerPtr document_interface_broker_content, | 
|  | const base::UnguessableToken& devtools_frame_token) | 
|  | : render_view(render_view), | 
|  | routing_id(routing_id), | 
|  | interface_provider(std::move(interface_provider)), | 
|  | document_interface_broker_content( | 
|  | std::move(document_interface_broker_content)), | 
|  | devtools_frame_token(devtools_frame_token) {} | 
|  | RenderFrameImpl::CreateParams::~CreateParams() = default; | 
|  | RenderFrameImpl::CreateParams::CreateParams(CreateParams&&) = default; | 
|  | RenderFrameImpl::CreateParams& RenderFrameImpl::CreateParams::operator=( | 
|  | CreateParams&&) = default; | 
|  |  | 
|  | // RenderFrameImpl ---------------------------------------------------------- | 
|  | RenderFrameImpl::RenderFrameImpl(CreateParams params) | 
|  | : frame_(nullptr), | 
|  | is_main_frame_(true), | 
|  | unique_name_frame_adapter_(this), | 
|  | unique_name_helper_(&unique_name_frame_adapter_), | 
|  | in_frame_tree_(false), | 
|  | render_view_(params.render_view), | 
|  | routing_id_(params.routing_id), | 
|  | previous_routing_id_(MSG_ROUTING_NONE), | 
|  | #if BUILDFLAG(ENABLE_PLUGINS) | 
|  | plugin_power_saver_helper_(nullptr), | 
|  | #endif | 
|  | cookie_jar_(this), | 
|  | selection_text_offset_(0), | 
|  | selection_range_(gfx::Range::InvalidRange()), | 
|  | handling_select_range_(false), | 
|  | web_user_media_client_(nullptr), | 
|  | push_messaging_client_(nullptr), | 
|  | render_accessibility_(nullptr), | 
|  | previews_state_(PREVIEWS_UNSPECIFIED), | 
|  | effective_connection_type_( | 
|  | blink::WebEffectiveConnectionType::kTypeUnknown), | 
|  | is_pasting_(false), | 
|  | suppress_further_dialogs_(false), | 
|  | blame_context_(nullptr), | 
|  | #if BUILDFLAG(ENABLE_PLUGINS) | 
|  | focused_pepper_plugin_(nullptr), | 
|  | pepper_last_mouse_event_target_(nullptr), | 
|  | #endif | 
|  | autoplay_configuration_binding_(this), | 
|  | frame_binding_(this), | 
|  | host_zoom_binding_(this), | 
|  | frame_bindings_control_binding_(this), | 
|  | frame_navigation_control_binding_(this), | 
|  | fullscreen_binding_(this), | 
|  | mhtml_file_writer_binding_(this), | 
|  | navigation_client_impl_(nullptr), | 
|  | has_accessed_initial_document_(false), | 
|  | media_factory_(this, | 
|  | base::Bind(&RenderFrameImpl::RequestOverlayRoutingToken, | 
|  | base::Unretained(this))), | 
|  | input_target_client_impl_(this), | 
|  | devtools_frame_token_(params.devtools_frame_token), | 
|  | weak_factory_(this) { | 
|  | DCHECK(RenderThread::IsMainThread()); | 
|  | // The InterfaceProvider to access Mojo services exposed by the RFHI must be | 
|  | // provided at construction time. See: https://crbug.com/729021/. | 
|  | CHECK(params.interface_provider.is_bound()); | 
|  | remote_interfaces_.Bind(std::move(params.interface_provider)); | 
|  | blink_interface_registry_.reset(new BlinkInterfaceRegistryImpl( | 
|  | registry_.GetWeakPtr(), associated_interfaces_.GetWeakPtr())); | 
|  |  | 
|  | // The DocumentInterfaceBroker to access Mojo services exposed by the RFHI | 
|  | // must be provided at construction time. See: https://crbug.com/718652/. | 
|  | CHECK(params.document_interface_broker_content.is_bound()); | 
|  | document_interface_broker_ = | 
|  | std::move(params.document_interface_broker_content); | 
|  |  | 
|  | // Must call after binding our own remote interfaces. | 
|  | media_factory_.SetupMojo(); | 
|  |  | 
|  | std::pair<RoutingIDFrameMap::iterator, bool> result = | 
|  | g_routing_id_frame_map.Get().insert(std::make_pair(routing_id_, this)); | 
|  | CHECK(result.second) << "Inserting a duplicate item."; | 
|  |  | 
|  | // Everything below subclasses RenderFrameObserver and is automatically | 
|  | // deleted when the RenderFrame gets deleted. | 
|  | #if defined(OS_ANDROID) | 
|  | new GinJavaBridgeDispatcher(this); | 
|  | #endif | 
|  |  | 
|  | #if BUILDFLAG(ENABLE_PLUGINS) | 
|  | // Manages its own lifetime. | 
|  | plugin_power_saver_helper_ = new PluginPowerSaverHelper(this); | 
|  | #endif | 
|  |  | 
|  | manifest_manager_ = std::make_unique<ManifestManager>(this); | 
|  | // TODO(ajwong): This always returns true as is_main_frame_ gets initialized | 
|  | // later in RenderFrameImpl::Initialize(). Should the conditional be in | 
|  | // RenderFrameImpl::Initialize()?  https://crbug.com/840533 | 
|  | if (IsMainFrame()) { | 
|  | // Manages its own lifetime. | 
|  | new ManifestChangeNotifier(this); | 
|  | } | 
|  | } | 
|  |  | 
|  | mojom::FrameHost* RenderFrameImpl::GetFrameHost() { | 
|  | if (!frame_host_ptr_.is_bound()) | 
|  | GetRemoteAssociatedInterfaces()->GetInterface(&frame_host_ptr_); | 
|  | return frame_host_ptr_.get(); | 
|  | } | 
|  |  | 
|  | RenderFrameImpl::~RenderFrameImpl() { | 
|  | for (auto& observer : observers_) | 
|  | observer.RenderFrameGone(); | 
|  | for (auto& observer : observers_) | 
|  | observer.OnDestruct(); | 
|  |  | 
|  | base::trace_event::TraceLog::GetInstance()->RemoveProcessLabel(routing_id_); | 
|  |  | 
|  | if (auto* factory = AudioOutputIPCFactory::get()) | 
|  | factory->MaybeDeregisterRemoteFactory(GetRoutingID()); | 
|  |  | 
|  | // |thread| may be null in tests. | 
|  | if (auto* thread = RenderThreadImpl::current()) { | 
|  | if (auto* controller = thread->low_memory_mode_controller()) | 
|  | controller->OnFrameDestroyed(IsMainFrame()); | 
|  | } | 
|  |  | 
|  | if (is_main_frame_) { | 
|  | // Ensure the RenderView doesn't point to this object, once it is destroyed. | 
|  | // TODO(nasko): Add a check that the |main_render_frame_| of |render_view_| | 
|  | // is |this|, once the object is no longer leaked. | 
|  | // See https://crbug.com/464764. | 
|  | render_view_->main_render_frame_ = nullptr; | 
|  | } | 
|  |  | 
|  | g_routing_id_frame_map.Get().erase(routing_id_); | 
|  | RenderThread::Get()->RemoveRoute(routing_id_); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::Initialize() { | 
|  | is_main_frame_ = !frame_->Parent(); | 
|  |  | 
|  | GetLocalRootRenderWidget()->RegisterRenderFrame(this); | 
|  |  | 
|  | RenderFrameImpl* parent_frame = | 
|  | RenderFrameImpl::FromWebFrame(frame_->Parent()); | 
|  | if (parent_frame) { | 
|  | previews_state_ = parent_frame->GetPreviewsState(); | 
|  | effective_connection_type_ = parent_frame->GetEffectiveConnectionType(); | 
|  | } | 
|  |  | 
|  | bool is_tracing_rail = false; | 
|  | bool is_tracing_navigation = false; | 
|  | TRACE_EVENT_CATEGORY_GROUP_ENABLED("navigation", &is_tracing_navigation); | 
|  | TRACE_EVENT_CATEGORY_GROUP_ENABLED("rail", &is_tracing_rail); | 
|  | if (is_tracing_rail || is_tracing_navigation) { | 
|  | int parent_id = RenderFrame::GetRoutingIdForWebFrame(frame_->Parent()); | 
|  | TRACE_EVENT2("navigation,rail", "RenderFrameImpl::Initialize", | 
|  | "id", routing_id_, | 
|  | "parent", parent_id); | 
|  | } | 
|  |  | 
|  | // |thread| may be null in tests. | 
|  | if (auto* thread = RenderThreadImpl::current()) { | 
|  | if (auto* controller = thread->low_memory_mode_controller()) | 
|  | controller->OnFrameCreated(IsMainFrame()); | 
|  | } | 
|  |  | 
|  | #if BUILDFLAG(ENABLE_PLUGINS) | 
|  | new PepperBrowserConnection(this); | 
|  | #endif | 
|  |  | 
|  | RegisterMojoInterfaces(); | 
|  |  | 
|  | // We delay calling this until we have the WebFrame so that any observer or | 
|  | // embedder can call GetWebFrame on any RenderFrame. | 
|  | GetContentClient()->renderer()->RenderFrameCreated(this); | 
|  |  | 
|  | // AudioOutputIPCFactory may be null in tests. | 
|  | if (auto* factory = AudioOutputIPCFactory::get()) | 
|  | factory->RegisterRemoteFactory(GetRoutingID(), GetRemoteInterfaces()); | 
|  |  | 
|  | AudioRendererSinkCache::ObserveFrame(this); | 
|  |  | 
|  | const base::CommandLine& command_line = | 
|  | *base::CommandLine::ForCurrentProcess(); | 
|  | if (command_line.HasSwitch(switches::kDomAutomationController)) | 
|  | enabled_bindings_ |= BINDINGS_POLICY_DOM_AUTOMATION; | 
|  | if (command_line.HasSwitch(switches::kStatsCollectionController)) | 
|  | enabled_bindings_ |= BINDINGS_POLICY_STATS_COLLECTION; | 
|  | if (base::FeatureList::IsEnabled(network::features::kNetworkService)) | 
|  | frame_request_blocker_ = base::MakeRefCounted<FrameRequestBlocker>(); | 
|  |  | 
|  | // Bind this frame and the message router. This must be called after |frame_| | 
|  | // is set since binding requires a per-frame task runner. | 
|  | RenderThread::Get()->AddRoute(routing_id_, this); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::InitializeBlameContext(RenderFrameImpl* parent_frame) { | 
|  | DCHECK(!blame_context_); | 
|  | blame_context_ = std::make_unique<FrameBlameContext>(this, parent_frame); | 
|  | blame_context_->Initialize(); | 
|  | } | 
|  |  | 
|  | 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; | 
|  | } | 
|  | } | 
|  |  | 
|  | RenderWidget* RenderFrameImpl::GetLocalRootRenderWidget() { | 
|  | return GetLocalRoot()->render_widget_.get(); | 
|  | } | 
|  |  | 
|  | RenderWidget* RenderFrameImpl::GetMainFrameRenderWidget() { | 
|  | return render_view()->GetWidget(); | 
|  | } | 
|  |  | 
|  | #if BUILDFLAG(ENABLE_PLUGINS) | 
|  | void RenderFrameImpl::PepperPluginCreated(RendererPpapiHost* host) { | 
|  | for (auto& observer : observers_) | 
|  | observer.DidCreatePepperPlugin(host); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::PepperDidChangeCursor( | 
|  | PepperPluginInstanceImpl* instance, | 
|  | const blink::WebCursorInfo& cursor) { | 
|  | // Update the cursor appearance immediately if the requesting plugin is the | 
|  | // one which receives the last mouse event. Otherwise, the new cursor won't be | 
|  | // picked up until the plugin gets the next input event. That is bad if, e.g., | 
|  | // the plugin would like to set an invisible cursor when there isn't any user | 
|  | // input for a while. | 
|  | if (instance == pepper_last_mouse_event_target_) | 
|  | GetLocalRootRenderWidget()->DidChangeCursor(cursor); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::PepperDidReceiveMouseEvent( | 
|  | PepperPluginInstanceImpl* instance) { | 
|  | set_pepper_last_mouse_event_target(instance); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::PepperTextInputTypeChanged( | 
|  | PepperPluginInstanceImpl* instance) { | 
|  | if (instance != focused_pepper_plugin_) | 
|  | return; | 
|  |  | 
|  | GetLocalRootRenderWidget()->UpdateTextInputState(); | 
|  |  | 
|  | FocusedNodeChangedForAccessibility(WebNode()); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::PepperCaretPositionChanged( | 
|  | PepperPluginInstanceImpl* instance) { | 
|  | if (instance != focused_pepper_plugin_) | 
|  | return; | 
|  | GetLocalRootRenderWidget()->UpdateSelectionBounds(); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::PepperCancelComposition( | 
|  | PepperPluginInstanceImpl* instance) { | 
|  | if (instance != focused_pepper_plugin_) | 
|  | return; | 
|  | if (mojom::WidgetInputHandlerHost* host = GetLocalRootRenderWidget() | 
|  | ->widget_input_handler_manager() | 
|  | ->GetWidgetInputHandlerHost()) { | 
|  | host->ImeCancelComposition(); | 
|  | } | 
|  | #if defined(OS_MACOSX) || defined(USE_AURA) | 
|  | GetLocalRootRenderWidget()->UpdateCompositionInfo( | 
|  | false /* not an immediate request */); | 
|  | #endif | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::PepperSelectionChanged( | 
|  | PepperPluginInstanceImpl* instance) { | 
|  | if (instance != focused_pepper_plugin_) | 
|  | return; | 
|  | SyncSelectionIfRequired(); | 
|  | } | 
|  |  | 
|  | RenderWidgetFullscreenPepper* RenderFrameImpl::CreatePepperFullscreenContainer( | 
|  | PepperPluginInstanceImpl* plugin) { | 
|  | // Get the URL of the main frame if possible. | 
|  | blink::WebURL main_frame_url; | 
|  | WebFrame* main_frame = render_view()->webview()->MainFrame(); | 
|  | if (main_frame->IsWebLocalFrame()) | 
|  | main_frame_url = main_frame->ToWebLocalFrame()->GetDocument().Url(); | 
|  |  | 
|  | mojom::WidgetPtr widget_channel; | 
|  | mojom::WidgetRequest widget_channel_request = | 
|  | mojo::MakeRequest(&widget_channel); | 
|  |  | 
|  | // Synchronous IPC to obtain a routing id for the fullscreen widget. | 
|  | int32_t fullscreen_widget_routing_id = MSG_ROUTING_NONE; | 
|  | if (!RenderThreadImpl::current_render_message_filter() | 
|  | ->CreateFullscreenWidget(render_view()->GetRoutingID(), | 
|  | std::move(widget_channel), | 
|  | &fullscreen_widget_routing_id)) { | 
|  | return nullptr; | 
|  | } | 
|  | RenderWidget::ShowCallback show_callback = | 
|  | base::BindOnce(&RenderViewImpl::ShowCreatedFullscreenWidget, | 
|  | render_view()->GetWeakPtr()); | 
|  |  | 
|  | // TODO(fsamuel): It's not clear if we should be passing in the | 
|  | // web ScreenInfo or the original ScreenInfo here. | 
|  | RenderWidgetFullscreenPepper* widget = RenderWidgetFullscreenPepper::Create( | 
|  | fullscreen_widget_routing_id, std::move(show_callback), | 
|  | GetLocalRootRenderWidget()->compositor_deps(), plugin, | 
|  | std::move(main_frame_url), GetLocalRootRenderWidget()->GetWebScreenInfo(), | 
|  | std::move(widget_channel_request)); | 
|  | // TODO(nick): The show() handshake seems like unnecessary complexity here, | 
|  | // since there's no real delay between CreateFullscreenWidget and | 
|  | // ShowCreatedFullscreenWidget. Would it be simpler to have the | 
|  | // CreateFullscreenWidget mojo method implicitly show the window, and skip the | 
|  | // subsequent step? | 
|  | widget->Show(blink::kWebNavigationPolicyCurrentTab); | 
|  | return widget; | 
|  | } | 
|  |  | 
|  | bool RenderFrameImpl::IsPepperAcceptingCompositionEvents() const { | 
|  | if (!focused_pepper_plugin_) | 
|  | return false; | 
|  | return focused_pepper_plugin_->IsPluginAcceptingCompositionEvents(); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::PluginCrashed(const base::FilePath& plugin_path, | 
|  | base::ProcessId plugin_pid) { | 
|  | // TODO(jam): dispatch this IPC in RenderFrameHost and switch to use | 
|  | // routing_id_ as a result. | 
|  | Send(new FrameHostMsg_PluginCrashed(routing_id_, plugin_path, plugin_pid)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::SimulateImeSetComposition( | 
|  | const base::string16& text, | 
|  | const std::vector<blink::WebImeTextSpan>& ime_text_spans, | 
|  | int selection_start, | 
|  | int selection_end) { | 
|  | GetMainFrameRenderWidget()->OnImeSetComposition( | 
|  | text, ime_text_spans, gfx::Range::InvalidRange(), selection_start, | 
|  | selection_end); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::SimulateImeCommitText( | 
|  | const base::string16& text, | 
|  | const std::vector<blink::WebImeTextSpan>& ime_text_spans, | 
|  | const gfx::Range& replacement_range) { | 
|  | GetMainFrameRenderWidget()->OnImeCommitText(text, ime_text_spans, | 
|  | replacement_range, 0); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::SimulateImeFinishComposingText(bool keep_selection) { | 
|  | GetMainFrameRenderWidget()->OnImeFinishComposingText(keep_selection); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::OnImeSetComposition( | 
|  | const base::string16& text, | 
|  | const std::vector<blink::WebImeTextSpan>& ime_text_spans, | 
|  | int selection_start, | 
|  | int selection_end) { | 
|  | // When a PPAPI plugin has focus, we bypass WebKit. | 
|  | if (!IsPepperAcceptingCompositionEvents()) { | 
|  | pepper_composition_text_ = text; | 
|  | } else { | 
|  | // TODO(kinaba) currently all composition events are sent directly to | 
|  | // plugins. Use DOM event mechanism after WebKit is made aware about | 
|  | // plugins that support composition. | 
|  | // The code below mimics the behavior of WebCore::Editor::setComposition. | 
|  |  | 
|  | // Empty -> nonempty: composition started. | 
|  | if (pepper_composition_text_.empty() && !text.empty()) { | 
|  | focused_pepper_plugin_->HandleCompositionStart(base::string16()); | 
|  | } | 
|  | // Nonempty -> empty: composition canceled. | 
|  | if (!pepper_composition_text_.empty() && text.empty()) { | 
|  | focused_pepper_plugin_->HandleCompositionEnd(base::string16()); | 
|  | } | 
|  | pepper_composition_text_ = text; | 
|  | // Nonempty: composition is ongoing. | 
|  | if (!pepper_composition_text_.empty()) { | 
|  | focused_pepper_plugin_->HandleCompositionUpdate( | 
|  | pepper_composition_text_, ime_text_spans, selection_start, | 
|  | selection_end); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::OnImeCommitText(const base::string16& text, | 
|  | const gfx::Range& replacement_range, | 
|  | int relative_cursor_pos) { | 
|  | HandlePepperImeCommit(text); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::OnImeFinishComposingText(bool keep_selection) { | 
|  | const base::string16& text = pepper_composition_text_; | 
|  | HandlePepperImeCommit(text); | 
|  | } | 
|  | #endif  // BUILDFLAG(ENABLE_PLUGINS) | 
|  |  | 
|  | MediaStreamDeviceObserver* RenderFrameImpl::GetMediaStreamDeviceObserver() { | 
|  | if (!web_user_media_client_) | 
|  | InitializeUserMediaClient(); | 
|  | return web_user_media_client_ | 
|  | ? web_user_media_client_->media_stream_device_observer() | 
|  | : nullptr; | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::ScriptedPrint(bool user_initiated) { | 
|  | for (auto& observer : observers_) | 
|  | observer.ScriptedPrint(user_initiated); | 
|  | } | 
|  |  | 
|  | bool RenderFrameImpl::Send(IPC::Message* message) { | 
|  | return RenderThread::Get()->Send(message); | 
|  | } | 
|  |  | 
|  | #if BUILDFLAG(USE_EXTERNAL_POPUP_MENU) | 
|  | void RenderFrameImpl::DidHideExternalPopupMenu() { | 
|  | // We need to clear external_popup_menu_ as soon as ExternalPopupMenu::close | 
|  | // is called. Otherwise, createExternalPopupMenu() for new popup will fail. | 
|  | external_popup_menu_.reset(); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | bool RenderFrameImpl::OnMessageReceived(const IPC::Message& msg) { | 
|  | // Forward Page IPCs to the RenderView. | 
|  | if ((IPC_MESSAGE_CLASS(msg) == PageMsgStart)) { | 
|  | if (render_view()) | 
|  | return render_view()->OnMessageReceived(msg); | 
|  |  | 
|  | return false; | 
|  | } | 
|  |  | 
|  | // We may get here while detaching, when the WebFrame has been deleted.  Do | 
|  | // not process any messages in this state. | 
|  | if (!frame_) | 
|  | return false; | 
|  |  | 
|  | DCHECK(!frame_->GetDocument().IsNull()); | 
|  |  | 
|  | GetContentClient()->SetActiveURL( | 
|  | frame_->GetDocument().Url(), | 
|  | frame_->Top()->GetSecurityOrigin().ToString().Utf8()); | 
|  |  | 
|  | for (auto& observer : observers_) { | 
|  | if (observer.OnMessageReceived(msg)) | 
|  | return true; | 
|  | } | 
|  |  | 
|  | bool handled = true; | 
|  | IPC_BEGIN_MESSAGE_MAP(RenderFrameImpl, msg) | 
|  | IPC_MESSAGE_HANDLER(FrameMsg_BeforeUnload, OnBeforeUnload) | 
|  | IPC_MESSAGE_HANDLER(FrameMsg_SwapOut, OnSwapOut) | 
|  | IPC_MESSAGE_HANDLER(FrameMsg_SwapIn, OnSwapIn) | 
|  | IPC_MESSAGE_HANDLER(FrameMsg_Delete, OnDeleteFrame) | 
|  | IPC_MESSAGE_HANDLER(FrameMsg_Stop, OnStop) | 
|  | IPC_MESSAGE_HANDLER(FrameMsg_DroppedNavigation, OnDroppedNavigation) | 
|  | IPC_MESSAGE_HANDLER(FrameMsg_Collapse, OnCollapse) | 
|  | IPC_MESSAGE_HANDLER(FrameMsg_ContextMenuClosed, OnContextMenuClosed) | 
|  | IPC_MESSAGE_HANDLER(FrameMsg_CustomContextMenuAction, | 
|  | OnCustomContextMenuAction) | 
|  | #if BUILDFLAG(ENABLE_PLUGINS) | 
|  | IPC_MESSAGE_HANDLER(FrameMsg_SetPepperVolume, OnSetPepperVolume) | 
|  | #endif | 
|  | IPC_MESSAGE_HANDLER(FrameMsg_CopyImageAt, OnCopyImageAt) | 
|  | IPC_MESSAGE_HANDLER(FrameMsg_SaveImageAt, OnSaveImageAt) | 
|  | IPC_MESSAGE_HANDLER(FrameMsg_AddMessageToConsole, OnAddMessageToConsole) | 
|  | IPC_MESSAGE_HANDLER(FrameMsg_VisualStateRequest, | 
|  | OnVisualStateRequest) | 
|  | IPC_MESSAGE_HANDLER(FrameMsg_Reload, OnReload) | 
|  | IPC_MESSAGE_HANDLER(FrameMsg_ReloadLoFiImages, OnReloadLoFiImages) | 
|  | IPC_MESSAGE_HANDLER(FrameMsg_TextSurroundingSelectionRequest, | 
|  | OnTextSurroundingSelectionRequest) | 
|  | IPC_MESSAGE_HANDLER(FrameMsg_SetAccessibilityMode, | 
|  | OnSetAccessibilityMode) | 
|  | IPC_MESSAGE_HANDLER(AccessibilityMsg_SnapshotTree, | 
|  | OnSnapshotAccessibilityTree) | 
|  | IPC_MESSAGE_HANDLER(FrameMsg_UpdateOpener, OnUpdateOpener) | 
|  | IPC_MESSAGE_HANDLER(FrameMsg_DidUpdateFramePolicy, OnDidUpdateFramePolicy) | 
|  | IPC_MESSAGE_HANDLER(FrameMsg_SetFrameOwnerProperties, | 
|  | OnSetFrameOwnerProperties) | 
|  | IPC_MESSAGE_HANDLER(FrameMsg_AdvanceFocus, OnAdvanceFocus) | 
|  | IPC_MESSAGE_HANDLER(FrameMsg_AdvanceFocusInForm, OnAdvanceFocusInForm) | 
|  | IPC_MESSAGE_HANDLER(FrameMsg_SetFocusedFrame, OnSetFocusedFrame) | 
|  | IPC_MESSAGE_HANDLER(FrameMsg_SetTextTrackSettings, | 
|  | OnTextTrackSettingsChanged) | 
|  | IPC_MESSAGE_HANDLER(FrameMsg_CheckCompleted, OnCheckCompleted) | 
|  | IPC_MESSAGE_HANDLER(FrameMsg_ReportContentSecurityPolicyViolation, | 
|  | OnReportContentSecurityPolicyViolation) | 
|  | IPC_MESSAGE_HANDLER(FrameMsg_GetSavableResourceLinks, | 
|  | OnGetSavableResourceLinks) | 
|  | IPC_MESSAGE_HANDLER(FrameMsg_GetSerializedHtmlWithLocalLinks, | 
|  | OnGetSerializedHtmlWithLocalLinks) | 
|  | IPC_MESSAGE_HANDLER(FrameMsg_EnableViewSourceMode, OnEnableViewSourceMode) | 
|  | IPC_MESSAGE_HANDLER(FrameMsg_SuppressFurtherDialogs, | 
|  | OnSuppressFurtherDialogs) | 
|  | IPC_MESSAGE_HANDLER(FrameMsg_ClearFocusedElement, OnClearFocusedElement) | 
|  | IPC_MESSAGE_HANDLER(FrameMsg_BlinkFeatureUsageReport, | 
|  | OnBlinkFeatureUsageReport) | 
|  | IPC_MESSAGE_HANDLER(FrameMsg_MixedContentFound, OnMixedContentFound) | 
|  | IPC_MESSAGE_HANDLER(FrameMsg_SetOverlayRoutingToken, | 
|  | OnSetOverlayRoutingToken) | 
|  | IPC_MESSAGE_HANDLER(FrameMsg_NotifyUserActivation, OnNotifyUserActivation) | 
|  | IPC_MESSAGE_HANDLER(FrameMsg_MediaPlayerActionAt, OnMediaPlayerActionAt) | 
|  | IPC_MESSAGE_HANDLER(FrameMsg_RenderFallbackContent, OnRenderFallbackContent) | 
|  | #if BUILDFLAG(USE_EXTERNAL_POPUP_MENU) | 
|  | #if defined(OS_MACOSX) | 
|  | IPC_MESSAGE_HANDLER(FrameMsg_SelectPopupMenuItem, OnSelectPopupMenuItem) | 
|  | #else | 
|  | IPC_MESSAGE_HANDLER(FrameMsg_SelectPopupMenuItems, OnSelectPopupMenuItems) | 
|  | #endif | 
|  | #endif | 
|  |  | 
|  | IPC_END_MESSAGE_MAP() | 
|  |  | 
|  | return handled; | 
|  | } | 
|  |  | 
|  | 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::BindFullscreen( | 
|  | mojom::FullscreenVideoElementHandlerAssociatedRequest request) { | 
|  | fullscreen_binding_.Bind(std::move(request), | 
|  | GetTaskRunner(blink::TaskType::kInternalIPC)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::BindAutoplayConfiguration( | 
|  | blink::mojom::AutoplayConfigurationClientAssociatedRequest request) { | 
|  | autoplay_configuration_binding_.Bind( | 
|  | std::move(request), GetTaskRunner(blink::TaskType::kInternalIPC)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::BindFrame( | 
|  | const service_manager::BindSourceInfo& browser_info, | 
|  | mojom::FrameRequest request) { | 
|  | browser_info_ = browser_info; | 
|  | frame_binding_.Bind(std::move(request), | 
|  | GetTaskRunner(blink::TaskType::kInternalIPC)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::BindFrameBindingsControl( | 
|  | mojom::FrameBindingsControlAssociatedRequest request) { | 
|  | frame_bindings_control_binding_.Bind( | 
|  | std::move(request), GetTaskRunner(blink::TaskType::kInternalIPC)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::BindFrameNavigationControl( | 
|  | mojom::FrameNavigationControlAssociatedRequest request) { | 
|  | frame_navigation_control_binding_.Bind( | 
|  | std::move(request), GetTaskRunner(blink::TaskType::kInternalIPC)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::BindNavigationClient( | 
|  | mojom::NavigationClientAssociatedRequest request) { | 
|  | navigation_client_impl_ = std::make_unique<NavigationClient>(this); | 
|  | navigation_client_impl_->Bind(std::move(request)); | 
|  | } | 
|  |  | 
|  | blink::mojom::ManifestManager& RenderFrameImpl::GetManifestManager() { | 
|  | return *manifest_manager_; | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::OnBeforeUnload(bool is_reload) { | 
|  | TRACE_EVENT1("navigation,rail", "RenderFrameImpl::OnBeforeUnload", | 
|  | "id", routing_id_); | 
|  | // Save the routing_id, as the RenderFrameImpl can be deleted in | 
|  | // dispatchBeforeUnloadEvent. See https://crbug.com/666714 for details. | 
|  | int routing_id = routing_id_; | 
|  |  | 
|  | base::TimeTicks before_unload_start_time = base::TimeTicks::Now(); | 
|  |  | 
|  | // This will execute the BeforeUnload event in this frame and all of its | 
|  | // local descendant frames, including children of remote frames.  The browser | 
|  | // process will send separate IPCs to dispatch beforeunload in any | 
|  | // out-of-process child frames. | 
|  | bool proceed = frame_->DispatchBeforeUnloadEvent(is_reload); | 
|  |  | 
|  | base::TimeTicks before_unload_end_time = base::TimeTicks::Now(); | 
|  | RenderThread::Get()->Send(new FrameHostMsg_BeforeUnload_ACK( | 
|  | routing_id, proceed, before_unload_start_time, before_unload_end_time)); | 
|  | } | 
|  |  | 
|  | // Swap this RenderFrame out so the frame can navigate to a document rendered by | 
|  | // a different process. We also allow this process to exit if there are no other | 
|  | // active RenderFrames in it. | 
|  | // This executes the unload handlers on this frame and its local descendants. | 
|  | void RenderFrameImpl::OnSwapOut( | 
|  | int proxy_routing_id, | 
|  | bool is_loading, | 
|  | const FrameReplicationState& replicated_frame_state) { | 
|  | TRACE_EVENT1("navigation,rail", "RenderFrameImpl::OnSwapOut", | 
|  | "id", routing_id_); | 
|  |  | 
|  | // Send an UpdateState message before we get deleted. | 
|  | SendUpdateState(); | 
|  |  | 
|  | // There should always be a proxy to replace this RenderFrame. Create it now | 
|  | // so its routing id is registered for receiving IPC messages. | 
|  | CHECK_NE(proxy_routing_id, MSG_ROUTING_NONE); | 
|  | RenderFrameProxy* proxy = RenderFrameProxy::CreateProxyToReplaceFrame( | 
|  | this, proxy_routing_id, replicated_frame_state.scope); | 
|  |  | 
|  | // Swap out and stop sending any IPC messages that are not ACKs. | 
|  | if (is_main_frame_) { | 
|  | // The RenderWidget isn't actually closed here because we might need to use | 
|  | // it again. It can't be destroyed and recreated later as it is part of | 
|  | // the |render_view_|, which must be kept alive. So instead freeze the | 
|  | // widget. | 
|  | render_view_->GetWidget()->SetIsFrozen(true); | 
|  | } | 
|  |  | 
|  | RenderViewImpl* render_view = render_view_; | 
|  | bool is_main_frame = is_main_frame_; | 
|  | int routing_id = GetRoutingID(); | 
|  |  | 
|  | // Before |this| is destroyed, grab the TaskRunner to be used for sending the | 
|  | // SwapOut ACK.  This will be used to schedule SwapOut ACK to be sent after | 
|  | // any postMessage IPCs scheduled from the unload event above. | 
|  | scoped_refptr<base::SingleThreadTaskRunner> task_runner = | 
|  | GetTaskRunner(blink::TaskType::kPostedMessage); | 
|  |  | 
|  | // Now that all of the cleanup is complete and the browser side is notified, | 
|  | // start using the RenderFrameProxy. | 
|  | // | 
|  | // The swap call deletes this RenderFrame via FrameDetached.  Do not access | 
|  | // any members after this call. | 
|  | // | 
|  | // TODO(creis): WebFrame::swap() can return false.  Most of those cases | 
|  | // should be due to the frame being detached during unload (in which case | 
|  | // the necessary cleanup has happened anyway), but it might be possible for | 
|  | // it to return false without detaching.  Catch any cases that the | 
|  | // RenderView's main_render_frame_ isn't cleared below (whether swap returns | 
|  | // false or not). | 
|  | // | 
|  | // This executes the unload handlers on this frame and its local descendants. | 
|  | bool success = frame_->Swap(proxy->web_frame()); | 
|  |  | 
|  | if (is_main_frame) { | 
|  | // Main frames should always swap successfully because there is no parent | 
|  | // frame to cause them to become detached. | 
|  | DCHECK(success); | 
|  | // For main frames, the swap should have cleared the RenderView's pointer to | 
|  | // this frame. | 
|  | CHECK(!render_view->main_render_frame_); | 
|  | } | 
|  |  | 
|  | if (!success) { | 
|  | // The swap can fail when the frame is detached during swap (this can | 
|  | // happen while running the unload handlers). When that happens, delete | 
|  | // the proxy. | 
|  | proxy->FrameDetached(blink::WebRemoteFrameClient::DetachType::kSwap); | 
|  | return; | 
|  | } | 
|  |  | 
|  | if (is_loading) | 
|  | proxy->OnDidStartLoading(); | 
|  |  | 
|  | // Initialize the WebRemoteFrame with the replication state passed by the | 
|  | // process that is now rendering the frame. | 
|  | proxy->SetReplicatedState(replicated_frame_state); | 
|  |  | 
|  | // Notify the browser that this frame was swapped. Use the RenderThread | 
|  | // directly because |this| is deleted.  Post a task to send the ACK, so that | 
|  | // any postMessage IPCs scheduled from the unload handler are sent before | 
|  | // the ACK (see https://crbug.com/857274). | 
|  | auto send_swapout_ack = base::BindOnce( | 
|  | [](int routing_id, bool is_main_frame) { | 
|  | RenderThread::Get()->Send(new FrameHostMsg_SwapOut_ACK(routing_id)); | 
|  | }, | 
|  | routing_id, is_main_frame); | 
|  | task_runner->PostTask(FROM_HERE, std::move(send_swapout_ack)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::OnSwapIn() { | 
|  | SwapIn(); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::OnDeleteFrame() { | 
|  | // This will result in a call to RenderFrameImpl::FrameDetached, which | 
|  | // deletes the object. Do not access |this| after detach. | 
|  | frame_->Detach(); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::OnContextMenuClosed( | 
|  | const CustomContextMenuContext& custom_context) { | 
|  | if (custom_context.request_id) { | 
|  | // External request, should be in our map. | 
|  | ContextMenuClient* client = | 
|  | pending_context_menus_.Lookup(custom_context.request_id); | 
|  | if (client) { | 
|  | client->OnMenuClosed(custom_context.request_id); | 
|  | pending_context_menus_.Remove(custom_context.request_id); | 
|  | } | 
|  | } else { | 
|  | if (custom_context.link_followed.is_valid()) | 
|  | frame_->SendPings(custom_context.link_followed); | 
|  | } | 
|  |  | 
|  | render_view()->webview()->DidCloseContextMenu(); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::OnCustomContextMenuAction( | 
|  | const CustomContextMenuContext& custom_context, | 
|  | unsigned action) { | 
|  | if (custom_context.request_id) { | 
|  | // External context menu request, look in our map. | 
|  | ContextMenuClient* client = | 
|  | pending_context_menus_.Lookup(custom_context.request_id); | 
|  | if (client) | 
|  | client->OnMenuAction(custom_context.request_id, action); | 
|  | } else { | 
|  | // Internal request, forward to WebKit. | 
|  | render_view_->webview()->PerformCustomContextMenuAction(action); | 
|  | } | 
|  | } | 
|  |  | 
|  | #if defined(OS_MACOSX) | 
|  | void RenderFrameImpl::OnCopyToFindPboard() { | 
|  | // Since the find pasteboard supports only plain text, this can be simpler | 
|  | // than the |OnCopy()| case. | 
|  | if (frame_->HasSelection()) { | 
|  | if (!clipboard_host_) { | 
|  | auto* platform = RenderThreadImpl::current_blink_platform_impl(); | 
|  | platform->GetConnector()->BindInterface(platform->GetBrowserServiceName(), | 
|  | &clipboard_host_); | 
|  | clipboard_host_.set_connection_error_handler(base::BindOnce( | 
|  | &RenderFrameImpl::OnClipboardHostError, base::Unretained(this))); | 
|  | } | 
|  | base::string16 selection = frame_->SelectionAsText().Utf16(); | 
|  | clipboard_host_->WriteStringToFindPboard(selection); | 
|  | } | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::OnClipboardHostError() { | 
|  | clipboard_host_.reset(); | 
|  | } | 
|  | #endif | 
|  |  | 
|  | void RenderFrameImpl::OnCopyImageAt(int x, int y) { | 
|  | blink::WebFloatRect viewport_position(x, y, 0, 0); | 
|  | GetLocalRootRenderWidget()->ConvertWindowToViewport(&viewport_position); | 
|  | frame_->CopyImageAt(WebPoint(viewport_position.x, viewport_position.y)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::OnSaveImageAt(int x, int y) { | 
|  | blink::WebFloatRect viewport_position(x, y, 0, 0); | 
|  | GetLocalRootRenderWidget()->ConvertWindowToViewport(&viewport_position); | 
|  | frame_->SaveImageAt(WebPoint(viewport_position.x, viewport_position.y)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::OnAddMessageToConsole( | 
|  | blink::mojom::ConsoleMessageLevel level, | 
|  | const std::string& message) { | 
|  | AddMessageToConsole(level, message); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::JavaScriptExecuteRequest( | 
|  | const base::string16& javascript, | 
|  | JavaScriptExecuteRequestCallback callback) { | 
|  | TRACE_EVENT_INSTANT0("test_tracing", "JavaScriptExecuteRequest", | 
|  | TRACE_EVENT_SCOPE_THREAD); | 
|  |  | 
|  | // Note that ExecuteScriptAndReturnValue may end up killing this object. | 
|  | base::WeakPtr<RenderFrameImpl> weak_this = weak_factory_.GetWeakPtr(); | 
|  |  | 
|  | v8::HandleScope handle_scope(v8::Isolate::GetCurrent()); | 
|  | v8::Local<v8::Value> result = frame_->ExecuteScriptAndReturnValue( | 
|  | WebScriptSource(WebString::FromUTF16(javascript))); | 
|  |  | 
|  | if (!weak_this) | 
|  | return; | 
|  |  | 
|  | std::move(callback).Run(GetJavaScriptExecutionResult(result)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::JavaScriptExecuteRequestForTests( | 
|  | const base::string16& javascript, | 
|  | bool has_user_gesture, | 
|  | JavaScriptExecuteRequestForTestsCallback callback) { | 
|  | TRACE_EVENT_INSTANT0("test_tracing", "JavaScriptExecuteRequestForTests", | 
|  | TRACE_EVENT_SCOPE_THREAD); | 
|  |  | 
|  | // Note that ExecuteScriptAndReturnValue may end up killing this object. | 
|  | base::WeakPtr<RenderFrameImpl> weak_this = weak_factory_.GetWeakPtr(); | 
|  |  | 
|  | // A bunch of tests expect to run code in the context of a user gesture, which | 
|  | // can grant additional privileges (e.g. the ability to create popups). | 
|  | base::Optional<blink::WebScopedUserGesture> gesture; | 
|  | if (has_user_gesture) | 
|  | gesture.emplace(frame_); | 
|  |  | 
|  | v8::HandleScope handle_scope(blink::MainThreadIsolate()); | 
|  | v8::Local<v8::Value> result = frame_->ExecuteScriptAndReturnValue( | 
|  | WebScriptSource(WebString::FromUTF16(javascript))); | 
|  |  | 
|  | if (!weak_this) | 
|  | return; | 
|  |  | 
|  | std::move(callback).Run(GetJavaScriptExecutionResult(result)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::JavaScriptExecuteRequestInIsolatedWorld( | 
|  | const base::string16& javascript, | 
|  | int32_t world_id, | 
|  | JavaScriptExecuteRequestInIsolatedWorldCallback callback) { | 
|  | TRACE_EVENT_INSTANT0("test_tracing", | 
|  | "JavaScriptExecuteRequestInIsolatedWorld", | 
|  | TRACE_EVENT_SCOPE_THREAD); | 
|  |  | 
|  | if (world_id <= ISOLATED_WORLD_ID_GLOBAL || | 
|  | world_id > ISOLATED_WORLD_ID_MAX) { | 
|  | // Return if the world_id is not valid. world_id is passed as a plain int | 
|  | // over IPC and needs to be verified here, in the IPC endpoint. | 
|  | NOTREACHED(); | 
|  | std::move(callback).Run(base::Value()); | 
|  | return; | 
|  | } | 
|  |  | 
|  | v8::HandleScope handle_scope(v8::Isolate::GetCurrent()); | 
|  | WebScriptSource script = WebScriptSource(WebString::FromUTF16(javascript)); | 
|  | JavaScriptIsolatedWorldRequest* request = new JavaScriptIsolatedWorldRequest( | 
|  | weak_factory_.GetWeakPtr(), std::move(callback)); | 
|  | frame_->RequestExecuteScriptInIsolatedWorld( | 
|  | world_id, &script, 1, false, WebLocalFrame::kSynchronous, request); | 
|  | } | 
|  |  | 
|  | RenderFrameImpl::JavaScriptIsolatedWorldRequest::JavaScriptIsolatedWorldRequest( | 
|  | base::WeakPtr<RenderFrameImpl> render_frame_impl, | 
|  | JavaScriptExecuteRequestInIsolatedWorldCallback callback) | 
|  | : render_frame_impl_(render_frame_impl), callback_(std::move(callback)) {} | 
|  |  | 
|  | RenderFrameImpl::JavaScriptIsolatedWorldRequest:: | 
|  | ~JavaScriptIsolatedWorldRequest() { | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::JavaScriptIsolatedWorldRequest::Completed( | 
|  | const blink::WebVector<v8::Local<v8::Value>>& result) { | 
|  | if (!render_frame_impl_) { | 
|  | // If the frame is gone, there's nothing that can be safely done; bail. | 
|  | delete this; | 
|  | return; | 
|  | } | 
|  |  | 
|  | base::Value value; | 
|  | if (!result.empty()) { | 
|  | // It's safe to always use the main world context when converting | 
|  | // here. V8ValueConverterImpl shouldn't actually care about the | 
|  | // context scope, and it switches to v8::Object's creation context | 
|  | // when encountered. (from extensions/renderer/script_injection.cc) | 
|  | v8::Local<v8::Context> context = | 
|  | render_frame_impl_.get()->frame_->MainWorldScriptContext(); | 
|  | v8::Context::Scope context_scope(context); | 
|  | V8ValueConverterImpl converter; | 
|  | converter.SetDateAllowed(true); | 
|  | converter.SetRegExpAllowed(true); | 
|  | std::unique_ptr<base::Value> new_value = | 
|  | converter.FromV8Value(*result.begin(), context); | 
|  | if (new_value) | 
|  | value = base::Value::FromUniquePtrValue(std::move(new_value)); | 
|  | } | 
|  |  | 
|  | std::move(callback_).Run(std::move(value)); | 
|  |  | 
|  | delete this; | 
|  | } | 
|  |  | 
|  | base::Value RenderFrameImpl::GetJavaScriptExecutionResult( | 
|  | v8::Local<v8::Value> result) { | 
|  | if (!result.IsEmpty()) { | 
|  | v8::Local<v8::Context> context = frame_->MainWorldScriptContext(); | 
|  | v8::Context::Scope context_scope(context); | 
|  | V8ValueConverterImpl converter; | 
|  | converter.SetDateAllowed(true); | 
|  | converter.SetRegExpAllowed(true); | 
|  | std::unique_ptr<base::Value> new_value = | 
|  | converter.FromV8Value(result, context); | 
|  | if (new_value) | 
|  | return std::move(*new_value); | 
|  | } | 
|  | return base::Value(); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::OnVisualStateRequest(uint64_t id) { | 
|  | GetLocalRootRenderWidget()->QueueMessage( | 
|  | new FrameHostMsg_VisualStateResponse(routing_id_, id)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::OnSetAccessibilityMode(ui::AXMode new_mode) { | 
|  | if (accessibility_mode_ == new_mode) | 
|  | return; | 
|  | ui::AXMode old_mode = accessibility_mode_; | 
|  | accessibility_mode_ = new_mode; | 
|  |  | 
|  | if (new_mode.has_mode(ui::AXMode::kWebContents) && | 
|  | !old_mode.has_mode(ui::AXMode::kWebContents)) { | 
|  | render_accessibility_ = new RenderAccessibilityImpl(this, new_mode); | 
|  | } else if (!new_mode.has_mode(ui::AXMode::kWebContents) && | 
|  | old_mode.has_mode(ui::AXMode::kWebContents)) { | 
|  | delete render_accessibility_; | 
|  | render_accessibility_ = nullptr; | 
|  | } | 
|  |  | 
|  | for (auto& observer : observers_) | 
|  | observer.AccessibilityModeChanged(); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::OnSnapshotAccessibilityTree(int callback_id, | 
|  | ui::AXMode ax_mode) { | 
|  | AXContentTreeUpdate response; | 
|  | RenderAccessibilityImpl::SnapshotAccessibilityTree(this, &response, ax_mode); | 
|  | Send(new AccessibilityHostMsg_SnapshotResponse( | 
|  | routing_id_, callback_id, response)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::OnPortalActivated( | 
|  | const base::UnguessableToken& portal_token, | 
|  | blink::mojom::PortalAssociatedPtrInfo portal, | 
|  | blink::TransferableMessage data, | 
|  | OnPortalActivatedCallback callback) { | 
|  | frame_->OnPortalActivated(portal_token, portal.PassHandle(), std::move(data), | 
|  | std::move(callback)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::ForwardMessageToPortalHost( | 
|  | blink::TransferableMessage message, | 
|  | const url::Origin& source_origin, | 
|  | const base::Optional<url::Origin>& target_origin) { | 
|  | frame_->ForwardMessageToPortalHost(std::move(message), source_origin, | 
|  | target_origin); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::SetLifecycleState( | 
|  | blink::mojom::FrameLifecycleState state) { | 
|  | frame_->SetLifecycleState(state); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::VisibilityChanged( | 
|  | blink::mojom::FrameVisibility visibility) { | 
|  | GetFrameHost()->VisibilityChanged(visibility); | 
|  | } | 
|  |  | 
|  | #if defined(OS_ANDROID) | 
|  | void RenderFrameImpl::ExtractSmartClipData( | 
|  | const gfx::Rect& rect, | 
|  | ExtractSmartClipDataCallback callback) { | 
|  | blink::WebString clip_text; | 
|  | blink::WebString clip_html; | 
|  | blink::WebRect clip_rect; | 
|  | GetWebFrame()->ExtractSmartClipData(rect, clip_text, clip_html, clip_rect); | 
|  | std::move(callback).Run(clip_text.Utf16(), clip_html.Utf16(), clip_rect); | 
|  | } | 
|  | #endif  // defined(OS_ANDROID) | 
|  |  | 
|  | void RenderFrameImpl::OnUpdateOpener(int opener_routing_id) { | 
|  | WebFrame* opener = ResolveOpener(opener_routing_id); | 
|  | frame_->SetOpener(opener); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::OnDidUpdateFramePolicy( | 
|  | const blink::FramePolicy& frame_policy) { | 
|  | frame_->SetFrameOwnerPolicy(frame_policy); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::OnSetFrameOwnerProperties( | 
|  | const FrameOwnerProperties& frame_owner_properties) { | 
|  | DCHECK(frame_); | 
|  | frame_->SetFrameOwnerProperties( | 
|  | ConvertFrameOwnerPropertiesToWebFrameOwnerProperties( | 
|  | frame_owner_properties)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::OnAdvanceFocus(blink::WebFocusType type, | 
|  | int32_t source_routing_id) { | 
|  | RenderFrameProxy* source_frame = | 
|  | RenderFrameProxy::FromRoutingID(source_routing_id); | 
|  | if (!source_frame) { | 
|  | render_view_->webview()->SetInitialFocus(type == | 
|  | blink::kWebFocusTypeBackward); | 
|  | return; | 
|  | } | 
|  |  | 
|  | render_view_->webview()->AdvanceFocusAcrossFrames( | 
|  | type, source_frame->web_frame(), frame_); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::OnAdvanceFocusInForm(blink::WebFocusType focus_type) { | 
|  | if (render_view_->webview()->FocusedFrame() != frame_) | 
|  | return; | 
|  | frame_->AdvanceFocusInForm(focus_type); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::OnSetFocusedFrame() { | 
|  | // This uses focusDocumentView rather than setFocusedFrame so that focus/blur | 
|  | // events are properly dispatched on any currently focused elements. | 
|  | render_view_->webview()->FocusDocumentView(frame_); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::OnTextTrackSettingsChanged( | 
|  | const FrameMsg_TextTrackSettings_Params& params) { | 
|  | DCHECK(!frame_->Parent()); | 
|  | if (!render_view_->webview()) | 
|  | return; | 
|  |  | 
|  | if (params.text_tracks_enabled) { | 
|  | render_view_->webview()->GetSettings()->SetTextTrackKindUserPreference( | 
|  | WebSettings::TextTrackKindUserPreference::kCaptions); | 
|  | } else { | 
|  | render_view_->webview()->GetSettings()->SetTextTrackKindUserPreference( | 
|  | WebSettings::TextTrackKindUserPreference::kDefault); | 
|  | } | 
|  | render_view_->webview()->GetSettings()->SetTextTrackBackgroundColor( | 
|  | WebString::FromUTF8(params.text_track_background_color)); | 
|  | render_view_->webview()->GetSettings()->SetTextTrackFontFamily( | 
|  | WebString::FromUTF8(params.text_track_font_family)); | 
|  | render_view_->webview()->GetSettings()->SetTextTrackFontStyle( | 
|  | WebString::FromUTF8(params.text_track_font_style)); | 
|  | render_view_->webview()->GetSettings()->SetTextTrackFontVariant( | 
|  | WebString::FromUTF8(params.text_track_font_variant)); | 
|  | render_view_->webview()->GetSettings()->SetTextTrackTextColor( | 
|  | WebString::FromUTF8(params.text_track_text_color)); | 
|  | render_view_->webview()->GetSettings()->SetTextTrackTextShadow( | 
|  | WebString::FromUTF8(params.text_track_text_shadow)); | 
|  | render_view_->webview()->GetSettings()->SetTextTrackTextSize( | 
|  | WebString::FromUTF8(params.text_track_text_size)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::OnCheckCompleted() { | 
|  | frame_->CheckCompleted(); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::PostMessageEvent(int32_t source_routing_id, | 
|  | const base::string16& source_origin, | 
|  | const base::string16& target_origin, | 
|  | blink::TransferableMessage message) { | 
|  | // Make sure that |message| owns its data so that the data is alive even after | 
|  | // moved. | 
|  | message.EnsureDataIsOwned(); | 
|  |  | 
|  | // Find the source frame if it exists. | 
|  | WebFrame* source_frame = nullptr; | 
|  | if (source_routing_id != MSG_ROUTING_NONE) { | 
|  | RenderFrameProxy* source_proxy = | 
|  | RenderFrameProxy::FromRoutingID(source_routing_id); | 
|  | if (source_proxy) | 
|  | source_frame = source_proxy->web_frame(); | 
|  | } | 
|  |  | 
|  | // We must pass in the target_origin to do the security check on this side, | 
|  | // since it may have changed since the original postMessage call was made. | 
|  | WebSecurityOrigin target_security_origin; | 
|  | if (!target_origin.empty()) { | 
|  | target_security_origin = WebSecurityOrigin::CreateFromString( | 
|  | WebString::FromUTF16(target_origin)); | 
|  | } | 
|  |  | 
|  | WebDOMMessageEvent msg_event(std::move(message), | 
|  | WebString::FromUTF16(source_origin), | 
|  | source_frame, frame_->GetDocument()); | 
|  |  | 
|  | frame_->DispatchMessageEventWithOriginCheck(target_security_origin, msg_event, | 
|  | message.has_user_gesture); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::OnReload(bool bypass_cache) { | 
|  | frame_->StartReload(bypass_cache ? WebFrameLoadType::kReloadBypassingCache | 
|  | : WebFrameLoadType::kReload); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::OnReloadLoFiImages() { | 
|  | previews_state_ = PREVIEWS_NO_TRANSFORM; | 
|  | GetWebFrame()->ReloadLoFiImages(); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::OnTextSurroundingSelectionRequest(uint32_t max_length) { | 
|  | blink::WebSurroundingText surrounding_text(frame_, max_length); | 
|  |  | 
|  | if (surrounding_text.IsEmpty()) { | 
|  | // |surrounding_text| might not be correctly initialized, for example if | 
|  | // |frame_->SelectionRange().IsNull()|, in other words, if there was no | 
|  | // selection. | 
|  | Send(new FrameHostMsg_TextSurroundingSelectionResponse( | 
|  | routing_id_, base::string16(), 0, 0)); | 
|  | return; | 
|  | } | 
|  |  | 
|  | Send(new FrameHostMsg_TextSurroundingSelectionResponse( | 
|  | routing_id_, surrounding_text.TextContent().Utf16(), | 
|  | surrounding_text.StartOffsetInTextContent(), | 
|  | surrounding_text.EndOffsetInTextContent())); | 
|  | } | 
|  |  | 
|  | bool RenderFrameImpl::RunJavaScriptDialog(JavaScriptDialogType type, | 
|  | const base::string16& message, | 
|  | const base::string16& default_value, | 
|  | base::string16* result) { | 
|  | // Don't allow further dialogs if we are waiting to swap out, since the | 
|  | // ScopedPageLoadDeferrer in our stack prevents it. | 
|  | if (suppress_further_dialogs_) | 
|  | return false; | 
|  |  | 
|  | int32_t message_length = static_cast<int32_t>(message.length()); | 
|  | if (WebUserGestureIndicator::ProcessedUserGestureSinceLoad(frame_)) { | 
|  | UMA_HISTOGRAM_COUNTS_1M("JSDialogs.CharacterCount.UserGestureSinceLoad", | 
|  | message_length); | 
|  | } else { | 
|  | UMA_HISTOGRAM_COUNTS_1M("JSDialogs.CharacterCount.NoUserGestureSinceLoad", | 
|  | message_length); | 
|  | } | 
|  |  | 
|  | if (is_main_frame_) | 
|  | UMA_HISTOGRAM_COUNTS_1M("JSDialogs.CharacterCount.MainFrame", | 
|  | message_length); | 
|  | else | 
|  | UMA_HISTOGRAM_COUNTS_1M("JSDialogs.CharacterCount.Subframe", | 
|  | message_length); | 
|  |  | 
|  | // 10k ought to be enough for anyone. | 
|  | const base::string16::size_type kMaxMessageSize = 10 * 1024; | 
|  | base::string16 truncated_message = message.substr(0, kMaxMessageSize); | 
|  |  | 
|  | bool success = false; | 
|  | base::string16 result_temp; | 
|  | if (!result) | 
|  | result = &result_temp; | 
|  |  | 
|  | Send(new FrameHostMsg_RunJavaScriptDialog( | 
|  | routing_id_, truncated_message, default_value, type, &success, result)); | 
|  | return success; | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidFailProvisionalLoad( | 
|  | const WebURLError& error, | 
|  | blink::WebHistoryCommitType commit_type) { | 
|  | TRACE_EVENT1("navigation,benchmark,rail", | 
|  | "RenderFrameImpl::didFailProvisionalLoad", "id", routing_id_); | 
|  | // Note: It is important this notification occur before DidStopLoading so the | 
|  | //       SSL manager can react to the provisional load failure before being | 
|  | //       notified the load stopped. | 
|  | // | 
|  | NotifyObserversOfFailedProvisionalLoad(error); | 
|  |  | 
|  | WebDocumentLoader* document_loader = frame_->GetProvisionalDocumentLoader(); | 
|  | if (!document_loader) | 
|  | return; | 
|  |  | 
|  | // Notify the browser that we failed a provisional load with an error. | 
|  | SendFailedProvisionalLoad(document_loader->HttpMethod().Ascii(), error, | 
|  | frame_); | 
|  |  | 
|  | if (!ShouldDisplayErrorPageForFailedLoad(error.reason(), error.url())) | 
|  | return; | 
|  |  | 
|  | // If this is a failed back/forward/reload navigation, then we need to do a | 
|  | // 'replace' load. This is necessary to avoid messing up session history. | 
|  | // Otherwise, we do a normal load, which simulates a 'go' navigation as far | 
|  | // as session history is concerned. | 
|  | bool replace_current_item = commit_type != blink::kWebStandardCommit; | 
|  |  | 
|  | // If we failed on a browser initiated request, then make sure that our error | 
|  | // page load is regarded as the same browser initiated request. | 
|  | bool inherit_document_state = | 
|  | !NavigationState::FromDocumentLoader(document_loader) | 
|  | ->IsContentInitiated(); | 
|  | LoadNavigationErrorPage(document_loader, error, base::nullopt, | 
|  | replace_current_item, inherit_document_state); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::NotifyObserversOfFailedProvisionalLoad( | 
|  | const blink::WebURLError& error) { | 
|  | for (auto& observer : render_view_->observers()) | 
|  | observer.DidFailProvisionalLoad(frame_, error); | 
|  | for (auto& observer : observers_) | 
|  | observer.DidFailProvisionalLoad(error); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::LoadNavigationErrorPage( | 
|  | WebDocumentLoader* document_loader, | 
|  | const WebURLError& error, | 
|  | const base::Optional<std::string>& error_page_content, | 
|  | bool replace_current_item, | 
|  | bool inherit_document_state) { | 
|  | std::string error_html; | 
|  | if (error_page_content) { | 
|  | error_html = error_page_content.value(); | 
|  | } else { | 
|  | GetContentClient()->renderer()->PrepareErrorPage( | 
|  | this, error, document_loader->HttpMethod().Ascii(), | 
|  | false /* ignoring_cache */, &error_html); | 
|  | } | 
|  |  | 
|  | // Make sure we never show errors in view source mode. | 
|  | frame_->EnableViewSourceMode(false); | 
|  |  | 
|  | auto navigation_params = WebNavigationParams::CreateForErrorPage( | 
|  | document_loader, error_html, GURL(kUnreachableWebDataURL), error.url(), | 
|  | error.reason()); | 
|  | std::unique_ptr<DocumentState> document_state; | 
|  |  | 
|  | if (inherit_document_state) { | 
|  | NavigationState* navigation_state = | 
|  | NavigationState::FromDocumentLoader(document_loader); | 
|  | // The error page load (not to confuse with a failed load of original page) | 
|  | // was not initiated through BeginNavigation, therefore | 
|  | // |was_initiated_in_this_frame| is false. | 
|  | document_state = BuildDocumentStateFromParams( | 
|  | navigation_state->common_params(), navigation_state->commit_params(), | 
|  | base::TimeTicks(),  // Not used for failed navigation. | 
|  | mojom::FrameNavigationControl::CommitNavigationCallback(), | 
|  | mojom::NavigationClient::CommitNavigationCallback(), nullptr, nullptr, | 
|  | ResourceDispatcher::MakeRequestID(), | 
|  | false /* was_initiated_in_this_frame */); | 
|  | FillMiscNavigationParams(navigation_state->common_params(), | 
|  | navigation_state->commit_params(), | 
|  | navigation_params.get()); | 
|  | } else { | 
|  | document_state = BuildDocumentState(); | 
|  | } | 
|  |  | 
|  | if (replace_current_item) | 
|  | navigation_params->frame_load_type = WebFrameLoadType::kReplaceCurrentItem; | 
|  | navigation_params->service_worker_network_provider = | 
|  | ServiceWorkerNetworkProviderForFrame::CreateInvalidInstance(); | 
|  |  | 
|  | // The load of the error page can result in this frame being removed. | 
|  | frame_->CommitNavigation(std::move(navigation_params), | 
|  | std::move(document_state)); | 
|  | // Do not access |this| or |frame_| without checking weak self. | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidMeaningfulLayout( | 
|  | blink::WebMeaningfulLayout layout_type) { | 
|  | for (auto& observer : observers_) | 
|  | observer.DidMeaningfulLayout(layout_type); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidCommitAndDrawCompositorFrame() { | 
|  | #if BUILDFLAG(ENABLE_PLUGINS) | 
|  | // Notify all instances that we painted.  The same caveats apply as for | 
|  | // ViewFlushedPaint regarding instances closing themselves, so we take | 
|  | // similar precautions. | 
|  | PepperPluginSet plugins = active_pepper_instances_; | 
|  | for (auto* plugin : plugins) { | 
|  | if (active_pepper_instances_.find(plugin) != active_pepper_instances_.end()) | 
|  | plugin->ViewInitiatedPaint(); | 
|  | } | 
|  | #endif | 
|  | } | 
|  |  | 
|  | RenderView* RenderFrameImpl::GetRenderView() { | 
|  | return render_view_; | 
|  | } | 
|  |  | 
|  | RenderAccessibility* RenderFrameImpl::GetRenderAccessibility() { | 
|  | return render_accessibility_; | 
|  | } | 
|  |  | 
|  | int RenderFrameImpl::GetRoutingID() { | 
|  | return routing_id_; | 
|  | } | 
|  |  | 
|  | blink::WebLocalFrame* RenderFrameImpl::GetWebFrame() { | 
|  | DCHECK(frame_); | 
|  | return frame_; | 
|  | } | 
|  |  | 
|  | const WebPreferences& RenderFrameImpl::GetWebkitPreferences() { | 
|  | return render_view_->GetWebkitPreferences(); | 
|  | } | 
|  |  | 
|  | const blink::mojom::RendererPreferences& | 
|  | RenderFrameImpl::GetRendererPreferences() const { | 
|  | return render_view_->renderer_preferences(); | 
|  | } | 
|  |  | 
|  | int RenderFrameImpl::ShowContextMenu(ContextMenuClient* client, | 
|  | const ContextMenuParams& params) { | 
|  | DCHECK(client);  // A null client means "internal" when we issue callbacks. | 
|  | ContextMenuParams our_params(params); | 
|  |  | 
|  | blink::WebRect position_in_window(params.x, params.y, 0, 0); | 
|  | GetLocalRootRenderWidget()->ConvertViewportToWindow(&position_in_window); | 
|  | our_params.x = position_in_window.x; | 
|  | our_params.y = position_in_window.y; | 
|  |  | 
|  | our_params.custom_context.request_id = pending_context_menus_.Add(client); | 
|  | Send(new FrameHostMsg_ContextMenu(routing_id_, our_params)); | 
|  | return our_params.custom_context.request_id; | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::CancelContextMenu(int request_id) { | 
|  | DCHECK(pending_context_menus_.Lookup(request_id)); | 
|  | pending_context_menus_.Remove(request_id); | 
|  | } | 
|  |  | 
|  | 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 WebPluginInfo& info, | 
|  | const blink::WebPluginParams& params, | 
|  | std::unique_ptr<content::PluginInstanceThrottler> throttler) { | 
|  | #if BUILDFLAG(ENABLE_PLUGINS) | 
|  | if (info.type == WebPluginInfo::PLUGIN_TYPE_BROWSER_PLUGIN) { | 
|  | // |delegate| deletes itself. | 
|  | BrowserPluginDelegate* delegate = | 
|  | GetContentClient()->renderer()->CreateBrowserPluginDelegate( | 
|  | this, info, params.mime_type.Utf8(), GURL(params.url)); | 
|  | return BrowserPluginManager::Get()->CreateBrowserPlugin( | 
|  | this, delegate->GetWeakPtr()); | 
|  | } | 
|  |  | 
|  | base::Optional<url::Origin> origin_lock; | 
|  | if (base::FeatureList::IsEnabled(features::kPdfIsolation) && | 
|  | GetContentClient()->renderer()->IsOriginIsolatedPepperPlugin(info.path)) { | 
|  | origin_lock = url::Origin::Create(GURL(params.url)); | 
|  | } | 
|  |  | 
|  | bool pepper_plugin_was_registered = false; | 
|  | scoped_refptr<PluginModule> pepper_module(PluginModule::Create( | 
|  | this, info, origin_lock, &pepper_plugin_was_registered, | 
|  | GetTaskRunner(blink::TaskType::kNetworking))); | 
|  | if (pepper_plugin_was_registered) { | 
|  | if (pepper_module.get()) { | 
|  | return new PepperWebPluginImpl( | 
|  | pepper_module.get(), params, this, | 
|  | base::WrapUnique( | 
|  | static_cast<PluginInstanceThrottlerImpl*>(throttler.release()))); | 
|  | } | 
|  | } | 
|  | #if defined(OS_CHROMEOS) | 
|  | LOG(WARNING) << "Pepper module/plugin creation failed."; | 
|  | #endif | 
|  | #endif  // BUILDFLAG(ENABLE_PLUGINS) | 
|  | return nullptr; | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::LoadErrorPage(int reason) { | 
|  | LoadNavigationErrorPage(frame_->GetDocumentLoader(), | 
|  | WebURLError(reason, frame_->GetDocument().Url()), | 
|  | base::nullopt, true /* replace_current_item */, | 
|  | false /* inherit_document_state */); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::ExecuteJavaScript(const base::string16& javascript) { | 
|  | JavaScriptExecuteRequest(javascript, base::DoNothing()); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::BindLocalInterface( | 
|  | const std::string& interface_name, | 
|  | mojo::ScopedMessagePipeHandle interface_pipe) { | 
|  | GetInterface(interface_name, std::move(interface_pipe)); | 
|  | } | 
|  |  | 
|  | service_manager::InterfaceProvider* RenderFrameImpl::GetRemoteInterfaces() { | 
|  | return &remote_interfaces_; | 
|  | } | 
|  |  | 
|  | blink::mojom::DocumentInterfaceBroker* | 
|  | RenderFrameImpl::GetDocumentInterfaceBroker() { | 
|  | DCHECK(document_interface_broker_.is_bound()); | 
|  | return document_interface_broker_.get(); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::SetDocumentInterfaceBrokerForTesting( | 
|  | blink::mojom::DocumentInterfaceBrokerPtr test_broker) { | 
|  | document_interface_broker_.FlushForTesting(); | 
|  | document_interface_broker_ = std::move(test_broker); | 
|  | } | 
|  |  | 
|  | blink::AssociatedInterfaceRegistry* | 
|  | RenderFrameImpl::GetAssociatedInterfaceRegistry() { | 
|  | return &associated_interfaces_; | 
|  | } | 
|  |  | 
|  | blink::AssociatedInterfaceProvider* | 
|  | RenderFrameImpl::GetRemoteAssociatedInterfaces() { | 
|  | if (!remote_associated_interfaces_) { | 
|  | ChildThreadImpl* thread = ChildThreadImpl::current(); | 
|  | if (thread) { | 
|  | blink::mojom::AssociatedInterfaceProviderAssociatedPtr remote_interfaces; | 
|  | thread->GetRemoteRouteProvider()->GetRoute( | 
|  | routing_id_, mojo::MakeRequest(&remote_interfaces)); | 
|  | remote_associated_interfaces_ = | 
|  | std::make_unique<blink::AssociatedInterfaceProvider>( | 
|  | std::move(remote_interfaces), | 
|  | GetTaskRunner(blink::TaskType::kInternalIPC)); | 
|  | } else { | 
|  | // In some tests the thread may be null, | 
|  | // so set up a self-contained interface provider instead. | 
|  | remote_associated_interfaces_ = | 
|  | std::make_unique<blink::AssociatedInterfaceProvider>( | 
|  | GetTaskRunner(blink::TaskType::kInternalIPC)); | 
|  | } | 
|  | } | 
|  | return remote_associated_interfaces_.get(); | 
|  | } | 
|  |  | 
|  | #if BUILDFLAG(ENABLE_PLUGINS) | 
|  | void RenderFrameImpl::RegisterPeripheralPlugin( | 
|  | const url::Origin& content_origin, | 
|  | const base::Closure& unthrottle_callback) { | 
|  | return plugin_power_saver_helper_->RegisterPeripheralPlugin( | 
|  | content_origin, unthrottle_callback); | 
|  | } | 
|  |  | 
|  | RenderFrame::PeripheralContentStatus | 
|  | RenderFrameImpl::GetPeripheralContentStatus( | 
|  | const url::Origin& main_frame_origin, | 
|  | const url::Origin& content_origin, | 
|  | const gfx::Size& unobscured_size, | 
|  | RecordPeripheralDecision record_decision) { | 
|  | return plugin_power_saver_helper_->GetPeripheralContentStatus( | 
|  | main_frame_origin, content_origin, unobscured_size, record_decision); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::WhitelistContentOrigin( | 
|  | const url::Origin& content_origin) { | 
|  | return plugin_power_saver_helper_->WhitelistContentOrigin(content_origin); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::PluginDidStartLoading() { | 
|  | DidStartLoading(); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::PluginDidStopLoading() { | 
|  | DidStopLoading(); | 
|  | } | 
|  | #endif  // BUILDFLAG(ENABLE_PLUGINS) | 
|  |  | 
|  | bool RenderFrameImpl::IsFTPDirectoryListing() { | 
|  | return frame_->GetDocumentLoader()->IsListingFtpDirectory(); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::AttachGuest(int element_instance_id) { | 
|  | BrowserPluginManager::Get()->Attach(element_instance_id); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DetachGuest(int element_instance_id) { | 
|  | BrowserPluginManager::Get()->Detach(element_instance_id); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::SetSelectedText(const base::string16& selection_text, | 
|  | size_t offset, | 
|  | const gfx::Range& range) { | 
|  | Send(new FrameHostMsg_SelectionChanged(routing_id_, selection_text, | 
|  | static_cast<uint32_t>(offset), range)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::SetZoomLevel(double zoom_level) { | 
|  | render_view_->UpdateZoomLevel(zoom_level); | 
|  | } | 
|  |  | 
|  | double RenderFrameImpl::GetZoomLevel() { | 
|  | return render_view_->page_zoom_level(); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::AddMessageToConsole( | 
|  | blink::mojom::ConsoleMessageLevel level, | 
|  | const std::string& message) { | 
|  | blink::WebConsoleMessage wcm(level, WebString::FromUTF8(message)); | 
|  | frame_->AddMessageToConsole(wcm); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::SetPreviewsState(PreviewsState previews_state) { | 
|  | previews_state_ = previews_state; | 
|  | } | 
|  |  | 
|  | PreviewsState RenderFrameImpl::GetPreviewsState() { | 
|  | return previews_state_; | 
|  | } | 
|  |  | 
|  | bool RenderFrameImpl::IsPasting() { | 
|  | return is_pasting_; | 
|  | } | 
|  |  | 
|  | // blink::mojom::FullscreenVideoElementHandler implementation ------------------ | 
|  | void RenderFrameImpl::RequestFullscreenVideoElement() { | 
|  | WebElement video_element = | 
|  | frame_->GetDocument().GetElementsByHTMLTagName("video").FirstItem(); | 
|  |  | 
|  | if (!video_element.IsNull()) { | 
|  | // This is always initiated from browser side (which should require the user | 
|  | // interacting with ui) which suffices for a user gesture even though there | 
|  | // will have been no input to the frame at this point. | 
|  | blink::WebScopedUserGesture gesture(frame_); | 
|  |  | 
|  | video_element.RequestFullscreen(); | 
|  | } | 
|  | } | 
|  |  | 
|  | // blink::mojom::AutoplayConfigurationClient implementation | 
|  | // -------------------------- | 
|  |  | 
|  | void RenderFrameImpl::AddAutoplayFlags(const url::Origin& origin, | 
|  | const int32_t flags) { | 
|  | // If the origin is the same as the previously stored flags then we should | 
|  | // merge the two sets of flags together. | 
|  | if (autoplay_flags_.first == origin) { | 
|  | autoplay_flags_.second |= flags; | 
|  | } else { | 
|  | autoplay_flags_ = std::make_pair(origin, flags); | 
|  | } | 
|  | } | 
|  |  | 
|  | // mojom::Frame implementation ------------------------------------------------- | 
|  |  | 
|  | void RenderFrameImpl::GetInterfaceProvider( | 
|  | service_manager::mojom::InterfaceProviderRequest request) { | 
|  | service_manager::Connector* connector = ChildThread::Get()->GetConnector(); | 
|  | service_manager::mojom::InterfaceProviderPtr provider; | 
|  | interface_provider_bindings_.AddBinding(this, mojo::MakeRequest(&provider)); | 
|  | connector->FilterInterfaces(mojom::kNavigation_FrameSpec, | 
|  | browser_info_.identity, std::move(request), | 
|  | std::move(provider)); | 
|  | } | 
|  | void RenderFrameImpl::GetCanonicalUrlForSharing( | 
|  | GetCanonicalUrlForSharingCallback callback) { | 
|  | WebURL canonical_url = GetWebFrame()->GetDocument().CanonicalUrlForSharing(); | 
|  | std::move(callback).Run(canonical_url.IsNull() | 
|  | ? base::nullopt | 
|  | : base::make_optional(GURL(canonical_url))); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::BlockRequests() { | 
|  | frame_request_blocker_->Block(); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::ResumeBlockedRequests() { | 
|  | frame_request_blocker_->Resume(); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::CancelBlockedRequests() { | 
|  | frame_request_blocker_->Cancel(); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::AllowBindings(int32_t enabled_bindings_flags) { | 
|  | if (IsMainFrame() && (enabled_bindings_flags & BINDINGS_POLICY_WEB_UI) && | 
|  | !(enabled_bindings_ & BINDINGS_POLICY_WEB_UI)) { | 
|  | // TODO(sammc): Move WebUIExtensionData to be a RenderFrameObserver. | 
|  | // WebUIExtensionData deletes itself when |render_view_| is destroyed. | 
|  | new WebUIExtensionData(render_view_); | 
|  | } | 
|  |  | 
|  | enabled_bindings_ |= enabled_bindings_flags; | 
|  |  | 
|  | // Keep track of the total bindings accumulated in this process. | 
|  | RenderProcess::current()->AddBindings(enabled_bindings_flags); | 
|  | } | 
|  |  | 
|  | // mojom::FrameNavigationControl implementation -------------------------------- | 
|  |  | 
|  | void RenderFrameImpl::CommitNavigation( | 
|  | const network::ResourceResponseHead& head, | 
|  | const CommonNavigationParams& common_params, | 
|  | const CommitNavigationParams& commit_params, | 
|  | network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints, | 
|  | std::unique_ptr<blink::URLLoaderFactoryBundleInfo> | 
|  | subresource_loader_factories, | 
|  | base::Optional<std::vector<mojom::TransferrableURLLoaderPtr>> | 
|  | subresource_overrides, | 
|  | blink::mojom::ControllerServiceWorkerInfoPtr controller_service_worker_info, | 
|  | blink::mojom::ServiceWorkerProviderInfoForWindowPtr provider_info, | 
|  | network::mojom::URLLoaderFactoryPtr prefetch_loader_factory, | 
|  | const base::UnguessableToken& devtools_navigation_token, | 
|  | CommitNavigationCallback commit_callback) { | 
|  | DCHECK(!navigation_client_impl_); | 
|  | // We can have a FrameNavigationControl::CommitNavigation with | 
|  | // IsPerNavigationMojoInterfaceEnabled() == true, for non-committed | 
|  | // interstitials where no NavigationRequest was created. Therefore, no DCHECK. | 
|  | CommitNavigationInternal( | 
|  | head, common_params, commit_params, | 
|  | std::move(url_loader_client_endpoints), | 
|  | std::move(subresource_loader_factories), std::move(subresource_overrides), | 
|  | std::move(controller_service_worker_info), std::move(provider_info), | 
|  | std::move(prefetch_loader_factory), devtools_navigation_token, | 
|  | std::move(commit_callback), | 
|  | mojom::NavigationClient::CommitNavigationCallback()); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::CommitPerNavigationMojoInterfaceNavigation( | 
|  | const network::ResourceResponseHead& head, | 
|  | const CommonNavigationParams& common_params, | 
|  | const CommitNavigationParams& commit_params, | 
|  | network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints, | 
|  | std::unique_ptr<blink::URLLoaderFactoryBundleInfo> | 
|  | subresource_loader_factories, | 
|  | base::Optional<std::vector<mojom::TransferrableURLLoaderPtr>> | 
|  | subresource_overrides, | 
|  | blink::mojom::ControllerServiceWorkerInfoPtr controller_service_worker_info, | 
|  | blink::mojom::ServiceWorkerProviderInfoForWindowPtr provider_info, | 
|  | network::mojom::URLLoaderFactoryPtr prefetch_loader_factory, | 
|  | const base::UnguessableToken& devtools_navigation_token, | 
|  | mojom::NavigationClient::CommitNavigationCallback | 
|  | per_navigation_mojo_interface_callback) { | 
|  | DCHECK(navigation_client_impl_); | 
|  | DCHECK(IsPerNavigationMojoInterfaceEnabled()); | 
|  | CommitNavigationInternal( | 
|  | head, common_params, commit_params, | 
|  | std::move(url_loader_client_endpoints), | 
|  | std::move(subresource_loader_factories), std::move(subresource_overrides), | 
|  | std::move(controller_service_worker_info), std::move(provider_info), | 
|  | std::move(prefetch_loader_factory), devtools_navigation_token, | 
|  | mojom::FrameNavigationControl::CommitNavigationCallback(), | 
|  | std::move(per_navigation_mojo_interface_callback)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::CommitNavigationInternal( | 
|  | const network::ResourceResponseHead& head, | 
|  | const CommonNavigationParams& common_params, | 
|  | const CommitNavigationParams& commit_params, | 
|  | network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints, | 
|  | std::unique_ptr<blink::URLLoaderFactoryBundleInfo> | 
|  | subresource_loader_factories, | 
|  | base::Optional<std::vector<mojom::TransferrableURLLoaderPtr>> | 
|  | subresource_overrides, | 
|  | blink::mojom::ControllerServiceWorkerInfoPtr controller_service_worker_info, | 
|  | blink::mojom::ServiceWorkerProviderInfoForWindowPtr provider_info, | 
|  | network::mojom::URLLoaderFactoryPtr prefetch_loader_factory, | 
|  | const base::UnguessableToken& devtools_navigation_token, | 
|  | mojom::FrameNavigationControl::CommitNavigationCallback callback, | 
|  | mojom::NavigationClient::CommitNavigationCallback | 
|  | per_navigation_mojo_interface_callback) { | 
|  | DCHECK(!IsRendererDebugURL(common_params.url)); | 
|  | DCHECK( | 
|  | !FrameMsg_Navigate_Type::IsSameDocument(common_params.navigation_type)); | 
|  | if (ShouldIgnoreCommitNavigation(commit_params)) { | 
|  | browser_side_navigation_pending_url_ = GURL(); | 
|  | AbortCommitNavigation(std::move(callback), | 
|  | blink::mojom::CommitResult::Aborted); | 
|  | return; | 
|  | } | 
|  |  | 
|  | bool was_initiated_in_this_frame = false; | 
|  | if (IsPerNavigationMojoInterfaceEnabled()) { | 
|  | was_initiated_in_this_frame = | 
|  | navigation_client_impl_ && | 
|  | navigation_client_impl_->was_initiated_in_this_frame(); | 
|  | } else { | 
|  | was_initiated_in_this_frame = | 
|  | browser_side_navigation_pending_ && | 
|  | browser_side_navigation_pending_url_ == commit_params.original_url && | 
|  | commit_params.nav_entry_id == 0; | 
|  | } | 
|  |  | 
|  | // Sanity check that the browser always sends us new loader factories on | 
|  | // cross-document navigations with the Network Service enabled. | 
|  | DCHECK(common_params.url.SchemeIs(url::kJavaScriptScheme) || | 
|  | !base::FeatureList::IsEnabled(network::features::kNetworkService) || | 
|  | subresource_loader_factories); | 
|  |  | 
|  | // We only save metrics of the main frame's main resource to the | 
|  | // document state. In view source mode, we effectively let the user | 
|  | // see the source of the server's error page instead of using custom | 
|  | // one derived from the metrics saved to document state. | 
|  | const network::ResourceResponseHead* response_head = nullptr; | 
|  | if (!frame_->Parent() && !frame_->IsViewSourceModeEnabled()) | 
|  | response_head = &head; | 
|  | int request_id = ResourceDispatcher::MakeRequestID(); | 
|  | std::unique_ptr<DocumentState> document_state = BuildDocumentStateFromParams( | 
|  | common_params, commit_params, base::TimeTicks::Now(), std::move(callback), | 
|  | std::move(per_navigation_mojo_interface_callback), response_head, | 
|  | std::move(navigation_client_impl_), request_id, | 
|  | was_initiated_in_this_frame); | 
|  |  | 
|  | // Check if the navigation being committed originated as a client redirect. | 
|  | bool is_client_redirect = | 
|  | !!(common_params.transition & ui::PAGE_TRANSITION_CLIENT_REDIRECT); | 
|  | auto navigation_params = | 
|  | std::make_unique<WebNavigationParams>(devtools_navigation_token); | 
|  | navigation_params->is_client_redirect = is_client_redirect; | 
|  | FillMiscNavigationParams(common_params, commit_params, | 
|  | navigation_params.get()); | 
|  |  | 
|  | auto commit_with_params = base::BindOnce( | 
|  | &RenderFrameImpl::CommitNavigationWithParams, weak_factory_.GetWeakPtr(), | 
|  | common_params, commit_params, std::move(subresource_loader_factories), | 
|  | std::move(subresource_overrides), | 
|  | std::move(controller_service_worker_info), std::move(provider_info), | 
|  | std::move(prefetch_loader_factory), std::move(document_state)); | 
|  |  | 
|  | // Perform a navigation to a data url if needed (for main frames). | 
|  | // Note: the base URL might be invalid, so also check the data URL string. | 
|  | bool should_load_data_url = !common_params.base_url_for_data_url.is_empty(); | 
|  | #if defined(OS_ANDROID) | 
|  | should_load_data_url |= !commit_params.data_url_as_string.empty(); | 
|  | #endif | 
|  | if (is_main_frame_ && should_load_data_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); | 
|  | // Needed so that history-url-only changes don't become reloads. | 
|  | navigation_params->unreachable_url = common_params.history_url_for_data_url; | 
|  | 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)) { | 
|  | // Normally, data urls will have |url_loader_client_endpoints| set. | 
|  | // However, tests and interstitial pages pass data urls directly, | 
|  | // without creating url loader. | 
|  | std::string mime_type, charset, data; | 
|  | if (!net::DataURL::Parse(common_params.url, &mime_type, &charset, &data)) { | 
|  | CHECK(false) << "Invalid URL passed: " | 
|  | << common_params.url.possibly_invalid_spec(); | 
|  | return; | 
|  | } | 
|  | WebNavigationParams::FillStaticResponse(navigation_params.get(), | 
|  | WebString::FromUTF8(mime_type), | 
|  | WebString::FromUTF8(charset), data); | 
|  | } else { | 
|  | NavigationBodyLoader::FillNavigationParamsResponseAndBodyLoader( | 
|  | common_params, commit_params, request_id, head, | 
|  | std::move(url_loader_client_endpoints), | 
|  | GetTaskRunner(blink::TaskType::kInternalLoading), GetRoutingID(), | 
|  | !frame_->Parent(), navigation_params.get()); | 
|  | } | 
|  |  | 
|  | // The MHTML mime type should be same as the one we check in the browser | 
|  | // process's download_utils::MustDownload. | 
|  | bool is_mhtml_archive = | 
|  | base::LowerCaseEqualsASCII(head.mime_type, "multipart/related") || | 
|  | base::LowerCaseEqualsASCII(head.mime_type, "message/rfc822"); | 
|  | if (is_mhtml_archive && navigation_params->body_loader) { | 
|  | // Load full mhtml archive before committing navigation. | 
|  | // We need this to retrieve the document mime type prior to committing. | 
|  | mhtml_body_loader_client_ = | 
|  | std::make_unique<RenderFrameImpl::MHTMLBodyLoaderClient>( | 
|  | std::move(navigation_params), std::move(commit_with_params)); | 
|  | return; | 
|  | } | 
|  |  | 
|  | // Common case - fill navigation params from provided information and commit. | 
|  | std::move(commit_with_params).Run(std::move(navigation_params)); | 
|  | } | 
|  |  | 
|  | bool RenderFrameImpl::ShouldIgnoreCommitNavigation( | 
|  | const CommitNavigationParams& commit_params) { | 
|  | // We can ignore renderer-initiated navigations (nav_entry_id == 0) which | 
|  | // have been canceled in the renderer, but browser was not aware yet at the | 
|  | // moment of issuing a CommitNavigation call. | 
|  | if (!browser_side_navigation_pending_ && | 
|  | !browser_side_navigation_pending_url_.is_empty() && | 
|  | browser_side_navigation_pending_url_ == commit_params.original_url && | 
|  | commit_params.nav_entry_id == 0) { | 
|  | return true; | 
|  | } | 
|  | return false; | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::CommitNavigationWithParams( | 
|  | const CommonNavigationParams& common_params, | 
|  | const CommitNavigationParams& commit_params, | 
|  | std::unique_ptr<blink::URLLoaderFactoryBundleInfo> | 
|  | subresource_loader_factories, | 
|  | base::Optional<std::vector<mojom::TransferrableURLLoaderPtr>> | 
|  | subresource_overrides, | 
|  | blink::mojom::ControllerServiceWorkerInfoPtr controller_service_worker_info, | 
|  | blink::mojom::ServiceWorkerProviderInfoForWindowPtr provider_info, | 
|  | network::mojom::URLLoaderFactoryPtr prefetch_loader_factory, | 
|  | std::unique_ptr<DocumentState> document_state, | 
|  | std::unique_ptr<WebNavigationParams> navigation_params) { | 
|  | if (ShouldIgnoreCommitNavigation(commit_params)) { | 
|  | browser_side_navigation_pending_url_ = GURL(); | 
|  | return; | 
|  | } | 
|  |  | 
|  | // TODO(yoichio): This is temporary switch to have chrome WebUI | 
|  | // use the old web APIs. | 
|  | // After completion of the migration, we should remove this. | 
|  | // See crbug.com/924871 for detail. | 
|  | if (common_params.url.SchemeIs(content::kChromeUIScheme)) { | 
|  | blink::WebRuntimeFeatures::EnableShadowDOMV0(true); | 
|  | blink::WebRuntimeFeatures::EnableCustomElementsV0(true); | 
|  | blink::WebRuntimeFeatures::EnableHTMLImports(true); | 
|  | } | 
|  |  | 
|  | SetupLoaderFactoryBundle(std::move(subresource_loader_factories), | 
|  | std::move(subresource_overrides), | 
|  | std::move(prefetch_loader_factory)); | 
|  |  | 
|  | // If the navigation is for "view source", the WebLocalFrame needs to be put | 
|  | // in a special mode. | 
|  | if (commit_params.is_view_source) | 
|  | frame_->EnableViewSourceMode(true); | 
|  |  | 
|  | PrepareFrameForCommit(common_params.url, commit_params); | 
|  |  | 
|  | blink::WebFrameLoadType load_type = NavigationTypeToLoadType( | 
|  | common_params.navigation_type, common_params.should_replace_current_entry, | 
|  | commit_params.page_state.IsValid()); | 
|  |  | 
|  | WebHistoryItem item_for_history_navigation; | 
|  | blink::mojom::CommitResult commit_status = blink::mojom::CommitResult::Ok; | 
|  |  | 
|  | if (load_type == WebFrameLoadType::kBackForward) { | 
|  | // We must know the nav entry ID of the page we are navigating back to, | 
|  | // which should be the case because history navigations are routed via the | 
|  | // browser. | 
|  | DCHECK_NE(0, commit_params.nav_entry_id); | 
|  |  | 
|  | // Check that the history navigation can commit. | 
|  | commit_status = PrepareForHistoryNavigationCommit( | 
|  | common_params.navigation_type, commit_params, | 
|  | &item_for_history_navigation, &load_type); | 
|  | } | 
|  |  | 
|  | if (commit_status != blink::mojom::CommitResult::Ok) { | 
|  | // The browser expects the frame to be loading this navigation. Inform it | 
|  | // that the load stopped if needed. | 
|  | if (frame_ && !frame_->IsLoading()) | 
|  | Send(new FrameHostMsg_DidStopLoading(routing_id_)); | 
|  | return; | 
|  | } | 
|  |  | 
|  | navigation_params->frame_load_type = load_type; | 
|  | navigation_params->history_item = item_for_history_navigation; | 
|  | navigation_params->service_worker_network_provider = | 
|  | BuildServiceWorkerNetworkProviderForNavigation( | 
|  | std::move(controller_service_worker_info), std::move(provider_info)); | 
|  |  | 
|  | frame_->CommitNavigation(std::move(navigation_params), | 
|  | std::move(document_state)); | 
|  | // The commit can result in this frame being removed. Do not use | 
|  | // |this| without checking a WeakPtr. | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::CommitFailedNavigation( | 
|  | const CommonNavigationParams& common_params, | 
|  | const CommitNavigationParams& commit_params, | 
|  | bool has_stale_copy_in_cache, | 
|  | int error_code, | 
|  | const base::Optional<std::string>& error_page_content, | 
|  | std::unique_ptr<blink::URLLoaderFactoryBundleInfo> | 
|  | subresource_loader_factories, | 
|  | mojom::FrameNavigationControl::CommitFailedNavigationCallback callback) { | 
|  | DCHECK(!navigation_client_impl_); | 
|  | DCHECK(!IsPerNavigationMojoInterfaceEnabled()); | 
|  | CommitFailedNavigationInternal( | 
|  | common_params, commit_params, has_stale_copy_in_cache, error_code, | 
|  | error_page_content, std::move(subresource_loader_factories), | 
|  | std::move(callback), | 
|  | mojom::NavigationClient::CommitFailedNavigationCallback()); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::CommitFailedPerNavigationMojoInterfaceNavigation( | 
|  | const CommonNavigationParams& common_params, | 
|  | const CommitNavigationParams& commit_params, | 
|  | bool has_stale_copy_in_cache, | 
|  | int error_code, | 
|  | const base::Optional<std::string>& error_page_content, | 
|  | std::unique_ptr<blink::URLLoaderFactoryBundleInfo> | 
|  | subresource_loader_factories, | 
|  | mojom::NavigationClient::CommitFailedNavigationCallback | 
|  | per_navigation_mojo_interface_callback) { | 
|  | DCHECK(navigation_client_impl_); | 
|  | DCHECK(IsPerNavigationMojoInterfaceEnabled()); | 
|  | CommitFailedNavigationInternal( | 
|  | common_params, commit_params, has_stale_copy_in_cache, error_code, | 
|  | error_page_content, std::move(subresource_loader_factories), | 
|  | mojom::FrameNavigationControl::CommitFailedNavigationCallback(), | 
|  | std::move(per_navigation_mojo_interface_callback)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::CommitFailedNavigationInternal( | 
|  | const CommonNavigationParams& common_params, | 
|  | const CommitNavigationParams& commit_params, | 
|  | bool has_stale_copy_in_cache, | 
|  | int error_code, | 
|  | const base::Optional<std::string>& error_page_content, | 
|  | std::unique_ptr<blink::URLLoaderFactoryBundleInfo> | 
|  | subresource_loader_factories, | 
|  | mojom::FrameNavigationControl::CommitFailedNavigationCallback callback, | 
|  | mojom::NavigationClient::CommitFailedNavigationCallback | 
|  | per_navigation_mojo_interface_callback) { | 
|  | TRACE_EVENT1("navigation,benchmark,rail", | 
|  | "RenderFrameImpl::CommitFailedNavigation", "id", routing_id_); | 
|  | DCHECK( | 
|  | !FrameMsg_Navigate_Type::IsSameDocument(common_params.navigation_type)); | 
|  | RenderFrameImpl::PrepareRenderViewForNavigation(common_params.url, | 
|  | commit_params); | 
|  | sync_navigation_callback_.Cancel(); | 
|  | mhtml_body_loader_client_.reset(); | 
|  |  | 
|  | GetContentClient()->SetActiveURL( | 
|  | common_params.url, frame_->Top()->GetSecurityOrigin().ToString().Utf8()); | 
|  |  | 
|  | SetupLoaderFactoryBundle(std::move(subresource_loader_factories), | 
|  | base::nullopt /* subresource_overrides */, | 
|  | nullptr /* prefetch_loader_factory */); | 
|  |  | 
|  | // Send the provisional load failure. | 
|  | WebURLError error( | 
|  | error_code, 0, | 
|  | has_stale_copy_in_cache ? WebURLError::HasCopyInCache::kTrue | 
|  | : WebURLError::HasCopyInCache::kFalse, | 
|  | WebURLError::IsWebSecurityViolation::kFalse, common_params.url); | 
|  |  | 
|  | auto navigation_params = std::make_unique<WebNavigationParams>(); | 
|  | FillNavigationParamsRequest(common_params, commit_params, | 
|  | navigation_params.get()); | 
|  | navigation_params->url = GURL(kUnreachableWebDataURL); | 
|  | navigation_params->error_code = error_code; | 
|  |  | 
|  | if (!ShouldDisplayErrorPageForFailedLoad(error_code, common_params.url)) { | 
|  | // The browser expects this frame to be loading an error page. Inform it | 
|  | // that the load stopped. | 
|  | AbortCommitNavigation(std::move(callback), | 
|  | blink::mojom::CommitResult::Aborted); | 
|  | Send(new FrameHostMsg_DidStopLoading(routing_id_)); | 
|  | browser_side_navigation_pending_ = false; | 
|  | browser_side_navigation_pending_url_ = GURL(); | 
|  | return; | 
|  | } | 
|  |  | 
|  | // On load failure, a frame can ask its owner to render fallback content. | 
|  | // When that happens, don't load an error page. | 
|  | blink::WebNavigationControl::FallbackContentResult fallback_result = | 
|  | frame_->MaybeRenderFallbackContent(error); | 
|  | if (fallback_result != blink::WebNavigationControl::NoFallbackContent) { | 
|  | if (fallback_result == blink::WebNavigationControl::NoLoadInProgress) { | 
|  | // If the frame wasn't loading but was fallback-eligible, the fallback | 
|  | // content won't be shown. However, showing an error page isn't right | 
|  | // either, as the frame has already been populated with something | 
|  | // unrelated to this navigation failure. In that case, just send a stop | 
|  | // IPC to the browser to unwind its state, and leave the frame as-is. | 
|  | AbortCommitNavigation(std::move(callback), | 
|  | blink::mojom::CommitResult::Aborted); | 
|  | Send(new FrameHostMsg_DidStopLoading(routing_id_)); | 
|  | } else { | 
|  | AbortCommitNavigation(std::move(callback), | 
|  | blink::mojom::CommitResult::Ok); | 
|  | } | 
|  | browser_side_navigation_pending_ = false; | 
|  | browser_side_navigation_pending_url_ = GURL(); | 
|  | return; | 
|  | } | 
|  |  | 
|  | // Replace the current history entry in reloads, and loads of the same url. | 
|  | // This corresponds to Blink's notion of a standard commit. | 
|  | // Also replace the current history entry if the browser asked for it | 
|  | // specifically. | 
|  | // TODO(clamy): see if initial commits in subframes should be handled | 
|  | // separately. | 
|  | bool is_reload_or_history = | 
|  | FrameMsg_Navigate_Type::IsReload(common_params.navigation_type) || | 
|  | FrameMsg_Navigate_Type::IsHistory(common_params.navigation_type); | 
|  | bool replace = is_reload_or_history || common_params.url == GetLoadingUrl() || | 
|  | common_params.should_replace_current_entry; | 
|  | std::unique_ptr<HistoryEntry> history_entry; | 
|  | if (commit_params.page_state.IsValid()) | 
|  | history_entry = PageStateToHistoryEntry(commit_params.page_state); | 
|  |  | 
|  | if (commit_params.nav_entry_id == 0) { | 
|  | // For renderer initiated navigations, we send out a | 
|  | // DidFailProvisionalLoad() notification. | 
|  | NotifyObserversOfFailedProvisionalLoad(error); | 
|  |  | 
|  | // Provisional document loader can be null in cases such as cross | 
|  | // process failures, e.g. error pages. | 
|  | if (frame_->GetProvisionalDocumentLoader()) { | 
|  | // TODO(dgozman): why do we need to notify browser in response | 
|  | // to it's own request? | 
|  | SendFailedProvisionalLoad(navigation_params->http_method.Ascii(), error, | 
|  | frame_); | 
|  | } | 
|  | } | 
|  |  | 
|  | std::string error_html; | 
|  | if (error_page_content.has_value()) { | 
|  | error_html = error_page_content.value(); | 
|  | // We don't need the actual error page content, but still call this | 
|  | // for any possible side effects. | 
|  | GetContentClient()->renderer()->PrepareErrorPage( | 
|  | this, error, navigation_params->http_method.Ascii(), | 
|  | false /* ignoring_cache */, nullptr); | 
|  | } else { | 
|  | GetContentClient()->renderer()->PrepareErrorPage( | 
|  | this, error, navigation_params->http_method.Ascii(), | 
|  | false /* ignoring_cache */, &error_html); | 
|  | } | 
|  |  | 
|  | // Make sure we never show errors in view source mode. | 
|  | frame_->EnableViewSourceMode(false); | 
|  |  | 
|  | if (history_entry) { | 
|  | navigation_params->frame_load_type = WebFrameLoadType::kBackForward; | 
|  | navigation_params->history_item = history_entry->root(); | 
|  | } else if (replace) { | 
|  | 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(); | 
|  |  | 
|  | // The error page load (not to confuse with a failed load of original page) | 
|  | // was not initiated through BeginNavigation, therefore | 
|  | // |was_initiated_in_this_frame| is false. | 
|  | std::unique_ptr<DocumentState> document_state = BuildDocumentStateFromParams( | 
|  | common_params, commit_params, base::TimeTicks(), std::move(callback), | 
|  | std::move(per_navigation_mojo_interface_callback), nullptr, | 
|  | std::move(navigation_client_impl_), ResourceDispatcher::MakeRequestID(), | 
|  | false /* was_initiated_in_this_frame */); | 
|  |  | 
|  | // The load of the error page can result in this frame being removed. | 
|  | // Use a WeakPtr as an easy way to detect whether this has occured. If so, | 
|  | // this method should return immediately and not touch any part of the object, | 
|  | // otherwise it will result in a use-after-free bug. | 
|  | base::WeakPtr<RenderFrameImpl> weak_this = weak_factory_.GetWeakPtr(); | 
|  | frame_->CommitNavigation(std::move(navigation_params), | 
|  | std::move(document_state)); | 
|  | if (!weak_this) | 
|  | return; | 
|  |  | 
|  | browser_side_navigation_pending_ = false; | 
|  | browser_side_navigation_pending_url_ = GURL(); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::CommitSameDocumentNavigation( | 
|  | const CommonNavigationParams& common_params, | 
|  | const CommitNavigationParams& commit_params, | 
|  | CommitSameDocumentNavigationCallback callback) { | 
|  | DCHECK(!IsRendererDebugURL(common_params.url)); | 
|  | DCHECK(!FrameMsg_Navigate_Type::IsReload(common_params.navigation_type)); | 
|  | DCHECK(!commit_params.is_view_source); | 
|  | DCHECK(FrameMsg_Navigate_Type::IsSameDocument(common_params.navigation_type)); | 
|  |  | 
|  | PrepareFrameForCommit(common_params.url, commit_params); | 
|  |  | 
|  | blink::WebFrameLoadType load_type = NavigationTypeToLoadType( | 
|  | common_params.navigation_type, common_params.should_replace_current_entry, | 
|  | commit_params.page_state.IsValid()); | 
|  |  | 
|  | blink::mojom::CommitResult commit_status = blink::mojom::CommitResult::Ok; | 
|  | WebHistoryItem item_for_history_navigation; | 
|  |  | 
|  | if (common_params.navigation_type == | 
|  | FrameMsg_Navigate_Type::HISTORY_SAME_DOCUMENT) { | 
|  | DCHECK(commit_params.page_state.IsValid()); | 
|  | // We must know the nav entry ID of the page we are navigating back to, | 
|  | // which should be the case because history navigations are routed via the | 
|  | // browser. | 
|  | DCHECK_NE(0, commit_params.nav_entry_id); | 
|  | DCHECK(!commit_params.is_history_navigation_in_new_child); | 
|  | commit_status = PrepareForHistoryNavigationCommit( | 
|  | common_params.navigation_type, commit_params, | 
|  | &item_for_history_navigation, &load_type); | 
|  | } | 
|  |  | 
|  | if (commit_status == blink::mojom::CommitResult::Ok) { | 
|  | base::WeakPtr<RenderFrameImpl> weak_this = weak_factory_.GetWeakPtr(); | 
|  | bool is_client_redirect = | 
|  | !!(common_params.transition & ui::PAGE_TRANSITION_CLIENT_REDIRECT); | 
|  | DocumentState* original_document_state = | 
|  | DocumentState::FromDocumentLoader(frame_->GetDocumentLoader()); | 
|  | std::unique_ptr<DocumentState> document_state = | 
|  | original_document_state->Clone(); | 
|  | InternalDocumentStateData* internal_data = | 
|  | InternalDocumentStateData::FromDocumentState(document_state.get()); | 
|  | internal_data->CopyFrom( | 
|  | InternalDocumentStateData::FromDocumentState(original_document_state)); | 
|  | // This is a browser-initiated same-document navigation (as opposed to a | 
|  | // fragment link click), therefore |was_initiated_in_this_frame| is false. | 
|  | internal_data->set_navigation_state(NavigationState::CreateBrowserInitiated( | 
|  | common_params, commit_params, | 
|  | base::TimeTicks(),  // Not used for same-document navigation. | 
|  | mojom::FrameNavigationControl::CommitNavigationCallback(), | 
|  | mojom::NavigationClient::CommitNavigationCallback(), nullptr, | 
|  | false /* was_initiated_in_this_frame */)); | 
|  |  | 
|  | // Load the request. | 
|  | commit_status = frame_->CommitSameDocumentNavigation( | 
|  | common_params.url, load_type, item_for_history_navigation, | 
|  | is_client_redirect, std::move(document_state)); | 
|  |  | 
|  | // The load of the URL can result in this frame being removed. Use a | 
|  | // WeakPtr as an easy way to detect whether this has occured. If so, this | 
|  | // method should return immediately and not touch any part of the object, | 
|  | // otherwise it will result in a use-after-free bug. | 
|  | if (!weak_this) | 
|  | return; | 
|  | } | 
|  |  | 
|  | std::move(callback).Run(commit_status); | 
|  |  | 
|  | // The browser expects the frame to be loading this navigation. Inform it | 
|  | // that the load stopped if needed. | 
|  | if (frame_ && !frame_->IsLoading() && | 
|  | commit_status != blink::mojom::CommitResult::Ok) { | 
|  | Send(new FrameHostMsg_DidStopLoading(routing_id_)); | 
|  | } | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::HandleRendererDebugURL(const GURL& url) { | 
|  | DCHECK(IsRendererDebugURL(url)); | 
|  | base::WeakPtr<RenderFrameImpl> weak_this = weak_factory_.GetWeakPtr(); | 
|  | if (url.SchemeIs(url::kJavaScriptScheme)) { | 
|  | // Javascript URLs should be sent to Blink for handling. | 
|  | frame_->LoadJavaScriptURL(url); | 
|  | } else { | 
|  | // This is a Chrome Debug URL. Handle it. | 
|  | HandleChromeDebugURL(url); | 
|  | } | 
|  |  | 
|  | // The browser sets its status as loading before calling this IPC. Inform it | 
|  | // that the load stopped if needed, while leaving the debug URL visible in the | 
|  | // address bar. | 
|  | if (weak_this && frame_ && !frame_->IsLoading()) | 
|  | Send(new FrameHostMsg_DidStopLoading(routing_id_)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::UpdateSubresourceLoaderFactories( | 
|  | std::unique_ptr<blink::URLLoaderFactoryBundleInfo> | 
|  | subresource_loader_factories) { | 
|  | DCHECK(loader_factories_); | 
|  | if (loader_factories_->IsHostChildURLLoaderFactoryBundle()) { | 
|  | static_cast<HostChildURLLoaderFactoryBundle*>(loader_factories_.get()) | 
|  | ->UpdateThisAndAllClones(std::move(subresource_loader_factories)); | 
|  | } else { | 
|  | #if DCHECK_IS_ON() | 
|  | // In presence of the NetworkService, this situation should happen only if | 
|  | // the frame hosts a document that isn't related to a real navigation (i.e. | 
|  | // if the frame should "inherit" the factories from its opener/parent - for | 
|  | // example for about:blank or about:srcdoc or about:blank#someHref frames, | 
|  | // or for frames with no URL - like the initial frame opened by window('', | 
|  | // 'popup')). | 
|  | if (base::FeatureList::IsEnabled(network::features::kNetworkService)) { | 
|  | WebURL url = GetWebFrame()->GetDocument().Url(); | 
|  | if (url.IsValid() && !url.IsEmpty()) | 
|  | DCHECK(url.ProtocolIs(url::kAboutScheme)); | 
|  | } | 
|  | #endif | 
|  | auto partial_bundle = base::MakeRefCounted<ChildURLLoaderFactoryBundle>(); | 
|  | static_cast<blink::URLLoaderFactoryBundle*>(partial_bundle.get()) | 
|  | ->Update(std::move(subresource_loader_factories)); | 
|  | loader_factories_->Update(partial_bundle->PassInterface()); | 
|  | } | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::MarkInitiatorAsRequiringSeparateURLLoaderFactory( | 
|  | const url::Origin& initiator_origin, | 
|  | network::mojom::URLLoaderFactoryPtr url_loader_factory) { | 
|  | DCHECK(base::FeatureList::IsEnabled(network::features::kNetworkService)); | 
|  |  | 
|  | // Set up |loader_factories_| to be updated by the | 
|  | // UpdateSubresourceLoaderFactories() below. | 
|  | GetLoaderFactoryBundle(); | 
|  | auto factory_bundle = std::make_unique<blink::URLLoaderFactoryBundleInfo>(); | 
|  | factory_bundle->initiator_specific_factory_infos()[initiator_origin] = | 
|  | url_loader_factory.PassInterface(); | 
|  | UpdateSubresourceLoaderFactories(std::move(factory_bundle)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::BindDevToolsAgent( | 
|  | blink::mojom::DevToolsAgentHostAssociatedPtrInfo host, | 
|  | blink::mojom::DevToolsAgentAssociatedRequest request) { | 
|  | frame_->BindDevToolsAgent(host.PassHandle(), request.PassHandle()); | 
|  | } | 
|  |  | 
|  | // mojom::HostZoom implementation ---------------------------------------------- | 
|  |  | 
|  | void RenderFrameImpl::SetHostZoomLevel(const GURL& url, double zoom_level) { | 
|  | // TODO(wjmaclean): We should see if this restriction is really necessary, | 
|  | // since it isn't enforced in other parts of the page zoom system (e.g. | 
|  | // when a users changes the zoom of a currently displayed page). Android | 
|  | // has no UI for this, so in theory the following code would normally just use | 
|  | // the default zoom anyways. | 
|  | #if !defined(OS_ANDROID) | 
|  | // On Android, page zoom isn't used, and in case of WebView, text zoom is used | 
|  | // for legacy WebView text scaling emulation. Thus, the code that resets | 
|  | // the zoom level from this map will be effectively resetting text zoom level. | 
|  | host_zoom_levels_[url] = zoom_level; | 
|  | #endif | 
|  | } | 
|  |  | 
|  | // blink::WebLocalFrameClient implementation | 
|  | // ---------------------------------------- | 
|  |  | 
|  | bool RenderFrameImpl::MaybeCreateMimeHandlerView( | 
|  | const blink::WebElement& plugin_element, | 
|  | const blink::WebURL& url, | 
|  | const blink::WebString& suggested_mime_type) { | 
|  | DCHECK(content::MimeHandlerViewMode::UsesCrossProcessFrame()); | 
|  | #if BUILDFLAG(ENABLE_PLUGINS) | 
|  | return GetContentClient()->renderer()->MaybeCreateMimeHandlerView( | 
|  | this, plugin_element, GURL(url), suggested_mime_type.Utf8()); | 
|  | #else | 
|  | return false; | 
|  | #endif | 
|  | } | 
|  |  | 
|  | v8::Local<v8::Object> RenderFrameImpl::GetScriptableObject( | 
|  | const blink::WebElement& plugin_element, | 
|  | v8::Isolate* isolate) { | 
|  | #if BUILDFLAG(ENABLE_PLUGINS) | 
|  | if (!content::MimeHandlerViewMode::UsesCrossProcessFrame()) | 
|  | return v8::Local<v8::Object>(); | 
|  |  | 
|  | return GetContentClient()->renderer()->GetScriptableObject(plugin_element, | 
|  | isolate); | 
|  | #else | 
|  | return v8::Local<v8::Object>(); | 
|  | #endif | 
|  | } | 
|  |  | 
|  | blink::WebPlugin* RenderFrameImpl::CreatePlugin( | 
|  | const blink::WebPluginParams& params) { | 
|  | blink::WebPlugin* plugin = nullptr; | 
|  | if (GetContentClient()->renderer()->OverrideCreatePlugin(this, params, | 
|  | &plugin)) { | 
|  | return plugin; | 
|  | } | 
|  |  | 
|  | if (params.mime_type.ContainsOnlyASCII() && | 
|  | params.mime_type.Ascii() == kBrowserPluginMimeType) { | 
|  | // |delegate| deletes itself. | 
|  | BrowserPluginDelegate* delegate = | 
|  | GetContentClient()->renderer()->CreateBrowserPluginDelegate( | 
|  | this, WebPluginInfo(), kBrowserPluginMimeType, GURL(params.url)); | 
|  | return BrowserPluginManager::Get()->CreateBrowserPlugin( | 
|  | this, delegate->GetWeakPtr()); | 
|  | } | 
|  |  | 
|  | #if BUILDFLAG(ENABLE_PLUGINS) | 
|  | WebPluginInfo info; | 
|  | std::string mime_type; | 
|  | bool found = false; | 
|  | Send(new FrameHostMsg_GetPluginInfo( | 
|  | routing_id_, params.url, frame_->Top()->GetSecurityOrigin(), | 
|  | params.mime_type.Utf8(), &found, &info, &mime_type)); | 
|  | if (!found) | 
|  | return nullptr; | 
|  |  | 
|  | WebPluginParams params_to_use = params; | 
|  | params_to_use.mime_type = WebString::FromUTF8(mime_type); | 
|  | return CreatePlugin(info, params_to_use, nullptr /* throttler */); | 
|  | #else | 
|  | return nullptr; | 
|  | #endif  // BUILDFLAG(ENABLE_PLUGINS) | 
|  | } | 
|  |  | 
|  | blink::WebMediaPlayer* RenderFrameImpl::CreateMediaPlayer( | 
|  | const blink::WebMediaPlayerSource& source, | 
|  | WebMediaPlayerClient* client, | 
|  | WebMediaPlayerEncryptedMediaClient* encrypted_client, | 
|  | WebContentDecryptionModule* initial_cdm, | 
|  | const blink::WebString& sink_id, | 
|  | blink::WebLayerTreeView* layer_tree_view) { | 
|  | const cc::LayerTreeSettings& settings = | 
|  | GetLocalRootRenderWidget()->layer_tree_view()->GetLayerTreeSettings(); | 
|  | return media_factory_.CreateMediaPlayer(source, client, encrypted_client, | 
|  | initial_cdm, sink_id, layer_tree_view, | 
|  | settings); | 
|  | } | 
|  |  | 
|  | std::unique_ptr<blink::WebApplicationCacheHost> | 
|  | RenderFrameImpl::CreateApplicationCacheHost( | 
|  | blink::WebDocumentLoader* document_loader, | 
|  | blink::WebApplicationCacheHostClient* client) { | 
|  | if (!frame_ || !frame_->View()) | 
|  | return nullptr; | 
|  |  | 
|  | NavigationState* navigation_state = | 
|  | NavigationState::FromDocumentLoader(document_loader); | 
|  |  | 
|  | scoped_refptr<base::SingleThreadTaskRunner> task_runner = | 
|  | frame_->GetTaskRunner(blink::TaskType::kNetworking); | 
|  |  | 
|  | return std::make_unique<RendererWebApplicationCacheHostImpl>( | 
|  | RenderViewImpl::FromWebView(frame_->View()), client, | 
|  | navigation_state->commit_params().appcache_host_id, routing_id_, | 
|  | std::move(task_runner)); | 
|  | } | 
|  |  | 
|  | std::unique_ptr<blink::WebContentSettingsClient> | 
|  | RenderFrameImpl::CreateWorkerContentSettingsClient() { | 
|  | if (!frame_ || !frame_->View()) | 
|  | return nullptr; | 
|  | return GetContentClient()->renderer()->CreateWorkerContentSettingsClient( | 
|  | this); | 
|  | } | 
|  |  | 
|  | scoped_refptr<blink::WebWorkerFetchContext> | 
|  | RenderFrameImpl::CreateWorkerFetchContext() { | 
|  | ServiceWorkerNetworkProviderForFrame* provider = | 
|  | static_cast<ServiceWorkerNetworkProviderForFrame*>( | 
|  | frame_->GetDocumentLoader()->GetServiceWorkerNetworkProvider()); | 
|  | DCHECK(provider); | 
|  |  | 
|  | blink::mojom::RendererPreferenceWatcherPtr watcher; | 
|  | blink::mojom::RendererPreferenceWatcherRequest watcher_request = | 
|  | mojo::MakeRequest(&watcher); | 
|  | render_view()->RegisterRendererPreferenceWatcher(std::move(watcher)); | 
|  |  | 
|  | scoped_refptr<WebWorkerFetchContextImpl> worker_fetch_context = | 
|  | WebWorkerFetchContextImpl::Create( | 
|  | provider->context(), render_view_->renderer_preferences(), | 
|  | std::move(watcher_request), GetLoaderFactoryBundle()->Clone(), | 
|  | GetLoaderFactoryBundle()->CloneWithoutAppCacheFactory()); | 
|  |  | 
|  | worker_fetch_context->set_ancestor_frame_id(routing_id_); | 
|  | worker_fetch_context->set_frame_request_blocker(frame_request_blocker_); | 
|  | worker_fetch_context->set_site_for_cookies( | 
|  | frame_->GetDocument().SiteForCookies()); | 
|  | worker_fetch_context->set_top_frame_origin( | 
|  | frame_->GetDocument().TopFrameOrigin()); | 
|  | worker_fetch_context->set_is_secure_context( | 
|  | frame_->GetDocument().IsSecureContext()); | 
|  | worker_fetch_context->set_origin_url( | 
|  | GURL(frame_->GetDocument().Url()).GetOrigin()); | 
|  |  | 
|  | for (auto& observer : observers_) | 
|  | observer.WillCreateWorkerFetchContext(worker_fetch_context.get()); | 
|  | return worker_fetch_context; | 
|  | } | 
|  |  | 
|  | scoped_refptr<blink::WebWorkerFetchContext> | 
|  | RenderFrameImpl::CreateWorkerFetchContextForPlzDedicatedWorker( | 
|  | blink::WebDedicatedWorkerHostFactoryClient* factory_client) { | 
|  | DCHECK(blink::features::IsPlzDedicatedWorkerEnabled()); | 
|  | DCHECK(factory_client); | 
|  |  | 
|  | blink::mojom::RendererPreferenceWatcherPtr watcher; | 
|  | blink::mojom::RendererPreferenceWatcherRequest watcher_request = | 
|  | mojo::MakeRequest(&watcher); | 
|  | render_view()->RegisterRendererPreferenceWatcher(std::move(watcher)); | 
|  |  | 
|  | scoped_refptr<WebWorkerFetchContextImpl> worker_fetch_context = | 
|  | static_cast<DedicatedWorkerHostFactoryClient*>(factory_client) | 
|  | ->CreateWorkerFetchContext(render_view_->renderer_preferences(), | 
|  | std::move(watcher_request)); | 
|  |  | 
|  | worker_fetch_context->set_ancestor_frame_id(routing_id_); | 
|  | worker_fetch_context->set_frame_request_blocker(frame_request_blocker_); | 
|  | worker_fetch_context->set_site_for_cookies( | 
|  | frame_->GetDocument().SiteForCookies()); | 
|  | worker_fetch_context->set_top_frame_origin( | 
|  | frame_->GetDocument().TopFrameOrigin()); | 
|  | worker_fetch_context->set_is_secure_context( | 
|  | frame_->GetDocument().IsSecureContext()); | 
|  | worker_fetch_context->set_origin_url( | 
|  | GURL(frame_->GetDocument().Url()).GetOrigin()); | 
|  |  | 
|  | for (auto& observer : observers_) | 
|  | observer.WillCreateWorkerFetchContext(worker_fetch_context.get()); | 
|  | return worker_fetch_context; | 
|  | } | 
|  |  | 
|  | WebExternalPopupMenu* RenderFrameImpl::CreateExternalPopupMenu( | 
|  | const WebPopupMenuInfo& popup_menu_info, | 
|  | WebExternalPopupMenuClient* popup_menu_client) { | 
|  | #if BUILDFLAG(USE_EXTERNAL_POPUP_MENU) | 
|  | // An IPC message is sent to the browser to build and display the actual | 
|  | // popup. The user could have time to click a different select by the time | 
|  | // the popup is shown. In that case external_popup_menu_ is non NULL. | 
|  | // By returning NULL in that case, we instruct Blink to cancel that new | 
|  | // popup. So from the user perspective, only the first one will show, and | 
|  | // will have to close the first one before another one can be shown. | 
|  | if (external_popup_menu_) | 
|  | return NULL; | 
|  | external_popup_menu_.reset( | 
|  | new ExternalPopupMenu(this, popup_menu_info, popup_menu_client)); | 
|  | render_view_->GetWidget()->SetExternalPopupOriginAdjustmentsForEmulation( | 
|  | external_popup_menu_.get()); | 
|  | return external_popup_menu_.get(); | 
|  | #else | 
|  | return nullptr; | 
|  | #endif | 
|  | } | 
|  |  | 
|  | blink::WebCookieJar* RenderFrameImpl::CookieJar() { | 
|  | return &cookie_jar_; | 
|  | } | 
|  |  | 
|  | blink::BlameContext* RenderFrameImpl::GetFrameBlameContext() { | 
|  | DCHECK(blame_context_); | 
|  | return blame_context_.get(); | 
|  | } | 
|  |  | 
|  | std::unique_ptr<blink::WebServiceWorkerProvider> | 
|  | RenderFrameImpl::CreateServiceWorkerProvider() { | 
|  | // Bail-out if we are about to be navigated away. | 
|  | // We check that DocumentLoader is attached since: | 
|  | // - This serves as the signal since the DocumentLoader is detached in | 
|  | //   FrameLoader::PrepareForCommit(). | 
|  | // - Creating ServiceWorkerProvider in | 
|  | //   RenderFrameImpl::CreateServiceWorkerProvider() assumes that there is a | 
|  | //   DocumentLoader attached to the frame. | 
|  | if (!frame_->GetDocumentLoader()) | 
|  | return nullptr; | 
|  |  | 
|  | // At this point we should have non-null data source. | 
|  | if (!ChildThreadImpl::current()) | 
|  | return nullptr;  // May be null in some tests. | 
|  | ServiceWorkerNetworkProviderForFrame* provider = | 
|  | static_cast<ServiceWorkerNetworkProviderForFrame*>( | 
|  | frame_->GetDocumentLoader()->GetServiceWorkerNetworkProvider()); | 
|  | if (!provider->context()) { | 
|  | // The context can be null when the frame is sandboxed. | 
|  | return nullptr; | 
|  | } | 
|  | return std::make_unique<WebServiceWorkerProviderImpl>(provider->context()); | 
|  | } | 
|  |  | 
|  | service_manager::InterfaceProvider* RenderFrameImpl::GetInterfaceProvider() { | 
|  | return &remote_interfaces_; | 
|  | } | 
|  |  | 
|  | blink::AssociatedInterfaceProvider* | 
|  | RenderFrameImpl::GetRemoteNavigationAssociatedInterfaces() { | 
|  | return GetRemoteAssociatedInterfaces(); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidAccessInitialDocument() { | 
|  | DCHECK(!frame_->Parent()); | 
|  | // NOTE: Do not call back into JavaScript here, since this call is made from a | 
|  | // V8 security check. | 
|  |  | 
|  | // If the request hasn't yet committed, notify the browser process that it is | 
|  | // no longer safe to show the pending URL of the main frame, since a URL spoof | 
|  | // is now possible. (If the request has committed, the browser already knows.) | 
|  | if (!has_accessed_initial_document_) { | 
|  | NavigationState* navigation_state = | 
|  | NavigationState::FromDocumentLoader(frame_->GetDocumentLoader()); | 
|  | if (!navigation_state->request_committed()) { | 
|  | Send(new FrameHostMsg_DidAccessInitialDocument(routing_id_)); | 
|  | } | 
|  | } | 
|  |  | 
|  | has_accessed_initial_document_ = true; | 
|  | } | 
|  |  | 
|  | blink::WebLocalFrame* RenderFrameImpl::CreateChildFrame( | 
|  | blink::WebLocalFrame* parent, | 
|  | blink::WebTreeScopeType 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) { | 
|  | DCHECK_EQ(frame_, parent); | 
|  |  | 
|  | // Synchronously notify the browser of a child frame creation to get the | 
|  | // routing_id for the RenderFrame. | 
|  | FrameHostMsg_CreateChildFrame_Params params; | 
|  | params.parent_routing_id = routing_id_; | 
|  | params.scope = scope; | 
|  | params.frame_name = name.Utf8(); | 
|  |  | 
|  | FrameHostMsg_CreateChildFrame_Params_Reply params_reply; | 
|  |  | 
|  | // The unique name generation logic was moved out of Blink, so for historical | 
|  | // reasons, unique name generation needs to take something called the | 
|  | // |fallback_name| into account. Normally, unique names are generated based on | 
|  | // the browing context name. For new frames, the initial browsing context name | 
|  | // comes from the name attribute of the browsing context container element. | 
|  | // | 
|  | // However, when the browsing context name is null, Blink instead uses the | 
|  | // "fallback name" to derive the unique name. The exact contents of the | 
|  | // "fallback name" are unspecified, but may contain the value of the | 
|  | // 'subresource attribute' of the browsing context container element. | 
|  | // | 
|  | // Note that Blink can't be changed to just pass |fallback_name| as |name| in | 
|  | // the case |name| is empty: |fallback_name| should never affect the actual | 
|  | // browsing context name, only unique name generation. | 
|  | params.is_created_by_script = | 
|  | v8::Isolate::GetCurrent() && v8::Isolate::GetCurrent()->InContext(); | 
|  | params.frame_unique_name = unique_name_helper_.GenerateNameForNewChildFrame( | 
|  | params.frame_name.empty() ? fallback_name.Utf8() : params.frame_name, | 
|  | params.is_created_by_script); | 
|  | params.frame_policy = frame_policy; | 
|  | params.frame_owner_properties = | 
|  | ConvertWebFrameOwnerPropertiesToFrameOwnerProperties( | 
|  | frame_owner_properties); | 
|  | params.frame_owner_element_type = frame_owner_element_type; | 
|  | if (!Send(new FrameHostMsg_CreateChildFrame(params, ¶ms_reply))) { | 
|  | // Allocation of routing id failed, so we can't create a child frame. This can | 
|  | // happen if the synchronous IPC message above has failed.  This can | 
|  | // legitimately happen when the browser process has already destroyed | 
|  | // RenderProcessHost, but the renderer process hasn't quit yet. | 
|  | return nullptr; | 
|  | } | 
|  |  | 
|  | DCHECK(params_reply.new_interface_provider.is_valid()); | 
|  | service_manager::mojom::InterfaceProviderPtr child_interface_provider; | 
|  | child_interface_provider.Bind( | 
|  | service_manager::mojom::InterfaceProviderPtrInfo( | 
|  | mojo::ScopedMessagePipeHandle(params_reply.new_interface_provider), | 
|  | 0u), | 
|  | GetTaskRunner(blink::TaskType::kInternalIPC)); | 
|  |  | 
|  | DCHECK(params_reply.document_interface_broker_content_handle.is_valid()); | 
|  | DCHECK(params_reply.document_interface_broker_blink_handle.is_valid()); | 
|  |  | 
|  | blink::mojom::DocumentInterfaceBrokerPtr document_interface_broker_content; | 
|  | document_interface_broker_content.Bind( | 
|  | blink::mojom::DocumentInterfaceBrokerPtrInfo( | 
|  | mojo::ScopedMessagePipeHandle( | 
|  | params_reply.document_interface_broker_content_handle), | 
|  | blink::mojom::DocumentInterfaceBroker::Version_), | 
|  | GetTaskRunner(blink::TaskType::kInternalIPC)); | 
|  |  | 
|  | blink::mojom::DocumentInterfaceBrokerPtr document_interface_broker_blink; | 
|  | document_interface_broker_blink.Bind( | 
|  | blink::mojom::DocumentInterfaceBrokerPtrInfo( | 
|  | mojo::ScopedMessagePipeHandle( | 
|  | params_reply.document_interface_broker_blink_handle), | 
|  | blink::mojom::DocumentInterfaceBroker::Version_), | 
|  | GetTaskRunner(blink::TaskType::kInternalIPC)); | 
|  |  | 
|  | // This method is always called by local frames, never remote frames. | 
|  |  | 
|  | // Tracing analysis uses this to find main frames when this value is | 
|  | // MSG_ROUTING_NONE, and build the frame tree otherwise. | 
|  | TRACE_EVENT2("navigation,rail", "RenderFrameImpl::createChildFrame", "id", | 
|  | routing_id_, "child", params_reply.child_routing_id); | 
|  |  | 
|  | // Create the RenderFrame and WebLocalFrame, linking the two. | 
|  | RenderFrameImpl* child_render_frame = | 
|  | RenderFrameImpl::Create(render_view_, params_reply.child_routing_id, | 
|  | std::move(child_interface_provider), | 
|  | std::move(document_interface_broker_content), | 
|  | params_reply.devtools_frame_token); | 
|  | child_render_frame->unique_name_helper_.set_propagated_name( | 
|  | params.frame_unique_name); | 
|  | if (params.is_created_by_script) | 
|  | child_render_frame->unique_name_helper_.Freeze(); | 
|  | child_render_frame->InitializeBlameContext(this); | 
|  | blink::WebLocalFrame* web_frame = parent->CreateLocalChild( | 
|  | scope, child_render_frame, | 
|  | child_render_frame->blink_interface_registry_.get(), | 
|  | document_interface_broker_blink.PassInterface().PassHandle()); | 
|  |  | 
|  | child_render_frame->in_frame_tree_ = true; | 
|  | child_render_frame->Initialize(); | 
|  |  | 
|  | return web_frame; | 
|  | } | 
|  |  | 
|  | std::pair<blink::WebRemoteFrame*, base::UnguessableToken> | 
|  | RenderFrameImpl::CreatePortal(mojo::ScopedInterfaceEndpointHandle pipe) { | 
|  | int proxy_routing_id = MSG_ROUTING_NONE; | 
|  | base::UnguessableToken portal_token; | 
|  | GetFrameHost()->CreatePortal( | 
|  | blink::mojom::PortalAssociatedRequest(std::move(pipe)), &proxy_routing_id, | 
|  | &portal_token); | 
|  | RenderFrameProxy* proxy = | 
|  | RenderFrameProxy::CreateProxyForPortal(this, proxy_routing_id); | 
|  | return std::make_pair(proxy->web_frame(), portal_token); | 
|  | } | 
|  |  | 
|  | blink::WebRemoteFrame* RenderFrameImpl::AdoptPortal( | 
|  | const base::UnguessableToken& portal_token) { | 
|  | int proxy_routing_id = MSG_ROUTING_NONE; | 
|  | GetFrameHost()->AdoptPortal(portal_token, &proxy_routing_id); | 
|  | RenderFrameProxy* proxy = | 
|  | RenderFrameProxy::CreateProxyForPortal(this, proxy_routing_id); | 
|  | return proxy->web_frame(); | 
|  | } | 
|  |  | 
|  | blink::WebFrame* RenderFrameImpl::FindFrame(const blink::WebString& name) { | 
|  | if (render_view_->renderer_wide_named_frame_lookup()) { | 
|  | for (const auto& it : g_routing_id_frame_map.Get()) { | 
|  | WebLocalFrame* frame = it.second->GetWebFrame(); | 
|  | if (frame->AssignedName() == name) | 
|  | return frame; | 
|  | } | 
|  | } | 
|  |  | 
|  | return GetContentClient()->renderer()->FindFrame(this->GetWebFrame(), | 
|  | name.Utf8()); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidChangeOpener(blink::WebFrame* opener) { | 
|  | // Only a local frame should be able to update another frame's opener. | 
|  | DCHECK(!opener || opener->IsWebLocalFrame()); | 
|  |  | 
|  | int opener_routing_id = | 
|  | opener ? RenderFrameImpl::FromWebFrame(opener->ToWebLocalFrame()) | 
|  | ->GetRoutingID() | 
|  | : MSG_ROUTING_NONE; | 
|  | Send(new FrameHostMsg_DidChangeOpener(routing_id_, opener_routing_id)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::FrameDetached(DetachType type) { | 
|  | for (auto& observer : observers_) | 
|  | observer.FrameDetached(); | 
|  |  | 
|  | // Send a state update before the frame is detached. | 
|  | SendUpdateState(); | 
|  |  | 
|  | // We only notify the browser process when the frame is being detached for | 
|  | // removal, not after a swap. | 
|  | if (type == DetachType::kRemove) | 
|  | Send(new FrameHostMsg_Detach(routing_id_)); | 
|  |  | 
|  | // Clean up the associated RenderWidget for the frame, if there is one. | 
|  | GetLocalRootRenderWidget()->UnregisterRenderFrame(this); | 
|  | if (is_main_frame_) { | 
|  | // TODO(crbug.com/419087): The RenderWidget for the main frame can't be | 
|  | // closed/destroyed since it is part of the RenderView. So instead it is | 
|  | // swapped out, which we would be in the middle of here. So instead of | 
|  | // closing the RenderWidget we only drop the WebFrameWidget in order to also | 
|  | // drop its reference on the WebLocalFrameImpl for this detaching frame. | 
|  | render_view_->DetachWebFrameWidget(); | 
|  | // In the main frame case, we WarmupCompositor() when setting up the | 
|  | // WebFrameWidget, because we can't unfreeze the RenderWidget until | 
|  | // navigation completes. If that navigation aborts then we detach the | 
|  | // provisional main frame, and drop the WebFrameWidget. Since we then no | 
|  | // longer expect to use this RenderWidget immediately, we drop any resources | 
|  | // that were being prepared. This is a no-op if the RenderWidget was already | 
|  | // unfrozen and not in a warming up state. | 
|  | render_widget_->AbortWarmupCompositor(); | 
|  | } else if (render_widget_) { | 
|  | // This closes/deletes the RenderWidget if this frame was a local root. | 
|  | render_widget_->CloseForFrame(); | 
|  | } | 
|  |  | 
|  | // We need to clean up subframes by removing them from the map and deleting | 
|  | // the RenderFrameImpl.  In contrast, the main frame is owned by its | 
|  | // containing RenderViewHost (so that they have the same lifetime), so only | 
|  | // removal from the map is needed and no deletion. | 
|  | 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); | 
|  |  | 
|  | // |frame_| may not be referenced after this, so clear the pointer since | 
|  | // the actual WebLocalFrame may not be deleted immediately and other methods | 
|  | // may try to access it. | 
|  | frame_->Close(); | 
|  | frame_ = nullptr; | 
|  |  | 
|  | // If this was a provisional frame with an associated proxy, tell the proxy | 
|  | // that it's no longer associated with this frame. | 
|  | if (previous_routing_id_ != MSG_ROUTING_NONE) { | 
|  | RenderFrameProxy* proxy = | 
|  | RenderFrameProxy::FromRoutingID(previous_routing_id_); | 
|  |  | 
|  | // |proxy| should always exist.  Detaching the proxy would've also detached | 
|  | // this provisional frame.  The proxy should also not be associated with | 
|  | // another provisional frame at this point. | 
|  | CHECK(proxy); | 
|  | CHECK_EQ(routing_id_, proxy->provisional_frame_routing_id()); | 
|  |  | 
|  | proxy->set_provisional_frame_routing_id(MSG_ROUTING_NONE); | 
|  | } | 
|  |  | 
|  | delete this; | 
|  | // Object is invalid after this point. | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::FrameFocused() { | 
|  | Send(new FrameHostMsg_FrameFocused(routing_id_)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidChangeName(const blink::WebString& name) { | 
|  | if (current_history_item_.IsNull()) { | 
|  | // Once a navigation has committed, the unique name must no longer change to | 
|  | // avoid breaking back/forward navigations: https://crbug.com/607205 | 
|  | unique_name_helper_.UpdateName(name.Utf8()); | 
|  | } | 
|  | GetFrameHost()->DidChangeName(name.Utf8(), unique_name_helper_.value()); | 
|  |  | 
|  | if (!committed_first_load_) | 
|  | name_changed_before_first_commit_ = true; | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidEnforceInsecureRequestPolicy( | 
|  | blink::WebInsecureRequestPolicy policy) { | 
|  | GetFrameHost()->EnforceInsecureRequestPolicy(policy); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidEnforceInsecureNavigationsSet( | 
|  | const std::vector<uint32_t>& set) { | 
|  | GetFrameHost()->EnforceInsecureNavigationsSet(set); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidChangeFramePolicy( | 
|  | blink::WebFrame* child_frame, | 
|  | const blink::FramePolicy& frame_policy) { | 
|  | Send(new FrameHostMsg_DidChangeFramePolicy( | 
|  | routing_id_, RenderFrame::GetRoutingIdForWebFrame(child_frame), | 
|  | frame_policy)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidSetFramePolicyHeaders( | 
|  | blink::WebSandboxFlags flags, | 
|  | const blink::ParsedFeaturePolicy& parsed_header) { | 
|  | // If either Feature Policy or Sandbox Flags are different from the default | 
|  | // (empty) values, then send them to the browser. | 
|  | if (!parsed_header.empty() || flags != blink::WebSandboxFlags::kNone) { | 
|  | GetFrameHost()->DidSetFramePolicyHeaders(flags, parsed_header); | 
|  | } | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidAddContentSecurityPolicies( | 
|  | const blink::WebVector<blink::WebContentSecurityPolicy>& policies) { | 
|  | std::vector<ContentSecurityPolicy> content_policies; | 
|  | for (const auto& policy : policies) | 
|  | content_policies.push_back(BuildContentSecurityPolicy(policy)); | 
|  |  | 
|  | Send(new FrameHostMsg_DidAddContentSecurityPolicies(routing_id_, | 
|  | content_policies)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidChangeFrameOwnerProperties( | 
|  | blink::WebFrame* child_frame, | 
|  | const blink::WebFrameOwnerProperties& frame_owner_properties) { | 
|  | Send(new FrameHostMsg_DidChangeFrameOwnerProperties( | 
|  | routing_id_, RenderFrame::GetRoutingIdForWebFrame(child_frame), | 
|  | ConvertWebFrameOwnerPropertiesToFrameOwnerProperties( | 
|  | frame_owner_properties))); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidMatchCSS( | 
|  | const blink::WebVector<blink::WebString>& newly_matching_selectors, | 
|  | const blink::WebVector<blink::WebString>& stopped_matching_selectors) { | 
|  | for (auto& observer : observers_) | 
|  | observer.DidMatchCSS(newly_matching_selectors, stopped_matching_selectors); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::UpdateUserActivationState( | 
|  | blink::UserActivationUpdateType update_type) { | 
|  | Send(new FrameHostMsg_UpdateUserActivationState(routing_id_, update_type)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::SetHasReceivedUserGestureBeforeNavigation(bool value) { | 
|  | Send(new FrameHostMsg_SetHasReceivedUserGestureBeforeNavigation(routing_id_, | 
|  | value)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::SetMouseCapture(bool capture) { | 
|  | GetLocalRootRenderWidget()->SetMouseCapture(capture); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::SetNeedsOcclusionTracking(bool needs_tracking) { | 
|  | Send(new FrameHostMsg_SetNeedsOcclusionTracking(routing_id_, needs_tracking)); | 
|  | } | 
|  |  | 
|  | bool RenderFrameImpl::ShouldReportDetailedMessageForSource( | 
|  | const blink::WebString& source) { | 
|  | 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) { | 
|  | logging::LogSeverity log_severity = logging::LOG_VERBOSE; | 
|  | switch (message.level) { | 
|  | case blink::mojom::ConsoleMessageLevel::kVerbose: | 
|  | log_severity = logging::LOG_VERBOSE; | 
|  | break; | 
|  | case blink::mojom::ConsoleMessageLevel::kInfo: | 
|  | log_severity = logging::LOG_INFO; | 
|  | break; | 
|  | case blink::mojom::ConsoleMessageLevel::kWarning: | 
|  | log_severity = logging::LOG_WARNING; | 
|  | break; | 
|  | case blink::mojom::ConsoleMessageLevel::kError: | 
|  | log_severity = logging::LOG_ERROR; | 
|  | break; | 
|  | default: | 
|  | log_severity = logging::LOG_VERBOSE; | 
|  | } | 
|  |  | 
|  | if (ShouldReportDetailedMessageForSource(source_name)) { | 
|  | for (auto& observer : observers_) { | 
|  | observer.DetailedConsoleMessageAdded( | 
|  | message.text.Utf16(), source_name.Utf16(), stack_trace.Utf16(), | 
|  | source_line, static_cast<uint32_t>(log_severity)); | 
|  | } | 
|  | } | 
|  |  | 
|  | Send(new FrameHostMsg_DidAddMessageToConsole( | 
|  | routing_id_, static_cast<int32_t>(log_severity), message.text.Utf16(), | 
|  | static_cast<int32_t>(source_line), source_name.Utf16())); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DownloadURL( | 
|  | const blink::WebURLRequest& request, | 
|  | CrossOriginRedirects cross_origin_redirect_behavior, | 
|  | mojo::ScopedMessagePipeHandle blob_url_token) { | 
|  | if (ShouldThrottleDownload()) | 
|  | return; | 
|  |  | 
|  | FrameHostMsg_DownloadUrl_Params params; | 
|  | params.render_view_id = render_view_->GetRoutingID(); | 
|  | params.render_frame_id = GetRoutingID(); | 
|  | params.url = request.Url(); | 
|  | params.referrer = RenderViewImpl::GetReferrerFromRequest(frame_, request); | 
|  | params.initiator_origin = request.RequestorOrigin(); | 
|  | if (request.GetSuggestedFilename().has_value()) | 
|  | params.suggested_name = request.GetSuggestedFilename()->Utf16(); | 
|  | params.follow_cross_origin_redirects = | 
|  | (cross_origin_redirect_behavior == CrossOriginRedirects::kFollow); | 
|  | params.blob_url_token = blob_url_token.release(); | 
|  |  | 
|  | Send(new FrameHostMsg_DownloadUrl(params)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::WillSendSubmitEvent(const blink::WebFormElement& form) { | 
|  | for (auto& observer : observers_) | 
|  | observer.WillSendSubmitEvent(form); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidCreateDocumentLoader( | 
|  | blink::WebDocumentLoader* document_loader) { | 
|  | DocumentState* document_state = | 
|  | DocumentState::FromDocumentLoader(document_loader); | 
|  | if (!document_state) { | 
|  | // This is either a placeholder document loader or an initial empty | 
|  | // document. | 
|  | document_loader->SetExtraData(BuildDocumentState()); | 
|  | document_loader->SetServiceWorkerNetworkProvider( | 
|  | ServiceWorkerNetworkProviderForFrame::CreateInvalidInstance()); | 
|  | } | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidStartProvisionalLoad( | 
|  | blink::WebDocumentLoader* document_loader) { | 
|  | // In fast/loader/stop-provisional-loads.html, we abort the load before this | 
|  | // callback is invoked. | 
|  | if (!document_loader) | 
|  | return; | 
|  |  | 
|  | TRACE_EVENT2("navigation,benchmark,rail", | 
|  | "RenderFrameImpl::didStartProvisionalLoad", "id", routing_id_, | 
|  | "url", document_loader->GetUrl().GetString().Utf8()); | 
|  |  | 
|  | NavigationState* navigation_state = | 
|  | NavigationState::FromDocumentLoader(document_loader); | 
|  | // TODO(dgozman): call DidStartNavigation in various places where we call | 
|  | // CommitNavigation() on the frame. This will happen naturally once we remove | 
|  | // WebLocalFrameClient::DidStartProvisionalLoad. | 
|  | if (!navigation_state->was_initiated_in_this_frame()) { | 
|  | // Navigation initiated in this frame has been already reported in | 
|  | // BeginNavigation. | 
|  | for (auto& observer : observers_) | 
|  | observer.DidStartNavigation(document_loader->GetUrl(), base::nullopt); | 
|  | } | 
|  |  | 
|  | for (auto& observer : observers_) | 
|  | observer.ReadyToCommitNavigation(document_loader); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidCommitProvisionalLoad( | 
|  | const blink::WebHistoryItem& item, | 
|  | blink::WebHistoryCommitType commit_type, | 
|  | mojo::ScopedMessagePipeHandle document_interface_broker_blink_handle) { | 
|  | TRACE_EVENT2("navigation,rail", "RenderFrameImpl::didCommitProvisionalLoad", | 
|  | "id", routing_id_, | 
|  | "url", GetLoadingUrl().possibly_invalid_spec()); | 
|  | // TODO(dcheng): Remove this UMA once we have enough measurements. | 
|  | // Record the number of subframes where window.name changes between the | 
|  | // creation of the frame and the first commit that records a history entry | 
|  | // with a persisted unique name. We'd like to make unique name immutable to | 
|  | // simplify code, but it's unclear if there are site that depend on the | 
|  | // following pattern: | 
|  | //   1. Create a new subframe. | 
|  | //   2. Assign it a window.name. | 
|  | //   3. Navigate it. | 
|  | // | 
|  | // If unique name are immutable, then it's possible that session history would | 
|  | // become less reliable for subframes: | 
|  | //   * A subframe with no initial name will receive a generated name that | 
|  | //     depends on DOM insertion order instead of using a name baed on the | 
|  | //     window.name assigned in step 2. | 
|  | //   * A subframe may intentionally try to choose a non-conflicting | 
|  | //     window.name if it detects a conflict. Immutability would prevent this | 
|  | //     from having the desired effect. | 
|  | // | 
|  | // The logic for when to record the UMA is a bit subtle: | 
|  | //   * if |committed_first_load_| is false and |current_history_item_| is | 
|  | //     null, then this is being called to commit the initial empty document. | 
|  | //     Don't record the UMA yet. |current_history_item_| will be non-null in | 
|  | //     subsequent invocations of this callback. | 
|  | //   * if |committed_first_load_| is false and |current_history_item_| is | 
|  | //     *not* null, then the initial empty document has already committed. | 
|  | //     Record if window.name has changed. | 
|  | if (!committed_first_load_ && !current_history_item_.IsNull()) { | 
|  | if (!IsMainFrame()) { | 
|  | UMA_HISTOGRAM_BOOLEAN( | 
|  | "SessionRestore.SubFrameUniqueNameChangedBeforeFirstCommit", | 
|  | name_changed_before_first_commit_); | 
|  | } | 
|  | // TODO(dcheng): This signal is likely calculated incorrectly, and will be | 
|  | // removed in a followup CL (as we've decided to try to preserve backwards | 
|  | // compatibility as much as possible for the time being). | 
|  | committed_first_load_ = true; | 
|  | } | 
|  |  | 
|  | InternalDocumentStateData* internal_data = | 
|  | InternalDocumentStateData::FromDocumentLoader( | 
|  | frame_->GetDocumentLoader()); | 
|  | NavigationState* navigation_state = internal_data->navigation_state(); | 
|  | DCHECK(!navigation_state->WasWithinSameDocument()); | 
|  |  | 
|  | // Only update the PreviewsState and effective connection type states for new | 
|  | // main frame documents. Subframes inherit from the main frame and should not | 
|  | // change at commit time. | 
|  | if (is_main_frame_) { | 
|  | previews_state_ = internal_data->previews_state(); | 
|  | effective_connection_type_ = | 
|  | EffectiveConnectionTypeToWebEffectiveConnectionType( | 
|  | internal_data->effective_connection_type()); | 
|  | } | 
|  |  | 
|  | if (previous_routing_id_ != MSG_ROUTING_NONE) { | 
|  | // If this is a provisional frame associated with a proxy (i.e., a frame | 
|  | // created for a remote-to-local navigation), swap it into the frame tree | 
|  | // now. | 
|  | if (!SwapIn()) | 
|  | return; | 
|  | } | 
|  |  | 
|  | // Navigations that change the document represent a new content source.  Keep | 
|  | // track of that on the widget to help the browser process detect when stale | 
|  | // compositor frames are being shown after a commit. | 
|  | if (is_main_frame_) { | 
|  | GetLocalRootRenderWidget()->DidNavigate(); | 
|  |  | 
|  | // Update the URL used to key Ukm metrics in the compositor if the | 
|  | // navigation is not in the same document, which represents a new source | 
|  | // URL. | 
|  | // Note that this is only done for the main frame since the metrics for all | 
|  | // frames are keyed to the main frame's URL. | 
|  | GetLocalRootRenderWidget()->layer_tree_view()->SetURLForUkm( | 
|  | GetLoadingUrl()); | 
|  | } | 
|  |  | 
|  | service_manager::mojom::InterfaceProviderRequest | 
|  | remote_interface_provider_request; | 
|  | blink::mojom::DocumentInterfaceBrokerRequest | 
|  | document_interface_broker_request; | 
|  |  | 
|  | // blink passes a valid DocumentInterfaceBroker handle when the new pipe needs | 
|  | // to be bound. | 
|  | if (document_interface_broker_blink_handle.is_valid()) { | 
|  | // If we're navigating to a new document, bind |remote_interfaces_| to a new | 
|  | // message pipe. The request end of the new InterfaceProvider interface will | 
|  | // be sent over as part of DidCommitProvisionalLoad. After the RFHI receives | 
|  | // the commit confirmation, it will immediately close the old message pipe | 
|  | // to avoid GetInterface calls racing with navigation commit, and bind the | 
|  | // request end of the message pipe created here. | 
|  | service_manager::mojom::InterfaceProviderPtr interfaces_provider; | 
|  | remote_interface_provider_request = mojo::MakeRequest(&interfaces_provider); | 
|  |  | 
|  | // Must initialize |remote_interfaces_| with a new working pipe *before* | 
|  | // observers receive DidCommitProvisionalLoad, so they can already request | 
|  | // remote interfaces. The interface requests will be serviced once the | 
|  | // InterfaceProvider interface request is bound by the RenderFrameHostImpl. | 
|  | remote_interfaces_.Close(); | 
|  | remote_interfaces_.Bind(std::move(interfaces_provider)); | 
|  |  | 
|  | // If we're navigating to a new document, bind |document_interface_broker_| | 
|  | // to a new message pipe. The request end of the new DocumentInterfaceBroker | 
|  | // interface will be sent over as part of DidCommitProvisionalLoad. After | 
|  | // the RFHI receives the commit confirmation, it will immediately close the | 
|  | // old message pipe to avoid Get<interface> calls racing with navigation | 
|  | // commit, and bind the request end of the message pipe created here. Must | 
|  | // initialize |document_interface_broker_| with a new working pipe *before* | 
|  | // observers receive DidCommitProvisionalLoad, so they can already request | 
|  | // remote interfaces. The interface requests will be serviced once the | 
|  | // DocumentInterfaceBroker interface request is bound by the | 
|  | // RenderFrameHostImpl. | 
|  | document_interface_broker_.reset(); | 
|  | document_interface_broker_request = | 
|  | mojo::MakeRequest(&document_interface_broker_); | 
|  |  | 
|  | // AudioOutputIPCFactory may be null in tests. | 
|  | if (auto* factory = AudioOutputIPCFactory::get()) { | 
|  | // The RendererAudioOutputStreamFactory must be readily accessible on the | 
|  | // IO thread when it's needed, because the main thread may block while | 
|  | // waiting for the factory call to finish on the IO thread, so if we tried | 
|  | // to lazily initialize it, we could deadlock. | 
|  | // | 
|  | // TODO(https://crbug.com/668275): Still, it is odd for one specific | 
|  | // factory to be registered here, make this a RenderFrameObserver. | 
|  | // code. | 
|  | factory->MaybeDeregisterRemoteFactory(GetRoutingID()); | 
|  | factory->RegisterRemoteFactory(GetRoutingID(), GetRemoteInterfaces()); | 
|  | } | 
|  |  | 
|  | // If the request for |audio_input_stream_factory_| is in flight when | 
|  | // |remote_interfaces_| is reset, it will be silently dropped. We reset | 
|  | // |audio_input_stream_factory_| to force a new mojo request to be sent | 
|  | // the next time it's used. See https://crbug.com/795258 for implementing a | 
|  | // nicer solution. | 
|  | audio_input_stream_factory_.reset(); | 
|  | } | 
|  |  | 
|  | // Notify the MediaPermissionDispatcher that its connection will be closed | 
|  | // due to a navigation to a different document. | 
|  | if (media_permission_dispatcher_) | 
|  | media_permission_dispatcher_->OnNavigation(); | 
|  |  | 
|  | if (!navigation_state->uses_per_navigation_mojo_interface()) { | 
|  | navigation_state->RunCommitNavigationCallback( | 
|  | blink::mojom::CommitResult::Ok); | 
|  | } | 
|  |  | 
|  | ui::PageTransition transition = GetTransitionType( | 
|  | frame_->GetDocumentLoader(), IsMainFrame(), true /* loading */); | 
|  |  | 
|  | DidCommitNavigationInternal( | 
|  | item, commit_type, false /* was_within_same_document */, transition, | 
|  | document_interface_broker_blink_handle.is_valid() | 
|  | ? mojom::DidCommitProvisionalLoadInterfaceParams::New( | 
|  | std::move(remote_interface_provider_request), | 
|  | std::move(document_interface_broker_request), | 
|  | blink::mojom::DocumentInterfaceBrokerRequest( | 
|  | std::move(document_interface_broker_blink_handle))) | 
|  | : nullptr); | 
|  |  | 
|  | // Record time between receiving the message to commit the navigation until it | 
|  | // has committed. Only successful cross-document navigation handled by the | 
|  | // browser process are taken into account. | 
|  | if (!navigation_state->time_commit_requested().is_null()) { | 
|  | RecordReadyToCommitUntilCommitHistogram( | 
|  | base::TimeTicks::Now() - navigation_state->time_commit_requested(), | 
|  | transition); | 
|  | } | 
|  |  | 
|  | // If we end up reusing this WebRequest (for example, due to a #ref click), | 
|  | // we don't want the transition type to persist.  Just clear it. | 
|  | navigation_state->set_transition_type(ui::PAGE_TRANSITION_LINK); | 
|  |  | 
|  | // Check whether we have new encoding name. | 
|  | UpdateEncoding(frame_, frame_->View()->PageEncoding().Utf8()); | 
|  |  | 
|  | // Reset warning state that prevents log spam. | 
|  | certificate_warning_origins_.clear(); | 
|  | tls_version_warning_origins_.clear(); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidCreateNewDocument() { | 
|  | for (auto& observer : observers_) | 
|  | observer.DidCreateNewDocument(); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidClearWindowObject() { | 
|  | if (enabled_bindings_ & BINDINGS_POLICY_WEB_UI) | 
|  | WebUIExtension::Install(frame_); | 
|  |  | 
|  | if (enabled_bindings_ & BINDINGS_POLICY_DOM_AUTOMATION) | 
|  | DomAutomationController::Install(this, frame_); | 
|  |  | 
|  | if (enabled_bindings_ & BINDINGS_POLICY_STATS_COLLECTION) | 
|  | StatsCollectionController::Install(frame_); | 
|  |  | 
|  | const base::CommandLine& command_line = | 
|  | *base::CommandLine::ForCurrentProcess(); | 
|  |  | 
|  | if (command_line.HasSwitch(cc::switches::kEnableGpuBenchmarking)) | 
|  | GpuBenchmarking::Install(this); | 
|  |  | 
|  | if (command_line.HasSwitch(switches::kEnableSkiaBenchmarking)) | 
|  | SkiaBenchmarking::Install(frame_); | 
|  |  | 
|  | for (auto& observer : render_view_->observers()) | 
|  | observer.DidClearWindowObject(frame_); | 
|  | for (auto& observer : observers_) | 
|  | observer.DidClearWindowObject(); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidCreateDocumentElement() { | 
|  | // Notify the browser about non-blank documents loading in the top frame. | 
|  | GURL url = frame_->GetDocument().Url(); | 
|  | if (url.is_valid() && url.spec() != url::kAboutBlankURL) { | 
|  | // TODO(nasko): Check if webview()->mainFrame() is the same as the | 
|  | // frame_->tree()->top(). | 
|  | blink::WebFrame* main_frame = render_view_->webview()->MainFrame(); | 
|  | if (frame_ == main_frame) { | 
|  | // For now, don't remember plugin zoom values.  We don't want to mix them | 
|  | // with normal web content (i.e. a fixed layout plugin would usually want | 
|  | // them different). | 
|  | render_view_->Send(new ViewHostMsg_DocumentAvailableInMainFrame( | 
|  | render_view_->GetRoutingID(), | 
|  | frame_->GetDocument().IsPluginDocument())); | 
|  | } | 
|  | } | 
|  |  | 
|  | for (auto& observer : observers_) | 
|  | observer.DidCreateDocumentElement(); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::RunScriptsAtDocumentElementAvailable() { | 
|  | GetContentClient()->renderer()->RunScriptsAtDocumentStart(this); | 
|  | // Do not use |this|! ContentClient might have deleted them by now! | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidReceiveTitle(const blink::WebString& title, | 
|  | blink::WebTextDirection direction) { | 
|  | // Ignore all but top level navigations. | 
|  | if (!frame_->Parent()) { | 
|  | base::trace_event::TraceLog::GetInstance()->UpdateProcessLabel( | 
|  | routing_id_, title.Utf8()); | 
|  |  | 
|  | base::string16 title16 = title.Utf16(); | 
|  | base::string16 shortened_title = title16.substr(0, kMaxTitleChars); | 
|  | Send(new FrameHostMsg_UpdateTitle(routing_id_, | 
|  | shortened_title, direction)); | 
|  | } else { | 
|  | // Set process title for sub-frames in traces. | 
|  | GURL loading_url = GetLoadingUrl(); | 
|  | if (!loading_url.host().empty() && | 
|  | loading_url.scheme() != url::kFileScheme) { | 
|  | std::string subframe_title = "Subframe: " + loading_url.scheme() + | 
|  | url::kStandardSchemeSeparator + | 
|  | loading_url.host(); | 
|  | base::trace_event::TraceLog::GetInstance()->UpdateProcessLabel( | 
|  | routing_id_, subframe_title); | 
|  | } | 
|  | } | 
|  |  | 
|  | // Also check whether we have new encoding name. | 
|  | UpdateEncoding(frame_, frame_->View()->PageEncoding().Utf8()); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidChangeIcon(blink::WebIconURL::Type icon_type) { | 
|  | SendUpdateFaviconURL(); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::SendUpdateFaviconURL() { | 
|  | if (frame_->Parent()) | 
|  | return; | 
|  |  | 
|  | blink::WebIconURL::Type icon_types_mask = | 
|  | static_cast<blink::WebIconURL::Type>( | 
|  | blink::WebIconURL::kTypeFavicon | | 
|  | blink::WebIconURL::kTypeTouchPrecomposed | | 
|  | blink::WebIconURL::kTypeTouch); | 
|  |  | 
|  | WebVector<blink::WebIconURL> icon_urls = frame_->IconURLs(icon_types_mask); | 
|  | if (icon_urls.empty()) | 
|  | return; | 
|  |  | 
|  | std::vector<FaviconURL> urls; | 
|  | urls.reserve(icon_urls.size()); | 
|  | for (const blink::WebIconURL& icon_url : icon_urls) { | 
|  | urls.push_back(FaviconURL(icon_url.GetIconURL(), | 
|  | ToFaviconType(icon_url.IconType()), | 
|  | ConvertToFaviconSizes(icon_url.Sizes()))); | 
|  | } | 
|  | DCHECK_EQ(icon_urls.size(), urls.size()); | 
|  |  | 
|  | Send(new FrameHostMsg_UpdateFaviconURL(GetRoutingID(), urls)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidFinishDocumentLoad() { | 
|  | TRACE_EVENT1("navigation,benchmark,rail", | 
|  | "RenderFrameImpl::didFinishDocumentLoad", "id", routing_id_); | 
|  | Send(new FrameHostMsg_DidFinishDocumentLoad(routing_id_)); | 
|  |  | 
|  | for (auto& observer : observers_) | 
|  | observer.DidFinishDocumentLoad(); | 
|  |  | 
|  | // Check whether we have new encoding name. | 
|  | UpdateEncoding(frame_, frame_->View()->PageEncoding().Utf8()); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::RunScriptsAtDocumentReady(bool document_is_empty) { | 
|  | base::WeakPtr<RenderFrameImpl> weak_self = weak_factory_.GetWeakPtr(); | 
|  |  | 
|  | GetContentClient()->renderer()->RunScriptsAtDocumentEnd(this); | 
|  |  | 
|  | // ContentClient might have deleted |frame_| and |this| by now! | 
|  | if (!weak_self.get()) | 
|  | return; | 
|  |  | 
|  | // If this is an empty document with an http status code indicating an error, | 
|  | // we may want to display our own error page, so the user doesn't end up | 
|  | // with an unexplained blank page. | 
|  | if (!document_is_empty) | 
|  | return; | 
|  |  | 
|  | // Display error page instead of a blank page, if appropriate. | 
|  | InternalDocumentStateData* internal_data = | 
|  | InternalDocumentStateData::FromDocumentLoader( | 
|  | frame_->GetDocumentLoader()); | 
|  | int http_status_code = internal_data->http_status_code(); | 
|  | if (GetContentClient()->renderer()->HasErrorPage(http_status_code)) { | 
|  | WebDocumentLoader* document_loader = frame_->GetDocumentLoader(); | 
|  | WebURL unreachable_url = frame_->GetDocument().Url(); | 
|  | std::string error_html; | 
|  | GetContentClient()->renderer()->PrepareErrorPageForHttpStatusError( | 
|  | this, unreachable_url, document_loader->HttpMethod().Ascii(), | 
|  | false /* ignoring_cache */, http_status_code, &error_html); | 
|  | // This call may run scripts, e.g. via the beforeunload event, and possibly | 
|  | // delete |this|. | 
|  | LoadNavigationErrorPage(document_loader, | 
|  | WebURLError(net::ERR_FAILED, unreachable_url), | 
|  | error_html, true /* replace_current_item */, | 
|  | false /* inherit_document_state */); | 
|  | if (!weak_self) | 
|  | return; | 
|  | // Do not use |this| or |frame_| here without checking |weak_self|. | 
|  | } | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::RunScriptsAtDocumentIdle() { | 
|  | GetContentClient()->renderer()->RunScriptsAtDocumentIdle(this); | 
|  | // ContentClient might have deleted |this| by now! | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidHandleOnloadEvents() { | 
|  | if (!frame_->Parent()) { | 
|  | GetFrameHost()->DocumentOnLoadCompleted(); | 
|  | } | 
|  | for (auto& observer : observers_) | 
|  | observer.DidHandleOnloadEvents(); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidFailLoad(const WebURLError& error, | 
|  | blink::WebHistoryCommitType commit_type) { | 
|  | TRACE_EVENT1("navigation,rail", "RenderFrameImpl::didFailLoad", | 
|  | "id", routing_id_); | 
|  | // TODO(nasko): Move implementation here. No state needed. | 
|  | WebDocumentLoader* document_loader = frame_->GetDocumentLoader(); | 
|  | DCHECK(document_loader); | 
|  |  | 
|  | base::string16 error_description; | 
|  | GetContentClient()->renderer()->GetErrorDescription( | 
|  | error, document_loader->HttpMethod().Ascii(), &error_description); | 
|  | Send(new FrameHostMsg_DidFailLoadWithError( | 
|  | routing_id_, document_loader->GetUrl(), error.reason(), | 
|  | error_description)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidFinishLoad() { | 
|  | TRACE_EVENT1("navigation,benchmark,rail", | 
|  | "RenderFrameImpl::didFinishLoad", "id", routing_id_); | 
|  | if (!frame_->Parent()) { | 
|  | TRACE_EVENT_INSTANT0("WebCore,benchmark,rail", "LoadFinished", | 
|  | TRACE_EVENT_SCOPE_PROCESS); | 
|  | } | 
|  |  | 
|  | for (auto& observer : observers_) | 
|  | observer.DidFinishLoad(); | 
|  |  | 
|  | WebDocumentLoader* document_loader = frame_->GetDocumentLoader(); | 
|  | Send(new FrameHostMsg_DidFinishLoad(routing_id_, document_loader->GetUrl())); | 
|  |  | 
|  | if (!RenderThreadImpl::current()) | 
|  | return; | 
|  | RenderThreadImpl::RendererMemoryMetrics memory_metrics; | 
|  | if (!RenderThreadImpl::current()->GetRendererMemoryMetrics(&memory_metrics)) | 
|  | return; | 
|  | RecordSuffixedRendererMemoryMetrics(memory_metrics, ".DidFinishLoad"); | 
|  | if (!IsMainFrame()) | 
|  | return; | 
|  | RecordSuffixedRendererMemoryMetrics(memory_metrics, | 
|  | ".MainFrameDidFinishLoad"); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidFinishSameDocumentNavigation( | 
|  | const blink::WebHistoryItem& item, | 
|  | blink::WebHistoryCommitType commit_type, | 
|  | bool content_initiated) { | 
|  | TRACE_EVENT1("navigation,rail", | 
|  | "RenderFrameImpl::didFinishSameDocumentNavigation", "id", | 
|  | routing_id_); | 
|  | InternalDocumentStateData* data = | 
|  | InternalDocumentStateData::FromDocumentLoader( | 
|  | frame_->GetDocumentLoader()); | 
|  | if (content_initiated) | 
|  | data->set_navigation_state(NavigationState::CreateContentInitiated()); | 
|  | data->navigation_state()->set_was_within_same_document(true); | 
|  |  | 
|  | ui::PageTransition transition = GetTransitionType( | 
|  | frame_->GetDocumentLoader(), IsMainFrame(), true /* loading */); | 
|  | DidCommitNavigationInternal(item, commit_type, | 
|  | // was_within_same_document | 
|  | true, transition, | 
|  | // interface_params | 
|  | nullptr); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidUpdateCurrentHistoryItem() { | 
|  | render_view_->StartNavStateSyncTimerIfNecessary(this); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidChangeThemeColor() { | 
|  | if (frame_->Parent()) | 
|  | return; | 
|  |  | 
|  | Send(new FrameHostMsg_DidChangeThemeColor( | 
|  | routing_id_, frame_->GetDocument().ThemeColor())); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::ForwardResourceTimingToParent( | 
|  | const blink::WebResourceTimingInfo& info) { | 
|  | Send(new FrameHostMsg_ForwardResourceTimingToParent( | 
|  | routing_id_, WebResourceTimingInfoToResourceTimingInfo(info))); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DispatchLoad() { | 
|  | Send(new FrameHostMsg_DispatchLoad(routing_id_)); | 
|  | } | 
|  |  | 
|  | blink::WebEffectiveConnectionType | 
|  | RenderFrameImpl::GetEffectiveConnectionType() { | 
|  | return effective_connection_type_; | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::SetEffectiveConnectionTypeForTesting( | 
|  | blink::WebEffectiveConnectionType type) { | 
|  | effective_connection_type_ = type; | 
|  | } | 
|  |  | 
|  | blink::WebURLRequest::PreviewsState RenderFrameImpl::GetPreviewsStateForFrame() | 
|  | const { | 
|  | PreviewsState disabled_state = previews_state_ & kDisabledPreviewsBits; | 
|  | if (disabled_state) { | 
|  | // Sanity check disabled vs. enabled bits here before passing on. | 
|  | DCHECK(!(previews_state_ & ~kDisabledPreviewsBits)) << previews_state_; | 
|  | return disabled_state; | 
|  | } | 
|  | return static_cast<WebURLRequest::PreviewsState>(previews_state_); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidBlockFramebust(const WebURL& url) { | 
|  | Send(new FrameHostMsg_DidBlockFramebust(GetRoutingID(), url)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::NavigateBackForwardSoon(int offset, | 
|  | bool has_user_gesture) { | 
|  | render_view()->NavigateBackForwardSoon(offset, has_user_gesture); | 
|  | Send(new FrameHostMsg_GoToEntryAtOffset(GetRoutingID(), offset, | 
|  | has_user_gesture)); | 
|  | } | 
|  |  | 
|  | base::UnguessableToken RenderFrameImpl::GetDevToolsFrameToken() { | 
|  | return devtools_frame_token_; | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::RenderFallbackContentInParentProcess() { | 
|  | Send(new FrameHostMsg_RenderFallbackContentInParentProcess(routing_id_)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::AbortClientNavigation() { | 
|  | browser_side_navigation_pending_ = false; | 
|  | sync_navigation_callback_.Cancel(); | 
|  | mhtml_body_loader_client_.reset(); | 
|  | if (!IsPerNavigationMojoInterfaceEnabled()) | 
|  | Send(new FrameHostMsg_AbortNavigation(routing_id_)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidChangeSelection(bool is_empty_selection) { | 
|  | if (!GetLocalRootRenderWidget()->input_handler().handling_input_event() && | 
|  | !handling_select_range_) | 
|  | return; | 
|  |  | 
|  | if (is_empty_selection) | 
|  | selection_text_.clear(); | 
|  |  | 
|  | // UpdateTextInputState should be called before SyncSelectionIfRequired. | 
|  | // UpdateTextInputState may send TextInputStateChanged to notify the focus | 
|  | // was changed, and SyncSelectionIfRequired may send SelectionChanged | 
|  | // to notify the selection was changed.  Focus change should be notified | 
|  | // before selection change. | 
|  | GetLocalRootRenderWidget()->UpdateTextInputState(); | 
|  | SyncSelectionIfRequired(); | 
|  | } | 
|  |  | 
|  | bool RenderFrameImpl::HandleCurrentKeyboardEvent() { | 
|  | bool did_execute_command = false; | 
|  | for (auto command : GetLocalRootRenderWidget()->edit_commands()) { | 
|  | // In gtk and cocoa, it's possible to bind multiple edit commands to one | 
|  | // key (but it's the exception). Once one edit command is not executed, it | 
|  | // seems safest to not execute the rest. | 
|  | if (!frame_->ExecuteCommand(blink::WebString::FromUTF8(command.name), | 
|  | blink::WebString::FromUTF8(command.value))) | 
|  | break; | 
|  | did_execute_command = true; | 
|  | } | 
|  |  | 
|  | return did_execute_command; | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::RunModalAlertDialog(const blink::WebString& message) { | 
|  | RunJavaScriptDialog(JAVASCRIPT_DIALOG_TYPE_ALERT, message.Utf16(), | 
|  | base::string16(), nullptr); | 
|  | } | 
|  |  | 
|  | bool RenderFrameImpl::RunModalConfirmDialog(const blink::WebString& message) { | 
|  | return RunJavaScriptDialog(JAVASCRIPT_DIALOG_TYPE_CONFIRM, message.Utf16(), | 
|  | base::string16(), nullptr); | 
|  | } | 
|  |  | 
|  | bool RenderFrameImpl::RunModalPromptDialog( | 
|  | const blink::WebString& message, | 
|  | const blink::WebString& default_value, | 
|  | blink::WebString* actual_value) { | 
|  | base::string16 result; | 
|  | bool ok = RunJavaScriptDialog(JAVASCRIPT_DIALOG_TYPE_PROMPT, message.Utf16(), | 
|  | default_value.Utf16(), &result); | 
|  | if (ok) | 
|  | *actual_value = WebString::FromUTF16(result); | 
|  | return ok; | 
|  | } | 
|  |  | 
|  | bool RenderFrameImpl::RunModalBeforeUnloadDialog(bool is_reload) { | 
|  | // Don't allow further dialogs if we are waiting to swap out, since the | 
|  | // ScopedPageLoadDeferrer in our stack prevents it. | 
|  | if (suppress_further_dialogs_) | 
|  | return false; | 
|  |  | 
|  | bool success = false; | 
|  | // This is an ignored return value, but is included so we can accept the same | 
|  | // response as RunJavaScriptDialog. | 
|  | base::string16 ignored_result; | 
|  | Send(new FrameHostMsg_RunBeforeUnloadConfirm(routing_id_, is_reload, &success, | 
|  | &ignored_result)); | 
|  | return success; | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::ShowContextMenu(const blink::WebContextMenuData& data) { | 
|  | ContextMenuParams params = ContextMenuParamsBuilder::Build(data); | 
|  | blink::WebRect position_in_window(params.x, params.y, 0, 0); | 
|  | GetLocalRootRenderWidget()->ConvertViewportToWindow(&position_in_window); | 
|  | params.x = position_in_window.x; | 
|  | params.y = position_in_window.y; | 
|  | GetLocalRootRenderWidget()->OnShowHostContextMenu(¶ms); | 
|  | if (GetLocalRootRenderWidget()->has_host_context_menu_location()) { | 
|  | params.x = GetLocalRootRenderWidget()->host_context_menu_location().x(); | 
|  | params.y = GetLocalRootRenderWidget()->host_context_menu_location().y(); | 
|  | } | 
|  |  | 
|  | // Serializing a GURL longer than kMaxURLChars will fail, so don't do | 
|  | // it.  We replace it with an empty GURL so the appropriate items are disabled | 
|  | // in the context menu. | 
|  | // TODO(jcivelli): http://crbug.com/45160 This prevents us from saving large | 
|  | //                 data encoded images.  We should have a way to save them. | 
|  | if (params.src_url.spec().size() > url::kMaxURLChars) | 
|  | params.src_url = GURL(); | 
|  |  | 
|  | blink::WebRect selection_in_window(data.selection_rect); | 
|  | GetLocalRootRenderWidget()->ConvertViewportToWindow(&selection_in_window); | 
|  | params.selection_rect = selection_in_window; | 
|  |  | 
|  | #if defined(OS_ANDROID) | 
|  | // The Samsung Email app relies on the context menu being shown after the | 
|  | // javascript onselectionchanged is triggered. | 
|  | // See crbug.com/729488 | 
|  | base::ThreadTaskRunnerHandle::Get()->PostTask( | 
|  | FROM_HERE, base::BindOnce(&RenderFrameImpl::ShowDeferredContextMenu, | 
|  | weak_factory_.GetWeakPtr(), params)); | 
|  | #else | 
|  | ShowDeferredContextMenu(params); | 
|  | #endif | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::ShowDeferredContextMenu(const ContextMenuParams& params) { | 
|  | Send(new FrameHostMsg_ContextMenu(routing_id_, params)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::SaveImageFromDataURL(const blink::WebString& data_url) { | 
|  | // Note: We should basically send GURL but we use size-limited string instead | 
|  | // in order to send a larger data url to save a image for <canvas> or <img>. | 
|  | if (data_url.length() < kMaxLengthOfDataURLString) { | 
|  | Send(new FrameHostMsg_SaveImageFromDataURL(render_view_->GetRoutingID(), | 
|  | routing_id_, data_url.Utf8())); | 
|  | } | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::FrameRectsChanged(const blink::WebRect& frame_rect) { | 
|  | // To limit the number of IPCs, only notify the browser when the rect's size | 
|  | // changes, not when the position changes. The size needs to be replicated if | 
|  | // the iframe goes out-of-process. | 
|  | gfx::Size frame_size(frame_rect.width, frame_rect.height); | 
|  | if (!frame_size_ || *frame_size_ != frame_size) { | 
|  | frame_size_ = frame_size; | 
|  | GetFrameHost()->FrameSizeChanged(frame_size); | 
|  | } | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::WillSendRequest(blink::WebURLRequest& request) { | 
|  | WebDocumentLoader* document_loader = frame_->GetDocumentLoader(); | 
|  | WillSendRequestInternal( | 
|  | request, WebURLRequestToResourceType(request), | 
|  | DocumentState::FromDocumentLoader(document_loader), | 
|  | GetTransitionType(document_loader, IsMainFrame(), false /* loading */)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::WillSendRequestInternal( | 
|  | blink::WebURLRequest& request, | 
|  | ResourceType resource_type, | 
|  | DocumentState* document_state, | 
|  | ui::PageTransition transition_type) { | 
|  | if (render_view_->renderer_preferences_.enable_do_not_track) | 
|  | request.SetHttpHeaderField(blink::WebString::FromUTF8(kDoNotTrackHeader), | 
|  | "1"); | 
|  |  | 
|  | InternalDocumentStateData* internal_data = | 
|  | InternalDocumentStateData::FromDocumentState(document_state); | 
|  | NavigationState* navigation_state = internal_data->navigation_state(); | 
|  |  | 
|  | ApplyFilePathAlias(&request); | 
|  | GURL new_url; | 
|  | bool attach_same_site_cookies = false; | 
|  | base::Optional<url::Origin> initiator_origin = | 
|  | request.RequestorOrigin().IsNull() | 
|  | ? base::Optional<url::Origin>() | 
|  | : base::Optional<url::Origin>(request.RequestorOrigin()); | 
|  | GetContentClient()->renderer()->WillSendRequest( | 
|  | frame_, transition_type, request.Url(), | 
|  | base::OptionalOrNullptr(initiator_origin), &new_url, | 
|  | &attach_same_site_cookies); | 
|  | if (!new_url.is_empty()) | 
|  | request.SetUrl(WebURL(new_url)); | 
|  |  | 
|  | if (internal_data->is_cache_policy_override_set()) | 
|  | request.SetCacheMode(internal_data->cache_policy_override()); | 
|  |  | 
|  | // The request's extra data may indicate that we should set a custom user | 
|  | // agent. This needs to be done here, after WebKit is through with setting the | 
|  | // user agent on its own. | 
|  | WebString custom_user_agent; | 
|  | std::unique_ptr<NavigationResponseOverrideParameters> response_override; | 
|  | if (request.GetExtraData()) { | 
|  | RequestExtraData* old_extra_data = | 
|  | static_cast<RequestExtraData*>(request.GetExtraData()); | 
|  |  | 
|  | custom_user_agent = old_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); | 
|  | } | 
|  | response_override = | 
|  | old_extra_data->TakeNavigationResponseOverrideOwnership(); | 
|  | } | 
|  |  | 
|  | // Set an empty HTTP origin header for non GET methods if none is currently | 
|  | // present. | 
|  | request.SetHttpOriginIfNeeded(WebSecurityOrigin::CreateUnique()); | 
|  |  | 
|  | WebDocument frame_document = frame_->GetDocument(); | 
|  | if (!request.GetExtraData()) | 
|  | request.SetExtraData(std::make_unique<RequestExtraData>()); | 
|  | auto* extra_data = static_cast<RequestExtraData*>(request.GetExtraData()); | 
|  | extra_data->set_is_preprerendering( | 
|  | GetContentClient()->renderer()->IsPrerenderingFrame(this)); | 
|  | extra_data->set_custom_user_agent(custom_user_agent); | 
|  | extra_data->set_render_frame_id(routing_id_); | 
|  | extra_data->set_is_main_frame(IsMainFrame()); | 
|  | extra_data->set_allow_download( | 
|  | navigation_state->common_params().download_policy.IsDownloadAllowed()); | 
|  | extra_data->set_transition_type(transition_type); | 
|  | extra_data->set_navigation_response_override(std::move(response_override)); | 
|  | bool is_for_no_state_prefetch = | 
|  | GetContentClient()->renderer()->IsPrefetchOnly(this, request); | 
|  | extra_data->set_is_for_no_state_prefetch(is_for_no_state_prefetch); | 
|  | extra_data->set_initiated_in_secure_context(frame_document.IsSecureContext()); | 
|  | extra_data->set_attach_same_site_cookies(attach_same_site_cookies); | 
|  | extra_data->set_frame_request_blocker(frame_request_blocker_); | 
|  |  | 
|  | request.SetDownloadToNetworkCacheOnly( | 
|  | is_for_no_state_prefetch && resource_type != ResourceType::kMainFrame); | 
|  |  | 
|  | // The RenderThreadImpl or its URLLoaderThrottleProvider member may not be | 
|  | // valid in some tests. | 
|  | RenderThreadImpl* render_thread = RenderThreadImpl::current(); | 
|  | if (render_thread && render_thread->url_loader_throttle_provider()) { | 
|  | extra_data->set_url_loader_throttles( | 
|  | render_thread->url_loader_throttle_provider()->CreateThrottles( | 
|  | routing_id_, request, resource_type)); | 
|  | } | 
|  |  | 
|  | if (request.GetPreviewsState() == WebURLRequest::kPreviewsUnspecified) { | 
|  | if (is_main_frame_ && !navigation_state->request_committed()) { | 
|  | request.SetPreviewsState(static_cast<WebURLRequest::PreviewsState>( | 
|  | navigation_state->common_params().previews_state)); | 
|  | } else { | 
|  | WebURLRequest::PreviewsState request_previews_state = | 
|  | static_cast<WebURLRequest::PreviewsState>(previews_state_); | 
|  |  | 
|  | // The decision of whether or not to enable Client Lo-Fi is made earlier | 
|  | // in the request lifetime, in LocalFrame::MaybeAllowImagePlaceholder(), | 
|  | // so don't add the Client Lo-Fi bit to the request here. | 
|  | request_previews_state &= ~(WebURLRequest::kClientLoFiOn); | 
|  | request_previews_state &= ~(WebURLRequest::kLazyImageLoadDeferred); | 
|  | if (request_previews_state == WebURLRequest::kPreviewsUnspecified) | 
|  | request_previews_state = WebURLRequest::kPreviewsOff; | 
|  |  | 
|  | request.SetPreviewsState(request_previews_state); | 
|  | } | 
|  | } | 
|  |  | 
|  | // This is an instance where we embed a copy of the routing id | 
|  | // into the data portion of the message. This can cause problems if we | 
|  | // don't register this id on the browser side, since the download manager | 
|  | // expects to find a RenderViewHost based off the id. | 
|  | request.SetRequestorID(render_view_->GetRoutingID()); | 
|  | request.SetHasUserGesture( | 
|  | WebUserGestureIndicator::IsProcessingUserGesture(frame_)); | 
|  |  | 
|  | if (!render_view_->renderer_preferences_.enable_referrers) | 
|  | request.SetHttpReferrer(WebString(), | 
|  | network::mojom::ReferrerPolicy::kDefault); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidLoadResourceFromMemoryCache( | 
|  | const blink::WebURLRequest& request, | 
|  | const blink::WebURLResponse& response) { | 
|  | // The recipients of this message have no use for data: URLs: they don't | 
|  | // affect the page's insecure content list and are not in the disk cache. To | 
|  | // prevent large (1M+) data: URLs from crashing in the IPC system, we simply | 
|  | // filter them out here. | 
|  | if (request.Url().ProtocolIs(url::kDataScheme)) | 
|  | return; | 
|  |  | 
|  | // Let the browser know we loaded a resource from the memory cache.  This | 
|  | // message is needed to display the correct SSL indicators. | 
|  | Send(new FrameHostMsg_DidLoadResourceFromMemoryCache( | 
|  | routing_id_, request.Url(), request.HttpMethod().Utf8(), | 
|  | response.MimeType().Utf8(), request.TopFrameOrigin(), | 
|  | WebURLRequestToResourceType(request))); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidStartResponse( | 
|  | const GURL& response_url, | 
|  | int request_id, | 
|  | const network::ResourceResponseHead& response_head, | 
|  | content::ResourceType resource_type, | 
|  | PreviewsState previews_state) { | 
|  | for (auto& observer : observers_) | 
|  | observer.DidStartResponse(response_url, request_id, response_head, | 
|  | resource_type, previews_state); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidCompleteResponse( | 
|  | int request_id, | 
|  | const network::URLLoaderCompletionStatus& status) { | 
|  | for (auto& observer : observers_) | 
|  | observer.DidCompleteResponse(request_id, status); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidCancelResponse(int request_id) { | 
|  | 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, received_data_length); | 
|  | } | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidDisplayInsecureContent() { | 
|  | Send(new FrameHostMsg_DidDisplayInsecureContent(routing_id_)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidContainInsecureFormAction() { | 
|  | Send(new FrameHostMsg_DidContainInsecureFormAction(routing_id_)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidRunInsecureContent( | 
|  | const blink::WebSecurityOrigin& origin, | 
|  | const blink::WebURL& target) { | 
|  | Send(new FrameHostMsg_DidRunInsecureContent( | 
|  | routing_id_, GURL(origin.ToString().Utf8()), target)); | 
|  | GetContentClient()->renderer()->RecordRapporURL( | 
|  | "ContentSettings.MixedScript.RanMixedScript", | 
|  | GURL(origin.ToString().Utf8())); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidDisplayContentWithCertificateErrors() { | 
|  | Send(new FrameHostMsg_DidDisplayContentWithCertificateErrors(routing_id_)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidRunContentWithCertificateErrors() { | 
|  | Send(new FrameHostMsg_DidRunContentWithCertificateErrors(routing_id_)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::ReportLegacyTLSVersion(const blink::WebURL& url) { | 
|  | url::Origin origin = url::Origin::Create(GURL(url)); | 
|  | // To prevent log spam, only log the message once per origin. | 
|  | if (base::ContainsKey(tls_version_warning_origins_, origin)) | 
|  | return; | 
|  |  | 
|  | size_t num_warnings = tls_version_warning_origins_.size(); | 
|  | // After |kMaxSecurityWarningMessages| warnings, stop printing messages to the | 
|  | // console. At exactly |kMaxSecurityWarningMessages| warnings, print a message | 
|  | // that additional resources on the page use legacy certificates without | 
|  | // specifying which exact resources. Before |kMaxSecurityWarningMessages| | 
|  | // messages, print the exact resource URL in the message to help the developer | 
|  | // pinpoint the problematic resources. | 
|  | if (num_warnings > kMaxSecurityWarningMessages) | 
|  | return; | 
|  |  | 
|  | // Allow the embedded to suppress these warnings. This is a workaround for an | 
|  | // outdated test server used by Blink tests on macOS. See | 
|  | // https://crbug.com/936515. | 
|  | if (GetContentClient() | 
|  | ->renderer() | 
|  | ->SuppressLegacyTLSVersionConsoleMessage()) { | 
|  | return; | 
|  | } | 
|  |  | 
|  | std::string console_message; | 
|  | if (num_warnings == kMaxSecurityWarningMessages) { | 
|  | console_message = | 
|  | "Additional resources on this page were loaded with TLS 1.0 or TLS " | 
|  | "1.1, which are deprecated and will be disabled in the future. Once " | 
|  | "disabled, users will be prevented from loading these resources. " | 
|  | "Servers should enable TLS 1.2 or later. See " | 
|  | "https://www.chromestatus.com/feature/5654791610957824 for more " | 
|  | "information."; | 
|  | } else { | 
|  | console_message = base::StringPrintf( | 
|  | "The connection used to load resources from %s used TLS 1.0 or TLS " | 
|  | "1.1, which are deprecated and will be disabled in the future. Once " | 
|  | "disabled, users will be prevented from loading these resources. The " | 
|  | "server should enable TLS 1.2 or later. See " | 
|  | "https://www.chromestatus.com/feature/5654791610957824 for more " | 
|  | "information.", | 
|  | origin.Serialize().c_str()); | 
|  | } | 
|  |  | 
|  | tls_version_warning_origins_.insert(origin); | 
|  | // To avoid spamming the console, use verbose message level for subframe | 
|  | // resources, and only use the warning level for main-frame resources. | 
|  | AddMessageToConsole(frame_->Parent() | 
|  | ? blink::mojom::ConsoleMessageLevel::kVerbose | 
|  | : blink::mojom::ConsoleMessageLevel::kWarning, | 
|  | console_message); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidChangePerformanceTiming() { | 
|  | for (auto& observer : observers_) | 
|  | observer.DidChangePerformanceTiming(); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidChangeCpuTiming(base::TimeDelta time) { | 
|  | for (auto& observer : observers_) | 
|  | observer.DidChangeCpuTiming(time); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidChangeActiveSchedulerTrackedFeatures( | 
|  | uint64_t features_mask) { | 
|  | GetFrameHost()->UpdateActiveSchedulerTrackedFeatures(features_mask); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidObserveLoadingBehavior( | 
|  | blink::WebLoadingBehaviorFlag behavior) { | 
|  | for (auto& observer : observers_) | 
|  | observer.DidObserveLoadingBehavior(behavior); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidObserveNewFeatureUsage( | 
|  | blink::mojom::WebFeature feature) { | 
|  | for (auto& observer : observers_) | 
|  | observer.DidObserveNewFeatureUsage(feature); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidObserveNewCssPropertyUsage(int css_property, | 
|  | bool is_animated) { | 
|  | for (auto& observer : observers_) | 
|  | observer.DidObserveNewCssPropertyUsage(css_property, is_animated); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidObserveLayoutJank(double jank_fraction) { | 
|  | for (auto& observer : observers_) | 
|  | observer.DidObserveLayoutJank(jank_fraction); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidObserveLazyLoadBehavior( | 
|  | WebLocalFrameClient::LazyLoadBehavior lazy_load_behavior) { | 
|  | for (auto& observer : observers_) | 
|  | observer.DidObserveLazyLoadBehavior(lazy_load_behavior); | 
|  | } | 
|  |  | 
|  | bool RenderFrameImpl::ShouldTrackUseCounter(const blink::WebURL& url) { | 
|  | return GetContentClient()->renderer()->ShouldTrackUseCounter(url); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidCreateScriptContext(v8::Local<v8::Context> context, | 
|  | int world_id) { | 
|  | if ((enabled_bindings_ & BINDINGS_POLICY_MOJO_WEB_UI) && IsMainFrame() && | 
|  | world_id == ISOLATED_WORLD_ID_GLOBAL) { | 
|  | // We only allow these bindings to be installed when creating the main | 
|  | // world context of the main frame. | 
|  | blink::WebContextFeatures::EnableMojoJS(context, true); | 
|  | } | 
|  |  | 
|  | 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() { | 
|  | render_view_->StartNavStateSyncTimerIfNecessary(this); | 
|  |  | 
|  | for (auto& observer : observers_) | 
|  | observer.DidChangeScrollOffset(); | 
|  | } | 
|  |  | 
|  | blink::WebPushClient* RenderFrameImpl::PushClient() { | 
|  | if (!push_messaging_client_) | 
|  | push_messaging_client_ = new PushMessagingClient(this); | 
|  | return push_messaging_client_; | 
|  | } | 
|  |  | 
|  | blink::WebRelatedAppsFetcher* RenderFrameImpl::GetRelatedAppsFetcher() { | 
|  | if (!related_apps_fetcher_) | 
|  | related_apps_fetcher_.reset(new RelatedAppsFetcher(&GetManifestManager())); | 
|  |  | 
|  | return related_apps_fetcher_.get(); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::WillStartUsingPeerConnectionHandler( | 
|  | blink::WebRTCPeerConnectionHandler* handler) { | 
|  | static_cast<RTCPeerConnectionHandler*>(handler)->associateWithFrame(frame_); | 
|  | } | 
|  |  | 
|  | blink::WebUserMediaClient* RenderFrameImpl::UserMediaClient() { | 
|  | if (!web_user_media_client_) | 
|  | InitializeUserMediaClient(); | 
|  | return web_user_media_client_; | 
|  | } | 
|  |  | 
|  | blink::WebEncryptedMediaClient* RenderFrameImpl::EncryptedMediaClient() { | 
|  | return media_factory_.EncryptedMediaClient(); | 
|  | } | 
|  |  | 
|  | blink::WebString RenderFrameImpl::UserAgentOverride() { | 
|  | if (!render_view_->webview() || !render_view_->webview()->MainFrame() || | 
|  | render_view_->renderer_preferences_.user_agent_override.empty()) { | 
|  | return blink::WebString(); | 
|  | } | 
|  |  | 
|  | // TODO(nasko): When the top-level frame is remote, there is no | 
|  | // WebDocumentLoader associated with it, so the checks below are not valid. | 
|  | // Temporarily return early and fix properly as part of | 
|  | // https://crbug.com/426555. | 
|  | if (render_view_->webview()->MainFrame()->IsWebRemoteFrame()) | 
|  | return blink::WebString(); | 
|  | WebLocalFrame* main_frame = | 
|  | render_view_->webview()->MainFrame()->ToWebLocalFrame(); | 
|  |  | 
|  | // If we're in the middle of committing a load, the data source we need | 
|  | // will still be provisional. | 
|  | WebDocumentLoader* document_loader = nullptr; | 
|  | if (main_frame->GetProvisionalDocumentLoader()) | 
|  | document_loader = main_frame->GetProvisionalDocumentLoader(); | 
|  | else | 
|  | document_loader = main_frame->GetDocumentLoader(); | 
|  |  | 
|  | InternalDocumentStateData* internal_data = | 
|  | document_loader | 
|  | ? InternalDocumentStateData::FromDocumentLoader(document_loader) | 
|  | : nullptr; | 
|  | if (internal_data && internal_data->is_overriding_user_agent()) | 
|  | return WebString::FromUTF8( | 
|  | render_view_->renderer_preferences_.user_agent_override); | 
|  | return blink::WebString(); | 
|  | } | 
|  |  | 
|  | blink::WebString RenderFrameImpl::DoNotTrackValue() { | 
|  | if (render_view_->renderer_preferences_.enable_do_not_track) | 
|  | return WebString::FromUTF8("1"); | 
|  | return WebString(); | 
|  | } | 
|  |  | 
|  | mojom::RendererAudioInputStreamFactory* | 
|  | RenderFrameImpl::GetAudioInputStreamFactory() { | 
|  | if (!audio_input_stream_factory_) | 
|  | GetRemoteInterfaces()->GetInterface(&audio_input_stream_factory_); | 
|  | return audio_input_stream_factory_.get(); | 
|  | } | 
|  |  | 
|  | bool RenderFrameImpl::ShouldBlockWebGL() { | 
|  | bool blocked = true; | 
|  | Send(new FrameHostMsg_Are3DAPIsBlocked( | 
|  | routing_id_, url::Origin(frame_->Top()->GetSecurityOrigin()).GetURL(), | 
|  | THREE_D_API_TYPE_WEBGL, &blocked)); | 
|  | return blocked; | 
|  | } | 
|  |  | 
|  | bool RenderFrameImpl::AllowContentInitiatedDataUrlNavigations( | 
|  | const blink::WebURL& url) { | 
|  | // Error pages can navigate to data URLs. | 
|  | return url.GetString() == kUnreachableWebDataURL; | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::PostAccessibilityEvent(const blink::WebAXObject& obj, | 
|  | ax::mojom::Event event) { | 
|  | if (render_accessibility_) | 
|  | render_accessibility_->HandleWebAccessibilityEvent(obj, event); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::MarkWebAXObjectDirty(const blink::WebAXObject& obj, | 
|  | bool subtree) { | 
|  | if (render_accessibility_) | 
|  | render_accessibility_->MarkWebAXObjectDirty(obj, subtree); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::HandleAccessibilityFindInPageResult( | 
|  | int identifier, | 
|  | int match_index, | 
|  | const blink::WebNode& start_node, | 
|  | int start_offset, | 
|  | const blink::WebNode& end_node, | 
|  | int end_offset) { | 
|  | if (render_accessibility_) { | 
|  | render_accessibility_->HandleAccessibilityFindInPageResult( | 
|  | identifier, match_index, blink::WebAXObject::FromWebNode(start_node), | 
|  | start_offset, blink::WebAXObject::FromWebNode(end_node), end_offset); | 
|  | } | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidChangeManifest() { | 
|  | for (auto& observer : observers_) | 
|  | observer.DidChangeManifest(); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::EnterFullscreen( | 
|  | const blink::WebFullscreenOptions& options) { | 
|  | Send(new FrameHostMsg_EnterFullscreen(routing_id_, options)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::ExitFullscreen() { | 
|  | Send(new FrameHostMsg_ExitFullscreen(routing_id_)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::FullscreenStateChanged(bool is_fullscreen) { | 
|  | GetFrameHost()->FullscreenStateChanged(is_fullscreen); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::SuddenTerminationDisablerChanged( | 
|  | bool present, | 
|  | blink::WebSuddenTerminationDisablerType disabler_type) { | 
|  | Send(new FrameHostMsg_SuddenTerminationDisablerChanged(routing_id_, present, | 
|  | disabler_type)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::RegisterProtocolHandler(const WebString& scheme, | 
|  | const WebURL& url, | 
|  | const WebString& title) { | 
|  | bool user_gesture = WebUserGestureIndicator::IsProcessingUserGesture(frame_); | 
|  | Send(new FrameHostMsg_RegisterProtocolHandler(routing_id_, scheme.Utf8(), url, | 
|  | title.Utf16(), user_gesture)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::UnregisterProtocolHandler(const WebString& scheme, | 
|  | const WebURL& url) { | 
|  | bool user_gesture = WebUserGestureIndicator::IsProcessingUserGesture(frame_); | 
|  | Send(new FrameHostMsg_UnregisterProtocolHandler(routing_id_, scheme.Utf8(), | 
|  | url, user_gesture)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidSerializeDataForFrame( | 
|  | const WebVector<char>& data, | 
|  | WebFrameSerializerClient::FrameSerializationStatus status) { | 
|  | bool end_of_data = | 
|  | status == WebFrameSerializerClient::kCurrentFrameIsFinished; | 
|  | Send(new FrameHostMsg_SerializedHtmlWithLocalLinksResponse( | 
|  | routing_id_, std::string(data.Data(), data.size()), end_of_data)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::AddObserver(RenderFrameObserver* observer) { | 
|  | observers_.AddObserver(observer); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::RemoveObserver(RenderFrameObserver* observer) { | 
|  | observer->RenderFrameGone(); | 
|  | observers_.RemoveObserver(observer); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::OnStop() { | 
|  | DCHECK(frame_); | 
|  |  | 
|  | // The stopLoading call may run script, which may cause this frame to be | 
|  | // detached/deleted.  If that happens, return immediately. | 
|  | base::WeakPtr<RenderFrameImpl> weak_this = weak_factory_.GetWeakPtr(); | 
|  | frame_->StopLoading(); | 
|  | if (!weak_this) | 
|  | return; | 
|  |  | 
|  | for (auto& observer : observers_) | 
|  | observer.OnStop(); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::OnDroppedNavigation() { | 
|  | browser_side_navigation_pending_ = false; | 
|  | browser_side_navigation_pending_url_ = GURL(); | 
|  | frame_->ClientDroppedNavigation(); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::OnCollapse(bool collapsed) { | 
|  | frame_->Collapse(collapsed); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::WasHidden() { | 
|  | for (auto& observer : observers_) | 
|  | observer.WasHidden(); | 
|  |  | 
|  | #if BUILDFLAG(ENABLE_PLUGINS) | 
|  | for (auto* plugin : active_pepper_instances_) | 
|  | plugin->PageVisibilityChanged(false); | 
|  | #endif  // ENABLE_PLUGINS | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::WasShown() { | 
|  | for (auto& observer : observers_) | 
|  | observer.WasShown(); | 
|  |  | 
|  | #if BUILDFLAG(ENABLE_PLUGINS) | 
|  | for (auto* plugin : active_pepper_instances_) | 
|  | plugin->PageVisibilityChanged(true); | 
|  | #endif  // ENABLE_PLUGINS | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::WidgetWillClose() { | 
|  | for (auto& observer : observers_) | 
|  | observer.WidgetWillClose(); | 
|  | } | 
|  |  | 
|  | bool RenderFrameImpl::IsMainFrame() { | 
|  | return is_main_frame_; | 
|  | } | 
|  |  | 
|  | bool RenderFrameImpl::IsHidden() { | 
|  | return GetLocalRootRenderWidget()->is_hidden(); | 
|  | } | 
|  |  | 
|  | bool RenderFrameImpl::IsLocalRoot() const { | 
|  | bool is_local_root = static_cast<bool>(render_widget_); | 
|  | DCHECK_EQ(is_local_root, | 
|  | !(frame_->Parent() && frame_->Parent()->IsWebLocalFrame())); | 
|  | return is_local_root; | 
|  | } | 
|  |  | 
|  | const RenderFrameImpl* RenderFrameImpl::GetLocalRoot() const { | 
|  | return IsLocalRoot() ? this | 
|  | : RenderFrameImpl::FromWebFrame(frame_->LocalRoot()); | 
|  | } | 
|  |  | 
|  | std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params> | 
|  | RenderFrameImpl::MakeDidCommitProvisionalLoadParams( | 
|  | blink::WebHistoryCommitType commit_type, | 
|  | ui::PageTransition transition) { | 
|  | WebDocumentLoader* document_loader = frame_->GetDocumentLoader(); | 
|  | const WebURLResponse& response = document_loader->GetResponse(); | 
|  |  | 
|  | InternalDocumentStateData* internal_data = | 
|  | InternalDocumentStateData::FromDocumentLoader( | 
|  | frame_->GetDocumentLoader()); | 
|  | NavigationState* navigation_state = internal_data->navigation_state(); | 
|  |  | 
|  | std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params> params = | 
|  | std::make_unique<FrameHostMsg_DidCommitProvisionalLoad_Params>(); | 
|  | params->http_status_code = response.HttpStatusCode(); | 
|  | params->url_is_unreachable = document_loader->HasUnreachableURL(); | 
|  | params->method = "GET"; | 
|  | params->intended_as_new_entry = | 
|  | navigation_state->commit_params().intended_as_new_entry; | 
|  | params->should_replace_current_entry = | 
|  | document_loader->ReplacesCurrentHistoryItem(); | 
|  | params->post_id = -1; | 
|  | params->nav_entry_id = navigation_state->commit_params().nav_entry_id; | 
|  |  | 
|  | // Pass the navigation token back to the browser process, or generate a new | 
|  | // one if this navigation is committing without the browser process asking for | 
|  | // it. | 
|  | // TODO(clamy): We should add checks on navigations that commit without having | 
|  | // been asked to commit by the browser process. | 
|  | params->navigation_token = navigation_state->commit_params().navigation_token; | 
|  | if (params->navigation_token.is_empty()) | 
|  | params->navigation_token = base::UnguessableToken::Create(); | 
|  |  | 
|  | // "Standard" commits from Blink create new NavigationEntries. We also treat | 
|  | // main frame "inert" commits as creating new NavigationEntries if they | 
|  | // replace the current entry on a cross-document navigation (e.g., client | 
|  | // redirects, location.replace, navigation to same URL), since this will | 
|  | // replace all the subframes and could go cross-origin. We don't want to rely | 
|  | // on updating the existing NavigationEntry in this case, since it could leave | 
|  | // stale state around. | 
|  | params->did_create_new_entry = | 
|  | (commit_type == blink::kWebStandardCommit) || | 
|  | (commit_type == blink::kWebHistoryInertCommit && !frame_->Parent() && | 
|  | params->should_replace_current_entry && | 
|  | !navigation_state->WasWithinSameDocument()); | 
|  |  | 
|  | WebDocument frame_document = frame_->GetDocument(); | 
|  | // Set the origin of the frame.  This will be replicated to the corresponding | 
|  | // RenderFrameProxies in other processes. | 
|  | WebSecurityOrigin frame_origin = frame_document.GetSecurityOrigin(); | 
|  | params->origin = frame_origin; | 
|  |  | 
|  | params->insecure_request_policy = frame_->GetInsecureRequestPolicy(); | 
|  | params->insecure_navigations_set = frame_->GetInsecureRequestToUpgrade(); | 
|  |  | 
|  | params->has_potentially_trustworthy_unique_origin = | 
|  | frame_origin.IsUnique() && frame_origin.IsPotentiallyTrustworthy(); | 
|  |  | 
|  | // Set the URL to be displayed in the browser UI to the user. | 
|  | params->url = GetLoadingUrl(); | 
|  | if (GURL(frame_document.BaseURL()) != params->url) | 
|  | params->base_url = frame_document.BaseURL(); | 
|  |  | 
|  | GetRedirectChain(document_loader, ¶ms->redirects); | 
|  | params->should_update_history = | 
|  | !document_loader->HasUnreachableURL() && response.HttpStatusCode() != 404; | 
|  |  | 
|  | params->gesture = document_loader->HadUserGesture() ? NavigationGestureUser | 
|  | : NavigationGestureAuto; | 
|  |  | 
|  | // Make navigation state a part of the DidCommitProvisionalLoad message so | 
|  | // that committed entry has it at all times.  Send a single HistoryItem for | 
|  | // this frame, rather than the whole tree.  It will be stored in the | 
|  | // corresponding FrameNavigationEntry. | 
|  | params->page_state = SingleHistoryItemToPageState(current_history_item_); | 
|  |  | 
|  | params->content_source_id = GetLocalRootRenderWidget()->GetContentSourceId(); | 
|  |  | 
|  | params->method = document_loader->HttpMethod().Latin1(); | 
|  | if (params->method == "POST") | 
|  | params->post_id = ExtractPostId(current_history_item_); | 
|  |  | 
|  | params->item_sequence_number = current_history_item_.ItemSequenceNumber(); | 
|  | params->document_sequence_number = | 
|  | current_history_item_.DocumentSequenceNumber(); | 
|  |  | 
|  | // If the page contained a client redirect (meta refresh, document.loc...), | 
|  | // set the referrer appropriately. | 
|  | if (document_loader->IsClientRedirect()) { | 
|  | params->referrer = | 
|  | Referrer(params->redirects[0], document_loader->GetReferrerPolicy()); | 
|  | } else { | 
|  | params->referrer = | 
|  | Referrer(blink::WebStringToGURL(document_loader->Referrer()), | 
|  | document_loader->GetReferrerPolicy()); | 
|  | } | 
|  |  | 
|  | if (!frame_->Parent()) { | 
|  | // Top-level navigation. | 
|  |  | 
|  | // Update contents MIME type for main frame. | 
|  | params->contents_mime_type = | 
|  | document_loader->GetResponse().MimeType().Utf8(); | 
|  |  | 
|  | params->transition = transition; | 
|  | DCHECK(ui::PageTransitionIsMainFrame(params->transition)); | 
|  |  | 
|  | // If the page contained a client redirect (meta refresh, document.loc...), | 
|  | // set the transition appropriately. | 
|  | if (document_loader->IsClientRedirect()) { | 
|  | params->transition = ui::PageTransitionFromInt( | 
|  | params->transition | ui::PAGE_TRANSITION_CLIENT_REDIRECT); | 
|  | } | 
|  |  | 
|  | // Send the user agent override back. | 
|  | params->is_overriding_user_agent = | 
|  | internal_data->is_overriding_user_agent(); | 
|  |  | 
|  | // Track the URL of the original request.  We use the first entry of the | 
|  | // redirect chain if it exists because the chain may have started in another | 
|  | // process. | 
|  | params->original_request_url = GetOriginalRequestURL(document_loader); | 
|  |  | 
|  | params->history_list_was_cleared = | 
|  | navigation_state->commit_params().should_clear_history_list; | 
|  | } else { | 
|  | // Subframe navigation: the type depends on whether this navigation | 
|  | // generated a new session history entry. When they do generate a session | 
|  | // history entry, it means the user initiated the navigation and we should | 
|  | // mark it as such. | 
|  | 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; | 
|  | } | 
|  |  | 
|  | // Standard URLs must match the reported origin, when it is not unique. | 
|  | // This check is very similar to RenderFrameHostImpl::CanCommitOrigin, but | 
|  | // adapted to the renderer process side. | 
|  | if (!params->origin.opaque() && params->url.IsStandard() && | 
|  | render_view_->GetWebkitPreferences().web_security_enabled) { | 
|  | // Exclude file: URLs when settings allow them access any origin. | 
|  | if (params->origin.scheme() != url::kFileScheme || | 
|  | !render_view_->GetWebkitPreferences() | 
|  | .allow_universal_access_from_file_urls) { | 
|  | CHECK(params->origin.IsSameOriginWith(url::Origin::Create(params->url))) | 
|  | << " url:" << params->url << " origin:" << params->origin; | 
|  | } | 
|  | } | 
|  | params->request_id = internal_data->request_id(); | 
|  |  | 
|  | return params; | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::UpdateZoomLevel() { | 
|  | if (!frame_->Parent()) { | 
|  | // Reset the zoom limits in case a plugin had changed them previously. This | 
|  | // will also call us back which will cause us to send a message to | 
|  | // update WebContentsImpl. | 
|  | render_view_->webview()->ZoomLimitsChanged( | 
|  | ZoomFactorToZoomLevel(kMinimumZoomFactor), | 
|  | ZoomFactorToZoomLevel(kMaximumZoomFactor)); | 
|  |  | 
|  | // Set zoom level, but don't do it for full-page plugin since they don't use | 
|  | // the same zoom settings. | 
|  | auto host_zoom = host_zoom_levels_.find(GetLoadingUrl()); | 
|  | if (render_view_->webview()->MainFrame()->IsWebLocalFrame() && | 
|  | render_view_->webview() | 
|  | ->MainFrame() | 
|  | ->ToWebLocalFrame() | 
|  | ->GetDocument() | 
|  | .IsPluginDocument()) { | 
|  | // Reset the zoom levels for plugins. | 
|  | render_view_->SetZoomLevel(0); | 
|  | } else { | 
|  | // If the zoom level is not found, then do nothing. In-page navigation | 
|  | // relies on not changing the zoom level in this case. | 
|  | if (host_zoom != host_zoom_levels_.end()) | 
|  | render_view_->SetZoomLevel(host_zoom->second); | 
|  | } | 
|  |  | 
|  | if (host_zoom != host_zoom_levels_.end()) { | 
|  | // This zoom level was merely recorded transiently for this load.  We can | 
|  | // erase it now.  If at some point we reload this page, the browser will | 
|  | // send us a new, up-to-date zoom level. | 
|  | host_zoom_levels_.erase(host_zoom); | 
|  | } | 
|  | } else { | 
|  | // Subframes should match the zoom level of the main frame. | 
|  | render_view_->SetZoomLevel(render_view_->page_zoom_level()); | 
|  | } | 
|  | } | 
|  |  | 
|  | bool RenderFrameImpl::UpdateNavigationHistory( | 
|  | const blink::WebHistoryItem& item, | 
|  | blink::WebHistoryCommitType commit_type) { | 
|  | NavigationState* navigation_state = | 
|  | NavigationState::FromDocumentLoader(frame_->GetDocumentLoader()); | 
|  | const CommitNavigationParams& commit_params = | 
|  | navigation_state->commit_params(); | 
|  |  | 
|  | // Update the current history item for this frame. | 
|  | current_history_item_ = item; | 
|  | // Note: don't reference |item| after this point, as its value may not match | 
|  | // |current_history_item_|. | 
|  | current_history_item_.SetTarget( | 
|  | blink::WebString::FromUTF8(unique_name_helper_.value())); | 
|  | bool is_new_navigation = commit_type == blink::kWebStandardCommit; | 
|  | if (commit_params.should_clear_history_list) { | 
|  | render_view_->history_list_offset_ = 0; | 
|  | render_view_->history_list_length_ = 1; | 
|  | } else if (is_new_navigation) { | 
|  | DCHECK(!navigation_state->common_params().should_replace_current_entry || | 
|  | render_view_->history_list_length_ > 0); | 
|  | if (!navigation_state->common_params().should_replace_current_entry) { | 
|  | // Advance our offset in session history, applying the length limit. | 
|  | // There is now no forward history. | 
|  | render_view_->history_list_offset_++; | 
|  | if (render_view_->history_list_offset_ >= kMaxSessionHistoryEntries) | 
|  | render_view_->history_list_offset_ = kMaxSessionHistoryEntries - 1; | 
|  | render_view_->history_list_length_ = | 
|  | render_view_->history_list_offset_ + 1; | 
|  | } | 
|  | } else if (commit_params.nav_entry_id != 0 && | 
|  | !commit_params.intended_as_new_entry) { | 
|  | render_view_->history_list_offset_ = | 
|  | navigation_state->commit_params().pending_history_list_offset; | 
|  | } | 
|  |  | 
|  | if (commit_type == blink::WebHistoryCommitType::kWebBackForwardCommit) | 
|  | render_view_->DidCommitProvisionalHistoryLoad(); | 
|  |  | 
|  | return is_new_navigation; | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::NotifyObserversOfNavigationCommit( | 
|  | bool is_new_navigation, | 
|  | bool is_same_document, | 
|  | ui::PageTransition transition) { | 
|  | for (auto& observer : render_view_->observers_) | 
|  | observer.DidCommitProvisionalLoad(frame_, is_new_navigation); | 
|  | for (auto& observer : observers_) | 
|  | observer.DidCommitProvisionalLoad(is_same_document, transition); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::UpdateStateForCommit( | 
|  | const blink::WebHistoryItem& item, | 
|  | blink::WebHistoryCommitType commit_type, | 
|  | ui::PageTransition transition) { | 
|  | InternalDocumentStateData* internal_data = | 
|  | InternalDocumentStateData::FromDocumentLoader( | 
|  | frame_->GetDocumentLoader()); | 
|  | NavigationState* navigation_state = internal_data->navigation_state(); | 
|  |  | 
|  | // We need to update the last committed session history entry with state for | 
|  | // the previous page. Do this before updating the current history item. | 
|  | SendUpdateState(); | 
|  |  | 
|  | bool is_new_navigation = UpdateNavigationHistory(item, commit_type); | 
|  | NotifyObserversOfNavigationCommit( | 
|  | is_new_navigation, navigation_state->WasWithinSameDocument(), transition); | 
|  |  | 
|  | if (internal_data->must_reset_scroll_and_scale_state()) { | 
|  | render_view_->webview()->ResetScrollAndScaleState(); | 
|  | internal_data->set_must_reset_scroll_and_scale_state(false); | 
|  | } | 
|  | UpdateZoomLevel(); | 
|  |  | 
|  | if (!frame_->Parent()) {  // Only for top frames. | 
|  | RenderThreadImpl* render_thread_impl = RenderThreadImpl::current(); | 
|  | if (render_thread_impl) {  // Can be NULL in tests. | 
|  | render_thread_impl->histogram_customizer()->RenderViewNavigatedToHost( | 
|  | GURL(GetLoadingUrl()).host(), RenderView::GetRenderViewCount()); | 
|  | } | 
|  | } | 
|  |  | 
|  | // Remember that we've already processed this request, so we don't update | 
|  | // the session history again.  We do this regardless of whether this is | 
|  | // a session history navigation, because if we attempted a session history | 
|  | // navigation without valid HistoryItem state, WebCore will think it is a | 
|  | // new navigation. | 
|  | navigation_state->set_request_committed(true); | 
|  |  | 
|  | // If we are a top frame navigation to another document we should clear any | 
|  | // existing autoplay flags on the Page. This is because flags are stored at | 
|  | // the page level so subframes would only add to them. | 
|  | if (!frame_->Parent() && !navigation_state->WasWithinSameDocument()) { | 
|  | render_view_->webview()->ClearAutoplayFlags(); | 
|  | } | 
|  |  | 
|  | // Set the correct autoplay flags on the Page and wipe the cached origin so | 
|  | // this will not be used incorrectly. | 
|  | if (url::Origin(frame_->GetSecurityOrigin()) == autoplay_flags_.first) { | 
|  | render_view_->webview()->AddAutoplayFlags(autoplay_flags_.second); | 
|  | autoplay_flags_.first = url::Origin(); | 
|  | } | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidCommitNavigationInternal( | 
|  | const blink::WebHistoryItem& item, | 
|  | blink::WebHistoryCommitType commit_type, | 
|  | bool was_within_same_document, | 
|  | ui::PageTransition transition, | 
|  | mojom::DidCommitProvisionalLoadInterfaceParamsPtr interface_params) { | 
|  | DCHECK(!(was_within_same_document && interface_params)); | 
|  | UpdateStateForCommit(item, commit_type, transition); | 
|  |  | 
|  | // This invocation must precede any calls to allowScripts(), allowImages(), or | 
|  | // allowPlugins() for the new page. This ensures that when these functions | 
|  | // send ViewHostMsg_ContentBlocked messages, those arrive after the browser | 
|  | // process has already been informed of the provisional load committing. | 
|  | auto params = MakeDidCommitProvisionalLoadParams(commit_type, transition); | 
|  | if (was_within_same_document) { | 
|  | GetFrameHost()->DidCommitSameDocumentNavigation(std::move(params)); | 
|  | } else { | 
|  | NavigationState* navigation_state = | 
|  | NavigationState::FromDocumentLoader(frame_->GetDocumentLoader()); | 
|  | if (navigation_state->uses_per_navigation_mojo_interface()) { | 
|  | navigation_state->RunPerNavigationInterfaceCommitNavigationCallback( | 
|  | std::move(params), std::move(interface_params)); | 
|  | } else { | 
|  | GetFrameHost()->DidCommitProvisionalLoad(std::move(params), | 
|  | std::move(interface_params)); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::PrepareFrameForCommit( | 
|  | const GURL& url, | 
|  | const CommitNavigationParams& commit_params) { | 
|  | browser_side_navigation_pending_ = false; | 
|  | browser_side_navigation_pending_url_ = GURL(); | 
|  | sync_navigation_callback_.Cancel(); | 
|  | mhtml_body_loader_client_.reset(); | 
|  |  | 
|  | GetContentClient()->SetActiveURL( | 
|  | url, frame_->Top()->GetSecurityOrigin().ToString().Utf8()); | 
|  |  | 
|  | RenderFrameImpl::PrepareRenderViewForNavigation(url, commit_params); | 
|  | } | 
|  |  | 
|  | blink::mojom::CommitResult RenderFrameImpl::PrepareForHistoryNavigationCommit( | 
|  | FrameMsg_Navigate_Type::Value navigation_type, | 
|  | const CommitNavigationParams& commit_params, | 
|  | WebHistoryItem* item_for_history_navigation, | 
|  | blink::WebFrameLoadType* load_type) { | 
|  | DCHECK(navigation_type == FrameMsg_Navigate_Type::HISTORY_SAME_DOCUMENT || | 
|  | navigation_type == | 
|  | FrameMsg_Navigate_Type::HISTORY_DIFFERENT_DOCUMENT || | 
|  | navigation_type == FrameMsg_Navigate_Type::RESTORE || | 
|  | navigation_type == FrameMsg_Navigate_Type::RESTORE_WITH_POST); | 
|  | std::unique_ptr<HistoryEntry> entry = | 
|  | PageStateToHistoryEntry(commit_params.page_state); | 
|  | if (!entry) | 
|  | return blink::mojom::CommitResult::Aborted; | 
|  |  | 
|  | // The browser process sends a single WebHistoryItem for this frame. | 
|  | // TODO(creis): Change PageState to FrameState.  In the meantime, we | 
|  | // store the relevant frame's WebHistoryItem in the root of the | 
|  | // PageState. | 
|  | *item_for_history_navigation = entry->root(); | 
|  | *load_type = blink::WebFrameLoadType::kBackForward; | 
|  |  | 
|  | // Keep track of which subframes the browser process has history items | 
|  | // for during a history navigation. | 
|  | history_subframe_unique_names_ = commit_params.subframe_unique_names; | 
|  |  | 
|  | if (navigation_type == FrameMsg_Navigate_Type::HISTORY_SAME_DOCUMENT) { | 
|  | // If this is marked as a same document load but we haven't committed | 
|  | // anything, we can't proceed with the load. The browser shouldn't let this | 
|  | // happen. | 
|  | if (current_history_item_.IsNull()) { | 
|  | NOTREACHED(); | 
|  | return blink::mojom::CommitResult::RestartCrossDocument; | 
|  | } | 
|  |  | 
|  | // Additionally, if the |current_history_item_|'s document sequence number | 
|  | // doesn't match the one sent from the browser, it is possible that this | 
|  | // renderer has committed a different document. In such case, the navigation | 
|  | // cannot be loaded as a same-document navigation. | 
|  | if (current_history_item_.DocumentSequenceNumber() != | 
|  | item_for_history_navigation->DocumentSequenceNumber()) { | 
|  | return blink::mojom::CommitResult::RestartCrossDocument; | 
|  | } | 
|  | } | 
|  |  | 
|  | // If this navigation is to a history item for a new child frame, we may | 
|  | // want to ignore it in some cases.  If a Javascript navigation (i.e., | 
|  | // client redirect) interrupted it and has either been scheduled, | 
|  | // started loading, or has committed, we should ignore the history item. | 
|  | bool interrupted_by_client_redirect = | 
|  | frame_->IsNavigationScheduledWithin(0) || | 
|  | frame_->GetProvisionalDocumentLoader() || !current_history_item_.IsNull(); | 
|  | if (commit_params.is_history_navigation_in_new_child && | 
|  | interrupted_by_client_redirect) { | 
|  | return blink::mojom::CommitResult::Aborted; | 
|  | } | 
|  |  | 
|  | return blink::mojom::CommitResult::Ok; | 
|  | } | 
|  |  | 
|  | bool RenderFrameImpl::SwapIn() { | 
|  | CHECK_NE(previous_routing_id_, MSG_ROUTING_NONE); | 
|  | CHECK(!in_frame_tree_); | 
|  |  | 
|  | // The proxy should always exist.  If it was detached while the provisional | 
|  | // LocalFrame was being navigated, the provisional frame would've been | 
|  | // cleaned up by RenderFrameProxy::FrameDetached.  See | 
|  | // https://crbug.com/526304 and https://crbug.com/568676 for context. | 
|  | RenderFrameProxy* proxy = | 
|  | RenderFrameProxy::FromRoutingID(previous_routing_id_); | 
|  | CHECK(proxy); | 
|  |  | 
|  | unique_name_helper_.set_propagated_name(proxy->unique_name()); | 
|  |  | 
|  | // Note: Calling swap() will detach and delete |proxy|, so do not reference it | 
|  | // after this. | 
|  | if (!proxy->web_frame()->Swap(frame_)) { | 
|  | // Main frames should always swap successfully because there is no parent | 
|  | // frame to cause them to become detached. | 
|  | DCHECK(!is_main_frame_); | 
|  | return false; | 
|  | } | 
|  |  | 
|  | previous_routing_id_ = MSG_ROUTING_NONE; | 
|  | in_frame_tree_ = true; | 
|  |  | 
|  | // If this is the main frame going from a remote frame to a local frame, | 
|  | // it needs to set RenderViewImpl's pointer for the main frame to itself, | 
|  | // ensure RenderWidget is no longer frozen. | 
|  | if (is_main_frame_) { | 
|  | CHECK(!render_view_->main_render_frame_); | 
|  | render_view_->main_render_frame_ = this; | 
|  | if (render_view_->GetWidget()->is_frozen()) { | 
|  | // TODO(crbug.com/419087): The RenderWidget should be newly created here, | 
|  | // then we won't have to do this. | 
|  | render_view_->GetWidget()->SetIsFrozen(false); | 
|  | } | 
|  | render_view_->GetWidget()->UpdateWebViewWithDeviceScaleFactor(); | 
|  |  | 
|  | // The WebFrame being swapped in here has now been attached to the Page as | 
|  | // its main frame, and the WebFrameWidget was previously initialized when | 
|  | // the frame was created, so we can call WebViewImpl's | 
|  | // DidAttachLocalMainFrame(). | 
|  | render_view_->webview()->DidAttachLocalMainFrame(render_view_->GetWidget()); | 
|  | } | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidStartLoading() { | 
|  | // TODO(dgozman): consider removing this callback. | 
|  | TRACE_EVENT1("navigation,rail", "RenderFrameImpl::didStartLoading", | 
|  | "id", routing_id_); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidStopLoading() { | 
|  | TRACE_EVENT1("navigation,rail", "RenderFrameImpl::didStopLoading", | 
|  | "id", routing_id_); | 
|  |  | 
|  | // Any subframes created after this point won't be considered part of the | 
|  | // current history navigation (if this was one), so we don't need to track | 
|  | // this state anymore. | 
|  | history_subframe_unique_names_.clear(); | 
|  |  | 
|  | SendUpdateFaviconURL(); | 
|  |  | 
|  | Send(new FrameHostMsg_DidStopLoading(routing_id_)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DidChangeLoadProgress(double load_progress) { | 
|  | Send(new FrameHostMsg_DidChangeLoadProgress(routing_id_, load_progress)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::FocusedNodeChanged(const WebNode& node) { | 
|  | has_scrolled_focused_editable_node_into_rect_ = false; | 
|  | bool is_editable = false; | 
|  | gfx::Rect node_bounds; | 
|  | if (!node.IsNull() && node.IsElementNode()) { | 
|  | WebElement element = const_cast<WebNode&>(node).To<WebElement>(); | 
|  | blink::WebRect rect = element.BoundsInViewport(); | 
|  | GetLocalRootRenderWidget()->ConvertViewportToWindow(&rect); | 
|  | is_editable = element.IsEditable(); | 
|  | node_bounds = gfx::Rect(rect); | 
|  | } | 
|  | Send(new FrameHostMsg_FocusedNodeChanged(routing_id_, is_editable, | 
|  | node_bounds)); | 
|  | // Ensures that further text input state can be sent even when previously | 
|  | // focused input and the newly focused input share the exact same state. | 
|  | GetLocalRootRenderWidget()->ClearTextInputState(); | 
|  |  | 
|  | for (auto& observer : observers_) | 
|  | observer.FocusedNodeChanged(node); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::FocusedNodeChangedForAccessibility(const WebNode& node) { | 
|  | if (render_accessibility()) | 
|  | render_accessibility()->AccessibilityFocusedNodeChanged(node); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::OnReportContentSecurityPolicyViolation( | 
|  | const content::CSPViolationParams& violation_params) { | 
|  | frame_->ReportContentSecurityPolicyViolation( | 
|  | BuildWebContentSecurityPolicyViolation(violation_params)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::BeginNavigation( | 
|  | std::unique_ptr<blink::WebNavigationInfo> info) { | 
|  | // This method is only called for renderer initiated navigations, which | 
|  | // may have originated from a link-click, script, drag-n-drop operation, etc. | 
|  |  | 
|  | // Note that we don't want to go to browser for a navigation to an empty url, | 
|  | // which happens for window.open('') call. An example would be embedder | 
|  | // deciding to fork the process for the empty url, or setting | 
|  | // |browser_handles_all_top_level_requests| preference. | 
|  | // | 
|  | // Doing a browser-side navigation might later trigger unload handlers, | 
|  | // e.g. when the dom window of the popup has already been touched | 
|  | // synchronously in this process. We should avoid that. | 
|  | // | 
|  | // See the checks for empty url in the cases below. | 
|  | // TODO(dgozman): if we rewrite empty url to about:blank earlier | 
|  | // (we currently do that in DocumentLoader), all the empty checks can be | 
|  | // removed, since they already account for an empty url. | 
|  |  | 
|  | // Blink is asking whether to navigate to a new URL. | 
|  | // This is fine normally, except if we're showing UI from one security | 
|  | // context and they're trying to navigate to a different context. | 
|  | const GURL& url = info->url_request.Url(); | 
|  |  | 
|  | // When an MHTML Archive is present, it should be used to serve iframe | 
|  | // content instead of doing a network request. This should never be true for | 
|  | // the main frame. | 
|  | bool use_archive = (info->archive_status == | 
|  | blink::WebNavigationInfo::ArchiveStatus::Present) && | 
|  | !url.SchemeIs(url::kDataScheme); | 
|  | DCHECK(!(use_archive && IsMainFrame())); | 
|  |  | 
|  | #ifdef OS_ANDROID | 
|  | bool render_view_was_created_by_renderer = | 
|  | render_view_->was_created_by_renderer_; | 
|  | // The handlenavigation API is deprecated and will be removed once | 
|  | // crbug.com/325351 is resolved. | 
|  | if (!url.is_empty() && !use_archive && !IsURLHandledByNetworkStack(url) && | 
|  | GetContentClient()->renderer()->HandleNavigation( | 
|  | this, true /* is_content_initiated */, | 
|  | render_view_was_created_by_renderer, frame_, info->url_request, | 
|  | info->navigation_type, info->navigation_policy, | 
|  | false /* is_redirect */)) { | 
|  | return; | 
|  | } | 
|  | #endif | 
|  |  | 
|  | // If the browser is interested, then give it a chance to look at the request. | 
|  | if (IsTopLevelNavigation(frame_) && | 
|  | render_view_->renderer_preferences_ | 
|  | .browser_handles_all_top_level_requests) { | 
|  | OpenURL(std::move(info), /*is_history_navigation_in_new_child=*/false); | 
|  | return;  // Suppress the load here. | 
|  | } | 
|  |  | 
|  | // Back/forward navigations in newly created subframes should be sent to the | 
|  | // browser if there is a matching FrameNavigationEntry, and if it isn't just | 
|  | // staying at about:blank.  If this frame isn't in the map of unique names | 
|  | // that have history items, or if it's staying at the initial about:blank URL, | 
|  | // fall back to loading the default url.  (We remove each name as we encounter | 
|  | // it, because it will only be used once as the frame is created.) | 
|  | // Note: Skip this logic for MHTML files (|use_archive|), which should load | 
|  | // their subframes from the archive and not from history. | 
|  | if (info->is_history_navigation_in_new_child_frame && frame_->Parent() && | 
|  | !use_archive) { | 
|  | // Check whether the browser has a history item for this frame that isn't | 
|  | // just staying at the initial about:blank document. | 
|  | bool should_ask_browser = false; | 
|  | 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; | 
|  | should_ask_browser = | 
|  | !history_item_is_about_blank || url != url::kAboutBlankURL; | 
|  | parent->history_subframe_unique_names_.erase(iter); | 
|  | } | 
|  |  | 
|  | if (should_ask_browser) { | 
|  | // Don't do this if |info| also says it is a client redirect, in which | 
|  | // case JavaScript on the page is trying to interrupt the history | 
|  | // navigation. | 
|  | if (!info->is_client_redirect) { | 
|  | OpenURL(std::move(info), /*is_history_navigation_in_new_child=*/true); | 
|  | // TODO(japhet): This case wants to flag the frame as loading and do | 
|  | // nothing else. It'd be nice if it could go through the placeholder | 
|  | // DocumentLoader path, too. | 
|  | frame_->MarkAsLoading(); | 
|  | return; | 
|  | } | 
|  | // Client redirects during an initial history load should attempt to | 
|  | // cancel the history navigation.  They will create a provisional | 
|  | // document loader, causing the history load to be ignored in | 
|  | // NavigateInternal, and this IPC will try to cancel any cross-process | 
|  | // history load. | 
|  | GetFrameHost()->CancelInitialHistoryLoad(); | 
|  | } | 
|  | } | 
|  |  | 
|  | // Use the frame's original request's URL rather than the document's URL for | 
|  | // subsequent checks.  For a popup, the document's URL may become the opener | 
|  | // window's URL if the opener has called document.write(). | 
|  | // See http://crbug.com/93517. | 
|  | GURL old_url(frame_->GetDocumentLoader()->GetUrl()); | 
|  |  | 
|  | // Detect when we're crossing a permission-based boundary (e.g. into or out of | 
|  | // an extension or app origin, leaving a WebUI page, etc). We only care about | 
|  | // top-level navigations (not iframes). But we sometimes navigate to | 
|  | // about:blank to clear a tab, and we want to still allow that. | 
|  | if (!frame_->Parent() && !url.SchemeIs(url::kAboutScheme) && | 
|  | !url.is_empty()) { | 
|  | // All navigations to or from WebUI URLs or within WebUI-enabled | 
|  | // RenderProcesses must be handled by the browser process so that the | 
|  | // correct bindings and data sources can be registered. | 
|  | // Similarly, navigations to view-source URLs or within ViewSource mode | 
|  | // must be handled by the browser process (except for reloads - those are | 
|  | // safe to leave within the renderer). | 
|  | // Lastly, access to file:// URLs from non-file:// URL pages must be | 
|  | // handled by the browser so that ordinary renderer processes don't get | 
|  | // blessed with file permissions. | 
|  | int cumulative_bindings = RenderProcess::current()->GetEnabledBindings(); | 
|  | bool is_initial_navigation = render_view_->history_list_length_ == 0; | 
|  | bool should_fork = | 
|  | HasWebUIScheme(url) || HasWebUIScheme(old_url) || | 
|  | (cumulative_bindings & kWebUIBindingsPolicyMask) || | 
|  | url.SchemeIs(kViewSourceScheme) || | 
|  | (frame_->IsViewSourceModeEnabled() && | 
|  | info->navigation_type != blink::kWebNavigationTypeReload); | 
|  | if (!should_fork && url.SchemeIs(url::kFileScheme)) { | 
|  | // Fork non-file to file opens.  Note that this may fork unnecessarily if | 
|  | // another tab (hosting a file or not) targeted this one before its | 
|  | // initial navigation, but that shouldn't cause a problem. | 
|  | should_fork = !old_url.SchemeIs(url::kFileScheme); | 
|  | } | 
|  |  | 
|  | if (!should_fork) { | 
|  | // Give the embedder a chance. | 
|  | should_fork = GetContentClient()->renderer()->ShouldFork( | 
|  | frame_, url, info->url_request.HttpMethod().Utf8(), | 
|  | is_initial_navigation, false /* is_redirect */); | 
|  | } | 
|  |  | 
|  | if (should_fork) { | 
|  | OpenURL(std::move(info), /*is_history_navigation_in_new_child=*/false); | 
|  | return;  // Suppress the load here. | 
|  | } | 
|  | } | 
|  |  | 
|  | bool should_dispatch_before_unload = | 
|  | info->navigation_policy == blink::kWebNavigationPolicyCurrentTab && | 
|  | // No need to dispatch beforeunload if the frame has not committed a | 
|  | // navigation and contains an empty initial document. | 
|  | (has_accessed_initial_document_ || !current_history_item_.IsNull()); | 
|  |  | 
|  | if (should_dispatch_before_unload) { | 
|  | // Execute the BeforeUnload event. If asked not to proceed or the frame is | 
|  | // destroyed, ignore the navigation. | 
|  | // Keep a WeakPtr to this RenderFrameHost to detect if executing the | 
|  | // BeforeUnload event destriyed this frame. | 
|  | base::WeakPtr<RenderFrameImpl> weak_self = weak_factory_.GetWeakPtr(); | 
|  |  | 
|  | if (!frame_->DispatchBeforeUnloadEvent(info->navigation_type == | 
|  | blink::kWebNavigationTypeReload) || | 
|  | !weak_self) { | 
|  | return; | 
|  | } | 
|  | } | 
|  |  | 
|  | if (info->navigation_policy == blink::kWebNavigationPolicyCurrentTab) { | 
|  | if (!info->form.IsNull()) { | 
|  | for (auto& observer : observers_) | 
|  | observer.WillSubmitForm(info->form); | 
|  | } | 
|  |  | 
|  | sync_navigation_callback_.Cancel(); | 
|  | mhtml_body_loader_client_.reset(); | 
|  |  | 
|  | for (auto& observer : observers_) | 
|  | observer.DidStartNavigation(url, info->navigation_type); | 
|  |  | 
|  | // Navigations which require network request should be sent to the browser. | 
|  | if (!use_archive && IsURLHandledByNetworkStack(url)) { | 
|  | BeginNavigationInternal(std::move(info)); | 
|  | return; | 
|  | } | 
|  |  | 
|  | // First navigaiton in a frame to an empty document must be handled | 
|  | // synchronously. | 
|  | if (WebDocumentLoader::WillLoadUrlAsEmpty(url) && | 
|  | !frame_->HasCommittedFirstRealLoad()) { | 
|  | CommitSyncNavigation(std::move(info)); | 
|  | return; | 
|  | } | 
|  |  | 
|  | // Everything else (does not require networking, not an empty document) | 
|  | // will be committed asynchronously in the renderer. | 
|  | if (!frame_->CreatePlaceholderDocumentLoader(*info, BuildDocumentState())) | 
|  | return; | 
|  | sync_navigation_callback_.Reset( | 
|  | base::BindOnce(&RenderFrameImpl::CommitSyncNavigation, | 
|  | weak_factory_.GetWeakPtr(), base::Passed(&info))); | 
|  | frame_->GetTaskRunner(blink::TaskType::kInternalLoading) | 
|  | ->PostTask(FROM_HERE, sync_navigation_callback_.callback()); | 
|  | return; | 
|  | } | 
|  |  | 
|  | if (info->navigation_policy == blink::kWebNavigationPolicyDownload) { | 
|  | blink::mojom::BlobURLTokenPtrInfo blob_url_token = | 
|  | CloneBlobURLToken(info->blob_url_token.get()); | 
|  | DownloadURL(info->url_request, | 
|  | blink::WebLocalFrameClient::CrossOriginRedirects::kFollow, | 
|  | blob_url_token.PassHandle()); | 
|  | } else { | 
|  | OpenURL(std::move(info), /*is_history_navigation_in_new_child=*/false); | 
|  | } | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::CommitSyncNavigation( | 
|  | std::unique_ptr<blink::WebNavigationInfo> info) { | 
|  | // TODO(dgozman): should we follow the RFI::CommitNavigation path instead? | 
|  | auto navigation_params = WebNavigationParams::CreateFromInfo(*info); | 
|  | // We need the provider to be non-null, otherwise Blink crashes, even | 
|  | // though the provider should not be used for any actual networking. | 
|  | navigation_params->service_worker_network_provider = | 
|  | ServiceWorkerNetworkProviderForFrame::CreateInvalidInstance(); | 
|  | frame_->CommitNavigation(std::move(navigation_params), BuildDocumentState()); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::OnGetSavableResourceLinks() { | 
|  | std::vector<GURL> resources_list; | 
|  | std::vector<SavableSubframe> subframes; | 
|  | SavableResourcesResult result(&resources_list, &subframes); | 
|  |  | 
|  | if (!GetSavableResourceLinksForFrame(frame_, &result)) { | 
|  | Send(new FrameHostMsg_SavableResourceLinksError(routing_id_)); | 
|  | return; | 
|  | } | 
|  |  | 
|  | Referrer referrer = Referrer(frame_->GetDocument().Url(), | 
|  | frame_->GetDocument().GetReferrerPolicy()); | 
|  |  | 
|  | Send(new FrameHostMsg_SavableResourceLinksResponse( | 
|  | routing_id_, resources_list, referrer, subframes)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::OnGetSerializedHtmlWithLocalLinks( | 
|  | const std::map<GURL, base::FilePath>& url_to_local_path, | 
|  | const std::map<int, base::FilePath>& frame_routing_id_to_local_path, | 
|  | bool save_with_empty_url) { | 
|  | // Convert input to the canonical way of passing a map into a Blink API. | 
|  | LinkRewritingDelegate delegate(url_to_local_path, | 
|  | frame_routing_id_to_local_path); | 
|  |  | 
|  | // Serialize the frame (without recursing into subframes). | 
|  | WebFrameSerializer::Serialize(GetWebFrame(), | 
|  | this,  // WebFrameSerializerClient. | 
|  | &delegate, save_with_empty_url); | 
|  | } | 
|  |  | 
|  | // mojom::MhtmlFileWriter implementation | 
|  | // ---------------------------------------- | 
|  |  | 
|  | void RenderFrameImpl::SerializeAsMHTML(mojom::SerializeAsMHTMLParamsPtr params, | 
|  | SerializeAsMHTMLCallback callback) { | 
|  | TRACE_EVENT0("page-serialization", "RenderFrameImpl::SerializeAsMHTML"); | 
|  | base::TimeTicks start_time = base::TimeTicks::Now(); | 
|  |  | 
|  | // Unpack payload. | 
|  | const WebString mhtml_boundary = | 
|  | WebString::FromUTF8(params->mhtml_boundary_marker); | 
|  | DCHECK(!mhtml_boundary.IsEmpty()); | 
|  |  | 
|  | // Holds WebThreadSafeData instances for some or all of header, contents and | 
|  | // footer. | 
|  | std::vector<WebThreadSafeData> mhtml_contents; | 
|  | std::unordered_set<std::string> serialized_resources_uri_digests; | 
|  | MHTMLPartsGenerationDelegate delegate(*params, | 
|  | &serialized_resources_uri_digests); | 
|  |  | 
|  | mojom::MhtmlSaveStatus save_status = mojom::MhtmlSaveStatus::kSuccess; | 
|  | bool has_some_data = false; | 
|  |  | 
|  | // Generate MHTML header if needed. | 
|  | if (IsMainFrame()) { | 
|  | TRACE_EVENT0("page-serialization", | 
|  | "RenderFrameImpl::SerializeAsMHTML header"); | 
|  | // The returned data can be empty if the main frame should be skipped. If | 
|  | // the main frame is skipped, then the whole archive is bad. | 
|  | mhtml_contents.emplace_back(WebFrameSerializer::GenerateMHTMLHeader( | 
|  | mhtml_boundary, GetWebFrame(), &delegate)); | 
|  | has_some_data = true; | 
|  | } | 
|  |  | 
|  | // Generate MHTML parts.  Note that if this is not the main frame, then even | 
|  | // skipping the whole parts generation step is not an error - it simply | 
|  | // results in an omitted resource in the final file. | 
|  | if (save_status == mojom::MhtmlSaveStatus::kSuccess) { | 
|  | TRACE_EVENT0("page-serialization", | 
|  | "RenderFrameImpl::SerializeAsMHTML parts serialization"); | 
|  | // The returned data can be empty if the frame should be skipped, but this | 
|  | // is OK. | 
|  | mhtml_contents.emplace_back(WebFrameSerializer::GenerateMHTMLParts( | 
|  | mhtml_boundary, GetWebFrame(), &delegate)); | 
|  | has_some_data |= !mhtml_contents.back().IsEmpty(); | 
|  | } | 
|  |  | 
|  | // Note: the MHTML footer is written by the browser process, after the last | 
|  | // frame is serialized by a renderer process. | 
|  |  | 
|  | // Note: we assume RenderFrameImpl::OnWriteMHTMLComplete and the rest of | 
|  | // this function will be fast enough to not need to be accounted for in this | 
|  | // metric. | 
|  | base::TimeDelta main_thread_use_time = base::TimeTicks::Now() - start_time; | 
|  | UMA_HISTOGRAM_TIMES( | 
|  | "PageSerialization.MhtmlGeneration.RendererMainThreadTime.SingleFrame", | 
|  | main_thread_use_time); | 
|  |  | 
|  | MHTMLHandleWriterDelegate handle_delegate( | 
|  | *params, | 
|  | base::BindOnce(&RenderFrameImpl::OnWriteMHTMLComplete, | 
|  | weak_factory_.GetWeakPtr(), std::move(callback), | 
|  | std::move(serialized_resources_uri_digests), | 
|  | main_thread_use_time), | 
|  | GetTaskRunner(blink::TaskType::kInternalDefault)); | 
|  |  | 
|  | if (save_status == mojom::MhtmlSaveStatus::kSuccess && has_some_data) { | 
|  | handle_delegate.WriteContents(mhtml_contents); | 
|  | } else { | 
|  | handle_delegate.Finish(save_status); | 
|  | } | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::OnWriteMHTMLComplete( | 
|  | SerializeAsMHTMLCallback callback, | 
|  | std::unordered_set<std::string> serialized_resources_uri_digests, | 
|  | base::TimeDelta main_thread_use_time, | 
|  | 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"; | 
|  |  | 
|  | // Convert the set into a vector for transport. | 
|  | 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())); | 
|  |  | 
|  | // Notify the browser process about completion using the callback. | 
|  | // Note: we assume this method is fast enough to not need to be accounted for | 
|  | // in PageSerialization.MhtmlGeneration.RendererMainThreadTime.SingleFrame. | 
|  | std::move(callback).Run(save_status, std::move(digests_of_new_parts), | 
|  | main_thread_use_time); | 
|  | } | 
|  |  | 
|  | #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::OnEnableViewSourceMode() { | 
|  | DCHECK(frame_); | 
|  | DCHECK(!frame_->Parent()); | 
|  | frame_->EnableViewSourceMode(true); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::OnSuppressFurtherDialogs() { | 
|  | suppress_further_dialogs_ = true; | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::OnClearFocusedElement() { | 
|  | // TODO(ekaramad): Should we add a method to WebLocalFrame instead and avoid | 
|  | // calling this on the WebView? | 
|  | if (auto* webview = render_view_->GetWebView()) | 
|  | webview->ClearFocusedElement(); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::OnBlinkFeatureUsageReport(const std::set<int>& features) { | 
|  | frame_->BlinkFeatureUsageReport(features); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::OnMixedContentFound( | 
|  | const FrameMsg_MixedContentFound_Params& params) { | 
|  | blink::WebSourceLocation source_location; | 
|  | source_location.url = WebString::FromLatin1(params.source_location.url); | 
|  | source_location.line_number = params.source_location.line_number; | 
|  | source_location.column_number = params.source_location.column_number; | 
|  | auto request_context = static_cast<blink::mojom::RequestContextType>( | 
|  | params.request_context_type); | 
|  | frame_->MixedContentFound(params.main_resource_url, params.mixed_content_url, | 
|  | request_context, params.was_allowed, | 
|  | params.had_redirect, source_location); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::OnSetOverlayRoutingToken( | 
|  | const base::UnguessableToken& token) { | 
|  | overlay_routing_token_ = token; | 
|  | for (const auto& cb : pending_routing_token_callbacks_) | 
|  | cb.Run(overlay_routing_token_.value()); | 
|  | pending_routing_token_callbacks_.clear(); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::RequestOverlayRoutingToken( | 
|  | media::RoutingTokenCallback callback) { | 
|  | if (overlay_routing_token_.has_value()) { | 
|  | std::move(callback).Run(overlay_routing_token_.value()); | 
|  | return; | 
|  | } | 
|  |  | 
|  | // Send a request to the host for the token.  We'll notify |callback| when it | 
|  | // arrives later. | 
|  | Send(new FrameHostMsg_RequestOverlayRoutingToken(routing_id_)); | 
|  |  | 
|  | pending_routing_token_callbacks_.push_back(std::move(callback)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::OnNotifyUserActivation() { | 
|  | frame_->NotifyUserActivation(); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::OnMediaPlayerActionAt( | 
|  | const gfx::PointF& location, | 
|  | const blink::WebMediaPlayerAction& action) { | 
|  | blink::WebFloatRect viewport_position(location.x(), location.y(), 0, 0); | 
|  | GetLocalRootRenderWidget()->ConvertWindowToViewport(&viewport_position); | 
|  | frame_->PerformMediaPlayerAction( | 
|  | WebPoint(viewport_position.x, viewport_position.y), action); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::OnRenderFallbackContent() const { | 
|  | frame_->RenderFallbackContent(); | 
|  | } | 
|  |  | 
|  | #if BUILDFLAG(USE_EXTERNAL_POPUP_MENU) | 
|  | #if defined(OS_MACOSX) | 
|  | void RenderFrameImpl::OnSelectPopupMenuItem(int selected_index) { | 
|  | if (external_popup_menu_ == NULL) | 
|  | return; | 
|  |  | 
|  | blink::WebScopedUserGesture gesture(frame_); | 
|  | // We need to reset |external_popup_menu_| before calling DidSelectItem(), | 
|  | // which might delete |this|. | 
|  | // See ExternalPopupMenuRemoveTest.RemoveFrameOnChange | 
|  | std::unique_ptr<ExternalPopupMenu> popup; | 
|  | popup.swap(external_popup_menu_); | 
|  | popup->DidSelectItem(selected_index); | 
|  | } | 
|  | #else | 
|  | void RenderFrameImpl::OnSelectPopupMenuItems( | 
|  | bool canceled, | 
|  | const std::vector<int>& selected_indices) { | 
|  | // It is possible to receive more than one of these calls if the user presses | 
|  | // a select faster than it takes for the show-select-popup IPC message to make | 
|  | // it to the browser UI thread. Ignore the extra-messages. | 
|  | // TODO(jcivelli): http:/b/5793321 Implement a better fix, as detailed in bug. | 
|  | if (!external_popup_menu_) | 
|  | return; | 
|  |  | 
|  | blink::WebScopedUserGesture gesture(frame_); | 
|  | // We need to reset |external_popup_menu_| before calling DidSelectItems(), | 
|  | // which might delete |this|. | 
|  | // See ExternalPopupMenuRemoveTest.RemoveFrameOnChange | 
|  | std::unique_ptr<ExternalPopupMenu> popup; | 
|  | popup.swap(external_popup_menu_); | 
|  | popup->DidSelectItems(canceled, selected_indices); | 
|  | } | 
|  | #endif | 
|  | #endif | 
|  |  | 
|  | void RenderFrameImpl::OpenURL(std::unique_ptr<blink::WebNavigationInfo> info, | 
|  | bool is_history_navigation_in_new_child) { | 
|  | // A valid RequestorOrigin is always expected to be present. | 
|  | DCHECK(!info->url_request.RequestorOrigin().IsNull()); | 
|  |  | 
|  | WebNavigationPolicy policy = info->navigation_policy; | 
|  | FrameHostMsg_OpenURL_Params params; | 
|  | params.url = info->url_request.Url(); | 
|  | params.initiator_origin = info->url_request.RequestorOrigin(); | 
|  | params.uses_post = IsHttpPost(info->url_request); | 
|  | params.resource_request_body = | 
|  | GetRequestBodyForWebURLRequest(info->url_request); | 
|  | params.extra_headers = GetWebURLRequestHeadersAsString(info->url_request); | 
|  | params.referrer = | 
|  | RenderViewImpl::GetReferrerFromRequest(frame_, info->url_request); | 
|  | params.disposition = RenderViewImpl::NavigationPolicyToDisposition(policy); | 
|  | params.triggering_event_info = info->triggering_event_info; | 
|  | params.blob_url_token = | 
|  | CloneBlobURLToken(info->blob_url_token.get()).PassHandle().release(); | 
|  | params.should_replace_current_entry = | 
|  | info->frame_load_type == WebFrameLoadType::kReplaceCurrentItem && | 
|  | render_view_->history_list_length_; | 
|  | params.user_gesture = info->has_transient_user_activation; | 
|  | if (GetContentClient()->renderer()->AllowPopup()) | 
|  | params.user_gesture = true; | 
|  |  | 
|  | // TODO(csharrison,dgozman): FrameLoader::StartNavigation already consumes for | 
|  | // all main frame navigations, except in the case where page A is navigating | 
|  | // page B (e.g. using anchor targets). This edge case can go away when | 
|  | // UserActivationV2 ships, which would make the conditional below redundant. | 
|  | if (is_main_frame_ || policy == blink::kWebNavigationPolicyNewBackgroundTab || | 
|  | policy == blink::kWebNavigationPolicyNewForegroundTab || | 
|  | policy == blink::kWebNavigationPolicyNewWindow || | 
|  | policy == blink::kWebNavigationPolicyNewPopup) { | 
|  | WebUserGestureIndicator::ConsumeUserGesture(frame_); | 
|  | } | 
|  |  | 
|  | if (is_history_navigation_in_new_child) | 
|  | params.is_history_navigation_in_new_child = true; | 
|  |  | 
|  | params.href_translate = info->href_translate.Latin1(); | 
|  |  | 
|  | bool current_frame_has_download_sandbox_flag = | 
|  | !frame_->IsAllowedToDownloadWithoutUserActivation(); | 
|  | 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_->IsAdSubframe(); | 
|  |  | 
|  | MaybeSetDownloadFramePolicy( | 
|  | info->is_opener_navigation, info->url_request, | 
|  | frame_->GetSecurityOrigin(), has_download_sandbox_flag, | 
|  | info->blocking_downloads_in_sandbox_without_user_activation_enabled, | 
|  | from_ad, ¶ms.download_policy); | 
|  |  | 
|  | Send(new FrameHostMsg_OpenURL(routing_id_, params)); | 
|  | } | 
|  |  | 
|  | ChildURLLoaderFactoryBundle* RenderFrameImpl::GetLoaderFactoryBundle() { | 
|  | if (!loader_factories_) { | 
|  | RenderFrameImpl* creator = RenderFrameImpl::FromWebFrame( | 
|  | frame_->Parent() ? frame_->Parent() : frame_->Opener()); | 
|  | if (creator) { | 
|  | auto bundle_info = | 
|  | base::WrapUnique(static_cast<TrackedChildURLLoaderFactoryBundleInfo*>( | 
|  | creator->GetLoaderFactoryBundle()->Clone().release())); | 
|  | loader_factories_ = | 
|  | base::MakeRefCounted<TrackedChildURLLoaderFactoryBundle>( | 
|  | std::move(bundle_info)); | 
|  | } else { | 
|  | SetupLoaderFactoryBundle(nullptr, | 
|  | base::nullopt /* subresource_overrides */, | 
|  | nullptr /* prefetch_loader_factory */); | 
|  | } | 
|  | } | 
|  | return loader_factories_.get(); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::SetupLoaderFactoryBundle( | 
|  | std::unique_ptr<blink::URLLoaderFactoryBundleInfo> info, | 
|  | base::Optional<std::vector<mojom::TransferrableURLLoaderPtr>> | 
|  | subresource_overrides, | 
|  | network::mojom::URLLoaderFactoryPtr prefetch_loader_factory) { | 
|  | RenderThreadImpl* render_thread = RenderThreadImpl::current(); | 
|  |  | 
|  | loader_factories_ = base::MakeRefCounted<HostChildURLLoaderFactoryBundle>( | 
|  | GetTaskRunner(blink::TaskType::kInternalLoading)); | 
|  |  | 
|  | // In some tests |render_thread| could be null. | 
|  | if (render_thread && !info) { | 
|  | // This should only happen for: | 
|  | // 1) non-NetworkService cases, or | 
|  | // 2) With NetworkService, but only for a placeholder document or an | 
|  | // initial empty document cases. | 
|  | DCHECK(!base::FeatureList::IsEnabled(network::features::kNetworkService) || | 
|  | GetLoadingUrl().is_empty() || | 
|  | GetLoadingUrl().spec() == url::kAboutBlankURL); | 
|  | loader_factories_->Update(render_thread->blink_platform_impl() | 
|  | ->CreateDefaultURLLoaderFactoryBundle() | 
|  | ->PassInterface()); | 
|  | } | 
|  |  | 
|  | if (info) { | 
|  | loader_factories_->Update( | 
|  | std::make_unique<ChildURLLoaderFactoryBundleInfo>(std::move(info))); | 
|  | } | 
|  | if (subresource_overrides) { | 
|  | loader_factories_->UpdateSubresourceOverrides(&*subresource_overrides); | 
|  | } | 
|  | if (prefetch_loader_factory) { | 
|  | loader_factories_->SetPrefetchLoaderFactory( | 
|  | std::move(prefetch_loader_factory)); | 
|  | } | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::UpdateEncoding(WebFrame* frame, | 
|  | const std::string& encoding_name) { | 
|  | // Only update main frame's encoding_name. | 
|  | if (!frame->Parent()) | 
|  | GetFrameHost()->UpdateEncoding(encoding_name); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::SyncSelectionIfRequired() { | 
|  | base::string16 text; | 
|  | size_t offset; | 
|  | gfx::Range range; | 
|  | #if BUILDFLAG(ENABLE_PLUGINS) | 
|  | if (focused_pepper_plugin_) { | 
|  | focused_pepper_plugin_->GetSurroundingText(&text, &range); | 
|  | offset = 0;  // Pepper API does not support offset reporting. | 
|  | // TODO(kinaba): cut as needed. | 
|  | } else | 
|  | #endif | 
|  | { | 
|  | WebRange selection = | 
|  | frame_->GetInputMethodController()->GetSelectionOffsets(); | 
|  | if (selection.IsNull()) | 
|  | return; | 
|  |  | 
|  | range = gfx::Range(selection.StartOffset(), selection.EndOffset()); | 
|  |  | 
|  | if (frame_->GetInputMethodController()->TextInputType() != | 
|  | blink::kWebTextInputTypeNone) { | 
|  | // If current focused element is editable, we will send 100 more chars | 
|  | // before and after selection. It is for input method surrounding text | 
|  | // feature. | 
|  | if (selection.StartOffset() > kExtraCharsBeforeAndAfterSelection) | 
|  | offset = selection.StartOffset() - kExtraCharsBeforeAndAfterSelection; | 
|  | else | 
|  | offset = 0; | 
|  | size_t length = | 
|  | selection.EndOffset() - offset + kExtraCharsBeforeAndAfterSelection; | 
|  | text = frame_->RangeAsText(WebRange(offset, length)).Utf16(); | 
|  | } else { | 
|  | offset = selection.StartOffset(); | 
|  | text = frame_->SelectionAsText().Utf16(); | 
|  | // http://crbug.com/101435 | 
|  | // In some case, frame->selectionAsText() returned text's length is not | 
|  | // equal to the length returned from frame_->GetSelectionOffsets(). So we | 
|  | // have to set the range according to text.length(). | 
|  | range.set_end(range.start() + text.length()); | 
|  | } | 
|  | } | 
|  |  | 
|  | // TODO(dglazkov): Investigate if and why this would be happening, | 
|  | // and resolve this. We shouldn't be carrying selection text here. | 
|  | // http://crbug.com/632920. | 
|  | // Sometimes we get repeated didChangeSelection calls from webkit when | 
|  | // the selection hasn't actually changed. We don't want to report these | 
|  | // because it will cause us to continually claim the X clipboard. | 
|  | if (selection_text_offset_ != offset || | 
|  | selection_range_ != range || | 
|  | selection_text_ != text) { | 
|  | selection_text_ = text; | 
|  | selection_text_offset_ = offset; | 
|  | selection_range_ = range; | 
|  | SetSelectedText(text, offset, range); | 
|  | } | 
|  | GetLocalRootRenderWidget()->UpdateSelectionBounds(); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::ScrollFocusedEditableElementIntoRect( | 
|  | const gfx::Rect& rect) { | 
|  | // TODO(ekaramad): Perhaps we should remove |rect| since all it seems to be | 
|  | // doing is helping verify if scrolling animation for a given focused editable | 
|  | // element has finished. | 
|  | blink::WebAutofillClient* autofill_client = frame_->AutofillClient(); | 
|  | if (has_scrolled_focused_editable_node_into_rect_ && | 
|  | rect == rect_for_scrolled_focused_editable_node_ && autofill_client) { | 
|  | autofill_client->DidCompleteFocusChangeInFrame(); | 
|  | return; | 
|  | } | 
|  |  | 
|  | if (!frame_->LocalRoot() | 
|  | ->FrameWidget() | 
|  | ->ScrollFocusedEditableElementIntoView()) { | 
|  | return; | 
|  | } | 
|  |  | 
|  | rect_for_scrolled_focused_editable_node_ = rect; | 
|  | has_scrolled_focused_editable_node_into_rect_ = true; | 
|  | if (!GetLocalRootRenderWidget()->HasPendingPageScaleAnimation() && | 
|  | autofill_client) { | 
|  | autofill_client->DidCompleteFocusChangeInFrame(); | 
|  | } | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::ResetHasScrolledFocusedEditableIntoView() { | 
|  | has_scrolled_focused_editable_node_into_rect_ = false; | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::InitializeUserMediaClient() { | 
|  | RenderThreadImpl* render_thread = RenderThreadImpl::current(); | 
|  | if (!render_thread)  // Will be NULL during unit tests. | 
|  | return; | 
|  |  | 
|  | DCHECK(!web_user_media_client_); | 
|  | web_user_media_client_ = new UserMediaClientImpl( | 
|  | this, RenderThreadImpl::current()->GetPeerConnectionDependencyFactory(), | 
|  | std::make_unique<MediaStreamDeviceObserver>(this), | 
|  | GetTaskRunner(blink::TaskType::kInternalMedia)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::PrepareRenderViewForNavigation( | 
|  | const GURL& url, | 
|  | const CommitNavigationParams& commit_params) { | 
|  | DCHECK(render_view_->webview()); | 
|  |  | 
|  | if (is_main_frame_) { | 
|  | for (auto& observer : render_view_->observers_) | 
|  | observer.Navigate(url); | 
|  | } | 
|  |  | 
|  | render_view_->history_list_offset_ = | 
|  | commit_params.current_history_list_offset; | 
|  | render_view_->history_list_length_ = | 
|  | commit_params.current_history_list_length; | 
|  | } | 
|  |  | 
|  | namespace { | 
|  | std::unique_ptr<base::DictionaryValue> GetDevToolsInitiator( | 
|  | const WebString& initiator_str) { | 
|  | if (initiator_str.IsNull()) | 
|  | return nullptr; | 
|  | std::unique_ptr<base::DictionaryValue> initiator = | 
|  | base::DictionaryValue::From( | 
|  | base::JSONReader::ReadDeprecated(initiator_str.Utf8())); | 
|  | if (!initiator) | 
|  | return nullptr; | 
|  | // TODO(kozy,caseq): the hack below is due to the fact that initiators include | 
|  | // the chain of async callstacks that results in a tree of Values so deep | 
|  | // that it triggers mojo structure nesting limit upon deserialization. | 
|  | // See https://crbug.com/809996 for more details. | 
|  | // We trim async stacks here, but it should be possible to capture locations | 
|  | // without async stacks (or with custom limit on their number) instead. | 
|  | base::Value* parent = initiator->FindPath({"stack", "parent"}); | 
|  | if (parent && parent->is_dict()) | 
|  | parent->RemoveKey("parent"); | 
|  | return initiator; | 
|  | } | 
|  | }  // namespace | 
|  |  | 
|  | void RenderFrameImpl::BeginNavigationInternal( | 
|  | std::unique_ptr<blink::WebNavigationInfo> info) { | 
|  | std::unique_ptr<DocumentState> document_state_owned = BuildDocumentState(); | 
|  | DocumentState* document_state = document_state_owned.get(); | 
|  | if (!frame_->CreatePlaceholderDocumentLoader( | 
|  | *info, std::move(document_state_owned))) { | 
|  | return; | 
|  | } | 
|  |  | 
|  | browser_side_navigation_pending_ = true; | 
|  | browser_side_navigation_pending_url_ = info->url_request.Url(); | 
|  |  | 
|  | blink::WebURLRequest& request = info->url_request; | 
|  |  | 
|  | // Set SiteForCookies. | 
|  | WebDocument frame_document = frame_->GetDocument(); | 
|  | if (info->frame_type == network::mojom::RequestContextFrameType::kTopLevel) | 
|  | request.SetSiteForCookies(request.Url()); | 
|  | else | 
|  | request.SetSiteForCookies(frame_document.SiteForCookies()); | 
|  |  | 
|  | ui::PageTransition transition_type = GetTransitionType( | 
|  | ui::PAGE_TRANSITION_LINK, | 
|  | info->frame_load_type == WebFrameLoadType::kReplaceCurrentItem, | 
|  | IsMainFrame(), info->navigation_type); | 
|  | if (info->is_client_redirect) { | 
|  | transition_type = ui::PageTransitionFromInt( | 
|  | transition_type | ui::PAGE_TRANSITION_CLIENT_REDIRECT); | 
|  | } | 
|  |  | 
|  | // Note: At this stage, the goal is to apply all the modifications the | 
|  | // renderer wants to make to the request, and then send it to the browser, so | 
|  | // that the actual network request can be started. Ideally, all such | 
|  | // modifications should take place in WillSendRequestInternal, and in the | 
|  | // implementation of willSendRequest for the various InspectorAgents | 
|  | // (devtools). | 
|  | // | 
|  | // TODO(clamy): Apply devtools override. | 
|  | // TODO(clamy): Make sure that navigation requests are not modified somewhere | 
|  | // else in blink. | 
|  | WillSendRequestInternal( | 
|  | request, | 
|  | frame_->Parent() ? ResourceType::kSubFrame : ResourceType::kMainFrame, | 
|  | document_state, transition_type); | 
|  |  | 
|  | if (!info->url_request.GetExtraData()) | 
|  | info->url_request.SetExtraData(std::make_unique<RequestExtraData>()); | 
|  |  | 
|  | // TODO(clamy): Same-document navigations should not be sent back to the | 
|  | // browser. | 
|  | // TODO(clamy): Data urls should not be sent back to the browser either. | 
|  | // These values are assumed on the browser side for navigations. These checks | 
|  | // ensure the renderer has the correct values. | 
|  | DCHECK_EQ(network::mojom::FetchRequestMode::kNavigate, | 
|  | info->url_request.GetFetchRequestMode()); | 
|  | DCHECK_EQ(network::mojom::FetchCredentialsMode::kInclude, | 
|  | info->url_request.GetFetchCredentialsMode()); | 
|  | DCHECK_EQ(network::mojom::FetchRedirectMode::kManual, | 
|  | info->url_request.GetFetchRedirectMode()); | 
|  | DCHECK(frame_->Parent() || | 
|  | info->frame_type == | 
|  | network::mojom::RequestContextFrameType::kTopLevel); | 
|  | DCHECK(!frame_->Parent() || | 
|  | info->frame_type == network::mojom::RequestContextFrameType::kNested); | 
|  |  | 
|  | bool is_form_submission = | 
|  | info->navigation_type == blink::kWebNavigationTypeFormSubmitted || | 
|  | info->navigation_type == blink::kWebNavigationTypeFormResubmitted; | 
|  |  | 
|  | 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(); | 
|  |  | 
|  | blink::mojom::BlobURLTokenPtr blob_url_token( | 
|  | CloneBlobURLToken(info->blob_url_token.get())); | 
|  |  | 
|  | int load_flags = info->url_request.GetLoadFlagsForWebUrlRequest(); | 
|  | std::unique_ptr<base::DictionaryValue> initiator = | 
|  | GetDevToolsInitiator(info->devtools_initiator_info); | 
|  | mojom::BeginNavigationParamsPtr begin_navigation_params = | 
|  | mojom::BeginNavigationParams::New( | 
|  | GetWebURLRequestHeadersAsString(info->url_request), load_flags, | 
|  | info->url_request.GetSkipServiceWorker(), | 
|  | GetRequestContextTypeForWebURLRequest(info->url_request), | 
|  | GetMixedContentContextTypeForWebURLRequest(info->url_request), | 
|  | is_form_submission, searchable_form_url, searchable_form_encoding, | 
|  | client_side_redirect_url, | 
|  | initiator ? base::make_optional<base::Value>(std::move(*initiator)) | 
|  | : base::nullopt); | 
|  |  | 
|  | mojom::NavigationClientAssociatedPtrInfo navigation_client_info; | 
|  | if (IsPerNavigationMojoInterfaceEnabled()) { | 
|  | BindNavigationClient(mojo::MakeRequest(&navigation_client_info)); | 
|  | navigation_client_impl_->MarkWasInitiatedInThisFrame(); | 
|  | } | 
|  |  | 
|  | blink::mojom::NavigationInitiatorPtr initiator_ptr( | 
|  | blink::mojom::NavigationInitiatorPtrInfo( | 
|  | std::move(info->navigation_initiator_handle), 0)); | 
|  |  | 
|  | bool current_frame_has_download_sandbox_flag = | 
|  | !frame_->IsAllowedToDownloadWithoutUserActivation(); | 
|  | 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_->IsAdSubframe(); | 
|  |  | 
|  | GetFrameHost()->BeginNavigation( | 
|  | MakeCommonNavigationParams(frame_->GetSecurityOrigin(), std::move(info), | 
|  | load_flags, has_download_sandbox_flag, | 
|  | from_ad), | 
|  | std::move(begin_navigation_params), std::move(blob_url_token), | 
|  | std::move(navigation_client_info), std::move(initiator_ptr)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DecodeDataURL(const CommonNavigationParams& common_params, | 
|  | const CommitNavigationParams& commit_params, | 
|  | std::string* mime_type, | 
|  | std::string* charset, | 
|  | std::string* data, | 
|  | GURL* base_url) { | 
|  | // A loadData request with a specified base URL. | 
|  | GURL data_url = common_params.url; | 
|  | #if defined(OS_ANDROID) | 
|  | 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 { | 
|  | CHECK(false) << "Invalid URL passed: " | 
|  | << common_params.url.possibly_invalid_spec(); | 
|  | } | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::SendUpdateState() { | 
|  | if (current_history_item_.IsNull()) | 
|  | return; | 
|  |  | 
|  | Send(new FrameHostMsg_UpdateState( | 
|  | routing_id_, SingleHistoryItemToPageState(current_history_item_))); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::SendFailedProvisionalLoad(const std::string& http_method, | 
|  | const WebURLError& error, | 
|  | blink::WebLocalFrame* frame) { | 
|  | bool show_repost_interstitial = | 
|  | error.reason() == net::ERR_CACHE_MISS && http_method == "POST"; | 
|  |  | 
|  | FrameHostMsg_DidFailProvisionalLoadWithError_Params params; | 
|  | params.error_code = error.reason(); | 
|  | GetContentClient()->renderer()->GetErrorDescription( | 
|  | error, http_method, ¶ms.error_description); | 
|  | params.url = error.url(), | 
|  | params.showing_repost_interstitial = show_repost_interstitial; | 
|  | Send(new FrameHostMsg_DidFailProvisionalLoadWithError(routing_id_, params)); | 
|  | } | 
|  |  | 
|  | bool RenderFrameImpl::ShouldDisplayErrorPageForFailedLoad( | 
|  | int error_code, | 
|  | const GURL& unreachable_url) { | 
|  | // Don't display an error page if this is simply a cancelled load.  Aside | 
|  | // from being dumb, Blink doesn't expect it and it will cause a crash. | 
|  | if (error_code == net::ERR_ABORTED) | 
|  | return false; | 
|  |  | 
|  | // Don't display "client blocked" error page if browser has asked us not to. | 
|  | if (error_code == net::ERR_BLOCKED_BY_CLIENT && | 
|  | render_view_->renderer_preferences_.disable_client_blocked_error_page) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | // Allow the embedder to suppress an error page. | 
|  | if (GetContentClient()->renderer()->ShouldSuppressErrorPage( | 
|  | this, unreachable_url)) { | 
|  | return false; | 
|  | } | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | 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_.reset(new MediaPermissionDispatcher(this)); | 
|  | return media_permission_dispatcher_.get(); | 
|  | } | 
|  |  | 
|  | #if BUILDFLAG(ENABLE_PLUGINS) | 
|  | void RenderFrameImpl::HandlePepperImeCommit(const base::string16& text) { | 
|  | if (text.empty()) | 
|  | return; | 
|  |  | 
|  | if (!IsPepperAcceptingCompositionEvents()) { | 
|  | // For pepper plugins unable to handle IME events, send the plugin a | 
|  | // sequence of characters instead. | 
|  | base::i18n::UTF16CharIterator iterator(&text); | 
|  | int32_t i = 0; | 
|  | while (iterator.Advance()) { | 
|  | blink::WebKeyboardEvent char_event(blink::WebInputEvent::kChar, | 
|  | blink::WebInputEvent::kNoModifiers, | 
|  | ui::EventTimeForNow()); | 
|  | char_event.windows_key_code = text[i]; | 
|  | char_event.native_key_code = text[i]; | 
|  |  | 
|  | const int32_t char_start = i; | 
|  | for (; i < iterator.array_pos(); ++i) { | 
|  | char_event.text[i - char_start] = text[i]; | 
|  | char_event.unmodified_text[i - char_start] = text[i]; | 
|  | } | 
|  |  | 
|  | if (GetLocalRootRenderWidget()->GetWebWidget()) | 
|  | GetLocalRootRenderWidget()->GetWebWidget()->HandleInputEvent( | 
|  | blink::WebCoalescedInputEvent(char_event)); | 
|  | } | 
|  | } else { | 
|  | // Mimics the order of events sent by WebKit. | 
|  | // See WebCore::Editor::setComposition() for the corresponding code. | 
|  | focused_pepper_plugin_->HandleCompositionEnd(text); | 
|  | focused_pepper_plugin_->HandleTextInput(text); | 
|  | } | 
|  | pepper_composition_text_.clear(); | 
|  | } | 
|  | #endif  // ENABLE_PLUGINS | 
|  |  | 
|  | void RenderFrameImpl::RegisterMojoInterfaces() { | 
|  | GetAssociatedInterfaceRegistry()->AddInterface(base::Bind( | 
|  | &RenderFrameImpl::BindAutoplayConfiguration, weak_factory_.GetWeakPtr())); | 
|  |  | 
|  | GetAssociatedInterfaceRegistry()->AddInterface(base::Bind( | 
|  | &RenderFrameImpl::BindFrameBindingsControl, weak_factory_.GetWeakPtr())); | 
|  |  | 
|  | GetAssociatedInterfaceRegistry()->AddInterface( | 
|  | base::Bind(&RenderFrameImpl::BindFrameNavigationControl, | 
|  | weak_factory_.GetWeakPtr())); | 
|  |  | 
|  | if (IsPerNavigationMojoInterfaceEnabled()) { | 
|  | GetAssociatedInterfaceRegistry()->AddInterface(base::BindRepeating( | 
|  | &RenderFrameImpl::BindNavigationClient, weak_factory_.GetWeakPtr())); | 
|  | } | 
|  |  | 
|  | GetAssociatedInterfaceRegistry()->AddInterface(base::BindRepeating( | 
|  | &RenderFrameImpl::BindFullscreen, weak_factory_.GetWeakPtr())); | 
|  |  | 
|  | registry_.AddInterface(base::Bind(&FrameInputHandlerImpl::CreateMojoService, | 
|  | weak_factory_.GetWeakPtr())); | 
|  |  | 
|  | registry_.AddInterface( | 
|  | base::Bind(&InputTargetClientImpl::BindToRequest, | 
|  | base::Unretained(&input_target_client_impl_))); | 
|  |  | 
|  | registry_.AddInterface( | 
|  | base::Bind(&RenderFrameImpl::BindWidget, weak_factory_.GetWeakPtr())); | 
|  |  | 
|  | GetAssociatedInterfaceRegistry()->AddInterface(base::BindRepeating( | 
|  | &RenderFrameImpl::BindMhtmlFileWriter, base::Unretained(this))); | 
|  |  | 
|  | if (!frame_->Parent()) { | 
|  | // Only main frame have ImageDownloader service. | 
|  | registry_.AddInterface(base::Bind(&ImageDownloaderImpl::CreateMojoService, | 
|  | base::Unretained(this))); | 
|  |  | 
|  | // Host zoom is per-page, so only added on the main frame. | 
|  | GetAssociatedInterfaceRegistry()->AddInterface(base::Bind( | 
|  | &RenderFrameImpl::OnHostZoomClientRequest, weak_factory_.GetWeakPtr())); | 
|  |  | 
|  | // Web manifests are only requested for main frames. | 
|  | registry_.AddInterface( | 
|  | base::Bind(&ManifestManager::BindToRequest, | 
|  | base::Unretained(manifest_manager_.get()))); | 
|  | } | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::OnHostZoomClientRequest( | 
|  | mojom::HostZoomAssociatedRequest request) { | 
|  | DCHECK(!host_zoom_binding_.is_bound()); | 
|  | host_zoom_binding_.Bind(std::move(request), | 
|  | GetTaskRunner(blink::TaskType::kInternalIPC)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::BindMhtmlFileWriter( | 
|  | mojom::MhtmlFileWriterAssociatedRequest request) { | 
|  | mhtml_file_writer_binding_.Bind( | 
|  | std::move(request), GetTaskRunner(blink::TaskType::kInternalDefault)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::CheckIfAudioSinkExistsAndIsAuthorized( | 
|  | const blink::WebString& sink_id, | 
|  | blink::WebSetSinkIdCompleteCallback completion_callback) { | 
|  | std::move( | 
|  | media::ConvertToOutputDeviceStatusCB(std::move(completion_callback))) | 
|  | .Run(AudioDeviceFactory::GetOutputDeviceInfo( | 
|  | GetRoutingID(), media::AudioSinkParameters(0, sink_id.Utf8())) | 
|  | .device_status()); | 
|  | } | 
|  |  | 
|  | std::unique_ptr<blink::WebURLLoaderFactory> | 
|  | RenderFrameImpl::CreateURLLoaderFactory() { | 
|  | if (!RenderThreadImpl::current()) { | 
|  | // Some tests (e.g. RenderViewTests) do not have RenderThreadImpl, | 
|  | // use the platform's default WebURLLoaderFactoryImpl for them. | 
|  | return WebURLLoaderFactoryImpl::CreateTestOnlyFactory(); | 
|  | } | 
|  | return std::make_unique<FrameURLLoaderFactory>(weak_factory_.GetWeakPtr()); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::DraggableRegionsChanged() { | 
|  | for (auto& observer : observers_) | 
|  | observer.DraggableRegionsChanged(); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::ScrollRectToVisibleInParentFrame( | 
|  | const blink::WebRect& rect_to_scroll, | 
|  | const blink::WebScrollIntoViewParams& params) { | 
|  | DCHECK(IsLocalRoot()); | 
|  | Send(new FrameHostMsg_ScrollRectToVisibleInParentFrame( | 
|  | routing_id_, rect_to_scroll, params)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::BubbleLogicalScrollInParentFrame( | 
|  | blink::WebScrollDirection direction, | 
|  | blink::WebScrollGranularity granularity) { | 
|  | DCHECK(IsLocalRoot()); | 
|  | DCHECK(!IsMainFrame()); | 
|  | Send(new FrameHostMsg_BubbleLogicalScrollInParentFrame(routing_id_, direction, | 
|  | granularity)); | 
|  | } | 
|  |  | 
|  | bool RenderFrameImpl::IsBrowserSideNavigationPending() { | 
|  | return browser_side_navigation_pending_; | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::LoadHTMLString(const std::string& html, | 
|  | const GURL& base_url, | 
|  | const std::string& text_encoding, | 
|  | const GURL& unreachable_url, | 
|  | bool replace_current_item) { | 
|  | 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; | 
|  | frame_->CommitNavigation(std::move(navigation_params), | 
|  | nullptr /* extra_data */); | 
|  | } | 
|  |  | 
|  | scoped_refptr<base::SingleThreadTaskRunner> RenderFrameImpl::GetTaskRunner( | 
|  | blink::TaskType task_type) { | 
|  | return GetWebFrame()->GetTaskRunner(task_type); | 
|  | } | 
|  |  | 
|  | int RenderFrameImpl::GetEnabledBindings() { | 
|  | return enabled_bindings_; | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::FrameDidCallFocus() { | 
|  | Send(new FrameHostMsg_FrameDidCallFocus(routing_id_)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::SetAccessibilityModeForTest(ui::AXMode new_mode) { | 
|  | OnSetAccessibilityMode(new_mode); | 
|  | } | 
|  |  | 
|  | scoped_refptr<network::SharedURLLoaderFactory> | 
|  | RenderFrameImpl::GetURLLoaderFactory() { | 
|  | return GetLoaderFactoryBundle(); | 
|  | } | 
|  |  | 
|  | const RenderFrameMediaPlaybackOptions& | 
|  | RenderFrameImpl::GetRenderFrameMediaPlaybackOptions() { | 
|  | return renderer_media_playback_options_; | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::SetRenderFrameMediaPlaybackOptions( | 
|  | const RenderFrameMediaPlaybackOptions& opts) { | 
|  | renderer_media_playback_options_ = opts; | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::UpdateAllLifecyclePhasesAndCompositeForTesting() { | 
|  | // This is only called for web tests and WebFrameTestProxy overrides this | 
|  | // method to implement it there. | 
|  | NOTREACHED(); | 
|  | } | 
|  |  | 
|  | #if BUILDFLAG(ENABLE_PLUGINS) | 
|  | void RenderFrameImpl::PepperInstanceCreated( | 
|  | PepperPluginInstanceImpl* instance) { | 
|  | active_pepper_instances_.insert(instance); | 
|  |  | 
|  | Send(new FrameHostMsg_PepperInstanceCreated( | 
|  | routing_id_, instance->pp_instance())); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::PepperInstanceDeleted( | 
|  | PepperPluginInstanceImpl* instance) { | 
|  | active_pepper_instances_.erase(instance); | 
|  |  | 
|  | if (pepper_last_mouse_event_target_ == instance) | 
|  | pepper_last_mouse_event_target_ = nullptr; | 
|  | if (focused_pepper_plugin_ == instance) | 
|  | PepperFocusChanged(instance, false); | 
|  |  | 
|  | RenderFrameImpl* const render_frame = instance->render_frame(); | 
|  | if (render_frame) { | 
|  | render_frame->Send( | 
|  | new FrameHostMsg_PepperInstanceDeleted( | 
|  | render_frame->GetRoutingID(), | 
|  | instance->pp_instance())); | 
|  | } | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::PepperFocusChanged(PepperPluginInstanceImpl* instance, | 
|  | bool focused) { | 
|  | if (focused) | 
|  | focused_pepper_plugin_ = instance; | 
|  | else if (focused_pepper_plugin_ == instance) | 
|  | focused_pepper_plugin_ = nullptr; | 
|  |  | 
|  | GetLocalRootRenderWidget()->UpdateTextInputState(); | 
|  | GetLocalRootRenderWidget()->UpdateSelectionBounds(); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::PepperStartsPlayback(PepperPluginInstanceImpl* instance) { | 
|  | RenderFrameImpl* const render_frame = instance->render_frame(); | 
|  | if (render_frame) { | 
|  | render_frame->Send( | 
|  | new FrameHostMsg_PepperStartsPlayback( | 
|  | render_frame->GetRoutingID(), | 
|  | instance->pp_instance())); | 
|  | } | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::PepperStopsPlayback(PepperPluginInstanceImpl* instance) { | 
|  | RenderFrameImpl* const render_frame = instance->render_frame(); | 
|  | if (render_frame) { | 
|  | render_frame->Send( | 
|  | new FrameHostMsg_PepperStopsPlayback( | 
|  | render_frame->GetRoutingID(), | 
|  | instance->pp_instance())); | 
|  | } | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::OnSetPepperVolume(int32_t pp_instance, double volume) { | 
|  | PepperPluginInstanceImpl* instance = static_cast<PepperPluginInstanceImpl*>( | 
|  | PepperPluginInstance::Get(pp_instance)); | 
|  | if (instance) | 
|  | instance->audio_controller().SetVolume(volume); | 
|  | } | 
|  | #endif  // ENABLE_PLUGINS | 
|  |  | 
|  | void RenderFrameImpl::ShowCreatedWindow(bool opened_by_user_gesture, | 
|  | RenderWidget* render_widget_to_show, | 
|  | WebNavigationPolicy policy, | 
|  | const gfx::Rect& initial_rect) { | 
|  | // |render_widget_to_show| is the main RenderWidget for a pending window | 
|  | // created by this object, but not yet shown. The tab is currently offscreen, | 
|  | // and still owned by the opener. Sending |FrameHostMsg_ShowCreatedWindow| | 
|  | // will move it off the opener's pending list, and put it in its own tab or | 
|  | // window. | 
|  | // | 
|  | // This call happens only for renderer-created windows; for example, when a | 
|  | // tab is created by script via window.open(). | 
|  | Send(new FrameHostMsg_ShowCreatedWindow( | 
|  | GetRoutingID(), render_widget_to_show->routing_id(), | 
|  | RenderViewImpl::NavigationPolicyToDisposition(policy), initial_rect, | 
|  | opened_by_user_gesture)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::RenderWidgetSetFocus(bool enable) { | 
|  | #if BUILDFLAG(ENABLE_PLUGINS) | 
|  | // Notify all Pepper plugins. | 
|  | for (auto* plugin : active_pepper_instances_) | 
|  | plugin->SetContentAreaFocus(enable); | 
|  | #endif | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::RenderWidgetWillHandleMouseEvent() { | 
|  | #if BUILDFLAG(ENABLE_PLUGINS) | 
|  | // This method is called for every mouse event that the RenderWidget receives. | 
|  | // And then the mouse event is forwarded to blink, which dispatches it to the | 
|  | // event target. Potentially a Pepper plugin will receive the event. | 
|  | // In order to tell whether a plugin gets the last mouse event and which it | 
|  | // is, we set |pepper_last_mouse_event_target_| to null here. If a plugin gets | 
|  | // the event, it will notify us via DidReceiveMouseEvent() and set itself as | 
|  | // |pepper_last_mouse_event_target_|. | 
|  | pepper_last_mouse_event_target_ = nullptr; | 
|  | #endif | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::BindWidget(mojom::WidgetRequest request) { | 
|  | GetLocalRootRenderWidget()->SetWidgetBinding(std::move(request)); | 
|  | } | 
|  |  | 
|  | blink::WebComputedAXTree* RenderFrameImpl::GetOrCreateWebComputedAXTree() { | 
|  | if (!computed_ax_tree_) | 
|  | computed_ax_tree_ = std::make_unique<AomContentAxTree>(this); | 
|  | return computed_ax_tree_.get(); | 
|  | } | 
|  |  | 
|  | std::unique_ptr<blink::WebSocketHandshakeThrottle> | 
|  | RenderFrameImpl::CreateWebSocketHandshakeThrottle() { | 
|  | WebLocalFrame* web_local_frame = GetWebFrame(); | 
|  | if (!web_local_frame) | 
|  | return nullptr; | 
|  | auto* render_frame = content::RenderFrame::FromWebFrame(web_local_frame); | 
|  | if (!render_frame) | 
|  | return nullptr; | 
|  | int render_frame_id = render_frame->GetRoutingID(); | 
|  |  | 
|  | // Lazily create the provider. | 
|  | 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( | 
|  | render_frame_id, | 
|  | render_frame->GetTaskRunner(blink::TaskType::kInternalDefault)); | 
|  | } | 
|  |  | 
|  | bool RenderFrameImpl::ShouldThrottleDownload() { | 
|  | const auto now = base::TimeTicks::Now(); | 
|  | if (num_burst_download_requests_ == 0) { | 
|  | burst_download_start_time_ = now; | 
|  | } else if (num_burst_download_requests_ >= kBurstDownloadLimit) { | 
|  | static constexpr auto kBurstDownloadLimitResetInterval = | 
|  | TimeDelta::FromSeconds(1); | 
|  | if (now - burst_download_start_time_ > kBurstDownloadLimitResetInterval) { | 
|  | num_burst_download_requests_ = 1; | 
|  | burst_download_start_time_ = now; | 
|  | return false; | 
|  | } | 
|  | return true; | 
|  | } | 
|  |  | 
|  | num_burst_download_requests_++; | 
|  | return false; | 
|  | } | 
|  |  | 
|  | std::unique_ptr<blink::WebServiceWorkerNetworkProvider> | 
|  | RenderFrameImpl::BuildServiceWorkerNetworkProviderForNavigation( | 
|  | blink::mojom::ControllerServiceWorkerInfoPtr controller_service_worker_info, | 
|  | blink::mojom::ServiceWorkerProviderInfoForWindowPtr provider_info) { | 
|  | // An empty provider will always be created since it is expected in a certain | 
|  | // number of places. | 
|  | if (!provider_info) { | 
|  | return ServiceWorkerNetworkProviderForFrame::CreateInvalidInstance(); | 
|  | } | 
|  | scoped_refptr<network::SharedURLLoaderFactory> fallback_factory = | 
|  | network::SharedURLLoaderFactory::Create( | 
|  | GetLoaderFactoryBundle()->CloneWithoutAppCacheFactory()); | 
|  | return ServiceWorkerNetworkProviderForFrame::Create( | 
|  | this, std::move(provider_info), std::move(controller_service_worker_info), | 
|  | std::move(fallback_factory)); | 
|  | } | 
|  |  | 
|  | void RenderFrameImpl::AbortCommitNavigation( | 
|  | mojom::FrameNavigationControl::CommitNavigationCallback callback, | 
|  | blink::mojom::CommitResult reason) { | 
|  | DCHECK(callback || IsPerNavigationMojoInterfaceEnabled()); | 
|  | // The callback will trigger | 
|  | // RenderFrameHostImpl::OnCrossDocumentCommitProcessed() as will the interface | 
|  | // disconnection. Note: We are using the callback and not the flag to | 
|  | // determine if NavigationClient::CommitNavigation was used, because in | 
|  | // certain cases we use the old path even when the flag is on (e.g. some | 
|  | // interstitials). | 
|  | if (callback) { | 
|  | std::move(callback).Run(reason); | 
|  | } else { | 
|  | navigation_client_impl_.reset(); | 
|  | } | 
|  | } | 
|  |  | 
|  | }  // namespace content |