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/test/test_render_frame_host.h"
6 
7 #include <algorithm>
8 #include <memory>
9 #include <utility>
10 
11 #include "base/guid.h"
12 #include "base/optional.h"
13 #include "base/run_loop.h"
14 #include "content/browser/renderer_host/frame_tree.h"
15 #include "content/browser/renderer_host/navigation_request.h"
16 #include "content/browser/renderer_host/navigator.h"
17 #include "content/browser/renderer_host/render_frame_host_delegate.h"
18 #include "content/browser/web_contents/web_contents_impl.h"
19 #include "content/common/navigation_params.h"
20 #include "content/common/navigation_params_utils.h"
21 #include "content/public/browser/navigation_throttle.h"
22 #include "content/public/common/navigation_policy.h"
23 #include "content/public/common/url_constants.h"
24 #include "content/public/common/url_utils.h"
25 #include "content/test/test_navigation_url_loader.h"
26 #include "content/test/test_render_view_host.h"
27 #include "content/test/test_render_widget_host.h"
28 #include "ipc/ipc_message.h"
29 #include "mojo/public/cpp/bindings/pending_associated_remote.h"
30 #include "mojo/public/cpp/bindings/pending_receiver.h"
31 #include "mojo/public/cpp/bindings/pending_remote.h"
32 #include "net/base/ip_endpoint.h"
33 #include "net/base/load_flags.h"
34 #include "net/http/http_response_headers.h"
35 #include "services/network/public/cpp/parsed_headers.h"
36 #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
37 #include "third_party/blink/public/common/frame/frame_policy.h"
38 #include "third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom.h"
39 #include "third_party/blink/public/mojom/frame/frame_owner_element_type.mojom.h"
40 #include "third_party/blink/public/mojom/frame/frame_owner_properties.mojom.h"
41 #include "third_party/blink/public/mojom/frame/tree_scope_type.mojom.h"
42 #include "third_party/blink/public/mojom/security_context/insecure_request_policy.mojom.h"
43 #include "third_party/blink/public/platform/web_mixed_content_context_type.h"
44 #include "ui/base/page_transition_types.h"
45 
46 namespace content {
47 
TestRenderFrameHostCreationObserver(WebContents * web_contents)48 TestRenderFrameHostCreationObserver::TestRenderFrameHostCreationObserver(
49     WebContents* web_contents)
50     : WebContentsObserver(web_contents), last_created_frame_(nullptr) {}
51 
52 TestRenderFrameHostCreationObserver::~TestRenderFrameHostCreationObserver() =
53     default;
54 
RenderFrameCreated(RenderFrameHost * render_frame_host)55 void TestRenderFrameHostCreationObserver::RenderFrameCreated(
56     RenderFrameHost* render_frame_host) {
57   last_created_frame_ = render_frame_host;
58 }
59 
TestRenderFrameHost(SiteInstance * site_instance,scoped_refptr<RenderViewHostImpl> render_view_host,RenderFrameHostDelegate * delegate,FrameTree * frame_tree,FrameTreeNode * frame_tree_node,int32_t routing_id,const base::UnguessableToken & frame_token,RenderFrameHostImpl::LifecycleState lifecyle_state)60 TestRenderFrameHost::TestRenderFrameHost(
61     SiteInstance* site_instance,
62     scoped_refptr<RenderViewHostImpl> render_view_host,
63     RenderFrameHostDelegate* delegate,
64     FrameTree* frame_tree,
65     FrameTreeNode* frame_tree_node,
66     int32_t routing_id,
67     const base::UnguessableToken& frame_token,
68     RenderFrameHostImpl::LifecycleState lifecyle_state)
69     : RenderFrameHostImpl(site_instance,
70                           std::move(render_view_host),
71                           delegate,
72                           frame_tree,
73                           frame_tree_node,
74                           routing_id,
75                           frame_token,
76                           /*renderer_initiated_creation=*/false,
77                           lifecyle_state),
78       child_creation_observer_(delegate ? delegate->GetAsWebContents()
79                                         : nullptr),
80       simulate_history_list_was_cleared_(false),
81       last_commit_was_error_page_(false) {}
82 
83 TestRenderFrameHost::~TestRenderFrameHost() = default;
84 
GetRenderViewHost()85 TestRenderViewHost* TestRenderFrameHost::GetRenderViewHost() {
86   return static_cast<TestRenderViewHost*>(
87       RenderFrameHostImpl::GetRenderViewHost());
88 }
89 
GetProcess()90 MockRenderProcessHost* TestRenderFrameHost::GetProcess() {
91   return static_cast<MockRenderProcessHost*>(RenderFrameHostImpl::GetProcess());
92 }
93 
GetRenderWidgetHost()94 TestRenderWidgetHost* TestRenderFrameHost::GetRenderWidgetHost() {
95   return static_cast<TestRenderWidgetHost*>(
96       RenderFrameHostImpl::GetRenderWidgetHost());
97 }
98 
AddMessageToConsole(blink::mojom::ConsoleMessageLevel level,const std::string & message)99 void TestRenderFrameHost::AddMessageToConsole(
100     blink::mojom::ConsoleMessageLevel level,
101     const std::string& message) {
102   console_messages_.push_back(message);
103   RenderFrameHostImpl::AddMessageToConsole(level, message);
104 }
105 
ReportHeavyAdIssue(blink::mojom::HeavyAdResolutionStatus resolution,blink::mojom::HeavyAdReason reason)106 void TestRenderFrameHost::ReportHeavyAdIssue(
107     blink::mojom::HeavyAdResolutionStatus resolution,
108     blink::mojom::HeavyAdReason reason) {
109   switch (reason) {
110     case blink::mojom::HeavyAdReason::kNetworkTotalLimit:
111       heavy_ad_issue_network_count_++;
112       break;
113     case blink::mojom::HeavyAdReason::kCpuTotalLimit:
114       heavy_ad_issue_cpu_total_count_++;
115       break;
116     case blink::mojom::HeavyAdReason::kCpuPeakLimit:
117       heavy_ad_issue_cpu_peak_count_++;
118       break;
119   }
120   RenderFrameHostImpl::ReportHeavyAdIssue(resolution, reason);
121 }
122 
IsTestRenderFrameHost() const123 bool TestRenderFrameHost::IsTestRenderFrameHost() const {
124   return true;
125 }
126 
DidFailLoadWithError(const GURL & url,int error_code)127 void TestRenderFrameHost::DidFailLoadWithError(const GURL& url,
128                                                int error_code) {
129   RenderFrameHostImpl::DidFailLoadWithError(url, error_code);
130 }
131 
InitializeRenderFrameIfNeeded()132 void TestRenderFrameHost::InitializeRenderFrameIfNeeded() {
133   if (!render_view_host()->IsRenderViewLive()) {
134     render_view_host()->GetProcess()->Init();
135     RenderViewHostTester::For(render_view_host())
136         ->CreateTestRenderView(base::nullopt, MSG_ROUTING_NONE, false);
137   }
138 }
139 
AppendChild(const std::string & frame_name)140 TestRenderFrameHost* TestRenderFrameHost::AppendChild(
141     const std::string& frame_name) {
142   return AppendChildWithPolicy(frame_name, {});
143 }
144 
AppendChildWithPolicy(const std::string & frame_name,const blink::ParsedFeaturePolicy & allow)145 TestRenderFrameHost* TestRenderFrameHost::AppendChildWithPolicy(
146     const std::string& frame_name,
147     const blink::ParsedFeaturePolicy& allow) {
148   std::string frame_unique_name = base::GenerateGUID();
149   OnCreateChildFrame(
150       GetProcess()->GetNextRoutingID(), CreateStubInterfaceProviderReceiver(),
151       CreateStubBrowserInterfaceBrokerReceiver(),
152       blink::mojom::TreeScopeType::kDocument, frame_name, frame_unique_name,
153       false, base::UnguessableToken::Create(), base::UnguessableToken::Create(),
154       blink::FramePolicy(
155           {network::mojom::WebSandboxFlags::kNone, allow, {}, true, false}),
156       blink::mojom::FrameOwnerProperties(),
157       blink::mojom::FrameOwnerElementType::kIframe);
158   return static_cast<TestRenderFrameHost*>(
159       child_creation_observer_.last_created_frame());
160 }
161 
Detach()162 void TestRenderFrameHost::Detach() {
163   DetachForTesting();
164 }
165 
SimulateNavigationStart(const GURL & url)166 void TestRenderFrameHost::SimulateNavigationStart(const GURL& url) {
167   SendRendererInitiatedNavigationRequest(url, false);
168 }
169 
SimulateRedirect(const GURL & new_url)170 void TestRenderFrameHost::SimulateRedirect(const GURL& new_url) {
171   NavigationRequest* request = frame_tree_node_->navigation_request();
172   if (!request->loader_for_testing()) {
173     base::RunLoop loop;
174     request->set_on_start_checks_complete_closure_for_testing(
175         loop.QuitClosure());
176     loop.Run();
177   }
178   TestNavigationURLLoader* url_loader =
179       static_cast<TestNavigationURLLoader*>(request->loader_for_testing());
180   CHECK(url_loader);
181   url_loader->SimulateServerRedirect(new_url);
182 }
183 
SimulateNavigationCommit(const GURL & url)184 void TestRenderFrameHost::SimulateNavigationCommit(const GURL& url) {
185   if (frame_tree_node_->navigation_request())
186     PrepareForCommit();
187 
188   bool is_auto_subframe =
189       GetParent() && !frame_tree_node()->has_committed_real_load();
190 
191   FrameHostMsg_DidCommitProvisionalLoad_Params params;
192   params.nav_entry_id = 0;
193   params.url = url;
194   params.origin = url::Origin::Create(url);
195   if (!GetParent())
196     params.transition = ui::PAGE_TRANSITION_LINK;
197   else if (is_auto_subframe)
198     params.transition = ui::PAGE_TRANSITION_AUTO_SUBFRAME;
199   else
200     params.transition = ui::PAGE_TRANSITION_MANUAL_SUBFRAME;
201   params.should_update_history = true;
202   params.did_create_new_entry = !is_auto_subframe;
203   params.gesture = NavigationGestureUser;
204   params.contents_mime_type = "text/html";
205   params.method = "GET";
206   params.http_status_code = 200;
207   params.history_list_was_cleared = simulate_history_list_was_cleared_;
208   params.original_request_url = url;
209 
210   url::Replacements<char> replacements;
211   replacements.ClearRef();
212 
213   // This approach to determining whether a navigation is to be treated as
214   // same document is not robust, as it will not handle pushState type
215   // navigation. Do not use elsewhere!
216   bool was_within_same_document =
217       (GetLastCommittedURL().is_valid() && !last_commit_was_error_page_ &&
218        url.ReplaceComponents(replacements) ==
219            GetLastCommittedURL().ReplaceComponents(replacements));
220 
221   params.page_state =
222       blink::PageState::CreateForTesting(url, false, nullptr, nullptr);
223   if (!was_within_same_document)
224     params.embedding_token = base::UnguessableToken::Create();
225 
226   SendNavigateWithParams(&params, was_within_same_document);
227 }
228 
SimulateBeforeUnloadCompleted(bool proceed)229 void TestRenderFrameHost::SimulateBeforeUnloadCompleted(bool proceed) {
230   base::TimeTicks now = base::TimeTicks::Now();
231   ProcessBeforeUnloadCompleted(
232       proceed, false /* treat_as_final_completion_callback */, now, now);
233 }
234 
SimulateUnloadACK()235 void TestRenderFrameHost::SimulateUnloadACK() {
236   OnUnloadACK();
237 }
238 
SimulateFeaturePolicyHeader(blink::mojom::FeaturePolicyFeature feature,const std::vector<url::Origin> & allowlist)239 void TestRenderFrameHost::SimulateFeaturePolicyHeader(
240     blink::mojom::FeaturePolicyFeature feature,
241     const std::vector<url::Origin>& allowlist) {
242   blink::ParsedFeaturePolicy header(1);
243   header[0].feature = feature;
244   header[0].matches_all_origins = false;
245   header[0].matches_opaque_src = false;
246   for (const auto& origin : allowlist) {
247     header[0].allowed_origins.push_back(origin);
248   }
249   DidSetFramePolicyHeaders(network::mojom::WebSandboxFlags::kNone, header,
250                            {} /* dp_header */);
251 }
252 
SimulateUserActivation()253 void TestRenderFrameHost::SimulateUserActivation() {
254   frame_tree_node()->UpdateUserActivationState(
255       blink::mojom::UserActivationUpdateType::kNotifyActivation,
256       blink::mojom::UserActivationNotificationType::kTest);
257 }
258 
GetConsoleMessages()259 const std::vector<std::string>& TestRenderFrameHost::GetConsoleMessages() {
260   return console_messages_;
261 }
262 
GetHeavyAdIssueCount(RenderFrameHostTester::HeavyAdIssueType type)263 int TestRenderFrameHost::GetHeavyAdIssueCount(
264     RenderFrameHostTester::HeavyAdIssueType type) {
265   switch (type) {
266     case RenderFrameHostTester::HeavyAdIssueType::kNetworkTotal:
267       return heavy_ad_issue_network_count_;
268     case RenderFrameHostTester::HeavyAdIssueType::kCpuTotal:
269       return heavy_ad_issue_cpu_total_count_;
270     case RenderFrameHostTester::HeavyAdIssueType::kCpuPeak:
271       return heavy_ad_issue_cpu_peak_count_;
272     case RenderFrameHostTester::HeavyAdIssueType::kAll:
273       return heavy_ad_issue_network_count_ + heavy_ad_issue_cpu_total_count_ +
274              heavy_ad_issue_cpu_peak_count_;
275   }
276 }
277 
SendNavigate(int nav_entry_id,bool did_create_new_entry,const GURL & url)278 void TestRenderFrameHost::SendNavigate(int nav_entry_id,
279                                        bool did_create_new_entry,
280                                        const GURL& url) {
281   SendNavigateWithParameters(nav_entry_id, did_create_new_entry, url,
282                              ui::PAGE_TRANSITION_LINK, 200);
283 }
284 
SendNavigateWithTransition(int nav_entry_id,bool did_create_new_entry,const GURL & url,ui::PageTransition transition)285 void TestRenderFrameHost::SendNavigateWithTransition(
286     int nav_entry_id,
287     bool did_create_new_entry,
288     const GURL& url,
289     ui::PageTransition transition) {
290   SendNavigateWithParameters(nav_entry_id, did_create_new_entry, url,
291                              transition, 200);
292 }
293 
SendNavigateWithParameters(int nav_entry_id,bool did_create_new_entry,const GURL & url,ui::PageTransition transition,int response_code)294 void TestRenderFrameHost::SendNavigateWithParameters(
295     int nav_entry_id,
296     bool did_create_new_entry,
297     const GURL& url,
298     ui::PageTransition transition,
299     int response_code) {
300   // This approach to determining whether a navigation is to be treated as
301   // same document is not robust, as it will not handle pushState type
302   // navigation. Do not use elsewhere!
303   url::Replacements<char> replacements;
304   replacements.ClearRef();
305   bool was_within_same_document =
306       !ui::PageTransitionCoreTypeIs(transition, ui::PAGE_TRANSITION_RELOAD) &&
307       !ui::PageTransitionCoreTypeIs(transition, ui::PAGE_TRANSITION_TYPED) &&
308       (GetLastCommittedURL().is_valid() && !last_commit_was_error_page_ &&
309        url.ReplaceComponents(replacements) ==
310            GetLastCommittedURL().ReplaceComponents(replacements));
311 
312   auto params = BuildDidCommitParams(nav_entry_id, did_create_new_entry, url,
313                                      transition, response_code);
314   if (!was_within_same_document)
315     params->embedding_token = base::UnguessableToken::Create();
316 
317   SendNavigateWithParams(params.get(), was_within_same_document);
318 }
319 
SendNavigateWithParams(FrameHostMsg_DidCommitProvisionalLoad_Params * params,bool was_within_same_document)320 void TestRenderFrameHost::SendNavigateWithParams(
321     FrameHostMsg_DidCommitProvisionalLoad_Params* params,
322     bool was_within_same_document) {
323   SendNavigateWithParamsAndInterfaceParams(
324       std::move(params),
325       BuildDidCommitInterfaceParams(was_within_same_document),
326       was_within_same_document);
327 }
328 
SendNavigateWithParamsAndInterfaceParams(FrameHostMsg_DidCommitProvisionalLoad_Params * params,mojom::DidCommitProvisionalLoadInterfaceParamsPtr interface_params,bool was_within_same_document)329 void TestRenderFrameHost::SendNavigateWithParamsAndInterfaceParams(
330     FrameHostMsg_DidCommitProvisionalLoad_Params* params,
331     mojom::DidCommitProvisionalLoadInterfaceParamsPtr interface_params,
332     bool was_within_same_document) {
333   if (was_within_same_document) {
334     DidCommitSameDocumentNavigation(
335         std::make_unique<FrameHostMsg_DidCommitProvisionalLoad_Params>(
336             *params));
337   } else {
338     DidCommitProvisionalLoad(
339         std::make_unique<FrameHostMsg_DidCommitProvisionalLoad_Params>(*params),
340         std::move(interface_params));
341   }
342   last_commit_was_error_page_ = params->url_is_unreachable;
343 }
344 
SendRendererInitiatedNavigationRequest(const GURL & url,bool has_user_gesture)345 void TestRenderFrameHost::SendRendererInitiatedNavigationRequest(
346     const GURL& url,
347     bool has_user_gesture) {
348   // Since this is renderer-initiated navigation, the RenderFrame must be
349   // initialized. Do it if it hasn't happened yet.
350   InitializeRenderFrameIfNeeded();
351 
352   mojom::BeginNavigationParamsPtr begin_params =
353       mojom::BeginNavigationParams::New(
354           MSG_ROUTING_NONE /* initiator_routing_id */,
355           std::string() /* headers */, net::LOAD_NORMAL,
356           false /* skip_service_worker */,
357           blink::mojom::RequestContextType::HYPERLINK,
358           network::mojom::RequestDestination::kDocument,
359           blink::WebMixedContentContextType::kBlockable,
360           false /* is_form_submission */,
361           false /* was_initiated_by_link_click */,
362           GURL() /* searchable_form_url */,
363           std::string() /* searchable_form_encoding */,
364           GURL() /* client_side_redirect_url */,
365           base::nullopt /* devtools_initiator_info */,
366           false /* force_ignore_site_for_cookies */,
367           nullptr /* trust_token_params */, base::nullopt /* impression */,
368           base::TimeTicks() /* renderer_before_unload_start */,
369           base::TimeTicks() /* renderer_before_unload_end */);
370   auto common_params = CreateCommonNavigationParams();
371   common_params->url = url;
372   common_params->initiator_origin = GetLastCommittedOrigin();
373   common_params->referrer = blink::mojom::Referrer::New(
374       GURL(), network::mojom::ReferrerPolicy::kDefault);
375   common_params->transition = ui::PAGE_TRANSITION_LINK;
376   common_params->navigation_type = mojom::NavigationType::DIFFERENT_DOCUMENT;
377   common_params->has_user_gesture = has_user_gesture;
378 
379   mojo::PendingAssociatedRemote<mojom::NavigationClient>
380       navigation_client_remote;
381   GetRemoteAssociatedInterfaces()->GetInterface(
382       navigation_client_remote.InitWithNewEndpointAndPassReceiver());
383   BeginNavigation(std::move(common_params), std::move(begin_params),
384                   mojo::NullRemote(), std::move(navigation_client_remote),
385                   mojo::NullRemote());
386 }
387 
SimulateDidChangeOpener(const base::Optional<base::UnguessableToken> & opener_frame_token)388 void TestRenderFrameHost::SimulateDidChangeOpener(
389     const base::Optional<base::UnguessableToken>& opener_frame_token) {
390   DidChangeOpener(opener_frame_token);
391 }
392 
DidEnforceInsecureRequestPolicy(blink::mojom::InsecureRequestPolicy policy)393 void TestRenderFrameHost::DidEnforceInsecureRequestPolicy(
394     blink::mojom::InsecureRequestPolicy policy) {
395   EnforceInsecureRequestPolicy(policy);
396 }
397 
PrepareForCommit()398 void TestRenderFrameHost::PrepareForCommit() {
399   PrepareForCommitInternal(net::IPEndPoint(),
400                            /* was_fetched_via_cache=*/false,
401                            /* is_signed_exchange_inner_response=*/false,
402                            net::HttpResponseInfo::CONNECTION_INFO_UNKNOWN,
403                            base::nullopt, nullptr);
404 }
405 
PrepareForCommitDeprecatedForNavigationSimulator(const net::IPEndPoint & remote_endpoint,bool was_fetched_via_cache,bool is_signed_exchange_inner_response,net::HttpResponseInfo::ConnectionInfo connection_info,base::Optional<net::SSLInfo> ssl_info,scoped_refptr<net::HttpResponseHeaders> response_headers)406 void TestRenderFrameHost::PrepareForCommitDeprecatedForNavigationSimulator(
407     const net::IPEndPoint& remote_endpoint,
408     bool was_fetched_via_cache,
409     bool is_signed_exchange_inner_response,
410     net::HttpResponseInfo::ConnectionInfo connection_info,
411     base::Optional<net::SSLInfo> ssl_info,
412     scoped_refptr<net::HttpResponseHeaders> response_headers) {
413   PrepareForCommitInternal(remote_endpoint, was_fetched_via_cache,
414                            is_signed_exchange_inner_response, connection_info,
415                            ssl_info, response_headers);
416 }
417 
PrepareForCommitInternal(const net::IPEndPoint & remote_endpoint,bool was_fetched_via_cache,bool is_signed_exchange_inner_response,net::HttpResponseInfo::ConnectionInfo connection_info,base::Optional<net::SSLInfo> ssl_info,scoped_refptr<net::HttpResponseHeaders> response_headers)418 void TestRenderFrameHost::PrepareForCommitInternal(
419     const net::IPEndPoint& remote_endpoint,
420     bool was_fetched_via_cache,
421     bool is_signed_exchange_inner_response,
422     net::HttpResponseInfo::ConnectionInfo connection_info,
423     base::Optional<net::SSLInfo> ssl_info,
424     scoped_refptr<net::HttpResponseHeaders> response_headers) {
425   NavigationRequest* request = frame_tree_node_->navigation_request();
426   CHECK(request);
427   bool have_to_make_network_request =
428       IsURLHandledByNetworkStack(request->common_params().url) &&
429       !NavigationTypeUtils::IsSameDocument(
430           request->common_params().navigation_type);
431 
432   // Simulate a beforeUnload completion callback from the renderer if the
433   // browser is waiting for it. If it runs it will update the request state.
434   if (request->state() == NavigationRequest::WAITING_FOR_RENDERER_RESPONSE) {
435     static_cast<TestRenderFrameHost*>(frame_tree_node()->current_frame_host())
436         ->SimulateBeforeUnloadCompleted(true);
437   }
438 
439   if (!have_to_make_network_request)
440     return;  // |request| is destructed by now.
441 
442   CHECK(request->state() >= NavigationRequest::WILL_START_NAVIGATION &&
443         request->state() < NavigationRequest::READY_TO_COMMIT);
444 
445   if (!request->loader_for_testing()) {
446     base::RunLoop loop;
447     request->set_on_start_checks_complete_closure_for_testing(
448         loop.QuitClosure());
449     loop.Run();
450   }
451 
452   TestNavigationURLLoader* url_loader =
453       static_cast<TestNavigationURLLoader*>(request->loader_for_testing());
454   CHECK(url_loader);
455 
456   // Simulate the network stack commit.
457   auto response = network::mojom::URLResponseHead::New();
458   response->remote_endpoint = remote_endpoint;
459   response->was_fetched_via_cache = was_fetched_via_cache;
460   response->is_signed_exchange_inner_response =
461       is_signed_exchange_inner_response;
462   response->connection_info = connection_info;
463   response->ssl_info = ssl_info;
464   response->load_timing.send_start = base::TimeTicks::Now();
465   response->load_timing.receive_headers_start = base::TimeTicks::Now();
466   response->headers = response_headers;
467   response->parsed_headers =
468       network::PopulateParsedHeaders(response->headers, request->GetURL());
469   // TODO(carlosk): Ideally, it should be possible someday to
470   // fully commit the navigation at this call to CallOnResponseStarted.
471   url_loader->CallOnResponseStarted(std::move(response));
472 }
473 
SimulateCommitProcessed(NavigationRequest * navigation_request,std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params> params,mojo::PendingReceiver<service_manager::mojom::InterfaceProvider> interface_provider_receiver,mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker> browser_interface_broker_receiver,bool same_document)474 void TestRenderFrameHost::SimulateCommitProcessed(
475     NavigationRequest* navigation_request,
476     std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params> params,
477     mojo::PendingReceiver<service_manager::mojom::InterfaceProvider>
478         interface_provider_receiver,
479     mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
480         browser_interface_broker_receiver,
481     bool same_document) {
482   CHECK(params);
483 
484   bool did_commit = false;
485   if (!same_document) {
486     // Note: Although the code does not prohibit the running of multiple
487     // callbacks, no more than 1 callback will ever run, because navigation_id
488     // is unique across all callback storages.
489     {
490       auto callback_it = commit_callback_.find(navigation_request);
491       if (callback_it != commit_callback_.end()) {
492         std::move(callback_it->second)
493             .Run(std::move(params),
494                  mojom::DidCommitProvisionalLoadInterfaceParams::New(
495                      std::move(interface_provider_receiver),
496                      std::move(browser_interface_broker_receiver)));
497         did_commit = true;
498       }
499     }
500     {
501       auto callback_it = commit_failed_callback_.find(navigation_request);
502       if (callback_it != commit_failed_callback_.end()) {
503         std::move(callback_it->second)
504             .Run(std::move(params),
505                  mojom::DidCommitProvisionalLoadInterfaceParams::New(
506                      std::move(interface_provider_receiver),
507                      std::move(browser_interface_broker_receiver)));
508         did_commit = true;
509       }
510     }
511   }
512 
513   if (!did_commit) {
514     SendNavigateWithParamsAndInterfaceParams(
515         params.get(),
516         mojom::DidCommitProvisionalLoadInterfaceParams::New(
517             std::move(interface_provider_receiver),
518             std::move(browser_interface_broker_receiver)),
519         same_document);
520   }
521 }
522 
523 WebBluetoothServiceImpl*
CreateWebBluetoothServiceForTesting()524 TestRenderFrameHost::CreateWebBluetoothServiceForTesting() {
525   RenderFrameHostImpl::CreateWebBluetoothService(
526       dummy_web_bluetooth_service_remote_.InitWithNewPipeAndPassReceiver());
527   return RenderFrameHostImpl::GetWebBluetoothServiceForTesting();
528 }
529 
SendFramePolicy(network::mojom::WebSandboxFlags sandbox_flags,const blink::ParsedFeaturePolicy & fp_header,const blink::DocumentPolicyFeatureState & dp_header)530 void TestRenderFrameHost::SendFramePolicy(
531     network::mojom::WebSandboxFlags sandbox_flags,
532     const blink::ParsedFeaturePolicy& fp_header,
533     const blink::DocumentPolicyFeatureState& dp_header) {
534   DidSetFramePolicyHeaders(sandbox_flags, fp_header, dp_header);
535 }
536 
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<blink::mojom::TransferrableURLLoaderPtr>> subresource_overrides,blink::mojom::ControllerServiceWorkerInfoPtr controller,blink::mojom::ServiceWorkerContainerInfoForClientPtr container_info,mojo::PendingRemote<network::mojom::URLLoaderFactory> prefetch_loader_factory,blink::mojom::PolicyContainerPtr policy_container,const base::UnguessableToken & devtools_navigation_token)537 void TestRenderFrameHost::SendCommitNavigation(
538     mojom::NavigationClient* navigation_client,
539     NavigationRequest* navigation_request,
540     mojom::CommonNavigationParamsPtr common_params,
541     mojom::CommitNavigationParamsPtr commit_params,
542     network::mojom::URLResponseHeadPtr response_head,
543     mojo::ScopedDataPipeConsumerHandle response_body,
544     network::mojom::URLLoaderClientEndpointsPtr url_loader_client_endpoints,
545     std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
546         subresource_loader_factories,
547     base::Optional<std::vector<blink::mojom::TransferrableURLLoaderPtr>>
548         subresource_overrides,
549     blink::mojom::ControllerServiceWorkerInfoPtr controller,
550     blink::mojom::ServiceWorkerContainerInfoForClientPtr container_info,
551     mojo::PendingRemote<network::mojom::URLLoaderFactory>
552         prefetch_loader_factory,
553     blink::mojom::PolicyContainerPtr policy_container,
554     const base::UnguessableToken& devtools_navigation_token) {
555   CHECK(navigation_client);
556   commit_callback_[navigation_request] =
557       BuildCommitNavigationCallback(navigation_request);
558 }
559 
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)560 void TestRenderFrameHost::SendCommitFailedNavigation(
561     mojom::NavigationClient* navigation_client,
562     NavigationRequest* navigation_request,
563     mojom::CommonNavigationParamsPtr common_params,
564     mojom::CommitNavigationParamsPtr commit_params,
565     bool has_stale_copy_in_cache,
566     int32_t error_code,
567     const base::Optional<std::string>& error_page_content,
568     std::unique_ptr<blink::PendingURLLoaderFactoryBundle>
569         subresource_loader_factories) {
570   CHECK(navigation_client);
571   commit_failed_callback_[navigation_request] =
572       BuildCommitFailedNavigationCallback(navigation_request);
573 }
574 
575 std::unique_ptr<FrameHostMsg_DidCommitProvisionalLoad_Params>
BuildDidCommitParams(int nav_entry_id,bool did_create_new_entry,const GURL & url,ui::PageTransition transition,int response_code)576 TestRenderFrameHost::BuildDidCommitParams(int nav_entry_id,
577                                           bool did_create_new_entry,
578                                           const GURL& url,
579                                           ui::PageTransition transition,
580                                           int response_code) {
581   auto params =
582       std::make_unique<FrameHostMsg_DidCommitProvisionalLoad_Params>();
583   params->nav_entry_id = nav_entry_id;
584   params->url = url;
585   params->transition = transition;
586   params->should_update_history = true;
587   params->did_create_new_entry = did_create_new_entry;
588   params->should_replace_current_entry = false;
589   params->gesture = NavigationGestureUser;
590   params->contents_mime_type = "text/html";
591   params->method = "GET";
592   params->http_status_code = response_code;
593   params->history_list_was_cleared = simulate_history_list_was_cleared_;
594   params->original_request_url = url;
595 
596   // Simulate Blink assigning an item and document sequence number to the
597   // navigation.
598   params->item_sequence_number = base::Time::Now().ToDoubleT() * 1000000;
599   params->document_sequence_number = params->item_sequence_number + 1;
600 
601   // When the user hits enter in the Omnibox without changing the URL, Blink
602   // behaves similarly to a reload and does not change the item and document
603   // sequence numbers. Simulate this behavior here too.
604   if (PageTransitionCoreTypeIs(transition, ui::PAGE_TRANSITION_TYPED)) {
605     NavigationEntryImpl* entry =
606         static_cast<NavigationEntryImpl*>(frame_tree_node()
607                                               ->navigator()
608                                               .GetController()
609                                               ->GetLastCommittedEntry());
610     if (entry && entry->GetURL() == url) {
611       FrameNavigationEntry* frame_entry =
612           entry->GetFrameEntry(frame_tree_node());
613       if (frame_entry) {
614         params->item_sequence_number = frame_entry->item_sequence_number();
615         params->document_sequence_number =
616             frame_entry->document_sequence_number();
617       }
618     }
619   }
620 
621   // In most cases, the origin will match the URL's origin.  Tests that need to
622   // check corner cases (like about:blank) should specify the origin param
623   // manually.
624   url::Origin origin = url::Origin::Create(url);
625   params->origin = origin;
626 
627   params->page_state = blink::PageState::CreateForTestingWithSequenceNumbers(
628       url, params->item_sequence_number, params->document_sequence_number);
629 
630   return params;
631 }
632 
633 mojom::DidCommitProvisionalLoadInterfaceParamsPtr
BuildDidCommitInterfaceParams(bool is_same_document)634 TestRenderFrameHost::BuildDidCommitInterfaceParams(bool is_same_document) {
635   mojo::PendingRemote<service_manager::mojom::InterfaceProvider>
636       interface_provider;
637   mojo::PendingReceiver<service_manager::mojom::InterfaceProvider>
638       interface_provider_receiver;
639 
640   mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
641       browser_interface_broker_receiver;
642 
643   if (!is_same_document) {
644     interface_provider_receiver =
645         interface_provider.InitWithNewPipeAndPassReceiver();
646     browser_interface_broker_receiver =
647         mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>()
648             .InitWithNewPipeAndPassReceiver();
649   }
650 
651   auto interface_params = mojom::DidCommitProvisionalLoadInterfaceParams::New(
652       std::move(interface_provider_receiver),
653       std::move(browser_interface_broker_receiver));
654   return interface_params;
655 }
656 
AbortCommit(NavigationRequest * navigation_request)657 void TestRenderFrameHost::AbortCommit(NavigationRequest* navigation_request) {
658   OnCrossDocumentCommitProcessed(navigation_request,
659                                  blink::mojom::CommitResult::Aborted);
660 }
661 
662 // static
663 mojo::PendingReceiver<service_manager::mojom::InterfaceProvider>
CreateStubInterfaceProviderReceiver()664 TestRenderFrameHost::CreateStubInterfaceProviderReceiver() {
665   mojo::PendingRemote<::service_manager::mojom::InterfaceProvider>
666       dead_interface_provider_proxy;
667   return dead_interface_provider_proxy.InitWithNewPipeAndPassReceiver();
668 }
669 
670 // static
671 mojo::PendingReceiver<blink::mojom::BrowserInterfaceBroker>
CreateStubBrowserInterfaceBrokerReceiver()672 TestRenderFrameHost::CreateStubBrowserInterfaceBrokerReceiver() {
673   return mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker>()
674       .InitWithNewPipeAndPassReceiver();
675 }
676 
SimulateLoadingCompleted(TestRenderFrameHost::LoadingScenario loading_scenario)677 void TestRenderFrameHost::SimulateLoadingCompleted(
678     TestRenderFrameHost::LoadingScenario loading_scenario) {
679   if (!is_loading())
680     return;
681 
682   if (loading_scenario == LoadingScenario::NewDocumentNavigation) {
683     if (frame_tree_node_->IsMainFrame())
684       DocumentAvailableInMainFrame(/* uses_temporary_zoom_level */ false);
685 
686     DidFinishDocumentLoad();
687 
688     DocumentOnLoadCompleted();
689 
690     DidFinishLoad(GetLastCommittedURL());
691   }
692 
693   DidStopLoading();
694 }
695 
696 }  // namespace content
697