1a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)# Copyright 2014 The Chromium Authors. All rights reserved.
2a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be
3a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)# found in the LICENSE file.
4a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
6a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class ContentSettings(dict):
7a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
8a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  """A dict interface to interact with device content settings.
9a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
10a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  System properties are key/value pairs as exposed by adb shell content.
11a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  """
12a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
13a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  def __init__(self, table, device):
14a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    super(ContentSettings, self).__init__()
15116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    sdk_version_string = device.GetProp('ro.build.version.sdk')
16a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    try:
17a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      sdk_version = int(sdk_version_string)
18a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      assert sdk_version >= 16, (
19a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          'ContentSettings supported only on SDK 16 and later')
20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    except ValueError:
21a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      assert False, ('Unknown SDK version %s' % sdk_version_string)
22a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    self._table = table
23a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    self._device = device
24a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  @staticmethod
26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  def _GetTypeBinding(value):
27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if isinstance(value, bool):
28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return 'b'
29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if isinstance(value, float):
30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return 'f'
31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if isinstance(value, int):
32a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return 'i'
33a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if isinstance(value, long):
34a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return 'l'
35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if isinstance(value, str):
36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      return 's'
37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    raise ValueError('Unsupported type %s' % type(value))
38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  def iteritems(self):
40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    # Example row:
41a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    # 'Row: 0 _id=13, name=logging_id2, value=-1fccbaa546705b05'
42f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    for row in self._device.RunShellCommand(
43116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        'content query --uri content://%s' % self._table, as_root=True):
44a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      fields = row.split(', ')
45a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      key = None
46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      value = None
47a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      for field in fields:
48a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        k, _, v = field.partition('=')
49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        if k == 'name':
50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          key = v
51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        elif k == 'value':
52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          value = v
536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      if not key:
546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        continue
556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      if not value:
566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        value = ''
57a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      yield key, value
58a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  def __getitem__(self, key):
60f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return self._device.RunShellCommand(
61a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        'content query --uri content://%s --where "name=\'%s\'" '
62116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        '--projection value' % (self._table, key), as_root=True).strip()
63a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
64a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  def __setitem__(self, key, value):
65a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if key in self:
66f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      self._device.RunShellCommand(
67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          'content update --uri content://%s '
68a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          '--bind value:%s:%s --where "name=\'%s\'"' % (
69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)              self._table,
70f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)              self._GetTypeBinding(value), value, key),
71116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          as_root=True)
72a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    else:
73f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      self._device.RunShellCommand(
74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          'content insert --uri content://%s '
75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          '--bind name:%s:%s --bind value:%s:%s' % (
76a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)              self._table,
77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)              self._GetTypeBinding(key), key,
78f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)              self._GetTypeBinding(value), value),
79116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch          as_root=True)
80a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  def __delitem__(self, key):
82f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    self._device.RunShellCommand(
83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        'content delete --uri content://%s '
84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        '--bind name:%s:%s' % (
85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            self._table,
86f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            self._GetTypeBinding(key), key),
87116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        as_root=True)
88