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 | |
7 from grit.format.policy_templates.writers import template_writer | |
8 | |
9 | |
10 NEWLINE = '\r\n' | |
11 | |
12 | |
13 def GetWriter(config): | |
14 '''Factory method for creating AdmWriter objects. | |
15 See the constructor of TemplateWriter for description of | |
16 arguments. | |
17 ''' | |
18 return AdmWriter(['win'], config) | |
19 | |
20 | |
21 class IndentedStringBuilder: | |
22 '''Utility class for building text with indented lines.''' | |
23 | |
24 def __init__(self): | |
25 self.lines = [] | |
26 self.indent = '' | |
27 | |
28 def AddLine(self, string='', indent_diff=0): | |
29 '''Appends a string with indentation and a linebreak to |self.lines|. | |
30 | |
31 Args: | |
32 string: The string to print. | |
33 indent_diff: the difference of indentation of the printed line, | |
34 compared to the next/previous printed line. Increment occurs | |
35 after printing the line, while decrement occurs before that. | |
36 ''' | |
37 indent_diff *= 2 | |
38 if indent_diff < 0: | |
39 self.indent = self.indent[(-indent_diff):] | |
40 if string != '': | |
41 self.lines.append(self.indent + string) | |
42 else: | |
43 self.lines.append('') | |
44 if indent_diff > 0: | |
45 self.indent += ''.ljust(indent_diff) | |
46 | |
47 def AddLines(self, other): | |
48 '''Appends the content of another |IndentedStringBuilder| to |self.lines|. | |
49 Indentation of the added lines will be the sum of |self.indent| and | |
50 their original indentation. | |
51 | |
52 Args: | |
53 other: The buffer from which lines are copied. | |
54 ''' | |
55 for line in other.lines: | |
56 self.AddLine(line) | |
57 | |
58 def ToString(self): | |
59 '''Returns |self.lines| as text string.''' | |
60 return NEWLINE.join(self.lines) | |
61 | |
62 | |
63 class AdmWriter(template_writer.TemplateWriter): | |
64 '''Class for generating policy templates in Windows ADM format. | |
65 It is used by PolicyTemplateGenerator to write ADM files. | |
66 ''' | |
67 | |
68 TYPE_TO_INPUT = { | |
69 'string': 'EDITTEXT', | |
70 'int': 'NUMERIC', | |
71 'string-enum': 'DROPDOWNLIST', | |
72 'int-enum': 'DROPDOWNLIST', | |
73 'list': 'LISTBOX', | |
74 'string-enum-list': 'LISTBOX', | |
75 'dict': 'EDITTEXT' | |
76 } | |
77 | |
78 def _Escape(self, string): | |
79 return string.replace('.', '_') | |
80 | |
81 def _AddGuiString(self, name, value): | |
82 # The |name| must be escaped. | |
83 assert name == self._Escape(name) | |
84 # Escape newlines in the value. | |
85 value = value.replace('\n', '\\n') | |
86 if name in self.strings_seen: | |
87 err = ('%s was added as "%s" and now added again as "%s"' % | |
88 (name, self.strings_seen[name], value)) | |
89 assert value == self.strings_seen[name], err | |
90 else: | |
91 self.strings_seen[name] = value | |
92 line = '%s="%s"' % (name, value) | |
93 self.strings.AddLine(line) | |
94 | |
95 def _WriteSupported(self, builder): | |
96 builder.AddLine('#if version >= 4', 1) | |
97 builder.AddLine('SUPPORTED !!SUPPORTED_WINXPSP2') | |
98 builder.AddLine('#endif', -1) | |
99 | |
100 def _WritePart(self, policy, key_name, builder): | |
101 '''Writes the PART ... END PART section of a policy. | |
102 | |
103 Args: | |
104 policy: The policy to write to the output. | |
105 key_name: The registry key backing the policy. | |
106 builder: Builder to append lines to. | |
107 ''' | |
108 policy_part_name = self._Escape(policy['name'] + '_Part') | |
109 self._AddGuiString(policy_part_name, policy['label']) | |
110 | |
111 # Print the PART ... END PART section: | |
112 builder.AddLine() | |
113 adm_type = self.TYPE_TO_INPUT[policy['type']] | |
114 builder.AddLine('PART !!%s %s' % (policy_part_name, adm_type), 1) | |
115 if policy['type'] in ('list', 'string-enum-list'): | |
116 # Note that the following line causes FullArmor ADMX Migrator to create | |
117 # corrupt ADMX files. Please use admx_writer to get ADMX files. | |
118 builder.AddLine('KEYNAME "%s\\%s"' % (key_name, policy['name'])) | |
119 builder.AddLine('VALUEPREFIX ""') | |
120 else: | |
121 builder.AddLine('VALUENAME "%s"' % policy['name']) | |
122 if policy['type'] == 'int': | |
123 # The default max for NUMERIC values is 9999 which is too small for us. | |
124 builder.AddLine('MIN 0 MAX 2000000000') | |
125 if policy['type'] in ('string', 'dict'): | |
126 # The default max for EDITTEXT values is 1023, which is too small for | |
127 # big JSON blobs and other string policies. | |
128 builder.AddLine('MAXLEN 1000000') | |
129 if policy['type'] in ('int-enum', 'string-enum'): | |
130 builder.AddLine('ITEMLIST', 1) | |
131 for item in policy['items']: | |
132 if policy['type'] == 'int-enum': | |
133 value_text = 'NUMERIC ' + str(item['value']) | |
134 else: | |
135 value_text = '"' + item['value'] + '"' | |
136 string_id = self._Escape(item['name'] + '_DropDown') | |
137 builder.AddLine('NAME !!%s VALUE %s' % (string_id, value_text)) | |
138 self._AddGuiString(string_id, item['caption']) | |
139 builder.AddLine('END ITEMLIST', -1) | |
140 builder.AddLine('END PART', -1) | |
141 | |
142 def _WritePolicy(self, policy, key_name, builder): | |
143 if policy['type'] == 'external': | |
144 # This type can only be set through cloud policy. | |
145 return | |
146 | |
147 policy_name = self._Escape(policy['name'] + '_Policy') | |
148 self._AddGuiString(policy_name, policy['caption']) | |
149 builder.AddLine('POLICY !!%s' % policy_name, 1) | |
150 self._WriteSupported(builder) | |
151 policy_explain_name = self._Escape(policy['name'] + '_Explain') | |
152 self._AddGuiString(policy_explain_name, policy['desc']) | |
153 builder.AddLine('EXPLAIN !!' + policy_explain_name) | |
154 | |
155 if policy['type'] == 'main': | |
156 builder.AddLine('VALUENAME "%s"' % policy['name']) | |
157 builder.AddLine('VALUEON NUMERIC 1') | |
158 builder.AddLine('VALUEOFF NUMERIC 0') | |
159 else: | |
160 self._WritePart(policy, key_name, builder) | |
161 | |
162 builder.AddLine('END POLICY', -1) | |
163 builder.AddLine() | |
164 | |
165 def WriteComment(self, comment): | |
166 self.lines.AddLine('; ' + comment) | |
167 | |
168 def WritePolicy(self, policy): | |
169 if self.CanBeMandatory(policy): | |
170 self._WritePolicy(policy, | |
171 self.config['win_reg_mandatory_key_name'], | |
172 self.policies) | |
173 | |
174 def WriteRecommendedPolicy(self, policy): | |
175 self._WritePolicy(policy, | |
176 self.config['win_reg_recommended_key_name'], | |
177 self.recommended_policies) | |
178 | |
179 def BeginPolicyGroup(self, group): | |
180 category_name = self._Escape(group['name'] + '_Category') | |
181 self._AddGuiString(category_name, group['caption']) | |
182 self.policies.AddLine('CATEGORY !!' + category_name, 1) | |
183 | |
184 def EndPolicyGroup(self): | |
185 self.policies.AddLine('END CATEGORY', -1) | |
186 self.policies.AddLine('') | |
187 | |
188 def BeginRecommendedPolicyGroup(self, group): | |
189 category_name = self._Escape(group['name'] + '_Category') | |
190 self._AddGuiString(category_name, group['caption']) | |
191 self.recommended_policies.AddLine('CATEGORY !!' + category_name, 1) | |
192 | |
193 def EndRecommendedPolicyGroup(self): | |
194 self.recommended_policies.AddLine('END CATEGORY', -1) | |
195 self.recommended_policies.AddLine('') | |
196 | |
197 def _CreateTemplate(self, category_path, key_name, policies): | |
198 '''Creates the whole ADM template except for the [Strings] section, and | |
199 returns it as an |IndentedStringBuilder|. | |
200 | |
201 Args: | |
202 category_path: List of strings representing the category path. | |
203 key_name: Main registry key backing the policies. | |
204 policies: ADM code for all the policies in an |IndentedStringBuilder|. | |
205 ''' | |
206 lines = IndentedStringBuilder() | |
207 for part in category_path: | |
208 lines.AddLine('CATEGORY !!' + part, 1) | |
209 lines.AddLine('KEYNAME "%s"' % key_name) | |
210 lines.AddLine() | |
211 | |
212 lines.AddLines(policies) | |
213 | |
214 for part in category_path: | |
215 lines.AddLine('END CATEGORY', -1) | |
216 lines.AddLine() | |
217 | |
218 return lines | |
219 | |
220 def BeginTemplate(self): | |
221 if self._GetChromiumVersionString() is not None: | |
222 self.WriteComment(self.config['build'] + ' version: ' + \ | |
223 self._GetChromiumVersionString()) | |
224 self._AddGuiString(self.config['win_supported_os'], | |
225 self.messages['win_supported_winxpsp2']['text']) | |
226 category_path = self.config['win_mandatory_category_path'] | |
227 recommended_category_path = self.config['win_recommended_category_path'] | |
228 recommended_name = '%s - %s' % \ | |
229 (self.config['app_name'], self.messages['doc_recommended']['text']) | |
230 if self.config['build'] == 'chrome': | |
231 self._AddGuiString(category_path[0], 'Google') | |
232 self._AddGuiString(category_path[1], self.config['app_name']) | |
233 self._AddGuiString(recommended_category_path[1], recommended_name) | |
234 elif self.config['build'] == 'chromium': | |
235 self._AddGuiString(category_path[0], self.config['app_name']) | |
236 self._AddGuiString(recommended_category_path[0], recommended_name) | |
237 # All the policies will be written into self.policies. | |
238 # The final template text will be assembled into self.lines by | |
239 # self.EndTemplate(). | |
240 | |
241 def EndTemplate(self): | |
242 # Copy policies into self.lines. | |
243 policy_class = self.config['win_group_policy_class'].upper() | |
244 for class_name in ['MACHINE', 'USER']: | |
245 if policy_class != 'BOTH' and policy_class != class_name: | |
246 continue | |
247 self.lines.AddLine('CLASS ' + class_name, 1) | |
248 self.lines.AddLines(self._CreateTemplate( | |
249 self.config['win_mandatory_category_path'], | |
250 self.config['win_reg_mandatory_key_name'], | |
251 self.policies)) | |
252 self.lines.AddLines(self._CreateTemplate( | |
253 self.config['win_recommended_category_path'], | |
254 self.config['win_reg_recommended_key_name'], | |
255 self.recommended_policies)) | |
256 self.lines.AddLine('', -1) | |
257 # Copy user strings into self.lines. | |
258 self.lines.AddLine('[Strings]') | |
259 self.lines.AddLines(self.strings) | |
260 | |
261 def Init(self): | |
262 # String buffer for building the whole ADM file. | |
263 self.lines = IndentedStringBuilder() | |
264 # String buffer for building the strings section of the ADM file. | |
265 self.strings = IndentedStringBuilder() | |
266 # Map of strings seen, to avoid duplicates. | |
267 self.strings_seen = {} | |
268 # String buffer for building the policies of the ADM file. | |
269 self.policies = IndentedStringBuilder() | |
270 # String buffer for building the recommended policies of the ADM file. | |
271 self.recommended_policies = IndentedStringBuilder() | |
272 | |
273 def GetTemplateText(self): | |
274 return self.lines.ToString() | |
OLD | NEW |