summaryrefslogtreecommitdiffstats
path: root/components
diff options
context:
space:
mode:
authorbinjin@chromium.org <binjin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-09 17:51:43 +0000
committerbinjin@chromium.org <binjin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-09 17:51:43 +0000
commitb245d6aa8ed382b85237d8157fad7309d3670dbf (patch)
treeeef497a7eb9dd9866da9e2c703e8674ff1fcbd66 /components
parent1c3626ee7aa7f098e70aef46c2a14b8a68e2251b (diff)
downloadchromium_src-b245d6aa8ed382b85237d8157fad7309d3670dbf.zip
chromium_src-b245d6aa8ed382b85237d8157fad7309d3670dbf.tar.gz
chromium_src-b245d6aa8ed382b85237d8157fad7309d3670dbf.tar.bz2
Add $ref support to policy schema
BUG=347082 Review URL: https://codereview.chromium.org/228423002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@262738 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'components')
-rw-r--r--components/policy/core/common/generate_policy_source_unittest.cc49
-rw-r--r--components/policy/resources/policy_templates.json69
-rwxr-xr-xcomponents/policy/tools/generate_policy_source.py63
3 files changed, 109 insertions, 72 deletions
diff --git a/components/policy/core/common/generate_policy_source_unittest.cc b/components/policy/core/common/generate_policy_source_unittest.cc
index a2b1462..108b568 100644
--- a/components/policy/core/common/generate_policy_source_unittest.cc
+++ b/components/policy/core/common/generate_policy_source_unittest.cc
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include <cstring>
#include <string>
#include "base/memory/scoped_ptr.h"
@@ -17,6 +18,40 @@
namespace policy {
+namespace {
+
+// Checks if two schemas are the same or not. Note that this function doesn't
+// consider restrictions on integers and strings nor pattern properties.
+bool IsSameSchema(Schema a, Schema b) {
+ if (a.valid() != b.valid())
+ return false;
+ if (!a.valid())
+ return true;
+ if (a.type() != b.type())
+ return false;
+ if (a.type() == base::Value::TYPE_LIST)
+ return IsSameSchema(a.GetItems(), b.GetItems());
+ if (a.type() != base::Value::TYPE_DICTIONARY)
+ return true;
+ Schema::Iterator a_it = a.GetPropertiesIterator();
+ Schema::Iterator b_it = b.GetPropertiesIterator();
+ while (!a_it.IsAtEnd()) {
+ if (b_it.IsAtEnd())
+ return false;
+ if (strcmp(a_it.key(), b_it.key()) != 0)
+ return false;
+ if (!IsSameSchema(a_it.schema(), b_it.schema()))
+ return false;
+ a_it.Advance();
+ b_it.Advance();
+ }
+ if (!b_it.IsAtEnd())
+ return false;
+ return IsSameSchema(a.GetAdditionalProperties(), b.GetAdditionalProperties());
+}
+
+} // namespace
+
TEST(GeneratePolicySource, ChromeSchemaData) {
Schema schema = Schema::Wrap(GetChromeSchemaData());
ASSERT_TRUE(schema.valid());
@@ -83,6 +118,20 @@ TEST(GeneratePolicySource, ChromeSchemaData) {
EXPECT_EQ(base::Value::TYPE_STRING, it.schema().type());
}
EXPECT_TRUE(*next == NULL);
+
+#if defined(OS_CHROMEOS)
+ subschema = schema.GetKnownProperty(key::kPowerManagementIdleSettings);
+ ASSERT_TRUE(subschema.valid());
+
+ EXPECT_TRUE(IsSameSchema(subschema.GetKnownProperty("AC"),
+ subschema.GetKnownProperty("Battery")));
+
+ subschema = schema.GetKnownProperty(key::kDeviceLoginScreenPowerManagement);
+ ASSERT_TRUE(subschema.valid());
+
+ EXPECT_TRUE(IsSameSchema(subschema.GetKnownProperty("AC"),
+ subschema.GetKnownProperty("Battery")));
+#endif
}
TEST(GeneratePolicySource, PolicyDetails) {
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json
index 0033a8f..6042bfe 100644
--- a/components/policy/resources/policy_templates.json
+++ b/components/policy/resources/policy_templates.json
@@ -5286,6 +5286,7 @@
'AC': {
'description': 'Delays and actions to take when the device is idle and running on AC power',
'type': 'object',
+ 'id': 'PowerManagementDelays',
'properties': {
'Delays': {
'type': 'object',
@@ -5321,42 +5322,8 @@
},
'Battery': {
'description': 'Delays and actions to take when the device is idle and running on battery',
- 'type': 'object',
- # TODO(binjin): Use $ref placeholder here once generated policy
- # constants get full support of it. http://crbug.com/347082
- 'properties': {
- 'Delays': {
- 'type': 'object',
- 'properties': {
- 'ScreenDim': {
- 'description': 'The length of time without user input after which the screen is dimmed, in milliseconds',
- 'type': 'integer',
- 'minimum': 0
- },
- 'ScreenOff': {
- 'description': 'The length of time without user input after which the screen is turned off, in milliseconds',
- 'type': 'integer',
- 'minimum': 0
- },
- 'IdleWarning': {
- 'description': 'The length of time without user input after which a warning dialog is shown, in milliseconds',
- 'type': 'integer',
- 'minimum': 0
- },
- 'Idle': {
- 'description': 'The length of time without user input after which the idle action is taken, in milliseconds',
- 'type': 'integer',
- 'minimum': 0
- }
- }
- },
- 'IdleAction': {
- 'description': 'Action to take when the idle delay is reached',
- 'type': 'string',
- 'enum': [ 'Suspend', 'Logout', 'Shutdown', 'DoNothing' ]
- }
- }
- },
+ '$ref': 'PowerManagementDelays'
+ }
}
},
'supported_on': ['chrome_os:35-'],
@@ -5453,6 +5420,7 @@
'AC': {
'description': 'Power management settings applicable only when running on AC power',
'type': 'object',
+ 'id': 'DeviceLoginScreenPowerSettings',
'properties': {
'Delays': {
'type': 'object',
@@ -5483,34 +5451,7 @@
},
'Battery': {
'description': 'Power management settings applicable only when running on battery power',
- 'type': 'object',
- 'properties': {
- 'Delays': {
- 'type': 'object',
- 'properties': {
- 'ScreenDim': {
- 'description': 'The length of time without user input after which the screen is dimmed, in milliseconds',
- 'type': 'integer',
- 'minimum': 0
- },
- 'ScreenOff': {
- 'description': 'The length of time without user input after which the screen is turned off, in milliseconds',
- 'type': 'integer',
- 'minimum': 0
- },
- 'Idle': {
- 'description': 'The length of time without user input after which the idle action is taken, in milliseconds',
- 'type': 'integer',
- 'minimum': 0
- }
- }
- },
- 'IdleAction': {
- 'description': 'Action to take when the idle delay is reached',
- 'type': 'string',
- 'enum': [ 'Suspend', 'Shutdown', 'DoNothing' ]
- }
- }
+ '$ref': 'DeviceLoginScreenPowerSettings'
},
'LidCloseAction': {
'description': 'Action to take when the lid is closed',
diff --git a/components/policy/tools/generate_policy_source.py b/components/policy/tools/generate_policy_source.py
index 9ccf881..0be012a 100755
--- a/components/policy/tools/generate_policy_source.py
+++ b/components/policy/tools/generate_policy_source.py
@@ -11,11 +11,13 @@ 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
+from functools import partial
import json
from optparse import OptionParser
import re
import sys
import textwrap
+import types
CHROME_POLICY_KEY = 'SOFTWARE\\\\Policies\\\\Google\\\\Chrome'
@@ -282,6 +284,7 @@ class SchemaNodesGenerator:
}
self.stringlist_type = None
self.ranges = {}
+ self.id_map = {}
def GetString(self, s):
if s in self.shared_strings:
@@ -398,6 +401,12 @@ 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")
+ if not isinstance(schema['$ref'], types.StringTypes):
+ raise RuntimeError("$ref attribute must be a string")
+ return schema['$ref']
if schema['type'] in self.simple_types:
if not self.SchemaHaveRestriction(schema):
# Simple types use shared nodes.
@@ -413,9 +422,8 @@ class SchemaNodesGenerator:
# 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))
+ return self.AppendSchema('TYPE_LIST',
+ self.GenerateAndCollectID(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
@@ -423,7 +431,7 @@ class SchemaNodesGenerator:
index = self.AppendSchema('TYPE_DICTIONARY', -1)
if 'additionalProperties' in schema:
- additionalProperties = self.Generate(
+ additionalProperties = self.GenerateAndCollectID(
schema['additionalProperties'],
'additionalProperties of ' + name)
else:
@@ -434,13 +442,14 @@ class SchemaNodesGenerator:
# 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(subschema, key))
- for key, subschema in sorted_properties ]
+ properties = [
+ (self.GetString(key), self.GenerateAndCollectID(subschema, key))
+ for key, subschema in sorted_properties ]
pattern_properties = []
for pattern, subschema in schema.get('patternProperties', {}).items():
pattern_properties.append((self.GetString(pattern),
- self.Generate(subschema, pattern)));
+ self.GenerateAndCollectID(subschema, pattern)));
begin = len(self.property_nodes)
self.property_nodes += properties
@@ -462,6 +471,20 @@ class SchemaNodesGenerator:
else:
assert False
+ def GenerateAndCollectID(self, schema, name):
+ """A wrapper of Generate(), will take the return value, check and add 'id'
+ attribute to self.id_map. The wrapper needs to be used for every call to
+ Generate().
+ """
+ index = self.Generate(schema, name)
+ 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 Write(self, f):
"""Writes the generated structs to the given file.
@@ -516,6 +539,29 @@ class SchemaNodesGenerator:
f.write(' kStringEnumerations,\n' if self.string_enums else ' NULL,\n')
f.write('};\n\n')
+ def GetByID(self, id_str):
+ if not isinstance(id_str, types.StringTypes):
+ return id_str
+ if not self.id_map.has_key(id_str):
+ raise RuntimeError('Invalid $ref: ' + id_str)
+ return self.id_map[id_str]
+
+ def ResolveID(self, index, params):
+ return params[:index] + (self.GetByID(params[index]),) + params[index+1:]
+
+ def ResolveReferences(self):
+ """Resolve reference mapping, required to be called after Generate()
+
+ After calling Generate(), the type of indices used in schema structures
+ might be either int or string. An int type suggests that it's a resolved
+ index, but for string type it's unresolved. Resolving a reference is as
+ simple as looking up for corresponding ID in self.id_map, and replace the
+ old index with the mapped index.
+ """
+ self.schema_nodes = map(partial(self.ResolveID, 1), self.schema_nodes)
+ self.property_nodes = map(partial(self.ResolveID, 1), self.property_nodes)
+ self.properties_nodes = map(partial(self.ResolveID, 3),
+ self.properties_nodes)
def _WritePolicyConstantSource(policies, os, f):
f.write('#include "policy/policy_constants.h"\n'
@@ -558,7 +604,8 @@ def _WritePolicyConstantSource(policies, os, f):
f.write('};\n\n')
schema_generator = SchemaNodesGenerator(shared_strings)
- schema_generator.Generate(chrome_schema, 'root node')
+ schema_generator.GenerateAndCollectID(chrome_schema, 'root node')
+ schema_generator.ResolveReferences()
schema_generator.Write(f)
f.write('bool CompareKeys(const internal::PropertyNode& node,\n'