Commit 2f6398f8 authored by Filip Gorski's avatar Filip Gorski Committed by Commit Bot

[Omnibox][Incognito] Fix theme leaking in Incognito suggestions list

Adds a ripple definition specific to Incognito and changes where the
selectable background is applied to DecoratedSuggestionView and action
buttons.

We logically have 3 possible sources of selection colors now:
* Device light theme based
* Device dark theme based
* Incognito based (very similar to dark theme, but does not leak
  attributes).

To better manage the 3 possible states this patch introduces
OmniboxTheme with values { LIGHT_MODE, DARK_MODE, INCOGNITO }.

To better resolve attribute values for the OmniboxTheme, this patch
introduces OmniboxResourceProvider.

All changes appropriately update USE_DARK_COLORS model property to
OMNIBOX_THEME.

Bug: 1103291
Change-Id: I14f276274b25b6afa51ed7fbc3661a5437c5b1d0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2288074
Commit-Queue: Krishna Govind <govind@chromium.org>
Reviewed-by: default avatarTed Choc <tedchoc@chromium.org>
Reviewed-by: Ender 💬 = 🕐 (ping me for faster reviews) <ender@google.com>
Reviewed-by: default avatarLijin Shen <lazzzis@google.com>
Cr-Commit-Position: refs/heads/master@{#791375}
parent 77a51f9a
...@@ -1109,6 +1109,8 @@ chrome_java_sources = [ ...@@ -1109,6 +1109,8 @@ chrome_java_sources = [
"java/src/org/chromium/chrome/browser/omnibox/status/StatusView.java", "java/src/org/chromium/chrome/browser/omnibox/status/StatusView.java",
"java/src/org/chromium/chrome/browser/omnibox/status/StatusViewBinder.java", "java/src/org/chromium/chrome/browser/omnibox/status/StatusViewBinder.java",
"java/src/org/chromium/chrome/browser/omnibox/status/StatusViewCoordinator.java", "java/src/org/chromium/chrome/browser/omnibox/status/StatusViewCoordinator.java",
"java/src/org/chromium/chrome/browser/omnibox/styles/OmniboxResourceProvider.java",
"java/src/org/chromium/chrome/browser/omnibox/styles/OmniboxTheme.java",
"java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteController.java", "java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteController.java",
"java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinator.java", "java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinator.java",
"java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinatorFactory.java", "java/src/org/chromium/chrome/browser/omnibox/suggestions/AutocompleteCoordinatorFactory.java",
......
...@@ -171,6 +171,7 @@ chrome_junit_test_java_sources = [ ...@@ -171,6 +171,7 @@ chrome_junit_test_java_sources = [
"junit/src/org/chromium/chrome/browser/omnibox/geo/PlatformNetworksManagerTest.java", "junit/src/org/chromium/chrome/browser/omnibox/geo/PlatformNetworksManagerTest.java",
"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/styles/OmniboxResourceProviderTest.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",
......
// 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.styles;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.util.TypedValue;
import androidx.annotation.DrawableRes;
import androidx.core.content.ContextCompat;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.night_mode.NightModeUtils;
/** Provides resources specific to Omnibox. */
public class OmniboxResourceProvider {
/**
* Provides {@link OmniboxTheme} appropriate for the current UI, specifically whether we are
* showing incognito and if not which theme is selected.
*
* @param useDarkColors whether UI Theme is dark or not.
* @param isIncognito Whether the Omnibox is shown in incognito at the moment.
* @return {@link OmniboxTheme} matching the provided parameters.
*/
public static @OmniboxTheme int getThemeFromDarkColorsAndIncognito(
boolean useDarkColors, boolean isIncognito) {
if (isIncognito) return OmniboxTheme.INCOGNITO;
if (useDarkColors) return OmniboxTheme.LIGHT_THEME;
return OmniboxTheme.DARK_THEME;
}
/** @return Whether the mode is dark (dark theme or incognito). */
public static boolean isDarkMode(@OmniboxTheme int omniboxTheme) {
return omniboxTheme == OmniboxTheme.DARK_THEME || omniboxTheme == OmniboxTheme.INCOGNITO;
}
/**
* Returns a drawable for a given attribute depending on a {@link OmniboxTheme}
*
* @param context The {@link Context} used to retrieve resources.
* @param omniboxTheme {@link OmniboxTheme} to use.
* @param attributeResId A resource ID of an attribute to resolve.
* @return A background drawable resource ID providing ripple effect.
*/
public static Drawable resolveAttributeToDrawable(
Context context, @OmniboxTheme int omniboxTheme, int attributeResId) {
Context wrappedContext = maybeWrapContext(context, omniboxTheme);
@DrawableRes
int resourceId = resolveAttributeToDrawableRes(wrappedContext, attributeResId);
return ContextCompat.getDrawable(wrappedContext, resourceId);
}
/**
* Wraps the context if necessary to force dark resources for incognito.
*
* @param context The {@link Context} to be wrapped.
* @param omniboxTheme Current omnibox theme.
* @return Context with resources appropriate to the {@link OmniboxTheme}.
*/
private static Context maybeWrapContext(Context context, @OmniboxTheme int omniboxTheme) {
// Only wraps the context in case of incognito.
if (omniboxTheme == OmniboxTheme.INCOGNITO) {
return NightModeUtils.wrapContextWithNightModeConfig(
context, R.style.Theme_Chromium_TabbedMode, /*nightMode=*/true);
}
return context;
}
/**
* Resolves the attribute based on the current theme.
*
* @param context The {@link Context} used to retrieve resources.
* @param attributeResId Resource ID of the attribute to resolve.
* @return Resource ID of the expected drawable.
*/
private static @DrawableRes int resolveAttributeToDrawableRes(
Context context, int attributeResId) {
TypedValue themeRes = new TypedValue();
context.getTheme().resolveAttribute(attributeResId, themeRes, true);
return themeRes.resourceId;
}
}
// 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.styles;
import androidx.annotation.IntDef;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@IntDef({OmniboxTheme.LIGHT_THEME, OmniboxTheme.DARK_THEME, OmniboxTheme.INCOGNITO})
@Retention(RetentionPolicy.SOURCE)
public @interface OmniboxTheme {
int LIGHT_THEME = 0;
int DARK_THEME = 1;
int INCOGNITO = 2;
}
...@@ -41,6 +41,8 @@ import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher; ...@@ -41,6 +41,8 @@ import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
import org.chromium.chrome.browser.lifecycle.StartStopWithNativeObserver; import org.chromium.chrome.browser.lifecycle.StartStopWithNativeObserver;
import org.chromium.chrome.browser.omnibox.OmniboxSuggestionType; import org.chromium.chrome.browser.omnibox.OmniboxSuggestionType;
import org.chromium.chrome.browser.omnibox.UrlBarEditingTextStateProvider; import org.chromium.chrome.browser.omnibox.UrlBarEditingTextStateProvider;
import org.chromium.chrome.browser.omnibox.styles.OmniboxResourceProvider;
import org.chromium.chrome.browser.omnibox.styles.OmniboxTheme;
import org.chromium.chrome.browser.omnibox.suggestions.AutocompleteController.OnSuggestionsReceivedListener; import org.chromium.chrome.browser.omnibox.suggestions.AutocompleteController.OnSuggestionsReceivedListener;
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;
...@@ -308,7 +310,10 @@ class AutocompleteMediator implements OnSuggestionsReceivedListener, StartStopWi ...@@ -308,7 +310,10 @@ class AutocompleteMediator implements OnSuggestionsReceivedListener, StartStopWi
* @param isIncognito Whether the UI is for incognito mode or not. * @param isIncognito Whether the UI is for incognito mode or not.
*/ */
void updateVisualsForState(boolean useDarkColors, boolean isIncognito) { void updateVisualsForState(boolean useDarkColors, boolean isIncognito) {
mDropdownViewInfoListManager.setUseDarkColors(useDarkColors); @OmniboxTheme
int omniboxTheme = OmniboxResourceProvider.getThemeFromDarkColorsAndIncognito(
useDarkColors, isIncognito);
mDropdownViewInfoListManager.setOmniboxTheme(omniboxTheme);
mListPropertyModel.set(SuggestionListProperties.IS_INCOGNITO, isIncognito); mListPropertyModel.set(SuggestionListProperties.IS_INCOGNITO, isIncognito);
} }
......
...@@ -10,6 +10,7 @@ import android.view.View; ...@@ -10,6 +10,7 @@ import android.view.View;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.metrics.RecordHistogram;
import org.chromium.chrome.browser.omnibox.styles.OmniboxTheme;
import org.chromium.ui.modelutil.MVCListAdapter.ModelList; import org.chromium.ui.modelutil.MVCListAdapter.ModelList;
import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModel;
...@@ -21,14 +22,14 @@ class DropdownItemViewInfoListManager { ...@@ -21,14 +22,14 @@ class DropdownItemViewInfoListManager {
private static final int OMNIBOX_HISTOGRAMS_MAX_SUGGESTIONS = 10; private static final int OMNIBOX_HISTOGRAMS_MAX_SUGGESTIONS = 10;
private final ModelList mManagedModel; private final ModelList mManagedModel;
private int mLayoutDirection; private int mLayoutDirection;
private boolean mUseDarkColors; private @OmniboxTheme int mOmniboxTheme;
private List<DropdownItemViewInfo> mSourceViewInfoList; private List<DropdownItemViewInfo> mSourceViewInfoList;
private SparseArray<Boolean> mGroupVisibility; private SparseArray<Boolean> mGroupVisibility;
DropdownItemViewInfoListManager(@NonNull ModelList managedModel) { DropdownItemViewInfoListManager(@NonNull ModelList managedModel) {
assert managedModel != null : "Must specify a non-null model."; assert managedModel != null : "Must specify a non-null model.";
mLayoutDirection = View.LAYOUT_DIRECTION_INHERIT; mLayoutDirection = View.LAYOUT_DIRECTION_INHERIT;
mUseDarkColors = true; mOmniboxTheme = OmniboxTheme.LIGHT_THEME;
mSourceViewInfoList = Collections.emptyList(); mSourceViewInfoList = Collections.emptyList();
mGroupVisibility = new SparseArray<>(); mGroupVisibility = new SparseArray<>();
mManagedModel = managedModel; mManagedModel = managedModel;
...@@ -54,16 +55,16 @@ class DropdownItemViewInfoListManager { ...@@ -54,16 +55,16 @@ class DropdownItemViewInfoListManager {
} }
/** /**
* Specifies the visual state to be used by the suggestions. * Specifies the visual theme to be used by the suggestions.
* @param useDarkColors Whether dark colors should be used for fonts and icons. * @param omniboxTheme Specifies which {@link OmniboxTheme} should be used.
*/ */
void setUseDarkColors(boolean useDarkColors) { void setOmniboxTheme(@OmniboxTheme int omniboxTheme) {
if (mUseDarkColors == useDarkColors) return; if (mOmniboxTheme == omniboxTheme) return;
mUseDarkColors = useDarkColors; mOmniboxTheme = omniboxTheme;
for (int i = 0; i < mSourceViewInfoList.size(); i++) { for (int i = 0; i < mSourceViewInfoList.size(); i++) {
PropertyModel model = mSourceViewInfoList.get(i).model; PropertyModel model = mSourceViewInfoList.get(i).model;
model.set(SuggestionCommonProperties.USE_DARK_COLORS, useDarkColors); model.set(SuggestionCommonProperties.OMNIBOX_THEME, omniboxTheme);
} }
} }
...@@ -134,7 +135,7 @@ class DropdownItemViewInfoListManager { ...@@ -134,7 +135,7 @@ class DropdownItemViewInfoListManager {
for (int i = 0; i < mSourceViewInfoList.size(); i++) { for (int i = 0; i < mSourceViewInfoList.size(); i++) {
PropertyModel model = mSourceViewInfoList.get(i).model; PropertyModel model = mSourceViewInfoList.get(i).model;
model.set(SuggestionCommonProperties.LAYOUT_DIRECTION, mLayoutDirection); model.set(SuggestionCommonProperties.LAYOUT_DIRECTION, mLayoutDirection);
model.set(SuggestionCommonProperties.USE_DARK_COLORS, mUseDarkColors); model.set(SuggestionCommonProperties.OMNIBOX_THEME, mOmniboxTheme);
} }
// Note: Despite DropdownItemViewInfo extending ListItem, we can't use the // Note: Despite DropdownItemViewInfo extending ListItem, we can't use the
// List<DropdownItemViewInfo> as a parameter expecting a List<ListItem>. // List<DropdownItemViewInfo> as a parameter expecting a List<ListItem>.
......
...@@ -5,19 +5,17 @@ ...@@ -5,19 +5,17 @@
package org.chromium.chrome.browser.omnibox.suggestions; package org.chromium.chrome.browser.omnibox.suggestions;
import org.chromium.ui.modelutil.PropertyKey; import org.chromium.ui.modelutil.PropertyKey;
import org.chromium.ui.modelutil.PropertyModel.WritableBooleanPropertyKey;
import org.chromium.ui.modelutil.PropertyModel.WritableIntPropertyKey; import org.chromium.ui.modelutil.PropertyModel.WritableIntPropertyKey;
/** /**
* The set of common properties associated with any omnibox suggestion. * The set of common properties associated with any omnibox suggestion.
*/ */
public class SuggestionCommonProperties { public class SuggestionCommonProperties {
/** Whether dark colors should be applied to text, icons */ /** Whether dark colors should be applied to text, icons. */
public static final WritableBooleanPropertyKey USE_DARK_COLORS = public static final WritableIntPropertyKey OMNIBOX_THEME = new WritableIntPropertyKey();
new WritableBooleanPropertyKey();
/** The layout direction to be applied to the entire suggestion view. */ /** The layout direction to be applied to the entire suggestion view. */
public static final WritableIntPropertyKey LAYOUT_DIRECTION = new WritableIntPropertyKey(); public static final WritableIntPropertyKey LAYOUT_DIRECTION = new WritableIntPropertyKey();
public static final PropertyKey[] ALL_KEYS = public static final PropertyKey[] ALL_KEYS =
new PropertyKey[] {USE_DARK_COLORS, LAYOUT_DIRECTION}; new PropertyKey[] {OMNIBOX_THEME, LAYOUT_DIRECTION};
} }
...@@ -5,14 +5,12 @@ ...@@ -5,14 +5,12 @@
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.util.TypedValue;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View; import android.view.View;
import android.widget.ImageView; import android.widget.ImageView;
import androidx.annotation.DrawableRes;
import androidx.annotation.LayoutRes; import androidx.annotation.LayoutRes;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import androidx.appcompat.widget.AppCompatImageView; import androidx.appcompat.widget.AppCompatImageView;
...@@ -33,7 +31,6 @@ import java.util.List; ...@@ -33,7 +31,6 @@ import java.util.List;
*/ */
public class BaseSuggestionView<T extends View> extends SimpleHorizontalLayoutView { public class BaseSuggestionView<T extends View> extends SimpleHorizontalLayoutView {
private final List<ImageView> mActionButtons; private final List<ImageView> mActionButtons;
private final @DrawableRes int mSelectableBackgroundRes;
private final DecoratedSuggestionView<T> mDecoratedView; private final DecoratedSuggestionView<T> mDecoratedView;
private SuggestionViewDelegate mDelegate; private SuggestionViewDelegate mDelegate;
...@@ -45,11 +42,7 @@ public class BaseSuggestionView<T extends View> extends SimpleHorizontalLayoutVi ...@@ -45,11 +42,7 @@ public class BaseSuggestionView<T extends View> extends SimpleHorizontalLayoutVi
public BaseSuggestionView(T view) { public BaseSuggestionView(T view) {
super(view.getContext()); super(view.getContext());
TypedValue themeRes = new TypedValue(); mDecoratedView = new DecoratedSuggestionView<>(getContext());
getContext().getTheme().resolveAttribute(R.attr.selectableItemBackground, themeRes, true);
mSelectableBackgroundRes = themeRes.resourceId;
mDecoratedView = new DecoratedSuggestionView<>(getContext(), mSelectableBackgroundRes);
mDecoratedView.setOnClickListener(v -> mDelegate.onSelection()); mDecoratedView.setOnClickListener(v -> mDelegate.onSelection());
mDecoratedView.setOnLongClickListener(v -> { mDecoratedView.setOnLongClickListener(v -> {
mDelegate.onLongPress(); mDelegate.onLongPress();
...@@ -93,7 +86,6 @@ public class BaseSuggestionView<T extends View> extends SimpleHorizontalLayoutVi ...@@ -93,7 +86,6 @@ public class BaseSuggestionView<T extends View> extends SimpleHorizontalLayoutVi
private void increaseActionButtonsCount(int desiredViewCount) { private void increaseActionButtonsCount(int desiredViewCount) {
for (int index = mActionButtons.size(); index < desiredViewCount; index++) { for (int index = mActionButtons.size(); index < desiredViewCount; index++) {
ImageView actionView = new AppCompatImageView(getContext()); ImageView actionView = new AppCompatImageView(getContext());
actionView.setBackgroundResource(mSelectableBackgroundRes);
actionView.setClickable(true); actionView.setClickable(true);
actionView.setFocusable(true); actionView.setFocusable(true);
actionView.setScaleType(ImageView.ScaleType.CENTER); actionView.setScaleType(ImageView.ScaleType.CENTER);
...@@ -177,7 +169,7 @@ public class BaseSuggestionView<T extends View> extends SimpleHorizontalLayoutVi ...@@ -177,7 +169,7 @@ public class BaseSuggestionView<T extends View> extends SimpleHorizontalLayoutVi
} }
/** @return Decorated suggestion view. */ /** @return Decorated suggestion view. */
@VisibleForTesting @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
public DecoratedSuggestionView<T> getDecoratedSuggestionView() { public DecoratedSuggestionView<T> getDecoratedSuggestionView() {
return mDecoratedView; return mDecoratedView;
} }
......
...@@ -6,6 +6,7 @@ package org.chromium.chrome.browser.omnibox.suggestions.base; ...@@ -6,6 +6,7 @@ package org.chromium.chrome.browser.omnibox.suggestions.base;
import android.content.res.ColorStateList; import android.content.res.ColorStateList;
import android.content.res.Resources; import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.view.View; import android.view.View;
import android.widget.ImageView; import android.widget.ImageView;
...@@ -15,6 +16,7 @@ import androidx.core.view.ViewCompat; ...@@ -15,6 +16,7 @@ import androidx.core.view.ViewCompat;
import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.chrome.R; import org.chromium.chrome.R;
import org.chromium.chrome.browser.omnibox.styles.OmniboxResourceProvider;
import org.chromium.chrome.browser.omnibox.suggestions.SuggestionCommonProperties; import org.chromium.chrome.browser.omnibox.suggestions.SuggestionCommonProperties;
import org.chromium.chrome.browser.omnibox.suggestions.base.BaseSuggestionViewProperties.Action; import org.chromium.chrome.browser.omnibox.suggestions.base.BaseSuggestionViewProperties.Action;
import org.chromium.components.browser_ui.styles.ChromeColors; import org.chromium.components.browser_ui.styles.ChromeColors;
...@@ -57,7 +59,7 @@ public final class BaseSuggestionViewBinder<T extends View> ...@@ -57,7 +59,7 @@ public final class BaseSuggestionViewBinder<T extends View>
ViewCompat.setLayoutDirection( ViewCompat.setLayoutDirection(
view, model.get(SuggestionCommonProperties.LAYOUT_DIRECTION)); view, model.get(SuggestionCommonProperties.LAYOUT_DIRECTION));
updateContentViewPadding(model, view.getDecoratedSuggestionView()); updateContentViewPadding(model, view.getDecoratedSuggestionView());
} else if (SuggestionCommonProperties.USE_DARK_COLORS == propertyKey) { } else if (SuggestionCommonProperties.OMNIBOX_THEME == propertyKey) {
updateColorScheme(model, view); updateColorScheme(model, view);
} else if (BaseSuggestionViewProperties.ACTIONS == propertyKey) { } else if (BaseSuggestionViewProperties.ACTIONS == propertyKey) {
bindActionButtons(model, view, model.get(BaseSuggestionViewProperties.ACTIONS)); bindActionButtons(model, view, model.get(BaseSuggestionViewProperties.ACTIONS));
...@@ -78,7 +80,7 @@ public final class BaseSuggestionViewBinder<T extends View> ...@@ -78,7 +80,7 @@ public final class BaseSuggestionViewBinder<T extends View>
actionView.setContentDescription( actionView.setContentDescription(
view.getContext().getResources().getString(action.accessibilityDescription)); view.getContext().getResources().getString(action.accessibilityDescription));
updateIcon(actionView, action.icon, updateIcon(actionView, action.icon,
ChromeColors.getPrimaryIconTintRes(!isDarkMode(model))); ChromeColors.getPrimaryIconTintRes(!useDarkColors(model)));
} }
} }
...@@ -86,6 +88,10 @@ public final class BaseSuggestionViewBinder<T extends View> ...@@ -86,6 +88,10 @@ public final class BaseSuggestionViewBinder<T extends View>
private static <T extends View> void updateColorScheme( private static <T extends View> void updateColorScheme(
PropertyModel model, BaseSuggestionView<T> view) { PropertyModel model, BaseSuggestionView<T> view) {
updateSuggestionIcon(model, view); updateSuggestionIcon(model, view);
Drawable selectableBackgroundDrawable = OmniboxResourceProvider.resolveAttributeToDrawable(
view.getContext(), model.get(SuggestionCommonProperties.OMNIBOX_THEME),
R.attr.selectableItemBackground);
view.getDecoratedSuggestionView().setBackground(selectableBackgroundDrawable);
final List<Action> actions = model.get(BaseSuggestionViewProperties.ACTIONS); final List<Action> actions = model.get(BaseSuggestionViewProperties.ACTIONS);
// Setting ACTIONS and updating actionViews can happen later. Appropriate color scheme will // Setting ACTIONS and updating actionViews can happen later. Appropriate color scheme will
...@@ -94,14 +100,17 @@ public final class BaseSuggestionViewBinder<T extends View> ...@@ -94,14 +100,17 @@ public final class BaseSuggestionViewBinder<T extends View>
final List<ImageView> actionViews = view.getActionButtons(); final List<ImageView> actionViews = view.getActionButtons();
for (int index = 0; index < actionViews.size(); index++) { for (int index = 0; index < actionViews.size(); index++) {
updateIcon(actionViews.get(index), actions.get(index).icon, ImageView actionView = actionViews.get(index);
ChromeColors.getPrimaryIconTintRes(!isDarkMode(model))); actionView.setBackground(selectableBackgroundDrawable.getConstantState().newDrawable());
updateIcon(actionView, actions.get(index).icon,
ChromeColors.getPrimaryIconTintRes(!useDarkColors(model)));
} }
} }
/** Returns which color scheme should be used to tint drawables. */ /** @return Whether currently used color scheme is considered to be dark. */
private static boolean isDarkMode(PropertyModel model) { private static boolean useDarkColors(PropertyModel model) {
return model.get(SuggestionCommonProperties.USE_DARK_COLORS); return !OmniboxResourceProvider.isDarkMode(
model.get(SuggestionCommonProperties.OMNIBOX_THEME));
} }
/** Update attributes of decorated suggestion icon. */ /** Update attributes of decorated suggestion icon. */
...@@ -133,7 +142,7 @@ public final class BaseSuggestionViewBinder<T extends View> ...@@ -133,7 +142,7 @@ public final class BaseSuggestionViewBinder<T extends View>
rciv.setRoundedCorners(radius, radius, radius, radius); rciv.setRoundedCorners(radius, radius, radius, radius);
} }
updateIcon(rciv, sds, ChromeColors.getSecondaryIconTintRes(!isDarkMode(model))); updateIcon(rciv, sds, ChromeColors.getSecondaryIconTintRes(!useDarkColors(model)));
} }
/** /**
......
...@@ -9,8 +9,6 @@ import android.view.View; ...@@ -9,8 +9,6 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ImageView; import android.widget.ImageView;
import androidx.annotation.DrawableRes;
import org.chromium.chrome.R; import org.chromium.chrome.R;
import org.chromium.components.browser_ui.widget.RoundedCornerImageView; import org.chromium.components.browser_ui.widget.RoundedCornerImageView;
...@@ -25,12 +23,10 @@ class DecoratedSuggestionView<T extends View> extends SimpleHorizontalLayoutView ...@@ -25,12 +23,10 @@ class DecoratedSuggestionView<T extends View> extends SimpleHorizontalLayoutView
* Constructs a new suggestion view. * Constructs a new suggestion view.
* *
* @param context The context used to construct the suggestion view. * @param context The context used to construct the suggestion view.
* @param background Selectable background resource ID.
*/ */
DecoratedSuggestionView(Context context, @DrawableRes int background) { DecoratedSuggestionView(Context context) {
super(context); super(context);
setBackgroundResource(background);
setClickable(true); setClickable(true);
setFocusable(true); setFocusable(true);
......
...@@ -12,6 +12,7 @@ import androidx.annotation.ColorRes; ...@@ -12,6 +12,7 @@ import androidx.annotation.ColorRes;
import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.chrome.R; import org.chromium.chrome.R;
import org.chromium.chrome.browser.omnibox.styles.OmniboxResourceProvider;
import org.chromium.chrome.browser.omnibox.suggestions.SuggestionCommonProperties; import org.chromium.chrome.browser.omnibox.suggestions.SuggestionCommonProperties;
import org.chromium.chrome.browser.omnibox.suggestions.base.SuggestionSpannable; import org.chromium.chrome.browser.omnibox.suggestions.base.SuggestionSpannable;
import org.chromium.ui.modelutil.PropertyKey; import org.chromium.ui.modelutil.PropertyKey;
...@@ -24,7 +25,7 @@ public class SuggestionViewViewBinder { ...@@ -24,7 +25,7 @@ public class SuggestionViewViewBinder {
if (propertyKey == SuggestionViewProperties.TEXT_LINE_1_TEXT) { if (propertyKey == SuggestionViewProperties.TEXT_LINE_1_TEXT) {
TextView tv = view.findViewById(R.id.line_1); TextView tv = view.findViewById(R.id.line_1);
tv.setText(model.get(SuggestionViewProperties.TEXT_LINE_1_TEXT)); tv.setText(model.get(SuggestionViewProperties.TEXT_LINE_1_TEXT));
} else if (propertyKey == SuggestionCommonProperties.USE_DARK_COLORS) { } else if (propertyKey == SuggestionCommonProperties.OMNIBOX_THEME) {
updateSuggestionTextColor(view, model); updateSuggestionTextColor(view, model);
} else if (propertyKey == SuggestionViewProperties.IS_SEARCH_SUGGESTION) { } else if (propertyKey == SuggestionViewProperties.IS_SEARCH_SUGGESTION) {
updateSuggestionTextColor(view, model); updateSuggestionTextColor(view, model);
...@@ -52,7 +53,8 @@ public class SuggestionViewViewBinder { ...@@ -52,7 +53,8 @@ public class SuggestionViewViewBinder {
private static void updateSuggestionTextColor(View view, PropertyModel model) { private static void updateSuggestionTextColor(View view, PropertyModel model) {
final boolean isSearch = model.get(SuggestionViewProperties.IS_SEARCH_SUGGESTION); final boolean isSearch = model.get(SuggestionViewProperties.IS_SEARCH_SUGGESTION);
final boolean useDarkMode = model.get(SuggestionCommonProperties.USE_DARK_COLORS); final boolean useDarkMode = !OmniboxResourceProvider.isDarkMode(
model.get(SuggestionCommonProperties.OMNIBOX_THEME));
final TextView line1 = view.findViewById(R.id.line_1); final TextView line1 = view.findViewById(R.id.line_1);
final TextView line2 = view.findViewById(R.id.line_2); final TextView line2 = view.findViewById(R.id.line_2);
......
...@@ -9,6 +9,7 @@ import androidx.core.widget.TextViewCompat; ...@@ -9,6 +9,7 @@ import androidx.core.widget.TextViewCompat;
import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.chrome.R; import org.chromium.chrome.R;
import org.chromium.chrome.browser.omnibox.styles.OmniboxResourceProvider;
import org.chromium.chrome.browser.omnibox.suggestions.SuggestionCommonProperties; import org.chromium.chrome.browser.omnibox.suggestions.SuggestionCommonProperties;
import org.chromium.components.browser_ui.styles.ChromeColors; import org.chromium.components.browser_ui.styles.ChromeColors;
import org.chromium.ui.modelutil.PropertyKey; import org.chromium.ui.modelutil.PropertyKey;
...@@ -20,8 +21,9 @@ public class HeaderViewBinder { ...@@ -20,8 +21,9 @@ public class HeaderViewBinder {
public static void bind(PropertyModel model, HeaderView view, PropertyKey propertyKey) { public static void bind(PropertyModel model, HeaderView view, PropertyKey propertyKey) {
if (HeaderViewProperties.TITLE == propertyKey) { if (HeaderViewProperties.TITLE == propertyKey) {
view.getTextView().setText(model.get(HeaderViewProperties.TITLE)); view.getTextView().setText(model.get(HeaderViewProperties.TITLE));
} else if (propertyKey == SuggestionCommonProperties.USE_DARK_COLORS) { } else if (propertyKey == SuggestionCommonProperties.OMNIBOX_THEME) {
final boolean useDarkColors = model.get(SuggestionCommonProperties.USE_DARK_COLORS); final boolean useDarkColors = !OmniboxResourceProvider.isDarkMode(
model.get(SuggestionCommonProperties.OMNIBOX_THEME));
TextViewCompat.setTextAppearance( TextViewCompat.setTextAppearance(
view.getTextView(), ChromeColors.getMediumTextSecondaryStyle(!useDarkColors)); view.getTextView(), ChromeColors.getMediumTextSecondaryStyle(!useDarkColors));
ApiCompatibilityUtils.setImageTintList(view.getIconView(), ApiCompatibilityUtils.setImageTintList(view.getIconView(),
......
...@@ -8,6 +8,7 @@ import androidx.annotation.ColorRes; ...@@ -8,6 +8,7 @@ import androidx.annotation.ColorRes;
import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.chrome.R; import org.chromium.chrome.R;
import org.chromium.chrome.browser.omnibox.styles.OmniboxResourceProvider;
import org.chromium.chrome.browser.omnibox.suggestions.SuggestionCommonProperties; import org.chromium.chrome.browser.omnibox.suggestions.SuggestionCommonProperties;
import org.chromium.ui.modelutil.PropertyKey; import org.chromium.ui.modelutil.PropertyKey;
import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModel;
...@@ -22,8 +23,9 @@ public class TailSuggestionViewBinder { ...@@ -22,8 +23,9 @@ public class TailSuggestionViewBinder {
view.setTailText(model.get(TailSuggestionViewProperties.TEXT)); view.setTailText(model.get(TailSuggestionViewProperties.TEXT));
} else if (propertyKey == TailSuggestionViewProperties.FILL_INTO_EDIT) { } else if (propertyKey == TailSuggestionViewProperties.FILL_INTO_EDIT) {
view.setFullText(model.get(TailSuggestionViewProperties.FILL_INTO_EDIT)); view.setFullText(model.get(TailSuggestionViewProperties.FILL_INTO_EDIT));
} else if (propertyKey == SuggestionCommonProperties.USE_DARK_COLORS) { } else if (propertyKey == SuggestionCommonProperties.OMNIBOX_THEME) {
final boolean useDarkMode = model.get(SuggestionCommonProperties.USE_DARK_COLORS); final boolean useDarkMode = !OmniboxResourceProvider.isDarkMode(
model.get(SuggestionCommonProperties.OMNIBOX_THEME));
@ColorRes @ColorRes
final int color = useDarkMode ? R.color.default_text_color_dark final int color = useDarkMode ? R.color.default_text_color_dark
: R.color.default_text_color_light; : R.color.default_text_color_light;
......
...@@ -25,6 +25,7 @@ import org.mockito.MockitoAnnotations; ...@@ -25,6 +25,7 @@ import org.mockito.MockitoAnnotations;
import org.chromium.base.test.BaseJUnit4ClassRunner; import org.chromium.base.test.BaseJUnit4ClassRunner;
import org.chromium.base.test.util.Batch; import org.chromium.base.test.util.Batch;
import org.chromium.chrome.browser.omnibox.styles.OmniboxTheme;
import org.chromium.ui.modelutil.ListObservable.ListObserver; import org.chromium.ui.modelutil.ListObservable.ListObserver;
import org.chromium.ui.modelutil.MVCListAdapter.ModelList; import org.chromium.ui.modelutil.MVCListAdapter.ModelList;
import org.chromium.ui.modelutil.PropertyModel; import org.chromium.ui.modelutil.PropertyModel;
...@@ -86,16 +87,16 @@ public class DropdownItemViewInfoListManagerUnitTest { ...@@ -86,16 +87,16 @@ public class DropdownItemViewInfoListManagerUnitTest {
/** /**
* Verify that PropertyModels of all suggestions on managed list reflect the expected values. * Verify that PropertyModels of all suggestions on managed list reflect the expected values.
*/ */
private void verifyPropertyValues(int layoutDirection, boolean useDarkColors) { private void verifyPropertyValues(int layoutDirection, @OmniboxTheme int omniboxTheme) {
for (int index = 0; index < mSuggestionModels.size(); index++) { for (int index = 0; index < mSuggestionModels.size(); index++) {
Assert.assertEquals("Unexpected layout direction for suggestion at position " + index, Assert.assertEquals("Unexpected layout direction for suggestion at position " + index,
layoutDirection, layoutDirection,
mSuggestionModels.get(index).model.get( mSuggestionModels.get(index).model.get(
SuggestionCommonProperties.LAYOUT_DIRECTION)); SuggestionCommonProperties.LAYOUT_DIRECTION));
Assert.assertEquals("Unexpected visual theme for suggestion at position " + index, Assert.assertEquals("Unexpected visual theme for suggestion at position " + index,
useDarkColors, omniboxTheme,
mSuggestionModels.get(index).model.get( mSuggestionModels.get(index).model.get(
SuggestionCommonProperties.USE_DARK_COLORS)); SuggestionCommonProperties.OMNIBOX_THEME));
} }
} }
...@@ -285,13 +286,16 @@ public class DropdownItemViewInfoListManagerUnitTest { ...@@ -285,13 +286,16 @@ public class DropdownItemViewInfoListManagerUnitTest {
mManager.setSourceViewInfoList(list); mManager.setSourceViewInfoList(list);
verifyModelEquals(list); verifyModelEquals(list);
verifyPropertyValues(View.LAYOUT_DIRECTION_INHERIT, /* useDarkColors= */ true); verifyPropertyValues(View.LAYOUT_DIRECTION_INHERIT, OmniboxTheme.LIGHT_THEME);
mManager.setLayoutDirection(View.LAYOUT_DIRECTION_RTL); mManager.setLayoutDirection(View.LAYOUT_DIRECTION_RTL);
verifyPropertyValues(View.LAYOUT_DIRECTION_RTL, /* useDarkColors= */ true); verifyPropertyValues(View.LAYOUT_DIRECTION_RTL, OmniboxTheme.LIGHT_THEME);
mManager.setUseDarkColors(false); mManager.setOmniboxTheme(OmniboxTheme.DARK_THEME);
verifyPropertyValues(View.LAYOUT_DIRECTION_RTL, /* useDarkColors= */ false); verifyPropertyValues(View.LAYOUT_DIRECTION_RTL, OmniboxTheme.DARK_THEME);
mManager.setOmniboxTheme(OmniboxTheme.INCOGNITO);
verifyPropertyValues(View.LAYOUT_DIRECTION_RTL, OmniboxTheme.INCOGNITO);
// Finally, set the new list and confirm that the values are still applied. // Finally, set the new list and confirm that the values are still applied.
list = Arrays.asList(new DropdownItemViewInfo(mHeaderProcessor, list = Arrays.asList(new DropdownItemViewInfo(mHeaderProcessor,
...@@ -304,7 +308,7 @@ public class DropdownItemViewInfoListManagerUnitTest { ...@@ -304,7 +308,7 @@ public class DropdownItemViewInfoListManagerUnitTest {
new PropertyModel(SuggestionCommonProperties.ALL_KEYS), 2)); new PropertyModel(SuggestionCommonProperties.ALL_KEYS), 2));
mManager.setSourceViewInfoList(list); mManager.setSourceViewInfoList(list);
verifyModelEquals(list); verifyModelEquals(list);
verifyPropertyValues(View.LAYOUT_DIRECTION_RTL, /* useDarkColors= */ false); verifyPropertyValues(View.LAYOUT_DIRECTION_RTL, OmniboxTheme.INCOGNITO);
} }
@Test @Test
......
...@@ -120,8 +120,7 @@ public class ClipboardSuggestionProcessorTest { ...@@ -120,8 +120,7 @@ public class ClipboardSuggestionProcessorTest {
mModel = mProcessor.createModel(); mModel = mProcessor.createModel();
mProcessor.populateModel(mSuggestion, mModel, 0); mProcessor.populateModel(mSuggestion, mModel, 0);
SuggestionViewViewBinder.bind(mModel, mRootView, SuggestionViewProperties.TEXT_LINE_1_TEXT); SuggestionViewViewBinder.bind(mModel, mRootView, SuggestionViewProperties.TEXT_LINE_1_TEXT);
SuggestionViewViewBinder.bind( SuggestionViewViewBinder.bind(mModel, mRootView, SuggestionCommonProperties.OMNIBOX_THEME);
mModel, mRootView, SuggestionCommonProperties.USE_DARK_COLORS);
SuggestionViewViewBinder.bind( SuggestionViewViewBinder.bind(
mModel, mRootView, SuggestionViewProperties.IS_SEARCH_SUGGESTION); mModel, mRootView, SuggestionViewProperties.IS_SEARCH_SUGGESTION);
SuggestionViewViewBinder.bind(mModel, mRootView, SuggestionViewProperties.TEXT_LINE_2_TEXT); SuggestionViewViewBinder.bind(mModel, mRootView, SuggestionViewProperties.TEXT_LINE_2_TEXT);
......
// 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.styles;
import android.app.Activity;
import android.graphics.drawable.Drawable;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
import org.robolectric.annotation.Config;
import org.chromium.chrome.R;
import org.chromium.testing.local.LocalRobolectricTestRunner;
/** Tests for {@link OmniboxResourceProvider}. */
@RunWith(LocalRobolectricTestRunner.class)
@Config(manifest = Config.NONE)
public class OmniboxResourceProviderTest {
@Test
public void getThemeFromDarkColorsAndIncognito() {
@OmniboxTheme
int actual = OmniboxResourceProvider.getThemeFromDarkColorsAndIncognito(
/*useDarkColors=*/true, /*isIncognito=*/false);
Assert.assertEquals(OmniboxTheme.LIGHT_THEME, actual);
actual = OmniboxResourceProvider.getThemeFromDarkColorsAndIncognito(
/*useDarkColors=*/false, /*isIncognito=*/false);
Assert.assertEquals(OmniboxTheme.DARK_THEME, actual);
actual = OmniboxResourceProvider.getThemeFromDarkColorsAndIncognito(
/*useDarkColors=*/false, /*isIncognito=*/true);
Assert.assertEquals(OmniboxTheme.INCOGNITO, actual);
actual = OmniboxResourceProvider.getThemeFromDarkColorsAndIncognito(
/*useDarkColors=*/true, /*isIncognito=*/true);
Assert.assertEquals(OmniboxTheme.INCOGNITO, actual);
}
@Test
public void isDarkMode() {
Assert.assertTrue(OmniboxResourceProvider.isDarkMode(OmniboxTheme.DARK_THEME));
Assert.assertTrue(OmniboxResourceProvider.isDarkMode(OmniboxTheme.INCOGNITO));
Assert.assertFalse(OmniboxResourceProvider.isDarkMode(OmniboxTheme.LIGHT_THEME));
}
@Test
public void resolveAttributeToDrawable() {
Activity activity = Robolectric.buildActivity(Activity.class).setup().get();
activity.setTheme(R.style.Light);
Drawable drawableLight = OmniboxResourceProvider.resolveAttributeToDrawable(
activity, OmniboxTheme.LIGHT_THEME, R.attr.selectableItemBackground);
Assert.assertNotNull(drawableLight);
activity.setTheme(R.style.Dark);
Drawable drawableDark = OmniboxResourceProvider.resolveAttributeToDrawable(
activity, OmniboxTheme.DARK_THEME, R.attr.selectableItemBackground);
Assert.assertNotNull(drawableDark);
}
}
...@@ -29,6 +29,7 @@ import org.robolectric.Robolectric; ...@@ -29,6 +29,7 @@ import org.robolectric.Robolectric;
import org.robolectric.annotation.Config; import org.robolectric.annotation.Config;
import org.chromium.chrome.R; import org.chromium.chrome.R;
import org.chromium.chrome.browser.omnibox.styles.OmniboxTheme;
import org.chromium.chrome.browser.omnibox.suggestions.SuggestionCommonProperties; import org.chromium.chrome.browser.omnibox.suggestions.SuggestionCommonProperties;
import org.chromium.chrome.browser.omnibox.suggestions.base.BaseSuggestionViewProperties.Action; import org.chromium.chrome.browser.omnibox.suggestions.base.BaseSuggestionViewProperties.Action;
import org.chromium.components.browser_ui.widget.RoundedCornerImageView; import org.chromium.components.browser_ui.widget.RoundedCornerImageView;
...@@ -225,7 +226,7 @@ public class BaseSuggestionViewBinderUnitTest { ...@@ -225,7 +226,7 @@ public class BaseSuggestionViewBinderUnitTest {
Assert.assertNull(mModel.get(BaseSuggestionViewProperties.ACTIONS)); Assert.assertNull(mModel.get(BaseSuggestionViewProperties.ACTIONS));
mBaseView.setActionButtonsCount(1); mBaseView.setActionButtonsCount(1);
// Change in color scheme happening ahead of setting action could cause a crash. // Change in color scheme happening ahead of setting action could cause a crash.
mModel.set(SuggestionCommonProperties.USE_DARK_COLORS, false); mModel.set(SuggestionCommonProperties.OMNIBOX_THEME, OmniboxTheme.LIGHT_THEME);
} }
@Test @Test
......
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