OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 <memory> | 5 #include <memory> |
6 #include <utility> | 6 #include <utility> |
7 | 7 |
8 #include "base/memory/ptr_util.h" | 8 #include "base/memory/ptr_util.h" |
9 #include "base/run_loop.h" | 9 #include "base/run_loop.h" |
10 #include "build/build_config.h" | 10 #include "build/build_config.h" |
(...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
379 | 379 |
380 // Behavior during blocked stages. During other stages, just | 380 // Behavior during blocked stages. During other stages, just |
381 // returns OK or NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION. | 381 // returns OK or NetworkDelegate::AUTH_REQUIRED_RESPONSE_NO_ACTION. |
382 enum BlockMode { | 382 enum BlockMode { |
383 SYNCHRONOUS, // No callback, returns specified return values. | 383 SYNCHRONOUS, // No callback, returns specified return values. |
384 AUTO_CALLBACK, // |this| posts a task to run the callback using the | 384 AUTO_CALLBACK, // |this| posts a task to run the callback using the |
385 // specified return codes. | 385 // specified return codes. |
386 USER_CALLBACK, // User takes care of doing a callback. |retval_| and | 386 USER_CALLBACK, // User takes care of doing a callback. |retval_| and |
387 // |auth_retval_| are ignored. In every blocking stage the | 387 // |auth_retval_| are ignored. In every blocking stage the |
388 // message loop is quit. | 388 // message loop is quit. |
| 389 USER_NOTIFY, // User is notified by a provided callback of the |
| 390 // blocking, and synchronously returns instructions |
| 391 // for handling it. |
389 }; | 392 }; |
390 | 393 |
| 394 using NotificationCallback = |
| 395 base::Callback<Error(const CompletionCallback&, const URLRequest*)>; |
| 396 |
| 397 using NotificationAuthCallback = |
| 398 base::Callback<NetworkDelegate::AuthRequiredResponse(const AuthCallback&, |
| 399 const URLRequest*)>; |
| 400 |
391 // Creates a delegate which does not block at all. | 401 // Creates a delegate which does not block at all. |
392 explicit BlockingNetworkDelegate(BlockMode block_mode); | 402 explicit BlockingNetworkDelegate(BlockMode block_mode); |
393 | 403 |
394 // For users to trigger a callback returning |response|. | 404 // For users to trigger a callback returning |response|. |
395 // Side-effects: resets |stage_blocked_for_callback_| and stored callbacks. | 405 // Side-effects: resets |stage_blocked_for_callback_| and stored callbacks. |
396 // Only call if |block_mode_| == USER_CALLBACK. | 406 // Only call if |block_mode_| == USER_CALLBACK. |
397 void DoCallback(int response); | 407 void DoCallback(int response); |
398 void DoAuthCallback(NetworkDelegate::AuthRequiredResponse response); | 408 void DoAuthCallback(NetworkDelegate::AuthRequiredResponse response); |
399 | 409 |
400 // Setters. | 410 // Setters. |
(...skipping 16 matching lines...) Expand all Loading... |
417 } | 427 } |
418 | 428 |
419 void set_redirect_url(const GURL& url) { | 429 void set_redirect_url(const GURL& url) { |
420 redirect_url_ = url; | 430 redirect_url_ = url; |
421 } | 431 } |
422 | 432 |
423 void set_block_on(int block_on) { | 433 void set_block_on(int block_on) { |
424 block_on_ = block_on; | 434 block_on_ = block_on; |
425 } | 435 } |
426 | 436 |
| 437 // Only valid if |block_mode_| == USER_NOTIFY |
| 438 void set_notification_callback( |
| 439 const NotificationCallback& notification_callback) { |
| 440 notification_callback_ = notification_callback; |
| 441 } |
| 442 |
| 443 void set_notification_auth_callback( |
| 444 const NotificationAuthCallback& notification_auth_callback) { |
| 445 notification_auth_callback_ = notification_auth_callback; |
| 446 } |
| 447 |
427 // Allows the user to check in which state did we block. | 448 // Allows the user to check in which state did we block. |
428 Stage stage_blocked_for_callback() const { | 449 Stage stage_blocked_for_callback() const { |
429 EXPECT_EQ(USER_CALLBACK, block_mode_); | 450 EXPECT_EQ(USER_CALLBACK, block_mode_); |
430 return stage_blocked_for_callback_; | 451 return stage_blocked_for_callback_; |
431 } | 452 } |
432 | 453 |
433 private: | 454 private: |
434 void RunCallback(int response, const CompletionCallback& callback); | 455 void RunCallback(int response, const CompletionCallback& callback); |
435 void RunAuthCallback(AuthRequiredResponse response, | 456 void RunAuthCallback(AuthRequiredResponse response, |
436 const AuthCallback& callback); | 457 const AuthCallback& callback); |
(...skipping 18 matching lines...) Expand all Loading... |
455 URLRequest* request, | 476 URLRequest* request, |
456 const AuthChallengeInfo& auth_info, | 477 const AuthChallengeInfo& auth_info, |
457 const AuthCallback& callback, | 478 const AuthCallback& callback, |
458 AuthCredentials* credentials) override; | 479 AuthCredentials* credentials) override; |
459 | 480 |
460 // Resets the callbacks and |stage_blocked_for_callback_|. | 481 // Resets the callbacks and |stage_blocked_for_callback_|. |
461 void Reset(); | 482 void Reset(); |
462 | 483 |
463 // Checks whether we should block in |stage|. If yes, returns an error code | 484 // Checks whether we should block in |stage|. If yes, returns an error code |
464 // and optionally sets up callback based on |block_mode_|. If no, returns OK. | 485 // and optionally sets up callback based on |block_mode_|. If no, returns OK. |
465 int MaybeBlockStage(Stage stage, const CompletionCallback& callback); | 486 int MaybeBlockStage(Stage stage, |
| 487 const URLRequest* request, |
| 488 const CompletionCallback& callback); |
466 | 489 |
467 // Configuration parameters, can be adjusted by public methods: | 490 // Configuration parameters, can be adjusted by public methods: |
468 const BlockMode block_mode_; | 491 const BlockMode block_mode_; |
469 | 492 |
470 // Values returned on blocking stages when mode is SYNCHRONOUS or | 493 // Values returned on blocking stages when mode is SYNCHRONOUS or |
471 // AUTO_CALLBACK. For USER_CALLBACK these are set automatically to IO_PENDING. | 494 // AUTO_CALLBACK. For USER_CALLBACK these are set automatically to IO_PENDING. |
472 int retval_; // To be returned in non-auth stages. | 495 int retval_; // To be returned in non-auth stages. |
473 AuthRequiredResponse auth_retval_; | 496 AuthRequiredResponse auth_retval_; |
474 | 497 |
475 GURL redirect_url_; // Used if non-empty during OnBeforeURLRequest. | 498 GURL redirect_url_; // Used if non-empty during OnBeforeURLRequest. |
476 int block_on_; // Bit mask: in which stages to block. | 499 int block_on_; // Bit mask: in which stages to block. |
477 | 500 |
478 // |auth_credentials_| will be copied to |*target_auth_credential_| on | 501 // |auth_credentials_| will be copied to |*target_auth_credential_| on |
479 // callback. | 502 // callback. |
480 AuthCredentials auth_credentials_; | 503 AuthCredentials auth_credentials_; |
481 AuthCredentials* target_auth_credentials_; | 504 AuthCredentials* target_auth_credentials_; |
482 | 505 |
483 // Internal variables, not set by not the user: | 506 // Internal variables, not set by not the user: |
484 // Last blocked stage waiting for user callback (unused if |block_mode_| != | 507 // Last blocked stage waiting for user callback (unused if |block_mode_| != |
485 // USER_CALLBACK). | 508 // USER_CALLBACK). |
486 Stage stage_blocked_for_callback_; | 509 Stage stage_blocked_for_callback_; |
487 | 510 |
488 // Callback objects stored during blocking stages. | 511 // Callback objects stored during blocking stages. |
489 CompletionCallback callback_; | 512 CompletionCallback callback_; |
490 AuthCallback auth_callback_; | 513 AuthCallback auth_callback_; |
491 | 514 |
| 515 // Callback to request user instructions for blocking. |
| 516 NotificationCallback notification_callback_; |
| 517 NotificationAuthCallback notification_auth_callback_; |
| 518 |
492 base::WeakPtrFactory<BlockingNetworkDelegate> weak_factory_; | 519 base::WeakPtrFactory<BlockingNetworkDelegate> weak_factory_; |
493 | 520 |
494 DISALLOW_COPY_AND_ASSIGN(BlockingNetworkDelegate); | 521 DISALLOW_COPY_AND_ASSIGN(BlockingNetworkDelegate); |
495 }; | 522 }; |
496 | 523 |
497 BlockingNetworkDelegate::BlockingNetworkDelegate(BlockMode block_mode) | 524 BlockingNetworkDelegate::BlockingNetworkDelegate(BlockMode block_mode) |
498 : block_mode_(block_mode), | 525 : block_mode_(block_mode), |
499 retval_(OK), | 526 retval_(OK), |
500 auth_retval_(AUTH_REQUIRED_RESPONSE_NO_ACTION), | 527 auth_retval_(AUTH_REQUIRED_RESPONSE_NO_ACTION), |
501 block_on_(0), | 528 block_on_(0), |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
541 const CompletionCallback& callback, | 568 const CompletionCallback& callback, |
542 GURL* new_url) { | 569 GURL* new_url) { |
543 if (redirect_url_ == request->url()) | 570 if (redirect_url_ == request->url()) |
544 return OK; // We've already seen this request and redirected elsewhere. | 571 return OK; // We've already seen this request and redirected elsewhere. |
545 | 572 |
546 TestNetworkDelegate::OnBeforeURLRequest(request, callback, new_url); | 573 TestNetworkDelegate::OnBeforeURLRequest(request, callback, new_url); |
547 | 574 |
548 if (!redirect_url_.is_empty()) | 575 if (!redirect_url_.is_empty()) |
549 *new_url = redirect_url_; | 576 *new_url = redirect_url_; |
550 | 577 |
551 return MaybeBlockStage(ON_BEFORE_URL_REQUEST, callback); | 578 return MaybeBlockStage(ON_BEFORE_URL_REQUEST, request, callback); |
552 } | 579 } |
553 | 580 |
554 int BlockingNetworkDelegate::OnBeforeStartTransaction( | 581 int BlockingNetworkDelegate::OnBeforeStartTransaction( |
555 URLRequest* request, | 582 URLRequest* request, |
556 const CompletionCallback& callback, | 583 const CompletionCallback& callback, |
557 HttpRequestHeaders* headers) { | 584 HttpRequestHeaders* headers) { |
558 TestNetworkDelegate::OnBeforeStartTransaction(request, callback, headers); | 585 TestNetworkDelegate::OnBeforeStartTransaction(request, callback, headers); |
559 | 586 |
560 return MaybeBlockStage(ON_BEFORE_SEND_HEADERS, callback); | 587 return MaybeBlockStage(ON_BEFORE_SEND_HEADERS, request, callback); |
561 } | 588 } |
562 | 589 |
563 int BlockingNetworkDelegate::OnHeadersReceived( | 590 int BlockingNetworkDelegate::OnHeadersReceived( |
564 URLRequest* request, | 591 URLRequest* request, |
565 const CompletionCallback& callback, | 592 const CompletionCallback& callback, |
566 const HttpResponseHeaders* original_response_headers, | 593 const HttpResponseHeaders* original_response_headers, |
567 scoped_refptr<HttpResponseHeaders>* override_response_headers, | 594 scoped_refptr<HttpResponseHeaders>* override_response_headers, |
568 GURL* allowed_unsafe_redirect_url) { | 595 GURL* allowed_unsafe_redirect_url) { |
569 TestNetworkDelegate::OnHeadersReceived(request, | 596 TestNetworkDelegate::OnHeadersReceived(request, |
570 callback, | 597 callback, |
571 original_response_headers, | 598 original_response_headers, |
572 override_response_headers, | 599 override_response_headers, |
573 allowed_unsafe_redirect_url); | 600 allowed_unsafe_redirect_url); |
574 | 601 |
575 return MaybeBlockStage(ON_HEADERS_RECEIVED, callback); | 602 return MaybeBlockStage(ON_HEADERS_RECEIVED, request, callback); |
576 } | 603 } |
577 | 604 |
578 NetworkDelegate::AuthRequiredResponse BlockingNetworkDelegate::OnAuthRequired( | 605 NetworkDelegate::AuthRequiredResponse BlockingNetworkDelegate::OnAuthRequired( |
579 URLRequest* request, | 606 URLRequest* request, |
580 const AuthChallengeInfo& auth_info, | 607 const AuthChallengeInfo& auth_info, |
581 const AuthCallback& callback, | 608 const AuthCallback& callback, |
582 AuthCredentials* credentials) { | 609 AuthCredentials* credentials) { |
583 TestNetworkDelegate::OnAuthRequired(request, auth_info, callback, | 610 TestNetworkDelegate::OnAuthRequired(request, auth_info, callback, |
584 credentials); | 611 credentials); |
585 // Check that the user has provided callback for the previous blocked stage. | 612 // Check that the user has provided callback for the previous blocked stage. |
(...skipping 17 matching lines...) Expand all Loading... |
603 base::Bind(&BlockingNetworkDelegate::RunAuthCallback, | 630 base::Bind(&BlockingNetworkDelegate::RunAuthCallback, |
604 weak_factory_.GetWeakPtr(), auth_retval_, callback)); | 631 weak_factory_.GetWeakPtr(), auth_retval_, callback)); |
605 return AUTH_REQUIRED_RESPONSE_IO_PENDING; | 632 return AUTH_REQUIRED_RESPONSE_IO_PENDING; |
606 | 633 |
607 case USER_CALLBACK: | 634 case USER_CALLBACK: |
608 auth_callback_ = callback; | 635 auth_callback_ = callback; |
609 stage_blocked_for_callback_ = ON_AUTH_REQUIRED; | 636 stage_blocked_for_callback_ = ON_AUTH_REQUIRED; |
610 base::ThreadTaskRunnerHandle::Get()->PostTask( | 637 base::ThreadTaskRunnerHandle::Get()->PostTask( |
611 FROM_HERE, base::MessageLoop::QuitWhenIdleClosure()); | 638 FROM_HERE, base::MessageLoop::QuitWhenIdleClosure()); |
612 return AUTH_REQUIRED_RESPONSE_IO_PENDING; | 639 return AUTH_REQUIRED_RESPONSE_IO_PENDING; |
| 640 |
| 641 case USER_NOTIFY: |
| 642 // If the callback returns ERR_IO_PENDING, the user has accepted |
| 643 // responsibility for running the callback in the future. |
| 644 return notification_auth_callback_.Run(callback, request); |
613 } | 645 } |
614 NOTREACHED(); | 646 NOTREACHED(); |
615 return AUTH_REQUIRED_RESPONSE_NO_ACTION; // Dummy value. | 647 return AUTH_REQUIRED_RESPONSE_NO_ACTION; // Dummy value. |
616 } | 648 } |
617 | 649 |
618 void BlockingNetworkDelegate::Reset() { | 650 void BlockingNetworkDelegate::Reset() { |
619 EXPECT_NE(NOT_BLOCKED, stage_blocked_for_callback_); | 651 EXPECT_NE(NOT_BLOCKED, stage_blocked_for_callback_); |
620 stage_blocked_for_callback_ = NOT_BLOCKED; | 652 stage_blocked_for_callback_ = NOT_BLOCKED; |
621 callback_.Reset(); | 653 callback_.Reset(); |
622 auth_callback_.Reset(); | 654 auth_callback_.Reset(); |
623 } | 655 } |
624 | 656 |
625 int BlockingNetworkDelegate::MaybeBlockStage( | 657 int BlockingNetworkDelegate::MaybeBlockStage( |
626 BlockingNetworkDelegate::Stage stage, | 658 BlockingNetworkDelegate::Stage stage, |
| 659 const URLRequest* request, |
627 const CompletionCallback& callback) { | 660 const CompletionCallback& callback) { |
628 // Check that the user has provided callback for the previous blocked stage. | 661 // Check that the user has provided callback for the previous blocked stage. |
629 EXPECT_EQ(NOT_BLOCKED, stage_blocked_for_callback_); | 662 EXPECT_EQ(NOT_BLOCKED, stage_blocked_for_callback_); |
630 | 663 |
631 if ((block_on_ & stage) == 0) { | 664 if ((block_on_ & stage) == 0) { |
632 return OK; | 665 return OK; |
633 } | 666 } |
634 | 667 |
635 switch (block_mode_) { | 668 switch (block_mode_) { |
636 case SYNCHRONOUS: | 669 case SYNCHRONOUS: |
637 EXPECT_NE(OK, retval_); | 670 EXPECT_NE(OK, retval_); |
638 return retval_; | 671 return retval_; |
639 | 672 |
640 case AUTO_CALLBACK: | 673 case AUTO_CALLBACK: |
641 base::ThreadTaskRunnerHandle::Get()->PostTask( | 674 base::ThreadTaskRunnerHandle::Get()->PostTask( |
642 FROM_HERE, base::Bind(&BlockingNetworkDelegate::RunCallback, | 675 FROM_HERE, base::Bind(&BlockingNetworkDelegate::RunCallback, |
643 weak_factory_.GetWeakPtr(), retval_, callback)); | 676 weak_factory_.GetWeakPtr(), retval_, callback)); |
644 return ERR_IO_PENDING; | 677 return ERR_IO_PENDING; |
645 | 678 |
646 case USER_CALLBACK: | 679 case USER_CALLBACK: |
647 callback_ = callback; | 680 callback_ = callback; |
648 stage_blocked_for_callback_ = stage; | 681 stage_blocked_for_callback_ = stage; |
649 base::ThreadTaskRunnerHandle::Get()->PostTask( | 682 base::ThreadTaskRunnerHandle::Get()->PostTask( |
650 FROM_HERE, base::MessageLoop::QuitWhenIdleClosure()); | 683 FROM_HERE, base::MessageLoop::QuitWhenIdleClosure()); |
651 return ERR_IO_PENDING; | 684 return ERR_IO_PENDING; |
| 685 |
| 686 case USER_NOTIFY: |
| 687 // If the callback returns ERR_IO_PENDING, the user has accepted |
| 688 // responsibility for running the callback in the future. |
| 689 return notification_callback_.Run(callback, request); |
652 } | 690 } |
653 NOTREACHED(); | 691 NOTREACHED(); |
654 return 0; | 692 return 0; |
655 } | 693 } |
656 | 694 |
657 class TestURLRequestContextWithProxy : public TestURLRequestContext { | 695 class TestURLRequestContextWithProxy : public TestURLRequestContext { |
658 public: | 696 public: |
659 // Does not own |delegate|. | 697 // Does not own |delegate|. |
660 TestURLRequestContextWithProxy(const std::string& proxy, | 698 TestURLRequestContextWithProxy(const std::string& proxy, |
661 NetworkDelegate* delegate) | 699 NetworkDelegate* delegate) |
(...skipping 7115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
7777 std::unique_ptr<URLRequest> req( | 7815 std::unique_ptr<URLRequest> req( |
7778 default_context_.CreateRequest(test_url, DEFAULT_PRIORITY, &d)); | 7816 default_context_.CreateRequest(test_url, DEFAULT_PRIORITY, &d)); |
7779 req->SetLoadFlags(LOAD_ONLY_FROM_CACHE); | 7817 req->SetLoadFlags(LOAD_ONLY_FROM_CACHE); |
7780 | 7818 |
7781 req->Start(); | 7819 req->Start(); |
7782 base::RunLoop().Run(); | 7820 base::RunLoop().Run(); |
7783 | 7821 |
7784 EXPECT_FALSE(req->response_info().network_accessed); | 7822 EXPECT_FALSE(req->response_info().network_accessed); |
7785 } | 7823 } |
7786 | 7824 |
7787 // Test that a single job with a throttled priority completes | 7825 // Test that a single job with a THROTTLED priority completes |
7788 // correctly in the absence of contention. | 7826 // correctly in the absence of contention. |
7789 TEST_F(URLRequestTestHTTP, ThrottledPriority) { | 7827 TEST_F(URLRequestTestHTTP, ThrottledPriority) { |
7790 ASSERT_TRUE(http_test_server()->Start()); | 7828 ASSERT_TRUE(http_test_server()->Start()); |
7791 | 7829 |
7792 TestDelegate d; | 7830 TestDelegate d; |
7793 GURL test_url(http_test_server()->GetURL("/")); | 7831 GURL test_url(http_test_server()->GetURL("/")); |
7794 std::unique_ptr<URLRequest> req( | 7832 std::unique_ptr<URLRequest> req( |
7795 default_context_.CreateRequest(test_url, THROTTLED, &d)); | 7833 default_context_.CreateRequest(test_url, THROTTLED, &d)); |
7796 req->Start(); | 7834 req->Start(); |
7797 base::RunLoop().Run(); | 7835 base::RunLoop().Run(); |
7798 | 7836 |
7799 EXPECT_TRUE(req->status().is_success()); | 7837 EXPECT_TRUE(req->status().is_success()); |
7800 } | 7838 } |
7801 | 7839 |
| 7840 // A class to hold state for responding to USER_NOTIFY callbacks from |
| 7841 // BlockingNetworkDelegate. It also accepts a RunLoop that will be |
| 7842 // signaled via QuitWhenIdle() when any request is blocked. |
| 7843 // |
| 7844 class NotificationCallbackHandler { |
| 7845 public: |
| 7846 // Default constructed object doesn't block anything. |
| 7847 NotificationCallbackHandler() : run_loop_(nullptr) {} |
| 7848 |
| 7849 void AddURLRequestToBlockList(const URLRequest* request) { |
| 7850 requests_to_block_.insert(request); |
| 7851 } |
| 7852 |
| 7853 Error ShouldBlockRequest(const CompletionCallback& callback, |
| 7854 const URLRequest* request) { |
| 7855 if (requests_to_block_.find(request) == requests_to_block_.end()) { |
| 7856 return OK; |
| 7857 } |
| 7858 |
| 7859 DCHECK(blocked_callbacks_.find(request) == blocked_callbacks_.end()); |
| 7860 blocked_callbacks_[request] = callback; |
| 7861 if (run_loop_) |
| 7862 run_loop_->QuitWhenIdle(); |
| 7863 return ERR_IO_PENDING; |
| 7864 } |
| 7865 |
| 7866 // Erases object's memory of blocked callbacks as a side effect. |
| 7867 void GetBlockedCallbacks( |
| 7868 std::map<const URLRequest*, CompletionCallback>* blocked_callbacks) { |
| 7869 blocked_callbacks_.swap(*blocked_callbacks); |
| 7870 } |
| 7871 |
| 7872 // Set a RunLoop that, if non-null, will be signaled if any request |
| 7873 // is blocked. It is the callers responsibility to make sure the |
| 7874 // passed object lives past the destruction of this class or |
| 7875 // next call to SetRunLoop(). |
| 7876 void SetRunLoop(base::RunLoop* run_loop) { run_loop_ = run_loop; } |
| 7877 |
| 7878 private: |
| 7879 std::set<const URLRequest*> requests_to_block_; |
| 7880 std::map<const URLRequest*, CompletionCallback> blocked_callbacks_; |
| 7881 |
| 7882 base::RunLoop* run_loop_; |
| 7883 |
| 7884 DISALLOW_COPY_AND_ASSIGN(NotificationCallbackHandler); |
| 7885 }; |
| 7886 |
| 7887 TEST_F(URLRequestTestHTTP, MultiThrottledPriority) { |
| 7888 ASSERT_TRUE(http_test_server()->Start()); |
| 7889 |
| 7890 base::RunLoop run_until_request_blocked; |
| 7891 |
| 7892 NotificationCallbackHandler notification_handler; |
| 7893 notification_handler.SetRunLoop(&run_until_request_blocked); |
| 7894 BlockingNetworkDelegate network_delegate( |
| 7895 BlockingNetworkDelegate::USER_NOTIFY); |
| 7896 network_delegate.set_block_on(BlockingNetworkDelegate::ON_HEADERS_RECEIVED); |
| 7897 network_delegate.set_notification_callback( |
| 7898 base::Bind(&NotificationCallbackHandler::ShouldBlockRequest, |
| 7899 // Both objects are owned by this function, and |
| 7900 // |*network_delegate| will be destroyed first, so |
| 7901 // it's safe to pass it an unretained pointer. |
| 7902 base::Unretained(¬ification_handler))); |
| 7903 |
| 7904 TestURLRequestContext context(true); |
| 7905 context.set_network_delegate(&network_delegate); |
| 7906 context.Init(); |
| 7907 |
| 7908 // Use different test URLs to make sure all three requests turn into |
| 7909 // HttpNetworkTransacations. Use different URLRequest::Delegates so that |
| 7910 // the requests may be waited on separately. |
| 7911 TestDelegate d1; |
| 7912 std::unique_ptr<URLRequest> req1(context.CreateRequest( |
| 7913 http_test_server()->GetURL("/echoall/l"), THROTTLED, &d1)); |
| 7914 notification_handler.AddURLRequestToBlockList(req1.get()); |
| 7915 |
| 7916 TestDelegate d2; |
| 7917 std::unique_ptr<URLRequest> req2(context.CreateRequest( |
| 7918 http_test_server()->GetURL("/echoall/2"), THROTTLED, &d2)); |
| 7919 notification_handler.AddURLRequestToBlockList(req2.get()); |
| 7920 |
| 7921 TestDelegate d3; |
| 7922 std::unique_ptr<URLRequest> req3(context.CreateRequest( |
| 7923 http_test_server()->GetURL("/echoall/3"), THROTTLED, &d3)); |
| 7924 req1->Start(); |
| 7925 req2->Start(); |
| 7926 req3->Start(); |
| 7927 run_until_request_blocked.Run(); |
| 7928 notification_handler.SetRunLoop(nullptr); |
| 7929 |
| 7930 // The first two requests should be blocked based on the notification |
| 7931 // callback, and their status should have blocked the third request |
| 7932 // through throttling. |
| 7933 EXPECT_TRUE(req1->status().is_io_pending()); |
| 7934 EXPECT_TRUE(req2->status().is_io_pending()); |
| 7935 EXPECT_TRUE(req3->status().is_io_pending()); |
| 7936 |
| 7937 std::map<const URLRequest*, CompletionCallback> blocked_callbacks; |
| 7938 notification_handler.GetBlockedCallbacks(&blocked_callbacks); |
| 7939 ASSERT_EQ(2u, blocked_callbacks.size()); |
| 7940 ASSERT_TRUE(blocked_callbacks.find(req1.get()) != blocked_callbacks.end()); |
| 7941 ASSERT_TRUE(blocked_callbacks.find(req2.get()) != blocked_callbacks.end()); |
| 7942 |
| 7943 // Unblocking one of the requests blocked on the notification callback |
| 7944 // should let it complete, which should then let the third request |
| 7945 // complete. Unblock the second request, then wait for the third |
| 7946 // request to complete. |
| 7947 // TODO(rdsmith): Find something to wait on other than the third |
| 7948 // requests completion; if there's a bug in throttling, that will |
| 7949 // result in this test hanging rather than failing quickly. |
| 7950 d1.set_quit_on_complete(false); |
| 7951 d2.set_quit_on_complete(false); |
| 7952 d3.set_quit_on_complete(true); |
| 7953 blocked_callbacks[req2.get()].Run(OK); |
| 7954 base::RunLoop().Run(); |
| 7955 |
| 7956 notification_handler.GetBlockedCallbacks(&blocked_callbacks); |
| 7957 EXPECT_EQ(0u, blocked_callbacks.size()); |
| 7958 EXPECT_TRUE(req1->status().is_io_pending()); |
| 7959 // req3 is only unblocked after req2 completes, so req2's |
| 7960 // success is guaranteed at this point in the function. |
| 7961 EXPECT_EQ(URLRequestStatus::SUCCESS, req2->status().status()); |
| 7962 EXPECT_EQ(URLRequestStatus::SUCCESS, req3->status().status()); |
| 7963 } |
| 7964 |
| 7965 // Confirm that failing a request unblocks following requests. |
| 7966 TEST_F(URLRequestTestHTTP, ThrottledFailure) { |
| 7967 ASSERT_TRUE(http_test_server()->Start()); |
| 7968 |
| 7969 base::RunLoop run_until_request_blocked; |
| 7970 |
| 7971 NotificationCallbackHandler notification_handler; |
| 7972 notification_handler.SetRunLoop(&run_until_request_blocked); |
| 7973 BlockingNetworkDelegate network_delegate( |
| 7974 BlockingNetworkDelegate::USER_NOTIFY); |
| 7975 network_delegate.set_block_on(BlockingNetworkDelegate::ON_HEADERS_RECEIVED); |
| 7976 network_delegate.set_notification_callback( |
| 7977 base::Bind(&NotificationCallbackHandler::ShouldBlockRequest, |
| 7978 // Both objects are owned by this function, and |
| 7979 // |*network_delegate| will be destroyed first, so |
| 7980 // it's safe to pass it an unretained pointer. |
| 7981 base::Unretained(¬ification_handler))); |
| 7982 |
| 7983 TestURLRequestContext context(true); |
| 7984 context.set_network_delegate(&network_delegate); |
| 7985 context.Init(); |
| 7986 |
| 7987 // Use different test URLs to make sure all three requests turn into |
| 7988 // HttpNetworkTransacations. Use different URLRequest::Delegates so that |
| 7989 // the requests may be waited on separately. |
| 7990 TestDelegate d1; |
| 7991 std::unique_ptr<URLRequest> req1(context.CreateRequest( |
| 7992 http_test_server()->GetURL("/echoall/l"), THROTTLED, &d1)); |
| 7993 notification_handler.AddURLRequestToBlockList(req1.get()); |
| 7994 |
| 7995 TestDelegate d2; |
| 7996 std::unique_ptr<URLRequest> req2(context.CreateRequest( |
| 7997 http_test_server()->GetURL("/echoall/2"), THROTTLED, &d2)); |
| 7998 notification_handler.AddURLRequestToBlockList(req2.get()); |
| 7999 |
| 8000 TestDelegate d3; |
| 8001 std::unique_ptr<URLRequest> req3(context.CreateRequest( |
| 8002 http_test_server()->GetURL("/echoall/3"), THROTTLED, &d3)); |
| 8003 req1->Start(); |
| 8004 req2->Start(); |
| 8005 req3->Start(); |
| 8006 run_until_request_blocked.Run(); |
| 8007 notification_handler.SetRunLoop(nullptr); |
| 8008 |
| 8009 // The first two requests should be blocked based on the notification |
| 8010 // callback, and their status should have blocked the third request |
| 8011 // through throttling. |
| 8012 EXPECT_TRUE(req1->status().is_io_pending()); |
| 8013 EXPECT_TRUE(req2->status().is_io_pending()); |
| 8014 EXPECT_TRUE(req3->status().is_io_pending()); |
| 8015 |
| 8016 std::map<const URLRequest*, CompletionCallback> blocked_callbacks; |
| 8017 notification_handler.GetBlockedCallbacks(&blocked_callbacks); |
| 8018 ASSERT_EQ(2u, blocked_callbacks.size()); |
| 8019 ASSERT_TRUE(blocked_callbacks.find(req1.get()) != blocked_callbacks.end()); |
| 8020 ASSERT_TRUE(blocked_callbacks.find(req2.get()) != blocked_callbacks.end()); |
| 8021 |
| 8022 // Confirm canceling one of the outstanding requests allows the |
| 8023 // blocked request to complete. |
| 8024 |
| 8025 // TODO(rdsmith): Find something to wait on other than the third |
| 8026 // requests completion; if there's a bug in throttling, that will |
| 8027 // result in this test hanging rather than failing quickly. |
| 8028 d1.set_quit_on_complete(false); |
| 8029 d2.set_quit_on_complete(false); |
| 8030 d3.set_quit_on_complete(true); |
| 8031 req2->Cancel(); |
| 8032 base::RunLoop().Run(); |
| 8033 |
| 8034 notification_handler.GetBlockedCallbacks(&blocked_callbacks); |
| 8035 EXPECT_EQ(0u, blocked_callbacks.size()); |
| 8036 EXPECT_TRUE(req1->status().is_io_pending()); |
| 8037 EXPECT_EQ(URLRequestStatus::CANCELED, req2->status().status()); |
| 8038 EXPECT_EQ(URLRequestStatus::SUCCESS, req3->status().status()); |
| 8039 } |
| 8040 |
| 8041 TEST_F(URLRequestTestHTTP, ThrottledRepriUnblock) { |
| 8042 ASSERT_TRUE(http_test_server()->Start()); |
| 8043 |
| 8044 base::RunLoop run_until_request_blocked; |
| 8045 |
| 8046 NotificationCallbackHandler notification_handler; |
| 8047 notification_handler.SetRunLoop(&run_until_request_blocked); |
| 8048 BlockingNetworkDelegate network_delegate( |
| 8049 BlockingNetworkDelegate::USER_NOTIFY); |
| 8050 network_delegate.set_block_on(BlockingNetworkDelegate::ON_HEADERS_RECEIVED); |
| 8051 network_delegate.set_notification_callback( |
| 8052 base::Bind(&NotificationCallbackHandler::ShouldBlockRequest, |
| 8053 // Both objects are owned by this function, and |
| 8054 // |*network_delegate| will be destroyed first, so |
| 8055 // it's safe to pass it an unretained pointer. |
| 8056 base::Unretained(¬ification_handler))); |
| 8057 |
| 8058 TestURLRequestContext context(true); |
| 8059 context.set_network_delegate(&network_delegate); |
| 8060 context.Init(); |
| 8061 |
| 8062 // Use different test URLs to make sure all three requests turn into |
| 8063 // HttpNetworkTransacations. Use different URLRequest::Delegates so that |
| 8064 // the requests may be waited on separately. |
| 8065 TestDelegate d1; |
| 8066 std::unique_ptr<URLRequest> req1(context.CreateRequest( |
| 8067 http_test_server()->GetURL("/echoall/l"), THROTTLED, &d1)); |
| 8068 notification_handler.AddURLRequestToBlockList(req1.get()); |
| 8069 |
| 8070 TestDelegate d2; |
| 8071 std::unique_ptr<URLRequest> req2(context.CreateRequest( |
| 8072 http_test_server()->GetURL("/echoall/2"), THROTTLED, &d2)); |
| 8073 notification_handler.AddURLRequestToBlockList(req2.get()); |
| 8074 |
| 8075 TestDelegate d3; |
| 8076 std::unique_ptr<URLRequest> req3(context.CreateRequest( |
| 8077 http_test_server()->GetURL("/echoall/3"), THROTTLED, &d3)); |
| 8078 req1->Start(); |
| 8079 req2->Start(); |
| 8080 req3->Start(); |
| 8081 run_until_request_blocked.Run(); |
| 8082 notification_handler.SetRunLoop(nullptr); |
| 8083 |
| 8084 // The first two requests should be blocked based on the notification |
| 8085 // callback, and their status should have blocked the third request |
| 8086 // through throttling. |
| 8087 EXPECT_TRUE(req1->status().is_io_pending()); |
| 8088 EXPECT_TRUE(req2->status().is_io_pending()); |
| 8089 EXPECT_TRUE(req3->status().is_io_pending()); |
| 8090 |
| 8091 std::map<const URLRequest*, CompletionCallback> blocked_callbacks; |
| 8092 notification_handler.GetBlockedCallbacks(&blocked_callbacks); |
| 8093 ASSERT_EQ(2u, blocked_callbacks.size()); |
| 8094 ASSERT_TRUE(blocked_callbacks.find(req1.get()) != blocked_callbacks.end()); |
| 8095 ASSERT_TRUE(blocked_callbacks.find(req2.get()) != blocked_callbacks.end()); |
| 8096 |
| 8097 // Confirm raising the priority of the third request allows it to complete. |
| 8098 |
| 8099 // TODO(rdsmith): Find something to wait on other than the third |
| 8100 // requests completion; if there's a bug in throttling, that will |
| 8101 // result in this test hanging rather than failing quickly. |
| 8102 d1.set_quit_on_complete(false); |
| 8103 d2.set_quit_on_complete(false); |
| 8104 d3.set_quit_on_complete(true); |
| 8105 req3->SetPriority(IDLE); |
| 8106 base::RunLoop().Run(); |
| 8107 |
| 8108 notification_handler.GetBlockedCallbacks(&blocked_callbacks); |
| 8109 EXPECT_EQ(0u, blocked_callbacks.size()); |
| 8110 EXPECT_TRUE(req1->status().is_io_pending()); |
| 8111 EXPECT_TRUE(req2->status().is_io_pending()); |
| 8112 EXPECT_EQ(URLRequestStatus::SUCCESS, req3->status().status()); |
| 8113 } |
| 8114 |
7802 TEST_F(URLRequestTestHTTP, RawBodyBytesNoContentEncoding) { | 8115 TEST_F(URLRequestTestHTTP, RawBodyBytesNoContentEncoding) { |
7803 ASSERT_TRUE(http_test_server()->Start()); | 8116 ASSERT_TRUE(http_test_server()->Start()); |
7804 | 8117 |
7805 TestDelegate d; | 8118 TestDelegate d; |
7806 std::unique_ptr<URLRequest> req(default_context().CreateRequest( | 8119 std::unique_ptr<URLRequest> req(default_context().CreateRequest( |
7807 http_test_server()->GetURL("/simple.html"), DEFAULT_PRIORITY, &d)); | 8120 http_test_server()->GetURL("/simple.html"), DEFAULT_PRIORITY, &d)); |
7808 req->Start(); | 8121 req->Start(); |
7809 base::RunLoop().Run(); | 8122 base::RunLoop().Run(); |
7810 | 8123 |
7811 EXPECT_EQ(5, req->GetRawBodyBytes()); | 8124 EXPECT_EQ(5, req->GetRawBodyBytes()); |
(...skipping 2395 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10207 AddTestInterceptor()->set_main_intercept_job(std::move(job)); | 10520 AddTestInterceptor()->set_main_intercept_job(std::move(job)); |
10208 | 10521 |
10209 req->Start(); | 10522 req->Start(); |
10210 req->Cancel(); | 10523 req->Cancel(); |
10211 base::RunLoop().RunUntilIdle(); | 10524 base::RunLoop().RunUntilIdle(); |
10212 EXPECT_EQ(ERR_ABORTED, d.request_status()); | 10525 EXPECT_EQ(ERR_ABORTED, d.request_status()); |
10213 EXPECT_EQ(0, d.received_redirect_count()); | 10526 EXPECT_EQ(0, d.received_redirect_count()); |
10214 } | 10527 } |
10215 | 10528 |
10216 } // namespace net | 10529 } // namespace net |
OLD | NEW |