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