Animated SVG images are not paused in pages loaded in the background
authorcdumez@apple.com <cdumez@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 29 Mar 2017 20:54:21 +0000 (20:54 +0000)
committercdumez@apple.com <cdumez@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 29 Mar 2017 20:54:21 +0000 (20:54 +0000)
commite458b960dcfced5c66d2d74c36fce63673f8eb7b
treed496a081cf2dc81dd1f02febc1fd882c71bdbf1b
parent2eace2e46609115abb6f5658b570360431d4b9a1
Animated SVG images are not paused in pages loaded in the background
https://bugs.webkit.org/show_bug.cgi?id=170043
<rdar://problem/31234412>

Reviewed by Simon Fraser.

Source/WebCore:

Animated SVG images are not paused in pages loaded in the background. We rely
on FrameView::isOffscreen() to stop images animations in background tab (See
logic in RenderElement's shouldRepaintForImageAnimation()). This works fine
if a tab is visble and then becomes hidden (i.e. by switching to another
tab). However, in the case where the tab gets loaded while in the background
(e.g. opening link in new background tab, or session restore), then the
animations would not be paused, due to FrameView::isOffscreen() erroneously
returning false in this case.

Normally, the following chain of events happens:
- Page is visible, we construct a main frame and its FrameView for loading
  the page. When a FrameView is constructed, we call FrameView::show() to
  make it visible. Then, if the page becomes non-visible, we call
  Page::setIsVisibleInternal(false) which calls FrameView::hide(). After
  that, FrameView::isOffscreen() correctly returns true because we properly
  called FrameView::hide().

However, when doing a load while the Page is hidden, the following was
happening:
- Page is not visible, we call Page::setIsVisibleInternal(false) which tries
  to call FrameView::hide() for the main frame but it does not have a FrameView
  yet (because the load has not started). We start the load and end up creating
  a FrameView. The FrameView constructor was calling FrameView::show()
  unconditionally, thus making the FrameView think is visible, even though its
  page isn't. At this point, FrameView::isOffscreen() was returning false
  and animations would keep running, even though the page is not visible.

To address the issue, we now call FrameView::show() in FrameView::create() only
if the Page is actually visible, instead of calling it unconditionally. If the
page ever becomes visible, Page::setIsVisibleInternal(true) will be called and
it will take care of calling FrameView::show() then.

Tests: svg/animations/animations-paused-in-background-page-iframe.html
       svg/animations/animations-paused-in-background-page.html

* page/FrameView.cpp:
(WebCore::FrameView::create):

LayoutTests:

Extend layout test coverage.

* svg/animations/animations-paused-in-background-page-expected.txt: Added.
* svg/animations/animations-paused-in-background-page-iframe-expected.txt: Added.
* svg/animations/animations-paused-in-background-page-iframe.html: Added.
* svg/animations/animations-paused-in-background-page.html: Added.
* svg/animations/resources/iframe-with-animated-svg-image.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@214561 268f45cc-cd09-0410-ab3c-d52691b4dbfc
LayoutTests/ChangeLog
LayoutTests/platform/ios/TestExpectations
LayoutTests/platform/mac-wk1/TestExpectations
LayoutTests/svg/animations/animations-paused-in-background-page-expected.txt [new file with mode: 0644]
LayoutTests/svg/animations/animations-paused-in-background-page-iframe-expected.txt [new file with mode: 0644]
LayoutTests/svg/animations/animations-paused-in-background-page-iframe.html [new file with mode: 0644]
LayoutTests/svg/animations/animations-paused-in-background-page.html [new file with mode: 0644]
LayoutTests/svg/animations/resources/iframe-with-animated-svg-image.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/page/FrameView.cpp