Commit a984a785 authored by Pavol Drotar's avatar Pavol Drotar Committed by Commit Bot

Add support for changing navbar divider color in chrome custom tabs

Users required the ability to change the color of the navigation bar
divider which looked inconsistent in custom tabs when both the
contents of a web app and nav bar were the same color. This CL
extends CustomTabNavigationBarController to set the divider color,
and extends CustomTabIntentDataProvider to contain the divider color.

Test: Added a new test file CustomTabNavigationBarControllerTest.java
to test possible combinations of setting navigation bar and divider colors.

Bug: 1021436
Change-Id: I2077c44c3be5f8fe2c842884e4f85ce70b1376b7
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2297394Reviewed-by: default avatarPeter Conn <peconn@chromium.org>
Commit-Queue: Pavol Drotár <pavoldrotar@google.com>
Cr-Commit-Position: refs/heads/master@{#789106}
parent 1a219396
...@@ -62,6 +62,7 @@ chrome_junit_test_java_sources = [ ...@@ -62,6 +62,7 @@ chrome_junit_test_java_sources = [
"junit/src/org/chromium/chrome/browser/cryptids/ProbabilisticCryptidRendererUnitTest.java", "junit/src/org/chromium/chrome/browser/cryptids/ProbabilisticCryptidRendererUnitTest.java",
"junit/src/org/chromium/chrome/browser/customtabs/CloseButtonNavigatorTest.java", "junit/src/org/chromium/chrome/browser/customtabs/CloseButtonNavigatorTest.java",
"junit/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProviderTest.java", "junit/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProviderTest.java",
"junit/src/org/chromium/chrome/browser/customtabs/CustomTabNavigationBarControllerTest.java",
"junit/src/org/chromium/chrome/browser/customtabs/CustomTabNightModeStateControllerTest.java", "junit/src/org/chromium/chrome/browser/customtabs/CustomTabNightModeStateControllerTest.java",
"junit/src/org/chromium/chrome/browser/customtabs/CustomTabStatusBarColorProviderTest.java", "junit/src/org/chromium/chrome/browser/customtabs/CustomTabStatusBarColorProviderTest.java",
"junit/src/org/chromium/chrome/browser/customtabs/NavigationInfoCaptureTriggerTest.java", "junit/src/org/chromium/chrome/browser/customtabs/NavigationInfoCaptureTriggerTest.java",
......
...@@ -170,6 +170,14 @@ public abstract class BrowserServicesIntentDataProvider { ...@@ -170,6 +170,14 @@ public abstract class BrowserServicesIntentDataProvider {
return null; return null;
} }
/**
* @return The navigation bar divider color specified in the intent, or null if not specified.
*/
@Nullable
public Integer getNavigationBarDividerColor() {
return null;
}
/** /**
* @return The drawable of the icon of close button shown in the custom tab toolbar. * @return The drawable of the icon of close button shown in the custom tab toolbar.
*/ */
......
...@@ -92,7 +92,7 @@ public class CustomTabActivity extends BaseCustomTabActivity { ...@@ -92,7 +92,7 @@ public class CustomTabActivity extends BaseCustomTabActivity {
mSession = mIntentDataProvider.getSession(); mSession = mIntentDataProvider.getSession();
CustomTabNavigationBarController.updateNavigationBarColor(this, mIntentDataProvider); CustomTabNavigationBarController.update(getWindow(), mIntentDataProvider, getResources());
} }
@Override @Override
......
...@@ -172,6 +172,8 @@ public class CustomTabIntentDataProvider extends BrowserServicesIntentDataProvid ...@@ -172,6 +172,8 @@ public class CustomTabIntentDataProvider extends BrowserServicesIntentDataProvid
private final @ActivityType int mActivityType; private final @ActivityType int mActivityType;
@Nullable @Nullable
private final Integer mNavigationBarColor; private final Integer mNavigationBarColor;
@Nullable
private final Integer mNavigationBarDividerColor;
private final boolean mIsIncognito; private final boolean mIsIncognito;
@Nullable @Nullable
private final List<String> mTrustedWebActivityAdditionalOrigins; private final List<String> mTrustedWebActivityAdditionalOrigins;
...@@ -277,6 +279,7 @@ public class CustomTabIntentDataProvider extends BrowserServicesIntentDataProvid ...@@ -277,6 +279,7 @@ public class CustomTabIntentDataProvider extends BrowserServicesIntentDataProvid
mNavigationBarColor = params.navigationBarColor == null mNavigationBarColor = params.navigationBarColor == null
? null ? null
: ColorUtils.getOpaqueColor(params.navigationBarColor); : ColorUtils.getOpaqueColor(params.navigationBarColor);
mNavigationBarDividerColor = params.navigationBarDividerColor;
mInitialBackgroundColor = retrieveInitialBackgroundColor(intent); mInitialBackgroundColor = retrieveInitialBackgroundColor(intent);
mEnableUrlBarHiding = IntentUtils.safeGetBooleanExtra( mEnableUrlBarHiding = IntentUtils.safeGetBooleanExtra(
...@@ -614,6 +617,12 @@ public class CustomTabIntentDataProvider extends BrowserServicesIntentDataProvid ...@@ -614,6 +617,12 @@ public class CustomTabIntentDataProvider extends BrowserServicesIntentDataProvid
return mNavigationBarColor; return mNavigationBarColor;
} }
@Override
@Nullable
public Integer getNavigationBarDividerColor() {
return mNavigationBarDividerColor;
}
@Override @Override
@Nullable @Nullable
public Drawable getCloseButtonDrawable() { public Drawable getCloseButtonDrawable() {
......
// Copyright 2019 The Chromium Authors. All rights reserved. // Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
package org.chromium.chrome.browser.customtabs.features; package org.chromium.chrome.browser.customtabs.features;
import android.app.Activity; import android.content.res.Resources;
import android.os.Build; import android.os.Build;
import android.view.Window; import android.view.Window;
import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.browserservices.BrowserServicesIntentDataProvider; import org.chromium.chrome.browser.browserservices.BrowserServicesIntentDataProvider;
import org.chromium.ui.UiUtils; import org.chromium.ui.UiUtils;
import org.chromium.ui.util.ColorUtils; import org.chromium.ui.util.ColorUtils;
...@@ -24,16 +23,31 @@ public class CustomTabNavigationBarController { ...@@ -24,16 +23,31 @@ public class CustomTabNavigationBarController {
private CustomTabNavigationBarController() {} private CustomTabNavigationBarController() {}
/** /**
* Sets the navigation bar color according to intent extras. * Sets the navigation bar color and navigation divider color according to intent extras.
*/ */
public static void updateNavigationBarColor(Activity activity, public static void update(Window window, BrowserServicesIntentDataProvider intentDataProvider,
BrowserServicesIntentDataProvider intentDataProvider) { Resources resources) {
Integer color = intentDataProvider.getNavigationBarColor(); Integer navigationBarColor = intentDataProvider.getNavigationBarColor();
if (color == null) return; Integer navigationBarDividerColor = intentDataProvider.getNavigationBarDividerColor();
int lightBackgroundDividerColor = ApiCompatibilityUtils.getColor(
resources, org.chromium.chrome.R.color.black_alpha_12);
boolean needsDarkButtons = navigationBarColor != null
&& !ColorUtils.shouldUseLightForegroundOnBackground(navigationBarColor);
Window window = activity.getWindow(); updateBarColor(window, navigationBarColor, needsDarkButtons);
updateDividerColor(window, navigationBarColor, navigationBarDividerColor,
lightBackgroundDividerColor, needsDarkButtons);
}
/**
* Sets the navigation bar color according to intent extras.
*/
private static void updateBarColor(
Window window, Integer navigationBarColor, boolean needsDarkButtons) {
if (navigationBarColor == null) return;
boolean needsDarkButtons = !ColorUtils.shouldUseLightForegroundOnBackground(color);
boolean supportsDarkButtons = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O; boolean supportsDarkButtons = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O;
if (supportsDarkButtons) { if (supportsDarkButtons) {
...@@ -42,18 +56,29 @@ public class CustomTabNavigationBarController { ...@@ -42,18 +56,29 @@ public class CustomTabNavigationBarController {
} else if (needsDarkButtons) { } else if (needsDarkButtons) {
// Can't make the buttons dark, darken the background instead with the same algorithm // Can't make the buttons dark, darken the background instead with the same algorithm
// as for the status bar. // as for the status bar.
color = ColorUtils.getDarkenedColorForStatusBar(color); navigationBarColor = ColorUtils.getDarkenedColorForStatusBar(navigationBarColor);
} }
window.setNavigationBarColor(color); window.setNavigationBarColor(navigationBarColor);
}
/**
* Sets the navigation bar divider color according to intent extras.
*/
private static void updateDividerColor(Window window, Integer navigationBarColor,
Integer navigationBarDividerColor, int lightBackgroundDividerColor,
boolean needsDarkButtons) {
// navigationBarDividerColor can only be set in Android P+
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) return;
if (needsDarkButtons && Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { if (navigationBarDividerColor != null) {
window.setNavigationBarDividerColor(navigationBarDividerColor);
} else if (navigationBarColor != null && needsDarkButtons) {
// Add grey divider color if the background is light (similar to // Add grey divider color if the background is light (similar to
// TabbedNavigationBarColorController#setNavigationBarColor). // TabbedNavigationBarColorController#setNavigationBarColor).
// bottom_system_nav_divider_color is overridden to black on Q+, so using it's pre-Q // bottom_system_nav_divider_color is overridden to black on Q+, so using it's pre-Q
// value, black_alpha_12, directly. // value, black_alpha_12, directly.
window.setNavigationBarDividerColor(ApiCompatibilityUtils.getColor( window.setNavigationBarDividerColor(lightBackgroundDividerColor);
activity.getResources(), R.color.black_alpha_12));
} }
} }
} }
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.customtabs;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.Activity;
import android.content.res.Resources;
import android.graphics.Color;
import android.os.Build;
import android.view.Window;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
import org.robolectric.annotation.Config;
import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.base.test.BaseRobolectricTestRunner;
import org.chromium.chrome.browser.customtabs.features.CustomTabNavigationBarController;
import org.chromium.ui.util.ColorUtils;
/** Tests for {@link CustomTabNavigationBarController}. */
@RunWith(BaseRobolectricTestRunner.class)
@Config(manifest = Config.NONE)
public class CustomTabNavigationBarControllerTest {
@Mock
private CustomTabIntentDataProvider mCustomTabIntentDataProvider;
private Window mWindow;
private Resources mResources;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
Activity activity = Robolectric.buildActivity(Activity.class).get();
mWindow = spy(activity.getWindow());
mResources = activity.getResources();
}
@Test
public void doesNotSetBarColorWhenNull() {
when(mCustomTabIntentDataProvider.getNavigationBarColor()).thenReturn(null);
CustomTabNavigationBarController.update(mWindow, mCustomTabIntentDataProvider, mResources);
verify(mWindow, never()).setNavigationBarColor(Mockito.anyInt());
}
@Test
@Config(sdk = Build.VERSION_CODES.P) // Android P+ (>=28) is needed for setting divider color.
public void doesNotSetDividerColorWhenNull() {
when(mCustomTabIntentDataProvider.getNavigationBarDividerColor()).thenReturn(null);
// Bar color needs to be null. Otherwise the divider color could still be set if
// needsDarkButtons is true.
when(mCustomTabIntentDataProvider.getNavigationBarColor()).thenReturn(null);
CustomTabNavigationBarController.update(mWindow, mCustomTabIntentDataProvider, mResources);
verify(mWindow, never()).setNavigationBarDividerColor(Mockito.anyInt());
}
@Test
@Config(sdk = Build.VERSION_CODES.O_MR1)
// Android P+ (>=28) is needed for setting the divider color.
public void doesNotSetDividerColorWhenSdkLow() {
when(mCustomTabIntentDataProvider.getNavigationBarDividerColor()).thenReturn(Color.RED);
when(mCustomTabIntentDataProvider.getNavigationBarColor()).thenReturn(Color.GREEN);
// Make sure calling the line below does not throw an exception, because the method does not
// exist in android P+.
CustomTabNavigationBarController.update(mWindow, mCustomTabIntentDataProvider, mResources);
}
@Test
@Config(sdk = Build.VERSION_CODES.N_MR1) // SDK 25 is used to trigger supportsDarkButtons=false.
public void setsCorrectBarColor() {
when(mCustomTabIntentDataProvider.getNavigationBarDividerColor()).thenReturn(Color.RED);
// The case when needsDarkButtons=true.
when(mCustomTabIntentDataProvider.getNavigationBarColor()).thenReturn(Color.WHITE);
CustomTabNavigationBarController.update(mWindow, mCustomTabIntentDataProvider, mResources);
verify(mWindow).setNavigationBarColor(ColorUtils.getDarkenedColorForStatusBar(Color.WHITE));
// The case when needsDarkButtons=false.
when(mCustomTabIntentDataProvider.getNavigationBarColor()).thenReturn(Color.BLACK);
CustomTabNavigationBarController.update(mWindow, mCustomTabIntentDataProvider, mResources);
verify(mWindow).setNavigationBarColor(Color.BLACK);
}
@Test
@Config(sdk = Build.VERSION_CODES.O) // SDK 26 is used to trigger supportDarkButtons=true.
public void setsCorrectBarColorWhenDarkButtonsSupported() {
when(mCustomTabIntentDataProvider.getNavigationBarDividerColor()).thenReturn(Color.RED);
when(mCustomTabIntentDataProvider.getNavigationBarColor()).thenReturn(Color.GREEN);
// The case when needsDarkButtons=true
when(mCustomTabIntentDataProvider.getNavigationBarColor()).thenReturn(Color.WHITE);
CustomTabNavigationBarController.update(mWindow, mCustomTabIntentDataProvider, mResources);
verify(mWindow).setNavigationBarColor(Color.WHITE);
}
@Test
@Config(sdk = Build.VERSION_CODES.P) // Android P+ (>=28) needed for setting divider color.
public void setsCorrectDividerColor() {
// The case when divider color is set explicitly.
when(mCustomTabIntentDataProvider.getNavigationBarDividerColor()).thenReturn(Color.RED);
when(mCustomTabIntentDataProvider.getNavigationBarColor()).thenReturn(Color.BLACK);
CustomTabNavigationBarController.update(mWindow, mCustomTabIntentDataProvider, mResources);
verify(mWindow).setNavigationBarDividerColor(Color.RED);
// The case when divider color is set implicitly due to needsDarkButtons=true.
when(mCustomTabIntentDataProvider.getNavigationBarDividerColor()).thenReturn(null);
when(mCustomTabIntentDataProvider.getNavigationBarColor()).thenReturn(Color.WHITE);
CustomTabNavigationBarController.update(mWindow, mCustomTabIntentDataProvider, mResources);
verify(mWindow).setNavigationBarDividerColor(ApiCompatibilityUtils.getColor(
mResources, org.chromium.chrome.R.color.black_alpha_12));
}
}
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