Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1431)

Unified Diff: chrome/tools/build/generate_policy_source.py

Issue 31273002: Generate the Chrome policy schema at compile time. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 7 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « chrome/chrome_tests_unit.gypi ('k') | components/policy/core/common/schema.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
« no previous file with comments | « chrome/chrome_tests_unit.gypi ('k') | components/policy/core/common/schema.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698