Index: content/browser/frame_host/navigation_controller_impl_browsertest.cc |
diff --git a/content/browser/frame_host/navigation_controller_impl_browsertest.cc b/content/browser/frame_host/navigation_controller_impl_browsertest.cc |
index 4b98ab1516f2c28dd46662533ba0461b03ac2d82..b96154d2ec5af45bbe7336a9d9b71ef1c8226c0a 100644 |
--- a/content/browser/frame_host/navigation_controller_impl_browsertest.cc |
+++ b/content/browser/frame_host/navigation_controller_impl_browsertest.cc |
@@ -50,6 +50,7 @@ |
#include "content/test/content_browser_test_utils_internal.h" |
#include "net/dns/mock_host_resolver.h" |
#include "net/test/embedded_test_server/embedded_test_server.h" |
+#include "net/test/embedded_test_server/embedded_test_server_connection_listener.h" |
#include "net/test/embedded_test_server/http_request.h" |
#include "net/test/url_request/url_request_failed_job.h" |
#include "testing/gmock/include/gmock/gmock-matchers.h" |
@@ -71,13 +72,54 @@ static std::string kRemoveFrameScript = |
namespace content { |
+// Gets notified by the EmbeddedTestServer on incoming requests. |
+class ConnectionListener |
+ : public net::test_server::EmbeddedTestServerConnectionListener { |
+ public: |
+ |
+ ConnectionListener() |
+ : bytes_read(0) {} |
+ ~ConnectionListener() override {} |
+ |
+ // Get called from the EmbeddedTestServer thread to be notified that |
+ // a connection was accepted. |
+ void AcceptedSocket(const net::StreamSocket& connection) override {} |
+ |
+ // Get called from the EmbeddedTestServer thread to be notified that |
+ // a connection was read from. |
+ void ReadFromSocket(const net::StreamSocket& connection, int bytes) override { |
+ base::AutoLock lock(lock_); |
+ bytes_read += bytes; |
+ } |
+ |
+ int BytesRead() { |
+ base::AutoLock lock(lock_); |
+ return bytes_read; |
+ } |
+ |
+ void ResetBytesRead() { |
+ base::AutoLock lock(lock_); |
+ bytes_read = 0; |
+ } |
+ |
+ private: |
+ // This lock protects all the members below, which each are used on both the |
+ // IO and UI thread. Members declared after the lock are protected by it. |
+ mutable base::Lock lock_; |
+ int bytes_read; |
+}; |
+ |
class NavigationControllerBrowserTest : public ContentBrowserTest { |
protected: |
void SetUpOnMainThread() override { |
host_resolver()->AddRule("*", "127.0.0.1"); |
content::SetupCrossSiteRedirector(embedded_test_server()); |
+ connection_listener.reset(new ConnectionListener()); |
+ embedded_test_server()->SetConnectionListener(connection_listener.get()); |
ASSERT_TRUE(embedded_test_server()->Start()); |
} |
+ |
+ std::unique_ptr<ConnectionListener> connection_listener; |
}; |
// Ensure that tests can navigate subframes cross-site in both default mode and |
@@ -7036,4 +7078,39 @@ IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, |
EXPECT_FALSE(handle_observer.was_renderer_initiated()); |
} |
+// Ensure that browser-initiated same-document navigations are detected and |
+// don't issue network requests. |
+// see crbug.com/663777 |
+IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, |
+ SamePageBrowserInitiatedNoReload) { |
+ GURL url(embedded_test_server()->GetURL("/title1.html")); |
+ GURL url_fragment_1(embedded_test_server()->GetURL("/title1.html#id_1")); |
+ GURL url_fragment_2(embedded_test_server()->GetURL("/title1.html#id_2")); |
+ |
+ // 1) Perform a new-document navigation. |
+ connection_listener->ResetBytesRead(); |
+ EXPECT_TRUE(NavigateToURL(shell(), url)); |
+ EXPECT_TRUE(connection_listener->BytesRead() > 0); |
+ |
+ // 2) Perform a same-document navigation by adding a fragment. |
+ connection_listener->ResetBytesRead(); |
+ EXPECT_TRUE(NavigateToURL(shell(), url_fragment_1)); |
+ EXPECT_TRUE(connection_listener->BytesRead() == 0); |
+ |
+ // 3) Perform a same-document navigation by modifying the fragment. |
+ connection_listener->ResetBytesRead(); |
+ EXPECT_TRUE(NavigateToURL(shell(), url_fragment_2)); |
+ EXPECT_TRUE(connection_listener->BytesRead() == 0); |
+ |
+ // 4) Redo the last navigation, but this time it should trigger a reload. |
+ connection_listener->ResetBytesRead(); |
+ EXPECT_TRUE(NavigateToURL(shell(), url_fragment_2)); |
+ EXPECT_TRUE(connection_listener->BytesRead() > 0); |
+ |
+ // 5) Perform a new-document navigation by removing the fragment. |
+ connection_listener->ResetBytesRead(); |
+ EXPECT_TRUE(NavigateToURL(shell(), url)); |
+ EXPECT_TRUE(connection_listener->BytesRead() > 0); |
+} |
+ |
} // namespace content |