Index: content/browser/frame_host/navigator_impl_unittest.cc |
diff --git a/content/browser/frame_host/navigator_impl_unittest.cc b/content/browser/frame_host/navigator_impl_unittest.cc |
index 8b0ae22c17e5b5e4ca745890e6607255de9f16e7..4b4f03ab61632cbacccc3f301464d29dcbb10fe6 100644 |
--- a/content/browser/frame_host/navigator_impl_unittest.cc |
+++ b/content/browser/frame_host/navigator_impl_unittest.cc |
@@ -14,6 +14,8 @@ |
#include "content/browser/frame_host/navigator.h" |
#include "content/browser/frame_host/navigator_impl.h" |
#include "content/browser/frame_host/render_frame_host_manager.h" |
+#include "content/browser/loader/navigation_url_loader.h" |
+#include "content/browser/loader/navigation_url_loader_factory.h" |
#include "content/browser/site_instance_impl.h" |
#include "content/browser/streams/stream.h" |
#include "content/browser/streams/stream_registry.h" |
@@ -26,15 +28,97 @@ |
#include "content/test/test_web_contents.h" |
#include "net/base/load_flags.h" |
#include "net/http/http_response_headers.h" |
+#include "net/url_request/redirect_info.h" |
#include "ui/base/page_transition_types.h" |
#include "url/url_constants.h" |
namespace content { |
+namespace { |
+ |
+class TestNavigationURLLoader : public NavigationURLLoader { |
+ public: |
+ TestNavigationURLLoader(const CommonNavigationParams& common_params, |
+ scoped_ptr<NavigationRequestInfo> request_info, |
+ NavigationURLLoader::Delegate* delegate) |
+ : common_params_(common_params), |
+ request_info_(request_info.Pass()), |
+ delegate_(delegate) { |
+ } |
+ |
+ virtual ~TestNavigationURLLoader() { |
+ // Record the number of times a loader was canceled before ResponseStarted |
+ // or RequestFailed was returned. |
+ if (delegate_) |
nasko
2014/10/20 13:52:17
What would set delegate_ to nullptr?
davidben
2014/10/22 01:32:37
Oh hrm. I think CallOnResponseStarted used to null
|
+ cancel_count_++; |
+ } |
+ |
+ // NavigationURLLoader implementation. |
+ virtual void FollowRedirect() override { |
+ redirect_count_++; |
+ } |
+ |
+ const CommonNavigationParams& common_params() const { return common_params_; } |
+ NavigationRequestInfo* request_info() const { return request_info_.get(); } |
+ |
+ void CallOnRequestRedirected(const net::RedirectInfo& redirect_info, |
+ ResourceResponse* response) { |
+ delegate_->OnRequestRedirected(redirect_info, response); |
+ } |
+ |
+ void CallOnResponseStarted(ResourceResponse* response, |
+ scoped_ptr<StreamHandle> body) { |
+ delegate_->OnResponseStarted(response, body.Pass()); |
+ } |
+ |
+ static int redirect_count() { return redirect_count_; } |
+ static int cancel_count() { return cancel_count_; } |
+ |
+ private: |
+ static int redirect_count_; |
+ static int cancel_count_; |
+ |
+ CommonNavigationParams common_params_; |
+ scoped_ptr<NavigationRequestInfo> request_info_; |
+ NavigationURLLoader::Delegate* delegate_; |
+}; |
+ |
+int TestNavigationURLLoader::redirect_count_ = 0; |
+int TestNavigationURLLoader::cancel_count_ = 0; |
+ |
+class TestNavigationURLLoaderFactory : public NavigationURLLoaderFactory { |
+ public: |
+ // NavigationURLLoaderFactory implementation. |
+ virtual scoped_ptr<NavigationURLLoader> CreateLoader( |
+ BrowserContext* browser_context, |
+ int64 frame_tree_node_id, |
+ const CommonNavigationParams& common_params, |
+ scoped_ptr<NavigationRequestInfo> request_info, |
+ ResourceRequestBody* request_body, |
+ NavigationURLLoader::Delegate* delegate) override { |
+ return scoped_ptr<NavigationURLLoader>(new TestNavigationURLLoader( |
+ common_params, request_info.Pass(), delegate)); |
+ } |
+}; |
+ |
+} // namespace |
+ |
class NavigatorTest : public RenderViewHostImplTestHarness { |
public: |
NavigatorTest() : stream_registry_(new StreamRegistry) {} |
+ virtual void SetUp() override { |
+ RenderViewHostImplTestHarness::SetUp(); |
+ loader_factory_.reset(new TestNavigationURLLoaderFactory); |
+ NavigationURLLoader::SetFactoryForTesting(loader_factory_.get()); |
+ } |
+ |
+ virtual void TearDown() override { |
+ NavigationURLLoader::SetFactoryForTesting(nullptr); |
+ loader_factory_.reset(); |
+ RenderViewHostImplTestHarness::TearDown(); |
+ } |
+ |
NavigationRequest* GetNavigationRequestForFrameTreeNode( |
FrameTreeNode* frame_tree_node) const { |
NavigatorImpl* navigator = |
@@ -43,6 +127,11 @@ class NavigatorTest : public RenderViewHostImplTestHarness { |
frame_tree_node->frame_tree_node_id()); |
} |
+ TestNavigationURLLoader* GetLoaderForNavigationRequest( |
+ NavigationRequest* request) const { |
+ return static_cast<TestNavigationURLLoader*>(request->loader_for_testing()); |
+ } |
+ |
void EnableBrowserSideNavigation() { |
CommandLine::ForCurrentProcess()->AppendSwitch( |
switches::kEnableBrowserSideNavigation); |
@@ -83,6 +172,7 @@ class NavigatorTest : public RenderViewHostImplTestHarness { |
private: |
scoped_ptr<StreamRegistry> stream_registry_; |
+ scoped_ptr<TestNavigationURLLoaderFactory> loader_factory_; |
}; |
// PlzNavigate: Test that a proper NavigationRequest is created by |
@@ -109,12 +199,15 @@ TEST_F(NavigatorTest, BrowserSideNavigationBeginNavigation) { |
// handled already. |
NavigationRequest* subframe_request = |
GetNavigationRequestForFrameTreeNode(subframe_node); |
+ TestNavigationURLLoader* subframe_loader = |
+ GetLoaderForNavigationRequest(subframe_request); |
ASSERT_TRUE(subframe_request); |
EXPECT_EQ(kUrl2, subframe_request->common_params().url); |
+ EXPECT_EQ(kUrl2, subframe_loader->common_params().url); |
// First party for cookies url should be that of the main frame. |
- EXPECT_EQ(kUrl1, subframe_request->info_for_test()->first_party_for_cookies); |
- EXPECT_FALSE(subframe_request->info_for_test()->is_main_frame); |
- EXPECT_TRUE(subframe_request->info_for_test()->parent_is_main_frame); |
+ EXPECT_EQ(kUrl1, subframe_loader->request_info()->first_party_for_cookies); |
+ EXPECT_FALSE(subframe_loader->request_info()->is_main_frame); |
+ EXPECT_TRUE(subframe_loader->request_info()->parent_is_main_frame); |
FrameTreeNode* main_frame_node = |
contents()->GetMainFrame()->frame_tree_node(); |
@@ -123,11 +216,14 @@ TEST_F(NavigatorTest, BrowserSideNavigationBeginNavigation) { |
contents()->GetMainFrame()->SendBeginNavigationWithURL(kUrl3); |
NavigationRequest* main_request = |
GetNavigationRequestForFrameTreeNode(main_frame_node); |
+ TestNavigationURLLoader* main_loader = |
+ GetLoaderForNavigationRequest(main_request); |
ASSERT_TRUE(main_request); |
EXPECT_EQ(kUrl3, main_request->common_params().url); |
- EXPECT_EQ(kUrl3, main_request->info_for_test()->first_party_for_cookies); |
- EXPECT_TRUE(main_request->info_for_test()->is_main_frame); |
- EXPECT_FALSE(main_request->info_for_test()->parent_is_main_frame); |
+ EXPECT_EQ(kUrl3, main_loader->common_params().url); |
+ EXPECT_EQ(kUrl3, main_loader->request_info()->first_party_for_cookies); |
+ EXPECT_TRUE(main_loader->request_info()->is_main_frame); |
+ EXPECT_FALSE(main_loader->request_info()->parent_is_main_frame); |
} |
// PlzNavigate: Test that RequestNavigation creates a NavigationRequest and that |
@@ -144,9 +240,11 @@ TEST_F(NavigatorTest, BrowserSideNavigationRequestNavigationNoLiveRenderer) { |
EXPECT_TRUE(main_request != NULL); |
RenderFrameHostImpl* rfh = main_test_rfh(); |
- // Now commit the same url. |
+ // Now return the response without any redirects. This will cause the |
+ // navigation to commit at the same URL. |
scoped_refptr<ResourceResponse> response(new ResourceResponse); |
- node->navigator()->CommitNavigation(node, response.get(), MakeEmptyStream()); |
+ GetLoaderForNavigationRequest(main_request)->CallOnResponseStarted( |
+ response.get(), MakeEmptyStream()); |
main_request = GetNavigationRequestForFrameTreeNode(node); |
// The main RFH should not have been changed, and the renderer should have |
@@ -181,7 +279,8 @@ TEST_F(NavigatorTest, BrowserSideNavigationNoContent) { |
const char kNoContentHeaders[] = "HTTP/1.1 204 No Content\0\0"; |
response->head.headers = new net::HttpResponseHeaders( |
std::string(kNoContentHeaders, arraysize(kNoContentHeaders))); |
- node->navigator()->CommitNavigation(node, response.get(), MakeEmptyStream()); |
+ GetLoaderForNavigationRequest(main_request)->CallOnResponseStarted( |
+ response.get(), MakeEmptyStream()); |
// There should be no pending RenderFrameHost; the navigation was aborted. |
EXPECT_FALSE(GetNavigationRequestForFrameTreeNode(node)); |
@@ -200,7 +299,8 @@ TEST_F(NavigatorTest, BrowserSideNavigationNoContent) { |
const char kResetContentHeaders[] = "HTTP/1.1 205 Reset Content\0\0"; |
response->head.headers = new net::HttpResponseHeaders( |
std::string(kResetContentHeaders, arraysize(kResetContentHeaders))); |
- node->navigator()->CommitNavigation(node, response.get(), MakeEmptyStream()); |
+ GetLoaderForNavigationRequest(main_request)->CallOnResponseStarted( |
+ response.get(), MakeEmptyStream()); |
// There should be no pending RenderFrameHost; the navigation was aborted. |
EXPECT_FALSE(GetNavigationRequestForFrameTreeNode(node)); |
@@ -227,7 +327,51 @@ TEST_F(NavigatorTest, BrowserSideNavigationCrossSiteNavigation) { |
ASSERT_TRUE(main_request); |
scoped_refptr<ResourceResponse> response(new ResourceResponse); |
- node->navigator()->CommitNavigation(node, response.get(), MakeEmptyStream()); |
+ GetLoaderForNavigationRequest(main_request)->CallOnResponseStarted( |
+ response.get(), MakeEmptyStream()); |
+ RenderFrameHostImpl* pending_rfh = |
+ node->render_manager()->pending_frame_host(); |
+ ASSERT_TRUE(pending_rfh); |
+ EXPECT_NE(pending_rfh, rfh); |
+ EXPECT_TRUE(pending_rfh->IsRenderFrameLive()); |
+ EXPECT_TRUE(pending_rfh->render_view_host()->IsRenderViewLive()); |
+} |
+ |
+// PlzNavigate: Test that redirects are followed. |
+TEST_F(NavigatorTest, BrowserSideNavigationRedirectCrossSite) { |
+ const GURL kUrl1("http://www.chromium.org/"); |
+ const GURL kUrl2("http://www.google.com/"); |
+ |
+ contents()->NavigateAndCommit(kUrl1); |
+ RenderFrameHostImpl* rfh = main_test_rfh(); |
+ EXPECT_EQ(RenderFrameHostImpl::STATE_DEFAULT, rfh->rfh_state()); |
+ FrameTreeNode* node = main_test_rfh()->frame_tree_node(); |
+ |
+ EnableBrowserSideNavigation(); |
+ |
+ // Navigate to a URL on the same site. |
+ SendRequestNavigation(node, kUrl1); |
+ main_test_rfh()->SendBeginNavigationWithURL(kUrl1); |
+ NavigationRequest* main_request = GetNavigationRequestForFrameTreeNode(node); |
+ ASSERT_TRUE(main_request); |
+ |
+ // It then redirects to another site. |
+ net::RedirectInfo redirect_info; |
+ redirect_info.status_code = 302; |
+ redirect_info.new_method = "GET"; |
+ redirect_info.new_url = kUrl2; |
+ redirect_info.new_first_party_for_cookies = kUrl2; |
+ scoped_refptr<ResourceResponse> response(new ResourceResponse); |
+ GetLoaderForNavigationRequest(main_request)->CallOnRequestRedirected( |
+ redirect_info, response.get()); |
+ |
+ // The redirect should have been followed. |
+ EXPECT_EQ(1, TestNavigationURLLoader::redirect_count()); |
+ |
+ // Then it commits. |
+ response = new ResourceResponse; |
+ GetLoaderForNavigationRequest(main_request)->CallOnResponseStarted( |
+ response.get(), MakeEmptyStream()); |
RenderFrameHostImpl* pending_rfh = |
node->render_manager()->pending_frame_host(); |
ASSERT_TRUE(pending_rfh); |
@@ -268,7 +412,8 @@ TEST_F(NavigatorTest, BrowserSideNavigationReplacePendingNavigation) { |
// Confirm that the commit corresonds to the new request. |
scoped_refptr<ResourceResponse> response(new ResourceResponse); |
- node->navigator()->CommitNavigation(node, response.get(), MakeEmptyStream()); |
+ GetLoaderForNavigationRequest(request2)->CallOnResponseStarted( |
+ response.get(), MakeEmptyStream()); |
RenderFrameHostImpl* pending_rfh = |
node->render_manager()->pending_frame_host(); |
ASSERT_TRUE(pending_rfh); |