| # Copyright 2017 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. |
| |
| """Utility functions for modifying an app's settings file using JSON.""" |
| |
| import json |
| import logging |
| |
| |
| def UnicodeToStr(data): |
| """Recursively converts any Unicode to Python strings. |
| |
| Args: |
| data: The data to be converted. |
| |
| Return: |
| A copy of the given data, but with instances of Unicode converted to Python |
| strings. |
| """ |
| if isinstance(data, dict): |
| return {UnicodeToStr(key): UnicodeToStr(value) |
| for key, value in data.iteritems()} |
| elif isinstance(data, list): |
| return [UnicodeToStr(element) for element in data] |
| elif isinstance(data, unicode): |
| return data.encode('utf-8') |
| return data |
| |
| |
| def ExtractSettingsFromJson(filepath): |
| """Extracts the settings data from the given JSON file. |
| |
| Args: |
| filepath: The path to the JSON file to read. |
| |
| Return: |
| The data read from the JSON file with strings converted to Python strings. |
| """ |
| # json.load() loads strings as unicode, which causes issues when trying |
| # to edit string values in preference files, so convert to Python strings |
| with open(filepath) as prefs_file: |
| return UnicodeToStr(json.load(prefs_file)) |
| |
| |
| def ApplySharedPreferenceSetting(shared_pref, setting): |
| """Applies the given app settings to the given device. |
| |
| Modifies an installed app's settings by modifying its shared preference |
| settings file. Provided settings data must be a settings dictionary, |
| which are in the following format: |
| { |
| "package": "com.example.package", |
| "filename": "AppSettingsFile.xml", |
| "supports_encrypted_path": true, |
| "set": { |
| "SomeBoolToSet": true, |
| "SomeStringToSet": "StringValue", |
| }, |
| "remove": [ |
| "list", |
| "of", |
| "keys", |
| "to", |
| "remove", |
| ] |
| } |
| |
| Example JSON files that can be read with ExtractSettingsFromJson and passed to |
| this function are in //chrome/android/shared_preference_files/test/. |
| |
| Args: |
| shared_pref: The devil SharedPrefs object for the device the settings will |
| be applied to. |
| setting: A settings dictionary to apply. |
| """ |
| shared_pref.Load() |
| for key in setting.get('remove', []): |
| try: |
| shared_pref.Remove(key) |
| except KeyError: |
| logging.warning("Attempted to remove non-existent key %s", key) |
| for key, value in setting.get('set', {}).iteritems(): |
| if isinstance(value, bool): |
| shared_pref.SetBoolean(key, value) |
| elif isinstance(value, basestring): |
| shared_pref.SetString(key, value) |
| elif isinstance(value, long) or isinstance(value, int): |
| shared_pref.SetLong(key, value) |
| elif isinstance(value, list): |
| shared_pref.SetStringSet(key, value) |
| else: |
| raise ValueError("Given invalid value type %s for key %s" % ( |
| str(type(value)), key)) |
| shared_pref.Commit() |