diff options
author | Andras Becsi <andras.becsi@digia.com> | 2014-03-18 13:16:26 +0100 |
---|---|---|
committer | Frederik Gladhorn <frederik.gladhorn@digia.com> | 2014-03-20 15:55:39 +0100 |
commit | 3f0f86b0caed75241fa71c95a5d73bc0164348c5 (patch) | |
tree | 92b9fb00f2e9e90b0be2262093876d4f43b6cd13 /chromium/components/policy/tools/generate_policy_source.py | |
parent | e90d7c4b152c56919d963987e2503f9909a666d2 (diff) | |
download | qtwebengine-chromium-3f0f86b0caed75241fa71c95a5d73bc0164348c5.tar.gz |
Update to new stable branch 1750
This also includes an updated ninja and chromium dependencies
needed on Windows.
Change-Id: Icd597d80ed3fa4425933c9f1334c3c2e31291c42
Reviewed-by: Zoltan Arvai <zarvai@inf.u-szeged.hu>
Reviewed-by: Zeno Albisser <zeno.albisser@digia.com>
Diffstat (limited to 'chromium/components/policy/tools/generate_policy_source.py')
-rwxr-xr-x | chromium/components/policy/tools/generate_policy_source.py | 748 |
1 files changed, 748 insertions, 0 deletions
diff --git a/chromium/components/policy/tools/generate_policy_source.py b/chromium/components/policy/tools/generate_policy_source.py new file mode 100755 index 00000000000..315650de251 --- /dev/null +++ b/chromium/components/policy/tools/generate_policy_source.py @@ -0,0 +1,748 @@ +#!/usr/bin/env python +# Copyright (c) 2012 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +'''python %prog [options] platform chromium_os_flag template + +platform specifies which platform source is being generated for + and can be one of (win, mac, linux) +chromium_os_flag should be 1 if this is a Chromium OS build +template is the path to a .json policy template file.''' + +from __future__ import with_statement +import json +from optparse import OptionParser +import re +import sys +import textwrap + + +CHROME_POLICY_KEY = 'SOFTWARE\\\\Policies\\\\Google\\\\Chrome' +CHROMIUM_POLICY_KEY = 'SOFTWARE\\\\Policies\\\\Chromium' + + +class PolicyDetails: + """Parses a policy template and caches all its details.""" + + # Maps policy types to a tuple with 3 other types: + # - the equivalent base::Value::Type or 'TYPE_EXTERNAL' if the policy + # references external data + # - the equivalent Protobuf field type + # - the name of one of the protobufs for shared policy types + # TODO(joaodasilva): refactor the 'dict' type into a more generic 'json' type + # that can also be used to represent lists of other JSON objects. + TYPE_MAP = { + 'dict': ('TYPE_DICTIONARY', 'string', 'String'), + 'external': ('TYPE_EXTERNAL', 'string', 'String'), + 'int': ('TYPE_INTEGER', 'int64', 'Integer'), + 'int-enum': ('TYPE_INTEGER', 'int64', 'Integer'), + 'list': ('TYPE_LIST', 'StringList', 'StringList'), + 'main': ('TYPE_BOOLEAN', 'bool', 'Boolean'), + 'string': ('TYPE_STRING', 'string', 'String'), + 'string-enum': ('TYPE_STRING', 'string', 'String'), + } + + class EnumItem: + def __init__(self, item): + self.caption = PolicyDetails._RemovePlaceholders(item['caption']) + self.value = item['value'] + + def __init__(self, policy, os, is_chromium_os): + self.id = policy['id'] + self.name = policy['name'] + self.is_deprecated = policy.get('deprecated', False) + self.is_device_only = policy.get('device_only', False) + self.schema = policy.get('schema', {}) + + expected_platform = 'chrome_os' if is_chromium_os else os.lower() + self.platforms = [] + for platform, version in [ p.split(':') for p in policy['supported_on'] ]: + if not version.endswith('-'): + continue + + if platform.startswith('chrome.'): + platform_sub = platform[7:] + if platform_sub == '*': + self.platforms.extend(['win', 'mac', 'linux']) + else: + self.platforms.append(platform_sub) + else: + self.platforms.append(platform) + + self.platforms.sort() + self.is_supported = expected_platform in self.platforms + + if not PolicyDetails.TYPE_MAP.has_key(policy['type']): + raise NotImplementedError('Unknown policy type for %s: %s' % + (policy['name'], policy['type'])) + self.policy_type, self.protobuf_type, self.policy_protobuf_type = \ + PolicyDetails.TYPE_MAP[policy['type']] + self.schema = policy['schema'] + + self.desc = '\n'.join( + map(str.strip, + PolicyDetails._RemovePlaceholders(policy['desc']).splitlines())) + self.caption = PolicyDetails._RemovePlaceholders(policy['caption']) + self.max_size = policy.get('max_size', 0) + + items = policy.get('items') + if items is None: + self.items = None + else: + self.items = [ PolicyDetails.EnumItem(entry) for entry in items ] + + PH_PATTERN = re.compile('<ph[^>]*>([^<]*|[^<]*<ex>([^<]*)</ex>[^<]*)</ph>') + + # Simplistic grit placeholder stripper. + @staticmethod + def _RemovePlaceholders(text): + result = '' + pos = 0 + for m in PolicyDetails.PH_PATTERN.finditer(text): + result += text[pos:m.start(0)] + result += m.group(2) or m.group(1) + pos = m.end(0) + result += text[pos:] + return result + + +def main(): + parser = OptionParser(usage=__doc__) + parser.add_option('--pch', '--policy-constants-header', dest='header_path', + help='generate header file of policy constants', + metavar='FILE') + parser.add_option('--pcc', '--policy-constants-source', dest='source_path', + help='generate source file of policy constants', + metavar='FILE') + parser.add_option('--cpp', '--cloud-policy-protobuf', + dest='cloud_policy_proto_path', + help='generate cloud policy protobuf file', + metavar='FILE') + parser.add_option('--csp', '--chrome-settings-protobuf', + dest='chrome_settings_proto_path', + help='generate chrome settings protobuf file', + metavar='FILE') + parser.add_option('--cpd', '--cloud-policy-decoder', + dest='cloud_policy_decoder_path', + help='generate C++ code decoding the cloud policy protobuf', + metavar='FILE') + + (opts, args) = parser.parse_args() + + if len(args) != 3: + print 'exactly platform, chromium_os flag and input file must be specified.' + parser.print_help() + return 2 + + os = args[0] + is_chromium_os = args[1] == '1' + template_file_name = args[2] + + template_file_contents = _LoadJSONFile(template_file_name) + policy_details = [ PolicyDetails(policy, os, is_chromium_os) + for policy in _Flatten(template_file_contents) ] + sorted_policy_details = sorted(policy_details, key=lambda policy: policy.name) + + def GenerateFile(path, writer, sorted=False): + if path: + with open(path, 'w') as f: + _OutputGeneratedWarningHeader(f, template_file_name) + writer(sorted and sorted_policy_details or policy_details, os, f) + + GenerateFile(opts.header_path, _WritePolicyConstantHeader, sorted=True) + GenerateFile(opts.source_path, _WritePolicyConstantSource, sorted=True) + GenerateFile(opts.cloud_policy_proto_path, _WriteCloudPolicyProtobuf) + GenerateFile(opts.chrome_settings_proto_path, _WriteChromeSettingsProtobuf) + GenerateFile(opts.cloud_policy_decoder_path, _WriteCloudPolicyDecoder) + + return 0 + + +#------------------ shared helpers ---------------------------------# + +def _OutputGeneratedWarningHeader(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' + '//\n\n') + + +COMMENT_WRAPPER = textwrap.TextWrapper() +COMMENT_WRAPPER.width = 80 +COMMENT_WRAPPER.initial_indent = '// ' +COMMENT_WRAPPER.subsequent_indent = '// ' +COMMENT_WRAPPER.replace_whitespace = False + + +# Writes a comment, each line prefixed by // and wrapped to 80 spaces. +def _OutputComment(f, comment): + for line in comment.splitlines(): + if len(line) == 0: + f.write('//') + else: + f.write(COMMENT_WRAPPER.fill(line)) + f.write('\n') + + +# Returns an iterator over all the policies in |template_file_contents|. +def _Flatten(template_file_contents): + for policy in template_file_contents['policy_definitions']: + if policy['type'] == 'group': + for sub_policy in policy['policies']: + yield sub_policy + else: + yield policy + + +def _LoadJSONFile(json_file): + with open(json_file, 'r') as f: + text = f.read() + return eval(text) + + +#------------------ policy constants header ------------------------# + +def _WritePolicyConstantHeader(policies, os, f): + f.write('#ifndef CHROME_COMMON_POLICY_CONSTANTS_H_\n' + '#define CHROME_COMMON_POLICY_CONSTANTS_H_\n' + '\n' + '#include <string>\n' + '\n' + '#include "base/basictypes.h"\n' + '#include "base/values.h"\n' + '#include "components/policy/core/common/policy_details.h"\n' + '\n' + 'namespace policy {\n' + '\n' + 'namespace internal {\n' + 'struct SchemaData;\n' + '}\n\n') + + if os == 'win': + f.write('// The windows registry path where Chrome policy ' + 'configuration resides.\n' + 'extern const wchar_t kRegistryChromePolicyKey[];\n') + + f.write('// Returns the PolicyDetails for |policy| if |policy| is a known\n' + '// Chrome policy, otherwise returns NULL.\n' + 'const PolicyDetails* GetChromePolicyDetails(' + 'const std::string& policy);\n' + '\n' + '// Returns the schema data of the Chrome policy schema.\n' + 'const internal::SchemaData* GetChromeSchemaData();\n' + '\n') + f.write('// Key names for the policy settings.\n' + 'namespace key {\n\n') + for policy in policies: + # TODO(joaodasilva): Include only supported policies in + # configuration_policy_handler.cc and configuration_policy_handler_list.cc + # so that these names can be conditional on 'policy.is_supported'. + # http://crbug.com/223616 + f.write('extern const char k' + policy.name + '[];\n') + f.write('\n} // namespace key\n\n' + '} // namespace policy\n\n' + '#endif // CHROME_COMMON_POLICY_CONSTANTS_H_\n') + + +#------------------ policy constants source ------------------------# + +# A mapping of the simple schema types to base::Value::Types. +SIMPLE_SCHEMA_NAME_MAP = { + 'boolean': 'TYPE_BOOLEAN', + 'integer': 'TYPE_INTEGER', + 'null' : 'TYPE_NULL', + 'number' : 'TYPE_DOUBLE', + 'string' : 'TYPE_STRING', +} + + +class SchemaNodesGenerator: + """Builds the internal structs to represent a JSON schema.""" + + def __init__(self, shared_strings): + """Creates a new generator. + + |shared_strings| is a map of strings to a C expression that evaluates to + that string at runtime. This mapping can be used to reuse existing string + constants.""" + self.shared_strings = shared_strings + self.schema_nodes = [] + self.property_nodes = [] + self.properties_nodes = [] + self.simple_types = { + 'boolean': None, + 'integer': None, + 'null': None, + 'number': None, + 'string': None, + } + self.stringlist_type = None + + def GetString(self, s): + return self.shared_strings[s] if s in self.shared_strings else '"%s"' % s + + def AppendSchema(self, type, extra, comment=''): + index = len(self.schema_nodes) + self.schema_nodes.append((type, extra, comment)) + return index + + def GetSimpleType(self, name): + if self.simple_types[name] == None: + self.simple_types[name] = self.AppendSchema( + SIMPLE_SCHEMA_NAME_MAP[name], + -1, + 'simple type: ' + name) + return self.simple_types[name] + + def GetStringList(self): + if self.stringlist_type == None: + self.stringlist_type = self.AppendSchema( + 'TYPE_LIST', + self.GetSimpleType('string'), + 'simple type: stringlist') + return self.stringlist_type + + def Generate(self, schema, name): + """Generates the structs for the given schema. + + |schema|: a valid JSON schema in a dictionary. + |name|: the name of the current node, for the generated comments.""" + # Simple types use shared nodes. + if schema['type'] in self.simple_types: + return self.GetSimpleType(schema['type']) + + if schema['type'] == 'array': + # Special case for lists of strings, which is a common policy type. + if schema['items']['type'] == 'string': + return self.GetStringList() + return self.AppendSchema( + 'TYPE_LIST', + self.Generate(schema['items'], 'items of ' + name)) + elif schema['type'] == 'object': + # Reserve an index first, so that dictionaries come before their + # properties. This makes sure that the root node is the first in the + # SchemaNodes array. + index = self.AppendSchema('TYPE_DICTIONARY', -1) + + if 'additionalProperties' in schema: + additionalProperties = self.Generate( + schema['additionalProperties'], + 'additionalProperties of ' + name) + else: + additionalProperties = -1 + + # Properties must be sorted by name, for the binary search lookup. + # Note that |properties| must be evaluated immediately, so that all the + # recursive calls to Generate() append the necessary child nodes; if + # |properties| were a generator then this wouldn't work. + sorted_properties = sorted(schema.get('properties', {}).items()) + properties = [ (self.GetString(key), self.Generate(schema, key)) + for key, schema in sorted_properties ] + begin = len(self.property_nodes) + self.property_nodes += properties + end = len(self.property_nodes) + if index == 0: + self.root_properties_begin = begin + self.root_properties_end = end + + extra = len(self.properties_nodes) + self.properties_nodes.append((begin, end, additionalProperties, name)) + + # Set the right data at |index| now. + self.schema_nodes[index] = ('TYPE_DICTIONARY', extra, name) + return index + else: + assert False + + def Write(self, f): + """Writes the generated structs to the given file. + + |f| an open file to write to.""" + f.write('const internal::SchemaNode kSchemas[] = {\n' + '// Type Extra\n') + for type, extra, comment in self.schema_nodes: + type += ',' + f.write(' { base::Value::%-18s %3d }, // %s\n' % (type, extra, comment)) + f.write('};\n\n') + + f.write('const internal::PropertyNode kPropertyNodes[] = {\n' + '// Property #Schema\n') + for key, schema in self.property_nodes: + key += ',' + f.write(' { %-50s %7d },\n' % (key, schema)) + f.write('};\n\n') + + f.write('const internal::PropertiesNode kProperties[] = {\n' + '// Begin End Additional Properties\n') + for node in self.properties_nodes: + f.write(' { %5d, %5d, %5d }, // %s\n' % node) + f.write('};\n\n') + + f.write('const internal::SchemaData kChromeSchemaData = {\n' + ' kSchemas,\n' + ' kPropertyNodes,\n' + ' kProperties,\n' + '};\n\n') + + +def _WritePolicyConstantSource(policies, os, f): + f.write('#include "policy/policy_constants.h"\n' + '\n' + '#include <algorithm>\n' + '\n' + '#include "base/logging.h"\n' + '#include "components/policy/core/common/schema_internal.h"\n' + '\n' + 'namespace policy {\n' + '\n' + 'namespace {\n' + '\n') + + # Generate the Chrome schema. + chrome_schema = { + 'type': 'object', + 'properties': {}, + } + shared_strings = {} + for policy in policies: + shared_strings[policy.name] = "key::k%s" % policy.name + if policy.is_supported: + chrome_schema['properties'][policy.name] = policy.schema + + # Note: this list must be kept in sync with the known property list of the + # Chrome schema, so that binary seaching in the PropertyNode array gets the + # right index on this array as well. See the implementation of + # GetChromePolicyDetails() below. + f.write('const PolicyDetails kChromePolicyDetails[] = {\n' + '// is_deprecated is_device_policy id max_external_data_size\n') + for policy in policies: + if policy.is_supported: + f.write(' { %-14s %-16s %3s, %24s },\n' % ( + 'true,' if policy.is_deprecated else 'false,', + 'true,' if policy.is_device_only else 'false,', + policy.id, + policy.max_size)) + f.write('};\n\n') + + schema_generator = SchemaNodesGenerator(shared_strings) + schema_generator.Generate(chrome_schema, 'root node') + schema_generator.Write(f) + + f.write('bool CompareKeys(const internal::PropertyNode& node,\n' + ' const std::string& key) {\n' + ' return node.key < key;\n' + '}\n\n') + + f.write('} // namespace\n\n') + + if os == 'win': + f.write('#if defined(GOOGLE_CHROME_BUILD)\n' + 'const wchar_t kRegistryChromePolicyKey[] = ' + 'L"' + CHROME_POLICY_KEY + '";\n' + '#else\n' + 'const wchar_t kRegistryChromePolicyKey[] = ' + 'L"' + CHROMIUM_POLICY_KEY + '";\n' + '#endif\n\n') + + f.write('const internal::SchemaData* GetChromeSchemaData() {\n' + ' return &kChromeSchemaData;\n' + '}\n\n') + + f.write('const PolicyDetails* GetChromePolicyDetails(' + 'const std::string& policy) {\n' + ' // First index in kPropertyNodes of the Chrome policies.\n' + ' static const int begin_index = %s;\n' + ' // One-past-the-end of the Chrome policies in kPropertyNodes.\n' + ' static const int end_index = %s;\n' % + (schema_generator.root_properties_begin, + schema_generator.root_properties_end)) + f.write(' const internal::PropertyNode* begin =\n' + ' kPropertyNodes + begin_index;\n' + ' const internal::PropertyNode* end = kPropertyNodes + end_index;\n' + ' const internal::PropertyNode* it =\n' + ' std::lower_bound(begin, end, policy, CompareKeys);\n' + ' if (it == end || it->key != policy)\n' + ' return NULL;\n' + ' // This relies on kPropertyNodes from begin_index to end_index\n' + ' // having exactly the same policies (and in the same order) as\n' + ' // kChromePolicyDetails, so that binary searching on the first\n' + ' // gets the same results as a binary search on the second would.\n' + ' // However, kPropertyNodes has the policy names and\n' + ' // kChromePolicyDetails doesn\'t, so we obtain the index into\n' + ' // the second array by searching the first to avoid duplicating\n' + ' // the policy name pointers.\n' + ' // Offsetting |it| from |begin| here obtains the index we\'re\n' + ' // looking for.\n' + ' size_t index = it - begin;\n' + ' CHECK_LT(index, arraysize(kChromePolicyDetails));\n' + ' return kChromePolicyDetails + index;\n' + '}\n\n') + + f.write('namespace key {\n\n') + for policy in policies: + # TODO(joaodasilva): Include only supported policies in + # configuration_policy_handler.cc and configuration_policy_handler_list.cc + # so that these names can be conditional on 'policy.is_supported'. + # http://crbug.com/223616 + f.write('const char k{name}[] = "{name}";\n'.format(name=policy.name)) + f.write('\n} // namespace key\n\n' + '} // namespace policy\n') + + +#------------------ policy protobufs --------------------------------# + +CHROME_SETTINGS_PROTO_HEAD = ''' +syntax = "proto2"; + +option optimize_for = LITE_RUNTIME; + +package enterprise_management; + +// For StringList and PolicyOptions. +import "cloud_policy.proto"; + +''' + + +CLOUD_POLICY_PROTO_HEAD = ''' +syntax = "proto2"; + +option optimize_for = LITE_RUNTIME; + +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; + // No policy value is present and the policy should be ignored. + UNSET = 2; + } + optional PolicyMode mode = 1 [default = MANDATORY]; +} + +message BooleanPolicyProto { + optional PolicyOptions policy_options = 1; + optional bool value = 2; +} + +message IntegerPolicyProto { + optional PolicyOptions policy_options = 1; + optional int64 value = 2; +} + +message StringPolicyProto { + optional PolicyOptions policy_options = 1; + optional string value = 2; +} + +message StringListPolicyProto { + optional PolicyOptions policy_options = 1; + optional StringList value = 2; +} + +''' + + +# Field IDs [1..RESERVED_IDS] will not be used in the wrapping protobuf. +RESERVED_IDS = 2 + + +def _WritePolicyProto(f, policy, fields): + _OutputComment(f, policy.caption + '\n\n' + policy.desc) + if policy.items is not None: + _OutputComment(f, '\nValid values:') + for item in policy.items: + _OutputComment(f, ' %s: %s' % (str(item.value), item.caption)) + if policy.policy_type == 'TYPE_DICTIONARY': + _OutputComment(f, '\nValue schema:\n%s' % + json.dumps(policy.schema, sort_keys=True, indent=4, + separators=(',', ': '))) + _OutputComment(f, '\nSupported on: %s' % ', '.join(policy.platforms)) + f.write('message %sProto {\n' % policy.name) + f.write(' optional PolicyOptions policy_options = 1;\n') + f.write(' optional %s %s = 2;\n' % (policy.protobuf_type, policy.name)) + f.write('}\n\n') + fields += [ ' optional %sProto %s = %s;\n' % + (policy.name, policy.name, policy.id + RESERVED_IDS) ] + + +def _WriteChromeSettingsProtobuf(policies, os, f): + f.write(CHROME_SETTINGS_PROTO_HEAD) + + fields = [] + f.write('// PBs for individual settings.\n\n') + for policy in policies: + # Note: this protobuf also gets the unsupported policies, since it's an + # exaustive list of all the supported user policies on any platform. + if not policy.is_device_only: + _WritePolicyProto(f, policy, fields) + + f.write('// --------------------------------------------------\n' + '// Big wrapper PB containing the above groups.\n\n' + 'message ChromeSettingsProto {\n') + f.write(''.join(fields)) + f.write('}\n\n') + + +def _WriteCloudPolicyProtobuf(policies, os, f): + f.write(CLOUD_POLICY_PROTO_HEAD) + f.write('message CloudPolicySettings {\n') + for policy in policies: + if policy.is_supported and not policy.is_device_only: + f.write(' optional %sPolicyProto %s = %s;\n' % + (policy.policy_protobuf_type, policy.name, + policy.id + RESERVED_IDS)) + f.write('}\n\n') + + +#------------------ protobuf decoder -------------------------------# + +CPP_HEAD = ''' +#include <limits> +#include <string> + +#include "base/basictypes.h" +#include "base/callback.h" +#include "base/json/json_reader.h" +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "base/memory/weak_ptr.h" +#include "base/values.h" +#include "components/policy/core/common/cloud/cloud_external_data_manager.h" +#include "components/policy/core/common/external_data_fetcher.h" +#include "components/policy/core/common/policy_map.h" +#include "policy/policy_constants.h" +#include "policy/proto/cloud_policy.pb.h" + +using google::protobuf::RepeatedPtrField; + +namespace policy { + +namespace em = enterprise_management; + +base::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 base::Value::CreateIntegerValue(static_cast<int>(value)); +} + +base::ListValue* DecodeStringList(const em::StringList& string_list) { + base::ListValue* list_value = new base::ListValue; + RepeatedPtrField<std::string>::const_iterator entry; + for (entry = string_list.entries().begin(); + entry != string_list.entries().end(); ++entry) { + list_value->Append(base::Value::CreateStringValue(*entry)); + } + return list_value; +} + +base::Value* DecodeJson(const std::string& json) { + scoped_ptr<base::Value> root( + base::JSONReader::Read(json, base::JSON_ALLOW_TRAILING_COMMAS)); + + if (!root) + LOG(WARNING) << "Invalid JSON string, ignoring: " << json; + + // Accept any Value type that parsed as JSON, and leave it to the handler to + // convert and check the concrete type. + return root.release(); +} + +void DecodePolicy(const em::CloudPolicySettings& policy, + base::WeakPtr<CloudExternalDataManager> external_data_manager, + PolicyMap* map) { +''' + + +CPP_FOOT = '''} + +} // namespace policy +''' + + +def _CreateValue(type, arg): + if type == 'TYPE_BOOLEAN': + return 'base::Value::CreateBooleanValue(%s)' % arg + elif type == 'TYPE_INTEGER': + return 'DecodeIntegerValue(%s)' % arg + elif type == 'TYPE_STRING': + return 'base::Value::CreateStringValue(%s)' % arg + elif type == 'TYPE_LIST': + return 'DecodeStringList(%s)' % arg + elif type == 'TYPE_DICTIONARY' or type == 'TYPE_EXTERNAL': + return 'DecodeJson(%s)' % arg + else: + raise NotImplementedError('Unknown type %s' % type) + + +def _CreateExternalDataFetcher(type, name): + if type == 'TYPE_EXTERNAL': + return 'new ExternalDataFetcher(external_data_manager, key::k%s)' % name + return 'NULL' + + +def _WritePolicyCode(f, policy): + membername = policy.name.lower() + proto_type = '%sPolicyProto' % policy.policy_protobuf_type + f.write(' if (policy.has_%s()) {\n' % membername) + f.write(' const em::%s& policy_proto = policy.%s();\n' % + (proto_type, membername)) + f.write(' if (policy_proto.has_value()) {\n') + f.write(' PolicyLevel level = POLICY_LEVEL_MANDATORY;\n' + ' bool do_set = true;\n' + ' if (policy_proto.has_policy_options()) {\n' + ' do_set = false;\n' + ' switch(policy_proto.policy_options().mode()) {\n' + ' case em::PolicyOptions::MANDATORY:\n' + ' do_set = true;\n' + ' level = POLICY_LEVEL_MANDATORY;\n' + ' break;\n' + ' case em::PolicyOptions::RECOMMENDED:\n' + ' do_set = true;\n' + ' level = POLICY_LEVEL_RECOMMENDED;\n' + ' break;\n' + ' case em::PolicyOptions::UNSET:\n' + ' break;\n' + ' }\n' + ' }\n' + ' if (do_set) {\n') + f.write(' base::Value* value = %s;\n' % + (_CreateValue(policy.policy_type, 'policy_proto.value()'))) + # TODO(bartfab): |value| == NULL indicates that the policy value could not be + # parsed successfully. Surface such errors in the UI. + f.write(' if (value) {\n') + f.write(' ExternalDataFetcher* external_data_fetcher = %s;\n' % + _CreateExternalDataFetcher(policy.policy_type, policy.name)) + f.write(' map->Set(key::k%s, level, POLICY_SCOPE_USER,\n' % + policy.name) + f.write(' value, external_data_fetcher);\n' + ' }\n' + ' }\n' + ' }\n' + ' }\n') + + +def _WriteCloudPolicyDecoder(policies, os, f): + f.write(CPP_HEAD) + for policy in policies: + if policy.is_supported and not policy.is_device_only: + _WritePolicyCode(f, policy) + f.write(CPP_FOOT) + + +if __name__ == '__main__': + sys.exit(main()) |