| // Copyright 2015 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.preferences; |
| |
| import android.content.Intent; |
| import android.os.Build; |
| import android.os.Bundle; |
| import android.os.Handler; |
| import android.preference.Preference; |
| import android.preference.PreferenceFragment; |
| import android.provider.Settings; |
| |
| import org.chromium.base.ContextUtils; |
| import org.chromium.base.VisibleForTesting; |
| import org.chromium.chrome.R; |
| import org.chromium.chrome.browser.AppHooks; |
| import org.chromium.chrome.browser.ChromeFeatureList; |
| import org.chromium.chrome.browser.contextual_suggestions.ContextualSuggestionsEnabledStateUtils; |
| import org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings; |
| import org.chromium.chrome.browser.partnercustomizations.HomepageManager; |
| import org.chromium.chrome.browser.password_manager.ManagePasswordsReferrer; |
| import org.chromium.chrome.browser.preferences.datareduction.DataReductionPreferences; |
| import org.chromium.chrome.browser.preferences.developer.DeveloperPreferences; |
| import org.chromium.chrome.browser.search_engines.TemplateUrl; |
| import org.chromium.chrome.browser.search_engines.TemplateUrlService; |
| import org.chromium.chrome.browser.signin.SigninManager; |
| import org.chromium.chrome.browser.util.FeatureUtilities; |
| |
| import java.util.HashMap; |
| import java.util.Map; |
| |
| /** |
| * The main settings screen, shown when the user first opens Settings. |
| */ |
| public class MainPreferences extends PreferenceFragment |
| implements SigninManager.SignInStateObserver, TemplateUrlService.LoadListener { |
| public static final String PREF_ACCOUNT_SECTION = "account_section"; |
| public static final String PREF_SIGN_IN = "sign_in"; |
| public static final String PREF_SYNC_AND_SERVICES = "sync_and_services"; |
| public static final String PREF_SEARCH_ENGINE = "search_engine"; |
| public static final String PREF_SAVED_PASSWORDS = "saved_passwords"; |
| public static final String PREF_CONTEXTUAL_SUGGESTIONS = "contextual_suggestions"; |
| public static final String PREF_HOMEPAGE = "homepage"; |
| public static final String PREF_DATA_REDUCTION = "data_reduction"; |
| public static final String PREF_NOTIFICATIONS = "notifications"; |
| public static final String PREF_LANGUAGES = "languages"; |
| public static final String PREF_DOWNLOADS = "downloads"; |
| public static final String PREF_DEVELOPER = "developer"; |
| public static final String PREF_AUTOFILL_ASSISTANT = "autofill_assistant"; |
| |
| public static final String AUTOFILL_GUID = "guid"; |
| // Needs to be in sync with kSettingsOrigin[] in |
| // chrome/browser/ui/webui/options/autofill_options_handler.cc |
| public static final String SETTINGS_ORIGIN = "Chrome settings"; |
| |
| private final ManagedPreferenceDelegate mManagedPreferenceDelegate; |
| private final Map<String, Preference> mAllPreferences = new HashMap<>(); |
| private SignInPreference mSignInPreference; |
| |
| public MainPreferences() { |
| setHasOptionsMenu(true); |
| mManagedPreferenceDelegate = createManagedPreferenceDelegate(); |
| } |
| |
| @Override |
| public void onCreate(Bundle savedInstanceState) { |
| super.onCreate(savedInstanceState); |
| createPreferences(); |
| } |
| |
| @Override |
| public void onDestroy() { |
| super.onDestroy(); |
| mSignInPreference.onPreferenceFragmentDestroyed(); |
| } |
| |
| @Override |
| public void onStart() { |
| super.onStart(); |
| if (SigninManager.get().isSigninSupported()) { |
| SigninManager.get().addSignInStateObserver(this); |
| mSignInPreference.registerForUpdates(); |
| } |
| } |
| |
| @Override |
| public void onStop() { |
| super.onStop(); |
| if (SigninManager.get().isSigninSupported()) { |
| SigninManager.get().removeSignInStateObserver(this); |
| mSignInPreference.unregisterForUpdates(); |
| } |
| } |
| |
| @Override |
| public void onResume() { |
| super.onResume(); |
| updatePreferences(); |
| } |
| |
| private void createPreferences() { |
| PreferenceUtils.addPreferencesFromResource(this, R.xml.main_preferences); |
| cachePreferences(); |
| |
| if (ChromeFeatureList.isEnabled(ChromeFeatureList.UNIFIED_CONSENT)) { |
| mSignInPreference.setOnStateChangedCallback(this::onSignInPreferenceStateChanged); |
| } else { |
| getPreferenceScreen().removePreference(findPreference(PREF_ACCOUNT_SECTION)); |
| getPreferenceScreen().removePreference(findPreference(PREF_SYNC_AND_SERVICES)); |
| } |
| |
| setManagedPreferenceDelegateForPreference(PREF_SEARCH_ENGINE); |
| setManagedPreferenceDelegateForPreference(PREF_SAVED_PASSWORDS); |
| setManagedPreferenceDelegateForPreference(PREF_DATA_REDUCTION); |
| |
| updatePasswordsPreference(); |
| |
| if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { |
| // If we are on Android O+ the Notifications preference should lead to the Android |
| // Settings notifications page, not to Chrome's notifications settings page. |
| Preference notifications = findPreference(PREF_NOTIFICATIONS); |
| notifications.setOnPreferenceClickListener(preference -> { |
| Intent intent = new Intent(); |
| intent.setAction(Settings.ACTION_APP_NOTIFICATION_SETTINGS); |
| intent.putExtra(Settings.EXTRA_APP_PACKAGE, |
| ContextUtils.getApplicationContext().getPackageName()); |
| startActivity(intent); |
| // We handle the click so the default action (opening NotificationsPreference) |
| // isn't triggered. |
| return true; |
| }); |
| } else if (!ChromeFeatureList.isEnabled( |
| ChromeFeatureList.CONTENT_SUGGESTIONS_NOTIFICATIONS)) { |
| // The Notifications Preferences page currently only contains the Content Suggestions |
| // Notifications setting and a link to per-website notification settings. The latter can |
| // be access through Site Settings, so if the Content Suggestions Notifications feature |
| // isn't enabled we don't show the Notifications Preferences page. |
| |
| // This checks whether the Content Suggestions Notifications *feature* is enabled on the |
| // user's device, not whether the user has Content Suggestions Notifications themselves |
| // enabled (which is what the user can toggle on the Notifications Preferences page). |
| getPreferenceScreen().removePreference(findPreference(PREF_NOTIFICATIONS)); |
| } |
| |
| // This checks whether the Languages Preference *feature* is enabled on the user's device. |
| // If not, remove the languages preference. |
| if (!ChromeFeatureList.isEnabled(ChromeFeatureList.LANGUAGES_PREFERENCE)) { |
| getPreferenceScreen().removePreference(findPreference(PREF_LANGUAGES)); |
| } |
| |
| if (!TemplateUrlService.getInstance().isLoaded()) { |
| TemplateUrlService.getInstance().registerLoadListener(this); |
| TemplateUrlService.getInstance().load(); |
| } |
| |
| // This checks whether the flag for Downloads Preferences is enabled. |
| if (!ChromeFeatureList.isEnabled(ChromeFeatureList.DOWNLOADS_LOCATION_CHANGE)) { |
| getPreferenceScreen().removePreference(findPreference(PREF_DOWNLOADS)); |
| } |
| |
| // This checks whether Autofill Assistant is enabled. |
| if (!ChromeFeatureList.isEnabled(ChromeFeatureList.AUTOFILL_ASSISTANT)) { |
| getPreferenceScreen().removePreference(findPreference(PREF_AUTOFILL_ASSISTANT)); |
| } |
| } |
| |
| /** |
| * Stores all preferences in memory so that, if they needed to be added/removed from the |
| * PreferenceScreen, there would be no need to reload them from 'main_preferences.xml'. |
| */ |
| private void cachePreferences() { |
| int preferenceCount = getPreferenceScreen().getPreferenceCount(); |
| for (int index = 0; index < preferenceCount; index++) { |
| Preference preference = getPreferenceScreen().getPreference(index); |
| mAllPreferences.put(preference.getKey(), preference); |
| } |
| mSignInPreference = (SignInPreference) mAllPreferences.get(PREF_SIGN_IN); |
| } |
| |
| private void setManagedPreferenceDelegateForPreference(String key) { |
| ChromeBasePreference chromeBasePreference = (ChromeBasePreference) mAllPreferences.get(key); |
| chromeBasePreference.setManagedPreferenceDelegate(mManagedPreferenceDelegate); |
| } |
| |
| private void updatePreferences() { |
| if (SigninManager.get().isSigninSupported()) { |
| addPreferenceIfAbsent(PREF_SIGN_IN); |
| } else { |
| removePreferenceIfPresent(PREF_SIGN_IN); |
| } |
| |
| updateSearchEnginePreference(); |
| |
| if (HomepageManager.shouldShowHomepageSetting()) { |
| Preference homepagePref = addPreferenceIfAbsent(PREF_HOMEPAGE); |
| if (FeatureUtilities.isNewTabPageButtonEnabled()) { |
| homepagePref.setTitle(R.string.options_startup_page_title); |
| } |
| setOnOffSummary(homepagePref, HomepageManager.getInstance().getPrefHomepageEnabled()); |
| } else { |
| removePreferenceIfPresent(PREF_HOMEPAGE); |
| } |
| |
| if (!ChromeFeatureList.isEnabled(ChromeFeatureList.UNIFIED_CONSENT) |
| && FeatureUtilities.areContextualSuggestionsEnabled(getActivity()) |
| && ContextualSuggestionsEnabledStateUtils.shouldShowSettings()) { |
| Preference contextualSuggestions = addPreferenceIfAbsent(PREF_CONTEXTUAL_SUGGESTIONS); |
| setOnOffSummary(contextualSuggestions, |
| ContextualSuggestionsEnabledStateUtils.getEnabledState()); |
| } else { |
| removePreferenceIfPresent(PREF_CONTEXTUAL_SUGGESTIONS); |
| } |
| |
| if (DeveloperPreferences.shouldShowDeveloperPreferences()) { |
| addPreferenceIfAbsent(PREF_DEVELOPER); |
| } else { |
| removePreferenceIfPresent(PREF_DEVELOPER); |
| } |
| |
| ChromeBasePreference dataReduction = |
| (ChromeBasePreference) findPreference(PREF_DATA_REDUCTION); |
| dataReduction.setSummary(DataReductionPreferences.generateSummary(getResources())); |
| } |
| |
| private Preference addPreferenceIfAbsent(String key) { |
| Preference preference = getPreferenceScreen().findPreference(key); |
| if (preference == null) getPreferenceScreen().addPreference(mAllPreferences.get(key)); |
| return mAllPreferences.get(key); |
| } |
| |
| private void removePreferenceIfPresent(String key) { |
| Preference preference = getPreferenceScreen().findPreference(key); |
| if (preference != null) getPreferenceScreen().removePreference(preference); |
| } |
| |
| private void updateSearchEnginePreference() { |
| if (!TemplateUrlService.getInstance().isLoaded()) { |
| ChromeBasePreference searchEnginePref = |
| (ChromeBasePreference) findPreference(PREF_SEARCH_ENGINE); |
| searchEnginePref.setEnabled(false); |
| return; |
| } |
| |
| String defaultSearchEngineName = null; |
| TemplateUrl dseTemplateUrl = |
| TemplateUrlService.getInstance().getDefaultSearchEngineTemplateUrl(); |
| if (dseTemplateUrl != null) defaultSearchEngineName = dseTemplateUrl.getShortName(); |
| |
| Preference searchEnginePreference = findPreference(PREF_SEARCH_ENGINE); |
| searchEnginePreference.setEnabled(true); |
| searchEnginePreference.setSummary(defaultSearchEngineName); |
| } |
| |
| private void updatePasswordsPreference() { |
| Preference passwordsPreference = findPreference(PREF_SAVED_PASSWORDS); |
| passwordsPreference.setOnPreferenceClickListener(preference -> { |
| AppHooks.get().createManagePasswordsUIProvider().showManagePasswordsUI( |
| getActivity(), ManagePasswordsReferrer.CHROME_SETTINGS); |
| return true; |
| }); |
| } |
| |
| private void setOnOffSummary(Preference pref, boolean isOn) { |
| pref.setSummary(getResources().getString(isOn ? R.string.text_on : R.string.text_off)); |
| } |
| |
| // SigninManager.SignInStateObserver implementation. |
| @Override |
| public void onSignedIn() { |
| // After signing in or out of a managed account, preferences may change or become enabled |
| // or disabled. |
| new Handler().post(() -> updatePreferences()); |
| } |
| |
| @Override |
| public void onSignedOut() { |
| updatePreferences(); |
| } |
| |
| private void onSignInPreferenceStateChanged() { |
| // Remove "Account" section header if the personalized sign-in promo is shown. |
| if (mSignInPreference.getState() == SignInPreference.State.PERSONALIZED_PROMO) { |
| removePreferenceIfPresent(PREF_ACCOUNT_SECTION); |
| } else { |
| addPreferenceIfAbsent(PREF_ACCOUNT_SECTION); |
| } |
| } |
| |
| // TemplateUrlService.LoadListener implementation. |
| @Override |
| public void onTemplateUrlServiceLoaded() { |
| TemplateUrlService.getInstance().unregisterLoadListener(this); |
| updateSearchEnginePreference(); |
| } |
| |
| @VisibleForTesting |
| ManagedPreferenceDelegate getManagedPreferenceDelegateForTest() { |
| return mManagedPreferenceDelegate; |
| } |
| |
| private ManagedPreferenceDelegate createManagedPreferenceDelegate() { |
| return new ManagedPreferenceDelegate() { |
| @Override |
| public boolean isPreferenceControlledByPolicy(Preference preference) { |
| if (PREF_SAVED_PASSWORDS.equals(preference.getKey())) { |
| return PrefServiceBridge.getInstance().isRememberPasswordsManaged(); |
| } |
| if (PREF_DATA_REDUCTION.equals(preference.getKey())) { |
| return DataReductionProxySettings.getInstance().isDataReductionProxyManaged(); |
| } |
| if (PREF_SEARCH_ENGINE.equals(preference.getKey())) { |
| return TemplateUrlService.getInstance().isDefaultSearchManaged(); |
| } |
| return false; |
| } |
| |
| @Override |
| public boolean isPreferenceClickDisabledByPolicy(Preference preference) { |
| if (PREF_SAVED_PASSWORDS.equals(preference.getKey())) { |
| PrefServiceBridge prefs = PrefServiceBridge.getInstance(); |
| return prefs.isRememberPasswordsManaged() |
| && !prefs.isRememberPasswordsEnabled(); |
| } |
| if (PREF_DATA_REDUCTION.equals(preference.getKey())) { |
| DataReductionProxySettings settings = DataReductionProxySettings.getInstance(); |
| return settings.isDataReductionProxyManaged() |
| && !settings.isDataReductionProxyEnabled(); |
| } |
| if (PREF_SEARCH_ENGINE.equals(preference.getKey())) { |
| return TemplateUrlService.getInstance().isDefaultSearchManaged(); |
| } |
| return isPreferenceControlledByPolicy(preference) |
| || isPreferenceControlledByCustodian(preference); |
| } |
| }; |
| } |
| } |