| 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();
 | 
| 
 |