| Index: Source/modules/crypto/NormalizeAlgorithm.cpp | 
| diff --git a/Source/modules/crypto/NormalizeAlgorithm.cpp b/Source/modules/crypto/NormalizeAlgorithm.cpp | 
| index 4d799e7b3b6c554de036dfa04073da7b0c43973f..19965eeb8aab1e51759a8bcca196f5b11a9bfd2d 100644 | 
| --- a/Source/modules/crypto/NormalizeAlgorithm.cpp | 
| +++ b/Source/modules/crypto/NormalizeAlgorithm.cpp | 
| @@ -396,6 +396,21 @@ const AlgorithmInfo* lookupAlgorithmInfo(blink::WebCryptoAlgorithmId id) | 
| return &algorithmIdToInfo[id]; | 
| } | 
|  | 
| +void completeWithSyntaxError(const String& message, CryptoResult* result) | 
| +{ | 
| +    result->completeWithError(blink::WebCryptoErrorTypeSyntax, message); | 
| +} | 
| + | 
| +void completeWithNotSupportedError(const String& message, CryptoResult* result) | 
| +{ | 
| +    result->completeWithError(blink::WebCryptoErrorTypeNotSupported, message); | 
| +} | 
| + | 
| +void completeWithDataError(const String& message, CryptoResult* result) | 
| +{ | 
| +    result->completeWithError(blink::WebCryptoErrorTypeData, message); | 
| +} | 
| + | 
| // ErrorContext holds a stack of string literals which describe what was | 
| // happening at the time the error occurred. This is helpful because | 
| // parsing of the algorithm dictionary can be recursive and it is difficult to | 
| @@ -407,6 +422,11 @@ public: | 
| m_messages.append(message); | 
| } | 
|  | 
| +    void removeLast() | 
| +    { | 
| +        m_messages.removeLast(); | 
| +    } | 
| + | 
| // Join all of the string literals into a single String. | 
| String toString() const | 
| { | 
| @@ -456,7 +476,7 @@ private: | 
| //     typedef (ArrayBuffer or ArrayBufferView) CryptoOperationData; | 
| // | 
| // FIXME: Currently only supports ArrayBufferView. | 
| -bool getOptionalCryptoOperationData(const Dictionary& raw, const char* propertyName, bool& hasProperty, RefPtr<ArrayBufferView>& buffer, const ErrorContext& context, String& errorDetails) | 
| +bool getOptionalCryptoOperationData(const Dictionary& raw, const char* propertyName, bool& hasProperty, RefPtr<ArrayBufferView>& buffer, const ErrorContext& context, CryptoResult* result) | 
| { | 
| if (!raw.get(propertyName, buffer)) { | 
| hasProperty = false; | 
| @@ -466,7 +486,7 @@ bool getOptionalCryptoOperationData(const Dictionary& raw, const char* propertyN | 
| hasProperty = true; | 
|  | 
| if (!buffer) { | 
| -        errorDetails = context.toString(propertyName, "Not an ArrayBufferView"); | 
| +        completeWithSyntaxError(context.toString(propertyName, "Not an ArrayBufferView"), result); | 
| return false; | 
| } | 
|  | 
| @@ -478,21 +498,21 @@ bool getOptionalCryptoOperationData(const Dictionary& raw, const char* propertyN | 
| //     typedef (ArrayBuffer or ArrayBufferView) CryptoOperationData; | 
| // | 
| // FIXME: Currently only supports ArrayBufferView. | 
| -bool getCryptoOperationData(const Dictionary& raw, const char* propertyName, RefPtr<ArrayBufferView>& buffer, const ErrorContext& context, String& errorDetails) | 
| +bool getCryptoOperationData(const Dictionary& raw, const char* propertyName, RefPtr<ArrayBufferView>& buffer, const ErrorContext& context, CryptoResult* result) | 
| { | 
| bool hasProperty; | 
| -    bool ok = getOptionalCryptoOperationData(raw, propertyName, hasProperty, buffer, context, errorDetails); | 
| +    bool ok = getOptionalCryptoOperationData(raw, propertyName, hasProperty, buffer, context, result); | 
| if (!hasProperty) { | 
| -        errorDetails = context.toString(propertyName, "Missing required property"); | 
| +        completeWithSyntaxError(context.toString(propertyName, "Missing required property"), result); | 
| return false; | 
| } | 
| return ok; | 
| } | 
|  | 
| -bool getUint8Array(const Dictionary& raw, const char* propertyName, RefPtr<Uint8Array>& array, const ErrorContext& context, String& errorDetails) | 
| +bool getUint8Array(const Dictionary& raw, const char* propertyName, RefPtr<Uint8Array>& array, const ErrorContext& context, CryptoResult* result) | 
| { | 
| if (!raw.get(propertyName, array) || !array) { | 
| -        errorDetails = context.toString(propertyName, "Missing or not a Uint8Array"); | 
| +        completeWithSyntaxError(context.toString(propertyName, "Missing or not a Uint8Array"), result); | 
| return false; | 
| } | 
| return true; | 
| @@ -501,25 +521,25 @@ bool getUint8Array(const Dictionary& raw, const char* propertyName, RefPtr<Uint8 | 
| // Defined by the WebCrypto spec as: | 
| // | 
| //     typedef Uint8Array BigInteger; | 
| -bool getBigInteger(const Dictionary& raw, const char* propertyName, RefPtr<Uint8Array>& array, const ErrorContext& context, String& errorDetails) | 
| +bool getBigInteger(const Dictionary& raw, const char* propertyName, RefPtr<Uint8Array>& array, const ErrorContext& context, CryptoResult* result) | 
| { | 
| -    if (!getUint8Array(raw, propertyName, array, context, errorDetails)) | 
| +    if (!getUint8Array(raw, propertyName, array, context, result)) | 
| return false; | 
|  | 
| if (!array->byteLength()) { | 
| -        errorDetails = context.toString(propertyName, "BigInteger should not be empty"); | 
| +        completeWithSyntaxError(context.toString(propertyName, "BigInteger should not be empty"), result); | 
| return false; | 
| } | 
|  | 
| if (!raw.get(propertyName, array) || !array) { | 
| -        errorDetails = context.toString(propertyName, "Missing or not a Uint8Array"); | 
| +        completeWithSyntaxError(context.toString(propertyName, "Missing or not a Uint8Array"), result); | 
| return false; | 
| } | 
| return true; | 
| } | 
|  | 
| // Gets an integer according to WebIDL's [EnforceRange]. | 
| -bool getOptionalInteger(const Dictionary& raw, const char* propertyName, bool& hasProperty, double& value, double minValue, double maxValue, const ErrorContext& context, String& errorDetails) | 
| +bool getOptionalInteger(const Dictionary& raw, const char* propertyName, bool& hasProperty, double& value, double minValue, double maxValue, const ErrorContext& context, CryptoResult* result) | 
| { | 
| double number; | 
| bool ok = raw.get(propertyName, number, hasProperty); | 
| @@ -528,14 +548,14 @@ bool getOptionalInteger(const Dictionary& raw, const char* propertyName, bool& h | 
| return true; | 
|  | 
| if (!ok || std::isnan(number)) { | 
| -        errorDetails = context.toString(propertyName, "Is not a number"); | 
| +        completeWithSyntaxError(context.toString(propertyName, "Is not a number"), result); | 
| return false; | 
| } | 
|  | 
| number = trunc(number); | 
|  | 
| if (std::isinf(number) || number < minValue || number > maxValue) { | 
| -        errorDetails = context.toString(propertyName, "Outside of numeric range"); | 
| +        completeWithSyntaxError(context.toString(propertyName, "Outside of numeric range"), result); | 
| return false; | 
| } | 
|  | 
| @@ -543,51 +563,51 @@ bool getOptionalInteger(const Dictionary& raw, const char* propertyName, bool& h | 
| return true; | 
| } | 
|  | 
| -bool getInteger(const Dictionary& raw, const char* propertyName, double& value, double minValue, double maxValue, const ErrorContext& context, String& errorDetails) | 
| +bool getInteger(const Dictionary& raw, const char* propertyName, double& value, double minValue, double maxValue, const ErrorContext& context, CryptoResult* result) | 
| { | 
| bool hasProperty; | 
| -    if (!getOptionalInteger(raw, propertyName, hasProperty, value, minValue, maxValue, context, errorDetails)) | 
| +    if (!getOptionalInteger(raw, propertyName, hasProperty, value, minValue, maxValue, context, result)) | 
| return false; | 
|  | 
| if (!hasProperty) { | 
| -        errorDetails = context.toString(propertyName, "Missing required property"); | 
| +        completeWithSyntaxError(context.toString(propertyName, "Missing required property"), result); | 
| return false; | 
| } | 
|  | 
| return true; | 
| } | 
|  | 
| -bool getUint32(const Dictionary& raw, const char* propertyName, uint32_t& value, const ErrorContext& context, String& errorDetails) | 
| +bool getUint32(const Dictionary& raw, const char* propertyName, uint32_t& value, const ErrorContext& context, CryptoResult* result) | 
| { | 
| double number; | 
| -    if (!getInteger(raw, propertyName, number, 0, 0xFFFFFFFF, context, errorDetails)) | 
| +    if (!getInteger(raw, propertyName, number, 0, 0xFFFFFFFF, context, result)) | 
| return false; | 
| value = number; | 
| return true; | 
| } | 
|  | 
| -bool getUint16(const Dictionary& raw, const char* propertyName, uint16_t& value, const ErrorContext& context, String& errorDetails) | 
| +bool getUint16(const Dictionary& raw, const char* propertyName, uint16_t& value, const ErrorContext& context, CryptoResult* result) | 
| { | 
| double number; | 
| -    if (!getInteger(raw, propertyName, number, 0, 0xFFFF, context, errorDetails)) | 
| +    if (!getInteger(raw, propertyName, number, 0, 0xFFFF, context, result)) | 
| return false; | 
| value = number; | 
| return true; | 
| } | 
|  | 
| -bool getUint8(const Dictionary& raw, const char* propertyName, uint8_t& value, const ErrorContext& context, String& errorDetails) | 
| +bool getUint8(const Dictionary& raw, const char* propertyName, uint8_t& value, const ErrorContext& context, CryptoResult* result) | 
| { | 
| double number; | 
| -    if (!getInteger(raw, propertyName, number, 0, 0xFF, context, errorDetails)) | 
| +    if (!getInteger(raw, propertyName, number, 0, 0xFF, context, result)) | 
| return false; | 
| value = number; | 
| return true; | 
| } | 
|  | 
| -bool getOptionalUint32(const Dictionary& raw, const char* propertyName, bool& hasValue, uint32_t& value, const ErrorContext& context, String& errorDetails) | 
| +bool getOptionalUint32(const Dictionary& raw, const char* propertyName, bool& hasValue, uint32_t& value, const ErrorContext& context, CryptoResult* result) | 
| { | 
| double number; | 
| -    if (!getOptionalInteger(raw, propertyName, hasValue, number, 0, 0xFFFFFFFF, context, errorDetails)) | 
| +    if (!getOptionalInteger(raw, propertyName, hasValue, number, 0, 0xFFFFFFFF, context, result)) | 
| return false; | 
| if (hasValue) | 
| value = number; | 
| @@ -599,14 +619,14 @@ bool getOptionalUint32(const Dictionary& raw, const char* propertyName, bool& ha | 
| //    dictionary AesCbcParams : Algorithm { | 
| //      CryptoOperationData iv; | 
| //    }; | 
| -bool parseAesCbcParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, String& errorDetails) | 
| +bool parseAesCbcParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, CryptoResult* result) | 
| { | 
| RefPtr<ArrayBufferView> iv; | 
| -    if (!getCryptoOperationData(raw, "iv", iv, context, errorDetails)) | 
| +    if (!getCryptoOperationData(raw, "iv", iv, context, result)) | 
| return false; | 
|  | 
| if (iv->byteLength() != 16) { | 
| -        errorDetails = context.toString("iv", "Must be 16 bytes"); | 
| +        completeWithDataError(context.toString("iv", "Must be 16 bytes"), result); | 
| return false; | 
| } | 
|  | 
| @@ -619,28 +639,28 @@ bool parseAesCbcParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmPa | 
| //    dictionary AesKeyGenParams : Algorithm { | 
| //      [EnforceRange] unsigned short length; | 
| //    }; | 
| -bool parseAesKeyGenParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, String& errorDetails) | 
| +bool parseAesKeyGenParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, CryptoResult* result) | 
| { | 
| uint16_t length; | 
| -    if (!getUint16(raw, "length", length, context, errorDetails)) | 
| +    if (!getUint16(raw, "length", length, context, result)) | 
| return false; | 
|  | 
| params = adoptPtr(new blink::WebCryptoAesKeyGenParams(length)); | 
| return true; | 
| } | 
|  | 
| -bool parseAlgorithm(const Dictionary&, AlgorithmOperation, blink::WebCryptoAlgorithm&, ErrorContext, String&); | 
| +bool parseAlgorithm(const Dictionary&, AlgorithmOperation, blink::WebCryptoAlgorithm&, ErrorContext, CryptoResult*); | 
|  | 
| -bool parseHash(const Dictionary& raw, blink::WebCryptoAlgorithm& hash, ErrorContext context, String& errorDetails) | 
| +bool parseHash(const Dictionary& raw, blink::WebCryptoAlgorithm& hash, ErrorContext context, CryptoResult* result) | 
| { | 
| Dictionary rawHash; | 
| if (!raw.get("hash", rawHash)) { | 
| -        errorDetails = context.toString("hash", "Missing or not a dictionary"); | 
| +        completeWithSyntaxError(context.toString("hash", "Missing or not a dictionary"), result); | 
| return false; | 
| } | 
|  | 
| context.add("hash"); | 
| -    return parseAlgorithm(rawHash, Digest, hash, context, errorDetails); | 
| +    return parseAlgorithm(rawHash, Digest, hash, context, result); | 
| } | 
|  | 
| // Defined by the WebCrypto spec as: | 
| @@ -648,10 +668,10 @@ bool parseHash(const Dictionary& raw, blink::WebCryptoAlgorithm& hash, ErrorCont | 
| //    dictionary HmacImportParams : Algorithm { | 
| //      AlgorithmIdentifier hash; | 
| //    }; | 
| -bool parseHmacImportParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, String& errorDetails) | 
| +bool parseHmacImportParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, CryptoResult* result) | 
| { | 
| blink::WebCryptoAlgorithm hash; | 
| -    if (!parseHash(raw, hash, context, errorDetails)) | 
| +    if (!parseHash(raw, hash, context, result)) | 
| return false; | 
|  | 
| params = adoptPtr(new blink::WebCryptoHmacImportParams(hash)); | 
| @@ -667,15 +687,15 @@ bool parseHmacImportParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorit | 
| //      // size. | 
| //      unsigned long length; | 
| //    }; | 
| -bool parseHmacKeyGenParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, String& errorDetails) | 
| +bool parseHmacKeyGenParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, CryptoResult* result) | 
| { | 
| blink::WebCryptoAlgorithm hash; | 
| -    if (!parseHash(raw, hash, context, errorDetails)) | 
| +    if (!parseHash(raw, hash, context, result)) | 
| return false; | 
|  | 
| bool hasLength; | 
| uint32_t length = 0; | 
| -    if (!getOptionalUint32(raw, "length", hasLength, length, context, errorDetails)) | 
| +    if (!getOptionalUint32(raw, "length", hasLength, length, context, result)) | 
| return false; | 
|  | 
| params = adoptPtr(new blink::WebCryptoHmacKeyGenParams(hash, hasLength, length)); | 
| @@ -687,10 +707,10 @@ bool parseHmacKeyGenParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorit | 
| //    dictionary RsaHashedImportParams { | 
| //      AlgorithmIdentifier hash; | 
| //    }; | 
| -bool parseRsaHashedImportParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, String& errorDetails) | 
| +bool parseRsaHashedImportParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, CryptoResult* result) | 
| { | 
| blink::WebCryptoAlgorithm hash; | 
| -    if (!parseHash(raw, hash, context, errorDetails)) | 
| +    if (!parseHash(raw, hash, context, result)) | 
| return false; | 
|  | 
| params = adoptPtr(new blink::WebCryptoRsaHashedImportParams(hash)); | 
| @@ -703,22 +723,22 @@ bool parseRsaHashedImportParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAl | 
| //      unsigned long modulusLength; | 
| //      BigInteger publicExponent; | 
| //    }; | 
| -bool parseRsaKeyGenParams(const Dictionary& raw, uint32_t& modulusLength, RefPtr<Uint8Array>& publicExponent, const ErrorContext& context, String& errorDetails) | 
| +bool parseRsaKeyGenParams(const Dictionary& raw, uint32_t& modulusLength, RefPtr<Uint8Array>& publicExponent, const ErrorContext& context, CryptoResult* result) | 
| { | 
| -    if (!getUint32(raw, "modulusLength", modulusLength, context, errorDetails)) | 
| +    if (!getUint32(raw, "modulusLength", modulusLength, context, result)) | 
| return false; | 
|  | 
| -    if (!getBigInteger(raw, "publicExponent", publicExponent, context, errorDetails)) | 
| +    if (!getBigInteger(raw, "publicExponent", publicExponent, context, result)) | 
| return false; | 
|  | 
| return true; | 
| } | 
|  | 
| -bool parseRsaKeyGenParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, String& errorDetails) | 
| +bool parseRsaKeyGenParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, CryptoResult* result) | 
| { | 
| uint32_t modulusLength; | 
| RefPtr<Uint8Array> publicExponent; | 
| -    if (!parseRsaKeyGenParams(raw, modulusLength, publicExponent, context, errorDetails)) | 
| +    if (!parseRsaKeyGenParams(raw, modulusLength, publicExponent, context, result)) | 
| return false; | 
|  | 
| params = adoptPtr(new blink::WebCryptoRsaKeyGenParams(modulusLength, static_cast<const unsigned char*>(publicExponent->baseAddress()), publicExponent->byteLength())); | 
| @@ -730,15 +750,15 @@ bool parseRsaKeyGenParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorith | 
| //    dictionary RsaHashedKeyGenParams : RsaKeyGenParams { | 
| //      AlgorithmIdentifier hash; | 
| //    }; | 
| -bool parseRsaHashedKeyGenParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, String& errorDetails) | 
| +bool parseRsaHashedKeyGenParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, CryptoResult* result) | 
| { | 
| uint32_t modulusLength; | 
| RefPtr<Uint8Array> publicExponent; | 
| -    if (!parseRsaKeyGenParams(raw, modulusLength, publicExponent, context, errorDetails)) | 
| +    if (!parseRsaKeyGenParams(raw, modulusLength, publicExponent, context, result)) | 
| return false; | 
|  | 
| blink::WebCryptoAlgorithm hash; | 
| -    if (!parseHash(raw, hash, context, errorDetails)) | 
| +    if (!parseHash(raw, hash, context, result)) | 
| return false; | 
|  | 
| params = adoptPtr(new blink::WebCryptoRsaHashedKeyGenParams(hash, modulusLength, static_cast<const unsigned char*>(publicExponent->baseAddress()), publicExponent->byteLength())); | 
| @@ -751,14 +771,14 @@ bool parseRsaHashedKeyGenParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAl | 
| //      CryptoOperationData counter; | 
| //      [EnforceRange] octet length; | 
| //    }; | 
| -bool parseAesCtrParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, String& errorDetails) | 
| +bool parseAesCtrParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, CryptoResult* result) | 
| { | 
| RefPtr<ArrayBufferView> counter; | 
| -    if (!getCryptoOperationData(raw, "counter", counter, context, errorDetails)) | 
| +    if (!getCryptoOperationData(raw, "counter", counter, context, result)) | 
| return false; | 
|  | 
| uint8_t length; | 
| -    if (!getUint8(raw, "length", length, context, errorDetails)) | 
| +    if (!getUint8(raw, "length", length, context, result)) | 
| return false; | 
|  | 
| params = adoptPtr(new blink::WebCryptoAesCtrParams(length, static_cast<const unsigned char*>(counter->baseAddress()), counter->byteLength())); | 
| @@ -772,20 +792,20 @@ bool parseAesCtrParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmPa | 
| //       CryptoOperationData? additionalData; | 
| //       [EnforceRange] octet? tagLength;  // May be 0-128 | 
| //     } | 
| -bool parseAesGcmParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, String& errorDetails) | 
| +bool parseAesGcmParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmParams>& params, const ErrorContext& context, CryptoResult* result) | 
| { | 
| RefPtr<ArrayBufferView> iv; | 
| -    if (!getCryptoOperationData(raw, "iv", iv, context, errorDetails)) | 
| +    if (!getCryptoOperationData(raw, "iv", iv, context, result)) | 
| return false; | 
|  | 
| bool hasAdditionalData; | 
| RefPtr<ArrayBufferView> additionalData; | 
| -    if (!getOptionalCryptoOperationData(raw, "additionalData", hasAdditionalData, additionalData, context, errorDetails)) | 
| +    if (!getOptionalCryptoOperationData(raw, "additionalData", hasAdditionalData, additionalData, context, result)) | 
| return false; | 
|  | 
| double tagLength; | 
| bool hasTagLength; | 
| -    if (!getOptionalInteger(raw, "tagLength", hasTagLength, tagLength, 0, 128, context, errorDetails)) | 
| +    if (!getOptionalInteger(raw, "tagLength", hasTagLength, tagLength, 0, 128, context, result)) | 
| return false; | 
|  | 
| const unsigned char* ivStart = static_cast<const unsigned char*>(iv->baseAddress()); | 
| @@ -798,38 +818,38 @@ bool parseAesGcmParams(const Dictionary& raw, OwnPtr<blink::WebCryptoAlgorithmPa | 
| return true; | 
| } | 
|  | 
| -bool parseAlgorithmParams(const Dictionary& raw, blink::WebCryptoAlgorithmParamsType type, OwnPtr<blink::WebCryptoAlgorithmParams>& params, ErrorContext& context, String& errorDetails) | 
| +bool parseAlgorithmParams(const Dictionary& raw, blink::WebCryptoAlgorithmParamsType type, OwnPtr<blink::WebCryptoAlgorithmParams>& params, ErrorContext& context, CryptoResult* result) | 
| { | 
| switch (type) { | 
| case blink::WebCryptoAlgorithmParamsTypeNone: | 
| return true; | 
| case blink::WebCryptoAlgorithmParamsTypeAesCbcParams: | 
| context.add("AesCbcParams"); | 
| -        return parseAesCbcParams(raw, params, context, errorDetails); | 
| +        return parseAesCbcParams(raw, params, context, result); | 
| case blink::WebCryptoAlgorithmParamsTypeAesKeyGenParams: | 
| context.add("AesKeyGenParams"); | 
| -        return parseAesKeyGenParams(raw, params, context, errorDetails); | 
| +        return parseAesKeyGenParams(raw, params, context, result); | 
| case blink::WebCryptoAlgorithmParamsTypeHmacImportParams: | 
| context.add("HmacImportParams"); | 
| -        return parseHmacImportParams(raw, params, context, errorDetails); | 
| +        return parseHmacImportParams(raw, params, context, result); | 
| case blink::WebCryptoAlgorithmParamsTypeHmacKeyGenParams: | 
| context.add("HmacKeyGenParams"); | 
| -        return parseHmacKeyGenParams(raw, params, context, errorDetails); | 
| +        return parseHmacKeyGenParams(raw, params, context, result); | 
| case blink::WebCryptoAlgorithmParamsTypeRsaHashedKeyGenParams: | 
| context.add("RsaHashedKeyGenParams"); | 
| -        return parseRsaHashedKeyGenParams(raw, params, context, errorDetails); | 
| +        return parseRsaHashedKeyGenParams(raw, params, context, result); | 
| case blink::WebCryptoAlgorithmParamsTypeRsaHashedImportParams: | 
| context.add("RsaHashedImportParams"); | 
| -        return parseRsaHashedImportParams(raw, params, context, errorDetails); | 
| +        return parseRsaHashedImportParams(raw, params, context, result); | 
| case blink::WebCryptoAlgorithmParamsTypeRsaKeyGenParams: | 
| context.add("RsaKeyGenParams"); | 
| -        return parseRsaKeyGenParams(raw, params, context, errorDetails); | 
| +        return parseRsaKeyGenParams(raw, params, context, result); | 
| case blink::WebCryptoAlgorithmParamsTypeAesCtrParams: | 
| context.add("AesCtrParams"); | 
| -        return parseAesCtrParams(raw, params, context, errorDetails); | 
| +        return parseAesCtrParams(raw, params, context, result); | 
| case blink::WebCryptoAlgorithmParamsTypeAesGcmParams: | 
| context.add("AesGcmParams"); | 
| -        return parseAesGcmParams(raw, params, context, errorDetails); | 
| +        return parseAesGcmParams(raw, params, context, result); | 
| case blink::WebCryptoAlgorithmParamsTypeRsaOaepParams: | 
| // TODO | 
| notImplemented(); | 
| @@ -839,39 +859,73 @@ bool parseAlgorithmParams(const Dictionary& raw, blink::WebCryptoAlgorithmParams | 
| return false; | 
| } | 
|  | 
| -bool parseAlgorithm(const Dictionary& raw, AlgorithmOperation op, blink::WebCryptoAlgorithm& algorithm, ErrorContext context, String& errorDetails) | 
| +const char* operationToString(AlgorithmOperation op) | 
| +{ | 
| +    switch (op) { | 
| +    case Encrypt: | 
| +        return "encrypt"; | 
| +    case Decrypt: | 
| +        return "decrypt"; | 
| +    case Sign: | 
| +        return "sign"; | 
| +    case Verify: | 
| +        return "verify"; | 
| +    case Digest: | 
| +        return "digest"; | 
| +    case GenerateKey: | 
| +        return "generateKey"; | 
| +    case ImportKey: | 
| +        return "importKey"; | 
| +    case DeriveKey: | 
| +        return "deriveKey"; | 
| +    case DeriveBits: | 
| +        return "deriveBits"; | 
| +    case WrapKey: | 
| +        return "wrapKey"; | 
| +    case UnwrapKey: | 
| +        return "unwrapKey"; | 
| +    } | 
| +    return 0; | 
| +} | 
| + | 
| +bool parseAlgorithm(const Dictionary& raw, AlgorithmOperation op, blink::WebCryptoAlgorithm& algorithm, ErrorContext context, CryptoResult* result) | 
| { | 
| context.add("Algorithm"); | 
|  | 
| if (!raw.isObject()) { | 
| -        errorDetails = context.toString("Not an object"); | 
| +        completeWithSyntaxError(context.toString("Not an object"), result); | 
| return false; | 
| } | 
|  | 
| String algorithmName; | 
| if (!raw.get("name", algorithmName)) { | 
| -        errorDetails = context.toString("name", "Missing or not a string"); | 
| +        completeWithSyntaxError(context.toString("name", "Missing or not a string"), result); | 
| return false; | 
| } | 
|  | 
| blink::WebCryptoAlgorithmId algorithmId; | 
| if (!lookupAlgorithmIdByName(algorithmName, algorithmId)) { | 
| -        errorDetails = context.toString("Unrecognized algorithm name"); | 
| +        // FIXME: The spec says to return a SyntaxError if the input contains | 
| +        //        any non-ASCII characters. | 
| +        completeWithNotSupportedError(context.toString("Unrecognized name"), result); | 
| return false; | 
| } | 
|  | 
| +    // Remove the "Algorithm:" prefix for all subsequent errors. | 
| +    context.removeLast(); | 
| + | 
| const AlgorithmInfo* algorithmInfo = lookupAlgorithmInfo(algorithmId); | 
| -    context.add(algorithmInfo->name); | 
|  | 
| if (algorithmInfo->operationToParamsType[op] == Undefined) { | 
| -        errorDetails = context.toString("Unsupported operation"); | 
| +        context.add(algorithmIdToName(algorithmId)); | 
| +        completeWithNotSupportedError(context.toString("Unsupported operation", operationToString(op)), result); | 
| return false; | 
| } | 
|  | 
| blink::WebCryptoAlgorithmParamsType paramsType = static_cast<blink::WebCryptoAlgorithmParamsType>(algorithmInfo->operationToParamsType[op]); | 
|  | 
| OwnPtr<blink::WebCryptoAlgorithmParams> params; | 
| -    if (!parseAlgorithmParams(raw, paramsType, params, context, errorDetails)) | 
| +    if (!parseAlgorithmParams(raw, paramsType, params, context, result)) | 
| return false; | 
|  | 
| algorithm = blink::WebCryptoAlgorithm(algorithmId, params.release()); | 
| @@ -882,12 +936,7 @@ bool parseAlgorithm(const Dictionary& raw, AlgorithmOperation op, blink::WebCryp | 
|  | 
| bool parseAlgorithm(const Dictionary& raw, AlgorithmOperation op, blink::WebCryptoAlgorithm& algorithm, CryptoResult* result) | 
| { | 
| -    String errorDetails; | 
| -    if (!parseAlgorithm(raw, op, algorithm, ErrorContext(), errorDetails)) { | 
| -        result->completeWithError(errorDetails); | 
| -        return false; | 
| -    } | 
| -    return true; | 
| +    return parseAlgorithm(raw, op, algorithm, ErrorContext(), result); | 
| } | 
|  | 
| const char* algorithmIdToName(blink::WebCryptoAlgorithmId id) | 
|  |