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 |