1 // Copyright 2015 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 package org.chromium.chrome.browser.toolbar.top; 6 7 import android.graphics.Color; 8 import android.os.Build; 9 import android.text.TextUtils; 10 11 import androidx.test.filters.SmallTest; 12 13 import org.hamcrest.Matchers; 14 import org.junit.Assert; 15 import org.junit.Rule; 16 import org.junit.Test; 17 import org.junit.runner.RunWith; 18 19 import org.chromium.base.ObserverList.RewindableIterator; 20 import org.chromium.base.SysUtils; 21 import org.chromium.base.task.PostTask; 22 import org.chromium.base.test.util.CommandLineFlags; 23 import org.chromium.base.test.util.Criteria; 24 import org.chromium.base.test.util.CriteriaHelper; 25 import org.chromium.base.test.util.Feature; 26 import org.chromium.base.test.util.Restriction; 27 import org.chromium.base.test.util.UrlUtils; 28 import org.chromium.chrome.R; 29 import org.chromium.chrome.browser.flags.ChromeSwitches; 30 import org.chromium.chrome.browser.tab.Tab; 31 import org.chromium.chrome.browser.tab.TabObserver; 32 import org.chromium.chrome.browser.tab.TabTestUtils; 33 import org.chromium.chrome.browser.toolbar.ToolbarDataProvider; 34 import org.chromium.chrome.test.ChromeJUnit4ClassRunner; 35 import org.chromium.chrome.test.ChromeTabbedActivityTestRule; 36 import org.chromium.components.browser_ui.styles.ChromeColors; 37 import org.chromium.content_public.browser.UiThreadTaskTraits; 38 import org.chromium.content_public.browser.test.util.TestThreadUtils; 39 import org.chromium.ui.test.util.UiRestriction; 40 import org.chromium.ui.util.ColorUtils; 41 42 /** 43 * Contains tests for the brand color feature. 44 */ 45 @RunWith(ChromeJUnit4ClassRunner.class) 46 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) 47 public class BrandColorTest { 48 @Rule 49 public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule(); 50 51 private static final String BRAND_COLOR_1 = "#482329"; 52 private static final String BRAND_COLOR_2 = "#505050"; 53 54 private ToolbarPhone mToolbar; 55 private ToolbarDataProvider mToolbarDataProvider; 56 private int mDefaultColor; 57 private boolean mSupportsDarkStatusIcons; 58 getUrlWithBrandColor(String brandColor)59 private static String getUrlWithBrandColor(String brandColor) { 60 String brandColorMetaTag = TextUtils.isEmpty(brandColor) 61 ? "" 62 : "<meta name='theme-color' content='" + brandColor + "'>"; 63 return UrlUtils.encodeHtmlDataUri("<html>" 64 + " <head>" 65 + " " + brandColorMetaTag + " </head>" 66 + " <body>" 67 + " Theme color set to " + brandColor + " </body>" 68 + "</html>"); 69 } 70 checkForBrandColor(final int brandColor)71 private void checkForBrandColor(final int brandColor) { 72 CriteriaHelper.pollUiThread(() -> { 73 Criteria.checkThat(mToolbarDataProvider.getPrimaryColor(), Matchers.is(brandColor)); 74 Criteria.checkThat(mToolbarDataProvider.getPrimaryColor(), 75 Matchers.is(mToolbar.getBackgroundDrawable().getColor())); 76 }); 77 if (!SysUtils.isLowEndDevice()) { 78 final int expectedStatusBarColor; 79 if (mSupportsDarkStatusIcons) { 80 expectedStatusBarColor = brandColor == mDefaultColor ? Color.WHITE : brandColor; 81 } else { 82 expectedStatusBarColor = brandColor == mDefaultColor 83 ? Color.BLACK 84 : ColorUtils.getDarkenedColorForStatusBar(brandColor); 85 } 86 CriteriaHelper.pollUiThread(() -> { 87 Criteria.checkThat(mActivityTestRule.getActivity().getWindow().getStatusBarColor(), 88 Matchers.is(expectedStatusBarColor)); 89 }); 90 } 91 } 92 startMainActivityWithURL(String url)93 protected void startMainActivityWithURL(String url) { 94 mActivityTestRule.startMainActivityWithURL(url); 95 mToolbar = (ToolbarPhone) mActivityTestRule.getActivity().findViewById(R.id.toolbar); 96 mToolbarDataProvider = mToolbar.getToolbarDataProvider(); 97 mDefaultColor = ChromeColors.getDefaultThemeColor( 98 mActivityTestRule.getActivity().getResources(), /* isIncognito = */ false); 99 // TODO(https://crbug.com/871805): Use helper class to determine whether dark status icons 100 // are supported. 101 mSupportsDarkStatusIcons = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M; 102 } 103 104 /** 105 * Test for having default primary color working correctly. 106 */ 107 @Test 108 @SmallTest 109 @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE) 110 @Feature({"StatusBar", "Omnibox"}) testNoBrandColor()111 public void testNoBrandColor() { 112 startMainActivityWithURL(getUrlWithBrandColor("")); 113 checkForBrandColor(mDefaultColor); 114 } 115 116 /** 117 * Test for adding a brand color for a url. 118 */ 119 @Test 120 @SmallTest 121 @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE) 122 @Feature({"StatusBar", "Omnibox"}) testBrandColorNoAlpha()123 public void testBrandColorNoAlpha() { 124 startMainActivityWithURL(getUrlWithBrandColor(BRAND_COLOR_1)); 125 checkForBrandColor(Color.parseColor(BRAND_COLOR_1)); 126 } 127 128 /** 129 * Test for immediately setting the brand color. 130 */ 131 @Test 132 @SmallTest 133 @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE) 134 @Feature({"StatusBar", "Omnibox"}) testImmediateColorChange()135 public void testImmediateColorChange() { 136 startMainActivityWithURL(getUrlWithBrandColor(BRAND_COLOR_1)); 137 checkForBrandColor(Color.parseColor(BRAND_COLOR_1)); 138 139 TestThreadUtils.runOnUiThreadBlocking(() -> { 140 mActivityTestRule.getActivity().getToolbarManager().onThemeColorChanged( 141 mDefaultColor, false); 142 // Since the color should change instantly, there is no need to use the criteria 143 // helper. 144 Assert.assertEquals(mToolbarDataProvider.getPrimaryColor(), 145 mToolbar.getBackgroundDrawable().getColor()); 146 }); 147 } 148 149 /** 150 * Test to make sure onLoadStarted doesn't reset the brand color. 151 */ 152 @Test 153 @SmallTest 154 @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE) 155 @Feature({"StatusBar", "Omnibox"}) testBrandColorWithLoadStarted()156 public void testBrandColorWithLoadStarted() { 157 startMainActivityWithURL(getUrlWithBrandColor(BRAND_COLOR_1)); 158 PostTask.postTask(UiThreadTaskTraits.DEFAULT, () -> { 159 Tab tab = mActivityTestRule.getActivity().getActivityTab(); 160 RewindableIterator<TabObserver> observers = TabTestUtils.getTabObservers(tab); 161 while (observers.hasNext()) { 162 observers.next().onLoadStarted(tab, true); 163 } 164 }); 165 checkForBrandColor(Color.parseColor(BRAND_COLOR_1)); 166 } 167 168 /** 169 * Test for checking navigating to new brand color updates correctly. 170 */ 171 @Test 172 @SmallTest 173 @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE) 174 @Feature({"StatusBar", "Omnibox"}) testNavigatingToNewBrandColor()175 public void testNavigatingToNewBrandColor() { 176 startMainActivityWithURL(getUrlWithBrandColor(BRAND_COLOR_1)); 177 checkForBrandColor(Color.parseColor(BRAND_COLOR_1)); 178 mActivityTestRule.loadUrl(getUrlWithBrandColor(BRAND_COLOR_2)); 179 checkForBrandColor(Color.parseColor(BRAND_COLOR_2)); 180 } 181 182 /** 183 * Test for checking navigating to a brand color site from a site with no brand color and then 184 * back again. 185 */ 186 @Test 187 @SmallTest 188 @Restriction(UiRestriction.RESTRICTION_TYPE_PHONE) 189 @Feature({"StatusBar", "Omnibox"}) testNavigatingToBrandColorAndBack()190 public void testNavigatingToBrandColorAndBack() { 191 startMainActivityWithURL("about:blank"); 192 checkForBrandColor(mDefaultColor); 193 mActivityTestRule.loadUrl(getUrlWithBrandColor(BRAND_COLOR_1)); 194 checkForBrandColor(Color.parseColor(BRAND_COLOR_1)); 195 mActivityTestRule.loadUrl("about:blank"); 196 checkForBrandColor(mDefaultColor); 197 PostTask.runOrPostTask( 198 UiThreadTaskTraits.DEFAULT, () -> mActivityTestRule.getActivity().onBackPressed()); 199 checkForBrandColor(Color.parseColor(BRAND_COLOR_1)); 200 PostTask.runOrPostTask( 201 UiThreadTaskTraits.DEFAULT, () -> mActivityTestRule.getActivity().onBackPressed()); 202 checkForBrandColor(mDefaultColor); 203 } 204 } 205