| 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 d88374d173342f98a96c3f951e641c090256ae58..da620e73e9f0b6db8e96f88b26e63ced94acee75 100755
|
| --- a/chrome/tools/build/generate_policy_source.py
|
| +++ b/chrome/tools/build/generate_policy_source.py
|
| @@ -53,12 +53,9 @@ class PolicyDetails:
|
| 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', {})
|
|
|
| - if is_chromium_os:
|
| - expected_platform = 'chrome_os'
|
| - else:
|
| - expected_platform = os.lower()
|
| -
|
| + 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('-'):
|
| @@ -216,7 +213,11 @@ def _WritePolicyConstantHeader(policies, os, f):
|
| '#include "base/basictypes.h"\n'
|
| '#include "base/values.h"\n'
|
| '\n'
|
| - 'namespace policy {\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 '
|
| @@ -243,7 +244,11 @@ def _WritePolicyConstantHeader(policies, os, f):
|
| 'bool IsDeprecatedPolicy(const std::string& policy);\n'
|
| '\n'
|
| '// Returns the default policy definition list for Chrome.\n'
|
| - 'const PolicyDefinitionList* GetChromePolicyDefinitionList();\n\n')
|
| + 'const PolicyDefinitionList* GetChromePolicyDefinitionList();\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:
|
| @@ -263,14 +268,163 @@ def _GetValueType(policy_type):
|
| return policy_type if policy_type != 'TYPE_EXTERNAL' else 'TYPE_DICTIONARY'
|
|
|
|
|
| +# 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)
|
| +
|
| + 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 "base/basictypes.h"\n'
|
| '#include "base/logging.h"\n'
|
| + '#include "components/policy/core/common/schema_internal.h"\n'
|
| '#include "policy/policy_constants.h"\n'
|
| '\n'
|
| - 'namespace policy {\n\n')
|
| + 'namespace policy {\n'
|
| + '\n'
|
| + 'namespace {\n'
|
| + '\n')
|
|
|
| - f.write('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
|
|
|
| f.write('const PolicyDefinitionList::Entry kEntries[] = {\n')
|
| for policy in policies:
|
| @@ -297,6 +451,10 @@ def _WritePolicyConstantSource(policies, os, f):
|
| f.write(' key::k%s,\n' % policy.name)
|
| f.write('};\n\n')
|
|
|
| + schema_generator = SchemaNodesGenerator(shared_strings)
|
| + schema_generator.Generate(chrome_schema, 'root node')
|
| + schema_generator.Write(f)
|
| +
|
| f.write('} // namespace\n\n')
|
|
|
| if os == 'win':
|
| @@ -323,6 +481,10 @@ def _WritePolicyConstantSource(policies, os, f):
|
| ' return &kChromePolicyList;\n'
|
| '}\n\n')
|
|
|
| + f.write('const internal::SchemaData* GetChromeSchemaData() {\n'
|
| + ' return &kChromeSchemaData;\n'
|
| + '}\n\n')
|
| +
|
| f.write('namespace key {\n\n')
|
| for policy in policies:
|
| # TODO(joaodasilva): Include only supported policies in
|
|
|