| Index: Source/modules/crypto/SubtleCrypto.cpp | 
| diff --git a/Source/modules/crypto/SubtleCrypto.cpp b/Source/modules/crypto/SubtleCrypto.cpp | 
| index f800a50d42a5ad1758a56abd58b0f2c98aa8ce5e..237569fa18a9a75aac46b96d8d8de2c264a442f5 100644 | 
| --- a/Source/modules/crypto/SubtleCrypto.cpp | 
| +++ b/Source/modules/crypto/SubtleCrypto.cpp | 
| @@ -31,26 +31,92 @@ | 
| #include "config.h" | 
| #include "modules/crypto/SubtleCrypto.h" | 
|  | 
| +#include "V8Key.h" // Must precede ScriptPromiseResolver.h | 
| #include "bindings/v8/ExceptionState.h" | 
| +#include "bindings/v8/custom/V8ArrayBufferCustom.h" // Must precede ScriptPromiseResolver.h | 
| +#include "bindings/v8/ScriptPromiseResolver.h" | 
| #include "core/dom/ExceptionCode.h" | 
| -#include "core/platform/NotImplemented.h" | 
| -#include "modules/crypto/CryptoOperation.h" | 
| #include "modules/crypto/Key.h" | 
| -#include "modules/crypto/KeyOperation.h" | 
| #include "modules/crypto/NormalizeAlgorithm.h" | 
| #include "public/platform/Platform.h" | 
| +#include "public/platform/WebArrayBuffer.h" | 
| #include "public/platform/WebCrypto.h" | 
| #include "public/platform/WebCryptoAlgorithmParams.h" | 
| #include "wtf/ArrayBufferView.h" | 
|  | 
| namespace WebCore { | 
|  | 
| -// FIXME: Outstanding KeyOperations and CryptoOperations should be aborted when | 
| -// tearing down SubtleCrypto (to avoid problems completing a | 
| -// ScriptPromiseResolver which is no longer valid). | 
| +// FIXME: asynchronous completion of CryptoResult. Need to re-enter the | 
| +//        v8::Context before trying to fulfill the promise, and enable test. | 
|  | 
| namespace { | 
|  | 
| +class CryptoResult : public WebKit::WebCryptoResultPrivate, public ThreadSafeRefCounted<CryptoResult> { | 
| +public: | 
| +    static PassRefPtr<CryptoResult> create() | 
| +    { | 
| +        return adoptRef(new CryptoResult); | 
| +    } | 
| + | 
| +    virtual void ref() OVERRIDE | 
| +    { | 
| +        ThreadSafeRefCounted<CryptoResult>::ref(); | 
| +    } | 
| + | 
| +    virtual void deref() OVERRIDE | 
| +    { | 
| +        ThreadSafeRefCounted<CryptoResult>::deref(); | 
| +    } | 
| + | 
| +    virtual void completeWithError() OVERRIDE | 
| +    { | 
| +        m_promiseResolver->reject(ScriptValue::createNull()); | 
| +        finish(); | 
| +    } | 
| + | 
| +    virtual void completeWithBuffer(const WebKit::WebArrayBuffer& buffer) OVERRIDE | 
| +    { | 
| +        m_promiseResolver->fulfill(PassRefPtr<ArrayBuffer>(buffer)); | 
| +        finish(); | 
| +    } | 
| + | 
| +    virtual void completeWithBoolean(bool b) OVERRIDE | 
| +    { | 
| +        m_promiseResolver->fulfill(ScriptValue::createBoolean(b)); | 
| +        finish(); | 
| +    } | 
| + | 
| +    virtual void completeWithKey(const WebKit::WebCryptoKey& key) OVERRIDE | 
| +    { | 
| +        m_promiseResolver->fulfill(Key::create(key)); | 
| +        finish(); | 
| +    } | 
| + | 
| +    WebKit::WebCryptoResult result() | 
| +    { | 
| +        return WebKit::WebCryptoResult(this); | 
| +    } | 
| + | 
| +    ScriptObject promise() | 
| +    { | 
| +        return m_promiseResolver->promise(); | 
| +    } | 
| + | 
| +private: | 
| +    CryptoResult() | 
| +        : m_promiseResolver(ScriptPromiseResolver::create()) | 
| +        , m_finished(false) { } | 
| + | 
| +    void finish() | 
| +    { | 
| +        ASSERT(!m_finished); | 
| +        m_finished = true; | 
| +    } | 
| + | 
| +    RefPtr<ScriptPromiseResolver> m_promiseResolver; | 
| +    bool m_finished; | 
| +}; | 
| + | 
| WebKit::WebCryptoKeyUsageMask toKeyUsage(AlgorithmOperation operation) | 
| { | 
| switch (operation) { | 
| @@ -101,64 +167,69 @@ bool keyCanBeUsedForAlgorithm(const WebKit::WebCryptoKey& key, const WebKit::Web | 
| return false; | 
| } | 
|  | 
| -PassRefPtr<CryptoOperation> createCryptoOperation(const Dictionary& rawAlgorithm, Key* key, AlgorithmOperation operationType, ArrayBufferView* signature, ExceptionState& es) | 
| +ScriptObject startCryptoOperation(const Dictionary& rawAlgorithm, Key* key, AlgorithmOperation operationType, ArrayBufferView* signature, ArrayBufferView* dataBuffer, ExceptionState& es) | 
| { | 
| WebKit::WebCrypto* platformCrypto = WebKit::Platform::current()->crypto(); | 
| if (!platformCrypto) { | 
| es.throwDOMException(NotSupportedError); | 
| -        return 0; | 
| +        return ScriptObject(); | 
| } | 
|  | 
| WebKit::WebCryptoAlgorithm algorithm; | 
| if (!normalizeAlgorithm(rawAlgorithm, operationType, algorithm, es)) | 
| -        return 0; | 
| +        return ScriptObject(); | 
|  | 
| // All operations other than Digest require a valid Key. | 
| if (operationType != Digest) { | 
| if (!key) { | 
| es.throwTypeError(); | 
| -            return 0; | 
| +            return ScriptObject(); | 
| } | 
|  | 
| if (!keyCanBeUsedForAlgorithm(key->key(), algorithm, operationType)) { | 
| es.throwDOMException(NotSupportedError); | 
| -            return 0; | 
| +            return ScriptObject(); | 
| } | 
| } | 
|  | 
| // Only Verify takes a signature. | 
| if (operationType == Verify && !signature) { | 
| es.throwTypeError(); | 
| -        return 0; | 
| +        return ScriptObject(); | 
| } | 
|  | 
| -    RefPtr<CryptoOperationImpl> opImpl = CryptoOperationImpl::create(); | 
| -    WebKit::WebCryptoOperationResult result(opImpl.get()); | 
| +    if (!dataBuffer) { | 
| +        es.throwTypeError(); | 
| +        return ScriptObject(); | 
| +    } | 
| + | 
| +    const unsigned char* data = static_cast<const unsigned char*>(dataBuffer->baseAddress()); | 
| +    size_t dataSize = dataBuffer->byteLength(); | 
| + | 
| +    RefPtr<CryptoResult> result = CryptoResult::create(); | 
|  | 
| switch (operationType) { | 
| case Encrypt: | 
| -        platformCrypto->encrypt(algorithm, key->key(), result); | 
| +        platformCrypto->encrypt(algorithm, key->key(), data, dataSize, result->result()); | 
| break; | 
| case Decrypt: | 
| -        platformCrypto->decrypt(algorithm, key->key(), result); | 
| +        platformCrypto->decrypt(algorithm, key->key(), data, dataSize, result->result()); | 
| break; | 
| case Sign: | 
| -        platformCrypto->sign(algorithm, key->key(), result); | 
| +        platformCrypto->sign(algorithm, key->key(), data, dataSize, result->result()); | 
| break; | 
| case Verify: | 
| -        platformCrypto->verifySignature(algorithm, key->key(), reinterpret_cast<const unsigned char*>(signature->baseAddress()), signature->byteLength(), result); | 
| +        platformCrypto->verifySignature(algorithm, key->key(), reinterpret_cast<const unsigned char*>(signature->baseAddress()), signature->byteLength(), data, dataSize, result->result()); | 
| break; | 
| case Digest: | 
| -        platformCrypto->digest(algorithm, result); | 
| +        platformCrypto->digest(algorithm, data, dataSize, result->result()); | 
| break; | 
| default: | 
| ASSERT_NOT_REACHED(); | 
| -        return 0; | 
| +        return ScriptObject(); | 
| } | 
|  | 
| -    if (opImpl->throwInitializationError(es)) | 
| -        return 0; | 
| -    return CryptoOperation::create(algorithm, opImpl.get()); | 
| +    return result->promise(); | 
| } | 
|  | 
| } // namespace | 
| @@ -168,29 +239,29 @@ SubtleCrypto::SubtleCrypto() | 
| ScriptWrappable::init(this); | 
| } | 
|  | 
| -PassRefPtr<CryptoOperation> SubtleCrypto::encrypt(const Dictionary& rawAlgorithm, Key* key, ExceptionState& es) | 
| +ScriptObject SubtleCrypto::encrypt(const Dictionary& rawAlgorithm, Key* key, ArrayBufferView* data, ExceptionState& es) | 
| { | 
| -    return createCryptoOperation(rawAlgorithm, key, Encrypt, 0, es); | 
| +    return startCryptoOperation(rawAlgorithm, key, Encrypt, 0, data, es); | 
| } | 
|  | 
| -PassRefPtr<CryptoOperation> SubtleCrypto::decrypt(const Dictionary& rawAlgorithm, Key* key, ExceptionState& es) | 
| +ScriptObject SubtleCrypto::decrypt(const Dictionary& rawAlgorithm, Key* key, ArrayBufferView* data, ExceptionState& es) | 
| { | 
| -    return createCryptoOperation(rawAlgorithm, key, Decrypt, 0, es); | 
| +    return startCryptoOperation(rawAlgorithm, key, Decrypt, 0, data, es); | 
| } | 
|  | 
| -PassRefPtr<CryptoOperation> SubtleCrypto::sign(const Dictionary& rawAlgorithm, Key* key, ExceptionState& es) | 
| +ScriptObject SubtleCrypto::sign(const Dictionary& rawAlgorithm, Key* key, ArrayBufferView* data, ExceptionState& es) | 
| { | 
| -    return createCryptoOperation(rawAlgorithm, key, Sign, 0, es); | 
| +    return startCryptoOperation(rawAlgorithm, key, Sign, 0, data, es); | 
| } | 
|  | 
| -PassRefPtr<CryptoOperation> SubtleCrypto::verifySignature(const Dictionary& rawAlgorithm, Key* key, ArrayBufferView* signature, ExceptionState& es) | 
| +ScriptObject SubtleCrypto::verifySignature(const Dictionary& rawAlgorithm, Key* key, ArrayBufferView* signature, ArrayBufferView* data, ExceptionState& es) | 
| { | 
| -    return createCryptoOperation(rawAlgorithm, key, Verify, signature, es); | 
| +    return startCryptoOperation(rawAlgorithm, key, Verify, signature, data, es); | 
| } | 
|  | 
| -PassRefPtr<CryptoOperation> SubtleCrypto::digest(const Dictionary& rawAlgorithm, ExceptionState& es) | 
| +ScriptObject SubtleCrypto::digest(const Dictionary& rawAlgorithm, ArrayBufferView* data, ExceptionState& es) | 
| { | 
| -    return createCryptoOperation(rawAlgorithm, 0, Digest, 0, es); | 
| +    return startCryptoOperation(rawAlgorithm, 0, Digest, 0, data, es); | 
| } | 
|  | 
| ScriptObject SubtleCrypto::generateKey(const Dictionary& rawAlgorithm, bool extractable, const Vector<String>& rawKeyUsages, ExceptionState& es) | 
| @@ -211,10 +282,9 @@ ScriptObject SubtleCrypto::generateKey(const Dictionary& rawAlgorithm, bool extr | 
| if (!normalizeAlgorithm(rawAlgorithm, GenerateKey, algorithm, es)) | 
| return ScriptObject(); | 
|  | 
| -    RefPtr<KeyOperation> keyOp = KeyOperation::create(); | 
| -    WebKit::WebCryptoKeyOperationResult result(keyOp.get()); | 
| -    platformCrypto->generateKey(algorithm, extractable, keyUsages, result); | 
| -    return keyOp->returnValue(es); | 
| +    RefPtr<CryptoResult> result = CryptoResult::create(); | 
| +    platformCrypto->generateKey(algorithm, extractable, keyUsages, result->result()); | 
| +    return result->promise(); | 
| } | 
|  | 
| ScriptObject SubtleCrypto::importKey(const String& rawFormat, ArrayBufferView* keyData, const Dictionary& rawAlgorithm, bool extractable, const Vector<String>& rawKeyUsages, ExceptionState& es) | 
| @@ -248,10 +318,9 @@ ScriptObject SubtleCrypto::importKey(const String& rawFormat, ArrayBufferView* k | 
|  | 
| const unsigned char* keyDataBytes = static_cast<unsigned char*>(keyData->baseAddress()); | 
|  | 
| -    RefPtr<KeyOperation> keyOp = KeyOperation::create(); | 
| -    WebKit::WebCryptoKeyOperationResult result(keyOp.get()); | 
| -    platformCrypto->importKey(format, keyDataBytes, keyData->byteLength(), algorithm, extractable, keyUsages, result); | 
| -    return keyOp->returnValue(es); | 
| +    RefPtr<CryptoResult> result = CryptoResult::create(); | 
| +    platformCrypto->importKey(format, keyDataBytes, keyData->byteLength(), algorithm, extractable, keyUsages, result->result()); | 
| +    return result->promise(); | 
| } | 
|  | 
| } // namespace WebCore | 
|  |