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 |