| Index: Source/modules/crypto/SubtleCrypto.cpp
|
| diff --git a/Source/modules/crypto/SubtleCrypto.cpp b/Source/modules/crypto/SubtleCrypto.cpp
|
| index e0e75ccb25244f1a819295c82288f3ccc6ddaa04..e567a443bb6dc91afd7c32eaf7a6e5a39b751cf5 100644
|
| --- a/Source/modules/crypto/SubtleCrypto.cpp
|
| +++ b/Source/modules/crypto/SubtleCrypto.cpp
|
| @@ -31,12 +31,16 @@
|
| #include "config.h"
|
| #include "modules/crypto/SubtleCrypto.h"
|
|
|
| +#include "V8Key.h" // NOTE: This must appear before ScriptPromiseResolver to define toV8()
|
| +#include "bindings/v8/ScriptPromiseResolver.h"
|
| #include "core/dom/ExceptionCode.h"
|
| #include "modules/crypto/CryptoOperation.h"
|
| +#include "modules/crypto/Key.h"
|
| #include "modules/crypto/NormalizeAlgorithm.h"
|
| #include "public/platform/Platform.h"
|
| #include "public/platform/WebArrayBuffer.h" // FIXME: temporary
|
| #include "public/platform/WebCrypto.h"
|
| +#include "public/platform/WebCryptoAlgorithmParams.h"
|
| #include "wtf/ArrayBuffer.h"
|
| #include "wtf/ArrayBufferView.h"
|
| #include "wtf/SHA1.h" // FIXME: temporary
|
| @@ -113,6 +117,25 @@ public:
|
| result->initializationSucceded(new DummyOperation(result));
|
| }
|
| }
|
| +
|
| + virtual void importKey(WebKit::WebCryptoKeyFormat, const unsigned char* keyData, size_t keyDataSize, const WebKit::WebCryptoAlgorithm& algorithm, bool extractable, WebKit::WebCryptoKeyUsageMask usages, WebKit::WebCryptoKeyOperationResult* result)
|
| + {
|
| + String keyDataString(keyData, keyDataSize);
|
| +
|
| + WebKit::WebCryptoKeyType type;
|
| + if (keyDataString == "reject") {
|
| + result->completeWithError();
|
| + } else if (keyDataString == "throw") {
|
| + result->initializationFailed();
|
| + } else {
|
| + if (keyDataString == "public") {
|
| + type = WebKit::WebCryptoKeyTypePublic;
|
| + } else if (keyDataString == "private") {
|
| + type = WebKit::WebCryptoKeyTypePrivate;
|
| + }
|
| + result->completeWithKey(WebKit::WebCryptoKey::create(0, type, extractable, algorithm, usages));
|
| + }
|
| + }
|
| };
|
|
|
| WebKit::WebCrypto* mockPlatformCrypto()
|
| @@ -132,6 +155,102 @@ PassRefPtr<CryptoOperation> doDummyOperation(const Dictionary& rawAlgorithm, Alg
|
| return op.release();
|
| }
|
| //------------------------------------------------------------------------------
|
| +//
|
| +//
|
| +class KeyOperation : public WebKit::WebCryptoKeyOperationResult {
|
| +public:
|
| + KeyOperation(ScriptPromiseResolver* resolver, ExceptionCode* ec)
|
| + : m_state(Initializing)
|
| + , m_impl(0)
|
| + , m_promiseResolver(resolver)
|
| + , m_exceptionCode(ec)
|
| + {
|
| + }
|
| +
|
| + ~KeyOperation();
|
| +
|
| + // Implementation of WebKit::WebCryptoKeyOperationResult.
|
| + virtual void initializationFailed() OVERRIDE;
|
| + virtual void initializationSucceeded(WebKit::WebCryptoKeyOperation*) OVERRIDE;
|
| + virtual void completeWithError() OVERRIDE;
|
| + virtual void completeWithKey(const WebKit::WebCryptoKey&) OVERRIDE;
|
| +
|
| +private:
|
| + enum State {
|
| + Initializing,
|
| + InProgress,
|
| + Done,
|
| + };
|
| +
|
| + State m_state;
|
| + WebKit::WebCryptoKeyOperation* m_impl;
|
| + ExceptionCode* m_exceptionCode;
|
| + RefPtr<ScriptPromiseResolver> m_promiseResolver;
|
| +};
|
| +
|
| +KeyOperation::~KeyOperation()
|
| +{
|
| + // Abort any inprogress operation.
|
| + switch (m_state) {
|
| + case Initializing:
|
| + ASSERT_NOT_REACHED();
|
| + break;
|
| + case InProgress:
|
| + // This will cause m_impl to be deleted.
|
| + m_state = Done;
|
| + m_impl->abort();
|
| + m_impl = 0;
|
| + case Done:
|
| + ASSERT(!m_impl);
|
| + break;
|
| + }
|
| +}
|
| +
|
| +void KeyOperation::initializationFailed()
|
| +{
|
| + ASSERT(m_state == Initializing);
|
| +
|
| + *m_exceptionCode = NotSupportedError;
|
| +
|
| + m_exceptionCode = 0;
|
| + m_state = Done;
|
| + delete this;
|
| +}
|
| +
|
| +void KeyOperation::initializationSucceeded(WebKit::WebCryptoKeyOperation* operationImpl)
|
| +{
|
| + ASSERT(m_state == Initializing);
|
| + ASSERT(operationImpl);
|
| + ASSERT(!m_impl);
|
| +
|
| + m_exceptionCode = 0;
|
| + m_impl = operationImpl;
|
| + m_state = InProgress;
|
| +}
|
| +
|
| +void KeyOperation::completeWithError()
|
| +{
|
| + ASSERT(m_state == Initializing || m_state == InProgress);
|
| +
|
| + m_exceptionCode = 0;
|
| + m_impl = 0;
|
| + m_state = Done;
|
| +
|
| + m_promiseResolver->reject(ScriptValue::createNull());
|
| + delete this;
|
| +}
|
| +
|
| +void KeyOperation::completeWithKey(const WebKit::WebCryptoKey& key)
|
| +{
|
| + ASSERT(m_state == Initializing || m_state == InProgress);
|
| +
|
| + m_exceptionCode = 0;
|
| + m_impl = 0;
|
| + m_state = Done;
|
| +
|
| + m_promiseResolver->fulfill(Key::create(key));
|
| + delete this;
|
| +}
|
|
|
| } // namespace
|
|
|
| @@ -177,4 +296,45 @@ PassRefPtr<CryptoOperation> SubtleCrypto::digest(const Dictionary& rawAlgorithm,
|
| return op.release();
|
| }
|
|
|
| +ScriptObject SubtleCrypto::importKey(const String& rawFormat, ArrayBufferView* keyData, const Dictionary& rawAlgorithm, bool extractable, const Vector<String>& rawKeyUsages, ExceptionCode& ec)
|
| +{
|
| + WebKit::WebCrypto* platformCrypto = mockPlatformCrypto();
|
| + if (!platformCrypto) {
|
| + ec = NotSupportedError;
|
| + return ScriptObject();
|
| + }
|
| +
|
| + WebKit::WebCryptoKeyUsageMask keyUsages;
|
| + if (!Key::parseUsageMask(rawKeyUsages, keyUsages)) {
|
| + ec = TypeError;
|
| + return ScriptObject();
|
| + }
|
| +
|
| + WebKit::WebCryptoKeyFormat format;
|
| + if (!Key::parseFormat(rawFormat, format)) {
|
| + ec = TypeError;
|
| + return ScriptObject();
|
| + }
|
| +
|
| + WebKit::WebCryptoAlgorithm algorithm;
|
| + if (!normalizeAlgorithmForImportKey(rawAlgorithm, algorithm, ec))
|
| + return ScriptObject();
|
| +
|
| + const unsigned char* keyDataBytes = static_cast<unsigned char*>(keyData->baseAddress());
|
| +
|
| + RefPtr<ScriptPromiseResolver> promiseResolver = ScriptPromiseResolver::create();
|
| +
|
| + // The |op| object is deleted upon completion of the underlying operation
|
| + // (i.e. when platformCrypto->importKey() notifies completion).
|
| + //
|
| + // FIXME: KeyOperation is never aborted. It should probably be aborted when
|
| + // the SubtleCrypto object that started it gets deleted. The concern being
|
| + // if the operation eventually does complete, the ScriptPromiseResolver
|
| + // might no longer be valid because the context it belonged to got torn
|
| + // down.
|
| + KeyOperation* op = new KeyOperation(promiseResolver.get(), &ec);
|
| + platformCrypto->importKey(format, keyDataBytes, keyData->byteLength(), algorithm, extractable, keyUsages, op);
|
| + return promiseResolver->promise();
|
| +}
|
| +
|
| } // namespace WebCore
|
|
|