Commit e8ec1f05 authored by Wenyu Fu's avatar Wenyu Fu Committed by Commit Bot

[HomepageLocationPolicy] Change Homepage Preference under Policy

Integrate the HomepagePolicyManager with HomepageManager,
HomepagePreference and HomeButton.

This CL includes several behavior changes when HomepageLocation Policy
is set to enabled:
1. Homepage will be set to the one assigned by policy
2. Long press on HomeButton will be disabled
3. In Homepage preference, the switch and the edit will be disabled

This CL does not include layout changes of Homepage Preference UI.

Bug: 978197
Change-Id: I42f022866cf346b9a3e82dd30b9e57e6d3a10af4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1929492
Commit-Queue: Wenyu Fu <wenyufu@chromium.org>
Auto-Submit: Wenyu Fu <wenyufu@chromium.org>
Reviewed-by: default avatarWei-Yin Chen (陳威尹) <wychen@chromium.org>
Reviewed-by: default avatarTheresa  <twellington@chromium.org>
Cr-Commit-Position: refs/heads/master@{#726882}
parent 94afbeb5
...@@ -195,6 +195,7 @@ chrome_test_java_sources = [ ...@@ -195,6 +195,7 @@ chrome_test_java_sources = [
"javatests/src/org/chromium/chrome/browser/hardware_acceleration/WebappActivityHWATest.java", "javatests/src/org/chromium/chrome/browser/hardware_acceleration/WebappActivityHWATest.java",
"javatests/src/org/chromium/chrome/browser/history/HistoryActivityScrollingTest.java", "javatests/src/org/chromium/chrome/browser/history/HistoryActivityScrollingTest.java",
"javatests/src/org/chromium/chrome/browser/history/HistoryActivityTest.java", "javatests/src/org/chromium/chrome/browser/history/HistoryActivityTest.java",
"javatests/src/org/chromium/chrome/browser/homepage/HomepagePolicyIntegrationTest.java",
"javatests/src/org/chromium/chrome/browser/identity/SettingsSecureBasedIdentificationGeneratorTest.java", "javatests/src/org/chromium/chrome/browser/identity/SettingsSecureBasedIdentificationGeneratorTest.java",
"javatests/src/org/chromium/chrome/browser/identity/UniqueIdentificationGeneratorFactoryTest.java", "javatests/src/org/chromium/chrome/browser/identity/UniqueIdentificationGeneratorFactoryTest.java",
"javatests/src/org/chromium/chrome/browser/identity/UuidBasedUniqueIdentificationGeneratorTest.java", "javatests/src/org/chromium/chrome/browser/identity/UuidBasedUniqueIdentificationGeneratorTest.java",
......
...@@ -127,6 +127,7 @@ public class FeatureUtilities { ...@@ -127,6 +127,7 @@ public class FeatureUtilities {
cacheReachedCodeProfilerTrialGroup(); cacheReachedCodeProfilerTrialGroup();
cacheStartSurfaceEnabled(); cacheStartSurfaceEnabled();
cacheNativeTabSwitcherUiFlags(); cacheNativeTabSwitcherUiFlags();
cacheHomepageLocationPolicyEnabled();
// Propagate REACHED_CODE_PROFILER feature value to LibraryLoader. This can't be done in // Propagate REACHED_CODE_PROFILER feature value to LibraryLoader. This can't be done in
// LibraryLoader itself because it lives in //base and can't depend on ChromeFeatureList. // LibraryLoader itself because it lives in //base and can't depend on ChromeFeatureList.
...@@ -670,6 +671,34 @@ public class FeatureUtilities { ...@@ -670,6 +671,34 @@ public class FeatureUtilities {
return sReachedCodeProfilerTrialGroup; return sReachedCodeProfilerTrialGroup;
} }
/**
* Caches the feature flag for whether we enable the homepage location policy.
*/
private static void cacheHomepageLocationPolicyEnabled() {
cacheFlag(ChromePreferenceKeys.FLAGS_CACHED.createKey(
ChromeFeatureList.HOMEPAGE_LOCATION_POLICY),
ChromeFeatureList.HOMEPAGE_LOCATION_POLICY);
}
/**
* @return True if homepage location policy is supported to be enabled.
*/
public static boolean isHomepageLocationPolicyEnabled() {
return isFlagEnabled(ChromePreferenceKeys.FLAGS_CACHED.createKey(
ChromeFeatureList.HOMEPAGE_LOCATION_POLICY),
false);
}
/**
* Expose an interface to set the homepage policy feature flag to be enabled during tests.
*/
@VisibleForTesting
public static void setHomepageLocationPolicyEnabledForTesting(@Nullable Boolean isEnabled) {
sFlags.put(ChromePreferenceKeys.FLAGS_CACHED.createKey(
ChromeFeatureList.HOMEPAGE_LOCATION_POLICY),
isEnabled);
}
private static void cacheFlag(String preferenceName, String featureName) { private static void cacheFlag(String preferenceName, String featureName) {
SharedPreferencesManager.getInstance().writeBoolean( SharedPreferencesManager.getInstance().writeBoolean(
preferenceName, ChromeFeatureList.isEnabled(featureName)); preferenceName, ChromeFeatureList.isEnabled(featureName));
......
...@@ -4,59 +4,146 @@ ...@@ -4,59 +4,146 @@
package org.chromium.chrome.browser.homepage; package org.chromium.chrome.browser.homepage;
import android.text.TextUtils;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import org.chromium.base.ThreadUtils; import org.chromium.base.ObserverList;
import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.flags.FeatureUtilities;
import org.chromium.chrome.browser.init.ChromeBrowserInitializer;
import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
import org.chromium.chrome.browser.preferences.Pref; import org.chromium.chrome.browser.preferences.Pref;
import org.chromium.chrome.browser.preferences.PrefChangeRegistrar; import org.chromium.chrome.browser.preferences.PrefChangeRegistrar;
import org.chromium.chrome.browser.preferences.PrefChangeRegistrar.PrefObserver; import org.chromium.chrome.browser.preferences.PrefChangeRegistrar.PrefObserver;
import org.chromium.chrome.browser.preferences.PrefServiceBridge; import org.chromium.chrome.browser.preferences.PrefServiceBridge;
import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
/** /**
* Provides information for the home page related policies. * Provides information for the home page related policies.
* Monitors changes for the homepage preference. * Monitors changes for the homepage preference.
*/ */
public class HomepagePolicyManager implements PrefObserver { public class HomepagePolicyManager implements PrefObserver {
/**
* An interface to receive updates from {@link HomepagePolicyManager}.
*/
public interface HomepagePolicyStateListener {
/**
* Will be called when homepage policy status change. Though cases are rare, when homepage
* policy has changed during runtime, listeners will receive updates.
*/
void onHomepagePolicyUpdate();
}
private static HomepagePolicyManager sInstance; private static HomepagePolicyManager sInstance;
private boolean mIsHomepageLocationPolicyEnabled; private boolean mIsHomepageLocationPolicyEnabled;
private String mHomepage; private String mHomepage;
private final PrefChangeRegistrar mPrefChangeRegistrar; private boolean mIsInitializedWithNative;
private PrefChangeRegistrar mPrefChangeRegistrar;
private SharedPreferencesManager mSharedPreferenceManager;
private final ObserverList<HomepagePolicyStateListener> mListeners = new ObserverList<>();
/** /**
* Get the singleton instance of HomepagePolicyManager. * @return The singleton instance of {@link HomepagePolicyManager}.
* @return HomepagePolicyManager
*/ */
public static HomepagePolicyManager getInstance() { public static HomepagePolicyManager getInstance() {
ThreadUtils.assertOnUiThread();
if (sInstance == null) { if (sInstance == null) {
sInstance = new HomepagePolicyManager(); sInstance = new HomepagePolicyManager();
} }
return sInstance; return sInstance;
} }
/**
* If policies such as HomepageLocation are enabled on this device, the home page will be marked
* as managed.
* @return True if the current home page is managed by enterprise policy.
*/
public static boolean isHomepageManagedByPolicy() {
return isFeatureFlagEnabled() && getInstance().isHomepageLocationPolicyEnabled();
}
/**
* @return The homepage URL from the homepage preference.
*/
@NonNull
public static String getHomepageUrl() {
return getInstance().getHomepagePreference();
}
/**
* Adds a HomepagePolicyStateListener to receive updates when the homepage policy changes.
* @param listener Object that would like to listen to changes from homepage policy.
*/
public void addListener(HomepagePolicyStateListener listener) {
mListeners.addObserver(listener);
}
/**
* Stop observing pref changes and destroy the singleton instance.
* Will be called from {@link org.chromium.chrome.browser.ChromeActivitySessionTracker}.
*/
public static void destroy() {
sInstance.destroyInternal();
sInstance = null;
}
@VisibleForTesting @VisibleForTesting
static void setInstanceForTests(HomepagePolicyManager instance) { static void setInstanceForTests(HomepagePolicyManager instance) {
assert instance != null; assert instance != null;
sInstance = instance; sInstance = instance;
} }
private HomepagePolicyManager() { @VisibleForTesting
this(new PrefChangeRegistrar()); HomepagePolicyManager() {
mIsInitializedWithNative = false;
mPrefChangeRegistrar = null;
// Update feature flag related setting
mSharedPreferenceManager = SharedPreferencesManager.getInstance();
mHomepage = mSharedPreferenceManager.readString(
ChromePreferenceKeys.HOMEPAGE_LOCATION_POLICY, "");
mIsHomepageLocationPolicyEnabled = !TextUtils.isEmpty(mHomepage);
if (isFeatureFlagEnabled()) {
ChromeBrowserInitializer.getInstance().runNowOrAfterNativeInitialization(
this::onFinishNativeInitialization);
}
} }
/**
* Constructor for unit tests.
* @param prefChangeRegistrar Instance of {@link PrefChangeRegistrar} or test mocking.
* @param listener Object extends {@link HomepagePolicyStateListener}. Will be added between
* singleton {@link HomepagePolicyManager} created, and have it initialized with {@link
* #initializeWithNative(PrefChangeRegistrar)} so that it will get the update from
* {@link HomepagePolicyStateListener#onHomepagePolicyUpdate()}.
*/
@VisibleForTesting @VisibleForTesting
HomepagePolicyManager(@NonNull PrefChangeRegistrar prefChangeRegistrar) { HomepagePolicyManager(@NonNull PrefChangeRegistrar prefChangeRegistrar,
if (!isFeatureFlagEnabled()) { @Nullable HomepagePolicyStateListener listener) {
mPrefChangeRegistrar = null; this();
return;
} if (listener != null) addListener(listener);
if (isFeatureFlagEnabled()) initializeWithNative(prefChangeRegistrar);
}
/**
* Initialize the instance with preference registrar, and start listen to changes for homepage
* preference.
* @param prefChangeRegistrar Instance of {@link PrefChangeRegistrar} or test mocking.
*/
@VisibleForTesting
void initializeWithNative(PrefChangeRegistrar prefChangeRegistrar) {
assert isFeatureFlagEnabled();
mPrefChangeRegistrar = prefChangeRegistrar; mPrefChangeRegistrar = prefChangeRegistrar;
mPrefChangeRegistrar.addObserver(Pref.HOME_PAGE, this); mPrefChangeRegistrar.addObserver(Pref.HOME_PAGE, this);
mIsInitializedWithNative = true;
refresh(); refresh();
} }
...@@ -66,30 +153,46 @@ public class HomepagePolicyManager implements PrefObserver { ...@@ -66,30 +153,46 @@ public class HomepagePolicyManager implements PrefObserver {
refresh(); refresh();
} }
/** private void destroyInternal() {
* Stop observing pref changes and destroy the singleton instance.
* Will be called from {@link org.chromium.chrome.browser.ChromeActivitySessionTracker}
*/
public static void destroy() {
sInstance.destroyInternal();
sInstance = null;
}
protected void destroyInternal() {
if (mPrefChangeRegistrar != null) mPrefChangeRegistrar.destroy(); if (mPrefChangeRegistrar != null) mPrefChangeRegistrar.destroy();
mListeners.clear();
} }
private void refresh() { private void refresh() {
assert mIsInitializedWithNative;
PrefServiceBridge prefServiceBridge = PrefServiceBridge.getInstance(); PrefServiceBridge prefServiceBridge = PrefServiceBridge.getInstance();
mIsHomepageLocationPolicyEnabled = prefServiceBridge.isManagedPreference(Pref.HOME_PAGE); boolean isEnabled = prefServiceBridge.isManagedPreference(Pref.HOME_PAGE);
String homepage = "";
if (isEnabled) {
homepage = prefServiceBridge.getString(Pref.HOME_PAGE);
assert homepage != null;
}
if (!mIsHomepageLocationPolicyEnabled) { // Early return when nothing changes
mHomepage = ""; if (isEnabled == mIsHomepageLocationPolicyEnabled && homepage.equals(mHomepage)) return;
return;
mIsHomepageLocationPolicyEnabled = isEnabled;
mHomepage = homepage;
// Update shared preference
mSharedPreferenceManager.writeString(
ChromePreferenceKeys.HOMEPAGE_LOCATION_POLICY, mHomepage);
// Update the listeners about the status
for (HomepagePolicyStateListener listener : mListeners) {
listener.onHomepagePolicyUpdate();
} }
}
mHomepage = prefServiceBridge.getString(Pref.HOME_PAGE); /**
assert mHomepage != null; * Called when the native library has finished loading.
*/
private void onFinishNativeInitialization() {
if (!mIsInitializedWithNative) initializeWithNative(new PrefChangeRegistrar());
}
private static boolean isFeatureFlagEnabled() {
return FeatureUtilities.isHomepageLocationPolicyEnabled();
} }
@VisibleForTesting @VisibleForTesting
...@@ -104,24 +207,13 @@ public class HomepagePolicyManager implements PrefObserver { ...@@ -104,24 +207,13 @@ public class HomepagePolicyManager implements PrefObserver {
return mHomepage; return mHomepage;
} }
/** @VisibleForTesting
* If Policies such as HomepageLocation / HomepageIsNewTabPage is enabled on this device, boolean isInitialized() {
* the home page will be marked as managed. return mIsInitializedWithNative;
* @return True if the current home page is managed by enterprice policy.
*/
public static boolean isHomepageManagedByPolicy() {
return isFeatureFlagEnabled() && getInstance().isHomepageLocationPolicyEnabled();
}
private static boolean isFeatureFlagEnabled() {
return ChromeFeatureList.isEnabled(ChromeFeatureList.HOMEPAGE_LOCATION_POLICY);
} }
/** @VisibleForTesting
* @return The homepage URL from native ObserverList<HomepagePolicyStateListener> getListenersForTesting() {
*/ return mListeners;
@NonNull
public static String getHomepageUrl() {
return getInstance().getHomepagePreference();
} }
} }
...@@ -8,6 +8,7 @@ import android.text.TextUtils; ...@@ -8,6 +8,7 @@ import android.text.TextUtils;
import org.chromium.base.ObserverList; import org.chromium.base.ObserverList;
import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.metrics.RecordHistogram;
import org.chromium.chrome.browser.homepage.HomepagePolicyManager;
import org.chromium.chrome.browser.ntp.NewTabPage; import org.chromium.chrome.browser.ntp.NewTabPage;
import org.chromium.chrome.browser.preferences.ChromePreferenceKeys; import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
import org.chromium.chrome.browser.preferences.SharedPreferencesManager; import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
...@@ -18,8 +19,7 @@ import org.chromium.chrome.browser.util.UrlConstants; ...@@ -18,8 +19,7 @@ import org.chromium.chrome.browser.util.UrlConstants;
* *
* This class serves as a single homepage logic gateway. * This class serves as a single homepage logic gateway.
*/ */
public class HomepageManager { public class HomepageManager implements HomepagePolicyManager.HomepagePolicyStateListener {
/** /**
* An interface to use for getting homepage related updates. * An interface to use for getting homepage related updates.
*/ */
...@@ -38,6 +38,7 @@ public class HomepageManager { ...@@ -38,6 +38,7 @@ public class HomepageManager {
private HomepageManager() { private HomepageManager() {
mSharedPreferencesManager = SharedPreferencesManager.getInstance(); mSharedPreferencesManager = SharedPreferencesManager.getInstance();
mHomepageStateListeners = new ObserverList<>(); mHomepageStateListeners = new ObserverList<>();
HomepagePolicyManager.getInstance().addListener(this);
} }
/** /**
...@@ -78,7 +79,8 @@ public class HomepageManager { ...@@ -78,7 +79,8 @@ public class HomepageManager {
* @return Whether or not homepage is enabled. * @return Whether or not homepage is enabled.
*/ */
public static boolean isHomepageEnabled() { public static boolean isHomepageEnabled() {
return getInstance().getPrefHomepageEnabled(); return HomepagePolicyManager.isHomepageManagedByPolicy()
|| getInstance().getPrefHomepageEnabled();
} }
/** /**
...@@ -107,9 +109,13 @@ public class HomepageManager { ...@@ -107,9 +109,13 @@ public class HomepageManager {
* if the homepage button is force enabled via flag. * if the homepage button is force enabled via flag.
*/ */
public static String getDefaultHomepageUri() { public static String getDefaultHomepageUri() {
return PartnerBrowserCustomizations.isHomepageProviderAvailableAndEnabled() if (HomepagePolicyManager.isHomepageManagedByPolicy()) {
? PartnerBrowserCustomizations.getHomePageUrl() return HomepagePolicyManager.getHomepageUrl();
: UrlConstants.NTP_NON_NATIVE_URL; }
if (PartnerBrowserCustomizations.isHomepageProviderAvailableAndEnabled()) {
return PartnerBrowserCustomizations.getHomePageUrl();
}
return UrlConstants.NTP_NON_NATIVE_URL;
} }
/** /**
...@@ -118,7 +124,7 @@ public class HomepageManager { ...@@ -118,7 +124,7 @@ public class HomepageManager {
* *
* @see #isHomepageEnabled * @see #isHomepageEnabled
*/ */
public boolean getPrefHomepageEnabled() { private boolean getPrefHomepageEnabled() {
return mSharedPreferencesManager.readBoolean(ChromePreferenceKeys.HOMEPAGE_ENABLED, true); return mSharedPreferencesManager.readBoolean(ChromePreferenceKeys.HOMEPAGE_ENABLED, true);
} }
...@@ -152,7 +158,8 @@ public class HomepageManager { ...@@ -152,7 +158,8 @@ public class HomepageManager {
*/ */
public boolean getPrefHomepageUseDefaultUri() { public boolean getPrefHomepageUseDefaultUri() {
return mSharedPreferencesManager.readBoolean( return mSharedPreferencesManager.readBoolean(
ChromePreferenceKeys.HOMEPAGE_USE_DEFAULT_URI, true); ChromePreferenceKeys.HOMEPAGE_USE_DEFAULT_URI, true)
|| HomepagePolicyManager.isHomepageManagedByPolicy();
} }
/** /**
...@@ -163,4 +170,9 @@ public class HomepageManager { ...@@ -163,4 +170,9 @@ public class HomepageManager {
mSharedPreferencesManager.writeBoolean( mSharedPreferencesManager.writeBoolean(
ChromePreferenceKeys.HOMEPAGE_USE_DEFAULT_URI, useDefaultUri); ChromePreferenceKeys.HOMEPAGE_USE_DEFAULT_URI, useDefaultUri);
} }
@Override
public void onHomepagePolicyUpdate() {
notifyHomepageUpdated();
}
} }
...@@ -209,7 +209,7 @@ public class MainPreferences extends PreferenceFragmentCompat ...@@ -209,7 +209,7 @@ public class MainPreferences extends PreferenceFragmentCompat
updateSearchEnginePreference(); updateSearchEnginePreference();
Preference homepagePref = addPreferenceIfAbsent(PREF_HOMEPAGE); Preference homepagePref = addPreferenceIfAbsent(PREF_HOMEPAGE);
setOnOffSummary(homepagePref, HomepageManager.getInstance().getPrefHomepageEnabled()); setOnOffSummary(homepagePref, HomepageManager.isHomepageEnabled());
if (NightModeUtils.isNightModeSupported() && FeatureUtilities.isNightModeAvailable()) { if (NightModeUtils.isNightModeSupported() && FeatureUtilities.isNightModeAvailable()) {
addPreferenceIfAbsent(PREF_UI_THEME); addPreferenceIfAbsent(PREF_UI_THEME);
......
...@@ -121,6 +121,7 @@ public class ManagedPreferencesUtils { ...@@ -121,6 +121,7 @@ public class ManagedPreferencesUtils {
if (delegate.isPreferenceClickDisabledByPolicy(preference)) { if (delegate.isPreferenceClickDisabledByPolicy(preference)) {
// Disable the views and prevent the Preference from mucking with the enabled state. // Disable the views and prevent the Preference from mucking with the enabled state.
preference.setShouldDisableView(false); preference.setShouldDisableView(false);
preference.setEnabled(false);
// Prevent default click behavior. // Prevent default click behavior.
preference.setFragment(null); preference.setFragment(null);
......
...@@ -12,8 +12,10 @@ import androidx.annotation.VisibleForTesting; ...@@ -12,8 +12,10 @@ import androidx.annotation.VisibleForTesting;
import org.chromium.chrome.R; import org.chromium.chrome.R;
import org.chromium.chrome.browser.flags.FeatureUtilities; import org.chromium.chrome.browser.flags.FeatureUtilities;
import org.chromium.chrome.browser.homepage.HomepagePolicyManager;
import org.chromium.chrome.browser.partnercustomizations.HomepageManager; import org.chromium.chrome.browser.partnercustomizations.HomepageManager;
import org.chromium.chrome.browser.settings.ChromeSwitchPreference; import org.chromium.chrome.browser.settings.ChromeSwitchPreference;
import org.chromium.chrome.browser.settings.ManagedPreferenceDelegate;
import org.chromium.chrome.browser.settings.SettingsUtils; import org.chromium.chrome.browser.settings.SettingsUtils;
/** /**
...@@ -22,7 +24,19 @@ import org.chromium.chrome.browser.settings.SettingsUtils; ...@@ -22,7 +24,19 @@ import org.chromium.chrome.browser.settings.SettingsUtils;
public class HomepageSettings extends PreferenceFragmentCompat { public class HomepageSettings extends PreferenceFragmentCompat {
@VisibleForTesting @VisibleForTesting
public static final String PREF_HOMEPAGE_SWITCH = "homepage_switch"; public static final String PREF_HOMEPAGE_SWITCH = "homepage_switch";
private static final String PREF_HOMEPAGE_EDIT = "homepage_edit"; @VisibleForTesting
public static final String PREF_HOMEPAGE_EDIT = "homepage_edit";
/**
* Delegate used to mark that the homepage is being managed.
* Created for {@link org.chromium.chrome.browser.settings.HomepagePreferences}
*/
private static class HomepageManagedPreferenceDelegate implements ManagedPreferenceDelegate {
@Override
public boolean isPreferenceControlledByPolicy(Preference preference) {
return HomepagePolicyManager.isHomepageManagedByPolicy();
}
}
private HomepageManager mHomepageManager; private HomepageManager mHomepageManager;
private Preference mHomepageEdit; private Preference mHomepageEdit;
...@@ -36,11 +50,12 @@ public class HomepageSettings extends PreferenceFragmentCompat { ...@@ -36,11 +50,12 @@ public class HomepageSettings extends PreferenceFragmentCompat {
ChromeSwitchPreference homepageSwitch = ChromeSwitchPreference homepageSwitch =
(ChromeSwitchPreference) findPreference(PREF_HOMEPAGE_SWITCH); (ChromeSwitchPreference) findPreference(PREF_HOMEPAGE_SWITCH);
homepageSwitch.setManagedPreferenceDelegate(new HomepageManagedPreferenceDelegate());
if (FeatureUtilities.isBottomToolbarEnabled()) { if (FeatureUtilities.isBottomToolbarEnabled()) {
homepageSwitch.setVisible(false); homepageSwitch.setVisible(false);
} else { } else {
boolean isHomepageEnabled = mHomepageManager.getPrefHomepageEnabled(); boolean isHomepageEnabled = HomepageManager.isHomepageEnabled();
homepageSwitch.setChecked(isHomepageEnabled); homepageSwitch.setChecked(isHomepageEnabled);
homepageSwitch.setOnPreferenceChangeListener((preference, newValue) -> { homepageSwitch.setOnPreferenceChangeListener((preference, newValue) -> {
mHomepageManager.setPrefHomepageEnabled((boolean) newValue); mHomepageManager.setPrefHomepageEnabled((boolean) newValue);
...@@ -53,6 +68,8 @@ public class HomepageSettings extends PreferenceFragmentCompat { ...@@ -53,6 +68,8 @@ public class HomepageSettings extends PreferenceFragmentCompat {
} }
private void updateCurrentHomepageUrl() { private void updateCurrentHomepageUrl() {
if (HomepagePolicyManager.isHomepageManagedByPolicy()) mHomepageEdit.setEnabled(false);
mHomepageEdit.setSummary(mHomepageManager.getPrefHomepageUseDefaultUri() mHomepageEdit.setSummary(mHomepageManager.getPrefHomepageUseDefaultUri()
? HomepageManager.getDefaultHomepageUri() ? HomepageManager.getDefaultHomepageUri()
: mHomepageManager.getPrefHomepageCustomUri()); : mHomepageManager.getPrefHomepageCustomUri());
......
...@@ -22,6 +22,7 @@ import org.chromium.chrome.browser.ActivityTabProvider.ActivityTabTabObserver; ...@@ -22,6 +22,7 @@ import org.chromium.chrome.browser.ActivityTabProvider.ActivityTabTabObserver;
import org.chromium.chrome.browser.ThemeColorProvider; import org.chromium.chrome.browser.ThemeColorProvider;
import org.chromium.chrome.browser.ThemeColorProvider.TintObserver; import org.chromium.chrome.browser.ThemeColorProvider.TintObserver;
import org.chromium.chrome.browser.flags.FeatureUtilities; import org.chromium.chrome.browser.flags.FeatureUtilities;
import org.chromium.chrome.browser.homepage.HomepagePolicyManager;
import org.chromium.chrome.browser.ntp.NewTabPage; import org.chromium.chrome.browser.ntp.NewTabPage;
import org.chromium.chrome.browser.partnercustomizations.HomepageManager; import org.chromium.chrome.browser.partnercustomizations.HomepageManager;
import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.Tab;
...@@ -49,11 +50,8 @@ public class HomeButton extends ChromeImageButton ...@@ -49,11 +50,8 @@ public class HomeButton extends ChromeImageButton
final int homeButtonIcon = R.drawable.btn_toolbar_home; final int homeButtonIcon = R.drawable.btn_toolbar_home;
setImageDrawable(ContextCompat.getDrawable(context, homeButtonIcon)); setImageDrawable(ContextCompat.getDrawable(context, homeButtonIcon));
if (!FeatureUtilities.isBottomToolbarEnabled()) {
setOnCreateContextMenuListener(this);
}
HomepageManager.getInstance().addListener(this); HomepageManager.getInstance().addListener(this);
updateContextMenuListener();
} }
public void destroy() { public void destroy() {
...@@ -88,6 +86,7 @@ public class HomeButton extends ChromeImageButton ...@@ -88,6 +86,7 @@ public class HomeButton extends ChromeImageButton
@Override @Override
public boolean onMenuItemClick(MenuItem item) { public boolean onMenuItemClick(MenuItem item) {
assert item.getItemId() == ID_REMOVE; assert item.getItemId() == ID_REMOVE;
assert !isManagedByPolicy();
HomepageManager.getInstance().setPrefHomepageEnabled(false); HomepageManager.getInstance().setPrefHomepageEnabled(false);
return true; return true;
} }
...@@ -137,6 +136,7 @@ public class HomeButton extends ChromeImageButton ...@@ -137,6 +136,7 @@ public class HomeButton extends ChromeImageButton
isEnabled = !isTabNTP(tab); isEnabled = !isTabNTP(tab);
} }
setEnabled(isEnabled); setEnabled(isEnabled);
updateContextMenuListener();
} }
/** /**
...@@ -156,4 +156,17 @@ public class HomeButton extends ChromeImageButton ...@@ -156,4 +156,17 @@ public class HomeButton extends ChromeImageButton
return mActivityTabProvider.get(); return mActivityTabProvider.get();
} }
private boolean isManagedByPolicy() {
return HomepagePolicyManager.isHomepageManagedByPolicy();
}
private void updateContextMenuListener() {
if (!FeatureUtilities.isBottomToolbarEnabled() && !isManagedByPolicy()) {
setOnCreateContextMenuListener(this);
} else {
setOnCreateContextMenuListener(null);
setLongClickable(false);
}
}
} }
...@@ -2096,4 +2096,15 @@ public class ToolbarManager implements ScrimObserver, ToolbarTabController, UrlF ...@@ -2096,4 +2096,15 @@ public class ToolbarManager implements ScrimObserver, ToolbarTabController, UrlF
public ToolbarLayout getToolbarLayoutForTesting() { public ToolbarLayout getToolbarLayoutForTesting() {
return mToolbar.getToolbarLayoutForTesting(); return mToolbar.getToolbarLayoutForTesting();
} }
/**
* Get the home button on the top toolbar to verify the button status.
* Note that this home button is not always the home button that on the UI, and the button is
* not always visible.
* @return The {@link HomeButton} that lives in the top toolbar.
*/
@VisibleForTesting
public HomeButton getHomeButtonForTesting() {
return mToolbar.getToolbarLayoutForTesting().getHomeButtonForTesting();
}
} }
...@@ -40,6 +40,7 @@ import org.chromium.chrome.browser.omnibox.UrlBarData; ...@@ -40,6 +40,7 @@ import org.chromium.chrome.browser.omnibox.UrlBarData;
import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.chrome.browser.tabmodel.TabModelSelector;
import org.chromium.chrome.browser.toolbar.HomeButton;
import org.chromium.chrome.browser.toolbar.MenuButton; import org.chromium.chrome.browser.toolbar.MenuButton;
import org.chromium.chrome.browser.toolbar.TabCountProvider; import org.chromium.chrome.browser.toolbar.TabCountProvider;
import org.chromium.chrome.browser.toolbar.ToolbarColors; import org.chromium.chrome.browser.toolbar.ToolbarColors;
...@@ -923,4 +924,12 @@ public abstract class ToolbarLayout ...@@ -923,4 +924,12 @@ public abstract class ToolbarLayout
* it. * it.
*/ */
void setTabModelSelector(TabModelSelector selector) {} void setTabModelSelector(TabModelSelector selector) {}
/**
* @return {@link HomeButton} this {@link ToolbarLayout} contains.
*/
@VisibleForTesting
public HomeButton getHomeButtonForTesting() {
return null;
}
} }
...@@ -1684,6 +1684,11 @@ public class ToolbarPhone extends ToolbarLayout implements Invalidator.Client, O ...@@ -1684,6 +1684,11 @@ public class ToolbarPhone extends ToolbarLayout implements Invalidator.Client, O
if (mLayoutUpdateHost != null) mLayoutUpdateHost.requestUpdate(); if (mLayoutUpdateHost != null) mLayoutUpdateHost.requestUpdate();
} }
@Override
public HomeButton getHomeButtonForTesting() {
return mHomeButton;
}
private void removeHomeButton() { private void removeHomeButton() {
mHomeButton.setVisibility(GONE); mHomeButton.setVisibility(GONE);
} }
......
...@@ -595,6 +595,11 @@ public class ToolbarTablet extends ToolbarLayout ...@@ -595,6 +595,11 @@ public class ToolbarTablet extends ToolbarLayout
return mExperimentalButton; return mExperimentalButton;
} }
@Override
public HomeButton getHomeButtonForTesting() {
return mHomeButton;
}
private void setToolbarButtonsVisible(boolean visible) { private void setToolbarButtonsVisible(boolean visible) {
if (mToolbarButtonsVisible == visible) return; if (mToolbarButtonsVisible == visible) return;
......
// 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.homepage;
import android.content.Intent;
import android.support.test.InstrumentationRegistry;
import android.support.test.filters.MediumTest;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceFragmentCompat;
import android.view.View;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.chromium.base.ActivityState;
import org.chromium.base.ApplicationStatus;
import org.chromium.base.metrics.RecordHistogram;
import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.base.test.util.Feature;
import org.chromium.chrome.browser.ChromeFeatureList;
import org.chromium.chrome.browser.ChromeSwitches;
import org.chromium.chrome.browser.ChromeTabbedActivity;
import org.chromium.chrome.browser.flags.FeatureUtilities;
import org.chromium.chrome.browser.partnercustomizations.HomepageManager;
import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
import org.chromium.chrome.browser.settings.ChromeSwitchPreference;
import org.chromium.chrome.browser.settings.SettingsActivity;
import org.chromium.chrome.browser.settings.homepage.HomepageSettings;
import org.chromium.chrome.browser.toolbar.HomeButton;
import org.chromium.chrome.browser.toolbar.ToolbarManager;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
import org.chromium.chrome.test.util.ChromeTabUtils;
import org.chromium.chrome.test.util.browser.Features;
import org.chromium.chrome.test.util.browser.TabLoadObserver;
import org.chromium.content_public.browser.test.util.Criteria;
import org.chromium.content_public.browser.test.util.CriteriaHelper;
import org.chromium.content_public.browser.test.util.TestThreadUtils;
import org.chromium.content_public.browser.test.util.TouchCommon;
import org.chromium.net.test.EmbeddedTestServer;
import org.chromium.policy.test.annotations.Policies;
/**
* Integration test for {@link HomepagePolicyManager}.
* Checking if enabling HomepageLocation policy will reflect the expected behaviors for
* {@link HomepageSettings} and {@link org.chromium.chrome.browser.toolbar.HomeButton}
*/
// clang-format off
@RunWith(ChromeJUnit4ClassRunner.class)
@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
@Features.EnableFeatures(ChromeFeatureList.HOMEPAGE_LOCATION_POLICY)
@Policies.Add({
@Policies.Item(key = "HomepageLocation", string = HomepagePolicyIntegrationTest.TEST_URL)
})
public class HomepagePolicyIntegrationTest {
// clang-format on
public static final String TEST_URL = "http://127.0.0.1:8000/foo.html";
public static final String GOOGLE_HTML = "/chrome/test/data/android/google.html";
private EmbeddedTestServer mTestServer;
@Rule
public ChromeTabbedActivityTestRule mActivityTestRule = new ChromeTabbedActivityTestRule();
@Before
public void setUp() {
// Disable Histogram for tests.
RecordHistogram.setDisabledForTests(true);
FeatureUtilities.setHomepageLocationPolicyEnabledForTesting(true);
// Give some user pref setting, simulate user that have their customized preference.
// Use shared preference manager, not to change the order object created in tests.
SharedPreferencesManager manager = SharedPreferencesManager.getInstance();
manager.writeBoolean(ChromePreferenceKeys.HOMEPAGE_ENABLED, true);
manager.writeString(ChromePreferenceKeys.HOMEPAGE_CUSTOM_URI, GOOGLE_HTML);
manager.writeBoolean(ChromePreferenceKeys.HOMEPAGE_USE_DEFAULT_URI, false);
mActivityTestRule.startMainActivityFromLauncher();
mTestServer = EmbeddedTestServer.createAndStartServer(
InstrumentationRegistry.getInstrumentation().getContext());
}
@After
public void tearDown() {
mTestServer.stopAndDestroyServer();
RecordHistogram.setDisabledForTests(false);
FeatureUtilities.setHomepageLocationPolicyEnabledForTesting(null);
}
@Test
@MediumTest
@Feature({"Homepage"})
public void testStartUpPage() {
TestThreadUtils.runOnUiThreadBlocking(
()
-> Assert.assertTrue("HomepageLocation Policy should be enforced",
HomepagePolicyManager.isHomepageManagedByPolicy()));
// The first time when the page starts, the homepage is fetched from shared preference
// So the homepage policy is not enforced yet at this point.
// Instead, we verify the shared preference to see if right policy URL were stored.
Assert.assertEquals("URL stored in shared preference should be the same as policy setting",
TEST_URL,
SharedPreferencesManager.getInstance().readString(
ChromePreferenceKeys.HOMEPAGE_LOCATION_POLICY, ""));
// Start the page again. This time, the homepage should be set to what policy is.
destroyAndRestartActivity();
Assert.assertEquals("Start up homepage should be the same as the policy setting", TEST_URL,
mActivityTestRule.getActivity().getActivityTab().getUrl());
}
@Test
@MediumTest
@Feature({"Homepage"})
public void testHomeButton() throws Exception {
String anotherUrl = mTestServer.getURL(GOOGLE_HTML);
new TabLoadObserver(mActivityTestRule.getActivity().getActivityTab())
.fullyLoadUrl(anotherUrl);
Assert.assertNotEquals("Did not switch to a different URL", TEST_URL,
mActivityTestRule.getActivity().getActivityTab().getUrl());
ChromeTabUtils.waitForTabPageLoaded(
mActivityTestRule.getActivity().getActivityTab(), TEST_URL, () -> {
ToolbarManager toolbarManager =
mActivityTestRule.getActivity().getToolbarManager();
if (toolbarManager != null) {
HomeButton homeButton = toolbarManager.getHomeButtonForTesting();
if (homeButton != null) {
Assert.assertEquals("Home Button should be visible", View.VISIBLE,
homeButton.getVisibility());
// Context menu is disabled by checking long clickable
Assert.assertFalse("Long press for home button should be disabled",
homeButton.isLongClickable());
TouchCommon.singleClickView(homeButton);
}
}
});
Assert.assertEquals("After clicking HomeButton, URL should be back to Homepage", TEST_URL,
mActivityTestRule.getActivity().getActivityTab().getUrl());
}
@Test
@MediumTest
@Feature({"Homepage"})
public void testHomepagePreference() {
// Launch homepage preference page
SettingsActivity homepagePreferenceActivity =
mActivityTestRule.startSettingsActivity(HomepageSettings.class.getName());
PreferenceFragmentCompat fragment =
(PreferenceFragmentCompat) homepagePreferenceActivity.getSupportFragmentManager()
.findFragmentById(android.R.id.content);
Assert.assertNotNull(fragment);
ChromeSwitchPreference homepageSwitch = (ChromeSwitchPreference) fragment.findPreference(
HomepageSettings.PREF_HOMEPAGE_SWITCH);
Preference homepageEdit = fragment.findPreference(HomepageSettings.PREF_HOMEPAGE_EDIT);
Assert.assertNotNull(homepageSwitch);
Assert.assertNotNull(homepageEdit);
TestThreadUtils.runOnUiThreadBlocking(() -> {
Assert.assertFalse("Switch should be disabled", homepageSwitch.isEnabled());
Assert.assertTrue("Switch should be checked", homepageSwitch.isChecked());
Assert.assertFalse(
"Homepage Edit should be disabled under policy", homepageEdit.isEnabled());
Assert.assertEquals("Homepage Url should be set as policy setting",
homepageEdit.getSummary(), TEST_URL);
});
}
private void destroyAndRestartActivity() {
ChromeTabbedActivity activity = mActivityTestRule.getActivity();
// Create an intent to launch a new ChromeTabbedActivity.
Intent intent = new Intent();
intent.setClass(activity, ChromeTabbedActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// Close all tabs so the new activity will create another initial tab with current homepage.
TestThreadUtils.runOnUiThreadBlocking(
() -> { activity.getTabModelSelector().closeAllTabs(); });
activity.finish();
CriteriaHelper.pollUiThread(new Criteria("Activity should be destroyed, current state: "
+ ApplicationStatus.getStateForActivity(activity)) {
@Override
public boolean isSatisfied() {
return ApplicationStatus.getStateForActivity(activity) == ActivityState.DESTROYED;
}
});
// Start a new ChromeActivity.
mActivityTestRule.startActivityCompletely(intent);
Assert.assertEquals("Start up page is not homepage", HomepageManager.getHomepageUri(),
mActivityTestRule.getActivity().getActivityTab().getUrl());
}
}
...@@ -359,6 +359,11 @@ public final class ChromePreferenceKeys { ...@@ -359,6 +359,11 @@ public final class ChromePreferenceKeys {
public static final String HOMEPAGE_ENABLED = "homepage"; public static final String HOMEPAGE_ENABLED = "homepage";
public static final String HOMEPAGE_USE_DEFAULT_URI = "homepage_partner_enabled"; public static final String HOMEPAGE_USE_DEFAULT_URI = "homepage_partner_enabled";
/**
* Key used to save homepage location set by enterprise policy
*/
public static final String HOMEPAGE_LOCATION_POLICY = "Chrome.Policy.HomepageLocation";
/** /**
* When the user is shown a badge that the current Android OS version is unsupported, and they * When the user is shown a badge that the current Android OS version is unsupported, and they
* tap it to display the menu (which has additional information), we store the current version * tap it to display the menu (which has additional information), we store the current version
...@@ -546,6 +551,7 @@ public final class ChromePreferenceKeys { ...@@ -546,6 +551,7 @@ public final class ChromePreferenceKeys {
HOMEPAGE_CUSTOM_URI, HOMEPAGE_CUSTOM_URI,
HOMEPAGE_ENABLED, HOMEPAGE_ENABLED,
HOMEPAGE_USE_DEFAULT_URI, HOMEPAGE_USE_DEFAULT_URI,
HOMEPAGE_LOCATION_POLICY,
LATEST_UNSUPPORTED_VERSION, LATEST_UNSUPPORTED_VERSION,
OFFLINE_INDICATOR_V2_ENABLED, OFFLINE_INDICATOR_V2_ENABLED,
PROMOS_SKIPPED_ON_FIRST_START, PROMOS_SKIPPED_ON_FIRST_START,
......
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