| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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_handle_impl.h" | 5 #include "content/browser/frame_host/navigation_handle_impl.h" |
| 6 #include "content/browser/web_contents/web_contents_impl.h" |
| 6 #include "content/public/browser/web_contents.h" | 7 #include "content/public/browser/web_contents.h" |
| 7 #include "content/public/browser/web_contents_observer.h" | 8 #include "content/public/browser/web_contents_observer.h" |
| 8 #include "content/public/test/browser_test_utils.h" | 9 #include "content/public/test/browser_test_utils.h" |
| 9 #include "content/public/test/content_browser_test.h" | 10 #include "content/public/test/content_browser_test.h" |
| 10 #include "content/public/test/content_browser_test_utils.h" | 11 #include "content/public/test/content_browser_test_utils.h" |
| 11 #include "content/shell/browser/shell.h" | 12 #include "content/shell/browser/shell.h" |
| 12 #include "net/dns/mock_host_resolver.h" | 13 #include "net/dns/mock_host_resolver.h" |
| 13 #include "ui/base/page_transition_types.h" | 14 #include "ui/base/page_transition_types.h" |
| 15 #include "url/url_constants.h" |
| 14 | 16 |
| 15 namespace content { | 17 namespace content { |
| 16 | 18 |
| 17 namespace { | 19 namespace { |
| 18 | 20 |
| 19 class NavigationHandleObserver : public WebContentsObserver { | 21 class NavigationHandleObserver : public WebContentsObserver { |
| 20 public: | 22 public: |
| 21 NavigationHandleObserver(WebContents* web_contents, const GURL& expected_url) | 23 NavigationHandleObserver(WebContents* web_contents, const GURL& expected_url) |
| 22 : WebContentsObserver(web_contents), | 24 : WebContentsObserver(web_contents), |
| 23 handle_(nullptr), | 25 handle_(nullptr), |
| 24 has_committed_(false), | 26 has_committed_(false), |
| 25 is_error_(false), | 27 is_error_(false), |
| 28 is_main_frame_(false), |
| 29 is_parent_main_frame_(false), |
| 30 is_synchronous_(false), |
| 31 is_srcdoc_(false), |
| 32 was_redirected_(false), |
| 33 frame_tree_node_id_(-1), |
| 26 page_transition_(ui::PAGE_TRANSITION_LINK), | 34 page_transition_(ui::PAGE_TRANSITION_LINK), |
| 27 expected_url_(expected_url) {} | 35 expected_url_(expected_url) {} |
| 28 | 36 |
| 29 void DidStartNavigation(NavigationHandle* navigation_handle) override { | 37 void DidStartNavigation(NavigationHandle* navigation_handle) override { |
| 30 if (handle_ || navigation_handle->GetURL() != expected_url_) | 38 if (handle_ || navigation_handle->GetURL() != expected_url_) |
| 31 return; | 39 return; |
| 32 | 40 |
| 33 handle_ = navigation_handle; | 41 handle_ = navigation_handle; |
| 34 has_committed_ = false; | 42 has_committed_ = false; |
| 35 is_error_ = false; | 43 is_error_ = false; |
| 36 page_transition_ = ui::PAGE_TRANSITION_LINK; | 44 page_transition_ = ui::PAGE_TRANSITION_LINK; |
| 37 last_committed_url_ = GURL(); | 45 last_committed_url_ = GURL(); |
| 46 |
| 47 is_main_frame_ = navigation_handle->IsInMainFrame(); |
| 48 is_parent_main_frame_ = navigation_handle->IsParentMainFrame(); |
| 49 is_synchronous_ = navigation_handle->IsSynchronousNavigation(); |
| 50 is_srcdoc_ = navigation_handle->IsSrcdoc(); |
| 51 was_redirected_ = navigation_handle->WasServerRedirect(); |
| 52 frame_tree_node_id_ = navigation_handle->GetFrameTreeNodeId(); |
| 38 } | 53 } |
| 39 | 54 |
| 40 void DidFinishNavigation(NavigationHandle* navigation_handle) override { | 55 void DidFinishNavigation(NavigationHandle* navigation_handle) override { |
| 41 if (navigation_handle != handle_) | 56 if (navigation_handle != handle_) |
| 42 return; | 57 return; |
| 43 | 58 |
| 59 DCHECK_EQ(is_main_frame_, navigation_handle->IsInMainFrame()); |
| 60 DCHECK_EQ(is_parent_main_frame_, navigation_handle->IsParentMainFrame()); |
| 61 DCHECK_EQ(is_synchronous_, navigation_handle->IsSynchronousNavigation()); |
| 62 DCHECK_EQ(is_srcdoc_, navigation_handle->IsSrcdoc()); |
| 63 DCHECK_EQ(frame_tree_node_id_, navigation_handle->GetFrameTreeNodeId()); |
| 64 |
| 65 was_redirected_ = navigation_handle->WasServerRedirect(); |
| 66 |
| 44 if (navigation_handle->HasCommitted()) { | 67 if (navigation_handle->HasCommitted()) { |
| 45 has_committed_ = true; | 68 has_committed_ = true; |
| 46 if (!navigation_handle->IsErrorPage()) { | 69 if (!navigation_handle->IsErrorPage()) { |
| 47 page_transition_ = navigation_handle->GetPageTransition(); | 70 page_transition_ = navigation_handle->GetPageTransition(); |
| 48 last_committed_url_ = navigation_handle->GetURL(); | 71 last_committed_url_ = navigation_handle->GetURL(); |
| 49 } else { | 72 } else { |
| 50 is_error_ = true; | 73 is_error_ = true; |
| 51 } | 74 } |
| 52 } else { | 75 } else { |
| 53 has_committed_ = false; | 76 has_committed_ = false; |
| 54 is_error_ = true; | 77 is_error_ = true; |
| 55 } | 78 } |
| 56 | 79 |
| 57 handle_ = nullptr; | 80 handle_ = nullptr; |
| 58 } | 81 } |
| 59 | 82 |
| 60 bool has_committed() { return has_committed_; } | 83 bool has_committed() { return has_committed_; } |
| 61 | |
| 62 bool is_error() { return is_error_; } | 84 bool is_error() { return is_error_; } |
| 85 bool is_main_frame() { return is_main_frame_; } |
| 86 bool is_parent_main_frame() { return is_parent_main_frame_; } |
| 87 bool is_synchronous() { return is_synchronous_; } |
| 88 bool is_srcdoc() { return is_srcdoc_; } |
| 89 bool was_redirected() { return was_redirected_; } |
| 90 int frame_tree_node_id() { return frame_tree_node_id_; } |
| 63 | 91 |
| 64 const GURL& last_committed_url() { return last_committed_url_; } | 92 const GURL& last_committed_url() { return last_committed_url_; } |
| 65 | 93 |
| 66 ui::PageTransition page_transition() { return page_transition_; } | 94 ui::PageTransition page_transition() { return page_transition_; } |
| 67 | 95 |
| 68 private: | 96 private: |
| 69 // A reference to the NavigationHandle so this class will track only | 97 // A reference to the NavigationHandle so this class will track only |
| 70 // one navigation at a time. It is set at DidStartNavigation and cleared | 98 // one navigation at a time. It is set at DidStartNavigation and cleared |
| 71 // at DidFinishNavigation before the NavigationHandle is destroyed. | 99 // at DidFinishNavigation before the NavigationHandle is destroyed. |
| 72 NavigationHandle* handle_; | 100 NavigationHandle* handle_; |
| 73 bool has_committed_; | 101 bool has_committed_; |
| 74 bool is_error_; | 102 bool is_error_; |
| 103 bool is_main_frame_; |
| 104 bool is_parent_main_frame_; |
| 105 bool is_synchronous_; |
| 106 bool is_srcdoc_; |
| 107 bool was_redirected_; |
| 108 int frame_tree_node_id_; |
| 75 ui::PageTransition page_transition_; | 109 ui::PageTransition page_transition_; |
| 76 GURL expected_url_; | 110 GURL expected_url_; |
| 77 GURL last_committed_url_; | 111 GURL last_committed_url_; |
| 78 }; | 112 }; |
| 79 | 113 |
| 80 } // namespace | 114 } // namespace |
| 81 | 115 |
| 82 class NavigationHandleImplBrowserTest : public ContentBrowserTest { | 116 class NavigationHandleImplBrowserTest : public ContentBrowserTest { |
| 83 protected: | 117 protected: |
| 84 void SetUpOnMainThread() override { | 118 void SetUpOnMainThread() override { |
| 85 host_resolver()->AddRule("*", "127.0.0.1"); | 119 host_resolver()->AddRule("*", "127.0.0.1"); |
| 86 ASSERT_TRUE(embedded_test_server()->Start()); | 120 ASSERT_TRUE(embedded_test_server()->Start()); |
| 87 SetupCrossSiteRedirector(embedded_test_server()); | 121 SetupCrossSiteRedirector(embedded_test_server()); |
| 88 } | 122 } |
| 89 }; | 123 }; |
| 90 | 124 |
| 91 // Ensure that PageTransition is properly set on the NavigationHandle. | 125 // Ensure that PageTransition is properly set on the NavigationHandle. |
| 92 IN_PROC_BROWSER_TEST_F(NavigationHandleImplBrowserTest, VerifyPageTransition) { | 126 IN_PROC_BROWSER_TEST_F(NavigationHandleImplBrowserTest, VerifyPageTransition) { |
| 93 { | 127 { |
| 94 // Test browser initiated navigation, which should have a PageTransition as | 128 // Test browser initiated navigation, which should have a PageTransition as |
| 95 // if it came from the omnibox. | 129 // if it came from the omnibox. |
| 96 GURL url(embedded_test_server()->GetURL("/title1.html")); | 130 GURL url(embedded_test_server()->GetURL("/title1.html")); |
| 97 NavigationHandleObserver observer(shell()->web_contents(), url); | 131 NavigationHandleObserver observer(shell()->web_contents(), url); |
| 98 ui::PageTransition expected_transition = ui::PageTransitionFromInt( | 132 ui::PageTransition expected_transition = ui::PageTransitionFromInt( |
| 99 ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR); | 133 ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR); |
| 100 | 134 |
| 101 NavigateToURL(shell(), url); | 135 EXPECT_TRUE(NavigateToURL(shell(), url)); |
| 136 |
| 102 EXPECT_TRUE(observer.has_committed()); | 137 EXPECT_TRUE(observer.has_committed()); |
| 103 EXPECT_FALSE(observer.is_error()); | 138 EXPECT_FALSE(observer.is_error()); |
| 104 EXPECT_EQ(url, observer.last_committed_url()); | 139 EXPECT_EQ(url, observer.last_committed_url()); |
| 105 EXPECT_EQ(expected_transition, observer.page_transition()); | 140 EXPECT_EQ(expected_transition, observer.page_transition()); |
| 106 } | 141 } |
| 107 | 142 |
| 108 { | 143 { |
| 109 // Test navigating to a page with subframe. The subframe will have | 144 // Test navigating to a page with subframe. The subframe will have |
| 110 // PageTransition of type AUTO_SUBFRAME. | 145 // PageTransition of type AUTO_SUBFRAME. |
| 111 GURL url( | 146 GURL url( |
| 112 embedded_test_server()->GetURL("/frame_tree/page_with_one_frame.html")); | 147 embedded_test_server()->GetURL("/frame_tree/page_with_one_frame.html")); |
| 113 NavigationHandleObserver observer( | 148 NavigationHandleObserver observer( |
| 114 shell()->web_contents(), | 149 shell()->web_contents(), |
| 115 embedded_test_server()->GetURL("/cross-site/baz.com/title1.html")); | 150 embedded_test_server()->GetURL("/cross-site/baz.com/title1.html")); |
| 116 ui::PageTransition expected_transition = | 151 ui::PageTransition expected_transition = |
| 117 ui::PageTransitionFromInt(ui::PAGE_TRANSITION_AUTO_SUBFRAME); | 152 ui::PageTransitionFromInt(ui::PAGE_TRANSITION_AUTO_SUBFRAME); |
| 118 | 153 |
| 119 NavigateToURL(shell(), url); | 154 EXPECT_TRUE(NavigateToURL(shell(), url)); |
| 155 |
| 120 EXPECT_TRUE(observer.has_committed()); | 156 EXPECT_TRUE(observer.has_committed()); |
| 121 EXPECT_FALSE(observer.is_error()); | 157 EXPECT_FALSE(observer.is_error()); |
| 122 EXPECT_EQ(embedded_test_server()->GetURL("baz.com", "/title1.html"), | 158 EXPECT_EQ(embedded_test_server()->GetURL("baz.com", "/title1.html"), |
| 123 observer.last_committed_url()); | 159 observer.last_committed_url()); |
| 124 EXPECT_EQ(expected_transition, observer.page_transition()); | 160 EXPECT_EQ(expected_transition, observer.page_transition()); |
| 161 EXPECT_FALSE(observer.is_main_frame()); |
| 125 } | 162 } |
| 126 } | 163 } |
| 127 | 164 |
| 165 // Ensure that the following methods on NavigationHandle behave correctly: |
| 166 // * IsInMainFrame |
| 167 // * IsParentMainFrame |
| 168 IN_PROC_BROWSER_TEST_F(NavigationHandleImplBrowserTest, VerifyFrameTree) { |
| 169 GURL main_url(embedded_test_server()->GetURL( |
| 170 "a.com", "/cross_site_iframe_factory.html?a(b(c))")); |
| 171 GURL b_url(embedded_test_server()->GetURL( |
| 172 "b.com", "/cross_site_iframe_factory.html?b(c())")); |
| 173 GURL c_url(embedded_test_server()->GetURL( |
| 174 "c.com", "/cross_site_iframe_factory.html?c()")); |
| 175 |
| 176 NavigationHandleObserver main_observer(shell()->web_contents(), main_url); |
| 177 NavigationHandleObserver b_observer(shell()->web_contents(), b_url); |
| 178 NavigationHandleObserver c_observer(shell()->web_contents(), c_url); |
| 179 |
| 180 EXPECT_TRUE(NavigateToURL(shell(), main_url)); |
| 181 |
| 182 FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents()) |
| 183 ->GetFrameTree() |
| 184 ->root(); |
| 185 |
| 186 // Verify the main frame. |
| 187 EXPECT_TRUE(main_observer.has_committed()); |
| 188 EXPECT_FALSE(main_observer.is_error()); |
| 189 EXPECT_EQ(main_url, main_observer.last_committed_url()); |
| 190 EXPECT_TRUE(main_observer.is_main_frame()); |
| 191 EXPECT_EQ(root->frame_tree_node_id(), main_observer.frame_tree_node_id()); |
| 192 |
| 193 // Verify the b.com frame. |
| 194 EXPECT_TRUE(b_observer.has_committed()); |
| 195 EXPECT_FALSE(b_observer.is_error()); |
| 196 EXPECT_EQ(b_url, b_observer.last_committed_url()); |
| 197 EXPECT_FALSE(b_observer.is_main_frame()); |
| 198 EXPECT_TRUE(b_observer.is_parent_main_frame()); |
| 199 EXPECT_EQ(root->child_at(0)->frame_tree_node_id(), |
| 200 b_observer.frame_tree_node_id()); |
| 201 |
| 202 // Verify the c.com frame. |
| 203 EXPECT_TRUE(c_observer.has_committed()); |
| 204 EXPECT_FALSE(c_observer.is_error()); |
| 205 EXPECT_EQ(c_url, c_observer.last_committed_url()); |
| 206 EXPECT_FALSE(c_observer.is_main_frame()); |
| 207 EXPECT_FALSE(c_observer.is_parent_main_frame()); |
| 208 EXPECT_EQ(root->child_at(0)->child_at(0)->frame_tree_node_id(), |
| 209 c_observer.frame_tree_node_id()); |
| 210 } |
| 211 |
| 212 // Ensure that the WasRedirected() method on NavigationHandle behaves correctly. |
| 213 IN_PROC_BROWSER_TEST_F(NavigationHandleImplBrowserTest, VerifyRedirect) { |
| 214 { |
| 215 GURL url(embedded_test_server()->GetURL("/title1.html")); |
| 216 NavigationHandleObserver observer(shell()->web_contents(), url); |
| 217 |
| 218 EXPECT_TRUE(NavigateToURL(shell(), url)); |
| 219 |
| 220 EXPECT_TRUE(observer.has_committed()); |
| 221 EXPECT_FALSE(observer.is_error()); |
| 222 EXPECT_FALSE(observer.was_redirected()); |
| 223 } |
| 224 |
| 225 { |
| 226 GURL url(embedded_test_server()->GetURL("/cross-site/baz.com/title1.html")); |
| 227 NavigationHandleObserver observer(shell()->web_contents(), url); |
| 228 |
| 229 NavigateToURL(shell(), url); |
| 230 |
| 231 EXPECT_TRUE(observer.has_committed()); |
| 232 EXPECT_FALSE(observer.is_error()); |
| 233 EXPECT_TRUE(observer.was_redirected()); |
| 234 } |
| 235 } |
| 236 |
| 237 // Ensure that the IsSrcdoc() method on NavigationHandle behaves correctly. |
| 238 IN_PROC_BROWSER_TEST_F(NavigationHandleImplBrowserTest, VerifySrcdoc) { |
| 239 GURL url(embedded_test_server()->GetURL( |
| 240 "/frame_tree/page_with_srcdoc_frame.html")); |
| 241 NavigationHandleObserver observer(shell()->web_contents(), |
| 242 GURL(url::kAboutBlankURL)); |
| 243 |
| 244 EXPECT_TRUE(NavigateToURL(shell(), url)); |
| 245 |
| 246 EXPECT_TRUE(observer.has_committed()); |
| 247 EXPECT_FALSE(observer.is_error()); |
| 248 EXPECT_TRUE(observer.is_srcdoc()); |
| 249 } |
| 250 |
| 251 // Ensure that the IsSynchronousNavigation() method on NavigationHandle behaves |
| 252 // correctly. |
| 253 IN_PROC_BROWSER_TEST_F(NavigationHandleImplBrowserTest, VerifySynchronous) { |
| 254 GURL url(embedded_test_server()->GetURL( |
| 255 "a.com", "/cross_site_iframe_factory.html?a(a())")); |
| 256 EXPECT_TRUE(NavigateToURL(shell(), url)); |
| 257 |
| 258 FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents()) |
| 259 ->GetFrameTree() |
| 260 ->root(); |
| 261 |
| 262 NavigationHandleObserver observer( |
| 263 shell()->web_contents(), embedded_test_server()->GetURL("a.com", "/bar")); |
| 264 EXPECT_TRUE(ExecuteScript(root->child_at(0)->current_frame_host(), |
| 265 "window.history.pushState({}, '', 'bar');")); |
| 266 |
| 267 EXPECT_TRUE(observer.has_committed()); |
| 268 EXPECT_FALSE(observer.is_error()); |
| 269 EXPECT_TRUE(observer.is_synchronous()); |
| 270 } |
| 271 |
| 128 } // namespace content | 272 } // namespace content |
| OLD | NEW |