Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(305)

Side by Side Diff: chrome/common/extensions/docs/server2/features_utility.py

Issue 344453003: Docserver: separate models for apps and extensions (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Quick fixes Created 6 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
5 '''
6 Utility functions for working with the Feature abstraction. Features are grouped
7 into a dictionary by name. Each Feature is guaranteed to have the following two
8 keys:
9 name - a string, the name of the feature
10 platform - a list containing 'apps' or 'extensions', both, or neither.
11
12 A Feature may have other keys from a _features.json file as well. Features with
13 a whitelist are ignored as they are only useful to specific apps or extensions.
14 '''
15
16 from copy import copy
17
18 from branch_utility import BranchUtility
19
20
21 def _GetPlatformsForExtensionTypes(extension_types):
22 platforms = []
23 if extension_types == 'all' or 'platform_app' in extension_types:
24 platforms.append('apps')
25 if extension_types == 'all' or 'extension' in extension_types:
26 platforms.append('extensions')
27 return platforms
28
29
30 def Parse(features_json):
31 '''Process JSON from a _features.json file, standardizing it into a dictionary
32 of Features.
33 '''
34 features = {}
35
36 def ignore_feature(name, value):
37 '''Returns true if this feature should be ignored. Features are ignored if
38 they are only available to whitelisted apps or component extensions/apps, as
39 in these cases the APIs are not available to public developers.
40
41 Private APIs are also unavailable to public developers, but logic elsewhere
42 makes sure they are not listed. So they shouldn't be ignored via this
43 mechanism.
44 '''
45 if name.endswith('Private'):
46 return False
47 return value.get('location') == 'component' or 'whitelist' in value
48
49 for name, rawvalue in features_json.iteritems():
50 # Some feature names correspond to a list, typically because they're
51 # whitelisted in stable for certain extensions and available in dev for
52 # everybody else. Force a list down to a single feature by attempting to
53 # remove the entries that don't affect the typical usage of an API.
54 if isinstance(rawvalue, list):
55 available_values = [subvalue for subvalue in rawvalue
56 if not ignore_feature(name, subvalue)]
57 if not available_values:
58 continue
59
60 if len(available_values) == 1:
61 value = available_values[0]
62 else:
63 # Multiple available values probably implies different feature
64 # configurations for apps vs extensions. Currently, this is 'commands'.
65 # To get the ball rolling, add a hack to combine the extension types.
66 # See http://crbug.com/316194.
67 extension_types = set()
68 for available_value in available_values:
69 extension_types.update(available_value.get('extension_types', ()))
70
71 # For the base value, select the one with the most recent availability.
72 channel_names = BranchUtility.GetAllChannelNames()
73 available_values.sort(
74 key=lambda v: channel_names.index(v.get('channel', 'stable')))
75
76 # Note: copy() is enough because only a single toplevel key is modified.
77 value = copy(available_values[0])
78 value['extension_types'] = list(extension_types)
79 else:
80 value = rawvalue
81
82 if ignore_feature(name, value):
83 continue
84
85 # Now we transform 'extension_types' into the more useful 'platforms'.
86 #
87 # But first, note that 'platforms' has a double meaning. In the docserver
88 # model (what we're in the process of generating) it means 'apps' vs
89 # 'extensions'. In the JSON features as read from Chrome it means 'win' vs
90 # 'mac'. Ignore the latter.
91 value.pop('platforms', None)
92 extension_types = value.pop('extension_types', None)
93
94 platforms = []
95 if extension_types is not None:
96 platforms = _GetPlatformsForExtensionTypes(extension_types)
97
98 features[name] = {
99 'name': name,
100 'platforms': platforms,
101 }
102 features[name].update(value)
103
104 return features
105
106
107 def Filtered(features, platform):
108 '''Create a new Features dictionary from |features| that contains only items
109 relevant to |platform|. Feature values are unmodified; callers should
110 deepcopy() if they need to modify them.
111 '''
112 return dict((name, feature) for name, feature in features.iteritems()
113 if platform in feature['platforms'])
114
115
116 def MergedWith(features, other):
117 '''Merge |features| with an additional dictionary to create a new features
118 dictionary. If a feature is common to both |features| and |other|, then it is
119 merged using the standard dictionary update instead of being overwritten.
120 Returns the new Features dictionary.
121 '''
122 for key, value in other.iteritems():
123 if key in features:
124 features[key].update(value)
125 else:
126 features[key] = value
127
128 # Ensure the Feature schema is enforced for all added items.
129 if not 'name' in features[key]:
130 features[key]['name'] = key
131 if not 'platforms' in features[key]:
132 features[key]['platforms'] = []
133
134 return features
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698