| Index: chrome/browser/renderer_host/intercept_navigation_resource_throttle_unittest.cc | 
| diff --git a/chrome/browser/renderer_host/intercept_navigation_resource_throttle_unittest.cc b/chrome/browser/renderer_host/intercept_navigation_resource_throttle_unittest.cc | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..caaea2563133da3aee97dd362ccaa9c7b4f10a60 | 
| --- /dev/null | 
| +++ b/chrome/browser/renderer_host/intercept_navigation_resource_throttle_unittest.cc | 
| @@ -0,0 +1,255 @@ | 
| +// Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
| +// Use of this source code is governed by a BSD-style license that can be | 
| +// found in the LICENSE file. | 
| + | 
| +#include "base/bind.h" | 
| +#include "base/bind_helpers.h" | 
| +#include "base/memory/scoped_ptr.h" | 
| +#include "base/memory/scoped_vector.h" | 
| +#include "chrome/browser/renderer_host/intercept_navigation_resource_throttle.h" | 
| +#include "chrome/test/base/chrome_render_view_host_test_harness.h" | 
| +#include "content/public/browser/render_process_host.h" | 
| +#include "content/public/browser/resource_context.h" | 
| +#include "content/public/browser/resource_dispatcher_host.h" | 
| +#include "content/public/browser/resource_dispatcher_host_delegate.h" | 
| +#include "content/public/browser/resource_request_info.h" | 
| +#include "content/public/browser/resource_throttle.h" | 
| +#include "content/public/browser/resource_throttle_controller.h" | 
| +#include "content/public/browser/web_contents.h" | 
| +#include "content/public/browser/web_contents_delegate.h" | 
| +#include "content/test/mock_resource_context.h" | 
| +#include "content/test/test_browser_thread.h" | 
| +#include "net/url_request/url_request.h" | 
| +#include "testing/gmock/include/gmock/gmock.h" | 
| +#include "testing/gtest/include/gtest/gtest.h" | 
| + | 
| +using namespace content; | 
| +using namespace ::testing; | 
| + | 
| +namespace { | 
| + | 
| +const char* kTestUrl = "http://www.test.com/"; | 
| + | 
| +void ContinueTestCase() { | 
| +  BrowserThread::PostTask( | 
| +      BrowserThread::UI, | 
| +      FROM_HERE, | 
| +      MessageLoop::QuitClosure()); | 
| +} | 
| + | 
| +} // namespace | 
| + | 
| +// MockWebContentsDelegate ---------------------------------------------------- | 
| + | 
| +class MockWebContentsDelegate : public content::WebContentsDelegate { | 
| + public: | 
| +  MOCK_METHOD4(ShouldIgnoreNavigation, bool(WebContents* source, | 
| +                                            const GURL& url, | 
| +                                            const content::Referrer& referrer, | 
| +                                            bool is_content_initiated)); | 
| +}; | 
| + | 
| +// MockResourceThrottleController | 
| +class MockResourceThrottleController | 
| +    : public content::ResourceThrottleController { | 
| + public: | 
| +  enum Status { | 
| +    UNKNOWN, | 
| +    RESUMED, | 
| +    CANCELLED | 
| +  }; | 
| + | 
| +  MockResourceThrottleController() | 
| +      : status_(UNKNOWN) { | 
| +  } | 
| + | 
| +  Status status() const { return status_; } | 
| + | 
| +  // content::ResourceThrottleController | 
| +  virtual void Cancel() { | 
| +    NOTREACHED(); | 
| +  } | 
| +  virtual void Resume() { | 
| +    DCHECK(status_ == UNKNOWN); | 
| +    status_ = RESUMED; | 
| +    ContinueTestCase(); | 
| +  } | 
| +  virtual void CancelWithHandledExternallyStatus() { | 
| +    DCHECK(status_ == UNKNOWN); | 
| +    status_ = CANCELLED; | 
| +    ContinueTestCase(); | 
| +  } | 
| + | 
| + private: | 
| +  Status status_; | 
| +}; | 
| + | 
| +// TestIOThreadState ---------------------------------------------------------- | 
| + | 
| +class TestIOThreadState { | 
| + public: | 
| +  TestIOThreadState(int render_process_id, int render_view_id) | 
| +      : request_(GURL(kTestUrl), NULL), | 
| +        throttle_(&request_) { | 
| +      DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 
| +      if (render_process_id != MSG_ROUTING_NONE && | 
| +          render_view_id != MSG_ROUTING_NONE) { | 
| +        ResourceRequestInfo::AllocateForTesting(&request_, | 
| +                                                ResourceType::MAIN_FRAME, | 
| +                                                &resource_context_, | 
| +                                                render_process_id, | 
| +                                                render_view_id); | 
| +      } | 
| +      throttle_.set_controller_for_testing(&throttle_controller_); | 
| +  } | 
| + | 
| +  void ThrottleWillStartRequest(bool* defer) { | 
| +    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 
| +    throttle_.WillStartRequest(defer); | 
| +  } | 
| + | 
| +  bool request_resumed() const { | 
| +    return throttle_controller_.status() == | 
| +        MockResourceThrottleController::RESUMED; | 
| +  } | 
| + | 
| +  bool request_cancelled() const { | 
| +    return throttle_controller_.status() == | 
| +        MockResourceThrottleController::CANCELLED; | 
| +  } | 
| + | 
| + private: | 
| +  content::MockResourceContext resource_context_; | 
| +  net::URLRequest request_; | 
| +  InterceptNavigationResourceThrottle throttle_; | 
| +  MockResourceThrottleController throttle_controller_; | 
| +}; | 
| + | 
| +// InterceptNavigationResourceThrottleTest ------------------------------------ | 
| + | 
| +class InterceptNavigationResourceThrottleTest | 
| +  : public ChromeRenderViewHostTestHarness { | 
| + public: | 
| +  InterceptNavigationResourceThrottleTest() | 
| +      : ui_thread_(BrowserThread::UI, &message_loop_), | 
| +        io_thread_(BrowserThread::IO), | 
| +        io_thread_state_(NULL) { | 
| +  } | 
| + | 
| +  virtual void SetUp() OVERRIDE { | 
| +    ChromeRenderViewHostTestHarness::SetUp(); | 
| + | 
| +    io_thread_.StartIOThread(); | 
| +  } | 
| + | 
| +  virtual void TearDown() OVERRIDE { | 
| +    web_contents()->SetDelegate(NULL); | 
| +    BrowserThread::PostTask( | 
| +        BrowserThread::IO, | 
| +        FROM_HERE, | 
| +        base::Bind(&base::DeletePointer<TestIOThreadState>, io_thread_state_)); | 
| + | 
| +    ChromeRenderViewHostTestHarness::TearDown(); | 
| +  } | 
| + | 
| +  void SetIOThreadState(TestIOThreadState* io_thread_state) { | 
| +    io_thread_state_ = io_thread_state; | 
| +  } | 
| + | 
| +  void RunThrottleWillStartRequestOnIOThread( | 
| +      int render_process_id, | 
| +      int render_view_id, | 
| +      bool* defer) { | 
| +    DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 
| +    TestIOThreadState* io_thread_state = | 
| +        new TestIOThreadState(render_process_id, render_view_id); | 
| + | 
| +    SetIOThreadState(io_thread_state); | 
| +    io_thread_state->ThrottleWillStartRequest(defer); | 
| + | 
| +    if (!*defer) { | 
| +      ContinueTestCase(); | 
| +    } | 
| +  } | 
| + | 
| + protected: | 
| +  enum ShouldIgnoreNavigationCallbackAction { | 
| +    IgnoreNavigation, | 
| +    DontIgnoreNavigation | 
| +  }; | 
| + | 
| +  void SetUpWebContentsDelegateAndRunMessageLoop( | 
| +      ShouldIgnoreNavigationCallbackAction callback_action, | 
| +      bool* defer) { | 
| +    scoped_ptr<MockWebContentsDelegate> web_contents_delegate( | 
| +        new MockWebContentsDelegate()); | 
| +    EXPECT_FALSE(web_contents()->GetDelegate()); | 
| +    web_contents()->SetDelegate(web_contents_delegate.get()); | 
| + | 
| +    ON_CALL(*web_contents_delegate, | 
| +            ShouldIgnoreNavigation(_, Eq(GURL(kTestUrl)), _, _)) | 
| +      .WillByDefault(Return(callback_action == IgnoreNavigation)); | 
| +    EXPECT_CALL(*web_contents_delegate, | 
| +                ShouldIgnoreNavigation(_, Eq(GURL(kTestUrl)), _, _)) | 
| +      .Times(1); | 
| + | 
| +    BrowserThread::PostTask( | 
| +        BrowserThread::IO, | 
| +        FROM_HERE, | 
| +        base::Bind( | 
| +            &InterceptNavigationResourceThrottleTest:: | 
| +                RunThrottleWillStartRequestOnIOThread, | 
| +            base::Unretained(this), | 
| +            contents()->GetRenderViewHost()->GetProcess()->GetID(), | 
| +            contents()->GetRenderViewHost()->GetRoutingID(), | 
| +            base::Unretained(defer))); | 
| + | 
| +    // Wait for the request to finish processing. | 
| +    message_loop_.Run(); | 
| +  } | 
| + | 
| +  content::TestBrowserThread ui_thread_; | 
| +  content::TestBrowserThread io_thread_; | 
| +  TestIOThreadState* io_thread_state_; | 
| +}; | 
| + | 
| +TEST_F(InterceptNavigationResourceThrottleTest, | 
| +       RequestDeferredAndResumedIfNavigationNotIgnored) { | 
| +  bool defer = false; | 
| +  SetUpWebContentsDelegateAndRunMessageLoop(DontIgnoreNavigation, &defer); | 
| + | 
| +  EXPECT_TRUE(defer); | 
| +  EXPECT_TRUE(io_thread_state_); | 
| +  EXPECT_TRUE(io_thread_state_->request_resumed()); | 
| +} | 
| + | 
| +TEST_F(InterceptNavigationResourceThrottleTest, | 
| +       RequestDeferredAndCancelledIfNavigationIgnored) { | 
| +  bool defer = false; | 
| +  SetUpWebContentsDelegateAndRunMessageLoop(IgnoreNavigation, &defer); | 
| + | 
| +  EXPECT_TRUE(defer); | 
| +  EXPECT_TRUE(io_thread_state_); | 
| +  EXPECT_TRUE(io_thread_state_->request_cancelled()); | 
| +} | 
| + | 
| +TEST_F(InterceptNavigationResourceThrottleTest, | 
| +       RequestNotDeferredForRequestNotAssociatedWithARenderView) { | 
| +  bool defer = false; | 
| + | 
| +  BrowserThread::PostTask( | 
| +      BrowserThread::IO, | 
| +      FROM_HERE, | 
| +      base::Bind( | 
| +          &InterceptNavigationResourceThrottleTest:: | 
| +              RunThrottleWillStartRequestOnIOThread, | 
| +          base::Unretained(this), | 
| +          MSG_ROUTING_NONE, | 
| +          MSG_ROUTING_NONE, | 
| +          base::Unretained(&defer))); | 
| + | 
| +  // Wait for the request to finish processing. | 
| +  message_loop_.Run(); | 
| + | 
| +  EXPECT_FALSE(defer); | 
| +} | 
|  |