| 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 "base/bind.h" | 5 #include "base/bind.h" |
| 6 #include "base/strings/stringprintf.h" | 6 #include "base/strings/stringprintf.h" |
| 7 #include "content/browser/frame_host/frame_tree.h" | 7 #include "content/browser/frame_host/frame_tree.h" |
| 8 #include "content/browser/frame_host/navigation_controller_impl.h" | 8 #include "content/browser/frame_host/navigation_controller_impl.h" |
| 9 #include "content/browser/frame_host/navigation_entry_impl.h" | 9 #include "content/browser/frame_host/navigation_entry_impl.h" |
| 10 #include "content/browser/web_contents/web_contents_impl.h" | 10 #include "content/browser/web_contents/web_contents_impl.h" |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 165 | 165 |
| 166 // Again, as above, there's no way to access the renderer's notion of the | 166 // Again, as above, there's no way to access the renderer's notion of the |
| 167 // history offset via JavaScript. Checking just the history length, again, | 167 // history offset via JavaScript. Checking just the history length, again, |
| 168 // will have to suffice. | 168 // will have to suffice. |
| 169 } | 169 } |
| 170 | 170 |
| 171 namespace { | 171 namespace { |
| 172 | 172 |
| 173 struct FrameNavigateParamsCapturer : public WebContentsObserver { | 173 struct FrameNavigateParamsCapturer : public WebContentsObserver { |
| 174 public: | 174 public: |
| 175 // Observes navigation for the specified |node|. |
| 175 explicit FrameNavigateParamsCapturer(FrameTreeNode* node) | 176 explicit FrameNavigateParamsCapturer(FrameTreeNode* node) |
| 176 : WebContentsObserver( | 177 : WebContentsObserver( |
| 177 node->current_frame_host()->delegate()->GetAsWebContents()), | 178 node->current_frame_host()->delegate()->GetAsWebContents()), |
| 178 frame_tree_node_id_(node->frame_tree_node_id()), | 179 frame_tree_node_id_(node->frame_tree_node_id()), |
| 179 message_loop_runner_(new MessageLoopRunner) {} | 180 message_loop_runner_(new MessageLoopRunner) {} |
| 180 | 181 |
| 181 void Wait() { | 182 void Wait() { |
| 182 message_loop_runner_->Run(); | 183 message_loop_runner_->Run(); |
| 183 } | 184 } |
| 184 | 185 |
| (...skipping 25 matching lines...) Expand all Loading... |
| 210 // The params of the last navigation. | 211 // The params of the last navigation. |
| 211 FrameNavigateParams params_; | 212 FrameNavigateParams params_; |
| 212 | 213 |
| 213 // The details of the last navigation. | 214 // The details of the last navigation. |
| 214 LoadCommittedDetails details_; | 215 LoadCommittedDetails details_; |
| 215 | 216 |
| 216 // The MessageLoopRunner used to spin the message loop. | 217 // The MessageLoopRunner used to spin the message loop. |
| 217 scoped_refptr<MessageLoopRunner> message_loop_runner_; | 218 scoped_refptr<MessageLoopRunner> message_loop_runner_; |
| 218 }; | 219 }; |
| 219 | 220 |
| 221 struct LoadCommittedCapturer : public WebContentsObserver { |
| 222 public: |
| 223 // Observes the load commit for the specified |node|. |
| 224 explicit LoadCommittedCapturer(FrameTreeNode* node) |
| 225 : WebContentsObserver( |
| 226 node->current_frame_host()->delegate()->GetAsWebContents()), |
| 227 frame_tree_node_id_(node->frame_tree_node_id()), |
| 228 message_loop_runner_(new MessageLoopRunner) {} |
| 229 |
| 230 // Observes the load commit for the next created frame in the specified |
| 231 // |web_contents|. |
| 232 explicit LoadCommittedCapturer(WebContents* web_contents) |
| 233 : WebContentsObserver(web_contents), |
| 234 frame_tree_node_id_(0), |
| 235 message_loop_runner_(new MessageLoopRunner) {} |
| 236 |
| 237 void Wait() { |
| 238 message_loop_runner_->Run(); |
| 239 } |
| 240 |
| 241 ui::PageTransition transition_type() const { |
| 242 return transition_type_; |
| 243 } |
| 244 |
| 245 private: |
| 246 void RenderFrameCreated(RenderFrameHost* render_frame_host) override { |
| 247 // If this object was created with a specified tree frame node, there |
| 248 // shouldn't be any frames being created. |
| 249 DCHECK_EQ(0, frame_tree_node_id_); |
| 250 RenderFrameHostImpl* rfh = |
| 251 static_cast<RenderFrameHostImpl*>(render_frame_host); |
| 252 frame_tree_node_id_ = rfh->frame_tree_node()->frame_tree_node_id(); |
| 253 } |
| 254 |
| 255 void DidCommitProvisionalLoadForFrame( |
| 256 RenderFrameHost* render_frame_host, |
| 257 const GURL& url, |
| 258 ui::PageTransition transition_type) override { |
| 259 DCHECK_NE(0, frame_tree_node_id_); |
| 260 RenderFrameHostImpl* rfh = |
| 261 static_cast<RenderFrameHostImpl*>(render_frame_host); |
| 262 if (rfh->frame_tree_node()->frame_tree_node_id() != frame_tree_node_id_) |
| 263 return; |
| 264 |
| 265 transition_type_ = transition_type; |
| 266 message_loop_runner_->Quit(); |
| 267 } |
| 268 |
| 269 // The id of the FrameTreeNode whose navigations to observe. |
| 270 int frame_tree_node_id_; |
| 271 |
| 272 // The transition_type of the last navigation. |
| 273 ui::PageTransition transition_type_; |
| 274 |
| 275 // The MessageLoopRunner used to spin the message loop. |
| 276 scoped_refptr<MessageLoopRunner> message_loop_runner_; |
| 277 }; |
| 278 |
| 220 } // namespace | 279 } // namespace |
| 221 | 280 |
| 222 // Verify that the distinction between manual and auto subframes is properly set | 281 // Verify that the distinction between manual and auto subframes is properly set |
| 223 // for subframe navigations. TODO(avi): It's rather bogus that the same info is | 282 // for subframe navigations. TODO(avi): It's rather bogus that the same info is |
| 224 // in two different enums; http://crbug.com/453555. | 283 // in two different enums; http://crbug.com/453555. |
| 225 IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, | 284 IN_PROC_BROWSER_TEST_F(NavigationControllerBrowserTest, |
| 226 ManualAndAutoSubframeNavigationClassification) { | 285 ManualAndAutoSubframeNavigationClassification) { |
| 227 GURL main_url( | 286 GURL main_url(embedded_test_server()->GetURL( |
| 228 embedded_test_server()->GetURL("/frame_tree/page_with_one_frame.html")); | 287 "/navigation_controller/page_with_iframe.html")); |
| 229 NavigateToURL(shell(), main_url); | 288 NavigateToURL(shell(), main_url); |
| 230 | 289 |
| 231 // It is safe to obtain the root frame tree node here, as it doesn't change. | 290 // It is safe to obtain the root frame tree node here, as it doesn't change. |
| 232 FrameTreeNode* root = | 291 FrameTreeNode* root = |
| 233 static_cast<WebContentsImpl*>(shell()->web_contents())-> | 292 static_cast<WebContentsImpl*>(shell()->web_contents())-> |
| 234 GetFrameTree()->root(); | 293 GetFrameTree()->root(); |
| 235 | 294 |
| 236 ASSERT_EQ(1U, root->child_count()); | 295 ASSERT_EQ(1U, root->child_count()); |
| 237 ASSERT_NE(nullptr, root->child_at(0)); | 296 ASSERT_NE(nullptr, root->child_at(0)); |
| 238 | 297 |
| 239 { | 298 { |
| 240 // Navigate the iframe to a new URL; expect a manual subframe transition. | 299 // Navigate the iframe to a new URL; expect a manual subframe transition. |
| 241 FrameNavigateParamsCapturer capturer(root->child_at(0)); | 300 FrameNavigateParamsCapturer capturer(root->child_at(0)); |
| 242 GURL frame_url( | 301 GURL frame_url(embedded_test_server()->GetURL( |
| 243 embedded_test_server()->GetURL("/frame_tree/2-1.html")); | 302 "/navigation_controller/simple_page_1.html")); |
| 244 NavigateFrameToURL(root->child_at(0), frame_url); | 303 NavigateFrameToURL(root->child_at(0), frame_url); |
| 245 capturer.Wait(); | 304 capturer.Wait(); |
| 246 EXPECT_EQ(ui::PAGE_TRANSITION_MANUAL_SUBFRAME, | 305 EXPECT_EQ(ui::PAGE_TRANSITION_MANUAL_SUBFRAME, |
| 247 capturer.params().transition); | 306 capturer.params().transition); |
| 248 EXPECT_EQ(NAVIGATION_TYPE_NEW_SUBFRAME, capturer.details().type); | 307 EXPECT_EQ(NAVIGATION_TYPE_NEW_SUBFRAME, capturer.details().type); |
| 249 } | 308 } |
| 250 | 309 |
| 251 { | 310 { |
| 252 // History navigations should result in an auto subframe transition. | 311 // Do a history navigation; expect an auto subframe transition. |
| 253 FrameNavigateParamsCapturer capturer(root->child_at(0)); | 312 FrameNavigateParamsCapturer capturer(root->child_at(0)); |
| 254 shell()->web_contents()->GetController().GoBack(); | 313 shell()->web_contents()->GetController().GoBack(); |
| 255 capturer.Wait(); | 314 capturer.Wait(); |
| 256 EXPECT_EQ(ui::PAGE_TRANSITION_AUTO_SUBFRAME, capturer.params().transition); | 315 EXPECT_EQ(ui::PAGE_TRANSITION_AUTO_SUBFRAME, capturer.params().transition); |
| 257 EXPECT_EQ(NAVIGATION_TYPE_AUTO_SUBFRAME, capturer.details().type); | 316 EXPECT_EQ(NAVIGATION_TYPE_AUTO_SUBFRAME, capturer.details().type); |
| 258 } | 317 } |
| 259 | 318 |
| 260 { | 319 { |
| 261 // History navigations should result in an auto subframe transition. | 320 // Do a history navigation; expect an auto subframe transition. |
| 262 FrameNavigateParamsCapturer capturer(root->child_at(0)); | 321 FrameNavigateParamsCapturer capturer(root->child_at(0)); |
| 263 shell()->web_contents()->GetController().GoForward(); | 322 shell()->web_contents()->GetController().GoForward(); |
| 264 capturer.Wait(); | 323 capturer.Wait(); |
| 265 EXPECT_EQ(ui::PAGE_TRANSITION_AUTO_SUBFRAME, capturer.params().transition); | 324 EXPECT_EQ(ui::PAGE_TRANSITION_AUTO_SUBFRAME, capturer.params().transition); |
| 266 EXPECT_EQ(NAVIGATION_TYPE_AUTO_SUBFRAME, capturer.details().type); | 325 EXPECT_EQ(NAVIGATION_TYPE_AUTO_SUBFRAME, capturer.details().type); |
| 267 } | 326 } |
| 268 | 327 |
| 269 { | 328 { |
| 270 // Navigate the iframe to a new URL; expect a manual subframe transition. | 329 // Navigate the iframe to a new URL; expect a manual subframe transition. |
| 271 FrameNavigateParamsCapturer capturer(root->child_at(0)); | 330 FrameNavigateParamsCapturer capturer(root->child_at(0)); |
| 272 GURL frame_url( | 331 GURL frame_url(embedded_test_server()->GetURL( |
| 273 embedded_test_server()->GetURL("/frame_tree/2-3.html")); | 332 "/navigation_controller/simple_page_2.html")); |
| 274 NavigateFrameToURL(root->child_at(0), frame_url); | 333 NavigateFrameToURL(root->child_at(0), frame_url); |
| 275 capturer.Wait(); | 334 capturer.Wait(); |
| 276 EXPECT_EQ(ui::PAGE_TRANSITION_MANUAL_SUBFRAME, | 335 EXPECT_EQ(ui::PAGE_TRANSITION_MANUAL_SUBFRAME, |
| 277 capturer.params().transition); | 336 capturer.params().transition); |
| 278 EXPECT_EQ(NAVIGATION_TYPE_NEW_SUBFRAME, capturer.details().type); | 337 EXPECT_EQ(NAVIGATION_TYPE_NEW_SUBFRAME, capturer.details().type); |
| 279 } | 338 } |
| 339 |
| 340 { |
| 341 // Use location.assign(); expect a manual subframe transition. |
| 342 FrameNavigateParamsCapturer capturer(root->child_at(0)); |
| 343 GURL frame_url(embedded_test_server()->GetURL( |
| 344 "/navigation_controller/simple_page_1.html")); |
| 345 std::string script = "location.assign('" + frame_url.spec() + "')"; |
| 346 EXPECT_TRUE(content::ExecuteScript(root->child_at(0)->current_frame_host(), |
| 347 script)); |
| 348 capturer.Wait(); |
| 349 EXPECT_EQ(ui::PAGE_TRANSITION_MANUAL_SUBFRAME, |
| 350 capturer.params().transition); |
| 351 EXPECT_EQ(NAVIGATION_TYPE_NEW_SUBFRAME, capturer.details().type); |
| 352 } |
| 353 |
| 354 { |
| 355 // Use location.replace(); expect an auto subframe transition. (Replacements |
| 356 // aren't "navigation" so we only see the frame load committing.) |
| 357 LoadCommittedCapturer capturer(root->child_at(0)); |
| 358 GURL frame_url(embedded_test_server()->GetURL( |
| 359 "/navigation_controller/simple_page_2.html")); |
| 360 std::string script = "location.replace('" + frame_url.spec() + "')"; |
| 361 EXPECT_TRUE(content::ExecuteScript(root->child_at(0)->current_frame_host(), |
| 362 script)); |
| 363 capturer.Wait(); |
| 364 EXPECT_EQ(ui::PAGE_TRANSITION_AUTO_SUBFRAME, capturer.transition_type()); |
| 365 } |
| 366 |
| 367 { |
| 368 // Reload the subframe; expect an auto subframe transition. (Reloads aren't |
| 369 // "navigation" so we only see the frame load committing.) |
| 370 LoadCommittedCapturer capturer(root->child_at(0)); |
| 371 EXPECT_TRUE(content::ExecuteScript(root->child_at(0)->current_frame_host(), |
| 372 "location.reload()")); |
| 373 capturer.Wait(); |
| 374 EXPECT_EQ(ui::PAGE_TRANSITION_AUTO_SUBFRAME, capturer.transition_type()); |
| 375 } |
| 376 |
| 377 { |
| 378 // Create an iframe; expect an auto subframe transition. (Initial frame |
| 379 // creation isn't "navigation" so we only see the frame load committing.) |
| 380 LoadCommittedCapturer capturer(shell()->web_contents()); |
| 381 GURL frame_url(embedded_test_server()->GetURL( |
| 382 "/navigation_controller/simple_page_1.html")); |
| 383 std::string script = "var iframe = document.createElement('iframe');" |
| 384 "iframe.src = '" + frame_url.spec() + "';" |
| 385 "document.body.appendChild(iframe);"; |
| 386 EXPECT_TRUE(content::ExecuteScript(root->current_frame_host(), script)); |
| 387 capturer.Wait(); |
| 388 EXPECT_EQ(ui::PAGE_TRANSITION_AUTO_SUBFRAME, capturer.transition_type()); |
| 389 } |
| 280 } | 390 } |
| 281 | 391 |
| 282 } // namespace content | 392 } // namespace content |
| OLD | NEW |