mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-17 07:15:46 +00:00
backout 91e7ba697b14 (Bug 1001309) for test failures. r=backout
This commit is contained in:
parent
f200d0a848
commit
300e4ef498
@ -11,11 +11,9 @@ import java.lang.Class;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Vector;
|
||||
import java.util.Set;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
@ -54,7 +52,6 @@ import org.mozilla.gecko.home.SearchEngine;
|
||||
import org.mozilla.gecko.menu.GeckoMenu;
|
||||
import org.mozilla.gecko.menu.GeckoMenuItem;
|
||||
import org.mozilla.gecko.preferences.GeckoPreferences;
|
||||
import org.mozilla.gecko.preferences.ClearOnShutdownPref;
|
||||
import org.mozilla.gecko.prompts.Prompt;
|
||||
import org.mozilla.gecko.prompts.PromptListItem;
|
||||
import org.mozilla.gecko.sync.setup.SyncAccounts;
|
||||
@ -70,7 +67,6 @@ import org.mozilla.gecko.util.NativeEventListener;
|
||||
import org.mozilla.gecko.util.NativeJSObject;
|
||||
import org.mozilla.gecko.util.HardwareUtils;
|
||||
import org.mozilla.gecko.util.MenuUtils;
|
||||
import org.mozilla.gecko.util.PrefUtils;
|
||||
import org.mozilla.gecko.util.StringUtils;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
import org.mozilla.gecko.util.UiAsyncTask;
|
||||
@ -2410,11 +2406,9 @@ public class BrowserApp extends GeckoApp
|
||||
MenuItem enterGuestMode = aMenu.findItem(R.id.new_guest_session);
|
||||
MenuItem exitGuestMode = aMenu.findItem(R.id.exit_guest_session);
|
||||
|
||||
// Only show the "Quit" menu item on pre-ICS, television devices, or if the user has explicitly enabled the clear on shutdown pref.
|
||||
// Only show the "Quit" menu item on pre-ICS or television devices.
|
||||
// In ICS+, it's easy to kill an app through the task switcher.
|
||||
final SharedPreferences prefs = GeckoSharedPrefs.forProfile(this);
|
||||
final Set<String> clearItems = PrefUtils.getStringSet(prefs, ClearOnShutdownPref.PREF, new HashSet<String>());
|
||||
aMenu.findItem(R.id.quit).setVisible(clearItems.size() > 0 || Build.VERSION.SDK_INT < 14 || HardwareUtils.isTelevision());
|
||||
aMenu.findItem(R.id.quit).setVisible(Build.VERSION.SDK_INT < 14 || HardwareUtils.isTelevision());
|
||||
|
||||
if (tab == null || tab.getURL() == null) {
|
||||
bookmark.setEnabled(false);
|
||||
|
@ -18,7 +18,6 @@ import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
@ -47,7 +46,6 @@ import org.mozilla.gecko.menu.GeckoMenu;
|
||||
import org.mozilla.gecko.menu.GeckoMenuInflater;
|
||||
import org.mozilla.gecko.menu.MenuPanel;
|
||||
import org.mozilla.gecko.mozglue.GeckoLoader;
|
||||
import org.mozilla.gecko.preferences.ClearOnShutdownPref;
|
||||
import org.mozilla.gecko.preferences.GeckoPreferences;
|
||||
import org.mozilla.gecko.prompts.PromptService;
|
||||
import org.mozilla.gecko.updater.UpdateService;
|
||||
@ -59,7 +57,6 @@ import org.mozilla.gecko.util.GeckoEventListener;
|
||||
import org.mozilla.gecko.util.HardwareUtils;
|
||||
import org.mozilla.gecko.util.NativeEventListener;
|
||||
import org.mozilla.gecko.util.NativeJSObject;
|
||||
import org.mozilla.gecko.util.PrefUtils;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
import org.mozilla.gecko.webapp.EventListener;
|
||||
import org.mozilla.gecko.webapp.UninstallListener;
|
||||
@ -466,23 +463,10 @@ public abstract class GeckoApp
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
if (item.getItemId() == R.id.quit) {
|
||||
if (GeckoThread.checkAndSetLaunchState(GeckoThread.LaunchState.GeckoRunning, GeckoThread.LaunchState.GeckoExiting)) {
|
||||
final SharedPreferences prefs = GeckoSharedPrefs.forProfile(this);
|
||||
final Set<String> clearSet = PrefUtils.getStringSet(prefs, ClearOnShutdownPref.PREF, new HashSet<String>());
|
||||
|
||||
final JSONObject clearObj = new JSONObject();
|
||||
for (String clear : clearSet) {
|
||||
try {
|
||||
clearObj.put(clear, true);
|
||||
} catch(JSONException ex) {
|
||||
Log.i(LOGTAG, "Error adding clear object " + clear);
|
||||
}
|
||||
}
|
||||
|
||||
GeckoAppShell.notifyGeckoOfEvent(GeckoEvent.createBroadcastEvent("Browser:Quit", clearObj.toString()));
|
||||
GeckoAppShell.notifyGeckoOfEvent(GeckoEvent.createBroadcastEvent("Browser:Quit", null));
|
||||
} else {
|
||||
GeckoAppShell.systemExit();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -612,7 +596,6 @@ public abstract class GeckoApp
|
||||
|
||||
} else if ("Sanitize:ClearHistory".equals(event)) {
|
||||
handleClearHistory();
|
||||
callback.sendSuccess(true);
|
||||
|
||||
} else if ("Session:StatePurged".equals(event)) {
|
||||
onStatePurged();
|
||||
|
@ -145,11 +145,7 @@
|
||||
<!ENTITY pref_char_encoding "Character encoding">
|
||||
<!ENTITY pref_char_encoding_on "Show menu">
|
||||
<!ENTITY pref_char_encoding_off "Don\'t show menu">
|
||||
<!ENTITY pref_clear_private_data2 "Clear now">
|
||||
<!ENTITY pref_clear_private_data_category "Clear private data">
|
||||
<!ENTITY pref_clear_on_exit_title "Always clear when quitting">
|
||||
<!ENTITY pref_clear_on_exit_summary "&brandShortName; will automatically clear your data whenever you select "Quit" from the main menu">
|
||||
<!ENTITY pref_clear_on_exit_dialog_title "Select which data to clear">
|
||||
<!ENTITY pref_clear_private_data "Clear private data">
|
||||
<!ENTITY pref_plugins "Plugins">
|
||||
<!ENTITY pref_plugins_enabled "Enabled">
|
||||
<!ENTITY pref_plugins_tap_to_play "Tap to play">
|
||||
|
@ -71,7 +71,6 @@ gujar.sources += [
|
||||
'util/NativeJSContainer.java',
|
||||
'util/NativeJSObject.java',
|
||||
'util/NonEvictingLruCache.java',
|
||||
'util/PrefUtils.java',
|
||||
'util/ProxySelector.java',
|
||||
'util/RawResource.java',
|
||||
'util/StringUtils.java',
|
||||
@ -335,18 +334,15 @@ gbjar.sources += [
|
||||
'preferences/AlignRightLinkPreference.java',
|
||||
'preferences/AndroidImport.java',
|
||||
'preferences/AndroidImportPreference.java',
|
||||
'preferences/ClearOnShutdownPref.java',
|
||||
'preferences/CustomListCategory.java',
|
||||
'preferences/CustomListPreference.java',
|
||||
'preferences/FontSizePreference.java',
|
||||
'preferences/GeckoPreferenceFragment.java',
|
||||
'preferences/GeckoPreferences.java',
|
||||
'preferences/LinkPreference.java',
|
||||
'preferences/ListCheckboxPreference.java',
|
||||
'preferences/LocaleListPreference.java',
|
||||
'preferences/ModifiableHintPreference.java',
|
||||
'preferences/MultiChoicePreference.java',
|
||||
'preferences/MultiPrefMultiChoicePreference.java',
|
||||
'preferences/PanelsPreference.java',
|
||||
'preferences/PanelsPreferenceCategory.java',
|
||||
'preferences/PrivateDataPreference.java',
|
||||
|
@ -8,14 +8,12 @@ package org.mozilla.gecko.preferences;
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
|
||||
class AndroidImportPreference extends MultiPrefMultiChoicePreference {
|
||||
class AndroidImportPreference extends MultiChoicePreference {
|
||||
static final private String LOGTAG = "AndroidImport";
|
||||
private static final String PREF_KEY_PREFIX = "import_android.data.";
|
||||
private Context mContext;
|
||||
@ -35,15 +33,19 @@ class AndroidImportPreference extends MultiPrefMultiChoicePreference {
|
||||
boolean bookmarksChecked = false;
|
||||
boolean historyChecked = false;
|
||||
|
||||
Set<String> values = getValues();
|
||||
CharSequence keys[] = getEntryKeys();
|
||||
boolean values[] = getValues();
|
||||
|
||||
for (String value : values) {
|
||||
// Import checkbox values are stored in Android prefs to
|
||||
for (int i = 0; i < keys.length; i++) {
|
||||
// Privacy pref checkbox values are stored in Android prefs to
|
||||
// remember their check states. The key names are import_android.data.X
|
||||
String key = value.substring(PREF_KEY_PREFIX.length());
|
||||
if ("bookmarks".equals(key)) {
|
||||
String key = keys[i].toString().substring(PREF_KEY_PREFIX.length());
|
||||
boolean value = values[i];
|
||||
|
||||
if (key.equals("bookmarks") && value) {
|
||||
bookmarksChecked = true;
|
||||
} else if ("history".equals(key)) {
|
||||
}
|
||||
if (key.equals("history") && value) {
|
||||
historyChecked = true;
|
||||
}
|
||||
}
|
||||
|
@ -1,36 +0,0 @@
|
||||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.gecko.preferences;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.mozilla.gecko.GeckoSharedPrefs;
|
||||
import org.mozilla.gecko.util.PrefUtils;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.Preference;
|
||||
|
||||
public class ClearOnShutdownPref implements GeckoPreferences.PrefHandler {
|
||||
public static final String PREF = GeckoPreferences.NON_PREF_PREFIX + "history.clear_on_exit";
|
||||
|
||||
@Override
|
||||
public void setupPref(Context context, Preference pref) {
|
||||
// The pref is initialized asynchronously. Read the pref explicitly
|
||||
// here to make sure we have the data.
|
||||
final SharedPreferences prefs = GeckoSharedPrefs.forProfile(context);
|
||||
final Set<String> clearItems = PrefUtils.getStringSet(prefs, PREF, new HashSet<String>());
|
||||
((ListCheckboxPreference) pref).setChecked(clearItems.size() > 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void onChange(Context context, Preference pref, Object newValue) {
|
||||
final Set<String> vals = (Set<String>) newValue;
|
||||
((ListCheckboxPreference) pref).setChecked(vals.size() > 0);
|
||||
}
|
||||
}
|
@ -6,10 +6,8 @@
|
||||
package org.mozilla.gecko.preferences;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import org.json.JSONObject;
|
||||
import org.mozilla.gecko.AppConstants;
|
||||
@ -94,7 +92,7 @@ OnSharedPreferenceChangeListener
|
||||
// devices.
|
||||
private static final boolean NO_TRANSITIONS = HardwareUtils.IS_KINDLE_DEVICE;
|
||||
|
||||
public static final String NON_PREF_PREFIX = "android.not_a_preference.";
|
||||
private static final String NON_PREF_PREFIX = "android.not_a_preference.";
|
||||
public static final String INTENT_EXTRA_RESOURCES = "resource";
|
||||
public static String PREFS_HEALTHREPORT_UPLOAD_ENABLED = NON_PREF_PREFIX + "healthreport.uploadEnabled";
|
||||
|
||||
@ -729,9 +727,6 @@ OnSharedPreferenceChangeListener
|
||||
return true;
|
||||
}
|
||||
});
|
||||
} else if (handlers.containsKey(key)) {
|
||||
PrefHandler handler = handlers.get(key);
|
||||
handler.setupPref(this, pref);
|
||||
}
|
||||
|
||||
// Some Preference UI elements are not actually preferences,
|
||||
@ -1001,20 +996,9 @@ OnSharedPreferenceChangeListener
|
||||
}
|
||||
}
|
||||
|
||||
public interface PrefHandler {
|
||||
public void setupPref(Context context, Preference pref);
|
||||
public void onChange(Context context, Preference pref, Object newValue);
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
private Map<String, PrefHandler> handlers = new HashMap<String, PrefHandler>() {{
|
||||
put(ClearOnShutdownPref.PREF, new ClearOnShutdownPref());
|
||||
}};
|
||||
|
||||
@Override
|
||||
public boolean onPreferenceChange(Preference preference, Object newValue) {
|
||||
final String prefName = preference.getKey();
|
||||
Log.i(LOGTAG, "Changed " + prefName + " = " + newValue);
|
||||
if (PREFS_MP_ENABLED.equals(prefName)) {
|
||||
showDialog((Boolean) newValue ? DIALOG_CREATE_MASTER_PASSWORD : DIALOG_REMOVE_MASTER_PASSWORD);
|
||||
|
||||
@ -1046,9 +1030,6 @@ OnSharedPreferenceChangeListener
|
||||
} else if (PREFS_GEO_REPORTING.equals(prefName)) {
|
||||
// Translate boolean value to int for geo reporting pref.
|
||||
newValue = ((Boolean) newValue) ? 1 : 0;
|
||||
} else if (handlers.containsKey(prefName)) {
|
||||
PrefHandler handler = handlers.get(prefName);
|
||||
handler.onChange(this, preference, newValue);
|
||||
}
|
||||
|
||||
// Send Gecko-side pref changes to Gecko
|
||||
|
@ -1,58 +0,0 @@
|
||||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.gecko.preferences;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
import android.widget.Checkable;
|
||||
|
||||
import org.mozilla.gecko.R;
|
||||
|
||||
/**
|
||||
* This preference shows a checkbox on its left hand side, but will show a menu when clicked.
|
||||
* Its used for preferences like "Clear on Exit" that have a boolean on-off state, but that represent
|
||||
* multiple boolean options inside.
|
||||
**/
|
||||
class ListCheckboxPreference extends MultiChoicePreference implements Checkable {
|
||||
private static final String LOGTAG = "GeckoListCheckboxPreference";
|
||||
private boolean checked;
|
||||
|
||||
public ListCheckboxPreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
setWidgetLayoutResource(R.layout.preference_checkbox);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChecked() {
|
||||
return checked;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onBindView(View view) {
|
||||
super.onBindView(view);
|
||||
|
||||
View checkboxView = view.findViewById(R.id.checkbox);
|
||||
if (checkboxView != null && checkboxView instanceof Checkable) {
|
||||
((Checkable) checkboxView).setChecked(checked);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setChecked(boolean checked) {
|
||||
boolean changed = checked != this.checked;
|
||||
this.checked = checked;
|
||||
if (changed) {
|
||||
notifyDependencyChange(shouldDisableDependents());
|
||||
notifyChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toggle() {
|
||||
checked = !checked;
|
||||
}
|
||||
}
|
@ -7,26 +7,23 @@ package org.mozilla.gecko.preferences;
|
||||
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.GeckoSharedPrefs;
|
||||
import org.mozilla.gecko.util.PrefUtils;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.AlertDialog.Builder;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.res.TypedArray;
|
||||
import android.content.SharedPreferences;
|
||||
import android.preference.DialogPreference;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.Button;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
class MultiChoicePreference extends DialogPreference implements DialogInterface.OnMultiChoiceClickListener {
|
||||
class MultiChoicePreference extends DialogPreference {
|
||||
private static final String LOGTAG = "GeckoMultiChoicePreference";
|
||||
|
||||
private boolean mValues[];
|
||||
private boolean mPrevValues[];
|
||||
private CharSequence mEntryValues[];
|
||||
private CharSequence mEntryKeys[];
|
||||
private CharSequence mEntries[];
|
||||
private CharSequence mInitialValues[];
|
||||
|
||||
@ -35,7 +32,7 @@ class MultiChoicePreference extends DialogPreference implements DialogInterface.
|
||||
|
||||
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MultiChoicePreference);
|
||||
mEntries = a.getTextArray(R.styleable.MultiChoicePreference_entries);
|
||||
mEntryValues = a.getTextArray(R.styleable.MultiChoicePreference_entryValues);
|
||||
mEntryKeys = a.getTextArray(R.styleable.MultiChoicePreference_entryKeys);
|
||||
mInitialValues = a.getTextArray(R.styleable.MultiChoicePreference_initialValues);
|
||||
a.recycle();
|
||||
|
||||
@ -51,9 +48,9 @@ class MultiChoicePreference extends DialogPreference implements DialogInterface.
|
||||
* shown in subsequent dialogs.
|
||||
* <p>
|
||||
* Each entry must have a corresponding index in
|
||||
* {@link #setEntryValues(CharSequence[])} and
|
||||
* {@link #setEntryKeys(CharSequence[])} and
|
||||
* {@link #setInitialValues(CharSequence[])}.
|
||||
*
|
||||
*
|
||||
* @param entries The entries.
|
||||
*/
|
||||
public void setEntries(CharSequence[] entries) {
|
||||
@ -68,22 +65,20 @@ class MultiChoicePreference extends DialogPreference implements DialogInterface.
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the preference values for preferences shown in the list.
|
||||
* Sets the preference keys for preferences shown in the list.
|
||||
*
|
||||
* @param entryValues The entry values.
|
||||
* @param entryKeys The entry keys.
|
||||
*/
|
||||
public void setEntryValues(CharSequence[] entryValues) {
|
||||
mEntryValues = entryValues.clone();
|
||||
public void setEntryKeys(CharSequence[] entryKeys) {
|
||||
mEntryKeys = entryKeys.clone();
|
||||
loadPersistedValues();
|
||||
}
|
||||
|
||||
/**
|
||||
* Entry values define a separate pref for each row in the dialog.
|
||||
*
|
||||
* @param entryValuesResId The entryValues array as a resource.
|
||||
* @param entryKeysResId The entryKeys array as a resource.
|
||||
*/
|
||||
public void setEntryValues(int entryValuesResId) {
|
||||
setEntryValues(getContext().getResources().getTextArray(entryValuesResId));
|
||||
public void setEntryKeys(int entryKeysResId) {
|
||||
setEntryKeys(getContext().getResources().getTextArray(entryKeysResId));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -116,12 +111,12 @@ class MultiChoicePreference extends DialogPreference implements DialogInterface.
|
||||
}
|
||||
|
||||
/**
|
||||
* The list of values corresponding to each preference.
|
||||
* The list of keys corresponding to each preference.
|
||||
*
|
||||
* @return The array of values.
|
||||
* @return The array of keys.
|
||||
*/
|
||||
public CharSequence[] getEntryValues() {
|
||||
return mEntryValues.clone();
|
||||
public CharSequence[] getEntryKeys() {
|
||||
return mEntryKeys.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -134,50 +129,46 @@ class MultiChoicePreference extends DialogPreference implements DialogInterface.
|
||||
return mInitialValues.clone();
|
||||
}
|
||||
|
||||
public void setValue(final int i, final boolean value) {
|
||||
mValues[i] = value;
|
||||
mPrevValues = mValues.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* The list of values for each preference. These values are updated after
|
||||
* the dialog has been displayed.
|
||||
*
|
||||
* @return The array of values.
|
||||
*/
|
||||
public Set<String> getValues() {
|
||||
final Set<String> values = new HashSet<String>();
|
||||
|
||||
if (mValues == null) {
|
||||
return values;
|
||||
}
|
||||
|
||||
for (int i = 0; i < mValues.length; i++) {
|
||||
if (mValues[i]) {
|
||||
values.add(mEntryValues[i].toString());
|
||||
}
|
||||
}
|
||||
|
||||
return values;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which, boolean val) {
|
||||
public boolean[] getValues() {
|
||||
return mValues.clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPrepareDialogBuilder(Builder builder) {
|
||||
if (mEntries == null || mInitialValues == null || mEntryValues == null) {
|
||||
if (mEntries == null || mEntryKeys == null || mInitialValues == null) {
|
||||
throw new IllegalStateException(
|
||||
"MultiChoicePreference requires entries, entryValues, and initialValues arrays.");
|
||||
"MultiChoicePreference requires entries, entryKeys, and initialValues arrays.");
|
||||
}
|
||||
|
||||
if (mEntries.length != mEntryValues.length || mEntries.length != mInitialValues.length) {
|
||||
if (mEntries.length != mEntryKeys.length || mEntryKeys.length != mInitialValues.length) {
|
||||
throw new IllegalStateException(
|
||||
"MultiChoicePreference entries, entryValues, and initialValues arrays must be the same length");
|
||||
"MultiChoicePreference entries, entryKeys, and initialValues arrays must be the same length");
|
||||
}
|
||||
|
||||
builder.setMultiChoiceItems(mEntries, mValues, this);
|
||||
builder.setMultiChoiceItems(mEntries, mValues, new DialogInterface.OnMultiChoiceClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which, boolean val) {
|
||||
// mValues is automatically updated when checkboxes are clicked
|
||||
|
||||
// enable positive button only if at least one item is checked
|
||||
boolean enabled = false;
|
||||
for (int i = 0; i < mValues.length; i++) {
|
||||
if (mValues[i]) {
|
||||
enabled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Button button = ((AlertDialog) dialog).getButton(DialogInterface.BUTTON_POSITIVE);
|
||||
if (button.isEnabled() != enabled)
|
||||
button.setEnabled(enabled);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -196,44 +187,37 @@ class MultiChoicePreference extends DialogPreference implements DialogInterface.
|
||||
mPrevValues = mValues.clone();
|
||||
}
|
||||
|
||||
if (!callChangeListener(getValues())) {
|
||||
return;
|
||||
}
|
||||
|
||||
persist();
|
||||
ThreadUtils.postToBackgroundThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (int i = 0; i < mEntryKeys.length; i++) {
|
||||
String key = mEntryKeys[i].toString();
|
||||
persistBoolean(key, mValues[i]);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* Persists the current data stored by this pref to SharedPreferences. */
|
||||
public boolean persist() {
|
||||
protected boolean persistBoolean(String key, boolean value) {
|
||||
if (isPersistent()) {
|
||||
final SharedPreferences.Editor edit = GeckoSharedPrefs.forProfile(getContext()).edit();
|
||||
final boolean res = persist(edit);
|
||||
edit.commit();
|
||||
return res;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Internal persist method. Take an edit so that multiple prefs can be persisted in a single commit. */
|
||||
protected boolean persist(SharedPreferences.Editor edit) {
|
||||
if (isPersistent()) {
|
||||
Set<String> vals = getValues();
|
||||
PrefUtils.putStringSet(edit, getKey(), vals);
|
||||
if (value == getPersistedBoolean(!value)) {
|
||||
// It's already there, so the same as persisting
|
||||
return true;
|
||||
}
|
||||
|
||||
GeckoSharedPrefs.forApp(getContext())
|
||||
.edit().putBoolean(key, value).commit();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Returns a list of EntryValues that are currently enabled. */
|
||||
public Set<String> getPersistedStrings(Set<String> defaultVal) {
|
||||
if (!isPersistent()) {
|
||||
return defaultVal;
|
||||
}
|
||||
|
||||
final SharedPreferences prefs = GeckoSharedPrefs.forProfile(getContext());
|
||||
return PrefUtils.getStringSet(prefs, getKey(), defaultVal);
|
||||
protected boolean getPersistedBoolean(String key, boolean defaultReturnValue) {
|
||||
if (!isPersistent())
|
||||
return defaultReturnValue;
|
||||
|
||||
return GeckoSharedPrefs.forApp(getContext())
|
||||
.getBoolean(key, defaultReturnValue);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -241,29 +225,25 @@ class MultiChoicePreference extends DialogPreference implements DialogInterface.
|
||||
* aren't persistent or haven't yet been stored, they will be set to their
|
||||
* initial values.
|
||||
*/
|
||||
protected void loadPersistedValues() {
|
||||
final int entryCount = mInitialValues.length;
|
||||
mValues = new boolean[entryCount];
|
||||
private void loadPersistedValues() {
|
||||
if (mEntryKeys == null || mInitialValues == null)
|
||||
return;
|
||||
|
||||
if (entryCount != mEntries.length || entryCount != mEntryValues.length) {
|
||||
final int entryCount = mEntryKeys.length;
|
||||
if (entryCount != mEntries.length || entryCount != mInitialValues.length) {
|
||||
throw new IllegalStateException(
|
||||
"MultiChoicePreference entryValues and initialValues arrays must be the same length");
|
||||
"MultiChoicePreference entryKeys and initialValues arrays must be the same length");
|
||||
}
|
||||
|
||||
mValues = new boolean[entryCount];
|
||||
ThreadUtils.postToBackgroundThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final Set<String> stringVals = getPersistedStrings(null);
|
||||
|
||||
for (int i = 0; i < entryCount; i++) {
|
||||
if (stringVals != null) {
|
||||
mValues[i] = stringVals.contains(mEntryValues[i]);
|
||||
} else {
|
||||
final boolean defaultVal = mInitialValues[i].equals("true");
|
||||
mValues[i] = defaultVal;
|
||||
}
|
||||
String key = mEntryKeys[i].toString();
|
||||
boolean initialValue = mInitialValues[i].equals("true");
|
||||
mValues[i] = getPersistedBoolean(key, initialValue);
|
||||
}
|
||||
|
||||
mPrevValues = mValues.clone();
|
||||
}
|
||||
});
|
||||
|
@ -1,116 +0,0 @@
|
||||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.gecko.preferences;
|
||||
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.GeckoSharedPrefs;
|
||||
import org.mozilla.gecko.util.ThreadUtils;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.res.TypedArray;
|
||||
import android.content.SharedPreferences;
|
||||
import android.widget.Button;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/* Provides backwards compatibility for some old multi-choice pref types used by Gecko.
|
||||
* This will import the old data from the old prefs the first time it is run.
|
||||
*/
|
||||
class MultiPrefMultiChoicePreference extends MultiChoicePreference {
|
||||
private static final String LOGTAG = "GeckoMultiPrefPreference";
|
||||
private static final String IMPORT_SUFFIX = "_imported_";
|
||||
private final CharSequence[] keys;
|
||||
|
||||
public MultiPrefMultiChoicePreference(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
|
||||
final TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MultiPrefMultiChoicePreference);
|
||||
keys = a.getTextArray(R.styleable.MultiPrefMultiChoicePreference_entryKeys);
|
||||
a.recycle();
|
||||
|
||||
loadPersistedValues();
|
||||
}
|
||||
|
||||
// Helper method for reading a boolean pref.
|
||||
private boolean getPersistedBoolean(SharedPreferences prefs, String key, boolean defaultReturnValue) {
|
||||
if (!isPersistent()) {
|
||||
return defaultReturnValue;
|
||||
}
|
||||
|
||||
return prefs.getBoolean(key, defaultReturnValue);
|
||||
}
|
||||
|
||||
// Overridden to do a one time import for the old preference type to the new one.
|
||||
@Override
|
||||
protected synchronized void loadPersistedValues() {
|
||||
// This will load the new pref if it exists.
|
||||
super.loadPersistedValues();
|
||||
|
||||
// First check if we've already done the import the old data. If so, nothing to load.
|
||||
final SharedPreferences prefs = GeckoSharedPrefs.forApp(getContext());
|
||||
final boolean imported = getPersistedBoolean(prefs, getKey() + IMPORT_SUFFIX, false);
|
||||
if (imported) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Load the data we'll need to find the old style prefs
|
||||
final CharSequence[] init = getInitialValues();
|
||||
final CharSequence[] entries = getEntries();
|
||||
if (keys == null || init == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final int entryCount = keys.length;
|
||||
if (entryCount != entries.length || entryCount != init.length) {
|
||||
throw new IllegalStateException("MultiChoicePreference entryKeys and initialValues arrays must be the same length");
|
||||
}
|
||||
|
||||
// Now iterate through the entries on a background thread.
|
||||
final SharedPreferences.Editor edit = prefs.edit();
|
||||
ThreadUtils.postToBackgroundThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
// Use one editor to batch as many changes as we can.
|
||||
for (int i = 0; i < entryCount; i++) {
|
||||
String key = keys[i].toString();
|
||||
boolean initialValue = "true".equals(init[i]);
|
||||
boolean val = getPersistedBoolean(prefs, key, initialValue);
|
||||
|
||||
// Save the pref and remove the old preference.
|
||||
setValue(i, val);
|
||||
edit.remove(key);
|
||||
}
|
||||
|
||||
persist(edit);
|
||||
edit.putBoolean(getKey() + IMPORT_SUFFIX, true);
|
||||
edit.commit();
|
||||
} catch(Exception ex) {
|
||||
Log.i(LOGTAG, "Err", ex);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which, boolean val) {
|
||||
// enable positive button only if at least one item is checked
|
||||
boolean enabled = false;
|
||||
final Set<String> values = getValues();
|
||||
|
||||
enabled = (values.size() > 0);
|
||||
final Button button = ((AlertDialog) dialog).getButton(DialogInterface.BUTTON_POSITIVE);
|
||||
if (button.isEnabled() != enabled) {
|
||||
button.setEnabled(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -13,13 +13,11 @@ import org.mozilla.gecko.TelemetryContract;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
|
||||
class PrivateDataPreference extends MultiPrefMultiChoicePreference {
|
||||
class PrivateDataPreference extends MultiChoicePreference {
|
||||
private static final String LOGTAG = "GeckoPrivateDataPreference";
|
||||
private static final String PREF_KEY_PREFIX = "private.data.";
|
||||
|
||||
@ -31,24 +29,25 @@ class PrivateDataPreference extends MultiPrefMultiChoicePreference {
|
||||
protected void onDialogClosed(boolean positiveResult) {
|
||||
super.onDialogClosed(positiveResult);
|
||||
|
||||
if (!positiveResult) {
|
||||
if (!positiveResult)
|
||||
return;
|
||||
}
|
||||
|
||||
Telemetry.sendUIEvent(TelemetryContract.Event.SANITIZE, TelemetryContract.Method.DIALOG, "settings");
|
||||
|
||||
final Set<String> values = getValues();
|
||||
final JSONObject json = new JSONObject();
|
||||
CharSequence keys[] = getEntryKeys();
|
||||
boolean values[] = getValues();
|
||||
JSONObject json = new JSONObject();
|
||||
|
||||
for (String value : values) {
|
||||
for (int i = 0; i < keys.length; i++) {
|
||||
// Privacy pref checkbox values are stored in Android prefs to
|
||||
// remember their check states. The key names are private.data.X,
|
||||
// where X is a string from Gecko sanitization. This prefix is
|
||||
// removed here so we can send the values to Gecko, which then does
|
||||
// the sanitization for each key.
|
||||
final String key = value.substring(PREF_KEY_PREFIX.length());
|
||||
String key = keys[i].toString().substring(PREF_KEY_PREFIX.length());
|
||||
boolean value = values[i];
|
||||
try {
|
||||
json.put(key, true);
|
||||
json.put(key, value);
|
||||
} catch (JSONException e) {
|
||||
Log.e(LOGTAG, "JSON error", e);
|
||||
}
|
||||
|
@ -1,24 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2006 The Android Open Source Project
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<!-- Layout used by CheckBoxPreference for the checkbox style. This is inflated
|
||||
inside android.R.layout.preference. -->
|
||||
<CheckBox xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/checkbox"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:focusable="false"
|
||||
android:clickable="false" />
|
@ -69,13 +69,9 @@
|
||||
<item>@string/bookmarks_title</item>
|
||||
<item>@string/history_title</item>
|
||||
</string-array>
|
||||
<string-array name="pref_import_android_defaults">
|
||||
<item>true</item>
|
||||
<item>true</item>
|
||||
</string-array>
|
||||
<string-array name="pref_import_android_values">
|
||||
<item>android_import.data.bookmarks</item>
|
||||
<item>android_import.data.history</item>
|
||||
<item>true</item>
|
||||
<item>true</item>
|
||||
</string-array>
|
||||
<string-array name="pref_import_android_keys">
|
||||
<item>android_import.data.bookmarks</item>
|
||||
@ -91,25 +87,15 @@
|
||||
<item>@string/pref_private_data_offlineApps</item>
|
||||
<item>@string/pref_private_data_siteSettings</item>
|
||||
</string-array>
|
||||
<string-array name="pref_private_data_defaults">
|
||||
<item>true</item>
|
||||
<item>true</item>
|
||||
<item>true</item>
|
||||
<item>true</item>
|
||||
<item>true</item>
|
||||
<item>true</item>
|
||||
<item>true</item>
|
||||
<item>true</item>
|
||||
</string-array>
|
||||
<string-array name="pref_private_data_values">
|
||||
<item>private.data.history</item>
|
||||
<item>private.data.downloadFiles</item>
|
||||
<item>private.data.formdata</item>
|
||||
<item>private.data.cookies_sessions</item>
|
||||
<item>private.data.passwords</item>
|
||||
<item>private.data.cache</item>
|
||||
<item>private.data.offlineApps</item>
|
||||
<item>private.data.siteSettings</item>
|
||||
<item>true</item>
|
||||
<item>true</item>
|
||||
<item>true</item>
|
||||
<item>true</item>
|
||||
<item>true</item>
|
||||
<item>true</item>
|
||||
<item>true</item>
|
||||
<item>true</item>
|
||||
</string-array>
|
||||
<string-array name="pref_private_data_keys">
|
||||
<item>private.data.history</item>
|
||||
@ -121,16 +107,6 @@
|
||||
<item>private.data.offlineApps</item>
|
||||
<item>private.data.siteSettings</item>
|
||||
</string-array>
|
||||
<string-array name="pref_clear_on_exit_defaults">
|
||||
<item>false</item>
|
||||
<item>false</item>
|
||||
<item>false</item>
|
||||
<item>false</item>
|
||||
<item>false</item>
|
||||
<item>false</item>
|
||||
<item>false</item>
|
||||
<item>false</item>
|
||||
</string-array>
|
||||
<string-array name="pref_restore_entries">
|
||||
<item>@string/pref_restore_always</item>
|
||||
<item>@string/pref_restore_quit</item>
|
||||
|
@ -84,12 +84,8 @@
|
||||
|
||||
<declare-styleable name="MultiChoicePreference">
|
||||
<attr name="entries" format="string"/>
|
||||
<attr name="entryValues" format="string"/>
|
||||
<attr name="initialValues" format="string"/>
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="MultiPrefMultiChoicePreference">
|
||||
<attr name="entryKeys" format="string"/>
|
||||
<attr name="initialValues" format="string"/>
|
||||
</declare-styleable>
|
||||
|
||||
<declare-styleable name="BrowserToolbarCurve">
|
||||
|
@ -33,9 +33,8 @@
|
||||
<org.mozilla.gecko.preferences.AndroidImportPreference
|
||||
android:key="android.not_a_preference.import_android"
|
||||
gecko:entries="@array/pref_import_android_entries"
|
||||
gecko:entryValues="@array/pref_import_android_values"
|
||||
gecko:initialValues="@array/pref_import_android_defaults"
|
||||
gecko:entryKeys="@array/pref_import_android_keys"
|
||||
gecko:initialValues="@array/pref_import_android_values"
|
||||
android:title="@string/pref_import_android"
|
||||
android:positiveButtonText="@string/bookmarkhistory_button_import"
|
||||
android:negativeButtonText="@string/button_cancel"
|
||||
|
@ -40,8 +40,8 @@
|
||||
<org.mozilla.gecko.preferences.AndroidImportPreference
|
||||
android:key="android.not_a_preference.import_android"
|
||||
gecko:entries="@array/pref_import_android_entries"
|
||||
gecko:entryValues="@array/pref_import_android_values"
|
||||
gecko:initialValues="@array/pref_import_android_defaults"
|
||||
gecko:entryKeys="@array/pref_import_android_keys"
|
||||
gecko:initialValues="@array/pref_import_android_values"
|
||||
android:title="@string/pref_import_android"
|
||||
android:positiveButtonText="@string/bookmarkhistory_button_import"
|
||||
android:negativeButtonText="@string/button_cancel"
|
||||
|
@ -41,9 +41,8 @@
|
||||
<org.mozilla.gecko.preferences.AndroidImportPreference
|
||||
android:key="android.not_a_preference.import_android"
|
||||
gecko:entries="@array/pref_import_android_entries"
|
||||
gecko:entryValues="@array/pref_import_android_values"
|
||||
gecko:initialValues="@array/pref_import_android_defaults"
|
||||
gecko:entryKeys="@array/pref_import_android_keys"
|
||||
gecko:initialValues="@array/pref_import_android_values"
|
||||
android:title="@string/pref_import_android"
|
||||
android:positiveButtonText="@string/bookmarkhistory_button_import"
|
||||
android:negativeButtonText="@string/button_cancel"
|
||||
|
@ -31,32 +31,14 @@
|
||||
android:persistent="false" />
|
||||
|
||||
<!-- keys prefixed with "android.not_a_preference." are not synced with Gecko -->
|
||||
<PreferenceCategory android:title="@string/pref_clear_private_data_category">
|
||||
|
||||
<org.mozilla.gecko.preferences.PrivateDataPreference
|
||||
android:key="android.not_a_preference.privacy.clear"
|
||||
android:title="@string/pref_clear_private_data"
|
||||
android:persistent="true"
|
||||
android:positiveButtonText="@string/button_clear_data"
|
||||
gecko:entries="@array/pref_private_data_entries"
|
||||
gecko:entryValues="@array/pref_private_data_values"
|
||||
gecko:entryKeys="@array/pref_private_data_keys"
|
||||
gecko:initialValues="@array/pref_private_data_defaults" />
|
||||
|
||||
<!-- This pref is persisted in both Gecko and Java -->
|
||||
<org.mozilla.gecko.preferences.ListCheckboxPreference
|
||||
android:key="android.not_a_preference.history.clear_on_exit"
|
||||
gecko:entries="@array/pref_private_data_entries"
|
||||
gecko:entryValues="@array/pref_private_data_values"
|
||||
gecko:initialValues="@array/pref_clear_on_exit_defaults"
|
||||
|
||||
android:title="@string/pref_clear_on_exit_title"
|
||||
android:summary="@string/pref_clear_on_exit_summary"
|
||||
|
||||
android:dialogTitle="@string/pref_clear_on_exit_dialog_title"
|
||||
android:positiveButtonText="@string/button_set"/>
|
||||
|
||||
</PreferenceCategory>
|
||||
<org.mozilla.gecko.preferences.PrivateDataPreference
|
||||
android:key="android.not_a_preference.privacy.clear"
|
||||
android:title="@string/pref_clear_private_data"
|
||||
android:persistent="true"
|
||||
android:positiveButtonText="@string/button_clear_data"
|
||||
gecko:entries="@array/pref_private_data_entries"
|
||||
gecko:entryKeys="@array/pref_private_data_keys"
|
||||
gecko:initialValues="@array/pref_private_data_values" />
|
||||
|
||||
</PreferenceScreen>
|
||||
|
||||
|
@ -165,11 +165,7 @@
|
||||
<string name="pref_char_encoding">&pref_char_encoding;</string>
|
||||
<string name="pref_char_encoding_on">&pref_char_encoding_on;</string>
|
||||
<string name="pref_char_encoding_off">&pref_char_encoding_off;</string>
|
||||
<string name="pref_clear_private_data">&pref_clear_private_data2;</string>
|
||||
<string name="pref_clear_private_data_category">&pref_clear_private_data_category;</string>
|
||||
<string name="pref_clear_on_exit_title">&pref_clear_on_exit_title;</string>
|
||||
<string name="pref_clear_on_exit_summary">&pref_clear_on_exit_summary;</string>
|
||||
<string name="pref_clear_on_exit_dialog_title">&pref_clear_on_exit_dialog_title;</string>
|
||||
<string name="pref_clear_private_data">&pref_clear_private_data;</string>
|
||||
<string name="pref_plugins">&pref_plugins;</string>
|
||||
<string name="pref_plugins_enabled">&pref_plugins_enabled;</string>
|
||||
<string name="pref_plugins_tap_to_play">&pref_plugins_tap_to_play;</string>
|
||||
|
@ -4,15 +4,16 @@
|
||||
|
||||
package org.mozilla.gecko.util;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.UUID;
|
||||
|
||||
public final class JSONUtils {
|
||||
@ -50,20 +51,4 @@ public final class JSONUtils {
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
// Handles conversions between a JSONArray and a Set<String>
|
||||
public static Set<String> parseStringSet(JSONArray json) {
|
||||
final Set<String> ret = new HashSet<String>();
|
||||
|
||||
for (int i = 0; i < json.length(); i++) {
|
||||
try {
|
||||
ret.add(json.getString(i));
|
||||
} catch(JSONException ex) {
|
||||
Log.i(LOGTAG, "Error parsing json", ex);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,72 +0,0 @@
|
||||
/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.gecko.util;
|
||||
|
||||
import android.content.SharedPreferences;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
|
||||
|
||||
public class PrefUtils {
|
||||
private static final String LOGTAG = "GeckoPrefUtils";
|
||||
|
||||
// Cross version compatible way to get a string set from a pref
|
||||
public static Set<String> getStringSet(final SharedPreferences prefs,
|
||||
final String key,
|
||||
final Set<String> defaultVal) {
|
||||
if (!prefs.contains(key)) {
|
||||
return defaultVal;
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT < 11) {
|
||||
return getFromJSON(prefs, key);
|
||||
}
|
||||
|
||||
// If this is Android version >= 11, try to use a Set<String>.
|
||||
try {
|
||||
return prefs.getStringSet(key, new HashSet<String>());
|
||||
} catch(ClassCastException ex) {
|
||||
// A ClassCastException means we've upgraded from a pre-v11 Android to a new one
|
||||
final Set<String> val = getFromJSON(prefs, key);
|
||||
SharedPreferences.Editor edit = prefs.edit();
|
||||
putStringSet(edit, key, val).commit();
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
private static Set<String> getFromJSON(SharedPreferences prefs, String key) {
|
||||
try {
|
||||
final String val = prefs.getString(key, "[]");
|
||||
return JSONUtils.parseStringSet(new JSONArray(val));
|
||||
} catch(JSONException ex) {
|
||||
Log.i(LOGTAG, "Unable to parse JSON", ex);
|
||||
}
|
||||
|
||||
return new HashSet<String>();
|
||||
}
|
||||
|
||||
// Cross version compatible way to save a string set to a pref.
|
||||
// NOTE: The editor that is passed in will not commit the transaction for you. It is up to callers to commit
|
||||
// when they are done with any other changes to the database.
|
||||
public static SharedPreferences.Editor putStringSet(final SharedPreferences.Editor edit,
|
||||
final String key,
|
||||
final Set<String> vals) {
|
||||
if (Build.VERSION.SDK_INT < 11) {
|
||||
final JSONArray json = new JSONArray(vals);
|
||||
edit.putString(key, json.toString()).commit();
|
||||
} else {
|
||||
edit.putStringSet(key, vals).commit();
|
||||
}
|
||||
|
||||
return edit;
|
||||
}
|
||||
}
|
@ -1113,7 +1113,7 @@ var BrowserApp = {
|
||||
aTab.browser.dispatchEvent(evt);
|
||||
},
|
||||
|
||||
quit: function quit(aClear = {}) {
|
||||
quit: function quit() {
|
||||
// Figure out if there's at least one other browser window around.
|
||||
let lastBrowser = true;
|
||||
let e = Services.wm.getEnumerator("navigator:browser");
|
||||
@ -1133,10 +1133,8 @@ var BrowserApp = {
|
||||
Services.obs.notifyObservers(null, "browser-lastwindow-close-granted", null);
|
||||
}
|
||||
|
||||
BrowserApp.sanitize(aClear, function() {
|
||||
window.QueryInterface(Ci.nsIDOMChromeWindow).minimize();
|
||||
window.close();
|
||||
});
|
||||
window.QueryInterface(Ci.nsIDOMChromeWindow).minimize();
|
||||
window.close();
|
||||
},
|
||||
|
||||
saveAsPDF: function saveAsPDF(aBrowser) {
|
||||
@ -1390,50 +1388,33 @@ var BrowserApp = {
|
||||
}
|
||||
},
|
||||
|
||||
sanitize: function (aItems, callback) {
|
||||
if (!aItems) {
|
||||
return;
|
||||
}
|
||||
|
||||
sanitize: function (aItems) {
|
||||
let json = JSON.parse(aItems);
|
||||
let success = true;
|
||||
|
||||
for (let key in aItems) {
|
||||
if (!aItems[key])
|
||||
for (let key in json) {
|
||||
if (!json[key])
|
||||
continue;
|
||||
|
||||
key = key.replace("private.data.", "");
|
||||
|
||||
var promises = [];
|
||||
switch (key) {
|
||||
case "cookies_sessions":
|
||||
promises.push(Sanitizer.clearItem("cookies"));
|
||||
promises.push(Sanitizer.clearItem("sessions"));
|
||||
break;
|
||||
default:
|
||||
promises.push(Sanitizer.clearItem(key));
|
||||
try {
|
||||
switch (key) {
|
||||
case "cookies_sessions":
|
||||
Sanitizer.clearItem("cookies");
|
||||
Sanitizer.clearItem("sessions");
|
||||
break;
|
||||
default:
|
||||
Sanitizer.clearItem(key);
|
||||
}
|
||||
} catch (e) {
|
||||
dump("sanitize error: " + e);
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
|
||||
Promise.all(promises).then(function() {
|
||||
sendMessageToJava({
|
||||
type: "Sanitize:Finished",
|
||||
success: true
|
||||
});
|
||||
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
}).catch(function(err) {
|
||||
sendMessageToJava({
|
||||
type: "Sanitize:Finished",
|
||||
error: err,
|
||||
success: false
|
||||
});
|
||||
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
})
|
||||
sendMessageToJava({
|
||||
type: "Sanitize:Finished",
|
||||
success: success
|
||||
});
|
||||
},
|
||||
|
||||
getFocusedInput: function(aBrowser, aOnlyInputElements = false) {
|
||||
@ -1620,8 +1601,7 @@ var BrowserApp = {
|
||||
break;
|
||||
|
||||
case "Browser:Quit":
|
||||
Services.console.logStringMessage(aData);
|
||||
this.quit(JSON.parse(aData));
|
||||
this.quit();
|
||||
break;
|
||||
|
||||
case "SaveAs:PDF":
|
||||
@ -1639,7 +1619,7 @@ var BrowserApp = {
|
||||
break;
|
||||
|
||||
case "Sanitize:ClearData":
|
||||
this.sanitize(JSON.parse(aData));
|
||||
this.sanitize(aData);
|
||||
break;
|
||||
|
||||
case "FullScreen:Exit":
|
||||
|
@ -64,20 +64,16 @@ Sanitizer.prototype = {
|
||||
cache: {
|
||||
clear: function ()
|
||||
{
|
||||
return new Promise(function(resolve, reject) {
|
||||
var cache = Cc["@mozilla.org/netwerk/cache-storage-service;1"].getService(Ci.nsICacheStorageService);
|
||||
try {
|
||||
cache.clear();
|
||||
} catch(er) {}
|
||||
var cache = Cc["@mozilla.org/netwerk/cache-storage-service;1"].getService(Ci.nsICacheStorageService);
|
||||
try {
|
||||
cache.clear();
|
||||
} catch(er) {}
|
||||
|
||||
let imageCache = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools)
|
||||
.getImgCacheForDocument(null);
|
||||
try {
|
||||
imageCache.clearCache(false); // true=chrome, false=content
|
||||
} catch(er) {}
|
||||
|
||||
resolve();
|
||||
});
|
||||
let imageCache = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools)
|
||||
.getImgCacheForDocument(null);
|
||||
try {
|
||||
imageCache.clearCache(false); // true=chrome, false=content
|
||||
} catch(er) {}
|
||||
},
|
||||
|
||||
get canClear()
|
||||
@ -89,10 +85,7 @@ Sanitizer.prototype = {
|
||||
cookies: {
|
||||
clear: function ()
|
||||
{
|
||||
return new Promise(function(resolve, reject) {
|
||||
Services.cookies.removeAll();
|
||||
resolve();
|
||||
});
|
||||
Services.cookies.removeAll();
|
||||
},
|
||||
|
||||
get canClear()
|
||||
@ -104,24 +97,20 @@ Sanitizer.prototype = {
|
||||
siteSettings: {
|
||||
clear: function ()
|
||||
{
|
||||
return new Promise(function(resolve, reject) {
|
||||
// Clear site-specific permissions like "Allow this site to open popups"
|
||||
Services.perms.removeAll();
|
||||
// Clear site-specific permissions like "Allow this site to open popups"
|
||||
Services.perms.removeAll();
|
||||
|
||||
// Clear site-specific settings like page-zoom level
|
||||
Cc["@mozilla.org/content-pref/service;1"]
|
||||
.getService(Ci.nsIContentPrefService2)
|
||||
.removeAllDomains(null);
|
||||
// Clear site-specific settings like page-zoom level
|
||||
Cc["@mozilla.org/content-pref/service;1"]
|
||||
.getService(Ci.nsIContentPrefService2)
|
||||
.removeAllDomains(null);
|
||||
|
||||
// Clear "Never remember passwords for this site", which is not handled by
|
||||
// the permission manager
|
||||
var hosts = Services.logins.getAllDisabledHosts({})
|
||||
for (var host of hosts) {
|
||||
Services.logins.setLoginSavingEnabled(host, true);
|
||||
}
|
||||
|
||||
resolve();
|
||||
});
|
||||
// Clear "Never remember passwords for this site", which is not handled by
|
||||
// the permission manager
|
||||
var hosts = Services.logins.getAllDisabledHosts({})
|
||||
for (var host of hosts) {
|
||||
Services.logins.setLoginSavingEnabled(host, true);
|
||||
}
|
||||
},
|
||||
|
||||
get canClear()
|
||||
@ -133,15 +122,11 @@ Sanitizer.prototype = {
|
||||
offlineApps: {
|
||||
clear: function ()
|
||||
{
|
||||
return new Promise(function(resolve, reject) {
|
||||
var cacheService = Cc["@mozilla.org/netwerk/cache-storage-service;1"].getService(Ci.nsICacheStorageService);
|
||||
var appCacheStorage = cacheService.appCacheStorage(LoadContextInfo.default, null);
|
||||
try {
|
||||
appCacheStorage.asyncEvictStorage(null);
|
||||
} catch(er) {}
|
||||
|
||||
resolve();
|
||||
});
|
||||
var cacheService = Cc["@mozilla.org/netwerk/cache-storage-service;1"].getService(Ci.nsICacheStorageService);
|
||||
var appCacheStorage = cacheService.appCacheStorage(LoadContextInfo.default, null);
|
||||
try {
|
||||
appCacheStorage.asyncEvictStorage(null);
|
||||
} catch(er) {}
|
||||
},
|
||||
|
||||
get canClear()
|
||||
@ -153,21 +138,17 @@ Sanitizer.prototype = {
|
||||
history: {
|
||||
clear: function ()
|
||||
{
|
||||
return new Promise(function(resolve, reject) {
|
||||
sendMessageToJava({ type: "Sanitize:ClearHistory" }, function() {
|
||||
try {
|
||||
Services.obs.notifyObservers(null, "browser:purge-session-history", "");
|
||||
}
|
||||
catch (e) { }
|
||||
sendMessageToJava({ type: "Sanitize:ClearHistory" });
|
||||
|
||||
try {
|
||||
var predictor = Cc["@mozilla.org/network/predictor;1"].getService(Ci.nsINetworkPredictor);
|
||||
predictor.reset();
|
||||
} catch (e) { }
|
||||
try {
|
||||
Services.obs.notifyObservers(null, "browser:purge-session-history", "");
|
||||
}
|
||||
catch (e) { }
|
||||
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
try {
|
||||
var predictor = Cc["@mozilla.org/network/predictor;1"].getService(Ci.nsINetworkPredictor);
|
||||
predictor.reset();
|
||||
} catch (e) { }
|
||||
},
|
||||
|
||||
get canClear()
|
||||
@ -181,10 +162,7 @@ Sanitizer.prototype = {
|
||||
formdata: {
|
||||
clear: function ()
|
||||
{
|
||||
return new Promise(function(resolve, reject) {
|
||||
FormHistory.update({ op: "remove" });
|
||||
resolve();
|
||||
});
|
||||
FormHistory.update({ op: "remove" });
|
||||
},
|
||||
|
||||
canClear: function (aCallback)
|
||||
@ -202,18 +180,15 @@ Sanitizer.prototype = {
|
||||
downloadFiles: {
|
||||
clear: function ()
|
||||
{
|
||||
return new Promise(function(resolve, reject) {
|
||||
downloads.iterate(function (dl) {
|
||||
// Delete the downloaded files themselves
|
||||
let f = dl.targetFile;
|
||||
if (f.exists()) {
|
||||
f.remove(false);
|
||||
}
|
||||
downloads.iterate(function (dl) {
|
||||
// Delete the downloaded files themselves
|
||||
let f = dl.targetFile;
|
||||
if (f.exists()) {
|
||||
f.remove(false);
|
||||
}
|
||||
|
||||
// Also delete downloads from history
|
||||
dl.remove();
|
||||
});
|
||||
resolve();
|
||||
// Also delete downloads from history
|
||||
dl.remove();
|
||||
});
|
||||
},
|
||||
|
||||
@ -226,10 +201,7 @@ Sanitizer.prototype = {
|
||||
passwords: {
|
||||
clear: function ()
|
||||
{
|
||||
return new Promise(function(resolve, reject) {
|
||||
Services.logins.removeAllLogins();
|
||||
resolve();
|
||||
});
|
||||
Services.logins.removeAllLogins();
|
||||
},
|
||||
|
||||
get canClear()
|
||||
@ -242,16 +214,12 @@ Sanitizer.prototype = {
|
||||
sessions: {
|
||||
clear: function ()
|
||||
{
|
||||
return new Promise(function(resolve, reject) {
|
||||
// clear all auth tokens
|
||||
var sdr = Cc["@mozilla.org/security/sdr;1"].getService(Ci.nsISecretDecoderRing);
|
||||
sdr.logoutAndTeardown();
|
||||
// clear all auth tokens
|
||||
var sdr = Cc["@mozilla.org/security/sdr;1"].getService(Ci.nsISecretDecoderRing);
|
||||
sdr.logoutAndTeardown();
|
||||
|
||||
// clear FTP and plain HTTP auth sessions
|
||||
Services.obs.notifyObservers(null, "net:clear-active-logins", null);
|
||||
|
||||
resolve();
|
||||
});
|
||||
// clear FTP and plain HTTP auth sessions
|
||||
Services.obs.notifyObservers(null, "net:clear-active-logins", null);
|
||||
},
|
||||
|
||||
get canClear()
|
||||
|
Loading…
Reference in New Issue
Block a user