| 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 "core/frame/FrameHost.h" | 5 #include "core/frame/FrameHost.h" |
| 6 #include "core/frame/FrameView.h" | 6 #include "core/frame/FrameView.h" |
| 7 #include "core/frame/TopControls.h" | 7 #include "core/frame/TopControls.h" |
| 8 #include "core/html/HTMLFrameOwnerElement.h" | 8 #include "core/html/HTMLFrameOwnerElement.h" |
| 9 #include "core/page/Page.h" | 9 #include "core/page/Page.h" |
| 10 #include "core/page/scrolling/RootScrollerController.h" |
| 10 #include "platform/testing/URLTestHelpers.h" | 11 #include "platform/testing/URLTestHelpers.h" |
| 11 #include "platform/testing/UnitTestHelpers.h" | 12 #include "platform/testing/UnitTestHelpers.h" |
| 12 #include "public/platform/Platform.h" | 13 #include "public/platform/Platform.h" |
| 13 #include "public/platform/WebURLLoaderMockFactory.h" | 14 #include "public/platform/WebURLLoaderMockFactory.h" |
| 14 #include "public/web/WebCache.h" | 15 #include "public/web/WebCache.h" |
| 15 #include "public/web/WebConsoleMessage.h" | 16 #include "public/web/WebConsoleMessage.h" |
| 16 #include "public/web/WebScriptSource.h" | 17 #include "public/web/WebScriptSource.h" |
| 17 #include "public/web/WebSettings.h" | 18 #include "public/web/WebSettings.h" |
| 18 #include "testing/gtest/include/gtest/gtest.h" | 19 #include "testing/gtest/include/gtest/gtest.h" |
| 19 #include "web/WebLocalFrameImpl.h" | 20 #include "web/WebLocalFrameImpl.h" |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 148 VisualViewport& visualViewport() const | 149 VisualViewport& visualViewport() const |
| 149 { | 150 { |
| 150 return frameHost().visualViewport(); | 151 return frameHost().visualViewport(); |
| 151 } | 152 } |
| 152 | 153 |
| 153 TopControls& topControls() const | 154 TopControls& topControls() const |
| 154 { | 155 { |
| 155 return frameHost().topControls(); | 156 return frameHost().topControls(); |
| 156 } | 157 } |
| 157 | 158 |
| 159 Element* effectiveRootScroller(Document* doc) const |
| 160 { |
| 161 return doc->rootScrollerController()->effectiveRootScroller(); |
| 162 } |
| 163 |
| 158 protected: | 164 protected: |
| 159 std::string m_baseURL; | 165 std::string m_baseURL; |
| 160 RootScrollerTestWebViewClient m_client; | 166 RootScrollerTestWebViewClient m_client; |
| 161 FrameTestHelpers::WebViewHelper m_helper; | 167 FrameTestHelpers::WebViewHelper m_helper; |
| 162 RuntimeEnabledFeatures::Backup m_featuresBackup; | 168 RuntimeEnabledFeatures::Backup m_featuresBackup; |
| 163 }; | 169 }; |
| 164 | 170 |
| 165 // Test that no root scroller element is set if setRootScroller isn't called on | 171 // Test that no root scroller element is set if setRootScroller isn't called on |
| 166 // any elements. The document element should be the default effective root | 172 // any elements. The document element should be the default effective root |
| 167 // scroller. | 173 // scroller. |
| 168 TEST_F(RootScrollerTest, TestDefaultRootScroller) | 174 TEST_F(RootScrollerTest, TestDefaultRootScroller) |
| 169 { | 175 { |
| 170 initialize("overflow-scrolling.html"); | 176 initialize("overflow-scrolling.html"); |
| 171 | 177 |
| 172 ASSERT_EQ(nullptr, mainFrame()->document()->rootScroller()); | 178 ASSERT_EQ(nullptr, mainFrame()->document()->rootScroller()); |
| 173 | 179 |
| 174 Element* htmlElement = mainFrame()->document()->documentElement(); | 180 Element* htmlElement = mainFrame()->document()->documentElement(); |
| 175 EXPECT_EQ(htmlElement, mainFrame()->document()->effectiveRootScroller()); | 181 EXPECT_EQ(htmlElement, effectiveRootScroller(mainFrame()->document())); |
| 176 } | 182 } |
| 177 | 183 |
| 178 // Tests that setting an element as the root scroller causes it to control url | 184 // Tests that setting an element as the root scroller causes it to control url |
| 179 // bar hiding and overscroll. | 185 // bar hiding and overscroll. |
| 180 TEST_F(RootScrollerTest, TestSetRootScroller) | 186 TEST_F(RootScrollerTest, TestSetRootScroller) |
| 181 { | 187 { |
| 182 initialize("root-scroller.html"); | 188 initialize("root-scroller.html"); |
| 183 | 189 |
| 184 Element* container = mainFrame()->document()->getElementById("container"); | 190 Element* container = mainFrame()->document()->getElementById("container"); |
| 185 TrackExceptionState exceptionState; | 191 TrackExceptionState exceptionState; |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 287 { | 293 { |
| 288 initialize("root-scroller.html"); | 294 initialize("root-scroller.html"); |
| 289 | 295 |
| 290 ASSERT_EQ(nullptr, mainFrame()->document()->rootScroller()); | 296 ASSERT_EQ(nullptr, mainFrame()->document()->rootScroller()); |
| 291 | 297 |
| 292 Element* container = mainFrame()->document()->getElementById("container"); | 298 Element* container = mainFrame()->document()->getElementById("container"); |
| 293 TrackExceptionState exceptionState; | 299 TrackExceptionState exceptionState; |
| 294 mainFrame()->document()->setRootScroller(container, exceptionState); | 300 mainFrame()->document()->setRootScroller(container, exceptionState); |
| 295 | 301 |
| 296 ASSERT_EQ(container, mainFrame()->document()->rootScroller()); | 302 ASSERT_EQ(container, mainFrame()->document()->rootScroller()); |
| 297 ASSERT_EQ(container, mainFrame()->document()->effectiveRootScroller()); | 303 ASSERT_EQ(container, effectiveRootScroller(mainFrame()->document())); |
| 298 | 304 |
| 299 mainFrame()->document()->body()->removeChild(container); | 305 mainFrame()->document()->body()->removeChild(container); |
| 300 mainFrameView()->updateAllLifecyclePhases(); | 306 mainFrameView()->updateAllLifecyclePhases(); |
| 301 | 307 |
| 302 ASSERT_EQ(container, mainFrame()->document()->rootScroller()); | 308 ASSERT_EQ(container, mainFrame()->document()->rootScroller()); |
| 303 ASSERT_NE(container, mainFrame()->document()->effectiveRootScroller()); | 309 ASSERT_NE(container, effectiveRootScroller(mainFrame()->document())); |
| 304 } | 310 } |
| 305 | 311 |
| 306 // Tests that setting an element that isn't a valid scroller as the root | 312 // Tests that setting an element that isn't a valid scroller as the root |
| 307 // scroller doesn't change the effective root scroller. | 313 // scroller doesn't change the effective root scroller. |
| 308 TEST_F(RootScrollerTest, TestSetRootScrollerOnInvalidElement) | 314 TEST_F(RootScrollerTest, TestSetRootScrollerOnInvalidElement) |
| 309 { | 315 { |
| 310 initialize("root-scroller.html"); | 316 initialize("root-scroller.html"); |
| 311 | 317 |
| 312 { | 318 { |
| 313 // Set to a non-block element. Should be rejected and a console message | 319 // Set to a non-block element. Should be rejected and a console message |
| 314 // logged. | 320 // logged. |
| 315 Element* element = mainFrame()->document()->getElementById("nonBlock"); | 321 Element* element = mainFrame()->document()->getElementById("nonBlock"); |
| 316 TrackExceptionState exceptionState; | 322 TrackExceptionState exceptionState; |
| 317 mainFrame()->document()->setRootScroller(element, exceptionState); | 323 mainFrame()->document()->setRootScroller(element, exceptionState); |
| 318 mainFrameView()->updateAllLifecyclePhases(); | 324 mainFrameView()->updateAllLifecyclePhases(); |
| 319 ASSERT_EQ(element, mainFrame()->document()->rootScroller()); | 325 ASSERT_EQ(element, mainFrame()->document()->rootScroller()); |
| 320 ASSERT_NE(element, mainFrame()->document()->effectiveRootScroller()); | 326 ASSERT_NE(element, effectiveRootScroller(mainFrame()->document())); |
| 321 } | 327 } |
| 322 | 328 |
| 323 { | 329 { |
| 324 // Set to an element with no size. | 330 // Set to an element with no size. |
| 325 Element* element = mainFrame()->document()->getElementById("empty"); | 331 Element* element = mainFrame()->document()->getElementById("empty"); |
| 326 TrackExceptionState exceptionState; | 332 TrackExceptionState exceptionState; |
| 327 mainFrame()->document()->setRootScroller(element, exceptionState); | 333 mainFrame()->document()->setRootScroller(element, exceptionState); |
| 328 mainFrameView()->updateAllLifecyclePhases(); | 334 mainFrameView()->updateAllLifecyclePhases(); |
| 329 ASSERT_EQ(element, mainFrame()->document()->rootScroller()); | 335 ASSERT_EQ(element, mainFrame()->document()->rootScroller()); |
| 330 ASSERT_NE(element, mainFrame()->document()->effectiveRootScroller()); | 336 ASSERT_NE(element, effectiveRootScroller(mainFrame()->document())); |
| 331 } | 337 } |
| 332 } | 338 } |
| 333 | 339 |
| 334 // Test that the effective root scroller resets to the default element when the | 340 // Test that the effective root scroller resets to the default element when the |
| 335 // current root scroller element becomes invalid as a scroller. | 341 // current root scroller element becomes invalid as a scroller. |
| 336 TEST_F(RootScrollerTest, TestRootScrollerBecomesInvalid) | 342 TEST_F(RootScrollerTest, TestRootScrollerBecomesInvalid) |
| 337 { | 343 { |
| 338 initialize("root-scroller.html"); | 344 initialize("root-scroller.html"); |
| 339 | 345 |
| 340 Element* htmlElement = mainFrame()->document()->documentElement(); | 346 Element* htmlElement = mainFrame()->document()->documentElement(); |
| 341 Element* container = mainFrame()->document()->getElementById("container"); | 347 Element* container = mainFrame()->document()->getElementById("container"); |
| 342 TrackExceptionState exceptionState; | 348 TrackExceptionState exceptionState; |
| 343 | 349 |
| 344 ASSERT_EQ(nullptr, mainFrame()->document()->rootScroller()); | 350 ASSERT_EQ(nullptr, mainFrame()->document()->rootScroller()); |
| 345 ASSERT_EQ(htmlElement, mainFrame()->document()->effectiveRootScroller()); | 351 ASSERT_EQ(htmlElement, effectiveRootScroller(mainFrame()->document())); |
| 346 | 352 |
| 347 { | 353 { |
| 348 mainFrame()->document()->setRootScroller(container, exceptionState); | 354 mainFrame()->document()->setRootScroller(container, exceptionState); |
| 349 mainFrameView()->updateAllLifecyclePhases(); | 355 mainFrameView()->updateAllLifecyclePhases(); |
| 350 | 356 |
| 351 ASSERT_EQ(container, mainFrame()->document()->rootScroller()); | 357 ASSERT_EQ(container, mainFrame()->document()->rootScroller()); |
| 352 ASSERT_EQ(container, mainFrame()->document()->effectiveRootScroller()); | 358 ASSERT_EQ(container, effectiveRootScroller(mainFrame()->document())); |
| 353 | 359 |
| 354 executeScript( | 360 executeScript( |
| 355 "document.querySelector('#container').style.display = 'inline'"); | 361 "document.querySelector('#container').style.display = 'inline'"); |
| 356 mainFrameView()->updateAllLifecyclePhases(); | 362 mainFrameView()->updateAllLifecyclePhases(); |
| 357 | 363 |
| 358 ASSERT_EQ(container, mainFrame()->document()->rootScroller()); | 364 ASSERT_EQ(container, mainFrame()->document()->rootScroller()); |
| 359 ASSERT_EQ(htmlElement, | 365 ASSERT_EQ(htmlElement, |
| 360 mainFrame()->document()->effectiveRootScroller()); | 366 effectiveRootScroller(mainFrame()->document())); |
| 361 } | 367 } |
| 362 | 368 |
| 363 executeScript( | 369 executeScript( |
| 364 "document.querySelector('#container').style.display = 'block'"); | 370 "document.querySelector('#container').style.display = 'block'"); |
| 365 mainFrame()->document()->setRootScroller(nullptr, exceptionState); | 371 mainFrame()->document()->setRootScroller(nullptr, exceptionState); |
| 366 mainFrameView()->updateAllLifecyclePhases(); | 372 mainFrameView()->updateAllLifecyclePhases(); |
| 367 ASSERT_EQ(nullptr, mainFrame()->document()->rootScroller()); | 373 ASSERT_EQ(nullptr, mainFrame()->document()->rootScroller()); |
| 368 ASSERT_EQ(htmlElement, mainFrame()->document()->effectiveRootScroller()); | 374 ASSERT_EQ(htmlElement, effectiveRootScroller(mainFrame()->document())); |
| 369 | 375 |
| 370 { | 376 { |
| 371 mainFrame()->document()->setRootScroller(container, exceptionState); | 377 mainFrame()->document()->setRootScroller(container, exceptionState); |
| 372 mainFrameView()->updateAllLifecyclePhases(); | 378 mainFrameView()->updateAllLifecyclePhases(); |
| 373 | 379 |
| 374 ASSERT_EQ(container, mainFrame()->document()->rootScroller()); | 380 ASSERT_EQ(container, mainFrame()->document()->rootScroller()); |
| 375 ASSERT_EQ(container, mainFrame()->document()->effectiveRootScroller()); | 381 ASSERT_EQ(container, effectiveRootScroller(mainFrame()->document())); |
| 376 | 382 |
| 377 executeScript( | 383 executeScript( |
| 378 "document.querySelector('#container').style.width = '98%'"); | 384 "document.querySelector('#container').style.width = '98%'"); |
| 379 mainFrameView()->updateAllLifecyclePhases(); | 385 mainFrameView()->updateAllLifecyclePhases(); |
| 380 | 386 |
| 381 ASSERT_EQ(container, mainFrame()->document()->rootScroller()); | 387 ASSERT_EQ(container, mainFrame()->document()->rootScroller()); |
| 382 ASSERT_EQ(htmlElement, | 388 ASSERT_EQ(htmlElement, |
| 383 mainFrame()->document()->effectiveRootScroller()); | 389 effectiveRootScroller(mainFrame()->document())); |
| 384 } | 390 } |
| 385 } | 391 } |
| 386 | 392 |
| 387 // Tests that setting the root scroller of the top document to an element that | 393 // Tests that setting the root scroller of the top document to an element that |
| 388 // belongs to a nested document works. | 394 // belongs to a nested document works. |
| 389 TEST_F(RootScrollerTest, TestSetRootScrollerOnElementInIframe) | 395 TEST_F(RootScrollerTest, TestSetRootScrollerOnElementInIframe) |
| 390 { | 396 { |
| 391 initialize("root-scroller-iframe.html"); | 397 initialize("root-scroller-iframe.html"); |
| 392 | 398 |
| 393 ASSERT_EQ(nullptr, mainFrame()->document()->rootScroller()); | 399 ASSERT_EQ(nullptr, mainFrame()->document()->rootScroller()); |
| 394 | 400 |
| 395 { | 401 { |
| 396 // Trying to set an element from a nested document should fail. | 402 // Trying to set an element from a nested document should fail. |
| 397 HTMLFrameOwnerElement* iframe = toHTMLFrameOwnerElement( | 403 HTMLFrameOwnerElement* iframe = toHTMLFrameOwnerElement( |
| 398 mainFrame()->document()->getElementById("iframe")); | 404 mainFrame()->document()->getElementById("iframe")); |
| 399 Element* innerContainer = | 405 Element* innerContainer = |
| 400 iframe->contentDocument()->getElementById("container"); | 406 iframe->contentDocument()->getElementById("container"); |
| 401 | 407 |
| 402 TrackExceptionState exceptionState; | 408 TrackExceptionState exceptionState; |
| 403 mainFrame()->document()->setRootScroller( | 409 mainFrame()->document()->setRootScroller( |
| 404 innerContainer, | 410 innerContainer, |
| 405 exceptionState); | 411 exceptionState); |
| 406 mainFrameView()->updateAllLifecyclePhases(); | 412 mainFrameView()->updateAllLifecyclePhases(); |
| 407 | 413 |
| 408 ASSERT_EQ(innerContainer, mainFrame()->document()->rootScroller()); | 414 ASSERT_EQ(innerContainer, mainFrame()->document()->rootScroller()); |
| 409 ASSERT_EQ(innerContainer, | 415 ASSERT_EQ(innerContainer, |
| 410 mainFrame()->document()->effectiveRootScroller()); | 416 effectiveRootScroller(mainFrame()->document())); |
| 411 } | 417 } |
| 412 | 418 |
| 413 { | 419 { |
| 414 // Setting the iframe itself should also work. | 420 // Setting the iframe itself should also work. |
| 415 HTMLFrameOwnerElement* iframe = toHTMLFrameOwnerElement( | 421 HTMLFrameOwnerElement* iframe = toHTMLFrameOwnerElement( |
| 416 mainFrame()->document()->getElementById("iframe")); | 422 mainFrame()->document()->getElementById("iframe")); |
| 417 | 423 |
| 418 TrackExceptionState exceptionState; | 424 TrackExceptionState exceptionState; |
| 419 mainFrame()->document()->setRootScroller(iframe, exceptionState); | 425 mainFrame()->document()->setRootScroller(iframe, exceptionState); |
| 420 mainFrameView()->updateAllLifecyclePhases(); | 426 mainFrameView()->updateAllLifecyclePhases(); |
| 421 | 427 |
| 422 ASSERT_EQ(iframe, mainFrame()->document()->rootScroller()); | 428 ASSERT_EQ(iframe, mainFrame()->document()->rootScroller()); |
| 423 ASSERT_EQ(iframe, mainFrame()->document()->effectiveRootScroller()); | 429 ASSERT_EQ(iframe, effectiveRootScroller(mainFrame()->document())); |
| 424 } | 430 } |
| 425 } | 431 } |
| 426 | 432 |
| 427 // Tests that setting a valid element as the root scroller on a document within | 433 // Tests that setting a valid element as the root scroller on a document within |
| 428 // an iframe works as expected. | 434 // an iframe works as expected. |
| 429 TEST_F(RootScrollerTest, TestRootScrollerWithinIframe) | 435 TEST_F(RootScrollerTest, TestRootScrollerWithinIframe) |
| 430 { | 436 { |
| 431 initialize("root-scroller-iframe.html"); | 437 initialize("root-scroller-iframe.html"); |
| 432 | 438 |
| 433 ASSERT_EQ(nullptr, mainFrame()->document()->rootScroller()); | 439 ASSERT_EQ(nullptr, mainFrame()->document()->rootScroller()); |
| 434 | 440 |
| 435 { | 441 { |
| 436 HTMLFrameOwnerElement* iframe = toHTMLFrameOwnerElement( | 442 HTMLFrameOwnerElement* iframe = toHTMLFrameOwnerElement( |
| 437 mainFrame()->document()->getElementById("iframe")); | 443 mainFrame()->document()->getElementById("iframe")); |
| 438 | 444 |
| 439 ASSERT_EQ(iframe->contentDocument()->documentElement(), | 445 ASSERT_EQ(iframe->contentDocument()->documentElement(), |
| 440 iframe->contentDocument()->effectiveRootScroller()); | 446 effectiveRootScroller(iframe->contentDocument())); |
| 441 | 447 |
| 442 Element* innerContainer = | 448 Element* innerContainer = |
| 443 iframe->contentDocument()->getElementById("container"); | 449 iframe->contentDocument()->getElementById("container"); |
| 444 TrackExceptionState exceptionState; | 450 TrackExceptionState exceptionState; |
| 445 iframe->contentDocument()->setRootScroller( | 451 iframe->contentDocument()->setRootScroller( |
| 446 innerContainer, | 452 innerContainer, |
| 447 exceptionState); | 453 exceptionState); |
| 448 mainFrameView()->updateAllLifecyclePhases(); | 454 mainFrameView()->updateAllLifecyclePhases(); |
| 449 | 455 |
| 450 ASSERT_EQ(innerContainer, iframe->contentDocument()->rootScroller()); | 456 ASSERT_EQ(innerContainer, iframe->contentDocument()->rootScroller()); |
| 451 ASSERT_EQ(innerContainer, | 457 ASSERT_EQ(innerContainer, |
| 452 iframe->contentDocument()->effectiveRootScroller()); | 458 effectiveRootScroller(iframe->contentDocument())); |
| 453 } | 459 } |
| 454 } | 460 } |
| 455 | 461 |
| 456 // Tests that trying to set an element as the root scroller of a document inside | 462 // Tests that trying to set an element as the root scroller of a document inside |
| 457 // an iframe fails when that element belongs to the parent document. | 463 // an iframe fails when that element belongs to the parent document. |
| 458 // TODO(bokan): Recent changes mean this is now possible but should be fixed. | 464 // TODO(bokan): Recent changes mean this is now possible but should be fixed. |
| 459 TEST_F(RootScrollerTest, DISABLED_TestSetRootScrollerOnElementFromOutsideIframe) | 465 TEST_F(RootScrollerTest, DISABLED_TestSetRootScrollerOnElementFromOutsideIframe) |
| 460 { | 466 { |
| 461 initialize("root-scroller-iframe.html"); | 467 initialize("root-scroller-iframe.html"); |
| 462 | 468 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 485 body, | 491 body, |
| 486 exceptionState); | 492 exceptionState); |
| 487 | 493 |
| 488 ASSERT_EQ(body, iframe->contentDocument()->rootScroller()); | 494 ASSERT_EQ(body, iframe->contentDocument()->rootScroller()); |
| 489 } | 495 } |
| 490 } | 496 } |
| 491 | 497 |
| 492 } // namespace | 498 } // namespace |
| 493 | 499 |
| 494 } // namespace blink | 500 } // namespace blink |
| OLD | NEW |