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.
5 from copy
import deepcopy
8 from data_source
import DataSource
9 from features_utility
import Filtered
10 from future
import Future
11 from manifest_features
import ConvertDottedKeysToNested
13 def _ListifyAndSortDocs(features
, app_name
):
14 '''Convert a |feautres| dictionary, and all 'children' dictionaries, into
15 lists recursively. Sort lists first by 'level' then by name.
18 '''Key function to sort items primarily by level (according to index into
19 levels) then subsort by name.
21 levels
= ('required', 'recommended', 'only_one', 'optional')
23 return (levels
.index(item
.get('level', 'optional')), item
['name'])
25 def coerce_example_to_feature(feature
):
26 '''To display json in examples more clearly, convert the example of
27 |feature| into the feature format, with a name and children, to be rendered
28 by the templates. Only applicable to examples that are dictionaries.
30 if not isinstance(feature
.get('example'), dict):
31 if 'example' in feature
:
32 feature
['example'] = json
.dumps(feature
['example'])
34 # Add any keys/value pairs in the dict as children
35 for key
, value
in feature
['example'].iteritems():
36 if not 'children' in feature
:
37 feature
['children'] = {}
38 feature
['children'][key
] = { 'name': key
, 'example': value
}
39 del feature
['example']
40 del feature
['has_example']
42 def convert_and_sort(features
):
43 for key
, value
in features
.items():
44 if 'example' in value
:
45 value
['has_example'] = True
46 example
= json
.dumps(value
['example'])
48 value
['example'] = '{...}'
50 value
['example'] = '[...]'
51 elif example
== '[{}]':
52 value
['example'] = '[{...}]'
54 coerce_example_to_feature(value
)
55 if 'children' in value
:
56 features
[key
]['children'] = convert_and_sort(value
['children'])
57 return sorted(features
.values(), key
=sort_key
)
59 # Replace {{platform}} in the 'name' manifest property example with
60 # |app_name|, the convention that the normal template rendering uses.
61 # TODO(kalman): Make the example a template and pass this through there.
62 if 'name' in features
:
63 name
= features
['name']
64 name
['example'] = name
['example'].replace('{{platform}}', app_name
)
66 features
= convert_and_sort(features
)
70 def _AddLevelAnnotations(features
):
71 '''Add level annotations to |features|. |features| and children lists must be
72 sorted by 'level'. Annotations are added to the first item in a group of
73 features of the same 'level'.
75 The last item in a list has 'is_last' set to True.
78 'required': 'Required',
79 'recommended': 'Recommended',
80 'only_one': 'Pick one (or none)',
81 'optional': 'Optional'
84 def add_annotation(item
, annotation
):
85 if not 'annotations' in item
:
86 item
['annotations'] = []
87 item
['annotations'].insert(0, annotation
)
89 def annotate(parent_level
, features
):
90 current_level
= parent_level
92 level
= item
.get('level', 'optional')
93 if level
!= current_level
:
94 add_annotation(item
, annotations
[level
])
96 if 'children' in item
:
97 annotate(level
, item
['children'])
99 features
[-1]['is_last'] = True
101 annotate('required', features
)
104 class ManifestDataSource(DataSource
):
105 '''Provides access to the properties in manifest features.
107 def __init__(self
, server_instance
, _
):
108 self
._features
_bundle
= server_instance
.features_bundle
109 self
._object
_store
= server_instance
.object_store_creator
.Create(
112 def _CreateManifestData(self
):
113 future_manifest_features
= self
._features
_bundle
.GetManifestFeatures()
115 manifest_features
= future_manifest_features
.Get()
116 def for_templates(manifest_features
, platform
):
117 return _AddLevelAnnotations(_ListifyAndSortDocs(
118 ConvertDottedKeysToNested(
119 deepcopy(Filtered(manifest_features
, platform
+ 's'))),
120 app_name
=platform
.capitalize()))
122 'apps': for_templates(manifest_features
, 'app'),
123 'extensions': for_templates(manifest_features
, 'extension')
125 return Future(callback
=resolve
)
127 def _GetCachedManifestData(self
):
128 data
= self
._object
_store
.Get('manifest_data').Get()
130 data
= self
._CreateManifestData
().Get()
131 self
._object
_store
.Set('manifest_data', data
)
135 return self
._CreateManifestData
()
138 return self
._GetCachedManifestData
().get(key
)