// 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.datareduction; import static org.chromium.third_party.android.datausagechart.ChartDataUsageView.DAYS_IN_CHART; import android.content.res.Resources; import android.os.Bundle; import android.preference.Preference; import android.preference.Preference.OnPreferenceChangeListener; import android.preference.PreferenceFragment; import android.text.format.DateUtils; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import org.chromium.base.CommandLine; import org.chromium.chrome.R; import org.chromium.chrome.browser.help.HelpAndFeedback; import org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings; import org.chromium.chrome.browser.preferences.ChromeSwitchPreference; import org.chromium.chrome.browser.preferences.ManagedPreferenceDelegate; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.third_party.android.datausagechart.NetworkStats; import org.chromium.third_party.android.datausagechart.NetworkStatsHistory; /** * Settings fragment that allows the user to configure Data Saver. */ public class DataReductionPreferences extends PreferenceFragment { public static final String PREF_DATA_REDUCTION_SWITCH = "data_reduction_switch"; private static final String PREF_DATA_REDUCTION_STATS = "data_reduction_stats"; // This is the same as Chromium data_reduction_proxy::switches::kEnableDataReductionProxy. private static final String ENABLE_DATA_REDUCTION_PROXY = "enable-spdy-proxy-auth"; private boolean mIsEnabled; private boolean mWasEnabledAtCreation; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.data_reduction_preferences); getActivity().setTitle(R.string.data_reduction_title); boolean isEnabled = DataReductionProxySettings.getInstance().isDataReductionProxyEnabled(); mIsEnabled = !isEnabled; mWasEnabledAtCreation = isEnabled; updatePreferences(isEnabled); setHasOptionsMenu(true); } @Override public void onDestroy() { super.onDestroy(); int statusChange; if (mWasEnabledAtCreation) { statusChange = mIsEnabled ? DataReductionProxyUma.ACTION_ON_TO_ON : DataReductionProxyUma.ACTION_ON_TO_OFF; } else { statusChange = mIsEnabled ? DataReductionProxyUma.ACTION_OFF_TO_ON : DataReductionProxyUma.ACTION_OFF_TO_OFF; } DataReductionProxyUma.dataReductionProxyUIAction(statusChange); } @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { menu.clear(); MenuItem help = menu.add( Menu.NONE, R.id.menu_id_targeted_help, Menu.NONE, R.string.menu_help); help.setIcon(R.drawable.ic_help_and_feedback); } @Override public boolean onOptionsItemSelected(MenuItem item) { if (item.getItemId() == R.id.menu_id_targeted_help) { HelpAndFeedback.getInstance(getActivity()) .show(getActivity(), getString(R.string.help_context_data_reduction), Profile.getLastUsedProfile(), null); return true; } return false; } /** * Switches preference screens depending on whether data reduction is enabled/disabled. * @param isEnabled Indicates whether data reduction is enabled. */ public void updatePreferences(boolean isEnabled) { if (mIsEnabled == isEnabled) return; getPreferenceScreen().removeAll(); createDataReductionSwitch(isEnabled); if (isEnabled) { addPreferencesFromResource(R.xml.data_reduction_preferences); updateReductionStatistics(); } else { addPreferencesFromResource(R.xml.data_reduction_preferences_off); } mIsEnabled = isEnabled; } /** * Updates the preference screen to convey current statistics on data reduction. */ public void updateReductionStatistics() { DataReductionProxySettings config = DataReductionProxySettings.getInstance(); DataReductionStatsPreference statsPref = (DataReductionStatsPreference) getPreferenceScreen().findPreference(PREF_DATA_REDUCTION_STATS); long original[] = config.getOriginalNetworkStatsHistory(); long received[] = config.getReceivedNetworkStatsHistory(); statsPref.setReductionStats( config.getDataReductionLastUpdateTime(), getNetworkStatsHistory(original, DAYS_IN_CHART), getNetworkStatsHistory(received, DAYS_IN_CHART)); } /** * Returns summary string. */ public static String generateSummary(Resources resources) { if (DataReductionProxySettings.getInstance().isDataReductionProxyEnabled()) { String percent = DataReductionProxySettings.getInstance() .getContentLengthPercentSavings(); return resources.getString( R.string.data_reduction_menu_item_summary, percent); } else { return (String) resources.getText(R.string.text_off); } } private static NetworkStatsHistory getNetworkStatsHistory(long[] history, int days) { if (days > history.length) days = history.length; NetworkStatsHistory networkStatsHistory = new NetworkStatsHistory( DateUtils.DAY_IN_MILLIS, days, NetworkStatsHistory.FIELD_RX_BYTES); DataReductionProxySettings config = DataReductionProxySettings.getInstance(); long time = config.getDataReductionLastUpdateTime() - days * DateUtils.DAY_IN_MILLIS; for (int i = history.length - days, bucket = 0; i < history.length; i++, bucket++) { NetworkStats.Entry entry = new NetworkStats.Entry(); entry.rxBytes = history[i]; long startTime = time + (DateUtils.DAY_IN_MILLIS * bucket); // Spread each day's record over the first hour of the day. networkStatsHistory.recordData( startTime, startTime + DateUtils.HOUR_IN_MILLIS, entry); } return networkStatsHistory; } private void createDataReductionSwitch(boolean isEnabled) { final ChromeSwitchPreference dataReductionSwitch = new ChromeSwitchPreference(getActivity(), null); dataReductionSwitch.setKey(PREF_DATA_REDUCTION_SWITCH); dataReductionSwitch.setSummaryOn(R.string.text_on); dataReductionSwitch.setSummaryOff(R.string.text_off); dataReductionSwitch.setDrawDivider(true); dataReductionSwitch.setOnPreferenceChangeListener(new OnPreferenceChangeListener() { @Override public boolean onPreferenceChange(Preference preference, Object newValue) { DataReductionProxySettings.getInstance().setDataReductionProxyEnabled( dataReductionSwitch.getContext(), (boolean) newValue); DataReductionPreferences.this.updatePreferences((boolean) newValue); return true; } }); dataReductionSwitch.setManagedPreferenceDelegate(new ManagedPreferenceDelegate() { @Override public boolean isPreferenceControlledByPolicy(Preference preference) { return CommandLine.getInstance().hasSwitch(ENABLE_DATA_REDUCTION_PROXY) || DataReductionProxySettings.getInstance().isDataReductionProxyManaged(); } }); getPreferenceScreen().addPreference(dataReductionSwitch); // Note: setting the switch state before the preference is added to the screen results in // some odd behavior where the switch state doesn't always match the internal enabled state // (e.g. the switch will say "On" when data reduction is really turned off), so // .setChecked() should be called after .addPreference() dataReductionSwitch.setChecked(isEnabled); } }