OLD | NEW |
---|---|
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 '''python %prog [options] platform template | 6 '''python %prog [options] platform template |
7 | 7 |
8 platform specifies which platform source is being generated for | 8 platform specifies which platform source is being generated for |
9 and can be one of (win, mac, linux). | 9 and can be one of (win, mac, linux). |
10 template is the path to a .json policy template file.''' | 10 template is the path to a .json policy template file.''' |
(...skipping 11 matching lines...) Expand all Loading... | |
22 parser = OptionParser(usage=__doc__); | 22 parser = OptionParser(usage=__doc__); |
23 parser.add_option("--pch", "--policy-constants-header", dest="header_path", | 23 parser.add_option("--pch", "--policy-constants-header", dest="header_path", |
24 help="generate header file of policy constants", | 24 help="generate header file of policy constants", |
25 metavar="FILE"); | 25 metavar="FILE"); |
26 parser.add_option("--pcc", "--policy-constants-source", dest="source_path", | 26 parser.add_option("--pcc", "--policy-constants-source", dest="source_path", |
27 help="generate source file of policy constants", | 27 help="generate source file of policy constants", |
28 metavar="FILE"); | 28 metavar="FILE"); |
29 parser.add_option("--pth", "--policy-type-header", dest="type_path", | 29 parser.add_option("--pth", "--policy-type-header", dest="type_path", |
30 help="generate header file for policy type enumeration", | 30 help="generate header file for policy type enumeration", |
31 metavar="FILE"); | 31 metavar="FILE"); |
32 parser.add_option("--ppb", "--policy-protobuf", dest="proto_path", | |
33 help="generate cloud policy protobuf file", | |
34 metavar="FILE"); | |
35 parser.add_option("--ppd", "--protobuf-decoder", dest="decoder_path", | |
36 help="generate CPP code decoding the policy protobuf", | |
Mattias Nissler (ping if slow)
2011/02/02 12:27:55
In my experience CPP most of the time refers to th
Jakob Kummerow
2011/02/03 14:36:52
Done.
| |
37 metavar="FILE"); | |
32 | 38 |
33 (opts, args) = parser.parse_args(); | 39 (opts, args) = parser.parse_args(); |
34 | 40 |
35 if len(args) < 2 or len(args) > 2: | 41 if len(args) < 2 or len(args) > 2: |
36 print "exactly one platform and input file must be specified." | 42 print "exactly one platform and input file must be specified." |
37 parser.print_help() | 43 parser.print_help() |
38 sys.exit(2) | 44 sys.exit(2) |
39 template_file_contents = _LoadJSONFile(args[1]); | 45 template_file_contents = _LoadJSONFile(args[1]); |
40 if opts.header_path is not None: | 46 if opts.header_path is not None: |
41 _WritePolicyConstantHeader(template_file_contents, | 47 _WritePolicyConstantHeader(template_file_contents, args, opts); |
42 args, | |
43 opts); | |
44 if opts.source_path is not None: | 48 if opts.source_path is not None: |
45 _WritePolicyConstantSource(template_file_contents, | 49 _WritePolicyConstantSource(template_file_contents, args, opts); |
46 args, | |
47 opts); | |
48 if opts.type_path is not None: | 50 if opts.type_path is not None: |
49 _WritePolicyTypeEnumerationHeader(template_file_contents, | 51 _WritePolicyTypeEnumerationHeader(template_file_contents, args, opts); |
50 args, | 52 if opts.proto_path is not None: |
51 opts); | 53 _WriteProtobuf(template_file_contents, args, opts.proto_path) |
54 if opts.decoder_path is not None: | |
55 _WriteProtobufParser(template_file_contents, args, opts.decoder_path) | |
52 | 56 |
53 | 57 |
58 #------------------ shared helpers ---------------------------------# | |
Mattias Nissler (ping if slow)
2011/02/02 12:27:55
Is that commonly used comment style in chromium py
Jakob Kummerow
2011/02/03 14:36:52
No, I guess it's not. I just felt that this file w
| |
54 def _OutputGeneratedWarningForC(f, template_file_path): | 59 def _OutputGeneratedWarningForC(f, template_file_path): |
55 f.write('//\n' | 60 f.write('//\n' |
56 '// DO NOT MODIFY THIS FILE DIRECTLY!\n' | 61 '// DO NOT MODIFY THIS FILE DIRECTLY!\n' |
57 '// IT IS GENERATED BY generate_policy_source.py\n' | 62 '// IT IS GENERATED BY generate_policy_source.py\n' |
58 '// FROM ' + template_file_path + ' \n' | 63 '// FROM ' + template_file_path + '\n' |
59 '//\n\n') | 64 '//\n\n') |
60 | 65 |
61 | 66 |
67 def _GetPolicyNameList(template_file_contents): | |
68 policy_names = []; | |
69 for policy in template_file_contents['policy_definitions']: | |
70 if policy['type'] == 'group': | |
71 for sub_policy in policy['policies']: | |
72 policy_names.append(sub_policy['name']) | |
73 else: | |
74 policy_names.append(policy['name']) | |
75 policy_names.sort() | |
76 return policy_names | |
77 | |
78 | |
79 def _LoadJSONFile(json_file): | |
80 with open(json_file, "r") as f: | |
81 text = f.read() | |
82 return eval(text) | |
83 | |
84 | |
85 #------------------ policy constants header ------------------------# | |
62 def _WritePolicyConstantHeader(template_file_contents, args, opts): | 86 def _WritePolicyConstantHeader(template_file_contents, args, opts): |
63 platform = args[0]; | 87 platform = args[0]; |
64 with open(opts.header_path, "w") as f: | 88 with open(opts.header_path, "w") as f: |
65 _OutputGeneratedWarningForC(f, args[1]) | 89 _OutputGeneratedWarningForC(f, args[1]) |
66 f.write('#ifndef CHROME_COMMON_POLICY_CONSTANTS_H_\n' | 90 f.write('#ifndef CHROME_COMMON_POLICY_CONSTANTS_H_\n' |
67 '#define CHROME_COMMON_POLICY_CONSTANTS_H_\n' | 91 '#define CHROME_COMMON_POLICY_CONSTANTS_H_\n' |
68 '#pragma once\n' | 92 '#pragma once\n' |
69 '\n' | 93 '\n' |
70 'namespace policy {\n\n') | 94 'namespace policy {\n\n') |
71 if platform == "win": | 95 if platform == "win": |
72 f.write('// The windows registry path where policy configuration ' | 96 f.write('// The windows registry path where policy configuration ' |
73 'resides.\nextern const wchar_t kRegistrySubKey[];\n\n') | 97 'resides.\nextern const wchar_t kRegistrySubKey[];\n\n') |
74 f.write('// Key names for the policy settings.\n' | 98 f.write('// Key names for the policy settings.\n' |
75 'namespace key {\n\n') | 99 'namespace key {\n\n') |
76 for policy_name in _GetPolicyNameList(template_file_contents): | 100 for policy_name in _GetPolicyNameList(template_file_contents): |
77 f.write('extern const char k' + policy_name + '[];\n') | 101 f.write('extern const char k' + policy_name + '[];\n') |
78 f.write('\n} // namespace key\n\n' | 102 f.write('\n} // namespace key\n\n' |
79 '} // namespace policy\n\n' | 103 '} // namespace policy\n\n' |
80 '#endif // CHROME_COMMON_POLICY_CONSTANTS_H_\n') | 104 '#endif // CHROME_COMMON_POLICY_CONSTANTS_H_\n') |
81 | 105 |
82 | 106 |
107 #------------------ policy constants source ------------------------# | |
83 def _WritePolicyConstantSource(template_file_contents, args, opts): | 108 def _WritePolicyConstantSource(template_file_contents, args, opts): |
84 platform = args[0]; | 109 platform = args[0]; |
85 with open(opts.source_path, "w") as f: | 110 with open(opts.source_path, "w") as f: |
86 _OutputGeneratedWarningForC(f, args[1]) | 111 _OutputGeneratedWarningForC(f, args[1]) |
87 f.write('#include "policy/policy_constants.h"\n' | 112 f.write('#include "policy/policy_constants.h"\n' |
88 '\n' | 113 '\n' |
89 'namespace policy {\n' | 114 'namespace policy {\n' |
90 '\n') | 115 '\n') |
91 if platform == "win": | 116 if platform == "win": |
92 f.write('#if defined(GOOGLE_CHROME_BUILD)\n' | 117 f.write('#if defined(GOOGLE_CHROME_BUILD)\n' |
93 'const wchar_t kRegistrySubKey[] = ' | 118 'const wchar_t kRegistrySubKey[] = ' |
94 'L"' + CHROME_SUBKEY + '";\n' | 119 'L"' + CHROME_SUBKEY + '";\n' |
95 '#else\n' | 120 '#else\n' |
96 'const wchar_t kRegistrySubKey[] = ' | 121 'const wchar_t kRegistrySubKey[] = ' |
97 'L"' + CHROMIUM_SUBKEY + '";\n' | 122 'L"' + CHROMIUM_SUBKEY + '";\n' |
98 '#endif\n\n') | 123 '#endif\n\n') |
99 f.write('namespace key {\n\n') | 124 f.write('namespace key {\n\n') |
100 for policy_name in _GetPolicyNameList(template_file_contents): | 125 for policy_name in _GetPolicyNameList(template_file_contents): |
101 f.write('const char k%s[] = "%s";\n' % (policy_name, policy_name)) | 126 f.write('const char k%s[] = "%s";\n' % (policy_name, policy_name)) |
102 f.write('\n} // namespace key\n\n' | 127 f.write('\n} // namespace key\n\n' |
103 '} // namespace policy\n') | 128 '} // namespace policy\n') |
104 | 129 |
105 | 130 |
131 #------------------ policy type enumeration header -----------------# | |
106 def _WritePolicyTypeEnumerationHeader(template_file_contents, args, opts): | 132 def _WritePolicyTypeEnumerationHeader(template_file_contents, args, opts): |
107 with open(opts.type_path, "w") as f: | 133 with open(opts.type_path, "w") as f: |
108 _OutputGeneratedWarningForC(f, args[1]) | 134 _OutputGeneratedWarningForC(f, args[1]) |
109 f.write('#ifndef CHROME_BROWSER_POLICY_CONFIGURATION_POLICY_TYPE_H_\n' | 135 f.write('#ifndef CHROME_BROWSER_POLICY_CONFIGURATION_POLICY_TYPE_H_\n' |
110 '#define CHROME_BROWSER_POLICY_CONFIGURATION_POLICY_TYPE_H_\n' | 136 '#define CHROME_BROWSER_POLICY_CONFIGURATION_POLICY_TYPE_H_\n' |
111 '#pragma once\n' | 137 '#pragma once\n' |
112 '\n' | 138 '\n' |
113 'namespace policy {\n' | 139 'namespace policy {\n' |
114 '\n' | 140 '\n' |
115 'enum ConfigurationPolicyType {\n') | 141 'enum ConfigurationPolicyType {\n') |
116 for policy_name in _GetPolicyNameList(template_file_contents): | 142 for policy_name in _GetPolicyNameList(template_file_contents): |
117 f.write(' kPolicy' + policy_name + ",\n"); | 143 f.write(' kPolicy' + policy_name + ",\n"); |
118 f.write('};\n\n' | 144 f.write('};\n\n' |
119 '} // namespace policy\n\n' | 145 '} // namespace policy\n\n' |
120 '#endif // CHROME_BROWSER_POLICY_CONFIGURATION_POLICY_TYPE_H_\n') | 146 '#endif // CHROME_BROWSER_POLICY_CONFIGURATION_POLICY_TYPE_H_\n') |
121 | 147 |
122 | 148 |
123 def _GetPolicyNameList(template_file_contents): | 149 #------------------ policy protobuf --------------------------------# |
124 policy_names = []; | 150 PROTO_HEAD = ''' |
125 for policy in template_file_contents['policy_definitions']: | 151 syntax = "proto2"; |
126 if policy['type'] == 'group': | 152 |
127 for sub_policy in policy['policies']: | 153 option optimize_for = LITE_RUNTIME; |
128 policy_names.append(sub_policy['name']) | 154 |
129 else: | 155 package enterprise_management; |
130 policy_names.append(policy['name']) | 156 |
131 policy_names.sort() | 157 // Only included in serialized form in the PBs below. |
gfeher
2011/02/02 08:42:45
Please update comment.
Mattias Nissler (ping if slow)
2011/02/02 12:27:55
and can't we just switch to repeated string instea
Jakob Kummerow
2011/02/03 14:36:52
Done.
Jakob Kummerow
2011/02/03 14:36:52
As discussed offline: Yes, we could, but we would
| |
132 return policy_names | 158 message StringList { |
159 repeated string entries = 1; | |
160 } | |
161 | |
162 message PolicyOptions { | |
163 enum PolicyMode { | |
164 // The user may choose to override the given settings. | |
165 RECOMMENDED = 1; | |
166 // The given settings are applied regardless of user choice. | |
167 MANDATORY = 2; | |
168 } | |
169 optional PolicyMode mode = 1; | |
170 } | |
171 | |
Mattias Nissler (ping if slow)
2011/02/02 12:27:55
Can we have this in a separate .proto that include
Jakob Kummerow
2011/02/03 14:36:52
As discussed offline: Yes, we could, but since it'
| |
172 ''' | |
133 | 173 |
134 | 174 |
135 def _LoadJSONFile(json_file): | 175 def _PolicyTypeToProtobufType(type): |
136 with open(json_file, "r") as f: | 176 if type == 'main': |
137 text = f.read() | 177 return 'bool' |
138 return eval(text) | 178 elif type in ('string', 'string-enum'): |
179 return 'string' | |
180 elif type in ('int', 'int-enum'): | |
181 return 'int64' | |
182 elif type == 'list': | |
183 return 'StringList' | |
184 else: | |
185 raise NotImplementedError() | |
139 | 186 |
140 | 187 |
188 def _WriteProtobuf(data, args, outfilepath): | |
Mattias Nissler (ping if slow)
2011/02/02 12:27:55
What's data? Can we have a better name?
Jakob Kummerow
2011/02/03 14:36:52
Done.
| |
189 with open(outfilepath, 'w') as f: | |
190 _OutputGeneratedWarningForC(f, args[1]) | |
191 f.write(PROTO_HEAD) | |
192 | |
193 # Write protobufs for individual settings/groups. | |
194 f.write('// PBs for individual settings.\n\n') | |
195 for policy in data['policy_definitions']: | |
196 f.write('message %sProto {\n' % policy['name']) | |
197 f.write(' optional PolicyOptions policy_options = 1;\n') | |
198 if policy['type'] == 'group': | |
199 for sub_policy in policy['policies']: | |
200 f.write(' optional %s %s = %s;\n' % | |
201 (_PolicyTypeToProtobufType(sub_policy['type']), | |
202 sub_policy['name'], (sub_policy['protobuf_id'] + 1))) | |
Mattias Nissler (ping if slow)
2011/02/02 12:27:55
hm, we might want to name the id just ID and not p
Jakob Kummerow
2011/02/03 14:36:52
Done.
| |
203 else: | |
204 f.write(' optional %s %s = 2;\n' % | |
205 (_PolicyTypeToProtobufType(policy['type']), policy['name'])) | |
Mattias Nissler (ping if slow)
2011/02/02 12:27:55
Seems like you could use a _WritePolicy function a
Jakob Kummerow
2011/02/03 14:36:52
Done.
| |
206 f.write('}\n\n') | |
207 # end of: for policy in data['policy_definitions']. | |
208 | |
209 f.write('// --------------------------------------------------\n' | |
210 '// Big wrapper PB containing the above groups.\n\n' | |
211 'message CloudPolicySettings {\n') | |
212 for policy in data['policy_definitions']: | |
213 f.write(' optional %sProto %s = %s;\n' % | |
214 (policy['name'], policy['name'], policy['protobuf_id'])) | |
215 f.write('}\n\n') | |
216 | |
217 | |
218 #------------------ protobuf decoder -------------------------------# | |
219 CPP_HEAD = ''' | |
220 #include <limits> | |
221 #include <map> | |
222 #include <string> | |
223 | |
224 #include "base/logging.h" | |
225 #include "base/values.h" | |
226 #include "chrome/browser/policy/proto/device_management_backend.pb.h" | |
227 #include "policy/configuration_policy_type.h" | |
228 | |
229 using google::protobuf::RepeatedPtrField; | |
230 | |
231 namespace policy { | |
232 | |
233 namespace em = enterprise_management; | |
234 | |
235 typedef std::map<ConfigurationPolicyType, Value*> PolicyMapType; | |
236 | |
237 Value* DecodeIntegerValue(google::protobuf::int64 value) { | |
238 if (value < std::numeric_limits<int>::min() || | |
239 value > std::numeric_limits<int>::max()) { | |
240 LOG(WARNING) << "Integer value " << value | |
241 << " out of numeric limits, ignoring."; | |
242 return NULL; | |
243 } | |
244 | |
245 return Value::CreateIntegerValue(static_cast<int>(value)); | |
246 } | |
247 | |
248 ListValue* DecodeStringList(const em::StringList& string_list) { | |
249 ListValue* list_value = new ListValue; | |
250 RepeatedPtrField<std::string>::const_iterator entry; | |
251 for (entry = string_list.entries().begin(); | |
252 entry != string_list.entries().end(); ++entry) { | |
253 list_value->Append(Value::CreateStringValue(*entry)); | |
254 } | |
255 return list_value; | |
256 } | |
257 | |
258 void DecodePolicy(const em::CloudPolicySettings& policy, | |
259 PolicyMapType* mandatory, PolicyMapType* recommended) { | |
260 DCHECK(mandatory); | |
261 DCHECK(recommended); | |
262 ''' | |
Mattias Nissler (ping if slow)
2011/02/02 12:27:55
I wouldn't worry to much about this boilerplate he
Jakob Kummerow
2011/02/03 14:36:52
Same as above: as discussed offline, we'll leave t
| |
263 | |
264 | |
265 CPP_FOOT = '''} | |
266 | |
267 } // namespace policy | |
268 ''' | |
269 | |
270 | |
271 def _CreateValue(type): | |
272 if type == 'main': | |
273 return "Value::CreateBooleanValue" | |
274 elif type in ('int', 'int-enum'): | |
275 return "DecodeIntegerValue" | |
276 elif type in ('string', 'string-enum'): | |
277 return "Value::CreateStringValue" | |
278 elif type == 'list': | |
279 return "DecodeStringList" | |
280 else: | |
281 raise NotImplementedError() | |
282 | |
283 | |
284 def _GeneratePolicyCode(policy, protoname=None): | |
285 membername = policy['name'].lower() | |
286 if protoname is None: | |
287 protoname = "%s_proto" % policy['name'].lower() | |
Mattias Nissler (ping if slow)
2011/02/02 12:27:55
can use membername instead of the repeated policy[
Jakob Kummerow
2011/02/03 14:36:52
Done.
| |
288 code = ' if (%s.has_%s()) {\n' % (protoname, membername) | |
289 code += (' Value* value = %s(%s.%s());\n' % | |
290 (_CreateValue(policy['type']), protoname, membername)) | |
291 code += (' PolicyMapType* result = mandatory;\n' | |
gfeher
2011/02/02 08:42:45
Nit: rename |result| to |destination|?
Jakob Kummerow
2011/02/03 14:36:52
Done.
| |
292 ' if (%s.has_policy_options() &&\n' | |
293 ' (%s.policy_options().mode() == ' | |
294 'em::PolicyOptions::RECOMMENDED)) {\n' % | |
Mattias Nissler (ping if slow)
2011/02/02 12:27:55
I think I would rather have used a switch(%s.polic
Jakob Kummerow
2011/02/03 14:36:52
Done.
| |
295 (protoname, protoname)) | |
296 code += (' result = recommended;\n' | |
297 ' }\n' | |
298 ' result->insert(std::make_pair(kPolicy%s, value));\n' % | |
299 policy['name']) | |
300 code += ' }\n' | |
301 return code | |
302 | |
303 | |
304 def _WriteProtobufParser(data, args, outfilepath): | |
305 with open(outfilepath, 'w') as f: | |
306 _OutputGeneratedWarningForC(f, args[1]) | |
307 f.write(CPP_HEAD) | |
308 for policy in data['policy_definitions']: | |
309 policyname = policy['name'] | |
310 membername = policyname.lower() | |
311 proto_type = "%sProto" % policyname | |
312 protoname = "%s_proto" % policyname.lower() | |
Mattias Nissler (ping if slow)
2011/02/02 12:27:55
why not use membername?
Jakob Kummerow
2011/02/03 14:36:52
Done.
| |
313 f.write(' if (policy.has_%s()) {\n' % membername) | |
314 f.write(' const em::%s& %s = policy.%s();\n' % | |
315 (proto_type, protoname, membername)) | |
316 if policy['type'] == 'group': | |
317 for sub_policy in policy['policies']: | |
318 f.write(_GeneratePolicyCode(sub_policy, protoname)) | |
Mattias Nissler (ping if slow)
2011/02/02 12:27:55
Why not just pass f to the function instead of bui
Jakob Kummerow
2011/02/03 14:36:52
Done.
| |
319 else: | |
320 f.write(_GeneratePolicyCode(policy)) | |
321 f.write(' }\n') | |
322 f.write(CPP_FOOT) | |
323 | |
324 | |
325 #------------------ main() -----------------------------------------# | |
141 if __name__ == '__main__': | 326 if __name__ == '__main__': |
142 main(); | 327 main(); |
OLD | NEW |