Index: android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientFullScreenTest.java |
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientFullScreenTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientFullScreenTest.java |
index da731d22f0b2b5136624b0cfeaf4c81919b30c83..a2131959dad2e947fc4829eb7f352656b159e692 100644 |
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientFullScreenTest.java |
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwContentsClientFullScreenTest.java |
@@ -4,12 +4,16 @@ |
package org.chromium.android_webview.test; |
+import static org.chromium.base.test.util.ScalableTimeout.scaleTimeout; |
+ |
import android.test.suitebuilder.annotation.MediumTest; |
import android.view.KeyEvent; |
import android.view.View; |
import android.view.ViewGroup; |
+import org.chromium.android_webview.ExternalVideoSurfaceContainer.NoPunchingSurfaceView; |
import org.chromium.android_webview.test.util.JavascriptEventObserver; |
+import org.chromium.base.CommandLine; |
import org.chromium.base.test.util.Feature; |
import org.chromium.content.browser.ContentVideoView; |
import org.chromium.content.browser.ContentViewCore; |
@@ -182,6 +186,84 @@ public class AwContentsClientFullScreenTest extends AwTestBase { |
@MediumTest |
@Feature({"AndroidWebView"}) |
+ public void testHolePunchingSurfaceNotCreatedForClearVideo() |
+ throws Throwable { |
+ loadTestPage(VIDEO_TEST_URL); |
+ assertFalse(DOMUtils.isFullscreen(getWebContentsOnUiThread())); |
+ |
+ // Play and verify that a surface view for hole punching is not created. |
+ // Note that VIDEO_TEST_URL contains clear video. |
+ tapPlayButton(); |
+ assertTrue(DOMUtils.waitForVideoPlay(getWebContentsOnUiThread(), VIDEO_ID)); |
+ assertContainsHolePunchingSurfaceView(mTestContainerView, false); |
+ } |
+ |
+ @MediumTest |
+ @Feature({"AndroidWebView"}) |
+ public void testOnShowCustomViewTransfersHolePunchingSurfaceForVideoInsideDiv() |
+ throws Throwable { |
+ forceUseHolePunchingExternalSurface(); |
+ |
+ loadTestPage(VIDEO_INSIDE_DIV_TEST_URL); |
+ assertFalse(DOMUtils.isFullscreen(getWebContentsOnUiThread())); |
+ |
+ // Play and verify that there is a surface view for hole punching. |
+ tapPlayButton(); |
+ assertTrue(DOMUtils.waitForVideoPlay(getWebContentsOnUiThread(), VIDEO_ID)); |
+ assertContainsHolePunchingSurfaceView(mTestContainerView, true); |
+ |
+ // Enter fullscreen and verify that the hole punching surface is transferred. Note |
+ // that VIDEO_INSIDE_DIV_TEST_URL goes fullscreen on a <div> element, so in fullscreen |
+ // the video will still be embedded in the page and the hole punching surface required. |
+ // We need to transfer the external surface so that scrolling is synchronized with the |
+ // new container view. |
+ DOMUtils.clickNode(this, mContentViewCore, CUSTOM_FULLSCREEN_CONTROL_ID); |
+ mContentsClient.waitForCustomViewShown(); |
+ View customView = mContentsClient.getCustomView(); |
+ assertContainsHolePunchingSurfaceView(mTestContainerView, false); |
+ // Wait to ensure that the surface view stays there after being transfered and not |
+ // removed asynchronously. |
+ waitAndAssertContainsHolePunchingSurfaceView(customView, true); |
+ } |
+ |
+ @MediumTest |
+ @Feature({"AndroidWebView"}) |
+ public void testOnShowCustomViewRemovesHolePunchingSurfaceForVideo() |
+ throws Throwable { |
+ forceUseHolePunchingExternalSurface(); |
+ |
+ loadTestPage(VIDEO_TEST_URL); |
+ assertFalse(DOMUtils.isFullscreen(getWebContentsOnUiThread())); |
+ |
+ // Play and verify that there is a surface view for hole punching. |
+ tapPlayButton(); |
+ assertTrue(DOMUtils.waitForVideoPlay(getWebContentsOnUiThread(), VIDEO_ID)); |
+ assertContainsHolePunchingSurfaceView(mTestContainerView, true); |
+ |
+ // Enter fullscreen and verify that the surface view is removed. Note that |
+ // VIDEO_TEST_URL goes fullscreen on the <video> element, so in fullscreen |
+ // the video will not be embedded in the page and the external surface |
+ // not longer required. |
+ DOMUtils.clickNode(this, mContentViewCore, CUSTOM_FULLSCREEN_CONTROL_ID); |
+ mContentsClient.waitForCustomViewShown(); |
+ View customView = mContentsClient.getCustomView(); |
+ assertContainsHolePunchingSurfaceView(mTestContainerView, false); |
+ // We need to wait because the surface view is first transfered, and then removed |
+ // asynchronously. |
+ waitAndAssertContainsHolePunchingSurfaceView(customView, false); |
+ } |
+ |
+ /** |
+ * Force the use of the hole punching external surface (see VIDEO_HOLE). If this method is |
+ * called the external surface will also be created for clear video (that this test class uses) |
+ * and not just for encrypted video. |
+ */ |
+ private void forceUseHolePunchingExternalSurface() { |
+ CommandLine.getInstance().appendSwitch("force-use-overlay-embedded-video"); |
+ } |
+ |
+ @MediumTest |
+ @Feature({"AndroidWebView"}) |
public void testFullscreenNotSupported_video() throws Throwable { |
doTestFullscreenNotSupported(VIDEO_TEST_URL); |
} |
@@ -228,11 +310,11 @@ public class AwContentsClientFullScreenTest extends AwTestBase { |
// Play and verify that there is an active power save blocker. |
tapPlayButton(); |
- assertKeepScreenOnActive(customView, true); |
+ assertWaitForKeepScreenOnActive(customView, true); |
// Stop the video and verify that the power save blocker is gone. |
DOMUtils.pauseVideo(getWebContentsOnUiThread(), VIDEO_ID); |
- assertKeepScreenOnActive(customView, false); |
+ assertWaitForKeepScreenOnActive(customView, false); |
} |
@MediumTest |
@@ -247,11 +329,11 @@ public class AwContentsClientFullScreenTest extends AwTestBase { |
// Play and verify that there is an active power save blocker. |
tapPlayButton(); |
- assertKeepScreenOnActive(mTestContainerView, true); |
+ assertWaitForKeepScreenOnActive(mTestContainerView, true); |
// Stop the video and verify that the power save blocker is gone. |
DOMUtils.pauseVideo(getWebContentsOnUiThread(), VIDEO_ID); |
- assertKeepScreenOnActive(mTestContainerView, false); |
+ assertWaitForKeepScreenOnActive(mTestContainerView, false); |
} |
@MediumTest |
@@ -263,7 +345,7 @@ public class AwContentsClientFullScreenTest extends AwTestBase { |
// Play and verify that there is an active power save blocker. |
tapPlayButton(); |
- assertKeepScreenOnActive(mTestContainerView, true); |
+ assertWaitForKeepScreenOnActive(mTestContainerView, true); |
// Enter fullscreen and verify that the power save blocker is |
// still there. |
@@ -274,7 +356,7 @@ public class AwContentsClientFullScreenTest extends AwTestBase { |
// Pause the video and the power save blocker is gone. |
DOMUtils.pauseVideo(getWebContentsOnUiThread(), VIDEO_ID); |
- assertKeepScreenOnActive(customView, false); |
+ assertWaitForKeepScreenOnActive(customView, false); |
// Exit fullscreen and the power save blocker is still gone. |
DOMUtils.exitFullscreen(getWebContentsOnUiThread()); |
@@ -293,7 +375,7 @@ public class AwContentsClientFullScreenTest extends AwTestBase { |
// Play and verify that there is an active power save blocker |
// in fullscreen. |
tapPlayButton(); |
- assertKeepScreenOnActive(customView, true); |
+ assertWaitForKeepScreenOnActive(customView, true); |
// Exit fullscreen and verify that the power save blocker is |
// still there. |
@@ -304,18 +386,17 @@ public class AwContentsClientFullScreenTest extends AwTestBase { |
private void tapPlayButton() throws Exception { |
String testUrl = mTestContainerView.getAwContents().getUrl(); |
- if (VIDEO_INSIDE_DIV_TEST_URL.equals(testUrl)) { |
- // VIDEO_INSIDE_DIV_TEST_URL uses a custom play control with known id. |
- DOMUtils.clickNode(this, mContentViewCore, CUSTOM_PLAY_CONTROL_ID); |
- } else if (VIDEO_TEST_URL.equals(testUrl) |
+ if (VIDEO_TEST_URL.equals(testUrl) |
&& DOMUtils.isFullscreen(getWebContentsOnUiThread())) { |
- // VIDEO_TEST_URL uses the standard html5 video controls. The standard |
- // html5 controls are shadow html elements without any ids. In fullscreen we can still |
- // tap the play button because this is rendered in the center of the custom view. |
- // In embedded mode we don't have an easy way of retrieving its location. |
+ // The VIDEO_TEST_URL page goes fullscreen on the <video> element. In fullscreen |
+ // the button with id CUSTOM_PLAY_CONTROL_ID will not be visible, but the standard |
+ // html5 video controls are. The standard html5 controls are shadow html elements |
+ // without any ids so it is difficult to retrieve its precise location. However, |
+ // a large play control is rendered in the center of the custom view |
+ // (containing the fullscreen <video>) so we just rely on that fact here. |
TouchCommon.singleClickView(mContentsClient.getCustomView()); |
} else { |
- fail("Unable to tap standard html5 play control in embedded mode"); |
+ DOMUtils.clickNode(this, mContentViewCore, CUSTOM_PLAY_CONTROL_ID); |
} |
} |
@@ -323,7 +404,7 @@ public class AwContentsClientFullScreenTest extends AwTestBase { |
* Asserts that the keep screen on property in the given {@code view} is active as |
* {@code expected}. It also verifies that it is only active when the video is playing. |
*/ |
- private void assertKeepScreenOnActive(final View view, final boolean expected) |
+ private void assertWaitForKeepScreenOnActive(final View view, final boolean expected) |
throws InterruptedException { |
// We need to poll because it takes time to synchronize the state between the android |
// views and Javascript. |
@@ -342,6 +423,12 @@ public class AwContentsClientFullScreenTest extends AwTestBase { |
})); |
} |
+ private void assertKeepScreenOnActive(final View view, final boolean expected) |
+ throws Exception { |
+ assertTrue(getKeepScreenOn(view) == expected |
+ && DOMUtils.isVideoPaused(getWebContentsOnUiThread(), VIDEO_ID) != expected); |
+ } |
+ |
private boolean getKeepScreenOn(View view) { |
// The power save blocker is added to a child anchor view, |
// so we need to traverse the hierarchy. |
@@ -356,7 +443,7 @@ public class AwContentsClientFullScreenTest extends AwTestBase { |
return view.getKeepScreenOn(); |
} |
- private void assertIsFullscreen() throws InterruptedException { |
+ private void assertWaitForIsFullscreen() throws InterruptedException { |
// We need to poll because the Javascript state is updated asynchronously |
assertTrue(CriteriaHelper.pollForCriteria(new Criteria() { |
@Override |
@@ -371,35 +458,41 @@ public class AwContentsClientFullScreenTest extends AwTestBase { |
})); |
} |
- private void assertContainsContentVideoView() |
- throws InterruptedException { |
- // We need to poll because the ContentVideoView is added to the customView asynchronously |
- assertTrue(CriteriaHelper.pollForCriteria(new Criteria() { |
+ private void assertContainsContentVideoView() throws Exception { |
+ assertTrue(containsChildOfType(mContentsClient.getCustomView(), |
+ ContentVideoView.class)); |
+ } |
+ |
+ private void assertContainsHolePunchingSurfaceView(View view, boolean expected) |
+ throws Exception { |
+ assertEquals(containsChildOfType(view, NoPunchingSurfaceView.class), expected); |
+ } |
+ |
+ private void waitAndAssertContainsHolePunchingSurfaceView(View view, boolean expected) |
+ throws Exception { |
+ Thread.sleep(scaleTimeout(100)); |
+ assertEquals(expected, containsChildOfType(view, NoPunchingSurfaceView.class)); |
+ } |
+ |
+ private boolean containsChildOfType(final View view, final Class<? extends View> childType) |
+ throws Exception { |
+ return runTestOnUiThreadAndGetResult(new Callable<Boolean>() { |
@Override |
- public boolean isSatisfied() { |
- try { |
- return runTestOnUiThreadAndGetResult(new Callable<Boolean>() { |
- @Override |
- public Boolean call() throws Exception { |
- return containsVideoView(mContentsClient.getCustomView()); |
- } |
- }); |
- } catch (Exception e) { |
- fail(e.getMessage()); |
- return false; |
- } |
+ public Boolean call() throws Exception { |
+ return containsChildOfTypeOnUiThread(view, childType); |
} |
- })); |
+ }); |
} |
- private boolean containsVideoView(View view) { |
- if (view instanceof ContentVideoView) { |
+ private boolean containsChildOfTypeOnUiThread(final View view, |
+ final Class<? extends View> childType) throws Exception { |
+ if (childType.isInstance(view)) { |
return true; |
} |
if (view instanceof ViewGroup) { |
ViewGroup viewGroup = (ViewGroup) view; |
for (int i = 0; i < viewGroup.getChildCount(); i++) { |
- if (containsVideoView(viewGroup.getChildAt(i))) { |
+ if (containsChildOfTypeOnUiThread(viewGroup.getChildAt(i), childType)) { |
return true; |
} |
} |
@@ -428,7 +521,7 @@ public class AwContentsClientFullScreenTest extends AwTestBase { |
private void doOnShowCustomViewTest(String videoTestUrl) throws Exception { |
loadTestPageAndClickFullscreen(videoTestUrl); |
mContentsClient.waitForCustomViewShown(); |
- assertIsFullscreen(); |
+ assertWaitForIsFullscreen(); |
if (videoTestUrl.equals(VIDEO_TEST_URL)) { |
// We only create a ContentVideoView (ie. a hardware accelerated surface) when going |
// fullscreen on a video element. |