Index: components/policy/tools/generate_policy_source.py |
diff --git a/components/policy/tools/generate_policy_source.py b/components/policy/tools/generate_policy_source.py |
index 9ccf881d17137a2ecd5b98f6e3ea77f21a44cda8..62f558a74976f141c244ae048668f48e2a36c96d 100755 |
--- a/components/policy/tools/generate_policy_source.py |
+++ b/components/policy/tools/generate_policy_source.py |
@@ -16,6 +16,7 @@ from optparse import OptionParser |
import re |
import sys |
import textwrap |
+import types |
CHROME_POLICY_KEY = 'SOFTWARE\\\\Policies\\\\Google\\\\Chrome' |
@@ -282,6 +283,7 @@ class SchemaNodesGenerator: |
} |
self.stringlist_type = None |
self.ranges = {} |
+ self.id_map = {} |
def GetString(self, s): |
if s in self.shared_strings: |
@@ -398,24 +400,28 @@ class SchemaNodesGenerator: |
|schema|: a valid JSON schema in a dictionary. |
|name|: the name of the current node, for the generated comments.""" |
+ if schema.has_key('$ref'): |
+ if schema.has_key('id'): |
+ raise RuntimeError("Schemas with a $ref can't have an id") |
+ return schema['$ref'] |
if schema['type'] in self.simple_types: |
if not self.SchemaHaveRestriction(schema): |
# Simple types use shared nodes. |
- return self.GetSimpleType(schema['type']) |
+ return self.CheckID(schema, self.GetSimpleType(schema['type'])) |
Joao da Silva
2014/04/08 15:02:10
I think adding CheckID() in the right places is ha
binjin
2014/04/09 11:00:36
Done.
|
elif 'enum' in schema: |
- return self.GetEnumType(schema, name) |
+ return self.CheckID(schema, self.GetEnumType(schema, name)) |
elif 'pattern' in schema: |
- return self.GetPatternType(schema, name) |
+ return self.CheckID(schema, self.GetPatternType(schema, name)) |
else: |
- return self.GetRangedType(schema, name) |
+ return self.CheckID(schema, self.GetRangedType(schema, name)) |
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( |
+ return self.CheckID(schema, self.GetStringList()) |
+ return self.CheckID(schema, self.AppendSchema( |
'TYPE_LIST', |
- self.Generate(schema['items'], 'items of ' + name)) |
+ 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 |
@@ -458,7 +464,7 @@ class SchemaNodesGenerator: |
# Set the right data at |index| now. |
self.schema_nodes[index] = ('TYPE_DICTIONARY', extra, name) |
- return index |
+ return self.CheckID(schema, index) |
else: |
assert False |
@@ -516,6 +522,48 @@ class SchemaNodesGenerator: |
f.write(' kStringEnumerations,\n' if self.string_enums else ' NULL,\n') |
f.write('};\n\n') |
+ def CheckID(self, schema, index): |
+ """Check and add 'id' attribute to id_map |
+ |
+ |schema|: target JSON schema that might come with 'id' attribute |
+ |index|: index for parsed |schema|, like the one returned by Generate() |
+ """ |
+ if not schema.has_key('id'): |
+ return index |
+ id_str = schema['id'] |
+ if self.id_map.has_key(id_str): |
+ raise RuntimeError('Duplicated id: ' + id_str) |
+ self.id_map[id_str] = index |
+ return index |
+ |
+ def ResolveReference(self): |
Joao da Silva
2014/04/08 15:02:10
ResolveReferences
binjin
2014/04/09 11:00:36
Done.
|
+ """ Resolve reference mapping, required to be called after Generate() |
Joao da Silva
2014/04/08 15:02:10
Remove the space after """
binjin
2014/04/09 11:00:36
Done.
|
+ |
+ After calling Generate(), the type of indices used in schema structures |
+ might be either int or string. An int type suggest that it's a resolved |
+ index, but for string type it's unresolved. Resolving a reference is as |
+ simple as looking up for corresponding index in self.id_map, and replace the |
Joao da Silva
2014/04/08 15:02:10
corresponding ID
binjin
2014/04/09 11:00:36
Done.
|
+ old index with it. |
Joao da Silva
2014/04/08 15:02:10
old index with the mapped index.
binjin
2014/04/09 11:00:36
Done.
|
+ """ |
+ for i in xrange(len(self.schema_nodes)): |
+ (type, extra, comment) = self.schema_nodes[i] |
+ if isinstance(extra, types.StringTypes): |
+ self.schema_nodes[i] = (type, self.GetByID(extra), comment) |
+ for i in xrange(len(self.property_nodes)): |
+ (key, schema) = self.property_nodes[i] |
+ if isinstance(schema, types.StringTypes): |
+ self.property_nodes[i] = (key, self.GetByID(schema)) |
+ for i in xrange(len(self.properties_nodes)): |
+ (begin, end, pattern_end, additional, name) = self.properties_nodes[i] |
+ if isinstance(additional, types.StringTypes): |
+ self.properties_nodes[i] = (begin, end, pattern_end, |
+ self.GetByID(additional), name) |
Joao da Silva
2014/04/08 15:02:10
This is a bit more complicated than it needs to be
binjin
2014/04/09 11:00:36
Done.
|
+ |
+ def GetByID(self, id_str): |
+ if not self.id_map.has_key(id_str): |
+ raise RuntimeError('Invalid $ref: ' + id_str) |
+ return self.id_map[id_str] |
+ |
def _WritePolicyConstantSource(policies, os, f): |
f.write('#include "policy/policy_constants.h"\n' |
@@ -559,6 +607,7 @@ def _WritePolicyConstantSource(policies, os, f): |
schema_generator = SchemaNodesGenerator(shared_strings) |
schema_generator.Generate(chrome_schema, 'root node') |
+ schema_generator.ResolveReference() |
schema_generator.Write(f) |
f.write('bool CompareKeys(const internal::PropertyNode& node,\n' |