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