already_AddRefed<Promise> Cache::AddAll(JSContext* aContext, const Sequence<OwningRequestOrUSVString>& aRequestList, CallerType aCallerType, ErrorResult& aRv) { if (NS_WARN_IF(!mActor)) { aRv.Throw(NS_ERROR_UNEXPECTED); return nullptr; } CacheChild::AutoLock actorLock(mActor); GlobalObject global(aContext, mGlobal->GetGlobalJSObject()); MOZ_DIAGNOSTIC_ASSERT(!global.Failed()); nsTArray<RefPtr<Request>> requestList(aRequestList.Length()); for (uint32_t i = 0; i < aRequestList.Length(); ++i) { RequestOrUSVString requestOrString; if (aRequestList[i].IsRequest()) { requestOrString.SetAsRequest() = aRequestList[i].GetAsRequest(); if (NS_WARN_IF(!IsValidPutRequestMethod(requestOrString.GetAsRequest(), aRv))) { return nullptr; } } else { requestOrString.SetAsUSVString().Rebind( aRequestList[i].GetAsUSVString().Data(), aRequestList[i].GetAsUSVString().Length()); } RefPtr<Request> request = Request::Constructor(global, requestOrString, RequestInit(), aRv); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } nsAutoString url; request->GetUrl(url); if (NS_WARN_IF(!IsValidPutRequestURL(url, aRv))) { return nullptr; } requestList.AppendElement(std::move(request)); } return AddAll(global, std::move(requestList), aCallerType, aRv); }
void MobileMessageManager::Send(const Sequence<nsString>& aNumbers, const nsAString& aText, const SmsSendParameters& aSendParams, nsTArray<RefPtr<DOMRequest>>& aReturn, ErrorResult& aRv) { nsCOMPtr<nsISmsService> smsService = do_GetService(SMS_SERVICE_CONTRACTID); if (!smsService) { aRv.Throw(NS_ERROR_FAILURE); return; } // Use the default one unless |aSendParams.serviceId| is available. uint32_t serviceId; if (aSendParams.mServiceId.WasPassed()) { serviceId = aSendParams.mServiceId.Value(); } else { nsresult rv = smsService->GetSmsDefaultServiceId(&serviceId); if (NS_FAILED(rv)) { aRv.Throw(rv); return; } } const uint32_t size = aNumbers.Length(); for (uint32_t i = 0; i < size; ++i) { RefPtr<DOMRequest> request = Send(smsService, serviceId, aNumbers[i], aText, aRv); if (aRv.Failed()) { return; } aReturn.AppendElement(request); } }
already_AddRefed<DOMRequest> MobileMessageManager::Delete(const Sequence<OwningLongOrSmsMessageOrMmsMessage>& aParams, ErrorResult& aRv) { const uint32_t size = aParams.Length(); FallibleTArray<int32_t> idArray; if (!idArray.SetLength(size, fallible)) { aRv.Throw(NS_ERROR_OUT_OF_MEMORY); return nullptr; } DebugOnly<nsresult> rv; for (uint32_t i = 0; i < size; i++) { const OwningLongOrSmsMessageOrMmsMessage& element = aParams[i]; int32_t &id = idArray[i]; if (element.IsLong()) { id = element.GetAsLong(); } else if (element.IsMmsMessage()) { id = element.GetAsMmsMessage()->Id(); } else /*if (element.IsSmsMessage())*/ { id = element.GetAsSmsMessage()->Id(); } } return Delete(idArray.Elements(), size, aRv); }
already_AddRefed<DOMMatrix> DOMMatrix::Constructor(const GlobalObject& aGlobal, const Sequence<double>& aNumberSequence, ErrorResult& aRv) { RefPtr<DOMMatrix> obj = new DOMMatrix(aGlobal.GetAsSupports()); SetDataInMatrix(obj, aNumberSequence.Elements(), aNumberSequence.Length(), aRv); return obj.forget(); }
already_AddRefed<TouchList> TouchEvent::CopyTouches( const Sequence<OwningNonNull<Touch>>& aTouches) { RefPtr<TouchList> list = new TouchList(GetParentObject()); size_t len = aTouches.Length(); for (size_t i = 0; i < len; ++i) { list->Append(aTouches[i]); } return list.forget(); }
already_AddRefed<Promise> Cache::AddAll(const Sequence<OwningRequestOrUSVString>& aRequests, ErrorResult& aRv) { MOZ_ASSERT(mActor); nsRefPtr<Promise> promise = Promise::Create(mGlobal, aRv); if (!promise) { return nullptr; } // If there is no work to do, then resolve immediately if (aRequests.IsEmpty()) { promise->MaybeResolve(JS::UndefinedHandleValue); return promise.forget(); } AutoChildRequestList requests(this, aRequests.Length()); for (uint32_t i = 0; i < aRequests.Length(); ++i) { if (!IsValidPutRequestMethod(aRequests[i], aRv)) { return nullptr; } nsRefPtr<InternalRequest> ir = ToInternalRequest(aRequests[i], ReadBody, aRv); if (aRv.Failed()) { return nullptr; } requests.Add(ir, ReadBody, ExpandReferrer, NetworkErrorOnInvalidScheme, aRv); if (aRv.Failed()) { return nullptr; } } RequestId requestId = AddRequestPromise(promise, aRv); unused << mActor->SendAddAll(requestId, requests.SendAsRequestList()); return promise.forget(); }
bool CryptoKey::AllUsagesRecognized(const Sequence<nsString>& aUsages) { for (uint32_t i = 0; i < aUsages.Length(); ++i) { if (!IsRecognizedUsage(aUsages[i])) { return false; } } return true; }
void MultipartBlobImpl::InitializeBlob( JSContext* aCx, const Sequence<OwningArrayBufferOrArrayBufferViewOrBlobOrString>& aData, const nsAString& aContentType, bool aNativeEOL, ErrorResult& aRv) { mContentType = aContentType; BlobSet blobSet; for (uint32_t i = 0, len = aData.Length(); i < len; ++i) { const OwningArrayBufferOrArrayBufferViewOrBlobOrString& data = aData[i]; if (data.IsBlob()) { nsRefPtr<Blob> blob = data.GetAsBlob().get(); blobSet.AppendBlobImpl(blob->Impl()); } else if (data.IsString()) { aRv = blobSet.AppendString(data.GetAsString(), aNativeEOL, aCx); if (aRv.Failed()) { return; } } else if (data.IsArrayBuffer()) { const ArrayBuffer& buffer = data.GetAsArrayBuffer(); buffer.ComputeLengthAndData(); aRv = blobSet.AppendVoidPtr(buffer.Data(), buffer.Length()); if (aRv.Failed()) { return; } } else if (data.IsArrayBufferView()) { const ArrayBufferView& buffer = data.GetAsArrayBufferView(); buffer.ComputeLengthAndData(); aRv = blobSet.AppendVoidPtr(buffer.Data(), buffer.Length()); if (aRv.Failed()) { return; } } else { MOZ_CRASH("Impossible blob data type."); } } mBlobImpls = blobSet.GetBlobImpls(); SetLengthAndModifiedDate(); }
void Initialize(JSContext* aCx, Console::MethodName aName, const nsAString& aString, const Sequence<JS::Value>& aArguments) { mGlobal = JS::CurrentGlobalOrNull(aCx); mMethodName = aName; mMethodString = aString; for (uint32_t i = 0; i < aArguments.Length(); ++i) { mArguments.AppendElement(aArguments[i]); } }
void InternalHeaders::Fill(const Sequence<Sequence<nsCString>>& aInit, ErrorResult& aRv) { for (uint32_t i = 0; i < aInit.Length() && !aRv.Failed(); ++i) { const Sequence<nsCString>& tuple = aInit[i]; if (tuple.Length() != 2) { aRv.ThrowTypeError<MSG_INVALID_HEADER_SEQUENCE>(); return; } Append(tuple[0], tuple[1], aRv); } }
static nsCString ToCString(const Sequence<Type>& aSequence) { nsCString str; str.AppendLiteral("["); for (size_t i = 0; i < aSequence.Length(); i++) { if (i != 0) { str.AppendLiteral(","); } str.Append(ToCString(aSequence[i])); } str.AppendLiteral("]"); return str; }
void MultipartBlobImpl::InitializeBlob(const Sequence<Blob::BlobPart>& aData, const nsAString& aContentType, bool aNativeEOL, ErrorResult& aRv) { mContentType = aContentType; BlobSet blobSet; for (uint32_t i = 0, len = aData.Length(); i < len; ++i) { const Blob::BlobPart& data = aData[i]; if (data.IsBlob()) { RefPtr<Blob> blob = data.GetAsBlob().get(); blobSet.AppendBlobImpl(blob->Impl()); } else if (data.IsUSVString()) { aRv = blobSet.AppendString(data.GetAsUSVString(), aNativeEOL); if (aRv.Failed()) { return; } } else if (data.IsArrayBuffer()) { const ArrayBuffer& buffer = data.GetAsArrayBuffer(); buffer.ComputeLengthAndData(); aRv = blobSet.AppendVoidPtr(buffer.Data(), buffer.Length()); if (aRv.Failed()) { return; } } else if (data.IsArrayBufferView()) { const ArrayBufferView& buffer = data.GetAsArrayBufferView(); buffer.ComputeLengthAndData(); aRv = blobSet.AppendVoidPtr(buffer.Data(), buffer.Length()); if (aRv.Failed()) { return; } } else { MOZ_CRASH("Impossible blob data type."); } } mBlobImpls = blobSet.GetBlobImpls(); SetLengthAndModifiedDate(aRv); NS_WARNING_ASSERTION(!aRv.Failed(), "SetLengthAndModifiedDate failed"); }
// static nsresult KeyPath::Parse(const Sequence<nsString>& aStrings, KeyPath* aKeyPath) { KeyPath keyPath(0); keyPath.SetType(ARRAY); for (uint32_t i = 0; i < aStrings.Length(); ++i) { if (!keyPath.AppendStringWithValidation(aStrings[i])) { return NS_ERROR_FAILURE; } } *aKeyPath = keyPath; return NS_OK; }
void BluetoothAdapter::DispatchAttributeEvent(const Sequence<nsString>& aTypes) { NS_ENSURE_TRUE_VOID(aTypes.Length()); BluetoothAttributeEventInit init; init.mAttrs = aTypes; nsRefPtr<BluetoothAttributeEvent> event = BluetoothAttributeEvent::Constructor( this, NS_LITERAL_STRING(ATTRIBUTE_CHANGED_ID), init); DispatchTrustedEvent(event); }
bool nsScreen::MozLockOrientation(const Sequence<nsString>& aOrientations, ErrorResult& aRv) { if (ShouldResistFingerprinting()) { return false; } hal::ScreenOrientation orientation = hal::eScreenOrientation_None; for (uint32_t i = 0; i < aOrientations.Length(); ++i) { const nsString& item = aOrientations[i]; if (item.EqualsLiteral("portrait")) { orientation |= hal::eScreenOrientation_PortraitPrimary | hal::eScreenOrientation_PortraitSecondary; } else if (item.EqualsLiteral("portrait-primary")) { orientation |= hal::eScreenOrientation_PortraitPrimary; } else if (item.EqualsLiteral("portrait-secondary")) { orientation |= hal::eScreenOrientation_PortraitSecondary; } else if (item.EqualsLiteral("landscape")) { orientation |= hal::eScreenOrientation_LandscapePrimary | hal::eScreenOrientation_LandscapeSecondary; } else if (item.EqualsLiteral("landscape-primary")) { orientation |= hal::eScreenOrientation_LandscapePrimary; } else if (item.EqualsLiteral("landscape-secondary")) { orientation |= hal::eScreenOrientation_LandscapeSecondary; } else if (item.EqualsLiteral("default")) { orientation |= hal::eScreenOrientation_Default; } else { // If we don't recognize the token, we should just return 'false' // without throwing. return false; } } switch (mScreenOrientation->GetLockOrientationPermission(false)) { case ScreenOrientation::LOCK_DENIED: return false; case ScreenOrientation::LOCK_ALLOWED: UpdateDocShellOrientationLock(GetOwner(), orientation); return mScreenOrientation->LockDeviceOrientation(orientation, false, aRv); case ScreenOrientation::FULLSCREEN_LOCK_ALLOWED: UpdateDocShellOrientationLock(GetOwner(), orientation); return mScreenOrientation->LockDeviceOrientation(orientation, true, aRv); } // This is only for compilers that don't understand that the previous switch // will always return. MOZ_CRASH("unexpected lock orientation permission value"); }
already_AddRefed<nsIDocument> nsDOMParser::ParseFromBuffer(const Sequence<uint8_t>& aBuf, uint32_t aBufLen, SupportedType aType, ErrorResult& rv) { if (aBufLen > aBuf.Length()) { rv.Throw(NS_ERROR_XPC_NOT_ENOUGH_ELEMENTS_IN_ARRAY); return nullptr; } nsCOMPtr<nsIDOMDocument> domDocument; rv = nsDOMParser::ParseFromBuffer(aBuf.Elements(), aBufLen, SupportedTypeValues::strings[aType].value, getter_AddRefs(domDocument)); nsCOMPtr<nsIDocument> document(do_QueryInterface(domDocument)); return document.forget(); }
void nsBrowserElement::SendTouchEvent(const nsAString& aType, const Sequence<uint32_t>& aIdentifiers, const Sequence<int32_t>& aXs, const Sequence<int32_t>& aYs, const Sequence<uint32_t>& aRxs, const Sequence<uint32_t>& aRys, const Sequence<float>& aRotationAngles, const Sequence<float>& aForces, uint32_t aCount, uint32_t aModifiers, ErrorResult& aRv) { NS_ENSURE_TRUE_VOID(IsBrowserElementOrThrow(aRv)); NS_ENSURE_TRUE_VOID(IsNotWidgetOrThrow(aRv)); if (aIdentifiers.Length() != aCount || aXs.Length() != aCount || aYs.Length() != aCount || aRxs.Length() != aCount || aRys.Length() != aCount || aRotationAngles.Length() != aCount || aForces.Length() != aCount) { aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR); return; } nsresult rv = mBrowserElementAPI->SendTouchEvent(aType, aIdentifiers.Elements(), aXs.Elements(), aYs.Elements(), aRxs.Elements(), aRys.Elements(), aRotationAngles.Elements(), aForces.Elements(), aCount, aModifiers); if (NS_WARN_IF(NS_FAILED(rv))) { aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); } }
/* static */ bool MediaKeySystemAccess::IsSupported(const nsAString& aKeySystem, const Sequence<MediaKeySystemOptions>& aOptions) { nsCOMPtr<mozIGeckoMediaPluginService> mps = do_GetService("@mozilla.org/gecko-media-plugin-service;1"); if (NS_WARN_IF(!mps)) { return false; } for (size_t i = 0; i < aOptions.Length(); i++) { const MediaKeySystemOptions& options = aOptions[i]; if (!options.mInitDataType.EqualsLiteral("cenc")) { continue; } if (!options.mAudioCapability.IsEmpty() || !options.mVideoCapability.IsEmpty()) { // Don't support any capabilites until we know we have a CDM with // capabilities... continue; } if (!options.mAudioType.IsEmpty() && !IsPlayableWithGMP(mps, aKeySystem, options.mAudioType)) { continue; } if (!options.mVideoType.IsEmpty() && !IsPlayableWithGMP(mps, aKeySystem, options.mVideoType)) { continue; } // Our sandbox provides an origin specific unique identifier, and the // ability to persist data. We don't yet have a way to turn those off // and on for specific GMPs/CDMs, so we don't check the uniqueidentifier // and stateful attributes here. return true; } return false; }
bool nsScreen::MozLockOrientation(const Sequence<nsString>& aOrientations, ErrorResult& aRv) { ScreenOrientation orientation = eScreenOrientation_None; for (uint32_t i = 0; i < aOrientations.Length(); ++i) { const nsString& item = aOrientations[i]; if (item.EqualsLiteral("portrait")) { orientation |= eScreenOrientation_PortraitPrimary | eScreenOrientation_PortraitSecondary; } else if (item.EqualsLiteral("portrait-primary")) { orientation |= eScreenOrientation_PortraitPrimary; } else if (item.EqualsLiteral("portrait-secondary")) { orientation |= eScreenOrientation_PortraitSecondary; } else if (item.EqualsLiteral("landscape")) { orientation |= eScreenOrientation_LandscapePrimary | eScreenOrientation_LandscapeSecondary; } else if (item.EqualsLiteral("landscape-primary")) { orientation |= eScreenOrientation_LandscapePrimary; } else if (item.EqualsLiteral("landscape-secondary")) { orientation |= eScreenOrientation_LandscapeSecondary; } else { // If we don't recognize the token, we should just return 'false' // without throwing. return false; } } switch (GetLockOrientationPermission()) { case LOCK_DENIED: return false; case LOCK_ALLOWED: return hal::LockScreenOrientation(orientation); case FULLSCREEN_LOCK_ALLOWED: { // We need to register a listener so we learn when we leave full-screen // and when we will have to unlock the screen. // This needs to be done before LockScreenOrientation call to make sure // the locking can be unlocked. nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(GetOwner()); if (!target) { return false; } if (!hal::LockScreenOrientation(orientation)) { return false; } // We are fullscreen and lock has been accepted. if (!mEventListener) { mEventListener = new FullScreenEventListener(); } aRv = target->AddSystemEventListener(NS_LITERAL_STRING("mozfullscreenchange"), mEventListener, /* useCapture = */ true); return true; } } // This is only for compilers that don't understand that the previous switch // will always return. MOZ_NOT_REACHED(); return false; }
already_AddRefed<WebSocket> WebSocket::Constructor(JSContext* aCx, nsISupports* aGlobal, const nsAString& aUrl, const Sequence<nsString>& aProtocols, ErrorResult& aRv) { if (!PrefEnabled()) { aRv.Throw(NS_ERROR_DOM_SECURITY_ERR); return nullptr; } nsCOMPtr<nsIScriptObjectPrincipal> scriptPrincipal = do_QueryInterface(aGlobal); if (!scriptPrincipal) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } nsCOMPtr<nsIPrincipal> principal = scriptPrincipal->GetPrincipal(); if (!principal) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(aGlobal); if (!sgo) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } nsCOMPtr<nsPIDOMWindow> ownerWindow = do_QueryInterface(aGlobal); if (!ownerWindow) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } nsTArray<nsString> protocolArray; for (uint32_t index = 0, len = aProtocols.Length(); index < len; ++index) { const nsString& protocolElement = aProtocols[index]; if (protocolElement.IsEmpty()) { aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR); return nullptr; } if (protocolArray.Contains(protocolElement)) { aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR); return nullptr; } if (protocolElement.FindChar(',') != -1) /* interferes w/list */ { aRv.Throw(NS_ERROR_DOM_SYNTAX_ERR); return nullptr; } protocolArray.AppendElement(protocolElement); } nsRefPtr<WebSocket> webSocket = new WebSocket(); nsresult rv = webSocket->Init(aCx, principal, ownerWindow, aUrl, protocolArray); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; } return webSocket.forget(); }
void MessagePort::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage, const Sequence<JSObject*>& aTransferable, ErrorResult& aRv) { // We *must* clone the data here, or the JS::Value could be modified // by script // Here we want to check if the transerable object list contains // this port. for (uint32_t i = 0; i < aTransferable.Length(); ++i) { JS::Rooted<JSObject*> object(aCx, aTransferable[i]); if (!object) { continue; } MessagePort* port = nullptr; nsresult rv = UNWRAP_OBJECT(MessagePort, &object, port); if (NS_SUCCEEDED(rv) && port == this) { aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR); return; } } JS::Rooted<JS::Value> transferable(aCx, JS::UndefinedValue()); aRv = nsContentUtils::CreateJSValueFromSequenceOfObject(aCx, aTransferable, &transferable); if (NS_WARN_IF(aRv.Failed())) { return; } RefPtr<SharedMessagePortMessage> data = new SharedMessagePortMessage(); UniquePtr<AbstractTimelineMarker> start; UniquePtr<AbstractTimelineMarker> end; RefPtr<TimelineConsumers> timelines = TimelineConsumers::Get(); bool isTimelineRecording = timelines && !timelines->IsEmpty(); if (isTimelineRecording) { start = MakeUnique<MessagePortTimelineMarker>( ProfileTimelineMessagePortOperationType::SerializeData, MarkerTracingType::START); } data->Write(aCx, aMessage, transferable, aRv); if (isTimelineRecording) { end = MakeUnique<MessagePortTimelineMarker>( ProfileTimelineMessagePortOperationType::SerializeData, MarkerTracingType::END); timelines->AddMarkerForAllObservedDocShells(start); timelines->AddMarkerForAllObservedDocShells(end); } if (NS_WARN_IF(aRv.Failed())) { return; } // This message has to be ignored. if (mState > eStateEntangled) { return; } // If we are unshipped we are connected to the other port on the same thread. if (mState == eStateUnshippedEntangled) { MOZ_ASSERT(mUnshippedEntangledPort); mUnshippedEntangledPort->mMessages.AppendElement(data); mUnshippedEntangledPort->Dispatch(); return; } // Not entangled yet, but already closed/disentangled. if (mState == eStateEntanglingForDisentangle || mState == eStateEntanglingForClose) { return; } RemoveDocFromBFCache(); // Not entangled yet. if (mState == eStateEntangling) { mMessagesForTheOtherPort.AppendElement(data); return; } MOZ_ASSERT(mActor); MOZ_ASSERT(mMessagesForTheOtherPort.IsEmpty()); AutoTArray<RefPtr<SharedMessagePortMessage>, 1> array; array.AppendElement(data); AutoTArray<ClonedMessageData, 1> messages; // note: `messages` will borrow the underlying buffer, but this is okay // because reverse destruction order means `messages` will be destroyed prior // to `array`/`data`. SharedMessagePortMessage::FromSharedToMessagesChild(mActor, array, messages); mActor->SendPostMessages(messages); }
already_AddRefed<Promise> WebAuthentication::MakeCredential(JSContext* aCx, const Account& aAccount, const Sequence<ScopedCredentialParameters>& aCryptoParameters, const ArrayBufferViewOrArrayBuffer& aChallenge, const ScopedCredentialOptions& aOptions) { MOZ_ASSERT(mParent); nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetParentObject()); if (!global) { return nullptr; } ErrorResult rv; RefPtr<Promise> promise = Promise::Create(global, rv); nsresult initRv = InitLazily(); if (NS_FAILED(initRv)) { promise->MaybeReject(initRv); return promise.forget(); } // 4.1.1.1 If timeoutSeconds was specified, check if its value lies within a // reasonable range as defined by the platform and if not, correct it to the // closest value lying within that range. double adjustedTimeout = 30.0; if (aOptions.mTimeoutSeconds.WasPassed()) { adjustedTimeout = aOptions.mTimeoutSeconds.Value(); adjustedTimeout = std::max(15.0, adjustedTimeout); adjustedTimeout = std::min(120.0, adjustedTimeout); } // 4.1.1.2 Let promise be a new Promise. Return promise and start a timer for // adjustedTimeout seconds. RefPtr<CredentialRequest> requestMonitor = new CredentialRequest(); requestMonitor->SetDeadline(TimeDuration::FromSeconds(adjustedTimeout)); if (mOrigin.EqualsLiteral("null")) { // 4.1.1.3 If callerOrigin is an opaque origin, reject promise with a // DOMException whose name is "NotAllowedError", and terminate this // algorithm MOZ_LOG(gWebauthLog, LogLevel::Debug, ("Rejecting due to opaque origin")); promise->MaybeReject(NS_ERROR_DOM_NOT_ALLOWED_ERR); return promise.forget(); } nsCString rpId; if (!aOptions.mRpId.WasPassed()) { // 4.1.1.3.a If rpId is not specified, then set rpId to callerOrigin, and // rpIdHash to the SHA-256 hash of rpId. rpId.Assign(NS_ConvertUTF16toUTF8(mOrigin)); } else { // 4.1.1.3.b If rpId is specified, then invoke the procedure used for // relaxing the same-origin restriction by setting the document.domain // attribute, using rpId as the given value but without changing the current // document’s domain. If no errors are thrown, set rpId to the value of host // as computed by this procedure, and rpIdHash to the SHA-256 hash of rpId. // Otherwise, reject promise with a DOMException whose name is // "SecurityError", and terminate this algorithm. if (NS_FAILED(RelaxSameOrigin(aOptions.mRpId.Value(), rpId))) { promise->MaybeReject(NS_ERROR_DOM_SECURITY_ERR); return promise.forget(); } } CryptoBuffer rpIdHash; if (!rpIdHash.SetLength(SHA256_LENGTH, fallible)) { promise->MaybeReject(NS_ERROR_OUT_OF_MEMORY); return promise.forget(); } nsresult srv; nsCOMPtr<nsICryptoHash> hashService = do_CreateInstance(NS_CRYPTO_HASH_CONTRACTID, &srv); if (NS_WARN_IF(NS_FAILED(srv))) { promise->MaybeReject(NS_ERROR_DOM_SECURITY_ERR); return promise.forget(); } srv = HashCString(hashService, rpId, rpIdHash); if (NS_WARN_IF(NS_FAILED(srv))) { promise->MaybeReject(NS_ERROR_DOM_SECURITY_ERR); return promise.forget(); } // 4.1.1.4 Process each element of cryptoParameters using the following steps, // to produce a new sequence normalizedParameters. nsTArray<ScopedCredentialParameters> normalizedParams; for (size_t a = 0; a < aCryptoParameters.Length(); ++a) { // 4.1.1.4.a Let current be the currently selected element of // cryptoParameters. // 4.1.1.4.b If current.type does not contain a ScopedCredentialType // supported by this implementation, then stop processing current and move // on to the next element in cryptoParameters. if (aCryptoParameters[a].mType != ScopedCredentialType::ScopedCred) { continue; } // 4.1.1.4.c Let normalizedAlgorithm be the result of normalizing an // algorithm using the procedure defined in [WebCryptoAPI], with alg set to // current.algorithm and op set to 'generateKey'. If an error occurs during // this procedure, then stop processing current and move on to the next // element in cryptoParameters. nsString algName; if (NS_FAILED(GetAlgorithmName(aCx, aCryptoParameters[a].mAlgorithm, algName))) { continue; } // 4.1.1.4.d Add a new object of type ScopedCredentialParameters to // normalizedParameters, with type set to current.type and algorithm set to // normalizedAlgorithm. ScopedCredentialParameters normalizedObj; normalizedObj.mType = aCryptoParameters[a].mType; normalizedObj.mAlgorithm.SetAsString().Assign(algName); if (!normalizedParams.AppendElement(normalizedObj, mozilla::fallible)){ promise->MaybeReject(NS_ERROR_OUT_OF_MEMORY); return promise.forget(); } } // 4.1.1.5 If normalizedAlgorithm is empty and cryptoParameters was not empty, // cancel the timer started in step 2, reject promise with a DOMException // whose name is "NotSupportedError", and terminate this algorithm. if (normalizedParams.IsEmpty() && !aCryptoParameters.IsEmpty()) { promise->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR); return promise.forget(); } // 4.1.1.6 If excludeList is undefined, set it to the empty list. // 4.1.1.7 If extensions was specified, process any extensions supported by // this client platform, to produce the extension data that needs to be sent // to the authenticator. If an error is encountered while processing an // extension, skip that extension and do not produce any extension data for // it. Call the result of this processing clientExtensions. // Currently no extensions are supported // 4.1.1.8 Use attestationChallenge, callerOrigin and rpId, along with the // token binding key associated with callerOrigin (if any), to create a // ClientData structure representing this request. Choose a hash algorithm for // hashAlg and compute the clientDataJSON and clientDataHash. CryptoBuffer challenge; if (!challenge.Assign(aChallenge)) { promise->MaybeReject(NS_ERROR_DOM_SECURITY_ERR); return promise.forget(); } nsAutoCString clientDataJSON; srv = AssembleClientData(mOrigin, challenge, clientDataJSON); if (NS_WARN_IF(NS_FAILED(srv))) { promise->MaybeReject(NS_ERROR_DOM_SECURITY_ERR); return promise.forget(); } CryptoBuffer clientDataHash; if (!clientDataHash.SetLength(SHA256_LENGTH, fallible)) { promise->MaybeReject(NS_ERROR_DOM_SECURITY_ERR); return promise.forget(); } srv = HashCString(hashService, clientDataJSON, clientDataHash); if (NS_WARN_IF(NS_FAILED(srv))) { promise->MaybeReject(NS_ERROR_DOM_SECURITY_ERR); return promise.forget(); } // 4.1.1.9 Initialize issuedRequests to an empty list. RefPtr<CredentialPromise> monitorPromise = requestMonitor->Ensure(); // 4.1.1.10 For each authenticator currently available on this platform: // asynchronously invoke the authenticatorMakeCredential operation on that // authenticator with rpIdHash, clientDataHash, accountInformation, // normalizedParameters, excludeList and clientExtensions as parameters. Add a // corresponding entry to issuedRequests. for (Authenticator u2ftoken : mAuthenticators) { // 4.1.1.10.a For each credential C in excludeList that has a non-empty // transports list, optionally use only the specified transports to test for // the existence of C. U2FAuthMakeCredential(requestMonitor, u2ftoken, rpIdHash, clientDataJSON, clientDataHash, aAccount, normalizedParams, aOptions.mExcludeList, aOptions.mExtensions); } requestMonitor->CompleteTask(); monitorPromise->Then(AbstractThread::MainThread(), __func__, [promise] (CredentialPtr aInfo) { promise->MaybeResolve(aInfo); }, [promise] (nsresult aErrorCode) { promise->MaybeReject(aErrorCode); }); return promise.forget(); }
#include <catch.hpp> #include <nsearch/Sequence.h> #include <nsearch/Alphabet/DNA.h> TEST_CASE( "Sequence" ) { Sequence< DNA > seq( "Id", "ACCT", "JJ::" ); REQUIRE( seq.Length() == 4 ); REQUIRE( seq.identifier == "Id" ); REQUIRE( seq.sequence == "ACCT" ); REQUIRE( seq.quality == "JJ::" ); SECTION( "subsequence" ) { Sequence< DNA > sub = seq.Subsequence( 2, 2 ); REQUIRE( sub.sequence == "CT" ); REQUIRE( sub.quality == "::" ); REQUIRE( seq.Subsequence( 2 ).sequence == "CT" ); REQUIRE( seq.Subsequence( 4 ).sequence == "" ); Sequence< DNA > sub3 = Sequence< DNA >( "ATTG" ).Subsequence( 10, 10 ); REQUIRE( sub3.sequence == "" ); } SECTION( "operator +" ) { Sequence< DNA > m = seq + Sequence< DNA >( "Id2", "GCTT", "BBAJ" ); REQUIRE( m.identifier == "Id" ); REQUIRE( m.sequence == "ACCTGCTT" ); REQUIRE( m.quality == "JJ::BBAJ" ); }