diff options
Diffstat (limited to 'chromium/chrome/renderer/resources/extensions/json_schema.js')
-rw-r--r-- | chromium/chrome/renderer/resources/extensions/json_schema.js | 524 |
1 files changed, 0 insertions, 524 deletions
diff --git a/chromium/chrome/renderer/resources/extensions/json_schema.js b/chromium/chrome/renderer/resources/extensions/json_schema.js deleted file mode 100644 index 6d0631b8bbd..00000000000 --- a/chromium/chrome/renderer/resources/extensions/json_schema.js +++ /dev/null @@ -1,524 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// ----------------------------------------------------------------------------- -// NOTE: If you change this file you need to touch renderer_resources.grd to -// have your change take effect. -// ----------------------------------------------------------------------------- - -//============================================================================== -// This file contains a class that implements a subset of JSON Schema. -// See: http://www.json.com/json-schema-proposal/ for more details. -// -// The following features of JSON Schema are not implemented: -// - requires -// - unique -// - disallow -// - union types (but replaced with 'choices') -// -// The following properties are not applicable to the interface exposed by -// this class: -// - options -// - readonly -// - title -// - description -// - format -// - default -// - transient -// - hidden -// -// There are also these departures from the JSON Schema proposal: -// - function and undefined types are supported -// - null counts as 'unspecified' for optional values -// - added the 'choices' property, to allow specifying a list of possible types -// for a value -// - by default an "object" typed schema does not allow additional properties. -// if present, "additionalProperties" is to be a schema against which all -// additional properties will be validated. -//============================================================================== - -var loadTypeSchema = require('utils').loadTypeSchema; -var CHECK = requireNative('logging').CHECK; - -function isInstanceOfClass(instance, className) { - while ((instance = instance.__proto__)) { - if (instance.constructor.name == className) - return true; - } - return false; -} - -function isOptionalValue(value) { - return typeof(value) === 'undefined' || value === null; -} - -function enumToString(enumValue) { - if (enumValue.name === undefined) - return enumValue; - - return enumValue.name; -} - -/** - * Validates an instance against a schema and accumulates errors. Usage: - * - * var validator = new JSONSchemaValidator(); - * validator.validate(inst, schema); - * if (validator.errors.length == 0) - * console.log("Valid!"); - * else - * console.log(validator.errors); - * - * The errors property contains a list of objects. Each object has two - * properties: "path" and "message". The "path" property contains the path to - * the key that had the problem, and the "message" property contains a sentence - * describing the error. - */ -function JSONSchemaValidator() { - this.errors = []; - this.types = []; -} - -JSONSchemaValidator.messages = { - invalidEnum: "Value must be one of: [*].", - propertyRequired: "Property is required.", - unexpectedProperty: "Unexpected property.", - arrayMinItems: "Array must have at least * items.", - arrayMaxItems: "Array must not have more than * items.", - itemRequired: "Item is required.", - stringMinLength: "String must be at least * characters long.", - stringMaxLength: "String must not be more than * characters long.", - stringPattern: "String must match the pattern: *.", - numberFiniteNotNan: "Value must not be *.", - numberMinValue: "Value must not be less than *.", - numberMaxValue: "Value must not be greater than *.", - numberIntValue: "Value must fit in a 32-bit signed integer.", - numberMaxDecimal: "Value must not have more than * decimal places.", - invalidType: "Expected '*' but got '*'.", - invalidTypeIntegerNumber: - "Expected 'integer' but got 'number', consider using Math.round().", - invalidChoice: "Value does not match any valid type choices.", - invalidPropertyType: "Missing property type.", - schemaRequired: "Schema value required.", - unknownSchemaReference: "Unknown schema reference: *.", - notInstance: "Object must be an instance of *." -}; - -/** - * Builds an error message. Key is the property in the |errors| object, and - * |opt_replacements| is an array of values to replace "*" characters with. - */ -JSONSchemaValidator.formatError = function(key, opt_replacements) { - var message = this.messages[key]; - if (opt_replacements) { - for (var i = 0; i < opt_replacements.length; i++) { - message = message.replace("*", opt_replacements[i]); - } - } - return message; -}; - -/** - * Classifies a value as one of the JSON schema primitive types. Note that we - * don't explicitly disallow 'function', because we want to allow functions in - * the input values. - */ -JSONSchemaValidator.getType = function(value) { - var s = typeof value; - - if (s == "object") { - if (value === null) { - return "null"; - } else if (Object.prototype.toString.call(value) == "[object Array]") { - return "array"; - } else if (typeof(ArrayBuffer) != "undefined" && - value.constructor == ArrayBuffer) { - return "binary"; - } - } else if (s == "number") { - if (value % 1 == 0) { - return "integer"; - } - } - - return s; -}; - -/** - * 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. - */ -JSONSchemaValidator.prototype.addTypes = function(typeOrTypeList) { - function addType(validator, type) { - if (!type.id) - throw new Error("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); - } -} - -/** - * Returns a list of strings of the types that this schema accepts. - */ -JSONSchemaValidator.prototype.getAllTypesForSchema = function(schema) { - var schemaTypes = []; - if (schema.type) - $Array.push(schemaTypes, schema.type); - if (schema.choices) { - for (var i = 0; i < schema.choices.length; i++) { - var choiceTypes = this.getAllTypesForSchema(schema.choices[i]); - schemaTypes = $Array.concat(schemaTypes, choiceTypes); - } - } - var ref = schema['$ref']; - if (ref) { - var type = this.getOrAddType(ref); - CHECK(type, 'Could not find type ' + ref); - schemaTypes = $Array.concat(schemaTypes, this.getAllTypesForSchema(type)); - } - return schemaTypes; -}; - -JSONSchemaValidator.prototype.getOrAddType = function(typeName) { - if (!this.types[typeName]) - this.types[typeName] = loadTypeSchema(typeName); - return this.types[typeName]; -}; - -/** - * Returns true if |schema| would accept an argument of type |type|. - */ -JSONSchemaValidator.prototype.isValidSchemaType = function(type, schema) { - if (type == 'any') - return true; - - // TODO(kalman): I don't understand this code. How can type be "null"? - if (schema.optional && (type == "null" || type == "undefined")) - return true; - - var schemaTypes = this.getAllTypesForSchema(schema); - for (var i = 0; i < schemaTypes.length; i++) { - if (schemaTypes[i] == "any" || type == schemaTypes[i]) - return true; - } - - return false; -}; - -/** - * Returns true if there is a non-null argument that both |schema1| and - * |schema2| would accept. - */ -JSONSchemaValidator.prototype.checkSchemaOverlap = function(schema1, schema2) { - var schema1Types = this.getAllTypesForSchema(schema1); - for (var i = 0; i < schema1Types.length; i++) { - if (this.isValidSchemaType(schema1Types[i], schema2)) - return true; - } - return false; -}; - -/** - * 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. - */ -JSONSchemaValidator.prototype.validate = function(instance, schema, opt_path) { - var path = opt_path || ""; - - if (!schema) { - this.addError(path, "schemaRequired"); - 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. - var ref = schema["$ref"]; - if (ref) { - if (!this.getOrAddType(ref)) - this.addError(path, "unknownSchemaReference", [ ref ]); - else - this.validate(instance, this.getOrAddType(ref), path) - } - - // If the schema has a choices property, the instance must validate against at - // least one of the items in that array. - if (schema.choices) { - this.validateChoices(instance, schema, path); - return; - } - - // If the schema has an enum property, the instance must be one of those - // values. - if (schema.enum) { - if (!this.validateEnum(instance, schema, path)) - return; - } - - if (schema.type && schema.type != "any") { - if (!this.validateType(instance, schema, path)) - return; - - // Type-specific validation. - switch (schema.type) { - case "object": - this.validateObject(instance, schema, path); - break; - case "array": - this.validateArray(instance, schema, path); - break; - case "string": - this.validateString(instance, schema, path); - break; - case "number": - case "integer": - this.validateNumber(instance, schema, path); - break; - } - } -}; - -/** - * Validates an instance against a choices schema. The instance must match at - * least one of the provided choices. - */ -JSONSchemaValidator.prototype.validateChoices = - function(instance, schema, path) { - var originalErrors = this.errors; - - for (var i = 0; i < schema.choices.length; i++) { - this.errors = []; - this.validate(instance, schema.choices[i], path); - if (this.errors.length == 0) { - this.errors = originalErrors; - return; - } - } - - this.errors = originalErrors; - this.addError(path, "invalidChoice"); -}; - -/** - * Validates an instance against a schema with an enum type. Populates the - * |errors| property, and returns a boolean indicating whether the instance - * validates. - */ -JSONSchemaValidator.prototype.validateEnum = function(instance, schema, path) { - for (var i = 0; i < schema.enum.length; i++) { - if (instance === enumToString(schema.enum[i])) - return true; - } - - this.addError(path, "invalidEnum", - [schema.enum.map(enumToString).join(", ")]); - return false; -}; - -/** - * Validates an instance against an object schema and populates the errors - * property. - */ -JSONSchemaValidator.prototype.validateObject = - function(instance, schema, path) { - if (schema.properties) { - for (var prop in schema.properties) { - // It is common in JavaScript to add properties to Object.prototype. This - // check prevents such additions from being interpreted as required - // schema properties. - // TODO(aa): If it ever turns out that we actually want this to work, - // there are other checks we could put here, like requiring that schema - // properties be objects that have a 'type' property. - if (!$Object.hasOwnProperty(schema.properties, prop)) - continue; - - var propPath = path ? path + "." + prop : prop; - if (schema.properties[prop] == undefined) { - this.addError(propPath, "invalidPropertyType"); - } else if (prop in instance && !isOptionalValue(instance[prop])) { - this.validate(instance[prop], schema.properties[prop], propPath); - } else if (!schema.properties[prop].optional) { - this.addError(propPath, "propertyRequired"); - } - } - } - - // If "instanceof" property is set, check that this object inherits from - // the specified constructor (function). - if (schema.isInstanceOf) { - if (!isInstanceOfClass(instance, schema.isInstanceOf)) - this.addError(propPath, "notInstance", [schema.isInstanceOf]); - } - - // Exit early from additional property check if "type":"any" is defined. - if (schema.additionalProperties && - schema.additionalProperties.type && - schema.additionalProperties.type == "any") { - return; - } - - // By default, additional properties are not allowed on instance objects. This - // can be overridden by setting the additionalProperties property to a schema - // which any additional properties must validate against. - for (var prop in instance) { - if (schema.properties && prop in schema.properties) - continue; - - // Any properties inherited through the prototype are ignored. - if (!$Object.hasOwnProperty(instance, prop)) - continue; - - var propPath = path ? path + "." + prop : prop; - if (schema.additionalProperties) - this.validate(instance[prop], schema.additionalProperties, propPath); - else - this.addError(propPath, "unexpectedProperty"); - } -}; - -/** - * Validates an instance against an array schema and populates the errors - * property. - */ -JSONSchemaValidator.prototype.validateArray = function(instance, schema, path) { - var typeOfItems = JSONSchemaValidator.getType(schema.items); - - if (typeOfItems == 'object') { - if (schema.minItems && instance.length < schema.minItems) { - this.addError(path, "arrayMinItems", [schema.minItems]); - } - - if (typeof schema.maxItems != "undefined" && - instance.length > schema.maxItems) { - this.addError(path, "arrayMaxItems", [schema.maxItems]); - } - - // If the items property is a single schema, each item in the array must - // have that schema. - for (var i = 0; i < instance.length; i++) { - this.validate(instance[i], schema.items, path + "." + i); - } - } else if (typeOfItems == 'array') { - // If the items property is an array of schemas, each item in the array must - // validate against the corresponding schema. - for (var i = 0; i < schema.items.length; i++) { - var itemPath = path ? path + "." + i : String(i); - if (i in instance && !isOptionalValue(instance[i])) { - this.validate(instance[i], schema.items[i], itemPath); - } else if (!schema.items[i].optional) { - this.addError(itemPath, "itemRequired"); - } - } - - if (schema.additionalProperties) { - for (var i = schema.items.length; i < instance.length; i++) { - var itemPath = path ? path + "." + i : String(i); - this.validate(instance[i], schema.additionalProperties, itemPath); - } - } else { - if (instance.length > schema.items.length) { - this.addError(path, "arrayMaxItems", [schema.items.length]); - } - } - } -}; - -/** - * Validates a string and populates the errors property. - */ -JSONSchemaValidator.prototype.validateString = - function(instance, schema, path) { - if (schema.minLength && instance.length < schema.minLength) - this.addError(path, "stringMinLength", [schema.minLength]); - - if (schema.maxLength && instance.length > schema.maxLength) - this.addError(path, "stringMaxLength", [schema.maxLength]); - - if (schema.pattern && !schema.pattern.test(instance)) - this.addError(path, "stringPattern", [schema.pattern]); -}; - -/** - * Validates a number and populates the errors property. The instance is - * assumed to be a number. - */ -JSONSchemaValidator.prototype.validateNumber = - function(instance, schema, path) { - // Forbid NaN, +Infinity, and -Infinity. Our APIs don't use them, and - // JSON serialization encodes them as 'null'. Re-evaluate supporting - // them if we add an API that could reasonably take them as a parameter. - if (isNaN(instance) || - instance == Number.POSITIVE_INFINITY || - instance == Number.NEGATIVE_INFINITY ) - this.addError(path, "numberFiniteNotNan", [instance]); - - if (schema.minimum !== undefined && instance < schema.minimum) - this.addError(path, "numberMinValue", [schema.minimum]); - - if (schema.maximum !== undefined && instance > schema.maximum) - this.addError(path, "numberMaxValue", [schema.maximum]); - - // Check for integer values outside of -2^31..2^31-1. - if (schema.type === "integer" && (instance | 0) !== instance) - this.addError(path, "numberIntValue", []); - - if (schema.maxDecimal && instance * Math.pow(10, schema.maxDecimal) % 1) - this.addError(path, "numberMaxDecimal", [schema.maxDecimal]); -}; - -/** - * Validates the primitive type of an instance and populates the errors - * property. Returns true if the instance validates, false otherwise. - */ -JSONSchemaValidator.prototype.validateType = function(instance, schema, path) { - var actualType = JSONSchemaValidator.getType(instance); - if (schema.type == actualType || - (schema.type == "number" && actualType == "integer")) { - return true; - } else if (schema.type == "integer" && actualType == "number") { - this.addError(path, "invalidTypeIntegerNumber"); - return false; - } else { - this.addError(path, "invalidType", [schema.type, actualType]); - return false; - } -}; - -/** - * Adds an error message. |key| is an index into the |messages| object. - * |replacements| is an array of values to replace '*' characters in the - * message. - */ -JSONSchemaValidator.prototype.addError = function(path, key, replacements) { - $Array.push(this.errors, { - path: path, - message: JSONSchemaValidator.formatError(key, replacements) - }); -}; - -/** - * Resets errors to an empty list so you can call 'validate' again. - */ -JSONSchemaValidator.prototype.resetErrors = function() { - this.errors = []; -}; - -exports.JSONSchemaValidator = JSONSchemaValidator; |