Index: chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/PrivacyPreferencesManager.java |
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/PrivacyPreferencesManager.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/PrivacyPreferencesManager.java |
new file mode 100644 |
index 0000000000000000000000000000000000000000..e42e855864baacc9e99764ea00360c32168bee4d |
--- /dev/null |
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/PrivacyPreferencesManager.java |
@@ -0,0 +1,291 @@ |
+// 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.privacy; |
+ |
+import android.content.Context; |
+import android.content.SharedPreferences; |
+import android.net.ConnectivityManager; |
+import android.net.NetworkInfo; |
+import android.preference.PreferenceManager; |
+ |
+import org.chromium.base.CommandLine; |
+import org.chromium.base.VisibleForTesting; |
+import org.chromium.chrome.ChromeSwitches; |
+import org.chromium.chrome.R; |
+import org.chromium.chrome.browser.device.DeviceClassManager; |
+import org.chromium.chrome.browser.preferences.NetworkPredictionOptions; |
+import org.chromium.chrome.browser.preferences.PrefServiceBridge; |
+import org.chromium.chrome.browser.preferences.bandwidth.BandwidthType; |
+ |
+/** |
+ * Reads, writes, and migrates preferences related to network usage and privacy. |
+ */ |
+public class PrivacyPreferencesManager { |
+ |
+ static final String PREF_CRASH_DUMP_UPLOAD = "crash_dump_upload"; |
+ static final String PREF_CRASH_DUMP_UPLOAD_NO_CELLULAR = "crash_dump_upload_no_cellular"; |
+ private static final String PREF_NETWORK_PREDICTIONS = "network_predictions"; |
+ private static final String PREF_BANDWIDTH_OLD = "prefetch_bandwidth"; |
+ private static final String PREF_BANDWIDTH_NO_CELLULAR_OLD = "prefetch_bandwidth_no_cellular"; |
+ private static final String ALLOW_PRERENDER_OLD = "allow_prefetch"; |
+ |
+ private static PrivacyPreferencesManager sInstance; |
+ |
+ private final Context mContext; |
+ private final SharedPreferences mSharedPreferences; |
+ |
+ private boolean mCrashUploadingEnabled; |
+ private final String mCrashDumpNeverUpload; |
+ private final String mCrashDumpWifiOnlyUpload; |
+ private final String mCrashDumpAlwaysUpload; |
+ |
+ @VisibleForTesting |
+ PrivacyPreferencesManager(Context context) { |
+ mContext = context; |
+ mSharedPreferences = PreferenceManager.getDefaultSharedPreferences(context); |
+ mCrashUploadingEnabled = true; |
+ mCrashDumpNeverUpload = context.getString(R.string.crash_dump_never_upload_value); |
+ mCrashDumpWifiOnlyUpload = context.getString(R.string.crash_dump_only_with_wifi_value); |
+ mCrashDumpAlwaysUpload = context.getString(R.string.crash_dump_always_upload_value); |
+ } |
+ |
+ public static PrivacyPreferencesManager getInstance(Context context) { |
+ if (sInstance == null) { |
+ sInstance = new PrivacyPreferencesManager(context); |
+ } |
+ return sInstance; |
+ } |
+ |
+ /** |
+ * Returns the Crash Dump Upload preference value. |
+ * @return String value of the preference. |
+ */ |
+ public String getPrefCrashDumpUploadPreference() { |
+ return mSharedPreferences.getString(PREF_CRASH_DUMP_UPLOAD, |
+ mCrashDumpNeverUpload); |
+ } |
+ |
+ /** |
+ * Migrate and delete old preferences. Note that migration has to happen in Android-specific |
+ * code because we need to access ALLOW_PRERENDER sharedPreference. |
+ * TODO(bnc) https://crbug.com/394845. This change is planned for M38. After a year or so, it |
+ * would be worth considering removing this migration code (also removing accessors in |
+ * PrefServiceBridge and pref_service_bridge), and reverting to default for users |
+ * who had set preferences but have not used Chrome for a year. This change would be subject to |
+ * privacy review. |
+ */ |
+ public void migrateNetworkPredictionPreferences() { |
+ PrefServiceBridge prefService = PrefServiceBridge.getInstance(); |
+ |
+ // See if PREF_NETWORK_PREDICTIONS is an old boolean value. |
+ boolean predictionOptionIsBoolean = false; |
+ try { |
+ mSharedPreferences.getString(PREF_NETWORK_PREDICTIONS, ""); |
+ } catch (ClassCastException ex) { |
+ predictionOptionIsBoolean = true; |
+ } |
+ |
+ // Nothing to do if the user or this migration code has already set the new |
+ // preference. |
+ if (!predictionOptionIsBoolean |
+ && prefService.networkPredictionOptionsHasUserSetting()) { |
+ return; |
+ } |
+ |
+ // Nothing to do if the old preferences are unset. |
+ if (!predictionOptionIsBoolean |
+ && !mSharedPreferences.contains(PREF_BANDWIDTH_OLD) |
+ && !mSharedPreferences.contains(PREF_BANDWIDTH_NO_CELLULAR_OLD)) { |
+ return; |
+ } |
+ |
+ // Migrate if the old preferences are at their default values. |
+ // (Note that for PREF_BANDWIDTH*, if the setting is default, then there is no way to tell |
+ // whether the user has set it.) |
+ final String prefBandwidthDefault = BandwidthType.PRERENDER_ON_WIFI.title(); |
+ final String prefBandwidth = |
+ mSharedPreferences.getString(PREF_BANDWIDTH_OLD, prefBandwidthDefault); |
+ boolean prefBandwidthNoCellularDefault = true; |
+ boolean prefBandwidthNoCellular = mSharedPreferences.getBoolean( |
+ PREF_BANDWIDTH_NO_CELLULAR_OLD, prefBandwidthNoCellularDefault); |
+ |
+ if (!(prefBandwidthDefault.equals(prefBandwidth)) |
+ || (prefBandwidthNoCellular != prefBandwidthNoCellularDefault)) { |
+ NetworkPredictionOptions newValue = NetworkPredictionOptions.DEFAULT; |
+ // Observe PREF_BANDWIDTH on mobile network capable devices. |
+ if (isMobileNetworkCapable()) { |
+ if (mSharedPreferences.contains(PREF_BANDWIDTH_OLD)) { |
+ BandwidthType prefetchBandwidthTypePref = BandwidthType.getBandwidthFromTitle( |
+ prefBandwidth); |
+ if (BandwidthType.NEVER_PRERENDER.equals(prefetchBandwidthTypePref)) { |
+ newValue = NetworkPredictionOptions.NETWORK_PREDICTION_NEVER; |
+ } else if (BandwidthType.PRERENDER_ON_WIFI.equals(prefetchBandwidthTypePref)) { |
+ newValue = NetworkPredictionOptions.NETWORK_PREDICTION_WIFI_ONLY; |
+ } else if (BandwidthType.ALWAYS_PRERENDER.equals(prefetchBandwidthTypePref)) { |
+ newValue = NetworkPredictionOptions.NETWORK_PREDICTION_ALWAYS; |
+ } |
+ } |
+ // Observe PREF_BANDWIDTH_NO_CELLULAR on devices without mobile network. |
+ } else { |
+ if (mSharedPreferences.contains(PREF_BANDWIDTH_NO_CELLULAR_OLD)) { |
+ if (prefBandwidthNoCellular) { |
+ newValue = NetworkPredictionOptions.NETWORK_PREDICTION_WIFI_ONLY; |
+ } else { |
+ newValue = NetworkPredictionOptions.NETWORK_PREDICTION_NEVER; |
+ } |
+ } |
+ } |
+ // But disable after all if kNetworkPredictionEnabled was disabled by the user. |
+ if (prefService.networkPredictionEnabledHasUserSetting() |
+ && !prefService.getNetworkPredictionEnabledUserPrefValue()) { |
+ newValue = NetworkPredictionOptions.NETWORK_PREDICTION_NEVER; |
+ } |
+ // Save new value in Chrome PrefService. |
+ prefService.setNetworkPredictionOptions(newValue); |
+ } |
+ |
+ // Delete old sharedPreferences. |
+ SharedPreferences.Editor sharedPreferencesEditor = mSharedPreferences.edit(); |
+ // Delete PREF_BANDWIDTH and PREF_BANDWIDTH_NO_CELLULAR: just migrated these options. |
+ if (mSharedPreferences.contains(PREF_BANDWIDTH_OLD)) { |
+ sharedPreferencesEditor.remove(PREF_BANDWIDTH_OLD); |
+ } |
+ if (mSharedPreferences.contains(PREF_BANDWIDTH_NO_CELLULAR_OLD)) { |
+ sharedPreferencesEditor.remove(PREF_BANDWIDTH_NO_CELLULAR_OLD); |
+ } |
+ // Also delete ALLOW_PRERENDER, which was updated based on PREF_BANDWIDTH[_NO_CELLULAR] and |
+ // network connectivity type, therefore does not carry additional information. |
+ if (mSharedPreferences.contains(ALLOW_PRERENDER_OLD)) { |
+ sharedPreferencesEditor.remove(ALLOW_PRERENDER_OLD); |
+ } |
+ // Delete bool PREF_NETWORK_PREDICTIONS so that string values can be stored. Note that this |
+ // SharedPreference carries no information, because it used to be overwritten by |
+ // kNetworkPredictionEnabled on startup, and now it is overwritten by |
+ // kNetworkPredictionOptions on startup. |
+ if (mSharedPreferences.contains(PREF_NETWORK_PREDICTIONS)) { |
+ sharedPreferencesEditor.remove(PREF_NETWORK_PREDICTIONS); |
+ } |
+ sharedPreferencesEditor.apply(); |
+ } |
+ |
+ private NetworkInfo getActiveNetworkInfo() { |
+ ConnectivityManager connectivityManager = |
+ (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE); |
+ return connectivityManager.getActiveNetworkInfo(); |
+ } |
+ |
+ protected boolean isNetworkAvailable() { |
+ NetworkInfo networkInfo = getActiveNetworkInfo(); |
+ return (networkInfo != null && networkInfo.isConnected()); |
+ } |
+ |
+ protected boolean isWiFiOrEthernetNetwork() { |
+ NetworkInfo networkInfo = getActiveNetworkInfo(); |
+ return networkInfo != null |
+ && (networkInfo.getType() == ConnectivityManager.TYPE_WIFI |
+ || networkInfo.getType() == ConnectivityManager.TYPE_ETHERNET); |
+ } |
+ |
+ protected boolean isMobileNetworkCapable() { |
+ return ((ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE)) |
+ .getNetworkInfo(ConnectivityManager.TYPE_MOBILE) != null; |
+ } |
+ |
+ /** |
+ * Checks whether prerender should be allowed and updates the preference if it is not set yet. |
+ * @return Whether prerendering should be allowed. |
+ */ |
+ public boolean shouldPrerender() { |
+ if (!DeviceClassManager.enablePrerendering()) return false; |
+ migrateNetworkPredictionPreferences(); |
+ return PrefServiceBridge.getInstance().canPredictNetworkActions(); |
+ } |
+ |
+ /** |
+ * Check whether to allow uploading crash dump. The option should be either |
+ * "always upload", or "wifi only" with current connection being wifi/ethernet. |
+ * |
+ * @return boolean to whether to allow uploading crash dump. |
+ */ |
+ private boolean allowUploadCrashDump() { |
+ if (!isMobileNetworkCapable()) { |
+ return mSharedPreferences.getBoolean(PREF_CRASH_DUMP_UPLOAD_NO_CELLULAR, false); |
+ } else { |
+ String option = |
+ mSharedPreferences.getString(PREF_CRASH_DUMP_UPLOAD, mCrashDumpNeverUpload); |
+ return option.equals(mCrashDumpAlwaysUpload) |
+ || (option.equals(mCrashDumpWifiOnlyUpload) && isWiFiOrEthernetNetwork()); |
+ } |
+ } |
+ |
+ /** |
+ * Sets the crash upload preference, which determines whether crash dumps will be uploaded |
+ * always, never, or only on wifi. |
+ * |
+ * @param when A String denoting when crash dump uploading is allowed. One of |
+ * R.array.crash_upload_values. |
+ */ |
+ public void setUploadCrashDump(String when) { |
+ // Set the crash upload preference regardless of the current connection status. |
+ boolean canUpload = !when.equals(mCrashDumpNeverUpload); |
+ PrefServiceBridge.getInstance().setCrashReporting(canUpload); |
+ } |
+ |
+ /** |
+ * Provides a way to disable crash uploading entirely, regardless of the preferences. |
+ * Used by tests that trigger crashers intentionally, so these crashers are not uploaded. |
+ */ |
+ public void disableCrashUploading() { |
+ mCrashUploadingEnabled = false; |
+ } |
+ |
+ /** |
+ * Check whether to allow uploading crash dump now. |
+ * {@link #allowUploadCrashDump()} should return {@code true}, |
+ * and the network should be connected as well. |
+ * |
+ * @return boolean to whether to allow uploading crash dump now. |
+ */ |
+ public boolean allowUploadCrashDumpNow() { |
+ return mCrashUploadingEnabled && isNetworkAvailable() && (allowUploadCrashDump() |
+ || CommandLine.getInstance().hasSwitch(ChromeSwitches.FORCE_CRASH_DUMP_UPLOAD)); |
+ } |
+ |
+ /** |
+ * Check whether crash dump upload preference is set to NEVER only. |
+ * |
+ * @return boolean {@code true} if the option is set to NEVER |
+ */ |
+ public boolean isNeverUploadCrashDump() { |
+ boolean option; |
+ if (isMobileNetworkCapable()) { |
+ option = mSharedPreferences.getString(PREF_CRASH_DUMP_UPLOAD, mCrashDumpNeverUpload) |
+ .equals(mCrashDumpNeverUpload); |
+ } else { |
+ option = !mSharedPreferences.getBoolean(PREF_CRASH_DUMP_UPLOAD_NO_CELLULAR, false); |
+ } |
+ return option; |
+ } |
+ |
+ /** |
+ * Sets the initial value for whether crash stacks may be uploaded. |
+ * This should be called only once, the first time Chrome is launched. |
+ */ |
+ public void initCrashUploadPreference(boolean allowCrashUpload) { |
+ SharedPreferences.Editor ed = mSharedPreferences.edit(); |
+ if (isMobileNetworkCapable()) { |
+ if (allowCrashUpload) { |
+ ed.putString(PREF_CRASH_DUMP_UPLOAD, mCrashDumpWifiOnlyUpload); |
+ } else { |
+ ed.putString(PREF_CRASH_DUMP_UPLOAD, mCrashDumpNeverUpload); |
+ } |
+ } else { |
+ ed.putString(PREF_CRASH_DUMP_UPLOAD, mCrashDumpNeverUpload); |
+ ed.putBoolean(PREF_CRASH_DUMP_UPLOAD_NO_CELLULAR, allowCrashUpload); |
+ } |
+ ed.apply(); |
+ PrefServiceBridge.getInstance().setCrashReporting(allowCrashUpload); |
+ } |
+} |