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

Unified Diff: components/navigation_interception/intercept_navigation_resource_throttle_unittest.cc

Issue 1350913008: Revert of Add a NavigationThrottle to the public content/ interface (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@navigation-api
Patch Set: Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: components/navigation_interception/intercept_navigation_resource_throttle_unittest.cc
diff --git a/components/navigation_interception/intercept_navigation_resource_throttle_unittest.cc b/components/navigation_interception/intercept_navigation_resource_throttle_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..8855f4248f7ad6bf26893932ffb49441f7de77bc
--- /dev/null
+++ b/components/navigation_interception/intercept_navigation_resource_throttle_unittest.cc
@@ -0,0 +1,481 @@
+// 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/run_loop.h"
+#include "base/synchronization/waitable_event.h"
+#include "components/navigation_interception/intercept_navigation_resource_throttle.h"
+#include "components/navigation_interception/navigation_params.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/resource_context.h"
+#include "content/public/browser/resource_controller.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/web_contents.h"
+#include "content/public/browser/web_contents_delegate.h"
+#include "content/public/test/mock_resource_context.h"
+#include "content/public/test/test_renderer_host.h"
+#include "net/base/request_priority.h"
+#include "net/http/http_response_headers.h"
+#include "net/http/http_response_info.h"
+#include "net/url_request/redirect_info.h"
+#include "net/url_request/url_request.h"
+#include "net/url_request/url_request_test_util.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+using content::ResourceType;
+using testing::_;
+using testing::Eq;
+using testing::Ne;
+using testing::Property;
+using testing::Return;
+
+namespace navigation_interception {
+
+namespace {
+
+const char kTestUrl[] = "http://www.test.com/";
+const char kUnsafeTestUrl[] = "about:crash";
+
+// The MS C++ compiler complains about not being able to resolve which url()
+// method (const or non-const) to use if we use the Property matcher to check
+// the return value of the NavigationParams::url() method.
+// It is possible to suppress the error by specifying the types directly but
+// that results in very ugly syntax, which is why these custom matchers are
+// used instead.
+MATCHER(NavigationParamsUrlIsTest, "") {
+ return arg.url() == GURL(kTestUrl);
+}
+
+MATCHER(NavigationParamsUrlIsSafe, "") {
+ return arg.url() != GURL(kUnsafeTestUrl);
+}
+
+} // namespace
+
+
+// MockInterceptCallbackReceiver ----------------------------------------------
+
+class MockInterceptCallbackReceiver {
+ public:
+ MOCK_METHOD2(ShouldIgnoreNavigation,
+ bool(content::WebContents* source,
+ const NavigationParams& navigation_params));
+};
+
+// MockResourceController -----------------------------------------------------
+class MockResourceController : public content::ResourceController {
+ public:
+ enum Status {
+ UNKNOWN,
+ RESUMED,
+ CANCELLED
+ };
+
+ MockResourceController()
+ : status_(UNKNOWN) {
+ }
+
+ Status status() const { return status_; }
+
+ // ResourceController:
+ void Cancel() override { NOTREACHED(); }
+ void CancelAndIgnore() override { status_ = CANCELLED; }
+ void CancelWithError(int error_code) override { NOTREACHED(); }
+ void Resume() override {
+ DCHECK(status_ == UNKNOWN);
+ status_ = RESUMED;
+ }
+
+ private:
+ Status status_;
+};
+
+// TestIOThreadState ----------------------------------------------------------
+
+enum RedirectMode {
+ REDIRECT_MODE_NO_REDIRECT,
+ REDIRECT_MODE_302,
+};
+
+class TestIOThreadState {
+ public:
+ TestIOThreadState(const GURL& url,
+ int render_process_id,
+ int render_frame_id,
+ const std::string& request_method,
+ RedirectMode redirect_mode,
+ MockInterceptCallbackReceiver* callback_receiver)
+ : resource_context_(&test_url_request_context_),
+ request_(resource_context_.GetRequestContext()->CreateRequest(
+ url,
+ net::DEFAULT_PRIORITY,
+ NULL /* delegate */)) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ if (render_process_id != MSG_ROUTING_NONE &&
+ render_frame_id != MSG_ROUTING_NONE) {
+ content::ResourceRequestInfo::AllocateForTesting(
+ request_.get(),
+ content::RESOURCE_TYPE_MAIN_FRAME,
+ &resource_context_,
+ render_process_id,
+ MSG_ROUTING_NONE,
+ render_frame_id,
+ true, // is_main_frame
+ false, // parent_is_main_frame
+ true, // allow_download
+ false); // is_async
+ }
+ throttle_.reset(new InterceptNavigationResourceThrottle(
+ request_.get(),
+ base::Bind(&MockInterceptCallbackReceiver::ShouldIgnoreNavigation,
+ base::Unretained(callback_receiver))));
+ throttle_->set_controller_for_testing(&throttle_controller_);
+ request_->set_method(request_method);
+
+ if (redirect_mode == REDIRECT_MODE_302) {
+ net::HttpResponseInfo& response_info =
+ const_cast<net::HttpResponseInfo&>(request_->response_info());
+ response_info.headers = new net::HttpResponseHeaders(
+ "Status: 302 Found\0\0");
+ }
+ }
+
+ void ThrottleWillStartRequest(bool* defer) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ throttle_->WillStartRequest(defer);
+ }
+
+ void ThrottleWillRedirectRequest(const net::RedirectInfo& redirect_info,
+ bool* defer) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ throttle_->WillRedirectRequest(redirect_info, defer);
+ }
+
+ bool request_resumed() const {
+ return throttle_controller_.status() ==
+ MockResourceController::RESUMED;
+ }
+
+ bool request_cancelled() const {
+ return throttle_controller_.status() ==
+ MockResourceController::CANCELLED;
+ }
+
+ private:
+ net::TestURLRequestContext test_url_request_context_;
+ content::MockResourceContext resource_context_;
+ scoped_ptr<net::URLRequest> request_;
+ scoped_ptr<InterceptNavigationResourceThrottle> throttle_;
+ MockResourceController throttle_controller_;
+};
+
+// InterceptNavigationResourceThrottleTest ------------------------------------
+
+class InterceptNavigationResourceThrottleTest
+ : public content::RenderViewHostTestHarness {
+ public:
+ InterceptNavigationResourceThrottleTest()
+ : mock_callback_receiver_(new MockInterceptCallbackReceiver()),
+ io_thread_state_(NULL) {
+ }
+
+ void SetUp() override { RenderViewHostTestHarness::SetUp(); }
+
+ void TearDown() override {
+ if (web_contents())
+ web_contents()->SetDelegate(NULL);
+
+ content::BrowserThread::DeleteSoon(
+ content::BrowserThread::IO, FROM_HERE, io_thread_state_);
+
+ RenderViewHostTestHarness::TearDown();
+ }
+
+ void SetIOThreadState(TestIOThreadState* io_thread_state) {
+ io_thread_state_ = io_thread_state;
+ }
+
+ void RunThrottleWillStartRequestOnIOThread(
+ const GURL& url,
+ const std::string& request_method,
+ RedirectMode redirect_mode,
+ int render_process_id,
+ int render_frame_id,
+ bool* defer) {
+ DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
+ TestIOThreadState* io_thread_state =
+ new TestIOThreadState(url, render_process_id, render_frame_id,
+ request_method, redirect_mode,
+ mock_callback_receiver_.get());
+
+ SetIOThreadState(io_thread_state);
+
+ if (redirect_mode == REDIRECT_MODE_NO_REDIRECT) {
+ io_thread_state->ThrottleWillStartRequest(defer);
+ } else {
+ // 302 redirects convert POSTs to gets.
+ net::RedirectInfo redirect_info;
+ redirect_info.new_url = url;
+ redirect_info.new_method = "GET";
+ io_thread_state->ThrottleWillRedirectRequest(redirect_info, defer);
+ }
+ }
+
+ protected:
+ enum ShouldIgnoreNavigationCallbackAction {
+ IgnoreNavigation,
+ DontIgnoreNavigation
+ };
+
+ void SetUpWebContentsDelegateAndDrainRunLoop(
+ ShouldIgnoreNavigationCallbackAction callback_action,
+ bool* defer) {
+ ON_CALL(*mock_callback_receiver_, ShouldIgnoreNavigation(_, _))
+ .WillByDefault(Return(callback_action == IgnoreNavigation));
+ EXPECT_CALL(*mock_callback_receiver_,
+ ShouldIgnoreNavigation(web_contents(),
+ NavigationParamsUrlIsTest()))
+ .Times(1);
+
+ content::BrowserThread::PostTask(
+ content::BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(
+ &InterceptNavigationResourceThrottleTest::
+ RunThrottleWillStartRequestOnIOThread,
+ base::Unretained(this),
+ GURL(kTestUrl),
+ "GET",
+ REDIRECT_MODE_NO_REDIRECT,
+ web_contents()->GetRenderViewHost()->GetProcess()->GetID(),
+ web_contents()->GetMainFrame()->GetRoutingID(),
+ base::Unretained(defer)));
+
+ // Wait for the request to finish processing.
+ base::RunLoop().RunUntilIdle();
+ }
+
+ void WaitForPreviouslyScheduledIoThreadWork() {
+ base::WaitableEvent io_thread_work_done(true, false);
+ content::BrowserThread::PostTask(
+ content::BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(
+ &base::WaitableEvent::Signal,
+ base::Unretained(&io_thread_work_done)));
+ io_thread_work_done.Wait();
+ }
+
+ scoped_ptr<MockInterceptCallbackReceiver> mock_callback_receiver_;
+ TestIOThreadState* io_thread_state_;
+};
+
+TEST_F(InterceptNavigationResourceThrottleTest,
+ RequestDeferredAndResumedIfNavigationNotIgnored) {
+ bool defer = false;
+ SetUpWebContentsDelegateAndDrainRunLoop(DontIgnoreNavigation, &defer);
+
+ EXPECT_TRUE(defer);
+ ASSERT_TRUE(io_thread_state_);
+ EXPECT_TRUE(io_thread_state_->request_resumed());
+}
+
+TEST_F(InterceptNavigationResourceThrottleTest,
+ RequestDeferredAndCancelledIfNavigationIgnored) {
+ bool defer = false;
+ SetUpWebContentsDelegateAndDrainRunLoop(IgnoreNavigation, &defer);
+
+ EXPECT_TRUE(defer);
+ ASSERT_TRUE(io_thread_state_);
+ EXPECT_TRUE(io_thread_state_->request_cancelled());
+}
+
+TEST_F(InterceptNavigationResourceThrottleTest,
+ NoCallbackMadeIfContentsDeletedWhileThrottleRunning) {
+ bool defer = false;
+
+ // The tested scenario is when the WebContents is deleted after the
+ // ResourceThrottle has finished processing on the IO thread but before the
+ // UI thread callback has been processed. Since both threads in this test
+ // are serviced by one message loop, the post order is the execution order.
+ EXPECT_CALL(*mock_callback_receiver_,
+ ShouldIgnoreNavigation(_, _))
+ .Times(0);
+
+ content::BrowserThread::PostTask(
+ content::BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(
+ &InterceptNavigationResourceThrottleTest::
+ RunThrottleWillStartRequestOnIOThread,
+ base::Unretained(this),
+ GURL(kTestUrl),
+ "GET",
+ REDIRECT_MODE_NO_REDIRECT,
+ web_contents()->GetRenderViewHost()->GetProcess()->GetID(),
+ web_contents()->GetMainFrame()->GetRoutingID(),
+ base::Unretained(&defer)));
+
+ content::BrowserThread::PostTask(
+ content::BrowserThread::UI,
+ FROM_HERE,
+ base::Bind(
+ &RenderViewHostTestHarness::DeleteContents,
+ base::Unretained(this)));
+
+ // The WebContents will now be deleted and only after that will the UI-thread
+ // callback posted by the ResourceThrottle be executed.
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_TRUE(defer);
+ ASSERT_TRUE(io_thread_state_);
+ EXPECT_TRUE(io_thread_state_->request_resumed());
+}
+
+TEST_F(InterceptNavigationResourceThrottleTest,
+ RequestNotDeferredForRequestNotAssociatedWithARenderView) {
+ bool defer = false;
+
+ content::BrowserThread::PostTask(
+ content::BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(
+ &InterceptNavigationResourceThrottleTest::
+ RunThrottleWillStartRequestOnIOThread,
+ base::Unretained(this),
+ GURL(kTestUrl),
+ "GET",
+ REDIRECT_MODE_NO_REDIRECT,
+ MSG_ROUTING_NONE,
+ MSG_ROUTING_NONE,
+ base::Unretained(&defer)));
+
+ // Wait for the request to finish processing.
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_FALSE(defer);
+}
+
+TEST_F(InterceptNavigationResourceThrottleTest,
+ CallbackCalledWithFilteredUrl) {
+ bool defer = false;
+
+ ON_CALL(*mock_callback_receiver_,
+ ShouldIgnoreNavigation(_, NavigationParamsUrlIsSafe()))
+ .WillByDefault(Return(false));
+ EXPECT_CALL(*mock_callback_receiver_,
+ ShouldIgnoreNavigation(_, NavigationParamsUrlIsSafe()))
+ .Times(1);
+
+ content::BrowserThread::PostTask(
+ content::BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(
+ &InterceptNavigationResourceThrottleTest::
+ RunThrottleWillStartRequestOnIOThread,
+ base::Unretained(this),
+ GURL(kUnsafeTestUrl),
+ "GET",
+ REDIRECT_MODE_NO_REDIRECT,
+ web_contents()->GetRenderViewHost()->GetProcess()->GetID(),
+ web_contents()->GetMainFrame()->GetRoutingID(),
+ base::Unretained(&defer)));
+
+ // Wait for the request to finish processing.
+ base::RunLoop().RunUntilIdle();
+}
+
+TEST_F(InterceptNavigationResourceThrottleTest,
+ CallbackIsPostFalseForGet) {
+ bool defer = false;
+
+ EXPECT_CALL(*mock_callback_receiver_,
+ ShouldIgnoreNavigation(_, AllOf(
+ NavigationParamsUrlIsSafe(),
+ Property(&NavigationParams::is_post, Eq(false)))))
+ .WillOnce(Return(false));
+
+ content::BrowserThread::PostTask(
+ content::BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(
+ &InterceptNavigationResourceThrottleTest::
+ RunThrottleWillStartRequestOnIOThread,
+ base::Unretained(this),
+ GURL(kTestUrl),
+ "GET",
+ REDIRECT_MODE_NO_REDIRECT,
+ web_contents()->GetRenderViewHost()->GetProcess()->GetID(),
+ web_contents()->GetMainFrame()->GetRoutingID(),
+ base::Unretained(&defer)));
+
+ // Wait for the request to finish processing.
+ base::RunLoop().RunUntilIdle();
+}
+
+TEST_F(InterceptNavigationResourceThrottleTest,
+ CallbackIsPostTrueForPost) {
+ bool defer = false;
+
+ EXPECT_CALL(*mock_callback_receiver_,
+ ShouldIgnoreNavigation(_, AllOf(
+ NavigationParamsUrlIsSafe(),
+ Property(&NavigationParams::is_post, Eq(true)))))
+ .WillOnce(Return(false));
+
+ content::BrowserThread::PostTask(
+ content::BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(
+ &InterceptNavigationResourceThrottleTest::
+ RunThrottleWillStartRequestOnIOThread,
+ base::Unretained(this),
+ GURL(kTestUrl),
+ "POST",
+ REDIRECT_MODE_NO_REDIRECT,
+ web_contents()->GetRenderViewHost()->GetProcess()->GetID(),
+ web_contents()->GetMainFrame()->GetRoutingID(),
+ base::Unretained(&defer)));
+
+ // Wait for the request to finish processing.
+ base::RunLoop().RunUntilIdle();
+}
+
+TEST_F(InterceptNavigationResourceThrottleTest,
+ CallbackIsPostFalseForPostConvertedToGetBy302) {
+ bool defer = false;
+
+ EXPECT_CALL(*mock_callback_receiver_,
+ ShouldIgnoreNavigation(_, AllOf(
+ NavigationParamsUrlIsSafe(),
+ Property(&NavigationParams::is_post, Eq(false)))))
+ .WillOnce(Return(false));
+
+ content::BrowserThread::PostTask(
+ content::BrowserThread::IO,
+ FROM_HERE,
+ base::Bind(
+ &InterceptNavigationResourceThrottleTest::
+ RunThrottleWillStartRequestOnIOThread,
+ base::Unretained(this),
+ GURL(kTestUrl),
+ "POST",
+ REDIRECT_MODE_302,
+ web_contents()->GetRenderViewHost()->GetProcess()->GetID(),
+ web_contents()->GetMainFrame()->GetRoutingID(),
+ base::Unretained(&defer)));
+
+ // Wait for the request to finish processing.
+ base::RunLoop().RunUntilIdle();
+}
+
+} // namespace navigation_interception

Powered by Google App Engine
This is Rietveld 408576698