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, &params->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       &params->header_client, &bypass_redirect_checks,
6432       &params->disable_secure_dns, &params->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, &params->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, &params->url);
7371   process->FilterURL(true, &params->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