summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
Diffstat (limited to 'chrome')
-rw-r--r--chrome/renderer/extensions/json_schema_unittest.cc5
-rw-r--r--chrome/renderer/renderer_resources.grd2
-rw-r--r--chrome/renderer/resources/json_schema.js36
-rw-r--r--chrome/test/data/extensions/json_schema_test.js78
4 files changed, 118 insertions, 3 deletions
diff --git a/chrome/renderer/extensions/json_schema_unittest.cc b/chrome/renderer/extensions/json_schema_unittest.cc
index 7d4073f..9b53094 100644
--- a/chrome/renderer/extensions/json_schema_unittest.cc
+++ b/chrome/renderer/extensions/json_schema_unittest.cc
@@ -77,3 +77,8 @@ TEST_F(JsonSchemaTest, TestNumber) {
TEST_F(JsonSchemaTest, TestType) {
TestFunction("testType");
}
+
+TEST_F(JsonSchemaTest, TestTypeReference) {
+ TestFunction("testTypeReference");
+}
+
diff --git a/chrome/renderer/renderer_resources.grd b/chrome/renderer/renderer_resources.grd
index ec1d32c..5ec2309 100644
--- a/chrome/renderer/renderer_resources.grd
+++ b/chrome/renderer/renderer_resources.grd
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- This comment is only here because changes to resources are not picked up
-without changes to the corresponding grd file. ek2 -->
+without changes to the corresponding grd file. rw -->
<grit latest_public_release="0" current_release="1">
<outputs>
<output filename="grit/renderer_resources.h" type="rc_header">
diff --git a/chrome/renderer/resources/json_schema.js b/chrome/renderer/resources/json_schema.js
index f5d06c6..70dd26f 100644
--- a/chrome/renderer/resources/json_schema.js
+++ b/chrome/renderer/resources/json_schema.js
@@ -55,6 +55,7 @@ var chrome = chrome || {};
*/
chrome.JSONSchemaValidator = function() {
this.errors = [];
+ this.types = [];
};
chrome.JSONSchemaValidator.messages = {
@@ -74,6 +75,7 @@ chrome.JSONSchemaValidator.messages = {
invalidChoice: "Value does not match any valid type choices.",
invalidPropertyType: "Missing property type.",
schemaRequired: "Schema value required.",
+ unknownSchemaReference: "Unknown schema reference: *."
};
/**
@@ -115,6 +117,27 @@ chrome.JSONSchemaValidator.getType = function(value) {
};
/**
+ * Add types that may be referenced by validated schemas that reference them
+ * with "$ref": <typeId>. Each type must be a valid schema and define an
+ * "id" property.
+ */
+chrome.JSONSchemaValidator.prototype.addTypes = function(typeOrTypeList) {
+ function addType(validator, type) {
+ if(!type.id)
+ throw "Attempt to addType with missing 'id' property";
+ validator.types[type.id] = type;
+ }
+
+ if (typeOrTypeList instanceof Array) {
+ for (var i = 0; i < typeOrTypeList.length; i++) {
+ addType(this, typeOrTypeList[i]);
+ }
+ } else {
+ addType(this, typeOrTypeList);
+ }
+}
+
+/**
* Validates an instance against a schema. The instance can be any JavaScript
* value and will be validated recursively. When this method returns, the
* |errors| property will contain a list of errors, if any.
@@ -128,10 +151,23 @@ chrome.JSONSchemaValidator.prototype.validate = function(instance, schema,
return;
}
+ // If this schema defines itself as reference type, save it in this.types.
+ if (schema.id)
+ this.types[schema.id] = schema;
+
// If the schema has an extends property, the instance must validate against
// that schema too.
if (schema.extends)
this.validate(instance, schema.extends, path);
+
+ // If the schema has a $ref property, the instance must validate against
+ // that schema too. It must be present in this.types to be referenced.
+ if (schema["$ref"]) {
+ if (!this.types[schema["$ref"]])
+ this.addError(path, "unknownSchemaReference", [ schema["$ref"] ]);
+ else
+ this.validate(instance, this.types[schema["$ref"]], path)
+ }
// If the schema has a choices property, the instance must validate against at
// least one of the items in that array.
diff --git a/chrome/test/data/extensions/json_schema_test.js b/chrome/test/data/extensions/json_schema_test.js
index 195dcba..4231888 100644
--- a/chrome/test/data/extensions/json_schema_test.js
+++ b/chrome/test/data/extensions/json_schema_test.js
@@ -7,8 +7,10 @@ function assert(truth) {
throw new Error("Assertion failed.");
}
-function assertValid(type, instance, schema) {
+function assertValid(type, instance, schema, types) {
var validator = new chrome.JSONSchemaValidator();
+ if (types)
+ validator.addTypes(types);
validator["validate" + type](instance, schema, "");
if (validator.errors.length != 0) {
log("Got unexpected errors");
@@ -17,8 +19,10 @@ function assertValid(type, instance, schema) {
}
}
-function assertNotValid(type, instance, schema, errors) {
+function assertNotValid(type, instance, schema, errors, types) {
var validator = new chrome.JSONSchemaValidator();
+ if (types)
+ validator.addTypes(types);
validator["validate" + type](instance, schema, "");
assert(validator.errors.length === errors.length);
for (var i = 0; i < errors.length; i++) {
@@ -199,6 +203,76 @@ function testObject() {
[formatError("invalidType", ["integer", "string"])]);
}
+function testTypeReference() {
+ var referencedTypes = [
+ {
+ id: "MinLengthString",
+ type: "string",
+ minLength: 2
+ },
+ {
+ id: "Max10Int",
+ type: "integer",
+ maximum: 10
+ }
+ ];
+
+ var schema = {
+ type: "object",
+ properties: {
+ "foo": {
+ type: "string"
+ },
+ "bar": {
+ $ref: "Max10Int"
+ },
+ "baz": {
+ $ref: "MinLengthString"
+ }
+ }
+ };
+
+ var schemaInlineReference = {
+ type: "object",
+ properties: {
+ "foo": {
+ type: "string"
+ },
+ "bar": {
+ id: "NegativeInt",
+ type: "integer",
+ maximum: 0
+ },
+ "baz": {
+ $ref: "NegativeInt"
+ }
+ }
+ }
+
+ // Valid type references externally added.
+ assertValid("", {foo:"foo",bar:4,baz:"ab"}, schema, referencedTypes);
+
+ // Valida type references internally defined.
+ assertValid("", {foo:"foo",bar:-4,baz:-2}, schemaInlineReference);
+
+ // Failures in validation, but succesful schema reference.
+ assertNotValid("", {foo:"foo",bar:4,baz:"a"}, schema,
+ [formatError("stringMinLength", [2])], referencedTypes);
+ assertNotValid("", {foo:"foo",bar:20,baz:"abc"}, schema,
+ [formatError("numberMaxValue", [10])], referencedTypes);
+
+ // Remove MinLengthString type.
+ referencedTypes.shift();
+ assertNotValid("", {foo:"foo",bar:4,baz:"ab"}, schema,
+ [formatError("unknownSchemaReference", ["MinLengthString"])],
+ referencedTypes);
+
+ // Remove internal type "NegativeInt"
+ delete schemaInlineReference.properties.bar;
+ assertNotValid("", {foo:"foo",baz:-2}, schemaInlineReference,
+ [formatError("unknownSchemaReference", ["NegativeInt"])]);
+}
+
function testArrayTuple() {
var schema = {
items: [