RESTRICT AUTOMERGE Do not linkify text with RLO/LRO characters.

Also don't show smart actions for selections in text with unsupported
characters.

Bug: 116321860
Test: runtest -x cts/tests/tests/text/src/android/text/util/cts/LinkifyTest.java
Change-Id: Ib2ee544b5783234fba8ee2f93adf0b36b039520f
This commit is contained in:
Abodunrinwa Toki
2019-01-04 17:18:39 +00:00
parent 9d93bdb61a
commit 4e3507d544
4 changed files with 61 additions and 3 deletions

View File

@@ -28,6 +28,7 @@ import android.text.Spanned;
import android.text.method.LinkMovementMethod; import android.text.method.LinkMovementMethod;
import android.text.method.MovementMethod; import android.text.method.MovementMethod;
import android.text.style.URLSpan; import android.text.style.URLSpan;
import android.util.Log;
import android.util.Patterns; import android.util.Patterns;
import android.webkit.WebView; import android.webkit.WebView;
import android.widget.TextView; import android.widget.TextView;
@@ -66,6 +67,9 @@ import java.util.regex.Pattern;
*/ */
public class Linkify { public class Linkify {
private static final String LOG_TAG = "Linkify";
/** /**
* Bit field indicating that web URLs should be matched in methods that * Bit field indicating that web URLs should be matched in methods that
* take an options mask * take an options mask
@@ -228,6 +232,11 @@ public class Linkify {
private static boolean addLinks(@NonNull Spannable text, @LinkifyMask int mask, private static boolean addLinks(@NonNull Spannable text, @LinkifyMask int mask,
@Nullable Context context) { @Nullable Context context) {
if (text != null && containsUnsupportedCharacters(text.toString())) {
android.util.EventLog.writeEvent(0x534e4554, "116321860", -1, "");
return false;
}
if (mask == 0) { if (mask == 0) {
return false; return false;
} }
@@ -273,6 +282,29 @@ public class Linkify {
return true; return true;
} }
/**
* Returns true if the specified text contains at least one unsupported character for applying
* links. Also logs the error.
*
* @param text the text to apply links to
* @hide
*/
public static boolean containsUnsupportedCharacters(String text) {
if (text.contains("\u202C")) {
Log.e(LOG_TAG, "Unsupported character for applying links: u202C");
return true;
}
if (text.contains("\u202D")) {
Log.e(LOG_TAG, "Unsupported character for applying links: u202D");
return true;
}
if (text.contains("\u202E")) {
Log.e(LOG_TAG, "Unsupported character for applying links: u202E");
return true;
}
return false;
}
/** /**
* Scans the text of the provided TextView and turns all occurrences of * Scans the text of the provided TextView and turns all occurrences of
* the link types indicated in the mask into clickable links. If matches * the link types indicated in the mask into clickable links. If matches
@@ -420,6 +452,10 @@ public class Linkify {
public static final boolean addLinks(@NonNull Spannable spannable, @NonNull Pattern pattern, public static final boolean addLinks(@NonNull Spannable spannable, @NonNull Pattern pattern,
@Nullable String scheme, @Nullable MatchFilter matchFilter, @Nullable String scheme, @Nullable MatchFilter matchFilter,
@Nullable TransformFilter transformFilter) { @Nullable TransformFilter transformFilter) {
if (spannable != null && containsUnsupportedCharacters(spannable.toString())) {
android.util.EventLog.writeEvent(0x534e4554, "116321860", -1, "");
return false;
}
return addLinks(spannable, pattern, scheme, null, matchFilter, return addLinks(spannable, pattern, scheme, null, matchFilter,
transformFilter); transformFilter);
} }

View File

@@ -38,7 +38,7 @@ public final class TextClassification {
/** /**
* @hide * @hide
*/ */
static final TextClassification EMPTY = new TextClassification.Builder().build(); public static final TextClassification EMPTY = new TextClassification.Builder().build();
@NonNull private final String mText; @NonNull private final String mText;
@Nullable private final Drawable mIcon; @Nullable private final Drawable mIcon;

View File

@@ -25,6 +25,7 @@ import android.os.LocaleList;
import android.text.Selection; import android.text.Selection;
import android.text.Spannable; import android.text.Spannable;
import android.text.TextUtils; import android.text.TextUtils;
import android.text.util.Linkify;
import android.util.Log; import android.util.Log;
import android.view.ActionMode; import android.view.ActionMode;
import android.view.textclassifier.TextClassification; import android.view.textclassifier.TextClassification;
@@ -692,11 +693,19 @@ final class SelectionActionModeHelper {
mLastClassificationLocales = mLocales; mLastClassificationLocales = mLocales;
trimText(); trimText();
final TextClassification classification;
if (Linkify.containsUnsupportedCharacters(mText)) {
// Do not show smart actions for text containing unsupported characters.
android.util.EventLog.writeEvent(0x534e4554, "116321860", -1, "");
classification = TextClassification.EMPTY;
} else {
classification = mTextClassifier.classifyText(
mTrimmedText, mRelativeStart, mRelativeEnd, mLocales);
}
mLastClassificationResult = new SelectionResult( mLastClassificationResult = new SelectionResult(
mSelectionStart, mSelectionStart,
mSelectionEnd, mSelectionEnd,
mTextClassifier.classifyText( classification,
mTrimmedText, mRelativeStart, mRelativeEnd, mLocales),
selection); selection);
} }

View File

@@ -838,6 +838,19 @@ public class TextViewActivityTest {
assertFloatingToolbarDoesNotContainItem(android.R.id.textAssist); assertFloatingToolbarDoesNotContainItem(android.R.id.textAssist);
} }
@Test
public void testNoAssistItemForTextFieldWithUnsupportedCharacters() throws Throwable {
useSystemDefaultTextClassifier();
final String text = "\u202Emoc.diordna.com";
final TextView textView = mActivity.findViewById(R.id.textview);
mActivityRule.runOnUiThread(() -> textView.setText(text));
mInstrumentation.waitForIdleSync();
onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf('.')));
sleepForFloatingToolbarPopup();
assertFloatingToolbarDoesNotContainItem(android.R.id.textAssist);
}
@Test @Test
public void testPastePlainText_menuAction() { public void testPastePlainText_menuAction() {
initializeClipboardWithText(TextStyle.STYLED); initializeClipboardWithText(TextStyle.STYLED);