1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/browser/frame_host/render_frame_host_impl.h"
6
7 #include <algorithm>
8 #include <memory>
9 #include <unordered_map>
10 #include <utility>
11
12 #include "base/bind.h"
13 #include "base/bind_helpers.h"
14 #include "base/command_line.h"
15 #include "base/containers/queue.h"
16 #include "base/debug/alias.h"
17 #include "base/debug/dump_without_crashing.h"
18 #include "base/hash/hash.h"
19 #include "base/i18n/character_encoding.h"
20 #include "base/lazy_instance.h"
21 #include "base/memory/ptr_util.h"
22 #include "base/memory/ref_counted.h"
23 #include "base/metrics/histogram_functions.h"
24 #include "base/metrics/histogram_macros.h"
25 #include "base/metrics/metrics_hashes.h"
26 #include "base/metrics/user_metrics.h"
27 #include "base/no_destructor.h"
28 #include "base/numerics/safe_conversions.h"
29 #include "base/process/kill.h"
30 #include "base/stl_util.h"
31 #include "base/task/post_task.h"
32 #include "base/task/thread_pool.h"
33 #include "base/threading/thread_task_runner_handle.h"
34 #include "base/time/time.h"
35 #include "base/trace_event/traced_value.h"
36 #include "build/build_config.h"
37 #include "components/download/public/common/download_url_parameters.h"
38 #include "content/browser/about_url_loader_factory.h"
39 #include "content/browser/accessibility/browser_accessibility_manager.h"
40 #include "content/browser/accessibility/browser_accessibility_state_impl.h"
41 #include "content/browser/appcache/appcache_navigation_handle.h"
42 #include "content/browser/bluetooth/web_bluetooth_service_impl.h"
43 #include "content/browser/browser_main_loop.h"
44 #include "content/browser/child_process_security_policy_impl.h"
45 #include "content/browser/contacts/contacts_manager_impl.h"
46 #include "content/browser/data_url_loader_factory.h"
47 #include "content/browser/devtools/devtools_instrumentation.h"
48 #include "content/browser/dom_storage/dom_storage_context_wrapper.h"
49 #include "content/browser/download/data_url_blob_reader.h"
50 #include "content/browser/download/mhtml_generation_manager.h"
51 #include "content/browser/file_system/file_system_manager_impl.h"
52 #include "content/browser/file_system/file_system_url_loader_factory.h"
53 #include "content/browser/frame_host/back_forward_cache_impl.h"
54 #include "content/browser/frame_host/cross_process_frame_connector.h"
55 #include "content/browser/frame_host/debug_urls.h"
56 #include "content/browser/frame_host/file_chooser_impl.h"
57 #include "content/browser/frame_host/frame_tree.h"
58 #include "content/browser/frame_host/frame_tree_node.h"
59 #include "content/browser/frame_host/input/input_injector_impl.h"
60 #include "content/browser/frame_host/ipc_utils.h"
61 #include "content/browser/frame_host/keep_alive_handle_factory.h"
62 #include "content/browser/frame_host/navigation_entry_impl.h"
63 #include "content/browser/frame_host/navigation_request.h"
64 #include "content/browser/frame_host/navigator.h"
65 #include "content/browser/frame_host/navigator_impl.h"
66 #include "content/browser/frame_host/render_frame_host_delegate.h"
67 #include "content/browser/frame_host/render_frame_proxy_host.h"
68 #include "content/browser/generic_sensor/sensor_provider_proxy_impl.h"
69 #include "content/browser/geolocation/geolocation_service_impl.h"
70 #include "content/browser/gpu/gpu_data_manager_impl.h"
71 #include "content/browser/installedapp/installed_app_provider_impl.h"
72 #include "content/browser/interface_provider_filtering.h"
73 #include "content/browser/loader/file_url_loader_factory.h"
74 #include "content/browser/loader/navigation_url_loader_impl.h"
75 #include "content/browser/loader/prefetch_url_loader_service.h"
76 #include "content/browser/log_console_message.h"
77 #include "content/browser/media/capture/audio_mirroring_manager.h"
78 #include "content/browser/media/media_interface_proxy.h"
79 #include "content/browser/media/webaudio/audio_context_manager_impl.h"
80 #include "content/browser/native_file_system/native_file_system_manager_impl.h"
81 #include "content/browser/navigation_subresource_loader_params.h"
82 #include "content/browser/net/cross_origin_embedder_policy_reporter.h"
83 #include "content/browser/payments/payment_app_context_impl.h"
84 #include "content/browser/permissions/permission_controller_impl.h"
85 #include "content/browser/permissions/permission_service_context.h"
86 #include "content/browser/permissions/permission_service_impl.h"
87 #include "content/browser/portal/portal.h"
88 #include "content/browser/presentation/presentation_service_impl.h"
89 #include "content/browser/push_messaging/push_messaging_manager.h"
90 #include "content/browser/renderer_host/dip_util.h"
91 #include "content/browser/renderer_host/input/input_router.h"
92 #include "content/browser/renderer_host/input/timeout_monitor.h"
93 #include "content/browser/renderer_host/render_process_host_impl.h"
94 #include "content/browser/renderer_host/render_view_host_delegate.h"
95 #include "content/browser/renderer_host/render_view_host_delegate_view.h"
96 #include "content/browser/renderer_host/render_view_host_impl.h"
97 #include "content/browser/renderer_host/render_widget_host_factory.h"
98 #include "content/browser/renderer_host/render_widget_host_impl.h"
99 #include "content/browser/renderer_host/render_widget_host_view_base.h"
100 #include "content/browser/renderer_host/render_widget_host_view_child_frame.h"
101 #include "content/browser/scoped_active_url.h"
102 #include "content/browser/service_worker/service_worker_container_host.h"
103 #include "content/browser/service_worker/service_worker_context_wrapper.h"
104 #include "content/browser/service_worker/service_worker_object_host.h"
105 #include "content/browser/sms/sms_service.h"
106 #include "content/browser/speech/speech_synthesis_impl.h"
107 #include "content/browser/storage_partition_impl.h"
108 #include "content/browser/url_loader_factory_params_helper.h"
109 #include "content/browser/web_package/prefetched_signed_exchange_cache.h"
110 #include "content/browser/web_package/web_bundle_handle.h"
111 #include "content/browser/web_package/web_bundle_handle_tracker.h"
112 #include "content/browser/web_package/web_bundle_navigation_info.h"
113 #include "content/browser/web_package/web_bundle_source.h"
114 #include "content/browser/webauth/authenticator_environment_impl.h"
115 #include "content/browser/webauth/authenticator_impl.h"
116 #include "content/browser/webauth/webauth_request_security_checker.h"
117 #include "content/browser/websockets/websocket_connector_impl.h"
118 #include "content/browser/webtransport/quic_transport_connector_impl.h"
119 #include "content/browser/webui/url_data_manager_backend.h"
120 #include "content/browser/webui/web_ui_controller_factory_registry.h"
121 #include "content/browser/webui/web_ui_url_loader_factory_internal.h"
122 #include "content/browser/worker_host/dedicated_worker_host.h"
123 #include "content/browser/worker_host/shared_worker_service_impl.h"
124 #include "content/common/associated_interfaces.mojom.h"
125 #include "content/common/content_constants_internal.h"
126 #include "content/common/content_navigation_policy.h"
127 #include "content/common/frame.mojom.h"
128 #include "content/common/frame_messages.h"
129 #include "content/common/input/input_handler.mojom.h"
130 #include "content/common/inter_process_time_ticks_converter.h"
131 #include "content/common/navigation_params.h"
132 #include "content/common/navigation_params_mojom_traits.h"
133 #include "content/common/navigation_params_utils.h"
134 #include "content/common/render_message_filter.mojom.h"
135 #include "content/common/renderer.mojom.h"
136 #include "content/common/unfreezable_frame_messages.h"
137 #include "content/common/widget.mojom.h"
138 #include "content/public/browser/ax_event_notification_details.h"
139 #include "content/public/browser/browser_accessibility_state.h"
140 #include "content/public/browser/browser_context.h"
141 #include "content/public/browser/browser_plugin_guest_manager.h"
142 #include "content/public/browser/browser_task_traits.h"
143 #include "content/public/browser/content_browser_client.h"
144 #include "content/public/browser/context_menu_params.h"
145 #include "content/public/browser/download_manager.h"
146 #include "content/public/browser/global_routing_id.h"
147 #include "content/public/browser/media_player_watch_time.h"
148 #include "content/public/browser/network_service_instance.h"
149 #include "content/public/browser/permission_type.h"
150 #include "content/public/browser/render_process_host.h"
151 #include "content/public/browser/render_widget_host_view.h"
152 #include "content/public/browser/shared_cors_origin_access_list.h"
153 #include "content/public/browser/site_isolation_policy.h"
154 #include "content/public/browser/sms_fetcher.h"
155 #include "content/public/browser/storage_partition.h"
156 #include "content/public/common/bindings_policy.h"
157 #include "content/public/common/content_client.h"
158 #include "content/public/common/content_constants.h"
159 #include "content/public/common/content_features.h"
160 #include "content/public/common/content_switches.h"
161 #include "content/public/common/isolated_world_ids.h"
162 #include "content/public/common/navigation_policy.h"
163 #include "content/public/common/network_service_util.h"
164 #include "content/public/common/origin_util.h"
165 #include "content/public/common/page_visibility_state.h"
166 #include "content/public/common/referrer_type_converters.h"
167 #include "content/public/common/service_manager_connection.h"
168 #include "content/public/common/service_names.mojom.h"
169 #include "content/public/common/three_d_api_types.h"
170 #include "content/public/common/url_constants.h"
171 #include "content/public/common/url_utils.h"
172 #include "device/gamepad/gamepad_monitor.h"
173 #include "media/audio/audio_manager.h"
174 #include "media/base/media_switches.h"
175 #include "media/base/user_input_monitor.h"
176 #include "media/learning/common/value.h"
177 #include "media/media_buildflags.h"
178 #include "media/mojo/mojom/remoting.mojom.h"
179 #include "media/mojo/services/media_interface_provider.h"
180 #include "media/mojo/services/video_decode_perf_history.h"
181 #include "mojo/public/cpp/bindings/message.h"
182 #include "mojo/public/cpp/bindings/self_owned_receiver.h"
183 #include "mojo/public/cpp/system/data_pipe.h"
184 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
185 #include "net/cookies/cookie_constants.h"
186 #include "services/device/public/cpp/device_features.h"
187 #include "services/device/public/mojom/sensor_provider.mojom.h"
188 #include "services/device/public/mojom/wake_lock.mojom.h"
189 #include "services/device/public/mojom/wake_lock_context.mojom.h"
190 #include "services/network/public/cpp/features.h"
191 #include "services/network/public/cpp/wrapper_shared_url_loader_factory.h"
192 #include "services/network/public/mojom/network_service.mojom.h"
193 #include "services/service_manager/public/cpp/connector.h"
194 #include "services/service_manager/public/cpp/interface_provider.h"
195 #include "storage/browser/blob/blob_storage_context.h"
196 #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
197 #include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
198 #include "third_party/blink/public/common/blob/blob_utils.h"
199 #include "third_party/blink/public/common/feature_policy/document_policy_features.h"
200 #include "third_party/blink/public/common/feature_policy/feature_policy.h"
201 #include "third_party/blink/public/common/features.h"
202 #include "third_party/blink/public/common/frame/frame_policy.h"
203 #include "third_party/blink/public/common/loader/resource_type_util.h"
204 #include "third_party/blink/public/common/messaging/transferable_message.h"
205 #include "third_party/blink/public/mojom/appcache/appcache.mojom.h"
206 #include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom.h"
207 #include "third_party/blink/public/mojom/cache_storage/cache_storage.mojom.h"
208 #include "third_party/blink/public/mojom/choosers/file_chooser.mojom.h"
209 #include "third_party/blink/public/mojom/frame/frame_owner_properties.mojom.h"
210 #include "third_party/blink/public/mojom/frame/fullscreen.mojom.h"
211 #include "third_party/blink/public/mojom/frame/media_player_action.mojom.h"
212 #include "third_party/blink/public/mojom/frame/user_activation_update_types.mojom.h"
213 #include "third_party/blink/public/mojom/geolocation/geolocation_service.mojom.h"
214 #include "third_party/blink/public/mojom/loader/pause_subresource_loading_handle.mojom.h"
215 #include "third_party/blink/public/mojom/loader/resource_load_info.mojom.h"
216 #include "third_party/blink/public/mojom/loader/url_loader_factory_bundle.mojom.h"
217 #include "third_party/blink/public/mojom/security_context/insecure_request_policy.mojom.h"
218 #include "third_party/blink/public/mojom/service_worker/service_worker_object.mojom.h"
219 #include "third_party/blink/public/mojom/sms/sms_receiver.mojom.h"
220 #include "third_party/blink/public/mojom/timing/resource_timing.mojom.h"
221 #include "third_party/blink/public/mojom/usb/web_usb_service.mojom.h"
222 #include "third_party/blink/public/mojom/webauthn/virtual_authenticator.mojom.h"
223 #include "ui/accessibility/ax_tree.h"
224 #include "ui/accessibility/ax_tree_id_registry.h"
225 #include "ui/accessibility/ax_tree_update.h"
226 #include "ui/gfx/geometry/quad_f.h"
227 #include "url/gurl.h"
228 #include "url/origin.h"
229 #include "url/url_constants.h"
230
231 #if defined(OS_ANDROID)
232 #include "content/browser/android/content_url_loader_factory.h"
233 #include "content/browser/android/java_interfaces_impl.h"
234 #include "content/browser/frame_host/render_frame_host_android.h"
235 #include "content/public/browser/android/java_interfaces.h"
236 #else
237 #include "content/browser/hid/hid_service.h"
238 #include "content/browser/host_zoom_map_impl.h"
239 #include "content/browser/serial/serial_service.h"
240 #endif
241
242 #if defined(OS_MACOSX)
243 #include "content/browser/frame_host/popup_menu_helper_mac.h"
244 #endif
245
246 using base::TimeDelta;
247
248 namespace content {
249
250 namespace {
251
252 #if defined(OS_ANDROID)
253 const void* const kRenderFrameHostAndroidKey = &kRenderFrameHostAndroidKey;
254 #endif // OS_ANDROID
255
256 // The next value to use for the accessibility reset token.
257 int g_next_accessibility_reset_token = 1;
258
259 // Whether to allow injecting javascript into any kind of frame, for Android
260 // WebView, WebLayer, Fuchsia web.ContextProvider and CastOS content shell.
261 bool g_allow_injecting_javascript = false;
262
263 typedef std::unordered_map<GlobalFrameRoutingId,
264 RenderFrameHostImpl*,
265 GlobalFrameRoutingIdHasher>
266 RoutingIDFrameMap;
267 base::LazyInstance<RoutingIDFrameMap>::DestructorAtExit g_routing_id_frame_map =
268 LAZY_INSTANCE_INITIALIZER;
269
270 using TokenFrameMap = std::unordered_map<base::UnguessableToken,
271 RenderFrameHostImpl*,
272 base::UnguessableTokenHash>;
273 base::LazyInstance<TokenFrameMap>::Leaky g_token_frame_map =
274 LAZY_INSTANCE_INITIALIZER;
275
276 // Returns true if |url| & |base_url| represents a WebView loadDataWithBaseUrl
277 // navigation.
IsLoadDataWithBaseURL(const GURL & url,const GURL & base_url)278 bool IsLoadDataWithBaseURL(const GURL& url, const GURL& base_url) {
279 return url.SchemeIs(url::kDataScheme) && !base_url.is_empty();
280 }
281
282 // Returns true if |common_params| represents a WebView loadDataWithBaseUrl
283 // navigation.
IsLoadDataWithBaseURL(const mojom::CommonNavigationParams & common_params)284 bool IsLoadDataWithBaseURL(const mojom::CommonNavigationParams& common_params) {
285 return IsLoadDataWithBaseURL(common_params.url,
286 common_params.base_url_for_data_url);
287 }
288
289 // Returns true if |validated_params| represents a WebView loadDataWithBaseUrl
290 // navigation.
IsLoadDataWithBaseURL(const FrameHostMsg_DidCommitProvisionalLoad_Params & validated_params)291 bool IsLoadDataWithBaseURL(
292 const FrameHostMsg_DidCommitProvisionalLoad_Params& validated_params) {
293 return IsLoadDataWithBaseURL(validated_params.url, validated_params.base_url);
294 }
295
296 // Ensure that we reset nav_entry_id_ in DidCommitProvisionalLoad if any of
297 // the validations fail and lead to an early return. Call disable() once we
298 // know the commit will be successful. Resetting nav_entry_id_ avoids acting on
299 // any UpdateState or UpdateTitle messages after an ignored commit.
300 class ScopedCommitStateResetter {
301 public:
ScopedCommitStateResetter(RenderFrameHostImpl * render_frame_host)302 explicit ScopedCommitStateResetter(RenderFrameHostImpl* render_frame_host)
303 : render_frame_host_(render_frame_host), disabled_(false) {}
304
~ScopedCommitStateResetter()305 ~ScopedCommitStateResetter() {
306 if (!disabled_) {
307 render_frame_host_->set_nav_entry_id(0);
308 }
309 }
310
disable()311 void disable() { disabled_ = true; }
312
313 private:
314 RenderFrameHostImpl* render_frame_host_;
315 bool disabled_;
316 };
317
318 class ActiveURLMessageFilter : public mojo::MessageFilter {
319 public:
ActiveURLMessageFilter(RenderFrameHostImpl * render_frame_host)320 explicit ActiveURLMessageFilter(RenderFrameHostImpl* render_frame_host)
321 : render_frame_host_(render_frame_host) {}
322
~ActiveURLMessageFilter()323 ~ActiveURLMessageFilter() override {
324 if (debug_url_set_) {
325 GetContentClient()->SetActiveURL(GURL(), "");
326 }
327 }
328
329 // mojo::MessageFilter overrides.
WillDispatch(mojo::Message * message)330 bool WillDispatch(mojo::Message* message) override {
331 debug_url_set_ = true;
332 auto* frame_tree_node = render_frame_host_->frame_tree_node();
333 GetContentClient()->SetActiveURL(frame_tree_node->current_url(),
334 frame_tree_node->frame_tree()
335 ->root()
336 ->current_origin()
337 .GetDebugString());
338 return true;
339 }
340
DidDispatchOrReject(mojo::Message * message,bool accepted)341 void DidDispatchOrReject(mojo::Message* message, bool accepted) override {
342 GetContentClient()->SetActiveURL(GURL(), "");
343 debug_url_set_ = false;
344 }
345
346 private:
347 RenderFrameHostImpl* render_frame_host_;
348 bool debug_url_set_ = false;
349 };
350
GrantFileAccess(int child_id,const std::vector<base::FilePath> & file_paths)351 void GrantFileAccess(int child_id,
352 const std::vector<base::FilePath>& file_paths) {
353 ChildProcessSecurityPolicyImpl* policy =
354 ChildProcessSecurityPolicyImpl::GetInstance();
355
356 for (const auto& file : file_paths) {
357 if (!policy->CanReadFile(child_id, file))
358 policy->GrantReadFile(child_id, file);
359 }
360 }
361
362 #if BUILDFLAG(ENABLE_MEDIA_REMOTING)
363 // RemoterFactory that delegates Create() calls to the ContentBrowserClient.
364 //
365 // Since Create() could be called at any time, perhaps by a stray task being run
366 // after a RenderFrameHost has been destroyed, the RemoterFactoryImpl uses the
367 // process/routing IDs as a weak reference to the RenderFrameHostImpl.
368 class RemoterFactoryImpl final : public media::mojom::RemoterFactory {
369 public:
RemoterFactoryImpl(int process_id,int routing_id)370 RemoterFactoryImpl(int process_id, int routing_id)
371 : process_id_(process_id), routing_id_(routing_id) {}
372
373 private:
Create(mojo::PendingRemote<media::mojom::RemotingSource> source,mojo::PendingReceiver<media::mojom::Remoter> receiver)374 void Create(mojo::PendingRemote<media::mojom::RemotingSource> source,
375 mojo::PendingReceiver<media::mojom::Remoter> receiver) final {
376 if (auto* host = RenderFrameHostImpl::FromID(process_id_, routing_id_)) {
377 GetContentClient()->browser()->CreateMediaRemoter(host, std::move(source),
378 std::move(receiver));
379 }
380 }
381
382 const int process_id_;
383 const int routing_id_;
384
385 DISALLOW_COPY_AND_ASSIGN(RemoterFactoryImpl);
386 };
387 #endif // BUILDFLAG(ENABLE_MEDIA_REMOTING)
388
389 using FrameCallback = base::RepeatingCallback<void(RenderFrameHostImpl*)>;
ForEachFrame(RenderFrameHostImpl * root_frame_host,const FrameCallback & frame_callback)390 void ForEachFrame(RenderFrameHostImpl* root_frame_host,
391 const FrameCallback& frame_callback) {
392 DCHECK_CURRENTLY_ON(BrowserThread::UI);
393
394 FrameTree* frame_tree = root_frame_host->frame_tree_node()->frame_tree();
395 DCHECK_EQ(root_frame_host, frame_tree->GetMainFrame());
396
397 for (FrameTreeNode* node : frame_tree->Nodes()) {
398 RenderFrameHostImpl* frame_host = node->current_frame_host();
399 RenderFrameHostImpl* pending_frame_host =
400 node->render_manager()->speculative_frame_host();
401 if (frame_host)
402 frame_callback.Run(frame_host);
403 if (pending_frame_host)
404 frame_callback.Run(pending_frame_host);
405 }
406 }
407
LookupRenderFrameHostOrProxy(int process_id,int routing_id,RenderFrameHostImpl ** rfh,RenderFrameProxyHost ** rfph)408 void LookupRenderFrameHostOrProxy(int process_id,
409 int routing_id,
410 RenderFrameHostImpl** rfh,
411 RenderFrameProxyHost** rfph) {
412 *rfh = RenderFrameHostImpl::FromID(process_id, routing_id);
413 if (*rfh == nullptr)
414 *rfph = RenderFrameProxyHost::FromID(process_id, routing_id);
415 }
416
417 // Takes the lower 31 bits of the metric-name-hash of a Mojo interface |name|.
HashInterfaceNameToHistogramSample(base::StringPiece name)418 base::Histogram::Sample HashInterfaceNameToHistogramSample(
419 base::StringPiece name) {
420 return base::strict_cast<base::Histogram::Sample>(
421 static_cast<int32_t>(base::HashMetricName(name) & 0x7fffffffull));
422 }
423
424 // Set crash keys that will help understand the circumstances of a renderer
425 // kill. Note that the commit URL is already reported in a crash key, and
426 // additional keys are logged in RenderProcessHostImpl::ShutdownForBadMessage.
LogRendererKillCrashKeys(const GURL & site_url)427 void LogRendererKillCrashKeys(const GURL& site_url) {
428 static auto* site_url_key = base::debug::AllocateCrashKeyString(
429 "current_site_url", base::debug::CrashKeySize::Size64);
430 base::debug::SetCrashKeyString(site_url_key,
431 site_url.possibly_invalid_spec());
432 }
433
GetOriginForURLLoaderFactoryUnchecked(NavigationRequest * navigation_request)434 url::Origin GetOriginForURLLoaderFactoryUnchecked(
435 NavigationRequest* navigation_request) {
436 // Return a safe opaque origin when there is no |navigation_request| (e.g.
437 // when RFHI::CommitNavigation is called via RFHI::NavigateToInterstitialURL).
438 if (!navigation_request)
439 return url::Origin();
440
441 // GetOriginForURLLoaderFactory should only be called at the ready-to-commit
442 // time, when the RFHI to commit the navigation is already known.
443 DCHECK_LE(NavigationRequest::READY_TO_COMMIT, navigation_request->state());
444 RenderFrameHostImpl* target_frame = navigation_request->GetRenderFrameHost();
445 DCHECK(target_frame);
446
447 // Check if this is loadDataWithBaseUrl (which needs special treatment).
448 auto& common_params = navigation_request->common_params();
449 if (IsLoadDataWithBaseURL(common_params)) {
450 // A (potentially attacker-controlled) renderer process should not be able
451 // to use loadDataWithBaseUrl code path to initiate fetches on behalf of a
452 // victim origin (fetches controlled by attacker-provided
453 // |common_params.url| data: URL in a victim's origin from the
454 // attacker-provided |common_params.base_url_for_data_url|). Browser
455 // process should verify that |common_params.base_url_for_data_url| is empty
456 // for all renderer-initiated navigations (e.g. see
457 // VerifyBeginNavigationCommonParams), but as a defense-in-depth this is
458 // also asserted below.
459 CHECK(navigation_request->browser_initiated());
460
461 // loadDataWithBaseUrl submits a data: |common_params.url| (which has a
462 // opaque origin), but commits that URL as if it came from
463 // |common_params.base_url_for_data_url|. See also
464 // https://crbug.com/976253.
465 return url::Origin::Create(common_params.base_url_for_data_url);
466 }
467
468 // MHTML frames should commit as a opaque origin (and should not be able to
469 // make network requests on behalf of the real origin).
470 //
471 // TODO(lukasza): Cover MHTML main frames here.
472 if (navigation_request->IsForMhtmlSubframe())
473 return url::Origin();
474
475 // Srcdoc subframes need to inherit their origin from their parent frame.
476 if (navigation_request->GetURL().IsAboutSrcdoc()) {
477 // Srcdoc navigations in main frames should be blocked before this function
478 // is called. This should guarantee existence of a parent here.
479 RenderFrameHostImpl* parent = target_frame->GetParent();
480 DCHECK(parent);
481
482 return parent->GetLastCommittedOrigin();
483 }
484
485 // In cases not covered above, URLLoaderFactory should be associated with the
486 // origin of |common_params.url| and/or |common_params.initiator_origin|.
487 return url::Origin::Resolve(
488 common_params.url,
489 common_params.initiator_origin.value_or(url::Origin()));
490 }
491
GetOriginForURLLoaderFactory(NavigationRequest * navigation_request)492 url::Origin GetOriginForURLLoaderFactory(
493 NavigationRequest* navigation_request) {
494 url::Origin result =
495 GetOriginForURLLoaderFactoryUnchecked(navigation_request);
496
497 // |result| must be an origin that is allowed to be accessed from the process
498 // that is the target of this navigation.
499 if (navigation_request) {
500 int process_id =
501 navigation_request->GetRenderFrameHost()->GetProcess()->GetID();
502 auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
503 CHECK(policy->CanAccessDataForOrigin(process_id, result));
504 }
505
506 return result;
507 }
508
CloneFactoryBundle(scoped_refptr<blink::URLLoaderFactoryBundle> bundle)509 std::unique_ptr<blink::PendingURLLoaderFactoryBundle> CloneFactoryBundle(
510 scoped_refptr<blink::URLLoaderFactoryBundle> bundle) {
511 return base::WrapUnique(static_cast<blink::PendingURLLoaderFactoryBundle*>(
512 bundle->Clone().release()));
513 }
514
515 // Helper method to download a URL on UI thread.
StartDownload(std::unique_ptr<download::DownloadUrlParameters> parameters,mojo::PendingRemote<blink::mojom::BlobURLToken> blob_url_token)516 void StartDownload(
517 std::unique_ptr<download::DownloadUrlParameters> parameters,
518 mojo::PendingRemote<blink::mojom::BlobURLToken> blob_url_token) {
519 DCHECK_CURRENTLY_ON(BrowserThread::UI);
520
521 RenderProcessHost* render_process_host =
522 RenderProcessHost::FromID(parameters->render_process_host_id());
523 if (!render_process_host)
524 return;
525
526 BrowserContext* browser_context = render_process_host->GetBrowserContext();
527
528 scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory;
529 if (blob_url_token) {
530 blob_url_loader_factory =
531 ChromeBlobStorageContext::URLLoaderFactoryForToken(
532 browser_context, std::move(blob_url_token));
533 }
534
535 DownloadManager* download_manager =
536 BrowserContext::GetDownloadManager(browser_context);
537 parameters->set_download_source(download::DownloadSource::FROM_RENDERER);
538 download_manager->DownloadUrl(std::move(parameters),
539 std::move(blob_url_loader_factory));
540 }
541
542 // Called on the UI thread when the data URL in the BlobDataHandle
543 // is read.
OnDataURLRetrieved(std::unique_ptr<download::DownloadUrlParameters> parameters,GURL data_url)544 void OnDataURLRetrieved(
545 std::unique_ptr<download::DownloadUrlParameters> parameters,
546 GURL data_url) {
547 DCHECK_CURRENTLY_ON(BrowserThread::UI);
548 if (!data_url.is_valid())
549 return;
550 parameters->set_url(std::move(data_url));
551 StartDownload(std::move(parameters), mojo::NullRemote());
552 }
553
554 // TODO(crbug.com/977040): Remove when no longer needed.
555 const uint32_t kMaxCookieSameSiteDeprecationUrls = 20;
556
RecordCrossOriginIsolationMetrics(RenderFrameHostImpl * rfh)557 void RecordCrossOriginIsolationMetrics(RenderFrameHostImpl* rfh) {
558 ContentBrowserClient* client = GetContentClient()->browser();
559 if (rfh->cross_origin_opener_policy() ==
560 network::mojom::CrossOriginOpenerPolicy::kSameOrigin) {
561 client->LogWebFeatureForCurrentPage(
562 rfh, blink::mojom::WebFeature::kCrossOriginOpenerPolicySameOrigin);
563 }
564 if (rfh->cross_origin_opener_policy() ==
565 network::mojom::CrossOriginOpenerPolicy::kSameOriginAllowPopups) {
566 client->LogWebFeatureForCurrentPage(
567 rfh, blink::mojom::WebFeature::
568 kCrossOriginOpenerPolicySameOriginAllowPopups);
569 }
570
571 if (rfh->cross_origin_embedder_policy().value ==
572 network::mojom::CrossOriginEmbedderPolicyValue::kRequireCorp) {
573 client->LogWebFeatureForCurrentPage(
574 rfh, blink::mojom::WebFeature::kCrossOriginEmbedderPolicyRequireCorp);
575 }
576
577 if ((rfh->cross_origin_opener_policy() ==
578 network::mojom::CrossOriginOpenerPolicy::kSameOrigin) &&
579 (rfh->cross_origin_embedder_policy().value ==
580 network::mojom::CrossOriginEmbedderPolicyValue::kRequireCorp)) {
581 client->LogWebFeatureForCurrentPage(
582 rfh, blink::mojom::WebFeature::kCoopAndCoepIsolated);
583 }
584 }
585
586 } // namespace
587
CreateNewHostForCrashedFrame()588 bool CreateNewHostForCrashedFrame() {
589 return GetRenderDocumentLevel() >= RenderDocumentLevel::kCrashedFrame;
590 }
591
592 class RenderFrameHostImpl::DroppedInterfaceRequestLogger
593 : public blink::mojom::BrowserInterfaceBroker {
594 public:
DroppedInterfaceRequestLogger(mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker> receiver)595 explicit DroppedInterfaceRequestLogger(
596 mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker> receiver) {
597 receiver_.Bind(std::move(receiver));
598 }
599
~DroppedInterfaceRequestLogger()600 ~DroppedInterfaceRequestLogger() override {
601 UMA_HISTOGRAM_EXACT_LINEAR("RenderFrameHostImpl.DroppedInterfaceRequests",
602 num_dropped_requests_, 20);
603 }
604
605 protected:
606 // blink::mojom::BrowserInterfaceBroker
GetInterface(mojo::GenericPendingReceiver receiver)607 void GetInterface(mojo::GenericPendingReceiver receiver) override {
608 ++num_dropped_requests_;
609 auto interface_name = receiver.interface_name().value_or("");
610 base::UmaHistogramSparse(
611 "RenderFrameHostImpl.DroppedInterfaceRequestName",
612 HashInterfaceNameToHistogramSample(interface_name));
613 DLOG(WARNING)
614 << "InterfaceRequest was dropped, the document is no longer active: "
615 << interface_name;
616 }
617
618 private:
619 mojo::Receiver<blink::mojom::BrowserInterfaceBroker> receiver_{this};
620 int num_dropped_requests_ = 0;
621
622 DISALLOW_COPY_AND_ASSIGN(DroppedInterfaceRequestLogger);
623 };
624
625 struct PendingNavigation {
626 mojom::CommonNavigationParamsPtr common_params;
627 mojom::BeginNavigationParamsPtr begin_navigation_params;
628 scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory;
629 mojo::PendingAssociatedRemote<mojom::NavigationClient> navigation_client;
630 mojo::PendingRemote<blink::mojom::NavigationInitiator> navigation_initiator;
631
632 PendingNavigation(
633 mojom::CommonNavigationParamsPtr common_params,
634 mojom::BeginNavigationParamsPtr begin_navigation_params,
635 scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
636 mojo::PendingAssociatedRemote<mojom::NavigationClient> navigation_client,
637 mojo::PendingRemote<blink::mojom::NavigationInitiator>
638 navigation_initiator);
639 };
640
PendingNavigation(mojom::CommonNavigationParamsPtr common_params,mojom::BeginNavigationParamsPtr begin_navigation_params,scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,mojo::PendingAssociatedRemote<mojom::NavigationClient> navigation_client,mojo::PendingRemote<blink::mojom::NavigationInitiator> navigation_initiator)641 PendingNavigation::PendingNavigation(
642 mojom::CommonNavigationParamsPtr common_params,
643 mojom::BeginNavigationParamsPtr begin_navigation_params,
644 scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory,
645 mojo::PendingAssociatedRemote<mojom::NavigationClient> navigation_client,
646 mojo::PendingRemote<blink::mojom::NavigationInitiator> navigation_initiator)
647 : common_params(std::move(common_params)),
648 begin_navigation_params(std::move(begin_navigation_params)),
649 blob_url_loader_factory(std::move(blob_url_loader_factory)),
650 navigation_client(std::move(navigation_client)),
651 navigation_initiator(std::move(navigation_initiator)) {}
652
653 // static
FromID(GlobalFrameRoutingId id)654 RenderFrameHost* RenderFrameHost::FromID(GlobalFrameRoutingId id) {
655 return RenderFrameHostImpl::FromID(id);
656 }
657
658 // static
FromID(int render_process_id,int render_frame_id)659 RenderFrameHost* RenderFrameHost::FromID(int render_process_id,
660 int render_frame_id) {
661 return RenderFrameHostImpl::FromID(
662 GlobalFrameRoutingId(render_process_id, render_frame_id));
663 }
664
665 // static
AllowInjectingJavaScript()666 void RenderFrameHost::AllowInjectingJavaScript() {
667 g_allow_injecting_javascript = true;
668 }
669
670 // static
FromID(GlobalFrameRoutingId id)671 RenderFrameHostImpl* RenderFrameHostImpl::FromID(GlobalFrameRoutingId id) {
672 DCHECK_CURRENTLY_ON(BrowserThread::UI);
673 RoutingIDFrameMap* frames = g_routing_id_frame_map.Pointer();
674 auto it = frames->find(id);
675 return it == frames->end() ? NULL : it->second;
676 }
677
678 // static
FromID(int render_process_id,int render_frame_id)679 RenderFrameHostImpl* RenderFrameHostImpl::FromID(int render_process_id,
680 int render_frame_id) {
681 return RenderFrameHostImpl::FromID(
682 GlobalFrameRoutingId(render_process_id, render_frame_id));
683 }
684 // static
FromAXTreeID(ui::AXTreeID ax_tree_id)685 RenderFrameHost* RenderFrameHost::FromAXTreeID(ui::AXTreeID ax_tree_id) {
686 return RenderFrameHostImpl::FromAXTreeID(ax_tree_id);
687 }
688
689 // static
FromAXTreeID(ui::AXTreeID ax_tree_id)690 RenderFrameHostImpl* RenderFrameHostImpl::FromAXTreeID(
691 ui::AXTreeID ax_tree_id) {
692 DCHECK_CURRENTLY_ON(BrowserThread::UI);
693 ui::AXTreeIDRegistry::FrameID frame_id =
694 ui::AXTreeIDRegistry::GetInstance()->GetFrameID(ax_tree_id);
695 return RenderFrameHostImpl::FromID(frame_id.first, frame_id.second);
696 }
697
698 // static
FromOverlayRoutingToken(const base::UnguessableToken & token)699 RenderFrameHostImpl* RenderFrameHostImpl::FromOverlayRoutingToken(
700 const base::UnguessableToken& token) {
701 DCHECK_CURRENTLY_ON(BrowserThread::UI);
702 auto it = g_token_frame_map.Get().find(token);
703 return it == g_token_frame_map.Get().end() ? nullptr : it->second;
704 }
705
706 // static
ClearAllPrefetchedSignedExchangeCache()707 void RenderFrameHostImpl::ClearAllPrefetchedSignedExchangeCache() {
708 DCHECK_CURRENTLY_ON(BrowserThread::UI);
709 RoutingIDFrameMap* frames = g_routing_id_frame_map.Pointer();
710 for (auto it : *frames)
711 it.second->ClearPrefetchedSignedExchangeCache();
712 }
713
RenderFrameHostImpl(SiteInstance * site_instance,scoped_refptr<RenderViewHostImpl> render_view_host,RenderFrameHostDelegate * delegate,FrameTree * frame_tree,FrameTreeNode * frame_tree_node,int32_t routing_id,bool renderer_initiated_creation)714 RenderFrameHostImpl::RenderFrameHostImpl(
715 SiteInstance* site_instance,
716 scoped_refptr<RenderViewHostImpl> render_view_host,
717 RenderFrameHostDelegate* delegate,
718 FrameTree* frame_tree,
719 FrameTreeNode* frame_tree_node,
720 int32_t routing_id,
721 bool renderer_initiated_creation)
722 : render_view_host_(std::move(render_view_host)),
723 delegate_(delegate),
724 site_instance_(static_cast<SiteInstanceImpl*>(site_instance)),
725 process_(site_instance->GetProcess()),
726 frame_tree_(frame_tree),
727 frame_tree_node_(frame_tree_node),
728 // If it has a parent, that parent must have a RFH.
729 parent_(frame_tree_node_->parent()
730 ? frame_tree_node_->parent()->current_frame_host()
731 : nullptr),
732 routing_id_(routing_id),
733 is_waiting_for_unload_ack_(false),
734 render_frame_created_(false),
735 is_waiting_for_beforeunload_completion_(false),
736 beforeunload_dialog_request_cancels_unload_(false),
737 unload_ack_is_for_navigation_(false),
738 beforeunload_timeout_delay_(base::TimeDelta::FromMilliseconds(
739 RenderViewHostImpl::kUnloadTimeoutMS)),
740 was_discarded_(false),
741 is_loading_(false),
742 nav_entry_id_(0),
743 accessibility_reset_token_(0),
744 accessibility_reset_count_(0),
745 browser_plugin_embedder_ax_tree_id_(ui::AXTreeIDUnknown()),
746 no_create_browser_accessibility_manager_for_testing_(false),
747 web_ui_type_(WebUI::kNoWebUI),
748 has_selection_(false),
749 is_audible_(false),
750 last_navigation_previews_state_(PREVIEWS_UNSPECIFIED),
751 waiting_for_init_(renderer_initiated_creation),
752 has_focused_editable_element_(false),
753 push_messaging_manager_(
754 nullptr,
755 base::OnTaskRunnerDeleter(base::CreateSequencedTaskRunner(
756 {ServiceWorkerContext::GetCoreThreadId()}))),
757 active_sandbox_flags_(blink::mojom::WebSandboxFlags::kNone),
758 keep_alive_timeout_(base::TimeDelta::FromSeconds(30)),
759 subframe_unload_timeout_(base::TimeDelta::FromMilliseconds(
760 RenderViewHostImpl::kUnloadTimeoutMS)),
761 commit_callback_interceptor_(nullptr),
762 media_device_id_salt_base_(
763 BrowserContext::CreateRandomMediaDeviceIDSalt()) {
764 DCHECK(delegate_);
765
766 GetProcess()->AddRoute(routing_id_, this);
767 g_routing_id_frame_map.Get().emplace(
768 GlobalFrameRoutingId(GetProcess()->GetID(), routing_id_), this);
769 g_token_frame_map.Get().insert(std::make_pair(frame_token_, this));
770 site_instance_->AddObserver(this);
771 process_->AddObserver(this);
772 GetSiteInstance()->IncrementActiveFrameCount();
773
774 if (frame_tree_node_->parent()) {
775 cross_origin_embedder_policy_ = parent_->cross_origin_embedder_policy();
776
777 // New child frames should inherit the nav_entry_id of their parent.
778 set_nav_entry_id(
779 frame_tree_node_->parent()->current_frame_host()->nav_entry_id());
780 }
781
782 SetUpMojoIfNeeded();
783
784 unload_event_monitor_timeout_ =
785 std::make_unique<TimeoutMonitor>(base::BindRepeating(
786 &RenderFrameHostImpl::OnUnloaded, weak_ptr_factory_.GetWeakPtr()));
787 beforeunload_timeout_.reset(new TimeoutMonitor(
788 base::BindRepeating(&RenderFrameHostImpl::BeforeUnloadTimeout,
789 weak_ptr_factory_.GetWeakPtr())));
790
791 // Local roots are:
792 // - main frames; or
793 // - subframes in a different SiteInstance from their parent.
794 //
795 // Local roots require a RenderWidget for input/layout/painting.
796 if (!parent_ || IsCrossProcessSubframe()) {
797 mojo::PendingRemote<mojom::Widget> widget;
798 GetRemoteInterfaces()->GetInterface(
799 widget.InitWithNewPipeAndPassReceiver());
800
801 if (!parent_) {
802 // For main frames, the RenderWidgetHost is owned by the RenderViewHost.
803 // TODO(https://crbug.com/545684): Once RenderViewHostImpl has-a
804 // RenderWidgetHostImpl, the main render frame should probably start
805 // owning the RenderWidgetHostImpl itself.
806 DCHECK(GetLocalRenderWidgetHost());
807 DCHECK(!GetLocalRenderWidgetHost()->owned_by_render_frame_host());
808
809 // Make the RenderWidgetHostImpl able to call the mojo Widget interface
810 // (implemented by the RenderWidgetImpl).
811 GetLocalRenderWidgetHost()->SetWidget(std::move(widget));
812 } else {
813 // For local child roots, the RenderFrameHost directly creates and owns
814 // its RenderWidgetHost.
815 int32_t widget_routing_id =
816 site_instance->GetProcess()->GetNextRoutingID();
817 DCHECK_EQ(nullptr, GetLocalRenderWidgetHost());
818 owned_render_widget_host_ = RenderWidgetHostFactory::Create(
819 frame_tree_->render_widget_delegate(), GetProcess(),
820 widget_routing_id, std::move(widget), /*hidden=*/true);
821 owned_render_widget_host_->set_owned_by_render_frame_host(true);
822 #if defined(OS_ANDROID)
823 owned_render_widget_host_->SetForceEnableZoom(
824 render_view_host_->GetWebkitPreferences().force_enable_zoom);
825 #endif // defined(OS_ANDROID)
826 }
827
828 if (!frame_tree_node_->parent())
829 GetLocalRenderWidgetHost()->SetIntersectsViewport(true);
830 GetLocalRenderWidgetHost()->SetFrameDepth(frame_tree_node_->depth());
831 GetLocalRenderWidgetHost()->SetFrameInputHandler(
832 frame_input_handler_.get());
833 GetLocalRenderWidgetHost()->input_router()->SetFrameTreeNodeId(
834 frame_tree_node_->frame_tree_node_id());
835 }
836 ResetFeaturePolicy();
837
838 ui::AXTreeIDRegistry::GetInstance()->SetFrameIDForAXTreeID(
839 ui::AXTreeIDRegistry::FrameID(GetProcess()->GetID(), routing_id_),
840 GetAXTreeID());
841
842 // Content-Security-Policy: The CSP source 'self' is usually the origin of the
843 // current document, set by SetLastCommittedOrigin(). However, before a new
844 // frame commits its first navigation, 'self' should correspond to the origin
845 // of the parent (in case of a new iframe) or the opener (in case of a new
846 // window). This is necessary to correctly enforce CSP during the initial
847 // navigation.
848 FrameTreeNode* frame_owner = frame_tree_node_->parent()
849 ? frame_tree_node_->parent()
850 : frame_tree_node_->opener();
851 if (frame_owner)
852 CSPContext::SetSelf(frame_owner->current_origin());
853 }
854
~RenderFrameHostImpl()855 RenderFrameHostImpl::~RenderFrameHostImpl() {
856 // When a RenderFrameHostImpl is deleted, it may still contain children. This
857 // can happen with the unload timer. It causes a RenderFrameHost to delete
858 // itself even if it is still waiting for its children to complete their
859 // unload handlers.
860 //
861 // Observers expect children to be deleted first. Do it now before notifying
862 // them.
863 ResetChildren();
864
865 // Destroying |navigation_request_| may call into delegates/observers,
866 // so we do it early while |this| object is still in a sane state.
867 ResetNavigationRequests();
868
869 // Release the WebUI instances before all else as the WebUI may accesses the
870 // RenderFrameHost during cleanup.
871 ClearWebUI();
872
873 SetLastCommittedSiteUrl(GURL());
874 if (last_committed_document_priority_) {
875 GetProcess()->UpdateFrameWithPriority(last_committed_document_priority_,
876 base::nullopt);
877 }
878
879 g_token_frame_map.Get().erase(frame_token_);
880
881 site_instance_->RemoveObserver(this);
882 process_->RemoveObserver(this);
883
884 const bool was_created = render_frame_created_;
885 render_frame_created_ = false;
886 if (was_created)
887 delegate_->RenderFrameDeleted(this);
888
889 // Ensure that the render process host has been notified that all audio
890 // streams from this frame have terminated. This is required to ensure the
891 // process host has the correct media stream count, which affects its
892 // background priority.
893 OnAudibleStateChanged(false);
894
895 // If this was the last active frame in the SiteInstance, the
896 // DecrementActiveFrameCount call will trigger the deletion of the
897 // SiteInstance's proxies.
898 GetSiteInstance()->DecrementActiveFrameCount();
899
900 // Once a RenderFrame is created in the renderer, there are three possible
901 // clean-up paths:
902 // 1. The RenderFrame can be the main frame. In this case, closing the
903 // associated RenderView will clean up the resources associated with the
904 // main RenderFrame.
905 // 2. The RenderFrame can be unloaded. In this case, the browser sends a
906 // UnfreezableFrameMsg_Unload for the RenderFrame to replace itself with a
907 // RenderFrameProxy and release its associated resources. |unload_state_|
908 // is advanced to UnloadState::InProgress to track that this IPC is in
909 // flight.
910 // 3. The RenderFrame can be detached, as part of removing a subtree (due to
911 // navigation, unload, or DOM mutation). In this case, the browser sends
912 // a UnfreezableFrameMsg_Delete for the RenderFrame to detach itself and
913 // release its associated resources. If the subframe contains an unload
914 // handler, |unload_state_| is advanced to UnloadState::InProgress to track
915 // that the detach is in progress; otherwise, it is advanced directly to
916 // UnloadState::Completed.
917 //
918 // The browser side gives the renderer a small timeout to finish processing
919 // unload / detach messages. When the timeout expires, the RFH will be
920 // removed regardless of whether or not the renderer acknowledged that it
921 // completed the work, to avoid indefinitely leaking browser-side state. To
922 // avoid leaks, ~RenderFrameHostImpl still validates that the appropriate
923 // cleanup IPC was sent to the renderer, by checking that |unload_state_| !=
924 // UnloadState::NotRun.
925 //
926 // TODO(dcheng): Due to how frame detach is signalled today, there are some
927 // bugs in this area. In particular, subtree detach is reported from the
928 // bottom up, so the replicated UnfreezableFrameMsg_Delete messages actually
929 // operate on a node-by-node basis rather than detaching an entire subtree at
930 // once...
931 //
932 // Note that this logic is fairly subtle. It needs to include all subframes
933 // and all speculative frames, but it should exclude case #1 (a main
934 // RenderFrame owned by the RenderView). It can't simply:
935 // - check |frame_tree_node_->render_manager()->speculative_frame_host()| for
936 // equality against |this|. The speculative frame host is unset before the
937 // speculative frame host is destroyed, so this condition would never be
938 // matched for a speculative RFH that needs to be destroyed.
939 // - check |IsCurrent()|, because the RenderFrames in an InterstitialPageImpl
940 // are never considered current.
941 //
942 // Directly comparing against |RenderViewHostImpl::GetMainFrame()| still has
943 // one additional subtlety though: |GetMainFrame()| can sometimes return a
944 // speculative RFH! For subframes, this obviously does not matter: a subframe
945 // will always pass the condition |render_view_host_->GetMainFrame() != this|.
946 // However, it turns out that a speculative main frame being deleted will
947 // *always* pass this condition as well: a speculative RFH being deleted will
948 // *always* first be unassociated from its corresponding RFHM. Thus, it
949 // follows that |GetMainFrame()| will never return the speculative main frame
950 // being deleted, since it must have already been unset.
951 if (was_created && render_view_host_->GetMainFrame() != this)
952 CHECK(!is_active());
953
954 GetProcess()->RemoveRoute(routing_id_);
955 g_routing_id_frame_map.Get().erase(
956 GlobalFrameRoutingId(GetProcess()->GetID(), routing_id_));
957
958 // Null out the unload timer; in crash dumps this member will be null only if
959 // the dtor has run. (It may also be null in tests.)
960 unload_event_monitor_timeout_.reset();
961
962 for (auto& iter : visual_state_callbacks_)
963 std::move(iter.second).Run(false);
964
965 // Delete this before destroying the widget, to guard against reentrancy
966 // by in-process screen readers such as JAWS.
967 browser_accessibility_manager_.reset();
968
969 // Note: The RenderWidgetHost of the main frame is owned by the RenderViewHost
970 // instead. In this case the RenderViewHost is responsible for shutting down
971 // its RenderViewHost.
972 if (owned_render_widget_host_)
973 owned_render_widget_host_->ShutdownAndDestroyWidget(false);
974
975 // This needs to be deleted before |frame_input_handler_| so associated
976 // remotes can send messages during shutdown. See crbug.com/1010478 for
977 // details.
978 render_view_host_.reset();
979
980 // If another frame is waiting for a beforeunload completion callback from
981 // this frame, simulate it now.
982 RenderFrameHostImpl* beforeunload_initiator = GetBeforeUnloadInitiator();
983 if (beforeunload_initiator && beforeunload_initiator != this) {
984 base::TimeTicks approx_renderer_start_time = send_before_unload_start_time_;
985 beforeunload_initiator->ProcessBeforeUnloadCompletedFromFrame(
986 true /* proceed */, false /* treat_as_final_completion_callback */,
987 this, true /* is_frame_being_destroyed */, approx_renderer_start_time,
988 base::TimeTicks::Now());
989 }
990
991 if (prefetched_signed_exchange_cache_)
992 prefetched_signed_exchange_cache_->RecordHistograms();
993 }
994
GetRoutingID()995 int RenderFrameHostImpl::GetRoutingID() {
996 return routing_id_;
997 }
998
GetAXTreeID()999 ui::AXTreeID RenderFrameHostImpl::GetAXTreeID() {
1000 return ax_tree_id();
1001 }
1002
GetTopFrameToken() const1003 const base::UnguessableToken& RenderFrameHostImpl::GetTopFrameToken() const {
1004 const RenderFrameHostImpl* frame = this;
1005 while (frame->parent_) {
1006 frame = frame->parent_;
1007 }
1008 return frame->frame_token();
1009 }
1010
AudioContextPlaybackStarted(int audio_context_id)1011 void RenderFrameHostImpl::AudioContextPlaybackStarted(int audio_context_id) {
1012 delegate_->AudioContextPlaybackStarted(this, audio_context_id);
1013 }
1014
AudioContextPlaybackStopped(int audio_context_id)1015 void RenderFrameHostImpl::AudioContextPlaybackStopped(int audio_context_id) {
1016 delegate_->AudioContextPlaybackStopped(this, audio_context_id);
1017 }
1018
1019 // The current frame went into the BackForwardCache.
EnterBackForwardCache()1020 void RenderFrameHostImpl::EnterBackForwardCache() {
1021 TRACE_EVENT0("navigation", "RenderFrameHostImpl::EnterBackForwardCache");
1022 DCHECK(IsBackForwardCacheEnabled());
1023 DCHECK(!is_in_back_forward_cache_);
1024 is_in_back_forward_cache_ = true;
1025 // Pages in the back-forward cache are automatically evicted after a certain
1026 // time.
1027 if (!GetParent())
1028 StartBackForwardCacheEvictionTimer();
1029 for (auto& child : children_)
1030 child->current_frame_host()->EnterBackForwardCache();
1031
1032 if (service_worker_container_hosts_.empty())
1033 return;
1034 std::vector<base::WeakPtr<ServiceWorkerContainerHost>> hosts;
1035 for (auto host : service_worker_container_hosts_)
1036 hosts.push_back(host.second);
1037 RunOrPostTaskOnThread(
1038 FROM_HERE, ServiceWorkerContext::GetCoreThreadId(),
1039 base::BindOnce(
1040 [](std::vector<base::WeakPtr<ServiceWorkerContainerHost>> hosts) {
1041 for (auto host : hosts) {
1042 if (host)
1043 host->OnEnterBackForwardCache();
1044 }
1045 },
1046 std::move(hosts)));
1047 }
1048
1049 // The frame as been restored from the BackForwardCache.
LeaveBackForwardCache()1050 void RenderFrameHostImpl::LeaveBackForwardCache() {
1051 TRACE_EVENT0("navigation", "RenderFrameHostImpl::LeaveBackForwardCache");
1052 DCHECK(IsBackForwardCacheEnabled());
1053 DCHECK(is_in_back_forward_cache_);
1054 is_in_back_forward_cache_ = false;
1055 if (back_forward_cache_eviction_timer_.IsRunning())
1056 back_forward_cache_eviction_timer_.Stop();
1057 for (auto& child : children_)
1058 child->current_frame_host()->LeaveBackForwardCache();
1059
1060 if (service_worker_container_hosts_.empty())
1061 return;
1062 std::vector<base::WeakPtr<ServiceWorkerContainerHost>> hosts;
1063 for (auto host : service_worker_container_hosts_)
1064 hosts.push_back(host.second);
1065 RunOrPostTaskOnThread(
1066 FROM_HERE, ServiceWorkerContext::GetCoreThreadId(),
1067 base::BindOnce(
1068 [](std::vector<base::WeakPtr<ServiceWorkerContainerHost>> hosts) {
1069 for (auto host : hosts) {
1070 if (host)
1071 host->OnRestoreFromBackForwardCache();
1072 }
1073 },
1074 std::move(hosts)));
1075 }
1076
1077 std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params>
TakeLastCommitParams()1078 RenderFrameHostImpl::TakeLastCommitParams() {
1079 return std::move(last_commit_params_);
1080 }
1081
StartBackForwardCacheEvictionTimer()1082 void RenderFrameHostImpl::StartBackForwardCacheEvictionTimer() {
1083 DCHECK(is_in_back_forward_cache_);
1084 base::TimeDelta evict_after =
1085 BackForwardCacheImpl::GetTimeToLiveInBackForwardCache();
1086 NavigationControllerImpl* controller = static_cast<NavigationControllerImpl*>(
1087 frame_tree_node_->navigator()->GetController());
1088
1089 back_forward_cache_eviction_timer_.SetTaskRunner(
1090 controller->GetBackForwardCache().GetTaskRunner());
1091
1092 back_forward_cache_eviction_timer_.Start(
1093 FROM_HERE, evict_after,
1094 base::BindOnce(&RenderFrameHostImpl::EvictFromBackForwardCacheWithReason,
1095 weak_ptr_factory_.GetWeakPtr(),
1096 BackForwardCacheMetrics::NotRestoredReason::kTimeout));
1097 }
1098
DisableBackForwardCache(base::StringPiece reason)1099 void RenderFrameHostImpl::DisableBackForwardCache(base::StringPiece reason) {
1100 back_forward_cache_disabled_reasons_.insert(reason.as_string());
1101 MaybeEvictFromBackForwardCache();
1102 }
1103
OnGrantedMediaStreamAccess()1104 void RenderFrameHostImpl::OnGrantedMediaStreamAccess() {
1105 was_granted_media_access_ = true;
1106 MaybeEvictFromBackForwardCache();
1107 }
1108
OnPortalActivated(std::unique_ptr<WebContents> predecessor_web_contents,blink::TransferableMessage data,base::OnceCallback<void (blink::mojom::PortalActivateResult)> callback)1109 void RenderFrameHostImpl::OnPortalActivated(
1110 std::unique_ptr<WebContents> predecessor_web_contents,
1111 blink::TransferableMessage data,
1112 base::OnceCallback<void(blink::mojom::PortalActivateResult)> callback) {
1113 mojo::PendingAssociatedRemote<blink::mojom::Portal> pending_portal;
1114 auto portal_receiver = pending_portal.InitWithNewEndpointAndPassReceiver();
1115 mojo::PendingAssociatedRemote<blink::mojom::PortalClient> pending_client;
1116 auto client_receiver = pending_client.InitWithNewEndpointAndPassReceiver();
1117
1118 auto predecessor =
1119 std::make_unique<Portal>(this, std::move(predecessor_web_contents));
1120 predecessor->Bind(std::move(portal_receiver), std::move(pending_client));
1121 auto it = portals_.insert(std::move(predecessor)).first;
1122
1123 GetNavigationControl()->OnPortalActivated(
1124 (*it)->portal_token(), std::move(pending_portal),
1125 std::move(client_receiver), std::move(data),
1126 base::BindOnce(
1127 [](base::OnceCallback<void(blink::mojom::PortalActivateResult)>
1128 callback,
1129 blink::mojom::PortalActivateResult result) {
1130 switch (result) {
1131 case blink::mojom::PortalActivateResult::kPredecessorWillUnload:
1132 case blink::mojom::PortalActivateResult::kPredecessorWasAdopted:
1133 // These values are acceptable from the renderer.
1134 break;
1135 case blink::mojom::PortalActivateResult::
1136 kRejectedDueToPredecessorNavigation:
1137 case blink::mojom::PortalActivateResult::
1138 kRejectedDueToPortalNotReady:
1139 case blink::mojom::PortalActivateResult::kDisconnected:
1140 case blink::mojom::PortalActivateResult::kAbortedDueToBug:
1141 // The renderer is misbehaving.
1142 mojo::ReportBadMessage(
1143 "Unexpected PortalActivateResult from renderer");
1144 result = blink::mojom::PortalActivateResult::kAbortedDueToBug;
1145 break;
1146 }
1147 std::move(callback).Run(result);
1148 },
1149 std::move(callback)));
1150 }
1151
OnPortalCreatedForTesting(std::unique_ptr<Portal> portal)1152 void RenderFrameHostImpl::OnPortalCreatedForTesting(
1153 std::unique_ptr<Portal> portal) {
1154 portals_.insert(std::move(portal));
1155 }
1156
FindPortalByToken(const base::UnguessableToken & portal_token)1157 Portal* RenderFrameHostImpl::FindPortalByToken(
1158 const base::UnguessableToken& portal_token) {
1159 auto it =
1160 std::find_if(portals_.begin(), portals_.end(), [&](const auto& portal) {
1161 return portal->portal_token() == portal_token;
1162 });
1163 return it == portals_.end() ? nullptr : it->get();
1164 }
1165
DestroyPortal(Portal * portal)1166 void RenderFrameHostImpl::DestroyPortal(Portal* portal) {
1167 auto it = portals_.find(portal);
1168 CHECK(it != portals_.end());
1169 std::unique_ptr<Portal> owned_portal(std::move(*it));
1170 portals_.erase(it);
1171 // |owned_portal| is deleted as it goes out of scope.
1172 }
1173
ForwardMessageFromHost(blink::TransferableMessage message,const url::Origin & source_origin,const base::Optional<url::Origin> & target_origin)1174 void RenderFrameHostImpl::ForwardMessageFromHost(
1175 blink::TransferableMessage message,
1176 const url::Origin& source_origin,
1177 const base::Optional<url::Origin>& target_origin) {
1178 // The target origin check needs to be done here in case the frame has
1179 // navigated after the postMessage call, or if the renderer is compromised and
1180 // the check done in PortalHost::ReceiveMessage is bypassed.
1181 if (target_origin) {
1182 if (target_origin != GetLastCommittedOrigin())
1183 return;
1184 }
1185 GetNavigationControl()->ForwardMessageFromHost(std::move(message),
1186 source_origin, target_origin);
1187 }
1188
GetSiteInstance()1189 SiteInstanceImpl* RenderFrameHostImpl::GetSiteInstance() {
1190 return site_instance_.get();
1191 }
1192
GetProcess()1193 RenderProcessHost* RenderFrameHostImpl::GetProcess() {
1194 return process_;
1195 }
1196
GetParent()1197 RenderFrameHostImpl* RenderFrameHostImpl::GetParent() {
1198 return parent_;
1199 }
1200
GetFramesInSubtree()1201 std::vector<RenderFrameHost*> RenderFrameHostImpl::GetFramesInSubtree() {
1202 std::vector<RenderFrameHost*> frame_hosts;
1203 for (FrameTreeNode* node : frame_tree_->SubtreeNodes(frame_tree_node()))
1204 frame_hosts.push_back(node->current_frame_host());
1205 return frame_hosts;
1206 }
1207
IsDescendantOf(RenderFrameHost * ancestor)1208 bool RenderFrameHostImpl::IsDescendantOf(RenderFrameHost* ancestor) {
1209 if (!ancestor || !static_cast<RenderFrameHostImpl*>(ancestor)->child_count())
1210 return false;
1211
1212 for (RenderFrameHostImpl* current = GetParent(); current;
1213 current = current->GetParent()) {
1214 if (current == ancestor)
1215 return true;
1216 }
1217 return false;
1218 }
1219
GetFrameTreeNodeId()1220 int RenderFrameHostImpl::GetFrameTreeNodeId() {
1221 return frame_tree_node_->frame_tree_node_id();
1222 }
1223
GetDevToolsFrameToken()1224 base::UnguessableToken RenderFrameHostImpl::GetDevToolsFrameToken() {
1225 return frame_tree_node_->devtools_frame_token();
1226 }
1227
1228 base::Optional<base::UnguessableToken>
GetEmbeddingToken()1229 RenderFrameHostImpl::GetEmbeddingToken() {
1230 if (!IsCurrent())
1231 return base::nullopt;
1232 return frame_tree_node_->GetEmbeddingToken();
1233 }
1234
GetFrameName()1235 const std::string& RenderFrameHostImpl::GetFrameName() {
1236 return frame_tree_node_->frame_name();
1237 }
1238
IsFrameDisplayNone()1239 bool RenderFrameHostImpl::IsFrameDisplayNone() {
1240 return frame_tree_node()->frame_owner_properties().is_display_none;
1241 }
1242
GetFrameSize()1243 const base::Optional<gfx::Size>& RenderFrameHostImpl::GetFrameSize() {
1244 return frame_size_;
1245 }
1246
GetFrameDepth()1247 size_t RenderFrameHostImpl::GetFrameDepth() {
1248 return frame_tree_node()->depth();
1249 }
1250
IsCrossProcessSubframe()1251 bool RenderFrameHostImpl::IsCrossProcessSubframe() {
1252 if (!parent_)
1253 return false;
1254 return GetSiteInstance() != parent_->GetSiteInstance();
1255 }
1256
GetLastCommittedURL()1257 const GURL& RenderFrameHostImpl::GetLastCommittedURL() {
1258 return last_committed_url_;
1259 }
1260
GetLastCommittedOrigin()1261 const url::Origin& RenderFrameHostImpl::GetLastCommittedOrigin() {
1262 return last_committed_origin_;
1263 }
1264
GetNetworkIsolationKey()1265 const net::NetworkIsolationKey& RenderFrameHostImpl::GetNetworkIsolationKey() {
1266 return network_isolation_key_;
1267 }
1268
GetCanonicalUrlForSharing(mojom::Frame::GetCanonicalUrlForSharingCallback callback)1269 void RenderFrameHostImpl::GetCanonicalUrlForSharing(
1270 mojom::Frame::GetCanonicalUrlForSharingCallback callback) {
1271 // TODO(https://crbug.com/859110): Remove this once frame_ can no longer be
1272 // null.
1273 if (IsRenderFrameLive()) {
1274 frame_->GetCanonicalUrlForSharing(std::move(callback));
1275 } else {
1276 std::move(callback).Run(base::nullopt);
1277 }
1278 }
1279
1280 mojo::Remote<blink::mojom::PauseSubresourceLoadingHandle>
PauseSubresourceLoading()1281 RenderFrameHostImpl::PauseSubresourceLoading() {
1282 DCHECK(frame_);
1283 mojo::Remote<blink::mojom::PauseSubresourceLoadingHandle>
1284 pause_subresource_loading_handle;
1285 GetRemoteInterfaces()->GetInterface(
1286 pause_subresource_loading_handle.BindNewPipeAndPassReceiver());
1287
1288 return pause_subresource_loading_handle;
1289 }
1290
ExecuteMediaPlayerActionAtLocation(const gfx::Point & location,const blink::mojom::MediaPlayerAction & action)1291 void RenderFrameHostImpl::ExecuteMediaPlayerActionAtLocation(
1292 const gfx::Point& location,
1293 const blink::mojom::MediaPlayerAction& action) {
1294 auto media_player_action = blink::mojom::MediaPlayerAction::New();
1295 media_player_action->type = action.type;
1296 media_player_action->enable = action.enable;
1297 gfx::PointF point_in_view = GetView()->TransformRootPointToViewCoordSpace(
1298 gfx::PointF(location.x(), location.y()));
1299 GetAssociatedLocalFrame()->MediaPlayerActionAt(
1300 gfx::Point(point_in_view.x(), point_in_view.y()),
1301 std::move(media_player_action));
1302 }
1303
CreateNetworkServiceDefaultFactory(mojo::PendingReceiver<network::mojom::URLLoaderFactory> default_factory_receiver)1304 bool RenderFrameHostImpl::CreateNetworkServiceDefaultFactory(
1305 mojo::PendingReceiver<network::mojom::URLLoaderFactory>
1306 default_factory_receiver) {
1307 mojo::PendingRemote<network::mojom::CrossOriginEmbedderPolicyReporter>
1308 coep_reporter_remote;
1309 if (coep_reporter_) {
1310 coep_reporter_->Clone(
1311 coep_reporter_remote.InitWithNewPipeAndPassReceiver());
1312 }
1313
1314 // We use the last committed Origin and ClientSecurityState. If the caller
1315 // wanted a factory associated to a navigation about to commit, the params
1316 // generated won't be correct. There is no good way of fixing this before
1317 // RenderDocumentHost (ie swapping RenderFrameHost on each navigation).
1318 return CreateNetworkServiceDefaultFactoryInternal(
1319 CreateURLLoaderFactoryParamsForMainWorld(
1320 last_committed_origin_,
1321 mojo::Clone(last_committed_client_security_state_),
1322 std::move(coep_reporter_remote)),
1323 std::move(default_factory_receiver));
1324 }
1325
MarkIsolatedWorldsAsRequiringSeparateURLLoaderFactory(base::flat_set<url::Origin> isolated_world_origins,bool push_to_renderer_now)1326 void RenderFrameHostImpl::MarkIsolatedWorldsAsRequiringSeparateURLLoaderFactory(
1327 base::flat_set<url::Origin> isolated_world_origins,
1328 bool push_to_renderer_now) {
1329 size_t old_size =
1330 isolated_worlds_requiring_separate_url_loader_factory_.size();
1331 isolated_worlds_requiring_separate_url_loader_factory_.insert(
1332 isolated_world_origins.begin(), isolated_world_origins.end());
1333 size_t new_size =
1334 isolated_worlds_requiring_separate_url_loader_factory_.size();
1335 bool insertion_took_place = (old_size != new_size);
1336
1337 // Push the updated set of factories to the renderer, but only if
1338 // 1) the caller requested an immediate push (e.g. for content scripts
1339 // injected programmatically chrome.tabs.executeCode, but not for content
1340 // scripts declared in the manifest - the difference is that the latter
1341 // happen at a commit and the factories can just be send in the commit
1342 // IPC).
1343 // 2) an insertion actually took place / the factories have been modified
1344 // 3) a commit has taken place before (i.e. the frame has received a factory
1345 // bundle before).
1346 if (push_to_renderer_now && insertion_took_place &&
1347 has_committed_any_navigation_) {
1348 std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
1349 subresource_loader_factories =
1350 std::make_unique<blink::PendingURLLoaderFactoryBundle>();
1351 subresource_loader_factories->pending_isolated_world_factories() =
1352 CreateURLLoaderFactoriesForIsolatedWorlds(
1353 GetExpectedMainWorldOriginForUrlLoaderFactory(),
1354 isolated_world_origins,
1355 mojo::Clone(last_committed_client_security_state_));
1356 GetNavigationControl()->UpdateSubresourceLoaderFactories(
1357 std::move(subresource_loader_factories));
1358 }
1359 }
1360
IsSandboxed(blink::mojom::WebSandboxFlags flags)1361 bool RenderFrameHostImpl::IsSandboxed(blink::mojom::WebSandboxFlags flags) {
1362 if (base::FeatureList::IsEnabled(features::kFeaturePolicyForSandbox)) {
1363 blink::mojom::FeaturePolicyFeature feature =
1364 blink::FeaturePolicy::FeatureForSandboxFlag(flags);
1365 if (feature != blink::mojom::FeaturePolicyFeature::kNotFound)
1366 return !IsFeatureEnabled(feature);
1367 }
1368 return static_cast<int>(active_sandbox_flags_) & static_cast<int>(flags);
1369 }
1370
1371 blink::PendingURLLoaderFactoryBundle::OriginMap
CreateURLLoaderFactoriesForIsolatedWorlds(const url::Origin & main_world_origin,const base::flat_set<url::Origin> & isolated_world_origins,network::mojom::ClientSecurityStatePtr client_security_state)1372 RenderFrameHostImpl::CreateURLLoaderFactoriesForIsolatedWorlds(
1373 const url::Origin& main_world_origin,
1374 const base::flat_set<url::Origin>& isolated_world_origins,
1375 network::mojom::ClientSecurityStatePtr client_security_state) {
1376 WebPreferences preferences = GetRenderViewHost()->GetWebkitPreferences();
1377
1378 blink::PendingURLLoaderFactoryBundle::OriginMap result;
1379 for (const url::Origin& isolated_world_origin : isolated_world_origins) {
1380 network::mojom::URLLoaderFactoryParamsPtr factory_params =
1381 URLLoaderFactoryParamsHelper::CreateForIsolatedWorld(
1382 this, isolated_world_origin, main_world_origin,
1383 mojo::Clone(client_security_state));
1384
1385 mojo::PendingRemote<network::mojom::URLLoaderFactory> factory_remote;
1386 CreateNetworkServiceDefaultFactoryAndObserve(
1387 std::move(factory_params),
1388 factory_remote.InitWithNewPipeAndPassReceiver());
1389 result[isolated_world_origin] = std::move(factory_remote);
1390 }
1391 return result;
1392 }
1393
GetNativeView()1394 gfx::NativeView RenderFrameHostImpl::GetNativeView() {
1395 RenderWidgetHostView* view = render_view_host_->GetWidget()->GetView();
1396 if (!view)
1397 return nullptr;
1398 return view->GetNativeView();
1399 }
1400
AddMessageToConsole(blink::mojom::ConsoleMessageLevel level,const std::string & message)1401 void RenderFrameHostImpl::AddMessageToConsole(
1402 blink::mojom::ConsoleMessageLevel level,
1403 const std::string& message) {
1404 AddMessageToConsoleImpl(level, message, false /* discard_duplicates */);
1405 }
1406
ExecuteJavaScript(const base::string16 & javascript,JavaScriptResultCallback callback)1407 void RenderFrameHostImpl::ExecuteJavaScript(const base::string16& javascript,
1408 JavaScriptResultCallback callback) {
1409 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1410 CHECK(CanExecuteJavaScript());
1411
1412 const bool wants_result = !callback.is_null();
1413 GetNavigationControl()->JavaScriptExecuteRequest(javascript, wants_result,
1414 std::move(callback));
1415 }
1416
ExecuteJavaScriptInIsolatedWorld(const base::string16 & javascript,JavaScriptResultCallback callback,int32_t world_id)1417 void RenderFrameHostImpl::ExecuteJavaScriptInIsolatedWorld(
1418 const base::string16& javascript,
1419 JavaScriptResultCallback callback,
1420 int32_t world_id) {
1421 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1422 DCHECK_GT(world_id, ISOLATED_WORLD_ID_GLOBAL);
1423 DCHECK_LE(world_id, ISOLATED_WORLD_ID_MAX);
1424
1425 const bool wants_result = !callback.is_null();
1426 GetNavigationControl()->JavaScriptExecuteRequestInIsolatedWorld(
1427 javascript, wants_result, world_id, std::move(callback));
1428 }
1429
ExecuteJavaScriptForTests(const base::string16 & javascript,JavaScriptResultCallback callback,int32_t world_id)1430 void RenderFrameHostImpl::ExecuteJavaScriptForTests(
1431 const base::string16& javascript,
1432 JavaScriptResultCallback callback,
1433 int32_t world_id) {
1434 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1435
1436 const bool has_user_gesture = false;
1437 const bool wants_result = !callback.is_null();
1438 GetNavigationControl()->JavaScriptExecuteRequestForTests(
1439 javascript, wants_result, has_user_gesture, world_id,
1440 std::move(callback));
1441 }
1442
ExecuteJavaScriptWithUserGestureForTests(const base::string16 & javascript,int32_t world_id)1443 void RenderFrameHostImpl::ExecuteJavaScriptWithUserGestureForTests(
1444 const base::string16& javascript,
1445 int32_t world_id) {
1446 DCHECK_CURRENTLY_ON(BrowserThread::UI);
1447
1448 // TODO(mustaq): The render-to-browser state update caused by the below
1449 // JavaScriptExecuteRequestsForTests call is redundant with this update. We
1450 // should determine if the redundancy can be removed.
1451 frame_tree_node()->UpdateUserActivationState(
1452 blink::mojom::UserActivationUpdateType::kNotifyActivation);
1453
1454 const bool has_user_gesture = true;
1455 GetNavigationControl()->JavaScriptExecuteRequestForTests(
1456 javascript, false, has_user_gesture, world_id, base::NullCallback());
1457 }
1458
CopyImageAt(int x,int y)1459 void RenderFrameHostImpl::CopyImageAt(int x, int y) {
1460 gfx::PointF point_in_view =
1461 GetView()->TransformRootPointToViewCoordSpace(gfx::PointF(x, y));
1462 GetAssociatedLocalFrame()->CopyImageAt(
1463 gfx::Point(point_in_view.x(), point_in_view.y()));
1464 }
1465
SaveImageAt(int x,int y)1466 void RenderFrameHostImpl::SaveImageAt(int x, int y) {
1467 gfx::PointF point_in_view =
1468 GetView()->TransformRootPointToViewCoordSpace(gfx::PointF(x, y));
1469 GetAssociatedLocalFrame()->SaveImageAt(
1470 gfx::Point(point_in_view.x(), point_in_view.y()));
1471 }
1472
GetRenderViewHost()1473 RenderViewHost* RenderFrameHostImpl::GetRenderViewHost() {
1474 return render_view_host_.get();
1475 }
1476
GetRemoteInterfaces()1477 service_manager::InterfaceProvider* RenderFrameHostImpl::GetRemoteInterfaces() {
1478 return remote_interfaces_.get();
1479 }
1480
1481 blink::AssociatedInterfaceProvider*
GetRemoteAssociatedInterfaces()1482 RenderFrameHostImpl::GetRemoteAssociatedInterfaces() {
1483 if (!remote_associated_interfaces_) {
1484 mojo::AssociatedRemote<blink::mojom::AssociatedInterfaceProvider>
1485 remote_interfaces;
1486 IPC::ChannelProxy* channel = GetProcess()->GetChannel();
1487 if (channel) {
1488 RenderProcessHostImpl* process =
1489 static_cast<RenderProcessHostImpl*>(GetProcess());
1490 process->GetRemoteRouteProvider()->GetRoute(
1491 GetRoutingID(), remote_interfaces.BindNewEndpointAndPassReceiver());
1492 } else {
1493 // The channel may not be initialized in some tests environments. In this
1494 // case we set up a dummy interface provider.
1495 ignore_result(remote_interfaces
1496 .BindNewEndpointAndPassDedicatedReceiverForTesting());
1497 }
1498 remote_associated_interfaces_ =
1499 std::make_unique<blink::AssociatedInterfaceProvider>(
1500 remote_interfaces.Unbind());
1501 }
1502 return remote_associated_interfaces_.get();
1503 }
1504
GetVisibilityState()1505 PageVisibilityState RenderFrameHostImpl::GetVisibilityState() {
1506 // Works around the crashes seen in https://crbug.com/501863, where the
1507 // active WebContents from a browser iterator may contain a render frame
1508 // detached from the frame tree. This tries to find a RenderWidgetHost
1509 // attached to an ancestor frame, and defaults to visibility hidden if
1510 // it fails.
1511 // TODO(yfriedman, peter): Ideally this would never be called on an
1512 // unattached frame and we could omit this check. See
1513 // https://crbug.com/615867.
1514 RenderFrameHostImpl* frame = this;
1515 while (frame) {
1516 if (frame->GetLocalRenderWidgetHost())
1517 break;
1518 frame = frame->GetParent();
1519 }
1520 if (!frame)
1521 return PageVisibilityState::kHidden;
1522
1523 PageVisibilityState visibility_state = GetRenderWidgetHost()->is_hidden()
1524 ? PageVisibilityState::kHidden
1525 : PageVisibilityState::kVisible;
1526 GetContentClient()->browser()->OverridePageVisibilityState(this,
1527 &visibility_state);
1528 return visibility_state;
1529 }
1530
Send(IPC::Message * message)1531 bool RenderFrameHostImpl::Send(IPC::Message* message) {
1532 return GetProcess()->Send(message);
1533 }
1534
OnMessageReceived(const IPC::Message & msg)1535 bool RenderFrameHostImpl::OnMessageReceived(const IPC::Message& msg) {
1536 // Only process messages if the RenderFrame is alive.
1537 if (!render_frame_created_)
1538 return false;
1539
1540 // Crash reports triggered by IPC messages for this frame should be associated
1541 // with its URL.
1542 ScopedActiveURL scoped_active_url(this);
1543
1544 if (delegate_->OnMessageReceived(this, msg))
1545 return true;
1546
1547 RenderFrameProxyHost* proxy =
1548 frame_tree_node_->render_manager()->GetProxyToParent();
1549 if (proxy && proxy->cross_process_frame_connector() &&
1550 proxy->cross_process_frame_connector()->OnMessageReceived(msg))
1551 return true;
1552
1553 bool handled = true;
1554 IPC_BEGIN_MESSAGE_MAP(RenderFrameHostImpl, msg)
1555 IPC_MESSAGE_HANDLER(FrameHostMsg_Detach, OnDetach)
1556 IPC_MESSAGE_HANDLER(FrameHostMsg_UpdateState, OnUpdateState)
1557 IPC_MESSAGE_HANDLER(FrameHostMsg_OpenURL, OnOpenURL)
1558 IPC_MESSAGE_HANDLER(FrameHostMsg_Unload_ACK, OnUnloadACK)
1559 IPC_MESSAGE_HANDLER(FrameHostMsg_ContextMenu, OnContextMenu)
1560 IPC_MESSAGE_HANDLER(FrameHostMsg_VisualStateResponse, OnVisualStateResponse)
1561 IPC_MESSAGE_HANDLER(FrameHostMsg_DidChangeOpener, OnDidChangeOpener)
1562 IPC_MESSAGE_HANDLER(FrameHostMsg_DidChangeFramePolicy,
1563 OnDidChangeFramePolicy)
1564 IPC_MESSAGE_HANDLER(FrameHostMsg_DidChangeFrameOwnerProperties,
1565 OnDidChangeFrameOwnerProperties)
1566 IPC_MESSAGE_HANDLER(FrameHostMsg_DidStopLoading, OnDidStopLoading)
1567 IPC_MESSAGE_HANDLER(FrameHostMsg_SelectionChanged, OnSelectionChanged)
1568 IPC_MESSAGE_HANDLER(FrameHostMsg_FrameDidCallFocus, OnFrameDidCallFocus)
1569 #if BUILDFLAG(USE_EXTERNAL_POPUP_MENU)
1570 IPC_MESSAGE_HANDLER(FrameHostMsg_ShowPopup, OnShowPopup)
1571 IPC_MESSAGE_HANDLER(FrameHostMsg_HidePopup, OnHidePopup)
1572 #endif
1573 IPC_END_MESSAGE_MAP()
1574
1575 // No further actions here, since we may have been deleted.
1576 return handled;
1577 }
1578
OnAssociatedInterfaceRequest(const std::string & interface_name,mojo::ScopedInterfaceEndpointHandle handle)1579 void RenderFrameHostImpl::OnAssociatedInterfaceRequest(
1580 const std::string& interface_name,
1581 mojo::ScopedInterfaceEndpointHandle handle) {
1582 ContentBrowserClient* browser_client = GetContentClient()->browser();
1583 if (!associated_registry_->TryBindInterface(interface_name, &handle) &&
1584 !browser_client->BindAssociatedReceiverFromFrame(this, interface_name,
1585 &handle)) {
1586 delegate_->OnAssociatedInterfaceRequest(this, interface_name,
1587 std::move(handle));
1588 }
1589 }
1590
AccessibilityPerformAction(const ui::AXActionData & action_data)1591 void RenderFrameHostImpl::AccessibilityPerformAction(
1592 const ui::AXActionData& action_data) {
1593 if (!is_active() || !render_accessibility_)
1594 return;
1595
1596 // Use the dedicated HitTest method so that we can handle its response via
1597 // mojo callback once it's been handled in the renderer process.
1598 if (action_data.action == ax::mojom::Action::kHitTest) {
1599 render_accessibility_->HitTest(
1600 action_data,
1601 base::BindOnce(&RenderFrameHostImpl::RequestAXHitTestCallback,
1602 weak_ptr_factory_.GetWeakPtr(), action_data.request_id));
1603 return;
1604 }
1605
1606 render_accessibility_->PerformAction(action_data);
1607 }
1608
AccessibilityViewHasFocus() const1609 bool RenderFrameHostImpl::AccessibilityViewHasFocus() const {
1610 if (!is_active())
1611 return false;
1612
1613 RenderWidgetHostView* view = render_view_host_->GetWidget()->GetView();
1614 if (view)
1615 return view->HasFocus();
1616 return false;
1617 }
1618
AccessibilityViewSetFocus()1619 void RenderFrameHostImpl::AccessibilityViewSetFocus() {
1620 if (!is_active())
1621 return;
1622
1623 RenderWidgetHostView* view = render_view_host_->GetWidget()->GetView();
1624 if (view)
1625 view->Focus();
1626 }
1627
AccessibilityGetViewBounds() const1628 gfx::Rect RenderFrameHostImpl::AccessibilityGetViewBounds() const {
1629 if (!is_active())
1630 return gfx::Rect();
1631
1632 RenderWidgetHostView* view = render_view_host_->GetWidget()->GetView();
1633 if (view)
1634 return view->GetViewBounds();
1635 return gfx::Rect();
1636 }
1637
AccessibilityGetDeviceScaleFactor() const1638 float RenderFrameHostImpl::AccessibilityGetDeviceScaleFactor() const {
1639 if (!is_active())
1640 return 1.0f;
1641
1642 RenderWidgetHostView* view = render_view_host_->GetWidget()->GetView();
1643 if (view)
1644 return GetScaleFactorForView(view);
1645 return 1.0f;
1646 }
1647
AccessibilityReset()1648 void RenderFrameHostImpl::AccessibilityReset() {
1649 if (!render_accessibility_)
1650 return;
1651
1652 accessibility_reset_token_ = g_next_accessibility_reset_token++;
1653 render_accessibility_->Reset(accessibility_reset_token_);
1654 }
1655
AccessibilityFatalError()1656 void RenderFrameHostImpl::AccessibilityFatalError() {
1657 browser_accessibility_manager_.reset(nullptr);
1658 if (accessibility_reset_token_ || !render_accessibility_)
1659 return;
1660
1661 accessibility_reset_count_++;
1662 if (accessibility_reset_count_ >= kMaxAccessibilityResets) {
1663 render_accessibility_->FatalError();
1664 } else {
1665 AccessibilityReset();
1666 }
1667 }
1668
1669 gfx::AcceleratedWidget
AccessibilityGetAcceleratedWidget()1670 RenderFrameHostImpl::AccessibilityGetAcceleratedWidget() {
1671 // Only the main frame's current frame host is connected to the native
1672 // widget tree for accessibility, so return null if this is queried on
1673 // any other frame.
1674 if (!is_active() || frame_tree_node()->parent() || !IsCurrent())
1675 return gfx::kNullAcceleratedWidget;
1676
1677 RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>(
1678 render_view_host_->GetWidget()->GetView());
1679 if (view)
1680 return view->AccessibilityGetAcceleratedWidget();
1681 return gfx::kNullAcceleratedWidget;
1682 }
1683
1684 gfx::NativeViewAccessible
AccessibilityGetNativeViewAccessible()1685 RenderFrameHostImpl::AccessibilityGetNativeViewAccessible() {
1686 if (!is_active())
1687 return nullptr;
1688
1689 RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>(
1690 render_view_host_->GetWidget()->GetView());
1691 if (view)
1692 return view->AccessibilityGetNativeViewAccessible();
1693 return nullptr;
1694 }
1695
1696 gfx::NativeViewAccessible
AccessibilityGetNativeViewAccessibleForWindow()1697 RenderFrameHostImpl::AccessibilityGetNativeViewAccessibleForWindow() {
1698 if (!is_active())
1699 return nullptr;
1700
1701 RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>(
1702 render_view_host_->GetWidget()->GetView());
1703 if (view)
1704 return view->AccessibilityGetNativeViewAccessibleForWindow();
1705 return nullptr;
1706 }
1707
AccessibilityWebContents()1708 WebContents* RenderFrameHostImpl::AccessibilityWebContents() {
1709 if (!is_active())
1710 return nullptr;
1711 return delegate()->GetAsWebContents();
1712 }
1713
AccessibilityIsMainFrame() const1714 bool RenderFrameHostImpl::AccessibilityIsMainFrame() const {
1715 if (!is_active())
1716 return false;
1717 return frame_tree_node()->IsMainFrame();
1718 }
1719
RenderProcessExited(RenderProcessHost * host,const ChildProcessTerminationInfo & info)1720 void RenderFrameHostImpl::RenderProcessExited(
1721 RenderProcessHost* host,
1722 const ChildProcessTerminationInfo& info) {
1723 if (base::FeatureList::IsEnabled(features::kCrashReporting))
1724 MaybeGenerateCrashReport(info.status, info.exit_code);
1725
1726 // When a frame's process dies, its RenderFrame no longer exists, which means
1727 // that its child frames must be cleaned up as well.
1728 ResetChildren();
1729
1730 // Reset state for the current RenderFrameHost once the FrameTreeNode has been
1731 // reset.
1732 SetRenderFrameCreated(false);
1733 InvalidateMojoConnection();
1734 document_scoped_interface_provider_receiver_.reset();
1735 broker_receiver_.reset();
1736 SetLastCommittedUrl(GURL());
1737 web_bundle_handle_.reset();
1738
1739 must_be_replaced_ = CreateNewHostForCrashedFrame();
1740 has_committed_any_navigation_ = false;
1741
1742 #if defined(OS_ANDROID)
1743 // Execute any pending Samsung smart clip callbacks.
1744 for (base::IDMap<std::unique_ptr<ExtractSmartClipDataCallback>>::iterator
1745 iter(&smart_clip_callbacks_);
1746 !iter.IsAtEnd(); iter.Advance()) {
1747 std::move(*iter.GetCurrentValue())
1748 .Run(base::string16(), base::string16(), gfx::Rect());
1749 }
1750 smart_clip_callbacks_.Clear();
1751 #endif // defined(OS_ANDROID)
1752
1753 visual_state_callbacks_.clear();
1754
1755 // Ensure that future remote interface requests are associated with the new
1756 // process's channel.
1757 remote_associated_interfaces_.reset();
1758
1759 // Any termination disablers in content loaded by the new process will
1760 // be sent again.
1761 has_before_unload_handler_ = false;
1762 has_unload_handler_ = false;
1763
1764 if (unload_state_ != UnloadState::NotRun) {
1765 // If the process has died, we don't need to wait for the ACK. Complete the
1766 // deletion immediately.
1767 unload_state_ = UnloadState::Completed;
1768 DCHECK(children_.empty());
1769 PendingDeletionCheckCompleted();
1770 // |this| is deleted. Don't add any more code at this point in the function.
1771 return;
1772 }
1773
1774 // If this was the current pending or speculative RFH dying, cancel and
1775 // destroy it.
1776 frame_tree_node_->render_manager()->CancelPendingIfNecessary(this);
1777
1778 // Note: don't add any more code at this point in the function because
1779 // |this| may be deleted. Any additional cleanup should happen before
1780 // the last block of code here.
1781 }
1782
RenderProcessGone(SiteInstanceImpl * site_instance,const ChildProcessTerminationInfo & info)1783 void RenderFrameHostImpl::RenderProcessGone(
1784 SiteInstanceImpl* site_instance,
1785 const ChildProcessTerminationInfo& info) {
1786 DCHECK_EQ(site_instance_.get(), site_instance);
1787
1788 if (is_in_back_forward_cache_) {
1789 EvictFromBackForwardCacheWithReason(
1790 info.status == base::TERMINATION_STATUS_PROCESS_CRASHED
1791 ? BackForwardCacheMetrics::NotRestoredReason::
1792 kRendererProcessCrashed
1793 : BackForwardCacheMetrics::NotRestoredReason::
1794 kRendererProcessKilled);
1795 return;
1796 }
1797
1798 if (owned_render_widget_host_)
1799 owned_render_widget_host_->RendererExited();
1800
1801 // The renderer process is gone, so this frame can no longer be loading.
1802 if (navigation_request())
1803 navigation_request()->set_net_error(net::ERR_ABORTED);
1804 ResetNavigationRequests();
1805 ResetLoadingState();
1806
1807 // Any future UpdateState or UpdateTitle messages from this or a recreated
1808 // process should be ignored until the next commit.
1809 set_nav_entry_id(0);
1810
1811 OnAudibleStateChanged(false);
1812 }
1813
ReportContentSecurityPolicyViolation(network::mojom::CSPViolationPtr violation_params)1814 void RenderFrameHostImpl::ReportContentSecurityPolicyViolation(
1815 network::mojom::CSPViolationPtr violation_params) {
1816 GetAssociatedLocalFrame()->ReportContentSecurityPolicyViolation(
1817 std::move(violation_params));
1818 }
1819
SanitizeDataForUseInCspViolation(bool is_redirect,network::mojom::CSPDirectiveName directive,GURL * blocked_url,network::mojom::SourceLocation * source_location) const1820 void RenderFrameHostImpl::SanitizeDataForUseInCspViolation(
1821 bool is_redirect,
1822 network::mojom::CSPDirectiveName directive,
1823 GURL* blocked_url,
1824 network::mojom::SourceLocation* source_location) const {
1825 DCHECK(blocked_url);
1826 DCHECK(source_location);
1827 GURL source_location_url(source_location->url);
1828
1829 // The main goal of this is to avoid leaking information between potentially
1830 // separate renderers, in the event of one of them being compromised.
1831 // See https://crbug.com/633306.
1832 bool sanitize_blocked_url = true;
1833 bool sanitize_source_location = true;
1834
1835 // There is no need to sanitize data when it is same-origin with the current
1836 // url of the renderer.
1837 if (url::Origin::Create(*blocked_url)
1838 .IsSameOriginWith(last_committed_origin_))
1839 sanitize_blocked_url = false;
1840 if (url::Origin::Create(source_location_url)
1841 .IsSameOriginWith(last_committed_origin_))
1842 sanitize_source_location = false;
1843
1844 // When a renderer tries to do a form submission, it already knows the url of
1845 // the blocked url, except when it is redirected.
1846 if (!is_redirect && directive == network::mojom::CSPDirectiveName::FormAction)
1847 sanitize_blocked_url = false;
1848
1849 if (sanitize_blocked_url)
1850 *blocked_url = blocked_url->GetOrigin();
1851 if (sanitize_source_location) {
1852 source_location->url = source_location_url.GetOrigin().spec();
1853 source_location->line = 0u;
1854 source_location->column = 0u;
1855 }
1856 }
1857
PerformAction(const ui::AXActionData & data)1858 void RenderFrameHostImpl::PerformAction(const ui::AXActionData& data) {
1859 AccessibilityPerformAction(data);
1860 }
1861
RequiresPerformActionPointInPixels() const1862 bool RenderFrameHostImpl::RequiresPerformActionPointInPixels() const {
1863 return true;
1864 }
1865
SchemeShouldBypassCSP(const base::StringPiece & scheme)1866 bool RenderFrameHostImpl::SchemeShouldBypassCSP(
1867 const base::StringPiece& scheme) {
1868 // Blink uses its SchemeRegistry to check if a scheme should be bypassed.
1869 // It can't be used on the browser process. It is used for two things:
1870 // 1) Bypassing the "chrome-extension" scheme when chrome is built with the
1871 // extensions support.
1872 // 2) Bypassing arbitrary scheme for testing purpose only in blink and in V8.
1873 // TODO(arthursonzogni): url::GetBypassingCSPScheme() is used instead of the
1874 // blink::SchemeRegistry. It contains 1) but not 2).
1875 const auto& bypassing_schemes = url::GetCSPBypassingSchemes();
1876 return base::Contains(bypassing_schemes, scheme);
1877 }
1878
GetFrameInputHandler()1879 mojom::FrameInputHandler* RenderFrameHostImpl::GetFrameInputHandler() {
1880 if (!frame_input_handler_)
1881 return nullptr;
1882 return frame_input_handler_.get();
1883 }
1884
CreateRenderFrame(int previous_routing_id,int opener_routing_id,int parent_routing_id,int previous_sibling_routing_id)1885 bool RenderFrameHostImpl::CreateRenderFrame(int previous_routing_id,
1886 int opener_routing_id,
1887 int parent_routing_id,
1888 int previous_sibling_routing_id) {
1889 TRACE_EVENT0("navigation", "RenderFrameHostImpl::CreateRenderFrame");
1890 DCHECK(!IsRenderFrameLive()) << "Creating frame twice";
1891
1892 // The process may (if we're sharing a process with another host that already
1893 // initialized it) or may not (we have our own process or the old process
1894 // crashed) have been initialized. Calling Init multiple times will be
1895 // ignored, so this is safe.
1896 if (!GetProcess()->Init())
1897 return false;
1898
1899 DCHECK(GetProcess()->IsInitializedAndNotDead());
1900
1901 mojo::PendingRemote<service_manager::mojom::InterfaceProvider>
1902 interface_provider;
1903 BindInterfaceProviderReceiver(
1904 interface_provider.InitWithNewPipeAndPassReceiver());
1905
1906 mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>
1907 browser_interface_broker;
1908 BindBrowserInterfaceBrokerReceiver(
1909 browser_interface_broker.InitWithNewPipeAndPassReceiver());
1910
1911 mojom::CreateFrameParamsPtr params = mojom::CreateFrameParams::New();
1912 params->interface_bundle = mojom::DocumentScopedInterfaceBundle::New(
1913 std::move(interface_provider), std::move(browser_interface_broker));
1914
1915 params->routing_id = routing_id_;
1916 params->previous_routing_id = previous_routing_id;
1917 params->opener_routing_id = opener_routing_id;
1918 params->parent_routing_id = parent_routing_id;
1919 params->previous_sibling_routing_id = previous_sibling_routing_id;
1920 params->replication_state = frame_tree_node()->current_replication_state();
1921 params->devtools_frame_token = frame_tree_node()->devtools_frame_token();
1922
1923 // Normally, the replication state contains effective frame policy, excluding
1924 // sandbox flags and feature policy attributes that were updated but have not
1925 // taken effect. However, a new RenderFrame should use the pending frame
1926 // policy, since it is being created as part of the navigation that will
1927 // commit it. (I.e., the RenderFrame needs to know the policy to use when
1928 // initializing the new document once it commits).
1929 params->replication_state.frame_policy =
1930 frame_tree_node()->pending_frame_policy();
1931
1932 // If we switched BrowsingInstances because of the COOP header, we should
1933 // clear the frame name. This below informs the renderer at frame creation.
1934 NavigationRequest* navigation_request =
1935 frame_tree_node()->navigation_request();
1936 if (navigation_request &&
1937 navigation_request->require_coop_browsing_instance_swap()) {
1938 params->replication_state.name = "";
1939 // "COOP swaps" only affect main frames, that have an empty unique name.
1940 DCHECK(params->replication_state.unique_name.empty());
1941 }
1942
1943 params->frame_owner_properties =
1944 frame_tree_node()->frame_owner_properties().Clone();
1945
1946 params->has_committed_real_load =
1947 frame_tree_node()->has_committed_real_load();
1948
1949 // The RenderWidgetHost takes ownership of its view. It is tied to the
1950 // lifetime of the current RenderProcessHost for this RenderFrameHost.
1951 // TODO(avi): This will need to change to initialize a
1952 // RenderWidgetHostViewAura for the main frame once RenderViewHostImpl has-a
1953 // RenderWidgetHostImpl. https://crbug.com/545684
1954 if (owned_render_widget_host_) {
1955 DCHECK(parent_);
1956 DCHECK_NE(parent_routing_id, MSG_ROUTING_NONE);
1957 RenderWidgetHostView* rwhv =
1958 RenderWidgetHostViewChildFrame::Create(owned_render_widget_host_.get());
1959 // The child frame should be created hidden.
1960 DCHECK(!rwhv->IsShowing());
1961 }
1962
1963 if (auto* rwh = GetLocalRenderWidgetHost()) {
1964 params->widget_params = mojom::CreateFrameWidgetParams::New();
1965 params->widget_params->routing_id =
1966 GetLocalRenderWidgetHost()->GetRoutingID();
1967 params->widget_params->visual_properties =
1968 GetLocalRenderWidgetHost()->GetInitialVisualProperties();
1969
1970 std::tie(params->widget_params->widget_host,
1971 params->widget_params->widget) = rwh->BindNewWidgetInterfaces();
1972 std::tie(params->widget_params->frame_widget_host,
1973 params->widget_params->frame_widget) =
1974 rwh->BindNewFrameWidgetInterfaces();
1975 }
1976
1977 // TODO(https://crbug.com/1006814): Remove this.
1978 if (params->previous_routing_id == MSG_ROUTING_NONE &&
1979 params->parent_routing_id == MSG_ROUTING_NONE) {
1980 base::debug::DumpWithoutCrashing();
1981 NOTREACHED();
1982 }
1983 GetProcess()->GetRendererInterface()->CreateFrame(std::move(params));
1984
1985 if (previous_routing_id != MSG_ROUTING_NONE) {
1986 RenderFrameProxyHost* proxy = RenderFrameProxyHost::FromID(
1987 GetProcess()->GetID(), previous_routing_id);
1988 // We have also created a RenderFrameProxy in CreateFrame above, so
1989 // remember that.
1990 //
1991 // RenderDocument: |proxy| can be null, when |previous_routing_id| refers to
1992 // a RenderFrameHost instead of a RenderFrameProxy.
1993 if (proxy)
1994 proxy->SetRenderFrameProxyCreated(true);
1995 }
1996
1997 // The renderer now has a RenderFrame for this RenderFrameHost. Note that
1998 // this path is only used for out-of-process iframes. Main frame RenderFrames
1999 // are created with their RenderView, and same-site iframes are created at the
2000 // time of OnCreateChildFrame.
2001 SetRenderFrameCreated(true);
2002
2003 return true;
2004 }
2005
DeleteRenderFrame(FrameDeleteIntention intent)2006 void RenderFrameHostImpl::DeleteRenderFrame(FrameDeleteIntention intent) {
2007 if (unload_state_ != UnloadState::NotRun)
2008 return;
2009
2010 if (render_frame_created_) {
2011 Send(new UnfreezableFrameMsg_Delete(routing_id_, intent));
2012
2013 if (!frame_tree_node_->IsMainFrame() && IsCurrent()) {
2014 // If this subframe has an unload handler (and isn't speculative), ensure
2015 // that it has a chance to execute by delaying process cleanup. This will
2016 // prevent the process from shutting down immediately in the case where
2017 // this is the last active frame in the process. See
2018 // https://crbug.com/852204.
2019 if (has_unload_handler()) {
2020 RenderProcessHostImpl* process =
2021 static_cast<RenderProcessHostImpl*>(GetProcess());
2022 process->DelayProcessShutdownForUnload(subframe_unload_timeout_);
2023 }
2024
2025 // If the subframe takes too long to unload, force its removal from the
2026 // tree. See https://crbug.com/950625.
2027 subframe_unload_timer_.Start(FROM_HERE, subframe_unload_timeout_, this,
2028 &RenderFrameHostImpl::OnUnloadTimeout);
2029 }
2030 }
2031
2032 unload_state_ =
2033 has_unload_handler() ? UnloadState::InProgress : UnloadState::Completed;
2034 }
2035
SetRenderFrameCreated(bool created)2036 void RenderFrameHostImpl::SetRenderFrameCreated(bool created) {
2037 // We should not create new RenderFrames while our delegate is being destroyed
2038 // (e.g., via a WebContentsObserver during WebContents shutdown). This seems
2039 // to have caused crashes in https://crbug.com/717650.
2040 if (created)
2041 CHECK(!delegate_->IsBeingDestroyed());
2042
2043 bool was_created = render_frame_created_;
2044 render_frame_created_ = created;
2045
2046 // If the current status is different than the new status, the delegate
2047 // needs to be notified.
2048 if (created != was_created) {
2049 if (created) {
2050 SetUpMojoIfNeeded();
2051 delegate_->RenderFrameCreated(this);
2052 } else {
2053 delegate_->RenderFrameDeleted(this);
2054 }
2055 }
2056 // TODO(http://crbug.com/1014212): Change to DCHECK.
2057 if (created)
2058 CHECK(frame_);
2059
2060 if (created && GetLocalRenderWidgetHost()) {
2061 mojo::PendingRemote<mojom::Widget> widget;
2062 GetRemoteInterfaces()->GetInterface(
2063 widget.InitWithNewPipeAndPassReceiver());
2064 GetLocalRenderWidgetHost()->SetWidget(std::move(widget));
2065 GetLocalRenderWidgetHost()->SetFrameInputHandler(
2066 frame_input_handler_.get());
2067 GetLocalRenderWidgetHost()->input_router()->SetFrameTreeNodeId(
2068 frame_tree_node_->frame_tree_node_id());
2069 mojo::Remote<viz::mojom::InputTargetClient> input_target_client;
2070 remote_interfaces_->GetInterface(
2071 input_target_client.BindNewPipeAndPassReceiver());
2072 input_target_client_ = input_target_client.get();
2073 GetLocalRenderWidgetHost()->SetInputTargetClient(
2074 std::move(input_target_client));
2075 GetLocalRenderWidgetHost()->InitForFrame();
2076 }
2077
2078 if (enabled_bindings_ && created) {
2079 if (!frame_bindings_control_)
2080 GetRemoteAssociatedInterfaces()->GetInterface(&frame_bindings_control_);
2081 frame_bindings_control_->AllowBindings(enabled_bindings_);
2082 }
2083 }
2084
Init()2085 void RenderFrameHostImpl::Init() {
2086 ResumeBlockedRequestsForFrame();
2087 if (!waiting_for_init_)
2088 return;
2089
2090 waiting_for_init_ = false;
2091 if (pending_navigate_) {
2092 frame_tree_node()->navigator()->OnBeginNavigation(
2093 frame_tree_node(), std::move(pending_navigate_->common_params),
2094 std::move(pending_navigate_->begin_navigation_params),
2095 std::move(pending_navigate_->blob_url_loader_factory),
2096 std::move(pending_navigate_->navigation_client),
2097 std::move(pending_navigate_->navigation_initiator),
2098 EnsurePrefetchedSignedExchangeCache(),
2099 web_bundle_handle_ ? web_bundle_handle_->MaybeCreateTracker()
2100 : nullptr);
2101 pending_navigate_.reset();
2102 }
2103 }
2104
OnAudibleStateChanged(bool is_audible)2105 void RenderFrameHostImpl::OnAudibleStateChanged(bool is_audible) {
2106 if (is_audible_ == is_audible)
2107 return;
2108 if (is_audible)
2109 GetProcess()->OnMediaStreamAdded();
2110 else
2111 GetProcess()->OnMediaStreamRemoved();
2112 is_audible_ = is_audible;
2113 }
2114
DidAddMessageToConsole(blink::mojom::ConsoleMessageLevel log_level,const base::string16 & message,int32_t line_no,const base::string16 & source_id)2115 void RenderFrameHostImpl::DidAddMessageToConsole(
2116 blink::mojom::ConsoleMessageLevel log_level,
2117 const base::string16& message,
2118 int32_t line_no,
2119 const base::string16& source_id) {
2120 if (delegate_->DidAddMessageToConsole(log_level, message, line_no,
2121 source_id)) {
2122 return;
2123 }
2124
2125 // Pass through log severity only on builtin components pages to limit console
2126 // spew.
2127 const bool is_builtin_component =
2128 HasWebUIScheme(delegate_->GetMainFrameLastCommittedURL()) ||
2129 GetContentClient()->browser()->IsBuiltinComponent(
2130 GetProcess()->GetBrowserContext(), GetLastCommittedOrigin());
2131 const bool is_off_the_record =
2132 GetSiteInstance()->GetBrowserContext()->IsOffTheRecord();
2133
2134 LogConsoleMessage(log_level, message, line_no, is_builtin_component,
2135 is_off_the_record, source_id);
2136 }
2137
OnCreateChildFrame(int new_routing_id,mojo::PendingReceiver<service_manager::mojom::InterfaceProvider> new_interface_provider_provider_receiver,mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker> browser_interface_broker_receiver,blink::WebTreeScopeType scope,const std::string & frame_name,const std::string & frame_unique_name,bool is_created_by_script,const base::UnguessableToken & devtools_frame_token,const blink::FramePolicy & frame_policy,const blink::mojom::FrameOwnerProperties & frame_owner_properties,const blink::FrameOwnerElementType owner_type)2138 void RenderFrameHostImpl::OnCreateChildFrame(
2139 int new_routing_id,
2140 mojo::PendingReceiver<service_manager::mojom::InterfaceProvider>
2141 new_interface_provider_provider_receiver,
2142 mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
2143 browser_interface_broker_receiver,
2144 blink::WebTreeScopeType scope,
2145 const std::string& frame_name,
2146 const std::string& frame_unique_name,
2147 bool is_created_by_script,
2148 const base::UnguessableToken& devtools_frame_token,
2149 const blink::FramePolicy& frame_policy,
2150 const blink::mojom::FrameOwnerProperties& frame_owner_properties,
2151 const blink::FrameOwnerElementType owner_type) {
2152 // TODO(lukasza): Call ReceivedBadMessage when |frame_unique_name| is empty.
2153 DCHECK(!frame_unique_name.empty());
2154 DCHECK(new_interface_provider_provider_receiver.is_valid());
2155 DCHECK(browser_interface_broker_receiver.is_valid());
2156 if (owner_type == blink::FrameOwnerElementType::kNone) {
2157 // Any child frame must have a HTMLFrameOwnerElement in its parent document
2158 // and therefore the corresponding type of kNone (specific to main frames)
2159 // is invalid.
2160 bad_message::ReceivedBadMessage(
2161 GetProcess(), bad_message::RFH_CHILD_FRAME_NEEDS_OWNER_ELEMENT_TYPE);
2162 }
2163
2164 // The RenderFrame corresponding to this host sent an IPC message to create a
2165 // child, but by the time we get here, it's possible for the host to have been
2166 // swapped out, or for its process to have disconnected (maybe due to browser
2167 // shutdown). Ignore such messages.
2168 if (!is_active() || !IsCurrent() || !render_frame_created_)
2169 return;
2170
2171 // |new_routing_id|, |new_interface_provider_provider_receiver|,
2172 // |browser_interface_broker_receiver| and |devtools_frame_token| were
2173 // generated on the browser's IO thread and not taken from the renderer
2174 // process.
2175 frame_tree_->AddFrame(frame_tree_node_, GetProcess()->GetID(), new_routing_id,
2176 std::move(new_interface_provider_provider_receiver),
2177 std::move(browser_interface_broker_receiver), scope,
2178 frame_name, frame_unique_name, is_created_by_script,
2179 devtools_frame_token, frame_policy,
2180 frame_owner_properties, was_discarded_, owner_type);
2181 }
2182
DidNavigate(const FrameHostMsg_DidCommitProvisionalLoad_Params & params,bool is_same_document_navigation)2183 void RenderFrameHostImpl::DidNavigate(
2184 const FrameHostMsg_DidCommitProvisionalLoad_Params& params,
2185 bool is_same_document_navigation) {
2186 // Keep track of the last committed URL and origin in the RenderFrameHost
2187 // itself. These allow GetLastCommittedURL and GetLastCommittedOrigin to
2188 // stay correct even if the render_frame_host later becomes pending deletion.
2189 // The URL is set regardless of whether it's for a net error or not.
2190 frame_tree_node_->SetCurrentURL(params.url);
2191 SetLastCommittedOrigin(params.origin);
2192
2193 // Separately, update the frame's last successful URL except for net error
2194 // pages, since those do not end up in the correct process after transfers
2195 // (see https://crbug.com/560511). Instead, the next cross-process navigation
2196 // or transfer should decide whether to swap as if the net error had not
2197 // occurred.
2198 // TODO(creis): Remove this block and always set the URL.
2199 // See https://crbug.com/588314.
2200 if (!params.url_is_unreachable)
2201 last_successful_url_ = params.url;
2202
2203 // After setting the last committed origin, reset the feature policy and
2204 // sandbox flags in the RenderFrameHost to a blank policy based on the parent
2205 // frame.
2206 if (!is_same_document_navigation) {
2207 ResetFeaturePolicy();
2208 active_sandbox_flags_ = frame_tree_node()->active_sandbox_flags();
2209 document_policy_ = blink::DocumentPolicy::CreateWithHeaderPolicy({});
2210 }
2211
2212 // Reset the salt so that media device IDs are reset after the new navigation
2213 // if necessary.
2214 media_device_id_salt_base_ = BrowserContext::CreateRandomMediaDeviceIDSalt();
2215 }
2216
SetLastCommittedOrigin(const url::Origin & origin)2217 void RenderFrameHostImpl::SetLastCommittedOrigin(const url::Origin& origin) {
2218 last_committed_origin_ = origin;
2219 CSPContext::SetSelf(origin);
2220 }
2221
SetLastCommittedOriginForTesting(const url::Origin & origin)2222 void RenderFrameHostImpl::SetLastCommittedOriginForTesting(
2223 const url::Origin& origin) {
2224 SetLastCommittedOrigin(origin);
2225 }
2226
ComputeTopFrameOrigin(const url::Origin & frame_origin) const2227 const url::Origin& RenderFrameHostImpl::ComputeTopFrameOrigin(
2228 const url::Origin& frame_origin) const {
2229 if (frame_tree_node_->IsMainFrame()) {
2230 return frame_origin;
2231 }
2232
2233 DCHECK(parent_);
2234 // It's important to go through parent_ rather than via
2235 // frame_free_->root() here in case we're in process of being deleted, as the
2236 // latter might point to what our ancestor is being replaced with rather than
2237 // the actual ancestor.
2238 RenderFrameHostImpl* host = parent_;
2239 while (host->parent_) {
2240 host = host->parent_;
2241 }
2242 return host->GetLastCommittedOrigin();
2243 }
2244
ComputeSiteForCookiesForNavigation(const GURL & destination) const2245 net::SiteForCookies RenderFrameHostImpl::ComputeSiteForCookiesForNavigation(
2246 const GURL& destination) const {
2247 // For top-level navigation, |site_for_cookies| will always be the destination
2248 // URL.
2249 if (frame_tree_node_->IsMainFrame())
2250 return net::SiteForCookies::FromUrl(destination);
2251
2252 // Check if everything above the frame being navigated is consistent. It's OK
2253 // to skip checking the frame itself since it will be validated against
2254 // |site_for_cookies| anyway.
2255 return ComputeSiteForCookiesInternal(parent_,
2256 destination.SchemeIsCryptographic());
2257 }
2258
ComputeSiteForCookies()2259 net::SiteForCookies RenderFrameHostImpl::ComputeSiteForCookies() {
2260 return ComputeSiteForCookiesInternal(
2261 this, GetLastCommittedURL().SchemeIsCryptographic());
2262 }
2263
ComputeSiteForCookiesInternal(const RenderFrameHostImpl * render_frame_host,bool is_origin_secure) const2264 net::SiteForCookies RenderFrameHostImpl::ComputeSiteForCookiesInternal(
2265 const RenderFrameHostImpl* render_frame_host,
2266 bool is_origin_secure) const {
2267 #if defined(OS_ANDROID)
2268 // On Android, a base URL can be set for the frame. If this the case, it is
2269 // the URL to use for cookies.
2270 NavigationEntry* last_committed_entry =
2271 frame_tree_node_->navigator()->GetController()->GetLastCommittedEntry();
2272 if (last_committed_entry &&
2273 !last_committed_entry->GetBaseURLForDataURL().is_empty()) {
2274 return net::SiteForCookies::FromUrl(
2275 last_committed_entry->GetBaseURLForDataURL());
2276 }
2277 #endif
2278
2279 const url::Origin& top_document_origin =
2280 ComputeTopFrameOrigin(render_frame_host->last_committed_origin_);
2281 net::SiteForCookies candidate =
2282 net::SiteForCookies::FromOrigin(top_document_origin);
2283
2284 if (GetContentClient()
2285 ->browser()
2286 ->ShouldTreatURLSchemeAsFirstPartyWhenTopLevel(
2287 top_document_origin.scheme(), is_origin_secure)) {
2288 return candidate;
2289 }
2290
2291 // Make sure every ancestors are same-domain with the main document. Otherwise
2292 // this will be a 3rd party cookie.
2293 for (const RenderFrameHostImpl* rfh = render_frame_host; rfh;
2294 rfh = rfh->parent_) {
2295 if (!candidate.IsEquivalent(
2296 net::SiteForCookies::FromOrigin(rfh->last_committed_origin_))) {
2297 return net::SiteForCookies();
2298 }
2299 }
2300
2301 return candidate;
2302 }
2303
SetOriginAndNetworkIsolationKeyOfNewFrame(const url::Origin & new_frame_creator)2304 void RenderFrameHostImpl::SetOriginAndNetworkIsolationKeyOfNewFrame(
2305 const url::Origin& new_frame_creator) {
2306 // This method should only be called for *new* frames, that haven't committed
2307 // a navigation yet.
2308 DCHECK(!has_committed_any_navigation_);
2309 DCHECK(GetLastCommittedOrigin().opaque());
2310 DCHECK(network_isolation_key_.IsEmpty());
2311
2312 // Calculate and set |new_frame_origin|.
2313 bool new_frame_should_be_sandboxed =
2314 blink::mojom::WebSandboxFlags::kOrigin ==
2315 (frame_tree_node()->active_sandbox_flags() &
2316 blink::mojom::WebSandboxFlags::kOrigin);
2317 url::Origin new_frame_origin = new_frame_should_be_sandboxed
2318 ? new_frame_creator.DeriveNewOpaqueOrigin()
2319 : new_frame_creator;
2320 network_isolation_key_ = net::NetworkIsolationKey(
2321 ComputeTopFrameOrigin(new_frame_origin), new_frame_origin);
2322 SetLastCommittedOrigin(new_frame_origin);
2323 }
2324
AddChild(std::unique_ptr<FrameTreeNode> child,int process_id,int frame_routing_id)2325 FrameTreeNode* RenderFrameHostImpl::AddChild(
2326 std::unique_ptr<FrameTreeNode> child,
2327 int process_id,
2328 int frame_routing_id) {
2329 // Child frame must always be created in the same process as the parent.
2330 CHECK_EQ(process_id, GetProcess()->GetID());
2331
2332 // Initialize the RenderFrameHost for the new node. We always create child
2333 // frames in the same SiteInstance as the current frame, and they can swap to
2334 // a different one if they navigate away.
2335 child->render_manager()->InitChild(GetSiteInstance(), frame_routing_id);
2336
2337 // Other renderer processes in this BrowsingInstance may need to find out
2338 // about the new frame. Create a proxy for the child frame in all
2339 // SiteInstances that have a proxy for the frame's parent, since all frames
2340 // in a frame tree should have the same set of proxies.
2341 frame_tree_node_->render_manager()->CreateProxiesForChildFrame(child.get());
2342
2343 // When the child is added, it hasn't committed any navigation yet - its
2344 // initial empty document should inherit the origin and network isolation key
2345 // of its parent (the origin may change after the first commit). See also
2346 // https://crbug.com/932067.
2347 child->current_frame_host()->SetOriginAndNetworkIsolationKeyOfNewFrame(
2348 GetLastCommittedOrigin());
2349
2350 children_.push_back(std::move(child));
2351 return children_.back().get();
2352 }
2353
RemoveChild(FrameTreeNode * child)2354 void RenderFrameHostImpl::RemoveChild(FrameTreeNode* child) {
2355 for (auto iter = children_.begin(); iter != children_.end(); ++iter) {
2356 if (iter->get() == child) {
2357 // Subtle: we need to make sure the node is gone from the tree before
2358 // observers are notified of its deletion.
2359 std::unique_ptr<FrameTreeNode> node_to_delete(std::move(*iter));
2360 children_.erase(iter);
2361 node_to_delete->current_frame_host()->DeleteRenderFrame(
2362 FrameDeleteIntention::kNotMainFrame);
2363 // Speculative RenderFrameHosts are deleted by the FrameTreeNode's
2364 // RenderFrameHostManager's destructor. RenderFrameProxyHosts send
2365 // UnfreezableFrameMsg_Delete automatically in the destructor.
2366 // TODO(dcheng): This is horribly confusing. Refactor this logic so it's
2367 // more understandable.
2368 node_to_delete.reset();
2369 PendingDeletionCheckCompleted();
2370 return;
2371 }
2372 }
2373 }
2374
ResetChildren()2375 void RenderFrameHostImpl::ResetChildren() {
2376 // Remove child nodes from the tree, then delete them. This destruction
2377 // operation will notify observers. See https://crbug.com/612450 for
2378 // explanation why we don't just call the std::vector::clear method.
2379 std::vector<std::unique_ptr<FrameTreeNode>> children;
2380 children.swap(children_);
2381 // TODO(dcheng): Ideally, this would be done by messaging all the proxies of
2382 // this RenderFrameHostImpl to detach the current frame's children, rather
2383 // than messaging each child's current frame host...
2384 for (auto& child : children)
2385 child->current_frame_host()->DeleteRenderFrame(
2386 FrameDeleteIntention::kNotMainFrame);
2387 }
2388
SetLastCommittedUrl(const GURL & url)2389 void RenderFrameHostImpl::SetLastCommittedUrl(const GURL& url) {
2390 last_committed_url_ = url;
2391 }
2392
UpdateRenderProcessHostFramePriorities()2393 void RenderFrameHostImpl::UpdateRenderProcessHostFramePriorities() {
2394 const auto new_committed_document_priority =
2395 delegate_->IsFrameLowPriority(this)
2396 ? RenderProcessHostImpl::FramePriority::kLow
2397 : RenderProcessHostImpl::FramePriority::kNormal;
2398 if (last_committed_document_priority_ != new_committed_document_priority) {
2399 GetProcess()->UpdateFrameWithPriority(last_committed_document_priority_,
2400 new_committed_document_priority);
2401 last_committed_document_priority_ = new_committed_document_priority;
2402 }
2403 }
2404
OnDetach()2405 void RenderFrameHostImpl::OnDetach() {
2406 if (!parent_) {
2407 bad_message::ReceivedBadMessage(GetProcess(),
2408 bad_message::RFH_DETACH_MAIN_FRAME);
2409 return;
2410 }
2411
2412 // A frame is removed while replacing this document with the new one. When it
2413 // happens, delete the frame and both the new and old documents. Unload
2414 // handlers aren't guaranteed to run here.
2415 if (is_waiting_for_unload_ack_) {
2416 parent_->RemoveChild(frame_tree_node_);
2417 return;
2418 }
2419
2420 if (unload_state_ != UnloadState::NotRun) {
2421 // The frame is pending deletion. FrameHostMsg_Detach is used to confirm
2422 // its unload handlers ran.
2423 unload_state_ = UnloadState::Completed;
2424 PendingDeletionCheckCompleted(); // Can delete |this|.
2425 return;
2426 }
2427
2428 // This frame is being removed by the renderer, and it has already executed
2429 // its unload handler.
2430 unload_state_ = UnloadState::Completed;
2431 // Before completing the removal, we still need to wait for all of its
2432 // descendant frames to execute unload handlers. Start executing those
2433 // handlers now.
2434 StartPendingDeletionOnSubtree();
2435 frame_tree_node_->frame_tree()->FrameUnloading(frame_tree_node_);
2436
2437 // Some children with no unload handler may be eligible for immediate
2438 // deletion. Cut the dead branches now. This is a performance optimization.
2439 PendingDeletionCheckCompletedOnSubtree(); // Can delete |this|.
2440 }
2441
DidFailLoadWithError(const GURL & url,int32_t error_code)2442 void RenderFrameHostImpl::DidFailLoadWithError(const GURL& url,
2443 int32_t error_code) {
2444 TRACE_EVENT2("navigation", "RenderFrameHostImpl::DidFailLoadWithError",
2445 "frame_tree_node", frame_tree_node_->frame_tree_node_id(),
2446 "error", error_code);
2447
2448 GURL validated_url(url);
2449 GetProcess()->FilterURL(false, &validated_url);
2450
2451 frame_tree_node_->navigator()->DidFailLoadWithError(this, validated_url,
2452 error_code);
2453 }
2454
DidFocusFrame()2455 void RenderFrameHostImpl::DidFocusFrame() {
2456 if (!is_active())
2457 return;
2458
2459 // We need to handle receiving this IPC from a frame that is inside a portal
2460 // despite there being a renderer side check (see Document::IsFocusAllowed).
2461 // This is because the IPC to notify a page that it is inside a portal (see
2462 // WebContentsImpl::NotifyInsidePortal) may race with portal activation, and
2463 // we may run into a situation where a frame inside a portal doesn't know it's
2464 // inside a portal yet and allows focus.
2465 if (InsidePortal())
2466 return;
2467
2468 delegate_->SetFocusedFrame(frame_tree_node_, GetSiteInstance());
2469 }
2470
DidAddContentSecurityPolicies(std::vector<network::mojom::ContentSecurityPolicyPtr> policies)2471 void RenderFrameHostImpl::DidAddContentSecurityPolicies(
2472 std::vector<network::mojom::ContentSecurityPolicyPtr> policies) {
2473 TRACE_EVENT1("navigation",
2474 "RenderFrameHostImpl::OnDidAddContentSecurityPolicies",
2475 "frame_tree_node", frame_tree_node_->frame_tree_node_id());
2476
2477 std::vector<network::mojom::ContentSecurityPolicyHeaderPtr> headers;
2478 for (auto& policy : policies) {
2479 headers.push_back(policy->header.Clone());
2480 AddContentSecurityPolicy(std::move(policy));
2481 }
2482 frame_tree_node()->AddContentSecurityPolicies(std::move(headers));
2483 }
2484
OnOpenURL(const FrameHostMsg_OpenURL_Params & params)2485 void RenderFrameHostImpl::OnOpenURL(const FrameHostMsg_OpenURL_Params& params) {
2486 // Verify and unpack IPC payload.
2487 GURL validated_url;
2488 scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory;
2489 if (!VerifyOpenURLParams(GetSiteInstance(), params, &validated_url,
2490 &blob_url_loader_factory)) {
2491 return;
2492 }
2493
2494 TRACE_EVENT1("navigation", "RenderFrameHostImpl::OpenURL", "url",
2495 validated_url.possibly_invalid_spec());
2496
2497 frame_tree_node_->navigator()->RequestOpenURL(
2498 this, validated_url, params.initiator_origin, params.post_body,
2499 params.extra_headers, params.referrer, params.disposition,
2500 params.should_replace_current_entry, params.user_gesture,
2501 params.triggering_event_info, params.href_translate,
2502 std::move(blob_url_loader_factory));
2503 }
2504
CancelInitialHistoryLoad()2505 void RenderFrameHostImpl::CancelInitialHistoryLoad() {
2506 // A Javascript navigation interrupted the initial history load. Check if an
2507 // initial subframe cross-process navigation needs to be canceled as a result.
2508 // TODO(creis, clamy): Cancel any cross-process navigation.
2509 NOTIMPLEMENTED();
2510 }
2511
DidChangeActiveSchedulerTrackedFeatures(uint64_t features_mask)2512 void RenderFrameHostImpl::DidChangeActiveSchedulerTrackedFeatures(
2513 uint64_t features_mask) {
2514 renderer_reported_scheduler_tracked_features_ = features_mask;
2515
2516 MaybeEvictFromBackForwardCache();
2517 }
2518
OnSchedulerTrackedFeatureUsed(blink::scheduler::WebSchedulerTrackedFeature feature)2519 void RenderFrameHostImpl::OnSchedulerTrackedFeatureUsed(
2520 blink::scheduler::WebSchedulerTrackedFeature feature) {
2521 browser_reported_scheduler_tracked_features_ |=
2522 static_cast<uint64_t>(1) << static_cast<uint64_t>(feature);
2523
2524 MaybeEvictFromBackForwardCache();
2525 }
2526
IsFrozen()2527 bool RenderFrameHostImpl::IsFrozen() {
2528 return frame_lifecycle_state_ != blink::mojom::FrameLifecycleState::kRunning;
2529 }
2530
DidCommitProvisionalLoad(std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params> params,mojom::DidCommitProvisionalLoadInterfaceParamsPtr interface_params)2531 void RenderFrameHostImpl::DidCommitProvisionalLoad(
2532 std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params> params,
2533 mojom::DidCommitProvisionalLoadInterfaceParamsPtr interface_params) {
2534 if (MaybeInterceptCommitCallback(nullptr, params.get(), &interface_params)) {
2535 DidCommitNavigation(std::move(navigation_request_), std::move(params),
2536 std::move(interface_params));
2537 }
2538 }
2539
DidCommitBackForwardCacheNavigation(NavigationRequest * committing_navigation_request,std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params> params)2540 void RenderFrameHostImpl::DidCommitBackForwardCacheNavigation(
2541 NavigationRequest* committing_navigation_request,
2542 std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params> params) {
2543 auto request = navigation_requests_.find(committing_navigation_request);
2544 CHECK(request != navigation_requests_.end());
2545
2546 std::unique_ptr<NavigationRequest> owned_request = std::move(request->second);
2547 navigation_requests_.erase(committing_navigation_request);
2548
2549 // During a normal (uncached) navigation, is_loading_ is set to true in
2550 // CommitNavigation(). When navigating to a document in the BackForwardCache,
2551 // CommitNavigation() is never called, so we have to set is_loading_ to true
2552 // ourselves.
2553 //
2554 // If is_start_loading_ is set to false, DidCommitNavigationInternal will
2555 // re-fire the DidStartLoading event, which we don't want since it has already
2556 // been fired.
2557 is_loading_ = true;
2558
2559 DidCommitNavigationInternal(std::move(owned_request), std::move(params),
2560 /*is_same_document_navigation=*/false);
2561
2562 // The page is already loaded since it came from the cache, so fire the stop
2563 // loading event.
2564 OnDidStopLoading();
2565 }
2566
DidCommitPerNavigationMojoInterfaceNavigation(NavigationRequest * committing_navigation_request,std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params> params,mojom::DidCommitProvisionalLoadInterfaceParamsPtr interface_params)2567 void RenderFrameHostImpl::DidCommitPerNavigationMojoInterfaceNavigation(
2568 NavigationRequest* committing_navigation_request,
2569 std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params> params,
2570 mojom::DidCommitProvisionalLoadInterfaceParamsPtr interface_params) {
2571 DCHECK(committing_navigation_request);
2572 committing_navigation_request->IgnoreCommitInterfaceDisconnection();
2573 if (!MaybeInterceptCommitCallback(committing_navigation_request, params.get(),
2574 &interface_params)) {
2575 return;
2576 }
2577
2578 auto request = navigation_requests_.find(committing_navigation_request);
2579
2580 // The committing request should be in the map of NavigationRequests for
2581 // this RenderFrameHost.
2582 CHECK(request != navigation_requests_.end());
2583
2584 std::unique_ptr<NavigationRequest> owned_request = std::move(request->second);
2585 navigation_requests_.erase(committing_navigation_request);
2586 DidCommitNavigation(std::move(owned_request), std::move(params),
2587 std::move(interface_params));
2588 }
2589
DidCommitSameDocumentNavigation(std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params> params)2590 void RenderFrameHostImpl::DidCommitSameDocumentNavigation(
2591 std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params> params) {
2592 ScopedActiveURL scoped_active_url(
2593 params->url, frame_tree_node()->frame_tree()->root()->current_origin());
2594 ScopedCommitStateResetter commit_state_resetter(this);
2595
2596 // When the frame is pending deletion, the browser is waiting for it to unload
2597 // properly. In the meantime, because of race conditions, it might tries to
2598 // commit a same-document navigation before unloading. Similarly to what is
2599 // done with cross-document navigations, such navigation are ignored. The
2600 // browser already committed to destroying this RenderFrameHost.
2601 // See https://crbug.com/805705 and https://crbug.com/930132.
2602 // TODO(ahemery): Investigate to see if this can be removed when the
2603 // NavigationClient interface is implemented.
2604 if (!is_active())
2605 return;
2606
2607 TRACE_EVENT2("navigation",
2608 "RenderFrameHostImpl::DidCommitSameDocumentNavigation",
2609 "frame_tree_node", frame_tree_node_->frame_tree_node_id(), "url",
2610 params->url.possibly_invalid_spec());
2611
2612 // Check if the navigation matches a stored same-document NavigationRequest.
2613 // In that case it is browser-initiated.
2614 bool is_browser_initiated =
2615 same_document_navigation_request_ &&
2616 (same_document_navigation_request_->commit_params().navigation_token ==
2617 params->navigation_token);
2618 if (!DidCommitNavigationInternal(
2619 is_browser_initiated ? std::move(same_document_navigation_request_)
2620 : nullptr,
2621 std::move(params), true /* is_same_document_navigation*/)) {
2622 return;
2623 }
2624
2625 // Since we didn't early return, it's safe to keep the commit state.
2626 commit_state_resetter.disable();
2627 }
2628
OnUpdateState(const PageState & state)2629 void RenderFrameHostImpl::OnUpdateState(const PageState& state) {
2630 // TODO(creis): Verify the state's ISN matches the last committed FNE.
2631
2632 // Without this check, the renderer can trick the browser into using
2633 // filenames it can't access in a future session restore.
2634 if (!CanAccessFilesOfPageState(state)) {
2635 bad_message::ReceivedBadMessage(
2636 GetProcess(), bad_message::RFH_CAN_ACCESS_FILES_OF_PAGE_STATE);
2637 return;
2638 }
2639
2640 delegate_->UpdateStateForFrame(this, state);
2641 }
2642
GetRenderWidgetHost()2643 RenderWidgetHostImpl* RenderFrameHostImpl::GetRenderWidgetHost() {
2644 RenderFrameHostImpl* frame = this;
2645 while (frame) {
2646 if (frame->GetLocalRenderWidgetHost())
2647 return frame->GetLocalRenderWidgetHost();
2648 frame = frame->GetParent();
2649 }
2650
2651 NOTREACHED();
2652 return nullptr;
2653 }
2654
GetView()2655 RenderWidgetHostView* RenderFrameHostImpl::GetView() {
2656 return GetRenderWidgetHost()->GetView();
2657 }
2658
GetGlobalFrameRoutingId()2659 GlobalFrameRoutingId RenderFrameHostImpl::GetGlobalFrameRoutingId() {
2660 return GlobalFrameRoutingId(GetProcess()->GetID(), GetRoutingID());
2661 }
2662
HasPendingCommitNavigation() const2663 bool RenderFrameHostImpl::HasPendingCommitNavigation() const {
2664 return navigation_request_ || same_document_navigation_request_ ||
2665 !navigation_requests_.empty();
2666 }
2667
ResetNavigationRequests()2668 void RenderFrameHostImpl::ResetNavigationRequests() {
2669 navigation_request_.reset();
2670 same_document_navigation_request_.reset();
2671 navigation_requests_.clear();
2672 }
2673
SetNavigationRequest(std::unique_ptr<NavigationRequest> navigation_request)2674 void RenderFrameHostImpl::SetNavigationRequest(
2675 std::unique_ptr<NavigationRequest> navigation_request) {
2676 DCHECK(navigation_request);
2677 if (NavigationTypeUtils::IsSameDocument(
2678 navigation_request->common_params().navigation_type)) {
2679 same_document_navigation_request_ = std::move(navigation_request);
2680 return;
2681 }
2682 navigation_requests_[navigation_request.get()] =
2683 std::move(navigation_request);
2684 }
2685
Unload(RenderFrameProxyHost * proxy,bool is_loading)2686 void RenderFrameHostImpl::Unload(RenderFrameProxyHost* proxy, bool is_loading) {
2687 // The end of this event is in OnUnloadACK when the RenderFrame has completed
2688 // the operation and sends back an IPC message.
2689 TRACE_EVENT_ASYNC_BEGIN1("navigation", "RenderFrameHostImpl::Unload", this,
2690 "frame_tree_node",
2691 frame_tree_node_->frame_tree_node_id());
2692
2693 // If this RenderFrameHost is already pending deletion, it must have already
2694 // gone through this, therefore just return.
2695 if (unload_state_ != UnloadState::NotRun) {
2696 NOTREACHED() << "RFH should be in default state when calling Unload.";
2697 return;
2698 }
2699
2700 if (unload_event_monitor_timeout_ && !do_not_delete_for_testing_) {
2701 unload_event_monitor_timeout_->Start(base::TimeDelta::FromMilliseconds(
2702 RenderViewHostImpl::kUnloadTimeoutMS));
2703 }
2704
2705 // TODO(nasko): If the frame is not live, the RFH should just be deleted by
2706 // simulating the receipt of unload ack.
2707 is_waiting_for_unload_ack_ = true;
2708
2709 if (proxy) {
2710 unload_state_ = UnloadState::InProgress;
2711 if (IsRenderFrameLive()) {
2712 Send(new UnfreezableFrameMsg_Unload(
2713 routing_id_, proxy->GetRoutingID(), is_loading,
2714 proxy->frame_tree_node()->current_replication_state()));
2715 // Remember that a RenderFrameProxy was created as part of processing the
2716 // Unload message above.
2717 proxy->SetRenderFrameProxyCreated(true);
2718 }
2719 } else {
2720 // RenderDocument: After a local<->local swap, this function is called with
2721 // a null |proxy|.
2722 CHECK(CreateNewHostForSameSiteSubframe());
2723
2724 // The unload handlers already ran for this document during the
2725 // local<->local swap. Hence, there is no need to send
2726 // UnfreezableFrameMsg_Unload here. It can be marked at completed.
2727 unload_state_ = UnloadState::Completed;
2728 }
2729
2730 if (web_ui())
2731 web_ui()->RenderFrameHostUnloading();
2732
2733 web_bluetooth_services_.clear();
2734 #if !defined(OS_ANDROID)
2735 serial_service_.reset();
2736 #endif
2737
2738 StartPendingDeletionOnSubtree();
2739 // Some children with no unload handler may be eligible for deletion. Cut the
2740 // dead branches now. This is a performance optimization.
2741 PendingDeletionCheckCompletedOnSubtree();
2742 // |this| is potentially deleted. Do not add code after this.
2743 }
2744
DetachFromProxy()2745 void RenderFrameHostImpl::DetachFromProxy() {
2746 if (unload_state_ != UnloadState::NotRun)
2747 return;
2748
2749 // Start pending deletion on this frame and its children.
2750 DeleteRenderFrame(FrameDeleteIntention::kNotMainFrame);
2751 StartPendingDeletionOnSubtree();
2752 frame_tree_node_->frame_tree()->FrameUnloading(frame_tree_node_);
2753
2754 // Some children with no unload handler may be eligible for immediate
2755 // deletion. Cut the dead branches now. This is a performance optimization.
2756 PendingDeletionCheckCompletedOnSubtree(); // May delete |this|.
2757 }
2758
ProcessBeforeUnloadCompleted(bool proceed,bool treat_as_final_completion_callback,const base::TimeTicks & renderer_before_unload_start_time,const base::TimeTicks & renderer_before_unload_end_time)2759 void RenderFrameHostImpl::ProcessBeforeUnloadCompleted(
2760 bool proceed,
2761 bool treat_as_final_completion_callback,
2762 const base::TimeTicks& renderer_before_unload_start_time,
2763 const base::TimeTicks& renderer_before_unload_end_time) {
2764 TRACE_EVENT_ASYNC_END1("navigation", "RenderFrameHostImpl BeforeUnload", this,
2765 "FrameTreeNode id",
2766 frame_tree_node_->frame_tree_node_id());
2767 // If this renderer navigated while the beforeunload request was in flight, we
2768 // may have cleared this state in DidCommitProvisionalLoad, in which case we
2769 // can ignore this message.
2770 // However renderer might also be swapped out but we still want to proceed
2771 // with navigation, otherwise it would block future navigations. This can
2772 // happen when pending cross-site navigation is canceled by a second one just
2773 // before DidCommitProvisionalLoad while current RVH is waiting for commit
2774 // but second navigation is started from the beginning.
2775 RenderFrameHostImpl* initiator = GetBeforeUnloadInitiator();
2776 if (!initiator)
2777 return;
2778
2779 // Continue processing the ACK in the frame that triggered beforeunload in
2780 // this frame. This could be either this frame itself or an ancestor frame.
2781 initiator->ProcessBeforeUnloadCompletedFromFrame(
2782 proceed, treat_as_final_completion_callback, this,
2783 false /* is_frame_being_destroyed */, renderer_before_unload_start_time,
2784 renderer_before_unload_end_time);
2785 }
2786
GetBeforeUnloadInitiator()2787 RenderFrameHostImpl* RenderFrameHostImpl::GetBeforeUnloadInitiator() {
2788 for (RenderFrameHostImpl* frame = this; frame; frame = frame->GetParent()) {
2789 if (frame->is_waiting_for_beforeunload_completion_)
2790 return frame;
2791 }
2792 return nullptr;
2793 }
2794
ProcessBeforeUnloadCompletedFromFrame(bool proceed,bool treat_as_final_completion_callback,RenderFrameHostImpl * frame,bool is_frame_being_destroyed,const base::TimeTicks & renderer_before_unload_start_time,const base::TimeTicks & renderer_before_unload_end_time)2795 void RenderFrameHostImpl::ProcessBeforeUnloadCompletedFromFrame(
2796 bool proceed,
2797 bool treat_as_final_completion_callback,
2798 RenderFrameHostImpl* frame,
2799 bool is_frame_being_destroyed,
2800 const base::TimeTicks& renderer_before_unload_start_time,
2801 const base::TimeTicks& renderer_before_unload_end_time) {
2802 // Check if we need to wait for more beforeunload completion callbacks. If
2803 // |proceed| is false, we know the navigation or window close will be aborted,
2804 // so we don't need to wait for beforeunload completion callbacks from any
2805 // other frames. |treat_as_final_completion_callback| also indicates that we
2806 // shouldn't wait for any other ACKs (e.g., when a beforeunload timeout
2807 // fires).
2808 if (!proceed || treat_as_final_completion_callback) {
2809 beforeunload_pending_replies_.clear();
2810 } else {
2811 beforeunload_pending_replies_.erase(frame);
2812 if (!beforeunload_pending_replies_.empty())
2813 return;
2814 }
2815
2816 DCHECK(!send_before_unload_start_time_.is_null());
2817
2818 // Sets a default value for before_unload_end_time so that the browser
2819 // survives a hacked renderer.
2820 base::TimeTicks before_unload_end_time = renderer_before_unload_end_time;
2821 if (!renderer_before_unload_start_time.is_null() &&
2822 !renderer_before_unload_end_time.is_null()) {
2823 base::TimeTicks before_unload_completed_time = base::TimeTicks::Now();
2824
2825 if (!base::TimeTicks::IsConsistentAcrossProcesses()) {
2826 // TimeTicks is not consistent across processes and we are passing
2827 // TimeTicks across process boundaries so we need to compensate for any
2828 // skew between the processes. Here we are converting the renderer's
2829 // notion of before_unload_end_time to TimeTicks in the browser process.
2830 // See comments in inter_process_time_ticks_converter.h for more.
2831 InterProcessTimeTicksConverter converter(
2832 LocalTimeTicks::FromTimeTicks(send_before_unload_start_time_),
2833 LocalTimeTicks::FromTimeTicks(before_unload_completed_time),
2834 RemoteTimeTicks::FromTimeTicks(renderer_before_unload_start_time),
2835 RemoteTimeTicks::FromTimeTicks(renderer_before_unload_end_time));
2836 LocalTimeTicks browser_before_unload_end_time =
2837 converter.ToLocalTimeTicks(
2838 RemoteTimeTicks::FromTimeTicks(renderer_before_unload_end_time));
2839 before_unload_end_time = browser_before_unload_end_time.ToTimeTicks();
2840 }
2841
2842 base::TimeDelta on_before_unload_overhead_time =
2843 (before_unload_completed_time - send_before_unload_start_time_) -
2844 (renderer_before_unload_end_time - renderer_before_unload_start_time);
2845 UMA_HISTOGRAM_TIMES("Navigation.OnBeforeUnloadOverheadTime",
2846 on_before_unload_overhead_time);
2847
2848 frame_tree_node_->navigator()->LogBeforeUnloadTime(
2849 renderer_before_unload_start_time, renderer_before_unload_end_time);
2850 }
2851
2852 // Resets beforeunload waiting state.
2853 is_waiting_for_beforeunload_completion_ = false;
2854 has_shown_beforeunload_dialog_ = false;
2855 if (beforeunload_timeout_)
2856 beforeunload_timeout_->Stop();
2857 send_before_unload_start_time_ = base::TimeTicks();
2858
2859 // If the ACK is for a navigation, send it to the Navigator to have the
2860 // current navigation stop/proceed. Otherwise, send it to the
2861 // RenderFrameHostManager which handles closing.
2862 if (unload_ack_is_for_navigation_) {
2863 frame_tree_node_->navigator()->BeforeUnloadCompleted(
2864 frame_tree_node_, proceed, before_unload_end_time);
2865 } else {
2866 // We could reach this from a subframe destructor for |frame| while we're
2867 // in the middle of closing the current tab. In that case, dispatch the
2868 // ACK to prevent re-entrancy and a potential nested attempt to free the
2869 // current frame. See https://crbug.com/866382.
2870 base::OnceClosure task = base::BindOnce(
2871 [](base::WeakPtr<RenderFrameHostImpl> self,
2872 const base::TimeTicks& before_unload_end_time, bool proceed) {
2873 if (!self)
2874 return;
2875 self->frame_tree_node()->render_manager()->BeforeUnloadCompleted(
2876 proceed, before_unload_end_time);
2877 },
2878 weak_ptr_factory_.GetWeakPtr(), before_unload_end_time, proceed);
2879 if (is_frame_being_destroyed) {
2880 DCHECK(proceed);
2881 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, std::move(task));
2882 } else {
2883 std::move(task).Run();
2884 }
2885 }
2886
2887 // If canceled, notify the delegate to cancel its pending navigation entry.
2888 // This is usually redundant with the dialog closure code in WebContentsImpl's
2889 // OnDialogClosed, but there may be some cases that Blink returns !proceed
2890 // without showing the dialog. We also update the address bar here to be safe.
2891 if (!proceed)
2892 delegate_->DidCancelLoading();
2893 }
2894
IsWaitingForUnloadACK() const2895 bool RenderFrameHostImpl::IsWaitingForUnloadACK() const {
2896 return render_view_host_->is_waiting_for_page_close_completion_ ||
2897 is_waiting_for_unload_ack_;
2898 }
2899
BeforeUnloadTimedOut() const2900 bool RenderFrameHostImpl::BeforeUnloadTimedOut() const {
2901 return beforeunload_timeout_ &&
2902 (send_before_unload_start_time_ != base::TimeTicks()) &&
2903 (base::TimeTicks::Now() - send_before_unload_start_time_) >
2904 beforeunload_timeout_delay_;
2905 }
2906
OnUnloadACK()2907 void RenderFrameHostImpl::OnUnloadACK() {
2908 if (frame_tree_node_->render_manager()->is_attaching_inner_delegate()) {
2909 // This RFH was unloaded while attaching an inner delegate. The RFH
2910 // will stay around but it will no longer be associated with a RenderFrame.
2911 SetRenderFrameCreated(false);
2912 return;
2913 }
2914
2915 // Ignore spurious unload ack.
2916 if (!is_waiting_for_unload_ack_)
2917 return;
2918
2919 // Ignore OnUnloadACK if the RenderFrameHost should be left in pending
2920 // deletion state.
2921 if (do_not_delete_for_testing_)
2922 return;
2923
2924 DCHECK_EQ(UnloadState::InProgress, unload_state_);
2925 unload_state_ = UnloadState::Completed;
2926 PendingDeletionCheckCompleted(); // Can delete |this|.
2927 }
2928
OnUnloaded()2929 void RenderFrameHostImpl::OnUnloaded() {
2930 DCHECK(is_waiting_for_unload_ack_);
2931
2932 TRACE_EVENT_ASYNC_END0("navigation", "RenderFrameHostImpl::Unload", this);
2933 if (unload_event_monitor_timeout_)
2934 unload_event_monitor_timeout_->Stop();
2935
2936 ClearWebUI();
2937
2938 bool deleted =
2939 frame_tree_node_->render_manager()->DeleteFromPendingList(this);
2940 CHECK(deleted);
2941 }
2942
DisableUnloadTimerForTesting()2943 void RenderFrameHostImpl::DisableUnloadTimerForTesting() {
2944 unload_event_monitor_timeout_.reset();
2945 }
2946
SetSubframeUnloadTimeoutForTesting(const base::TimeDelta & timeout)2947 void RenderFrameHostImpl::SetSubframeUnloadTimeoutForTesting(
2948 const base::TimeDelta& timeout) {
2949 subframe_unload_timeout_ = timeout;
2950 }
2951
OnContextMenu(const UntrustworthyContextMenuParams & params)2952 void RenderFrameHostImpl::OnContextMenu(
2953 const UntrustworthyContextMenuParams& params) {
2954 if (!is_active())
2955 return;
2956
2957 // Validate the URLs in |params|. If the renderer can't request the URLs
2958 // directly, don't show them in the context menu.
2959 ContextMenuParams validated_params(params);
2960 validated_params.frame_url = GetLastCommittedURL();
2961 validated_params.page_url = GetMainFrame()->GetLastCommittedURL();
2962
2963 // We don't validate |unfiltered_link_url| so that this field can be used
2964 // when users want to copy the original link URL.
2965 RenderProcessHost* process = GetProcess();
2966 process->FilterURL(true, &validated_params.link_url);
2967 process->FilterURL(true, &validated_params.src_url);
2968 process->FilterURL(false, &validated_params.page_url);
2969 process->FilterURL(true, &validated_params.frame_url);
2970
2971 // It is necessary to transform the coordinates to account for nested
2972 // RenderWidgetHosts, such as with out-of-process iframes.
2973 gfx::Point original_point(validated_params.x, validated_params.y);
2974 gfx::Point transformed_point =
2975 static_cast<RenderWidgetHostViewBase*>(GetView())
2976 ->TransformPointToRootCoordSpace(original_point);
2977 validated_params.x = transformed_point.x();
2978 validated_params.y = transformed_point.y();
2979
2980 if (validated_params.selection_start_offset < 0) {
2981 bad_message::ReceivedBadMessage(
2982 GetProcess(), bad_message::RFH_NEGATIVE_SELECTION_START_OFFSET);
2983 }
2984
2985 delegate_->ShowContextMenu(this, validated_params);
2986 }
2987
2988 #if defined(OS_ANDROID)
RequestSmartClipExtract(ExtractSmartClipDataCallback callback,gfx::Rect rect)2989 void RenderFrameHostImpl::RequestSmartClipExtract(
2990 ExtractSmartClipDataCallback callback,
2991 gfx::Rect rect) {
2992 int32_t callback_id = smart_clip_callbacks_.Add(
2993 std::make_unique<ExtractSmartClipDataCallback>(std::move(callback)));
2994 frame_->ExtractSmartClipData(
2995 rect, base::BindOnce(&RenderFrameHostImpl::OnSmartClipDataExtracted,
2996 base::Unretained(this), callback_id));
2997 }
2998
OnSmartClipDataExtracted(int32_t callback_id,const base::string16 & text,const base::string16 & html,const gfx::Rect & clip_rect)2999 void RenderFrameHostImpl::OnSmartClipDataExtracted(int32_t callback_id,
3000 const base::string16& text,
3001 const base::string16& html,
3002 const gfx::Rect& clip_rect) {
3003 std::move(*smart_clip_callbacks_.Lookup(callback_id))
3004 .Run(text, html, clip_rect);
3005 smart_clip_callbacks_.Remove(callback_id);
3006 }
3007 #endif // defined(OS_ANDROID)
3008
OnVisualStateResponse(uint64_t id)3009 void RenderFrameHostImpl::OnVisualStateResponse(uint64_t id) {
3010 auto it = visual_state_callbacks_.find(id);
3011 if (it != visual_state_callbacks_.end()) {
3012 std::move(it->second).Run(true);
3013 visual_state_callbacks_.erase(it);
3014 } else {
3015 NOTREACHED() << "Received script response for unknown request";
3016 }
3017 }
3018
RunModalAlertDialog(const base::string16 & alert_message,RunModalAlertDialogCallback response_callback)3019 void RenderFrameHostImpl::RunModalAlertDialog(
3020 const base::string16& alert_message,
3021 RunModalAlertDialogCallback response_callback) {
3022 auto dialog_closed_callback = base::BindOnce(
3023 [](RunModalAlertDialogCallback response_callback, bool success,
3024 const base::string16& response) {
3025 // The response string is unused but we use a generic mechanism for
3026 // closing the javascript dialog that returns two arguments.
3027 std::move(response_callback).Run();
3028 },
3029 std::move(response_callback));
3030 RunJavaScriptDialog(alert_message, base::string16(),
3031 JAVASCRIPT_DIALOG_TYPE_ALERT,
3032 std::move(dialog_closed_callback));
3033 }
3034
RunModalConfirmDialog(const base::string16 & alert_message,RunModalConfirmDialogCallback response_callback)3035 void RenderFrameHostImpl::RunModalConfirmDialog(
3036 const base::string16& alert_message,
3037 RunModalConfirmDialogCallback response_callback) {
3038 auto dialog_closed_callback = base::BindOnce(
3039 [](RunModalConfirmDialogCallback response_callback, bool success,
3040 const base::string16& response) {
3041 // The response string is unused but we use a generic mechanism for
3042 // closing the javascript dialog that returns two arguments.
3043 std::move(response_callback).Run(success);
3044 },
3045 std::move(response_callback));
3046 RunJavaScriptDialog(alert_message, base::string16(),
3047 JAVASCRIPT_DIALOG_TYPE_CONFIRM,
3048 std::move(dialog_closed_callback));
3049 }
3050
RunModalPromptDialog(const base::string16 & alert_message,const base::string16 & default_value,RunModalPromptDialogCallback response_callback)3051 void RenderFrameHostImpl::RunModalPromptDialog(
3052 const base::string16& alert_message,
3053 const base::string16& default_value,
3054 RunModalPromptDialogCallback response_callback) {
3055 RunJavaScriptDialog(alert_message, default_value,
3056 JAVASCRIPT_DIALOG_TYPE_PROMPT,
3057 std::move(response_callback));
3058 }
3059
RunJavaScriptDialog(const base::string16 & message,const base::string16 & default_prompt,JavaScriptDialogType dialog_type,JavaScriptDialogCallback ipc_response_callback)3060 void RenderFrameHostImpl::RunJavaScriptDialog(
3061 const base::string16& message,
3062 const base::string16& default_prompt,
3063 JavaScriptDialogType dialog_type,
3064 JavaScriptDialogCallback ipc_response_callback) {
3065 // Don't show the dialog if it's triggered on a frame that's pending deletion
3066 // (e.g., from an unload handler), or when the tab is being closed.
3067 if (!is_active()) {
3068 std::move(ipc_response_callback).Run(true, base::string16());
3069 return;
3070 }
3071
3072 // While a JS message dialog is showing, tabs in the same process shouldn't
3073 // process input events.
3074 GetProcess()->SetBlocked(true);
3075
3076 delegate_->RunJavaScriptDialog(
3077 this, message, default_prompt, dialog_type,
3078 base::BindOnce(&RenderFrameHostImpl::JavaScriptDialogClosed,
3079 weak_ptr_factory_.GetWeakPtr(),
3080 std::move(ipc_response_callback)));
3081 }
3082
RunBeforeUnloadConfirm(bool is_reload,RunBeforeUnloadConfirmCallback ipc_response_callback)3083 void RenderFrameHostImpl::RunBeforeUnloadConfirm(
3084 bool is_reload,
3085 RunBeforeUnloadConfirmCallback ipc_response_callback) {
3086 TRACE_EVENT1("navigation", "RenderFrameHostImpl::OnRunBeforeUnloadConfirm",
3087 "frame_tree_node", frame_tree_node_->frame_tree_node_id());
3088
3089 // Allow at most one attempt to show a beforeunload dialog per navigation.
3090 RenderFrameHostImpl* beforeunload_initiator = GetBeforeUnloadInitiator();
3091 if (beforeunload_initiator) {
3092 // If the running beforeunload handler wants to display a dialog and the
3093 // before-unload type wants to ignore it, then short-circuit the request and
3094 // respond as if the user decided to stay on the page, canceling the unload.
3095 if (beforeunload_initiator->beforeunload_dialog_request_cancels_unload_) {
3096 std::move(ipc_response_callback).Run(/*success=*/false);
3097 return;
3098 }
3099
3100 if (beforeunload_initiator->has_shown_beforeunload_dialog_) {
3101 // TODO(alexmos): Pass enough data back to renderer to record histograms
3102 // for Document.BeforeUnloadDialog and add the intervention console
3103 // message to match renderer-side behavior in
3104 // Document::DispatchBeforeUnloadEvent().
3105 std::move(ipc_response_callback).Run(/*success=*/true);
3106 return;
3107 }
3108 beforeunload_initiator->has_shown_beforeunload_dialog_ = true;
3109 } else {
3110 // TODO(alexmos): If a renderer-initiated beforeunload shows a dialog, it
3111 // won't find a |beforeunload_initiator|. This can happen for a
3112 // renderer-initiated navigation or window.close(). We should ensure that
3113 // when the browser process later kicks off subframe unload handlers (if
3114 // any), they won't be able to show additional dialogs. However, we can't
3115 // just set |has_shown_beforeunload_dialog_| because we don't know which
3116 // frame is navigating/closing here. Plumb enough information here to fix
3117 // this.
3118 }
3119
3120 // While a JS beforeunload dialog is showing, tabs in the same process
3121 // shouldn't process input events.
3122 GetProcess()->SetBlocked(true);
3123
3124 // The beforeunload dialog for this frame may have been triggered by a
3125 // browser-side request to this frame or a frame up in the frame hierarchy.
3126 // Stop any timers that are waiting.
3127 for (RenderFrameHostImpl* frame = this; frame; frame = frame->GetParent()) {
3128 if (frame->beforeunload_timeout_)
3129 frame->beforeunload_timeout_->Stop();
3130 }
3131
3132 auto ipc_callback_wrapper = base::BindOnce(
3133 [](RunBeforeUnloadConfirmCallback response_callback, bool success,
3134 const base::string16& response) {
3135 // The response string is unused but we use a generic mechanism for
3136 // closing the javascript dialog that returns two arguments.
3137 std::move(response_callback).Run(success);
3138 },
3139 std::move(ipc_response_callback));
3140 auto dialog_closed_callback = base::BindOnce(
3141 &RenderFrameHostImpl::JavaScriptDialogClosed,
3142 weak_ptr_factory_.GetWeakPtr(), std::move(ipc_callback_wrapper));
3143
3144 delegate_->RunBeforeUnloadConfirm(this, is_reload,
3145 std::move(dialog_closed_callback));
3146 }
3147
Are3DAPIsBlocked(Are3DAPIsBlockedCallback callback)3148 void RenderFrameHostImpl::Are3DAPIsBlocked(Are3DAPIsBlockedCallback callback) {
3149 bool blocked = GpuDataManagerImpl::GetInstance()->Are3DAPIsBlocked(
3150 GetMainFrame()->GetLastCommittedURL(), GetProcess()->GetID(),
3151 GetRoutingID(), THREE_D_API_TYPE_WEBGL);
3152 std::move(callback).Run(blocked);
3153 }
3154
ScaleFactorChanged(float scale)3155 void RenderFrameHostImpl::ScaleFactorChanged(float scale) {
3156 delegate_->OnPageScaleFactorChanged(this, scale);
3157 }
3158
ContentsPreferredSizeChanged(const gfx::Size & pref_size)3159 void RenderFrameHostImpl::ContentsPreferredSizeChanged(
3160 const gfx::Size& pref_size) {
3161 render_view_host_->OnDidContentsPreferredSizeChange(pref_size);
3162 }
3163
UpdateFaviconURL(std::vector<blink::mojom::FaviconURLPtr> favicon_urls)3164 void RenderFrameHostImpl::UpdateFaviconURL(
3165 std::vector<blink::mojom::FaviconURLPtr> favicon_urls) {
3166 delegate_->UpdateFaviconURL(this, std::move(favicon_urls));
3167 }
3168
DownloadURL(blink::mojom::DownloadURLParamsPtr blink_parameters)3169 void RenderFrameHostImpl::DownloadURL(
3170 blink::mojom::DownloadURLParamsPtr blink_parameters) {
3171 mojo::PendingRemote<blink::mojom::BlobURLToken> blob_url_token;
3172 if (!VerifyDownloadUrlParams(GetSiteInstance(), blink_parameters.get(),
3173 &blob_url_token))
3174 return;
3175
3176 mojo::PendingRemote<blink::mojom::Blob> blob_data_remote(
3177 std::move(blink_parameters->data_url_blob), blink::mojom::Blob::Version_);
3178
3179 net::NetworkTrafficAnnotationTag traffic_annotation =
3180 net::DefineNetworkTrafficAnnotation("renderer_initiated_download", R"(
3181 semantics {
3182 sender: "Download from Renderer"
3183 description:
3184 "The frame has either navigated to a URL that was determined to be "
3185 "a download via one of the renderer's classification mechanisms, "
3186 "or WebView has requested a <canvas> or <img> element at a "
3187 "specific location be to downloaded."
3188 trigger:
3189 "The user navigated to a destination that was categorized as a "
3190 "download, or WebView triggered saving a <canvas> or <img> tag."
3191 data: "Only the URL we are attempting to download."
3192 destination: WEBSITE
3193 }
3194 policy {
3195 cookies_allowed: YES
3196 cookies_store: "user"
3197 setting: "This feature cannot be disabled by settings."
3198 chrome_policy {
3199 DownloadRestrictions {
3200 DownloadRestrictions: 3
3201 }
3202 }
3203 })");
3204 std::unique_ptr<download::DownloadUrlParameters> parameters(
3205 new download::DownloadUrlParameters(blink_parameters->url,
3206 GetProcess()->GetID(),
3207 GetRenderViewHost()->GetRoutingID(),
3208 GetRoutingID(), traffic_annotation));
3209 parameters->set_content_initiated(true);
3210 parameters->set_suggested_name(
3211 blink_parameters->suggested_name.value_or(base::string16()));
3212 parameters->set_prompt(false);
3213 parameters->set_cross_origin_redirects(
3214 blink_parameters->cross_origin_redirects);
3215 parameters->set_referrer(
3216 blink_parameters->referrer ? blink_parameters->referrer->url : GURL());
3217 parameters->set_referrer_policy(Referrer::ReferrerPolicyForUrlRequest(
3218 blink_parameters->referrer ? blink_parameters->referrer->policy
3219 : network::mojom::ReferrerPolicy::kDefault));
3220 parameters->set_initiator(
3221 blink_parameters->initiator_origin.value_or(url::Origin()));
3222 parameters->set_download_source(download::DownloadSource::FROM_RENDERER);
3223
3224 if (blob_data_remote) {
3225 DataURLBlobReader::ReadDataURLFromBlob(
3226 std::move(blob_data_remote),
3227 base::BindOnce(&OnDataURLRetrieved, std::move(parameters)));
3228 return;
3229 }
3230
3231 StartDownload(std::move(parameters), std::move(blob_url_token));
3232 }
3233
3234 void RenderFrameHostImpl::ReportNoBinderForInterface(const std::string& error) {
3235 broker_receiver_.ReportBadMessage(error + " for the frame/document scope");
3236 }
3237
3238 void RenderFrameHostImpl::RequestTextSurroundingSelection(
3239 blink::mojom::LocalFrame::GetTextSurroundingSelectionCallback callback,
3240 int max_length) {
3241 DCHECK(!callback.is_null());
3242 GetAssociatedLocalFrame()->GetTextSurroundingSelection(max_length,
3243 std::move(callback));
3244 }
3245
3246 void RenderFrameHostImpl::SendInterventionReport(const std::string& id,
3247 const std::string& message) {
3248 GetAssociatedLocalFrame()->SendInterventionReport(id, message);
3249 }
3250
3251 void RenderFrameHostImpl::AllowBindings(int bindings_flags) {
3252 // Never grant any bindings to browser plugin guests.
3253 if (GetProcess()->IsForGuestsOnly()) {
3254 NOTREACHED() << "Never grant bindings to a guest process.";
3255 return;
3256 }
3257 TRACE_EVENT2("navigation", "RenderFrameHostImpl::AllowBindings",
3258 "frame_tree_node", frame_tree_node_->frame_tree_node_id(),
3259 "bindings flags", bindings_flags);
3260
3261 int webui_bindings = bindings_flags & kWebUIBindingsPolicyMask;
3262
3263 // TODO(nasko): Ensure callers that specify non-zero WebUI bindings are
3264 // doing so on a RenderFrameHost that has WebUI associated with it.
3265
3266 // The bindings being granted here should not differ from the bindings that
3267 // the associated WebUI requires.
3268 if (web_ui_)
3269 CHECK_EQ(web_ui_->GetBindings(), webui_bindings);
3270
3271 // Ensure we aren't granting WebUI bindings to a process that has already
3272 // been used for non-privileged views.
3273 if (webui_bindings && GetProcess()->IsInitializedAndNotDead() &&
3274 !ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
3275 GetProcess()->GetID())) {
3276 // This process has no bindings yet. Make sure it does not have more
3277 // than this single active view.
3278 // --single-process only has one renderer.
3279 if (GetProcess()->GetActiveViewCount() > 1 &&
3280 !base::CommandLine::ForCurrentProcess()->HasSwitch(
3281 switches::kSingleProcess))
3282 return;
3283 }
3284
3285 if (webui_bindings) {
3286 ChildProcessSecurityPolicyImpl::GetInstance()->GrantWebUIBindings(
3287 GetProcess()->GetID(), webui_bindings);
3288 }
3289
3290 enabled_bindings_ |= bindings_flags;
3291
3292 if (render_frame_created_) {
3293 if (!frame_bindings_control_)
3294 GetRemoteAssociatedInterfaces()->GetInterface(&frame_bindings_control_);
3295 frame_bindings_control_->AllowBindings(enabled_bindings_);
3296 }
3297 }
3298
GetEnabledBindings()3299 int RenderFrameHostImpl::GetEnabledBindings() {
3300 return enabled_bindings_;
3301 }
3302
SetWebUIProperty(const std::string & name,const std::string & value)3303 void RenderFrameHostImpl::SetWebUIProperty(const std::string& name,
3304 const std::string& value) {
3305 // This is a sanity check before telling the renderer to enable the property.
3306 // It could lie and send the corresponding IPC messages anyway, but we will
3307 // not act on them if enabled_bindings_ doesn't agree. If we get here without
3308 // WebUI bindings, terminate the renderer process.
3309 if (enabled_bindings_ & BINDINGS_POLICY_WEB_UI)
3310 Send(new FrameMsg_SetWebUIProperty(routing_id_, name, value));
3311 else
3312 ReceivedBadMessage(GetProcess(), bad_message::RVH_WEB_UI_BINDINGS_MISMATCH);
3313 }
3314
DisableBeforeUnloadHangMonitorForTesting()3315 void RenderFrameHostImpl::DisableBeforeUnloadHangMonitorForTesting() {
3316 beforeunload_timeout_.reset();
3317 }
3318
IsBeforeUnloadHangMonitorDisabledForTesting()3319 bool RenderFrameHostImpl::IsBeforeUnloadHangMonitorDisabledForTesting() {
3320 return !beforeunload_timeout_;
3321 }
3322
DoNotDeleteForTesting()3323 void RenderFrameHostImpl::DoNotDeleteForTesting() {
3324 do_not_delete_for_testing_ = true;
3325 }
3326
IsFeatureEnabled(blink::mojom::FeaturePolicyFeature feature)3327 bool RenderFrameHostImpl::IsFeatureEnabled(
3328 blink::mojom::FeaturePolicyFeature feature) {
3329 blink::mojom::PolicyValueType feature_type =
3330 feature_policy_->GetFeatureList().at(feature).second;
3331 return IsFeatureEnabled(
3332 feature, blink::PolicyValue::CreateMaxPolicyValue(feature_type));
3333 }
3334
IsFeatureEnabled(blink::mojom::FeaturePolicyFeature feature,blink::PolicyValue threshold_value)3335 bool RenderFrameHostImpl::IsFeatureEnabled(
3336 blink::mojom::FeaturePolicyFeature feature,
3337 blink::PolicyValue threshold_value) {
3338 return feature_policy_ &&
3339 feature_policy_->IsFeatureEnabledForOrigin(
3340 feature, GetLastCommittedOrigin(), threshold_value);
3341 }
3342
IsFeatureEnabled(blink::mojom::DocumentPolicyFeature feature)3343 bool RenderFrameHostImpl::IsFeatureEnabled(
3344 blink::mojom::DocumentPolicyFeature feature) {
3345 blink::mojom::PolicyValueType feature_type =
3346 blink::GetDocumentPolicyFeatureInfoMap().at(feature).default_value.Type();
3347 return IsFeatureEnabled(
3348 feature, blink::PolicyValue::CreateMaxPolicyValue(feature_type));
3349 }
3350
IsFeatureEnabled(blink::mojom::DocumentPolicyFeature feature,blink::PolicyValue threshold_value)3351 bool RenderFrameHostImpl::IsFeatureEnabled(
3352 blink::mojom::DocumentPolicyFeature feature,
3353 blink::PolicyValue threshold_value) {
3354 return document_policy_ &&
3355 document_policy_->IsFeatureEnabled(feature, threshold_value);
3356 }
3357
ViewSource()3358 void RenderFrameHostImpl::ViewSource() {
3359 delegate_->ViewSource(this);
3360 }
3361
FlushNetworkAndNavigationInterfacesForTesting()3362 void RenderFrameHostImpl::FlushNetworkAndNavigationInterfacesForTesting() {
3363 DCHECK(network_service_disconnect_handler_holder_);
3364 network_service_disconnect_handler_holder_.FlushForTesting();
3365
3366 if (!navigation_control_)
3367 GetNavigationControl();
3368 DCHECK(navigation_control_);
3369 navigation_control_.FlushForTesting();
3370 }
3371
PrepareForInnerWebContentsAttach(PrepareForInnerWebContentsAttachCallback callback)3372 void RenderFrameHostImpl::PrepareForInnerWebContentsAttach(
3373 PrepareForInnerWebContentsAttachCallback callback) {
3374 frame_tree_node_->render_manager()->PrepareForInnerDelegateAttach(
3375 std::move(callback));
3376 }
3377
UpdateSubresourceLoaderFactories()3378 void RenderFrameHostImpl::UpdateSubresourceLoaderFactories() {
3379 // We only send loader factory bundle upon navigation, so
3380 // bail out if the frame hasn't committed any yet.
3381 if (!has_committed_any_navigation_)
3382 return;
3383 DCHECK(!IsOutOfProcessNetworkService() ||
3384 network_service_disconnect_handler_holder_.is_bound());
3385
3386 // We use the last committed Origin and ClientSecurityState. If the caller
3387 // wanted a factory associated to a navigation about to commit, the params
3388 // generated won't be correct. There is no good way of fixing this before
3389 // RenderDocumentHost (ie swapping RenderFrameHost on each navigation).
3390 mojo::PendingRemote<network::mojom::URLLoaderFactory> default_factory_remote;
3391 bool bypass_redirect_checks = false;
3392 if (recreate_default_url_loader_factory_after_network_service_crash_) {
3393 mojo::PendingRemote<network::mojom::CrossOriginEmbedderPolicyReporter>
3394 coep_reporter_remote;
3395 if (coep_reporter_) {
3396 coep_reporter_->Clone(
3397 coep_reporter_remote.InitWithNewPipeAndPassReceiver());
3398 }
3399 bypass_redirect_checks = CreateNetworkServiceDefaultFactoryAndObserve(
3400 CreateURLLoaderFactoryParamsForMainWorld(
3401 last_committed_origin_,
3402 mojo::Clone(last_committed_client_security_state_),
3403 std::move(coep_reporter_remote)),
3404 default_factory_remote.InitWithNewPipeAndPassReceiver());
3405 }
3406
3407 std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
3408 subresource_loader_factories =
3409 std::make_unique<blink::PendingURLLoaderFactoryBundle>(
3410 std::move(default_factory_remote),
3411 blink::PendingURLLoaderFactoryBundle::SchemeMap(),
3412 CreateURLLoaderFactoriesForIsolatedWorlds(
3413 GetExpectedMainWorldOriginForUrlLoaderFactory(),
3414 isolated_worlds_requiring_separate_url_loader_factory_,
3415 mojo::Clone(last_committed_client_security_state_)),
3416 bypass_redirect_checks);
3417 GetNavigationControl()->UpdateSubresourceLoaderFactories(
3418 std::move(subresource_loader_factories));
3419 }
3420
GetFrameOwnerElementType()3421 blink::FrameOwnerElementType RenderFrameHostImpl::GetFrameOwnerElementType() {
3422 return frame_tree_node_->frame_owner_element_type();
3423 }
3424
HasTransientUserActivation()3425 bool RenderFrameHostImpl::HasTransientUserActivation() {
3426 return frame_tree_node_->HasTransientUserActivation();
3427 }
3428
DidAccessInitialDocument()3429 void RenderFrameHostImpl::DidAccessInitialDocument() {
3430 delegate_->DidAccessInitialDocument();
3431 }
3432
OnDidChangeOpener(int32_t opener_routing_id)3433 void RenderFrameHostImpl::OnDidChangeOpener(int32_t opener_routing_id) {
3434 frame_tree_node_->render_manager()->DidChangeOpener(opener_routing_id,
3435 GetSiteInstance());
3436 }
3437
DidChangeName(const std::string & name,const std::string & unique_name)3438 void RenderFrameHostImpl::DidChangeName(const std::string& name,
3439 const std::string& unique_name) {
3440 if (GetParent() != nullptr) {
3441 // TODO(lukasza): Call ReceivedBadMessage when |unique_name| is empty.
3442 DCHECK(!unique_name.empty());
3443 }
3444 TRACE_EVENT2("navigation", "RenderFrameHostImpl::OnDidChangeName",
3445 "frame_tree_node", frame_tree_node_->frame_tree_node_id(),
3446 "name length", name.length());
3447
3448 std::string old_name = frame_tree_node()->frame_name();
3449 frame_tree_node()->SetFrameName(name, unique_name);
3450 if (old_name.empty() && !name.empty())
3451 frame_tree_node_->render_manager()->CreateProxiesForNewNamedFrame();
3452 delegate_->DidChangeName(this, name);
3453 }
3454
DidSetFramePolicyHeaders(blink::mojom::WebSandboxFlags sandbox_flags,const blink::ParsedFeaturePolicy & feature_policy_header,const blink::DocumentPolicy::FeatureState & document_policy_header)3455 void RenderFrameHostImpl::DidSetFramePolicyHeaders(
3456 blink::mojom::WebSandboxFlags sandbox_flags,
3457 const blink::ParsedFeaturePolicy& feature_policy_header,
3458 const blink::DocumentPolicy::FeatureState& document_policy_header) {
3459 if (!is_active())
3460 return;
3461 // Rebuild |feature_policy_| for this frame.
3462 ResetFeaturePolicy();
3463 feature_policy_->SetHeaderPolicy(feature_policy_header);
3464
3465 // Rebuild |document_policy_| for this frame.
3466 // Note: document_policy_header is the document policy state used to
3467 // initialize |document_policy_| in SecurityContext on renderer side. It is
3468 // supposed to be compatible with required_document_policy. If not, kill the
3469 // renderer.
3470 if (blink::DocumentPolicy::IsPolicyCompatible(
3471 frame_tree_node()->effective_frame_policy().required_document_policy,
3472 document_policy_header)) {
3473 document_policy_ = blink::DocumentPolicy::CreateWithHeaderPolicy(
3474 {document_policy_header, {} /* endpoint_map */});
3475 } else {
3476 bad_message::ReceivedBadMessage(
3477 GetProcess(), bad_message::RFH_BAD_DOCUMENT_POLICY_HEADER);
3478 return;
3479 }
3480
3481 // Update the feature policy and sandbox flags in the frame tree. This will
3482 // send any updates to proxies if necessary.
3483 //
3484 // Feature policy's inheritance from parent frame's feature policy is through
3485 // accessing parent frame's security context(either remote or local) when
3486 // initializing child's security context, so the update to proxies is needed.
3487 //
3488 // Document policy's inheritance from parent frame's required document policy
3489 // is done at |HTMLFrameOwnerElement::UpdateRequiredPolicy|. Parent frame owns
3490 // both parent required document policy and child frame's frame owner element
3491 // which contains child's required document policy, so there is no need to
3492 // store required document policy in proxies.
3493 frame_tree_node()->UpdateFramePolicyHeaders(sandbox_flags,
3494 feature_policy_header);
3495
3496 // Save a copy of the now-active sandbox flags on this RFHI.
3497 active_sandbox_flags_ = frame_tree_node()->active_sandbox_flags();
3498 }
3499
EnforceInsecureRequestPolicy(blink::mojom::InsecureRequestPolicy policy)3500 void RenderFrameHostImpl::EnforceInsecureRequestPolicy(
3501 blink::mojom::InsecureRequestPolicy policy) {
3502 frame_tree_node()->SetInsecureRequestPolicy(policy);
3503 }
3504
EnforceInsecureNavigationsSet(const std::vector<uint32_t> & set)3505 void RenderFrameHostImpl::EnforceInsecureNavigationsSet(
3506 const std::vector<uint32_t>& set) {
3507 frame_tree_node()->SetInsecureNavigationsSet(set);
3508 }
3509
FindAndVerifyChild(int32_t child_frame_routing_id,bad_message::BadMessageReason reason)3510 FrameTreeNode* RenderFrameHostImpl::FindAndVerifyChild(
3511 int32_t child_frame_routing_id,
3512 bad_message::BadMessageReason reason) {
3513 FrameTreeNode* child = frame_tree_node()->frame_tree()->FindByRoutingID(
3514 GetProcess()->GetID(), child_frame_routing_id);
3515 // A race can result in |child| to be nullptr. Avoid killing the renderer in
3516 // that case.
3517 if (child && child->parent() != frame_tree_node()) {
3518 bad_message::ReceivedBadMessage(GetProcess(), reason);
3519 return nullptr;
3520 }
3521 return child;
3522 }
3523
OnDidChangeFramePolicy(int32_t frame_routing_id,const blink::FramePolicy & frame_policy)3524 void RenderFrameHostImpl::OnDidChangeFramePolicy(
3525 int32_t frame_routing_id,
3526 const blink::FramePolicy& frame_policy) {
3527 // Ensure that a frame can only update sandbox flags or feature policy for its
3528 // immediate children. If this is not the case, the renderer is considered
3529 // malicious and is killed.
3530 FrameTreeNode* child = FindAndVerifyChild(
3531 // TODO(iclelland): Rename this message
3532 frame_routing_id, bad_message::RFH_SANDBOX_FLAGS);
3533 if (!child)
3534 return;
3535
3536 child->SetPendingFramePolicy(frame_policy);
3537
3538 // Notify the RenderFrame if it lives in a different process from its parent.
3539 // The frame's proxies in other processes also need to learn about the updated
3540 // flags and policy, but these notifications are sent later in
3541 // RenderFrameHostManager::CommitPendingFramePolicy(), when the frame
3542 // navigates and the new policies take effect.
3543 RenderFrameHost* child_rfh = child->current_frame_host();
3544 if (child_rfh->GetSiteInstance() != GetSiteInstance()) {
3545 static_cast<RenderFrameHostImpl*>(child_rfh)
3546 ->GetAssociatedLocalFrame()
3547 ->DidUpdateFramePolicy(frame_policy);
3548 }
3549 }
3550
OnDidChangeFrameOwnerProperties(int32_t frame_routing_id,const blink::mojom::FrameOwnerProperties & properties)3551 void RenderFrameHostImpl::OnDidChangeFrameOwnerProperties(
3552 int32_t frame_routing_id,
3553 const blink::mojom::FrameOwnerProperties& properties) {
3554 FrameTreeNode* child =
3555 FindAndVerifyChild(frame_routing_id, bad_message::RFH_OWNER_PROPERTY);
3556 if (!child)
3557 return;
3558
3559 bool has_display_none_property_changed =
3560 properties.is_display_none !=
3561 child->frame_owner_properties().is_display_none;
3562
3563 child->set_frame_owner_properties(properties);
3564
3565 child->render_manager()->OnDidUpdateFrameOwnerProperties(properties);
3566 if (has_display_none_property_changed) {
3567 delegate_->DidChangeDisplayState(
3568 child->current_frame_host(),
3569 properties.is_display_none /* is_display_none */);
3570 }
3571 }
3572
UpdateTitle(const base::Optional<::base::string16> & title,base::i18n::TextDirection title_direction)3573 void RenderFrameHostImpl::UpdateTitle(
3574 const base::Optional<::base::string16>& title,
3575 base::i18n::TextDirection title_direction) {
3576 // This message should only be sent for top-level frames.
3577 if (frame_tree_node_->parent())
3578 return;
3579
3580 base::string16 received_title;
3581 if (title.has_value())
3582 received_title = title.value();
3583
3584 if (received_title.length() > blink::mojom::kMaxTitleChars) {
3585 mojo::ReportBadMessage("Renderer sent too many characters in title.");
3586 return;
3587 }
3588
3589 delegate_->UpdateTitle(this, received_title, title_direction);
3590 }
3591
UpdateEncoding(const std::string & encoding_name)3592 void RenderFrameHostImpl::UpdateEncoding(const std::string& encoding_name) {
3593 // This message is only sent for top-level frames. TODO(avi): when frame tree
3594 // mirroring works correctly, add a check here to enforce it.
3595 if (encoding_name == last_reported_encoding_)
3596 return;
3597 last_reported_encoding_ = encoding_name;
3598
3599 canonical_encoding_ =
3600 base::GetCanonicalEncodingNameByAliasName(encoding_name);
3601 }
3602
FrameSizeChanged(const gfx::Size & frame_size)3603 void RenderFrameHostImpl::FrameSizeChanged(const gfx::Size& frame_size) {
3604 frame_size_ = frame_size;
3605 delegate_->FrameSizeChanged(this, frame_size);
3606 }
3607
FullscreenStateChanged(bool is_fullscreen)3608 void RenderFrameHostImpl::FullscreenStateChanged(bool is_fullscreen) {
3609 if (!is_active())
3610 return;
3611 delegate_->FullscreenStateChanged(this, is_fullscreen);
3612 }
3613
RegisterProtocolHandler(const std::string & scheme,const GURL & url,const base::string16 & title,bool user_gesture)3614 void RenderFrameHostImpl::RegisterProtocolHandler(const std::string& scheme,
3615 const GURL& url,
3616 const base::string16& title,
3617 bool user_gesture) {
3618 delegate_->RegisterProtocolHandler(this, scheme, url, title, user_gesture);
3619 }
3620
UnregisterProtocolHandler(const std::string & scheme,const GURL & url,bool user_gesture)3621 void RenderFrameHostImpl::UnregisterProtocolHandler(const std::string& scheme,
3622 const GURL& url,
3623 bool user_gesture) {
3624 delegate_->UnregisterProtocolHandler(this, scheme, url, user_gesture);
3625 }
3626
DidDisplayInsecureContent()3627 void RenderFrameHostImpl::DidDisplayInsecureContent() {
3628 delegate_->DidDisplayInsecureContent();
3629 }
3630
DidContainInsecureFormAction()3631 void RenderFrameHostImpl::DidContainInsecureFormAction() {
3632 delegate_->DidContainInsecureFormAction();
3633 }
3634
DocumentAvailableInMainFrame(bool uses_temporary_zoom_level)3635 void RenderFrameHostImpl::DocumentAvailableInMainFrame(
3636 bool uses_temporary_zoom_level) {
3637 if (!frame_tree_node_->IsMainFrame()) {
3638 bad_message::ReceivedBadMessage(
3639 GetProcess(), bad_message::RFH_INVALID_CALL_FROM_NOT_MAIN_FRAME);
3640 return;
3641 }
3642 delegate_->DocumentAvailableInMainFrame();
3643
3644 if (!uses_temporary_zoom_level)
3645 return;
3646
3647 #if !defined(OS_ANDROID)
3648 HostZoomMapImpl* host_zoom_map =
3649 static_cast<HostZoomMapImpl*>(HostZoomMap::Get(GetSiteInstance()));
3650 host_zoom_map->SetTemporaryZoomLevel(GetProcess()->GetID(),
3651 render_view_host()->GetRoutingID(),
3652 host_zoom_map->GetDefaultZoomLevel());
3653 #endif // !defined(OS_ANDROID)
3654 }
3655
SetNeedsOcclusionTracking(bool needs_tracking)3656 void RenderFrameHostImpl::SetNeedsOcclusionTracking(bool needs_tracking) {
3657 // Don't process the IPC if this RFH is pending deletion. See also
3658 // https://crbug.com/972566.
3659 if (!is_active())
3660 return;
3661
3662 RenderFrameProxyHost* proxy =
3663 frame_tree_node()->render_manager()->GetProxyToParent();
3664 if (!proxy) {
3665 bad_message::ReceivedBadMessage(GetProcess(),
3666 bad_message::RFH_NO_PROXY_TO_PARENT);
3667 return;
3668 }
3669
3670 proxy->GetAssociatedRemoteFrame()->SetNeedsOcclusionTracking(needs_tracking);
3671 }
3672
LifecycleStateChanged(blink::mojom::FrameLifecycleState state)3673 void RenderFrameHostImpl::LifecycleStateChanged(
3674 blink::mojom::FrameLifecycleState state) {
3675 frame_lifecycle_state_ = state;
3676 }
3677
3678 #if defined(OS_ANDROID)
UpdateUserGestureCarryoverInfo()3679 void RenderFrameHostImpl::UpdateUserGestureCarryoverInfo() {
3680 delegate_->UpdateUserGestureCarryoverInfo();
3681 }
3682 #endif
3683
VisibilityChanged(blink::mojom::FrameVisibility visibility)3684 void RenderFrameHostImpl::VisibilityChanged(
3685 blink::mojom::FrameVisibility visibility) {
3686 visibility_ = visibility;
3687 UpdateFrameFrozenState();
3688 }
3689
DidChangeThemeColor(const base::Optional<SkColor> & theme_color)3690 void RenderFrameHostImpl::DidChangeThemeColor(
3691 const base::Optional<SkColor>& theme_color) {
3692 render_view_host_->OnThemeColorChanged(this, theme_color);
3693 }
3694
SetCommitCallbackInterceptorForTesting(CommitCallbackInterceptor * interceptor)3695 void RenderFrameHostImpl::SetCommitCallbackInterceptorForTesting(
3696 CommitCallbackInterceptor* interceptor) {
3697 // This DCHECK's aims to avoid unexpected replacement of an interceptor.
3698 // If this becomes a legitimate use case, feel free to remove.
3699 DCHECK(!commit_callback_interceptor_ || !interceptor);
3700 commit_callback_interceptor_ = interceptor;
3701 }
3702
DidBlockNavigation(const GURL & blocked_url,const GURL & initiator_url,blink::mojom::NavigationBlockedReason reason)3703 void RenderFrameHostImpl::DidBlockNavigation(
3704 const GURL& blocked_url,
3705 const GURL& initiator_url,
3706 blink::mojom::NavigationBlockedReason reason) {
3707 delegate_->OnDidBlockNavigation(blocked_url, initiator_url, reason);
3708 }
3709
DidChangeLoadProgress(double load_progress)3710 void RenderFrameHostImpl::DidChangeLoadProgress(double load_progress) {
3711 frame_tree_node_->DidChangeLoadProgress(load_progress);
3712 }
3713
DidFinishLoad(const GURL & validated_url)3714 void RenderFrameHostImpl::DidFinishLoad(const GURL& validated_url) {
3715 delegate_->OnDidFinishLoad(this, validated_url);
3716 }
3717
DispatchLoad()3718 void RenderFrameHostImpl::DispatchLoad() {
3719 TRACE_EVENT1("navigation", "RenderFrameHostImpl::DispatchLoad",
3720 "frame_tree_node", frame_tree_node_->frame_tree_node_id());
3721
3722 // Don't forward the load event if this RFH is pending deletion. This can
3723 // happen in a race where this RenderFrameHost finishes loading just after
3724 // the frame navigates away. See https://crbug.com/626802.
3725 if (!is_active())
3726 return;
3727
3728 // We should never be receiving this message from a speculative RFH.
3729 DCHECK(IsCurrent());
3730
3731 // Only frames with an out-of-process parent frame should be sending this
3732 // message.
3733 RenderFrameProxyHost* proxy =
3734 frame_tree_node()->render_manager()->GetProxyToParent();
3735 if (!proxy) {
3736 bad_message::ReceivedBadMessage(GetProcess(),
3737 bad_message::RFH_NO_PROXY_TO_PARENT);
3738 return;
3739 }
3740
3741 proxy->GetAssociatedRemoteFrame()->DispatchLoadEventForFrameOwner();
3742 }
3743
GoToEntryAtOffset(int32_t offset,bool has_user_gesture)3744 void RenderFrameHostImpl::GoToEntryAtOffset(int32_t offset,
3745 bool has_user_gesture) {
3746 delegate_->OnGoToEntryAtOffset(this, offset, has_user_gesture);
3747 }
3748
HandleAccessibilityFindInPageResult(blink::mojom::FindInPageResultAXParamsPtr params)3749 void RenderFrameHostImpl::HandleAccessibilityFindInPageResult(
3750 blink::mojom::FindInPageResultAXParamsPtr params) {
3751 ui::AXMode accessibility_mode = delegate_->GetAccessibilityMode();
3752 if (accessibility_mode.has_mode(ui::AXMode::kNativeAPIs) && is_active()) {
3753 BrowserAccessibilityManager* manager =
3754 GetOrCreateBrowserAccessibilityManager();
3755 if (manager) {
3756 manager->OnFindInPageResult(params->request_id, params->match_index,
3757 params->start_id, params->start_offset,
3758 params->end_id, params->end_offset);
3759 }
3760 }
3761 }
3762
HandleAccessibilityFindInPageTermination()3763 void RenderFrameHostImpl::HandleAccessibilityFindInPageTermination() {
3764 ui::AXMode accessibility_mode = delegate_->GetAccessibilityMode();
3765 if (accessibility_mode.has_mode(ui::AXMode::kNativeAPIs) && is_active()) {
3766 BrowserAccessibilityManager* manager =
3767 GetOrCreateBrowserAccessibilityManager();
3768 if (manager)
3769 manager->OnFindInPageTermination();
3770 }
3771 }
3772
DocumentOnLoadCompleted()3773 void RenderFrameHostImpl::DocumentOnLoadCompleted() {
3774 // This message is only sent for top-level frames.
3775 //
3776 // TODO(avi): when frame tree mirroring works correctly, add a check here
3777 // to enforce it.
3778 delegate_->DocumentOnLoadCompleted(this);
3779 }
3780
ForwardResourceTimingToParent(blink::mojom::ResourceTimingInfoPtr timing)3781 void RenderFrameHostImpl::ForwardResourceTimingToParent(
3782 blink::mojom::ResourceTimingInfoPtr timing) {
3783 // Don't forward the resource timing if this RFH is pending deletion. This can
3784 // happen in a race where this RenderFrameHost finishes loading just after
3785 // the frame navigates away. See https://crbug.com/626802.
3786 if (!is_active())
3787 return;
3788
3789 // We should never be receiving this message from a speculative RFH.
3790 DCHECK(IsCurrent());
3791
3792 RenderFrameProxyHost* proxy =
3793 frame_tree_node()->render_manager()->GetProxyToParent();
3794 if (!proxy) {
3795 bad_message::ReceivedBadMessage(GetProcess(),
3796 bad_message::RFH_NO_PROXY_TO_PARENT);
3797 return;
3798 }
3799 proxy->GetAssociatedRemoteFrame()->AddResourceTimingFromChild(
3800 std::move(timing));
3801 }
3802
GetViewForAccessibility()3803 RenderWidgetHostViewBase* RenderFrameHostImpl::GetViewForAccessibility() {
3804 return static_cast<RenderWidgetHostViewBase*>(
3805 frame_tree_node_->IsMainFrame()
3806 ? render_view_host_->GetWidget()->GetView()
3807 : GetMainFrame()->render_view_host_->GetWidget()->GetView());
3808 }
3809
UpdateBrowserControlsState(BrowserControlsState constraints,BrowserControlsState current,bool animate)3810 void RenderFrameHostImpl::UpdateBrowserControlsState(
3811 BrowserControlsState constraints,
3812 BrowserControlsState current,
3813 bool animate) {
3814 if (frame_)
3815 frame_->UpdateBrowserControlsState(constraints, current, animate);
3816 }
3817
Reload()3818 void RenderFrameHostImpl::Reload() {
3819 if (!IsRenderFrameLive())
3820 return;
3821
3822 // TODO(https://crbug.com/995428): This IPC is deprecated. Navigations are
3823 // handled from the browser process. There is no need to send an IPC to the
3824 // renderer process for this.
3825 Send(new FrameMsg_Reload(GetRoutingID()));
3826 }
3827
SendAccessibilityEventsToManager(const AXEventNotificationDetails & details)3828 void RenderFrameHostImpl::SendAccessibilityEventsToManager(
3829 const AXEventNotificationDetails& details) {
3830 if (browser_accessibility_manager_ &&
3831 !browser_accessibility_manager_->OnAccessibilityEvents(details)) {
3832 // OnAccessibilityEvents returns false in IPC error conditions
3833 AccessibilityFatalError();
3834 }
3835 }
3836
EvictFromBackForwardCache()3837 void RenderFrameHostImpl::EvictFromBackForwardCache() {
3838 // TODO(hajimehoshi): This function should take the reason from the renderer
3839 // side.
3840 EvictFromBackForwardCacheWithReason(
3841 BackForwardCacheMetrics::NotRestoredReason::kJavaScriptExecution);
3842 }
3843
EvictFromBackForwardCacheWithReason(BackForwardCacheMetrics::NotRestoredReason reason)3844 void RenderFrameHostImpl::EvictFromBackForwardCacheWithReason(
3845 BackForwardCacheMetrics::NotRestoredReason reason) {
3846 BackForwardCacheCanStoreDocumentResult can_store;
3847 can_store.No(reason);
3848 EvictFromBackForwardCacheWithReasons(can_store);
3849 }
3850
EvictFromBackForwardCacheWithReasons(const BackForwardCacheCanStoreDocumentResult & can_store)3851 void RenderFrameHostImpl::EvictFromBackForwardCacheWithReasons(
3852 const BackForwardCacheCanStoreDocumentResult& can_store) {
3853 TRACE_EVENT2("navigation", "RenderFrameHostImpl::EvictFromBackForwardCache",
3854 "can_store", can_store.ToString(), "rfh", this);
3855 DCHECK(IsBackForwardCacheEnabled());
3856
3857 if (is_evicted_from_back_forward_cache_)
3858 return;
3859
3860 bool in_back_forward_cache = is_in_back_forward_cache();
3861
3862 RenderFrameHostImpl* top_document = this;
3863 while (top_document->parent_) {
3864 top_document = top_document->parent_;
3865 DCHECK_EQ(top_document->is_in_back_forward_cache(), in_back_forward_cache);
3866 }
3867
3868 // TODO(hajimehoshi): Record the 'race condition' by JavaScript execution when
3869 // |is_in_back_forward_cache()| is false.
3870 BackForwardCacheMetrics* metrics = top_document->GetBackForwardCacheMetrics();
3871 if (is_in_back_forward_cache() && metrics)
3872 metrics->MarkNotRestoredWithReason(can_store);
3873
3874 if (!in_back_forward_cache) {
3875 TRACE_EVENT0("navigation", "BackForwardCache_EvictAfterDocumentRestored");
3876
3877 BackForwardCacheMetrics::RecordEvictedAfterDocumentRestored(
3878 BackForwardCacheMetrics::EvictedAfterDocumentRestoredReason::
3879 kByJavaScript);
3880
3881 // A document is evicted from the BackForwardCache, but it has already been
3882 // restored. The current document should be reloaded, because it is not
3883 // salvageable.
3884 frame_tree_node_->navigator()->GetController()->Reload(ReloadType::NORMAL,
3885 false);
3886 return;
3887 }
3888
3889 // Check if there is an in-flight navigation restoring the frame that
3890 // is being evicted.
3891 NavigationRequest* in_flight_navigation_request =
3892 top_document->frame_tree_node()->navigation_request();
3893 bool is_navigation_to_evicted_frame_in_flight =
3894 (in_flight_navigation_request &&
3895 in_flight_navigation_request->rfh_restored_from_back_forward_cache() ==
3896 top_document);
3897
3898 if (is_navigation_to_evicted_frame_in_flight) {
3899 // If we are currently navigating to the frame that was just evicted, we
3900 // must restart the navigation. This is important because restarting the
3901 // navigation deletes the NavigationRequest associated with the evicted
3902 // frame (preventing use-after-free).
3903 // This should also happen asynchronously as eviction might happen in the
3904 // middle of another navigation — we should not try to restart the
3905 // navigation in that case.
3906 // NOTE: Here we rely on the PostTask inside this function running before
3907 // the task posted to destroy the evicted frames below.
3908 in_flight_navigation_request->RestartBackForwardCachedNavigation();
3909 }
3910
3911 NavigationControllerImpl* controller = static_cast<NavigationControllerImpl*>(
3912 frame_tree_node_->navigator()->GetController());
3913
3914 // Evict the frame and schedule it to be destroyed. Eviction happens
3915 // immediately, but destruction is delayed, so that callers don't have to
3916 // worry about use-after-free of |this|.
3917 top_document->is_evicted_from_back_forward_cache_ = true;
3918 controller->GetBackForwardCache().PostTaskToDestroyEvictedFrames();
3919 }
3920
HasSeenRecentXrOverlaySetup()3921 bool RenderFrameHostImpl::HasSeenRecentXrOverlaySetup() {
3922 static constexpr base::TimeDelta kMaxInterval =
3923 base::TimeDelta::FromSeconds(1);
3924 base::TimeDelta delta = base::TimeTicks::Now() - last_xr_overlay_setup_time_;
3925 DVLOG(2) << __func__ << ": return " << (delta <= kMaxInterval);
3926 return delta <= kMaxInterval;
3927 }
3928
SetIsXrOverlaySetup()3929 void RenderFrameHostImpl::SetIsXrOverlaySetup() {
3930 DVLOG(2) << __func__;
3931 last_xr_overlay_setup_time_ = base::TimeTicks::Now();
3932 }
3933
3934 // TODO(alexmos): When the allowFullscreen flag is known in the browser
3935 // process, use it to double-check that fullscreen can be entered here.
EnterFullscreen(blink::mojom::FullscreenOptionsPtr options,EnterFullscreenCallback callback)3936 void RenderFrameHostImpl::EnterFullscreen(
3937 blink::mojom::FullscreenOptionsPtr options,
3938 EnterFullscreenCallback callback) {
3939 // Consume the user activation when entering fullscreen mode in the browser
3940 // side when the renderer is compromised and the fullscreen is not triggered
3941 // by a user generated orientation change, because the fullscreen can be
3942 // triggered by either a user activation or a user generated orientation
3943 // change.
3944 // CanEnterFullscreenWithoutUserActivation is always false by default, so it
3945 // keeps the current logic that we can enter fullscreen mode either by the
3946 // orientation change or successfully consuming the user activation. This
3947 // function is used for layout tests to allow fullscreen when mocking screen
3948 // screen orientation changes.
3949 // TODO(lanwei): Investigate whether we can terminate the renderer when the
3950 // user activation has already been consumed.
3951 if (!delegate_->HasSeenRecentScreenOrientationChange() &&
3952 !HasSeenRecentXrOverlaySetup() &&
3953 !GetContentClient()
3954 ->browser()
3955 ->CanEnterFullscreenWithoutUserActivation()) {
3956 bool is_consumed = frame_tree_node_->UpdateUserActivationState(
3957 blink::mojom::UserActivationUpdateType::kConsumeTransientActivation);
3958 if (!is_consumed) {
3959 DLOG(ERROR) << "Cannot enter fullscreen because there is no transient "
3960 << "user activation, orientation change, or XR overlay.";
3961 std::move(callback).Run(/*granted=*/false);
3962 return;
3963 }
3964 }
3965
3966 if (!delegate_->CanEnterFullscreenMode()) {
3967 std::move(callback).Run(/*granted=*/false);
3968 return;
3969 }
3970 std::move(callback).Run(/*granted=*/true);
3971
3972 // Entering fullscreen from a cross-process subframe also affects all
3973 // renderers for ancestor frames, which will need to apply fullscreen CSS to
3974 // appropriate ancestor <iframe> elements, fire fullscreenchange events, etc.
3975 // Thus, walk through the ancestor chain of this frame and for each (parent,
3976 // child) pair, send a message about the pending fullscreen change to the
3977 // child's proxy in parent's SiteInstance. The renderer process will use this
3978 // to find the <iframe> element in the parent frame that will need fullscreen
3979 // styles. This is done at most once per SiteInstance: for example, with a
3980 // A-B-A-B hierarchy, if the bottom frame goes fullscreen, this only needs to
3981 // notify its parent, and Blink-side logic will take care of applying
3982 // necessary changes to the other two ancestors.
3983 std::set<SiteInstance*> notified_instances;
3984 notified_instances.insert(GetSiteInstance());
3985 for (FrameTreeNode* node = frame_tree_node_; node->parent();
3986 node = node->parent()) {
3987 SiteInstance* parent_site_instance =
3988 node->parent()->current_frame_host()->GetSiteInstance();
3989 if (base::Contains(notified_instances, parent_site_instance))
3990 continue;
3991
3992 RenderFrameProxyHost* child_proxy =
3993 node->render_manager()->GetRenderFrameProxyHost(parent_site_instance);
3994 child_proxy->GetAssociatedRemoteFrame()->WillEnterFullscreen();
3995 notified_instances.insert(parent_site_instance);
3996 }
3997
3998 // TODO(alexmos): See if this can use the last committed origin instead.
3999 delegate_->EnterFullscreenMode(GetLastCommittedURL().GetOrigin(), *options);
4000 delegate_->FullscreenStateChanged(this, true /* is_fullscreen */);
4001 }
4002
4003 // TODO(alexmos): When the allowFullscreen flag is known in the browser
4004 // process, use it to double-check that fullscreen can be entered here.
ExitFullscreen()4005 void RenderFrameHostImpl::ExitFullscreen() {
4006 delegate_->ExitFullscreenMode(/* will_cause_resize */ true);
4007 }
4008
SuddenTerminationDisablerChanged(bool present,blink::mojom::SuddenTerminationDisablerType disabler_type)4009 void RenderFrameHostImpl::SuddenTerminationDisablerChanged(
4010 bool present,
4011 blink::mojom::SuddenTerminationDisablerType disabler_type) {
4012 switch (disabler_type) {
4013 case blink::mojom::SuddenTerminationDisablerType::kBeforeUnloadHandler:
4014 DCHECK_NE(has_before_unload_handler_, present);
4015 has_before_unload_handler_ = present;
4016 break;
4017 case blink::mojom::SuddenTerminationDisablerType::kUnloadHandler:
4018 DCHECK_NE(has_unload_handler_, present);
4019 has_unload_handler_ = present;
4020 break;
4021 }
4022 }
4023
GetSuddenTerminationDisablerState(blink::mojom::SuddenTerminationDisablerType disabler_type)4024 bool RenderFrameHostImpl::GetSuddenTerminationDisablerState(
4025 blink::mojom::SuddenTerminationDisablerType disabler_type) {
4026 switch (disabler_type) {
4027 case blink::mojom::SuddenTerminationDisablerType::kBeforeUnloadHandler:
4028 return has_before_unload_handler_;
4029 case blink::mojom::SuddenTerminationDisablerType::kUnloadHandler:
4030 return has_unload_handler();
4031 }
4032 }
4033
InsidePortal()4034 bool RenderFrameHostImpl::InsidePortal() {
4035 return GetRenderViewHost()->GetDelegate()->IsPortal();
4036 }
4037
DidFinishDocumentLoad()4038 void RenderFrameHostImpl::DidFinishDocumentLoad() {
4039 dom_content_loaded_ = true;
4040 delegate_->DOMContentLoaded(this);
4041 }
4042
OnDidStopLoading()4043 void RenderFrameHostImpl::OnDidStopLoading() {
4044 TRACE_EVENT1("navigation", "RenderFrameHostImpl::OnDidStopLoading",
4045 "frame_tree_node", frame_tree_node_->frame_tree_node_id());
4046
4047 // This method should never be called when the frame is not loading.
4048 // Unfortunately, it can happen if a history navigation happens during a
4049 // BeforeUnload or Unload event.
4050 // TODO(fdegans): Change this to a DCHECK after LoadEventProgress has been
4051 // refactored in Blink. See crbug.com/466089
4052 if (!is_loading_)
4053 return;
4054
4055 was_discarded_ = false;
4056 is_loading_ = false;
4057
4058 // If we have a PeakGpuMemoryTrack, close it as loading as stopped. It will
4059 // asynchronously receive the statistics from the GPU process, and update
4060 // UMA stats.
4061 if (loading_mem_tracker_)
4062 loading_mem_tracker_.reset();
4063
4064 // Only inform the FrameTreeNode of a change in load state if the load state
4065 // of this RenderFrameHost is being tracked.
4066 if (is_active())
4067 frame_tree_node_->DidStopLoading();
4068 }
4069
OnSelectionChanged(const base::string16 & text,uint32_t offset,const gfx::Range & range,bool user_initiated)4070 void RenderFrameHostImpl::OnSelectionChanged(const base::string16& text,
4071 uint32_t offset,
4072 const gfx::Range& range,
4073 bool user_initiated) {
4074 has_selection_ = !text.empty();
4075 GetRenderWidgetHost()->SelectionChanged(text, offset, range, user_initiated);
4076 }
4077
FocusedElementChanged(bool is_editable_element,const gfx::Rect & bounds_in_frame_widget)4078 void RenderFrameHostImpl::FocusedElementChanged(
4079 bool is_editable_element,
4080 const gfx::Rect& bounds_in_frame_widget) {
4081 if (!GetView())
4082 return;
4083
4084 has_focused_editable_element_ = is_editable_element;
4085 // First convert the bounds to root view.
4086 delegate_->OnFocusedElementChangedInFrame(
4087 this, gfx::Rect(GetView()->TransformPointToRootCoordSpace(
4088 bounds_in_frame_widget.origin()),
4089 bounds_in_frame_widget.size()));
4090 }
4091
DidReceiveFirstUserActivation()4092 void RenderFrameHostImpl::DidReceiveFirstUserActivation() {
4093 delegate_->DidReceiveFirstUserActivation(this);
4094 }
4095
UpdateUserActivationState(blink::mojom::UserActivationUpdateType update_type)4096 void RenderFrameHostImpl::UpdateUserActivationState(
4097 blink::mojom::UserActivationUpdateType update_type) {
4098 if (!is_active())
4099 return;
4100 frame_tree_node_->UpdateUserActivationState(update_type);
4101 }
4102
HadStickyUserActivationBeforeNavigationChanged(bool value)4103 void RenderFrameHostImpl::HadStickyUserActivationBeforeNavigationChanged(
4104 bool value) {
4105 frame_tree_node_->OnSetHadStickyUserActivationBeforeNavigation(value);
4106 }
4107
ScrollRectToVisibleInParentFrame(const gfx::Rect & rect_to_scroll,blink::mojom::ScrollIntoViewParamsPtr params)4108 void RenderFrameHostImpl::ScrollRectToVisibleInParentFrame(
4109 const gfx::Rect& rect_to_scroll,
4110 blink::mojom::ScrollIntoViewParamsPtr params) {
4111 RenderFrameProxyHost* proxy =
4112 frame_tree_node_->render_manager()->GetProxyToParent();
4113 if (!proxy)
4114 return;
4115 proxy->ScrollRectToVisible(rect_to_scroll, std::move(params));
4116 }
4117
BubbleLogicalScrollInParentFrame(blink::mojom::ScrollDirection direction,ui::ScrollGranularity granularity)4118 void RenderFrameHostImpl::BubbleLogicalScrollInParentFrame(
4119 blink::mojom::ScrollDirection direction,
4120 ui::ScrollGranularity granularity) {
4121 if (!is_active())
4122 return;
4123
4124 RenderFrameProxyHost* proxy =
4125 frame_tree_node()->render_manager()->GetProxyToParent();
4126 if (!proxy) {
4127 // Only frames with an out-of-process parent frame should be sending this
4128 // message.
4129 bad_message::ReceivedBadMessage(GetProcess(),
4130 bad_message::RFH_NO_PROXY_TO_PARENT);
4131 return;
4132 }
4133
4134 proxy->GetAssociatedRemoteFrame()->BubbleLogicalScroll(direction,
4135 granularity);
4136 }
4137
OnFrameDidCallFocus()4138 void RenderFrameHostImpl::OnFrameDidCallFocus() {
4139 delegate_->DidCallFocus();
4140 }
4141
RenderFallbackContentInParentProcess()4142 void RenderFrameHostImpl::RenderFallbackContentInParentProcess() {
4143 bool is_object_type =
4144 frame_tree_node()->current_replication_state().frame_owner_element_type ==
4145 blink::FrameOwnerElementType::kObject;
4146 if (!is_object_type) {
4147 // Only object elements are expected to render their own fallback content
4148 // and since the owner type is set at the creation time of the
4149 // FrameTreeNode, this received IPC makes no sense here.
4150 bad_message::ReceivedBadMessage(
4151 GetProcess(), bad_message::RFH_CANNOT_RENDER_FALLBACK_CONTENT);
4152 return;
4153 }
4154
4155 // The ContentFrame() of the owner element in parent process could be either
4156 // a frame or a proxy. When navigating cross-site from a frame which is same-
4157 // site with its parent, the frame is still local (e.g., about:blank).
4158 // However, navigating from an origin which is cross-site with parent, the
4159 // frame of the owner is a proxy.
4160 auto* rfh = frame_tree_node()->current_frame_host();
4161 if (rfh->GetSiteInstance() == rfh->GetParent()->GetSiteInstance()) {
4162 rfh->GetAssociatedLocalFrame()->RenderFallbackContent();
4163 } else if (auto* proxy =
4164 frame_tree_node()->render_manager()->GetProxyToParent()) {
4165 proxy->GetAssociatedRemoteFrame()->RenderFallbackContent();
4166 }
4167 }
4168
4169 #if BUILDFLAG(USE_EXTERNAL_POPUP_MENU)
OnShowPopup(const FrameHostMsg_ShowPopup_Params & params)4170 void RenderFrameHostImpl::OnShowPopup(
4171 const FrameHostMsg_ShowPopup_Params& params) {
4172 RenderViewHostDelegateView* view =
4173 render_view_host_->delegate_->GetDelegateView();
4174 if (view) {
4175 gfx::Point original_point(params.bounds.x(), params.bounds.y());
4176 gfx::Point transformed_point =
4177 static_cast<RenderWidgetHostViewBase*>(GetView())
4178 ->TransformPointToRootCoordSpace(original_point);
4179 gfx::Rect transformed_bounds(transformed_point.x(), transformed_point.y(),
4180 params.bounds.width(), params.bounds.height());
4181 view->ShowPopupMenu(this, transformed_bounds, params.item_height,
4182 params.item_font_size, params.selected_item,
4183 params.popup_items, params.right_aligned,
4184 params.allow_multiple_selection);
4185 }
4186 }
4187
OnHidePopup()4188 void RenderFrameHostImpl::OnHidePopup() {
4189 RenderViewHostDelegateView* view =
4190 render_view_host_->delegate_->GetDelegateView();
4191 if (view)
4192 view->HidePopupMenu();
4193 }
4194 #endif
4195
BindInterfaceProviderReceiver(mojo::PendingReceiver<service_manager::mojom::InterfaceProvider> interface_provider_receiver)4196 void RenderFrameHostImpl::BindInterfaceProviderReceiver(
4197 mojo::PendingReceiver<service_manager::mojom::InterfaceProvider>
4198 interface_provider_receiver) {
4199 DCHECK(!document_scoped_interface_provider_receiver_.is_bound());
4200 DCHECK(interface_provider_receiver.is_valid());
4201 document_scoped_interface_provider_receiver_.Bind(
4202 FilterRendererExposedInterfaces(mojom::kNavigation_FrameSpec,
4203 GetProcess()->GetID(),
4204 std::move(interface_provider_receiver)));
4205 document_scoped_interface_provider_receiver_.SetFilter(
4206 std::make_unique<ActiveURLMessageFilter>(this));
4207 }
4208
BindBrowserInterfaceBrokerReceiver(mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker> receiver)4209 void RenderFrameHostImpl::BindBrowserInterfaceBrokerReceiver(
4210 mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker> receiver) {
4211 DCHECK(receiver.is_valid());
4212 broker_receiver_.Bind(std::move(receiver));
4213 broker_receiver_.SetFilter(std::make_unique<ActiveURLMessageFilter>(this));
4214 }
4215
SetKeepAliveTimeoutForTesting(base::TimeDelta timeout)4216 void RenderFrameHostImpl::SetKeepAliveTimeoutForTesting(
4217 base::TimeDelta timeout) {
4218 keep_alive_timeout_ = timeout;
4219 if (keep_alive_handle_factory_)
4220 keep_alive_handle_factory_->SetTimeout(keep_alive_timeout_);
4221 }
4222
ShowCreatedWindow(int pending_widget_routing_id,WindowOpenDisposition disposition,const gfx::Rect & initial_rect,bool user_gesture)4223 void RenderFrameHostImpl::ShowCreatedWindow(int pending_widget_routing_id,
4224 WindowOpenDisposition disposition,
4225 const gfx::Rect& initial_rect,
4226 bool user_gesture) {
4227 delegate_->ShowCreatedWindow(GetProcess()->GetID(), pending_widget_routing_id,
4228 disposition, initial_rect, user_gesture);
4229 }
4230
RequestOverlayRoutingToken(RequestOverlayRoutingTokenCallback callback)4231 void RenderFrameHostImpl::RequestOverlayRoutingToken(
4232 RequestOverlayRoutingTokenCallback callback) {
4233 std::move(callback).Run(frame_token_);
4234 }
4235
4236 std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
CreateCrossOriginPrefetchLoaderFactoryBundle()4237 RenderFrameHostImpl::CreateCrossOriginPrefetchLoaderFactoryBundle() {
4238 DCHECK(base::FeatureList::IsEnabled(
4239 network::features::kPrefetchMainResourceNetworkIsolationKey));
4240
4241 network::mojom::URLLoaderFactoryParamsPtr factory_params =
4242 URLLoaderFactoryParamsHelper::CreateForPrefetch(
4243 this, mojo::Clone(last_committed_client_security_state_));
4244
4245 mojo::PendingRemote<network::mojom::URLLoaderFactory> pending_default_factory;
4246 bool bypass_redirect_checks = false;
4247 // Passing a nullopt NetworkIsolationKey ensures the factory is not
4248 // initialized with a NetworkIsolationKey. This is necessary for a
4249 // cross-origin prefetch factory because the factory must use the
4250 // NetworkIsolationKey provided by requests going through it.
4251 bypass_redirect_checks = CreateNetworkServiceDefaultFactoryAndObserve(
4252 std::move(factory_params),
4253 pending_default_factory.InitWithNewPipeAndPassReceiver());
4254
4255 return std::make_unique<blink::PendingURLLoaderFactoryBundle>(
4256 std::move(pending_default_factory),
4257 blink::PendingURLLoaderFactoryBundle::SchemeMap(),
4258 CreateURLLoaderFactoriesForIsolatedWorlds(
4259 GetExpectedMainWorldOriginForUrlLoaderFactory(),
4260 isolated_worlds_requiring_separate_url_loader_factory_,
4261 mojo::Clone(last_committed_client_security_state_)),
4262 bypass_redirect_checks);
4263 }
4264
GetWeakPtr()4265 base::WeakPtr<RenderFrameHostImpl> RenderFrameHostImpl::GetWeakPtr() {
4266 return weak_ptr_factory_.GetWeakPtr();
4267 }
4268
TransferUserActivationFrom(int32_t source_routing_id)4269 void RenderFrameHostImpl::TransferUserActivationFrom(
4270 int32_t source_routing_id) {
4271 RenderFrameHostImpl* source_rfh = RenderFrameHostImpl::FromID(
4272 GlobalFrameRoutingId(GetProcess()->GetID(), source_routing_id));
4273 if (source_rfh &&
4274 source_rfh->frame_tree_node()->HasTransientUserActivation()) {
4275 frame_tree_node()->TransferUserActivationFrom(source_rfh);
4276 }
4277 }
4278
CreateNewWindow(mojom::CreateNewWindowParamsPtr params,CreateNewWindowCallback callback)4279 void RenderFrameHostImpl::CreateNewWindow(
4280 mojom::CreateNewWindowParamsPtr params,
4281 CreateNewWindowCallback callback) {
4282 DCHECK_CURRENTLY_ON(BrowserThread::UI);
4283 TRACE_EVENT2("navigation", "RenderFrameHostImpl::CreateNewWindow",
4284 "frame_tree_node", frame_tree_node_->frame_tree_node_id(), "url",
4285 params->target_url.possibly_invalid_spec());
4286
4287 bool no_javascript_access = false;
4288
4289 // Filter out URLs to which navigation is disallowed from this context.
4290 //
4291 // Note that currently, "javascript:" URLs and empty strings (both of which
4292 // are legal arguments to window.open) make it here; FilterURL rewrites them
4293 // to "about:blank" -- they shouldn't be cancelled.
4294 GetProcess()->FilterURL(false, ¶ms->target_url);
4295
4296 bool effective_transient_activation_state =
4297 params->allow_popup || frame_tree_node_->HasTransientUserActivation();
4298
4299 // Ignore window creation when sent from a frame that's not current or
4300 // created.
4301 bool can_create_window =
4302 IsCurrent() && render_frame_created_ &&
4303 GetContentClient()->browser()->CanCreateWindow(
4304 this, GetLastCommittedURL(), GetMainFrame()->GetLastCommittedURL(),
4305 last_committed_origin_, params->window_container_type,
4306 params->target_url, params->referrer.To<Referrer>(),
4307 params->frame_name, params->disposition, *params->features,
4308 effective_transient_activation_state, params->opener_suppressed,
4309 &no_javascript_access);
4310
4311 bool was_consumed = false;
4312 if (can_create_window) {
4313 // Consume activation even w/o User Activation v2, to sync other renderers
4314 // with calling renderer.
4315 was_consumed = frame_tree_node_->UpdateUserActivationState(
4316 blink::mojom::UserActivationUpdateType::kConsumeTransientActivation);
4317 } else {
4318 std::move(callback).Run(mojom::CreateNewWindowStatus::kIgnore, nullptr);
4319 return;
4320 }
4321
4322 // For Android WebView, we support a pop-up like behavior for window.open()
4323 // even if the embedding app doesn't support multiple windows. In this case,
4324 // window.open() will return "window" and navigate it to whatever URL was
4325 // passed.
4326 if (!render_view_host_->GetWebkitPreferences().supports_multiple_windows) {
4327 // See crbug.com/1083819, we should ignore if the URL is javascript: scheme,
4328 // previously we already filtered out javascript: scheme and replace the
4329 // URL with |kBlockedURL|, so we check against |kBlockedURL| here.
4330 if (params->target_url == GURL(kBlockedURL)) {
4331 std::move(callback).Run(mojom::CreateNewWindowStatus::kIgnore, nullptr);
4332 } else {
4333 std::move(callback).Run(mojom::CreateNewWindowStatus::kReuse, nullptr);
4334 }
4335 return;
4336 }
4337
4338 // This will clone the sessionStorage for namespace_id_to_clone.
4339 StoragePartition* storage_partition = BrowserContext::GetStoragePartition(
4340 GetSiteInstance()->GetBrowserContext(), GetSiteInstance());
4341 DOMStorageContextWrapper* dom_storage_context =
4342 static_cast<DOMStorageContextWrapper*>(
4343 storage_partition->GetDOMStorageContext());
4344
4345 scoped_refptr<SessionStorageNamespaceImpl> cloned_namespace;
4346 if (!params->clone_from_session_storage_namespace_id.empty()) {
4347 cloned_namespace = SessionStorageNamespaceImpl::CloneFrom(
4348 dom_storage_context, params->session_storage_namespace_id,
4349 params->clone_from_session_storage_namespace_id);
4350 } else {
4351 cloned_namespace = SessionStorageNamespaceImpl::Create(
4352 dom_storage_context, params->session_storage_namespace_id);
4353 }
4354
4355 network::mojom::CrossOriginOpenerPolicy popup_coop =
4356 network::mojom::CrossOriginOpenerPolicy::kUnsafeNone;
4357 network::CrossOriginEmbedderPolicy popup_coep;
4358 if (base::FeatureList::IsEnabled(
4359 network::features::kCrossOriginOpenerPolicy)) {
4360 // On popup creation, if the opener and the openers's top-level document
4361 // are same origin, then the popup's initial empty document inherits its
4362 // COOP policy from the opener's top-level document. See
4363 // https://gist.github.com/annevk/6f2dd8c79c77123f39797f6bdac43f3e#model
4364 RenderFrameHostImpl* top_level_opener = GetMainFrame();
4365 // Verify that they are same origin.
4366 if (top_level_opener->GetLastCommittedOrigin().IsSameOriginWith(
4367 GetLastCommittedOrigin())) {
4368 popup_coop = top_level_opener->cross_origin_opener_policy();
4369 } else {
4370 // The documents are cross origin, leave COOP of the popup to the default
4371 // unsafe-none.
4372 // Then set the popup to noopener if the top level COOP is same origin.
4373 if (top_level_opener->cross_origin_opener_policy() ==
4374 network::mojom::CrossOriginOpenerPolicy::kSameOrigin) {
4375 params->opener_suppressed = true;
4376 // The frame name should not be forwarded to a noopener popup.
4377 // TODO(https://crbug.com/1060691) This should be applied to all
4378 // popups opened with noopener.
4379 params->frame_name.clear();
4380 }
4381 }
4382 }
4383
4384 // The initial empty document in the popup inherits the COEP of its opener (if
4385 // any).
4386 if (!params->opener_suppressed)
4387 popup_coep = cross_origin_embedder_policy();
4388
4389 // If the opener is suppressed or script access is disallowed, we should
4390 // open the window in a new BrowsingInstance, and thus a new process. That
4391 // means the current renderer process will not be able to route messages to
4392 // it. Because of this, we will immediately show and navigate the window
4393 // in OnCreateNewWindowOnUI, using the params provided here.
4394 bool is_new_browsing_instance =
4395 params->opener_suppressed || no_javascript_access;
4396
4397 DCHECK(IsRenderFrameLive());
4398
4399 // The non-owning pointer |new_window| is valid in this stack frame since
4400 // nothing can delete it until this thread is freed up again.
4401 RenderFrameHostDelegate* new_window =
4402 delegate_->CreateNewWindow(this, *params, is_new_browsing_instance,
4403 was_consumed, cloned_namespace.get());
4404
4405 if (is_new_browsing_instance || !new_window) {
4406 // Opener suppressed, Javascript access disabled, or delegate did not
4407 // provide a handle to any windows it created. In these cases, never tell
4408 // the renderer about the new window.
4409 std::move(callback).Run(mojom::CreateNewWindowStatus::kIgnore, nullptr);
4410 return;
4411 }
4412
4413 RenderFrameHostImpl* main_frame = new_window->GetMainFrame();
4414
4415 // When the popup is created, it hasn't committed any navigation yet - its
4416 // initial empty document should inherit the origin and network isolation key
4417 // of its opener (the origin may change after the first commit). See also
4418 // https://crbug.com/932067.
4419 //
4420 // Note that that origin of the new frame might depend on sandbox flags.
4421 // Checking sandbox flags of the new frame should be safe at this point,
4422 // because the flags should be already inherited by the CreateNewWindow call
4423 // above.
4424 main_frame->SetOriginAndNetworkIsolationKeyOfNewFrame(
4425 GetLastCommittedOrigin());
4426 main_frame->cross_origin_opener_policy_ = popup_coop;
4427 main_frame->cross_origin_embedder_policy_ = popup_coep;
4428
4429 if (main_frame->waiting_for_init_) {
4430 // Need to check |waiting_for_init_| as some paths inside CreateNewWindow
4431 // call above (eg if WebContentsDelegate::IsWebContentsCreationOverridden()
4432 // returns true) will resume requests by calling RenderFrameHostImpl::Init.
4433 main_frame->frame_->BlockRequests();
4434 }
4435
4436 mojo::PendingRemote<service_manager::mojom::InterfaceProvider>
4437 main_frame_interface_provider_info;
4438 main_frame->BindInterfaceProviderReceiver(
4439 main_frame_interface_provider_info.InitWithNewPipeAndPassReceiver());
4440
4441 mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>
4442 browser_interface_broker;
4443 main_frame->BindBrowserInterfaceBrokerReceiver(
4444 browser_interface_broker.InitWithNewPipeAndPassReceiver());
4445
4446 mojo::PendingAssociatedRemote<blink::mojom::FrameWidget> blink_frame_widget;
4447 mojo::PendingAssociatedReceiver<blink::mojom::FrameWidget>
4448 blink_frame_widget_receiver =
4449 blink_frame_widget.InitWithNewEndpointAndPassReceiver();
4450
4451 mojo::PendingAssociatedRemote<blink::mojom::FrameWidgetHost>
4452 blink_frame_widget_host;
4453 mojo::PendingAssociatedReceiver<blink::mojom::FrameWidgetHost>
4454 blink_frame_widget_host_receiver =
4455 blink_frame_widget_host.InitWithNewEndpointAndPassReceiver();
4456
4457 mojo::PendingAssociatedRemote<blink::mojom::Widget> blink_widget;
4458 mojo::PendingAssociatedReceiver<blink::mojom::Widget> blink_widget_receiver =
4459 blink_widget.InitWithNewEndpointAndPassReceiver();
4460
4461 mojo::PendingAssociatedRemote<blink::mojom::WidgetHost> blink_widget_host;
4462 mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost>
4463 blink_widget_host_receiver =
4464 blink_widget_host.InitWithNewEndpointAndPassReceiver();
4465
4466 // TODO(danakj): The main frame's RenderWidgetHost has no RenderWidgetHostView
4467 // yet here. It seems like it should though? In the meantime we send some
4468 // nonsense with a semi-valid but incorrect ScreenInfo (it needs a
4469 // RenderWidgetHostView to be correct). An updates VisualProperties will get
4470 // to the RenderWidget eventually.
4471 VisualProperties visual_properties;
4472 main_frame->GetLocalRenderWidgetHost()->GetScreenInfo(
4473 &visual_properties.screen_info);
4474 main_frame->GetLocalRenderWidgetHost()->BindFrameWidgetInterfaces(
4475 std::move(blink_frame_widget_host_receiver),
4476 std::move(blink_frame_widget));
4477 main_frame->GetLocalRenderWidgetHost()->BindWidgetInterfaces(
4478 std::move(blink_widget_host_receiver), std::move(blink_widget));
4479
4480 bool wait_for_debugger =
4481 devtools_instrumentation::ShouldWaitForDebuggerInWindowOpen();
4482 mojom::CreateNewWindowReplyPtr reply = mojom::CreateNewWindowReply::New(
4483 main_frame->GetRenderViewHost()->GetRoutingID(),
4484 main_frame->GetRoutingID(),
4485 main_frame->GetLocalRenderWidgetHost()->GetRoutingID(), visual_properties,
4486 std::move(blink_frame_widget_host),
4487 std::move(blink_frame_widget_receiver), std::move(blink_widget_host),
4488 std::move(blink_widget_receiver),
4489 mojom::DocumentScopedInterfaceBundle::New(
4490 std::move(main_frame_interface_provider_info),
4491 std::move(browser_interface_broker)),
4492 cloned_namespace->id(), main_frame->GetDevToolsFrameToken(),
4493 wait_for_debugger);
4494
4495 std::move(callback).Run(mojom::CreateNewWindowStatus::kSuccess,
4496 std::move(reply));
4497 }
4498
CreatePortal(mojo::PendingAssociatedReceiver<blink::mojom::Portal> pending_receiver,mojo::PendingAssociatedRemote<blink::mojom::PortalClient> client,CreatePortalCallback callback)4499 void RenderFrameHostImpl::CreatePortal(
4500 mojo::PendingAssociatedReceiver<blink::mojom::Portal> pending_receiver,
4501 mojo::PendingAssociatedRemote<blink::mojom::PortalClient> client,
4502 CreatePortalCallback callback) {
4503 if (!Portal::IsEnabled()) {
4504 mojo::ReportBadMessage(
4505 "blink.mojom.Portal can only be used if the Portals feature is "
4506 "enabled.");
4507 frame_host_associated_receiver_.reset();
4508 return;
4509 }
4510
4511 // We don't support attaching a portal inside a nested browsing context.
4512 if (frame_tree_node()->parent()) {
4513 mojo::ReportBadMessage(
4514 "RFHI::CreatePortal called in a nested browsing context");
4515 frame_host_associated_receiver_.reset();
4516 return;
4517 }
4518
4519 // Note that we don't check |GetLastCommittedOrigin|, since that is inherited
4520 // by the initial empty document of a new frame.
4521 // TODO(1008989): Once issue 1008989 is fixed we could move this check into
4522 // |Portal::Create|.
4523 if (!GetLastCommittedURL().SchemeIsHTTPOrHTTPS()) {
4524 mojo::ReportBadMessage("Portal creation is restricted to the HTTP family.");
4525 frame_host_associated_receiver_.reset();
4526 return;
4527 }
4528
4529 auto portal = std::make_unique<Portal>(this);
4530 portal->Bind(std::move(pending_receiver), std::move(client));
4531 auto it = portals_.insert(std::move(portal)).first;
4532
4533 RenderFrameProxyHost* proxy_host = (*it)->CreateProxyAndAttachPortal();
4534
4535 // Since the portal is newly created and has yet to commit a navigation, this
4536 // state is trivial.
4537 const FrameReplicationState& initial_replicated_state =
4538 proxy_host->frame_tree_node()->current_replication_state();
4539 DCHECK(initial_replicated_state.origin.opaque());
4540
4541 std::move(callback).Run(proxy_host->GetRoutingID(), initial_replicated_state,
4542 (*it)->portal_token(),
4543 (*it)->GetDevToolsFrameToken());
4544 }
4545
AdoptPortal(const base::UnguessableToken & portal_token,AdoptPortalCallback callback)4546 void RenderFrameHostImpl::AdoptPortal(
4547 const base::UnguessableToken& portal_token,
4548 AdoptPortalCallback callback) {
4549 Portal* portal = FindPortalByToken(portal_token);
4550 if (!portal) {
4551 mojo::ReportBadMessage("Unknown portal_token when adopting portal.");
4552 frame_host_associated_receiver_.reset();
4553 return;
4554 }
4555 DCHECK_EQ(portal->owner_render_frame_host(), this);
4556 RenderFrameProxyHost* proxy_host = portal->CreateProxyAndAttachPortal();
4557 std::move(callback).Run(
4558 proxy_host->GetRoutingID(),
4559 static_cast<RenderWidgetHostViewBase*>(proxy_host->frame_tree_node()
4560 ->render_manager()
4561 ->GetRenderWidgetHostView())
4562 ->GetFrameSinkId(),
4563 proxy_host->frame_tree_node()->current_replication_state(),
4564 portal->GetDevToolsFrameToken());
4565 }
4566
CreateNewWidget(mojo::PendingRemote<mojom::Widget> widget,mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost> blink_widget_host,mojo::PendingAssociatedRemote<blink::mojom::Widget> blink_widget,CreateNewWidgetCallback callback)4567 void RenderFrameHostImpl::CreateNewWidget(
4568 mojo::PendingRemote<mojom::Widget> widget,
4569 mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost> blink_widget_host,
4570 mojo::PendingAssociatedRemote<blink::mojom::Widget> blink_widget,
4571 CreateNewWidgetCallback callback) {
4572 int32_t widget_route_id = GetProcess()->GetNextRoutingID();
4573 std::move(callback).Run(widget_route_id);
4574 delegate_->CreateNewWidget(GetProcess()->GetID(), widget_route_id,
4575 std::move(widget), std::move(blink_widget_host),
4576 std::move(blink_widget));
4577 }
4578
CreateNewFullscreenWidget(mojo::PendingRemote<mojom::Widget> widget,mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost> blink_widget_host,mojo::PendingAssociatedRemote<blink::mojom::Widget> blink_widget,CreateNewFullscreenWidgetCallback callback)4579 void RenderFrameHostImpl::CreateNewFullscreenWidget(
4580 mojo::PendingRemote<mojom::Widget> widget,
4581 mojo::PendingAssociatedReceiver<blink::mojom::WidgetHost> blink_widget_host,
4582 mojo::PendingAssociatedRemote<blink::mojom::Widget> blink_widget,
4583 CreateNewFullscreenWidgetCallback callback) {
4584 int32_t widget_route_id = GetProcess()->GetNextRoutingID();
4585 std::move(callback).Run(widget_route_id);
4586 delegate_->CreateNewFullscreenWidget(
4587 GetProcess()->GetID(), widget_route_id, std::move(widget),
4588 std::move(blink_widget_host), std::move(blink_widget));
4589 }
4590
IssueKeepAliveHandle(mojo::PendingReceiver<mojom::KeepAliveHandle> receiver)4591 void RenderFrameHostImpl::IssueKeepAliveHandle(
4592 mojo::PendingReceiver<mojom::KeepAliveHandle> receiver) {
4593 DCHECK_CURRENTLY_ON(BrowserThread::UI);
4594 if (GetProcess()->IsKeepAliveRefCountDisabled())
4595 return;
4596
4597 if (base::FeatureList::IsEnabled(network::features::kDisableKeepaliveFetch)) {
4598 return;
4599 }
4600
4601 if (!keep_alive_handle_factory_) {
4602 keep_alive_handle_factory_ =
4603 std::make_unique<KeepAliveHandleFactory>(GetProcess());
4604 keep_alive_handle_factory_->SetTimeout(keep_alive_timeout_);
4605 }
4606 keep_alive_handle_factory_->Create(std::move(receiver));
4607 }
4608
4609 // TODO(ahemery): Move checks to mojo bad message reporting.
BeginNavigation(mojom::CommonNavigationParamsPtr common_params,mojom::BeginNavigationParamsPtr begin_params,mojo::PendingRemote<blink::mojom::BlobURLToken> blob_url_token,mojo::PendingAssociatedRemote<mojom::NavigationClient> navigation_client,mojo::PendingRemote<blink::mojom::NavigationInitiator> navigation_initiator)4610 void RenderFrameHostImpl::BeginNavigation(
4611 mojom::CommonNavigationParamsPtr common_params,
4612 mojom::BeginNavigationParamsPtr begin_params,
4613 mojo::PendingRemote<blink::mojom::BlobURLToken> blob_url_token,
4614 mojo::PendingAssociatedRemote<mojom::NavigationClient> navigation_client,
4615 mojo::PendingRemote<blink::mojom::NavigationInitiator>
4616 navigation_initiator) {
4617 if (frame_tree_node_->render_manager()->is_attaching_inner_delegate()) {
4618 // Avoid starting any new navigations since this frame is in the process of
4619 // attaching an inner delegate.
4620 return;
4621 }
4622
4623 if (!is_active())
4624 return;
4625
4626 TRACE_EVENT2("navigation", "RenderFrameHostImpl::BeginNavigation",
4627 "frame_tree_node", frame_tree_node_->frame_tree_node_id(), "url",
4628 common_params->url.possibly_invalid_spec());
4629
4630 DCHECK(navigation_client.is_valid());
4631
4632 mojom::CommonNavigationParamsPtr validated_params = common_params.Clone();
4633 if (!VerifyBeginNavigationCommonParams(GetSiteInstance(), &*validated_params))
4634 return;
4635
4636 GetProcess()->FilterURL(true, &begin_params->searchable_form_url);
4637
4638 // If the request was for a blob URL, but the validated URL is no longer a
4639 // blob URL, reset the blob_url_token to prevent hitting the ReportBadMessage
4640 // below, and to make sure we don't incorrectly try to use the blob_url_token.
4641 if (common_params->url.SchemeIsBlob() &&
4642 !validated_params->url.SchemeIsBlob()) {
4643 blob_url_token = mojo::NullRemote();
4644 }
4645
4646 if (blob_url_token && !validated_params->url.SchemeIsBlob()) {
4647 mojo::ReportBadMessage("Blob URL Token, but not a blob: URL");
4648 return;
4649 }
4650 scoped_refptr<network::SharedURLLoaderFactory> blob_url_loader_factory;
4651 if (blob_url_token) {
4652 blob_url_loader_factory =
4653 ChromeBlobStorageContext::URLLoaderFactoryForToken(
4654 GetSiteInstance()->GetBrowserContext(), std::move(blob_url_token));
4655 }
4656
4657 // If the request was for a blob URL, but no blob_url_token was passed in this
4658 // is not necessarily an error. Renderer initiated reloads for example are one
4659 // situation where a renderer currently doesn't have an easy way of resolving
4660 // the blob URL. For those situations resolve the blob URL here, as we don't
4661 // care about ordering with other blob URL manipulation anyway.
4662 if (validated_params->url.SchemeIsBlob() && !blob_url_loader_factory) {
4663 blob_url_loader_factory = ChromeBlobStorageContext::URLLoaderFactoryForUrl(
4664 GetSiteInstance()->GetBrowserContext(), validated_params->url);
4665 }
4666
4667 if (waiting_for_init_) {
4668 pending_navigate_ = std::make_unique<PendingNavigation>(
4669 std::move(validated_params), std::move(begin_params),
4670 std::move(blob_url_loader_factory), std::move(navigation_client),
4671 std::move(navigation_initiator));
4672 return;
4673 }
4674
4675 frame_tree_node()->navigator()->OnBeginNavigation(
4676 frame_tree_node(), std::move(validated_params), std::move(begin_params),
4677 std::move(blob_url_loader_factory), std::move(navigation_client),
4678 std::move(navigation_initiator), EnsurePrefetchedSignedExchangeCache(),
4679 web_bundle_handle_ ? web_bundle_handle_->MaybeCreateTracker() : nullptr);
4680 }
4681
SubresourceResponseStarted(const GURL & url,net::CertStatus cert_status)4682 void RenderFrameHostImpl::SubresourceResponseStarted(
4683 const GURL& url,
4684 net::CertStatus cert_status) {
4685 delegate_->SubresourceResponseStarted(url, cert_status);
4686 }
4687
ResourceLoadComplete(blink::mojom::ResourceLoadInfoPtr resource_load_info)4688 void RenderFrameHostImpl::ResourceLoadComplete(
4689 blink::mojom::ResourceLoadInfoPtr resource_load_info) {
4690 GlobalRequestID global_request_id;
4691 const bool is_frame_request =
4692 blink::IsRequestDestinationFrame(resource_load_info->request_destination);
4693 if (main_frame_request_ids_.first == resource_load_info->request_id) {
4694 global_request_id = main_frame_request_ids_.second;
4695 } else if (is_frame_request) {
4696 // The load complete message for the main resource arrived before
4697 // |DidCommitProvisionalLoad()|. We save the load info so
4698 // |ResourceLoadComplete()| can be called later in
4699 // |DidCommitProvisionalLoad()| when we can map to the global request ID.
4700 deferred_main_frame_load_info_ = std::move(resource_load_info);
4701 return;
4702 }
4703 delegate_->ResourceLoadComplete(this, global_request_id,
4704 std::move(resource_load_info));
4705 }
4706
HandleAXEvents(const std::vector<AXContentTreeUpdate> & updates,const std::vector<ui::AXEvent> & events,int32_t reset_token,HandleAXEventsCallback callback)4707 void RenderFrameHostImpl::HandleAXEvents(
4708 const std::vector<AXContentTreeUpdate>& updates,
4709 const std::vector<ui::AXEvent>& events,
4710 int32_t reset_token,
4711 HandleAXEventsCallback callback) {
4712 // Don't process this IPC if either we're waiting on a reset and this IPC
4713 // doesn't have the matching token ID, or if we're not waiting on a reset but
4714 // this message includes a reset token.
4715 if (accessibility_reset_token_ != reset_token) {
4716 std::move(callback).Run();
4717 return;
4718 }
4719 accessibility_reset_token_ = 0;
4720
4721 RenderWidgetHostViewBase* view = GetViewForAccessibility();
4722 ui::AXMode accessibility_mode = delegate_->GetAccessibilityMode();
4723 if (accessibility_mode.is_mode_off() || !view || !is_active()) {
4724 std::move(callback).Run();
4725 return;
4726 }
4727
4728 if (accessibility_mode.has_mode(ui::AXMode::kNativeAPIs))
4729 GetOrCreateBrowserAccessibilityManager();
4730
4731 AXEventNotificationDetails details;
4732 details.ax_tree_id = GetAXTreeID();
4733 details.events = events;
4734
4735 details.updates.resize(updates.size());
4736 for (size_t i = 0; i < updates.size(); ++i) {
4737 const AXContentTreeUpdate& src_update = updates[i];
4738 ui::AXTreeUpdate* dst_update = &details.updates[i];
4739 if (src_update.has_tree_data) {
4740 dst_update->has_tree_data = true;
4741 ax_content_tree_data_ = src_update.tree_data;
4742 AXContentTreeDataToAXTreeData(&dst_update->tree_data);
4743 }
4744 dst_update->root_id = src_update.root_id;
4745 dst_update->node_id_to_clear = src_update.node_id_to_clear;
4746 dst_update->event_from = src_update.event_from;
4747 dst_update->nodes.resize(src_update.nodes.size());
4748 for (size_t j = 0; j < src_update.nodes.size(); ++j) {
4749 AXContentNodeDataToAXNodeData(src_update.nodes[j], &dst_update->nodes[j]);
4750 }
4751 }
4752
4753 if (accessibility_mode.has_mode(ui::AXMode::kNativeAPIs))
4754 SendAccessibilityEventsToManager(details);
4755
4756 delegate_->AccessibilityEventReceived(details);
4757
4758 // For testing only.
4759 if (!accessibility_testing_callback_.is_null()) {
4760 if (details.events.empty()) {
4761 // Objects were marked dirty but no events were provided.
4762 // The callback must still run, otherwise dump event tests can hang.
4763 accessibility_testing_callback_.Run(this, ax::mojom::Event::kNone, 0);
4764 } else {
4765 // Call testing callback functions for each event to fire.
4766 for (auto& event : details.events) {
4767 if (static_cast<int>(event.event_type) < 0)
4768 continue;
4769
4770 accessibility_testing_callback_.Run(this, event.event_type, event.id);
4771 }
4772 }
4773 }
4774
4775 // Always send an ACK or the renderer can be in a bad state.
4776 std::move(callback).Run();
4777 }
4778
HandleAXLocationChanges(std::vector<mojom::LocationChangesPtr> changes)4779 void RenderFrameHostImpl::HandleAXLocationChanges(
4780 std::vector<mojom::LocationChangesPtr> changes) {
4781 if (accessibility_reset_token_ || !is_active())
4782 return;
4783
4784 RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>(
4785 render_view_host_->GetWidget()->GetView());
4786 if (view) {
4787 ui::AXMode accessibility_mode = delegate_->GetAccessibilityMode();
4788 if (accessibility_mode.has_mode(ui::AXMode::kNativeAPIs)) {
4789 BrowserAccessibilityManager* manager =
4790 GetOrCreateBrowserAccessibilityManager();
4791 if (manager)
4792 manager->OnLocationChanges(changes);
4793 }
4794
4795 // Send the updates to the automation extension API.
4796 std::vector<AXLocationChangeNotificationDetails> details;
4797 details.reserve(changes.size());
4798 for (auto& change : changes) {
4799 AXLocationChangeNotificationDetails detail;
4800 detail.id = change->id;
4801 detail.ax_tree_id = GetAXTreeID();
4802 detail.new_location = change->new_location;
4803 details.push_back(detail);
4804 }
4805 delegate_->AccessibilityLocationChangesReceived(details);
4806 }
4807 }
4808
RegisterMojoInterfaces()4809 void RenderFrameHostImpl::RegisterMojoInterfaces() {
4810 file_system_manager_.reset(new FileSystemManagerImpl(
4811 GetProcess()->GetID(),
4812 GetProcess()->GetStoragePartition()->GetFileSystemContext(),
4813 ChromeBlobStorageContext::GetFor(GetProcess()->GetBrowserContext())));
4814 }
4815
4816 media::MediaMetricsProvider::RecordAggregateWatchTimeCallback
GetRecordAggregateWatchTimeCallback()4817 RenderFrameHostImpl::GetRecordAggregateWatchTimeCallback() {
4818 return delegate_->GetRecordAggregateWatchTimeCallback();
4819 }
4820
ResetWaitingState()4821 void RenderFrameHostImpl::ResetWaitingState() {
4822 DCHECK(is_active());
4823
4824 // Whenever we reset the RFH state, we should not be waiting for beforeunload
4825 // or close acks. We clear them here to be safe, since they can cause
4826 // navigations to be ignored in DidCommitProvisionalLoad.
4827 if (is_waiting_for_beforeunload_completion_) {
4828 is_waiting_for_beforeunload_completion_ = false;
4829 if (beforeunload_timeout_)
4830 beforeunload_timeout_->Stop();
4831 has_shown_beforeunload_dialog_ = false;
4832 beforeunload_pending_replies_.clear();
4833 }
4834 send_before_unload_start_time_ = base::TimeTicks();
4835 render_view_host_->is_waiting_for_page_close_completion_ = false;
4836 }
4837
CanCommitOriginAndUrl(const url::Origin & origin,const GURL & url)4838 CanCommitStatus RenderFrameHostImpl::CanCommitOriginAndUrl(
4839 const url::Origin& origin,
4840 const GURL& url) {
4841 // If the --disable-web-security flag is specified, all bets are off and the
4842 // renderer process can send any origin it wishes.
4843 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
4844 switches::kDisableWebSecurity)) {
4845 return CanCommitStatus::CAN_COMMIT_ORIGIN_AND_URL;
4846 }
4847
4848 // Renderer-debug URLs can never be committed.
4849 if (IsRendererDebugURL(url))
4850 return CanCommitStatus::CANNOT_COMMIT_URL;
4851
4852 // TODO(creis): We should also check for WebUI pages here. Also, when the
4853 // out-of-process iframes implementation is ready, we should check for
4854 // cross-site URLs that are not allowed to commit in this process.
4855
4856 // MHTML subframes can supply URLs at commit time that do not match the
4857 // process lock. For example, it can be either "cid:..." or arbitrary URL at
4858 // which the frame was at the time of generating the MHTML
4859 // (e.g. "http://localhost"). In such cases, don't verify the URL, but require
4860 // the URL to commit in the process of the main frame.
4861 if (!frame_tree_node()->IsMainFrame()) {
4862 RenderFrameHostImpl* main_frame = GetMainFrame();
4863 if (main_frame->is_mhtml_document()) {
4864 if (IsSameSiteInstance(main_frame))
4865 return CanCommitStatus::CAN_COMMIT_ORIGIN_AND_URL;
4866
4867 // If an MHTML subframe commits in a different process (even one that
4868 // appears correct for the subframe's URL), then we aren't correctly
4869 // loading it from the archive and should kill the renderer.
4870 base::debug::SetCrashKeyString(
4871 base::debug::AllocateCrashKeyString(
4872 "oopif_in_mhtml_page", base::debug::CrashKeySize::Size32),
4873 is_mhtml_document() ? "is_mhtml_doc" : "not_mhtml_doc");
4874 return CanCommitStatus::CANNOT_COMMIT_URL;
4875 }
4876 }
4877
4878 // Give the client a chance to disallow URLs from committing.
4879 if (!GetContentClient()->browser()->CanCommitURL(GetProcess(), url))
4880 return CanCommitStatus::CANNOT_COMMIT_URL;
4881
4882 auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
4883 const CanCommitStatus can_commit_status = policy->CanCommitOriginAndUrl(
4884 GetProcess()->GetID(), GetSiteInstance()->GetIsolationContext(), origin,
4885 url);
4886 if (can_commit_status != CanCommitStatus::CAN_COMMIT_ORIGIN_AND_URL)
4887 return can_commit_status;
4888
4889 const auto origin_tuple_or_precursor_tuple =
4890 origin.GetTupleOrPrecursorTupleIfOpaque();
4891 if (origin_tuple_or_precursor_tuple.IsValid()) {
4892 // Verify that the origin/precursor is allowed to commit in this process.
4893 // Note: This also handles non-standard cases for |url|, such as
4894 // about:blank, data, and blob URLs.
4895
4896 // Renderer-debug URLs can never be committed.
4897 if (IsRendererDebugURL(origin_tuple_or_precursor_tuple.GetURL()))
4898 return CanCommitStatus::CANNOT_COMMIT_ORIGIN;
4899
4900 // Give the client a chance to disallow origin URLs from committing.
4901 // TODO(acolwell): Fix this code to work with opaque origins. Currently
4902 // some opaque origin precursors, like chrome-extension schemes, can trigger
4903 // the commit to fail. These need to be investigated.
4904 if (!origin.opaque() && !GetContentClient()->browser()->CanCommitURL(
4905 GetProcess(), origin.GetURL())) {
4906 return CanCommitStatus::CANNOT_COMMIT_ORIGIN;
4907 }
4908 }
4909
4910 return CanCommitStatus::CAN_COMMIT_ORIGIN_AND_URL;
4911 }
4912
NavigateToInterstitialURL(const GURL & data_url)4913 void RenderFrameHostImpl::NavigateToInterstitialURL(const GURL& data_url) {
4914 TRACE_EVENT1("navigation", "RenderFrameHostImpl::NavigateToInterstitialURL",
4915 "frame_tree_node", frame_tree_node_->frame_tree_node_id());
4916 DCHECK(data_url.SchemeIs(url::kDataScheme));
4917 NavigationDownloadPolicy download_policy;
4918 download_policy.SetDisallowed(NavigationDownloadType::kInterstitial);
4919
4920 auto common_params = mojom::CommonNavigationParams::New(
4921 data_url, base::nullopt, blink::mojom::Referrer::New(),
4922 ui::PAGE_TRANSITION_LINK, mojom::NavigationType::DIFFERENT_DOCUMENT,
4923 download_policy, false, GURL(), GURL(), PREVIEWS_OFF,
4924 base::TimeTicks::Now(), "GET", nullptr,
4925 network::mojom::SourceLocation::New(),
4926 false /* started_from_context_menu */, false /* has_user_gesture */,
4927 CreateInitiatorCSPInfo(), std::vector<int>(), std::string(),
4928 false /* is_history_navigation_in_new_child_frame */, base::TimeTicks());
4929 CommitNavigation(nullptr /* navigation_request */, std::move(common_params),
4930 CreateCommitNavigationParams(), nullptr /* response_head */,
4931 mojo::ScopedDataPipeConsumerHandle(),
4932 network::mojom::URLLoaderClientEndpointsPtr(), false,
4933 base::nullopt, base::nullopt /* subresource_overrides */,
4934 nullptr /* provider_info */,
4935 base::UnguessableToken::Create() /* not traced */,
4936 nullptr /* web_bundle_factory */);
4937 }
4938
Stop()4939 void RenderFrameHostImpl::Stop() {
4940 TRACE_EVENT1("navigation", "RenderFrameHostImpl::Stop", "frame_tree_node",
4941 frame_tree_node_->frame_tree_node_id());
4942 Send(new FrameMsg_Stop(routing_id_));
4943 }
4944
DispatchBeforeUnload(BeforeUnloadType type,bool is_reload)4945 void RenderFrameHostImpl::DispatchBeforeUnload(BeforeUnloadType type,
4946 bool is_reload) {
4947 bool for_navigation =
4948 type == BeforeUnloadType::BROWSER_INITIATED_NAVIGATION ||
4949 type == BeforeUnloadType::RENDERER_INITIATED_NAVIGATION;
4950 bool for_inner_delegate_attach =
4951 type == BeforeUnloadType::INNER_DELEGATE_ATTACH;
4952 DCHECK(for_navigation || for_inner_delegate_attach || !is_reload);
4953
4954 // TAB_CLOSE and DISCARD should only dispatch beforeunload on main frames.
4955 DCHECK(type == BeforeUnloadType::BROWSER_INITIATED_NAVIGATION ||
4956 type == BeforeUnloadType::RENDERER_INITIATED_NAVIGATION ||
4957 type == BeforeUnloadType::INNER_DELEGATE_ATTACH ||
4958 frame_tree_node_->IsMainFrame());
4959
4960 if (!for_navigation) {
4961 // Cancel any pending navigations, to avoid their navigation commit/fail
4962 // event from wiping out the is_waiting_for_beforeunload_completion_ state.
4963 if (frame_tree_node_->navigation_request() &&
4964 frame_tree_node_->navigation_request()->IsNavigationStarted()) {
4965 frame_tree_node_->navigation_request()->set_net_error(net::ERR_ABORTED);
4966 }
4967 frame_tree_node_->ResetNavigationRequest(false);
4968 }
4969
4970 // In renderer-initiated navigations, don't check for beforeunload in the
4971 // navigating frame, as it has already run beforeunload before it sent the
4972 // BeginNavigation IPC.
4973 bool check_subframes_only =
4974 type == BeforeUnloadType::RENDERER_INITIATED_NAVIGATION;
4975 if (!ShouldDispatchBeforeUnload(check_subframes_only)) {
4976 // When running beforeunload for navigations, ShouldDispatchBeforeUnload()
4977 // is checked earlier and we would only get here if it had already returned
4978 // true.
4979 DCHECK(!for_navigation);
4980
4981 // Dispatch the ACK to prevent re-entrancy.
4982 base::OnceClosure task = base::BindOnce(
4983 [](base::WeakPtr<RenderFrameHostImpl> self) {
4984 if (!self)
4985 return;
4986 self->frame_tree_node_->render_manager()->BeforeUnloadCompleted(
4987 true, base::TimeTicks::Now());
4988 },
4989 weak_ptr_factory_.GetWeakPtr());
4990 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, std::move(task));
4991 return;
4992 }
4993 TRACE_EVENT_ASYNC_BEGIN1("navigation", "RenderFrameHostImpl BeforeUnload",
4994 this, "&RenderFrameHostImpl", (void*)this);
4995
4996 // This may be called more than once (if the user clicks the tab close button
4997 // several times, or if they click the tab close button then the browser close
4998 // button), and we only send the message once.
4999 if (is_waiting_for_beforeunload_completion_) {
5000 // Some of our close messages could be for the tab, others for cross-site
5001 // transitions. We always want to think it's for closing the tab if any
5002 // of the messages were, since otherwise it might be impossible to close
5003 // (if there was a cross-site "close" request pending when the user clicked
5004 // the close button). We want to keep the "for cross site" flag only if
5005 // both the old and the new ones are also for cross site.
5006 unload_ack_is_for_navigation_ =
5007 unload_ack_is_for_navigation_ && for_navigation;
5008 } else {
5009 // Start the hang monitor in case the renderer hangs in the beforeunload
5010 // handler.
5011 is_waiting_for_beforeunload_completion_ = true;
5012 beforeunload_dialog_request_cancels_unload_ = false;
5013 unload_ack_is_for_navigation_ = for_navigation;
5014 send_before_unload_start_time_ = base::TimeTicks::Now();
5015 if (render_view_host_->GetDelegate()->IsJavaScriptDialogShowing()) {
5016 // If there is a JavaScript dialog up, don't bother sending the renderer
5017 // the unload event because it is known unresponsive, waiting for the
5018 // reply from the dialog. If this incoming request is for a DISCARD be
5019 // sure to reply with |proceed = false|, because the presence of a dialog
5020 // indicates that the page can't be discarded.
5021 SimulateBeforeUnloadCompleted(type != BeforeUnloadType::DISCARD);
5022 } else {
5023 // Start a timer that will be shared by all frames that need to run
5024 // beforeunload in the current frame's subtree.
5025 if (beforeunload_timeout_)
5026 beforeunload_timeout_->Start(beforeunload_timeout_delay_);
5027
5028 beforeunload_pending_replies_.clear();
5029 beforeunload_dialog_request_cancels_unload_ =
5030 (type == BeforeUnloadType::DISCARD);
5031
5032 // Run beforeunload in this frame and its cross-process descendant
5033 // frames, in parallel.
5034 CheckOrDispatchBeforeUnloadForSubtree(check_subframes_only,
5035 true /* send_ipc */, is_reload);
5036 }
5037 }
5038 }
5039
CheckOrDispatchBeforeUnloadForSubtree(bool subframes_only,bool send_ipc,bool is_reload)5040 bool RenderFrameHostImpl::CheckOrDispatchBeforeUnloadForSubtree(
5041 bool subframes_only,
5042 bool send_ipc,
5043 bool is_reload) {
5044 bool found_beforeunload = false;
5045 for (FrameTreeNode* node :
5046 frame_tree_node_->frame_tree()->SubtreeNodes(frame_tree_node_)) {
5047 RenderFrameHostImpl* rfh = node->current_frame_host();
5048
5049 // If |subframes_only| is true, skip this frame and its same-site
5050 // descendants. This happens for renderer-initiated navigations, where
5051 // these frames have already run beforeunload.
5052 if (subframes_only && rfh->GetSiteInstance() == GetSiteInstance())
5053 continue;
5054
5055 // No need to run beforeunload if the RenderFrame isn't live.
5056 if (!rfh->IsRenderFrameLive())
5057 continue;
5058
5059 // Only run beforeunload in frames that have registered a beforeunload
5060 // handler.
5061 bool should_run_beforeunload = rfh->has_before_unload_handler_;
5062 // TODO(alexmos): Many tests, as well as some DevTools cases, currently
5063 // assume that beforeunload for a navigating/closing frame is always sent
5064 // to the renderer. For now, keep this assumption by checking |rfh ==
5065 // this|. In the future, this condition should be removed, and beforeunload
5066 // should only be sent when a handler is registered. For subframes of a
5067 // navigating/closing frame, this assumption was never present, so
5068 // subframes are included only if they have registered a beforeunload
5069 // handler.
5070 if (rfh == this)
5071 should_run_beforeunload = true;
5072
5073 if (!should_run_beforeunload)
5074 continue;
5075
5076 // If we're only checking whether there's at least one frame with
5077 // beforeunload, then we've just found one, so we can return now.
5078 found_beforeunload = true;
5079 if (!send_ipc)
5080 return true;
5081
5082 // Otherwise, figure out whether we need to send the IPC, or whether this
5083 // beforeunload was already triggered by an ancestor frame's IPC.
5084
5085 // Only send beforeunload to local roots, and let Blink handle any
5086 // same-site frames under them. That is, if a frame has a beforeunload
5087 // handler, ask its local root to run it. If we've already sent the message
5088 // to that local root, skip this frame. For example, in A1(A2,A3), if A2
5089 // and A3 contain beforeunload handlers, and all three frames are
5090 // same-site, we ask A1 to run beforeunload for all three frames, and only
5091 // ask it once.
5092 while (!rfh->is_local_root() && rfh != this)
5093 rfh = rfh->GetParent();
5094 if (base::Contains(beforeunload_pending_replies_, rfh))
5095 continue;
5096
5097 // For a case like A(B(A)), it's not necessary to send an IPC for the
5098 // innermost frame, as Blink will walk all same-site (local)
5099 // descendants. Detect cases like this and skip them.
5100 bool has_same_site_ancestor = false;
5101 for (auto* added_rfh : beforeunload_pending_replies_) {
5102 if (rfh->IsDescendantOf(added_rfh) &&
5103 rfh->GetSiteInstance() == added_rfh->GetSiteInstance()) {
5104 has_same_site_ancestor = true;
5105 break;
5106 }
5107 }
5108 if (has_same_site_ancestor)
5109 continue;
5110
5111 // Add |rfh| to the list of frames that need to receive beforeunload
5112 // ACKs.
5113 beforeunload_pending_replies_.insert(rfh);
5114
5115 SendBeforeUnload(is_reload, rfh->GetWeakPtr());
5116 }
5117
5118 return found_beforeunload;
5119 }
5120
SimulateBeforeUnloadCompleted(bool proceed)5121 void RenderFrameHostImpl::SimulateBeforeUnloadCompleted(bool proceed) {
5122 DCHECK(is_waiting_for_beforeunload_completion_);
5123 base::TimeTicks approx_renderer_start_time = send_before_unload_start_time_;
5124
5125 // Dispatch the ACK to prevent re-entrancy.
5126 base::ThreadTaskRunnerHandle::Get()->PostTask(
5127 FROM_HERE,
5128 base::BindOnce(&RenderFrameHostImpl::ProcessBeforeUnloadCompleted,
5129 weak_ptr_factory_.GetWeakPtr(), proceed,
5130 true /* treat_as_final_completion_callback */,
5131 approx_renderer_start_time, base::TimeTicks::Now()));
5132 }
5133
ShouldDispatchBeforeUnload(bool check_subframes_only)5134 bool RenderFrameHostImpl::ShouldDispatchBeforeUnload(
5135 bool check_subframes_only) {
5136 return CheckOrDispatchBeforeUnloadForSubtree(
5137 check_subframes_only, false /* send_ipc */, false /* is_reload */);
5138 }
5139
SetBeforeUnloadTimeoutDelayForTesting(const base::TimeDelta & timeout)5140 void RenderFrameHostImpl::SetBeforeUnloadTimeoutDelayForTesting(
5141 const base::TimeDelta& timeout) {
5142 beforeunload_timeout_delay_ = timeout;
5143 }
5144
StartPendingDeletionOnSubtree()5145 void RenderFrameHostImpl::StartPendingDeletionOnSubtree() {
5146 ResetNavigationsForPendingDeletion();
5147
5148 DCHECK_NE(UnloadState::NotRun, unload_state_);
5149 for (std::unique_ptr<FrameTreeNode>& child_frame : children_) {
5150 for (FrameTreeNode* node :
5151 frame_tree_node_->frame_tree()->SubtreeNodes(child_frame.get())) {
5152 RenderFrameHostImpl* child = node->current_frame_host();
5153 if (child->unload_state_ != UnloadState::NotRun)
5154 continue;
5155
5156 // Blink handles deletion of all same-process descendants, running their
5157 // unload handler if necessary. So delegate sending IPC on the topmost
5158 // ancestor using the same process.
5159 RenderFrameHostImpl* local_ancestor = child;
5160 for (auto* rfh = child->parent_; rfh != parent_; rfh = rfh->parent_) {
5161 if (rfh->GetSiteInstance() == child->GetSiteInstance())
5162 local_ancestor = rfh;
5163 }
5164
5165 local_ancestor->DeleteRenderFrame(FrameDeleteIntention::kNotMainFrame);
5166 if (local_ancestor != child) {
5167 child->unload_state_ = child->has_unload_handler()
5168 ? UnloadState::InProgress
5169 : UnloadState::Completed;
5170 }
5171
5172 node->frame_tree()->FrameUnloading(node);
5173 }
5174 }
5175 }
5176
PendingDeletionCheckCompleted()5177 void RenderFrameHostImpl::PendingDeletionCheckCompleted() {
5178 if (unload_state_ == UnloadState::Completed && children_.empty()) {
5179 if (is_waiting_for_unload_ack_)
5180 OnUnloaded();
5181 else
5182 parent_->RemoveChild(frame_tree_node_);
5183 }
5184 }
5185
PendingDeletionCheckCompletedOnSubtree()5186 void RenderFrameHostImpl::PendingDeletionCheckCompletedOnSubtree() {
5187 if (children_.empty()) {
5188 PendingDeletionCheckCompleted();
5189 return;
5190 }
5191
5192 // Collect children first before calling PendingDeletionCheckCompleted() on
5193 // them, because it may delete them.
5194 std::vector<RenderFrameHostImpl*> children_rfh;
5195 for (std::unique_ptr<FrameTreeNode>& child : children_)
5196 children_rfh.push_back(child->current_frame_host());
5197
5198 for (RenderFrameHostImpl* child_rfh : children_rfh)
5199 child_rfh->PendingDeletionCheckCompletedOnSubtree();
5200 }
5201
ResetNavigationsForPendingDeletion()5202 void RenderFrameHostImpl::ResetNavigationsForPendingDeletion() {
5203 for (auto& child : children_)
5204 child->current_frame_host()->ResetNavigationsForPendingDeletion();
5205 ResetNavigationRequests();
5206 frame_tree_node_->ResetNavigationRequest(false);
5207 frame_tree_node_->render_manager()->CleanUpNavigation();
5208 }
5209
OnUnloadTimeout()5210 void RenderFrameHostImpl::OnUnloadTimeout() {
5211 DCHECK_NE(unload_state_, UnloadState::NotRun);
5212 parent_->RemoveChild(frame_tree_node_);
5213 }
5214
UpdateOpener()5215 void RenderFrameHostImpl::UpdateOpener() {
5216 TRACE_EVENT1("navigation", "RenderFrameHostImpl::UpdateOpener",
5217 "frame_tree_node", frame_tree_node_->frame_tree_node_id());
5218
5219 // This frame (the frame whose opener is being updated) might not have had
5220 // proxies for the new opener chain in its SiteInstance. Make sure they
5221 // exist.
5222 if (frame_tree_node_->opener()) {
5223 frame_tree_node_->opener()->render_manager()->CreateOpenerProxies(
5224 GetSiteInstance(), frame_tree_node_);
5225 }
5226
5227 int opener_routing_id =
5228 frame_tree_node_->render_manager()->GetOpenerRoutingID(GetSiteInstance());
5229 Send(new FrameMsg_UpdateOpener(GetRoutingID(), opener_routing_id));
5230 }
5231
SetFocusedFrame()5232 void RenderFrameHostImpl::SetFocusedFrame() {
5233 GetAssociatedLocalFrame()->Focus();
5234 }
5235
AdvanceFocus(blink::mojom::FocusType type,RenderFrameProxyHost * source_proxy)5236 void RenderFrameHostImpl::AdvanceFocus(blink::mojom::FocusType type,
5237 RenderFrameProxyHost* source_proxy) {
5238 DCHECK(!source_proxy ||
5239 (source_proxy->GetProcess()->GetID() == GetProcess()->GetID()));
5240 int32_t source_proxy_routing_id = MSG_ROUTING_NONE;
5241 if (source_proxy)
5242 source_proxy_routing_id = source_proxy->GetRoutingID();
5243 Send(
5244 new FrameMsg_AdvanceFocus(GetRoutingID(), type, source_proxy_routing_id));
5245 }
5246
JavaScriptDialogClosed(JavaScriptDialogCallback dialog_closed_callback,bool success,const base::string16 & user_input)5247 void RenderFrameHostImpl::JavaScriptDialogClosed(
5248 JavaScriptDialogCallback dialog_closed_callback,
5249 bool success,
5250 const base::string16& user_input) {
5251 GetProcess()->SetBlocked(false);
5252 std::move(dialog_closed_callback).Run(success, user_input);
5253 // If executing as part of beforeunload event handling, there may have been
5254 // timers stopped in this frame or a frame up in the frame hierarchy. Restart
5255 // any timers that were stopped in OnRunBeforeUnloadConfirm().
5256 for (RenderFrameHostImpl* frame = this; frame; frame = frame->GetParent()) {
5257 if (frame->is_waiting_for_beforeunload_completion_ &&
5258 frame->beforeunload_timeout_) {
5259 frame->beforeunload_timeout_->Start(beforeunload_timeout_delay_);
5260 }
5261 }
5262 }
5263
CommitNavigation(NavigationRequest * navigation_request,mojom::CommonNavigationParamsPtr common_params,mojom::CommitNavigationParamsPtr commit_params,network::mojom::URLResponseHeadPtr response_head,mojo::ScopedDataPipeConsumerHandle response_body,network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,bool is_view_source,base::Optional<SubresourceLoaderParams> subresource_loader_params,base::Optional<std::vector<mojom::TransferrableURLLoaderPtr>> subresource_overrides,blink::mojom::ServiceWorkerProviderInfoForClientPtr provider_info,const base::UnguessableToken & devtools_navigation_token,std::unique_ptr<WebBundleHandle> web_bundle_handle)5264 void RenderFrameHostImpl::CommitNavigation(
5265 NavigationRequest* navigation_request,
5266 mojom::CommonNavigationParamsPtr common_params,
5267 mojom::CommitNavigationParamsPtr commit_params,
5268 network::mojom::URLResponseHeadPtr response_head,
5269 mojo::ScopedDataPipeConsumerHandle response_body,
5270 network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
5271 bool is_view_source,
5272 base::Optional<SubresourceLoaderParams> subresource_loader_params,
5273 base::Optional<std::vector<mojom::TransferrableURLLoaderPtr>>
5274 subresource_overrides,
5275 blink::mojom::ServiceWorkerProviderInfoForClientPtr provider_info,
5276 const base::UnguessableToken& devtools_navigation_token,
5277 std::unique_ptr<WebBundleHandle> web_bundle_handle) {
5278 web_bundle_handle_ = std::move(web_bundle_handle);
5279
5280 TRACE_EVENT2("navigation", "RenderFrameHostImpl::CommitNavigation",
5281 "frame_tree_node", frame_tree_node_->frame_tree_node_id(), "url",
5282 common_params->url.possibly_invalid_spec());
5283 DCHECK(!IsRendererDebugURL(common_params->url));
5284
5285 bool is_mhtml_iframe =
5286 navigation_request && navigation_request->IsForMhtmlSubframe();
5287
5288 // A |response| and a |url_loader_client_endpoints| must always be provided,
5289 // except for edge cases, where another way to load the document exist.
5290 DCHECK((response_head && url_loader_client_endpoints) ||
5291 common_params->url.SchemeIs(url::kDataScheme) ||
5292 NavigationTypeUtils::IsSameDocument(common_params->navigation_type) ||
5293 !IsURLHandledByNetworkStack(common_params->url) || is_mhtml_iframe);
5294
5295 // All children of MHTML documents must be MHTML documents.
5296 // As a defensive measure, crash the browser if something went wrong.
5297 if (!frame_tree_node()->IsMainFrame()) {
5298 RenderFrameHostImpl* root = GetMainFrame();
5299 if (root->is_mhtml_document_ &&
5300 !common_params->url.SchemeIs(url::kDataScheme)) {
5301 bool loaded_from_outside_the_archive =
5302 response_head || url_loader_client_endpoints;
5303 CHECK(!loaded_from_outside_the_archive);
5304 CHECK(is_mhtml_iframe);
5305 CHECK_EQ(GetSiteInstance(), root->GetSiteInstance());
5306 CHECK_EQ(GetProcess(), root->GetProcess());
5307 } else {
5308 DCHECK(!is_mhtml_iframe);
5309 }
5310 }
5311
5312 bool is_srcdoc = common_params->url.IsAboutSrcdoc();
5313 if (is_srcdoc) {
5314 // Main frame srcdoc navigation are meaningless. They are blocked whenever a
5315 // navigation attempt is made. It shouldn't reach CommitNavigation.
5316 CHECK(!frame_tree_node_->IsMainFrame());
5317
5318 // An about:srcdoc document is always same SiteInstance with its parent.
5319 // Otherwise, it won't be able to load. The parent's document contains the
5320 // iframe and its srcdoc attribute.
5321 CHECK_EQ(GetSiteInstance(), parent_->GetSiteInstance());
5322 }
5323
5324 // If this is an attempt to commit a URL in an incompatible process, capture a
5325 // crash dump to diagnose why it is occurring.
5326 // TODO(creis): Remove this check after we've gathered enough information to
5327 // debug issues with browser-side security checks. https://crbug.com/931895.
5328 auto* policy = ChildProcessSecurityPolicyImpl::GetInstance();
5329 const GURL& lock_url = GetSiteInstance()->lock_url();
5330 if (lock_url != GURL(kUnreachableWebDataURL) &&
5331 common_params->url.IsStandard() &&
5332 !policy->CanAccessDataForOrigin(GetProcess()->GetID(),
5333 common_params->url) &&
5334 !is_mhtml_iframe) {
5335 base::debug::SetCrashKeyString(
5336 base::debug::AllocateCrashKeyString("lock_url",
5337 base::debug::CrashKeySize::Size64),
5338 lock_url.possibly_invalid_spec());
5339 base::debug::SetCrashKeyString(
5340 base::debug::AllocateCrashKeyString("commit_origin",
5341 base::debug::CrashKeySize::Size64),
5342 common_params->url.GetOrigin().spec());
5343 base::debug::SetCrashKeyString(
5344 base::debug::AllocateCrashKeyString("is_main_frame",
5345 base::debug::CrashKeySize::Size32),
5346 frame_tree_node_->IsMainFrame() ? "true" : "false");
5347 NOTREACHED() << "Commiting in incompatible process for URL: " << lock_url
5348 << " lock vs " << common_params->url.GetOrigin();
5349 base::debug::DumpWithoutCrashing();
5350 }
5351
5352 const bool is_first_navigation = !has_committed_any_navigation_;
5353 has_committed_any_navigation_ = true;
5354
5355 UpdatePermissionsForNavigation(*common_params, *commit_params);
5356
5357 // Get back to a clean state, in case we start a new navigation without
5358 // completing an unload handler.
5359 ResetWaitingState();
5360
5361 // The renderer can exit view source mode when any error or cancellation
5362 // happen. When reusing the same renderer, overwrite to recover the mode.
5363 if (is_view_source && IsCurrent()) {
5364 DCHECK(!GetParent());
5365 GetAssociatedLocalFrame()->EnableViewSourceMode();
5366 }
5367
5368 // TODO(lfg): The renderer is not able to handle a null response, so the
5369 // browser provides an empty response instead. See the DCHECK in the beginning
5370 // of this method for the edge cases where a response isn't provided.
5371 network::mojom::URLResponseHeadPtr head =
5372 response_head ? std::move(response_head)
5373 : network::mojom::URLResponseHead::New();
5374 const bool is_same_document =
5375 NavigationTypeUtils::IsSameDocument(common_params->navigation_type);
5376
5377 // TODO(crbug.com/979296): Consider changing this code to copy an origin
5378 // instead of creating one from a URL which lacks opacity information.
5379 url::Origin main_world_origin_for_url_loader_factory =
5380 GetOriginForURLLoaderFactory(navigation_request);
5381
5382 // Network isolation key should be filled before the URLLoaderFactory for
5383 // sub-resources is created. Only update for cross document navigations since
5384 // for opaque origin same document navigations, a new origin should not be
5385 // created as that would be different from the original.
5386 if (!is_same_document) {
5387 network_isolation_key_ = net::NetworkIsolationKey(
5388 ComputeTopFrameOrigin(main_world_origin_for_url_loader_factory),
5389 main_world_origin_for_url_loader_factory);
5390 }
5391 DCHECK(network_isolation_key_.IsFullyPopulated());
5392
5393 if (navigation_request && navigation_request->appcache_handle()) {
5394 // AppCache may create a subresource URLLoaderFactory later, so make sure it
5395 // has the correct origin to use when calling
5396 // ContentBrowserClient::WillCreateURLLoaderFactory().
5397 navigation_request->appcache_handle()
5398 ->host()
5399 ->set_origin_for_url_loader_factory(
5400 main_world_origin_for_url_loader_factory);
5401 }
5402 std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
5403 subresource_loader_factories;
5404 if ((!is_same_document || is_first_navigation) && !is_srcdoc) {
5405 recreate_default_url_loader_factory_after_network_service_crash_ = false;
5406 subresource_loader_factories =
5407 std::make_unique<blink::PendingURLLoaderFactoryBundle>();
5408 BrowserContext* browser_context = GetSiteInstance()->GetBrowserContext();
5409
5410 // NOTE: On Network Service navigations, we want to ensure that a frame is
5411 // given everything it will need to load any accessible subresources. We
5412 // however only do this for cross-document navigations, because the
5413 // alternative would be redundant effort.
5414 if (subresource_loader_params &&
5415 subresource_loader_params->pending_appcache_loader_factory.is_valid()) {
5416 // If the caller has supplied a factory for AppCache, use it.
5417 mojo::Remote<network::mojom::URLLoaderFactory> appcache_remote(std::move(
5418 subresource_loader_params->pending_appcache_loader_factory));
5419
5420 mojo::PendingRemote<network::mojom::URLLoaderFactory>
5421 appcache_proxied_remote;
5422 auto appcache_proxied_receiver =
5423 appcache_proxied_remote.InitWithNewPipeAndPassReceiver();
5424 bool use_proxy =
5425 GetContentClient()->browser()->WillCreateURLLoaderFactory(
5426 browser_context, this, GetProcess()->GetID(),
5427 ContentBrowserClient::URLLoaderFactoryType::kDocumentSubResource,
5428 main_world_origin_for_url_loader_factory,
5429 base::nullopt /* navigation_id */, &appcache_proxied_receiver,
5430 nullptr /* header_client */, nullptr /* bypass_redirect_checks */,
5431 nullptr /* disable_secure_dns */, nullptr /* factory_override */);
5432 if (use_proxy) {
5433 appcache_remote->Clone(std::move(appcache_proxied_receiver));
5434 appcache_remote.reset();
5435 appcache_remote.Bind(std::move(appcache_proxied_remote));
5436 }
5437
5438 subresource_loader_factories->pending_appcache_factory() =
5439 appcache_remote.Unbind();
5440 }
5441
5442 non_network_url_loader_factories_.clear();
5443
5444 // Set up the default factory.
5445 mojo::PendingRemote<network::mojom::URLLoaderFactory>
5446 pending_default_factory;
5447
5448 // See if this is for WebUI.
5449 std::string scheme = common_params->url.scheme();
5450 const auto& webui_schemes = URLDataManagerBackend::GetWebUISchemes();
5451 if (base::Contains(webui_schemes, scheme)) {
5452 mojo::PendingRemote<network::mojom::URLLoaderFactory> factory_for_webui;
5453 auto factory_receiver =
5454 factory_for_webui.InitWithNewPipeAndPassReceiver();
5455 GetContentClient()->browser()->WillCreateURLLoaderFactory(
5456 browser_context, this, GetProcess()->GetID(),
5457 ContentBrowserClient::URLLoaderFactoryType::kDocumentSubResource,
5458 main_world_origin_for_url_loader_factory,
5459 base::nullopt /* navigation_id */, &factory_receiver,
5460 nullptr /* header_client */, nullptr /* bypass_redirect_checks */,
5461 nullptr /* disable_secure_dns */, nullptr /* factory_override */);
5462 CreateWebUIURLLoaderBinding(this, scheme, std::move(factory_receiver));
5463 // If the renderer has webui bindings, then don't give it access to
5464 // network loader for security reasons.
5465 // http://crbug.com/829412: make an exception for a small whitelist
5466 // of WebUIs that need to be fixed to not make network requests in JS.
5467 if ((enabled_bindings_ & kWebUIBindingsPolicyMask) &&
5468 !GetContentClient()->browser()->IsWebUIAllowedToMakeNetworkRequests(
5469 url::Origin::Create(common_params->url.GetOrigin()))) {
5470 pending_default_factory = std::move(factory_for_webui);
5471 // WebUIURLLoaderFactory will kill the renderer if it sees a request
5472 // with a non-chrome scheme. Register a URLLoaderFactory for the about
5473 // scheme so about:blank doesn't kill the renderer.
5474 non_network_url_loader_factories_[url::kAboutScheme] =
5475 std::make_unique<AboutURLLoaderFactory>();
5476 } else {
5477 // This is a webui scheme that doesn't have webui bindings. Give it
5478 // access to the network loader as it might require it.
5479 subresource_loader_factories->pending_scheme_specific_factories()
5480 .emplace(scheme, std::move(factory_for_webui));
5481 }
5482 }
5483
5484 if (!pending_default_factory) {
5485 // Otherwise default to a Network Service-backed loader from the
5486 // appropriate NetworkContext.
5487 // TODO(clamy): Always use the NavigationRequest's ClientSecurityState
5488 // when all interstitials are committed and we are guaranteed to have a
5489 // NavigationRequest in this function.
5490 recreate_default_url_loader_factory_after_network_service_crash_ = true;
5491 CrossOriginEmbedderPolicyReporter* const coep_reporter =
5492 navigation_request ? navigation_request->coep_reporter() : nullptr;
5493 mojo::PendingRemote<network::mojom::CrossOriginEmbedderPolicyReporter>
5494 coep_reporter_remote;
5495 if (coep_reporter) {
5496 coep_reporter->Clone(
5497 coep_reporter_remote.InitWithNewPipeAndPassReceiver());
5498 }
5499 bool bypass_redirect_checks =
5500 CreateNetworkServiceDefaultFactoryAndObserve(
5501 CreateURLLoaderFactoryParamsForMainWorld(
5502 main_world_origin_for_url_loader_factory,
5503 navigation_request
5504 ? mojo::Clone(navigation_request->client_security_state())
5505 : network::mojom::ClientSecurityState::New(),
5506 std::move(coep_reporter_remote)),
5507 pending_default_factory.InitWithNewPipeAndPassReceiver());
5508 subresource_loader_factories->set_bypass_redirect_checks(
5509 bypass_redirect_checks);
5510 }
5511
5512 bool navigation_to_web_bundle = false;
5513
5514 if (web_bundle_handle_ && web_bundle_handle_->IsReadyForLoading()) {
5515 navigation_to_web_bundle = true;
5516 mojo::Remote<network::mojom::URLLoaderFactory> fallback_factory(
5517 std::move(pending_default_factory));
5518 web_bundle_handle_->CreateURLLoaderFactory(
5519 pending_default_factory.InitWithNewPipeAndPassReceiver(),
5520 std::move(fallback_factory));
5521 DCHECK(web_bundle_handle_->navigation_info());
5522 commit_params->web_bundle_physical_url =
5523 web_bundle_handle_->navigation_info()->source().url();
5524 if (web_bundle_handle_->claimed_url().is_valid()) {
5525 commit_params->web_bundle_claimed_url =
5526 web_bundle_handle_->claimed_url();
5527 }
5528 }
5529
5530 DCHECK(pending_default_factory);
5531 subresource_loader_factories->pending_default_factory() =
5532 std::move(pending_default_factory);
5533
5534 // Only file resources and about:blank with an initiator that can load files
5535 // can load file subresources.
5536 //
5537 // Other URLs like about:srcdoc might be able load files, but only because
5538 // they will inherit loaders from their parents instead of the ones
5539 // provided by the browser process here.
5540 // TODO(crbug.com/949510): Make about:srcdoc also use this path instead of
5541 // inheriting loaders from the parent.
5542 //
5543 // For loading Web Bundle files, we don't set FileURLLoaderFactory.
5544 // Because loading local files from a Web Bundle file is prohibited.
5545 //
5546 // TODO(crbug.com/888079): In the future, use
5547 // GetOriginForURLLoaderFactory/GetOriginToCommit.
5548 if ((common_params->url.SchemeIsFile() ||
5549 (common_params->url.IsAboutBlank() &&
5550 common_params->initiator_origin &&
5551 common_params->initiator_origin->scheme() == url::kFileScheme)) &&
5552 !navigation_to_web_bundle) {
5553 auto file_factory = std::make_unique<FileURLLoaderFactory>(
5554 browser_context->GetPath(),
5555 browser_context->GetSharedCorsOriginAccessList(),
5556 // A user-initiated navigation is USER_BLOCKING.
5557 base::TaskPriority::USER_BLOCKING);
5558 non_network_url_loader_factories_.emplace(url::kFileScheme,
5559 std::move(file_factory));
5560 }
5561
5562 #if defined(OS_ANDROID)
5563 if (common_params->url.SchemeIs(url::kContentScheme)) {
5564 // Only content:// URLs can load content:// subresources
5565 auto content_factory = std::make_unique<ContentURLLoaderFactory>(
5566 base::ThreadPool::CreateSequencedTaskRunner(
5567 {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
5568 base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}));
5569 non_network_url_loader_factories_.emplace(url::kContentScheme,
5570 std::move(content_factory));
5571 }
5572 #endif
5573
5574 StoragePartition* partition =
5575 BrowserContext::GetStoragePartition(browser_context, GetSiteInstance());
5576 std::string storage_domain;
5577 if (site_instance_) {
5578 std::string partition_name;
5579 bool in_memory;
5580 GetContentClient()->browser()->GetStoragePartitionConfigForSite(
5581 browser_context, site_instance_->GetSiteURL(), true, &storage_domain,
5582 &partition_name, &in_memory);
5583 }
5584 non_network_url_loader_factories_.emplace(
5585 url::kFileSystemScheme,
5586 content::CreateFileSystemURLLoaderFactory(
5587 process_->GetID(), GetFrameTreeNodeId(),
5588 partition->GetFileSystemContext(), storage_domain));
5589
5590 non_network_url_loader_factories_.emplace(
5591 url::kDataScheme, std::make_unique<DataURLLoaderFactory>());
5592
5593 GetContentClient()
5594 ->browser()
5595 ->RegisterNonNetworkSubresourceURLLoaderFactories(
5596 process_->GetID(), routing_id_, &non_network_url_loader_factories_);
5597
5598 for (auto& factory : non_network_url_loader_factories_) {
5599 mojo::PendingRemote<network::mojom::URLLoaderFactory>
5600 pending_factory_proxy;
5601 mojo::PendingReceiver<network::mojom::URLLoaderFactory> factory_receiver =
5602 pending_factory_proxy.InitWithNewPipeAndPassReceiver();
5603 GetContentClient()->browser()->WillCreateURLLoaderFactory(
5604 browser_context, this, GetProcess()->GetID(),
5605 ContentBrowserClient::URLLoaderFactoryType::kDocumentSubResource,
5606 main_world_origin_for_url_loader_factory,
5607 base::nullopt /* navigation_id */, &factory_receiver,
5608 nullptr /* header_client */, nullptr /* bypass_redirect_checks */,
5609 nullptr /* disable_secure_dns */, nullptr /* factory_override */);
5610 // Keep DevTools proxy last, i.e. closest to the network.
5611 devtools_instrumentation::WillCreateURLLoaderFactory(
5612 this, false /* is_navigation */, false /* is_download */,
5613 &factory_receiver, nullptr /* factory_override */);
5614 factory.second->Clone(std::move(factory_receiver));
5615 subresource_loader_factories->pending_scheme_specific_factories().emplace(
5616 factory.first, std::move(pending_factory_proxy));
5617 }
5618
5619 // TODO(clamy): Always use the NavigationRequest's ClientSecurityState
5620 // when all interstitials are committed and we are guaranteed to have a
5621 // NavigationRequest in this function.
5622 subresource_loader_factories->pending_isolated_world_factories() =
5623 CreateURLLoaderFactoriesForIsolatedWorlds(
5624 main_world_origin_for_url_loader_factory,
5625 isolated_worlds_requiring_separate_url_loader_factory_,
5626 navigation_request
5627 ? mojo::Clone(navigation_request->client_security_state())
5628 : network::mojom::ClientSecurityState::New());
5629 }
5630
5631 // It is imperative that cross-document navigations always provide a set of
5632 // subresource ULFs.
5633 DCHECK(is_same_document || !is_first_navigation || is_srcdoc ||
5634 subresource_loader_factories);
5635
5636 if (is_same_document) {
5637 bool should_replace_current_entry =
5638 common_params->should_replace_current_entry;
5639 DCHECK(same_document_navigation_request_);
5640 GetNavigationControl()->CommitSameDocumentNavigation(
5641 std::move(common_params), std::move(commit_params),
5642 base::BindOnce(&RenderFrameHostImpl::OnSameDocumentCommitProcessed,
5643 base::Unretained(this),
5644 same_document_navigation_request_->GetNavigationId(),
5645 should_replace_current_entry));
5646 } else {
5647 // Pass the controller service worker info if we have one.
5648 blink::mojom::ControllerServiceWorkerInfoPtr controller;
5649 mojo::PendingAssociatedRemote<blink::mojom::ServiceWorkerObject>
5650 remote_object;
5651 blink::mojom::ServiceWorkerState sent_state;
5652 if (subresource_loader_params &&
5653 subresource_loader_params->controller_service_worker_info) {
5654 controller =
5655 std::move(subresource_loader_params->controller_service_worker_info);
5656 if (controller->object_info) {
5657 controller->object_info->receiver =
5658 remote_object.InitWithNewEndpointAndPassReceiver();
5659 sent_state = controller->object_info->state;
5660 }
5661 }
5662
5663 std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
5664 factory_bundle_for_prefetch;
5665 mojo::PendingRemote<network::mojom::URLLoaderFactory>
5666 prefetch_loader_factory;
5667 if (subresource_loader_factories) {
5668 // Clone the factory bundle for prefetch.
5669 auto bundle = base::MakeRefCounted<blink::URLLoaderFactoryBundle>(
5670 std::move(subresource_loader_factories));
5671 subresource_loader_factories = CloneFactoryBundle(bundle);
5672 factory_bundle_for_prefetch = CloneFactoryBundle(bundle);
5673 }
5674
5675 if (factory_bundle_for_prefetch) {
5676 if (prefetched_signed_exchange_cache_) {
5677 prefetched_signed_exchange_cache_->RecordHistograms();
5678 // Reset |prefetched_signed_exchange_cache_|, not to reuse the cached
5679 // signed exchange which was prefetched in the previous page.
5680 prefetched_signed_exchange_cache_.reset();
5681 }
5682
5683 // Also set-up URLLoaderFactory for prefetch using the same loader
5684 // factories. TODO(kinuko): Consider setting this up only when prefetch
5685 // is used. Currently we have this here to make sure we have non-racy
5686 // situation (https://crbug.com/849929).
5687 auto* storage_partition = static_cast<StoragePartitionImpl*>(
5688 BrowserContext::GetStoragePartition(
5689 GetSiteInstance()->GetBrowserContext(), GetSiteInstance()));
5690 storage_partition->GetPrefetchURLLoaderService()->GetFactory(
5691 prefetch_loader_factory.InitWithNewPipeAndPassReceiver(),
5692 frame_tree_node_->frame_tree_node_id(),
5693 std::move(factory_bundle_for_prefetch),
5694 weak_ptr_factory_.GetWeakPtr(),
5695 EnsurePrefetchedSignedExchangeCache());
5696 }
5697
5698 mojom::NavigationClient* navigation_client = nullptr;
5699 if (navigation_request)
5700 navigation_client = navigation_request->GetCommitNavigationClient();
5701
5702 // Record the metrics about the state of the old main frame at the moment
5703 // when we navigate away from it as it matters for whether the page
5704 // is eligible for being put into back-forward cache.
5705 //
5706 // Ideally we would do this when we are just about to swap out the old
5707 // render frame and swap in the new one, but we can't do this for
5708 // same-process navigations yet as we are reusing the RenderFrameHost and
5709 // as the local frame navigates it overrides the values that we are
5710 // interested in. The cross-process navigation case is handled in
5711 // RenderFrameHostManager::UnloadOldFrame.
5712 //
5713 // Here we are recording the metrics for same-process navigations at the
5714 // point just before the navigation commits.
5715 // TODO(altimin, crbug.com/933147): Remove this logic after we are done with
5716 // implementing back-forward cache.
5717 if (!GetParent() && frame_tree_node()->current_frame_host() == this) {
5718 if (NavigationEntryImpl* last_committed_entry =
5719 NavigationEntryImpl::FromNavigationEntry(
5720 frame_tree_node()
5721 ->navigator()
5722 ->GetController()
5723 ->GetLastCommittedEntry())) {
5724 if (last_committed_entry->back_forward_cache_metrics()) {
5725 last_committed_entry->back_forward_cache_metrics()
5726 ->RecordFeatureUsage(this);
5727 }
5728 }
5729 }
5730
5731 // about:srcdoc "inherits" loaders from its parent in the renderer process,
5732 // There are no need to provide new ones here.
5733 // TODO(arthursonzogni): What about about:blank URLs?
5734 // TODO(arthursonzogni): What about data-URLs?
5735 //
5736 // Note: Inheriting loaders could be done in the browser process, but we
5737 // aren't confident there are enough reliable information in the
5738 // browser process to always make the correct decision. "Inheriting"
5739 // in the renderer process is slightly less problematic in that it
5740 // guarantees the renderer won't have higher privileges than it
5741 // originally had (since it will inherit loader factories it already
5742 // had access to).
5743 if (is_srcdoc) {
5744 DCHECK(!subresource_loader_factories);
5745 DCHECK(!subresource_overrides);
5746 DCHECK(!prefetch_loader_factory);
5747 }
5748
5749 // If a network request was made, update the Previews state.
5750 if (IsURLHandledByNetworkStack(common_params->url))
5751 last_navigation_previews_state_ = common_params->previews_state;
5752
5753 dom_content_loaded_ = false;
5754 SendCommitNavigation(
5755 navigation_client, navigation_request, std::move(common_params),
5756 std::move(commit_params), std::move(head), std::move(response_body),
5757 std::move(url_loader_client_endpoints),
5758 std::move(subresource_loader_factories),
5759 std::move(subresource_overrides), std::move(controller),
5760 std::move(provider_info), std::move(prefetch_loader_factory),
5761 devtools_navigation_token);
5762
5763 // |remote_object| is an associated interface ptr, so calls can't be made on
5764 // it until its request endpoint is sent. Now that the request endpoint was
5765 // sent, it can be used, so add it to ServiceWorkerObjectHost.
5766 if (remote_object.is_valid()) {
5767 RunOrPostTaskOnThread(
5768 FROM_HERE, ServiceWorkerContext::GetCoreThreadId(),
5769 base::BindOnce(
5770 &ServiceWorkerObjectHost::AddRemoteObjectPtrAndUpdateState,
5771 subresource_loader_params->controller_service_worker_object_host,
5772 std::move(remote_object), sent_state));
5773 }
5774 }
5775
5776 is_loading_ = true;
5777 }
5778
FailedNavigation(NavigationRequest * navigation_request,const mojom::CommonNavigationParams & common_params,const mojom::CommitNavigationParams & commit_params,bool has_stale_copy_in_cache,int error_code,const base::Optional<std::string> & error_page_content)5779 void RenderFrameHostImpl::FailedNavigation(
5780 NavigationRequest* navigation_request,
5781 const mojom::CommonNavigationParams& common_params,
5782 const mojom::CommitNavigationParams& commit_params,
5783 bool has_stale_copy_in_cache,
5784 int error_code,
5785 const base::Optional<std::string>& error_page_content) {
5786 TRACE_EVENT2("navigation", "RenderFrameHostImpl::FailedNavigation",
5787 "frame_tree_node", frame_tree_node_->frame_tree_node_id(),
5788 "error", error_code);
5789
5790 DCHECK(navigation_request);
5791
5792 // Update renderer permissions even for failed commits, so that for example
5793 // the URL bar correctly displays privileged URLs instead of filtering them.
5794 UpdatePermissionsForNavigation(common_params, commit_params);
5795
5796 // Get back to a clean state, in case a new navigation started without
5797 // completing an unload handler.
5798 ResetWaitingState();
5799
5800 // Error page will commit in an opaque origin.
5801 //
5802 // TODO(lukasza): https://crbug.com/888079: Use this origin when committing
5803 // later on.
5804 url::Origin origin = url::Origin();
5805
5806 std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
5807 subresource_loader_factories;
5808 mojo::PendingRemote<network::mojom::URLLoaderFactory> default_factory_remote;
5809 bool bypass_redirect_checks = CreateNetworkServiceDefaultFactoryAndObserve(
5810 CreateURLLoaderFactoryParamsForMainWorld(
5811 origin, mojo::Clone(navigation_request->client_security_state()),
5812 /*coep_reporter=*/mojo::NullRemote()),
5813 default_factory_remote.InitWithNewPipeAndPassReceiver());
5814 subresource_loader_factories =
5815 std::make_unique<blink::PendingURLLoaderFactoryBundle>(
5816 std::move(default_factory_remote),
5817 blink::PendingURLLoaderFactoryBundle::SchemeMap(),
5818 blink::PendingURLLoaderFactoryBundle::OriginMap(),
5819 bypass_redirect_checks);
5820
5821 mojom::NavigationClient* navigation_client =
5822 navigation_request->GetCommitNavigationClient();
5823
5824 SendCommitFailedNavigation(
5825 navigation_client, navigation_request, common_params.Clone(),
5826 commit_params.Clone(), has_stale_copy_in_cache, error_code,
5827 error_page_content, std::move(subresource_loader_factories));
5828
5829 // An error page is expected to commit, hence why is_loading_ is set to true.
5830 is_loading_ = true;
5831 dom_content_loaded_ = false;
5832 DCHECK(navigation_request && navigation_request->IsNavigationStarted() &&
5833 navigation_request->GetNetErrorCode() != net::OK);
5834 }
5835
HandleRendererDebugURL(const GURL & url)5836 void RenderFrameHostImpl::HandleRendererDebugURL(const GURL& url) {
5837 DCHECK(IsRendererDebugURL(url));
5838
5839 // Several tests expect a load of Chrome Debug URLs to send a DidStopLoading
5840 // notification, so set is loading to true here to properly surface it when
5841 // the renderer process is done handling the URL.
5842 // TODO(clamy): Remove the test dependency on this behavior.
5843 if (!url.SchemeIs(url::kJavaScriptScheme)) {
5844 bool was_loading = frame_tree_node()->frame_tree()->IsLoading();
5845 is_loading_ = true;
5846 frame_tree_node()->DidStartLoading(true, was_loading);
5847 }
5848
5849 GetNavigationControl()->HandleRendererDebugURL(url);
5850 }
5851
SetUpMojoIfNeeded()5852 void RenderFrameHostImpl::SetUpMojoIfNeeded() {
5853 if (registry_.get())
5854 return;
5855
5856 associated_registry_ = std::make_unique<blink::AssociatedInterfaceRegistry>();
5857 registry_ = std::make_unique<service_manager::BinderRegistry>();
5858
5859 auto bind_frame_host_receiver =
5860 [](RenderFrameHostImpl* impl,
5861 mojo::PendingAssociatedReceiver<mojom::FrameHost> receiver) {
5862 impl->frame_host_associated_receiver_.Bind(std::move(receiver));
5863 impl->frame_host_associated_receiver_.SetFilter(
5864 std::make_unique<ActiveURLMessageFilter>(impl));
5865 };
5866 associated_registry_->AddInterface(
5867 base::BindRepeating(bind_frame_host_receiver, base::Unretained(this)));
5868
5869 associated_registry_->AddInterface(base::BindRepeating(
5870 [](RenderFrameHostImpl* self,
5871 mojo::PendingAssociatedReceiver<blink::mojom::PortalHost> receiver) {
5872 Portal::BindPortalHostReceiver(self, std::move(receiver));
5873 },
5874 base::Unretained(this)));
5875
5876 associated_registry_->AddInterface(base::BindRepeating(
5877 [](RenderFrameHostImpl* impl,
5878 mojo::PendingAssociatedReceiver<blink::mojom::LocalFrameHost>
5879 receiver) {
5880 impl->local_frame_host_receiver_.Bind(std::move(receiver));
5881 impl->local_frame_host_receiver_.SetFilter(
5882 std::make_unique<ActiveURLMessageFilter>(impl));
5883 },
5884 base::Unretained(this)));
5885
5886 if (frame_tree_node_->IsMainFrame()) {
5887 associated_registry_->AddInterface(base::BindRepeating(
5888 [](RenderFrameHostImpl* impl,
5889 mojo::PendingAssociatedReceiver<blink::mojom::LocalMainFrameHost>
5890 receiver) {
5891 impl->local_main_frame_host_receiver_.Bind(std::move(receiver));
5892 impl->local_main_frame_host_receiver_.SetFilter(
5893 std::make_unique<ActiveURLMessageFilter>(impl));
5894 },
5895 base::Unretained(this)));
5896 }
5897
5898 associated_registry_->AddInterface(base::BindRepeating(
5899 [](RenderFrameHostImpl* impl,
5900 mojo::PendingAssociatedReceiver<mojom::RenderAccessibilityHost>
5901 receiver) {
5902 impl->render_accessibility_host_receiver_.Bind(std::move(receiver));
5903 },
5904 base::Unretained(this)));
5905
5906 RegisterMojoInterfaces();
5907 mojo::PendingRemote<mojom::FrameFactory> frame_factory;
5908 GetProcess()->BindReceiver(frame_factory.InitWithNewPipeAndPassReceiver());
5909 mojo::Remote<mojom::FrameFactory>(std::move(frame_factory))
5910 ->CreateFrame(routing_id_, frame_.BindNewPipeAndPassReceiver());
5911
5912 // TODO(http://crbug.com/1014212): Change to DCHECK.
5913 CHECK(frame_);
5914
5915 mojo::PendingRemote<service_manager::mojom::InterfaceProvider>
5916 remote_interfaces;
5917 frame_->GetInterfaceProvider(
5918 remote_interfaces.InitWithNewPipeAndPassReceiver());
5919 remote_interfaces_.reset(new service_manager::InterfaceProvider);
5920 remote_interfaces_->Bind(std::move(remote_interfaces));
5921
5922 remote_interfaces_->GetInterface(
5923 frame_input_handler_.BindNewPipeAndPassReceiver());
5924 }
5925
InvalidateMojoConnection()5926 void RenderFrameHostImpl::InvalidateMojoConnection() {
5927 registry_.reset();
5928
5929 frame_.reset();
5930 frame_bindings_control_.reset();
5931 frame_host_associated_receiver_.reset();
5932 local_frame_.reset();
5933 local_main_frame_.reset();
5934 navigation_control_.reset();
5935 frame_input_handler_.reset();
5936 find_in_page_.reset();
5937 render_accessibility_.reset();
5938
5939 // Disconnect with ImageDownloader Mojo service in Blink.
5940 mojo_image_downloader_.reset();
5941
5942 // The geolocation service and sensor provider proxy may attempt to cancel
5943 // permission requests so they must be reset before the routing_id mapping is
5944 // removed.
5945 geolocation_service_.reset();
5946 sensor_provider_proxy_.reset();
5947
5948 render_accessibility_host_receiver_.reset();
5949 local_frame_host_receiver_.reset();
5950 local_main_frame_host_receiver_.reset();
5951 associated_registry_.reset();
5952 }
5953
IsFocused()5954 bool RenderFrameHostImpl::IsFocused() {
5955 if (!GetRenderWidgetHost()->is_focused() || !frame_tree_->GetFocusedFrame())
5956 return false;
5957
5958 RenderFrameHostImpl* focused_rfh =
5959 frame_tree_->GetFocusedFrame()->current_frame_host();
5960 return focused_rfh == this || focused_rfh->IsDescendantOf(this);
5961 }
5962
CreateWebUI(const GURL & dest_url,int entry_bindings)5963 bool RenderFrameHostImpl::CreateWebUI(const GURL& dest_url,
5964 int entry_bindings) {
5965 // Verify expectation that WebUI should not be created for error pages.
5966 DCHECK_NE(GetSiteInstance()->GetSiteURL(), GURL(kUnreachableWebDataURL));
5967
5968 WebUI::TypeID new_web_ui_type =
5969 WebUIControllerFactoryRegistry::GetInstance()->GetWebUIType(
5970 GetSiteInstance()->GetBrowserContext(), dest_url);
5971 CHECK_NE(new_web_ui_type, WebUI::kNoWebUI);
5972
5973 // If |web_ui_| already exists, there is no need to create a new one. However,
5974 // it is useful to verify that its type hasn't changed. Site isolation
5975 // guarantees that RenderFrameHostImpl will be changed if the WebUI type
5976 // differs.
5977 if (web_ui_) {
5978 CHECK_EQ(new_web_ui_type, web_ui_type_);
5979 return false;
5980 }
5981
5982 web_ui_ = delegate_->CreateWebUIForRenderFrameHost(dest_url);
5983 if (!web_ui_)
5984 return false;
5985
5986 // If we have assigned (zero or more) bindings to the NavigationEntry in
5987 // the past, make sure we're not granting it different bindings than it
5988 // had before. If so, note it and don't give it any bindings, to avoid a
5989 // potential privilege escalation.
5990 if (entry_bindings != FrameNavigationEntry::kInvalidBindings &&
5991 web_ui_->GetBindings() != entry_bindings) {
5992 RecordAction(base::UserMetricsAction("ProcessSwapBindingsMismatch_RVHM"));
5993 ClearWebUI();
5994 return false;
5995 }
5996
5997 // It is not expected for GuestView to be able to navigate to WebUI.
5998 DCHECK(!GetProcess()->IsForGuestsOnly());
5999
6000 web_ui_type_ = new_web_ui_type;
6001
6002 // WebUIs need the ability to request certain schemes.
6003 for (const auto& scheme : web_ui_->GetRequestableSchemes()) {
6004 ChildProcessSecurityPolicyImpl::GetInstance()->GrantRequestScheme(
6005 GetProcess()->GetID(), scheme);
6006 }
6007
6008 // Since this is new WebUI instance, this RenderFrameHostImpl should not
6009 // have had any bindings. Verify that and grant the required bindings.
6010 DCHECK_EQ(0, GetEnabledBindings());
6011 AllowBindings(web_ui_->GetBindings());
6012
6013 return true;
6014 }
6015
ClearWebUI()6016 void RenderFrameHostImpl::ClearWebUI() {
6017 web_ui_type_ = WebUI::kNoWebUI;
6018 web_ui_.reset();
6019 }
6020
6021 const mojo::Remote<blink::mojom::ImageDownloader>&
GetMojoImageDownloader()6022 RenderFrameHostImpl::GetMojoImageDownloader() {
6023 if (!mojo_image_downloader_.is_bound() && GetRemoteInterfaces()) {
6024 GetRemoteInterfaces()->GetInterface(
6025 mojo_image_downloader_.BindNewPipeAndPassReceiver());
6026 }
6027 return mojo_image_downloader_;
6028 }
6029
6030 const mojo::AssociatedRemote<blink::mojom::FindInPage>&
GetFindInPage()6031 RenderFrameHostImpl::GetFindInPage() {
6032 if (!find_in_page_)
6033 GetRemoteAssociatedInterfaces()->GetInterface(&find_in_page_);
6034 return find_in_page_;
6035 }
6036
6037 const mojo::AssociatedRemote<blink::mojom::LocalFrame>&
GetAssociatedLocalFrame()6038 RenderFrameHostImpl::GetAssociatedLocalFrame() {
6039 if (!local_frame_)
6040 GetRemoteAssociatedInterfaces()->GetInterface(&local_frame_);
6041 return local_frame_;
6042 }
6043
6044 const mojo::AssociatedRemote<blink::mojom::LocalMainFrame>&
GetAssociatedLocalMainFrame()6045 RenderFrameHostImpl::GetAssociatedLocalMainFrame() {
6046 DCHECK(frame_tree_node_->IsMainFrame());
6047 if (!local_main_frame_)
6048 GetRemoteAssociatedInterfaces()->GetInterface(&local_main_frame_);
6049 return local_main_frame_;
6050 }
6051
ResetLoadingState()6052 void RenderFrameHostImpl::ResetLoadingState() {
6053 if (is_loading()) {
6054 // When pending deletion, just set the loading state to not loading.
6055 // Otherwise, OnDidStopLoading will take care of that, as well as sending
6056 // notification to the FrameTreeNode about the change in loading state.
6057 if (!is_active())
6058 is_loading_ = false;
6059 else
6060 OnDidStopLoading();
6061 }
6062 }
6063
ClearFocusedElement()6064 void RenderFrameHostImpl::ClearFocusedElement() {
6065 has_focused_editable_element_ = false;
6066 GetAssociatedLocalFrame()->ClearFocusedElement();
6067 }
6068
BlockRequestsForFrame()6069 void RenderFrameHostImpl::BlockRequestsForFrame() {
6070 DCHECK_CURRENTLY_ON(BrowserThread::UI);
6071
6072 ForEachFrame(this,
6073 base::BindRepeating([](RenderFrameHostImpl* render_frame_host) {
6074 if (render_frame_host->frame_)
6075 render_frame_host->frame_->BlockRequests();
6076 }));
6077 }
6078
ResumeBlockedRequestsForFrame()6079 void RenderFrameHostImpl::ResumeBlockedRequestsForFrame() {
6080 ForEachFrame(this,
6081 base::BindRepeating([](RenderFrameHostImpl* render_frame_host) {
6082 if (render_frame_host->frame_)
6083 render_frame_host->frame_->ResumeBlockedRequests();
6084 }));
6085 }
6086
CancelBlockedRequestsForFrame()6087 void RenderFrameHostImpl::CancelBlockedRequestsForFrame() {
6088 DCHECK_CURRENTLY_ON(BrowserThread::UI);
6089 ForEachFrame(this,
6090 base::BindRepeating([](RenderFrameHostImpl* render_frame_host) {
6091 if (render_frame_host->frame_)
6092 render_frame_host->frame_->CancelBlockedRequests();
6093 }));
6094 }
6095
BindDevToolsAgent(mojo::PendingAssociatedRemote<blink::mojom::DevToolsAgentHost> host,mojo::PendingAssociatedReceiver<blink::mojom::DevToolsAgent> receiver)6096 void RenderFrameHostImpl::BindDevToolsAgent(
6097 mojo::PendingAssociatedRemote<blink::mojom::DevToolsAgentHost> host,
6098 mojo::PendingAssociatedReceiver<blink::mojom::DevToolsAgent> receiver) {
6099 GetNavigationControl()->BindDevToolsAgent(std::move(host),
6100 std::move(receiver));
6101 }
6102
IsSameSiteInstance(RenderFrameHostImpl * other_render_frame_host)6103 bool RenderFrameHostImpl::IsSameSiteInstance(
6104 RenderFrameHostImpl* other_render_frame_host) {
6105 // As a sanity check, make sure the frame belongs to the same BrowserContext.
6106 CHECK_EQ(GetSiteInstance()->GetBrowserContext(),
6107 other_render_frame_host->GetSiteInstance()->GetBrowserContext());
6108 return GetSiteInstance() == other_render_frame_host->GetSiteInstance();
6109 }
6110
UpdateAccessibilityMode()6111 void RenderFrameHostImpl::UpdateAccessibilityMode() {
6112 // Don't update accessibility mode for a frame that hasn't been created yet.
6113 if (!IsRenderFrameCreated())
6114 return;
6115
6116 ui::AXMode ax_mode = delegate_->GetAccessibilityMode();
6117 if (!ax_mode.has_mode(ui::AXMode::kWebContents)) {
6118 // Resetting the Remote signals the renderer to shutdown accessibility
6119 // in the renderer.
6120 render_accessibility_.reset();
6121 return;
6122 }
6123
6124 if (!render_accessibility_) {
6125 // Render accessibility is not enabled yet, so bind the interface first.
6126 GetRemoteAssociatedInterfaces()->GetInterface(&render_accessibility_);
6127 }
6128
6129 render_accessibility_->SetMode(ax_mode.mode());
6130 }
6131
RequestAXTreeSnapshot(AXTreeSnapshotCallback callback,ui::AXMode ax_mode)6132 void RenderFrameHostImpl::RequestAXTreeSnapshot(AXTreeSnapshotCallback callback,
6133 ui::AXMode ax_mode) {
6134 // TODO(https://crbug.com/859110): Remove once frame_ can no longer be null.
6135 if (!IsRenderFrameLive())
6136 return;
6137
6138 frame_->SnapshotAccessibilityTree(
6139 ax_mode.mode(),
6140 base::BindOnce(&RenderFrameHostImpl::RequestAXTreeSnapshotCallback,
6141 weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
6142 }
6143
SetAccessibilityCallbackForTesting(const AccessibilityCallbackForTesting & callback)6144 void RenderFrameHostImpl::SetAccessibilityCallbackForTesting(
6145 const AccessibilityCallbackForTesting& callback) {
6146 accessibility_testing_callback_ = callback;
6147 }
6148
UpdateAXTreeData()6149 void RenderFrameHostImpl::UpdateAXTreeData() {
6150 ui::AXMode accessibility_mode = delegate_->GetAccessibilityMode();
6151 if (accessibility_mode.is_mode_off() || !is_active()) {
6152 return;
6153 }
6154
6155 AXEventNotificationDetails detail;
6156 detail.ax_tree_id = GetAXTreeID();
6157 detail.updates.resize(1);
6158 detail.updates[0].has_tree_data = true;
6159 AXContentTreeDataToAXTreeData(&detail.updates[0].tree_data);
6160
6161 SendAccessibilityEventsToManager(detail);
6162 delegate_->AccessibilityEventReceived(detail);
6163 }
6164
6165 BrowserAccessibilityManager*
GetOrCreateBrowserAccessibilityManager()6166 RenderFrameHostImpl::GetOrCreateBrowserAccessibilityManager() {
6167 RenderWidgetHostViewBase* view = GetViewForAccessibility();
6168 if (view && !browser_accessibility_manager_ &&
6169 !no_create_browser_accessibility_manager_for_testing_) {
6170 bool is_root_frame = !frame_tree_node()->parent();
6171 browser_accessibility_manager_.reset(
6172 view->CreateBrowserAccessibilityManager(this, is_root_frame));
6173 }
6174 return browser_accessibility_manager_.get();
6175 }
6176
ActivateFindInPageResultForAccessibility(int request_id)6177 void RenderFrameHostImpl::ActivateFindInPageResultForAccessibility(
6178 int request_id) {
6179 ui::AXMode accessibility_mode = delegate_->GetAccessibilityMode();
6180 if (accessibility_mode.has_mode(ui::AXMode::kNativeAPIs)) {
6181 BrowserAccessibilityManager* manager =
6182 GetOrCreateBrowserAccessibilityManager();
6183 if (manager)
6184 manager->ActivateFindInPageResult(request_id);
6185 }
6186 }
6187
InsertVisualStateCallback(VisualStateCallback callback)6188 void RenderFrameHostImpl::InsertVisualStateCallback(
6189 VisualStateCallback callback) {
6190 static uint64_t next_id = 1;
6191 uint64_t key = next_id++;
6192 Send(new FrameMsg_VisualStateRequest(routing_id_, key));
6193 visual_state_callbacks_.emplace(key, std::move(callback));
6194 }
6195
IsRenderFrameCreated()6196 bool RenderFrameHostImpl::IsRenderFrameCreated() {
6197 return render_frame_created_;
6198 }
6199
IsRenderFrameLive()6200 bool RenderFrameHostImpl::IsRenderFrameLive() {
6201 bool is_live =
6202 GetProcess()->IsInitializedAndNotDead() && render_frame_created_;
6203
6204 // Sanity check: the RenderView should always be live if the RenderFrame is.
6205 DCHECK(!is_live || render_view_host_->IsRenderViewLive());
6206
6207 return is_live;
6208 }
6209
IsCurrent()6210 bool RenderFrameHostImpl::IsCurrent() {
6211 RenderFrameHostImpl* rfh = this;
6212 // Check this RenderFrameHost and all its ancestors to see if they are the
6213 // current ones in their respective FrameTreeNodes.
6214 // It is important to check for all ancestors as when navigation commits a new
6215 // RenderFrameHost may replace one of the parents, swapping out the old with
6216 // its entire subtree but |this| will still be a current one in its
6217 // FrameTreeNode.
6218 while (rfh) {
6219 if (rfh->frame_tree_node()->current_frame_host() != rfh)
6220 return false;
6221 rfh = rfh->GetParent();
6222 }
6223 return true;
6224 }
6225
GetProxyCount()6226 size_t RenderFrameHostImpl::GetProxyCount() {
6227 if (!IsCurrent())
6228 return 0;
6229 return frame_tree_node_->render_manager()->GetProxyCount();
6230 }
6231
HasSelection()6232 bool RenderFrameHostImpl::HasSelection() {
6233 return has_selection_;
6234 }
6235
GetMainFrame()6236 RenderFrameHostImpl* RenderFrameHostImpl::GetMainFrame() {
6237 // Iteration over the GetParent() chain is used below, because returning
6238 // |frame_tree_node()->frame_tree()->root()->current_frame_host()| might
6239 // give an incorrect result after |this| has been detached from the frame
6240 // tree.
6241 RenderFrameHostImpl* main_frame = this;
6242 while (main_frame->GetParent())
6243 main_frame = main_frame->GetParent();
6244 return main_frame;
6245 }
6246
6247 #if BUILDFLAG(USE_EXTERNAL_POPUP_MENU)
6248 #if defined(OS_MACOSX)
6249
DidSelectPopupMenuItem(int selected_index)6250 void RenderFrameHostImpl::DidSelectPopupMenuItem(int selected_index) {
6251 Send(new FrameMsg_SelectPopupMenuItem(routing_id_, selected_index));
6252 }
6253
DidCancelPopupMenu()6254 void RenderFrameHostImpl::DidCancelPopupMenu() {
6255 Send(new FrameMsg_SelectPopupMenuItem(routing_id_, -1));
6256 }
6257
6258 #else
6259
DidSelectPopupMenuItems(const std::vector<int> & selected_indices)6260 void RenderFrameHostImpl::DidSelectPopupMenuItems(
6261 const std::vector<int>& selected_indices) {
6262 Send(new FrameMsg_SelectPopupMenuItems(routing_id_, false, selected_indices));
6263 }
6264
DidCancelPopupMenu()6265 void RenderFrameHostImpl::DidCancelPopupMenu() {
6266 Send(
6267 new FrameMsg_SelectPopupMenuItems(routing_id_, true, std::vector<int>()));
6268 }
6269
6270 #endif
6271 #endif
6272
CanAccessFilesOfPageState(const PageState & state)6273 bool RenderFrameHostImpl::CanAccessFilesOfPageState(const PageState& state) {
6274 return ChildProcessSecurityPolicyImpl::GetInstance()->CanReadAllFiles(
6275 GetProcess()->GetID(), state.GetReferencedFiles());
6276 }
6277
GrantFileAccessFromPageState(const PageState & state)6278 void RenderFrameHostImpl::GrantFileAccessFromPageState(const PageState& state) {
6279 GrantFileAccess(GetProcess()->GetID(), state.GetReferencedFiles());
6280 }
6281
GrantFileAccessFromResourceRequestBody(const network::ResourceRequestBody & body)6282 void RenderFrameHostImpl::GrantFileAccessFromResourceRequestBody(
6283 const network::ResourceRequestBody& body) {
6284 GrantFileAccess(GetProcess()->GetID(), body.GetReferencedFiles());
6285 }
6286
UpdatePermissionsForNavigation(const mojom::CommonNavigationParams & common_params,const mojom::CommitNavigationParams & commit_params)6287 void RenderFrameHostImpl::UpdatePermissionsForNavigation(
6288 const mojom::CommonNavigationParams& common_params,
6289 const mojom::CommitNavigationParams& commit_params) {
6290 // Browser plugin guests are not allowed to navigate outside web-safe schemes,
6291 // so do not grant them the ability to commit additional URLs.
6292 if (!GetProcess()->IsForGuestsOnly()) {
6293 ChildProcessSecurityPolicyImpl::GetInstance()->GrantCommitURL(
6294 GetProcess()->GetID(), common_params.url);
6295 if (IsLoadDataWithBaseURL(common_params)) {
6296 // When there's a base URL specified for the data URL, we also need to
6297 // grant access to the base URL. This allows file: and other unexpected
6298 // schemes to be accepted at commit time and during CORS checks (e.g., for
6299 // font requests).
6300 ChildProcessSecurityPolicyImpl::GetInstance()->GrantCommitURL(
6301 GetProcess()->GetID(), common_params.base_url_for_data_url);
6302 }
6303 }
6304
6305 // We may be returning to an existing NavigationEntry that had been granted
6306 // file access. If this is a different process, we will need to grant the
6307 // access again. Abuse is prevented, because the files listed in the page
6308 // state are validated earlier, when they are received from the renderer (in
6309 // RenderFrameHostImpl::CanAccessFilesOfPageState).
6310 if (commit_params.page_state.IsValid())
6311 GrantFileAccessFromPageState(commit_params.page_state);
6312
6313 // We may be here after transferring navigation to a different renderer
6314 // process. In this case, we need to ensure that the new renderer retains
6315 // ability to access files that the old renderer could access. Abuse is
6316 // prevented, because the files listed in ResourceRequestBody are validated
6317 // earlier, when they are received from the renderer.
6318 if (common_params.post_data)
6319 GrantFileAccessFromResourceRequestBody(*common_params.post_data);
6320 }
6321
6322 mojo::AssociatedRemote<mojom::NavigationClient>
GetNavigationClientFromInterfaceProvider()6323 RenderFrameHostImpl::GetNavigationClientFromInterfaceProvider() {
6324 mojo::AssociatedRemote<mojom::NavigationClient> navigation_client_remote;
6325 GetRemoteAssociatedInterfaces()->GetInterface(&navigation_client_remote);
6326 return navigation_client_remote;
6327 }
6328
NavigationRequestCancelled(NavigationRequest * navigation_request)6329 void RenderFrameHostImpl::NavigationRequestCancelled(
6330 NavigationRequest* navigation_request) {
6331 OnCrossDocumentCommitProcessed(navigation_request,
6332 blink::mojom::CommitResult::Aborted);
6333 }
6334
6335 url::Origin
GetExpectedMainWorldOriginForUrlLoaderFactory()6336 RenderFrameHostImpl::GetExpectedMainWorldOriginForUrlLoaderFactory() {
6337 // Find the most recent NavigationRequest that has triggered a Commit IPC to
6338 // the renderer process. Once the renderer process handles the IPC, it may
6339 // possibly change the origin from |last_committed_origin_| to another origin.
6340 NavigationRequest* found_request = nullptr;
6341 for (const auto& it : navigation_requests_) {
6342 NavigationRequest* candidate = it.first;
6343 DCHECK_EQ(candidate, it.second.get());
6344
6345 if (candidate->state() < NavigationRequest::READY_TO_COMMIT)
6346 continue;
6347 if (candidate->state() >= NavigationRequest::DID_COMMIT)
6348 continue;
6349
6350 if (!found_request ||
6351 found_request->NavigationStart() < candidate->NavigationStart()) {
6352 found_request = candidate;
6353 }
6354 }
6355
6356 // If there are no pending navigation requests then the URLLoaderFactory sent
6357 // now to the renderer process will end up being used by
6358 // |last_committed_origin_|.
6359 if (!found_request) {
6360 DCHECK(has_committed_any_navigation_);
6361 return last_committed_origin_;
6362 }
6363
6364 // URLLoaderFactory sent now to the renderer process will end up being used by
6365 // the origin associated the navigation that is getting committed in that
6366 // renderer process.
6367 return GetOriginForURLLoaderFactory(found_request);
6368 }
6369
6370 network::mojom::URLLoaderFactoryParamsPtr
CreateURLLoaderFactoryParamsForMainWorld(const url::Origin & main_world_origin,network::mojom::ClientSecurityStatePtr client_security_state,mojo::PendingRemote<network::mojom::CrossOriginEmbedderPolicyReporter> coep_reporter)6371 RenderFrameHostImpl::CreateURLLoaderFactoryParamsForMainWorld(
6372 const url::Origin& main_world_origin,
6373 network::mojom::ClientSecurityStatePtr client_security_state,
6374 mojo::PendingRemote<network::mojom::CrossOriginEmbedderPolicyReporter>
6375 coep_reporter) {
6376 return URLLoaderFactoryParamsHelper::CreateForFrame(
6377 this, main_world_origin, std::move(client_security_state),
6378 std::move(coep_reporter), GetProcess());
6379 }
6380
CreateNetworkServiceDefaultFactoryAndObserve(network::mojom::URLLoaderFactoryParamsPtr params,mojo::PendingReceiver<network::mojom::URLLoaderFactory> default_factory_receiver)6381 bool RenderFrameHostImpl::CreateNetworkServiceDefaultFactoryAndObserve(
6382 network::mojom::URLLoaderFactoryParamsPtr params,
6383 mojo::PendingReceiver<network::mojom::URLLoaderFactory>
6384 default_factory_receiver) {
6385 bool bypass_redirect_checks = CreateNetworkServiceDefaultFactoryInternal(
6386 std::move(params), std::move(default_factory_receiver));
6387
6388 // Add a disconnect handler when Network Service is running
6389 // out-of-process.
6390 if (IsOutOfProcessNetworkService() &&
6391 (!network_service_disconnect_handler_holder_ ||
6392 !network_service_disconnect_handler_holder_.is_connected())) {
6393 network_service_disconnect_handler_holder_.reset();
6394 StoragePartition* storage_partition = BrowserContext::GetStoragePartition(
6395 GetSiteInstance()->GetBrowserContext(), GetSiteInstance());
6396 network::mojom::URLLoaderFactoryParamsPtr monitoring_factory_params =
6397 network::mojom::URLLoaderFactoryParams::New();
6398 monitoring_factory_params->process_id = GetProcess()->GetID();
6399
6400 // This factory should never be used to issue actual requests (i.e. it
6401 // should only be used to monitor for Network Service crashes). Below is an
6402 // attempt to enforce that the factory cannot be used in practice.
6403 monitoring_factory_params->request_initiator_site_lock =
6404 url::Origin::Create(
6405 GURL("https://monitoring.url.loader.factory.invalid"));
6406
6407 storage_partition->GetNetworkContext()->CreateURLLoaderFactory(
6408 network_service_disconnect_handler_holder_.BindNewPipeAndPassReceiver(),
6409 std::move(monitoring_factory_params));
6410 network_service_disconnect_handler_holder_.set_disconnect_handler(
6411 base::BindOnce(&RenderFrameHostImpl::UpdateSubresourceLoaderFactories,
6412 weak_ptr_factory_.GetWeakPtr()));
6413 }
6414 return bypass_redirect_checks;
6415 }
6416
CreateNetworkServiceDefaultFactoryInternal(network::mojom::URLLoaderFactoryParamsPtr params,mojo::PendingReceiver<network::mojom::URLLoaderFactory> default_factory_receiver)6417 bool RenderFrameHostImpl::CreateNetworkServiceDefaultFactoryInternal(
6418 network::mojom::URLLoaderFactoryParamsPtr params,
6419 mojo::PendingReceiver<network::mojom::URLLoaderFactory>
6420 default_factory_receiver) {
6421 auto* context = GetSiteInstance()->GetBrowserContext();
6422
6423 DCHECK(params->request_initiator_site_lock.has_value());
6424 const url::Origin& origin = params->request_initiator_site_lock.value();
6425
6426 bool bypass_redirect_checks = false;
6427 GetContentClient()->browser()->WillCreateURLLoaderFactory(
6428 context, this, GetProcess()->GetID(),
6429 ContentBrowserClient::URLLoaderFactoryType::kDocumentSubResource, origin,
6430 base::nullopt /* navigation_id */, &default_factory_receiver,
6431 ¶ms->header_client, &bypass_redirect_checks,
6432 ¶ms->disable_secure_dns, ¶ms->factory_override);
6433
6434 // Keep DevTools proxy last, i.e. closest to the network.
6435 devtools_instrumentation::WillCreateURLLoaderFactory(
6436 this, false /* is_navigation */, false /* is_download */,
6437 &default_factory_receiver, ¶ms->factory_override);
6438
6439 GetProcess()->CreateURLLoaderFactory(std::move(default_factory_receiver),
6440 std::move(params));
6441
6442 return bypass_redirect_checks;
6443 }
6444
CanExecuteJavaScript()6445 bool RenderFrameHostImpl::CanExecuteJavaScript() {
6446 if (g_allow_injecting_javascript)
6447 return true;
6448 return !frame_tree_node_->current_url().is_valid() ||
6449 frame_tree_node_->current_url().SchemeIs(kChromeDevToolsScheme) ||
6450 ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
6451 GetProcess()->GetID()) ||
6452 // It's possible to load about:blank in a Web UI renderer.
6453 // See http://crbug.com/42547
6454 (frame_tree_node_->current_url().spec() == url::kAboutBlankURL) ||
6455 // InterstitialPageImpl should be the only case matching this.
6456 (delegate_->GetAsWebContents() == nullptr);
6457 }
6458
6459 // static
GetFrameTreeNodeIdForRoutingId(int process_id,int routing_id)6460 int RenderFrameHost::GetFrameTreeNodeIdForRoutingId(int process_id,
6461 int routing_id) {
6462 RenderFrameHostImpl* rfh = nullptr;
6463 RenderFrameProxyHost* rfph = nullptr;
6464 LookupRenderFrameHostOrProxy(process_id, routing_id, &rfh, &rfph);
6465 if (rfh) {
6466 return rfh->GetFrameTreeNodeId();
6467 } else if (rfph) {
6468 return rfph->frame_tree_node()->frame_tree_node_id();
6469 }
6470 return kNoFrameTreeNodeId;
6471 }
6472
6473 // static
FromPlaceholderId(int render_process_id,int placeholder_routing_id)6474 RenderFrameHost* RenderFrameHost::FromPlaceholderId(
6475 int render_process_id,
6476 int placeholder_routing_id) {
6477 RenderFrameProxyHost* rfph =
6478 RenderFrameProxyHost::FromID(render_process_id, placeholder_routing_id);
6479 FrameTreeNode* node = rfph ? rfph->frame_tree_node() : nullptr;
6480 return node ? node->current_frame_host() : nullptr;
6481 }
6482
RoutingIDToAXTreeID(int routing_id)6483 ui::AXTreeID RenderFrameHostImpl::RoutingIDToAXTreeID(int routing_id) {
6484 RenderFrameHostImpl* rfh = nullptr;
6485 RenderFrameProxyHost* rfph = nullptr;
6486 LookupRenderFrameHostOrProxy(GetProcess()->GetID(), routing_id, &rfh, &rfph);
6487 if (rfph) {
6488 rfh = rfph->frame_tree_node()->current_frame_host();
6489 }
6490
6491 if (!rfh)
6492 return ui::AXTreeIDUnknown();
6493
6494 return rfh->GetAXTreeID();
6495 }
6496
AXContentNodeDataToAXNodeData(const AXContentNodeData & src,ui::AXNodeData * dst)6497 void RenderFrameHostImpl::AXContentNodeDataToAXNodeData(
6498 const AXContentNodeData& src,
6499 ui::AXNodeData* dst) {
6500 // Copy the common fields.
6501 *dst = src;
6502
6503 // Map content-specific's |child_routing_id| attribute to a generic attribute
6504 // with a global AXTreeID.
6505 if (src.child_routing_id != MSG_ROUTING_NONE) {
6506 dst->string_attributes.push_back(
6507 std::make_pair(ax::mojom::StringAttribute::kChildTreeId,
6508 RoutingIDToAXTreeID(src.child_routing_id).ToString()));
6509 }
6510 }
6511
AXContentTreeDataToAXTreeData(ui::AXTreeData * dst)6512 void RenderFrameHostImpl::AXContentTreeDataToAXTreeData(ui::AXTreeData* dst) {
6513 const AXContentTreeData& src = ax_content_tree_data_;
6514
6515 // Copy the common fields.
6516 *dst = src;
6517
6518 if (src.routing_id != MSG_ROUTING_NONE)
6519 dst->tree_id = RoutingIDToAXTreeID(src.routing_id);
6520
6521 if (src.parent_routing_id != MSG_ROUTING_NONE)
6522 dst->parent_tree_id = RoutingIDToAXTreeID(src.parent_routing_id);
6523
6524 if (browser_plugin_embedder_ax_tree_id_ != ui::AXTreeIDUnknown())
6525 dst->parent_tree_id = browser_plugin_embedder_ax_tree_id_;
6526
6527 // If this is not the root frame tree node, we're done.
6528 if (frame_tree_node()->parent())
6529 return;
6530
6531 // For the root frame tree node, also store the AXTreeID of the focused frame.
6532 auto* focused_frame = static_cast<RenderFrameHostImpl*>(
6533 delegate_->GetFocusedFrameIncludingInnerWebContents());
6534 if (!focused_frame)
6535 return;
6536 dst->focused_tree_id = focused_frame->GetAXTreeID();
6537 }
6538
RequestAXHitTestCallback(int action_request_id,mojom::ChildFrameHitTestInfoPtr child_frame_hit_test_info)6539 void RenderFrameHostImpl::RequestAXHitTestCallback(
6540 int action_request_id,
6541 mojom::ChildFrameHitTestInfoPtr child_frame_hit_test_info) {
6542 // Not receiving a child_frame_hit_test_info means that the renderer has
6543 // already handled this by emitting the requested event over the object found
6544 // as the result of the hit testing process, so nothing to do.
6545 if (!child_frame_hit_test_info)
6546 return;
6547
6548 // A child frame was found while hit testing on this frame, and so we need to
6549 // request a new hit test over such child frame now.
6550 RenderFrameHostImpl* child_frame = nullptr;
6551 RenderFrameProxyHost* rfph = nullptr;
6552 LookupRenderFrameHostOrProxy(
6553 GetProcess()->GetID(), child_frame_hit_test_info->child_frame_routing_id,
6554 &child_frame, &rfph);
6555 if (rfph)
6556 child_frame = rfph->frame_tree_node()->current_frame_host();
6557
6558 if (!child_frame || !child_frame->is_active())
6559 return;
6560
6561 ui::AXActionData action_data;
6562 action_data.request_id = action_request_id;
6563 action_data.target_point = child_frame_hit_test_info->transformed_point;
6564 action_data.action = ax::mojom::Action::kHitTest;
6565 action_data.hit_test_event_to_fire = child_frame_hit_test_info->event_to_fire;
6566
6567 child_frame->AccessibilityPerformAction(action_data);
6568 }
6569
RequestAXTreeSnapshotCallback(AXTreeSnapshotCallback callback,const AXContentTreeUpdate & snapshot)6570 void RenderFrameHostImpl::RequestAXTreeSnapshotCallback(
6571 AXTreeSnapshotCallback callback,
6572 const AXContentTreeUpdate& snapshot) {
6573 ui::AXTreeUpdate dst_snapshot;
6574 dst_snapshot.root_id = snapshot.root_id;
6575 dst_snapshot.nodes.resize(snapshot.nodes.size());
6576 for (size_t i = 0; i < snapshot.nodes.size(); ++i)
6577 AXContentNodeDataToAXNodeData(snapshot.nodes[i], &dst_snapshot.nodes[i]);
6578
6579 if (snapshot.has_tree_data) {
6580 ax_content_tree_data_ = snapshot.tree_data;
6581 AXContentTreeDataToAXTreeData(&dst_snapshot.tree_data);
6582 dst_snapshot.has_tree_data = true;
6583 }
6584 std::move(callback).Run(dst_snapshot);
6585 }
6586
CreatePaymentManager(mojo::PendingReceiver<payments::mojom::PaymentManager> receiver)6587 void RenderFrameHostImpl::CreatePaymentManager(
6588 mojo::PendingReceiver<payments::mojom::PaymentManager> receiver) {
6589 if (!IsFeatureEnabled(blink::mojom::FeaturePolicyFeature::kPayment)) {
6590 mojo::ReportBadMessage("Feature policy blocks Payment");
6591 return;
6592 }
6593 GetProcess()->CreatePaymentManagerForOrigin(GetLastCommittedOrigin(),
6594 std::move(receiver));
6595 }
6596
CreateWebBluetoothService(mojo::PendingReceiver<blink::mojom::WebBluetoothService> receiver)6597 void RenderFrameHostImpl::CreateWebBluetoothService(
6598 mojo::PendingReceiver<blink::mojom::WebBluetoothService> receiver) {
6599 BackForwardCache::DisableForRenderFrameHost(this, "WebBluetooth");
6600 // RFHI owns |web_bluetooth_services_| and |web_bluetooth_service| owns the
6601 // |receiver_| which may run the error handler. |receiver_| can't run the
6602 // error handler after it's destroyed so it can't run after the RFHI is
6603 // destroyed.
6604 auto web_bluetooth_service =
6605 std::make_unique<WebBluetoothServiceImpl>(this, std::move(receiver));
6606 web_bluetooth_service->SetClientConnectionErrorHandler(
6607 base::BindOnce(&RenderFrameHostImpl::DeleteWebBluetoothService,
6608 base::Unretained(this), web_bluetooth_service.get()));
6609 web_bluetooth_services_.push_back(std::move(web_bluetooth_service));
6610 }
6611
6612 WebBluetoothServiceImpl*
GetWebBluetoothServiceForTesting()6613 RenderFrameHostImpl::GetWebBluetoothServiceForTesting() {
6614 DCHECK(web_bluetooth_services_.back());
6615 return web_bluetooth_services_.back().get();
6616 }
6617
DeleteWebBluetoothService(WebBluetoothServiceImpl * web_bluetooth_service)6618 void RenderFrameHostImpl::DeleteWebBluetoothService(
6619 WebBluetoothServiceImpl* web_bluetooth_service) {
6620 auto it = std::find_if(
6621 web_bluetooth_services_.begin(), web_bluetooth_services_.end(),
6622 [web_bluetooth_service](
6623 const std::unique_ptr<WebBluetoothServiceImpl>& service) {
6624 return web_bluetooth_service == service.get();
6625 });
6626 DCHECK(it != web_bluetooth_services_.end());
6627 web_bluetooth_services_.erase(it);
6628 }
6629
CreateWebUsbService(mojo::PendingReceiver<blink::mojom::WebUsbService> receiver)6630 void RenderFrameHostImpl::CreateWebUsbService(
6631 mojo::PendingReceiver<blink::mojom::WebUsbService> receiver) {
6632 BackForwardCache::DisableForRenderFrameHost(this, "WebUSB");
6633 GetContentClient()->browser()->CreateWebUsbService(this, std::move(receiver));
6634 }
6635
ResetFeaturePolicy()6636 void RenderFrameHostImpl::ResetFeaturePolicy() {
6637 RenderFrameHostImpl* parent_frame_host = GetParent();
6638 if (!parent_frame_host && !frame_tree_node_->current_replication_state()
6639 .opener_feature_state.empty()) {
6640 DCHECK(base::FeatureList::IsEnabled(features::kFeaturePolicyForSandbox));
6641 feature_policy_ = blink::FeaturePolicy::CreateWithOpenerPolicy(
6642 frame_tree_node_->current_replication_state().opener_feature_state,
6643 last_committed_origin_);
6644 return;
6645 }
6646 const blink::FeaturePolicy* parent_policy =
6647 parent_frame_host ? parent_frame_host->feature_policy() : nullptr;
6648 blink::ParsedFeaturePolicy container_policy =
6649 frame_tree_node()->effective_frame_policy().container_policy;
6650 feature_policy_ = blink::FeaturePolicy::CreateFromParentPolicy(
6651 parent_policy, container_policy, last_committed_origin_);
6652 }
6653
CreateAudioInputStreamFactory(mojo::PendingReceiver<mojom::RendererAudioInputStreamFactory> receiver)6654 void RenderFrameHostImpl::CreateAudioInputStreamFactory(
6655 mojo::PendingReceiver<mojom::RendererAudioInputStreamFactory> receiver) {
6656 BrowserMainLoop* browser_main_loop = BrowserMainLoop::GetInstance();
6657 DCHECK(browser_main_loop);
6658 MediaStreamManager* msm = browser_main_loop->media_stream_manager();
6659 audio_service_audio_input_stream_factory_.emplace(std::move(receiver), msm,
6660 this);
6661 }
6662
CreateAudioOutputStreamFactory(mojo::PendingReceiver<mojom::RendererAudioOutputStreamFactory> receiver)6663 void RenderFrameHostImpl::CreateAudioOutputStreamFactory(
6664 mojo::PendingReceiver<mojom::RendererAudioOutputStreamFactory> receiver) {
6665 media::AudioSystem* audio_system =
6666 BrowserMainLoop::GetInstance()->audio_system();
6667 MediaStreamManager* media_stream_manager =
6668 BrowserMainLoop::GetInstance()->media_stream_manager();
6669 audio_service_audio_output_stream_factory_.emplace(
6670 this, audio_system, media_stream_manager, std::move(receiver));
6671 }
6672
GetFeatureObserver(mojo::PendingReceiver<blink::mojom::FeatureObserver> receiver)6673 void RenderFrameHostImpl::GetFeatureObserver(
6674 mojo::PendingReceiver<blink::mojom::FeatureObserver> receiver) {
6675 if (!feature_observer_) {
6676 // Lazy initialize because tests sets the overridden content client
6677 // after the RFHI constructor.
6678 auto* client = GetContentClient()->browser()->GetFeatureObserverClient();
6679 if (!client)
6680 return;
6681 feature_observer_ = std::make_unique<FeatureObserver>(
6682 client, GlobalFrameRoutingId(GetProcess()->GetID(), routing_id_));
6683 }
6684 feature_observer_->GetFeatureObserver(std::move(receiver));
6685 }
6686
BindMediaInterfaceFactoryReceiver(mojo::PendingReceiver<media::mojom::InterfaceFactory> receiver)6687 void RenderFrameHostImpl::BindMediaInterfaceFactoryReceiver(
6688 mojo::PendingReceiver<media::mojom::InterfaceFactory> receiver) {
6689 DCHECK(!media_interface_proxy_);
6690 media_interface_proxy_.reset(new MediaInterfaceProxy(
6691 this, std::move(receiver),
6692 base::BindOnce(
6693 &RenderFrameHostImpl::OnMediaInterfaceFactoryConnectionError,
6694 base::Unretained(this))));
6695 }
6696
BindMediaMetricsProviderReceiver(mojo::PendingReceiver<media::mojom::MediaMetricsProvider> receiver)6697 void RenderFrameHostImpl::BindMediaMetricsProviderReceiver(
6698 mojo::PendingReceiver<media::mojom::MediaMetricsProvider> receiver) {
6699 // Only save decode stats when BrowserContext provides a VideoPerfHistory.
6700 // Off-the-record contexts will internally use an ephemeral history DB.
6701 media::VideoDecodePerfHistory::SaveCallback save_stats_cb;
6702 if (GetSiteInstance()->GetBrowserContext()->GetVideoDecodePerfHistory()) {
6703 save_stats_cb = GetSiteInstance()
6704 ->GetBrowserContext()
6705 ->GetVideoDecodePerfHistory()
6706 ->GetSaveCallback();
6707 }
6708
6709 media::MediaMetricsProvider::Create(
6710 GetProcess()->GetBrowserContext()->IsOffTheRecord()
6711 ? media::MediaMetricsProvider::BrowsingMode::kIncognito
6712 : media::MediaMetricsProvider::BrowsingMode::kNormal,
6713 frame_tree_node_->IsMainFrame()
6714 ? media::MediaMetricsProvider::FrameStatus::kTopFrame
6715 : media::MediaMetricsProvider::FrameStatus::kNotTopFrame,
6716 base::BindRepeating(
6717 &RenderFrameHostDelegate::
6718 GetUkmSourceIdForLastCommittedSourceIncludingSameDocument,
6719 // This callback is only executed when Create() is called, during
6720 // which the lifetime of the |delegate_| is guaranteed.
6721 base::Unretained(delegate_)),
6722 base::BindRepeating(
6723 [](RenderFrameHostImpl* frame) {
6724 return ::media::learning::FeatureValue(
6725 frame->GetLastCommittedOrigin().host());
6726 },
6727 // Same as above.
6728 base::Unretained(this)),
6729 std::move(save_stats_cb),
6730 base::BindRepeating(
6731 [](base::WeakPtr<RenderFrameHostImpl> frame)
6732 -> media::learning::LearningSession* {
6733 if (!base::FeatureList::IsEnabled(media::kMediaLearningFramework) ||
6734 !frame) {
6735 return nullptr;
6736 }
6737
6738 return frame->GetProcess()
6739 ->GetBrowserContext()
6740 ->GetLearningSession();
6741 },
6742 weak_ptr_factory_.GetWeakPtr()),
6743 base::BindRepeating(
6744 &RenderFrameHostImpl::GetRecordAggregateWatchTimeCallback,
6745 base::Unretained(this)),
6746 std::move(receiver));
6747 }
6748
6749 #if BUILDFLAG(ENABLE_MEDIA_REMOTING)
BindMediaRemoterFactoryReceiver(mojo::PendingReceiver<media::mojom::RemoterFactory> receiver)6750 void RenderFrameHostImpl::BindMediaRemoterFactoryReceiver(
6751 mojo::PendingReceiver<media::mojom::RemoterFactory> receiver) {
6752 mojo::MakeSelfOwnedReceiver(
6753 std::make_unique<RemoterFactoryImpl>(GetProcess()->GetID(), routing_id_),
6754 std::move(receiver));
6755 }
6756 #endif
6757
CreateWebSocketConnector(mojo::PendingReceiver<blink::mojom::WebSocketConnector> receiver)6758 void RenderFrameHostImpl::CreateWebSocketConnector(
6759 mojo::PendingReceiver<blink::mojom::WebSocketConnector> receiver) {
6760 mojo::MakeSelfOwnedReceiver(
6761 std::make_unique<WebSocketConnectorImpl>(
6762 GetProcess()->GetID(), routing_id_, last_committed_origin_,
6763 network_isolation_key_),
6764 std::move(receiver));
6765 }
6766
CreateQuicTransportConnector(mojo::PendingReceiver<blink::mojom::QuicTransportConnector> receiver)6767 void RenderFrameHostImpl::CreateQuicTransportConnector(
6768 mojo::PendingReceiver<blink::mojom::QuicTransportConnector> receiver) {
6769 mojo::MakeSelfOwnedReceiver(std::make_unique<QuicTransportConnectorImpl>(
6770 GetProcess()->GetID(), last_committed_origin_,
6771 network_isolation_key_),
6772 std::move(receiver));
6773 }
6774
CreateNotificationService(mojo::PendingReceiver<blink::mojom::NotificationService> receiver)6775 void RenderFrameHostImpl::CreateNotificationService(
6776 mojo::PendingReceiver<blink::mojom::NotificationService> receiver) {
6777 GetProcess()->CreateNotificationService(GetLastCommittedOrigin(),
6778 std::move(receiver));
6779 }
6780
CreateInstalledAppProvider(mojo::PendingReceiver<blink::mojom::InstalledAppProvider> receiver)6781 void RenderFrameHostImpl::CreateInstalledAppProvider(
6782 mojo::PendingReceiver<blink::mojom::InstalledAppProvider> receiver) {
6783 InstalledAppProviderImpl::Create(this, std::move(receiver));
6784 }
6785
CreateDedicatedWorkerHostFactory(mojo::PendingReceiver<blink::mojom::DedicatedWorkerHostFactory> receiver)6786 void RenderFrameHostImpl::CreateDedicatedWorkerHostFactory(
6787 mojo::PendingReceiver<blink::mojom::DedicatedWorkerHostFactory> receiver) {
6788 // Allocate the worker in the same process as the creator.
6789 int worker_process_id = process_->GetID();
6790
6791 mojo::PendingRemote<network::mojom::CrossOriginEmbedderPolicyReporter>
6792 coep_reporter;
6793 auto coep_reporter_endpoint = coep_reporter.InitWithNewPipeAndPassReceiver();
6794 if (coep_reporter_)
6795 coep_reporter_->Clone(std::move(coep_reporter_endpoint));
6796
6797 // When a dedicated worker is created from the frame script, the frame is both
6798 // the creator and the ancestor.
6799 content::CreateDedicatedWorkerHostFactory(
6800 worker_process_id,
6801 /*creator_render_frame_host_id=*/GetGlobalFrameRoutingId(),
6802 /*ancestor_render_frame_host_id=*/GetGlobalFrameRoutingId(),
6803 last_committed_origin_, cross_origin_embedder_policy_,
6804 std::move(coep_reporter), std::move(receiver));
6805 }
6806
OnMediaInterfaceFactoryConnectionError()6807 void RenderFrameHostImpl::OnMediaInterfaceFactoryConnectionError() {
6808 DCHECK(media_interface_proxy_);
6809 media_interface_proxy_.reset();
6810 }
6811
6812 #if defined(OS_ANDROID)
BindNFCReceiver(mojo::PendingReceiver<device::mojom::NFC> receiver)6813 void RenderFrameHostImpl::BindNFCReceiver(
6814 mojo::PendingReceiver<device::mojom::NFC> receiver) {
6815 delegate_->GetNFC(this, std::move(receiver));
6816 }
6817 #endif
6818
6819 #if !defined(OS_ANDROID)
BindSerialService(mojo::PendingReceiver<blink::mojom::SerialService> receiver)6820 void RenderFrameHostImpl::BindSerialService(
6821 mojo::PendingReceiver<blink::mojom::SerialService> receiver) {
6822 if (!IsFeatureEnabled(blink::mojom::FeaturePolicyFeature::kSerial)) {
6823 mojo::ReportBadMessage("Feature policy blocks access to Serial.");
6824 return;
6825 }
6826
6827 if (!serial_service_)
6828 serial_service_ = std::make_unique<SerialService>(this);
6829
6830 serial_service_->Bind(std::move(receiver));
6831 }
6832 #endif
6833
6834 #if BUILDFLAG(ENABLE_WEB_AUTH)
BindAuthenticatorReceiver(mojo::PendingReceiver<blink::mojom::Authenticator> receiver)6835 void RenderFrameHostImpl::BindAuthenticatorReceiver(
6836 mojo::PendingReceiver<blink::mojom::Authenticator> receiver) {
6837 if (!authenticator_impl_)
6838 authenticator_impl_.reset(new AuthenticatorImpl(this));
6839
6840 authenticator_impl_->Bind(std::move(receiver));
6841 }
6842
GetHidService(mojo::PendingReceiver<blink::mojom::HidService> receiver)6843 void RenderFrameHostImpl::GetHidService(
6844 mojo::PendingReceiver<blink::mojom::HidService> receiver) {
6845 HidService::Create(this, std::move(receiver));
6846 }
6847 #endif
6848
GetIdleManager(mojo::PendingReceiver<blink::mojom::IdleManager> receiver)6849 void RenderFrameHostImpl::GetIdleManager(
6850 mojo::PendingReceiver<blink::mojom::IdleManager> receiver) {
6851 if (!IsFeatureEnabled(blink::mojom::FeaturePolicyFeature::kIdleDetection)) {
6852 mojo::ReportBadMessage("Feature policy blocks access to IdleDetection.");
6853 return;
6854 }
6855 static_cast<StoragePartitionImpl*>(GetProcess()->GetStoragePartition())
6856 ->GetIdleManager()
6857 ->CreateService(std::move(receiver));
6858 }
6859
GetPresentationService(mojo::PendingReceiver<blink::mojom::PresentationService> receiver)6860 void RenderFrameHostImpl::GetPresentationService(
6861 mojo::PendingReceiver<blink::mojom::PresentationService> receiver) {
6862 if (!presentation_service_)
6863 presentation_service_ = PresentationServiceImpl::Create(this);
6864 presentation_service_->Bind(std::move(receiver));
6865 }
6866
6867 PresentationServiceImpl&
GetPresentationServiceForTesting()6868 RenderFrameHostImpl::GetPresentationServiceForTesting() {
6869 DCHECK(presentation_service_);
6870 return *presentation_service_.get();
6871 }
6872
GetSpeechSynthesis(mojo::PendingReceiver<blink::mojom::SpeechSynthesis> receiver)6873 void RenderFrameHostImpl::GetSpeechSynthesis(
6874 mojo::PendingReceiver<blink::mojom::SpeechSynthesis> receiver) {
6875 #if BUILDFLAG(ENABLE_WEB_SPEECH)
6876 if (!speech_synthesis_impl_) {
6877 speech_synthesis_impl_ = std::make_unique<SpeechSynthesisImpl>(
6878 GetProcess()->GetBrowserContext());
6879 }
6880 speech_synthesis_impl_->AddReceiver(std::move(receiver));
6881 #endif
6882 }
6883
GetFileChooser(mojo::PendingReceiver<blink::mojom::FileChooser> receiver)6884 void RenderFrameHostImpl::GetFileChooser(
6885 mojo::PendingReceiver<blink::mojom::FileChooser> receiver) {
6886 FileChooserImpl::Create(this, std::move(receiver));
6887 }
6888
GetSensorProvider(mojo::PendingReceiver<device::mojom::SensorProvider> receiver)6889 void RenderFrameHostImpl::GetSensorProvider(
6890 mojo::PendingReceiver<device::mojom::SensorProvider> receiver) {
6891 if (!sensor_provider_proxy_) {
6892 sensor_provider_proxy_.reset(new SensorProviderProxyImpl(
6893 PermissionControllerImpl::FromBrowserContext(
6894 GetProcess()->GetBrowserContext()),
6895 this));
6896 }
6897 sensor_provider_proxy_->Bind(std::move(receiver));
6898 }
6899
6900 mojo::Remote<blink::mojom::FileChooser>
BindFileChooserForTesting()6901 RenderFrameHostImpl::BindFileChooserForTesting() {
6902 mojo::Remote<blink::mojom::FileChooser> chooser;
6903 FileChooserImpl::Create(this, chooser.BindNewPipeAndPassReceiver());
6904 return chooser;
6905 }
6906
BindCacheStorage(mojo::PendingReceiver<blink::mojom::CacheStorage> receiver)6907 void RenderFrameHostImpl::BindCacheStorage(
6908 mojo::PendingReceiver<blink::mojom::CacheStorage> receiver) {
6909 mojo::PendingRemote<network::mojom::CrossOriginEmbedderPolicyReporter>
6910 coep_reporter_remote;
6911 if (coep_reporter_) {
6912 coep_reporter_->Clone(
6913 coep_reporter_remote.InitWithNewPipeAndPassReceiver());
6914 }
6915 GetProcess()->BindCacheStorage(cross_origin_embedder_policy_,
6916 std::move(coep_reporter_remote),
6917 GetLastCommittedOrigin(), std::move(receiver));
6918 }
6919
BindInputInjectorReceiver(mojo::PendingReceiver<mojom::InputInjector> receiver)6920 void RenderFrameHostImpl::BindInputInjectorReceiver(
6921 mojo::PendingReceiver<mojom::InputInjector> receiver) {
6922 InputInjectorImpl::Create(weak_ptr_factory_.GetWeakPtr(),
6923 std::move(receiver));
6924 }
6925
BindSmsReceiverReceiver(mojo::PendingReceiver<blink::mojom::SmsReceiver> receiver)6926 void RenderFrameHostImpl::BindSmsReceiverReceiver(
6927 mojo::PendingReceiver<blink::mojom::SmsReceiver> receiver) {
6928 if (GetParent() && !GetMainFrame()->GetLastCommittedOrigin().IsSameOriginWith(
6929 GetLastCommittedOrigin())) {
6930 mojo::ReportBadMessage("Must have the same origin as the top-level frame.");
6931 return;
6932 }
6933 auto* fetcher = SmsFetcher::Get(GetProcess()->GetBrowserContext(),
6934 weak_ptr_factory_.GetWeakPtr());
6935 SmsService::Create(fetcher, this, std::move(receiver));
6936 }
6937
BindRestrictedCookieManager(mojo::PendingReceiver<network::mojom::RestrictedCookieManager> receiver)6938 void RenderFrameHostImpl::BindRestrictedCookieManager(
6939 mojo::PendingReceiver<network::mojom::RestrictedCookieManager> receiver) {
6940 GetProcess()->GetStoragePartition()->CreateRestrictedCookieManager(
6941 network::mojom::RestrictedCookieManagerRole::SCRIPT,
6942 GetLastCommittedOrigin(), ComputeSiteForCookies(),
6943 ComputeTopFrameOrigin(GetLastCommittedOrigin()),
6944 /* is_service_worker = */ false, GetProcess()->GetID(), routing_id(),
6945 std::move(receiver));
6946 }
6947
GetInterface(const std::string & interface_name,mojo::ScopedMessagePipeHandle interface_pipe)6948 void RenderFrameHostImpl::GetInterface(
6949 const std::string& interface_name,
6950 mojo::ScopedMessagePipeHandle interface_pipe) {
6951 // Requests are serviced on |document_scoped_interface_provider_receiver_|. It
6952 // is therefore safe to assume that every incoming interface request is coming
6953 // from the currently active document in the corresponding RenderFrame.
6954 if (!registry_ ||
6955 !registry_->TryBindInterface(interface_name, &interface_pipe)) {
6956 delegate_->OnInterfaceRequest(this, interface_name, &interface_pipe);
6957 if (interface_pipe.is_valid()) {
6958 GetContentClient()->browser()->BindInterfaceRequestFromFrame(
6959 this, interface_name, std::move(interface_pipe));
6960 }
6961 }
6962 }
6963
CreateAppCacheBackend(mojo::PendingReceiver<blink::mojom::AppCacheBackend> receiver)6964 void RenderFrameHostImpl::CreateAppCacheBackend(
6965 mojo::PendingReceiver<blink::mojom::AppCacheBackend> receiver) {
6966 DCHECK_CURRENTLY_ON(BrowserThread::UI);
6967 auto* storage_partition_impl =
6968 static_cast<StoragePartitionImpl*>(GetProcess()->GetStoragePartition());
6969 storage_partition_impl->GetAppCacheService()->CreateBackend(
6970 GetProcess()->GetID(), routing_id_, std::move(receiver));
6971 }
6972
GetAudioContextManager(mojo::PendingReceiver<blink::mojom::AudioContextManager> receiver)6973 void RenderFrameHostImpl::GetAudioContextManager(
6974 mojo::PendingReceiver<blink::mojom::AudioContextManager> receiver) {
6975 AudioContextManagerImpl::Create(this, std::move(receiver));
6976 }
6977
GetContactsManager(mojo::PendingReceiver<blink::mojom::ContactsManager> receiver)6978 void RenderFrameHostImpl::GetContactsManager(
6979 mojo::PendingReceiver<blink::mojom::ContactsManager> receiver) {
6980 ContactsManagerImpl::Create(this, std::move(receiver));
6981 }
6982
GetFileSystemManager(mojo::PendingReceiver<blink::mojom::FileSystemManager> receiver)6983 void RenderFrameHostImpl::GetFileSystemManager(
6984 mojo::PendingReceiver<blink::mojom::FileSystemManager> receiver) {
6985 // This is safe because file_system_manager_ is deleted on the IO thread
6986 base::PostTask(FROM_HERE, {BrowserThread::IO},
6987 base::BindOnce(&FileSystemManagerImpl::BindReceiver,
6988 base::Unretained(file_system_manager_.get()),
6989 std::move(receiver)));
6990 }
6991
GetGeolocationService(mojo::PendingReceiver<blink::mojom::GeolocationService> receiver)6992 void RenderFrameHostImpl::GetGeolocationService(
6993 mojo::PendingReceiver<blink::mojom::GeolocationService> receiver) {
6994 if (!geolocation_service_) {
6995 auto* geolocation_context = delegate_->GetGeolocationContext();
6996 if (!geolocation_context)
6997 return;
6998 geolocation_service_ =
6999 std::make_unique<GeolocationServiceImpl>(geolocation_context, this);
7000 }
7001 geolocation_service_->Bind(std::move(receiver));
7002 }
7003
GetNativeFileSystemManager(mojo::PendingReceiver<blink::mojom::NativeFileSystemManager> receiver)7004 void RenderFrameHostImpl::GetNativeFileSystemManager(
7005 mojo::PendingReceiver<blink::mojom::NativeFileSystemManager> receiver) {
7006 DCHECK_CURRENTLY_ON(BrowserThread::UI);
7007 auto* storage_partition =
7008 static_cast<StoragePartitionImpl*>(GetProcess()->GetStoragePartition());
7009 auto* manager = storage_partition->GetNativeFileSystemManager();
7010 manager->BindReceiver(NativeFileSystemManagerImpl::BindingContext(
7011 GetLastCommittedOrigin(), GetLastCommittedURL(),
7012 GetProcess()->GetID(), routing_id_),
7013 std::move(receiver));
7014 }
7015
CreateLockManager(mojo::PendingReceiver<blink::mojom::LockManager> receiver)7016 void RenderFrameHostImpl::CreateLockManager(
7017 mojo::PendingReceiver<blink::mojom::LockManager> receiver) {
7018 GetProcess()->CreateLockManager(GetRoutingID(), GetLastCommittedOrigin(),
7019 std::move(receiver));
7020 }
7021
CreateIDBFactory(mojo::PendingReceiver<blink::mojom::IDBFactory> receiver)7022 void RenderFrameHostImpl::CreateIDBFactory(
7023 mojo::PendingReceiver<blink::mojom::IDBFactory> receiver) {
7024 GetProcess()->BindIndexedDB(GetLastCommittedOrigin(), std::move(receiver));
7025 }
7026
CreatePermissionService(mojo::PendingReceiver<blink::mojom::PermissionService> receiver)7027 void RenderFrameHostImpl::CreatePermissionService(
7028 mojo::PendingReceiver<blink::mojom::PermissionService> receiver) {
7029 if (!permission_service_context_)
7030 permission_service_context_.reset(new PermissionServiceContext(this));
7031
7032 permission_service_context_->CreateService(std::move(receiver));
7033 }
7034
GetAuthenticator(mojo::PendingReceiver<blink::mojom::Authenticator> receiver)7035 void RenderFrameHostImpl::GetAuthenticator(
7036 mojo::PendingReceiver<blink::mojom::Authenticator> receiver) {
7037 #if BUILDFLAG(ENABLE_WEB_AUTH)
7038 if (base::FeatureList::IsEnabled(features::kWebAuth)) {
7039 BindAuthenticatorReceiver(std::move(receiver));
7040 }
7041 #elif defined(OS_ANDROID)
7042 GetJavaInterfaces()->GetInterface(std::move(receiver));
7043 #endif // !defined(OS_ANDROID)
7044 }
7045
GetCredentialManager(mojo::PendingReceiver<blink::mojom::CredentialManager> receiver)7046 void RenderFrameHostImpl::GetCredentialManager(
7047 mojo::PendingReceiver<blink::mojom::CredentialManager> receiver) {
7048 GetContentClient()->browser()->BindCredentialManagerReceiver(
7049 this, std::move(receiver));
7050 }
7051
GetPushMessaging(mojo::PendingReceiver<blink::mojom::PushMessaging> receiver)7052 void RenderFrameHostImpl::GetPushMessaging(
7053 mojo::PendingReceiver<blink::mojom::PushMessaging> receiver) {
7054 if (!push_messaging_manager_) {
7055 push_messaging_manager_.reset(new PushMessagingManager(
7056 GetProcess()->GetID(), routing_id_,
7057 static_cast<StoragePartitionImpl*>(GetProcess()->GetStoragePartition())
7058 ->GetServiceWorkerContext()));
7059 }
7060
7061 RunOrPostTaskOnThread(
7062 FROM_HERE, ServiceWorkerContext::GetCoreThreadId(),
7063 base::BindOnce(&PushMessagingManager::AddPushMessagingReceiver,
7064 push_messaging_manager_->AsWeakPtr(),
7065 std::move(receiver)));
7066 }
7067
GetVirtualAuthenticatorManager(mojo::PendingReceiver<blink::test::mojom::VirtualAuthenticatorManager> receiver)7068 void RenderFrameHostImpl::GetVirtualAuthenticatorManager(
7069 mojo::PendingReceiver<blink::test::mojom::VirtualAuthenticatorManager>
7070 receiver) {
7071 #if BUILDFLAG(ENABLE_WEB_AUTH)
7072 if (base::FeatureList::IsEnabled(features::kWebAuth)) {
7073 auto* environment_singleton = AuthenticatorEnvironmentImpl::GetInstance();
7074 environment_singleton->EnableVirtualAuthenticatorFor(frame_tree_node_);
7075 environment_singleton->AddVirtualAuthenticatorReceiver(frame_tree_node_,
7076 std::move(receiver));
7077 }
7078 #endif // !defined(OS_ANDROID)
7079 }
7080
7081 std::unique_ptr<NavigationRequest>
CreateNavigationRequestForCommit(const FrameHostMsg_DidCommitProvisionalLoad_Params & params,bool is_same_document,NavigationEntryImpl * entry_for_request)7082 RenderFrameHostImpl::CreateNavigationRequestForCommit(
7083 const FrameHostMsg_DidCommitProvisionalLoad_Params& params,
7084 bool is_same_document,
7085 NavigationEntryImpl* entry_for_request) {
7086 bool is_renderer_initiated =
7087 entry_for_request ? entry_for_request->is_renderer_initiated() : true;
7088 return NavigationRequest::CreateForCommit(
7089 frame_tree_node_, this, entry_for_request, params, is_renderer_initiated,
7090 is_same_document);
7091 }
7092
NavigationRequestWasIntendedForPendingEntry(NavigationRequest * request,const FrameHostMsg_DidCommitProvisionalLoad_Params & params,bool same_document)7093 bool RenderFrameHostImpl::NavigationRequestWasIntendedForPendingEntry(
7094 NavigationRequest* request,
7095 const FrameHostMsg_DidCommitProvisionalLoad_Params& params,
7096 bool same_document) {
7097 NavigationEntryImpl* pending_entry = NavigationEntryImpl::FromNavigationEntry(
7098 frame_tree_node()->navigator()->GetController()->GetPendingEntry());
7099 if (!pending_entry)
7100 return false;
7101 if (request->nav_entry_id() != pending_entry->GetUniqueID())
7102 return false;
7103 if (!same_document) {
7104 // Make sure that the pending entry was really loaded via
7105 // LoadDataWithBaseURL and that it matches this handle.
7106 // TODO(csharrison): The pending entry's base url should equal
7107 // |params.base_url|. This is not the case for loads with invalid base urls.
7108 if (request->common_params().url != params.base_url ||
7109 pending_entry->GetBaseURLForDataURL().is_empty()) {
7110 return false;
7111 }
7112 }
7113 return true;
7114 }
7115
BeforeUnloadTimeout()7116 void RenderFrameHostImpl::BeforeUnloadTimeout() {
7117 if (render_view_host_->GetDelegate()->ShouldIgnoreUnresponsiveRenderer())
7118 return;
7119
7120 SimulateBeforeUnloadCompleted(true /* proceed */);
7121 }
7122
SetLastCommittedSiteUrl(const GURL & url)7123 void RenderFrameHostImpl::SetLastCommittedSiteUrl(const GURL& url) {
7124 GURL site_url = url.is_empty()
7125 ? GURL()
7126 : SiteInstanceImpl::GetSiteForURL(
7127 GetSiteInstance()->GetIsolationContext(), url);
7128
7129 if (last_committed_site_url_ == site_url)
7130 return;
7131
7132 if (!last_committed_site_url_.is_empty()) {
7133 RenderProcessHostImpl::RemoveFrameWithSite(
7134 frame_tree_node_->navigator()->GetController()->GetBrowserContext(),
7135 GetProcess(), last_committed_site_url_);
7136 }
7137
7138 last_committed_site_url_ = site_url;
7139
7140 if (!last_committed_site_url_.is_empty()) {
7141 RenderProcessHostImpl::AddFrameWithSite(
7142 frame_tree_node_->navigator()->GetController()->GetBrowserContext(),
7143 GetProcess(), last_committed_site_url_);
7144 }
7145 }
7146
7147 #if defined(OS_ANDROID)
7148
7149 class RenderFrameHostImpl::JavaInterfaceProvider
7150 : public service_manager::mojom::InterfaceProvider {
7151 public:
7152 using BindCallback =
7153 base::RepeatingCallback<void(const std::string&,
7154 mojo::ScopedMessagePipeHandle)>;
7155
JavaInterfaceProvider(const BindCallback & bind_callback,mojo::PendingReceiver<service_manager::mojom::InterfaceProvider> receiver)7156 JavaInterfaceProvider(
7157 const BindCallback& bind_callback,
7158 mojo::PendingReceiver<service_manager::mojom::InterfaceProvider> receiver)
7159 : bind_callback_(bind_callback), receiver_(this, std::move(receiver)) {}
7160 ~JavaInterfaceProvider() override = default;
7161
7162 private:
7163 // service_manager::mojom::InterfaceProvider:
GetInterface(const std::string & interface_name,mojo::ScopedMessagePipeHandle handle)7164 void GetInterface(const std::string& interface_name,
7165 mojo::ScopedMessagePipeHandle handle) override {
7166 bind_callback_.Run(interface_name, std::move(handle));
7167 }
7168
7169 const BindCallback bind_callback_;
7170 mojo::Receiver<service_manager::mojom::InterfaceProvider> receiver_;
7171
7172 DISALLOW_COPY_AND_ASSIGN(JavaInterfaceProvider);
7173 };
7174
7175 base::android::ScopedJavaLocalRef<jobject>
GetJavaRenderFrameHost()7176 RenderFrameHostImpl::GetJavaRenderFrameHost() {
7177 RenderFrameHostAndroid* render_frame_host_android =
7178 static_cast<RenderFrameHostAndroid*>(
7179 GetUserData(kRenderFrameHostAndroidKey));
7180 if (!render_frame_host_android) {
7181 mojo::PendingRemote<service_manager::mojom::InterfaceProvider>
7182 interface_provider_remote;
7183 java_interface_registry_ = std::make_unique<JavaInterfaceProvider>(
7184 base::BindRepeating(
7185 &RenderFrameHostImpl::ForwardGetInterfaceToRenderFrame,
7186 weak_ptr_factory_.GetWeakPtr()),
7187 interface_provider_remote.InitWithNewPipeAndPassReceiver());
7188 render_frame_host_android =
7189 new RenderFrameHostAndroid(this, std::move(interface_provider_remote));
7190 SetUserData(kRenderFrameHostAndroidKey,
7191 base::WrapUnique(render_frame_host_android));
7192 }
7193 return render_frame_host_android->GetJavaObject();
7194 }
7195
GetJavaInterfaces()7196 service_manager::InterfaceProvider* RenderFrameHostImpl::GetJavaInterfaces() {
7197 if (!java_interfaces_) {
7198 mojo::PendingRemote<service_manager::mojom::InterfaceProvider> provider;
7199 BindInterfaceRegistryForRenderFrameHost(
7200 provider.InitWithNewPipeAndPassReceiver(), this);
7201 java_interfaces_.reset(new service_manager::InterfaceProvider);
7202 java_interfaces_->Bind(std::move(provider));
7203 }
7204 return java_interfaces_.get();
7205 }
7206
ForwardGetInterfaceToRenderFrame(const std::string & interface_name,mojo::ScopedMessagePipeHandle pipe)7207 void RenderFrameHostImpl::ForwardGetInterfaceToRenderFrame(
7208 const std::string& interface_name,
7209 mojo::ScopedMessagePipeHandle pipe) {
7210 GetRemoteInterfaces()->GetInterfaceByName(interface_name, std::move(pipe));
7211 }
7212 #endif
7213
ForEachImmediateLocalRoot(const base::RepeatingCallback<void (RenderFrameHostImpl *)> & callback)7214 void RenderFrameHostImpl::ForEachImmediateLocalRoot(
7215 const base::RepeatingCallback<void(RenderFrameHostImpl*)>& callback) {
7216 if (!frame_tree_node_->child_count())
7217 return;
7218
7219 base::queue<FrameTreeNode*> queue;
7220 for (size_t index = 0; index < frame_tree_node_->child_count(); ++index)
7221 queue.push(frame_tree_node_->child_at(index));
7222 while (queue.size()) {
7223 FrameTreeNode* current = queue.front();
7224 queue.pop();
7225 if (current->current_frame_host()->is_local_root()) {
7226 callback.Run(current->current_frame_host());
7227 } else {
7228 for (size_t index = 0; index < current->child_count(); ++index)
7229 queue.push(current->child_at(index));
7230 }
7231 }
7232 }
7233
SetVisibilityForChildViews(bool visible)7234 void RenderFrameHostImpl::SetVisibilityForChildViews(bool visible) {
7235 ForEachImmediateLocalRoot(base::BindRepeating(
7236 [](bool is_visible, RenderFrameHostImpl* frame_host) {
7237 if (auto* view = frame_host->GetView())
7238 return is_visible ? view->Show() : view->Hide();
7239 },
7240 visible));
7241 }
7242
GetNavigationControl()7243 mojom::FrameNavigationControl* RenderFrameHostImpl::GetNavigationControl() {
7244 if (!navigation_control_)
7245 GetRemoteAssociatedInterfaces()->GetInterface(&navigation_control_);
7246 return navigation_control_.get();
7247 }
7248
ValidateDidCommitParams(NavigationRequest * navigation_request,FrameHostMsg_DidCommitProvisionalLoad_Params * params,bool is_same_document_navigation)7249 bool RenderFrameHostImpl::ValidateDidCommitParams(
7250 NavigationRequest* navigation_request,
7251 FrameHostMsg_DidCommitProvisionalLoad_Params* params,
7252 bool is_same_document_navigation) {
7253 RenderProcessHost* process = GetProcess();
7254
7255 // Error pages may sometimes commit a URL in the wrong process, which requires
7256 // an exception for the CanCommitOriginAndUrl() checks. This is ok as long
7257 // as the origin is opaque.
7258 bool bypass_checks_for_error_page = false;
7259 if (SiteIsolationPolicy::IsErrorPageIsolationEnabled(
7260 frame_tree_node_->IsMainFrame())) {
7261 if (site_instance_->GetSiteURL() == GURL(content::kUnreachableWebDataURL)) {
7262 // Commits in the error page process must only be failures, otherwise
7263 // successful navigations could commit documents from origins different
7264 // than the chrome-error://chromewebdata/ one and violate expectations.
7265 if (!params->url_is_unreachable) {
7266 DEBUG_ALIAS_FOR_ORIGIN(origin_debug_alias, params->origin);
7267 bad_message::ReceivedBadMessage(
7268 process, bad_message::RFH_ERROR_PROCESS_NON_ERROR_COMMIT);
7269 return false;
7270 }
7271 // With error page isolation, any URL can commit in an error page process.
7272 bypass_checks_for_error_page = true;
7273 }
7274 } else {
7275 // Without error page isolation, a blocked navigation is expected to
7276 // commit in the old renderer process. This may be true for subframe
7277 // navigations even when error page isolation is enabled for main frames.
7278 if (navigation_request &&
7279 navigation_request->GetNetErrorCode() == net::ERR_BLOCKED_BY_CLIENT) {
7280 bypass_checks_for_error_page = true;
7281 }
7282 }
7283
7284 // Error pages must commit in a opaque origin. Terminate the renderer
7285 // process if this is violated.
7286 if (bypass_checks_for_error_page && !params->origin.opaque()) {
7287 DEBUG_ALIAS_FOR_ORIGIN(origin_debug_alias, params->origin);
7288 bad_message::ReceivedBadMessage(
7289 process, bad_message::RFH_ERROR_PROCESS_NON_UNIQUE_ORIGIN_COMMIT);
7290 return false;
7291 }
7292
7293 // file: URLs can be allowed to access any other origin, based on settings.
7294 bool bypass_checks_for_file_scheme = false;
7295 if (params->origin.scheme() == url::kFileScheme) {
7296 WebPreferences prefs = render_view_host_->GetWebkitPreferences();
7297 if (prefs.allow_universal_access_from_file_urls)
7298 bypass_checks_for_file_scheme = true;
7299 }
7300
7301 // WebView's loadDataWithBaseURL API is allowed to bypass normal commit
7302 // checks because it is allowed to commit anything into its unlocked process
7303 // and its data: URL and non-opaque origin would fail the normal commit
7304 // checks.
7305 bool bypass_checks_for_webview = false;
7306 if ((navigation_request &&
7307 IsLoadDataWithBaseURL(navigation_request->common_params())) ||
7308 (is_same_document_navigation && IsLoadDataWithBaseURL(*params))) {
7309 // Allow bypass if the process isn't locked. Otherwise run normal checks.
7310 bypass_checks_for_webview = ChildProcessSecurityPolicyImpl::GetInstance()
7311 ->GetOriginLock(process->GetID())
7312 .is_empty();
7313 }
7314
7315 if (!bypass_checks_for_error_page && !bypass_checks_for_file_scheme &&
7316 !bypass_checks_for_webview) {
7317 // Attempts to commit certain off-limits URL should be caught more strictly
7318 // than our FilterURL checks. If a renderer violates this policy, it
7319 // should be killed.
7320 switch (CanCommitOriginAndUrl(params->origin, params->url)) {
7321 case CanCommitStatus::CAN_COMMIT_ORIGIN_AND_URL:
7322 // The origin and URL are safe to commit.
7323 break;
7324 case CanCommitStatus::CANNOT_COMMIT_URL:
7325 DLOG(ERROR) << "CANNOT_COMMIT_URL url '" << params->url << "'"
7326 << " origin '" << params->origin << "'"
7327 << " lock '"
7328 << ChildProcessSecurityPolicyImpl::GetInstance()
7329 ->GetOriginLock(process->GetID())
7330 << "'";
7331 VLOG(1) << "Blocked URL " << params->url.spec();
7332 LogCannotCommitUrlCrashKeys(params->url, is_same_document_navigation,
7333 navigation_request);
7334
7335 // Kills the process.
7336 bad_message::ReceivedBadMessage(
7337 process, bad_message::RFH_CAN_COMMIT_URL_BLOCKED);
7338 return false;
7339 case CanCommitStatus::CANNOT_COMMIT_ORIGIN:
7340 DLOG(ERROR) << "CANNOT_COMMIT_ORIGIN url '" << params->url << "'"
7341 << " origin '" << params->origin << "'"
7342 << " lock '"
7343 << ChildProcessSecurityPolicyImpl::GetInstance()
7344 ->GetOriginLock(process->GetID())
7345 << "'";
7346 DEBUG_ALIAS_FOR_ORIGIN(origin_debug_alias, params->origin);
7347 LogCannotCommitOriginCrashKeys(is_same_document_navigation,
7348 navigation_request);
7349
7350 // Kills the process.
7351 bad_message::ReceivedBadMessage(
7352 process, bad_message::RFH_INVALID_ORIGIN_ON_COMMIT);
7353 return false;
7354 }
7355 }
7356
7357 // Without this check, an evil renderer can trick the browser into creating
7358 // a navigation entry for a banned URL. If the user clicks the back button
7359 // followed by the forward button (or clicks reload, or round-trips through
7360 // session restore, etc), we'll think that the browser commanded the
7361 // renderer to load the URL and grant the renderer the privileges to request
7362 // the URL. To prevent this attack, we block the renderer from inserting
7363 // banned URLs into the navigation controller in the first place.
7364 //
7365 // TODO(https://crbug.com/172694): Currently, when FilterURL detects a bad URL
7366 // coming from the renderer, it overwrites that URL to about:blank, which
7367 // requires |params| to be mutable. Once we kill the renderer
7368 // instead, the signature of RenderFrameHostImpl::DidCommitProvisionalLoad can
7369 // be modified to take |params| by const reference.
7370 process->FilterURL(false, ¶ms->url);
7371 process->FilterURL(true, ¶ms->referrer.url);
7372 for (auto it(params->redirects.begin()); it != params->redirects.end();
7373 ++it) {
7374 process->FilterURL(false, &(*it));
7375 }
7376
7377 // Without this check, the renderer can trick the browser into using
7378 // filenames it can't access in a future session restore.
7379 if (!CanAccessFilesOfPageState(params->page_state)) {
7380 bad_message::ReceivedBadMessage(
7381 process, bad_message::RFH_CAN_ACCESS_FILES_OF_PAGE_STATE);
7382 return false;
7383 }
7384
7385 // A cross-document navigation requires an embedding token for all embedded
7386 // frames (a child frame to a remote parent). Embedding tokens should not
7387 // exist for other cases.
7388 if (!is_same_document_navigation) {
7389 if (frame_tree_node()->IsMainFrame() &&
7390 params->embedding_token.has_value()) {
7391 bad_message::ReceivedBadMessage(
7392 process, bad_message::RFH_UNEXPECTED_EMBEDDING_TOKEN);
7393 return false;
7394 } else if (IsCrossProcessSubframe() &&
7395 !params->embedding_token.has_value()) {
7396 bad_message::ReceivedBadMessage(process,
7397 bad_message::RFH_MISSING_EMBEDDING_TOKEN);
7398 return false;
7399 }
7400 } else if (params->embedding_token.has_value()) {
7401 bad_message::ReceivedBadMessage(
7402 process, bad_message::RFH_UNEXPECTED_EMBEDDING_TOKEN);
7403 return false;
7404 }
7405
7406 return true;
7407 }
7408
UpdateSiteURL(const GURL & url,bool url_is_unreachable)7409 void RenderFrameHostImpl::UpdateSiteURL(const GURL& url,
7410 bool url_is_unreachable) {
7411 if (url_is_unreachable || delegate_->GetAsInterstitialPage()) {
7412 SetLastCommittedSiteUrl(GURL());
7413 } else {
7414 SetLastCommittedSiteUrl(url);
7415 }
7416 }
7417
DidCommitNavigationInternal(std::unique_ptr<NavigationRequest> navigation_request,std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params> params,bool is_same_document_navigation)7418 bool RenderFrameHostImpl::DidCommitNavigationInternal(
7419 std::unique_ptr<NavigationRequest> navigation_request,
7420 std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params> params,
7421 bool is_same_document_navigation) {
7422 // Sanity-check the page transition for frame type.
7423 DCHECK_EQ(ui::PageTransitionIsMainFrame(params->transition), !GetParent());
7424
7425 // Check that the committing navigation token matches the navigation request.
7426 if (navigation_request &&
7427 navigation_request->commit_params().navigation_token !=
7428 params->navigation_token) {
7429 navigation_request.reset();
7430 }
7431
7432 if (!navigation_request) {
7433 // A matching NavigationRequest should have been found, unless in a few very
7434 // specific cases. Check if this is one of those cases.
7435 bool is_commit_allowed_to_proceed = false;
7436
7437 // 1) This was a renderer-initiated navigation to an empty document. Most
7438 // of the time: about:blank.
7439 is_commit_allowed_to_proceed |= params->url.SchemeIs(url::kAboutScheme) &&
7440 params->url != GURL(url::kAboutSrcdocURL);
7441
7442 // 2) This was a same-document navigation.
7443 // TODO(clamy): We should enforce having a request on browser-initiated
7444 // same-document navigations.
7445 is_commit_allowed_to_proceed |= is_same_document_navigation;
7446
7447 // 3) Transient interstitial page commits will not have a matching
7448 // NavigationRequest.
7449 // TODO(clamy): Enforce having a NavigationRequest for data URLs when
7450 // committed interstitials have launched or interstitials create
7451 // NavigationRequests.
7452 is_commit_allowed_to_proceed |= !!delegate_->GetAsInterstitialPage();
7453
7454 // 4) Error pages implementations in Chrome can commit twice.
7455 // TODO(clamy): Fix this.
7456 is_commit_allowed_to_proceed |= params->url_is_unreachable;
7457
7458 // 5) Special case for DOMSerializerBrowsertests which are implemented
7459 // entirely renderer-side and unlike normal RenderView based tests load
7460 // file URLs instead of data URLs.
7461 // TODO(clamy): Rework the tests to remove this exception.
7462 is_commit_allowed_to_proceed |= params->url.SchemeIsFile();
7463
7464 if (!is_commit_allowed_to_proceed) {
7465 bad_message::ReceivedBadMessage(
7466 GetProcess(),
7467 bad_message::RFH_NO_MATCHING_NAVIGATION_REQUEST_ON_COMMIT);
7468 return false;
7469 }
7470 }
7471
7472 if (!ValidateDidCommitParams(navigation_request.get(), params.get(),
7473 is_same_document_navigation)) {
7474 return false;
7475 }
7476
7477 // TODO(clamy): We should stop having a special case for same-document
7478 // navigation and just put them in the general map of NavigationRequests.
7479 if (navigation_request &&
7480 navigation_request->common_params().url != params->url &&
7481 is_same_document_navigation) {
7482 same_document_navigation_request_ = std::move(navigation_request);
7483 }
7484
7485 // Set is loading to true now if it has not been set yet. This happens for
7486 // renderer-initiated same-document navigations. It can also happen when a
7487 // racy DidStopLoading IPC resets the loading state that was set to true in
7488 // CommitNavigation.
7489 if (!is_loading()) {
7490 bool was_loading = frame_tree_node()->frame_tree()->IsLoading();
7491 is_loading_ = true;
7492 frame_tree_node()->DidStartLoading(!is_same_document_navigation,
7493 was_loading);
7494 }
7495
7496 if (navigation_request)
7497 was_discarded_ = navigation_request->commit_params().was_discarded;
7498
7499 // If there is no valid NavigationRequest corresponding to this commit, create
7500 // one in order to properly issue DidFinishNavigation calls to
7501 // WebContentsObservers.
7502 if (!navigation_request) {
7503 navigation_request = CreateNavigationRequestForCommit(
7504 *params, is_same_document_navigation, nullptr);
7505 }
7506
7507 DCHECK(navigation_request);
7508 DCHECK(navigation_request->IsNavigationStarted());
7509
7510 // Update the page transition. For subframe navigations, the renderer process
7511 // only gives the correct page transition at commit time.
7512 // TODO(clamy): We should get the correct page transition when starting the
7513 // request.
7514 navigation_request->set_transition(params->transition);
7515
7516 navigation_request->set_has_user_gesture(params->gesture ==
7517 NavigationGestureUser);
7518
7519 last_http_status_code_ = params->http_status_code;
7520 last_http_method_ = params->method;
7521 UpdateSiteURL(params->url, params->url_is_unreachable);
7522 if (!is_same_document_navigation)
7523 UpdateRenderProcessHostFramePriorities();
7524
7525 // Set the state whether this navigation is to an MHTML document, since there
7526 // are certain security checks that we cannot apply to subframes in MHTML
7527 // documents. Do not trust renderer data when determining that, rather use
7528 // the |navigation_request|, which was generated and stays browser side.
7529 is_mhtml_document_ =
7530 (navigation_request->GetMimeType() == "multipart/related" ||
7531 navigation_request->GetMimeType() == "message/rfc822");
7532
7533 accessibility_reset_count_ = 0;
7534 appcache_handle_ = navigation_request->TakeAppCacheHandle();
7535
7536 if (navigation_request->IsInMainFrame() &&
7537 !navigation_request->IsSameDocument() &&
7538 !navigation_request->IsServedFromBackForwardCache()) {
7539 render_view_host_->ResetPerPageState();
7540 }
7541
7542 // If we still have a PeakGpuMemoryTracker, then the loading it was observing
7543 // never completed. Cancel it's callback so that we don't report partial
7544 // loads to UMA.
7545 if (loading_mem_tracker_)
7546 loading_mem_tracker_->Cancel();
7547 // Main Frames will create the tracker, which will be triggered after we
7548 // receive OnDidStopLoading.
7549 loading_mem_tracker_ = navigation_request->TakePeakGpuMemoryTracker();
7550
7551 network::mojom::ClientSecurityStatePtr client_security_state =
7552 navigation_request->TakeClientSecurityState();
7553 std::unique_ptr<CrossOriginEmbedderPolicyReporter> coep_reporter =
7554 navigation_request->TakeCoepReporter();
7555
7556 frame_tree_node()->navigator()->DidNavigate(this, *params,
7557 std::move(navigation_request),
7558 is_same_document_navigation);
7559
7560 if (IsBackForwardCacheEnabled()) {
7561 // Store the Commit params so they can be reused if the page is ever
7562 // restored from the BackForwardCache.
7563 last_commit_params_ = std::move(params);
7564 }
7565
7566 if (!is_same_document_navigation) {
7567 cookie_no_samesite_deprecation_url_hashes_.clear();
7568 cookie_samesite_none_insecure_deprecation_url_hashes_.clear();
7569 renderer_reported_scheduler_tracked_features_ = 0;
7570 browser_reported_scheduler_tracked_features_ = 0;
7571 last_committed_client_security_state_ = std::move(client_security_state);
7572 coep_reporter_ = std::move(coep_reporter);
7573 }
7574
7575 RecordCrossOriginIsolationMetrics(this);
7576
7577 return true;
7578 }
7579
OnSameDocumentCommitProcessed(int64_t navigation_id,bool should_replace_current_entry,blink::mojom::CommitResult result)7580 void RenderFrameHostImpl::OnSameDocumentCommitProcessed(
7581 int64_t navigation_id,
7582 bool should_replace_current_entry,
7583 blink::mojom::CommitResult result) {
7584 // If the NavigationRequest was deleted, another navigation commit started to
7585 // be processed. Let the latest commit go through and stop doing anything.
7586 if (!same_document_navigation_request_ ||
7587 same_document_navigation_request_->GetNavigationId() != navigation_id) {
7588 return;
7589 }
7590
7591 if (result == blink::mojom::CommitResult::RestartCrossDocument) {
7592 // The navigation could not be committed as a same-document navigation.
7593 // Restart the navigation cross-document.
7594 frame_tree_node_->navigator()->RestartNavigationAsCrossDocument(
7595 std::move(same_document_navigation_request_));
7596 }
7597
7598 if (result == blink::mojom::CommitResult::Aborted) {
7599 // Note: if the commit was successful, navigation_request_ is reset in
7600 // DidCommitProvisionalLoad.
7601 same_document_navigation_request_.reset();
7602 }
7603 }
7604
OnCrossDocumentCommitProcessed(NavigationRequest * navigation_request,blink::mojom::CommitResult result)7605 void RenderFrameHostImpl::OnCrossDocumentCommitProcessed(
7606 NavigationRequest* navigation_request,
7607 blink::mojom::CommitResult result) {
7608 DCHECK_NE(blink::mojom::CommitResult::RestartCrossDocument, result);
7609 if (result == blink::mojom::CommitResult::Ok) {
7610 // The navigation will soon be committed. Move it out of the map to the
7611 // NavigationRequest that is about to commit.
7612 auto find_request = navigation_requests_.find(navigation_request);
7613 if (find_request != navigation_requests_.end()) {
7614 navigation_request_ = std::move(find_request->second);
7615 } else {
7616 // This frame might be used for attaching an inner WebContents in which
7617 // case |navigation_requests_| are deleted during attaching.
7618 // TODO(ekaramad): Add a DCHECK to ensure the FrameTreeNode is attaching
7619 // an inner delegate (https://crbug.com/911161).
7620 }
7621 }
7622 // Remove the requests from the list of NavigationRequests waiting to commit.
7623 navigation_requests_.erase(navigation_request);
7624 }
7625
7626 std::unique_ptr<base::trace_event::TracedValue>
CommitAsTracedValue(FrameHostMsg_DidCommitProvisionalLoad_Params * params) const7627 RenderFrameHostImpl::CommitAsTracedValue(
7628 FrameHostMsg_DidCommitProvisionalLoad_Params* params) const {
7629 auto value = std::make_unique<base::trace_event::TracedValue>();
7630
7631 value->SetInteger("frame_tree_node", frame_tree_node_->frame_tree_node_id());
7632 value->SetInteger("site id", site_instance_->GetId());
7633 value->SetString("process lock", ChildProcessSecurityPolicyImpl::GetInstance()
7634 ->GetOriginLock(process_->GetID())
7635 .possibly_invalid_spec());
7636 value->SetString("origin", params->origin.Serialize());
7637 value->SetInteger("transition", params->transition);
7638
7639 if (!params->base_url.is_empty()) {
7640 value->SetString("base_url", params->base_url.possibly_invalid_spec());
7641 }
7642
7643 return value;
7644 }
7645
MaybeGenerateCrashReport(base::TerminationStatus status,int exit_code)7646 void RenderFrameHostImpl::MaybeGenerateCrashReport(
7647 base::TerminationStatus status,
7648 int exit_code) {
7649 if (!last_committed_url_.SchemeIsHTTPOrHTTPS())
7650 return;
7651
7652 // Only generate reports for local root frames.
7653 if (!frame_tree_node_->IsMainFrame() && !IsCrossProcessSubframe())
7654 return;
7655
7656 // Check the termination status to see if a crash occurred (and potentially
7657 // determine the |reason| for the crash).
7658 std::string reason;
7659 switch (status) {
7660 case base::TERMINATION_STATUS_ABNORMAL_TERMINATION:
7661 break;
7662 case base::TERMINATION_STATUS_PROCESS_CRASHED:
7663 if (exit_code == RESULT_CODE_HUNG)
7664 reason = "unresponsive";
7665 break;
7666 case base::TERMINATION_STATUS_PROCESS_WAS_KILLED:
7667 if (exit_code == RESULT_CODE_HUNG)
7668 reason = "unresponsive";
7669 else
7670 return;
7671 break;
7672 case base::TERMINATION_STATUS_OOM:
7673 #if defined(OS_CHROMEOS)
7674 case base::TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM:
7675 #endif
7676 #if defined(OS_ANDROID)
7677 case base::TERMINATION_STATUS_OOM_PROTECTED:
7678 #endif
7679 reason = "oom";
7680 break;
7681 default:
7682 // Other termination statuses do not indicate a crash.
7683 return;
7684 }
7685
7686 // Construct the crash report.
7687 auto body = base::DictionaryValue();
7688 if (!reason.empty())
7689 body.SetString("reason", reason);
7690
7691 // Send the crash report to the Reporting API.
7692 GetProcess()->GetStoragePartition()->GetNetworkContext()->QueueReport(
7693 "crash" /* type */, "default" /* group */, last_committed_url_,
7694 base::nullopt, std::move(body));
7695 }
7696
SendCommitNavigation(mojom::NavigationClient * navigation_client,NavigationRequest * navigation_request,mojom::CommonNavigationParamsPtr common_params,mojom::CommitNavigationParamsPtr commit_params,network::mojom::URLResponseHeadPtr response_head,mojo::ScopedDataPipeConsumerHandle response_body,network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,std::unique_ptr<blink::PendingURLLoaderFactoryBundle> subresource_loader_factories,base::Optional<std::vector<::content::mojom::TransferrableURLLoaderPtr>> subresource_overrides,blink::mojom::ControllerServiceWorkerInfoPtr controller,blink::mojom::ServiceWorkerProviderInfoForClientPtr provider_info,mojo::PendingRemote<network::mojom::URLLoaderFactory> prefetch_loader_factory,const base::UnguessableToken & devtools_navigation_token)7697 void RenderFrameHostImpl::SendCommitNavigation(
7698 mojom::NavigationClient* navigation_client,
7699 NavigationRequest* navigation_request,
7700 mojom::CommonNavigationParamsPtr common_params,
7701 mojom::CommitNavigationParamsPtr commit_params,
7702 network::mojom::URLResponseHeadPtr response_head,
7703 mojo::ScopedDataPipeConsumerHandle response_body,
7704 network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
7705 std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
7706 subresource_loader_factories,
7707 base::Optional<std::vector<::content::mojom::TransferrableURLLoaderPtr>>
7708 subresource_overrides,
7709 blink::mojom::ControllerServiceWorkerInfoPtr controller,
7710 blink::mojom::ServiceWorkerProviderInfoForClientPtr provider_info,
7711 mojo::PendingRemote<network::mojom::URLLoaderFactory>
7712 prefetch_loader_factory,
7713 const base::UnguessableToken& devtools_navigation_token) {
7714 // For committed interstitials, we do not have a NavigationRequest and use the
7715 // old NavigationControl mojo interface. For anything else we should have a
7716 // NavigationRequest, containing a NavigationClient, and commit through it.
7717 // TODO(ahemery): Update when https://crbug.com/448486 is done.
7718 if (navigation_client) {
7719 navigation_client->CommitNavigation(
7720 std::move(common_params), std::move(commit_params),
7721 std::move(response_head), std::move(response_body),
7722 std::move(url_loader_client_endpoints),
7723 std::move(subresource_loader_factories),
7724 std::move(subresource_overrides), std::move(controller),
7725 std::move(provider_info), std::move(prefetch_loader_factory),
7726 devtools_navigation_token,
7727 BuildCommitNavigationCallback(navigation_request));
7728 } else {
7729 DCHECK(!navigation_request);
7730 GetNavigationControl()->CommitNavigation(
7731 std::move(common_params), std::move(commit_params),
7732 std::move(response_head), std::move(response_body),
7733 std::move(url_loader_client_endpoints),
7734 std::move(subresource_loader_factories),
7735 std::move(subresource_overrides), std::move(controller),
7736 std::move(provider_info), std::move(prefetch_loader_factory),
7737 devtools_navigation_token,
7738 mojom::FrameNavigationControl::CommitNavigationCallback());
7739 }
7740 }
7741
SendCommitFailedNavigation(mojom::NavigationClient * navigation_client,NavigationRequest * navigation_request,mojom::CommonNavigationParamsPtr common_params,mojom::CommitNavigationParamsPtr commit_params,bool has_stale_copy_in_cache,int32_t error_code,const base::Optional<std::string> & error_page_content,std::unique_ptr<blink::PendingURLLoaderFactoryBundle> subresource_loader_factories)7742 void RenderFrameHostImpl::SendCommitFailedNavigation(
7743 mojom::NavigationClient* navigation_client,
7744 NavigationRequest* navigation_request,
7745 mojom::CommonNavigationParamsPtr common_params,
7746 mojom::CommitNavigationParamsPtr commit_params,
7747 bool has_stale_copy_in_cache,
7748 int32_t error_code,
7749 const base::Optional<std::string>& error_page_content,
7750 std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
7751 subresource_loader_factories) {
7752 DCHECK(navigation_client && navigation_request);
7753 navigation_client->CommitFailedNavigation(
7754 std::move(common_params), std::move(commit_params),
7755 has_stale_copy_in_cache, error_code,
7756 navigation_request->GetResolveErrorInfo(), error_page_content,
7757 std::move(subresource_loader_factories),
7758 BuildCommitFailedNavigationCallback(navigation_request));
7759 }
7760
7761 // Called when the renderer navigates. For every frame loaded, we'll get this
7762 // notification containing parameters identifying the navigation.
DidCommitNavigation(std::unique_ptr<NavigationRequest> committing_navigation_request,std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params> params,mojom::DidCommitProvisionalLoadInterfaceParamsPtr interface_params)7763 void RenderFrameHostImpl::DidCommitNavigation(
7764 std::unique_ptr<NavigationRequest> committing_navigation_request,
7765 std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params> params,
7766 mojom::DidCommitProvisionalLoadInterfaceParamsPtr interface_params) {
7767 NavigationRequest* request;
7768 if (committing_navigation_request) {
7769 request = committing_navigation_request.get();
7770 } else {
7771 request = navigation_request();
7772 }
7773
7774 if (request && request->IsNavigationStarted()) {
7775 main_frame_request_ids_ = {params->request_id,
7776 request->GetGlobalRequestID()};
7777 if (deferred_main_frame_load_info_)
7778 ResourceLoadComplete(std::move(deferred_main_frame_load_info_));
7779 }
7780 // DidCommitProvisionalLoad IPC should be associated with the URL being
7781 // committed (not with the *last* committed URL that most other IPCs are
7782 // associated with).
7783 ScopedActiveURL scoped_active_url(
7784 params->url, frame_tree_node()->frame_tree()->root()->current_origin());
7785
7786 ScopedCommitStateResetter commit_state_resetter(this);
7787 RenderProcessHost* process = GetProcess();
7788
7789 TRACE_EVENT2("navigation", "RenderFrameHostImpl::DidCommitProvisionalLoad",
7790 "url", params->url.possibly_invalid_spec(), "details",
7791 CommitAsTracedValue(params.get()));
7792
7793 // If we're waiting for a cross-site beforeunload completion callback from
7794 // this renderer and we receive a Navigate message from the main frame, then
7795 // the renderer was navigating already and sent it before hearing the
7796 // FrameMsg_Stop message. Treat this as an implicit beforeunload completion
7797 // callback to allow the pending navigation to continue.
7798 if (is_waiting_for_beforeunload_completion_ &&
7799 unload_ack_is_for_navigation_ && !GetParent()) {
7800 base::TimeTicks approx_renderer_start_time = send_before_unload_start_time_;
7801 ProcessBeforeUnloadCompleted(
7802 true /* proceed */, true /* treat_as_final_completion_callback */,
7803 approx_renderer_start_time, base::TimeTicks::Now());
7804 }
7805
7806 // When a frame enters pending deletion, it waits for itself and its children
7807 // to properly unload. Receiving DidCommitProvisionalLoad() here while the
7808 // frame is not active means it comes from a navigation that reached the
7809 // ReadyToCommit stage just before the frame entered pending deletion.
7810 //
7811 // We should ignore this message, because we have already committed to
7812 // destroying this RenderFrameHost. Note that we intentionally do not ignore
7813 // commits that happen while the current tab is being closed - see
7814 // https://crbug.com/805705.
7815 if (!is_active())
7816 return;
7817
7818 // Retroactive sanity check:
7819 // - If this is the first real load committing in this frame, then by this
7820 // time the RenderFrameHost's InterfaceProvider implementation should have
7821 // already been bound to a message pipe whose client end is used to service
7822 // interface requests from the initial empty document.
7823 // - Otherwise, the InterfaceProvider implementation should at this point be
7824 // bound to an interface connection servicing interface requests coming from
7825 // the document of the previously committed navigation.
7826 DCHECK(document_scoped_interface_provider_receiver_.is_bound());
7827 if (interface_params) {
7828 // As a general rule, expect the RenderFrame to have supplied the
7829 // receiver end of a new InterfaceProvider connection that will be used by
7830 // the new document to issue interface receivers to access RenderFrameHost
7831 // services.
7832 document_scoped_interface_provider_receiver_.reset();
7833 BindInterfaceProviderReceiver(
7834 std::move(interface_params->interface_provider_receiver));
7835 if (broker_receiver_.is_bound()) {
7836 auto broker_receiver_of_previous_document = broker_receiver_.Unbind();
7837 dropped_interface_request_logger_ =
7838 std::make_unique<DroppedInterfaceRequestLogger>(
7839 std::move(broker_receiver_of_previous_document));
7840 }
7841 BindBrowserInterfaceBrokerReceiver(
7842 std::move(interface_params->browser_interface_broker_receiver));
7843 } else {
7844 // If there had already been a real load committed in the frame, and this is
7845 // not a same-document navigation, then both the active document as well as
7846 // the global object was replaced in this browsing context. The RenderFrame
7847 // should have rebound its InterfaceProvider to a new pipe, but failed to do
7848 // so. Kill the renderer, and reset the old receiver to ensure that any
7849 // pending interface requests originating from the previous document, hence
7850 // possibly from a different security origin, will no longer be dispatched.
7851 if (frame_tree_node_->has_committed_real_load()) {
7852 document_scoped_interface_provider_receiver_.reset();
7853 broker_receiver_.reset();
7854 bad_message::ReceivedBadMessage(
7855 process, bad_message::RFH_INTERFACE_PROVIDER_MISSING);
7856 return;
7857 }
7858
7859 // Otherwise, it is the first real load committed, for which the RenderFrame
7860 // is allowed to, and will re-use the existing InterfaceProvider connection
7861 // if the new document is same-origin with the initial empty document, and
7862 // therefore the global object is not replaced.
7863 }
7864
7865 if (!DidCommitNavigationInternal(std::move(committing_navigation_request),
7866 std::move(params),
7867 false /* is_same_document_navigation */)) {
7868 return;
7869 }
7870
7871 // Since we didn't early return, it's safe to keep the commit state.
7872 commit_state_resetter.disable();
7873
7874 // For a top-level frame, there are potential security concerns associated
7875 // with displaying graphics from a previously loaded page after the URL in
7876 // the omnibar has been changed. It is unappealing to clear the page
7877 // immediately, but if the renderer is taking a long time to issue any
7878 // compositor output (possibly because of script deliberately creating this
7879 // situation) then we clear it after a while anyway.
7880 // See https://crbug.com/497588.
7881 if (frame_tree_node_->IsMainFrame() && GetView()) {
7882 RenderWidgetHostImpl::From(GetView()->GetRenderWidgetHost())->DidNavigate();
7883 }
7884
7885 // TODO(arthursonzogni): This can be removed when RenderDocument will be
7886 // implemented. See https://crbug.com/936696.
7887 EnsureDescendantsAreUnloading();
7888 }
7889
7890 mojom::NavigationClient::CommitNavigationCallback
BuildCommitNavigationCallback(NavigationRequest * navigation_request)7891 RenderFrameHostImpl::BuildCommitNavigationCallback(
7892 NavigationRequest* navigation_request) {
7893 DCHECK(navigation_request);
7894 return base::BindOnce(
7895 &RenderFrameHostImpl::DidCommitPerNavigationMojoInterfaceNavigation,
7896 base::Unretained(this), navigation_request);
7897 }
7898
7899 mojom::NavigationClient::CommitFailedNavigationCallback
BuildCommitFailedNavigationCallback(NavigationRequest * navigation_request)7900 RenderFrameHostImpl::BuildCommitFailedNavigationCallback(
7901 NavigationRequest* navigation_request) {
7902 DCHECK(navigation_request);
7903 return base::BindOnce(
7904 &RenderFrameHostImpl::DidCommitPerNavigationMojoInterfaceNavigation,
7905 base::Unretained(this), navigation_request);
7906 }
7907
SendBeforeUnload(bool is_reload,base::WeakPtr<RenderFrameHostImpl> rfh)7908 void RenderFrameHostImpl::SendBeforeUnload(
7909 bool is_reload,
7910 base::WeakPtr<RenderFrameHostImpl> rfh) {
7911 auto before_unload_closure = base::BindOnce(
7912 [](base::WeakPtr<RenderFrameHostImpl> impl, bool proceed,
7913 base::TimeTicks renderer_before_unload_start_time,
7914 base::TimeTicks renderer_before_unload_end_time) {
7915 if (!impl)
7916 return;
7917 impl->ProcessBeforeUnloadCompleted(
7918 proceed, false /* treat_as_final_completion_callback */,
7919 renderer_before_unload_start_time, renderer_before_unload_end_time);
7920 },
7921 rfh);
7922 rfh->GetAssociatedLocalFrame()->BeforeUnload(
7923 is_reload, std::move(before_unload_closure));
7924 }
7925
AddServiceWorkerContainerHost(const std::string & uuid,base::WeakPtr<content::ServiceWorkerContainerHost> host)7926 void RenderFrameHostImpl::AddServiceWorkerContainerHost(
7927 const std::string& uuid,
7928 base::WeakPtr<content::ServiceWorkerContainerHost> host) {
7929 if (is_in_back_forward_cache_) {
7930 // RenderFrameHost entered BackForwardCache before adding
7931 // ServiceWorkerContainerHost. In this case, evict the entry from the cache.
7932 EvictFromBackForwardCacheWithReason(
7933 BackForwardCacheMetrics::NotRestoredReason::
7934 kEnteredBackForwardCacheBeforeServiceWorkerHostAdded);
7935 }
7936 DCHECK(!base::Contains(service_worker_container_hosts_, uuid));
7937 service_worker_container_hosts_[uuid] = std::move(host);
7938 }
7939
RemoveServiceWorkerContainerHost(const std::string & uuid)7940 void RenderFrameHostImpl::RemoveServiceWorkerContainerHost(
7941 const std::string& uuid) {
7942 DCHECK(base::Contains(service_worker_container_hosts_, uuid));
7943 service_worker_container_hosts_.erase(uuid);
7944 }
7945
UpdateFrameFrozenState()7946 void RenderFrameHostImpl::UpdateFrameFrozenState() {
7947 // TODO(http://crbug.com/1014212): remove this.
7948 CHECK(frame_);
7949 if (!IsFeatureEnabled(
7950 blink::mojom::FeaturePolicyFeature::kExecutionWhileNotRendered) &&
7951 visibility_ == blink::mojom::FrameVisibility::kNotRendered) {
7952 frame_->SetLifecycleState(blink::mojom::FrameLifecycleState::kFrozen);
7953 } else if (!IsFeatureEnabled(blink::mojom::FeaturePolicyFeature::
7954 kExecutionWhileOutOfViewport) &&
7955 visibility_ ==
7956 blink::mojom::FrameVisibility::kRenderedOutOfViewport) {
7957 frame_->SetLifecycleState(
7958 blink::mojom::FrameLifecycleState::kFrozenAutoResumeMedia);
7959 } else {
7960 frame_->SetLifecycleState(blink::mojom::FrameLifecycleState::kRunning);
7961 }
7962 }
7963
MaybeInterceptCommitCallback(NavigationRequest * navigation_request,FrameHostMsg_DidCommitProvisionalLoad_Params * params,mojom::DidCommitProvisionalLoadInterfaceParamsPtr * interface_params)7964 bool RenderFrameHostImpl::MaybeInterceptCommitCallback(
7965 NavigationRequest* navigation_request,
7966 FrameHostMsg_DidCommitProvisionalLoad_Params* params,
7967 mojom::DidCommitProvisionalLoadInterfaceParamsPtr* interface_params) {
7968 if (commit_callback_interceptor_) {
7969 return commit_callback_interceptor_->WillProcessDidCommitNavigation(
7970 navigation_request, params, interface_params);
7971 }
7972 return true;
7973 }
7974
PostMessageEvent(int32_t source_routing_id,const base::string16 & source_origin,const base::string16 & target_origin,blink::TransferableMessage message)7975 void RenderFrameHostImpl::PostMessageEvent(int32_t source_routing_id,
7976 const base::string16& source_origin,
7977 const base::string16& target_origin,
7978 blink::TransferableMessage message) {
7979 DCHECK(render_frame_created_);
7980
7981 GetNavigationControl()->PostMessageEvent(source_routing_id, source_origin,
7982 target_origin, std::move(message));
7983 }
7984
IsTestRenderFrameHost() const7985 bool RenderFrameHostImpl::IsTestRenderFrameHost() const {
7986 return false;
7987 }
7988
7989 scoped_refptr<PrefetchedSignedExchangeCache>
EnsurePrefetchedSignedExchangeCache()7990 RenderFrameHostImpl::EnsurePrefetchedSignedExchangeCache() {
7991 if (!prefetched_signed_exchange_cache_) {
7992 prefetched_signed_exchange_cache_ =
7993 base::MakeRefCounted<PrefetchedSignedExchangeCache>();
7994 }
7995 return prefetched_signed_exchange_cache_;
7996 }
7997
ClearPrefetchedSignedExchangeCache()7998 void RenderFrameHostImpl::ClearPrefetchedSignedExchangeCache() {
7999 if (prefetched_signed_exchange_cache_)
8000 prefetched_signed_exchange_cache_->Clear();
8001 }
8002
GetLocalRenderWidgetHost() const8003 RenderWidgetHostImpl* RenderFrameHostImpl::GetLocalRenderWidgetHost() const {
8004 if (!parent_)
8005 return render_view_host_->GetWidget();
8006 else
8007 return owned_render_widget_host_.get();
8008 }
8009
EnsureDescendantsAreUnloading()8010 void RenderFrameHostImpl::EnsureDescendantsAreUnloading() {
8011 std::vector<RenderFrameHostImpl*> parents_to_be_checked = {this};
8012 std::vector<RenderFrameHostImpl*> rfhs_to_be_checked;
8013 while (!parents_to_be_checked.empty()) {
8014 RenderFrameHostImpl* document = parents_to_be_checked.back();
8015 parents_to_be_checked.pop_back();
8016
8017 for (auto& subframe : document->children_) {
8018 RenderFrameHostImpl* child = subframe->current_frame_host();
8019 // Every child is expected to be pending deletion. If it isn't the
8020 // case, their FrameTreeNode is immediately removed from the tree.
8021 if (child->unload_state_ == UnloadState::NotRun)
8022 rfhs_to_be_checked.push_back(child);
8023 else
8024 parents_to_be_checked.push_back(child);
8025 }
8026 }
8027 for (RenderFrameHostImpl* document : rfhs_to_be_checked)
8028 document->parent_->RemoveChild(document->frame_tree_node());
8029 }
8030
AddUniqueMessageToConsole(blink::mojom::ConsoleMessageLevel level,const std::string & message)8031 void RenderFrameHostImpl::AddUniqueMessageToConsole(
8032 blink::mojom::ConsoleMessageLevel level,
8033 const std::string& message) {
8034 AddMessageToConsoleImpl(level, message, true /* discard_duplicates */);
8035 }
8036
AddMessageToConsoleImpl(blink::mojom::ConsoleMessageLevel level,const std::string & message,bool discard_duplicates)8037 void RenderFrameHostImpl::AddMessageToConsoleImpl(
8038 blink::mojom::ConsoleMessageLevel level,
8039 const std::string& message,
8040 bool discard_duplicates) {
8041 GetAssociatedLocalFrame()->AddMessageToConsole(level, message,
8042 discard_duplicates);
8043 }
8044
AddSameSiteCookieDeprecationMessage(const std::string & cookie_url,net::CanonicalCookie::CookieInclusionStatus status,bool is_lax_by_default_enabled,bool is_none_requires_secure_enabled)8045 void RenderFrameHostImpl::AddSameSiteCookieDeprecationMessage(
8046 const std::string& cookie_url,
8047 net::CanonicalCookie::CookieInclusionStatus status,
8048 bool is_lax_by_default_enabled,
8049 bool is_none_requires_secure_enabled) {
8050 std::string deprecation_message;
8051 // The status will have, at most, one of these warning messages at any given
8052 // time.
8053 if (status.HasWarningReason(
8054 net::CanonicalCookie::CookieInclusionStatus::WarningReason::
8055 WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT)) {
8056 if (!ShouldAddCookieSameSiteDeprecationMessage(
8057 cookie_url, &cookie_no_samesite_deprecation_url_hashes_)) {
8058 return;
8059 }
8060 std::string warning_or_blocked_message =
8061 (is_lax_by_default_enabled
8062 ? "It has been blocked, as Chrome now only delivers "
8063 : "A future release of Chrome will only deliver ");
8064 deprecation_message =
8065 "A cookie associated with a cross-site resource at " + cookie_url +
8066 " was set without the `SameSite` attribute. " +
8067 warning_or_blocked_message +
8068 "cookies with "
8069 "cross-site requests if they are set with `SameSite=None` and "
8070 "`Secure`. You can review cookies in developer tools under "
8071 "Application>Storage>Cookies and see more details at "
8072 "https://www.chromestatus.com/feature/5088147346030592 and "
8073 "https://www.chromestatus.com/feature/5633521622188032.";
8074 } else if (status.HasWarningReason(
8075 net::CanonicalCookie::CookieInclusionStatus::WarningReason::
8076 WARN_SAMESITE_NONE_INSECURE)) {
8077 if (!ShouldAddCookieSameSiteDeprecationMessage(
8078 cookie_url,
8079 &cookie_samesite_none_insecure_deprecation_url_hashes_)) {
8080 return;
8081 }
8082 std::string warning_or_blocked_message =
8083 (is_none_requires_secure_enabled
8084 ? "It has been blocked, as Chrome now only delivers "
8085 : "A future release of Chrome will only deliver ");
8086 deprecation_message =
8087 "A cookie associated with a resource at " + cookie_url +
8088 " was set with `SameSite=None` but without `Secure`. " +
8089 warning_or_blocked_message +
8090 "cookies marked "
8091 "`SameSite=None` if they are also marked `Secure`. You "
8092 "can review cookies in developer tools under "
8093 "Application>Storage>Cookies and see more details at "
8094 "https://www.chromestatus.com/feature/5633521622188032.";
8095 } else if (status.HasWarningReason(
8096 net::CanonicalCookie::CookieInclusionStatus::WarningReason::
8097 WARN_SAMESITE_UNSPECIFIED_LAX_ALLOW_UNSAFE)) {
8098 if (!ShouldAddCookieSameSiteDeprecationMessage(
8099 cookie_url, &cookie_lax_allow_unsafe_deprecation_url_hashes_)) {
8100 return;
8101 }
8102 deprecation_message =
8103 "A cookie associated with a resource at " + cookie_url +
8104 " set without a `SameSite` attribute was sent with a non-idempotent "
8105 "top-level cross-site request because it was less than " +
8106 base::NumberToString(net::kLaxAllowUnsafeMaxAge.InMinutes()) +
8107 " minutes old. A future release of Chrome will treat such cookies as "
8108 "if they were set with `SameSite=Lax` and will only allow them to be "
8109 "sent with top-level cross-site requests if the HTTP method is safe. "
8110 "See more details at "
8111 "https://www.chromestatus.com/feature/5088147346030592.";
8112 }
8113
8114 if (deprecation_message.empty())
8115 return;
8116
8117 AddUniqueMessageToConsole(blink::mojom::ConsoleMessageLevel::kWarning,
8118 deprecation_message);
8119 }
8120
AddInspectorIssue(blink::mojom::InspectorIssueInfoPtr info)8121 void RenderFrameHostImpl::AddInspectorIssue(
8122 blink::mojom::InspectorIssueInfoPtr info) {
8123 GetAssociatedLocalFrame()->AddInspectorIssue(std::move(info));
8124 }
8125
ShouldAddCookieSameSiteDeprecationMessage(const std::string & cookie_url,base::circular_deque<size_t> * already_seen_url_hashes)8126 bool RenderFrameHostImpl::ShouldAddCookieSameSiteDeprecationMessage(
8127 const std::string& cookie_url,
8128 base::circular_deque<size_t>* already_seen_url_hashes) {
8129 DCHECK_LE(already_seen_url_hashes->size(), kMaxCookieSameSiteDeprecationUrls);
8130 size_t cookie_url_hash = base::FastHash(cookie_url);
8131 if (base::Contains(*already_seen_url_hashes, cookie_url_hash))
8132 return false;
8133
8134 // Put most recent ones at the front because we are likely to have multiple
8135 // consecutive cookies with the same URL.
8136 if (already_seen_url_hashes->size() == kMaxCookieSameSiteDeprecationUrls)
8137 already_seen_url_hashes->pop_back();
8138 already_seen_url_hashes->push_front(cookie_url_hash);
8139 return true;
8140 }
8141
LogCannotCommitUrlCrashKeys(const GURL & url,bool is_same_document_navigation,NavigationRequest * navigation_request)8142 void RenderFrameHostImpl::LogCannotCommitUrlCrashKeys(
8143 const GURL& url,
8144 bool is_same_document_navigation,
8145 NavigationRequest* navigation_request) {
8146 LogRendererKillCrashKeys(GetSiteInstance()->GetSiteURL());
8147
8148 // Temporary instrumentation to debug the root cause of renderer process
8149 // terminations. See https://crbug.com/931895.
8150 auto bool_to_crash_key = [](bool b) { return b ? "true" : "false"; };
8151 base::debug::SetCrashKeyString(
8152 base::debug::AllocateCrashKeyString("is_same_document",
8153 base::debug::CrashKeySize::Size32),
8154 bool_to_crash_key(is_same_document_navigation));
8155
8156 base::debug::SetCrashKeyString(
8157 base::debug::AllocateCrashKeyString("is_main_frame",
8158 base::debug::CrashKeySize::Size32),
8159 bool_to_crash_key(frame_tree_node_->IsMainFrame()));
8160
8161 base::debug::SetCrashKeyString(
8162 base::debug::AllocateCrashKeyString("is_cross_process_subframe",
8163 base::debug::CrashKeySize::Size32),
8164 bool_to_crash_key(IsCrossProcessSubframe()));
8165
8166 base::debug::SetCrashKeyString(
8167 base::debug::AllocateCrashKeyString("site_lock",
8168 base::debug::CrashKeySize::Size256),
8169 GetSiteInstance()->lock_url().possibly_invalid_spec());
8170
8171 if (!GetSiteInstance()->IsDefaultSiteInstance()) {
8172 base::debug::SetCrashKeyString(
8173 base::debug::AllocateCrashKeyString("original_url_origin",
8174 base::debug::CrashKeySize::Size256),
8175 GetSiteInstance()->original_url().GetOrigin().spec());
8176 }
8177
8178 base::debug::SetCrashKeyString(
8179 base::debug::AllocateCrashKeyString("is_mhtml_document",
8180 base::debug::CrashKeySize::Size32),
8181 bool_to_crash_key(is_mhtml_document()));
8182
8183 base::debug::SetCrashKeyString(
8184 base::debug::AllocateCrashKeyString("last_committed_url_origin",
8185 base::debug::CrashKeySize::Size256),
8186 GetLastCommittedURL().GetOrigin().spec());
8187
8188 base::debug::SetCrashKeyString(
8189 base::debug::AllocateCrashKeyString("last_successful_url_origin",
8190 base::debug::CrashKeySize::Size256),
8191 last_successful_url().GetOrigin().spec());
8192
8193 if (navigation_request && navigation_request->IsNavigationStarted()) {
8194 base::debug::SetCrashKeyString(
8195 base::debug::AllocateCrashKeyString("is_renderer_initiated",
8196 base::debug::CrashKeySize::Size32),
8197 bool_to_crash_key(navigation_request->IsRendererInitiated()));
8198
8199 base::debug::SetCrashKeyString(
8200 base::debug::AllocateCrashKeyString("is_server_redirect",
8201 base::debug::CrashKeySize::Size32),
8202 bool_to_crash_key(navigation_request->WasServerRedirect()));
8203
8204 base::debug::SetCrashKeyString(
8205 base::debug::AllocateCrashKeyString("is_form_submission",
8206 base::debug::CrashKeySize::Size32),
8207 bool_to_crash_key(navigation_request->IsFormSubmission()));
8208
8209 base::debug::SetCrashKeyString(
8210 base::debug::AllocateCrashKeyString("is_error_page",
8211 base::debug::CrashKeySize::Size32),
8212 bool_to_crash_key(navigation_request->IsErrorPage()));
8213
8214 base::debug::SetCrashKeyString(
8215 base::debug::AllocateCrashKeyString("from_begin_navigation",
8216 base::debug::CrashKeySize::Size32),
8217 bool_to_crash_key(navigation_request->from_begin_navigation()));
8218
8219 base::debug::SetCrashKeyString(
8220 base::debug::AllocateCrashKeyString("net_error",
8221 base::debug::CrashKeySize::Size32),
8222 base::NumberToString(navigation_request->GetNetErrorCode()));
8223
8224 base::debug::SetCrashKeyString(
8225 base::debug::AllocateCrashKeyString("initiator_origin",
8226 base::debug::CrashKeySize::Size64),
8227 navigation_request->GetInitiatorOrigin()
8228 ? navigation_request->GetInitiatorOrigin()->GetDebugString()
8229 : "none");
8230
8231 base::debug::SetCrashKeyString(
8232 base::debug::AllocateCrashKeyString("starting_site_instance",
8233 base::debug::CrashKeySize::Size64),
8234 navigation_request->GetStartingSiteInstance()
8235 ->GetSiteURL()
8236 .possibly_invalid_spec());
8237
8238 // Recompute the target SiteInstance to see if it matches the current
8239 // one at commit time.
8240 scoped_refptr<SiteInstance> dest_instance =
8241 frame_tree_node_->render_manager()->GetSiteInstanceForNavigationRequest(
8242 navigation_request);
8243 base::debug::SetCrashKeyString(
8244 base::debug::AllocateCrashKeyString(
8245 "does_recomputed_site_instance_match",
8246 base::debug::CrashKeySize::Size32),
8247 bool_to_crash_key(dest_instance == GetSiteInstance()));
8248 }
8249 }
8250
MaybeEvictFromBackForwardCache()8251 void RenderFrameHostImpl::MaybeEvictFromBackForwardCache() {
8252 if (!is_in_back_forward_cache_)
8253 return;
8254
8255 RenderFrameHostImpl* top_document = this;
8256 while (RenderFrameHostImpl* parent = top_document->GetParent())
8257 top_document = parent;
8258
8259 NavigationControllerImpl* controller = static_cast<NavigationControllerImpl*>(
8260 frame_tree_node_->navigator()->GetController());
8261 auto can_store =
8262 controller->GetBackForwardCache().CanStoreDocument(top_document);
8263 TRACE_EVENT1("navigation",
8264 "RenderFrameHostImpl::MaybeEvictFromBackForwardCache",
8265 "can_store", can_store.ToString());
8266
8267 if (can_store)
8268 return;
8269
8270 EvictFromBackForwardCacheWithReasons(can_store);
8271 }
8272
LogCannotCommitOriginCrashKeys(bool is_same_document_navigation,NavigationRequest * navigation_request)8273 void RenderFrameHostImpl::LogCannotCommitOriginCrashKeys(
8274 bool is_same_document_navigation,
8275 NavigationRequest* navigation_request) {
8276 LogRendererKillCrashKeys(GetSiteInstance()->GetSiteURL());
8277
8278 // Temporary instrumentation to debug the root cause of
8279 // https://crbug.com/923144.
8280 auto bool_to_crash_key = [](bool b) { return b ? "true" : "false"; };
8281 base::debug::SetCrashKeyString(
8282 base::debug::AllocateCrashKeyString("is_same_document",
8283 base::debug::CrashKeySize::Size32),
8284 bool_to_crash_key(is_same_document_navigation));
8285
8286 base::debug::SetCrashKeyString(
8287 base::debug::AllocateCrashKeyString("is_subframe",
8288 base::debug::CrashKeySize::Size32),
8289 bool_to_crash_key(!frame_tree_node_->IsMainFrame()));
8290
8291 base::debug::SetCrashKeyString(
8292 base::debug::AllocateCrashKeyString("is_active",
8293 base::debug::CrashKeySize::Size32),
8294 bool_to_crash_key(is_active()));
8295
8296 base::debug::SetCrashKeyString(
8297 base::debug::AllocateCrashKeyString("is_current",
8298 base::debug::CrashKeySize::Size32),
8299 bool_to_crash_key(IsCurrent()));
8300
8301 base::debug::SetCrashKeyString(
8302 base::debug::AllocateCrashKeyString("is_cross_process_subframe",
8303 base::debug::CrashKeySize::Size32),
8304 bool_to_crash_key(IsCrossProcessSubframe()));
8305
8306 if (navigation_request && navigation_request->IsNavigationStarted()) {
8307 base::debug::SetCrashKeyString(
8308 base::debug::AllocateCrashKeyString("is_renderer_initiated",
8309 base::debug::CrashKeySize::Size32),
8310 bool_to_crash_key(navigation_request->IsRendererInitiated()));
8311
8312 base::debug::SetCrashKeyString(
8313 base::debug::AllocateCrashKeyString("is_server_redirect",
8314 base::debug::CrashKeySize::Size32),
8315 bool_to_crash_key(navigation_request->WasServerRedirect()));
8316
8317 base::debug::SetCrashKeyString(
8318 base::debug::AllocateCrashKeyString("is_form_submission",
8319 base::debug::CrashKeySize::Size32),
8320 bool_to_crash_key(navigation_request->IsFormSubmission()));
8321
8322 base::debug::SetCrashKeyString(
8323 base::debug::AllocateCrashKeyString("is_error_page",
8324 base::debug::CrashKeySize::Size32),
8325 bool_to_crash_key(navigation_request->IsErrorPage()));
8326
8327 base::debug::SetCrashKeyString(
8328 base::debug::AllocateCrashKeyString("initiator_origin",
8329 base::debug::CrashKeySize::Size64),
8330 navigation_request->GetInitiatorOrigin()
8331 ? navigation_request->GetInitiatorOrigin()->GetDebugString()
8332 : "none");
8333
8334 base::debug::SetCrashKeyString(
8335 base::debug::AllocateCrashKeyString("starting_site_instance",
8336 base::debug::CrashKeySize::Size64),
8337 navigation_request->GetStartingSiteInstance()
8338 ->GetSiteURL()
8339 .possibly_invalid_spec());
8340 }
8341 }
8342
EnableMojoJsBindings()8343 void RenderFrameHostImpl::EnableMojoJsBindings() {
8344 // This method should only be called on RenderFrameHost which is for a WebUI.
8345 DCHECK_NE(WebUI::kNoWebUI,
8346 WebUIControllerFactoryRegistry::GetInstance()->GetWebUIType(
8347 GetSiteInstance()->GetBrowserContext(),
8348 site_instance_->GetSiteURL()));
8349
8350 if (!frame_bindings_control_)
8351 GetRemoteAssociatedInterfaces()->GetInterface(&frame_bindings_control_);
8352 frame_bindings_control_->EnableMojoJsBindings();
8353 }
8354
GetBackForwardCacheMetrics()8355 BackForwardCacheMetrics* RenderFrameHostImpl::GetBackForwardCacheMetrics() {
8356 NavigationEntryImpl* navigation_entry =
8357 static_cast<NavigationControllerImpl*>(
8358 frame_tree_node_->navigator()->GetController())
8359 ->GetEntryWithUniqueID(nav_entry_id());
8360 if (!navigation_entry)
8361 return nullptr;
8362 return navigation_entry->back_forward_cache_metrics();
8363 }
8364
IsBackForwardCacheDisabled() const8365 bool RenderFrameHostImpl::IsBackForwardCacheDisabled() const {
8366 return back_forward_cache_disabled_reasons_.size();
8367 }
8368
IsDOMContentLoaded()8369 bool RenderFrameHostImpl::IsDOMContentLoaded() {
8370 return dom_content_loaded_;
8371 }
8372
UpdateAdFrameType(blink::mojom::AdFrameType ad_frame_type)8373 void RenderFrameHostImpl::UpdateAdFrameType(
8374 blink::mojom::AdFrameType ad_frame_type) {
8375 frame_tree_node_->SetAdFrameType(ad_frame_type);
8376 }
8377
8378 blink::mojom::AuthenticatorStatus
PerformGetAssertionWebAuthSecurityChecks(const std::string & relying_party_id)8379 RenderFrameHostImpl::PerformGetAssertionWebAuthSecurityChecks(
8380 const std::string& relying_party_id) {
8381 #if BUILDFLAG(ENABLE_WEB_AUTH)
8382 bool is_cross_origin;
8383 blink::mojom::AuthenticatorStatus status =
8384 GetWebAuthRequestSecurityChecker()->ValidateAncestorOrigins(
8385 GetLastCommittedOrigin(), &is_cross_origin);
8386 if (status != blink::mojom::AuthenticatorStatus::SUCCESS) {
8387 return status;
8388 }
8389
8390 status = GetWebAuthRequestSecurityChecker()->ValidateDomainAndRelyingPartyID(
8391 GetLastCommittedOrigin(), relying_party_id);
8392 if (status != blink::mojom::AuthenticatorStatus::SUCCESS) {
8393 return status;
8394 }
8395
8396 return blink::mojom::AuthenticatorStatus::SUCCESS;
8397 #else
8398 return blink::mojom::AuthenticatorStatus::NOT_IMPLEMENTED;
8399 #endif
8400 }
8401
8402 blink::mojom::AuthenticatorStatus
PerformMakeCredentialWebAuthSecurityChecks(const std::string & relying_party_id)8403 RenderFrameHostImpl::PerformMakeCredentialWebAuthSecurityChecks(
8404 const std::string& relying_party_id) {
8405 #if BUILDFLAG(ENABLE_WEB_AUTH)
8406 bool is_cross_origin;
8407 blink::mojom::AuthenticatorStatus status =
8408 GetWebAuthRequestSecurityChecker()->ValidateAncestorOrigins(
8409 GetLastCommittedOrigin(), &is_cross_origin);
8410 if (status != blink::mojom::AuthenticatorStatus::SUCCESS) {
8411 return status;
8412 }
8413
8414 status = GetWebAuthRequestSecurityChecker()->ValidateDomainAndRelyingPartyID(
8415 GetLastCommittedOrigin(), relying_party_id);
8416 if (status != blink::mojom::AuthenticatorStatus::SUCCESS) {
8417 return status;
8418 }
8419
8420 return blink::mojom::AuthenticatorStatus::SUCCESS;
8421 #else
8422 return blink::mojom::AuthenticatorStatus::NOT_IMPLEMENTED;
8423 #endif
8424 }
8425
IsClipboardPasteAllowed(const ui::ClipboardFormatType & data_type,const std::string & data,IsClipboardPasteAllowedCallback callback)8426 void RenderFrameHostImpl::IsClipboardPasteAllowed(
8427 const ui::ClipboardFormatType& data_type,
8428 const std::string& data,
8429 IsClipboardPasteAllowedCallback callback) {
8430 delegate_->IsClipboardPasteAllowed(GetLastCommittedURL(), data_type, data,
8431 std::move(callback));
8432 }
8433
ParentOrOuterDelegateFrame()8434 RenderFrameHostImpl* RenderFrameHostImpl::ParentOrOuterDelegateFrame() {
8435 // Find the parent in the FrameTree (iframe).
8436 if (parent_)
8437 return parent_;
8438
8439 // Find the parent in the WebContentsTree (GuestView or Portal).
8440 FrameTreeNode* frame_in_embedder =
8441 frame_tree_node()->render_manager()->GetOuterDelegateNode();
8442 if (frame_in_embedder)
8443 return frame_in_embedder->current_frame_host()->GetParent();
8444
8445 // No parent found.
8446 return nullptr;
8447 }
8448
8449 #if BUILDFLAG(ENABLE_WEB_AUTH)
8450 scoped_refptr<WebAuthRequestSecurityChecker>
GetWebAuthRequestSecurityChecker()8451 RenderFrameHostImpl::GetWebAuthRequestSecurityChecker() {
8452 if (!webauth_request_security_checker_)
8453 webauth_request_security_checker_ =
8454 base::MakeRefCounted<WebAuthRequestSecurityChecker>(this);
8455
8456 return webauth_request_security_checker_;
8457 }
8458 #endif
8459
8460 } // namespace content
8461