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 6from xml.dom import minidom 7from grit.format.policy_templates.writers import xml_formatted_writer 8 9 10def GetWriter(config): 11 '''Factory method for instanciating the ADMLWriter. Every Writer needs a 12 GetWriter method because the TemplateFormatter uses this method to 13 instantiate a Writer. 14 ''' 15 return ADMLWriter(['win'], config) 16 17 18class ADMLWriter(xml_formatted_writer.XMLFormattedWriter): 19 ''' Class for generating an ADML policy template. It is used by the 20 PolicyTemplateGenerator to write the ADML file. 21 ''' 22 23 # DOM root node of the generated ADML document. 24 _doc = None 25 26 # The string-table contains all ADML "string" elements. 27 _string_table_elem = None 28 29 # The presentation-table is the container for presentation elements, that 30 # describe the presentation of Policy-Groups and Policies. 31 _presentation_table_elem = None 32 33 def _AddString(self, parent, id, text): 34 ''' Adds an ADML "string" element to the passed parent. The following 35 ADML snippet contains an example: 36 37 <string id="$(id)">$(text)</string> 38 39 Args: 40 parent: Parent element to which the new "string" element is added. 41 id: ID of the newly created "string" element. 42 text: Value of the newly created "string" element. 43 ''' 44 string_elem = self.AddElement(parent, 'string', {'id': id}) 45 string_elem.appendChild(self._doc.createTextNode(text)) 46 47 def WritePolicy(self, policy): 48 '''Generates the ADML elements for a Policy. 49 <stringTable> 50 ... 51 <string id="$(policy_group_name)">$(caption)</string> 52 <string id="$(policy_group_name)_Explain">$(description)</string> 53 </stringTable> 54 55 <presentationTables> 56 ... 57 <presentation id=$(policy_group_name)/> 58 </presentationTables> 59 60 Args: 61 policy: The Policy to generate ADML elements for. 62 ''' 63 policy_type = policy['type'] 64 policy_name = policy['name'] 65 if 'caption' in policy: 66 policy_caption = policy['caption'] 67 else: 68 policy_caption = policy_name 69 if 'desc' in policy: 70 policy_description = policy['desc'] 71 else: 72 policy_description = policy_name 73 if 'label' in policy: 74 policy_label = policy['label'] 75 else: 76 policy_label = policy_name 77 78 self._AddString(self._string_table_elem, policy_name, policy_caption) 79 self._AddString(self._string_table_elem, policy_name + '_Explain', 80 policy_description) 81 presentation_elem = self.AddElement( 82 self._presentation_table_elem, 'presentation', {'id': policy_name}) 83 84 if policy_type == 'main': 85 pass 86 elif policy_type in ('string', 'dict'): 87 # 'dict' policies are configured as JSON-encoded strings on Windows. 88 textbox_elem = self.AddElement(presentation_elem, 'textBox', 89 {'refId': policy_name}) 90 label_elem = self.AddElement(textbox_elem, 'label') 91 label_elem.appendChild(self._doc.createTextNode(policy_label)) 92 elif policy_type == 'int': 93 textbox_elem = self.AddElement(presentation_elem, 'decimalTextBox', 94 {'refId': policy_name}) 95 textbox_elem.appendChild(self._doc.createTextNode(policy_label + ':')) 96 elif policy_type in ('int-enum', 'string-enum'): 97 for item in policy['items']: 98 self._AddString(self._string_table_elem, item['name'], item['caption']) 99 dropdownlist_elem = self.AddElement(presentation_elem, 'dropdownList', 100 {'refId': policy_name}) 101 dropdownlist_elem.appendChild(self._doc.createTextNode(policy_label)) 102 elif policy_type in ('list', 'string-enum-list'): 103 self._AddString(self._string_table_elem, 104 policy_name + 'Desc', 105 policy_caption) 106 listbox_elem = self.AddElement(presentation_elem, 'listBox', 107 {'refId': policy_name + 'Desc'}) 108 listbox_elem.appendChild(self._doc.createTextNode(policy_label)) 109 elif policy_type == 'group': 110 pass 111 elif policy_type == 'external': 112 # This type can only be set through cloud policy. 113 pass 114 else: 115 raise Exception('Unknown policy type %s.' % policy_type) 116 117 def BeginPolicyGroup(self, group): 118 '''Generates ADML elements for a Policy-Group. For each Policy-Group two 119 ADML "string" elements are added to the string-table. One contains the 120 caption of the Policy-Group and the other a description. A Policy-Group also 121 requires an ADML "presentation" element that must be added to the 122 presentation-table. The "presentation" element is the container for the 123 elements that define the visual presentation of the Policy-Goup's Policies. 124 The following ADML snippet shows an example: 125 126 Args: 127 group: The Policy-Group to generate ADML elements for. 128 ''' 129 # Add ADML "string" elements to the string-table that are required by a 130 # Policy-Group. 131 self._AddString(self._string_table_elem, group['name'] + '_group', 132 group['caption']) 133 134 def _AddBaseStrings(self, string_table_elem, build): 135 ''' Adds ADML "string" elements to the string-table that are referenced by 136 the ADMX file but not related to any specific Policy-Group or Policy. 137 ''' 138 self._AddString(string_table_elem, self.config['win_supported_os'], 139 self.messages['win_supported_winxpsp2']['text']) 140 recommended_name = '%s - %s' % \ 141 (self.config['app_name'], self.messages['doc_recommended']['text']) 142 if build == 'chrome': 143 self._AddString(string_table_elem, 144 self.config['win_mandatory_category_path'][0], 145 'Google') 146 self._AddString(string_table_elem, 147 self.config['win_mandatory_category_path'][1], 148 self.config['app_name']) 149 self._AddString(string_table_elem, 150 self.config['win_recommended_category_path'][1], 151 recommended_name) 152 elif build == 'chromium': 153 self._AddString(string_table_elem, 154 self.config['win_mandatory_category_path'][0], 155 self.config['app_name']) 156 self._AddString(string_table_elem, 157 self.config['win_recommended_category_path'][0], 158 recommended_name) 159 160 def BeginTemplate(self): 161 dom_impl = minidom.getDOMImplementation('') 162 self._doc = dom_impl.createDocument(None, 'policyDefinitionResources', 163 None) 164 policy_definitions_resources_elem = self._doc.documentElement 165 policy_definitions_resources_elem.attributes['revision'] = '1.0' 166 policy_definitions_resources_elem.attributes['schemaVersion'] = '1.0' 167 168 self.AddElement(policy_definitions_resources_elem, 'displayName') 169 self.AddElement(policy_definitions_resources_elem, 'description') 170 resources_elem = self.AddElement(policy_definitions_resources_elem, 171 'resources') 172 self._string_table_elem = self.AddElement(resources_elem, 'stringTable') 173 self._AddBaseStrings(self._string_table_elem, self.config['build']) 174 self._presentation_table_elem = self.AddElement(resources_elem, 175 'presentationTable') 176 177 def GetTemplateText(self): 178 # Using "toprettyxml()" confuses the Windows Group Policy Editor 179 # (gpedit.msc) because it interprets whitespace characters in text between 180 # the "string" tags. This prevents gpedit.msc from displaying the category 181 # names correctly. 182 # TODO(markusheintz): Find a better formatting that works with gpedit. 183 return self._doc.toxml() 184