Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / tools / grit / grit / format / policy_templates / writers / admx_writer.py
1 #!/usr/bin/env python
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.
5
6 from xml.dom import minidom
7 from grit.format.policy_templates.writers import xml_formatted_writer
8
9
10 def GetWriter(config):
11   '''Factory method for instanciating the ADMXWriter. Every Writer needs a
12   GetWriter method because the TemplateFormatter uses this method to
13   instantiate a Writer.
14   '''
15   return ADMXWriter(['win'], config)
16
17
18 class ADMXWriter(xml_formatted_writer.XMLFormattedWriter):
19   '''Class for generating an ADMX policy template. It is used by the
20   PolicyTemplateGenerator to write the admx file.
21   '''
22
23   # DOM root node of the generated ADMX document.
24   _doc = None
25
26   # The ADMX "policies" element that contains the ADMX "policy" elements that
27   # are generated.
28   _active_policies_elem = None
29
30   def _AdmlString(self, name):
31     '''Creates a reference to the named string in an ADML file.
32     Args:
33       name: Name of the referenced ADML string.
34     '''
35     return '$(string.' + name + ')'
36
37   def _AdmlStringExplain(self, name):
38     '''Creates a reference to the named explanation string in an ADML file.
39     Args:
40       name: Name of the referenced ADML explanation.
41     '''
42     return '$(string.' + name + '_Explain)'
43
44   def _AdmlPresentation(self, name):
45     '''Creates a reference to the named presentation element in an ADML file.
46     Args:
47       name: Name of the referenced ADML presentation element.
48     '''
49     return '$(presentation.' + name + ')'
50
51   def _AddPolicyNamespaces(self, parent, prefix, namespace):
52     '''Generates the ADMX "policyNamespace" element and adds the elements to the
53     passed parent element. The namespace of the generated ADMX document is
54     define via the ADMX "target" element. Used namespaces are declared with an
55     ADMX "using" element. ADMX "target" and "using" elements are children of the
56     ADMX "policyNamespace" element.
57
58     Args:
59       parent: The parent node to which all generated elements are added.
60       prefix: A logical name that can be used in the generated ADMX document to
61         refere to this namespace.
62       namespace: Namespace of the generated ADMX document.
63     '''
64     policy_namespaces_elem = self.AddElement(parent, 'policyNamespaces')
65     attributes = {
66       'prefix': prefix,
67       'namespace': namespace,
68     }
69     self.AddElement(policy_namespaces_elem, 'target', attributes)
70     attributes = {
71       'prefix': 'windows',
72       'namespace': 'Microsoft.Policies.Windows',
73     }
74     self.AddElement(policy_namespaces_elem, 'using', attributes)
75
76   def _AddCategory(self, parent, name, display_name,
77                    parent_category_name=None):
78     '''Adds an ADMX category element to the passed parent node. The following
79     snippet shows an example of a category element where "chromium" is the value
80     of the parameter name:
81
82     <category displayName="$(string.chromium)" name="chromium"/>
83
84     Each parent node can have only one category with a given name. Adding the
85     same category again with the same attributes is ignored, but adding it
86     again with different attributes is an error.
87
88     Args:
89       parent: The parent node to which all generated elements are added.
90       name: Name of the category.
91       display_name: Display name of the category.
92       parent_category_name: Name of the parent category. Defaults to None.
93     '''
94     existing = filter(lambda e: e.getAttribute('name') == name,
95                       parent.getElementsByTagName('category'))
96     if existing:
97       assert len(existing) == 1
98       assert existing[0].getAttribute('name') == name
99       assert existing[0].getAttribute('displayName') == display_name
100       return
101     attributes = {
102       'name': name,
103       'displayName': display_name,
104     }
105     category_elem = self.AddElement(parent, 'category', attributes)
106     if parent_category_name:
107       attributes = {'ref': parent_category_name}
108       self.AddElement(category_elem, 'parentCategory', attributes)
109
110   def _AddCategories(self, categories):
111     '''Generates the ADMX "categories" element and adds it to the categories
112     main node. The "categories" element defines the category for the policies
113     defined in this ADMX document. Here is an example of an ADMX "categories"
114     element:
115
116     <categories>
117       <category displayName="$(string.google)" name="google"/>
118       <category displayName="$(string.googlechrome)" name="googlechrome">
119         <parentCategory ref="google"/>
120       </category>
121     </categories>
122
123     Args:
124       categories_path: The categories path e.g. ['google', 'googlechrome']. For
125         each level in the path a "category" element will be generated. Except
126         for the root level, each level refers to its parent. Since the root
127         level category has no parent it does not require a parent reference.
128     '''
129     category_name = None
130     for category in categories:
131       parent_category_name = category_name
132       category_name = category
133       self._AddCategory(self._categories_elem, category_name,
134                         self._AdmlString(category_name), parent_category_name)
135
136   def _AddSupportedOn(self, parent, supported_os):
137     '''Generates the "supportedOn" ADMX element and adds it to the passed
138     parent node. The "supportedOn" element contains information about supported
139     Windows OS versions. The following code snippet contains an example of a
140     "supportedOn" element:
141
142     <supportedOn>
143       <definitions>
144         <definition name="SUPPORTED_WINXPSP2"
145                     displayName="$(string.SUPPORTED_WINXPSP2)"/>
146         </definitions>
147         ...
148     </supportedOn>
149
150     Args:
151       parent: The parent element to which all generated elements are added.
152       supported_os: List with all supported Win OSes.
153     '''
154     supported_on_elem = self.AddElement(parent, 'supportedOn')
155     definitions_elem = self.AddElement(supported_on_elem, 'definitions')
156     attributes = {
157       'name': supported_os,
158       'displayName': self._AdmlString(supported_os)
159     }
160     self.AddElement(definitions_elem, 'definition', attributes)
161
162   def _AddStringPolicy(self, parent, name):
163     '''Generates ADMX elements for a String-Policy and adds them to the
164     passed parent node.
165     '''
166     attributes = {
167       'id': name,
168       'valueName': name,
169     }
170     self.AddElement(parent, 'text', attributes)
171
172   def _AddIntPolicy(self, parent, name):
173     '''Generates ADMX elements for an Int-Policy and adds them to the passed
174     parent node.
175     '''
176     attributes = {
177       'id': name,
178       'valueName': name,
179       'maxValue': '2000000000',
180     }
181     self.AddElement(parent, 'decimal', attributes)
182
183   def _AddEnumPolicy(self, parent, policy):
184     '''Generates ADMX elements for an Enum-Policy and adds them to the
185     passed parent element.
186     '''
187     name = policy['name']
188     items = policy['items']
189     attributes = {
190       'id': name,
191       'valueName': name,
192     }
193     enum_elem = self.AddElement(parent, 'enum', attributes)
194     for item in items:
195       attributes = {'displayName': self._AdmlString(item['name'])}
196       item_elem = self.AddElement(enum_elem, 'item', attributes)
197       value_elem = self.AddElement(item_elem, 'value')
198       value_string = str(item['value'])
199       if policy['type'] == 'int-enum':
200         self.AddElement(value_elem, 'decimal', {'value': value_string})
201       else:
202         self.AddElement(value_elem, 'string', {}, value_string)
203
204   def _AddListPolicy(self, parent, key, name):
205     '''Generates ADMX XML elements for a List-Policy and adds them to the
206     passed parent element.
207     '''
208     attributes = {
209       # The ID must be in sync with ID of the corresponding element in the ADML
210       # file.
211       'id': name + 'Desc',
212       'valuePrefix': '',
213       'key': key + '\\' + name,
214     }
215     self.AddElement(parent, 'list', attributes)
216
217   def _AddMainPolicy(self, parent):
218     '''Generates ADMX elements for a Main-Policy amd adds them to the
219     passed parent element.
220     '''
221     enabled_value_elem = self.AddElement(parent, 'enabledValue');
222     self.AddElement(enabled_value_elem, 'decimal', {'value': '1'})
223     disabled_value_elem = self.AddElement(parent, 'disabledValue');
224     self.AddElement(disabled_value_elem, 'decimal', {'value': '0'})
225
226   def _GetElements(self, policy_group_elem):
227     '''Returns the ADMX "elements" child from an ADMX "policy" element. If the
228     "policy" element has no "elements" child yet, a new child is created.
229
230     Args:
231       policy_group_elem: The ADMX "policy" element from which the child element
232         "elements" is returned.
233
234     Raises:
235       Exception: The policy_group_elem does not contain a ADMX "policy" element.
236     '''
237     if policy_group_elem.tagName != 'policy':
238       raise Exception('Expected a "policy" element but got a "%s" element'
239                       % policy_group_elem.tagName)
240     elements_list = policy_group_elem.getElementsByTagName('elements');
241     if len(elements_list) == 0:
242       return self.AddElement(policy_group_elem, 'elements')
243     elif len(elements_list) == 1:
244       return elements_list[0]
245     else:
246       raise Exception('There is supposed to be only one "elements" node but'
247                       ' there are %s.' % str(len(elements_list)))
248
249   def _WritePolicy(self, policy, name, key, parent):
250     '''Generates AMDX elements for a Policy. There are four different policy
251     types: Main-Policy, String-Policy, Enum-Policy and List-Policy.
252     '''
253     policies_elem = self._active_policies_elem
254     policy_type = policy['type']
255     policy_name = policy['name']
256     if policy_type == 'external':
257       # This type can only be set through cloud policy.
258       return
259
260     attributes = {
261       'name': name,
262       'class': self.config['win_group_policy_class'],
263       'displayName': self._AdmlString(policy_name),
264       'explainText': self._AdmlStringExplain(policy_name),
265       'presentation': self._AdmlPresentation(policy_name),
266       'key': key,
267     }
268     # Store the current "policy" AMDX element in self for later use by the
269     # WritePolicy method.
270     policy_elem = self.AddElement(policies_elem, 'policy',
271                                   attributes)
272     self.AddElement(policy_elem, 'parentCategory',
273                     {'ref': parent})
274     self.AddElement(policy_elem, 'supportedOn',
275                     {'ref': self.config['win_supported_os']})
276     if policy_type == 'main':
277       self.AddAttribute(policy_elem, 'valueName', policy_name)
278       self._AddMainPolicy(policy_elem)
279     elif policy_type in ('string', 'dict'):
280       # 'dict' policies are configured as JSON-encoded strings on Windows.
281       parent = self._GetElements(policy_elem)
282       self._AddStringPolicy(parent, policy_name)
283     elif policy_type == 'int':
284       parent = self._GetElements(policy_elem)
285       self._AddIntPolicy(parent, policy_name)
286     elif policy_type in ('int-enum', 'string-enum'):
287       parent = self._GetElements(policy_elem)
288       self._AddEnumPolicy(parent, policy)
289     elif policy_type in ('list', 'string-enum-list'):
290       parent = self._GetElements(policy_elem)
291       self._AddListPolicy(parent, key, policy_name)
292     elif policy_type == 'group':
293       pass
294     else:
295       raise Exception('Unknown policy type %s.' % policy_type)
296
297   def WritePolicy(self, policy):
298     if self.CanBeMandatory(policy):
299       self._WritePolicy(policy,
300                         policy['name'],
301                         self.config['win_reg_mandatory_key_name'],
302                         self._active_mandatory_policy_group_name)
303
304   def WriteRecommendedPolicy(self, policy):
305     self._WritePolicy(policy,
306                       policy['name'] + '_recommended',
307                       self.config['win_reg_recommended_key_name'],
308                       self._active_recommended_policy_group_name)
309
310   def _BeginPolicyGroup(self, group, name, parent):
311     '''Generates ADMX elements for a Policy-Group.
312     '''
313     attributes = {
314       'name': name,
315       'displayName': self._AdmlString(group['name'] + '_group'),
316     }
317     category_elem = self.AddElement(self._categories_elem,
318                                     'category',
319                                     attributes)
320     attributes = {
321       'ref': parent
322     }
323     self.AddElement(category_elem, 'parentCategory', attributes)
324
325   def BeginPolicyGroup(self, group):
326     self._BeginPolicyGroup(group,
327                            group['name'],
328                            self.config['win_mandatory_category_path'][-1])
329     self._active_mandatory_policy_group_name = group['name']
330
331   def EndPolicyGroup(self):
332     self._active_mandatory_policy_group_name = \
333         self.config['win_mandatory_category_path'][-1]
334
335   def BeginRecommendedPolicyGroup(self, group):
336     self._BeginPolicyGroup(group,
337                            group['name'] + '_recommended',
338                            self.config['win_recommended_category_path'][-1])
339     self._active_recommended_policy_group_name = group['name'] + '_recommended'
340
341   def EndRecommendedPolicyGroup(self):
342     self._active_recommended_policy_group_name = \
343         self.config['win_recommended_category_path'][-1]
344
345   def BeginTemplate(self):
346     '''Generates the skeleton of the ADMX template. An ADMX template contains
347     an ADMX "PolicyDefinitions" element with four child nodes: "policies"
348     "policyNamspaces", "resources", "supportedOn" and "categories"
349     '''
350     dom_impl = minidom.getDOMImplementation('')
351     self._doc = dom_impl.createDocument(None, 'policyDefinitions', None)
352     policy_definitions_elem = self._doc.documentElement
353
354     policy_definitions_elem.attributes['revision'] = '1.0'
355     policy_definitions_elem.attributes['schemaVersion'] = '1.0'
356
357     self._AddPolicyNamespaces(policy_definitions_elem,
358                               self.config['admx_prefix'],
359                               self.config['admx_namespace'])
360     self.AddElement(policy_definitions_elem, 'resources',
361                     {'minRequiredRevision' : '1.0'})
362     self._AddSupportedOn(policy_definitions_elem,
363                          self.config['win_supported_os'])
364     self._categories_elem = self.AddElement(policy_definitions_elem,
365                                             'categories')
366     self._AddCategories(self.config['win_mandatory_category_path'])
367     self._AddCategories(self.config['win_recommended_category_path'])
368     self._active_policies_elem = self.AddElement(policy_definitions_elem,
369                                                  'policies')
370     self._active_mandatory_policy_group_name = \
371         self.config['win_mandatory_category_path'][-1]
372     self._active_recommended_policy_group_name = \
373         self.config['win_recommended_category_path'][-1]
374
375   def GetTemplateText(self):
376     return self.ToPrettyXml(self._doc)