Bug 1250930 - Use correct global when creating WebCrypto objects r=bz a=ritu
authorTim Taubert <ttaubert@mozilla.com>
Thu, 10 Mar 2016 09:09:23 +0100
changeset 325270 648da47fced65908c6534eb0cdfdf99414f748d7
parent 325269 aaa3cdd45ed3a3b00da3fb4ed5024055d3d955c1
child 325271 23310a1c623289d20cb8b454ddc34c92e095a660
push id1128
push userjlund@mozilla.com
push dateWed, 01 Jun 2016 01:31:59 +0000
treeherdermozilla-release@fe0d30de989d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz, ritu
bugs1250930
milestone47.0a2
Bug 1250930 - Use correct global when creating WebCrypto objects r=bz a=ritu
dom/base/SubtleCrypto.cpp
dom/crypto/WebCryptoTask.cpp
dom/crypto/WebCryptoTask.h
dom/crypto/test/test_WebCrypto.html
dom/media/webrtc/RTCCertificate.cpp
--- a/dom/base/SubtleCrypto.cpp
+++ b/dom/base/SubtleCrypto.cpp
@@ -99,45 +99,46 @@ already_AddRefed<Promise>
 SubtleCrypto::ImportKey(JSContext* cx,
                         const nsAString& format,
                         JS::Handle<JSObject*> keyData,
                         const ObjectOrString& algorithm,
                         bool extractable,
                         const Sequence<nsString>& keyUsages,
                         ErrorResult& aRv)
 {
-  SUBTLECRYPTO_METHOD_BODY(ImportKey, aRv, cx, format, keyData, algorithm,
-                           extractable, keyUsages)
+  SUBTLECRYPTO_METHOD_BODY(ImportKey, aRv, mParent, cx, format, keyData,
+                           algorithm, extractable, keyUsages)
 }
 
 already_AddRefed<Promise>
 SubtleCrypto::ExportKey(const nsAString& format,
                         CryptoKey& key,
                         ErrorResult& aRv)
 {
   SUBTLECRYPTO_METHOD_BODY(ExportKey, aRv, format, key)
 }
 
 already_AddRefed<Promise>
 SubtleCrypto::GenerateKey(JSContext* cx, const ObjectOrString& algorithm,
                           bool extractable, const Sequence<nsString>& keyUsages,
                           ErrorResult& aRv)
 {
-  SUBTLECRYPTO_METHOD_BODY(GenerateKey, aRv, cx, algorithm, extractable, keyUsages)
+  SUBTLECRYPTO_METHOD_BODY(GenerateKey, aRv, mParent, cx, algorithm,
+                           extractable, keyUsages)
 }
 
 already_AddRefed<Promise>
 SubtleCrypto::DeriveKey(JSContext* cx,
                         const ObjectOrString& algorithm,
                         CryptoKey& baseKey,
                         const ObjectOrString& derivedKeyType,
                         bool extractable, const Sequence<nsString>& keyUsages,
                         ErrorResult& aRv)
 {
-  SUBTLECRYPTO_METHOD_BODY(DeriveKey, aRv, cx, algorithm, baseKey,
+  SUBTLECRYPTO_METHOD_BODY(DeriveKey, aRv, mParent, cx, algorithm, baseKey,
                            derivedKeyType, extractable, keyUsages)
 }
 
 already_AddRefed<Promise>
 SubtleCrypto::DeriveBits(JSContext* cx,
                          const ObjectOrString& algorithm,
                          CryptoKey& baseKey,
                          uint32_t length,
@@ -163,15 +164,15 @@ SubtleCrypto::UnwrapKey(JSContext* cx,
                         const ArrayBufferViewOrArrayBuffer& wrappedKey,
                         CryptoKey& unwrappingKey,
                         const ObjectOrString& unwrapAlgorithm,
                         const ObjectOrString& unwrappedKeyAlgorithm,
                         bool extractable,
                         const Sequence<nsString>& keyUsages,
                         ErrorResult& aRv)
 {
-  SUBTLECRYPTO_METHOD_BODY(UnwrapKey, aRv, cx, format, wrappedKey, unwrappingKey,
-                           unwrapAlgorithm, unwrappedKeyAlgorithm,
-                           extractable, keyUsages)
+  SUBTLECRYPTO_METHOD_BODY(UnwrapKey, aRv, mParent, cx, format, wrappedKey,
+                           unwrappingKey, unwrapAlgorithm,
+                           unwrappedKeyAlgorithm, extractable, keyUsages)
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/crypto/WebCryptoTask.cpp
+++ b/dom/crypto/WebCryptoTask.cpp
@@ -1327,34 +1327,26 @@ private:
 
     return rv;
   }
 };
 
 class ImportKeyTask : public WebCryptoTask
 {
 public:
-  void Init(JSContext* aCx,
-      const nsAString& aFormat,
-      const ObjectOrString& aAlgorithm, bool aExtractable,
-      const Sequence<nsString>& aKeyUsages)
+  void Init(nsIGlobalObject* aGlobal, JSContext* aCx,
+      const nsAString& aFormat, const ObjectOrString& aAlgorithm,
+      bool aExtractable, const Sequence<nsString>& aKeyUsages)
   {
     mFormat = aFormat;
     mDataIsSet = false;
     mDataIsJwk = false;
 
-    // Get the current global object from the context
-    nsIGlobalObject *global = xpc::NativeGlobal(JS::CurrentGlobalOrNull(aCx));
-    if (!global) {
-      mEarlyRv = NS_ERROR_DOM_UNKNOWN_ERR;
-      return;
-    }
-
     // This stuff pretty much always happens, so we'll do it here
-    mKey = new CryptoKey(global);
+    mKey = new CryptoKey(aGlobal);
     mKey->SetExtractable(aExtractable);
     mKey->ClearUsages();
     for (uint32_t i = 0; i < aKeyUsages.Length(); ++i) {
       mEarlyRv = mKey->AddUsage(aKeyUsages[i]);
       if (NS_FAILED(mEarlyRv)) {
         return;
       }
     }
@@ -1467,48 +1459,47 @@ private:
     mKey = nullptr;
   }
 };
 
 
 class ImportSymmetricKeyTask : public ImportKeyTask
 {
 public:
-  ImportSymmetricKeyTask(JSContext* aCx,
+  ImportSymmetricKeyTask(nsIGlobalObject* aGlobal, JSContext* aCx,
       const nsAString& aFormat,
       const ObjectOrString& aAlgorithm, bool aExtractable,
       const Sequence<nsString>& aKeyUsages)
   {
-    Init(aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
+    Init(aGlobal, aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
   }
 
-  ImportSymmetricKeyTask(JSContext* aCx,
+  ImportSymmetricKeyTask(nsIGlobalObject* aGlobal, JSContext* aCx,
       const nsAString& aFormat, const JS::Handle<JSObject*> aKeyData,
       const ObjectOrString& aAlgorithm, bool aExtractable,
       const Sequence<nsString>& aKeyUsages)
   {
-    Init(aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
+    Init(aGlobal, aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
     if (NS_FAILED(mEarlyRv)) {
       return;
     }
 
     SetKeyData(aCx, aKeyData);
     NS_ENSURE_SUCCESS_VOID(mEarlyRv);
     if (mDataIsJwk && !mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_JWK)) {
       mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
       return;
     }
   }
 
-  void Init(JSContext* aCx,
-      const nsAString& aFormat,
+  void Init(nsIGlobalObject* aGlobal, JSContext* aCx, const nsAString& aFormat,
       const ObjectOrString& aAlgorithm, bool aExtractable,
       const Sequence<nsString>& aKeyUsages)
   {
-    ImportKeyTask::Init(aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
+    ImportKeyTask::Init(aGlobal, aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
     if (NS_FAILED(mEarlyRv)) {
       return;
     }
 
     // This task only supports raw and JWK format.
     if (!mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_JWK) &&
         !mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_RAW)) {
       mEarlyRv = NS_ERROR_DOM_NOT_SUPPORTED_ERR;
@@ -1625,48 +1616,48 @@ public:
 
 private:
   nsString mHashName;
 };
 
 class ImportRsaKeyTask : public ImportKeyTask
 {
 public:
-  ImportRsaKeyTask(JSContext* aCx,
+  ImportRsaKeyTask(nsIGlobalObject* aGlobal, JSContext* aCx,
       const nsAString& aFormat,
       const ObjectOrString& aAlgorithm, bool aExtractable,
       const Sequence<nsString>& aKeyUsages)
   {
-    Init(aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
+    Init(aGlobal, aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
   }
 
-  ImportRsaKeyTask(JSContext* aCx,
+  ImportRsaKeyTask(nsIGlobalObject* aGlobal, JSContext* aCx,
       const nsAString& aFormat, JS::Handle<JSObject*> aKeyData,
       const ObjectOrString& aAlgorithm, bool aExtractable,
       const Sequence<nsString>& aKeyUsages)
   {
-    Init(aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
+    Init(aGlobal, aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
     if (NS_FAILED(mEarlyRv)) {
       return;
     }
 
     SetKeyData(aCx, aKeyData);
     NS_ENSURE_SUCCESS_VOID(mEarlyRv);
     if (mDataIsJwk && !mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_JWK)) {
       mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
       return;
     }
   }
 
-  void Init(JSContext* aCx,
+  void Init(nsIGlobalObject* aGlobal, JSContext* aCx,
       const nsAString& aFormat,
       const ObjectOrString& aAlgorithm, bool aExtractable,
       const Sequence<nsString>& aKeyUsages)
   {
-    ImportKeyTask::Init(aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
+    ImportKeyTask::Init(aGlobal, aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
     if (NS_FAILED(mEarlyRv)) {
       return;
     }
 
     // If this is RSA with a hash, cache the hash name
     if (mAlgName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1) ||
         mAlgName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP) ||
         mAlgName.EqualsLiteral(WEBCRYPTO_ALG_RSA_PSS)) {
@@ -1793,42 +1784,42 @@ private:
 
     return NS_OK;
   }
 };
 
 class ImportEcKeyTask : public ImportKeyTask
 {
 public:
-  ImportEcKeyTask(JSContext* aCx, const nsAString& aFormat,
+  ImportEcKeyTask(nsIGlobalObject* aGlobal, JSContext* aCx,
+                  const nsAString& aFormat, const ObjectOrString& aAlgorithm,
+                  bool aExtractable, const Sequence<nsString>& aKeyUsages)
+  {
+    Init(aGlobal, aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
+  }
+
+  ImportEcKeyTask(nsIGlobalObject* aGlobal, JSContext* aCx,
+                  const nsAString& aFormat, JS::Handle<JSObject*> aKeyData,
                   const ObjectOrString& aAlgorithm, bool aExtractable,
                   const Sequence<nsString>& aKeyUsages)
   {
-    Init(aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
-  }
-
-  ImportEcKeyTask(JSContext* aCx, const nsAString& aFormat,
-                  JS::Handle<JSObject*> aKeyData,
-                  const ObjectOrString& aAlgorithm, bool aExtractable,
-                  const Sequence<nsString>& aKeyUsages)
-  {
-    Init(aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
+    Init(aGlobal, aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
     if (NS_FAILED(mEarlyRv)) {
       return;
     }
 
     SetKeyData(aCx, aKeyData);
     NS_ENSURE_SUCCESS_VOID(mEarlyRv);
   }
 
-  void Init(JSContext* aCx, const nsAString& aFormat,
+  void Init(nsIGlobalObject* aGlobal, JSContext* aCx, const nsAString& aFormat,
             const ObjectOrString& aAlgorithm, bool aExtractable,
             const Sequence<nsString>& aKeyUsages)
   {
-    ImportKeyTask::Init(aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
+    ImportKeyTask::Init(aGlobal, aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
     if (NS_FAILED(mEarlyRv)) {
       return;
     }
 
     if (mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_RAW)) {
       RootedDictionary<EcKeyImportParams> params(aCx);
       mEarlyRv = Coerce(aCx, params, aAlgorithm);
       if (NS_FAILED(mEarlyRv) || !params.mNamedCurve.WasPassed()) {
@@ -1946,40 +1937,40 @@ private:
 
     return NS_OK;
   }
 };
 
 class ImportDhKeyTask : public ImportKeyTask
 {
 public:
-  ImportDhKeyTask(JSContext* aCx, const nsAString& aFormat,
+  ImportDhKeyTask(nsIGlobalObject* aGlobal, JSContext* aCx,
+                  const nsAString& aFormat, const ObjectOrString& aAlgorithm,
+                  bool aExtractable, const Sequence<nsString>& aKeyUsages)
+  {
+    Init(aGlobal, aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
+  }
+
+  ImportDhKeyTask(nsIGlobalObject* aGlobal, JSContext* aCx,
+                  const nsAString& aFormat, JS::Handle<JSObject*> aKeyData,
                   const ObjectOrString& aAlgorithm, bool aExtractable,
                   const Sequence<nsString>& aKeyUsages)
   {
-    Init(aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
-  }
-
-  ImportDhKeyTask(JSContext* aCx, const nsAString& aFormat,
-                  JS::Handle<JSObject*> aKeyData,
-                  const ObjectOrString& aAlgorithm, bool aExtractable,
-                  const Sequence<nsString>& aKeyUsages)
-  {
-    Init(aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
+    Init(aGlobal, aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
     if (NS_SUCCEEDED(mEarlyRv)) {
       SetKeyData(aCx, aKeyData);
       NS_ENSURE_SUCCESS_VOID(mEarlyRv);
     }
   }
 
-  void Init(JSContext* aCx, const nsAString& aFormat,
+  void Init(nsIGlobalObject* aGlobal, JSContext* aCx, const nsAString& aFormat,
             const ObjectOrString& aAlgorithm, bool aExtractable,
             const Sequence<nsString>& aKeyUsages)
   {
-    ImportKeyTask::Init(aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
+    ImportKeyTask::Init(aGlobal, aCx, aFormat, aAlgorithm, aExtractable, aKeyUsages);
     if (NS_FAILED(mEarlyRv)) {
       return;
     }
 
     if (mFormat.EqualsLiteral(WEBCRYPTO_KEY_FORMAT_RAW)) {
       RootedDictionary<DhImportKeyParams> params(aCx);
       mEarlyRv = Coerce(aCx, params, aAlgorithm);
       if (NS_FAILED(mEarlyRv)) {
@@ -2192,28 +2183,22 @@ private:
     TypedArrayCreator<ArrayBuffer> ret(mResult);
     mResultPromise->MaybeResolve(ret);
   }
 };
 
 class GenerateSymmetricKeyTask : public WebCryptoTask
 {
 public:
-  GenerateSymmetricKeyTask(JSContext* aCx,
+  GenerateSymmetricKeyTask(nsIGlobalObject* aGlobal, JSContext* aCx,
       const ObjectOrString& aAlgorithm, bool aExtractable,
       const Sequence<nsString>& aKeyUsages)
   {
-    nsIGlobalObject* global = xpc::NativeGlobal(JS::CurrentGlobalOrNull(aCx));
-    if (!global) {
-      mEarlyRv = NS_ERROR_DOM_UNKNOWN_ERR;
-      return;
-    }
-
     // Create an empty key and set easy attributes
-    mKey = new CryptoKey(global);
+    mKey = new CryptoKey(aGlobal);
     mKey->SetExtractable(aExtractable);
     mKey->SetType(CryptoKey::SECRET);
 
     // Extract algorithm name
     nsString algName;
     mEarlyRv = GetAlgorithmName(aCx, aAlgorithm, algName);
     if (NS_FAILED(mEarlyRv)) {
       mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
@@ -2321,35 +2306,29 @@ private:
 
   virtual void Cleanup() override
   {
     mKey = nullptr;
   }
 };
 
 GenerateAsymmetricKeyTask::GenerateAsymmetricKeyTask(
-    JSContext* aCx, const ObjectOrString& aAlgorithm, bool aExtractable,
-    const Sequence<nsString>& aKeyUsages)
+    nsIGlobalObject* aGlobal, JSContext* aCx, const ObjectOrString& aAlgorithm,
+    bool aExtractable, const Sequence<nsString>& aKeyUsages)
   : mKeyPair(new CryptoKeyPair())
 {
-  nsIGlobalObject* global = xpc::NativeGlobal(JS::CurrentGlobalOrNull(aCx));
-  if (!global) {
-    mEarlyRv = NS_ERROR_DOM_UNKNOWN_ERR;
-    return;
-  }
-
   mArena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
   if (!mArena) {
     mEarlyRv = NS_ERROR_DOM_UNKNOWN_ERR;
     return;
   }
 
   // Create an empty key pair and set easy attributes
-  mKeyPair->mPrivateKey = new CryptoKey(global);
-  mKeyPair->mPublicKey = new CryptoKey(global);
+  mKeyPair->mPrivateKey = new CryptoKey(aGlobal);
+  mKeyPair->mPublicKey = new CryptoKey(aGlobal);
 
   // Extract algorithm name
   mEarlyRv = GetAlgorithmName(aCx, aAlgorithm, mAlgName);
   if (NS_FAILED(mEarlyRv)) {
     mEarlyRv = NS_ERROR_DOM_SYNTAX_ERR;
     return;
   }
 
@@ -2848,29 +2827,29 @@ private:
     return NS_OK;
   }
 };
 
 template<class DeriveBitsTask>
 class DeriveKeyTask : public DeriveBitsTask
 {
 public:
-  DeriveKeyTask(JSContext* aCx,
+  DeriveKeyTask(nsIGlobalObject* aGlobal, JSContext* aCx,
                 const ObjectOrString& aAlgorithm, CryptoKey& aBaseKey,
                 const ObjectOrString& aDerivedKeyType, bool aExtractable,
                 const Sequence<nsString>& aKeyUsages)
     : DeriveBitsTask(aCx, aAlgorithm, aBaseKey, aDerivedKeyType)
     , mResolved(false)
   {
     if (NS_FAILED(this->mEarlyRv)) {
       return;
     }
 
     NS_NAMED_LITERAL_STRING(format, WEBCRYPTO_KEY_FORMAT_RAW);
-    mTask = new ImportSymmetricKeyTask(aCx, format, aDerivedKeyType,
+    mTask = new ImportSymmetricKeyTask(aGlobal, aCx, format, aDerivedKeyType,
                                        aExtractable, aKeyUsages);
   }
 
 protected:
   RefPtr<ImportSymmetricKeyTask> mTask;
   bool mResolved;
 
 private:
@@ -3290,17 +3269,18 @@ WebCryptoTask::CreateDigestTask(JSContex
       algName.EqualsLiteral(WEBCRYPTO_ALG_SHA512)) {
     return new DigestTask(aCx, aAlgorithm, aData);
   }
 
   return new FailureTask(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
 }
 
 WebCryptoTask*
-WebCryptoTask::CreateImportKeyTask(JSContext* aCx,
+WebCryptoTask::CreateImportKeyTask(nsIGlobalObject* aGlobal,
+                                   JSContext* aCx,
                                    const nsAString& aFormat,
                                    JS::Handle<JSObject*> aKeyData,
                                    const ObjectOrString& aAlgorithm,
                                    bool aExtractable,
                                    const Sequence<nsString>& aKeyUsages)
 {
   Telemetry::Accumulate(Telemetry::WEBCRYPTO_METHOD, TM_IMPORTKEY);
   Telemetry::Accumulate(Telemetry::WEBCRYPTO_EXTRACTABLE_IMPORT, aExtractable);
@@ -3328,29 +3308,29 @@ WebCryptoTask::CreateImportKeyTask(JSCon
   // However, the spec should be updated to allow it.
   if (algName.EqualsLiteral(WEBCRYPTO_ALG_AES_CBC) ||
       algName.EqualsLiteral(WEBCRYPTO_ALG_AES_CTR) ||
       algName.EqualsLiteral(WEBCRYPTO_ALG_AES_GCM) ||
       algName.EqualsLiteral(WEBCRYPTO_ALG_AES_KW) ||
       algName.EqualsLiteral(WEBCRYPTO_ALG_PBKDF2) ||
       algName.EqualsLiteral(WEBCRYPTO_ALG_HKDF) ||
       algName.EqualsLiteral(WEBCRYPTO_ALG_HMAC)) {
-    return new ImportSymmetricKeyTask(aCx, aFormat, aKeyData, aAlgorithm,
-                                      aExtractable, aKeyUsages);
+    return new ImportSymmetricKeyTask(aGlobal, aCx, aFormat, aKeyData,
+                                      aAlgorithm, aExtractable, aKeyUsages);
   } else if (algName.EqualsLiteral(WEBCRYPTO_ALG_RSASSA_PKCS1) ||
              algName.EqualsLiteral(WEBCRYPTO_ALG_RSA_OAEP) ||
              algName.EqualsLiteral(WEBCRYPTO_ALG_RSA_PSS)) {
-    return new ImportRsaKeyTask(aCx, aFormat, aKeyData, aAlgorithm,
+    return new ImportRsaKeyTask(aGlobal, aCx, aFormat, aKeyData, aAlgorithm,
                                 aExtractable, aKeyUsages);
   } else if (algName.EqualsLiteral(WEBCRYPTO_ALG_ECDH) ||
              algName.EqualsLiteral(WEBCRYPTO_ALG_ECDSA)) {
-    return new ImportEcKeyTask(aCx, aFormat, aKeyData, aAlgorithm,
+    return new ImportEcKeyTask(aGlobal, aCx, aFormat, aKeyData, aAlgorithm,
                                aExtractable, aKeyUsages);
   } else if (algName.EqualsLiteral(WEBCRYPTO_ALG_DH)) {
-    return new ImportDhKeyTask(aCx, aFormat, aKeyData, aAlgorithm,
+    return new ImportDhKeyTask(aGlobal, aCx, aFormat, aKeyData, aAlgorithm,
                                aExtractable, aKeyUsages);
   } else {
     return new FailureTask(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
   }
 }
 
 WebCryptoTask*
 WebCryptoTask::CreateExportKeyTask(const nsAString& aFormat,
@@ -3389,17 +3369,18 @@ WebCryptoTask::CreateExportKeyTask(const
       algName.EqualsLiteral(WEBCRYPTO_ALG_DH)) {
     return new ExportKeyTask(aFormat, aKey);
   }
 
   return new FailureTask(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
 }
 
 WebCryptoTask*
-WebCryptoTask::CreateGenerateKeyTask(JSContext* aCx,
+WebCryptoTask::CreateGenerateKeyTask(nsIGlobalObject* aGlobal,
+                                     JSContext* aCx,
                                      const ObjectOrString& aAlgorithm,
                                      bool aExtractable,
                                      const Sequence<nsString>& aKeyUsages)
 {
   Telemetry::Accumulate(Telemetry::WEBCRYPTO_METHOD, TM_GENERATEKEY);
   Telemetry::Accumulate(Telemetry::WEBCRYPTO_EXTRACTABLE_GENERATE, aExtractable);
 
   // Verify that aKeyUsages does not contain an unrecognized value
@@ -3415,31 +3396,34 @@ WebCryptoTask::CreateGenerateKeyTask(JSC
     return new FailureTask(rv);
   }
 
   if (algName.EqualsASCII(WEBCRYPTO_ALG_AES_CBC) ||
       algName.EqualsASCII(WEBCRYPTO_ALG_AES_CTR) ||
       algName.EqualsASCII(WEBCRYPTO_ALG_AES_GCM) ||
       algName.EqualsASCII(WEBCRYPTO_ALG_AES_KW) ||
       algName.EqualsASCII(WEBCRYPTO_ALG_HMAC)) {
-    return new GenerateSymmetricKeyTask(aCx, aAlgorithm, aExtractable, aKeyUsages);
+    return new GenerateSymmetricKeyTask(aGlobal, aCx, aAlgorithm, aExtractable,
+                                        aKeyUsages);
   } else if (algName.EqualsASCII(WEBCRYPTO_ALG_RSASSA_PKCS1) ||
              algName.EqualsASCII(WEBCRYPTO_ALG_RSA_OAEP) ||
              algName.EqualsASCII(WEBCRYPTO_ALG_RSA_PSS) ||
              algName.EqualsASCII(WEBCRYPTO_ALG_ECDH) ||
              algName.EqualsASCII(WEBCRYPTO_ALG_ECDSA) ||
              algName.EqualsASCII(WEBCRYPTO_ALG_DH)) {
-    return new GenerateAsymmetricKeyTask(aCx, aAlgorithm, aExtractable, aKeyUsages);
+    return new GenerateAsymmetricKeyTask(aGlobal, aCx, aAlgorithm, aExtractable,
+                                         aKeyUsages);
   } else {
     return new FailureTask(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
   }
 }
 
 WebCryptoTask*
-WebCryptoTask::CreateDeriveKeyTask(JSContext* aCx,
+WebCryptoTask::CreateDeriveKeyTask(nsIGlobalObject* aGlobal,
+                                   JSContext* aCx,
                                    const ObjectOrString& aAlgorithm,
                                    CryptoKey& aBaseKey,
                                    const ObjectOrString& aDerivedKeyType,
                                    bool aExtractable,
                                    const Sequence<nsString>& aKeyUsages)
 {
   Telemetry::Accumulate(Telemetry::WEBCRYPTO_METHOD, TM_DERIVEKEY);
 
@@ -3455,31 +3439,31 @@ WebCryptoTask::CreateDeriveKeyTask(JSCon
 
   nsString algName;
   nsresult rv = GetAlgorithmName(aCx, aAlgorithm, algName);
   if (NS_FAILED(rv)) {
     return new FailureTask(rv);
   }
 
   if (algName.EqualsASCII(WEBCRYPTO_ALG_HKDF)) {
-    return new DeriveKeyTask<DeriveHkdfBitsTask>(aCx, aAlgorithm, aBaseKey,
-                                                 aDerivedKeyType, aExtractable,
-                                                 aKeyUsages);
+    return new DeriveKeyTask<DeriveHkdfBitsTask>(aGlobal, aCx, aAlgorithm,
+                                                 aBaseKey, aDerivedKeyType,
+                                                 aExtractable, aKeyUsages);
   }
 
   if (algName.EqualsASCII(WEBCRYPTO_ALG_PBKDF2)) {
-    return new DeriveKeyTask<DerivePbkdfBitsTask>(aCx, aAlgorithm, aBaseKey,
-                                                  aDerivedKeyType, aExtractable,
-                                                  aKeyUsages);
+    return new DeriveKeyTask<DerivePbkdfBitsTask>(aGlobal, aCx, aAlgorithm,
+                                                  aBaseKey, aDerivedKeyType,
+                                                  aExtractable, aKeyUsages);
   }
 
   if (algName.EqualsASCII(WEBCRYPTO_ALG_ECDH)) {
-    return new DeriveKeyTask<DeriveEcdhBitsTask>(aCx, aAlgorithm, aBaseKey,
-                                                 aDerivedKeyType, aExtractable,
-                                                 aKeyUsages);
+    return new DeriveKeyTask<DeriveEcdhBitsTask>(aGlobal, aCx, aAlgorithm,
+                                                 aBaseKey, aDerivedKeyType,
+                                                 aExtractable, aKeyUsages);
   }
 
   return new FailureTask(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
 }
 
 WebCryptoTask*
 WebCryptoTask::CreateDeriveBitsTask(JSContext* aCx,
                                     const ObjectOrString& aAlgorithm,
@@ -3563,17 +3547,18 @@ WebCryptoTask::CreateWrapKeyTask(JSConte
     return new WrapKeyTask<RsaOaepTask>(aCx, aFormat, aKey,
                                         aWrappingKey, aWrapAlgorithm);
   }
 
   return new FailureTask(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
 }
 
 WebCryptoTask*
-WebCryptoTask::CreateUnwrapKeyTask(JSContext* aCx,
+WebCryptoTask::CreateUnwrapKeyTask(nsIGlobalObject* aGlobal,
+                                   JSContext* aCx,
                                    const nsAString& aFormat,
                                    const ArrayBufferViewOrArrayBuffer& aWrappedKey,
                                    CryptoKey& aUnwrappingKey,
                                    const ObjectOrString& aUnwrapAlgorithm,
                                    const ObjectOrString& aUnwrappedKeyAlgorithm,
                                    bool aExtractable,
                                    const Sequence<nsString>& aKeyUsages)
 {
@@ -3597,23 +3582,23 @@ WebCryptoTask::CreateUnwrapKeyTask(JSCon
 
   CryptoOperationData dummy;
   RefPtr<ImportKeyTask> importTask;
   if (keyAlgName.EqualsASCII(WEBCRYPTO_ALG_AES_CBC) ||
       keyAlgName.EqualsASCII(WEBCRYPTO_ALG_AES_CTR) ||
       keyAlgName.EqualsASCII(WEBCRYPTO_ALG_AES_GCM) ||
       keyAlgName.EqualsASCII(WEBCRYPTO_ALG_HKDF) ||
       keyAlgName.EqualsASCII(WEBCRYPTO_ALG_HMAC)) {
-    importTask = new ImportSymmetricKeyTask(aCx, aFormat,
+    importTask = new ImportSymmetricKeyTask(aGlobal, aCx, aFormat,
                                             aUnwrappedKeyAlgorithm,
                                             aExtractable, aKeyUsages);
   } else if (keyAlgName.EqualsASCII(WEBCRYPTO_ALG_RSASSA_PKCS1) ||
              keyAlgName.EqualsASCII(WEBCRYPTO_ALG_RSA_OAEP) ||
              keyAlgName.EqualsASCII(WEBCRYPTO_ALG_RSA_PSS)) {
-    importTask = new ImportRsaKeyTask(aCx, aFormat,
+    importTask = new ImportRsaKeyTask(aGlobal, aCx, aFormat,
                                       aUnwrappedKeyAlgorithm,
                                       aExtractable, aKeyUsages);
   } else {
     return new FailureTask(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
   }
 
   nsString unwrapAlgName;
   rv = GetAlgorithmName(aCx, aUnwrapAlgorithm, unwrapAlgName);
--- a/dom/crypto/WebCryptoTask.h
+++ b/dom/crypto/WebCryptoTask.h
@@ -117,46 +117,50 @@ public:
   {
     return CreateSignVerifyTask(aCx, aAlgorithm, aKey, aSignature, aData, false);
   }
 
   static WebCryptoTask* CreateDigestTask(JSContext* aCx,
                           const ObjectOrString& aAlgorithm,
                           const CryptoOperationData& aData);
 
-  static WebCryptoTask* CreateImportKeyTask(JSContext* aCx,
+  static WebCryptoTask* CreateImportKeyTask(nsIGlobalObject* aGlobal,
+                          JSContext* aCx,
                           const nsAString& aFormat,
                           JS::Handle<JSObject*> aKeyData,
                           const ObjectOrString& aAlgorithm,
                           bool aExtractable,
                           const Sequence<nsString>& aKeyUsages);
   static WebCryptoTask* CreateExportKeyTask(const nsAString& aFormat,
                           CryptoKey& aKey);
-  static WebCryptoTask* CreateGenerateKeyTask(JSContext* aCx,
+  static WebCryptoTask* CreateGenerateKeyTask(nsIGlobalObject* aGlobal,
+                          JSContext* aCx,
                           const ObjectOrString& aAlgorithm,
                           bool aExtractable,
                           const Sequence<nsString>& aKeyUsages);
 
-  static WebCryptoTask* CreateDeriveKeyTask(JSContext* aCx,
+  static WebCryptoTask* CreateDeriveKeyTask(nsIGlobalObject* aGlobal,
+                          JSContext* aCx,
                           const ObjectOrString& aAlgorithm,
                           CryptoKey& aBaseKey,
                           const ObjectOrString& aDerivedKeyType,
                           bool extractable,
                           const Sequence<nsString>& aKeyUsages);
   static WebCryptoTask* CreateDeriveBitsTask(JSContext* aCx,
                           const ObjectOrString& aAlgorithm,
                           CryptoKey& aKey,
                           uint32_t aLength);
 
   static WebCryptoTask* CreateWrapKeyTask(JSContext* aCx,
                           const nsAString& aFormat,
                           CryptoKey& aKey,
                           CryptoKey& aWrappingKey,
                           const ObjectOrString& aWrapAlgorithm);
-  static WebCryptoTask* CreateUnwrapKeyTask(JSContext* aCx,
+  static WebCryptoTask* CreateUnwrapKeyTask(nsIGlobalObject* aGlobal,
+                          JSContext* aCx,
                           const nsAString& aFormat,
                           const ArrayBufferViewOrArrayBuffer& aWrappedKey,
                           CryptoKey& aUnwrappingKey,
                           const ObjectOrString& aUnwrapAlgorithm,
                           const ObjectOrString& aUnwrappedKeyAlgorithm,
                           bool aExtractable,
                           const Sequence<nsString>& aKeyUsages);
 
@@ -223,17 +227,17 @@ private:
   bool mReleasedNSSResources;
   nsresult mRv;
 };
 
 // XXX This class is declared here (unlike others) to enable reuse by WebRTC.
 class GenerateAsymmetricKeyTask : public WebCryptoTask
 {
 public:
-  GenerateAsymmetricKeyTask(JSContext* aCx,
+  GenerateAsymmetricKeyTask(nsIGlobalObject* aGlobal, JSContext* aCx,
                             const ObjectOrString& aAlgorithm, bool aExtractable,
                             const Sequence<nsString>& aKeyUsages);
 protected:
   ScopedPLArenaPool mArena;
   UniquePtr<CryptoKeyPair> mKeyPair;
   nsString mAlgName;
   CK_MECHANISM_TYPE mMechanism;
   PK11RSAGenParams mRsaParams;
--- a/dom/crypto/test/test_WebCrypto.html
+++ b/dom/crypto/test/test_WebCrypto.html
@@ -982,26 +982,73 @@ TestArray.addTest(
       }
 
       return crypto.subtle.generateKey(alg, false, ["sign"]).then(doSign);
     }
 
     doCheckRSASSA().then(error(that), complete(that));
   }
 );
+
+// -----------------------------------------------------------------------------
+TestArray.addTest(
+  "Test that we're using the right globals when creating objects",
+  function() {
+    var that = this;
+    var data = crypto.getRandomValues(new Uint8Array(10));
+    var hmacAlg = {name: "HMAC", length: 256, hash: "SHA-1"};
+
+    var rsaAlg = {
+      name: "RSA-PSS",
+      hash: "SHA-1",
+      modulusLength: 1024,
+      publicExponent: new Uint8Array([0x01, 0x00, 0x01])
+    };
+
+    function checkPrototypes(obj, type) {
+      return obj.__proto__ != window[type].prototype &&
+             obj.__proto__ == frames[0][type].prototype
+    }
+
+    var p1 = crypto.subtle.importKey.call(
+      frames[0].crypto.subtle, "raw", data, hmacAlg, false, ["sign", "verify"]);
+    var p2 = crypto.subtle.generateKey.call(
+      frames[0].crypto.subtle, hmacAlg, false, ["sign", "verify"]);
+    var p3 = crypto.subtle.generateKey.call(
+      frames[0].crypto.subtle, rsaAlg, false, ["sign", "verify"]);
+
+    if (!checkPrototypes(p1, "Promise") ||
+        !checkPrototypes(p2, "Promise") ||
+        !checkPrototypes(p3, "Promise")) {
+      error(that)();
+    }
+
+    Promise.all([p1, p2, p3]).then(complete(that, keys => {
+      return keys.every(key => {
+        if (key instanceof CryptoKey) {
+          return checkPrototypes(key, "CryptoKey");
+        }
+
+        return checkPrototypes(key.publicKey, "CryptoKey") &&
+               checkPrototypes(key.privateKey, "CryptoKey");
+      });
+    }), error(that));
+  }
+);
 /*]]>*/</script>
 </head>
 
 <body>
 
 <div id="content">
 	<div id="head">
 		<b>Web</b>Crypto<br>
 	</div>
 
+    <iframe style="display: none;"></iframe>
     <div id="start" onclick="start();">RUN ALL</div>
 
     <div id="resultDiv" class="content">
     Summary:
     <span class="pass"><span id="passN">0</span> passed, </span>
     <span class="fail"><span id="failN">0</span> failed, </span>
     <span class="pending"><span id="pendingN">0</span> pending.</span>
     <br/>
--- a/dom/media/webrtc/RTCCertificate.cpp
+++ b/dom/media/webrtc/RTCCertificate.cpp
@@ -39,19 +39,20 @@ NS_INTERFACE_MAP_END
 #define EXPIRATION_MAX ONE_DAY * PRTime(365) /*year*/
 
 const size_t RTCCertificateCommonNameLength = 16;
 const size_t RTCCertificateMinRsaSize = 1024;
 
 class GenerateRTCCertificateTask : public GenerateAsymmetricKeyTask
 {
 public:
-  GenerateRTCCertificateTask(JSContext* aCx, const ObjectOrString& aAlgorithm,
-                     const Sequence<nsString>& aKeyUsages)
-      : GenerateAsymmetricKeyTask(aCx, aAlgorithm, true, aKeyUsages),
+  GenerateRTCCertificateTask(nsIGlobalObject* aGlobal, JSContext* aCx,
+                             const ObjectOrString& aAlgorithm,
+                             const Sequence<nsString>& aKeyUsages)
+      : GenerateAsymmetricKeyTask(aGlobal, aCx, aAlgorithm, true, aKeyUsages),
         mExpires(0),
         mAuthType(ssl_kea_null),
         mCertificate(nullptr),
         mSignatureAlg(SEC_OID_UNKNOWN)
   {
     // Expiry is 30 days after by default.
     // This is a sort of arbitrary range designed to be valid
     // now with some slack in case the other side expects
@@ -258,17 +259,17 @@ RTCCertificate::GenerateCertificate(
   if (aRv.Failed()) {
     return nullptr;
   }
   Sequence<nsString> usages;
   if (!usages.AppendElement(NS_LITERAL_STRING("sign"), fallible)) {
     return nullptr;
   }
   RefPtr<WebCryptoTask> task =
-      new GenerateRTCCertificateTask(aGlobal.Context(),
+      new GenerateRTCCertificateTask(global, aGlobal.Context(),
                                      aKeygenAlgorithm, usages);
   task->DispatchWithPromise(p);
   return p.forget();
 }
 
 RTCCertificate::RTCCertificate(nsIGlobalObject* aGlobal)
     : mGlobal(aGlobal),
       mPrivateKey(nullptr),