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(¶ms, 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