Index: chrome/tools/build/generate_policy_source.py |
diff --git a/chrome/tools/build/generate_policy_source.py b/chrome/tools/build/generate_policy_source.py |
index 1051092ece054d10ab6d4524bdecdef07fd38091..6b2ee462b4a52be39e764d0a038c7cf856259728 100644 |
--- a/chrome/tools/build/generate_policy_source.py |
+++ b/chrome/tools/build/generate_policy_source.py |
@@ -29,6 +29,12 @@ def main(): |
parser.add_option("--pth", "--policy-type-header", dest="type_path", |
help="generate header file for policy type enumeration", |
metavar="FILE"); |
+ parser.add_option("--ppb", "--policy-protobuf", dest="proto_path", |
+ help="generate cloud policy protobuf file", |
+ metavar="FILE"); |
+ parser.add_option("--ppd", "--protobuf-decoder", dest="decoder_path", |
+ help="generate C++ code decoding the policy protobuf", |
+ metavar="FILE"); |
(opts, args) = parser.parse_args(); |
@@ -38,27 +44,45 @@ def main(): |
sys.exit(2) |
template_file_contents = _LoadJSONFile(args[1]); |
if opts.header_path is not None: |
- _WritePolicyConstantHeader(template_file_contents, |
- args, |
- opts); |
+ _WritePolicyConstantHeader(template_file_contents, args, opts); |
if opts.source_path is not None: |
- _WritePolicyConstantSource(template_file_contents, |
- args, |
- opts); |
+ _WritePolicyConstantSource(template_file_contents, args, opts); |
if opts.type_path is not None: |
- _WritePolicyTypeEnumerationHeader(template_file_contents, |
- args, |
- opts); |
+ _WritePolicyTypeEnumerationHeader(template_file_contents, args, opts); |
+ if opts.proto_path is not None: |
+ _WriteProtobuf(template_file_contents, args, opts.proto_path) |
+ if opts.decoder_path is not None: |
+ _WriteProtobufParser(template_file_contents, args, opts.decoder_path) |
+#------------------ shared helpers ---------------------------------# |
def _OutputGeneratedWarningForC(f, template_file_path): |
f.write('//\n' |
'// DO NOT MODIFY THIS FILE DIRECTLY!\n' |
'// IT IS GENERATED BY generate_policy_source.py\n' |
- '// FROM ' + template_file_path + ' \n' |
+ '// FROM ' + template_file_path + '\n' |
'//\n\n') |
+def _GetPolicyNameList(template_file_contents): |
+ policy_names = []; |
+ for policy in template_file_contents['policy_definitions']: |
+ if policy['type'] == 'group': |
+ for sub_policy in policy['policies']: |
+ policy_names.append(sub_policy['name']) |
+ else: |
+ policy_names.append(policy['name']) |
+ policy_names.sort() |
+ return policy_names |
+ |
+ |
+def _LoadJSONFile(json_file): |
+ with open(json_file, "r") as f: |
+ text = f.read() |
+ return eval(text) |
+ |
+ |
+#------------------ policy constants header ------------------------# |
def _WritePolicyConstantHeader(template_file_contents, args, opts): |
platform = args[0]; |
with open(opts.header_path, "w") as f: |
@@ -80,6 +104,7 @@ def _WritePolicyConstantHeader(template_file_contents, args, opts): |
'#endif // CHROME_COMMON_POLICY_CONSTANTS_H_\n') |
+#------------------ policy constants source ------------------------# |
def _WritePolicyConstantSource(template_file_contents, args, opts): |
platform = args[0]; |
with open(opts.source_path, "w") as f: |
@@ -103,6 +128,7 @@ def _WritePolicyConstantSource(template_file_contents, args, opts): |
'} // namespace policy\n') |
+#------------------ policy type enumeration header -----------------# |
def _WritePolicyTypeEnumerationHeader(template_file_contents, args, opts): |
with open(opts.type_path, "w") as f: |
_OutputGeneratedWarningForC(f, args[1]) |
@@ -120,23 +146,183 @@ def _WritePolicyTypeEnumerationHeader(template_file_contents, args, opts): |
'#endif // CHROME_BROWSER_POLICY_CONFIGURATION_POLICY_TYPE_H_\n') |
-def _GetPolicyNameList(template_file_contents): |
- policy_names = []; |
- for policy in template_file_contents['policy_definitions']: |
- if policy['type'] == 'group': |
- for sub_policy in policy['policies']: |
- policy_names.append(sub_policy['name']) |
- else: |
- policy_names.append(policy['name']) |
- policy_names.sort() |
- return policy_names |
+#------------------ policy protobuf --------------------------------# |
+PROTO_HEAD = ''' |
+syntax = "proto2"; |
+option optimize_for = LITE_RUNTIME; |
-def _LoadJSONFile(json_file): |
- with open(json_file, "r") as f: |
- text = f.read() |
- return eval(text) |
+package enterprise_management; |
+ |
+message StringList { |
+ repeated string entries = 1; |
+} |
+ |
+message PolicyOptions { |
+ enum PolicyMode { |
+ // The given settings are applied regardless of user choice. |
+ MANDATORY = 0; |
+ // The user may choose to override the given settings. |
+ RECOMMENDED = 1; |
+ } |
+ optional PolicyMode mode = 1 [default = MANDATORY]; |
+} |
+ |
+''' |
+ |
+ |
+PROTOBUF_TYPE = { |
+ 'main': 'bool', |
+ 'string': 'string', |
+ 'string-enum': 'string', |
+ 'int': 'int64', |
+ 'int-enum': 'int64', |
+ 'list': 'StringList', |
+} |
+ |
+ |
+# Field IDs [1..RESERVED_IDS] will not be used in the wrapping protobuf. |
+RESERVED_IDS = 2 |
+ |
+ |
+def _WritePolicyProto(file, policy, fields): |
+ file.write('message %sProto {\n' % policy['name']) |
+ file.write(' optional PolicyOptions policy_options = 1;\n') |
+ file.write(' optional %s %s = 2;\n' % |
+ (PROTOBUF_TYPE[policy['type']], policy['name'])) |
+ file.write('}\n\n') |
+ fields += [' optional %sProto %s = %s;\n' % |
+ (policy['name'], policy['name'], policy['id'] + RESERVED_IDS)] |
+ |
+ |
+def _WriteProtobuf(template_file_contents, args, outfilepath): |
+ with open(outfilepath, 'w') as f: |
+ _OutputGeneratedWarningForC(f, args[1]) |
+ f.write(PROTO_HEAD) |
+ |
+ fields = [] |
+ f.write('// PBs for individual settings.\n\n') |
+ for policy in template_file_contents['policy_definitions']: |
+ if policy['type'] == 'group': |
+ for sub_policy in policy['policies']: |
+ _WritePolicyProto(f, sub_policy, fields) |
+ else: |
+ _WritePolicyProto(f, policy, fields) |
+ |
+ f.write('// --------------------------------------------------\n' |
+ '// Big wrapper PB containing the above groups.\n\n' |
+ 'message CloudPolicySettings {\n') |
+ f.write(''.join(fields)) |
+ f.write('}\n\n') |
+ |
+ |
+#------------------ protobuf decoder -------------------------------# |
+CPP_HEAD = ''' |
+#include <limits> |
+#include <map> |
+#include <string> |
+ |
+#include "base/logging.h" |
+#include "base/values.h" |
+#include "chrome/browser/policy/configuration_policy_provider.h" |
+#include "chrome/browser/policy/proto/device_management_backend.pb.h" |
+#include "policy/configuration_policy_type.h" |
+ |
+using google::protobuf::RepeatedPtrField; |
+ |
+namespace policy { |
+ |
+namespace em = enterprise_management; |
+ |
+Value* DecodeIntegerValue(google::protobuf::int64 value) { |
+ if (value < std::numeric_limits<int>::min() || |
+ value > std::numeric_limits<int>::max()) { |
+ LOG(WARNING) << "Integer value " << value |
+ << " out of numeric limits, ignoring."; |
+ return NULL; |
+ } |
+ |
+ return Value::CreateIntegerValue(static_cast<int>(value)); |
+} |
+ |
+ListValue* DecodeStringList(const em::StringList& string_list) { |
+ ListValue* list_value = new ListValue; |
+ RepeatedPtrField<std::string>::const_iterator entry; |
+ for (entry = string_list.entries().begin(); |
+ entry != string_list.entries().end(); ++entry) { |
+ list_value->Append(Value::CreateStringValue(*entry)); |
+ } |
+ return list_value; |
+} |
+ |
+void DecodePolicy(const em::CloudPolicySettings& policy, |
+ ConfigurationPolicyProvider::PolicyMapType* mandatory, |
+ ConfigurationPolicyProvider::PolicyMapType* recommended) { |
+ DCHECK(mandatory); |
+ DCHECK(recommended); |
+''' |
+ |
+ |
+CPP_FOOT = '''} |
+ |
+} // namespace policy |
+''' |
+ |
+ |
+def _CreateValue(type): |
+ if type == 'main': |
+ return "Value::CreateBooleanValue" |
+ elif type in ('int', 'int-enum'): |
+ return "DecodeIntegerValue" |
+ elif type in ('string', 'string-enum'): |
+ return "Value::CreateStringValue" |
+ elif type == 'list': |
+ return "DecodeStringList" |
+ else: |
+ raise NotImplementedError() |
+ |
+ |
+def _WritePolicyCode(file, policy): |
+ membername = policy['name'].lower() |
+ proto_type = "%sProto" % policy['name'] |
+ proto_name = "%s_proto" % membername |
+ file.write(' if (policy.has_%s()) {\n' % membername) |
+ file.write(' const em::%s& %s = policy.%s();\n' % |
+ (proto_type, proto_name, membername)) |
+ file.write(' if (%s.has_%s()) {\n' % (proto_name, membername)) |
+ file.write(' Value* value = %s(%s.%s());\n' % |
+ (_CreateValue(policy['type']), proto_name, membername)) |
+ file.write(' ConfigurationPolicyProvider::PolicyMapType* destination =' |
+ ' mandatory;\n' |
+ ' if (%s.has_policy_options()) {\n' |
+ ' switch(%s.policy_options().mode()) {\n' % |
+ (proto_name, proto_name)) |
+ file.write(' case em::PolicyOptions::RECOMMENDED:\n' |
+ ' destination = recommended;\n' |
+ ' break;\n' |
+ ' case em::PolicyOptions::MANDATORY:\n' |
+ ' break;\n' |
+ ' }\n' |
+ ' }\n' |
+ ' destination->insert(std::make_pair(kPolicy%s, value));\n' % |
+ policy['name']) |
+ file.write(' }\n' |
+ ' }\n') |
+ |
+ |
+def _WriteProtobufParser(template_file_contents, args, outfilepath): |
+ with open(outfilepath, 'w') as f: |
+ _OutputGeneratedWarningForC(f, args[1]) |
+ f.write(CPP_HEAD) |
+ for policy in template_file_contents['policy_definitions']: |
+ if policy['type'] == 'group': |
+ for sub_policy in policy['policies']: |
+ _WritePolicyCode(f, sub_policy) |
+ else: |
+ _WritePolicyCode(f, policy) |
+ f.write(CPP_FOOT) |
+#------------------ main() -----------------------------------------# |
if __name__ == '__main__': |
main(); |