Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(188)

Unified Diff: Source/bindings/modules/v8/ScriptValueSerializerForModules.cpp

Issue 718383003: bindings: fixed incorrect dependency of SerializedScriptValue. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Added fast/js/structured-clone.html Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: Source/bindings/modules/v8/ScriptValueSerializerForModules.cpp
diff --git a/Source/bindings/modules/v8/ScriptValueSerializerForModules.cpp b/Source/bindings/modules/v8/ScriptValueSerializerForModules.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..ab913ed96eee2a2657899c63f2441762687db43c
--- /dev/null
+++ b/Source/bindings/modules/v8/ScriptValueSerializerForModules.cpp
@@ -0,0 +1,596 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "config.h"
+#include "bindings/modules/v8/ScriptValueSerializerForModules.h"
+
+#include "bindings/core/v8/SerializationTag.h"
+#include "bindings/core/v8/V8Binding.h"
+#include "bindings/modules/v8/V8CryptoKey.h"
+#include "bindings/modules/v8/V8DOMFileSystem.h"
+#include "modules/filesystem/DOMFileSystem.h"
+#include "public/platform/Platform.h"
+
+namespace blink {
+
+enum CryptoKeyAlgorithmTag {
+ AesCbcTag = 1,
+ HmacTag = 2,
+ RsaSsaPkcs1v1_5Tag = 3,
+ // ID 4 was used by RsaEs, while still behind experimental flag.
+ Sha1Tag = 5,
+ Sha256Tag = 6,
+ Sha384Tag = 7,
+ Sha512Tag = 8,
+ AesGcmTag = 9,
+ RsaOaepTag = 10,
+ AesCtrTag = 11,
+ AesKwTag = 12,
+ RsaPssTag = 13,
+ EcdsaTag = 14,
+ // Maximum allowed value is 2^32-1
+};
+
+enum NamedCurveTag {
+ P256Tag = 1,
+ P384Tag = 2,
+ P521Tag = 3,
+};
+
+enum CryptoKeyUsage {
+ // Extractability is not a "usage" in the WebCryptoKeyUsages sense, however
+ // it fits conveniently into this bitfield.
+ ExtractableUsage = 1 << 0,
+
+ EncryptUsage = 1 << 1,
+ DecryptUsage = 1 << 2,
+ SignUsage = 1 << 3,
+ VerifyUsage = 1 << 4,
+ DeriveKeyUsage = 1 << 5,
+ WrapKeyUsage = 1 << 6,
+ UnwrapKeyUsage = 1 << 7,
+ DeriveBitsUsage = 1 << 8,
+ // Maximum allowed value is 1 << 31
+};
+
+enum CryptoKeySubTag {
+ AesKeyTag = 1,
+ HmacKeyTag = 2,
+ // ID 3 was used by RsaKeyTag, while still behind experimental flag.
+ RsaHashedKeyTag = 4,
+ EcKeyTag = 5,
+ // Maximum allowed value is 255
+};
+
+enum AssymetricCryptoKeyType {
+ PublicKeyType = 1,
+ PrivateKeyType = 2,
+ // Maximum allowed value is 2^32-1
+};
+
+
+ScriptValueSerializerForModules::ScriptValueSerializerForModules(SerializedScriptValueWriter& writer, MessagePortArray* messagePorts, ArrayBufferArray* arrayBuffers, WebBlobInfoArray* blobInfo, BlobDataHandleMap& blobDataHandles, v8::TryCatch& tryCatch, ScriptState* scriptState)
+ : ScriptValueSerializer(writer, messagePorts, arrayBuffers, blobInfo, blobDataHandles, tryCatch, scriptState)
+{
+}
+
+ScriptValueSerializer::StateBase* ScriptValueSerializerForModules::writeDOMFileSystem(v8::Handle<v8::Value> value, ScriptValueSerializer::StateBase* next)
+{
+ DOMFileSystem* fs = V8DOMFileSystem::toImpl(value.As<v8::Object>());
+ if (!fs)
+ return 0;
+ if (!fs->clonable())
+ return handleError(DataCloneError, "A FileSystem object could not be cloned.", next);
+
+ toSerializedScriptValueWriterForModules(writer()).writeDOMFileSystem(fs->type(), fs->name(), fs->rootURL().string());
+ return 0;
+}
+
+bool ScriptValueSerializerForModules::writeCryptoKey(v8::Handle<v8::Value> value)
+{
+ CryptoKey* key = V8CryptoKey::toImpl(value.As<v8::Object>());
+ if (!key)
+ return false;
+ return toSerializedScriptValueWriterForModules(writer()).writeCryptoKey(key->key());
+}
+
+void SerializedScriptValueWriterForModules::writeDOMFileSystem(int type, const String& name, const String& url)
+{
+ append(DOMFileSystemTag);
+ doWriteUint32(type);
+ doWriteWebCoreString(name);
+ doWriteWebCoreString(url);
+}
+
+bool SerializedScriptValueWriterForModules::writeCryptoKey(const WebCryptoKey& key)
+{
+ append(static_cast<uint8_t>(CryptoKeyTag));
+
+ switch (key.algorithm().paramsType()) {
+ case WebCryptoKeyAlgorithmParamsTypeAes:
+ doWriteAesKey(key);
+ break;
+ case WebCryptoKeyAlgorithmParamsTypeHmac:
+ doWriteHmacKey(key);
+ break;
+ case WebCryptoKeyAlgorithmParamsTypeRsaHashed:
+ doWriteRsaHashedKey(key);
+ break;
+ case WebCryptoKeyAlgorithmParamsTypeEc:
+ doWriteEcKey(key);
+ break;
+ case WebCryptoKeyAlgorithmParamsTypeNone:
+ ASSERT_NOT_REACHED();
+ return false;
+ }
+
+ doWriteKeyUsages(key.usages(), key.extractable());
+
+ WebVector<uint8_t> keyData;
+ if (!Platform::current()->crypto()->serializeKeyForClone(key, keyData))
+ return false;
+
+ doWriteUint32(keyData.size());
+ append(keyData.data(), keyData.size());
+ return true;
+}
+
+void SerializedScriptValueWriterForModules::doWriteHmacKey(const WebCryptoKey& key)
+{
+ ASSERT(key.algorithm().paramsType() == WebCryptoKeyAlgorithmParamsTypeHmac);
+
+ append(static_cast<uint8_t>(HmacKeyTag));
+ ASSERT(!(key.algorithm().hmacParams()->lengthBits() % 8));
+ doWriteUint32(key.algorithm().hmacParams()->lengthBits() / 8);
+ doWriteAlgorithmId(key.algorithm().hmacParams()->hash().id());
+}
+
+void SerializedScriptValueWriterForModules::doWriteAesKey(const WebCryptoKey& key)
+{
+ ASSERT(key.algorithm().paramsType() == WebCryptoKeyAlgorithmParamsTypeAes);
+
+ append(static_cast<uint8_t>(AesKeyTag));
+ doWriteAlgorithmId(key.algorithm().id());
+ // Converting the key length from bits to bytes is lossless and makes
+ // it fit in 1 byte.
+ ASSERT(!(key.algorithm().aesParams()->lengthBits() % 8));
+ doWriteUint32(key.algorithm().aesParams()->lengthBits() / 8);
+}
+
+void SerializedScriptValueWriterForModules::doWriteRsaHashedKey(const WebCryptoKey& key)
+{
+ ASSERT(key.algorithm().rsaHashedParams());
+ append(static_cast<uint8_t>(RsaHashedKeyTag));
+
+ doWriteAlgorithmId(key.algorithm().id());
+ doWriteAsymmetricKeyType(key.type());
+
+ const WebCryptoRsaHashedKeyAlgorithmParams* params = key.algorithm().rsaHashedParams();
+ doWriteUint32(params->modulusLengthBits());
+ doWriteUint32(params->publicExponent().size());
+ append(params->publicExponent().data(), params->publicExponent().size());
+ doWriteAlgorithmId(params->hash().id());
+}
+
+void SerializedScriptValueWriterForModules::doWriteEcKey(const WebCryptoKey& key)
+{
+ ASSERT(key.algorithm().ecParams());
+ append(static_cast<uint8_t>(EcKeyTag));
+
+ doWriteAlgorithmId(key.algorithm().id());
+ doWriteAsymmetricKeyType(key.type());
+ doWriteNamedCurve(key.algorithm().ecParams()->namedCurve());
+}
+
+void SerializedScriptValueWriterForModules::doWriteAlgorithmId(WebCryptoAlgorithmId id)
+{
+ switch (id) {
+ case WebCryptoAlgorithmIdAesCbc:
+ return doWriteUint32(AesCbcTag);
+ case WebCryptoAlgorithmIdHmac:
+ return doWriteUint32(HmacTag);
+ case WebCryptoAlgorithmIdRsaSsaPkcs1v1_5:
+ return doWriteUint32(RsaSsaPkcs1v1_5Tag);
+ case WebCryptoAlgorithmIdSha1:
+ return doWriteUint32(Sha1Tag);
+ case WebCryptoAlgorithmIdSha256:
+ return doWriteUint32(Sha256Tag);
+ case WebCryptoAlgorithmIdSha384:
+ return doWriteUint32(Sha384Tag);
+ case WebCryptoAlgorithmIdSha512:
+ return doWriteUint32(Sha512Tag);
+ case WebCryptoAlgorithmIdAesGcm:
+ return doWriteUint32(AesGcmTag);
+ case WebCryptoAlgorithmIdRsaOaep:
+ return doWriteUint32(RsaOaepTag);
+ case WebCryptoAlgorithmIdAesCtr:
+ return doWriteUint32(AesCtrTag);
+ case WebCryptoAlgorithmIdAesKw:
+ return doWriteUint32(AesKwTag);
+ case WebCryptoAlgorithmIdRsaPss:
+ return doWriteUint32(RsaPssTag);
+ case WebCryptoAlgorithmIdEcdsa:
+ return doWriteUint32(EcdsaTag);
+ }
+ ASSERT_NOT_REACHED();
+}
+
+void SerializedScriptValueWriterForModules::doWriteAsymmetricKeyType(WebCryptoKeyType keyType)
+{
+ switch (keyType) {
+ case WebCryptoKeyTypePublic:
+ doWriteUint32(PublicKeyType);
+ break;
+ case WebCryptoKeyTypePrivate:
+ doWriteUint32(PrivateKeyType);
+ break;
+ case WebCryptoKeyTypeSecret:
+ ASSERT_NOT_REACHED();
+ }
+}
+
+void SerializedScriptValueWriterForModules::doWriteNamedCurve(WebCryptoNamedCurve namedCurve)
+{
+ switch (namedCurve) {
+ case WebCryptoNamedCurveP256:
+ return doWriteUint32(P256Tag);
+ case WebCryptoNamedCurveP384:
+ return doWriteUint32(P384Tag);
+ case WebCryptoNamedCurveP521:
+ return doWriteUint32(P521Tag);
+ }
+ ASSERT_NOT_REACHED();
+}
+
+void SerializedScriptValueWriterForModules::doWriteKeyUsages(const WebCryptoKeyUsageMask usages, bool extractable)
+{
+ // Reminder to update this when adding new key usages.
+ COMPILE_ASSERT(EndOfWebCryptoKeyUsage == (1 << 7) + 1, UpdateMe);
+
+ uint32_t value = 0;
+
+ if (extractable)
+ value |= ExtractableUsage;
+
+ if (usages & WebCryptoKeyUsageEncrypt)
+ value |= EncryptUsage;
+ if (usages & WebCryptoKeyUsageDecrypt)
+ value |= DecryptUsage;
+ if (usages & WebCryptoKeyUsageSign)
+ value |= SignUsage;
+ if (usages & WebCryptoKeyUsageVerify)
+ value |= VerifyUsage;
+ if (usages & WebCryptoKeyUsageDeriveKey)
+ value |= DeriveKeyUsage;
+ if (usages & WebCryptoKeyUsageWrapKey)
+ value |= WrapKeyUsage;
+ if (usages & WebCryptoKeyUsageUnwrapKey)
+ value |= UnwrapKeyUsage;
+ if (usages & WebCryptoKeyUsageDeriveBits)
+ value |= DeriveBitsUsage;
+
+ doWriteUint32(value);
+}
+
+ScriptValueSerializer::StateBase* ScriptValueSerializerForModules::doSerializeValue(v8::Handle<v8::Value> value, ScriptValueSerializer::StateBase* next)
+{
+ bool isDOMFileSystem = V8DOMFileSystem::hasInstance(value, isolate());
+ if (isDOMFileSystem || V8CryptoKey::hasInstance(value, isolate())) {
+ v8::Handle<v8::Object> jsObject = value.As<v8::Object>();
+ if (jsObject.IsEmpty())
+ return handleError(DataCloneError, "An object could not be cloned.", next);
+ greyObject(jsObject);
+
+ if (isDOMFileSystem)
+ return writeDOMFileSystem(value, next);
+
+ if (!writeCryptoKey(value))
+ return handleError(DataCloneError, "Couldn't serialize key data", next);
+ return 0;
+ }
+ return ScriptValueSerializer::doSerializeValue(value, next);
+}
+
+bool SerializedScriptValueReaderForModules::read(v8::Handle<v8::Value>* value, ScriptValueCompositeCreator& creator)
+{
+ SerializationTag tag;
+ if (!readTag(&tag))
+ return false;
+ switch (tag) {
+ case DOMFileSystemTag:
+ if (!readDOMFileSystem(value))
+ return false;
+ creator.pushObjectReference(*value);
+ break;
+ case CryptoKeyTag:
+ if (!readCryptoKey(value))
+ return false;
+ creator.pushObjectReference(*value);
+ break;
+ default:
+ return SerializedScriptValueReader::readWithTag(tag, value, creator);
+ }
+ return !value->IsEmpty();
+}
+
+bool SerializedScriptValueReaderForModules::readDOMFileSystem(v8::Handle<v8::Value>* value)
+{
+ uint32_t type;
+ String name;
+ String url;
+ if (!doReadUint32(&type))
+ return false;
+ if (!readWebCoreString(&name))
+ return false;
+ if (!readWebCoreString(&url))
+ return false;
+ DOMFileSystem* fs = DOMFileSystem::create(scriptState()->executionContext(), name, static_cast<FileSystemType>(type), KURL(ParsedURLString, url));
+ *value = toV8(fs, scriptState()->context()->Global(), isolate());
+ return true;
+}
+
+bool SerializedScriptValueReaderForModules::readCryptoKey(v8::Handle<v8::Value>* value)
+{
+ uint32_t rawKeyType;
+ if (!doReadUint32(&rawKeyType))
+ return false;
+
+ WebCryptoKeyAlgorithm algorithm;
+ WebCryptoKeyType type = WebCryptoKeyTypeSecret;
+
+ switch (static_cast<CryptoKeySubTag>(rawKeyType)) {
+ case AesKeyTag:
+ if (!doReadAesKey(algorithm, type))
+ return false;
+ break;
+ case HmacKeyTag:
+ if (!doReadHmacKey(algorithm, type))
+ return false;
+ break;
+ case RsaHashedKeyTag:
+ if (!doReadRsaHashedKey(algorithm, type))
+ return false;
+ break;
+ case EcKeyTag:
+ if (!doReadEcKey(algorithm, type))
+ return false;
+ break;
+ default:
+ return false;
+ }
+
+ WebCryptoKeyUsageMask usages;
+ bool extractable;
+ if (!doReadKeyUsages(usages, extractable))
+ return false;
+
+ uint32_t keyDataLength;
+ if (!doReadUint32(&keyDataLength))
+ return false;
+
+ if (position() + keyDataLength > length())
+ return false;
+
+ const uint8_t* keyData = allocate(keyDataLength);
+ WebCryptoKey key = WebCryptoKey::createNull();
+ if (!Platform::current()->crypto()->deserializeKeyForClone(
+ algorithm, type, extractable, usages, keyData, keyDataLength, key)) {
+ return false;
+ }
+
+ *value = toV8(CryptoKey::create(key), scriptState()->context()->Global(), isolate());
+ return true;
+}
+
+bool SerializedScriptValueReaderForModules::doReadHmacKey(WebCryptoKeyAlgorithm& algorithm, WebCryptoKeyType& type)
+{
+ uint32_t lengthBytes;
+ if (!doReadUint32(&lengthBytes))
+ return false;
+ WebCryptoAlgorithmId hash;
+ if (!doReadAlgorithmId(hash))
+ return false;
+ algorithm = WebCryptoKeyAlgorithm::createHmac(hash, lengthBytes * 8);
+ type = WebCryptoKeyTypeSecret;
+ return !algorithm.isNull();
+}
+
+bool SerializedScriptValueReaderForModules::doReadAesKey(WebCryptoKeyAlgorithm& algorithm, WebCryptoKeyType& type)
+{
+ WebCryptoAlgorithmId id;
+ if (!doReadAlgorithmId(id))
+ return false;
+ uint32_t lengthBytes;
+ if (!doReadUint32(&lengthBytes))
+ return false;
+ algorithm = WebCryptoKeyAlgorithm::createAes(id, lengthBytes * 8);
+ type = WebCryptoKeyTypeSecret;
+ return !algorithm.isNull();
+}
+
+bool SerializedScriptValueReaderForModules::doReadRsaHashedKey(WebCryptoKeyAlgorithm& algorithm, WebCryptoKeyType& type)
+{
+ WebCryptoAlgorithmId id;
+ if (!doReadAlgorithmId(id))
+ return false;
+
+ if (!doReadAsymmetricKeyType(type))
+ return false;
+
+ uint32_t modulusLengthBits;
+ if (!doReadUint32(&modulusLengthBits))
+ return false;
+
+ uint32_t publicExponentSize;
+ if (!doReadUint32(&publicExponentSize))
+ return false;
+
+ if (position() + publicExponentSize > length())
+ return false;
+
+ const uint8_t* publicExponent = allocate(publicExponentSize);
+ WebCryptoAlgorithmId hash;
+ if (!doReadAlgorithmId(hash))
+ return false;
+ algorithm = WebCryptoKeyAlgorithm::createRsaHashed(id, modulusLengthBits, publicExponent, publicExponentSize, hash);
+
+ return !algorithm.isNull();
+}
+
+bool SerializedScriptValueReaderForModules::doReadEcKey(WebCryptoKeyAlgorithm& algorithm, WebCryptoKeyType& type)
+{
+ WebCryptoAlgorithmId id;
+ if (!doReadAlgorithmId(id))
+ return false;
+
+ if (!doReadAsymmetricKeyType(type))
+ return false;
+
+ WebCryptoNamedCurve namedCurve;
+ if (!doReadNamedCurve(namedCurve))
+ return false;
+
+ algorithm = WebCryptoKeyAlgorithm::createEc(id, namedCurve);
+ return !algorithm.isNull();
+}
+
+bool SerializedScriptValueReaderForModules::doReadAlgorithmId(WebCryptoAlgorithmId& id)
+{
+ uint32_t rawId;
+ if (!doReadUint32(&rawId))
+ return false;
+
+ switch (static_cast<CryptoKeyAlgorithmTag>(rawId)) {
+ case AesCbcTag:
+ id = WebCryptoAlgorithmIdAesCbc;
+ return true;
+ case HmacTag:
+ id = WebCryptoAlgorithmIdHmac;
+ return true;
+ case RsaSsaPkcs1v1_5Tag:
+ id = WebCryptoAlgorithmIdRsaSsaPkcs1v1_5;
+ return true;
+ case Sha1Tag:
+ id = WebCryptoAlgorithmIdSha1;
+ return true;
+ case Sha256Tag:
+ id = WebCryptoAlgorithmIdSha256;
+ return true;
+ case Sha384Tag:
+ id = WebCryptoAlgorithmIdSha384;
+ return true;
+ case Sha512Tag:
+ id = WebCryptoAlgorithmIdSha512;
+ return true;
+ case AesGcmTag:
+ id = WebCryptoAlgorithmIdAesGcm;
+ return true;
+ case RsaOaepTag:
+ id = WebCryptoAlgorithmIdRsaOaep;
+ return true;
+ case AesCtrTag:
+ id = WebCryptoAlgorithmIdAesCtr;
+ return true;
+ case AesKwTag:
+ id = WebCryptoAlgorithmIdAesKw;
+ return true;
+ case RsaPssTag:
+ id = WebCryptoAlgorithmIdRsaPss;
+ return true;
+ case EcdsaTag:
+ id = WebCryptoAlgorithmIdEcdsa;
+ return true;
+ }
+
+ return false;
+}
+
+bool SerializedScriptValueReaderForModules::doReadAsymmetricKeyType(WebCryptoKeyType& type)
+{
+ uint32_t rawType;
+ if (!doReadUint32(&rawType))
+ return false;
+
+ switch (static_cast<AssymetricCryptoKeyType>(rawType)) {
+ case PublicKeyType:
+ type = WebCryptoKeyTypePublic;
+ return true;
+ case PrivateKeyType:
+ type = WebCryptoKeyTypePrivate;
+ return true;
+ }
+
+ return false;
+}
+
+bool SerializedScriptValueReaderForModules::doReadNamedCurve(WebCryptoNamedCurve& namedCurve)
+{
+ uint32_t rawName;
+ if (!doReadUint32(&rawName))
+ return false;
+
+ switch (static_cast<NamedCurveTag>(rawName)) {
+ case P256Tag:
+ namedCurve = WebCryptoNamedCurveP256;
+ return true;
+ case P384Tag:
+ namedCurve = WebCryptoNamedCurveP384;
+ return true;
+ case P521Tag:
+ namedCurve = WebCryptoNamedCurveP521;
+ return true;
+ }
+
+ return false;
+}
+
+bool SerializedScriptValueReaderForModules::doReadKeyUsages(WebCryptoKeyUsageMask& usages, bool& extractable)
+{
+ // Reminder to update this when adding new key usages.
+ COMPILE_ASSERT(EndOfWebCryptoKeyUsage == (1 << 7) + 1, UpdateMe);
+ const uint32_t allPossibleUsages = ExtractableUsage | EncryptUsage | DecryptUsage | SignUsage | VerifyUsage | DeriveKeyUsage | WrapKeyUsage | UnwrapKeyUsage | DeriveBitsUsage;
+
+ uint32_t rawUsages;
+ if (!doReadUint32(&rawUsages))
+ return false;
+
+ // Make sure it doesn't contain an unrecognized usage value.
+ if (rawUsages & ~allPossibleUsages)
+ return false;
+
+ usages = 0;
+
+ extractable = rawUsages & ExtractableUsage;
+
+ if (rawUsages & EncryptUsage)
+ usages |= WebCryptoKeyUsageEncrypt;
+ if (rawUsages & DecryptUsage)
+ usages |= WebCryptoKeyUsageDecrypt;
+ if (rawUsages & SignUsage)
+ usages |= WebCryptoKeyUsageSign;
+ if (rawUsages & VerifyUsage)
+ usages |= WebCryptoKeyUsageVerify;
+ if (rawUsages & DeriveKeyUsage)
+ usages |= WebCryptoKeyUsageDeriveKey;
+ if (rawUsages & WrapKeyUsage)
+ usages |= WebCryptoKeyUsageWrapKey;
+ if (rawUsages & UnwrapKeyUsage)
+ usages |= WebCryptoKeyUsageUnwrapKey;
+ if (rawUsages & DeriveBitsUsage)
+ usages |= WebCryptoKeyUsageDeriveBits;
+
+ return true;
+}
+
+ScriptValueDeserializerForModules::ScriptValueDeserializerForModules(SerializedScriptValueReaderForModules& reader, MessagePortArray* messagePorts, ArrayBufferContentsArray* arrayBufferContents)
+ : ScriptValueDeserializer(reader, messagePorts, arrayBufferContents)
+{
+}
+
+bool ScriptValueDeserializerForModules::read(v8::Local<v8::Value>* value)
+{
+ return toSerializedScriptValueReaderForModules(reader()).read(value, *this);
+}
+
+} // namespace blink

Powered by Google App Engine
This is Rietveld 408576698