Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 41db50cd authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Disable smart sharing for password fields."

parents 59eeffcb 76b51dc4
Loading
Loading
Loading
Loading
+11 −12
Original line number Diff line number Diff line
@@ -68,9 +68,7 @@ final class SelectionActionModeHelper {

    public void startActionModeAsync(boolean adjustSelection) {
        cancelAsyncTask();
        if (isNoOpTextClassifier() || !hasSelection()) {
            // No need to make an async call for a no-op TextClassifier.
            // Do not call the TextClassifier if there is no selection.
        if (skipTextClassification()) {
            startActionMode(null);
        } else {
            resetTextClassificationHelper(true /* resetSelectionTag */);
@@ -88,9 +86,7 @@ final class SelectionActionModeHelper {

    public void invalidateActionModeAsync() {
        cancelAsyncTask();
        if (isNoOpTextClassifier() || !hasSelection()) {
            // No need to make an async call for a no-op TextClassifier.
            // Do not call the TextClassifier if there is no selection.
        if (skipTextClassification()) {
            invalidateActionMode(null);
        } else {
            resetTextClassificationHelper(false /* resetSelectionTag */);
@@ -132,13 +128,16 @@ final class SelectionActionModeHelper {
        mTextClassification = null;
    }

    private boolean isNoOpTextClassifier() {
        return mEditor.getTextView().getTextClassifier() == TextClassifier.NO_OP;
    }

    private boolean hasSelection() {
    private boolean skipTextClassification() {
        final TextView textView = mEditor.getTextView();
        return textView.getSelectionEnd() > textView.getSelectionStart();
        // No need to make an async call for a no-op TextClassifier.
        final boolean noOpTextClassifier = textView.getTextClassifier() == TextClassifier.NO_OP;
        // Do not call the TextClassifier if there is no selection.
        final boolean noSelection = textView.getSelectionEnd() == textView.getSelectionStart();
        // Do not call the TextClassifier if this is a password field.
        final boolean password = textView.hasPasswordTransformationMethod()
                || TextView.isPasswordInputType(textView.getInputType());
        return noOpTextClassifier || noSelection || password;
    }

    private void startActionMode(@Nullable SelectionResult result) {
+1 −1
Original line number Diff line number Diff line
@@ -5676,7 +5676,7 @@ public class TextView extends View implements ViewTreeObserver.OnPreDrawListener
        return mTransformation instanceof PasswordTransformationMethod;
    }

    private static boolean isPasswordInputType(int inputType) {
    static boolean isPasswordInputType(int inputType) {
        final int variation =
                inputType & (EditorInfo.TYPE_MASK_CLASS | EditorInfo.TYPE_MASK_VARIATION);
        return variation
+22 −1
Original line number Diff line number Diff line
@@ -786,7 +786,7 @@ public class TextViewActivityTest {

    @Test
    public void testAssistItemIsAtIndexZero() throws Throwable {
        mActivity.getSystemService(TextClassificationManager.class).setTextClassifier(null);
        useSystemDefaultTextClassifier();
        final TextView textView = mActivity.findViewById(R.id.textview);
        mActivityRule.runOnUiThread(() -> textView.setCustomSelectionActionModeCallback(
                new ActionMode.Callback() {
@@ -821,6 +821,23 @@ public class TextViewActivityTest {
        assertFloatingToolbarItemIndex(android.R.id.textAssist, 0);
    }

    @Test
    public void testNoAssistItemForPasswordField() throws Throwable {
        useSystemDefaultTextClassifier();
        final TextView textView = mActivity.findViewById(R.id.textview);
        mActivityRule.runOnUiThread(() -> {
            textView.setInputType(
                    InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
        });
        mInstrumentation.waitForIdleSync();
        final String password = "afigbo@android.com";

        onView(withId(R.id.textview)).perform(replaceText(password));
        onView(withId(R.id.textview)).perform(longPressOnTextAtIndex(password.indexOf('@')));
        sleepForFloatingToolbarPopup();
        assertFloatingToolbarDoesNotContainItem(android.R.id.textAssist);
    }

    @Test
    public void testPastePlainText_menuAction() {
        initializeClipboardWithText(TextStyle.STYLED);
@@ -848,6 +865,10 @@ public class TextViewActivityTest {
                mActivity.getString(com.android.internal.R.string.paste_as_plain_text));
    }

    private void useSystemDefaultTextClassifier() {
        mActivity.getSystemService(TextClassificationManager.class).setTextClassifier(null);
    }

    private void initializeClipboardWithText(TextStyle textStyle) {
        final ClipData clip;
        switch (textStyle) {
+44 −9
Original line number Diff line number Diff line
@@ -23,29 +23,31 @@ import static android.support.test.espresso.matcher.RootMatchers.withDecorView;
import static android.support.test.espresso.matcher.ViewMatchers.hasDescendant;
import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
import static android.support.test.espresso.matcher.ViewMatchers.isRoot;
import static android.support.test.espresso.matcher.ViewMatchers.withTagValue;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
import static android.support.test.espresso.matcher.ViewMatchers.withTagValue;
import static android.support.test.espresso.matcher.ViewMatchers.withText;

import static org.hamcrest.Matchers.allOf;
import static org.hamcrest.Matchers.is;

import android.view.MenuItem;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.List;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;

import android.support.test.espresso.NoMatchingRootException;
import android.support.test.espresso.NoMatchingViewException;
import android.support.test.espresso.UiController;
import android.support.test.espresso.ViewAction;
import android.support.test.espresso.ViewInteraction;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;

import com.android.internal.widget.FloatingToolbar;

import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.TypeSafeMatcher;

import java.util.ArrayList;
import java.util.List;

/**
 * Espresso utility methods for the floating toolbar.
 */
@@ -176,6 +178,39 @@ public class FloatingToolbarEspressoUtils {
        throw new AssertionError("Floating toolbar contains " + itemLabel);
    }

    /**
     * Asserts that the floating toolbar does not contain a menu item with the specified id.
     *
     * @param menuItemId id of the menu item
     * @throws AssertionError if the assertion fails
     */
    public static void assertFloatingToolbarDoesNotContainItem(final int menuItemId) {
        onFloatingToolBar().check(matches(new TypeSafeMatcher<View>() {
            @Override
            public boolean matchesSafely(View view) {
                return !hasMenuItemWithSpecifiedId(view);
            }

            @Override
            public void describeTo(Description description) {}

            private boolean hasMenuItemWithSpecifiedId(View view) {
                if (view.getTag() instanceof MenuItem
                        && ((MenuItem) view.getTag()).getItemId() == menuItemId) {
                    return true;
                } else if (view instanceof ViewGroup) {
                    ViewGroup viewGroup = (ViewGroup) view;
                    for (int i = 0; i < viewGroup.getChildCount(); i++) {
                        if (hasMenuItemWithSpecifiedId(viewGroup.getChildAt(i))) {
                            return true;
                        }
                    }
                }
                return false;
            }
        }));
    }

    /**
     * Click specified item on the floating tool bar.
     *