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 Merged-In: Ib2ee544b5783234fba8ee2f93adf0b36b039520f
This commit is contained in:
committed by
Abodunrinwa Toki
parent
5cf98f1399
commit
d9e75a497e
@@ -26,6 +26,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;
|
||||||
@@ -64,6 +65,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
|
||||||
@@ -221,6 +225,11 @@ public class Linkify {
|
|||||||
* @return True if at least one link is found and applied.
|
* @return True if at least one link is found and applied.
|
||||||
*/
|
*/
|
||||||
public static final boolean addLinks(@NonNull Spannable text, @LinkifyMask int mask) {
|
public static final boolean addLinks(@NonNull Spannable text, @LinkifyMask int mask) {
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
@@ -266,6 +275,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
|
||||||
@@ -413,6 +445,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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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.view.ActionMode;
|
import android.view.ActionMode;
|
||||||
import android.view.textclassifier.TextClassification;
|
import android.view.textclassifier.TextClassification;
|
||||||
import android.view.textclassifier.TextClassifier;
|
import android.view.textclassifier.TextClassifier;
|
||||||
@@ -454,11 +455,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));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
return mLastClassificationResult;
|
return mLastClassificationResult;
|
||||||
|
|||||||
@@ -761,6 +761,7 @@ public class TextViewActivityTest extends ActivityInstrumentationTestCase2<TextV
|
|||||||
public void onDestroyActionMode(ActionMode actionMode) {
|
public void onDestroyActionMode(ActionMode actionMode) {
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
getInstrumentation().waitForIdleSync();
|
||||||
final String text = "droid@android.com";
|
final String text = "droid@android.com";
|
||||||
|
|
||||||
onView(withId(R.id.textview)).perform(replaceText(text));
|
onView(withId(R.id.textview)).perform(replaceText(text));
|
||||||
@@ -769,6 +770,18 @@ public class TextViewActivityTest extends ActivityInstrumentationTestCase2<TextV
|
|||||||
assertFloatingToolbarItemIndex(android.R.id.textAssist, 0);
|
assertFloatingToolbarItemIndex(android.R.id.textAssist, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testNoAssistItemForTextFieldWithUnsupportedCharacters() throws Throwable {
|
||||||
|
getActivity().getSystemService(TextClassificationManager.class).setTextClassifier(null);
|
||||||
|
final String text = "\u202Emoc.diordna.com";
|
||||||
|
final TextView textView = getActivity().findViewById(R.id.textview);
|
||||||
|
textView.post(() -> textView.setText(text));
|
||||||
|
getInstrumentation().waitForIdleSync();
|
||||||
|
|
||||||
|
onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(text.indexOf('.')));
|
||||||
|
sleepForFloatingToolbarPopup();
|
||||||
|
assertFloatingToolbarItemIndex(android.R.id.cut, 0);
|
||||||
|
}
|
||||||
|
|
||||||
public void testPastePlainText_menuAction() throws Exception {
|
public void testPastePlainText_menuAction() throws Exception {
|
||||||
initializeClipboardWithText(TextStyle.STYLED);
|
initializeClipboardWithText(TextStyle.STYLED);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user