Commit 1d2589ec authored by Tomasz Wiszkowski's avatar Tomasz Wiszkowski Committed by Commit Bot

Share full, unmodified URL to ViewStructure for Autofill services.

This change fixes issue with third-party autofill applications, such as
password managers, where these apps would receive edited URL, making it
difficult to find associated data, and in turn, fail to work correctly.

Bug: 996402
Change-Id: Ie4b11ddcbc7818df31f7be2ac6b6bafdfd99f6af
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1764415
Commit-Queue: Ender <ender@google.com>
Reviewed-by: default avatarTed Choc <tedchoc@chromium.org>
Cr-Commit-Position: refs/heads/master@{#690448}
parent 06901e4a
......@@ -149,6 +149,7 @@ chrome_junit_test_java_sources = [
"junit/src/org/chromium/chrome/browser/omnibox/SearchEngineLogoUtilsTest.java",
"junit/src/org/chromium/chrome/browser/omnibox/SpannableAutocompleteEditTextModelUnitTest.java",
"junit/src/org/chromium/chrome/browser/omnibox/UrlBarDataTest.java",
"junit/src/org/chromium/chrome/browser/omnibox/UrlBarUnitTest.java",
"junit/src/org/chromium/chrome/browser/omnibox/UrlBarMediatorUnitTest.java",
"junit/src/org/chromium/chrome/browser/omnibox/geo/GeolocationHeaderUnitTest.java",
"junit/src/org/chromium/chrome/browser/omnibox/geo/PlatformNetworksManagerTest.java",
......
......@@ -20,6 +20,7 @@ import android.text.Editable;
import android.text.InputType;
import android.text.Layout;
import android.text.Selection;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.text.style.ReplacementSpan;
import android.util.AttributeSet;
......@@ -27,6 +28,7 @@ import android.view.GestureDetector;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewStructure;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputConnection;
......@@ -153,6 +155,14 @@ public class UrlBar extends AutocompleteEditText {
int SCROLL_TO_BEGINNING = 2;
}
/**
* An optional string to use with AccessibilityNodeInfo to report text content.
* This is particularly important for auto-fill applications, such as password managers, that
* rely on AccessibilityNodeInfo data to apply related form-fill data.
*/
private CharSequence mTextForAutofillServices;
private boolean mRequestingAutofillStructure;
/**
* Implement this to get updates when the direction of the text in the URL bar changes.
* E.g. If the user is typing a URL, then erases it and starts typing a query in Arabic,
......@@ -589,6 +599,13 @@ public class UrlBar extends AutocompleteEditText {
mTextChangeListener = listener;
}
/**
* Set the text to report to Autofill services upon call to onProvideAutofillStructure.
*/
public void setTextForAutofillServices(CharSequence text) {
mTextForAutofillServices = text;
}
@Override
public boolean onTextContextMenuItem(int id) {
if (mTextContextMenuDelegate == null) return super.onTextContextMenuItem(id);
......@@ -911,6 +928,21 @@ public class UrlBar extends AutocompleteEditText {
}
}
@Override
public void onProvideAutofillStructure(ViewStructure structure, int autofillFlags) {
// https://crbug.com/996402: Prevent breaking autofill services on newer versions of
// Android.
mRequestingAutofillStructure = true;
super.onProvideAutofillStructure(structure, autofillFlags);
mRequestingAutofillStructure = false;
}
@Override
public Editable getText() {
return mRequestingAutofillStructure ? new SpannableStringBuilder(mTextForAutofillServices)
: super.getText();
}
@Override
public CharSequence getAccessibilityClassName() {
// When UrlBar is used as a read-only TextView, force Talkback to pronounce it like
......
......@@ -102,12 +102,18 @@ class UrlBarMediator implements UrlBar.UrlBarTextContextMenuDelegate {
private void pushTextToModel() {
CharSequence text =
!mHasFocus ? mUrlBarData.displayText : mUrlBarData.getEditingOrDisplayText();
CharSequence textForAutofillServices = text;
if (!(mHasFocus || TextUtils.isEmpty(text) || mUrlBarData.url == null)) {
textForAutofillServices = mUrlBarData.url;
}
@ScrollType
int scrollType = mHasFocus ? UrlBar.ScrollType.NO_SCROLL : mScrollType;
if (text == null) text = "";
UrlBarTextState state =
new UrlBarTextState(text, scrollType, mUrlBarData.originEndIndex, mSelectionState);
UrlBarTextState state = new UrlBarTextState(text, textForAutofillServices, scrollType,
mUrlBarData.originEndIndex, mSelectionState);
mModel.set(UrlBarProperties.TEXT_STATE, state);
}
......
......@@ -31,6 +31,9 @@ class UrlBarProperties {
/** Text to be shown. */
public final CharSequence text;
/** Text for Autofill services. */
public final CharSequence textForAutofillServices;
/** Specifies how the text should be scrolled in the unfocused state. */
public final @ScrollType int scrollType;
......@@ -40,9 +43,10 @@ class UrlBarProperties {
/** Specifies how the text should be selected in the focused state. */
public final @SelectionState int selectionState;
public UrlBarTextState(CharSequence text, @ScrollType int scrollType, int scrollToIndex,
@SelectionState int selectionState) {
public UrlBarTextState(CharSequence text, CharSequence textForAutofillServices,
@ScrollType int scrollType, int scrollToIndex, @SelectionState int selectionState) {
this.text = text;
this.textForAutofillServices = textForAutofillServices;
this.scrollType = scrollType;
this.scrollToIndex = scrollToIndex;
this.selectionState = selectionState;
......
......@@ -55,6 +55,7 @@ class UrlBarViewBinder {
UrlBarTextState state = model.get(UrlBarProperties.TEXT_STATE);
view.setIgnoreTextChangesForAutocomplete(true);
view.setText(state.text);
view.setTextForAutofillServices(state.textForAutofillServices);
view.setScrollState(state.scrollType, state.scrollToIndex);
view.setIgnoreTextChangesForAutocomplete(false);
......
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.omnibox;
import static org.mockito.Mockito.verify;
import android.app.Activity;
import android.os.Build;
import android.support.test.filters.SmallTest;
import android.text.SpannableStringBuilder;
import android.view.ViewStructure;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
import org.chromium.base.test.util.Feature;
import org.chromium.base.test.util.MinAndroidSdkLevel;
import org.chromium.chrome.browser.omnibox.UrlBar.UrlBarDelegate;
import org.chromium.testing.local.LocalRobolectricTestRunner;
/**
* Unit tests for the URL bar UI component.
*/
@RunWith(LocalRobolectricTestRunner.class)
public class UrlBarUnitTest {
private UrlBar mUrlBar;
@Mock
private UrlBarDelegate mUrlBarDelegate;
@Mock
private ViewStructure mViewStructure;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
Activity activity = Robolectric.buildActivity(Activity.class).setup().get();
mUrlBar = new UrlBar(activity, null);
mUrlBar.setDelegate(mUrlBarDelegate);
}
@Test
@SmallTest
@MinAndroidSdkLevel(Build.VERSION_CODES.O)
@Feature("Omnibox")
public void testAutofillStructureReceivesFullURL() throws InterruptedException {
mUrlBar.setTextForAutofillServices("https://www.google.com");
mUrlBar.setText("www.google.com");
mUrlBar.onProvideAutofillStructure(mViewStructure, 0);
ArgumentCaptor<SpannableStringBuilder> haveUrl =
ArgumentCaptor.forClass(SpannableStringBuilder.class);
verify(mViewStructure).setText(haveUrl.capture());
Assert.assertEquals("https://www.google.com", haveUrl.getValue().toString());
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment