Chromium Code Reviews| 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 |