Commit 0dfb95cc authored by Gang Wu's avatar Gang Wu Committed by Commit Bot

[omnibox] Implement clipboard suggestion processor

Separate clipboard out of BasicSuggestionProcessor, and create a new
processor for clipboard.

Bug: 1020708
Change-Id: I9008c6263354562ffbc8232b28c839a45c96fe46
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2051292
Commit-Queue: Gang Wu <gangwu@chromium.org>
Reviewed-by: default avatarTed Choc <tedchoc@chromium.org>
Reviewed-by: default avatarEnder <ender@google.com>
Cr-Commit-Position: refs/heads/master@{#746162}
parent a52f7e9e
...@@ -1177,6 +1177,7 @@ chrome_java_sources = [ ...@@ -1177,6 +1177,7 @@ chrome_java_sources = [
"java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/SuggestionViewDelegate.java", "java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/SuggestionViewDelegate.java",
"java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/SuggestionViewProperties.java", "java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/SuggestionViewProperties.java",
"java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/SuggestionViewViewBinder.java", "java/src/org/chromium/chrome/browser/omnibox/suggestions/basic/SuggestionViewViewBinder.java",
"java/src/org/chromium/chrome/browser/omnibox/suggestions/clipboard/ClipboardSuggestionProcessor.java",
"java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionProcessor.java", "java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionProcessor.java",
"java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionProperties.java", "java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionProperties.java",
"java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionViewBinder.java", "java/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionViewBinder.java",
......
...@@ -155,12 +155,14 @@ chrome_junit_test_java_sources = [ ...@@ -155,12 +155,14 @@ chrome_junit_test_java_sources = [
"junit/src/org/chromium/chrome/browser/omnibox/geo/VisibleNetworksTest.java", "junit/src/org/chromium/chrome/browser/omnibox/geo/VisibleNetworksTest.java",
"junit/src/org/chromium/chrome/browser/omnibox/geo/VisibleNetworksTrackerTest.java", "junit/src/org/chromium/chrome/browser/omnibox/geo/VisibleNetworksTrackerTest.java",
"junit/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessorUnitTest.java", "junit/src/org/chromium/chrome/browser/omnibox/suggestions/answer/AnswerSuggestionProcessorUnitTest.java",
"junit/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionProcessorTest.java",
"junit/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewBinderUnitTest.java", "junit/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewBinderUnitTest.java",
"junit/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewProcessorUnitTest.java", "junit/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewProcessorUnitTest.java",
"junit/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewTest.java", "junit/src/org/chromium/chrome/browser/omnibox/suggestions/base/BaseSuggestionViewTest.java",
"junit/src/org/chromium/chrome/browser/omnibox/suggestions/base/SimpleHorizontalLayoutViewTest.java", "junit/src/org/chromium/chrome/browser/omnibox/suggestions/base/SimpleHorizontalLayoutViewTest.java",
"junit/src/org/chromium/chrome/browser/omnibox/suggestions/base/SuggestionSpannableUnitTest.java", "junit/src/org/chromium/chrome/browser/omnibox/suggestions/base/SuggestionSpannableUnitTest.java",
"junit/src/org/chromium/chrome/browser/omnibox/suggestions/basic/BasicSuggestionProcessorTest.java", "junit/src/org/chromium/chrome/browser/omnibox/suggestions/basic/BasicSuggestionProcessorTest.java",
"junit/src/org/chromium/chrome/browser/omnibox/suggestions/clipboard/ClipboardSuggestionProcessorTest.java",
"junit/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionTest.java", "junit/src/org/chromium/chrome/browser/omnibox/suggestions/editurl/EditUrlSuggestionTest.java",
"junit/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionProcessorUnitTest.java", "junit/src/org/chromium/chrome/browser/omnibox/suggestions/entity/EntitySuggestionProcessorUnitTest.java",
"junit/src/org/chromium/chrome/browser/omnibox/suggestions/tail/AlignmentManagerUnitTest.java", "junit/src/org/chromium/chrome/browser/omnibox/suggestions/tail/AlignmentManagerUnitTest.java",
......
...@@ -149,6 +149,12 @@ public class AutocompleteCoordinatorImpl implements AutocompleteCoordinator { ...@@ -149,6 +149,12 @@ public class AutocompleteCoordinatorImpl implements AutocompleteCoordinator {
new TailSuggestionView(parent.getContext())), new TailSuggestionView(parent.getContext())),
new BaseSuggestionViewBinder<TailSuggestionView>( new BaseSuggestionViewBinder<TailSuggestionView>(
TailSuggestionViewBinder::bind)); TailSuggestionViewBinder::bind));
adapter.registerType(
OmniboxSuggestionUiType.CLIPBOARD_SUGGESTION,
parent -> new BaseSuggestionView<View>(
parent.getContext(), R.layout.omnibox_basic_suggestion),
new BaseSuggestionViewBinder<View>(SuggestionViewViewBinder::bind));
// clang-format on // clang-format on
mHolder = new SuggestionListViewHolder(container, list); mHolder = new SuggestionListViewHolder(container, list);
......
...@@ -43,6 +43,7 @@ import org.chromium.chrome.browser.omnibox.suggestions.answer.AnswerSuggestionPr ...@@ -43,6 +43,7 @@ import org.chromium.chrome.browser.omnibox.suggestions.answer.AnswerSuggestionPr
import org.chromium.chrome.browser.omnibox.suggestions.basic.BasicSuggestionProcessor; import org.chromium.chrome.browser.omnibox.suggestions.basic.BasicSuggestionProcessor;
import org.chromium.chrome.browser.omnibox.suggestions.basic.SuggestionHost; import org.chromium.chrome.browser.omnibox.suggestions.basic.SuggestionHost;
import org.chromium.chrome.browser.omnibox.suggestions.basic.SuggestionViewDelegate; import org.chromium.chrome.browser.omnibox.suggestions.basic.SuggestionViewDelegate;
import org.chromium.chrome.browser.omnibox.suggestions.clipboard.ClipboardSuggestionProcessor;
import org.chromium.chrome.browser.omnibox.suggestions.editurl.EditUrlSuggestionProcessor; import org.chromium.chrome.browser.omnibox.suggestions.editurl.EditUrlSuggestionProcessor;
import org.chromium.chrome.browser.omnibox.suggestions.entity.EntitySuggestionProcessor; import org.chromium.chrome.browser.omnibox.suggestions.entity.EntitySuggestionProcessor;
import org.chromium.chrome.browser.omnibox.suggestions.tail.TailSuggestionProcessor; import org.chromium.chrome.browser.omnibox.suggestions.tail.TailSuggestionProcessor;
...@@ -195,6 +196,8 @@ class AutocompleteMediator implements OnSuggestionsReceivedListener, StartStopWi ...@@ -195,6 +196,8 @@ class AutocompleteMediator implements OnSuggestionsReceivedListener, StartStopWi
new EditUrlSuggestionProcessor(mContext, host, mDelegate, iconBridgeSupplier); new EditUrlSuggestionProcessor(mContext, host, mDelegate, iconBridgeSupplier);
registerSuggestionProcessor(new AnswerSuggestionProcessor( registerSuggestionProcessor(new AnswerSuggestionProcessor(
mContext, host, mUrlBarEditingTextProvider, imageFetcherSupplier)); mContext, host, mUrlBarEditingTextProvider, imageFetcherSupplier));
registerSuggestionProcessor(
new ClipboardSuggestionProcessor(mContext, host, iconBridgeSupplier));
registerSuggestionProcessor( registerSuggestionProcessor(
new EntitySuggestionProcessor(mContext, host, imageFetcherSupplier)); new EntitySuggestionProcessor(mContext, host, imageFetcherSupplier));
registerSuggestionProcessor(new TailSuggestionProcessor(mContext, host)); registerSuggestionProcessor(new TailSuggestionProcessor(mContext, host));
......
...@@ -12,7 +12,7 @@ import java.lang.annotation.RetentionPolicy; ...@@ -12,7 +12,7 @@ import java.lang.annotation.RetentionPolicy;
/** The different types of view that a suggestion can be. */ /** The different types of view that a suggestion can be. */
@IntDef({OmniboxSuggestionUiType.DEFAULT, OmniboxSuggestionUiType.EDIT_URL_SUGGESTION, @IntDef({OmniboxSuggestionUiType.DEFAULT, OmniboxSuggestionUiType.EDIT_URL_SUGGESTION,
OmniboxSuggestionUiType.ANSWER_SUGGESTION, OmniboxSuggestionUiType.ENTITY_SUGGESTION, OmniboxSuggestionUiType.ANSWER_SUGGESTION, OmniboxSuggestionUiType.ENTITY_SUGGESTION,
OmniboxSuggestionUiType.TAIL_SUGGESTION}) OmniboxSuggestionUiType.TAIL_SUGGESTION, OmniboxSuggestionUiType.CLIPBOARD_SUGGESTION})
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
public @interface OmniboxSuggestionUiType { public @interface OmniboxSuggestionUiType {
int DEFAULT = 0; int DEFAULT = 0;
...@@ -20,4 +20,5 @@ public @interface OmniboxSuggestionUiType { ...@@ -20,4 +20,5 @@ public @interface OmniboxSuggestionUiType {
int ANSWER_SUGGESTION = 2; int ANSWER_SUGGESTION = 2;
int ENTITY_SUGGESTION = 3; int ENTITY_SUGGESTION = 3;
int TAIL_SUGGESTION = 4; int TAIL_SUGGESTION = 4;
int CLIPBOARD_SUGGESTION = 5;
} }
...@@ -5,11 +5,15 @@ ...@@ -5,11 +5,15 @@
package org.chromium.chrome.browser.omnibox.suggestions.base; package org.chromium.chrome.browser.omnibox.suggestions.base;
import android.content.Context; import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Typeface; import android.graphics.Typeface;
import android.text.Spannable; import android.text.Spannable;
import android.text.style.StyleSpan; import android.text.style.StyleSpan;
import androidx.annotation.Nullable;
import org.chromium.chrome.R; import org.chromium.chrome.R;
import org.chromium.chrome.browser.favicon.LargeIconBridge;
import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.omnibox.MatchClassificationStyle; import org.chromium.chrome.browser.omnibox.MatchClassificationStyle;
import org.chromium.chrome.browser.omnibox.suggestions.OmniboxSuggestion; import org.chromium.chrome.browser.omnibox.suggestions.OmniboxSuggestion;
...@@ -28,6 +32,7 @@ public abstract class BaseSuggestionViewProcessor implements SuggestionProcessor ...@@ -28,6 +32,7 @@ public abstract class BaseSuggestionViewProcessor implements SuggestionProcessor
private final Context mContext; private final Context mContext;
private final SuggestionHost mSuggestionHost; private final SuggestionHost mSuggestionHost;
private boolean mEnableCompactSuggestions; private boolean mEnableCompactSuggestions;
private final int mDesiredFaviconWidthPx;
@Override @Override
public void onUrlFocusChange(boolean hasFocus) {} public void onUrlFocusChange(boolean hasFocus) {}
...@@ -53,6 +58,8 @@ public abstract class BaseSuggestionViewProcessor implements SuggestionProcessor ...@@ -53,6 +58,8 @@ public abstract class BaseSuggestionViewProcessor implements SuggestionProcessor
public BaseSuggestionViewProcessor(Context context, SuggestionHost host) { public BaseSuggestionViewProcessor(Context context, SuggestionHost host) {
mContext = context; mContext = context;
mSuggestionHost = host; mSuggestionHost = host;
mDesiredFaviconWidthPx = mContext.getResources().getDimensionPixelSize(
R.dimen.omnibox_suggestion_favicon_size);
} }
/** /**
...@@ -135,4 +142,31 @@ public abstract class BaseSuggestionViewProcessor implements SuggestionProcessor ...@@ -135,4 +142,31 @@ public abstract class BaseSuggestionViewProcessor implements SuggestionProcessor
} }
return hasAtLeastOneMatch; return hasAtLeastOneMatch;
} }
/**
* Fetch suggestion favicon, if one is available.
* Updates icon decoration in supplied |model| if |url| is not null and points to an already
* visited website.
*
* @param model Model representing current suggestion.
* @param url Target URL the suggestion points to.
* @param iconBridge A {@link LargeIconBridge} supplies site favicons.
* @param onIconFetched Optional callback that will be invoked after successful fetch of a
* favicon.
*/
protected void fetchSuggestionFavicon(PropertyModel model, String url,
LargeIconBridge iconBridge, @Nullable Runnable onIconFetched) {
if (url == null || iconBridge == null) return;
iconBridge.getLargeIconForStringUrl(url, mDesiredFaviconWidthPx,
(Bitmap icon, int fallbackColor, boolean isFallbackColorDefault, int iconType) -> {
if (icon == null) return;
setSuggestionDrawableState(model,
SuggestionDrawableState.Builder.forBitmap(mContext, icon).build());
if (onIconFetched != null) {
onIconFetched.run();
}
});
}
} }
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
package org.chromium.chrome.browser.omnibox.suggestions.basic; package org.chromium.chrome.browser.omnibox.suggestions.basic;
import android.content.Context; import android.content.Context;
import android.graphics.Bitmap;
import android.support.annotation.DrawableRes; import android.support.annotation.DrawableRes;
import android.text.TextUtils; import android.text.TextUtils;
...@@ -85,12 +84,6 @@ public class BasicSuggestionProcessor extends BaseSuggestionViewProcessor { ...@@ -85,12 +84,6 @@ public class BasicSuggestionProcessor extends BaseSuggestionViewProcessor {
protected boolean canRefine(OmniboxSuggestion suggestion) { protected boolean canRefine(OmniboxSuggestion suggestion) {
final @OmniboxSuggestionType int suggestionType = suggestion.getType(); final @OmniboxSuggestionType int suggestionType = suggestion.getType();
if (suggestionType == OmniboxSuggestionType.CLIPBOARD_TEXT
|| suggestionType == OmniboxSuggestionType.CLIPBOARD_URL
|| suggestionType == OmniboxSuggestionType.CLIPBOARD_IMAGE) {
return false;
}
return !mUrlBarEditingTextProvider.getTextWithoutAutocomplete().trim().equalsIgnoreCase( return !mUrlBarEditingTextProvider.getTextWithoutAutocomplete().trim().equalsIgnoreCase(
suggestion.getDisplayText()); suggestion.getDisplayText());
} }
...@@ -104,10 +97,7 @@ public class BasicSuggestionProcessor extends BaseSuggestionViewProcessor { ...@@ -104,10 +97,7 @@ public class BasicSuggestionProcessor extends BaseSuggestionViewProcessor {
*/ */
private @SuggestionIcon int getSuggestionIconType(OmniboxSuggestion suggestion) { private @SuggestionIcon int getSuggestionIconType(OmniboxSuggestion suggestion) {
if (suggestion.isUrlSuggestion()) { if (suggestion.isUrlSuggestion()) {
if (suggestion.getType() == OmniboxSuggestionType.CLIPBOARD_TEXT if (suggestion.isStarred()) {
|| suggestion.getType() == OmniboxSuggestionType.CLIPBOARD_IMAGE) {
return SuggestionIcon.MAGNIFIER;
} else if (suggestion.isStarred()) {
return SuggestionIcon.BOOKMARK; return SuggestionIcon.BOOKMARK;
} else { } else {
return SuggestionIcon.GLOBE; return SuggestionIcon.GLOBE;
...@@ -188,44 +178,12 @@ public class BasicSuggestionProcessor extends BaseSuggestionViewProcessor { ...@@ -188,44 +178,12 @@ public class BasicSuggestionProcessor extends BaseSuggestionViewProcessor {
getSuggestedQuery(suggestion, suggestion.isUrlSuggestion(), !urlHighlighted); getSuggestedQuery(suggestion, suggestion.isUrlSuggestion(), !urlHighlighted);
updateSuggestionIcon(suggestion, model); updateSuggestionIcon(suggestion, model);
model.set(SuggestionViewProperties.IS_SEARCH_SUGGESTION, model.set(SuggestionViewProperties.IS_SEARCH_SUGGESTION, !suggestion.isUrlSuggestion());
!suggestion.isUrlSuggestion()
|| suggestionType == OmniboxSuggestionType.CLIPBOARD_IMAGE
|| suggestionType == OmniboxSuggestionType.CLIPBOARD_TEXT);
model.set(SuggestionViewProperties.TEXT_LINE_1_TEXT, textLine1); model.set(SuggestionViewProperties.TEXT_LINE_1_TEXT, textLine1);
model.set(SuggestionViewProperties.TEXT_LINE_2_TEXT, textLine2); model.set(SuggestionViewProperties.TEXT_LINE_2_TEXT, textLine2);
fetchSuggestionFavicon(model, suggestion.getUrl(), suggestion.getType()); fetchSuggestionFavicon(model, suggestion.getUrl(), mIconBridgeSupplier.get(), () -> {
} model.set(SuggestionViewProperties.SUGGESTION_ICON_TYPE, SuggestionIcon.FAVICON);
});
/**
* Fetch suggestion favicon, if one is available.
* Updates icon decoration in supplied |model| if |url| is not null and points to an already
* visited website.
*
* @param model Model representing current suggestion.
* @param url Target URL the suggestion points to.
* @param type Suggestion type.
*/
private void fetchSuggestionFavicon(
PropertyModel model, String url, @OmniboxSuggestionType int type) {
if (url == null || type == OmniboxSuggestionType.CLIPBOARD_TEXT) {
return;
}
// Include site favicon if we are presenting URL and have favicon available.
// TODO(gangwu): Create a separate processor for clipboard suggestions.
final LargeIconBridge iconBridge = mIconBridgeSupplier.get();
if (iconBridge == null) return;
iconBridge.getLargeIconForStringUrl(url, mDesiredFaviconWidthPx,
(Bitmap icon, int fallbackColor, boolean isFallbackColorDefault, int iconType) -> {
if (icon == null) return;
setSuggestionDrawableState(model,
SuggestionDrawableState.Builder.forBitmap(mContext, icon).build());
model.set(
SuggestionViewProperties.SUGGESTION_ICON_TYPE, SuggestionIcon.FAVICON);
});
} }
/** /**
......
// Copyright 2020 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.suggestions.clipboard;
import android.content.Context;
import android.support.annotation.DrawableRes;
import org.chromium.base.supplier.Supplier;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.favicon.LargeIconBridge;
import org.chromium.chrome.browser.omnibox.OmniboxSuggestionType;
import org.chromium.chrome.browser.omnibox.suggestions.OmniboxSuggestion;
import org.chromium.chrome.browser.omnibox.suggestions.OmniboxSuggestionUiType;
import org.chromium.chrome.browser.omnibox.suggestions.base.BaseSuggestionViewProcessor;
import org.chromium.chrome.browser.omnibox.suggestions.base.SuggestionDrawableState;
import org.chromium.chrome.browser.omnibox.suggestions.base.SuggestionSpannable;
import org.chromium.chrome.browser.omnibox.suggestions.basic.SuggestionHost;
import org.chromium.chrome.browser.omnibox.suggestions.basic.SuggestionViewProperties;
import org.chromium.ui.modelutil.PropertyModel;
/** A class that handles model and view creation for the clipboard suggestions. */
public class ClipboardSuggestionProcessor extends BaseSuggestionViewProcessor {
private final Context mContext;
private final Supplier<LargeIconBridge> mIconBridgeSupplier;
private final int mDesiredFaviconWidthPx;
/**
* @param context An Android context.
* @param suggestionHost A handle to the object using the suggestions.
* @param iconBridgeSupplier A {@link LargeIconBridge} supplies site favicons.
*/
public ClipboardSuggestionProcessor(Context context, SuggestionHost suggestionHost,
Supplier<LargeIconBridge> iconBridgeSupplier) {
super(context, suggestionHost);
mContext = context;
mIconBridgeSupplier = iconBridgeSupplier;
mDesiredFaviconWidthPx = mContext.getResources().getDimensionPixelSize(
R.dimen.omnibox_suggestion_favicon_size);
}
@Override
public boolean doesProcessSuggestion(OmniboxSuggestion suggestion) {
return suggestion.getType() == OmniboxSuggestionType.CLIPBOARD_URL
|| suggestion.getType() == OmniboxSuggestionType.CLIPBOARD_TEXT
|| suggestion.getType() == OmniboxSuggestionType.CLIPBOARD_IMAGE;
}
@Override
public int getViewTypeId() {
return OmniboxSuggestionUiType.CLIPBOARD_SUGGESTION;
}
@Override
public PropertyModel createModelForSuggestion(OmniboxSuggestion suggestion) {
return new PropertyModel(SuggestionViewProperties.ALL_KEYS);
}
@Override
protected boolean canRefine(OmniboxSuggestion suggestion) {
return false;
}
@Override
public void populateModel(OmniboxSuggestion suggestion, PropertyModel model, int position) {
super.populateModel(suggestion, model, position);
boolean isUrlSuggestion = suggestion.getType() == OmniboxSuggestionType.CLIPBOARD_URL;
model.set(SuggestionViewProperties.IS_SEARCH_SUGGESTION, !isUrlSuggestion);
model.set(SuggestionViewProperties.TEXT_LINE_1_TEXT,
new SuggestionSpannable(suggestion.getDescription()));
model.set(SuggestionViewProperties.TEXT_LINE_2_TEXT,
new SuggestionSpannable(suggestion.getDisplayText()));
@DrawableRes
final int icon =
isUrlSuggestion ? R.drawable.ic_globe_24dp : R.drawable.ic_suggestion_magnifier;
setSuggestionDrawableState(model,
SuggestionDrawableState.Builder.forDrawableRes(mContext, icon)
.setAllowTint(true)
.build());
if (isUrlSuggestion) {
// Update favicon for URL if it is available.
fetchSuggestionFavicon(model, suggestion.getUrl(), mIconBridgeSupplier.get(), null);
}
}
}
// Copyright 2020 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.suggestions.base;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.verify;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
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.robolectric.annotation.Config;
import org.chromium.chrome.browser.favicon.LargeIconBridge;
import org.chromium.chrome.browser.favicon.LargeIconBridge.LargeIconCallback;
import org.chromium.chrome.browser.omnibox.OmniboxSuggestionType;
import org.chromium.chrome.browser.omnibox.suggestions.OmniboxSuggestion;
import org.chromium.chrome.browser.omnibox.suggestions.OmniboxSuggestionUiType;
import org.chromium.chrome.browser.omnibox.suggestions.basic.SuggestionHost;
import org.chromium.testing.local.LocalRobolectricTestRunner;
import org.chromium.ui.modelutil.PropertyModel;
import java.util.ArrayList;
/**
* Tests for {@link BaseSuggestionViewProcessor}.
*/
@RunWith(LocalRobolectricTestRunner.class)
@Config(manifest = Config.NONE)
public class BaseSuggestionProcessorTest {
private class TestBaseSuggestionProcessor extends BaseSuggestionViewProcessor {
private final Context mContext;
private final LargeIconBridge mLargeIconBridge;
private final Runnable mRunable;
public TestBaseSuggestionProcessor(Context context, SuggestionHost suggestionHost,
LargeIconBridge largeIconBridge, Runnable runable) {
super(context, suggestionHost);
mContext = context;
mLargeIconBridge = largeIconBridge;
mRunable = runable;
}
@Override
public PropertyModel createModelForSuggestion(OmniboxSuggestion suggestion) {
return new PropertyModel(BaseSuggestionViewProperties.ALL_KEYS);
}
@Override
public boolean doesProcessSuggestion(OmniboxSuggestion suggestion) {
return true;
}
@Override
public int getViewTypeId() {
return OmniboxSuggestionUiType.DEFAULT;
}
@Override
public void populateModel(OmniboxSuggestion suggestion, PropertyModel model, int position) {
super.populateModel(suggestion, model, position);
setSuggestionDrawableState(model,
SuggestionDrawableState.Builder.forBitmap(mContext, mFakeDefaultBitmap)
.build());
fetchSuggestionFavicon(model, suggestion.getUrl(), mLargeIconBridge, mRunable);
}
}
@Mock
SuggestionHost mSuggestionHost;
@Mock
LargeIconBridge mIconBridge;
@Mock
Runnable mRunnable;
@Mock
Bitmap mFakeBitmap;
@Mock
Bitmap mFakeDefaultBitmap;
private Activity mActivity;
private TestBaseSuggestionProcessor mProcessor;
private OmniboxSuggestion mSuggestion;
private PropertyModel mModel;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mActivity = Robolectric.buildActivity(Activity.class).setup().get();
mProcessor =
new TestBaseSuggestionProcessor(mActivity, mSuggestionHost, mIconBridge, mRunnable);
}
/**
* Create Suggestion for test.
*/
private void createSuggestion(int type, String url) {
mSuggestion = new OmniboxSuggestion(type,
/* isSearchType */ false, /* relevance */ 0, /* transition */ 0, "title",
/* displayTextClassifications */ new ArrayList<>(), "description",
/* descriptionClassifications */ new ArrayList<>(),
/* suggestionAnswer */ null, /* fillIntoEdit */ null, url,
/* imageUrl */ "", /* imageDominantColor */ "", false,
/* isDeletable */ false);
mModel = mProcessor.createModelForSuggestion(mSuggestion);
mProcessor.populateModel(mSuggestion, mModel, 0);
}
@Test
public void suggestionFavicons_showFaviconWhenAvailable() {
final ArgumentCaptor<LargeIconCallback> callback =
ArgumentCaptor.forClass(LargeIconCallback.class);
final String url = "http://url";
createSuggestion(OmniboxSuggestionType.URL_WHAT_YOU_TYPED, url);
SuggestionDrawableState icon1 = mModel.get(BaseSuggestionViewProperties.ICON);
Assert.assertNotNull(icon1);
verify(mIconBridge).getLargeIconForStringUrl(eq(url), anyInt(), callback.capture());
callback.getValue().onLargeIconAvailable(mFakeBitmap, 0, false, 0);
SuggestionDrawableState icon2 = mModel.get(BaseSuggestionViewProperties.ICON);
Assert.assertNotNull(icon2);
Assert.assertNotEquals(icon1, icon2);
Assert.assertEquals(mFakeBitmap, ((BitmapDrawable) icon2.drawable).getBitmap());
}
@Test
public void suggestionFavicons_doNotReplaceFallbackIconWhenNoFaviconIsAvailable() {
final ArgumentCaptor<LargeIconCallback> callback =
ArgumentCaptor.forClass(LargeIconCallback.class);
final String url = "http://url";
createSuggestion(OmniboxSuggestionType.URL_WHAT_YOU_TYPED, url);
SuggestionDrawableState icon1 = mModel.get(BaseSuggestionViewProperties.ICON);
Assert.assertNotNull(icon1);
verify(mIconBridge).getLargeIconForStringUrl(eq(url), anyInt(), callback.capture());
callback.getValue().onLargeIconAvailable(null, 0, false, 0);
SuggestionDrawableState icon2 = mModel.get(BaseSuggestionViewProperties.ICON);
Assert.assertNotNull(icon2);
Assert.assertEquals(icon1, icon2);
}
}
...@@ -91,12 +91,9 @@ public class BasicSuggestionProcessorTest { ...@@ -91,12 +91,9 @@ public class BasicSuggestionProcessorTest {
put(OmniboxSuggestionType.SEARCH_SUGGEST_PROFILE, "SEARCH_SUGGEST_PROFILE"); put(OmniboxSuggestionType.SEARCH_SUGGEST_PROFILE, "SEARCH_SUGGEST_PROFILE");
put(OmniboxSuggestionType.SEARCH_OTHER_ENGINE, "SEARCH_OTHER_ENGINE"); put(OmniboxSuggestionType.SEARCH_OTHER_ENGINE, "SEARCH_OTHER_ENGINE");
put(OmniboxSuggestionType.NAVSUGGEST_PERSONALIZED, "NAVSUGGEST_PERSONALIZED"); put(OmniboxSuggestionType.NAVSUGGEST_PERSONALIZED, "NAVSUGGEST_PERSONALIZED");
put(OmniboxSuggestionType.CLIPBOARD_URL, "CLIPBOARD_URL");
put(OmniboxSuggestionType.VOICE_SUGGEST, "VOICE_SUGGEST"); put(OmniboxSuggestionType.VOICE_SUGGEST, "VOICE_SUGGEST");
put(OmniboxSuggestionType.DOCUMENT_SUGGESTION, "DOCUMENT_SUGGESTION"); put(OmniboxSuggestionType.DOCUMENT_SUGGESTION, "DOCUMENT_SUGGESTION");
put(OmniboxSuggestionType.PEDAL, "PEDAL"); put(OmniboxSuggestionType.PEDAL, "PEDAL");
put(OmniboxSuggestionType.CLIPBOARD_TEXT, "CLIPBOARD_TEXT");
put(OmniboxSuggestionType.CLIPBOARD_IMAGE, "CLIPBOARD_IMAGE");
// Note: CALCULATOR suggestions are not handled by basic suggestion processor. // Note: CALCULATOR suggestions are not handled by basic suggestion processor.
// These suggestions are now processed by AnswerSuggestionProcessor instead. // These suggestions are now processed by AnswerSuggestionProcessor instead.
} }
...@@ -188,12 +185,9 @@ public class BasicSuggestionProcessorTest { ...@@ -188,12 +185,9 @@ public class BasicSuggestionProcessorTest {
{OmniboxSuggestionType.SEARCH_SUGGEST_PROFILE, SuggestionIcon.MAGNIFIER}, {OmniboxSuggestionType.SEARCH_SUGGEST_PROFILE, SuggestionIcon.MAGNIFIER},
{OmniboxSuggestionType.SEARCH_OTHER_ENGINE, SuggestionIcon.MAGNIFIER}, {OmniboxSuggestionType.SEARCH_OTHER_ENGINE, SuggestionIcon.MAGNIFIER},
{OmniboxSuggestionType.NAVSUGGEST_PERSONALIZED, SuggestionIcon.MAGNIFIER}, {OmniboxSuggestionType.NAVSUGGEST_PERSONALIZED, SuggestionIcon.MAGNIFIER},
{OmniboxSuggestionType.CLIPBOARD_URL, SuggestionIcon.MAGNIFIER},
{OmniboxSuggestionType.VOICE_SUGGEST, SuggestionIcon.VOICE}, {OmniboxSuggestionType.VOICE_SUGGEST, SuggestionIcon.VOICE},
{OmniboxSuggestionType.DOCUMENT_SUGGESTION, SuggestionIcon.MAGNIFIER}, {OmniboxSuggestionType.DOCUMENT_SUGGESTION, SuggestionIcon.MAGNIFIER},
{OmniboxSuggestionType.PEDAL, SuggestionIcon.MAGNIFIER}, {OmniboxSuggestionType.PEDAL, SuggestionIcon.MAGNIFIER},
{OmniboxSuggestionType.CLIPBOARD_TEXT, SuggestionIcon.MAGNIFIER},
{OmniboxSuggestionType.CLIPBOARD_IMAGE, SuggestionIcon.MAGNIFIER},
}; };
mProcessor.onNativeInitialized(); mProcessor.onNativeInitialized();
...@@ -223,7 +217,6 @@ public class BasicSuggestionProcessorTest { ...@@ -223,7 +217,6 @@ public class BasicSuggestionProcessorTest {
{OmniboxSuggestionType.SEARCH_SUGGEST_PROFILE, SuggestionIcon.GLOBE}, {OmniboxSuggestionType.SEARCH_SUGGEST_PROFILE, SuggestionIcon.GLOBE},
{OmniboxSuggestionType.SEARCH_OTHER_ENGINE, SuggestionIcon.GLOBE}, {OmniboxSuggestionType.SEARCH_OTHER_ENGINE, SuggestionIcon.GLOBE},
{OmniboxSuggestionType.NAVSUGGEST_PERSONALIZED, SuggestionIcon.GLOBE}, {OmniboxSuggestionType.NAVSUGGEST_PERSONALIZED, SuggestionIcon.GLOBE},
{OmniboxSuggestionType.CLIPBOARD_URL, SuggestionIcon.GLOBE},
{OmniboxSuggestionType.VOICE_SUGGEST, SuggestionIcon.GLOBE}, {OmniboxSuggestionType.VOICE_SUGGEST, SuggestionIcon.GLOBE},
{OmniboxSuggestionType.DOCUMENT_SUGGESTION, SuggestionIcon.GLOBE}, {OmniboxSuggestionType.DOCUMENT_SUGGESTION, SuggestionIcon.GLOBE},
{OmniboxSuggestionType.PEDAL, SuggestionIcon.GLOBE}, {OmniboxSuggestionType.PEDAL, SuggestionIcon.GLOBE},
...@@ -256,7 +249,6 @@ public class BasicSuggestionProcessorTest { ...@@ -256,7 +249,6 @@ public class BasicSuggestionProcessorTest {
{OmniboxSuggestionType.SEARCH_SUGGEST_PROFILE, SuggestionIcon.BOOKMARK}, {OmniboxSuggestionType.SEARCH_SUGGEST_PROFILE, SuggestionIcon.BOOKMARK},
{OmniboxSuggestionType.SEARCH_OTHER_ENGINE, SuggestionIcon.BOOKMARK}, {OmniboxSuggestionType.SEARCH_OTHER_ENGINE, SuggestionIcon.BOOKMARK},
{OmniboxSuggestionType.NAVSUGGEST_PERSONALIZED, SuggestionIcon.BOOKMARK}, {OmniboxSuggestionType.NAVSUGGEST_PERSONALIZED, SuggestionIcon.BOOKMARK},
{OmniboxSuggestionType.CLIPBOARD_URL, SuggestionIcon.BOOKMARK},
{OmniboxSuggestionType.VOICE_SUGGEST, SuggestionIcon.BOOKMARK}, {OmniboxSuggestionType.VOICE_SUGGEST, SuggestionIcon.BOOKMARK},
{OmniboxSuggestionType.DOCUMENT_SUGGESTION, SuggestionIcon.BOOKMARK}, {OmniboxSuggestionType.DOCUMENT_SUGGESTION, SuggestionIcon.BOOKMARK},
{OmniboxSuggestionType.PEDAL, SuggestionIcon.BOOKMARK}, {OmniboxSuggestionType.PEDAL, SuggestionIcon.BOOKMARK},
......
// Copyright 2020 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.suggestions.clipboard;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.Activity;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.view.View;
import android.widget.TextView;
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.robolectric.annotation.Config;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.favicon.LargeIconBridge;
import org.chromium.chrome.browser.favicon.LargeIconBridge.LargeIconCallback;
import org.chromium.chrome.browser.omnibox.OmniboxSuggestionType;
import org.chromium.chrome.browser.omnibox.suggestions.OmniboxSuggestion;
import org.chromium.chrome.browser.omnibox.suggestions.SuggestionCommonProperties;
import org.chromium.chrome.browser.omnibox.suggestions.base.BaseSuggestionViewProperties;
import org.chromium.chrome.browser.omnibox.suggestions.base.SuggestionDrawableState;
import org.chromium.chrome.browser.omnibox.suggestions.basic.SuggestionHost;
import org.chromium.chrome.browser.omnibox.suggestions.basic.SuggestionViewProperties;
import org.chromium.chrome.browser.omnibox.suggestions.basic.SuggestionViewViewBinder;
import org.chromium.testing.local.LocalRobolectricTestRunner;
import org.chromium.ui.modelutil.PropertyModel;
import java.util.ArrayList;
/**
* Tests for {@link ClipboardSuggestionProcessor}.
*/
@RunWith(LocalRobolectricTestRunner.class)
@Config(manifest = Config.NONE)
public class ClipboardSuggestionProcessorTest {
private static final String TEST_URL = "http://url";
private static final String ARABIC_URL = "http://site.com/مرحبا/123";
private static final String ARABIC_STRING = "مرحبامرحبامرحبا";
@Mock
SuggestionHost mSuggestionHost;
@Mock
LargeIconBridge mIconBridge;
@Mock
Bitmap mFakeBitmap;
@Mock
View mRootView;
@Mock
TextView mTitleTextView;
@Mock
TextView mContentTextView;
@Mock
Resources mResources;
private Activity mActivity;
private ClipboardSuggestionProcessor mProcessor;
private OmniboxSuggestion mSuggestion;
private PropertyModel mModel;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mActivity = Robolectric.buildActivity(Activity.class).setup().get();
mProcessor =
new ClipboardSuggestionProcessor(mActivity, mSuggestionHost, () -> mIconBridge);
when(mRootView.getContext()).thenReturn(mActivity);
when(mRootView.findViewById(R.id.line_1)).thenReturn(mTitleTextView);
when(mRootView.findViewById(R.id.line_2)).thenReturn(mContentTextView);
when(mRootView.getResources()).thenReturn(mResources);
}
/** Create clipboard suggestion for test. */
private void createClipboardSuggestion(int type, String url) {
mSuggestion = new OmniboxSuggestion(type,
/* isSearchType */ type != OmniboxSuggestionType.CLIPBOARD_URL, /* relevance */ 0,
/* transition */ 0, "test title",
/* displayTextClassifications */ new ArrayList<>(), "test description",
/* descriptionClassifications */ new ArrayList<>(),
/* suggestionAnswer */ null, /* fillIntoEdit */ null, url,
/* imageUrl */ "", /* imageDominantColor */ "", false,
/* isDeletable */ false);
mModel = mProcessor.createModelForSuggestion(mSuggestion);
mProcessor.populateModel(mSuggestion, mModel, 0);
SuggestionViewViewBinder.bind(mModel, mRootView, SuggestionViewProperties.TEXT_LINE_1_TEXT);
SuggestionViewViewBinder.bind(
mModel, mRootView, SuggestionCommonProperties.USE_DARK_COLORS);
SuggestionViewViewBinder.bind(
mModel, mRootView, SuggestionViewProperties.IS_SEARCH_SUGGESTION);
SuggestionViewViewBinder.bind(mModel, mRootView, SuggestionViewProperties.TEXT_LINE_2_TEXT);
}
@Test
public void clipboardSugestion_identifyUrlSuggestion() {
createClipboardSuggestion(OmniboxSuggestionType.CLIPBOARD_URL, "");
Assert.assertFalse(mModel.get(SuggestionViewProperties.IS_SEARCH_SUGGESTION));
createClipboardSuggestion(OmniboxSuggestionType.CLIPBOARD_TEXT, "");
Assert.assertTrue(mModel.get(SuggestionViewProperties.IS_SEARCH_SUGGESTION));
createClipboardSuggestion(OmniboxSuggestionType.CLIPBOARD_IMAGE, "");
Assert.assertTrue(mModel.get(SuggestionViewProperties.IS_SEARCH_SUGGESTION));
}
@Test
public void clipboardSuggestion_doesNotRefine() {
createClipboardSuggestion(OmniboxSuggestionType.CLIPBOARD_URL, "");
Assert.assertFalse(mProcessor.canRefine(mSuggestion));
createClipboardSuggestion(OmniboxSuggestionType.CLIPBOARD_TEXT, "");
Assert.assertFalse(mProcessor.canRefine(mSuggestion));
createClipboardSuggestion(OmniboxSuggestionType.CLIPBOARD_IMAGE, "");
Assert.assertFalse(mProcessor.canRefine(mSuggestion));
}
@Test
public void clipboardSuggestion_showsFaviconWhenAvailable() {
final ArgumentCaptor<LargeIconCallback> callback =
ArgumentCaptor.forClass(LargeIconCallback.class);
createClipboardSuggestion(OmniboxSuggestionType.CLIPBOARD_URL, TEST_URL);
SuggestionDrawableState icon1 = mModel.get(BaseSuggestionViewProperties.ICON);
Assert.assertNotNull(icon1);
verify(mIconBridge).getLargeIconForStringUrl(eq(TEST_URL), anyInt(), callback.capture());
callback.getValue().onLargeIconAvailable(mFakeBitmap, 0, false, 0);
SuggestionDrawableState icon2 = mModel.get(BaseSuggestionViewProperties.ICON);
Assert.assertNotNull(icon2);
Assert.assertNotEquals(icon1, icon2);
Assert.assertEquals(mFakeBitmap, ((BitmapDrawable) icon2.drawable).getBitmap());
}
@Test
public void clipboardSuggestion_showsFallbackIconWhenNoFaviconIsAvailable() {
final ArgumentCaptor<LargeIconCallback> callback =
ArgumentCaptor.forClass(LargeIconCallback.class);
createClipboardSuggestion(OmniboxSuggestionType.CLIPBOARD_URL, TEST_URL);
SuggestionDrawableState icon1 = mModel.get(BaseSuggestionViewProperties.ICON);
Assert.assertNotNull(icon1);
verify(mIconBridge).getLargeIconForStringUrl(eq(TEST_URL), anyInt(), callback.capture());
callback.getValue().onLargeIconAvailable(null, 0, false, 0);
SuggestionDrawableState icon2 = mModel.get(BaseSuggestionViewProperties.ICON);
Assert.assertNotNull(icon2);
Assert.assertEquals(icon1, icon2);
}
@Test
public void clipobardSuggestion_urlAndTextDirection() {
final ArgumentCaptor<LargeIconCallback> callback =
ArgumentCaptor.forClass(LargeIconCallback.class);
// URL
createClipboardSuggestion(OmniboxSuggestionType.CLIPBOARD_URL, ARABIC_URL);
Assert.assertFalse(mModel.get(SuggestionViewProperties.IS_SEARCH_SUGGESTION));
verify(mIconBridge).getLargeIconForStringUrl(eq(ARABIC_URL), anyInt(), callback.capture());
callback.getValue().onLargeIconAvailable(null, 0, false, 0);
verify(mContentTextView).setTextDirection(eq(TextView.TEXT_DIRECTION_LTR));
// Text
createClipboardSuggestion(OmniboxSuggestionType.CLIPBOARD_TEXT, "");
verify(mContentTextView).setTextDirection(eq(TextView.TEXT_DIRECTION_INHERIT));
}
}
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