permissions_data_source.py revision 3551c9c881056c480085172ff9840cab31610854
1# Copyright 2013 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5from itertools import ifilter
6from operator import itemgetter
7
8import features_utility as features
9from third_party.json_schema_compiler.json_parse import Parse
10
11def _ListifyPermissions(permissions):
12  '''Filter out any permissions that do not have a description or with a name
13  that ends with Private then sort permissions features by name into a list.
14  '''
15  def filter_permissions(perm):
16    return 'description' in perm and not perm['name'].endswith('Private')
17
18  return sorted(
19      ifilter(filter_permissions, permissions.values()),
20      key=itemgetter('name'))
21
22def _AddDependencyDescriptions(permissions, api_features):
23  '''Use |api_features| to determine the dependencies APIs have on permissions.
24  Add descriptions to |permissions| based on those dependencies.
25  '''
26  for name, permission in permissions.iteritems():
27    # Don't overwrite the description created by expanding a partial template.
28    if 'description' in permission or not permission['platforms']:
29      continue
30
31    has_deps = False
32    if name in api_features:
33      for dependency in api_features[name].get('dependencies', ()):
34        if dependency.startswith('permission:'):
35          has_deps = True
36
37    if has_deps:
38      permission['partial'] = 'permissions/generic_description'
39
40class PermissionsDataSource(object):
41  '''Load and format permissions features to be used by templates. Requries a
42  template data source be set before use.
43  '''
44  def __init__(self,
45               compiled_fs_factory,
46               file_system,
47               api_features_path,
48               permissions_features_path,
49               permissions_json_path):
50    self._api_features_path = api_features_path
51    self._permissions_features_path = permissions_features_path
52    self._permissions_json_path = permissions_json_path
53    self._file_system = file_system
54    self._cache = compiled_fs_factory.Create(
55        self._CreatePermissionsDataSource, PermissionsDataSource)
56
57  def SetTemplateDataSource(self, template_data_source_factory):
58    '''Initialize a template data source to be used to render partial templates
59    into descriptions for permissions. Must be called before .get
60    '''
61    self._template_data_source = template_data_source_factory.Create(None, '')
62
63  def _CreatePermissionsDataSource(self, _, content):
64    '''Combine the contents of |_permissions_json_path| and
65    |_permissions_features_path|. Filter into lists, one for extensions and
66    one for apps.
67    '''
68    api_features = Parse(self._file_system.ReadSingle(self._api_features_path))
69
70    def filter_for_platform(permissions, platform):
71      return _ListifyPermissions(features.Filtered(permissions, platform))
72
73    permissions_json = Parse(self._file_system.ReadSingle(
74        self._permissions_json_path))
75    permission_features = features.MergedWith(
76        features.Parse(Parse(content)), permissions_json)
77
78    _AddDependencyDescriptions(permission_features, api_features)
79    # Turn partial templates into descriptions, ensure anchors are set.
80    for permission in permission_features.values():
81      if not 'anchor' in permission:
82        permission['anchor'] = permission['name']
83      if 'partial' in permission:
84        permission['description'] = self._template_data_source.get(
85            permission['partial'])
86        del permission['partial']
87
88    return {
89      'declare_apps': filter_for_platform(permission_features, 'app'),
90      'declare_extensions': filter_for_platform(
91          permission_features, 'extension')
92    }
93
94  def get(self, key):
95    return self._cache.GetFromFile(self._permissions_features_path)[key]
96