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