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..9c99b50994f52f8a217104df0b5aa08727e31f15 100755 |
--- a/chrome/tools/build/generate_policy_source.py |
+++ b/chrome/tools/build/generate_policy_source.py |
@@ -53,6 +53,7 @@ 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' |
@@ -216,7 +217,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 SchemaNode;\n' |
+ '}\n\n') |
if os == 'win': |
f.write('// The windows registry path where Chrome policy ' |
@@ -243,7 +248,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 root node of the Chrome policy schema.\n' |
+ 'const internal::SchemaNode* GetChromeSchemaNode();\n' |
+ '\n') |
f.write('// Key names for the policy settings.\n' |
'namespace key {\n\n') |
for policy in policies: |
@@ -263,9 +272,75 @@ def _GetValueType(policy_type): |
return policy_type if policy_type != 'TYPE_EXTERNAL' else 'TYPE_DICTIONARY' |
+# Map simple schema types to the address of a static SchemaNode that |
+# represents that type. |
+SIMPLE_SCHEMA_NAME_MAP = { |
+ 'boolean': '&kSchema_boolean', |
+ 'integer': '&kSchema_integer', |
+ 'null' : '&kSchema_null', |
+ 'number' : '&kSchema_number', |
+ 'string' : '&kSchema_string', |
+} |
+ |
+ |
+# Generates SchemaNodes, PropertyNodes and PropertiesNodes for |schema| and |
+# its sub-schemas, and writes them to |f|. |
+# |prefix| is prepended to the generated variable names. |
+# |shared_keys_map| is optional. If present, then property names are looked up |
+# there to reuse shared strings. Otherwise a new static C string is generated. |
+# Returns an expression that evaluates to a SchemaNode*. |
+def _GenerateSchema(f, schema, prefix, shared_keys_map={}): |
+ # Simple types use the shared structures. |
+ if schema['type'] in SIMPLE_SCHEMA_NAME_MAP: |
+ return SIMPLE_SCHEMA_NAME_MAP[schema['type']] |
+ |
+ if schema['type'] == 'array': |
+ # Special case for lists of strings, which is a common policy type. |
+ if schema['items']['type'] == 'string': |
+ return '&kSchema_stringlist' |
+ value_type = 'TYPE_LIST' |
+ extra = _GenerateSchema(f, schema['items'], prefix + '_items') |
+ elif schema['type'] == 'object': |
+ value_type = 'TYPE_DICTIONARY' |
+ |
+ if 'additionalProperties' in schema: |
+ additionalProperties = _GenerateSchema( |
+ f, schema['additionalProperties'], prefix + '_additionalProperties') |
+ else: |
+ additionalProperties = 'NULL' |
+ |
+ properties = [] |
+ sorted_properties = sorted(schema.get('properties', {}).items()) |
+ for property_name, property_schema in sorted_properties: |
+ schema_ptr = _GenerateSchema( |
+ f, property_schema, prefix + '_property_' + property_name) |
+ properties.append((property_name, schema_ptr)) |
+ |
+ f.write('const PropertyNode %s_propertyNodes[] = {\n' % prefix) |
+ for key, ptr in properties: |
+ f.write(' { %s, %s },\n' % (shared_keys_map.get(key, '"%s"' % key), ptr)) |
+ f.write('};\n\n') |
+ |
+ f.write('const PropertiesNode %s_properties = {\n' |
+ ' %s_propertyNodes,\n' |
+ ' %s_propertyNodes + ARRAYSIZE_UNSAFE(%s_propertyNodes),\n' |
+ ' %s,\n' |
+ '};\n\n' % (prefix, prefix, prefix, prefix, additionalProperties)) |
+ |
+ extra = '&%s_properties' % prefix |
+ |
+ f.write('const SchemaNode %s = {\n' |
+ ' base::Value::%s,\n' |
+ ' %s,\n' |
+ '};\n\n' % (prefix, value_type, extra)) |
+ |
+ return '&%s' % prefix |
+ |
+ |
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') |
@@ -299,6 +374,38 @@ def _WritePolicyConstantSource(policies, os, f): |
f.write('} // namespace\n\n') |
+ f.write('namespace internal {\n' |
+ 'namespace {\n\n') |
+ |
+ # Write shared SchemaNodes for the simple types, and the string list. |
+ for node in [ ('boolean', 'BOOLEAN', 'NULL'), |
+ ('integer', 'INTEGER', 'NULL'), |
+ ('null', 'NULL', 'NULL'), |
+ ('number', 'DOUBLE', 'NULL'), |
+ ('string', 'STRING', 'NULL'), |
+ ('stringlist', 'LIST', '&kSchema_string') ]: |
+ f.write('const SchemaNode kSchema_%s = {\n' |
+ ' base::Value::TYPE_%s,\n' |
+ ' %s,\n' |
+ '};\n\n' % node) |
+ |
+ # Generate the Chrome schema. |
+ chrome_schema = { |
+ 'type': 'object', |
+ 'properties': {}, |
+ } |
+ shared_keys_map = {} |
+ for policy in policies: |
+ if policy.is_supported: |
+ chrome_schema['properties'][policy.name] = policy.schema |
+ shared_keys_map[policy.name] = 'key::k%s' % policy.name |
+ |
+ # And write it. |
+ _GenerateSchema(f, chrome_schema, 'kSchema', shared_keys_map) |
+ |
+ f.write('} // namespace\n' |
+ '} // namespace internal\n\n') |
+ |
if os == 'win': |
f.write('#if defined(GOOGLE_CHROME_BUILD)\n' |
'const wchar_t kRegistryChromePolicyKey[] = ' |
@@ -323,6 +430,10 @@ def _WritePolicyConstantSource(policies, os, f): |
' return &kChromePolicyList;\n' |
'}\n\n') |
+ f.write('const internal::SchemaNode* GetChromeSchemaNode() {\n' |
+ ' return &internal::kSchema;\n' |
+ '}\n\n') |
+ |
f.write('namespace key {\n\n') |
for policy in policies: |
# TODO(joaodasilva): Include only supported policies in |