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.
5 package org.chromium.content.browser;
7 import android.content.ClipData;
8 import android.content.ClipboardManager;
9 import android.content.Context;
10 import android.test.suitebuilder.annotation.SmallTest;
12 import org.chromium.base.ThreadUtils;
13 import org.chromium.base.test.util.Feature;
14 import org.chromium.base.test.util.UrlUtils;
15 import org.chromium.content.browser.test.util.Criteria;
16 import org.chromium.content.browser.test.util.CriteriaHelper;
17 import org.chromium.content.browser.test.util.DOMUtils;
18 import org.chromium.content_shell_apk.ContentShellTestBase;
21 * Integration tests for text selection-related behavior.
23 public 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>");
37 private ContentViewCore mContentViewCore;
40 public void setUp() throws Exception {
43 launchContentShellWithUrl(DATA_URL);
44 assertTrue("Page failed to load", waitForActiveShellToBeDoneLoading());
46 mContentViewCore = getContentViewCore();
47 assertWaitForPageScaleFactorMatch(1.1f);
48 assertWaitForSelectActionBarVisible(false);
49 assertWaitForPastePopupStatus(false);
53 @Feature({"TextSelection"})
54 public void testSelectionClearedAfterLossOfFocus() throws Throwable {
55 requestFocusOnUiThread(true);
57 DOMUtils.longPressNode(this, mContentViewCore, "textarea");
58 assertWaitForSelectActionBarVisible(true);
60 requestFocusOnUiThread(false);
61 assertWaitForSelectActionBarVisible(false);
62 assertFalse(mContentViewCore.hasSelection());
64 requestFocusOnUiThread(true);
65 assertWaitForSelectActionBarVisible(false);
66 assertFalse(mContentViewCore.hasSelection());
70 @Feature({"TextSelection"})
71 public void testSelectionPreservedAfterLossOfFocusIfRequested() throws Throwable {
72 requestFocusOnUiThread(true);
74 DOMUtils.longPressNode(this, mContentViewCore, "textarea");
75 assertWaitForSelectActionBarVisible(true);
76 assertTrue(mContentViewCore.hasSelection());
78 mContentViewCore.preserveSelectionOnNextLossOfFocus();
79 requestFocusOnUiThread(false);
80 assertWaitForSelectActionBarVisible(false);
81 assertTrue(mContentViewCore.hasSelection());
83 requestFocusOnUiThread(true);
84 assertWaitForSelectActionBarVisible(true);
85 assertTrue(mContentViewCore.hasSelection());
87 // Losing focus yet again should properly clear the selection.
88 requestFocusOnUiThread(false);
89 assertWaitForSelectActionBarVisible(false);
90 assertFalse(mContentViewCore.hasSelection());
94 @Feature({"TextSelection"})
95 public void testSelectionPreservedAfterReshown() throws Throwable {
96 DOMUtils.longPressNode(this, mContentViewCore, "textarea");
97 assertWaitForSelectActionBarVisible(true);
98 assertTrue(mContentViewCore.hasSelection());
100 setVisibileOnUiThread(false);
101 assertWaitForSelectActionBarVisible(false);
102 assertTrue(mContentViewCore.hasSelection());
104 setVisibileOnUiThread(true);
105 assertWaitForSelectActionBarVisible(true);
106 assertTrue(mContentViewCore.hasSelection());
110 @Feature({"TextSelection"})
111 public void testSelectionPreservedAfterReattached() throws Throwable {
112 DOMUtils.longPressNode(this, mContentViewCore, "textarea");
113 assertWaitForSelectActionBarVisible(true);
114 assertTrue(mContentViewCore.hasSelection());
116 setAttachedOnUiThread(false);
117 assertWaitForSelectActionBarVisible(false);
118 assertTrue(mContentViewCore.hasSelection());
120 setAttachedOnUiThread(true);
121 assertWaitForSelectActionBarVisible(true);
122 assertTrue(mContentViewCore.hasSelection());
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);
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);
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);
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);
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);
176 private void assertWaitForSelectActionBarVisible(
177 final boolean visible) throws InterruptedException {
178 assertTrue(CriteriaHelper.pollForCriteria(new Criteria() {
180 public boolean isSatisfied() {
181 return visible == mContentViewCore.isSelectActionBarShowing();
186 private void setVisibileOnUiThread(final boolean show) {
187 final ContentViewCore contentViewCore = mContentViewCore;
188 ThreadUtils.runOnUiThreadBlocking(new Runnable() {
192 contentViewCore.onShow();
194 contentViewCore.onHide();
200 private void setAttachedOnUiThread(final boolean attached) {
201 final ContentViewCore contentViewCore = mContentViewCore;
202 ThreadUtils.runOnUiThreadBlocking(new Runnable() {
206 contentViewCore.onAttachedToWindow();
208 contentViewCore.onDetachedFromWindow();
214 private void requestFocusOnUiThread(final boolean gainFocus) {
215 final ContentViewCore contentViewCore = mContentViewCore;
216 ThreadUtils.runOnUiThreadBlocking(new Runnable() {
219 contentViewCore.onFocusChanged(gainFocus);
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);
232 private void assertWaitForPastePopupStatus(final boolean show) throws InterruptedException {
233 assertTrue(CriteriaHelper.pollForCriteria(new Criteria() {
235 public boolean isSatisfied() {
236 return show == mContentViewCore.getPastePopupForTest().isShowing();