Commit 52c77521 authored by Nate Fischer's avatar Nate Fischer Committed by Commit Bot

AW: fix and enable flaky test

This enables
testExitFullscreenEndsIfAppInvokesCallbackFromOnHideCustomView. This
test flaked because DOMUtils was unreliable for clicking links. This CL
swaps out DOMUtils for EvaluateJavaScriptWithUserGesture (since the
relevant blink code requires user gesture and has no way to turn it off
for testing).

This plumbs EvaluateJavaScriptWithUserGesture to Java in a testonly
target, so the Java method will not be present in production (and so
this change should have no security implications).

R=boliu@chromium.org

    --repeat=1000 \
    --gtest_filter=AwContentsClientFullScreenTest#testExitFullscreenEndsIfAppInvokesCallbackFromOnHideCustomView

Bug: 789306
Test: run_webview_instrumentation_test_apk --break-on-failure \
Change-Id: I4407ce0daa399fbb289d4c9d74e3d9b64bccfcbf
Reviewed-on: https://chromium-review.googlesource.com/c/1286031Reviewed-by: default avatarBo <boliu@chromium.org>
Commit-Queue: Nate Fischer <ntfschr@chromium.org>
Cr-Commit-Position: refs/heads/master@{#600579}
parent 2463e855
...@@ -20,6 +20,7 @@ import org.junit.Rule; ...@@ -20,6 +20,7 @@ import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
import org.chromium.android_webview.test.util.JSUtils;
import org.chromium.android_webview.test.util.JavascriptEventObserver; import org.chromium.android_webview.test.util.JavascriptEventObserver;
import org.chromium.base.ThreadUtils; import org.chromium.base.ThreadUtils;
import org.chromium.base.test.util.DisabledTest; import org.chromium.base.test.util.DisabledTest;
...@@ -188,9 +189,8 @@ public class AwContentsClientFullScreenTest { ...@@ -188,9 +189,8 @@ public class AwContentsClientFullScreenTest {
} }
@Test @Test
//@MediumTest @MediumTest
//@Feature({"AndroidWebView"}) @Feature({"AndroidWebView"})
@DisabledTest(message = "crbug.com/789306")
public void testExitFullscreenEndsIfAppInvokesCallbackFromOnHideCustomView() throws Throwable { public void testExitFullscreenEndsIfAppInvokesCallbackFromOnHideCustomView() throws Throwable {
mContentsClient.setOnHideCustomViewRunnable( mContentsClient.setOnHideCustomViewRunnable(
() -> mContentsClient.getExitCallback().onCustomViewHidden()); () -> mContentsClient.getExitCallback().onCustomViewHidden());
...@@ -312,7 +312,8 @@ public class AwContentsClientFullScreenTest { ...@@ -312,7 +312,8 @@ public class AwContentsClientFullScreenTest {
// Enter fullscreen and verify that the power save blocker is // Enter fullscreen and verify that the power save blocker is
// still there. // still there.
DOMUtils.clickNode(mTestContainerView.getWebContents(), CUSTOM_FULLSCREEN_CONTROL_ID); JSUtils.clickNodeWithUserGesture(
mTestContainerView.getWebContents(), CUSTOM_FULLSCREEN_CONTROL_ID);
mContentsClient.waitForCustomViewShown(); mContentsClient.waitForCustomViewShown();
assertKeepScreenOnActive(mTestContainerView, true); assertKeepScreenOnActive(mTestContainerView, true);
...@@ -358,7 +359,8 @@ public class AwContentsClientFullScreenTest { ...@@ -358,7 +359,8 @@ public class AwContentsClientFullScreenTest {
// (containing the fullscreen <video>) so we just rely on that fact here. // (containing the fullscreen <video>) so we just rely on that fact here.
TouchCommon.singleClickView(mContentsClient.getCustomView()); TouchCommon.singleClickView(mContentsClient.getCustomView());
} else { } else {
DOMUtils.clickNode(mTestContainerView.getWebContents(), CUSTOM_PLAY_CONTROL_ID); JSUtils.clickNodeWithUserGesture(
mTestContainerView.getWebContents(), CUSTOM_PLAY_CONTROL_ID);
} }
} }
...@@ -467,7 +469,8 @@ public class AwContentsClientFullScreenTest { ...@@ -467,7 +469,8 @@ public class AwContentsClientFullScreenTest {
private void loadTestPageAndClickFullscreen(String videoTestUrl) throws Exception { private void loadTestPageAndClickFullscreen(String videoTestUrl) throws Exception {
loadTestPage(videoTestUrl); loadTestPage(videoTestUrl);
DOMUtils.clickNode(mTestContainerView.getWebContents(), CUSTOM_FULLSCREEN_CONTROL_ID); JSUtils.clickNodeWithUserGesture(
mTestContainerView.getWebContents(), CUSTOM_FULLSCREEN_CONTROL_ID);
} }
private void loadTestPage(String videoTestUrl) throws Exception { private void loadTestPage(String videoTestUrl) throws Exception {
......
...@@ -11,9 +11,11 @@ import android.app.Instrumentation; ...@@ -11,9 +11,11 @@ import android.app.Instrumentation;
import org.junit.Assert; import org.junit.Assert;
import org.chromium.android_webview.AwContents; import org.chromium.android_webview.AwContents;
import org.chromium.content_public.browser.WebContents;
import org.chromium.content_public.browser.test.util.Criteria; import org.chromium.content_public.browser.test.util.Criteria;
import org.chromium.content_public.browser.test.util.CriteriaHelper; import org.chromium.content_public.browser.test.util.CriteriaHelper;
import org.chromium.content_public.browser.test.util.TestCallbackHelperContainer.OnEvaluateJavaScriptResultHelper; import org.chromium.content_public.browser.test.util.TestCallbackHelperContainer.OnEvaluateJavaScriptResultHelper;
import org.chromium.content_public.browser.test.util.WebContentsUtils;
/** /**
* Collection of functions for JavaScript-based interactions with a page. * Collection of functions for JavaScript-based interactions with a page.
...@@ -22,6 +24,13 @@ public class JSUtils { ...@@ -22,6 +24,13 @@ public class JSUtils {
private static final long WAIT_TIMEOUT_MS = scaleTimeout(2000); private static final long WAIT_TIMEOUT_MS = scaleTimeout(2000);
private static final int CHECK_INTERVAL = 100; private static final int CHECK_INTERVAL = 100;
private static String createScriptToClickNode(String nodeId) {
String script = "var evObj = new MouseEvent('click', {bubbles: true});"
+ "document.getElementById('" + nodeId + "').dispatchEvent(evObj);"
+ "console.log('element with id [" + nodeId + "] clicked');";
return script;
}
public static void clickOnLinkUsingJs(final Instrumentation instrumentation, public static void clickOnLinkUsingJs(final Instrumentation instrumentation,
final AwContents awContents, final AwContents awContents,
final OnEvaluateJavaScriptResultHelper onEvaluateJavaScriptResultHelper, final OnEvaluateJavaScriptResultHelper onEvaluateJavaScriptResultHelper,
...@@ -42,12 +51,16 @@ public class JSUtils { ...@@ -42,12 +51,16 @@ public class JSUtils {
} }
}, WAIT_TIMEOUT_MS, CHECK_INTERVAL); }, WAIT_TIMEOUT_MS, CHECK_INTERVAL);
// clang-format off
instrumentation.runOnMainSync( instrumentation.runOnMainSync(
() -> awContents.getWebContents().evaluateJavaScriptForTests( () -> awContents.getWebContents().evaluateJavaScriptForTests(
"var evObj = new MouseEvent('click', {bubbles: true});" createScriptToClickNode(linkId), null));
+ "document.getElementById('" + linkId + "').dispatchEvent(evObj);" // clang-format on
+ "console.log('element with id [" + linkId + "] clicked');", }
null));
public static void clickNodeWithUserGesture(WebContents webContents, String nodeId) {
WebContentsUtils.evaluateJavaScriptWithUserGesture(
webContents, createScriptToClickNode(nodeId));
} }
public static String executeJavaScriptAndWaitForResult(Instrumentation instrumentation, public static String executeJavaScriptAndWaitForResult(Instrumentation instrumentation,
......
...@@ -135,6 +135,7 @@ shared_library("libstandalonelibwebviewchromium") { ...@@ -135,6 +135,7 @@ shared_library("libstandalonelibwebviewchromium") {
"//android_webview:common", "//android_webview:common",
"//components/heap_profiling:test_support", "//components/heap_profiling:test_support",
"//components/minidump_uploader", "//components/minidump_uploader",
"//content/public/test/android:content_native_test_support",
] ]
configs -= [ "//build/config/android:hide_all_but_jni_onload" ] configs -= [ "//build/config/android:hide_all_but_jni_onload" ]
configs += [ "//build/config/android:hide_all_but_jni" ] configs += [ "//build/config/android:hide_all_but_jni" ]
......
...@@ -97,7 +97,22 @@ public class WebContentsUtils { ...@@ -97,7 +97,22 @@ public class WebContentsUtils {
} }
} }
/**
* Injects the passed Javascript code in the current page and evaluates it, supplying a fake
* user gesture. This also differs from {@link WebContents#evaluateJavaScript()} in that it
* allows for executing script in non-webui frames.
*
* @param script The Javascript to execute.
*/
public static void evaluateJavaScriptWithUserGesture(WebContents webContents, String script) {
if (script == null) return;
ThreadUtils.runOnUiThreadBlocking(
() -> nativeEvaluateJavaScriptWithUserGesture(webContents, script));
}
private static native void nativeReportAllFrameSubmissions( private static native void nativeReportAllFrameSubmissions(
WebContents webContents, boolean enabled); WebContents webContents, boolean enabled);
private static native RenderFrameHost nativeGetFocusedFrame(WebContents webContents); private static native RenderFrameHost nativeGetFocusedFrame(WebContents webContents);
private static native void nativeEvaluateJavaScriptWithUserGesture(
WebContents webContents, String script);
} }
...@@ -3,14 +3,17 @@ ...@@ -3,14 +3,17 @@
// found in the LICENSE file. // found in the LICENSE file.
#include "base/android/jni_android.h" #include "base/android/jni_android.h"
#include "base/android/jni_string.h"
#include "base/android/scoped_java_ref.h" #include "base/android/scoped_java_ref.h"
#include "content/browser/frame_host/render_frame_host_impl.h" #include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_impl.h" #include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/render_frame_metadata_provider.h" #include "content/public/browser/render_frame_metadata_provider.h"
#include "content/public/browser/render_view_host.h" #include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
#include "jni/WebContentsUtils_jni.h" #include "jni/WebContentsUtils_jni.h"
using base::android::ConvertJavaStringToUTF16;
using base::android::JavaParamRef; using base::android::JavaParamRef;
using base::android::ScopedJavaLocalRef; using base::android::ScopedJavaLocalRef;
...@@ -39,4 +42,26 @@ ScopedJavaLocalRef<jobject> JNI_WebContentsUtils_GetFocusedFrame( ...@@ -39,4 +42,26 @@ ScopedJavaLocalRef<jobject> JNI_WebContentsUtils_GetFocusedFrame(
->GetJavaRenderFrameHost(); ->GetJavaRenderFrameHost();
} }
void JNI_WebContentsUtils_EvaluateJavaScriptWithUserGesture(
JNIEnv* env,
const JavaParamRef<jclass>& clazz,
const JavaParamRef<jobject>& jweb_contents,
const JavaParamRef<jstring>& script) {
WebContents* web_contents = WebContents::FromJavaWebContents(jweb_contents);
RenderViewHost* rvh = web_contents->GetRenderViewHost();
DCHECK(rvh);
if (!rvh->IsRenderViewLive()) {
if (!static_cast<WebContentsImpl*>(web_contents)
->CreateRenderViewForInitialEmptyDocument()) {
LOG(ERROR)
<< "Failed to create RenderView in EvaluateJavaScriptWithUserGesture";
return;
}
}
web_contents->GetMainFrame()->ExecuteJavaScriptWithUserGestureForTests(
ConvertJavaStringToUTF16(env, script));
}
} // namespace content } // namespace content
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment