1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
5 #include "jsfriendapi.h"
7 #include "nsIRandomGenerator.h"
8 #include "MainThreadUtils.h"
9 #include "nsXULAppAPI.h"
11 #include "mozilla/dom/ContentChild.h"
12 #include "mozilla/dom/CryptoBinding.h"
13 #include "nsServiceManagerUtils.h"
15 using mozilla::dom::ContentChild
;
20 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Crypto
)
21 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
22 NS_INTERFACE_MAP_ENTRY(nsISupports
)
23 NS_INTERFACE_MAP_ENTRY(nsIDOMCrypto
)
26 NS_IMPL_CYCLE_COLLECTING_ADDREF(Crypto
)
27 NS_IMPL_CYCLE_COLLECTING_RELEASE(Crypto
)
29 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Crypto
, mParent
, mSubtle
)
33 MOZ_COUNT_CTOR(Crypto
);
38 MOZ_COUNT_DTOR(Crypto
);
42 Crypto::Init(nsIGlobalObject
* aParent
)
44 mParent
= do_QueryInterface(aParent
);
48 /* virtual */ JSObject
*
49 Crypto::WrapObject(JSContext
* aCx
)
51 return CryptoBinding::Wrap(aCx
, this);
55 Crypto::GetRandomValues(JSContext
* aCx
, const ArrayBufferView
& aArray
,
56 JS::MutableHandle
<JSObject
*> aRetval
,
59 NS_ABORT_IF_FALSE(NS_IsMainThread(), "Called on the wrong thread");
61 JS::Rooted
<JSObject
*> view(aCx
, aArray
.Obj());
63 // Throw if the wrong type of ArrayBufferView is passed in
64 // (Part of the Web Crypto API spec)
65 switch (JS_GetArrayBufferViewType(view
)) {
66 case js::Scalar::Int8
:
67 case js::Scalar::Uint8
:
68 case js::Scalar::Uint8Clamped
:
69 case js::Scalar::Int16
:
70 case js::Scalar::Uint16
:
71 case js::Scalar::Int32
:
72 case js::Scalar::Uint32
:
75 aRv
.Throw(NS_ERROR_DOM_TYPE_MISMATCH_ERR
);
79 aArray
.ComputeLengthAndData();
80 uint32_t dataLen
= aArray
.Length();
82 NS_WARNING("ArrayBufferView length is 0, cannot continue");
85 } else if (dataLen
> 65536) {
86 aRv
.Throw(NS_ERROR_DOM_QUOTA_EXCEEDED_ERR
);
90 uint8_t* data
= aArray
.Data();
92 if (XRE_GetProcessType() != GeckoProcessType_Default
) {
93 InfallibleTArray
<uint8_t> randomValues
;
94 // Tell the parent process to generate random values via PContent
95 ContentChild
* cc
= ContentChild::GetSingleton();
96 if (!cc
->SendGetRandomValues(dataLen
, &randomValues
) ||
97 randomValues
.Length() == 0) {
98 aRv
.Throw(NS_ERROR_FAILURE
);
101 NS_ASSERTION(dataLen
== randomValues
.Length(),
102 "Invalid length returned from parent process!");
103 memcpy(data
, randomValues
.Elements(), dataLen
);
105 uint8_t *buf
= GetRandomValues(dataLen
);
108 aRv
.Throw(NS_ERROR_FAILURE
);
112 memcpy(data
, buf
, dataLen
);
123 mSubtle
= new SubtleCrypto(GetParentObject());
128 /* static */ uint8_t*
129 Crypto::GetRandomValues(uint32_t aLength
)
131 nsCOMPtr
<nsIRandomGenerator
> randomGenerator
;
133 randomGenerator
= do_GetService("@mozilla.org/security/random-generator;1");
134 NS_ENSURE_TRUE(randomGenerator
, nullptr);
137 rv
= randomGenerator
->GenerateRandomBytes(aLength
, &buf
);
139 NS_ENSURE_SUCCESS(rv
, nullptr);
145 } // namespace mozilla