Index: mojo/public/js/validator.js |
diff --git a/mojo/public/js/validator.js b/mojo/public/js/validator.js |
deleted file mode 100644 |
index a6be692ead7ca92d998b9fb0b26cc06533ec92cf..0000000000000000000000000000000000000000 |
--- a/mojo/public/js/validator.js |
+++ /dev/null |
@@ -1,356 +0,0 @@ |
-// Copyright 2014 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. |
- |
-define("mojo/public/js/validator", [ |
- "mojo/public/js/codec", |
-], function(codec) { |
- |
- var validationError = { |
- NONE: 'VALIDATION_ERROR_NONE', |
- MISALIGNED_OBJECT: 'VALIDATION_ERROR_MISALIGNED_OBJECT', |
- ILLEGAL_MEMORY_RANGE: 'VALIDATION_ERROR_ILLEGAL_MEMORY_RANGE', |
- UNEXPECTED_STRUCT_HEADER: 'VALIDATION_ERROR_UNEXPECTED_STRUCT_HEADER', |
- UNEXPECTED_ARRAY_HEADER: 'VALIDATION_ERROR_UNEXPECTED_ARRAY_HEADER', |
- ILLEGAL_HANDLE: 'VALIDATION_ERROR_ILLEGAL_HANDLE', |
- UNEXPECTED_INVALID_HANDLE: 'VALIDATION_ERROR_UNEXPECTED_INVALID_HANDLE', |
- ILLEGAL_POINTER: 'VALIDATION_ERROR_ILLEGAL_POINTER', |
- UNEXPECTED_NULL_POINTER: 'VALIDATION_ERROR_UNEXPECTED_NULL_POINTER', |
- MESSAGE_HEADER_INVALID_FLAG_COMBINATION: |
- 'VALIDATION_ERROR_MESSAGE_HEADER_INVALID_FLAG_COMBINATION', |
- MESSAGE_HEADER_MISSING_REQUEST_ID: |
- 'VALIDATION_ERROR_MESSAGE_HEADER_MISSING_REQUEST_ID', |
- DIFFERENT_SIZED_ARRAYS_IN_MAP: |
- 'VALIDATION_ERROR_DIFFERENT_SIZED_ARRAYS_IN_MAP', |
- }; |
- |
- var NULL_MOJO_POINTER = "NULL_MOJO_POINTER"; |
- |
- function isStringClass(cls) { |
- return cls === codec.String || cls === codec.NullableString; |
- } |
- |
- function isHandleClass(cls) { |
- return cls === codec.Handle || cls === codec.NullableHandle; |
- } |
- |
- function isNullable(type) { |
- return type === codec.NullableString || type === codec.NullableHandle || |
- type instanceof codec.NullableArrayOf || |
- type instanceof codec.NullablePointerTo; |
- } |
- |
- function Validator(message) { |
- this.message = message; |
- this.offset = 0; |
- this.handleIndex = 0; |
- } |
- |
- Object.defineProperty(Validator.prototype, "offsetLimit", { |
- get: function() { return this.message.buffer.byteLength; } |
- }); |
- |
- Object.defineProperty(Validator.prototype, "handleIndexLimit", { |
- get: function() { return this.message.handles.length; } |
- }); |
- |
- // True if we can safely allocate a block of bytes from start to |
- // to start + numBytes. |
- Validator.prototype.isValidRange = function(start, numBytes) { |
- // Only positive JavaScript integers that are less than 2^53 |
- // (Number.MAX_SAFE_INTEGER) can be represented exactly. |
- if (start < this.offset || numBytes <= 0 || |
- !Number.isSafeInteger(start) || |
- !Number.isSafeInteger(numBytes)) |
- return false; |
- |
- var newOffset = start + numBytes; |
- if (!Number.isSafeInteger(newOffset) || newOffset > this.offsetLimit) |
- return false; |
- |
- return true; |
- } |
- |
- Validator.prototype.claimRange = function(start, numBytes) { |
- if (this.isValidRange(start, numBytes)) { |
- this.offset = start + numBytes; |
- return true; |
- } |
- return false; |
- } |
- |
- Validator.prototype.claimHandle = function(index) { |
- if (index === codec.kEncodedInvalidHandleValue) |
- return true; |
- |
- if (index < this.handleIndex || index >= this.handleIndexLimit) |
- return false; |
- |
- // This is safe because handle indices are uint32. |
- this.handleIndex = index + 1; |
- return true; |
- } |
- |
- Validator.prototype.validateHandle = function(offset, nullable) { |
- var index = this.message.buffer.getUint32(offset); |
- |
- if (index === codec.kEncodedInvalidHandleValue) |
- return nullable ? |
- validationError.NONE : validationError.UNEXPECTED_INVALID_HANDLE; |
- |
- if (!this.claimHandle(index)) |
- return validationError.ILLEGAL_HANDLE; |
- return validationError.NONE; |
- } |
- |
- Validator.prototype.validateStructHeader = |
- function(offset, minNumBytes, minNumFields) { |
- if (!codec.isAligned(offset)) |
- return validationError.MISALIGNED_OBJECT; |
- |
- if (!this.isValidRange(offset, codec.kStructHeaderSize)) |
- return validationError.ILLEGAL_MEMORY_RANGE; |
- |
- var numBytes = this.message.buffer.getUint32(offset); |
- var numFields = this.message.buffer.getUint32(offset + 4); |
- |
- if (numBytes < minNumBytes || numFields < minNumFields) |
- return validationError.UNEXPECTED_STRUCT_HEADER; |
- |
- if (!this.claimRange(offset, numBytes)) |
- return validationError.ILLEGAL_MEMORY_RANGE; |
- |
- return validationError.NONE; |
- } |
- |
- Validator.prototype.validateMessageHeader = function() { |
- var err = this.validateStructHeader(0, codec.kMessageHeaderSize, 2); |
- if (err != validationError.NONE) |
- return err; |
- |
- var numBytes = this.message.getHeaderNumBytes(); |
- var numFields = this.message.getHeaderNumFields(); |
- |
- var validNumFieldsAndNumBytes = |
- (numFields == 2 && numBytes == codec.kMessageHeaderSize) || |
- (numFields == 3 && |
- numBytes == codec.kMessageWithRequestIDHeaderSize) || |
- (numFields > 3 && |
- numBytes >= codec.kMessageWithRequestIDHeaderSize); |
- if (!validNumFieldsAndNumBytes) |
- return validationError.UNEXPECTED_STRUCT_HEADER; |
- |
- var expectsResponse = this.message.expectsResponse(); |
- var isResponse = this.message.isResponse(); |
- |
- if (numFields == 2 && (expectsResponse || isResponse)) |
- return validationError.MESSAGE_HEADER_MISSING_REQUEST_ID; |
- |
- if (isResponse && expectsResponse) |
- return validationError.MESSAGE_HEADER_INVALID_FLAG_COMBINATION; |
- |
- return validationError.NONE; |
- } |
- |
- // Returns the message.buffer relative offset this pointer "points to", |
- // NULL_MOJO_POINTER if the pointer represents a null, or JS null if the |
- // pointer's value is not valid. |
- Validator.prototype.decodePointer = function(offset) { |
- var pointerValue = this.message.buffer.getUint64(offset); |
- if (pointerValue === 0) |
- return NULL_MOJO_POINTER; |
- var bufferOffset = offset + pointerValue; |
- return Number.isSafeInteger(bufferOffset) ? bufferOffset : null; |
- } |
- |
- Validator.prototype.validateArrayPointer = function( |
- offset, elementSize, elementType, nullable, expectedDimensionSizes, |
- currentDimension) { |
- var arrayOffset = this.decodePointer(offset); |
- if (arrayOffset === null) |
- return validationError.ILLEGAL_POINTER; |
- |
- if (arrayOffset === NULL_MOJO_POINTER) |
- return nullable ? |
- validationError.NONE : validationError.UNEXPECTED_NULL_POINTER; |
- |
- return this.validateArray(arrayOffset, elementSize, elementType, |
- expectedDimensionSizes, currentDimension); |
- } |
- |
- Validator.prototype.validateStructPointer = function( |
- offset, structClass, nullable) { |
- var structOffset = this.decodePointer(offset); |
- if (structOffset === null) |
- return validationError.ILLEGAL_POINTER; |
- |
- if (structOffset === NULL_MOJO_POINTER) |
- return nullable ? |
- validationError.NONE : validationError.UNEXPECTED_NULL_POINTER; |
- |
- return structClass.validate(this, structOffset); |
- } |
- |
- // This method assumes that the array at arrayPointerOffset has |
- // been validated. |
- |
- Validator.prototype.arrayLength = function(arrayPointerOffset) { |
- var arrayOffset = this.decodePointer(arrayPointerOffset); |
- return this.message.buffer.getUint32(arrayOffset + 4); |
- } |
- |
- Validator.prototype.validateMapPointer = function( |
- offset, mapIsNullable, keyClass, valueClass, valueIsNullable) { |
- // Validate the implicit map struct: |
- // struct {array<keyClass> keys; array<valueClass> values}; |
- var structOffset = this.decodePointer(offset); |
- if (structOffset === null) |
- return validationError.ILLEGAL_POINTER; |
- |
- if (structOffset === NULL_MOJO_POINTER) |
- return mapIsNullable ? |
- validationError.NONE : validationError.UNEXPECTED_NULL_POINTER; |
- |
- var mapEncodedSize = codec.kStructHeaderSize + codec.kMapStructPayloadSize; |
- var err = this.validateStructHeader(structOffset, mapEncodedSize, 2); |
- if (err !== validationError.NONE) |
- return err; |
- |
- // Validate the keys array. |
- var keysArrayPointerOffset = structOffset + codec.kStructHeaderSize; |
- err = this.validateArrayPointer( |
- keysArrayPointerOffset, keyClass.encodedSize, keyClass, false, [0], 0); |
- if (err !== validationError.NONE) |
- return err; |
- |
- // Validate the values array. |
- var valuesArrayPointerOffset = keysArrayPointerOffset + 8; |
- var valuesArrayDimensions = [0]; // Validate the actual length below. |
- if (valueClass instanceof codec.ArrayOf) |
- valuesArrayDimensions = |
- valuesArrayDimensions.concat(valueClass.dimensions()); |
- var err = this.validateArrayPointer(valuesArrayPointerOffset, |
- valueClass.encodedSize, |
- valueClass, |
- valueIsNullable, |
- valuesArrayDimensions, |
- 0); |
- if (err !== validationError.NONE) |
- return err; |
- |
- // Validate the lengths of the keys and values arrays. |
- var keysArrayLength = this.arrayLength(keysArrayPointerOffset); |
- var valuesArrayLength = this.arrayLength(valuesArrayPointerOffset); |
- if (keysArrayLength != valuesArrayLength) |
- return validationError.DIFFERENT_SIZED_ARRAYS_IN_MAP; |
- |
- return validationError.NONE; |
- } |
- |
- Validator.prototype.validateStringPointer = function(offset, nullable) { |
- return this.validateArrayPointer( |
- offset, codec.Uint8.encodedSize, codec.Uint8, nullable, [0], 0); |
- } |
- |
- // Similar to Array_Data<T>::Validate() |
- // mojo/public/cpp/bindings/lib/array_internal.h |
- |
- Validator.prototype.validateArray = |
- function (offset, elementSize, elementType, expectedDimensionSizes, |
- currentDimension) { |
- if (!codec.isAligned(offset)) |
- return validationError.MISALIGNED_OBJECT; |
- |
- if (!this.isValidRange(offset, codec.kArrayHeaderSize)) |
- return validationError.ILLEGAL_MEMORY_RANGE; |
- |
- var numBytes = this.message.buffer.getUint32(offset); |
- var numElements = this.message.buffer.getUint32(offset + 4); |
- |
- // Note: this computation is "safe" because elementSize <= 8 and |
- // numElements is a uint32. |
- var elementsTotalSize = (elementType === codec.PackedBool) ? |
- Math.ceil(numElements / 8) : (elementSize * numElements); |
- |
- if (numBytes < codec.kArrayHeaderSize + elementsTotalSize) |
- return validationError.UNEXPECTED_ARRAY_HEADER; |
- |
- if (expectedDimensionSizes[currentDimension] != 0 && |
- numElements != expectedDimensionSizes[currentDimension]) { |
- return validationError.UNEXPECTED_ARRAY_HEADER; |
- } |
- |
- if (!this.claimRange(offset, numBytes)) |
- return validationError.ILLEGAL_MEMORY_RANGE; |
- |
- // Validate the array's elements if they are pointers or handles. |
- |
- var elementsOffset = offset + codec.kArrayHeaderSize; |
- var nullable = isNullable(elementType); |
- |
- if (isHandleClass(elementType)) |
- return this.validateHandleElements(elementsOffset, numElements, nullable); |
- if (isStringClass(elementType)) |
- return this.validateArrayElements( |
- elementsOffset, numElements, codec.Uint8, nullable, [0], 0); |
- if (elementType instanceof codec.PointerTo) |
- return this.validateStructElements( |
- elementsOffset, numElements, elementType.cls, nullable); |
- if (elementType instanceof codec.ArrayOf) |
- return this.validateArrayElements( |
- elementsOffset, numElements, elementType.cls, nullable, |
- expectedDimensionSizes, currentDimension + 1); |
- |
- return validationError.NONE; |
- } |
- |
- // Note: the |offset + i * elementSize| computation in the validateFooElements |
- // methods below is "safe" because elementSize <= 8, offset and |
- // numElements are uint32, and 0 <= i < numElements. |
- |
- Validator.prototype.validateHandleElements = |
- function(offset, numElements, nullable) { |
- var elementSize = codec.Handle.encodedSize; |
- for (var i = 0; i < numElements; i++) { |
- var elementOffset = offset + i * elementSize; |
- var err = this.validateHandle(elementOffset, nullable); |
- if (err != validationError.NONE) |
- return err; |
- } |
- return validationError.NONE; |
- } |
- |
- // The elementClass parameter is the element type of the element arrays. |
- Validator.prototype.validateArrayElements = |
- function(offset, numElements, elementClass, nullable, |
- expectedDimensionSizes, currentDimension) { |
- var elementSize = codec.PointerTo.prototype.encodedSize; |
- for (var i = 0; i < numElements; i++) { |
- var elementOffset = offset + i * elementSize; |
- var err = this.validateArrayPointer( |
- elementOffset, elementClass.encodedSize, elementClass, nullable, |
- expectedDimensionSizes, currentDimension); |
- if (err != validationError.NONE) |
- return err; |
- } |
- return validationError.NONE; |
- } |
- |
- Validator.prototype.validateStructElements = |
- function(offset, numElements, structClass, nullable) { |
- var elementSize = codec.PointerTo.prototype.encodedSize; |
- for (var i = 0; i < numElements; i++) { |
- var elementOffset = offset + i * elementSize; |
- var err = |
- this.validateStructPointer(elementOffset, structClass, nullable); |
- if (err != validationError.NONE) |
- return err; |
- } |
- return validationError.NONE; |
- } |
- |
- var exports = {}; |
- exports.validationError = validationError; |
- exports.Validator = Validator; |
- return exports; |
-}); |