Don't allow the keyboard to probe Inline Suggestion content.

Test: manual
Test: atest android.autofillservice.cts.inline
Bug: 149243911
Change-Id: I1c1ddb46cef74b470aaebd8b0a6b79ea6a02f5c3
This commit is contained in:
Ahaan Ugale
2020-02-11 23:36:35 +01:00
parent 68a4ab95c6
commit 1715b69bee
2 changed files with 62 additions and 5 deletions

View File

@@ -2604,17 +2604,20 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
@GuardedBy("mLock")
private void updateViewStateAndUiOnValueChangedLocked(AutofillId id, AutofillValue value,
ViewState viewState, int flags) {
viewState.setCurrentValue(value);
final String filterText;
final String textValue;
if (value == null || !value.isText()) {
filterText = null;
textValue = null;
} else {
final CharSequence text = value.getTextValue();
// Text should never be null, but it doesn't hurt to check to avoid a
// system crash...
filterText = (text == null) ? null : text.toString();
textValue = (text == null) ? null : text.toString();
}
updateFilteringStateOnValueChangedLocked(textValue, viewState);
viewState.setCurrentValue(value);
final String filterText = textValue;
final AutofillValue filledValue = viewState.getAutofilledValue();
if (filledValue != null) {
@@ -2645,6 +2648,52 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
getUiForShowing().filterFillUi(filterText, this);
}
/**
* Disable filtering of inline suggestions for further text changes in this view if any
* character was removed earlier and now any character is being added. Such behaviour may
* indicate the IME attempting to probe the potentially sensitive content of inline suggestions.
*/
@GuardedBy("mLock")
private void updateFilteringStateOnValueChangedLocked(@Nullable String newTextValue,
ViewState viewState) {
if (newTextValue == null) {
// Don't just return here, otherwise the IME can circumvent this logic using non-text
// values.
newTextValue = "";
}
final AutofillValue currentValue = viewState.getCurrentValue();
final String currentTextValue;
if (currentValue == null || !currentValue.isText()) {
currentTextValue = "";
} else {
currentTextValue = currentValue.getTextValue().toString();
}
if ((viewState.getState() & ViewState.STATE_CHAR_REMOVED) == 0) {
if (!containsCharsInOrder(newTextValue, currentTextValue)) {
viewState.setState(ViewState.STATE_CHAR_REMOVED);
}
} else if (!containsCharsInOrder(currentTextValue, newTextValue)) {
// Characters were added or replaced.
viewState.setState(ViewState.STATE_INLINE_DISABLED);
}
}
/**
* Returns true if {@code s1} contains all characters of {@code s2}, in order.
*/
private static boolean containsCharsInOrder(String s1, String s2) {
int prevIndex = -1;
for (char ch : s2.toCharArray()) {
int index = TextUtils.indexOf(s1, ch, prevIndex + 1);
if (index == -1) {
return false;
}
prevIndex = index;
}
return true;
}
@Override
public void onFillReady(@NonNull FillResponse response, @NonNull AutofillId filledId,
@Nullable AutofillValue value) {
@@ -2735,6 +2784,10 @@ final class Session implements RemoteFillService.FillServiceCallbacks, ViewState
return false;
}
final ViewState currentView = mViewStates.get(mCurrentViewId);
if ((currentView.getState() & ViewState.STATE_INLINE_DISABLED) != 0) {
response.getDatasets().clear();
}
InlineSuggestionsResponse inlineSuggestionsResponse =
InlineSuggestionFactory.createInlineSuggestionsResponse(
inlineSuggestionsRequest.get(), response, filterText, mCurrentViewId,

View File

@@ -76,6 +76,10 @@ final class ViewState {
public static final int STATE_TRIGGERED_AUGMENTED_AUTOFILL = 0x1000;
/** Inline suggestions were shown for this View. */
public static final int STATE_INLINE_SHOWN = 0x2000;
/** A character was removed from the View value (not by the service). */
public static final int STATE_CHAR_REMOVED = 0x4000;
/** Showing inline suggestions is not allowed for this View. */
public static final int STATE_INLINE_DISABLED = 0x8000;
public final AutofillId id;