2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
7 class TemplateWriter(object):
8 '''Abstract base class for writing policy templates in various formats.
9 The methods of this class will be called by PolicyTemplateGenerator.
12 def __init__(self, platforms, config):
13 '''Initializes a TemplateWriter object.
16 platforms: List of platforms for which this writer can write policies.
17 config: A dictionary of information required to generate the template.
18 It contains some key-value pairs, including the following examples:
19 'build': 'chrome' or 'chromium'
20 'branding': 'Google Chrome' or 'Chromium'
21 'mac_bundle_id': The Mac bundle id of Chrome. (Only set when building
23 messages: List of all the message strings from the grd file. Most of them
24 are also present in the policy data structures that are passed to
25 methods. That is the preferred way of accessing them, this should only
26 be used in exceptional cases. An example for its use is the
27 IDS_POLICY_WIN_SUPPORTED_WINXPSP2 message in ADM files, because that
28 cannot be associated with any policy or group.
30 self.platforms = platforms
33 def IsDeprecatedPolicySupported(self, policy):
34 '''Checks if the given deprecated policy is supported by the writer.
37 policy: The dictionary of the policy.
40 True if the writer chooses to include the deprecated 'policy' in its
45 def IsFuturePolicySupported(self, policy):
46 '''Checks if the given future policy is supported by the writer.
49 policy: The dictionary of the policy.
52 True if the writer chooses to include the deprecated 'policy' in its
57 def IsPolicySupported(self, policy):
58 '''Checks if the given policy is supported by the writer.
59 In other words, the set of platforms supported by the writer
60 has a common subset with the set of platforms that support
64 policy: The dictionary of the policy.
67 True if the writer chooses to include 'policy' in its output.
69 if ('deprecated' in policy and policy['deprecated'] is True and
70 not self.IsDeprecatedPolicySupported(policy)):
73 if ('future' in policy and policy['future'] is True and
74 not self.IsFuturePolicySupported(policy)):
77 if '*' in self.platforms:
78 # Currently chrome_os is only catched here.
80 for supported_on in policy['supported_on']:
81 for supported_on_platform in supported_on['platforms']:
82 if supported_on_platform in self.platforms:
86 def CanBeRecommended(self, policy):
87 '''Checks if the given policy can be recommended.'''
88 return policy.get('features', {}).get('can_be_recommended', False)
90 def CanBeMandatory(self, policy):
91 '''Checks if the given policy can be mandatory.'''
92 return policy.get('features', {}).get('can_be_mandatory', True)
94 def IsPolicySupportedOnPlatform(self, policy, platform):
95 '''Checks if |policy| is supported on |platform|.
98 policy: The dictionary of the policy.
99 platform: The platform to check; one of 'win', 'mac', 'linux' or
102 is_supported = lambda x: platform in x['platforms']
103 return any(filter(is_supported, policy['supported_on']))
105 def _GetPoliciesForWriter(self, group):
106 '''Filters the list of policies in the passed group that are supported by
110 group: The dictionary of the policy group.
112 Returns: The list of policies of the policy group that are compatible
115 if not 'policies' in group:
118 for policy in group['policies']:
119 if self.IsPolicySupported(policy):
120 result.append(policy)
124 '''Initializes the writer. If the WriteTemplate method is overridden, then
125 this method must be called as first step of each template generation
130 def WriteTemplate(self, template):
131 '''Writes the given template definition.
134 template: Template definition to write.
137 Generated output for the passed template definition.
139 self.messages = template['messages']
141 template['policy_definitions'] = \
142 self.PreprocessPolicies(template['policy_definitions'])
144 for policy in template['policy_definitions']:
145 if policy['type'] == 'group':
146 child_policies = self._GetPoliciesForWriter(policy)
147 child_recommended_policies = filter(self.CanBeRecommended,
150 # Only write nonempty groups.
151 self.BeginPolicyGroup(policy)
152 for child_policy in child_policies:
153 # Nesting of groups is currently not supported.
154 self.WritePolicy(child_policy)
155 self.EndPolicyGroup()
156 if child_recommended_policies:
157 self.BeginRecommendedPolicyGroup(policy)
158 for child_policy in child_recommended_policies:
159 self.WriteRecommendedPolicy(child_policy)
160 self.EndRecommendedPolicyGroup()
161 elif self.IsPolicySupported(policy):
162 self.WritePolicy(policy)
163 if self.CanBeRecommended(policy):
164 self.WriteRecommendedPolicy(policy)
167 return self.GetTemplateText()
169 def PreprocessPolicies(self, policy_list):
170 '''Preprocesses a list of policies according to a given writer's needs.
171 Preprocessing steps include sorting policies and stripping unneeded
172 information such as groups (for writers that ignore them).
173 Subclasses are encouraged to override this method, overriding
174 implementations may call one of the provided specialized implementations.
175 The default behaviour is to use SortPoliciesGroupsFirst().
178 policy_list: A list containing the policies to sort.
181 The sorted policy list.
183 return self.SortPoliciesGroupsFirst(policy_list)
185 def WritePolicy(self, policy):
186 '''Appends the template text corresponding to a policy into the
190 policy: The policy as it is found in the JSON file.
192 raise NotImplementedError()
194 def WriteRecommendedPolicy(self, policy):
195 '''Appends the template text corresponding to a recommended policy into the
199 policy: The recommended policy as it is found in the JSON file.
202 #raise NotImplementedError()
205 def BeginPolicyGroup(self, group):
206 '''Appends the template text corresponding to the beginning of a
207 policy group into the internal buffer.
210 group: The policy group as it is found in the JSON file.
214 def EndPolicyGroup(self):
215 '''Appends the template text corresponding to the end of a
216 policy group into the internal buffer.
220 def BeginRecommendedPolicyGroup(self, group):
221 '''Appends the template text corresponding to the beginning of a recommended
222 policy group into the internal buffer.
225 group: The recommended policy group as it is found in the JSON file.
229 def EndRecommendedPolicyGroup(self):
230 '''Appends the template text corresponding to the end of a recommended
231 policy group into the internal buffer.
235 def BeginTemplate(self):
236 '''Appends the text corresponding to the beginning of the whole
237 template into the internal buffer.
239 raise NotImplementedError()
241 def EndTemplate(self):
242 '''Appends the text corresponding to the end of the whole
243 template into the internal buffer.
247 def GetTemplateText(self):
248 '''Gets the content of the internal template buffer.
251 The generated template from the the internal buffer as a string.
253 raise NotImplementedError()
255 def SortPoliciesGroupsFirst(self, policy_list):
256 '''Sorts a list of policies alphabetically. The order is the
257 following: first groups alphabetically by caption, then other policies
258 alphabetically by name. The order of policies inside groups is unchanged.
261 policy_list: The list of policies to sort. Sub-lists in groups will not
264 policy_list.sort(key=self.GetPolicySortingKeyGroupsFirst)
267 def FlattenGroupsAndSortPolicies(self, policy_list, sorting_key=None):
268 '''Sorts a list of policies according to |sorting_key|, defaulting
269 to alphabetical sorting if no key is given. If |policy_list| contains
270 policies with type="group", it is flattened first, i.e. any groups' contents
271 are inserted into the list as first-class elements and the groups are then
275 for policy in policy_list:
276 if policy['type'] == 'group':
277 for grouped_policy in policy['policies']:
278 new_list.append(grouped_policy)
280 new_list.append(policy)
281 if sorting_key == None:
282 sorting_key = self.GetPolicySortingKeyName
283 new_list.sort(key=sorting_key)
286 def GetPolicySortingKeyName(self, policy):
287 return policy['name']
289 def GetPolicySortingKeyGroupsFirst(self, policy):
290 '''Extracts a sorting key from a policy. These keys can be used for
291 list.sort() methods to sort policies.
292 See TemplateWriter.SortPolicies for usage.
294 is_group = policy['type'] == 'group'
296 # Groups are sorted by caption.
297 str_key = policy['caption']
299 # Regular policies are sorted by name.
300 str_key = policy['name']
301 # Groups come before regular policies.
302 return (not is_group, str_key)