OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/frame_host/navigation_controller_impl.h" | 5 #include "content/browser/frame_host/navigation_controller_impl.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
11 #include "base/command_line.h" | 11 #include "base/command_line.h" |
12 #include "base/macros.h" | 12 #include "base/macros.h" |
13 #include "base/strings/stringprintf.h" | 13 #include "base/strings/stringprintf.h" |
14 #include "base/strings/utf_string_conversions.h" | 14 #include "base/strings/utf_string_conversions.h" |
15 #include "content/browser/frame_host/frame_navigation_entry.h" | 15 #include "content/browser/frame_host/frame_navigation_entry.h" |
16 #include "content/browser/frame_host/frame_tree.h" | 16 #include "content/browser/frame_host/frame_tree.h" |
17 #include "content/browser/frame_host/navigation_entry_impl.h" | 17 #include "content/browser/frame_host/navigation_entry_impl.h" |
18 #include "content/browser/loader/resource_dispatcher_host_impl.h" | 18 #include "content/browser/loader/resource_dispatcher_host_impl.h" |
19 #include "content/browser/web_contents/web_contents_impl.h" | 19 #include "content/browser/web_contents/web_contents_impl.h" |
| 20 #include "content/common/frame_messages.h" |
20 #include "content/common/page_state_serialization.h" | 21 #include "content/common/page_state_serialization.h" |
21 #include "content/common/site_isolation_policy.h" | 22 #include "content/common/site_isolation_policy.h" |
22 #include "content/public/browser/navigation_handle.h" | 23 #include "content/public/browser/navigation_handle.h" |
23 #include "content/public/browser/render_view_host.h" | 24 #include "content/public/browser/render_view_host.h" |
24 #include "content/public/browser/resource_controller.h" | 25 #include "content/public/browser/resource_controller.h" |
25 #include "content/public/browser/resource_dispatcher_host.h" | 26 #include "content/public/browser/resource_dispatcher_host.h" |
26 #include "content/public/browser/resource_dispatcher_host_delegate.h" | 27 #include "content/public/browser/resource_dispatcher_host_delegate.h" |
27 #include "content/public/browser/resource_throttle.h" | 28 #include "content/public/browser/resource_throttle.h" |
28 #include "content/public/browser/web_contents.h" | 29 #include "content/public/browser/web_contents.h" |
29 #include "content/public/browser/web_contents_observer.h" | 30 #include "content/public/browser/web_contents_observer.h" |
(...skipping 5843 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5873 } | 5874 } |
5874 | 5875 |
5875 // Verify the expected origin through JavaScript. It also has the additional | 5876 // Verify the expected origin through JavaScript. It also has the additional |
5876 // verification of the process also being still alive. | 5877 // verification of the process also being still alive. |
5877 std::string origin; | 5878 std::string origin; |
5878 EXPECT_TRUE(ExecuteScriptAndExtractString( | 5879 EXPECT_TRUE(ExecuteScriptAndExtractString( |
5879 web_contents, "domAutomationController.send(document.origin)", &origin)); | 5880 web_contents, "domAutomationController.send(document.origin)", &origin)); |
5880 EXPECT_EQ(start_url.GetOrigin().spec(), origin + "/"); | 5881 EXPECT_EQ(start_url.GetOrigin().spec(), origin + "/"); |
5881 } | 5882 } |
5882 | 5883 |
| 5884 // A BrowserMessageFilter that drops FrameHostMsg_DidCommitProvisionaLoad IPC |
| 5885 // message for a specified URL and runs a callback on the UI thread. |
| 5886 class CommitMessageFilter : public BrowserMessageFilter { |
| 5887 public: |
| 5888 CommitMessageFilter(const GURL& url, base::Closure on_commit) |
| 5889 : BrowserMessageFilter(FrameMsgStart), url_(url), on_commit_(on_commit) {} |
| 5890 |
| 5891 protected: |
| 5892 ~CommitMessageFilter() override {} |
| 5893 |
| 5894 private: |
| 5895 // BrowserMessageFilter: |
| 5896 bool OnMessageReceived(const IPC::Message& message) override { |
| 5897 if (message.type() != FrameHostMsg_DidCommitProvisionalLoad::ID) |
| 5898 return false; |
| 5899 |
| 5900 // Parse the IPC message so the URL can be checked agains the expected one. |
| 5901 base::PickleIterator iter(message); |
| 5902 FrameHostMsg_DidCommitProvisionalLoad_Params validated_params; |
| 5903 if (!IPC::ParamTraits<FrameHostMsg_DidCommitProvisionalLoad_Params>::Read( |
| 5904 &message, &iter, &validated_params)) { |
| 5905 return false; |
| 5906 } |
| 5907 |
| 5908 // Only handle the message if the URLs are matching. |
| 5909 if (validated_params.url != url_) |
| 5910 return false; |
| 5911 |
| 5912 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, on_commit_); |
| 5913 return true; |
| 5914 } |
| 5915 |
| 5916 GURL url_; |
| 5917 base::Closure on_commit_; |
| 5918 |
| 5919 DISALLOW_COPY_AND_ASSIGN(CommitMessageFilter); |
| 5920 }; |
| 5921 |
| 5922 // Test which simulates a race condition between a cross-origin, same-process |
| 5923 // navigation and a same page session history navigation. When such a race |
| 5924 // occurs, the renderer will commit the cross-origin navigation, updating its |
| 5925 // version of the current document sequence number, and will send an IPC to the |
| 5926 // browser process. The session history navigation comes after the commit for |
| 5927 // the cross-origin navigation and updates the URL, but not the origin of the |
| 5928 // document. This results in mismatch between the two and causes the renderer |
| 5929 // process to be killed. See https://crbug.com/630103. |
| 5930 IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, |
| 5931 RaceCrossOriginNavigationAndSamePageHistoryNavigation) { |
| 5932 WebContentsImpl* web_contents = |
| 5933 static_cast<WebContentsImpl*>(shell()->web_contents()); |
| 5934 |
| 5935 // Navigate to a simple page and then perform an in-page navigation. |
| 5936 GURL start_url(embedded_test_server()->GetURL("a.com", "/title1.html")); |
| 5937 EXPECT_TRUE(NavigateToURL(shell(), start_url)); |
| 5938 |
| 5939 GURL same_page_url( |
| 5940 embedded_test_server()->GetURL("a.com", "/title1.html#foo")); |
| 5941 EXPECT_TRUE(NavigateToURL(shell(), same_page_url)); |
| 5942 EXPECT_EQ(2, web_contents->GetController().GetEntryCount()); |
| 5943 |
| 5944 // Create a CommitMessageFilter, which will drop the commit IPC for a |
| 5945 // cross-origin, same process navigation and will perform a GoBack. |
| 5946 GURL cross_origin_url( |
| 5947 embedded_test_server()->GetURL("suborigin.a.com", "/title2.html")); |
| 5948 scoped_refptr<CommitMessageFilter> filter = new CommitMessageFilter( |
| 5949 cross_origin_url, |
| 5950 base::Bind(&NavigationControllerImpl::GoBack, |
| 5951 base::Unretained(&web_contents->GetController()))); |
| 5952 web_contents->GetMainFrame()->GetProcess()->AddFilter(filter.get()); |
| 5953 |
| 5954 // Navigate cross-origin, which will fail and the back navigation should have |
| 5955 // succeeded. |
| 5956 EXPECT_FALSE(NavigateToURL(shell(), cross_origin_url)); |
| 5957 EXPECT_EQ(start_url, web_contents->GetLastCommittedURL()); |
| 5958 EXPECT_EQ(0, web_contents->GetController().GetLastCommittedEntryIndex()); |
| 5959 |
| 5960 // Verify the expected origin through JavaScript. It also has the additional |
| 5961 // verification of the process also being still alive. |
| 5962 std::string origin; |
| 5963 EXPECT_TRUE(ExecuteScriptAndExtractString( |
| 5964 web_contents, "domAutomationController.send(document.origin)", &origin)); |
| 5965 EXPECT_EQ(start_url.GetOrigin().spec(), origin + "/"); |
| 5966 } |
| 5967 |
5883 // Test that verifies that Referer and Origin http headers are correctly sent | 5968 // Test that verifies that Referer and Origin http headers are correctly sent |
5884 // to the final destination of a cross-site POST with a few redirects thrown in. | 5969 // to the final destination of a cross-site POST with a few redirects thrown in. |
5885 // This test is somewhat related to https://crbug.com/635400. | 5970 // This test is somewhat related to https://crbug.com/635400. |
5886 IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, | 5971 IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, |
5887 RefererAndOriginHeadersAfterRedirects) { | 5972 RefererAndOriginHeadersAfterRedirects) { |
5888 // Navigate to the page with form that posts via 307 redirection to | 5973 // Navigate to the page with form that posts via 307 redirection to |
5889 // |redirect_target_url| (cross-site from |form_url|). Using 307 (rather than | 5974 // |redirect_target_url| (cross-site from |form_url|). Using 307 (rather than |
5890 // 302) redirection is important to preserve the HTTP method and POST body. | 5975 // 302) redirection is important to preserve the HTTP method and POST body. |
5891 GURL form_url(embedded_test_server()->GetURL( | 5976 GURL form_url(embedded_test_server()->GetURL( |
5892 "a.com", "/form_that_posts_cross_site.html")); | 5977 "a.com", "/form_that_posts_cross_site.html")); |
(...skipping 24 matching lines...) Expand all Loading... |
5917 &headers)); | 6002 &headers)); |
5918 | 6003 |
5919 // Verify the Origin and Referer headers. | 6004 // Verify the Origin and Referer headers. |
5920 EXPECT_THAT(headers, ::testing::HasSubstr("Origin: null")); | 6005 EXPECT_THAT(headers, ::testing::HasSubstr("Origin: null")); |
5921 EXPECT_THAT(headers, | 6006 EXPECT_THAT(headers, |
5922 ::testing::ContainsRegex( | 6007 ::testing::ContainsRegex( |
5923 "Referer: http://a.com:.*/form_that_posts_cross_site.html")); | 6008 "Referer: http://a.com:.*/form_that_posts_cross_site.html")); |
5924 } | 6009 } |
5925 | 6010 |
5926 } // namespace content | 6011 } // namespace content |
OLD | NEW |