Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / common / extensions / docs / server2 / manifest_data_source.py
blob56da852d111b8a63c028f33f6e3c59e82ff00dde
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
6 import json
8 from data_source import DataSource
9 from future import Future
10 from manifest_features import ConvertDottedKeysToNested
11 from platform_util import GetPlatforms, PluralToSingular
14 def _ListifyAndSortDocs(features, app_name):
15 '''Convert a |feautres| dictionary, and all 'children' dictionaries, into
16 lists recursively. Sort lists first by 'level' then by name.
17 '''
18 def sort_key(item):
19 '''Key function to sort items primarily by level (according to index into
20 levels) then subsort by name.
21 '''
22 levels = ('required', 'recommended', 'only_one', 'optional')
24 return (levels.index(item.get('level', 'optional')), item['name'])
26 def coerce_example_to_feature(feature):
27 '''To display json in examples more clearly, convert the example of
28 |feature| into the feature format, with a name and children, to be rendered
29 by the templates. Only applicable to examples that are dictionaries.
30 '''
31 if not isinstance(feature.get('example'), dict):
32 if 'example' in feature:
33 feature['example'] = json.dumps(feature['example'])
34 return
35 # Add any keys/value pairs in the dict as children
36 for key, value in feature['example'].iteritems():
37 if not 'children' in feature:
38 feature['children'] = {}
39 feature['children'][key] = { 'name': key, 'example': value }
40 del feature['example']
41 del feature['has_example']
43 def convert_and_sort(features):
44 for key, value in features.items():
45 if 'example' in value:
46 value['has_example'] = True
47 example = json.dumps(value['example'])
48 if example == '{}':
49 value['example'] = '{...}'
50 elif example == '[]':
51 value['example'] = '[...]'
52 elif example == '[{}]':
53 value['example'] = '[{...}]'
54 else:
55 coerce_example_to_feature(value)
56 if 'children' in value:
57 features[key]['children'] = convert_and_sort(value['children'])
58 return sorted(features.values(), key=sort_key)
60 # Replace {{platform}} in the 'name' manifest property example with
61 # |app_name|, the convention that the normal template rendering uses.
62 # TODO(kalman): Make the example a template and pass this through there.
63 if 'name' in features:
64 name = features['name']
65 name['example'] = name['example'].replace('{{platform}}', app_name)
67 features = convert_and_sort(features)
69 return features
71 def _AddLevelAnnotations(features):
72 '''Add level annotations to |features|. |features| and children lists must be
73 sorted by 'level'. Annotations are added to the first item in a group of
74 features of the same 'level'.
76 The last item in a list has 'is_last' set to True.
77 '''
78 annotations = {
79 'required': 'Required',
80 'recommended': 'Recommended',
81 'only_one': 'Pick one (or none)',
82 'optional': 'Optional'
85 def add_annotation(item, annotation):
86 if not 'annotations' in item:
87 item['annotations'] = []
88 item['annotations'].insert(0, annotation)
90 def annotate(parent_level, features):
91 current_level = parent_level
92 for item in features:
93 level = item.get('level', 'optional')
94 if level != current_level:
95 add_annotation(item, annotations[level])
96 current_level = level
97 if 'children' in item:
98 annotate(level, item['children'])
99 if features:
100 features[-1]['is_last'] = True
102 annotate('required', features)
103 return features
105 class ManifestDataSource(DataSource):
106 '''Provides access to the properties in manifest features.
108 def __init__(self, server_instance, _):
109 self._platform_bundle = server_instance.platform_bundle
110 self._object_store = server_instance.object_store_creator.Create(
111 ManifestDataSource)
113 def _CreateManifestDataForPlatform(self, platform):
114 future_manifest_features = self._platform_bundle.GetFeaturesBundle(
115 platform).GetManifestFeatures()
116 def resolve():
117 manifest_features = future_manifest_features.Get()
118 return _AddLevelAnnotations(_ListifyAndSortDocs(
119 ConvertDottedKeysToNested(deepcopy(manifest_features)),
120 app_name=PluralToSingular(platform).capitalize()))
121 return Future(callback=resolve)
123 def _CreateManifestData(self):
124 manifest_data_futures = dict((p, self._CreateManifestDataForPlatform(p))
125 for p in GetPlatforms())
126 def resolve():
127 return dict((platform, future.Get())
128 for platform, future in manifest_data_futures.iteritems())
129 return Future(callback=resolve)
131 def _GetCachedManifestData(self):
132 data = self._object_store.Get('manifest_data').Get()
133 if data is None:
134 data = self._CreateManifestData().Get()
135 self._object_store.Set('manifest_data', data)
136 return data
138 def get(self, key):
139 return self._GetCachedManifestData().get(key)
141 def Refresh(self):
142 return self._CreateManifestData()