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 |