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