ContentViewCoreSelectionTest.java revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
1// Copyright 2014 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5package org.chromium.content.browser; 6 7import android.content.ClipData; 8import android.content.ClipboardManager; 9import android.content.Context; 10import android.test.suitebuilder.annotation.SmallTest; 11 12import org.chromium.base.ThreadUtils; 13import org.chromium.base.test.util.Feature; 14import org.chromium.base.test.util.UrlUtils; 15import org.chromium.content.browser.test.util.Criteria; 16import org.chromium.content.browser.test.util.CriteriaHelper; 17import org.chromium.content.browser.test.util.DOMUtils; 18import org.chromium.content_shell_apk.ContentShellTestBase; 19 20/** 21 * Integration tests for text selection-related behavior. 22 */ 23public class ContentViewCoreSelectionTest extends ContentShellTestBase { 24 private static final String DATA_URL = UrlUtils.encodeHtmlDataUri( 25 "<html><head><meta name=\"viewport\"" + 26 "content=\"width=device-width, initial-scale=1.1, maximum-scale=1.5\" /></head>" + 27 "<body><form action=\"about:blank\">" + 28 "<input id=\"empty_input_text\" type=\"text\" />" + 29 "<br/><p><span id=\"plain_text_1\">This is Plain Text One</span></p>" + 30 "<br/><p><span id=\"plain_text_2\">This is Plain Text Two</span></p>" + 31 "<br/><input id=\"empty_input_text\" type=\"text\" />" + 32 "<br/><input id=\"input_text\" type=\"text\" value=\"Sample Text\" />" + 33 "<br/><textarea id=\"empty_textarea\" rows=\"2\" cols=\"20\"></textarea>" + 34 "<br/><textarea id=\"textarea\" rows=\"2\" cols=\"20\">Sample Text</textarea>" + 35 "</form></body></html>"); 36 37 private ContentViewCore mContentViewCore; 38 39 @Override 40 public void setUp() throws Exception { 41 super.setUp(); 42 43 launchContentShellWithUrl(DATA_URL); 44 assertTrue("Page failed to load", waitForActiveShellToBeDoneLoading()); 45 46 mContentViewCore = getContentViewCore(); 47 assertWaitForPageScaleFactorMatch(1.1f); 48 assertWaitForSelectActionBarVisible(false); 49 assertWaitForPastePopupStatus(false); 50 } 51 52 @SmallTest 53 @Feature({"TextSelection"}) 54 public void testSelectionClearedAfterLossOfFocus() throws Throwable { 55 requestFocusOnUiThread(true); 56 57 DOMUtils.longPressNode(this, mContentViewCore, "textarea"); 58 assertWaitForSelectActionBarVisible(true); 59 60 requestFocusOnUiThread(false); 61 assertWaitForSelectActionBarVisible(false); 62 assertFalse(mContentViewCore.hasSelection()); 63 64 requestFocusOnUiThread(true); 65 assertWaitForSelectActionBarVisible(false); 66 assertFalse(mContentViewCore.hasSelection()); 67 } 68 69 @SmallTest 70 @Feature({"TextSelection"}) 71 public void testSelectionPreservedAfterLossOfFocusIfRequested() throws Throwable { 72 requestFocusOnUiThread(true); 73 74 DOMUtils.longPressNode(this, mContentViewCore, "textarea"); 75 assertWaitForSelectActionBarVisible(true); 76 assertTrue(mContentViewCore.hasSelection()); 77 78 mContentViewCore.preserveSelectionOnNextLossOfFocus(); 79 requestFocusOnUiThread(false); 80 assertWaitForSelectActionBarVisible(false); 81 assertTrue(mContentViewCore.hasSelection()); 82 83 requestFocusOnUiThread(true); 84 assertWaitForSelectActionBarVisible(true); 85 assertTrue(mContentViewCore.hasSelection()); 86 87 // Losing focus yet again should properly clear the selection. 88 requestFocusOnUiThread(false); 89 assertWaitForSelectActionBarVisible(false); 90 assertFalse(mContentViewCore.hasSelection()); 91 } 92 93 @SmallTest 94 @Feature({"TextSelection"}) 95 public void testSelectionPreservedAfterReshown() throws Throwable { 96 DOMUtils.longPressNode(this, mContentViewCore, "textarea"); 97 assertWaitForSelectActionBarVisible(true); 98 assertTrue(mContentViewCore.hasSelection()); 99 100 setVisibileOnUiThread(false); 101 assertWaitForSelectActionBarVisible(false); 102 assertTrue(mContentViewCore.hasSelection()); 103 104 setVisibileOnUiThread(true); 105 assertWaitForSelectActionBarVisible(true); 106 assertTrue(mContentViewCore.hasSelection()); 107 } 108 109 @SmallTest 110 @Feature({"TextSelection"}) 111 public void testSelectionPreservedAfterReattached() throws Throwable { 112 DOMUtils.longPressNode(this, mContentViewCore, "textarea"); 113 assertWaitForSelectActionBarVisible(true); 114 assertTrue(mContentViewCore.hasSelection()); 115 116 setAttachedOnUiThread(false); 117 assertWaitForSelectActionBarVisible(false); 118 assertTrue(mContentViewCore.hasSelection()); 119 120 setAttachedOnUiThread(true); 121 assertWaitForSelectActionBarVisible(true); 122 assertTrue(mContentViewCore.hasSelection()); 123 } 124 125 @SmallTest 126 @Feature({"TextInput"}) 127 public void testPastePopupNotShownOnLongPressingNonEmptyInput() throws Throwable { 128 copyStringToClipboard(); 129 DOMUtils.longPressNode(this, mContentViewCore, "empty_input_text"); 130 assertWaitForPastePopupStatus(true); 131 DOMUtils.longPressNode(this, mContentViewCore, "input_text"); 132 assertWaitForSelectActionBarVisible(true); 133 assertWaitForPastePopupStatus(false); 134 } 135 136 @SmallTest 137 @Feature({"TextInput"}) 138 public void testPastePopupClearedOnTappingEmptyInput() throws Throwable { 139 copyStringToClipboard(); 140 DOMUtils.longPressNode(this, mContentViewCore, "empty_input_text"); 141 assertWaitForPastePopupStatus(true); 142 DOMUtils.clickNode(this, mContentViewCore, "empty_input_text"); 143 assertWaitForPastePopupStatus(false); 144 } 145 146 @SmallTest 147 @Feature({"TextInput"}) 148 public void testPastePopupClearedOnTappingNonEmptyInput() throws Throwable { 149 copyStringToClipboard(); 150 DOMUtils.longPressNode(this, mContentViewCore, "empty_input_text"); 151 assertWaitForPastePopupStatus(true); 152 DOMUtils.clickNode(this, mContentViewCore, "input_text"); 153 assertWaitForPastePopupStatus(false); 154 } 155 156 @SmallTest 157 @Feature({"TextInput"}) 158 public void testPastePopupClearedOnTappingOutsideInput() throws Throwable { 159 copyStringToClipboard(); 160 DOMUtils.longPressNode(this, mContentViewCore, "empty_input_text"); 161 assertWaitForPastePopupStatus(true); 162 DOMUtils.clickNode(this, mContentViewCore, "plain_text_2"); 163 assertWaitForPastePopupStatus(false); 164 } 165 166 @SmallTest 167 @Feature({"TextInput"}) 168 public void testPastePopupClearedOnLongPressingOutsideInput() throws Throwable { 169 copyStringToClipboard(); 170 DOMUtils.longPressNode(this, mContentViewCore, "empty_input_text"); 171 assertWaitForPastePopupStatus(true); 172 DOMUtils.longPressNode(this, mContentViewCore, "plain_text_2"); 173 assertWaitForPastePopupStatus(false); 174 } 175 176 private void assertWaitForSelectActionBarVisible( 177 final boolean visible) throws InterruptedException { 178 assertTrue(CriteriaHelper.pollForCriteria(new Criteria() { 179 @Override 180 public boolean isSatisfied() { 181 return visible == mContentViewCore.isSelectActionBarShowing(); 182 } 183 })); 184 } 185 186 private void setVisibileOnUiThread(final boolean show) { 187 final ContentViewCore contentViewCore = mContentViewCore; 188 ThreadUtils.runOnUiThreadBlocking(new Runnable() { 189 @Override 190 public void run() { 191 if (show) { 192 contentViewCore.onShow(); 193 } else { 194 contentViewCore.onHide(); 195 } 196 } 197 }); 198 } 199 200 private void setAttachedOnUiThread(final boolean attached) { 201 final ContentViewCore contentViewCore = mContentViewCore; 202 ThreadUtils.runOnUiThreadBlocking(new Runnable() { 203 @Override 204 public void run() { 205 if (attached) { 206 contentViewCore.onAttachedToWindow(); 207 } else { 208 contentViewCore.onDetachedFromWindow(); 209 } 210 } 211 }); 212 } 213 214 private void requestFocusOnUiThread(final boolean gainFocus) { 215 final ContentViewCore contentViewCore = mContentViewCore; 216 ThreadUtils.runOnUiThreadBlocking(new Runnable() { 217 @Override 218 public void run() { 219 contentViewCore.onFocusChanged(gainFocus); 220 } 221 }); 222 } 223 224 private void copyStringToClipboard() { 225 ClipboardManager clipboardManager = 226 (ClipboardManager) getActivity().getSystemService( 227 Context.CLIPBOARD_SERVICE); 228 ClipData clip = ClipData.newPlainText("test", "Text to copy"); 229 clipboardManager.setPrimaryClip(clip); 230 } 231 232 private void assertWaitForPastePopupStatus(final boolean show) throws InterruptedException { 233 assertTrue(CriteriaHelper.pollForCriteria(new Criteria() { 234 @Override 235 public boolean isSatisfied() { 236 return show == mContentViewCore.getPastePopupForTest().isShowing(); 237 } 238 })); 239 } 240} 241