CMSettings: Add secure validators and relocate protected apps validator

Move validators from CMSettings.System into CMSettings,
add validators for CMSettings.Secure, and move protected apps validator
from CMSettings.System to CMSettings.Secure

Change-Id: I9f4e1bef7ff5be100376d2d03d34483d12938158
This commit is contained in:
Yvonne Wong 2015-12-03 15:33:56 -08:00 committed by Gerrit Code Review
parent 0fa8756f31
commit fc97734c06
2 changed files with 187 additions and 156 deletions

View File

@ -522,9 +522,11 @@ public class CMSettingsProvider extends ContentProvider {
// Validate value if inserting int System table
final String name = values.getAsString(Settings.NameValueTable.NAME);
final String value = values.getAsString(Settings.NameValueTable.VALUE);
if (CMDatabaseHelper.CMTableNames.TABLE_SYSTEM.equals(tableName)) {
final String value = values.getAsString(Settings.NameValueTable.VALUE);
validateSystemSettingNameValue(name, value);
} else if (CMDatabaseHelper.CMTableNames.TABLE_SECURE.equals(tableName)) {
validateSecureSettingValue(name, value);
}
SQLiteDatabase db = dbHelper.getWritableDatabase();
@ -591,9 +593,11 @@ public class CMSettingsProvider extends ContentProvider {
// Validate value if updating System table
final String name = values.getAsString(Settings.NameValueTable.NAME);
final String value = values.getAsString(Settings.NameValueTable.VALUE);
if (CMDatabaseHelper.CMTableNames.TABLE_SYSTEM.equals(tableName)) {
final String value = values.getAsString(Settings.NameValueTable.VALUE);
validateSystemSettingNameValue(name, value);
} else if (CMDatabaseHelper.CMTableNames.TABLE_SECURE.equals(tableName)) {
validateSecureSettingValue(name, value);
}
int callingUserId = UserHandle.getCallingUserId();
@ -792,7 +796,7 @@ public class CMSettingsProvider extends ContentProvider {
}
private void validateSystemSettingNameValue(String name, String value) {
CMSettings.System.Validator validator = CMSettings.System.VALIDATORS.get(name);
CMSettings.Validator validator = CMSettings.System.VALIDATORS.get(name);
if (validator == null) {
throw new IllegalArgumentException("Invalid setting: " + name);
}
@ -803,5 +807,16 @@ public class CMSettingsProvider extends ContentProvider {
}
}
private void validateSecureSettingValue(String name, String value) {
CMSettings.Validator validator = CMSettings.Secure.VALIDATORS.get(name);
// Not all secure settings have validators, but if a validator exists, the validate method
// should return true
if (validator != null && !validator.validate(value)) {
throw new IllegalArgumentException("Invalid value: " + value
+ " for setting: " + name);
}
}
// TODO Add caching
}

View File

@ -269,6 +269,140 @@ public final class CMSettings {
}
}
// region Validators
/** @hide */
public static interface Validator {
public boolean validate(String value);
}
private static final Validator sBooleanValidator =
new DiscreteValueValidator(new String[] {"0", "1"});
private static final Validator sNonNegativeIntegerValidator = new Validator() {
@Override
public boolean validate(String value) {
try {
return Integer.parseInt(value) >= 0;
} catch (NumberFormatException e) {
return false;
}
}
};
private static final Validator sUriValidator = new Validator() {
@Override
public boolean validate(String value) {
try {
Uri.decode(value);
return true;
} catch (IllegalArgumentException e) {
return false;
}
}
};
private static final Validator sColorValidator =
new InclusiveIntegerRangeValidator(Integer.MIN_VALUE, Integer.MAX_VALUE);
private static final Validator sAlwaysTrueValidator = new Validator() {
@Override
public boolean validate(String value) {
return true;
}
};
private static final class DiscreteValueValidator implements Validator {
private final String[] mValues;
public DiscreteValueValidator(String[] values) {
mValues = values;
}
@Override
public boolean validate(String value) {
return ArrayUtils.contains(mValues, value);
}
}
private static final class InclusiveIntegerRangeValidator implements Validator {
private final int mMin;
private final int mMax;
public InclusiveIntegerRangeValidator(int min, int max) {
mMin = min;
mMax = max;
}
@Override
public boolean validate(String value) {
try {
final int intValue = Integer.parseInt(value);
return intValue >= mMin && intValue <= mMax;
} catch (NumberFormatException e) {
return false;
}
}
}
private static final class InclusiveFloatRangeValidator implements Validator {
private final float mMin;
private final float mMax;
public InclusiveFloatRangeValidator(float min, float max) {
mMin = min;
mMax = max;
}
@Override
public boolean validate(String value) {
try {
final float floatValue = Float.parseFloat(value);
return floatValue >= mMin && floatValue <= mMax;
} catch (NumberFormatException e) {
return false;
}
}
}
private static final class DelimitedListValidator implements Validator {
private final ArraySet<String> mValidValueSet;
private final String mDelimiter;
private final boolean mAllowEmptyList;
public DelimitedListValidator(String[] validValues, String delimiter,
boolean allowEmptyList) {
mValidValueSet = new ArraySet<String>(Arrays.asList(validValues));
mDelimiter = delimiter;
mAllowEmptyList = allowEmptyList;
}
@Override
public boolean validate(String value) {
ArraySet<String> values = new ArraySet<String>();
if (!TextUtils.isEmpty(value)) {
final String[] array = TextUtils.split(value, Pattern.quote(mDelimiter));
for (String item : array) {
if (TextUtils.isEmpty(item)) {
continue;
}
values.add(item);
}
}
if (values.size() > 0) {
values.removeAll(mValidValueSet);
// values.size() will be non-zero if it contains any values not in
// mValidValueSet
return values.size() == 0;
} else if (mAllowEmptyList) {
return true;
}
return false;
}
}
// endregion Validators
/**
* System settings, containing miscellaneous CM system preferences. This table holds simple
* name/value pairs. There are convenience functions for accessing individual settings entries.
@ -278,53 +412,12 @@ public final class CMSettings {
public static final String SYS_PROP_CM_SETTING_VERSION = "sys.cm_settings_system_version";
/** @hide */
public static interface Validator {
public boolean validate(String value);
}
private static final NameValueCache sNameValueCache = new NameValueCache(
SYS_PROP_CM_SETTING_VERSION,
CONTENT_URI,
CALL_METHOD_GET_SYSTEM,
CALL_METHOD_PUT_SYSTEM);
private static final Validator sBooleanValidator =
new DiscreteValueValidator(new String[] {"0", "1"});
private static final Validator sNonNegativeIntegerValidator = new Validator() {
@Override
public boolean validate(String value) {
try {
return Integer.parseInt(value) >= 0;
} catch (NumberFormatException e) {
return false;
}
}
};
private static final Validator sUriValidator = new Validator() {
@Override
public boolean validate(String value) {
try {
Uri.decode(value);
return true;
} catch (IllegalArgumentException e) {
return false;
}
}
};
private static final Validator sColorValidator =
new InclusiveIntegerRangeValidator(Integer.MIN_VALUE, Integer.MAX_VALUE);
private static final Validator sAlwaysTrueValidator = new Validator() {
@Override
public boolean validate(String value) {
return true;
}
};
// region Methods
/**
@ -671,116 +764,6 @@ public final class CMSettings {
// endregion
private static final class DiscreteValueValidator implements Validator {
private final String[] mValues;
public DiscreteValueValidator(String[] values) {
mValues = values;
}
@Override
public boolean validate(String value) {
return ArrayUtils.contains(mValues, value);
}
}
private static final class InclusiveIntegerRangeValidator implements Validator {
private final int mMin;
private final int mMax;
public InclusiveIntegerRangeValidator(int min, int max) {
mMin = min;
mMax = max;
}
@Override
public boolean validate(String value) {
try {
final int intValue = Integer.parseInt(value);
return intValue >= mMin && intValue <= mMax;
} catch (NumberFormatException e) {
return false;
}
}
}
private static final class InclusiveFloatRangeValidator implements Validator {
private final float mMin;
private final float mMax;
public InclusiveFloatRangeValidator(float min, float max) {
mMin = min;
mMax = max;
}
@Override
public boolean validate(String value) {
try {
final float floatValue = Float.parseFloat(value);
return floatValue >= mMin && floatValue <= mMax;
} catch (NumberFormatException e) {
return false;
}
}
}
private static final class DelimitedListValidator implements Validator {
private final ArraySet<String> mValidValueSet;
private final String mDelimiter;
private final boolean mAllowEmptyList;
public DelimitedListValidator(String[] validValues, String delimiter,
boolean allowEmptyList) {
mValidValueSet = new ArraySet<String>(Arrays.asList(validValues));
mDelimiter = delimiter;
mAllowEmptyList = allowEmptyList;
}
@Override
public boolean validate(String value) {
ArraySet<String> values = new ArraySet<String>();
if (!TextUtils.isEmpty(value)) {
final String[] array = TextUtils.split(value, Pattern.quote(mDelimiter));
for (String item : array) {
if (TextUtils.isEmpty(item)) {
continue;
}
values.add(item);
}
}
if (values.size() > 0) {
values.removeAll(mValidValueSet);
// values.size() will be non-zero if it contains any values not in
// mValidValueSet
return values.size() == 0;
} else if (mAllowEmptyList) {
return true;
}
return false;
}
}
/**
* @hide
*/
public static final Validator PROTECTED_COMPONENTS_VALIDATOR = new Validator() {
private final String mDelimiter = "|";
@Override
public boolean validate(String value) {
if (!TextUtils.isEmpty(value)) {
final String[] array = TextUtils.split(value, Pattern.quote(mDelimiter));
for (String item : array) {
if (TextUtils.isEmpty(item)) {
return false; // Empty components not allowed
}
}
}
return true; // Empty list is allowed though.
}
};
// region System Settings
/**
@ -2024,7 +2007,6 @@ public final class CMSettings {
NOTIFICATION_LIGHT_PULSE_CUSTOM_ENABLE_VALIDATOR);
VALIDATORS.put(NOTIFICATION_LIGHT_PULSE_CUSTOM_VALUES,
NOTIFICATION_LIGHT_PULSE_CUSTOM_VALUES_VALIDATOR);
VALIDATORS.put(Secure.PROTECTED_COMPONENTS, PROTECTED_COMPONENTS_VALIDATOR);
};
// endregion
}
@ -2047,7 +2029,6 @@ public final class CMSettings {
// region Methods
/**
* Put a delimited list as a string
* @param resolver to access the database with
@ -2668,6 +2649,41 @@ public final class CMSettings {
public static boolean isLegacySetting(String key) {
return ArrayUtils.contains(LEGACY_SECURE_SETTINGS, key);
}
/**
* @hide
*/
public static final Validator PROTECTED_COMPONENTS_VALIDATOR = new Validator() {
private final String mDelimiter = "|";
@Override
public boolean validate(String value) {
if (!TextUtils.isEmpty(value)) {
final String[] array = TextUtils.split(value, Pattern.quote(mDelimiter));
for (String item : array) {
if (TextUtils.isEmpty(item)) {
return false; // Empty components not allowed
}
}
}
return true; // Empty list is allowed though.
}
};
/**
* Mapping of validators for all secure settings. This map is used to validate both valid
* keys as well as validating the values for those keys.
*
* Note: Make sure if you add a new Secure setting you create a Validator for it and add
* it to this map.
*
* @hide
*/
public static final Map<String, Validator> VALIDATORS =
new ArrayMap<String, Validator>();
static {
VALIDATORS.put(PROTECTED_COMPONENTS, PROTECTED_COMPONENTS_VALIDATOR);
}
}
/**