Commit 9210616d authored by Changwan Ryu's avatar Changwan Ryu Committed by Commit Bot

Fortify autofill tests for WebView

Currently, we are testing whether certain callbacks are called / not
called in specific situations. This type of one-off tests are easily
isolatable, but it has its own limits - it is difficult to detect newly
added callbacks.

The new scheme audits all the calls into AutofillManager and ensures
that WebView autofill functionalities can work as expected.

Also, this CL refactors out some variables from TestAwAutofillManager
(renamed from AwAutofillManagerHelper) into AwAutofillTest and make
the test manager a thin wrapper.

Note: All the tests were run locally, as there is no trybot for O.

BUG=717658

Change-Id: Idacea03727f5f1cd56cd62dc1420dc74f48b04cf
Reviewed-on: https://chromium-review.googlesource.com/706379Reviewed-by: default avatarTao Bai <michaelbai@chromium.org>
Reviewed-by: default avatarYoland Yan <yolandyan@chromium.org>
Commit-Queue: Changwan Ryu <changwan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#509690}
parent 93c331c2
......@@ -27,6 +27,7 @@ import android.view.ViewStructure.HtmlInfo.Builder;
import android.view.autofill.AutofillId;
import android.view.autofill.AutofillValue;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
......@@ -45,8 +46,11 @@ import org.chromium.net.test.util.TestWebServer;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.TimeoutException;
/**
* Tests for WebView Autofill.
......@@ -58,7 +62,7 @@ public class AwAutofillTest {
/**
* This class only implements the necessary methods of ViewStructure for testing.
*/
public static class TestViewStructure extends ViewStructure {
private static class TestViewStructure extends ViewStructure {
/**
* Implementation of HtmlInfo.
*/
......@@ -392,48 +396,21 @@ public class AwAutofillTest {
private boolean mChecked;
}
private static class AwAutofillManagerHelper extends AwAutofillManager {
private CallbackHelper mVirtualViewEntered = new CallbackHelper();
private CallbackHelper mVirtualValueChanged = new CallbackHelper();
private CallbackHelper mCommitCallbackHelper = new CallbackHelper();
private CallbackHelper mCancelCallbackHelper = new CallbackHelper();
private AwContents mAwContents;
private TestViewStructure mTestViewStructure;
private ArrayList<Pair<Integer, AutofillValue>> mChangedValues;
public AwAutofillManagerHelper(Context context) {
private class TestAwAutofillManager extends AwAutofillManager {
public TestAwAutofillManager(Context context) {
super(context);
}
@Override
public void notifyVirtualViewEntered(View parent, int childId, Rect absBounds) {
mVirtualViewEntered.notifyCalled();
}
public void waitForNotifyVirtualViewEnteredCalled() throws Throwable {
int count = mVirtualViewEntered.getCallCount();
mVirtualViewEntered.waitForCallback(count);
}
public CallbackHelper getVirtualValueChangedCallbackHelper() {
return mVirtualValueChanged;
}
public void setAwContents(AwContents awContents) {
mAwContents = awContents;
mEventQueue.add(AUTOFILL_VIEW_ENTERED);
mCallbackHelper.notifyCalled();
}
public void invokeOnProvideAutoFillVirtualStructure() {
mTestViewStructure = new TestViewStructure();
mAwContents.onProvideAutoFillVirtualStructure(mTestViewStructure, 1);
}
public void invokeAutofill(SparseArray<AutofillValue> values) {
mAwContents.autofill(values);
}
public TestViewStructure getTestViewStructure() {
return mTestViewStructure;
@Override
public void notifyVirtualViewExited(View parent, int childId) {
mEventQueue.add(AUTOFILL_VIEW_EXITED);
mCallbackHelper.notifyCalled();
}
@Override
......@@ -442,59 +419,57 @@ public class AwAutofillTest {
mChangedValues = new ArrayList<Pair<Integer, AutofillValue>>();
}
mChangedValues.add(new Pair<Integer, AutofillValue>(childId, value));
mVirtualValueChanged.notifyCalled();
}
public ArrayList<Pair<Integer, AutofillValue>> getChangedValues() {
return mChangedValues;
}
public void clearChangedValues() {
if (mChangedValues != null) mChangedValues.clear();
mEventQueue.add(AUTOFILL_VALUE_CHANGED);
mCallbackHelper.notifyCalled();
}
@Override
public void commit() {
mCommitCallbackHelper.notifyCalled();
}
public CallbackHelper getCommitCallbackHelper() {
return mCommitCallbackHelper;
mEventQueue.add(AUTOFILL_COMMIT);
mCallbackHelper.notifyCalled();
}
@Override
public void cancel() {
mCancelCallbackHelper.notifyCalled();
}
public CallbackHelper getCancelCallbackHelper() {
return mCancelCallbackHelper;
mEventQueue.add(AUTOFILL_CANCEL);
mCallbackHelper.notifyCalled();
}
}
public static final String FILE = "/login.html";
public static final String FILE_URL = "file:///android_asset/autofill.html";
public final static int AUTOFILL_VIEW_ENTERED = 1;
public final static int AUTOFILL_VIEW_EXITED = 2;
public final static int AUTOFILL_VALUE_CHANGED = 3;
public final static int AUTOFILL_COMMIT = 4;
public final static int AUTOFILL_CANCEL = 5;
@Rule
public AwActivityTestRule mActivityTestRule = new AwActivityTestRule();
public AwActivityTestRule mRule = new AwActivityTestRule();
private AwTestContainerView mTestContainerView;
private TestAwContentsClient mContentsClient;
private AwAutofillManagerHelper mHelper;
private CallbackHelper mCallbackHelper = new CallbackHelper();
private AwContents mAwContents;
private TestViewStructure mTestViewStructure;
private ArrayList<Pair<Integer, AutofillValue>> mChangedValues;
private ConcurrentLinkedQueue<Integer> mEventQueue = new ConcurrentLinkedQueue<>();
@Before
public void setUp() throws Exception {
mContentsClient = new TestAwContentsClient();
mTestContainerView = mActivityTestRule.createAwTestContainerViewOnMainSync(
mTestContainerView = mRule.createAwTestContainerViewOnMainSync(
mContentsClient, false, new TestDependencyFactory() {
@Override
public AutofillProvider createAutofillProvider(
Context context, ViewGroup containerView) {
mHelper = new AwAutofillManagerHelper(context);
return new AwAutofillProvider(containerView, mHelper);
return new AwAutofillProvider(
containerView, new TestAwAutofillManager(context));
}
});
mHelper.setAwContents(mTestContainerView.getAwContents());
mActivityTestRule.enableJavaScriptOnUiThread(mTestContainerView.getAwContents());
mAwContents = mTestContainerView.getAwContents();
mRule.enableJavaScriptOnUiThread(mAwContents);
}
@Test
......@@ -514,17 +489,20 @@ public class AwAutofillTest {
+ "</form></body></html>";
final int totalControls = 3;
try {
int cnt = 0;
final String url = webServer.setResponse(FILE, data, null);
mActivityTestRule.loadUrlSync(mTestContainerView.getAwContents(),
mContentsClient.getOnPageFinishedHelper(), url);
loadUrlSync(url);
executeJavaScriptAndWaitForResult("document.getElementById('text1').select();");
CallbackHelper callbackHelper = mHelper.getVirtualValueChangedCallbackHelper();
int count = callbackHelper.getCallCount();
// Note that we cancel autofill in loading as a precautious measure.
cnt += waitForCallbackAndVerifyTypes(
cnt, new Integer[] {AUTOFILL_CANCEL, AUTOFILL_CANCEL});
dispatchDownAndUpKeyEvents(KeyEvent.KEYCODE_A);
mHelper.waitForNotifyVirtualViewEnteredCalled();
callbackHelper.waitForCallback(count);
mHelper.invokeOnProvideAutoFillVirtualStructure();
TestViewStructure viewStructure = mHelper.getTestViewStructure();
// Note that we currently call ENTER/EXIT one more time.
cnt += waitForCallbackAndVerifyTypes(cnt,
new Integer[] {AUTOFILL_CANCEL, AUTOFILL_VIEW_ENTERED, AUTOFILL_VIEW_EXITED,
AUTOFILL_VIEW_ENTERED, AUTOFILL_VALUE_CHANGED});
invokeOnProvideAutoFillVirtualStructure();
TestViewStructure viewStructure = mTestViewStructure;
assertNotNull(viewStructure);
assertEquals(totalControls, viewStructure.getChildCount());
......@@ -575,9 +553,11 @@ public class AwAutofillTest {
values.append(child0.getId(), AutofillValue.forText("example@example.com"));
values.append(child1.getId(), AutofillValue.forToggle(true));
values.append(child2.getId(), AutofillValue.forList(1));
count = callbackHelper.getCallCount();
mHelper.invokeAutofill(values);
callbackHelper.waitForCallback(count, totalControls);
cnt = getCallbackCount();
invokeAutofill(values);
waitForCallbackAndVerifyTypes(cnt,
new Integer[] {AUTOFILL_VALUE_CHANGED, AUTOFILL_VALUE_CHANGED,
AUTOFILL_VALUE_CHANGED});
// Verify form filled by Javascript
String value0 =
......@@ -605,23 +585,32 @@ public class AwAutofillTest {
+ "</form></body></html>";
try {
final String url = webServer.setResponse(FILE, data, null);
mActivityTestRule.loadUrlSync(mTestContainerView.getAwContents(),
mContentsClient.getOnPageFinishedHelper(), url);
loadUrlSync(url);
int cnt = 0;
executeJavaScriptAndWaitForResult("document.getElementById('text1').select();");
CallbackHelper callbackHelper = mHelper.getVirtualValueChangedCallbackHelper();
int count = callbackHelper.getCallCount();
// Note that we cancel autofill in loading as a precautious measure.
cnt += waitForCallbackAndVerifyTypes(
cnt, new Integer[] {AUTOFILL_CANCEL, AUTOFILL_CANCEL});
dispatchDownAndUpKeyEvents(KeyEvent.KEYCODE_A);
callbackHelper.waitForCallback(count);
ArrayList<Pair<Integer, AutofillValue>> values = mHelper.getChangedValues();
// Note that we currently call ENTER/EXIT one more time.
cnt += waitForCallbackAndVerifyTypes(cnt,
new Integer[] {AUTOFILL_CANCEL, AUTOFILL_VIEW_ENTERED, AUTOFILL_VIEW_EXITED,
AUTOFILL_VIEW_ENTERED, AUTOFILL_VALUE_CHANGED});
ArrayList<Pair<Integer, AutofillValue>> values = getChangedValues();
// Check if NotifyVirtualValueChanged() called and value is 'a'.
assertEquals(1, values.size());
assertEquals("a", values.get(0).second.getTextValue());
count = callbackHelper.getCallCount();
dispatchDownAndUpKeyEvents(KeyEvent.KEYCODE_B);
// Check if NotifyVirtualValueChanged() called 2 times, first value is 'a',
// Check if NotifyVirtualValueChanged() called again, first value is 'a',
// second value is 'ab', and both time has the same id.
callbackHelper.waitForCallback(count);
values = mHelper.getChangedValues();
waitForCallbackAndVerifyTypes(cnt,
new Integer[] {
AUTOFILL_VIEW_EXITED, AUTOFILL_VIEW_ENTERED, AUTOFILL_VALUE_CHANGED});
values = getChangedValues();
assertEquals(2, values.size());
assertEquals("a", values.get(0).second.getTextValue());
assertEquals("ab", values.get(1).second.getTextValue());
......@@ -642,24 +631,30 @@ public class AwAutofillTest {
+ "</form></body></html>";
try {
final String url = webServer.setResponse(FILE, data, null);
mActivityTestRule.loadUrlSync(mTestContainerView.getAwContents(),
mContentsClient.getOnPageFinishedHelper(), url);
loadUrlSync(url);
int cnt = 0;
executeJavaScriptAndWaitForResult("document.getElementById('text1').select();");
CallbackHelper callbackHelper = mHelper.getVirtualValueChangedCallbackHelper();
int count = callbackHelper.getCallCount();
// Note that we cancel autofill in loading as a precautious measure.
cnt += waitForCallbackAndVerifyTypes(
cnt, new Integer[] {AUTOFILL_CANCEL, AUTOFILL_CANCEL});
dispatchDownAndUpKeyEvents(KeyEvent.KEYCODE_A);
callbackHelper.waitForCallback(count);
ArrayList<Pair<Integer, AutofillValue>> values = mHelper.getChangedValues();
// Note that we currently call ENTER/EXIT one more time.
cnt += waitForCallbackAndVerifyTypes(cnt,
new Integer[] {AUTOFILL_CANCEL, AUTOFILL_VIEW_ENTERED, AUTOFILL_VIEW_EXITED,
AUTOFILL_VIEW_ENTERED, AUTOFILL_VALUE_CHANGED});
ArrayList<Pair<Integer, AutofillValue>> values = getChangedValues();
// Check if NotifyVirtualValueChanged() called and value is 'a'.
assertEquals(1, values.size());
assertEquals("a", values.get(0).second.getTextValue());
count = callbackHelper.getCallCount();
executeJavaScriptAndWaitForResult("document.getElementById('text1').value='c';");
assertEquals(7, getCallbackCount());
dispatchDownAndUpKeyEvents(KeyEvent.KEYCODE_B);
// Check if NotifyVirtualValueChanged() called one more time and value is 'cb', this
// means javascript change didn't trigger the NotifyVirtualValueChanged().
callbackHelper.waitForCallback(count);
values = mHelper.getChangedValues();
waitForCallbackAndVerifyTypes(cnt,
new Integer[] {
AUTOFILL_VIEW_EXITED, AUTOFILL_VIEW_ENTERED, AUTOFILL_VALUE_CHANGED});
values = getChangedValues();
assertEquals(2, values.size());
assertEquals("a", values.get(0).second.getTextValue());
assertEquals("cb", values.get(1).second.getTextValue());
......@@ -683,30 +678,34 @@ public class AwAutofillTest {
+ "</form></body></html>";
try {
final String url = webServer.setResponse(FILE, data, null);
mActivityTestRule.loadUrlSync(mTestContainerView.getAwContents(),
mContentsClient.getOnPageFinishedHelper(), url);
loadUrlSync(url);
int cnt = 0;
executeJavaScriptAndWaitForResult("document.getElementById('text1').select();");
CallbackHelper valueChangedCallback = mHelper.getVirtualValueChangedCallbackHelper();
int count = valueChangedCallback.getCallCount();
// Commit() hasn't been called.
assertEquals(0, count);
// Note that we cancel autofill in loading as a precautious measure.
cnt += waitForCallbackAndVerifyTypes(
cnt, new Integer[] {AUTOFILL_CANCEL, AUTOFILL_CANCEL});
dispatchDownAndUpKeyEvents(KeyEvent.KEYCODE_A);
valueChangedCallback.waitForCallback(count);
mHelper.invokeOnProvideAutoFillVirtualStructure();
// Note that we currently call ENTER/EXIT one more time.
cnt += waitForCallbackAndVerifyTypes(cnt,
new Integer[] {AUTOFILL_CANCEL, AUTOFILL_VIEW_ENTERED, AUTOFILL_VIEW_EXITED,
AUTOFILL_VIEW_ENTERED, AUTOFILL_VALUE_CHANGED});
invokeOnProvideAutoFillVirtualStructure();
// Fill the password.
executeJavaScriptAndWaitForResult("document.getElementById('passwordid').select();");
count = valueChangedCallback.getCallCount();
cnt += waitForCallbackAndVerifyTypes(cnt,
new Integer[] {
AUTOFILL_VIEW_EXITED, AUTOFILL_VIEW_ENTERED, AUTOFILL_VALUE_CHANGED});
dispatchDownAndUpKeyEvents(KeyEvent.KEYCODE_B);
valueChangedCallback.waitForCallback(count);
CallbackHelper commitCallbackHelper = mHelper.getCommitCallbackHelper();
count = commitCallbackHelper.getCallCount();
// Commit() hasn't been called.
assertEquals(0, count);
mHelper.clearChangedValues();
cnt += waitForCallbackAndVerifyTypes(cnt,
new Integer[] {
AUTOFILL_VIEW_EXITED, AUTOFILL_VIEW_ENTERED, AUTOFILL_VALUE_CHANGED});
clearChangedValues();
// Submit form.
executeJavaScriptAndWaitForResult("document.getElementById('formid').submit();");
commitCallbackHelper.waitForCallback(count);
ArrayList<Pair<Integer, AutofillValue>> values = mHelper.getChangedValues();
waitForCallbackAndVerifyTypes(cnt,
new Integer[] {AUTOFILL_VALUE_CHANGED, AUTOFILL_VALUE_CHANGED, AUTOFILL_COMMIT,
AUTOFILL_CANCEL});
ArrayList<Pair<Integer, AutofillValue>> values = getChangedValues();
assertEquals(2, values.size());
assertEquals("a", values.get(0).second.getTextValue());
assertEquals("b", values.get(1).second.getTextValue());
......@@ -719,32 +718,23 @@ public class AwAutofillTest {
@SmallTest
@Feature({"AndroidWebView"})
public void testLoadFileURL() throws Throwable {
CallbackHelper valueChangedCallback = mHelper.getVirtualValueChangedCallbackHelper();
int count = valueChangedCallback.getCallCount();
mActivityTestRule.loadUrlSync(mTestContainerView.getAwContents(),
mContentsClient.getOnPageFinishedHelper(), FILE_URL);
executeJavaScriptAndWaitForResult("document.getElementById('text1').select();");
dispatchDownAndUpKeyEvents(KeyEvent.KEYCODE_A);
valueChangedCallback.waitForCallback(count);
}
@Test
@SmallTest
@Feature({"AndroidWebView"})
public void testCancelCalledForFirstQuery() throws Throwable {
mActivityTestRule.loadUrlSync(mTestContainerView.getAwContents(),
mContentsClient.getOnPageFinishedHelper(), FILE_URL);
int cnt = 0;
loadUrlSync(FILE_URL);
executeJavaScriptAndWaitForResult("document.getElementById('text1').select();");
CallbackHelper cacelCallback = mHelper.getCancelCallbackHelper();
int count = cacelCallback.getCallCount();
// Note that we cancel autofill in loading as a precautious measure.
cnt += waitForCallbackAndVerifyTypes(cnt, new Integer[] {AUTOFILL_CANCEL, AUTOFILL_CANCEL});
dispatchDownAndUpKeyEvents(KeyEvent.KEYCODE_A);
cacelCallback.waitForCallback(count);
// Cancel called for the first query.
// Note that we currently call ENTER/EXIT one more time.
waitForCallbackAndVerifyTypes(cnt,
new Integer[] {AUTOFILL_CANCEL, AUTOFILL_VIEW_ENTERED, AUTOFILL_VIEW_EXITED,
AUTOFILL_VIEW_ENTERED, AUTOFILL_VALUE_CHANGED});
}
@Test
@SmallTest
@Feature({"AndroidWebView"})
public void testCancelCalledWhenMovingToOtherForm() throws Throwable {
public void testMovingToOtherForm() throws Throwable {
TestWebServer webServer = TestWebServer.start();
final String data =
"<html><head></head><body><form action='a.html' name='formname' id='formid'>"
......@@ -757,29 +747,83 @@ public class AwAutofillTest {
+ "<input type='submit'>"
+ "</form></body></html>";
try {
int cnt = 0;
final String url = webServer.setResponse(FILE, data, null);
mActivityTestRule.loadUrlSync(mTestContainerView.getAwContents(),
mContentsClient.getOnPageFinishedHelper(), url);
loadUrlSync(url);
executeJavaScriptAndWaitForResult("document.getElementById('text1').select();");
CallbackHelper cancelCallback = mHelper.getCancelCallbackHelper();
int count = cancelCallback.getCallCount();
// Note that we cancel autofill in loading as a precautious measure.
cnt += waitForCallbackAndVerifyTypes(
cnt, new Integer[] {AUTOFILL_CANCEL, AUTOFILL_CANCEL});
dispatchDownAndUpKeyEvents(KeyEvent.KEYCODE_A);
cancelCallback.waitForCallback(count);
// Note that we currently call ENTER/EXIT one more time.
cnt += waitForCallbackAndVerifyTypes(cnt,
new Integer[] {AUTOFILL_CANCEL, AUTOFILL_VIEW_ENTERED, AUTOFILL_VIEW_EXITED,
AUTOFILL_VIEW_ENTERED, AUTOFILL_VALUE_CHANGED});
// Move to form2, cancel() should be called again.
executeJavaScriptAndWaitForResult("document.getElementById('text2').select();");
count = cancelCallback.getCallCount();
cnt += waitForCallbackAndVerifyTypes(cnt, new Integer[] {AUTOFILL_VIEW_EXITED});
dispatchDownAndUpKeyEvents(KeyEvent.KEYCODE_A);
cancelCallback.waitForCallback(count);
waitForCallbackAndVerifyTypes(cnt,
new Integer[] {AUTOFILL_CANCEL, AUTOFILL_VIEW_ENTERED, AUTOFILL_VIEW_EXITED,
AUTOFILL_VIEW_ENTERED, AUTOFILL_VALUE_CHANGED});
} finally {
webServer.shutdown();
}
}
private void loadUrlSync(String url) throws Exception {
mRule.loadUrlSync(
mTestContainerView.getAwContents(), mContentsClient.getOnPageFinishedHelper(), url);
}
private String executeJavaScriptAndWaitForResult(String code) throws Throwable {
return mActivityTestRule.executeJavaScriptAndWaitForResult(
return mRule.executeJavaScriptAndWaitForResult(
mTestContainerView.getAwContents(), mContentsClient, code);
}
private ArrayList<Pair<Integer, AutofillValue>> getChangedValues() {
return mChangedValues;
}
private void clearChangedValues() {
if (mChangedValues != null) mChangedValues.clear();
}
private void invokeOnProvideAutoFillVirtualStructure() {
mTestViewStructure = new TestViewStructure();
mAwContents.onProvideAutoFillVirtualStructure(mTestViewStructure, 1);
}
private void invokeAutofill(SparseArray<AutofillValue> values) {
mAwContents.autofill(values);
}
private int getCallbackCount() {
return mCallbackHelper.getCallCount();
}
/**
* Wait for expected callbacks to be called, and verify the types.
*
* @param currentCallCount The current call count to start from.
* @param expectedEventArray The callback types that need to be verified.
* @return The number of new callbacks since currentCallCount. This should be same as the length
* of expectedEventArray.
* @throws InterruptedException
* @throws TimeoutException
*/
private int waitForCallbackAndVerifyTypes(int currentCallCount, Integer[] expectedEventArray)
throws InterruptedException, TimeoutException {
// Check against the call count to avoid missing out a callback in between waits, while
// exposing it so that the test can control where the call count starts.
mCallbackHelper.waitForCallback(currentCallCount, expectedEventArray.length);
Object[] objectArray = mEventQueue.toArray();
mEventQueue.clear();
Integer[] resultArray = Arrays.copyOf(objectArray, objectArray.length, Integer[].class);
Assert.assertArrayEquals(Arrays.toString(resultArray), expectedEventArray, resultArray);
return expectedEventArray.length;
}
private void dispatchDownAndUpKeyEvents(final int code) throws Throwable {
dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, code));
dispatchKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, code));
......
......@@ -141,6 +141,7 @@ instrumentation_test_apk("webview_instrumentation_test_apk") {
"../javatests/src/org/chromium/android_webview/test/AndroidScrollIntegrationTest.java",
"../javatests/src/org/chromium/android_webview/test/AndroidViewIntegrationTest.java",
"../javatests/src/org/chromium/android_webview/test/ArchiveTest.java",
"../javatests/src/org/chromium/android_webview/test/AwActivityTestRule.java",
"../javatests/src/org/chromium/android_webview/test/AwAutofillTest.java",
"../javatests/src/org/chromium/android_webview/test/AwContentsAnchorViewTest.java",
"../javatests/src/org/chromium/android_webview/test/AwContentsClientAutoLoginTest.java",
......@@ -174,7 +175,6 @@ instrumentation_test_apk("webview_instrumentation_test_apk") {
"../javatests/src/org/chromium/android_webview/test/AwServiceWorkerClientTest.java",
"../javatests/src/org/chromium/android_webview/test/AwSettingsTest.java",
"../javatests/src/org/chromium/android_webview/test/AwStrictModeTest.java",
"../javatests/src/org/chromium/android_webview/test/AwActivityTestRule.java",
"../javatests/src/org/chromium/android_webview/test/AwWebContentsObserverTest.java",
"../javatests/src/org/chromium/android_webview/test/AwZoomTest.java",
"../javatests/src/org/chromium/android_webview/test/CleanupReferenceTest.java",
......
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