diff options
Diffstat (limited to 'components')
11 files changed, 709 insertions, 287 deletions
diff --git a/components/components_tests.gyp b/components/components_tests.gyp index f2917db..c3dd97c 100644 --- a/components/components_tests.gyp +++ b/components/components_tests.gyp @@ -354,7 +354,7 @@ 'nacl/zygote/nacl_fork_delegate_linux_unittest.cc', ], 'navigation_interception_unittest_sources': [ - 'navigation_interception/intercept_navigation_throttle_unittest.cc', + 'navigation_interception/intercept_navigation_resource_throttle_unittest.cc', ], 'network_hints_unittest_sources': [ 'network_hints/renderer/dns_prefetch_queue_unittest.cc', diff --git a/components/navigation_interception.gypi b/components/navigation_interception.gypi index 7ccc4cd..3511201 100644 --- a/components/navigation_interception.gypi +++ b/components/navigation_interception.gypi @@ -23,8 +23,8 @@ ], 'sources': [ # Note: sources list duplicated in GN build. - 'navigation_interception/intercept_navigation_throttle.cc', - 'navigation_interception/intercept_navigation_throttle.h', + 'navigation_interception/intercept_navigation_resource_throttle.cc', + 'navigation_interception/intercept_navigation_resource_throttle.h', 'navigation_interception/navigation_params.cc', 'navigation_interception/navigation_params.h', ], diff --git a/components/navigation_interception/BUILD.gn b/components/navigation_interception/BUILD.gn index f268510..12456ff 100644 --- a/components/navigation_interception/BUILD.gn +++ b/components/navigation_interception/BUILD.gn @@ -8,8 +8,8 @@ if (is_android) { source_set("navigation_interception") { sources = [ - "intercept_navigation_throttle.cc", - "intercept_navigation_throttle.h", + "intercept_navigation_resource_throttle.cc", + "intercept_navigation_resource_throttle.h", "navigation_params.cc", "navigation_params.h", ] @@ -49,7 +49,7 @@ if (is_android) { source_set("unit_tests") { testonly = true sources = [ - "intercept_navigation_throttle_unittest.cc", + "intercept_navigation_resource_throttle_unittest.cc", ] deps = [ ":navigation_interception", diff --git a/components/navigation_interception/intercept_navigation_delegate.cc b/components/navigation_interception/intercept_navigation_delegate.cc index 11017f3b..ba9053d 100644 --- a/components/navigation_interception/intercept_navigation_delegate.cc +++ b/components/navigation_interception/intercept_navigation_delegate.cc @@ -7,10 +7,9 @@ #include "base/android/jni_android.h" #include "base/android/jni_string.h" #include "base/callback.h" -#include "components/navigation_interception/intercept_navigation_throttle.h" +#include "components/navigation_interception/intercept_navigation_resource_throttle.h" #include "components/navigation_interception/navigation_params_android.h" #include "content/public/browser/browser_thread.h" -#include "content/public/browser/navigation_throttle.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/resource_request_info.h" @@ -84,12 +83,10 @@ InterceptNavigationDelegate* InterceptNavigationDelegate::Get( } // static -scoped_ptr<content::NavigationThrottle> -InterceptNavigationDelegate::CreateThrottleFor( - content::NavigationHandle* handle) { - return scoped_ptr<content::NavigationThrottle>( - new InterceptNavigationThrottle( - handle, base::Bind(&CheckIfShouldIgnoreNavigationOnUIThread))); +content::ResourceThrottle* InterceptNavigationDelegate::CreateThrottleFor( + net::URLRequest* request) { + return new InterceptNavigationResourceThrottle( + request, base::Bind(&CheckIfShouldIgnoreNavigationOnUIThread)); } // static diff --git a/components/navigation_interception/intercept_navigation_delegate.h b/components/navigation_interception/intercept_navigation_delegate.h index 57858fd..d84969f 100644 --- a/components/navigation_interception/intercept_navigation_delegate.h +++ b/components/navigation_interception/intercept_navigation_delegate.h @@ -12,8 +12,7 @@ class GURL; namespace content { -class NavigationHandle; -class NavigationThrottle; +class ResourceThrottle; class WebContents; } @@ -33,8 +32,9 @@ class NavigationParams; // 1) the Java-side interface implementation must be associated (via the // Associate method) with a WebContents for which URLRequests are to be // intercepted, -// 2) the NavigationThrottle obtained via CreateThrottleFor must be associated -// with the NavigationHandle in the ContentBrowserClient implementation. +// 2) the ResourceThrottle obtained via CreateThrottleFor must be associated +// with the URLRequests in the ResourceDispatcherHostDelegate +// implementation. class InterceptNavigationDelegate : public base::SupportsUserData::Data { public: InterceptNavigationDelegate(JNIEnv* env, jobject jdelegate); @@ -50,10 +50,10 @@ class InterceptNavigationDelegate : public base::SupportsUserData::Data { // can be null. static InterceptNavigationDelegate* Get(content::WebContents* web_contents); - // Creates a InterceptNavigationThrottle that will direct all callbacks to - // the InterceptNavigationDelegate. - static scoped_ptr<content::NavigationThrottle> CreateThrottleFor( - content::NavigationHandle* handle); + // Creates a InterceptNavigationResourceThrottle that will direct all + // callbacks to the InterceptNavigationDelegate. + static content::ResourceThrottle* CreateThrottleFor( + net::URLRequest* request); // Updates information to determine whether to have user gesture carryover or // not. diff --git a/components/navigation_interception/intercept_navigation_resource_throttle.cc b/components/navigation_interception/intercept_navigation_resource_throttle.cc new file mode 100644 index 0000000..1b0b89f --- /dev/null +++ b/components/navigation_interception/intercept_navigation_resource_throttle.cc @@ -0,0 +1,146 @@ +// 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 "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/child_process_security_policy.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_request_info.h" +#include "content/public/browser/web_contents.h" +#include "content/public/common/referrer.h" +#include "net/http/http_response_headers.h" +#include "net/url_request/redirect_info.h" +#include "net/url_request/url_request_context.h" +#include "net/url_request/url_request_job_factory.h" +#include "net/url_request/url_request.h" +#include "ui/base/page_transition_types.h" + +using content::BrowserThread; +using content::ChildProcessSecurityPolicy; +using ui::PageTransition; +using content::Referrer; +using content::RenderProcessHost; +using content::ResourceRequestInfo; + +namespace navigation_interception { + +namespace { + +void CheckIfShouldIgnoreNavigationOnUIThread( + int render_process_id, + int render_frame_id, + const NavigationParams& navigation_params, + InterceptNavigationResourceThrottle::CheckOnUIThreadCallback + should_ignore_callback, + base::Callback<void(bool)> callback) { + bool should_ignore_navigation = false; + RenderProcessHost* rph = RenderProcessHost::FromID(render_process_id); + if (rph) { + NavigationParams validated_params(navigation_params); + rph->FilterURL(false, &validated_params.url()); + + content::RenderFrameHost* render_frame_host = + content::RenderFrameHost::FromID(render_process_id, render_frame_id); + content::WebContents* web_contents = + content::WebContents::FromRenderFrameHost(render_frame_host); + + if (web_contents) { + should_ignore_navigation = should_ignore_callback.Run(web_contents, + validated_params); + } + } + + BrowserThread::PostTask( + BrowserThread::IO, + FROM_HERE, + base::Bind(callback, should_ignore_navigation)); +} + +} // namespace + +InterceptNavigationResourceThrottle::InterceptNavigationResourceThrottle( + net::URLRequest* request, + CheckOnUIThreadCallback should_ignore_callback) + : request_(request), + should_ignore_callback_(should_ignore_callback), + weak_ptr_factory_(this) { +} + +InterceptNavigationResourceThrottle::~InterceptNavigationResourceThrottle() { + DCHECK_CURRENTLY_ON(BrowserThread::IO); +} + +void InterceptNavigationResourceThrottle::WillStartRequest(bool* defer) { + *defer = + CheckIfShouldIgnoreNavigation(request_->url(), request_->method(), false); +} + +void InterceptNavigationResourceThrottle::WillRedirectRequest( + const net::RedirectInfo& redirect_info, + bool* defer) { + *defer = CheckIfShouldIgnoreNavigation(redirect_info.new_url, + redirect_info.new_method, true); +} + +const char* InterceptNavigationResourceThrottle::GetNameForLogging() const { + return "InterceptNavigationResourceThrottle"; +} + +bool InterceptNavigationResourceThrottle::CheckIfShouldIgnoreNavigation( + const GURL& url, + const std::string& method, + bool is_redirect) { + const ResourceRequestInfo* info = ResourceRequestInfo::ForRequest(request_); + if (!info) + return false; + + int render_process_id, render_frame_id; + if (!info->GetAssociatedRenderFrame(&render_process_id, &render_frame_id)) + return false; + + bool is_external_protocol = + !info->GetContext()->GetRequestContext()->job_factory()->IsHandledURL( + url); + NavigationParams navigation_params( + url, + Referrer::SanitizeForRequest( + url, Referrer(GURL(request_->referrer()), info->GetReferrerPolicy())), + info->HasUserGesture(), method == "POST", info->GetPageTransition(), + is_redirect, is_external_protocol, true); + + BrowserThread::PostTask( + BrowserThread::UI, + FROM_HERE, + base::Bind( + &CheckIfShouldIgnoreNavigationOnUIThread, + render_process_id, + render_frame_id, + navigation_params, + should_ignore_callback_, + base::Bind( + &InterceptNavigationResourceThrottle::OnResultObtained, + weak_ptr_factory_.GetWeakPtr()))); + + // Defer request while we wait for the UI thread to check if the navigation + // should be ignored. + return true; +} + +void InterceptNavigationResourceThrottle::OnResultObtained( + bool should_ignore_navigation) { + DCHECK_CURRENTLY_ON(BrowserThread::IO); + + if (should_ignore_navigation) { + controller()->CancelAndIgnore(); + } else { + controller()->Resume(); + } +} + +} // namespace navigation_interception diff --git a/components/navigation_interception/intercept_navigation_resource_throttle.h b/components/navigation_interception/intercept_navigation_resource_throttle.h new file mode 100644 index 0000000..db3a714 --- /dev/null +++ b/components/navigation_interception/intercept_navigation_resource_throttle.h @@ -0,0 +1,63 @@ +// 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. + +#ifndef COMPONENTS_NAVIGATION_INTERCEPTION_INTERCEPT_NAVIGATION_RESOURCE_THROTTLE_H_ +#define COMPONENTS_NAVIGATION_INTERCEPTION_INTERCEPT_NAVIGATION_RESOURCE_THROTTLE_H_ + +#include <string> + +#include "base/callback.h" +#include "base/memory/weak_ptr.h" +#include "content/public/browser/resource_throttle.h" + +class GURL; + +namespace content { +class WebContents; +} + +namespace net { +class URLRequest; +} + +namespace navigation_interception { + +class NavigationParams; + +// This class allows the provider of the Callback to selectively ignore top +// level navigations. +class InterceptNavigationResourceThrottle : public content::ResourceThrottle { + public: + typedef base::Callback<bool( + content::WebContents* /* source */, + const NavigationParams& /* navigation_params */)> + CheckOnUIThreadCallback; + + InterceptNavigationResourceThrottle( + net::URLRequest* request, + CheckOnUIThreadCallback should_ignore_callback); + ~InterceptNavigationResourceThrottle() override; + + // content::ResourceThrottle implementation: + void WillStartRequest(bool* defer) override; + void WillRedirectRequest(const net::RedirectInfo& redirect_info, + bool* defer) override; + const char* GetNameForLogging() const override; + + private: + bool CheckIfShouldIgnoreNavigation(const GURL& url, + const std::string& method, + bool is_redirect); + void OnResultObtained(bool should_ignore_navigation); + + net::URLRequest* request_; + CheckOnUIThreadCallback should_ignore_callback_; + base::WeakPtrFactory<InterceptNavigationResourceThrottle> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(InterceptNavigationResourceThrottle); +}; + +} // namespace navigation_interception + +#endif // COMPONENTS_NAVIGATION_INTERCEPTION_INTERCEPT_NAVIGATION_RESOURCE_THROTTLE_H_ 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 0000000..8855f42 --- /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 diff --git a/components/navigation_interception/intercept_navigation_throttle.cc b/components/navigation_interception/intercept_navigation_throttle.cc deleted file mode 100644 index cc256a1..0000000 --- a/components/navigation_interception/intercept_navigation_throttle.cc +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2015 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 "components/navigation_interception/intercept_navigation_throttle.h" - -#include "components/navigation_interception/navigation_params.h" -#include "content/public/browser/browser_thread.h" -#include "content/public/browser/navigation_handle.h" - -namespace navigation_interception { - -InterceptNavigationThrottle::InterceptNavigationThrottle( - content::NavigationHandle* navigation_handle, - CheckCallback should_ignore_callback) - : content::NavigationThrottle(navigation_handle), - should_ignore_callback_(should_ignore_callback) {} - -InterceptNavigationThrottle::~InterceptNavigationThrottle() {} - -content::NavigationThrottle::ThrottleCheckResult -InterceptNavigationThrottle::WillStartRequest() { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - return CheckIfShouldIgnoreNavigation(false); -} - -content::NavigationThrottle::ThrottleCheckResult -InterceptNavigationThrottle::WillRedirectRequest() { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - return CheckIfShouldIgnoreNavigation(true); -} - -content::NavigationThrottle::ThrottleCheckResult -InterceptNavigationThrottle::CheckIfShouldIgnoreNavigation(bool is_redirect) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - NavigationParams navigation_params( - navigation_handle()->GetURL(), navigation_handle()->GetReferrer(), - navigation_handle()->HasUserGesture(), navigation_handle()->IsPost(), - navigation_handle()->GetPageTransition(), is_redirect, - navigation_handle()->IsExternalProtocol(), true); - - bool should_ignore_navigation = should_ignore_callback_.Run( - navigation_handle()->GetWebContents(), navigation_params); - return should_ignore_navigation - ? content::NavigationThrottle::CANCEL_AND_IGNORE - : content::NavigationThrottle::PROCEED; -} - -} // namespace navigation_interception diff --git a/components/navigation_interception/intercept_navigation_throttle.h b/components/navigation_interception/intercept_navigation_throttle.h deleted file mode 100644 index 0b7f746..0000000 --- a/components/navigation_interception/intercept_navigation_throttle.h +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright 2015 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. - -#ifndef COMPONENTS_NAVIGATION_INTERCEPTION_INTERCEPT_NAVIGATION_THROTTLE_H_ -#define COMPONENTS_NAVIGATION_INTERCEPTION_INTERCEPT_NAVIGATION_THROTTLE_H_ - -#include <string> - -#include "base/callback.h" -#include "base/memory/weak_ptr.h" -#include "content/public/browser/navigation_throttle.h" - -class GURL; - -namespace content { -class NavigationHandle; -class WebContents; -} - -namespace navigation_interception { - -class NavigationParams; - -// This class allows the provider of the Callback to selectively ignore top -// level navigations. This is a UI thread class. -class InterceptNavigationThrottle : public content::NavigationThrottle { - public: - typedef base::Callback<bool(content::WebContents* /* source */, - const NavigationParams& /* navigation_params */)> - CheckCallback; - - InterceptNavigationThrottle(content::NavigationHandle* navigation_handle, - CheckCallback should_ignore_callback); - ~InterceptNavigationThrottle() override; - - // content::NavigationThrottle implementation: - ThrottleCheckResult WillStartRequest() override; - ThrottleCheckResult WillRedirectRequest() override; - - private: - ThrottleCheckResult CheckIfShouldIgnoreNavigation(bool is_redirect); - - CheckCallback should_ignore_callback_; - - DISALLOW_COPY_AND_ASSIGN(InterceptNavigationThrottle); -}; - -} // namespace navigation_interception - -#endif // COMPONENTS_NAVIGATION_INTERCEPTION_INTERCEPT_NAVIGATION_THROTTLE_H_ diff --git a/components/navigation_interception/intercept_navigation_throttle_unittest.cc b/components/navigation_interception/intercept_navigation_throttle_unittest.cc deleted file mode 100644 index 15e05ef..0000000 --- a/components/navigation_interception/intercept_navigation_throttle_unittest.cc +++ /dev/null @@ -1,165 +0,0 @@ -// Copyright 2015 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 "components/navigation_interception/intercept_navigation_throttle.h" -#include "components/navigation_interception/navigation_params.h" -#include "content/public/browser/navigation_handle.h" -#include "content/public/browser/navigation_throttle.h" -#include "content/public/browser/web_contents.h" -#include "content/public/test/test_renderer_host.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -using content::NavigationThrottle; -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/"; - -// 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); -} - -} // namespace - -// MockInterceptCallbackReceiver ---------------------------------------------- - -class MockInterceptCallbackReceiver { - public: - MOCK_METHOD2(ShouldIgnoreNavigation, - bool(content::WebContents* source, - const NavigationParams& navigation_params)); -}; - -// InterceptNavigationThrottleTest ------------------------------------ - -class InterceptNavigationThrottleTest - : public content::RenderViewHostTestHarness { - public: - InterceptNavigationThrottleTest() - : mock_callback_receiver_(new MockInterceptCallbackReceiver()) {} - - NavigationThrottle::ThrottleCheckResult - SimulateWillStart(const GURL& url, const GURL& sanitized_url, bool is_post) { - scoped_ptr<content::NavigationHandle> test_handle = - content::NavigationHandle::CreateNavigationHandleForTesting( - url, true, web_contents()); - test_handle->RegisterThrottleForTesting( - scoped_ptr<NavigationThrottle>( - new InterceptNavigationThrottle( - test_handle.get(), - base::Bind( - &MockInterceptCallbackReceiver::ShouldIgnoreNavigation, - base::Unretained(mock_callback_receiver_.get())))) - .Pass()); - return test_handle->CallWillStartRequestForTesting( - is_post, content::Referrer(), false, ui::PAGE_TRANSITION_LINK, false); - } - - NavigationThrottle::ThrottleCheckResult Simulate302() { - scoped_ptr<content::NavigationHandle> test_handle = - content::NavigationHandle::CreateNavigationHandleForTesting( - GURL(kTestUrl), true, web_contents()); - test_handle->RegisterThrottleForTesting( - scoped_ptr<NavigationThrottle>( - new InterceptNavigationThrottle( - test_handle.get(), - base::Bind( - &MockInterceptCallbackReceiver::ShouldIgnoreNavigation, - base::Unretained(mock_callback_receiver_.get())))) - .Pass()); - test_handle->CallWillStartRequestForTesting( - true, content::Referrer(), false, ui::PAGE_TRANSITION_LINK, false); - return test_handle->CallWillRedirectRequestForTesting(GURL(kTestUrl), false, - GURL(), false); - } - - scoped_ptr<MockInterceptCallbackReceiver> mock_callback_receiver_; -}; - -TEST_F(InterceptNavigationThrottleTest, - RequestDeferredAndResumedIfNavigationNotIgnored) { - ON_CALL(*mock_callback_receiver_, ShouldIgnoreNavigation(_, _)) - .WillByDefault(Return(false)); - EXPECT_CALL( - *mock_callback_receiver_, - ShouldIgnoreNavigation(web_contents(), NavigationParamsUrlIsTest())); - NavigationThrottle::ThrottleCheckResult result = - SimulateWillStart(GURL(kTestUrl), GURL(kTestUrl), false); - - EXPECT_EQ(NavigationThrottle::PROCEED, result); -} - -TEST_F(InterceptNavigationThrottleTest, - RequestDeferredAndCancelledIfNavigationIgnored) { - ON_CALL(*mock_callback_receiver_, ShouldIgnoreNavigation(_, _)) - .WillByDefault(Return(true)); - EXPECT_CALL( - *mock_callback_receiver_, - ShouldIgnoreNavigation(web_contents(), NavigationParamsUrlIsTest())); - NavigationThrottle::ThrottleCheckResult result = - SimulateWillStart(GURL(kTestUrl), GURL(kTestUrl), false); - - EXPECT_EQ(NavigationThrottle::CANCEL_AND_IGNORE, result); -} - -TEST_F(InterceptNavigationThrottleTest, CallbackIsPostFalseForGet) { - EXPECT_CALL(*mock_callback_receiver_, - ShouldIgnoreNavigation( - _, AllOf(NavigationParamsUrlIsTest(), - Property(&NavigationParams::is_post, Eq(false))))) - .WillOnce(Return(false)); - - NavigationThrottle::ThrottleCheckResult result = - SimulateWillStart(GURL(kTestUrl), GURL(kTestUrl), false); - - EXPECT_EQ(NavigationThrottle::PROCEED, result); -} - -TEST_F(InterceptNavigationThrottleTest, CallbackIsPostTrueForPost) { - EXPECT_CALL(*mock_callback_receiver_, - ShouldIgnoreNavigation( - _, AllOf(NavigationParamsUrlIsTest(), - Property(&NavigationParams::is_post, Eq(true))))) - .WillOnce(Return(false)); - NavigationThrottle::ThrottleCheckResult result = - SimulateWillStart(GURL(kTestUrl), GURL(kTestUrl), true); - - EXPECT_EQ(NavigationThrottle::PROCEED, result); -} - -TEST_F(InterceptNavigationThrottleTest, - CallbackIsPostFalseForPostConvertedToGetBy302) { - EXPECT_CALL(*mock_callback_receiver_, - ShouldIgnoreNavigation( - _, AllOf(NavigationParamsUrlIsTest(), - Property(&NavigationParams::is_post, Eq(true))))) - .WillOnce(Return(false)); - EXPECT_CALL(*mock_callback_receiver_, - ShouldIgnoreNavigation( - _, AllOf(NavigationParamsUrlIsTest(), - Property(&NavigationParams::is_post, Eq(false))))) - .WillOnce(Return(false)); - NavigationThrottle::ThrottleCheckResult result = Simulate302(); - - EXPECT_EQ(NavigationThrottle::PROCEED, result); -} - -} // namespace navigation_interception |