Index: build/android/devil/android/sdk/shared_prefs.py |
diff --git a/build/android/devil/android/sdk/shared_prefs.py b/build/android/devil/android/sdk/shared_prefs.py |
deleted file mode 100644 |
index 2b430d5c4dc719a61b51a50edeb642aa19a2cb19..0000000000000000000000000000000000000000 |
--- a/build/android/devil/android/sdk/shared_prefs.py |
+++ /dev/null |
@@ -1,390 +0,0 @@ |
-# 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. |
- |
-"""Helper object to read and modify Shared Preferences from Android apps. |
- |
-See e.g.: |
- http://developer.android.com/reference/android/content/SharedPreferences.html |
-""" |
- |
-import logging |
-import posixpath |
- |
-from xml.etree import ElementTree |
- |
- |
-_XML_DECLARATION = "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n" |
- |
- |
-class BasePref(object): |
- """Base class for getting/setting the value of a specific preference type. |
- |
- Should not be instantiated directly. The SharedPrefs collection will |
- instantiate the appropriate subclasses, which directly manipulate the |
- underlying xml document, to parse and serialize values according to their |
- type. |
- |
- Args: |
- elem: An xml ElementTree object holding the preference data. |
- |
- Properties: |
- tag_name: A string with the tag that must be used for this preference type. |
- """ |
- tag_name = None |
- |
- def __init__(self, elem): |
- if elem.tag != type(self).tag_name: |
- raise TypeError('Property %r has type %r, but trying to access as %r' % |
- (elem.get('name'), elem.tag, type(self).tag_name)) |
- self._elem = elem |
- |
- def __str__(self): |
- """Get the underlying xml element as a string.""" |
- return ElementTree.tostring(self._elem) |
- |
- def get(self): |
- """Get the value of this preference.""" |
- return self._elem.get('value') |
- |
- def set(self, value): |
- """Set from a value casted as a string.""" |
- self._elem.set('value', str(value)) |
- |
- @property |
- def has_value(self): |
- """Check whether the element has a value.""" |
- return self._elem.get('value') is not None |
- |
- |
-class BooleanPref(BasePref): |
- """Class for getting/setting a preference with a boolean value. |
- |
- The underlying xml element has the form, e.g.: |
- <boolean name="featureEnabled" value="false" /> |
- """ |
- tag_name = 'boolean' |
- VALUES = {'true': True, 'false': False} |
- |
- def get(self): |
- """Get the value as a Python bool.""" |
- return type(self).VALUES[super(BooleanPref, self).get()] |
- |
- def set(self, value): |
- """Set from a value casted as a bool.""" |
- super(BooleanPref, self).set('true' if value else 'false') |
- |
- |
-class FloatPref(BasePref): |
- """Class for getting/setting a preference with a float value. |
- |
- The underlying xml element has the form, e.g.: |
- <float name="someMetric" value="4.7" /> |
- """ |
- tag_name = 'float' |
- |
- def get(self): |
- """Get the value as a Python float.""" |
- return float(super(FloatPref, self).get()) |
- |
- |
-class IntPref(BasePref): |
- """Class for getting/setting a preference with an int value. |
- |
- The underlying xml element has the form, e.g.: |
- <int name="aCounter" value="1234" /> |
- """ |
- tag_name = 'int' |
- |
- def get(self): |
- """Get the value as a Python int.""" |
- return int(super(IntPref, self).get()) |
- |
- |
-class LongPref(IntPref): |
- """Class for getting/setting a preference with a long value. |
- |
- The underlying xml element has the form, e.g.: |
- <long name="aLongCounter" value="1234" /> |
- |
- We use the same implementation from IntPref. |
- """ |
- tag_name = 'long' |
- |
- |
-class StringPref(BasePref): |
- """Class for getting/setting a preference with a string value. |
- |
- The underlying xml element has the form, e.g.: |
- <string name="someHashValue">249b3e5af13d4db2</string> |
- """ |
- tag_name = 'string' |
- |
- def get(self): |
- """Get the value as a Python string.""" |
- return self._elem.text |
- |
- def set(self, value): |
- """Set from a value casted as a string.""" |
- self._elem.text = str(value) |
- |
- |
-class StringSetPref(StringPref): |
- """Class for getting/setting a preference with a set of string values. |
- |
- The underlying xml element has the form, e.g.: |
- <set name="managed_apps"> |
- <string>com.mine.app1</string> |
- <string>com.mine.app2</string> |
- <string>com.mine.app3</string> |
- </set> |
- """ |
- tag_name = 'set' |
- |
- def get(self): |
- """Get a list with the string values contained.""" |
- value = [] |
- for child in self._elem: |
- assert child.tag == 'string' |
- value.append(child.text) |
- return value |
- |
- def set(self, value): |
- """Set from a sequence of values, each casted as a string.""" |
- for child in list(self._elem): |
- self._elem.remove(child) |
- for item in value: |
- ElementTree.SubElement(self._elem, 'string').text = str(item) |
- |
- |
-_PREF_TYPES = {c.tag_name: c for c in [BooleanPref, FloatPref, IntPref, |
- LongPref, StringPref, StringSetPref]} |
- |
- |
-class SharedPrefs(object): |
- def __init__(self, device, package, filename): |
- """Helper object to read and update "Shared Prefs" of Android apps. |
- |
- Such files typically look like, e.g.: |
- |
- <?xml version='1.0' encoding='utf-8' standalone='yes' ?> |
- <map> |
- <int name="databaseVersion" value="107" /> |
- <boolean name="featureEnabled" value="false" /> |
- <string name="someHashValue">249b3e5af13d4db2</string> |
- </map> |
- |
- Example usage: |
- |
- prefs = shared_prefs.SharedPrefs(device, 'com.my.app', 'my_prefs.xml') |
- prefs.Load() |
- prefs.GetString('someHashValue') # => '249b3e5af13d4db2' |
- prefs.SetInt('databaseVersion', 42) |
- prefs.Remove('featureEnabled') |
- prefs.Commit() |
- |
- The object may also be used as a context manager to automatically load and |
- commit, respectively, upon entering and leaving the context. |
- |
- Args: |
- device: A DeviceUtils object. |
- package: A string with the package name of the app that owns the shared |
- preferences file. |
- filename: A string with the name of the preferences file to read/write. |
- """ |
- self._device = device |
- self._xml = None |
- self._package = package |
- self._filename = filename |
- self._path = '/data/data/%s/shared_prefs/%s' % (package, filename) |
- self._changed = False |
- |
- def __repr__(self): |
- """Get a useful printable representation of the object.""" |
- return '<{cls} file {filename} for {package} on {device}>'.format( |
- cls=type(self).__name__, filename=self.filename, package=self.package, |
- device=str(self._device)) |
- |
- def __str__(self): |
- """Get the underlying xml document as a string.""" |
- return _XML_DECLARATION + ElementTree.tostring(self.xml) |
- |
- @property |
- def package(self): |
- """Get the package name of the app that owns the shared preferences.""" |
- return self._package |
- |
- @property |
- def filename(self): |
- """Get the filename of the shared preferences file.""" |
- return self._filename |
- |
- @property |
- def path(self): |
- """Get the full path to the shared preferences file on the device.""" |
- return self._path |
- |
- @property |
- def changed(self): |
- """True if properties have changed and a commit would be needed.""" |
- return self._changed |
- |
- @property |
- def xml(self): |
- """Get the underlying xml document as an ElementTree object.""" |
- if self._xml is None: |
- self._xml = ElementTree.Element('map') |
- return self._xml |
- |
- def Load(self): |
- """Load the shared preferences file from the device. |
- |
- A empty xml document, which may be modified and saved on |commit|, is |
- created if the file does not already exist. |
- """ |
- if self._device.FileExists(self.path): |
- self._xml = ElementTree.fromstring( |
- self._device.ReadFile(self.path, as_root=True)) |
- assert self._xml.tag == 'map' |
- else: |
- self._xml = None |
- self._changed = False |
- |
- def Clear(self): |
- """Clear all of the preferences contained in this object.""" |
- if self._xml is not None and len(self): # only clear if not already empty |
- self._xml = None |
- self._changed = True |
- |
- def Commit(self): |
- """Save the current set of preferences to the device. |
- |
- Only actually saves if some preferences have been modified. |
- """ |
- if not self.changed: |
- return |
- self._device.RunShellCommand( |
- ['mkdir', '-p', posixpath.dirname(self.path)], |
- as_root=True, check_return=True) |
- self._device.WriteFile(self.path, str(self), as_root=True) |
- self._device.KillAll(self.package, exact=True, as_root=True, quiet=True) |
- self._changed = False |
- |
- def __len__(self): |
- """Get the number of preferences in this collection.""" |
- return len(self.xml) |
- |
- def PropertyType(self, key): |
- """Get the type (i.e. tag name) of a property in the collection.""" |
- return self._GetChild(key).tag |
- |
- def HasProperty(self, key): |
- try: |
- self._GetChild(key) |
- return True |
- except KeyError: |
- return False |
- |
- def GetBoolean(self, key): |
- """Get a boolean property.""" |
- return BooleanPref(self._GetChild(key)).get() |
- |
- def SetBoolean(self, key, value): |
- """Set a boolean property.""" |
- self._SetPrefValue(key, value, BooleanPref) |
- |
- def GetFloat(self, key): |
- """Get a float property.""" |
- return FloatPref(self._GetChild(key)).get() |
- |
- def SetFloat(self, key, value): |
- """Set a float property.""" |
- self._SetPrefValue(key, value, FloatPref) |
- |
- def GetInt(self, key): |
- """Get an int property.""" |
- return IntPref(self._GetChild(key)).get() |
- |
- def SetInt(self, key, value): |
- """Set an int property.""" |
- self._SetPrefValue(key, value, IntPref) |
- |
- def GetLong(self, key): |
- """Get a long property.""" |
- return LongPref(self._GetChild(key)).get() |
- |
- def SetLong(self, key, value): |
- """Set a long property.""" |
- self._SetPrefValue(key, value, LongPref) |
- |
- def GetString(self, key): |
- """Get a string property.""" |
- return StringPref(self._GetChild(key)).get() |
- |
- def SetString(self, key, value): |
- """Set a string property.""" |
- self._SetPrefValue(key, value, StringPref) |
- |
- def GetStringSet(self, key): |
- """Get a string set property.""" |
- return StringSetPref(self._GetChild(key)).get() |
- |
- def SetStringSet(self, key, value): |
- """Set a string set property.""" |
- self._SetPrefValue(key, value, StringSetPref) |
- |
- def Remove(self, key): |
- """Remove a preference from the collection.""" |
- self.xml.remove(self._GetChild(key)) |
- |
- def AsDict(self): |
- """Return the properties and their values as a dictionary.""" |
- d = {} |
- for child in self.xml: |
- pref = _PREF_TYPES[child.tag](child) |
- d[child.get('name')] = pref.get() |
- return d |
- |
- def __enter__(self): |
- """Load preferences file from the device when entering a context.""" |
- self.Load() |
- return self |
- |
- def __exit__(self, exc_type, _exc_value, _traceback): |
- """Save preferences file to the device when leaving a context.""" |
- if not exc_type: |
- self.Commit() |
- |
- def _GetChild(self, key): |
- """Get the underlying xml node that holds the property of a given key. |
- |
- Raises: |
- KeyError when the key is not found in the collection. |
- """ |
- for child in self.xml: |
- if child.get('name') == key: |
- return child |
- raise KeyError(key) |
- |
- def _SetPrefValue(self, key, value, pref_cls): |
- """Set the value of a property. |
- |
- Args: |
- key: The key of the property to set. |
- value: The new value of the property. |
- pref_cls: A subclass of BasePref used to access the property. |
- |
- Raises: |
- TypeError when the key already exists but with a different type. |
- """ |
- try: |
- pref = pref_cls(self._GetChild(key)) |
- old_value = pref.get() |
- except KeyError: |
- pref = pref_cls(ElementTree.SubElement( |
- self.xml, pref_cls.tag_name, {'name': key})) |
- old_value = None |
- if old_value != value: |
- pref.set(value) |
- self._changed = True |
- logging.info('Setting property: %s', pref) |