Index: android_webview/javatests/src/org/chromium/android_webview/test/AwSettingsTest.java |
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwSettingsTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwSettingsTest.java |
index b10e50e2a59e577681d046b14e90d6a4b14ba26d..309f93ccab1dc444f405ec71b826f91867806470 100644 |
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AwSettingsTest.java |
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwSettingsTest.java |
@@ -57,6 +57,8 @@ public class AwSettingsTest extends AwTestBase { |
private static final boolean ENABLED = true; |
private static final boolean DISABLED = false; |
+ private int mTitleIdx; |
+ |
/** |
* A helper class for testing a particular preference from AwSettings. |
* The generic type T is the type of the setting. Usually, to test an |
@@ -2913,7 +2915,8 @@ public class AwSettingsTest extends AwTestBase { |
@Override |
public AwSettings createAwSettings(Context context, boolean supportsLegacyQuirks) { |
return new AwSettings(context, false /* isAccessFromFileURLsGrantedByDefault */, |
- supportsLegacyQuirks, mAllow, true /* allowGeolocationOnInsecureOrigins */); |
+ supportsLegacyQuirks, mAllow, true /* allowGeolocationOnInsecureOrigins */, |
+ false /* doNotUpdateSelectionOnMutatingSelectionRange */); |
} |
} |
@@ -2946,6 +2949,103 @@ public class AwSettingsTest extends AwTestBase { |
doAllowEmptyDocumentPersistenceTest(false); |
} |
+ private static class SelectionRangeTestDependencyFactory extends TestDependencyFactory { |
+ private boolean mDoNotUpdate; |
+ public SelectionRangeTestDependencyFactory(boolean doNotUpdate) { |
+ mDoNotUpdate = doNotUpdate; |
+ } |
+ |
+ @Override |
+ public AwSettings createAwSettings(Context context, boolean supportsLegacyQuirks) { |
+ return new AwSettings(context, false /* isAccessFromFileURLsGrantedByDefault */, |
+ supportsLegacyQuirks, false /* allowEmptyDocumentPersistence */, |
+ true /* allowGeolocationOnInsecureOrigins */, |
+ mDoNotUpdate /* doNotUpdateSelectionOnMutatingSelectionRange */); |
+ } |
+ } |
+ |
+ private void selectionUpdateOnMutatingSelectionRangeTest(boolean doNotUpdate) throws Throwable { |
+ mOverridenFactory = new SelectionRangeTestDependencyFactory(doNotUpdate); |
+ |
+ final TestAwContentsClient client = new TestAwContentsClient(); |
+ final AwTestContainerView mContainerView = createAwTestContainerViewOnMainSync(client); |
+ final AwContents awContents = mContainerView.getAwContents(); |
+ enableJavaScriptOnUiThread(awContents); |
+ final String testPageHtml = |
+ "<html><head></head><body><div id='a' contenteditable></div><script>" |
+ + "var cnt = 0;" |
+ + "var a = document.getElementById('a');" |
+ + "document.addEventListener('selectionchange', onSelectionChange, false);" |
+ + "function onSelectionChange(event) {" |
+ + " cnt++;" |
+ + "}" |
+ + "</script></body></html>"; |
+ loadDataSync( |
+ awContents, client.getOnPageFinishedHelper(), testPageHtml, "text/html", false); |
+ |
+ // Focus on an empty DIV. |
+ JSUtils.executeJavaScriptAndWaitForResult(this, awContents, |
+ client.getOnEvaluateJavaScriptResultHelper(), "window.a.focus();"); |
+ assertEquals(1, getSelectionChangeCountForSelectionUpdateTest(awContents, client)); |
+ |
+ // Create and delete a zero-width space. See crbug.com/698752 for details. |
+ JSUtils.executeJavaScriptAndWaitForResult(this, awContents, |
+ client.getOnEvaluateJavaScriptResultHelper(), |
+ "(function() {" |
+ + "var sel = window.getSelection();" |
+ + "var range = sel.getRangeAt(0);" |
+ + "var span = document.createElement('span');" |
+ + "var textNodeForZWSP = document.createTextNode('\u200B');" |
+ + "span.appendChild(textNodeForZWSP);" |
+ + "range.insertNode(span);" |
+ + "range.selectNode(span);" |
+ + "range.deleteContents();" |
+ + "}) ();"); |
+ int expectedResult = doNotUpdate ? 0 : 1; |
+ assertEquals( |
+ expectedResult, getSelectionChangeCountForSelectionUpdateTest(awContents, client)); |
+ } |
+ |
+ private void pollTitleAs(final String title, final AwContents awContents) throws Exception { |
+ pollInstrumentationThread(new Callable<Boolean>() { |
+ @Override |
+ public Boolean call() throws Exception { |
+ return title.equals(getTitleOnUiThread(awContents)); |
+ } |
+ }); |
+ } |
+ |
+ private int getSelectionChangeCountForSelectionUpdateTest( |
+ AwContents awContents, TestAwContentsClient client) throws Exception { |
+ mTitleIdx++; |
+ String expectedTitle = Integer.toString(mTitleIdx); |
+ // Since selectionchange event is posted on a message loop, we run another message loop |
+ // before we get the result. On Chromium both run on the same message loop. |
+ JSUtils.executeJavaScriptAndWaitForResult(this, awContents, |
+ client.getOnEvaluateJavaScriptResultHelper(), |
+ "setTimeout(function() { document.title = '" + expectedTitle + "'; });"); |
+ pollTitleAs(expectedTitle, awContents); |
+ |
+ String result = JSUtils.executeJavaScriptAndWaitForResult( |
+ this, awContents, client.getOnEvaluateJavaScriptResultHelper(), "window.cnt"); |
+ // Clean up |
+ JSUtils.executeJavaScriptAndWaitForResult( |
+ this, awContents, client.getOnEvaluateJavaScriptResultHelper(), "window.cnt = 0;"); |
+ return Integer.parseInt(result); |
+ } |
+ |
+ @SmallTest |
+ @Feature({"AndroidWebView", "Selection"}) |
+ public void testDoNotUpdateSelectionOnMutatingSelectionRange() throws Throwable { |
+ selectionUpdateOnMutatingSelectionRangeTest(true); |
+ } |
+ |
+ @SmallTest |
+ @Feature({"AndroidWebView", "Selection"}) |
+ public void testUpdateSelectionOnMutatingSelectionRange() throws Throwable { |
+ selectionUpdateOnMutatingSelectionRangeTest(false); |
+ } |
+ |
static class ViewPair { |
private final AwTestContainerView mContainer0; |
private final TestAwContentsClient mClient0; |