Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(82)

Side by Side Diff: content/public/test/navigation_simulator.cc

Issue 2698393002: Allow asynchronous deferral in NavigationSimulator (Closed)
Patch Set: Remove the wait API Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/public/test/navigation_simulator.h" 5 #include "content/public/test/navigation_simulator.h"
6 6
7 #include "base/bind.h"
8 #include "base/memory/ptr_util.h"
9 #include "base/run_loop.h"
7 #include "content/browser/frame_host/navigation_handle_impl.h" 10 #include "content/browser/frame_host/navigation_handle_impl.h"
8 #include "content/browser/frame_host/navigation_request.h" 11 #include "content/browser/frame_host/navigation_request.h"
9 #include "content/common/frame_messages.h" 12 #include "content/common/frame_messages.h"
10 #include "content/public/browser/navigation_throttle.h" 13 #include "content/public/browser/navigation_throttle.h"
11 #include "content/public/browser/web_contents.h" 14 #include "content/public/browser/web_contents.h"
12 #include "content/public/common/browser_side_navigation_policy.h" 15 #include "content/public/common/browser_side_navigation_policy.h"
13 #include "content/test/test_navigation_url_loader.h" 16 #include "content/test/test_navigation_url_loader.h"
14 #include "content/test/test_render_frame_host.h" 17 #include "content/test/test_render_frame_host.h"
15 #include "net/base/load_flags.h" 18 #include "net/base/load_flags.h"
16 #include "net/url_request/redirect_info.h" 19 #include "net/url_request/redirect_info.h"
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
116 common_params.referrer = referrer_; 119 common_params.referrer = referrer_;
117 common_params.transition = transition_; 120 common_params.transition = transition_;
118 common_params.navigation_type = 121 common_params.navigation_type =
119 PageTransitionCoreTypeIs(transition_, ui::PAGE_TRANSITION_RELOAD) 122 PageTransitionCoreTypeIs(transition_, ui::PAGE_TRANSITION_RELOAD)
120 ? FrameMsg_Navigate_Type::RELOAD 123 ? FrameMsg_Navigate_Type::RELOAD
121 : FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT; 124 : FrameMsg_Navigate_Type::DIFFERENT_DOCUMENT;
122 render_frame_host_->OnMessageReceived(FrameHostMsg_BeginNavigation( 125 render_frame_host_->OnMessageReceived(FrameHostMsg_BeginNavigation(
123 render_frame_host_->GetRoutingID(), common_params, begin_params)); 126 render_frame_host_->GetRoutingID(), common_params, begin_params));
124 NavigationRequest* request = 127 NavigationRequest* request =
125 render_frame_host_->frame_tree_node()->navigation_request(); 128 render_frame_host_->frame_tree_node()->navigation_request();
126 DCHECK(request); 129 // The request failed synchronously.
clamy 2017/03/09 13:18:13 nit: blank line above.
Charlie Harrison 2017/03/09 14:36:01 Done.
130 if (!request)
131 return;
127 DCHECK_EQ(handle_, request->navigation_handle()); 132 DCHECK_EQ(handle_, request->navigation_handle());
128 } else { 133 } else {
129 render_frame_host_->OnMessageReceived( 134 render_frame_host_->OnMessageReceived(
130 FrameHostMsg_DidStartLoading(render_frame_host_->GetRoutingID(), true)); 135 FrameHostMsg_DidStartLoading(render_frame_host_->GetRoutingID(), true));
131 render_frame_host_->OnMessageReceived(FrameHostMsg_DidStartProvisionalLoad( 136 render_frame_host_->OnMessageReceived(FrameHostMsg_DidStartProvisionalLoad(
132 render_frame_host_->GetRoutingID(), navigation_url_, 137 render_frame_host_->GetRoutingID(), navigation_url_,
133 std::vector<GURL>(), base::TimeTicks::Now())); 138 std::vector<GURL>(), base::TimeTicks::Now()));
134 DCHECK_EQ(handle_, render_frame_host_->navigation_handle()); 139 DCHECK_EQ(handle_, render_frame_host_->navigation_handle());
135 handle_->WillStartRequest( 140 handle_->WillStartRequest(
136 "GET", scoped_refptr<content::ResourceRequestBodyImpl>(), referrer_, 141 "GET", scoped_refptr<content::ResourceRequestBodyImpl>(), referrer_,
137 true /* user_gesture */, transition_, false /* is_external_protocol */, 142 true /* user_gesture */, transition_, false /* is_external_protocol */,
138 REQUEST_CONTEXT_TYPE_LOCATION, 143 REQUEST_CONTEXT_TYPE_LOCATION,
139 blink::WebMixedContentContextType::NotMixedContent, 144 blink::WebMixedContentContextType::NotMixedContent,
140 base::Callback<void(NavigationThrottle::ThrottleCheckResult)>()); 145 base::Callback<void(NavigationThrottle::ThrottleCheckResult)>());
141 } 146 }
142 147
143 CHECK(handle_); 148 CHECK(handle_);
144 149 WaitForThrottleChecksComplete();
145 // Make sure all NavigationThrottles have run.
146 // TODO(clamy): provide a non auto-advance mode if needed.
147 while (handle_->state_for_testing() == NavigationHandleImpl::DEFERRING_START)
148 handle_->Resume();
149 150
150 CHECK_EQ(1, num_did_start_navigation_called_); 151 CHECK_EQ(1, num_did_start_navigation_called_);
151 CHECK_EQ(1, num_will_start_request_called_); 152 if (GetLastThrottleCheckResult() == NavigationThrottle::PROCEED) {
153 CHECK_EQ(1, num_will_start_request_called_);
154 } else {
155 state_ = FAILED;
clamy 2017/03/09 13:18:13 Could you add a TODO(clamy): Add error handling co
Charlie Harrison 2017/03/09 14:36:01 Done.
156 }
152 } 157 }
153 158
154 void NavigationSimulator::Redirect(const GURL& new_url) { 159 void NavigationSimulator::Redirect(const GURL& new_url) {
155 CHECK(state_ <= STARTED) << "NavigationSimulator::Redirect should be " 160 CHECK(state_ <= STARTED) << "NavigationSimulator::Redirect should be "
156 "called before Fail or Commit"; 161 "called before Fail or Commit";
157 CHECK_EQ(0, num_did_finish_navigation_called_) 162 CHECK_EQ(0, num_did_finish_navigation_called_)
158 << "NavigationSimulator::Redirect cannot be called after the " 163 << "NavigationSimulator::Redirect cannot be called after the "
159 "navigation has finished"; 164 "navigation has finished";
160 165
161 if (state_ == INITIALIZATION) 166 if (state_ == INITIALIZATION)
162 Start(); 167 Start();
163 168
164 navigation_url_ = new_url; 169 navigation_url_ = new_url;
165 170
166 int previous_num_will_redirect_request_called = 171 int previous_num_will_redirect_request_called =
167 num_will_redirect_request_called_; 172 num_will_redirect_request_called_;
168 int previous_did_redirect_navigation_called = 173 int previous_did_redirect_navigation_called =
169 num_did_redirect_navigation_called_; 174 num_did_redirect_navigation_called_;
170 175
176 PrepareCompleteCallbackOnHandle();
171 if (IsBrowserSideNavigationEnabled()) { 177 if (IsBrowserSideNavigationEnabled()) {
172 NavigationRequest* request = 178 NavigationRequest* request =
173 render_frame_host_->frame_tree_node()->navigation_request(); 179 render_frame_host_->frame_tree_node()->navigation_request();
174 TestNavigationURLLoader* url_loader = 180 TestNavigationURLLoader* url_loader =
175 static_cast<TestNavigationURLLoader*>(request->loader_for_testing()); 181 static_cast<TestNavigationURLLoader*>(request->loader_for_testing());
176 CHECK(url_loader); 182 CHECK(url_loader);
177 183
178 net::RedirectInfo redirect_info; 184 net::RedirectInfo redirect_info;
179 redirect_info.status_code = 302; 185 redirect_info.status_code = 302;
180 redirect_info.new_method = "GET"; 186 redirect_info.new_method = "GET";
181 redirect_info.new_url = new_url; 187 redirect_info.new_url = new_url;
182 redirect_info.new_first_party_for_cookies = new_url; 188 redirect_info.new_first_party_for_cookies = new_url;
183 redirect_info.new_referrer = referrer_.url.spec(); 189 redirect_info.new_referrer = referrer_.url.spec();
184 redirect_info.new_referrer_policy = 190 redirect_info.new_referrer_policy =
185 Referrer::ReferrerPolicyForUrlRequest(referrer_); 191 Referrer::ReferrerPolicyForUrlRequest(referrer_);
186 192
187 url_loader->CallOnRequestRedirected( 193 url_loader->CallOnRequestRedirected(
188 redirect_info, scoped_refptr<ResourceResponse>(new ResourceResponse)); 194 redirect_info, scoped_refptr<ResourceResponse>(new ResourceResponse));
189 } else { 195 } else {
190 handle_->WillRedirectRequest( 196 handle_->WillRedirectRequest(
191 new_url, "GET", referrer_.url, false /* is_external_protocol */, 197 new_url, "GET", referrer_.url, false /* is_external_protocol */,
192 scoped_refptr<net::HttpResponseHeaders>(), 198 scoped_refptr<net::HttpResponseHeaders>(),
193 net::HttpResponseInfo::ConnectionInfo(), 199 net::HttpResponseInfo::ConnectionInfo(),
194 base::Callback<void(NavigationThrottle::ThrottleCheckResult)>()); 200 base::Callback<void(NavigationThrottle::ThrottleCheckResult)>());
195 } 201 }
196 202
197 // Make sure all NavigationThrottles have run. 203 WaitForThrottleChecksComplete();
198 // TODO(clamy): provide a non auto-advance mode if needed. 204
199 while (handle_->state_for_testing() == 205 if (GetLastThrottleCheckResult() == NavigationThrottle::PROCEED) {
200 NavigationHandleImpl::DEFERRING_REDIRECT) { 206 CHECK_EQ(previous_num_will_redirect_request_called + 1,
201 handle_->Resume(); 207 num_will_redirect_request_called_);
208 CHECK_EQ(previous_did_redirect_navigation_called + 1,
209 num_did_redirect_navigation_called_);
210 } else {
211 state_ = FAILED;
202 } 212 }
203
204 CHECK_EQ(previous_num_will_redirect_request_called + 1,
205 num_will_redirect_request_called_);
206 CHECK_EQ(previous_did_redirect_navigation_called + 1,
207 num_did_redirect_navigation_called_);
208 } 213 }
209 214
210 void NavigationSimulator::Commit() { 215 void NavigationSimulator::Commit() {
211 CHECK_LE(state_, STARTED) << "NavigationSimulator::Commit can only be " 216 CHECK_LE(state_, STARTED) << "NavigationSimulator::Commit can only be "
212 "called once, and cannot be called after " 217 "called once, and cannot be called after "
213 "NavigationSimulator::Fail"; 218 "NavigationSimulator::Fail";
214 CHECK_EQ(0, num_did_finish_navigation_called_) 219 CHECK_EQ(0, num_did_finish_navigation_called_)
215 << "NavigationSimulator::Commit cannot be called after the " 220 << "NavigationSimulator::Commit cannot be called after the "
216 "navigation has finished"; 221 "navigation has finished";
217 222
218 if (state_ == INITIALIZATION) 223 if (state_ == INITIALIZATION)
219 Start(); 224 Start();
220 225
226 PrepareCompleteCallbackOnHandle();
221 if (IsBrowserSideNavigationEnabled() && 227 if (IsBrowserSideNavigationEnabled() &&
222 render_frame_host_->frame_tree_node()->navigation_request()) { 228 render_frame_host_->frame_tree_node()->navigation_request()) {
223 render_frame_host_->PrepareForCommit(); 229 render_frame_host_->PrepareForCommit();
224 } 230 }
225 231
226 // Call NavigationHandle::WillProcessResponse if needed. 232 // Call NavigationHandle::WillProcessResponse if needed.
227 if (handle_->state_for_testing() < 233 // Note that the handle's state can be CANCELING if a throttle cancelled it
228 NavigationHandleImpl::WILL_PROCESS_RESPONSE) { 234 // synchronously in PrepareForCommit.
235 if (handle_->state_for_testing() < NavigationHandleImpl::CANCELING) {
229 handle_->WillProcessResponse( 236 handle_->WillProcessResponse(
230 render_frame_host_, scoped_refptr<net::HttpResponseHeaders>(), 237 render_frame_host_, scoped_refptr<net::HttpResponseHeaders>(),
231 net::HttpResponseInfo::ConnectionInfo(), SSLStatus(), GlobalRequestID(), 238 net::HttpResponseInfo::ConnectionInfo(), SSLStatus(), GlobalRequestID(),
232 false /* should_replace_current_entry */, false /* is_download */, 239 false /* should_replace_current_entry */, false /* is_download */,
233 false /* is_stream */, base::Closure(), 240 false /* is_stream */, base::Closure(),
234 base::Callback<void(NavigationThrottle::ThrottleCheckResult)>()); 241 base::Callback<void(NavigationThrottle::ThrottleCheckResult)>());
235 } 242 }
236 243
237 // Make sure all NavigationThrottles have run. 244 WaitForThrottleChecksComplete();
238 // TODO(clamy): provide a non auto-advance mode if needed. 245
239 while (handle_->state_for_testing() == 246 if (GetLastThrottleCheckResult() != NavigationThrottle::PROCEED) {
240 NavigationHandleImpl::DEFERRING_RESPONSE) { 247 state_ = FAILED;
241 handle_->Resume(); 248 return;
242 } 249 }
243 250
244 CHECK_EQ(1, num_will_process_response_called_); 251 CHECK_EQ(1, num_will_process_response_called_);
245 CHECK_EQ(1, num_ready_to_commit_called_); 252 CHECK_EQ(1, num_ready_to_commit_called_);
246 253
247 // Update the RenderFrameHost now that we know which RenderFrameHost will 254 // Update the RenderFrameHost now that we know which RenderFrameHost will
248 // commit the navigation. 255 // commit the navigation.
249 TestRenderFrameHost* new_render_frame_host = 256 TestRenderFrameHost* new_render_frame_host =
250 static_cast<TestRenderFrameHost*>(handle_->GetRenderFrameHost()); 257 static_cast<TestRenderFrameHost*>(handle_->GetRenderFrameHost());
251 if (!IsBrowserSideNavigationEnabled() && 258 if (!IsBrowserSideNavigationEnabled() &&
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
439 << "The transition cannot be set after the navigation has started"; 446 << "The transition cannot be set after the navigation has started";
440 transition_ = transition; 447 transition_ = transition;
441 } 448 }
442 449
443 void NavigationSimulator::SetReferrer(const Referrer& referrer) { 450 void NavigationSimulator::SetReferrer(const Referrer& referrer) {
444 CHECK_LE(state_, STARTED) << "The referrer cannot be set after the " 451 CHECK_LE(state_, STARTED) << "The referrer cannot be set after the "
445 "navigation has committed or has failed"; 452 "navigation has committed or has failed";
446 referrer_ = referrer; 453 referrer_ = referrer;
447 } 454 }
448 455
456 NavigationThrottle::ThrottleCheckResult
457 NavigationSimulator::GetLastThrottleCheckResult() {
458 return last_throttle_check_result_.value();
459 }
460
449 void NavigationSimulator::DidStartNavigation( 461 void NavigationSimulator::DidStartNavigation(
450 NavigationHandle* navigation_handle) { 462 NavigationHandle* navigation_handle) {
451 // Check if this navigation is the one we're simulating. 463 // Check if this navigation is the one we're simulating.
452 if (handle_) 464 if (handle_)
453 return; 465 return;
454 466
455 if (navigation_handle->GetURL() != navigation_url_) 467 if (navigation_handle->GetURL() != navigation_url_)
456 return; 468 return;
457 469
458 NavigationHandleImpl* handle = 470 NavigationHandleImpl* handle =
459 static_cast<NavigationHandleImpl*>(navigation_handle); 471 static_cast<NavigationHandleImpl*>(navigation_handle);
460 472
461 if (handle->frame_tree_node() != render_frame_host_->frame_tree_node()) 473 if (handle->frame_tree_node() != render_frame_host_->frame_tree_node())
462 return; 474 return;
463 475
464 handle_ = handle; 476 handle_ = handle;
465 477
466 num_did_start_navigation_called_++; 478 num_did_start_navigation_called_++;
467 479
468 // Add a throttle to count NavigationThrottle calls count. 480 // Add a throttle to count NavigationThrottle calls count.
469 handle->RegisterThrottleForTesting( 481 handle->RegisterThrottleForTesting(
470 base::MakeUnique<NavigationThrottleCallbackRunner>( 482 base::MakeUnique<NavigationThrottleCallbackRunner>(
471 handle, 483 handle,
472 base::Bind(&NavigationSimulator::OnWillStartRequest, 484 base::Bind(&NavigationSimulator::OnWillStartRequest,
473 weak_factory_.GetWeakPtr()), 485 weak_factory_.GetWeakPtr()),
474 base::Bind(&NavigationSimulator::OnWillRedirectRequest, 486 base::Bind(&NavigationSimulator::OnWillRedirectRequest,
475 weak_factory_.GetWeakPtr()), 487 weak_factory_.GetWeakPtr()),
476 base::Bind(&NavigationSimulator::OnWillProcessResponse, 488 base::Bind(&NavigationSimulator::OnWillProcessResponse,
477 weak_factory_.GetWeakPtr()))); 489 weak_factory_.GetWeakPtr())));
490
491 PrepareCompleteCallbackOnHandle();
478 } 492 }
479 493
480 void NavigationSimulator::DidRedirectNavigation( 494 void NavigationSimulator::DidRedirectNavigation(
481 NavigationHandle* navigation_handle) { 495 NavigationHandle* navigation_handle) {
482 if (navigation_handle == handle_) 496 if (navigation_handle == handle_)
483 num_did_redirect_navigation_called_++; 497 num_did_redirect_navigation_called_++;
484 } 498 }
485 499
486 void NavigationSimulator::ReadyToCommitNavigation( 500 void NavigationSimulator::ReadyToCommitNavigation(
487 NavigationHandle* navigation_handle) { 501 NavigationHandle* navigation_handle) {
(...skipping 12 matching lines...) Expand all
500 } 514 }
501 515
502 void NavigationSimulator::OnWillRedirectRequest() { 516 void NavigationSimulator::OnWillRedirectRequest() {
503 num_will_redirect_request_called_++; 517 num_will_redirect_request_called_++;
504 } 518 }
505 519
506 void NavigationSimulator::OnWillProcessResponse() { 520 void NavigationSimulator::OnWillProcessResponse() {
507 num_will_process_response_called_++; 521 num_will_process_response_called_++;
508 } 522 }
509 523
524 void NavigationSimulator::WaitForThrottleChecksComplete() {
525 // If last_throttle_check_result_ is set, then throttle checks completed
526 // synchronously.
527 if (last_throttle_check_result_)
528 return;
529
530 base::RunLoop run_loop;
531 throttle_checks_wait_closure_ = run_loop.QuitClosure();
532 run_loop.Run();
533 throttle_checks_wait_closure_.Reset();
534 }
535
536 void NavigationSimulator::OnThrottleChecksComplete(
537 NavigationThrottle::ThrottleCheckResult result) {
538 DCHECK(!last_throttle_check_result_);
539 last_throttle_check_result_ = result;
540 if (throttle_checks_wait_closure_)
541 throttle_checks_wait_closure_.Run();
542 }
543
544 void NavigationSimulator::PrepareCompleteCallbackOnHandle() {
545 last_throttle_check_result_.reset();
546 handle_->set_complete_callback_for_testing(
547 base::Bind(&NavigationSimulator::OnThrottleChecksComplete,
548 weak_factory_.GetWeakPtr()));
549 }
550
510 } // namespace content 551 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698