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