Bug 1350254 part 8. Switch CryptoKey to [Serializable]. r=baku
authorBoris Zbarsky <bzbarsky@mit.edu>
Tue, 25 Jun 2019 06:48:41 +0000
changeset 543286 e02c73e7bd4bed108e60527f81fb8af00e361bb6
parent 543285 e6329e158fc17f21654867b588c768d8d7190381
child 543287 954a6de2b937021d511687a7d40d52910f82e3f4
push id2131
push userffxbld-merge
push dateMon, 26 Aug 2019 18:30:20 +0000
treeherdermozilla-release@b19ffb3ca153 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbaku
bugs1350254
milestone69.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1350254 part 8. Switch CryptoKey to [Serializable]. r=baku The spec doesn't say to do this, but I think we should. See https://github.com/w3c/webcrypto/issues/222 Differential Revision: https://phabricator.services.mozilla.com/D35722
dom/base/StructuredCloneHolder.cpp
dom/base/StructuredCloneTags.h
dom/crypto/CryptoKey.cpp
dom/crypto/CryptoKey.h
dom/webidl/SubtleCrypto.webidl
--- a/dom/base/StructuredCloneHolder.cpp
+++ b/dom/base/StructuredCloneHolder.cpp
@@ -5,17 +5,16 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "StructuredCloneHolder.h"
 
 #include "ImageContainer.h"
 #include "mozilla/AutoRestore.h"
 #include "mozilla/dom/BindingUtils.h"
 #include "mozilla/dom/BlobBinding.h"
-#include "mozilla/dom/CryptoKey.h"
 #include "mozilla/dom/StructuredCloneBlob.h"
 #include "mozilla/dom/Directory.h"
 #include "mozilla/dom/DirectoryBinding.h"
 #include "mozilla/dom/File.h"
 #include "mozilla/dom/FileList.h"
 #include "mozilla/dom/FileListBinding.h"
 #include "mozilla/dom/FormData.h"
 #include "mozilla/dom/ImageBitmap.h"
@@ -23,21 +22,19 @@
 #include "mozilla/dom/MessagePort.h"
 #include "mozilla/dom/MessagePortBinding.h"
 #include "mozilla/dom/OffscreenCanvas.h"
 #include "mozilla/dom/OffscreenCanvasBinding.h"
 #include "mozilla/dom/PMessagePort.h"
 #include "mozilla/dom/StructuredCloneTags.h"
 #include "mozilla/dom/StructuredCloneTester.h"
 #include "mozilla/dom/StructuredCloneTesterBinding.h"
-#include "mozilla/dom/SubtleCryptoBinding.h"
 #include "mozilla/dom/ToJSValue.h"
 #include "mozilla/dom/URLSearchParams.h"
 #include "mozilla/dom/URLSearchParamsBinding.h"
-#include "mozilla/dom/WebCryptoCommon.h"
 #include "mozilla/dom/WebIDLSerializable.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/ipc/BackgroundChild.h"
 #include "mozilla/ipc/BackgroundUtils.h"
 #include "mozilla/ipc/PBackgroundSharedTypes.h"
 #include "MultipartBlobImpl.h"
 #include "nsQueryObject.h"
 
@@ -118,17 +115,17 @@ bool StructuredCloneCallbacksCanTransfer
 void StructuredCloneCallbacksError(JSContext* aCx, uint32_t aErrorId) {
   NS_WARNING("Failed to clone data.");
 }
 
 void AssertTagValues() {
   static_assert(SCTAG_DOM_IMAGEDATA == 0xffff8007 &&
                     SCTAG_DOM_DOMPOINT == 0xffff8008 &&
                     SCTAG_DOM_DOMPOINTREADONLY == 0xffff8009 &&
-                    SCTAG_DOM_WEBCRYPTO_KEY == 0xffff800a &&
+                    SCTAG_DOM_CRYPTOKEY == 0xffff800a &&
                     SCTAG_DOM_NULL_PRINCIPAL == 0xffff800b &&
                     SCTAG_DOM_SYSTEM_PRINCIPAL == 0xffff800c &&
                     SCTAG_DOM_CONTENT_PRINCIPAL == 0xffff800d &&
                     SCTAG_DOM_DOMQUAD == 0xffff800e &&
                     SCTAG_DOM_RTC_CERTIFICATE == 0xffff800f &&
                     SCTAG_DOM_DOMRECT == 0xffff8010 &&
                     SCTAG_DOM_DOMRECTREADONLY == 0xffff8011 &&
                     SCTAG_DOM_EXPANDED_PRINCIPAL == 0xffff8012 &&
@@ -346,28 +343,21 @@ JSObject* StructuredCloneHolder::ReadFul
   }
 
   WebIDLDeserializer deserializer =
       LookupDeserializer(StructuredCloneTags(aTag));
   if (deserializer) {
     return deserializer(aCx, global, aReader);
   }
 
-  if (aTag == SCTAG_DOM_WEBCRYPTO_KEY || aTag == SCTAG_DOM_URLSEARCHPARAMS) {
+  if (aTag == SCTAG_DOM_URLSEARCHPARAMS) {
     // Prevent the return value from being trashed by a GC during ~nsRefPtr.
     JS::Rooted<JSObject*> result(aCx);
     {
-      if (aTag == SCTAG_DOM_WEBCRYPTO_KEY) {
-        RefPtr<CryptoKey> key = new CryptoKey(global);
-        if (!key->ReadStructuredClone(aReader)) {
-          result = nullptr;
-        } else {
-          result = key->WrapObject(aCx, nullptr);
-        }
-      } else if (aTag == SCTAG_DOM_URLSEARCHPARAMS) {
+      if (aTag == SCTAG_DOM_URLSEARCHPARAMS) {
         RefPtr<URLSearchParams> usp = new URLSearchParams(global);
         if (!usp->ReadStructuredClone(aReader)) {
           result = nullptr;
         } else {
           result = usp->WrapObject(aCx, nullptr);
         }
       }
     }
@@ -454,25 +444,16 @@ bool StructuredCloneHolder::WriteFullySe
   {
     URLSearchParams* usp = nullptr;
     if (NS_SUCCEEDED(UNWRAP_OBJECT(URLSearchParams, &obj, usp))) {
       return JS_WriteUint32Pair(aWriter, SCTAG_DOM_URLSEARCHPARAMS, 0) &&
              usp->WriteStructuredClone(aWriter);
     }
   }
 
-  // Handle Key cloning
-  {
-    CryptoKey* key = nullptr;
-    if (NS_SUCCEEDED(UNWRAP_OBJECT(CryptoKey, &obj, key))) {
-      return JS_WriteUint32Pair(aWriter, SCTAG_DOM_WEBCRYPTO_KEY, 0) &&
-             key->WriteStructuredClone(aWriter);
-    }
-  }
-
 #ifdef MOZ_WEBRTC
   {
     // Handle WebRTC Certificate cloning
     RTCCertificate* cert = nullptr;
     if (NS_SUCCEEDED(UNWRAP_OBJECT(RTCCertificate, &obj, cert))) {
       MOZ_ASSERT(NS_IsMainThread());
       return JS_WriteUint32Pair(aWriter, SCTAG_DOM_RTC_CERTIFICATE, 0) &&
              cert->WriteStructuredClone(aWriter);
--- a/dom/base/StructuredCloneTags.h
+++ b/dom/base/StructuredCloneTags.h
@@ -46,17 +46,17 @@ enum StructuredCloneTags {
   SCTAG_DOM_IMAGEDATA,
 
   SCTAG_DOM_DOMPOINT,
   SCTAG_DOM_DOMPOINTREADONLY,
 
   // IMPORTANT: Don't change the order of these enum values. You could break
   // IDB.
   // This tag is for WebCrypto keys
-  SCTAG_DOM_WEBCRYPTO_KEY,
+  SCTAG_DOM_CRYPTOKEY,
 
   // IMPORTANT: Don't change the order of these enum values. You could break
   // IDB.
   SCTAG_DOM_NULL_PRINCIPAL,
   // IMPORTANT: Don't change the order of these enum values. You could break
   // IDB.
   SCTAG_DOM_SYSTEM_PRINCIPAL,
   // IMPORTANT: Don't change the order of these enum values. You could break
--- a/dom/crypto/CryptoKey.cpp
+++ b/dom/crypto/CryptoKey.cpp
@@ -1133,17 +1133,18 @@ bool CryptoKey::PublicKeyValid(SECKEYPub
   if (id == CK_INVALID_HANDLE) {
     return false;
   }
 
   SECStatus rv = PK11_DestroyObject(slot.get(), id);
   return (rv == SECSuccess);
 }
 
-bool CryptoKey::WriteStructuredClone(JSStructuredCloneWriter* aWriter) const {
+bool CryptoKey::WriteStructuredClone(JSContext* aCX,
+                                     JSStructuredCloneWriter* aWriter) const {
   // Write in five pieces
   // 1. Attributes
   // 2. Symmetric key as raw (if present)
   // 3. Private key as pkcs8 (if present)
   // 4. Public key as spki (if present)
   // 5. Algorithm in whatever form it chooses
   CryptoBuffer priv, pub;
 
@@ -1159,48 +1160,53 @@ bool CryptoKey::WriteStructuredClone(JSS
     }
   }
 
   return JS_WriteUint32Pair(aWriter, mAttributes, CRYPTOKEY_SC_VERSION) &&
          WriteBuffer(aWriter, mSymKey) && WriteBuffer(aWriter, priv) &&
          WriteBuffer(aWriter, pub) && mAlgorithm.WriteStructuredClone(aWriter);
 }
 
-bool CryptoKey::ReadStructuredClone(JSStructuredCloneReader* aReader) {
+// static
+already_AddRefed<CryptoKey> CryptoKey::ReadStructuredClone(
+    JSContext* aCx, nsIGlobalObject* aGlobal,
+    JSStructuredCloneReader* aReader) {
   // Ensure that NSS is initialized.
   if (!EnsureNSSInitializedChromeOrContent()) {
-    return false;
+    return nullptr;
   }
 
+  RefPtr<CryptoKey> key = new CryptoKey(aGlobal);
+
   uint32_t version;
   CryptoBuffer sym, priv, pub;
 
-  bool read = JS_ReadUint32Pair(aReader, &mAttributes, &version) &&
+  bool read = JS_ReadUint32Pair(aReader, &key->mAttributes, &version) &&
               (version == CRYPTOKEY_SC_VERSION) && ReadBuffer(aReader, sym) &&
               ReadBuffer(aReader, priv) && ReadBuffer(aReader, pub) &&
-              mAlgorithm.ReadStructuredClone(aReader);
+              key->mAlgorithm.ReadStructuredClone(aReader);
   if (!read) {
-    return false;
+    return nullptr;
   }
 
-  if (sym.Length() > 0 && !mSymKey.Assign(sym)) {
-    return false;
+  if (sym.Length() > 0 && !key->mSymKey.Assign(sym)) {
+    return nullptr;
   }
   if (priv.Length() > 0) {
-    mPrivateKey = CryptoKey::PrivateKeyFromPkcs8(priv);
+    key->mPrivateKey = CryptoKey::PrivateKeyFromPkcs8(priv);
   }
   if (pub.Length() > 0) {
-    mPublicKey = CryptoKey::PublicKeyFromSpki(pub);
+    key->mPublicKey = CryptoKey::PublicKeyFromSpki(pub);
   }
 
   // Ensure that what we've read is consistent
   // If the attributes indicate a key type, should have a key of that type
-  if (!((GetKeyType() == SECRET && mSymKey.Length() > 0) ||
-        (GetKeyType() == PRIVATE && mPrivateKey) ||
-        (GetKeyType() == PUBLIC && mPublicKey))) {
-    return false;
+  if (!((key->GetKeyType() == SECRET && key->mSymKey.Length() > 0) ||
+        (key->GetKeyType() == PRIVATE && key->mPrivateKey) ||
+        (key->GetKeyType() == PUBLIC && key->mPublicKey))) {
+    return nullptr;
   }
 
-  return true;
+  return key.forget();
 }
 
 }  // namespace dom
 }  // namespace mozilla
--- a/dom/crypto/CryptoKey.h
+++ b/dom/crypto/CryptoKey.h
@@ -159,18 +159,21 @@ class CryptoKey final : public nsISuppor
   static UniqueSECKEYPublicKey PublicECKeyFromRaw(CryptoBuffer& aKeyData,
                                                   const nsString& aNamedCurve);
   static nsresult PublicECKeyToRaw(SECKEYPublicKey* aPubKey,
                                    CryptoBuffer& aRetVal);
 
   static bool PublicKeyValid(SECKEYPublicKey* aPubKey);
 
   // Structured clone methods use these to clone keys
-  bool WriteStructuredClone(JSStructuredCloneWriter* aWriter) const;
-  bool ReadStructuredClone(JSStructuredCloneReader* aReader);
+  bool WriteStructuredClone(JSContext* aCx,
+                            JSStructuredCloneWriter* aWriter) const;
+  static already_AddRefed<CryptoKey> ReadStructuredClone(
+      JSContext* aCx, nsIGlobalObject* aGlobal,
+      JSStructuredCloneReader* aReader);
 
  private:
   ~CryptoKey() {}
 
   RefPtr<nsIGlobalObject> mGlobal;
   uint32_t mAttributes;  // see above
   KeyAlgorithmProxy mAlgorithm;
 
--- a/dom/webidl/SubtleCrypto.webidl
+++ b/dom/webidl/SubtleCrypto.webidl
@@ -147,16 +147,17 @@ dictionary JsonWebKey {
   DOMString qi;
   sequence<RsaOtherPrimesInfo> oth;
   DOMString k;
 };
 
 
 /***** The Main API *****/
 
+[Serializable]
 interface CryptoKey {
   readonly attribute KeyType type;
   readonly attribute boolean extractable;
   [Cached, Constant, Throws] readonly attribute object algorithm;
   [Cached, Constant, Frozen] readonly attribute sequence<KeyUsage> usages;
 };
 
 dictionary CryptoKeyPair {