Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(430)

Side by Side Diff: chrome/tools/build/generate_policy_source.py

Issue 6409040: New policy protobuf protocol. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Ready for review! Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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();
OLDNEW
« chrome/browser/policy/proto/device_management_local.proto ('K') | « chrome/common/chrome_switches.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698