Chromium Code Reviews| 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" |
| (...skipping 5950 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 5961 } | 5961 } |
| 5962 | 5962 |
| 5963 // Verify the expected origin through JavaScript. It also has the additional | 5963 // Verify the expected origin through JavaScript. It also has the additional |
| 5964 // verification of the process also being still alive. | 5964 // verification of the process also being still alive. |
| 5965 std::string origin; | 5965 std::string origin; |
| 5966 EXPECT_TRUE(ExecuteScriptAndExtractString( | 5966 EXPECT_TRUE(ExecuteScriptAndExtractString( |
| 5967 web_contents, "domAutomationController.send(document.origin)", &origin)); | 5967 web_contents, "domAutomationController.send(document.origin)", &origin)); |
| 5968 EXPECT_EQ(start_url.GetOrigin().spec(), origin + "/"); | 5968 EXPECT_EQ(start_url.GetOrigin().spec(), origin + "/"); |
| 5969 } | 5969 } |
| 5970 | 5970 |
| 5971 // A BrowserMessageFilter that drops FrameHostMsg_DidCommitProvisionaLoad IPC | 5971 // A BrowserMessageFilter that delays FrameHostMsg_DidCommitProvisionaLoad IPC |
| 5972 // message for a specified URL and runs a callback on the UI thread. | 5972 // message for a specified URL, navigates the WebContents back and then |
| 5973 // processes the commit message. | |
| 5973 class CommitMessageFilter : public BrowserMessageFilter { | 5974 class CommitMessageFilter : public BrowserMessageFilter { |
|
Charlie Reis
2016/09/26 20:58:38
nit: Let's rename this now that it isn't general (
nasko
2016/09/26 22:03:49
Done.
| |
| 5974 public: | 5975 public: |
| 5975 CommitMessageFilter(const GURL& url, base::Closure on_commit) | 5976 CommitMessageFilter(const GURL& url, WebContentsImpl* web_contents) |
| 5976 : BrowserMessageFilter(FrameMsgStart), url_(url), on_commit_(on_commit) {} | 5977 : BrowserMessageFilter(FrameMsgStart), |
| 5978 url_(url), | |
| 5979 web_contents_(web_contents) {} | |
| 5977 | 5980 |
| 5978 protected: | 5981 protected: |
| 5979 ~CommitMessageFilter() override {} | 5982 ~CommitMessageFilter() override {} |
| 5980 | 5983 |
| 5981 private: | 5984 private: |
| 5985 static void NavigateBackAndCommit(const IPC::Message& message, | |
| 5986 WebContentsImpl* web_contents) { | |
| 5987 web_contents->GetController().GoBack(); | |
| 5988 | |
| 5989 RenderFrameHostImpl* rfh = web_contents->GetMainFrame(); | |
| 5990 DCHECK_EQ(rfh->routing_id(), message.routing_id()); | |
| 5991 rfh->OnMessageReceived(message); | |
| 5992 } | |
| 5993 | |
| 5982 // BrowserMessageFilter: | 5994 // BrowserMessageFilter: |
| 5983 bool OnMessageReceived(const IPC::Message& message) override { | 5995 bool OnMessageReceived(const IPC::Message& message) override { |
| 5984 if (message.type() != FrameHostMsg_DidCommitProvisionalLoad::ID) | 5996 if (message.type() != FrameHostMsg_DidCommitProvisionalLoad::ID) |
| 5985 return false; | 5997 return false; |
| 5986 | 5998 |
| 5987 // Parse the IPC message so the URL can be checked agains the expected one. | 5999 // Parse the IPC message so the URL can be checked agains the expected one. |
| 5988 base::PickleIterator iter(message); | 6000 base::PickleIterator iter(message); |
| 5989 FrameHostMsg_DidCommitProvisionalLoad_Params validated_params; | 6001 FrameHostMsg_DidCommitProvisionalLoad_Params validated_params; |
| 5990 if (!IPC::ParamTraits<FrameHostMsg_DidCommitProvisionalLoad_Params>::Read( | 6002 if (!IPC::ParamTraits<FrameHostMsg_DidCommitProvisionalLoad_Params>::Read( |
| 5991 &message, &iter, &validated_params)) { | 6003 &message, &iter, &validated_params)) { |
| 5992 return false; | 6004 return false; |
| 5993 } | 6005 } |
| 5994 | 6006 |
| 5995 // Only handle the message if the URLs are matching. | 6007 // Only handle the message if the URLs are matching. |
| 5996 if (validated_params.url != url_) | 6008 if (validated_params.url != url_) |
| 5997 return false; | 6009 return false; |
| 5998 | 6010 |
| 5999 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, on_commit_); | 6011 BrowserThread::PostTask( |
| 6012 BrowserThread::UI, FROM_HERE, | |
| 6013 base::Bind(&NavigateBackAndCommit, message, web_contents_)); | |
| 6000 return true; | 6014 return true; |
| 6001 } | 6015 } |
| 6002 | 6016 |
| 6003 GURL url_; | 6017 GURL url_; |
| 6004 base::Closure on_commit_; | 6018 WebContentsImpl* web_contents_; |
| 6005 | 6019 |
| 6006 DISALLOW_COPY_AND_ASSIGN(CommitMessageFilter); | 6020 DISALLOW_COPY_AND_ASSIGN(CommitMessageFilter); |
| 6007 }; | 6021 }; |
| 6008 | 6022 |
| 6009 // Test which simulates a race condition between a cross-origin, same-process | 6023 // Test which simulates a race condition between a cross-origin, same-process |
| 6010 // navigation and a same page session history navigation. When such a race | 6024 // navigation and a same page session history navigation. When such a race |
| 6011 // occurs, the renderer will commit the cross-origin navigation, updating its | 6025 // occurs, the renderer will commit the cross-origin navigation, updating its |
| 6012 // version of the current document sequence number, and will send an IPC to the | 6026 // version of the current document sequence number, and will send an IPC to the |
| 6013 // browser process. The session history navigation comes after the commit for | 6027 // browser process. The session history navigation comes after the commit for |
| 6014 // the cross-origin navigation and updates the URL, but not the origin of the | 6028 // the cross-origin navigation and updates the URL, but not the origin of the |
| 6015 // document. This results in mismatch between the two and causes the renderer | 6029 // document. This results in mismatch between the two and causes the renderer |
| 6016 // process to be killed. See https://crbug.com/630103. | 6030 // process to be killed. See https://crbug.com/630103. |
| 6017 // TODO(nasko): Investigate why this test is flaky, likely related to | 6031 IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, |
| 6018 // https://crbug.com/638089, and enable once resolved. | 6032 RaceCrossOriginNavigationAndSamePageHistoryNavigation) { |
| 6019 IN_PROC_BROWSER_TEST_F( | |
| 6020 NavigationControllerBrowserTest, | |
| 6021 DISABLED_RaceCrossOriginNavigationAndSamePageHistoryNavigation) { | |
| 6022 WebContentsImpl* web_contents = | 6033 WebContentsImpl* web_contents = |
| 6023 static_cast<WebContentsImpl*>(shell()->web_contents()); | 6034 static_cast<WebContentsImpl*>(shell()->web_contents()); |
| 6035 FrameTreeNode* root = web_contents->GetFrameTree()->root(); | |
| 6024 | 6036 |
| 6025 // Navigate to a simple page and then perform an in-page navigation. | 6037 // Navigate to a simple page and then perform an in-page navigation. |
| 6026 GURL start_url(embedded_test_server()->GetURL("a.com", "/title1.html")); | 6038 GURL start_url(embedded_test_server()->GetURL("a.com", "/title1.html")); |
| 6027 EXPECT_TRUE(NavigateToURL(shell(), start_url)); | 6039 EXPECT_TRUE(NavigateToURL(shell(), start_url)); |
| 6028 | 6040 |
| 6029 GURL same_page_url( | 6041 GURL same_page_url( |
| 6030 embedded_test_server()->GetURL("a.com", "/title1.html#foo")); | 6042 embedded_test_server()->GetURL("a.com", "/title1.html#foo")); |
| 6031 EXPECT_TRUE(NavigateToURL(shell(), same_page_url)); | 6043 EXPECT_TRUE(NavigateToURL(shell(), same_page_url)); |
| 6032 EXPECT_EQ(2, web_contents->GetController().GetEntryCount()); | 6044 EXPECT_EQ(2, web_contents->GetController().GetEntryCount()); |
| 6033 | 6045 |
| 6034 // Create a CommitMessageFilter, which will drop the commit IPC for a | 6046 // Create a CommitMessageFilter, which will delay the commit IPC for a |
| 6035 // cross-origin, same process navigation and will perform a GoBack. | 6047 // cross-origin, same process navigation and will perform a GoBack. |
| 6036 GURL cross_origin_url( | 6048 GURL cross_origin_url( |
| 6037 embedded_test_server()->GetURL("suborigin.a.com", "/title2.html")); | 6049 embedded_test_server()->GetURL("suborigin.a.com", "/title2.html")); |
| 6038 scoped_refptr<CommitMessageFilter> filter = new CommitMessageFilter( | 6050 scoped_refptr<CommitMessageFilter> filter = |
| 6039 cross_origin_url, | 6051 new CommitMessageFilter(cross_origin_url, web_contents); |
| 6040 base::Bind(&NavigationControllerImpl::GoBack, | |
| 6041 base::Unretained(&web_contents->GetController()))); | |
| 6042 web_contents->GetMainFrame()->GetProcess()->AddFilter(filter.get()); | 6052 web_contents->GetMainFrame()->GetProcess()->AddFilter(filter.get()); |
| 6043 | 6053 |
| 6044 // Navigate cross-origin, which will fail and the back navigation should have | 6054 // Navigate cross-origin, waiting for the commit to occur. |
| 6045 // succeeded. | 6055 UrlCommitObserver cross_origin_commit_observer(root, cross_origin_url); |
| 6046 EXPECT_FALSE(NavigateToURL(shell(), cross_origin_url)); | 6056 shell()->LoadURL(cross_origin_url); |
| 6057 cross_origin_commit_observer.Wait(); | |
| 6058 EXPECT_EQ(cross_origin_url, web_contents->GetLastCommittedURL()); | |
| 6059 EXPECT_EQ(2, web_contents->GetController().GetLastCommittedEntryIndex()); | |
| 6060 | |
| 6061 // Wait for the back navigation to commit as well. | |
| 6062 UrlCommitObserver history_commit_observer(root, start_url); | |
|
Charlie Reis
2016/09/26 20:58:38
Should we be declaring this before the LoadURL cal
nasko
2016/09/26 22:03:49
Done.
| |
| 6063 history_commit_observer.Wait(); | |
| 6047 EXPECT_EQ(start_url, web_contents->GetLastCommittedURL()); | 6064 EXPECT_EQ(start_url, web_contents->GetLastCommittedURL()); |
| 6048 EXPECT_EQ(0, web_contents->GetController().GetLastCommittedEntryIndex()); | 6065 EXPECT_EQ(0, web_contents->GetController().GetLastCommittedEntryIndex()); |
| 6049 | 6066 |
| 6050 // Verify the expected origin through JavaScript. It also has the additional | 6067 // Verify the expected origin through JavaScript. It also has the additional |
| 6051 // verification of the process also being still alive. | 6068 // verification of the process also being still alive. |
| 6052 std::string origin; | 6069 std::string origin; |
| 6053 EXPECT_TRUE(ExecuteScriptAndExtractString( | 6070 EXPECT_TRUE(ExecuteScriptAndExtractString( |
| 6054 web_contents, "domAutomationController.send(document.origin)", &origin)); | 6071 web_contents, "domAutomationController.send(document.origin)", &origin)); |
| 6055 EXPECT_EQ(start_url.GetOrigin().spec(), origin + "/"); | 6072 EXPECT_EQ(start_url.GetOrigin().spec(), origin + "/"); |
| 6056 } | 6073 } |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 6114 content::FaviconStatus& favicon_status2 = entry->GetFavicon(); | 6131 content::FaviconStatus& favicon_status2 = entry->GetFavicon(); |
| 6115 EXPECT_TRUE(favicon_status2.valid); | 6132 EXPECT_TRUE(favicon_status2.valid); |
| 6116 | 6133 |
| 6117 ASSERT_TRUE(RendererLocationReplace(shell(), GURL("data:text/html,page2"))); | 6134 ASSERT_TRUE(RendererLocationReplace(shell(), GURL("data:text/html,page2"))); |
| 6118 entry = controller.GetLastCommittedEntry(); | 6135 entry = controller.GetLastCommittedEntry(); |
| 6119 content::FaviconStatus& favicon_status3 = entry->GetFavicon(); | 6136 content::FaviconStatus& favicon_status3 = entry->GetFavicon(); |
| 6120 EXPECT_FALSE(favicon_status3.valid); | 6137 EXPECT_FALSE(favicon_status3.valid); |
| 6121 } | 6138 } |
| 6122 | 6139 |
| 6123 } // namespace content | 6140 } // namespace content |
| OLD | NEW |