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.
7 from data_source import DataSource
8 import features_utility
9 from manifest_features import ConvertDottedKeysToNested
10 from third_party.json_schema_compiler.json_parse import Parse
12 def _ListifyAndSortDocs(features, app_name):
13 '''Convert a |feautres| dictionary, and all 'children' dictionaries, into
14 lists recursively. Sort lists first by 'level' then by name.
17 '''Key function to sort items primarily by level (according to index into
18 levels) then subsort by name.
20 levels = ('required', 'recommended', 'only_one', 'optional')
22 return (levels.index(item.get('level', 'optional')), item['name'])
24 def coerce_example_to_feature(feature):
25 '''To display json in examples more clearly, convert the example of
26 |feature| into the feature format, with a name and children, to be rendered
27 by the templates. Only applicable to examples that are dictionaries.
29 if not isinstance(feature.get('example'), dict):
30 if 'example' in feature:
31 feature['example'] = json.dumps(feature['example'])
33 # Add any keys/value pairs in the dict as children
34 for key, value in feature['example'].iteritems():
35 if not 'children' in feature:
36 feature['children'] = {}
37 feature['children'][key] = { 'name': key, 'example': value }
38 del feature['example']
39 del feature['has_example']
41 def convert_and_sort(features):
42 for key, value in features.items():
43 if 'example' in value:
44 value['has_example'] = True
45 example = json.dumps(value['example'])
47 value['example'] = '{...}'
49 value['example'] = '[...]'
51 coerce_example_to_feature(value)
52 if 'children' in value:
53 features[key]['children'] = convert_and_sort(value['children'])
54 return sorted(features.values(), key=sort_key)
56 # Replace {{title}} in the 'name' manifest property example with |app_name|
57 if 'name' in features:
58 name = features['name']
59 name['example'] = name['example'].replace('{{title}}', app_name)
61 features = convert_and_sort(features)
65 def _AddLevelAnnotations(features):
66 '''Add level annotations to |features|. |features| and children lists must be
67 sorted by 'level'. Annotations are added to the first item in a group of
68 features of the same 'level'.
70 The last item in a list has 'is_last' set to True.
73 'required': 'Required',
74 'recommended': 'Recommended',
75 'only_one': 'Pick one (or none)',
76 'optional': 'Optional'
79 def add_annotation(item, annotation):
80 if not 'annotations' in item:
81 item['annotations'] = []
82 item['annotations'].insert(0, annotation)
84 def annotate(parent_level, features):
85 current_level = parent_level
87 level = item.get('level', 'optional')
88 if level != current_level:
89 add_annotation(item, annotations[level])
91 if 'children' in item:
92 annotate(level, item['children'])
94 features[-1]['is_last'] = True
96 annotate('required', features)
99 class ManifestDataSource(DataSource):
100 '''Provides access to the properties in manifest features.
102 def __init__(self, server_instance, _):
103 self._features_bundle = server_instance.features_bundle
104 self._object_store = server_instance.object_store_creator.Create(
107 def _CreateManifestData(self):
108 def for_templates(manifest_features, platform):
109 return _AddLevelAnnotations(
111 ConvertDottedKeysToNested(
112 features_utility.Filtered(manifest_features, platform)),
113 app_name=platform.capitalize()))
114 manifest_features = self._features_bundle.GetManifestFeatures()
116 'apps': for_templates(manifest_features, 'apps'),
117 'extensions': for_templates(manifest_features, 'extensions')
120 def _GetCachedManifestData(self, force_update=False):
121 data = self._object_store.Get('manifest_data').Get()
122 if data is None or force_update:
123 data = self._CreateManifestData()
124 self._object_store.Set('manifest_data', data)
128 self._GetCachedManifestData(force_update=True)
131 return self._GetCachedManifestData().get(key)