Commit 30c4010d authored by Brandon Wylie's avatar Brandon Wylie Committed by Commit Bot

Switch StatusCoordinator/Mediator to using TextWatcher

Events aren't getting through when they should when using
UrlBar.UrlTextChangeListener. Using a combination of TextWatcher and
UrlBarCoordinator triggers more frequently.

Bug: 1008474
Change-Id: I60252e7f2bca878089667cc29f79f82e18884789
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1835101
Commit-Queue: Brandon Wylie <wylieb@chromium.org>
Reviewed-by: default avatarTed Choc <tedchoc@chromium.org>
Cr-Commit-Position: refs/heads/master@{#704849}
parent 3f3f4ee8
......@@ -217,11 +217,11 @@ public class LocationBarLayout extends FrameLayout
StatusView statusView = findViewById(R.id.location_bar_status);
statusView.setCompositeTouchDelegate(mCompositeTouchDelegate);
mStatusViewCoordinator = new StatusViewCoordinator(mIsTablet, statusView);
mStatusViewCoordinator = new StatusViewCoordinator(mIsTablet, statusView, mUrlCoordinator);
mUrlCoordinator.addTextChangedListener(mStatusViewCoordinator);
updateShouldAnimateIconChanges();
mUrlBar.setOnKeyListener(new UrlBarKeyListener());
mUrlCoordinator.addUrlTextChangeListener(mStatusViewCoordinator);
// mLocationBar's direction is tied to this UrlBar's text direction. Icons inside the
// location bar, e.g. lock, refresh, X, should be reversed if UrlBar's text is RTL.
......@@ -1118,6 +1118,5 @@ public class LocationBarLayout extends FrameLayout
String textWithoutAutocomplete = mUrlCoordinator.getTextWithoutAutocomplete();
String textWithAutocomplete = mUrlCoordinator.getTextWithAutocomplete();
mAutocompleteCoordinator.onTextChanged(textWithoutAutocomplete, textWithAutocomplete);
mStatusViewCoordinator.onTextChanged(textWithoutAutocomplete, textWithAutocomplete);
}
}
......@@ -13,12 +13,14 @@ import android.os.StrictMode;
import android.provider.Settings;
import android.support.v13.view.inputmethod.EditorInfoCompat;
import android.support.v4.text.BidiFormatter;
import android.support.v4.util.ObjectsCompat;
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.TextWatcher;
import android.text.style.ReplacementSpan;
import android.util.AttributeSet;
import android.view.GestureDetector;
......@@ -97,7 +99,8 @@ public abstract class UrlBar extends AutocompleteEditText {
private int mUrlDirection;
private UrlBarDelegate mUrlBarDelegate;
private UrlTextChangeListener mTextChangeListener;
private UrlTextChangeListener mUrlTextChangeListener;
private TextWatcher mTextChangedListener;
private UrlBarTextContextMenuDelegate mTextContextMenuDelegate;
private UrlDirectionListener mUrlDirectionListener;
......@@ -590,7 +593,22 @@ public abstract class UrlBar extends AutocompleteEditText {
* @param listener The listener to be notified.
*/
public void setUrlTextChangeListener(UrlTextChangeListener listener) {
mTextChangeListener = listener;
mUrlTextChangeListener = listener;
}
/**
* Set the listener to be notified when the view's text has changed.
* @param textChangedListener The listener to be notified.
*/
public void setTextChangedListener(TextWatcher textChangedListener) {
if (ObjectsCompat.equals(mTextChangedListener, textChangedListener)) {
return;
} else if (mTextChangedListener != null) {
removeTextChangedListener(mTextChangedListener);
}
mTextChangedListener = textChangedListener;
addTextChangedListener(mTextChangedListener);
}
/**
......@@ -950,12 +968,13 @@ public abstract class UrlBar extends AutocompleteEditText {
if (DEBUG) {
Log.i(TAG, "onAutocompleteTextStateChanged: DIS[%b]", updateDisplay);
}
if (mTextChangeListener == null) return;
if (mUrlTextChangeListener == null) return;
if (updateDisplay) limitDisplayableLength();
// crbug.com/764749
Log.w(TAG, "Text change observed, triggering autocomplete.");
mTextChangeListener.onTextChanged(getTextWithoutAutocomplete(), getTextWithAutocomplete());
mUrlTextChangeListener.onTextChanged(
getTextWithoutAutocomplete(), getTextWithAutocomplete());
}
/**
......
......@@ -4,6 +4,7 @@
package org.chromium.chrome.browser.omnibox;
import android.text.TextWatcher;
import android.view.ActionMode;
import androidx.annotation.IntDef;
......@@ -60,6 +61,11 @@ public class UrlBarCoordinator implements UrlBarEditingTextStateProvider {
mMediator.addUrlTextChangeListener(listener);
}
/** @see TextWatcher */
public void addTextChangedListener(TextWatcher textWatcher) {
mMediator.addTextChangedListener(textWatcher);
}
/** @see UrlBarMediator#setUrlBarData(UrlBarData, int, int) */
public boolean setUrlBarData(
UrlBarData data, @ScrollType int scrollType, @SelectionState int state) {
......
......@@ -8,8 +8,10 @@ import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.net.Uri;
import android.text.Editable;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.text.format.DateUtils;
import android.view.ActionMode;
......@@ -41,7 +43,8 @@ import java.util.List;
/**
* Handles collecting and pushing state information to the UrlBar model.
*/
class UrlBarMediator implements UrlBar.UrlBarTextContextMenuDelegate, UrlBar.UrlTextChangeListener {
class UrlBarMediator
implements UrlBar.UrlBarTextContextMenuDelegate, UrlBar.UrlTextChangeListener, TextWatcher {
private final PropertyModel mModel;
private Callback<Boolean> mOnFocusChangeCallback;
......@@ -58,6 +61,7 @@ class UrlBarMediator implements UrlBar.UrlBarTextContextMenuDelegate, UrlBar.Url
private static final int NUM_OF_BUCKETS = 100;
private final List<UrlTextChangeListener> mUrlTextChangeListeners = new ArrayList<>();
private final List<TextWatcher> mTextChangedListeners = new ArrayList<>();
public UrlBarMediator(PropertyModel model) {
mModel = model;
......@@ -66,6 +70,7 @@ class UrlBarMediator implements UrlBar.UrlBarTextContextMenuDelegate, UrlBar.Url
mModel.set(UrlBarProperties.SHOW_CURSOR, false);
mModel.set(UrlBarProperties.TEXT_CONTEXT_MENU_DELEGATE, this);
mModel.set(UrlBarProperties.URL_TEXT_CHANGE_LISTENER, this);
mModel.set(UrlBarProperties.TEXT_CHANGED_LISTENER, this);
setUseDarkTextColors(true);
}
......@@ -81,6 +86,11 @@ class UrlBarMediator implements UrlBar.UrlBarTextContextMenuDelegate, UrlBar.Url
mUrlTextChangeListeners.add(listener);
}
/** @see android.widget.TextView#addTextChangedListener */
public void addTextChangedListener(TextWatcher textWatcher) {
mTextChangedListeners.add(textWatcher);
}
/**
* Updates the text content of the UrlBar.
*
......@@ -355,6 +365,7 @@ class UrlBarMediator implements UrlBar.UrlBarTextContextMenuDelegate, UrlBar.Url
return url.substring(0, pathIndex);
}
/** @see UrlTextChangeListener */
@Override
public void onTextChanged(String textWithoutAutocomplete, String textWithAutocomplete) {
for (int i = 0; i < mUrlTextChangeListeners.size(); i++) {
......@@ -363,6 +374,30 @@ class UrlBarMediator implements UrlBar.UrlBarTextContextMenuDelegate, UrlBar.Url
}
}
/** @see TextWatcher */
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
for (int i = 0; i < mTextChangedListeners.size(); i++) {
mTextChangedListeners.get(i).beforeTextChanged(s, start, count, after);
}
}
/** @see TextWatcher */
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
for (int i = 0; i < mTextChangedListeners.size(); i++) {
mTextChangedListeners.get(i).onTextChanged(s, start, before, count);
}
}
/** @see TextWatcher */
@Override
public void afterTextChanged(Editable editable) {
for (int i = 0; i < mTextChangedListeners.size(); i++) {
mTextChangedListeners.get(i).afterTextChanged(editable);
}
}
private void recordPasteMetrics(String text) {
boolean isUrl = BrowserStartupController.get(LibraryProcessType.PROCESS_BROWSER)
.isFullBrowserStarted()
......
......@@ -4,6 +4,7 @@
package org.chromium.chrome.browser.omnibox;
import android.text.TextWatcher;
import android.view.ActionMode;
import org.chromium.base.Callback;
......@@ -115,10 +116,14 @@ class UrlBarProperties {
public static final WritableObjectPropertyKey<UrlDirectionListener> URL_DIRECTION_LISTENER =
new WritableObjectPropertyKey<>();
/** The callback to be notified on text changes. */
/** The callback to be notified on url text changes. @see UrlTextChangeListener. */
public static final WritableObjectPropertyKey<UrlTextChangeListener> URL_TEXT_CHANGE_LISTENER =
new WritableObjectPropertyKey<>();
/** The callback to be notified on text changes. @see TextWatcher. */
public static final WritableObjectPropertyKey<TextWatcher> TEXT_CHANGED_LISTENER =
new WritableObjectPropertyKey<>();
/** Specifies whether dark text colors should be used in the view. */
public static final WritableBooleanPropertyKey USE_DARK_TEXT_COLORS =
new WritableBooleanPropertyKey();
......@@ -130,5 +135,5 @@ class UrlBarProperties {
public static final PropertyKey[] ALL_KEYS = new PropertyKey[] {ACTION_MODE_CALLBACK,
ALLOW_FOCUS, AUTOCOMPLETE_TEXT, DELEGATE, FOCUS_CHANGE_CALLBACK, SHOW_CURSOR,
TEXT_CONTEXT_MENU_DELEGATE, TEXT_STATE, URL_DIRECTION_LISTENER,
URL_TEXT_CHANGE_LISTENER, USE_DARK_TEXT_COLORS, WINDOW_DELEGATE};
URL_TEXT_CHANGE_LISTENER, TEXT_CHANGED_LISTENER, USE_DARK_TEXT_COLORS, WINDOW_DELEGATE};
}
......@@ -73,6 +73,8 @@ class UrlBarViewBinder {
view.setUrlDirectionListener(model.get(UrlBarProperties.URL_DIRECTION_LISTENER));
} else if (UrlBarProperties.URL_TEXT_CHANGE_LISTENER.equals(propertyKey)) {
view.setUrlTextChangeListener(model.get(UrlBarProperties.URL_TEXT_CHANGE_LISTENER));
} else if (UrlBarProperties.TEXT_CHANGED_LISTENER.equals(propertyKey)) {
view.setTextChangedListener(model.get(UrlBarProperties.TEXT_CHANGED_LISTENER));
} else if (UrlBarProperties.WINDOW_DELEGATE.equals(propertyKey)) {
view.setWindowDelegate(model.get(UrlBarProperties.WINDOW_DELEGATE));
}
......
......@@ -18,7 +18,7 @@ import org.chromium.base.VisibleForTesting;
import org.chromium.base.library_loader.LibraryProcessType;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.omnibox.SearchEngineLogoUtils;
import org.chromium.chrome.browser.omnibox.UrlBar;
import org.chromium.chrome.browser.omnibox.UrlBarEditingTextStateProvider;
import org.chromium.chrome.browser.omnibox.suggestions.AutocompleteCoordinatorFactory;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.toolbar.ToolbarCommonPropertiesModel;
......@@ -89,15 +89,18 @@ class StatusMediator {
private StatusMediatorDelegate mDelegate;
private Resources mResources;
private ToolbarCommonPropertiesModel mToolbarCommonPropertiesModel;
private UrlBarEditingTextStateProvider mUrlBarEditingTextStateProvider;
private String mUrlBarTextWithAutocomplete = "";
private boolean mUrlBarTextIsValidUrl;
StatusMediator(PropertyModel model, Resources resources) {
StatusMediator(PropertyModel model, Resources resources,
UrlBarEditingTextStateProvider urlBarEditingTextStateProvider) {
mModel = model;
mDelegate = new StatusMediatorDelegate();
updateColorTheme();
mResources = resources;
mUrlBarEditingTextStateProvider = urlBarEditingTextStateProvider;
}
/**
......@@ -497,8 +500,13 @@ class StatusMediator {
return 0;
}
/** @see {@link UrlBar.UrlTextChangeListener} */
void onTextChanged(String urlTextWithoutAutocomplete, String urlTextWithAutocomplete) {
/** @see android.text.TextWatcher#onTextChanged */
void onTextChanged(CharSequence charSequence) {
// TODO (crbug.com/1012870): This is a workaround for the linked bug. Once the bug is fixed,
// it should be removed.
String urlTextWithAutocomplete = TextUtils.isEmpty(charSequence)
? ""
: mUrlBarEditingTextStateProvider.getTextWithAutocomplete();
if (TextUtils.equals(mUrlBarTextWithAutocomplete, urlTextWithAutocomplete)) {
return;
}
......
......@@ -5,13 +5,15 @@
package org.chromium.chrome.browser.omnibox.status;
import android.content.res.Resources;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import androidx.annotation.DrawableRes;
import org.chromium.base.VisibleForTesting;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.omnibox.UrlBar;
import org.chromium.chrome.browser.omnibox.UrlBarEditingTextStateProvider;
import org.chromium.chrome.browser.page_info.PageInfoController;
import org.chromium.chrome.browser.toolbar.ToolbarDataProvider;
import org.chromium.ui.modelutil.PropertyModel;
......@@ -21,7 +23,7 @@ import org.chromium.ui.modelutil.PropertyModelChangeProcessor;
* A component for displaying a status icon (e.g. security icon or navigation icon) and optional
* verbose status text.
*/
public class StatusViewCoordinator implements View.OnClickListener, UrlBar.UrlTextChangeListener {
public class StatusViewCoordinator implements View.OnClickListener, TextWatcher {
private final StatusView mStatusView;
private final StatusMediator mMediator;
private final PropertyModel mModel;
......@@ -34,8 +36,10 @@ public class StatusViewCoordinator implements View.OnClickListener, UrlBar.UrlTe
* Creates a new StatusViewCoordinator.
* @param isTablet Whether the UI is shown on a tablet.
* @param statusView The status view, used to supply and manipulate child views.
* @param urlBarEditingTextStateProvider The url coordinator.
*/
public StatusViewCoordinator(boolean isTablet, StatusView statusView) {
public StatusViewCoordinator(boolean isTablet, StatusView statusView,
UrlBarEditingTextStateProvider urlBarEditingTextStateProvider) {
mIsTablet = isTablet;
mStatusView = statusView;
......@@ -44,7 +48,8 @@ public class StatusViewCoordinator implements View.OnClickListener, UrlBar.UrlTe
.build();
PropertyModelChangeProcessor.create(mModel, mStatusView, new StatusViewBinder());
mMediator = new StatusMediator(mModel, mStatusView.getResources());
mMediator = new StatusMediator(
mModel, mStatusView.getResources(), urlBarEditingTextStateProvider);
Resources res = mStatusView.getResources();
mMediator.setUrlMinWidth(res.getDimensionPixelSize(R.dimen.location_bar_min_url_width)
......@@ -216,7 +221,13 @@ public class StatusViewCoordinator implements View.OnClickListener, UrlBar.UrlTe
}
@Override
public void onTextChanged(String textWithoutAutocomplete, String textWithAutocomplete) {
mMediator.onTextChanged(textWithoutAutocomplete, textWithAutocomplete);
public void beforeTextChanged(CharSequence s, int start, int count, int after) {}
@Override
public void onTextChanged(CharSequence charSequence, int start, int before, int count) {
mMediator.onTextChanged(charSequence);
}
@Override
public void afterTextChanged(Editable editable) {}
}
......@@ -9,6 +9,7 @@ import android.content.ClipboardManager;
import android.content.Context;
import android.text.Selection;
import android.text.SpannableStringBuilder;
import android.text.TextWatcher;
import org.junit.After;
import org.junit.Assert;
......@@ -35,15 +36,30 @@ import org.chromium.ui.modelutil.PropertyObservable.PropertyObserver;
@Config(manifest = Config.NONE)
public class UrlBarMediatorUnitTest {
@Mock
UrlBar.UrlTextChangeListener mMockListener;
UrlBar.UrlTextChangeListener mMockUrlTextListener;
@Mock
UrlBar.UrlTextChangeListener mAnotherMockListener;
UrlBar.UrlTextChangeListener mAnotherUrlTextMockListener;
@Mock
TextWatcher mMockTextWatcher;
@Mock
TextWatcher mAnotherMockTextWatcher;
PropertyModel mModel;
UrlBarMediator mMediator;
@Before
public void setUp() {
RecordHistogram.setDisabledForTests(true);
RecordUserAction.setDisabledForTests(true);
MockitoAnnotations.initMocks(this);
mModel = new PropertyModel(UrlBarProperties.ALL_KEYS);
mMediator = new UrlBarMediator(mModel) {
@Override
protected String sanitizeTextForPaste(String text) {
return text.trim();
}
};
}
@After
......@@ -54,9 +70,6 @@ public class UrlBarMediatorUnitTest {
@Test
public void setUrlData_SendsUpdates() {
PropertyModel model = new PropertyModel(UrlBarProperties.ALL_KEYS);
UrlBarMediator mediator = new UrlBarMediator(model);
UrlBarData baseData = UrlBarData.create(
"http://www.example.com", spannable("www.example.com"), 0, 14, "Blah");
UrlBarData dataWithDifferentDisplay = UrlBarData.create(
......@@ -64,77 +77,68 @@ public class UrlBarMediatorUnitTest {
UrlBarData dataWithDifferentEditing = UrlBarData.create(
"http://www.example.com", spannable("www.example.com"), 0, 14, "Bar");
Assert.assertTrue(mediator.setUrlBarData(baseData, UrlBar.ScrollType.SCROLL_TO_TLD, 4));
Assert.assertTrue(mMediator.setUrlBarData(baseData, UrlBar.ScrollType.SCROLL_TO_TLD, 4));
@SuppressWarnings("unchecked")
PropertyObserver<PropertyKey> observer = Mockito.mock(PropertyObserver.class);
model.addObserver(observer);
mModel.addObserver(observer);
Mockito.<PropertyObserver>reset(observer);
Assert.assertTrue(mediator.setUrlBarData(
Assert.assertTrue(mMediator.setUrlBarData(
dataWithDifferentDisplay, UrlBar.ScrollType.SCROLL_TO_TLD, 4));
Assert.assertTrue(mediator.setUrlBarData(
Assert.assertTrue(mMediator.setUrlBarData(
dataWithDifferentEditing, UrlBar.ScrollType.SCROLL_TO_TLD, 4));
Assert.assertTrue(mediator.setUrlBarData(
Assert.assertTrue(mMediator.setUrlBarData(
dataWithDifferentEditing, UrlBar.ScrollType.SCROLL_TO_BEGINNING, 4));
Mockito.verify(observer, Mockito.times(3))
.onPropertyChanged(model, UrlBarProperties.TEXT_STATE);
.onPropertyChanged(mModel, UrlBarProperties.TEXT_STATE);
}
@Test
public void setUrlData_PreventsDuplicateUpdates() {
PropertyModel model = new PropertyModel(UrlBarProperties.ALL_KEYS);
UrlBarMediator mediator = new UrlBarMediator(model);
UrlBarData data1 = UrlBarData.create(
"http://www.example.com", spannable("www.example.com"), 0, 0, "Blah");
UrlBarData data2 = UrlBarData.create(
"http://www.example.com", spannable("www.example.com"), 0, 0, "Blah");
Assert.assertTrue(mediator.setUrlBarData(data1, UrlBar.ScrollType.SCROLL_TO_TLD, 4));
Assert.assertTrue(mMediator.setUrlBarData(data1, UrlBar.ScrollType.SCROLL_TO_TLD, 4));
@SuppressWarnings("unchecked")
PropertyObserver<PropertyKey> observer = Mockito.mock(PropertyObserver.class);
model.addObserver(observer);
mModel.addObserver(observer);
Mockito.<PropertyObserver>reset(observer);
Assert.assertFalse(mediator.setUrlBarData(data1, UrlBar.ScrollType.SCROLL_TO_TLD, 4));
Assert.assertFalse(mediator.setUrlBarData(data2, UrlBar.ScrollType.SCROLL_TO_TLD, 4));
Assert.assertFalse(mMediator.setUrlBarData(data1, UrlBar.ScrollType.SCROLL_TO_TLD, 4));
Assert.assertFalse(mMediator.setUrlBarData(data2, UrlBar.ScrollType.SCROLL_TO_TLD, 4));
Mockito.verifyZeroInteractions(observer);
}
@Test
public void setUrlData_ScrollStateForDataUrl() {
PropertyModel model = new PropertyModel(UrlBarProperties.ALL_KEYS);
UrlBarMediator mediator = new UrlBarMediator(model);
String displayText = "data:text/html,blah";
UrlBarData data = UrlBarData.create(
"data:text/html,blah,blah", spannable(displayText), 0, displayText.length(), null);
Assert.assertTrue(mediator.setUrlBarData(data, UrlBar.ScrollType.SCROLL_TO_TLD,
Assert.assertTrue(mMediator.setUrlBarData(data, UrlBar.ScrollType.SCROLL_TO_TLD,
UrlBarCoordinator.SelectionState.SELECT_ALL));
// The scroll state should be overridden to SCROLL_TO_BEGINNING for file-type schemes.
Assert.assertEquals(UrlBar.ScrollType.SCROLL_TO_BEGINNING,
model.get(UrlBarProperties.TEXT_STATE).scrollType);
mModel.get(UrlBarProperties.TEXT_STATE).scrollType);
}
@Test
public void setUrlData_ScrollStateForAboutUrl() {
PropertyModel model = new PropertyModel(UrlBarProperties.ALL_KEYS);
UrlBarMediator mediator = new UrlBarMediator(model);
String displayText = "about:blank#verylongurl.totallylegit.notsuspicious.url.com";
UrlBarData data = UrlBarData.create(
displayText, spannable(displayText), 0, displayText.length(), null);
Assert.assertTrue(mediator.setUrlBarData(data, UrlBar.ScrollType.SCROLL_TO_TLD,
Assert.assertTrue(mMediator.setUrlBarData(data, UrlBar.ScrollType.SCROLL_TO_TLD,
UrlBarCoordinator.SelectionState.SELECT_ALL));
// The scroll state should be overridden to SCROLL_TO_BEGINNING for file-type schemes.
Assert.assertEquals(UrlBar.ScrollType.SCROLL_TO_BEGINNING,
model.get(UrlBarProperties.TEXT_STATE).scrollType);
mModel.get(UrlBarProperties.TEXT_STATE).scrollType);
}
@Test
......@@ -222,74 +226,78 @@ public class UrlBarMediatorUnitTest {
@Test
public void pasteTextValidation() {
PropertyModel model = new PropertyModel(UrlBarProperties.ALL_KEYS);
UrlBarMediator mediator = new UrlBarMediator(model) {
@Override
protected String sanitizeTextForPaste(String text) {
return text.trim();
}
};
ClipboardManager clipboard =
(ClipboardManager) RuntimeEnvironment.application.getSystemService(
Context.CLIPBOARD_SERVICE);
clipboard.setPrimaryClip(null);
Assert.assertNull(mediator.getTextToPaste());
Assert.assertNull(mMediator.getTextToPaste());
clipboard.setPrimaryClip(ClipData.newPlainText("", ""));
Assert.assertEquals("", mediator.getTextToPaste());
Assert.assertEquals("", mMediator.getTextToPaste());
clipboard.setPrimaryClip(ClipData.newPlainText("", "test"));
Assert.assertEquals("test", mediator.getTextToPaste());
Assert.assertEquals("test", mMediator.getTextToPaste());
clipboard.setPrimaryClip(ClipData.newPlainText("", " test "));
Assert.assertEquals("test", mediator.getTextToPaste());
Assert.assertEquals("test", mMediator.getTextToPaste());
}
@Test
public void cutCopyReplacementTextValidation() {
PropertyModel model = new PropertyModel(UrlBarProperties.ALL_KEYS);
UrlBarMediator mediator = new UrlBarMediator(model);
String url = "https://www.test.com/blah";
String displayText = "test.com/blah";
String editingText = "www.test.com/blah";
mediator.setUrlBarData(UrlBarData.create(url, displayText, 0, 12, editingText),
mMediator.setUrlBarData(UrlBarData.create(url, displayText, 0, 12, editingText),
UrlBar.ScrollType.NO_SCROLL, UrlBarCoordinator.SelectionState.SELECT_ALL);
// Replacement is only valid if selecting the full text.
Assert.assertNull(mediator.getReplacementCutCopyText(editingText, 1, 2));
Assert.assertNull(mMediator.getReplacementCutCopyText(editingText, 1, 2));
// Editing text will be replaced with the full URL if selecting all of the text.
Assert.assertEquals(
url, mediator.getReplacementCutCopyText(editingText, 0, editingText.length()));
url, mMediator.getReplacementCutCopyText(editingText, 0, editingText.length()));
// If selecting just the URL portion of the editing text, it should be replaced with the
// unformatted URL.
Assert.assertEquals(
"https://www.test.com", mediator.getReplacementCutCopyText(editingText, 0, 12));
"https://www.test.com", mMediator.getReplacementCutCopyText(editingText, 0, 12));
// If the path changed in the editing text changed but the domain is untouched, it should
// be replaced with the full domain from the unformatted URL.
Assert.assertEquals("https://www.test.com/foo",
mediator.getReplacementCutCopyText("www.test.com/foo", 0, 16));
mMediator.getReplacementCutCopyText("www.test.com/foo", 0, 16));
}
@Test
public void urlTextChangeListenerCompositeObserver() {
PropertyModel model = new PropertyModel(UrlBarProperties.ALL_KEYS);
UrlBarMediator mediator = new UrlBarMediator(model);
mediator.addUrlTextChangeListener(mMockListener);
mMediator.addUrlTextChangeListener(mMockUrlTextListener);
String text = "foo";
String textWithAutocomplete = "foo.bar";
mediator.onTextChanged(text, textWithAutocomplete);
Mockito.verify(mMockListener, Mockito.times(1)).onTextChanged(text, textWithAutocomplete);
mMediator.onTextChanged(text, textWithAutocomplete);
Mockito.verify(mMockUrlTextListener, Mockito.times(1))
.onTextChanged(text, textWithAutocomplete);
mediator.addUrlTextChangeListener(mAnotherMockListener);
mediator.onTextChanged(text, textWithAutocomplete);
Mockito.verify(mMockListener, Mockito.times(2)).onTextChanged(text, textWithAutocomplete);
Mockito.verify(mAnotherMockListener, Mockito.times(1))
mMediator.addUrlTextChangeListener(mAnotherUrlTextMockListener);
mMediator.onTextChanged(text, textWithAutocomplete);
Mockito.verify(mMockUrlTextListener, Mockito.times(2))
.onTextChanged(text, textWithAutocomplete);
Mockito.verify(mAnotherUrlTextMockListener, Mockito.times(1))
.onTextChanged(text, textWithAutocomplete);
}
@Test
public void textWatcherCompositeObserver() {
mMediator.addTextChangedListener(mMockTextWatcher);
CharSequence text = "foo";
mMediator.onTextChanged(text, 0, 1, 2);
Mockito.verify(mMockTextWatcher, Mockito.times(1)).onTextChanged(text, 0, 1, 2);
mMediator.addTextChangedListener(mAnotherMockTextWatcher);
mMediator.onTextChanged(text, 0, 1, 2);
Mockito.verify(mMockTextWatcher, Mockito.times(2)).onTextChanged(text, 0, 1, 2);
Mockito.verify(mAnotherMockTextWatcher, Mockito.times(1)).onTextChanged(text, 0, 1, 2);
}
private static SpannableStringBuilder spannable(String text) {
......
......@@ -25,6 +25,7 @@ import org.chromium.base.Callback;
import org.chromium.base.test.BaseRobolectricTestRunner;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.ChromeFeatureList;
import org.chromium.chrome.browser.omnibox.UrlBarEditingTextStateProvider;
import org.chromium.chrome.browser.toolbar.ToolbarCommonPropertiesModel;
import org.chromium.chrome.test.util.browser.Features;
import org.chromium.ui.modelutil.PropertyModel;
......@@ -42,6 +43,8 @@ public final class StatusMediatorUnitTest {
@Mock
ToolbarCommonPropertiesModel mToolbarCommonPropertiesModel;
@Mock
UrlBarEditingTextStateProvider mUrlBarEditingTextStateProvider;
@Mock
StatusMediator.StatusMediatorDelegate mDelegate;
@Mock
Bitmap mBitmap;
......@@ -56,7 +59,7 @@ public final class StatusMediatorUnitTest {
MockitoAnnotations.initMocks(this);
mModel = new PropertyModel(StatusProperties.ALL_KEYS);
mMediator = new StatusMediator(mModel, mResources);
mMediator = new StatusMediator(mModel, mResources, mUrlBarEditingTextStateProvider);
mMediator.setToolbarCommonPropertiesModel(mToolbarCommonPropertiesModel);
mMediator.setDelegateForTesting(mDelegate);
}
......@@ -123,7 +126,7 @@ public final class StatusMediatorUnitTest {
mMediator.setUrlHasFocus(true);
mMediator.setShowIconsWhenUrlFocused(true);
mMediator.onTextChanged("", "testing");
mMediator.onTextChanged(TEST_SEARCH_URL);
Assert.assertEquals(R.drawable.ic_globe_24dp, mModel.get(StatusProperties.STATUS_ICON_RES));
}
......
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