Commit 090ff5d8 authored by Yoland Yan's avatar Yoland Yan Committed by Commit Bot

Merge TestCommon implementation to TestRule

Merge two TestCommon into ActivityTestRule since there is
no long need for sharing the implementation with other classes

Bug: 711517
Change-Id: I21c902f76891e2e75b4716a924871e0c2410f30f
Reviewed-on: https://chromium-review.googlesource.com/887341Reviewed-by: default avatarBo <boliu@chromium.org>
Commit-Queue: Yoland Yan <yolandyan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#532003}
parent 844af309
......@@ -466,7 +466,6 @@ android_library("content_javatests") {
"javatests/src/org/chromium/content/browser/JavaBridgeCoercionTest.java",
"javatests/src/org/chromium/content/browser/JavaBridgeFieldsTest.java",
"javatests/src/org/chromium/content/browser/JavaBridgeReturnValuesTest.java",
"javatests/src/org/chromium/content/browser/JavaBridgeTestCommon.java",
"javatests/src/org/chromium/content/browser/MediaResourceGetterTest.java",
"javatests/src/org/chromium/content/browser/MediaSessionTest.java",
"javatests/src/org/chromium/content/browser/NavigationTest.java",
......
......@@ -69,7 +69,7 @@ public class ContentViewPointerTypeTest {
final Rect rect = DOMUtils.getNodeBounds(mActivityTestRule.getWebContents(), nodeId);
OnCursorUpdateHelper onCursorUpdateHelper = mActivityTestRule.getOnCursorUpdateHelper();
int onCursorUpdateCount = onCursorUpdateHelper.getCallCount();
mActivityTestRule.runOnUiThreadForTestCommon(new Runnable() {
mActivityTestRule.runOnUiThread(new Runnable() {
@Override
public void run() {
RenderCoordinates coord = mActivityTestRule.getRenderCoordinates();
......
......@@ -4,15 +4,20 @@
package org.chromium.content.browser;
import org.junit.Assert;
import org.junit.runner.Description;
import org.junit.runners.model.Statement;
import org.chromium.base.Log;
import org.chromium.base.test.SetUpStatement;
import org.chromium.base.test.SetUpTestRule;
import org.chromium.base.test.util.UrlUtils;
import org.chromium.content.browser.test.util.TestCallbackHelperContainer;
import org.chromium.content_public.browser.JavascriptInjector;
import org.chromium.content_public.browser.LoadUrlParams;
import org.chromium.content_public.browser.WebContents;
import org.chromium.content_shell_apk.ContentShellActivity;
import org.chromium.content_shell_apk.ContentShellActivityTestRule;
import org.chromium.content_shell_apk.ContentShellTestCommon.TestCommonCallback;
import java.lang.annotation.Annotation;
......@@ -20,29 +25,75 @@ import java.lang.annotation.Annotation;
* ActivityTestRule with common functionality for testing the Java Bridge.
*/
public class JavaBridgeActivityTestRule
extends ContentShellActivityTestRule implements TestCommonCallback<ContentShellActivity>,
SetUpTestRule<JavaBridgeActivityTestRule> {
private JavaBridgeTestCommon mTestCommon;
extends ContentShellActivityTestRule implements SetUpTestRule<JavaBridgeActivityTestRule> {
private TestCallbackHelperContainer mTestCallbackHelperContainer;
private boolean mSetup = false;
public JavaBridgeActivityTestRule() {
super();
mTestCommon = new JavaBridgeTestCommon(this);
public static class Controller {
private static final int RESULT_WAIT_TIME = 5000;
private boolean mIsResultReady;
protected synchronized void notifyResultIsReady() {
mIsResultReady = true;
notify();
}
protected synchronized void waitForResult() {
while (!mIsResultReady) {
try {
wait(RESULT_WAIT_TIME);
} catch (Exception e) {
continue;
}
if (!mIsResultReady) {
Assert.fail("Wait timed out");
}
}
mIsResultReady = false;
}
}
public TestCallbackHelperContainer getTestCallBackHelperContainer() {
return mTestCallbackHelperContainer;
}
/**
* Sets up the ContentView. Intended to be called from setUp().
*/
public void setUpContentView() {
mTestCommon.setUpContentView();
}
// This starts the activity, so must be called on the test thread.
final ContentShellActivity activity = launchContentShellWithUrl(
UrlUtils.encodeHtmlDataUri("<html><head></head><body>test</body></html>"));
waitForActiveShellToBeDoneLoading();
public TestCallbackHelperContainer getTestCallBackHelperContainer() {
return mTestCommon.getTestCallBackHelperContainer();
try {
runOnUiThread(new Runnable() {
@Override
public void run() {
mTestCallbackHelperContainer =
new TestCallbackHelperContainer(activity.getActiveContentViewCore());
}
});
} catch (Throwable e) {
throw new RuntimeException(
"Failed to set up ContentView: " + Log.getStackTraceString(e));
}
}
public void executeJavaScript(String script) throws Throwable {
mTestCommon.executeJavaScript(script);
runOnUiThread(new Runnable() {
@Override
public void run() {
// When a JavaScript URL is executed, if the value of the last
// expression evaluated is not 'undefined', this value is
// converted to a string and used as the new document for the
// frame. We don't want this behaviour, so wrap the script in
// an anonymous function.
getWebContents().getNavigationController().loadUrl(
new LoadUrlParams("javascript:(function() { " + script + " })()"));
}
});
}
public void injectObjectAndReload(Object object, String name) throws Exception {
......@@ -51,19 +102,49 @@ public class JavaBridgeActivityTestRule
public void injectObjectAndReload(Object object, String name,
Class<? extends Annotation> requiredAnnotation) throws Exception {
mTestCommon.injectObjectsAndReload(object, name, null, null, requiredAnnotation);
injectObjectsAndReload(object, name, null, null, requiredAnnotation);
}
public void injectObjectsAndReload(final Object object1, final String name1,
final Object object2, final String name2,
final Class<? extends Annotation> requiredAnnotation) throws Exception {
mTestCommon.injectObjectsAndReload(object1, name1, object2, name2, requiredAnnotation);
TestCallbackHelperContainer.OnPageFinishedHelper onPageFinishedHelper =
mTestCallbackHelperContainer.getOnPageFinishedHelper();
int currentCallCount = onPageFinishedHelper.getCallCount();
try {
runOnUiThread(new Runnable() {
@Override
public void run() {
WebContents webContents = getWebContents();
JavascriptInjector injector = JavascriptInjector.fromWebContents(webContents);
injector.addPossiblyUnsafeInterface(object1, name1, requiredAnnotation);
if (object2 != null && name2 != null) {
injector.addPossiblyUnsafeInterface(object2, name2, requiredAnnotation);
}
webContents.getNavigationController().reload(true);
}
});
onPageFinishedHelper.waitForCallback(currentCallCount);
} catch (Throwable e) {
throw new RuntimeException(
"Failed to injectObjectsAndReload: " + Log.getStackTraceString(e));
}
}
public void synchronousPageReload() throws Throwable {
mTestCommon.synchronousPageReload();
TestCallbackHelperContainer.OnPageFinishedHelper onPageFinishedHelper =
mTestCallbackHelperContainer.getOnPageFinishedHelper();
int currentCallCount = onPageFinishedHelper.getCallCount();
runOnUiThread(new Runnable() {
@Override
public void run() {
getWebContents().getNavigationController().reload(true);
}
});
onPageFinishedHelper.waitForCallback(currentCallCount);
}
@Override
public Statement apply(Statement base, Description desc) {
SetUpStatement setUpBase = new SetUpStatement(base, this, mSetup);
......
......@@ -14,7 +14,7 @@ import org.junit.runner.RunWith;
import org.chromium.base.test.BaseJUnit4ClassRunner;
import org.chromium.base.test.util.Feature;
import org.chromium.content.browser.JavaBridgeTestCommon.Controller;
import org.chromium.content.browser.JavaBridgeActivityTestRule.Controller;
/**
* Part of the test suite for the Java Bridge. This class tests that we correctly convert
......
......@@ -14,7 +14,7 @@ import org.junit.runner.RunWith;
import org.chromium.base.test.BaseJUnit4ClassRunner;
import org.chromium.base.test.util.Feature;
import org.chromium.content.browser.JavaBridgeTestCommon.Controller;
import org.chromium.content.browser.JavaBridgeActivityTestRule.Controller;
/**
* Part of the test suite for the Java Bridge. This class tests the general use of arrays.
......
......@@ -29,7 +29,6 @@ public class JavaBridgeBareboneTest {
new JavaBridgeActivityTestRule().shouldSetUp(false);
private TestCallbackHelperContainer mTestCallbackHelperContainer;
private final JavaBridgeTestCommon mTestCommon = new JavaBridgeTestCommon(mActivityTestRule);
@Before
public void setUp() throws Exception {
......
......@@ -18,7 +18,7 @@ import org.junit.runner.RunWith;
import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.base.test.util.DisabledTest;
import org.chromium.base.test.util.Feature;
import org.chromium.content.browser.JavaBridgeTestCommon.Controller;
import org.chromium.content.browser.JavaBridgeActivityTestRule.Controller;
import org.chromium.content.browser.test.ContentJUnit4ClassRunner;
import org.chromium.content.browser.test.util.TestCallbackHelperContainer;
import org.chromium.content_public.browser.LoadUrlParams;
......
......@@ -17,7 +17,7 @@ import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.base.test.util.DisabledTest;
import org.chromium.base.test.util.Feature;
import org.chromium.base.test.util.RetryOnFailure;
import org.chromium.content.browser.JavaBridgeTestCommon.Controller;
import org.chromium.content.browser.JavaBridgeActivityTestRule.Controller;
import org.chromium.content.browser.test.ContentJUnit4ClassRunner;
import org.chromium.content_public.browser.JavaScriptCallback;
import org.chromium.content_public.browser.LoadUrlParams;
......
......@@ -17,7 +17,7 @@ import org.junit.runner.RunWith;
import org.chromium.base.test.BaseJUnit4ClassRunner;
import org.chromium.base.test.util.Feature;
import org.chromium.base.test.util.UrlUtils;
import org.chromium.content.browser.JavaBridgeTestCommon.Controller;
import org.chromium.content.browser.JavaBridgeActivityTestRule.Controller;
import java.io.File;
......
......@@ -14,7 +14,7 @@ import org.junit.runner.RunWith;
import org.chromium.base.test.BaseJUnit4ClassRunner;
import org.chromium.base.test.util.Feature;
import org.chromium.content.browser.JavaBridgeTestCommon.Controller;
import org.chromium.content.browser.JavaBridgeActivityTestRule.Controller;
/**
* Part of the test suite for the Java Bridge. This test tests the
......
......@@ -14,7 +14,7 @@ import org.junit.runner.RunWith;
import org.chromium.base.test.BaseJUnit4ClassRunner;
import org.chromium.base.test.util.Feature;
import org.chromium.content.browser.JavaBridgeTestCommon.Controller;
import org.chromium.content.browser.JavaBridgeActivityTestRule.Controller;
/**
* Part of the test suite for the Java Bridge. This test checks that we correctly convert Java
......
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.content.browser;
import android.util.Log;
import org.junit.Assert;
import org.chromium.base.test.util.UrlUtils;
import org.chromium.content.browser.test.util.TestCallbackHelperContainer;
import org.chromium.content_public.browser.JavascriptInjector;
import org.chromium.content_public.browser.LoadUrlParams;
import org.chromium.content_public.browser.WebContents;
import org.chromium.content_shell_apk.ContentShellActivity;
import org.chromium.content_shell_apk.ContentShellTestCommon.TestCommonCallback;
import java.lang.annotation.Annotation;
/**
* Common functionality implementation for testing the Java Bridge.
*/
public final class JavaBridgeTestCommon {
protected TestCallbackHelperContainer mTestCallbackHelperContainer;
private final TestCommonCallback<ContentShellActivity> mCallback;
public JavaBridgeTestCommon(TestCommonCallback<ContentShellActivity> callback) {
mCallback = callback;
}
public static class Controller {
private static final int RESULT_WAIT_TIME = 5000;
private boolean mIsResultReady;
protected synchronized void notifyResultIsReady() {
mIsResultReady = true;
notify();
}
protected synchronized void waitForResult() {
while (!mIsResultReady) {
try {
wait(RESULT_WAIT_TIME);
} catch (Exception e) {
continue;
}
if (!mIsResultReady) {
Assert.fail("Wait timed out");
}
}
mIsResultReady = false;
}
}
TestCallbackHelperContainer getTestCallBackHelperContainer() {
return mTestCallbackHelperContainer;
}
void setUpContentView() {
// This starts the activity, so must be called on the test thread.
final ContentShellActivity activity = mCallback.launchContentShellWithUrlForTestCommon(
UrlUtils.encodeHtmlDataUri("<html><head></head><body>test</body></html>"));
mCallback.waitForActiveShellToBeDoneLoadingForTestCommon();
try {
mCallback.runOnUiThreadForTestCommon(new Runnable() {
@Override
public void run() {
mTestCallbackHelperContainer =
new TestCallbackHelperContainer(activity.getActiveContentViewCore());
}
});
} catch (Throwable e) {
throw new RuntimeException(
"Failed to set up ContentView: " + Log.getStackTraceString(e));
}
}
void executeJavaScript(final String script) throws Throwable {
mCallback.runOnUiThreadForTestCommon(new Runnable() {
@Override
public void run() {
// When a JavaScript URL is executed, if the value of the last
// expression evaluated is not 'undefined', this value is
// converted to a string and used as the new document for the
// frame. We don't want this behaviour, so wrap the script in
// an anonymous function.
mCallback.getWebContentsForTestCommon().getNavigationController().loadUrl(
new LoadUrlParams("javascript:(function() { " + script + " })()"));
}
});
}
void injectObjectsAndReload(final Object object1, final String name1, final Object object2,
final String name2, final Class<? extends Annotation> requiredAnnotation)
throws Exception {
TestCallbackHelperContainer.OnPageFinishedHelper onPageFinishedHelper =
mTestCallbackHelperContainer.getOnPageFinishedHelper();
int currentCallCount = onPageFinishedHelper.getCallCount();
try {
mCallback.runOnUiThreadForTestCommon(new Runnable() {
@Override
public void run() {
WebContents webContents = mCallback.getWebContentsForTestCommon();
JavascriptInjector injector = JavascriptInjector.fromWebContents(webContents);
injector.addPossiblyUnsafeInterface(object1, name1, requiredAnnotation);
if (object2 != null && name2 != null) {
injector.addPossiblyUnsafeInterface(object2, name2, requiredAnnotation);
}
webContents.getNavigationController().reload(true);
}
});
onPageFinishedHelper.waitForCallback(currentCallCount);
} catch (Throwable e) {
throw new RuntimeException(
"Failed to injectObjectsAndReload: " + Log.getStackTraceString(e));
}
}
void synchronousPageReload() throws Throwable {
TestCallbackHelperContainer.OnPageFinishedHelper onPageFinishedHelper =
mTestCallbackHelperContainer.getOnPageFinishedHelper();
int currentCallCount = onPageFinishedHelper.getCallCount();
mCallback.runOnUiThreadForTestCommon(new Runnable() {
@Override
public void run() {
mCallback.getWebContentsForTestCommon().getNavigationController().reload(true);
}
});
onPageFinishedHelper.waitForCallback(currentCallCount);
}
}
......@@ -227,7 +227,7 @@ public class DialogOverlayImplTestRule extends ContentShellActivityTestRule {
}
};
getActivityForTestCommon().getActiveShell().setOverayModeChangedCallbackForTesting(
getActivity().getActiveShell().setOverayModeChangedCallbackForTesting(
overlayModeChanged);
}
}, desc);
......
......@@ -187,7 +187,6 @@ android_library("content_shell_test_java") {
java_files = [
"javatests/src/org/chromium/content_shell_apk/ContentShellPreconditionsTest.java",
"javatests/src/org/chromium/content_shell_apk/ContentShellShellManagementTest.java",
"javatests/src/org/chromium/content_shell_apk/ContentShellTestCommon.java",
"javatests/src/org/chromium/content_shell_apk/ContentShellActivityTestRule.java",
"javatests/src/org/chromium/content_shell_apk/ContentShellUrlTest.java",
]
......
......@@ -6,45 +6,59 @@ package org.chromium.content_shell_apk;
import static org.chromium.base.test.util.ScalableTimeout.scaleTimeout;
import android.app.Instrumentation;
import android.annotation.TargetApi;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.PowerManager;
import android.support.test.InstrumentationRegistry;
import android.support.test.rule.ActivityTestRule;
import android.text.TextUtils;
import android.view.ViewGroup;
import org.junit.Assert;
import org.chromium.base.ThreadUtils;
import org.chromium.base.test.util.CallbackHelper;
import org.chromium.base.test.util.UrlUtils;
import org.chromium.content.browser.ContentView;
import org.chromium.content.browser.ContentViewCore;
import org.chromium.content.browser.ContentViewCoreImpl;
import org.chromium.content.browser.RenderCoordinates;
import org.chromium.content.browser.test.util.Criteria;
import org.chromium.content.browser.test.util.CriteriaHelper;
import org.chromium.content.browser.test.util.TestCallbackHelperContainer;
import org.chromium.content.browser.webcontents.WebContentsImpl;
import org.chromium.content_public.browser.JavascriptInjector;
import org.chromium.content_public.browser.LoadUrlParams;
import org.chromium.content_public.browser.NavigationController;
import org.chromium.content_public.browser.WebContents;
import org.chromium.content_shell.Shell;
import org.chromium.content_shell.ShellViewAndroidDelegate.OnCursorUpdateHelper;
import org.chromium.content_shell_apk.ContentShellTestCommon.TestCommonCallback;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
/**
* ActivityTestRule for ContentShellActivity.
*
* Test can use this ActivityTestRule to launch or get ContentShellActivity.
*/
public class ContentShellActivityTestRule extends ActivityTestRule<ContentShellActivity>
implements TestCommonCallback<ContentShellActivity> {
private final ContentShellTestCommon mDelegate;
private final boolean mLaunchActivity;
public class ContentShellActivityTestRule extends ActivityTestRule<ContentShellActivity> {
/** The maximum time the waitForActiveShellToBeDoneLoading method will wait. */
private static final long WAIT_FOR_ACTIVE_SHELL_LOADING_TIMEOUT = scaleTimeout(10000);
protected static final long WAIT_PAGE_LOADING_TIMEOUT_SECONDS = scaleTimeout(15);
private final boolean mLaunchActivity;
public ContentShellActivityTestRule() {
this(false, false);
}
......@@ -52,12 +66,20 @@ public class ContentShellActivityTestRule extends ActivityTestRule<ContentShellA
public ContentShellActivityTestRule(boolean initialTouchMode, boolean launchActivity) {
super(ContentShellActivity.class, initialTouchMode, launchActivity);
mLaunchActivity = launchActivity;
mDelegate = new ContentShellTestCommon(this);
}
@Override
@TargetApi(Build.VERSION_CODES.KITKAT_WATCH)
@SuppressWarnings("deprecation")
protected void beforeActivityLaunched() {
mDelegate.assertScreenIsOn();
PowerManager pm = (PowerManager) InstrumentationRegistry.getInstrumentation()
.getContext()
.getSystemService(Context.POWER_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
Assert.assertTrue("Many tests will fail if the screen is not on.", pm.isInteractive());
} else {
Assert.assertTrue("Many tests will fail if the screen is not on.", pm.isScreenOn());
}
}
/**
......@@ -65,8 +87,17 @@ public class ContentShellActivityTestRule extends ActivityTestRule<ContentShellA
* The URL can be null, in which case will default to ContentShellActivity.DEFAULT_SHELL_URL.
*/
public ContentShellActivity launchContentShellWithUrl(String url) {
Assert.assertFalse(mLaunchActivity);
return mDelegate.launchContentShellWithUrl(url);
Assert.assertFalse(
"Activity is already launched, setup the test rule to NOT auto-launch activity",
mLaunchActivity);
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (url != null) intent.setData(Uri.parse(url));
intent.setComponent(
new ComponentName(InstrumentationRegistry.getInstrumentation().getTargetContext(),
ContentShellActivity.class));
return launchActivity(intent);
}
/**
......@@ -75,36 +106,66 @@ public class ContentShellActivityTestRule extends ActivityTestRule<ContentShellA
* @param url Test url to load.
*/
public ContentShellActivity launchContentShellWithUrlSync(String url) {
Assert.assertFalse(mLaunchActivity);
return mDelegate.launchContentShellWithUrlSync(url);
String isolatedTestFileUrl = UrlUtils.getIsolatedTestFileUrl(url);
ContentShellActivity activity = launchContentShellWithUrl(isolatedTestFileUrl);
Assert.assertNotNull(getActivity());
waitForActiveShellToBeDoneLoading();
Assert.assertEquals(
isolatedTestFileUrl, getContentViewCore().getWebContents().getLastCommittedUrl());
return activity;
}
/**
* Returns the OnCursorUpdateHelper.
*/
public OnCursorUpdateHelper getOnCursorUpdateHelper() throws ExecutionException {
return mDelegate.getOnCursorUpdateHelper();
return ThreadUtils.runOnUiThreadBlocking(new Callable<OnCursorUpdateHelper>() {
@Override
public OnCursorUpdateHelper call() {
return getActivity()
.getActiveShell()
.getViewAndroidDelegate()
.getOnCursorUpdateHelper();
}
});
}
/**
* Returns the current ContentViewCore or null if there is no ContentView.
*/
public ContentViewCoreImpl getContentViewCore() {
return (ContentViewCoreImpl) mDelegate.getContentViewCore();
try {
return ThreadUtils.runOnUiThreadBlocking(() -> {
return (ContentViewCoreImpl) getActivity().getActiveShell().getContentViewCore();
});
} catch (ExecutionException e) {
return null;
}
}
/**
* Returns the WebContents of this Shell.
*/
public WebContents getWebContents() {
return mDelegate.getWebContents();
try {
return ThreadUtils.runOnUiThreadBlocking(() -> {
return getActivity().getActiveShell().getWebContents();
});
} catch (ExecutionException e) {
return null;
}
}
/**
* Returns the RenderCoordinates of the WebContents.
*/
public RenderCoordinates getRenderCoordinates() {
return mDelegate.getRenderCoordinates();
try {
return ThreadUtils.runOnUiThreadBlocking(
() -> { return ((WebContentsImpl) getWebContents()).getRenderCoordinates(); });
} catch (ExecutionException e) {
return null;
}
}
public JavascriptInjector getJavascriptInjector() {
......@@ -118,7 +179,31 @@ public class ContentShellActivityTestRule extends ActivityTestRule<ContentShellA
* to wait is to use a TestCallbackHelperContainer after the initial load is completed.
*/
public void waitForActiveShellToBeDoneLoading() {
mDelegate.waitForActiveShellToBeDoneLoading();
// Wait for the Content Shell to be initialized.
CriteriaHelper.pollUiThread(new Criteria() {
@Override
public boolean isSatisfied() {
Shell shell = getActivity().getActiveShell();
// There are two cases here that need to be accounted for.
// The first is that we've just created a Shell and it isn't
// loading because it has no URL set yet. The second is that
// we've set a URL and it actually is loading.
if (shell == null) {
updateFailureReason("Shell is null.");
return false;
}
if (shell.isLoading()) {
updateFailureReason("Shell is still loading.");
return false;
}
if (TextUtils.isEmpty(
shell.getContentViewCore().getWebContents().getLastCommittedUrl())) {
updateFailureReason("Shell's URL is empty or null.");
return false;
}
return true;
}
}, WAIT_FOR_ACTIVE_SHELL_LOADING_TIMEOUT, CriteriaHelper.DEFAULT_POLLING_INTERVAL);
}
/**
......@@ -128,7 +213,18 @@ public class ContentShellActivityTestRule extends ActivityTestRule<ContentShellA
* @throws ExecutionException
*/
public Shell loadNewShell(String url) throws ExecutionException {
return mDelegate.loadNewShell(url);
Shell shell = ThreadUtils.runOnUiThreadBlocking(new Callable<Shell>() {
@Override
public Shell call() {
getActivity().getShellManager().launchShell(url);
return getActivity().getActiveShell();
}
});
Assert.assertNotNull("Unable to create shell.", shell);
Assert.assertEquals("Active shell unexpected.", shell,
getActivity().getActiveShell());
waitForActiveShellToBeDoneLoading();
return shell;
}
/**
......@@ -141,7 +237,13 @@ public class ContentShellActivityTestRule extends ActivityTestRule<ContentShellA
public void loadUrl(NavigationController navigationController,
TestCallbackHelperContainer callbackHelperContainer, LoadUrlParams params)
throws Throwable {
mDelegate.loadUrl(navigationController, callbackHelperContainer, params);
handleBlockingCallbackAction(
callbackHelperContainer.getOnPageFinishedHelper(), new Runnable() {
@Override
public void run() {
navigationController.loadUrl(params);
}
});
}
/**
......@@ -149,11 +251,14 @@ public class ContentShellActivityTestRule extends ActivityTestRule<ContentShellA
* is incremented.
*
* @param callbackHelper The callback helper that will be blocked on.
* @param action The action to be performed on the UI thread.
* @param uiThreadAction The action to be performed on the UI thread.
*/
public void handleBlockingCallbackAction(CallbackHelper callbackHelper, Runnable action)
public void handleBlockingCallbackAction(CallbackHelper callbackHelper, Runnable uiThreadAction)
throws Throwable {
mDelegate.handleBlockingCallbackAction(callbackHelper, action);
int currentCallCount = callbackHelper.getCallCount();
runOnUiThread(uiThreadAction);
callbackHelper.waitForCallback(
currentCallCount, 1, WAIT_PAGE_LOADING_TIMEOUT_SECONDS, TimeUnit.SECONDS);
}
// TODO(aelias): This method needs to be removed once http://crbug.com/179511 is fixed.
......@@ -163,7 +268,14 @@ public class ContentShellActivityTestRule extends ActivityTestRule<ContentShellA
* from the compositor and asserts that this happens.
*/
public void assertWaitForPageScaleFactorMatch(float expectedScale) {
mDelegate.assertWaitForPageScaleFactorMatch(expectedScale);
final RenderCoordinates coord = getRenderCoordinates();
CriteriaHelper.pollInstrumentationThread(
Criteria.equals(expectedScale, new Callable<Float>() {
@Override
public Float call() {
return coord.getPageScaleFactor();
}
}));
}
/**
......@@ -171,7 +283,18 @@ public class ContentShellActivityTestRule extends ActivityTestRule<ContentShellA
* {@link ContentView}.
*/
public void replaceContainerView() throws Throwable {
mDelegate.replaceContainerView();
ThreadUtils.runOnUiThreadBlocking(new Runnable() {
@Override
public void run() {
ContentView cv = ContentView.createContentView(
getActivity(), getContentViewCore());
((ViewGroup) getContentViewCore().getContainerView().getParent()).addView(cv);
getContentViewCore().setContainerView(cv);
getContentViewCore().setContainerViewInternals(cv);
cv.requestFocus();
}
});
}
/**
......@@ -183,44 +306,4 @@ public class ContentShellActivityTestRule extends ActivityTestRule<ContentShellA
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RerunWithUpdatedContainerView {}
@Override
public ContentShellActivity getActivityForTestCommon() {
return getActivity();
}
@Override
public Instrumentation getInstrumentationForTestCommon() {
return InstrumentationRegistry.getInstrumentation();
}
@Override
public ContentShellActivity launchActivityWithIntentForTestCommon(Intent t) {
return launchActivity(t);
}
@Override
public void runOnUiThreadForTestCommon(Runnable runnable) throws Throwable {
runOnUiThread(runnable);
}
@Override
public ContentViewCore getContentViewCoreForTestCommon() {
return getContentViewCore();
}
@Override
public WebContents getWebContentsForTestCommon() {
return getWebContents();
}
@Override
public void waitForActiveShellToBeDoneLoadingForTestCommon() {
waitForActiveShellToBeDoneLoading();
}
@Override
public ContentShellActivity launchContentShellWithUrlForTestCommon(String url) {
return launchContentShellWithUrl(url);
}
}
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.content_shell_apk;
import static org.chromium.base.test.util.ScalableTimeout.scaleTimeout;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.Instrumentation;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.PowerManager;
import android.text.TextUtils;
import android.view.ViewGroup;
import org.junit.Assert;
import org.chromium.base.ThreadUtils;
import org.chromium.base.test.util.CallbackHelper;
import org.chromium.base.test.util.UrlUtils;
import org.chromium.content.browser.ContentView;
import org.chromium.content.browser.ContentViewCore;
import org.chromium.content.browser.RenderCoordinates;
import org.chromium.content.browser.test.util.Criteria;
import org.chromium.content.browser.test.util.CriteriaHelper;
import org.chromium.content.browser.test.util.TestCallbackHelperContainer;
import org.chromium.content.browser.webcontents.WebContentsImpl;
import org.chromium.content_public.browser.LoadUrlParams;
import org.chromium.content_public.browser.NavigationController;
import org.chromium.content_public.browser.WebContents;
import org.chromium.content_shell.Shell;
import org.chromium.content_shell.ShellViewAndroidDelegate.OnCursorUpdateHelper;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
/**
* Implementation of utility methods for ContentShellTestBase and ContentShellActivityTestRule to
* wrap around during instrumentation test JUnit3 to JUnit4 migration
*
* Please do not use this class' methods in places other than {@link ContentShellTestBase}
* and {@link ContentShellActivityTestRule}
*/
public final class ContentShellTestCommon {
/** The maximum time the waitForActiveShellToBeDoneLoading method will wait. */
private static final long WAIT_FOR_ACTIVE_SHELL_LOADING_TIMEOUT = scaleTimeout(10000);
static final long WAIT_PAGE_LOADING_TIMEOUT_SECONDS = scaleTimeout(15);
private final TestCommonCallback<ContentShellActivity> mCallback;
ContentShellTestCommon(TestCommonCallback<ContentShellActivity> callback) {
mCallback = callback;
}
@TargetApi(Build.VERSION_CODES.KITKAT_WATCH)
@SuppressWarnings("deprecation")
void assertScreenIsOn() {
PowerManager pm = (PowerManager) mCallback.getInstrumentationForTestCommon()
.getContext()
.getSystemService(Context.POWER_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
Assert.assertTrue("Many tests will fail if the screen is not on.", pm.isInteractive());
} else {
Assert.assertTrue("Many tests will fail if the screen is not on.", pm.isScreenOn());
}
}
ContentShellActivity launchContentShellWithUrl(String url) {
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (url != null) intent.setData(Uri.parse(url));
intent.setComponent(
new ComponentName(mCallback.getInstrumentationForTestCommon().getTargetContext(),
ContentShellActivity.class));
return mCallback.launchActivityWithIntentForTestCommon(intent);
}
// TODO(yolandyan): This should use the url exactly without the getIsolatedTestFileUrl call.
ContentShellActivity launchContentShellWithUrlSync(String url) {
String isolatedTestFileUrl = UrlUtils.getIsolatedTestFileUrl(url);
ContentShellActivity activity = launchContentShellWithUrl(isolatedTestFileUrl);
Assert.assertNotNull(mCallback.getActivityForTestCommon());
waitForActiveShellToBeDoneLoading();
Assert.assertEquals(
isolatedTestFileUrl, getContentViewCore().getWebContents().getLastCommittedUrl());
return activity;
}
void waitForActiveShellToBeDoneLoading() {
// Wait for the Content Shell to be initialized.
CriteriaHelper.pollUiThread(new Criteria() {
@Override
public boolean isSatisfied() {
Shell shell = mCallback.getActivityForTestCommon().getActiveShell();
// There are two cases here that need to be accounted for.
// The first is that we've just created a Shell and it isn't
// loading because it has no URL set yet. The second is that
// we've set a URL and it actually is loading.
if (shell == null) {
updateFailureReason("Shell is null.");
return false;
}
if (shell.isLoading()) {
updateFailureReason("Shell is still loading.");
return false;
}
if (TextUtils.isEmpty(
shell.getContentViewCore().getWebContents().getLastCommittedUrl())) {
updateFailureReason("Shell's URL is empty or null.");
return false;
}
return true;
}
}, WAIT_FOR_ACTIVE_SHELL_LOADING_TIMEOUT, CriteriaHelper.DEFAULT_POLLING_INTERVAL);
}
OnCursorUpdateHelper getOnCursorUpdateHelper() throws ExecutionException {
return ThreadUtils.runOnUiThreadBlocking(new Callable<OnCursorUpdateHelper>() {
@Override
public OnCursorUpdateHelper call() {
return mCallback.getActivityForTestCommon()
.getActiveShell()
.getViewAndroidDelegate()
.getOnCursorUpdateHelper();
}
});
}
ContentViewCore getContentViewCore() {
try {
return ThreadUtils.runOnUiThreadBlocking(() -> {
return mCallback.getActivityForTestCommon().getActiveShell().getContentViewCore();
});
} catch (ExecutionException e) {
return null;
}
}
WebContents getWebContents() {
try {
return ThreadUtils.runOnUiThreadBlocking(() -> {
return mCallback.getActivityForTestCommon().getActiveShell().getWebContents();
});
} catch (ExecutionException e) {
return null;
}
}
RenderCoordinates getRenderCoordinates() {
try {
return ThreadUtils.runOnUiThreadBlocking(
() -> { return ((WebContentsImpl) getWebContents()).getRenderCoordinates(); });
} catch (ExecutionException e) {
return null;
}
}
void loadUrl(final NavigationController navigationController,
TestCallbackHelperContainer callbackHelperContainer, final LoadUrlParams params)
throws Throwable {
handleBlockingCallbackAction(
callbackHelperContainer.getOnPageFinishedHelper(), new Runnable() {
@Override
public void run() {
navigationController.loadUrl(params);
}
});
}
Shell loadNewShell(final String url) throws ExecutionException {
Shell shell = ThreadUtils.runOnUiThreadBlocking(new Callable<Shell>() {
@Override
public Shell call() {
mCallback.getActivityForTestCommon().getShellManager().launchShell(url);
return mCallback.getActivityForTestCommon().getActiveShell();
}
});
Assert.assertNotNull("Unable to create shell.", shell);
Assert.assertEquals("Active shell unexpected.", shell,
mCallback.getActivityForTestCommon().getActiveShell());
waitForActiveShellToBeDoneLoading();
return shell;
}
void handleBlockingCallbackAction(CallbackHelper callbackHelper, Runnable uiThreadAction)
throws Throwable {
int currentCallCount = callbackHelper.getCallCount();
mCallback.runOnUiThreadForTestCommon(uiThreadAction);
callbackHelper.waitForCallback(
currentCallCount, 1, WAIT_PAGE_LOADING_TIMEOUT_SECONDS, TimeUnit.SECONDS);
}
void assertWaitForPageScaleFactorMatch(float expectedScale) {
final RenderCoordinates coord = getRenderCoordinates();
CriteriaHelper.pollInstrumentationThread(
Criteria.equals(expectedScale, new Callable<Float>() {
@Override
public Float call() {
return coord.getPageScaleFactor();
}
}));
}
void replaceContainerView() throws Throwable {
ThreadUtils.runOnUiThreadBlocking(new Runnable() {
@Override
public void run() {
ContentView cv = ContentView.createContentView(
mCallback.getActivityForTestCommon(), getContentViewCore());
((ViewGroup) getContentViewCore().getContainerView().getParent()).addView(cv);
getContentViewCore().setContainerView(cv);
getContentViewCore().setContainerViewInternals(cv);
cv.requestFocus();
}
});
}
/**
* Interface used by TestRule and TestBase class to implement methods for TestCommonCallback
* class to use.
*/
public static interface TestCommonCallback<T extends Activity> {
Instrumentation getInstrumentationForTestCommon();
T launchActivityWithIntentForTestCommon(Intent t);
T getActivityForTestCommon();
void runOnUiThreadForTestCommon(Runnable runnable) throws Throwable;
ContentViewCore getContentViewCoreForTestCommon();
ContentShellActivity launchContentShellWithUrlForTestCommon(String url);
WebContents getWebContentsForTestCommon();
void waitForActiveShellToBeDoneLoadingForTestCommon();
}
}
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