void Crypto::DisableRightClick(ErrorResult& aRv) { aRv.Throw(NS_ERROR_NOT_IMPLEMENTED); }
NS_IMETHODIMP FetchDriver::OnStartRequest(nsIRequest* aRequest, nsISupports* aContext) { AssertIsOnMainThread(); // Note, this can be called multiple times if we are doing an opaqueredirect. // In that case we will get a simulated OnStartRequest() and then the real // channel will call in with an errored OnStartRequest(). if (!mChannel) { MOZ_ASSERT(!mObserver); return NS_BINDING_ABORTED; } nsresult rv; aRequest->GetStatus(&rv); if (NS_FAILED(rv)) { FailWithNetworkError(rv); return rv; } // We should only get to the following code once. MOZ_ASSERT(!mPipeOutputStream); MOZ_ASSERT(mObserver); mNeedToObserveOnDataAvailable = mObserver->NeedOnDataAvailable(); RefPtr<InternalResponse> response; nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest); nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aRequest); // On a successful redirect we perform the following substeps of HTTP Fetch, // step 5, "redirect status", step 11. bool foundOpaqueRedirect = false; int64_t contentLength = InternalResponse::UNKNOWN_BODY_SIZE; rv = channel->GetContentLength(&contentLength); MOZ_ASSERT_IF(NS_FAILED(rv), contentLength == InternalResponse::UNKNOWN_BODY_SIZE); if (httpChannel) { uint32_t responseStatus; rv = httpChannel->GetResponseStatus(&responseStatus); MOZ_ASSERT(NS_SUCCEEDED(rv)); if (mozilla::net::nsHttpChannel::IsRedirectStatus(responseStatus)) { if (mRequest->GetRedirectMode() == RequestRedirect::Error) { FailWithNetworkError(NS_BINDING_ABORTED); return NS_BINDING_FAILED; } if (mRequest->GetRedirectMode() == RequestRedirect::Manual) { foundOpaqueRedirect = true; } } nsAutoCString statusText; rv = httpChannel->GetResponseStatusText(statusText); MOZ_ASSERT(NS_SUCCEEDED(rv)); response = new InternalResponse(responseStatus, statusText); response->Headers()->FillResponseHeaders(httpChannel); // If Content-Encoding or Transfer-Encoding headers are set, then the actual // Content-Length (which refer to the decoded data) is obscured behind the encodings. ErrorResult result; if (response->Headers()->Has(NS_LITERAL_CSTRING("content-encoding"), result) || response->Headers()->Has(NS_LITERAL_CSTRING("transfer-encoding"), result)) { // We cannot trust the content-length when content-encoding or // transfer-encoding are set. There are many servers which just // get this wrong. contentLength = InternalResponse::UNKNOWN_BODY_SIZE; } MOZ_ASSERT(!result.Failed()); } else { response = new InternalResponse(200, NS_LITERAL_CSTRING("OK")); ErrorResult result; nsAutoCString contentType; rv = channel->GetContentType(contentType); if (NS_SUCCEEDED(rv) && !contentType.IsEmpty()) { nsAutoCString contentCharset; channel->GetContentCharset(contentCharset); if (NS_SUCCEEDED(rv) && !contentCharset.IsEmpty()) { contentType += NS_LITERAL_CSTRING(";charset=") + contentCharset; } response->Headers()->Append(NS_LITERAL_CSTRING("Content-Type"), contentType, result); MOZ_ASSERT(!result.Failed()); } if (contentLength > 0) { nsAutoCString contentLenStr; contentLenStr.AppendInt(contentLength); response->Headers()->Append(NS_LITERAL_CSTRING("Content-Length"), contentLenStr, result); MOZ_ASSERT(!result.Failed()); } } nsCOMPtr<nsICacheInfoChannel> cic = do_QueryInterface(aRequest); if (cic && mAltDataListener) { // Skip the case that mAltDataListener->Status() equals to FALLBACK, that means // the opened channel for alternative data loading is reused for loading the // main data. if (mAltDataListener->Status() != AlternativeDataStreamListener::FALLBACK) { // Verify the cache ID is the same with from alternative data cache. // If the cache ID is different, droping the alternative data loading, // otherwise setup the response's alternative body and cacheInfoChannel. uint64_t cacheEntryId = 0; if (NS_SUCCEEDED(cic->GetCacheEntryId(&cacheEntryId)) && cacheEntryId != mAltDataListener->GetAlternativeDataCacheEntryId()) { mAltDataListener->Cancel(); } else { // AlternativeDataStreamListener::OnStartRequest had already been called, // the alternative data input stream and cacheInfo channel must be created. nsCOMPtr<nsICacheInfoChannel> cacheInfo = mAltDataListener->GetCacheInfoChannel(); nsCOMPtr<nsIInputStream> altInputStream = mAltDataListener->GetAlternativeInputStream(); MOZ_ASSERT(altInputStream && cacheInfo); response->SetAlternativeBody(altInputStream); nsMainThreadPtrHandle<nsICacheInfoChannel> handle( new nsMainThreadPtrHolder<nsICacheInfoChannel>("nsICacheInfoChannel", cacheInfo, false)); response->SetCacheInfoChannel(handle); } } else if (!mAltDataListener->GetAlternativeDataType().IsEmpty()) { // If the status is FALLBACK and the mAltDataListener::mAlternativeDataType // is not empty, that means the data need to be saved into cache, setup the // response's nsICacheInfoChannel for caching the data after loading. nsMainThreadPtrHandle<nsICacheInfoChannel> handle( new nsMainThreadPtrHolder<nsICacheInfoChannel>("nsICacheInfoChannel", cic, false)); response->SetCacheInfoChannel(handle); } } // We open a pipe so that we can immediately set the pipe's read end as the // response's body. Setting the segment size to UINT32_MAX means that the // pipe has infinite space. The nsIChannel will continue to buffer data in // xpcom events even if we block on a fixed size pipe. It might be possible // to suspend the channel and then resume when there is space available, but // for now use an infinite pipe to avoid blocking. nsCOMPtr<nsIInputStream> pipeInputStream; rv = NS_NewPipe(getter_AddRefs(pipeInputStream), getter_AddRefs(mPipeOutputStream), 0, /* default segment size */ UINT32_MAX /* infinite pipe */, true /* non-blocking input, otherwise you deadlock */, false /* blocking output, since the pipe is 'in'finite */ ); if (NS_WARN_IF(NS_FAILED(rv))) { FailWithNetworkError(rv); // Cancel request. return rv; } response->SetBody(pipeInputStream, contentLength); response->InitChannelInfo(channel); nsCOMPtr<nsIURI> channelURI; rv = channel->GetURI(getter_AddRefs(channelURI)); if (NS_WARN_IF(NS_FAILED(rv))) { FailWithNetworkError(rv); // Cancel request. return rv; } nsCOMPtr<nsILoadInfo> loadInfo; rv = channel->GetLoadInfo(getter_AddRefs(loadInfo)); if (NS_WARN_IF(NS_FAILED(rv))) { FailWithNetworkError(rv); return rv; } // Propagate any tainting from the channel back to our response here. This // step is not reflected in the spec because the spec is written such that // FetchEvent.respondWith() just passes the already-tainted Response back to // the outer fetch(). In gecko, however, we serialize the Response through // the channel and must regenerate the tainting from the channel in the // interception case. mRequest->MaybeIncreaseResponseTainting(loadInfo->GetTainting()); // Resolves fetch() promise which may trigger code running in a worker. Make // sure the Response is fully initialized before calling this. mResponse = BeginAndGetFilteredResponse(response, foundOpaqueRedirect); if (NS_WARN_IF(!mResponse)) { // Fail to generate a paddingInfo for opaque response. MOZ_DIAGNOSTIC_ASSERT(mResponse->Type() == ResponseType::Opaque); FailWithNetworkError(NS_ERROR_UNEXPECTED); return rv; } // From "Main Fetch" step 19: SRI-part1. if (ShouldCheckSRI(mRequest, mResponse) && mSRIMetadata.IsEmpty()) { nsIConsoleReportCollector* reporter = nullptr; if (mObserver) { reporter = mObserver->GetReporter(); } nsAutoCString sourceUri; if (mDocument && mDocument->GetDocumentURI()) { mDocument->GetDocumentURI()->GetAsciiSpec(sourceUri); } else if (!mWorkerScript.IsEmpty()) { sourceUri.Assign(mWorkerScript); } SRICheck::IntegrityMetadata(mRequest->GetIntegrity(), sourceUri, reporter, &mSRIMetadata); mSRIDataVerifier = new SRICheckDataVerifier(mSRIMetadata, sourceUri, reporter); // Do not retarget off main thread when using SRI API. return NS_OK; } nsCOMPtr<nsIEventTarget> sts = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID, &rv); if (NS_WARN_IF(NS_FAILED(rv))) { FailWithNetworkError(rv); // Cancel request. return rv; } // Try to retarget off main thread. if (nsCOMPtr<nsIThreadRetargetableRequest> rr = do_QueryInterface(aRequest)) { Unused << NS_WARN_IF(NS_FAILED(rr->RetargetDeliveryTo(sts))); } return NS_OK; }
already_AddRefed<Promise> MobileMessageManager::SetSmscAddress(const SmscAddress& aSmscAddress, const Optional<uint32_t>& aServiceId, ErrorResult& aRv) { nsCOMPtr<nsISmsService> smsService = do_GetService(SMS_SERVICE_CONTRACTID); if (!smsService) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } // Use the default one unless |serviceId| is available. uint32_t serviceId; nsresult rv; if (aServiceId.WasPassed()) { serviceId = aServiceId.Value(); } else { rv = smsService->GetSmsDefaultServiceId(&serviceId); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; } } nsCOMPtr<nsPIDOMWindowInner> window = GetOwner(); if (!window) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(window); if (!global) { aRv.Throw(NS_ERROR_UNEXPECTED); return nullptr; } RefPtr<Promise> promise = Promise::Create(global, aRv); if (aRv.Failed()) { return nullptr; } if (!aSmscAddress.mAddress.WasPassed()) { NS_WARNING("SmscAddress.address is a mandatory field and can not be omitted."); promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR); return promise.forget(); } nsString address = aSmscAddress.mAddress.Value(); TypeOfNumber ton = aSmscAddress.mTypeOfAddress.mTypeOfNumber; NumberPlanIdentification npi = aSmscAddress.mTypeOfAddress.mNumberPlanIdentification; // If the address begins with +, set TON to international no matter what has // passed in. if (!address.IsEmpty() && address[0] == '+') { ton = TypeOfNumber::International; } nsCOMPtr<nsIMobileMessageCallback> msgCallback = new MobileMessageCallback(promise); rv = smsService->SetSmscAddress(serviceId, address, static_cast<uint32_t>(ton), static_cast<uint32_t>(npi), msgCallback); if (NS_FAILED(rv)) { promise->MaybeReject(rv); return promise.forget(); } return promise.forget(); }
already_AddRefed<IDBRequest> IDBCursor::Update(JSContext* aCx, JS::Handle<JS::Value> aValue, ErrorResult& aRv) { AssertIsOnOwningThread(); if (!mTransaction->IsOpen()) { aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR); return nullptr; } if (!mTransaction->IsWriteAllowed()) { aRv.Throw(NS_ERROR_DOM_INDEXEDDB_READ_ONLY_ERR); return nullptr; } if (mTransaction->GetMode() == IDBTransaction::CLEANUP || IsSourceDeleted() || !mHaveValue || mType == Type_ObjectStoreKey || mType == Type_IndexKey || mContinueCalled) { aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR); return nullptr; } MOZ_ASSERT(mType == Type_ObjectStore || mType == Type_Index); MOZ_ASSERT(!mKey.IsUnset()); MOZ_ASSERT_IF(mType == Type_Index, !mPrimaryKey.IsUnset()); IDBObjectStore* objectStore; if (mType == Type_ObjectStore) { objectStore = mSourceObjectStore; } else { objectStore = mSourceIndex->ObjectStore(); } MOZ_ASSERT(objectStore); const Key& primaryKey = (mType == Type_ObjectStore) ? mKey : mPrimaryKey; RefPtr<IDBRequest> request; if (objectStore->HasValidKeyPath()) { // Make sure the object given has the correct keyPath value set on it. const KeyPath& keyPath = objectStore->GetKeyPath(); Key key; aRv = keyPath.ExtractKey(aCx, aValue, key); if (aRv.Failed()) { return nullptr; } if (key != primaryKey) { aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR); return nullptr; } request = objectStore->AddOrPut(aCx, aValue, /* aKey */ JS::UndefinedHandleValue, /* aOverwrite */ true, /* aFromCursor */ true, aRv); if (aRv.Failed()) { return nullptr; } } else { JS::Rooted<JS::Value> keyVal(aCx); aRv = primaryKey.ToJSVal(aCx, &keyVal); if (aRv.Failed()) { return nullptr; } request = objectStore->AddOrPut(aCx, aValue, keyVal, /* aOverwrite */ true, /* aFromCursor */ true, aRv); if (aRv.Failed()) { return nullptr; } } request->SetSource(this); if (mType == Type_ObjectStore) { IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " "database(%s).transaction(%s).objectStore(%s)." "cursor(%s).update(%s)", "IndexedDB %s: C T[%lld] R[%llu]: IDBCursor.update()", IDB_LOG_ID_STRING(), mTransaction->LoggingSerialNumber(), request->LoggingSerialNumber(), IDB_LOG_STRINGIFY(mTransaction->Database()), IDB_LOG_STRINGIFY(mTransaction), IDB_LOG_STRINGIFY(objectStore), IDB_LOG_STRINGIFY(mDirection), IDB_LOG_STRINGIFY(objectStore, primaryKey)); } else { IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " "database(%s).transaction(%s).objectStore(%s)." "index(%s).cursor(%s).update(%s)", "IndexedDB %s: C T[%lld] R[%llu]: IDBCursor.update()", IDB_LOG_ID_STRING(), mTransaction->LoggingSerialNumber(), request->LoggingSerialNumber(), IDB_LOG_STRINGIFY(mTransaction->Database()), IDB_LOG_STRINGIFY(mTransaction), IDB_LOG_STRINGIFY(objectStore), IDB_LOG_STRINGIFY(mSourceIndex), IDB_LOG_STRINGIFY(mDirection), IDB_LOG_STRINGIFY(objectStore, primaryKey)); } return request.forget(); }
nsresult DataStoreDB::UpgradeSchema(nsIDOMEvent* aEvent) { MOZ_ASSERT(NS_IsMainThread()); // This DB has been just created and we have to inform the callback about // this. mCreatedSchema = true; #ifdef DEBUG nsCOMPtr<IDBVersionChangeEvent> event = do_QueryInterface(aEvent); MOZ_ASSERT(event); Nullable<uint64_t> version = event->GetNewVersion(); MOZ_ASSERT(!version.IsNull()); MOZ_ASSERT(version.Value() == DATASTOREDB_VERSION); #endif ErrorResult error; JS::Rooted<JS::Value> result(nsContentUtils::RootingCx()); mRequest->GetResult(&result, error); if (NS_WARN_IF(error.Failed())) { return error.StealNSResult(); } MOZ_ASSERT(result.isObject()); IDBDatabase* database = nullptr; nsresult rv = UNWRAP_OBJECT(IDBDatabase, &result.toObject(), database); if (NS_FAILED(rv)) { NS_WARNING("Didn't get the object we expected!"); return rv; } { IDBObjectStoreParameters params; params.Init(NS_LITERAL_STRING("{ \"autoIncrement\": true }")); RefPtr<IDBObjectStore> store = database->CreateObjectStore(NS_LITERAL_STRING(DATASTOREDB_NAME), params, error); if (NS_WARN_IF(error.Failed())) { return error.StealNSResult(); } } RefPtr<IDBObjectStore> store; { IDBObjectStoreParameters params; params.Init(NS_LITERAL_STRING("{ \"autoIncrement\": true, \"keyPath\": \"internalRevisionId\" }")); store = database->CreateObjectStore(NS_LITERAL_STRING(DATASTOREDB_REVISION), params, error); if (NS_WARN_IF(error.Failed())) { return error.StealNSResult(); } } { IDBIndexParameters params; params.Init(NS_LITERAL_STRING("{ \"unique\": true }")); RefPtr<IDBIndex> index = store->CreateIndex(NS_LITERAL_STRING(DATASTOREDB_REVISION_INDEX), NS_LITERAL_STRING("revisionId"), params, error); if (NS_WARN_IF(error.Failed())) { return error.StealNSResult(); } } return NS_OK; }
void HTMLTextAreaElement::SetRangeText(const nsAString& aReplacement, uint32_t aStart, uint32_t aEnd, const SelectionMode& aSelectMode, ErrorResult& aRv, int32_t aSelectionStart, int32_t aSelectionEnd) { if (aStart > aEnd) { aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR); return; } nsAutoString value; GetValueInternal(value, false); uint32_t inputValueLength = value.Length(); if (aStart > inputValueLength) { aStart = inputValueLength; } if (aEnd > inputValueLength) { aEnd = inputValueLength; } if (aSelectionStart == -1 && aSelectionEnd == -1) { aRv = GetSelectionRange(&aSelectionStart, &aSelectionEnd); if (aRv.Failed()) { if (mState.IsSelectionCached()) { aSelectionStart = mState.GetSelectionProperties().mStart; aSelectionEnd = mState.GetSelectionProperties().mEnd; aRv = NS_OK; } } } if (aStart <= aEnd) { value.Replace(aStart, aEnd - aStart, aReplacement); nsresult rv = SetValueInternal(value, nsTextEditorState::eSetValue_ByContent); if (NS_FAILED(rv)) { aRv.Throw(rv); return; } } uint32_t newEnd = aStart + aReplacement.Length(); int32_t delta = aReplacement.Length() - (aEnd - aStart); switch (aSelectMode) { case mozilla::dom::SelectionMode::Select: { aSelectionStart = aStart; aSelectionEnd = newEnd; } break; case mozilla::dom::SelectionMode::Start: { aSelectionStart = aSelectionEnd = aStart; } break; case mozilla::dom::SelectionMode::End: { aSelectionStart = aSelectionEnd = newEnd; } break; case mozilla::dom::SelectionMode::Preserve: { if ((uint32_t)aSelectionStart > aEnd) { aSelectionStart += delta; } else if ((uint32_t)aSelectionStart > aStart) { aSelectionStart = aStart; } if ((uint32_t)aSelectionEnd > aEnd) { aSelectionEnd += delta; } else if ((uint32_t)aSelectionEnd > aStart) { aSelectionEnd = newEnd; } } break; default: MOZ_CRASH("Unknown mode!"); } Optional<nsAString> direction; SetSelectionRange(aSelectionStart, aSelectionEnd, direction, aRv); }
void FileReaderSync::ReadAsText(JS::Handle<JSObject*> aBlob, const Optional<nsAString>& aEncoding, nsAString& aResult, ErrorResult& aRv) { nsIDOMBlob* blob = file::GetDOMBlobFromJSObject(aBlob); if (!blob) { aRv.Throw(NS_ERROR_INVALID_ARG); return; } nsCOMPtr<nsIInputStream> stream; nsresult rv = blob->GetInternalStream(getter_AddRefs(stream)); if (NS_FAILED(rv)) { aRv.Throw(rv); return; } nsAutoCString encoding; unsigned char sniffBuf[3] = { 0, 0, 0 }; uint32_t numRead; rv = stream->Read(reinterpret_cast<char*>(sniffBuf), sizeof(sniffBuf), &numRead); if (NS_FAILED(rv)) { aRv.Throw(rv); return; } // The BOM sniffing is baked into the "decode" part of the Encoding // Standard, which the File API references. if (!nsContentUtils::CheckForBOM(sniffBuf, numRead, encoding)) { // BOM sniffing failed. Try the API argument. if (!aEncoding.WasPassed() || !EncodingUtils::FindEncodingForLabel(aEncoding.Value(), encoding)) { // API argument failed. Try the type property of the blob. nsAutoString type16; blob->GetType(type16); NS_ConvertUTF16toUTF8 type(type16); nsAutoCString specifiedCharset; bool haveCharset; int32_t charsetStart, charsetEnd; NS_ExtractCharsetFromContentType(type, specifiedCharset, &haveCharset, &charsetStart, &charsetEnd); if (!EncodingUtils::FindEncodingForLabel(specifiedCharset, encoding)) { // Type property failed. Use UTF-8. encoding.AssignLiteral("UTF-8"); } } } nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(stream); if (!seekable) { aRv.Throw(NS_ERROR_FAILURE); return; } // Seek to 0 because to undo the BOM sniffing advance. UTF-8 and UTF-16 // decoders will swallow the BOM. rv = seekable->Seek(nsISeekableStream::NS_SEEK_SET, 0); if (NS_FAILED(rv)) { aRv.Throw(rv); return; } rv = ConvertStream(stream, encoding.get(), aResult); if (NS_FAILED(rv)) { aRv.Throw(rv); return; } }
already_AddRefed<Promise> ServiceWorkerRegistrationMainThread::Unregister(ErrorResult& aRv) { AssertIsOnMainThread(); nsCOMPtr<nsIGlobalObject> go = do_QueryInterface(GetOwner()); if (!go) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } // Although the spec says that the same-origin checks should also be done // asynchronously, we do them in sync because the Promise created by the // WebIDL infrastructure due to a returned error will be resolved // asynchronously. We aren't making any internal state changes in these // checks, so ordering of multiple calls is not affected. nsCOMPtr<nsIDocument> document = GetOwner()->GetExtantDoc(); if (!document) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } nsCOMPtr<nsIURI> scopeURI; nsCOMPtr<nsIURI> baseURI = document->GetBaseURI(); // "If the origin of scope is not client's origin..." nsresult rv = NS_NewURI(getter_AddRefs(scopeURI), mScope, nullptr, baseURI); if (NS_WARN_IF(NS_FAILED(rv))) { aRv.Throw(NS_ERROR_DOM_SECURITY_ERR); return nullptr; } nsCOMPtr<nsIPrincipal> documentPrincipal = document->NodePrincipal(); rv = documentPrincipal->CheckMayLoad(scopeURI, true /* report */, false /* allowIfInheritsPrinciple */); if (NS_FAILED(rv)) { aRv.Throw(NS_ERROR_DOM_SECURITY_ERR); return nullptr; } nsAutoCString uriSpec; aRv = scopeURI->GetSpecIgnoringRef(uriSpec); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } nsCOMPtr<nsIServiceWorkerManager> swm = mozilla::services::GetServiceWorkerManager(); RefPtr<Promise> promise = Promise::Create(go, aRv); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } RefPtr<UnregisterCallback> cb = new UnregisterCallback(promise); NS_ConvertUTF8toUTF16 scope(uriSpec); aRv = swm->Unregister(documentPrincipal, cb, scope); if (aRv.Failed()) { return nullptr; } return promise.forget(); }
/* static */ already_AddRefed<BroadcastChannel> BroadcastChannel::Constructor(const GlobalObject& aGlobal, const nsAString& aChannel, ErrorResult& aRv) { nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal.GetAsSupports()); // Window is null in workers. nsAutoString origin; PrincipalInfo principalInfo; bool privateBrowsing = false; WorkerPrivate* workerPrivate = nullptr; if (NS_IsMainThread()) { nsCOMPtr<nsIGlobalObject> incumbent = mozilla::dom::GetIncumbentGlobal(); if (!incumbent) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } nsIPrincipal* principal = incumbent->PrincipalOrNull(); if (!principal) { aRv.Throw(NS_ERROR_UNEXPECTED); return nullptr; } bool isNullPrincipal; aRv = principal->GetIsNullPrincipal(&isNullPrincipal); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } if (NS_WARN_IF(isNullPrincipal)) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } GetOrigin(principal, origin, aRv); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } aRv = PrincipalToPrincipalInfo(principal, &principalInfo); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } nsIDocument* doc = window->GetExtantDoc(); if (doc) { privateBrowsing = nsContentUtils::IsInPrivateBrowsing(doc); // No bfcache when BroadcastChannel is used. doc->DisallowBFCaching(); } } else { JSContext* cx = aGlobal.Context(); workerPrivate = GetWorkerPrivateFromContext(cx); MOZ_ASSERT(workerPrivate); nsRefPtr<InitializeRunnable> runnable = new InitializeRunnable(workerPrivate, origin, principalInfo, privateBrowsing, aRv); runnable->Dispatch(cx); } if (aRv.Failed()) { return nullptr; } nsRefPtr<BroadcastChannel> bc = new BroadcastChannel(window, principalInfo, origin, aChannel, privateBrowsing); // Register this component to PBackground. PBackgroundChild* actor = BackgroundChild::GetForCurrentThread(); if (actor) { bc->ActorCreated(actor); } else { BackgroundChild::GetOrCreateForCurrentThread(bc); } if (!workerPrivate) { MOZ_ASSERT(window); MOZ_ASSERT(window->IsInnerWindow()); bc->mInnerID = window->WindowID(); // Register as observer for inner-window-destroyed. nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService(); if (obs) { obs->AddObserver(bc, "inner-window-destroyed", false); } } else { bc->mWorkerFeature = new BroadcastChannelFeature(bc); JSContext* cx = workerPrivate->GetJSContext(); if (NS_WARN_IF(!workerPrivate->AddFeature(cx, bc->mWorkerFeature))) { NS_WARNING("Failed to register the BroadcastChannel worker feature."); bc->mWorkerFeature = nullptr; aRv.Throw(NS_ERROR_FAILURE); return nullptr; } } return bc.forget(); }
mozilla::ipc::IPCResult CacheOpChild::Recv__delete__( const ErrorResult& aRv, const CacheOpResult& aResult) { NS_ASSERT_OWNINGTHREAD(CacheOpChild); if (NS_WARN_IF(aRv.Failed())) { MOZ_DIAGNOSTIC_ASSERT(aResult.type() == CacheOpResult::Tvoid_t); // TODO: Remove this const_cast (bug 1152078). // It is safe for now since this ErrorResult is handed off to us by IPDL // and is thrown into the trash afterwards. mPromise->MaybeReject(const_cast<ErrorResult&>(aRv)); mPromise = nullptr; return IPC_OK(); } switch (aResult.type()) { case CacheOpResult::TCacheMatchResult: { HandleResponse(aResult.get_CacheMatchResult().maybeResponse()); break; } case CacheOpResult::TCacheMatchAllResult: { HandleResponseList(aResult.get_CacheMatchAllResult().responseList()); break; } case CacheOpResult::TCachePutAllResult: { mPromise->MaybeResolveWithUndefined(); break; } case CacheOpResult::TCacheDeleteResult: { mPromise->MaybeResolve(aResult.get_CacheDeleteResult().success()); break; } case CacheOpResult::TCacheKeysResult: { HandleRequestList(aResult.get_CacheKeysResult().requestList()); break; } case CacheOpResult::TStorageMatchResult: { HandleResponse(aResult.get_StorageMatchResult().maybeResponse()); break; } case CacheOpResult::TStorageHasResult: { mPromise->MaybeResolve(aResult.get_StorageHasResult().success()); break; } case CacheOpResult::TStorageOpenResult: { auto result = aResult.get_StorageOpenResult(); auto actor = static_cast<CacheChild*>(result.actorChild()); // If we have a success status then we should have an actor. Gracefully // reject instead of crashing, though, if we get a nullptr here. MOZ_DIAGNOSTIC_ASSERT(actor); if (!actor) { ErrorResult status; status.ThrowTypeError<MSG_CACHE_OPEN_FAILED>(); mPromise->MaybeReject(status); break; } RefPtr<CacheWorkerHolder> workerHolder = CacheWorkerHolder::PreferBehavior( GetWorkerHolder(), CacheWorkerHolder::AllowIdleShutdownStart); actor->SetWorkerHolder(workerHolder); RefPtr<Cache> cache = new Cache(mGlobal, actor, result.ns()); mPromise->MaybeResolve(cache); break; } case CacheOpResult::TStorageDeleteResult: { mPromise->MaybeResolve(aResult.get_StorageDeleteResult().success()); break; } case CacheOpResult::TStorageKeysResult: { mPromise->MaybeResolve(aResult.get_StorageKeysResult().keyList()); break; } default: MOZ_CRASH("Unknown Cache op result type!"); } mPromise = nullptr; return IPC_OK(); }
already_AddRefed<DetailedPromise> MediaKeys::Init(ErrorResult& aRv) { RefPtr<DetailedPromise> promise(MakePromise(aRv, NS_LITERAL_CSTRING("MediaKeys::Init()"))); if (aRv.Failed()) { return nullptr; } mProxy = new CDMProxy(this, mKeySystem); // Determine principal (at creation time) of the MediaKeys object. nsCOMPtr<nsIScriptObjectPrincipal> sop = do_QueryInterface(GetParentObject()); if (!sop) { promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR, NS_LITERAL_CSTRING("Couldn't get script principal in MediaKeys::Init")); return promise.forget(); } mPrincipal = sop->GetPrincipal(); // Determine principal of the "top-level" window; the principal of the // page that will display in the URL bar. nsCOMPtr<nsPIDOMWindowInner> window = GetParentObject(); if (!window) { promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR, NS_LITERAL_CSTRING("Couldn't get top-level window in MediaKeys::Init")); return promise.forget(); } nsCOMPtr<nsPIDOMWindowOuter> top = window->GetOuterWindow()->GetTop(); if (!top || !top->GetExtantDoc()) { promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR, NS_LITERAL_CSTRING("Couldn't get document in MediaKeys::Init")); return promise.forget(); } mTopLevelPrincipal = top->GetExtantDoc()->NodePrincipal(); if (!mPrincipal || !mTopLevelPrincipal) { NS_WARNING("Failed to get principals when creating MediaKeys"); promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR, NS_LITERAL_CSTRING("Couldn't get principal(s) in MediaKeys::Init")); return promise.forget(); } nsAutoString origin; nsresult rv = nsContentUtils::GetUTFOrigin(mPrincipal, origin); if (NS_FAILED(rv)) { promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR, NS_LITERAL_CSTRING("Couldn't get principal origin string in MediaKeys::Init")); return promise.forget(); } nsAutoString topLevelOrigin; rv = nsContentUtils::GetUTFOrigin(mTopLevelPrincipal, topLevelOrigin); if (NS_FAILED(rv)) { promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR, NS_LITERAL_CSTRING("Couldn't get top-level principal origin string in MediaKeys::Init")); return promise.forget(); } nsIDocument* doc = window->GetExtantDoc(); const bool inPrivateBrowsing = nsContentUtils::IsInPrivateBrowsing(doc); EME_LOG("MediaKeys[%p]::Create() (%s, %s), %s", this, NS_ConvertUTF16toUTF8(origin).get(), NS_ConvertUTF16toUTF8(topLevelOrigin).get(), (inPrivateBrowsing ? "PrivateBrowsing" : "NonPrivateBrowsing")); // The CDMProxy's initialization is asynchronous. The MediaKeys is // refcounted, and its instance is returned to JS by promise once // it's been initialized. No external refs exist to the MediaKeys while // we're waiting for the promise to be resolved, so we must hold a // reference to the new MediaKeys object until it's been created, // or its creation has failed. Store the id of the promise returned // here, and hold a self-reference until that promise is resolved or // rejected. MOZ_ASSERT(!mCreatePromiseId, "Should only be created once!"); mCreatePromiseId = StorePromise(promise); AddRef(); mProxy->Init(mCreatePromiseId, origin, topLevelOrigin, KeySystemToGMPName(mKeySystem), inPrivateBrowsing, new MediaKeysGMPCrashHelper(this)); return promise.forget(); }
void HTMLTextAreaElement::SetRangeText(const nsAString& aReplacement, uint32_t aStart, uint32_t aEnd, const SelectionMode& aSelectMode, ErrorResult& aRv, int32_t aSelectionStart, int32_t aSelectionEnd) { if (aStart > aEnd) { aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR); return; } nsAutoString value; GetValueInternal(value, false); uint32_t inputValueLength = value.Length(); if (aStart > inputValueLength) { aStart = inputValueLength; } if (aEnd > inputValueLength) { aEnd = inputValueLength; } if (aSelectionStart == -1 && aSelectionEnd == -1) { aRv = GetSelectionRange(&aSelectionStart, &aSelectionEnd); if (aRv.Failed()) { if (mState.IsSelectionCached()) { aSelectionStart = mState.GetSelectionProperties().mStart; aSelectionEnd = mState.GetSelectionProperties().mEnd; aRv = NS_OK; } } } if (aStart <= aEnd) { value.Replace(aStart, aEnd - aStart, aReplacement); SetValueInternal(value, false); } uint32_t newEnd = aStart + aReplacement.Length(); int32_t delta = aReplacement.Length() - (aEnd - aStart); switch (aSelectMode) { case mozilla::dom::SelectionMode::Select: { aSelectionStart = aStart; aSelectionEnd = newEnd; } break; case mozilla::dom::SelectionMode::Start: { aSelectionStart = aSelectionEnd = aStart; } break; case mozilla::dom::SelectionMode::End: { aSelectionStart = aSelectionEnd = newEnd; } break; case mozilla::dom::SelectionMode::Preserve: { if ((uint32_t)aSelectionStart > aEnd) { aSelectionStart += delta; } else if ((uint32_t)aSelectionStart > aStart) { aSelectionStart = aStart; } if ((uint32_t)aSelectionEnd > aEnd) { aSelectionEnd += delta; } else if ((uint32_t)aSelectionEnd > aStart) { aSelectionEnd = newEnd; } } break; } Optional<nsAString> direction; SetSelectionRange(aSelectionStart, aSelectionEnd, direction, aRv); if (!aRv.Failed()) { nsRefPtr<nsAsyncDOMEvent> event = new nsAsyncDOMEvent(this, NS_LITERAL_STRING("select"), true, false); event->PostDOMEvent(); } }
void DOMSVGPathSegList::InternalListWillChangeTo(const SVGPathData& aNewValue) { // When the number of items in our internal counterpart changes, we MUST stay // in sync. Everything in the scary comment in // DOMSVGLengthList::InternalBaseValListWillChangeTo applies here just as // much, but we have the additional issue that failing to stay in sync would // mean that - assuming we aren't reading bad memory - we would likely end up // decoding command types from argument floats when looking in our // SVGPathData's data array! Either way, we'll likely then go down // NS_NOTREACHED code paths, or end up reading/setting more bad memory!! // The only time that our other DOM list type implementations remove items is // if those items become surplus items due to an attribute change or SMIL // animation sample shortening the list. In general though, they try to keep // their existing DOM items, even when things change. To be consistent, we'd // really like to do the same thing. However, because different types of path // segment correspond to different DOMSVGPathSeg subclasses, the type of // items in our list are generally not the same, which makes this harder for // us. We have to remove DOM segments if their type is not the same as the // type of the new internal segment at their index. // // We also need to sync up mInternalDataIndex, but since we need to loop over // all the items in the new list checking types anyway, that's almost // insignificant in terms of overhead. // // Note that this method is called on every single SMIL animation resample // and we have no way to short circuit the overhead since we don't have a // way to tell if the call is due to a new animation, or a resample of an // existing animation (when the number and type of items would be the same). // (Note that a new animation could start overriding an existing animation at // any time, so checking IsAnimating() wouldn't work.) Because we get called // on every sample, it would not be acceptable alternative to throw away all // our items and let them be recreated lazily, since that would break what // script sees! uint32_t length = mItems.Length(); uint32_t index = 0; uint32_t dataLength = aNewValue.mData.Length(); uint32_t dataIndex = 0; // index into aNewValue's raw data array uint32_t newSegType; nsRefPtr<DOMSVGPathSegList> kungFuDeathGrip; if (length) { // RemovingFromList() might clear last reference to |this|. // Retain a temporary reference to keep from dying before returning. // // NOTE: For path-seg lists (unlike other list types), we have to do this // *whenever our list is nonempty* (even if we're growing in length). // That's because the path-seg-type of any segment could differ between old // list vs. new list, which will make us destroy & recreate that segment, // which could remove the last reference to us. // // (We explicitly *don't* want to create a kungFuDeathGrip in the length=0 // case, though, because we do hit this code inside our constructor before // any other owning references have been added, and at that point, the // deathgrip-removal would make us die before we exit our constructor.) kungFuDeathGrip = this; } while (index < length && dataIndex < dataLength) { newSegType = SVGPathSegUtils::DecodeType(aNewValue.mData[dataIndex]); if (ItemAt(index) && ItemAt(index)->Type() != newSegType) { ItemAt(index)->RemovingFromList(); ItemAt(index) = nullptr; } // Only after the RemovingFromList() can we touch mInternalDataIndex! mItems[index].mInternalDataIndex = dataIndex; ++index; dataIndex += 1 + SVGPathSegUtils::ArgCountForType(newSegType); } NS_ABORT_IF_FALSE((index == length && dataIndex <= dataLength) || (index <= length && dataIndex == dataLength), "very bad - list corruption?"); if (index < length) { // aNewValue has fewer items than our previous internal counterpart uint32_t newLength = index; // Remove excess items from the list: for (; index < length; ++index) { if (ItemAt(index)) { ItemAt(index)->RemovingFromList(); ItemAt(index) = nullptr; } } // Only now may we truncate mItems mItems.SetLength(newLength); } else if (dataIndex < dataLength) { // aNewValue has more items than our previous internal counterpart // Sync mItems: while (dataIndex < dataLength) { if (mItems.Length() && mItems.Length() - 1 > DOMSVGPathSeg::MaxListIndex()) { // It's safe to get out of sync with our internal list as long as we // have FEWER items than it does. return; } if (!mItems.AppendElement(ItemProxy(nullptr, dataIndex))) { // OOM ErrorResult rv; Clear(rv); MOZ_ASSERT(!rv.Failed()); return; } dataIndex += 1 + SVGPathSegUtils::ArgCountForType(SVGPathSegUtils::DecodeType(aNewValue.mData[dataIndex])); } } NS_ABORT_IF_FALSE(dataIndex == dataLength, "Serious processing error"); NS_ABORT_IF_FALSE(index == length, "Serious counting error"); }
already_AddRefed<DOMSVGPathSeg> DOMSVGPathSegList::ReplaceItem(DOMSVGPathSeg& aNewItem, uint32_t aIndex, ErrorResult& aError) { if (IsAnimValList()) { aError.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR); return nullptr; } if (aIndex >= LengthNoFlush()) { aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR); return nullptr; } nsRefPtr<DOMSVGPathSeg> domItem = &aNewItem; if (domItem->HasOwner()) { domItem = domItem->Clone(); // must do this before changing anything! } nsAttrValue emptyOrOldValue = Element()->WillChangePathSegList(); if (ItemAt(aIndex)) { // Notify any existing DOM item of removal *before* modifying the lists so // that the DOM item can copy the *old* value at its index: ItemAt(aIndex)->RemovingFromList(); } uint32_t internalIndex = mItems[aIndex].mInternalDataIndex; // We use InternalList() to get oldArgCount since we may not have a DOM // wrapper at the index being replaced. uint32_t oldType = SVGPathSegUtils::DecodeType(InternalList().mData[internalIndex]); // NOTE: ArgCountForType returns a (small) unsigned value, but we're // intentionally putting it in a signed variable, because we're going to // subtract these values and might produce something negative. int32_t oldArgCount = SVGPathSegUtils::ArgCountForType(oldType); int32_t newArgCount = SVGPathSegUtils::ArgCountForType(domItem->Type()); float segAsRaw[1 + NS_SVG_PATH_SEG_MAX_ARGS]; domItem->ToSVGPathSegEncodedData(segAsRaw); bool ok = !!InternalList().mData.ReplaceElementsAt( internalIndex, 1 + oldArgCount, segAsRaw, 1 + newArgCount); if (!ok) { aError.Throw(NS_ERROR_OUT_OF_MEMORY); return nullptr; } ItemAt(aIndex) = domItem; // This MUST come after the ToSVGPathSegEncodedData call, otherwise that call // would end up reading bad data from InternalList()! domItem->InsertingIntoList(this, aIndex, IsAnimValList()); int32_t delta = newArgCount - oldArgCount; if (delta != 0) { for (uint32_t i = aIndex + 1; i < LengthNoFlush(); ++i) { mItems[i].mInternalDataIndex += delta; } } Element()->DidChangePathSegList(emptyOrOldValue); if (AttrIsAnimating()) { Element()->AnimationNeedsResample(); } return domItem.forget(); }
NS_IMETHODIMP nsROCSSPrimitiveValue::GetCssText(nsAString& aCssText) { nsAutoString tmpStr; aCssText.Truncate(); nsresult result = NS_OK; switch (mType) { case CSS_PX : { float val = nsPresContext::AppUnitsToFloatCSSPixels(mValue.mAppUnits); nsStyleUtil::AppendCSSNumber(val, tmpStr); tmpStr.AppendLiteral("px"); break; } case CSS_IDENT : { AppendUTF8toUTF16(nsCSSKeywords::GetStringValue(mValue.mKeyword), tmpStr); break; } case CSS_STRING : case CSS_COUNTER : /* FIXME: COUNTER should use an object */ { tmpStr.Append(mValue.mString); break; } case CSS_URI : { if (mValue.mURI) { nsAutoCString specUTF8; mValue.mURI->GetSpec(specUTF8); tmpStr.AssignLiteral("url("); nsStyleUtil::AppendEscapedCSSString(NS_ConvertUTF8toUTF16(specUTF8), tmpStr); tmpStr.AppendLiteral(")"); } else { // http://dev.w3.org/csswg/css3-values/#attr defines // 'about:invalid' as the default value for url attributes, // so let's also use it here as the default computed value // for invalid URLs. tmpStr.Assign(NS_LITERAL_STRING("url(about:invalid)")); } break; } case CSS_ATTR : { tmpStr.AppendLiteral("attr("); tmpStr.Append(mValue.mString); tmpStr.Append(char16_t(')')); break; } case CSS_PERCENTAGE : { nsStyleUtil::AppendCSSNumber(mValue.mFloat * 100, tmpStr); tmpStr.Append(char16_t('%')); break; } case CSS_NUMBER : { nsStyleUtil::AppendCSSNumber(mValue.mFloat, tmpStr); break; } case CSS_DEG : { nsStyleUtil::AppendCSSNumber(mValue.mFloat, tmpStr); tmpStr.AppendLiteral("deg"); break; } case CSS_GRAD : { nsStyleUtil::AppendCSSNumber(mValue.mFloat, tmpStr); tmpStr.AppendLiteral("grad"); break; } case CSS_RAD : { nsStyleUtil::AppendCSSNumber(mValue.mFloat, tmpStr); tmpStr.AppendLiteral("rad"); break; } case CSS_TURN : { nsStyleUtil::AppendCSSNumber(mValue.mFloat, tmpStr); tmpStr.AppendLiteral("turn"); break; } case CSS_RECT : { NS_ASSERTION(mValue.mRect, "mValue.mRect should never be null"); NS_NAMED_LITERAL_STRING(comma, ", "); nsCOMPtr<nsIDOMCSSPrimitiveValue> sideCSSValue; nsAutoString sideValue; tmpStr.AssignLiteral("rect("); // get the top result = mValue.mRect->GetTop(getter_AddRefs(sideCSSValue)); if (NS_FAILED(result)) break; result = sideCSSValue->GetCssText(sideValue); if (NS_FAILED(result)) break; tmpStr.Append(sideValue + comma); // get the right result = mValue.mRect->GetRight(getter_AddRefs(sideCSSValue)); if (NS_FAILED(result)) break; result = sideCSSValue->GetCssText(sideValue); if (NS_FAILED(result)) break; tmpStr.Append(sideValue + comma); // get the bottom result = mValue.mRect->GetBottom(getter_AddRefs(sideCSSValue)); if (NS_FAILED(result)) break; result = sideCSSValue->GetCssText(sideValue); if (NS_FAILED(result)) break; tmpStr.Append(sideValue + comma); // get the left result = mValue.mRect->GetLeft(getter_AddRefs(sideCSSValue)); if (NS_FAILED(result)) break; result = sideCSSValue->GetCssText(sideValue); if (NS_FAILED(result)) break; tmpStr.Append(sideValue + NS_LITERAL_STRING(")")); break; } case CSS_RGBCOLOR : { NS_ASSERTION(mValue.mColor, "mValue.mColor should never be null"); ErrorResult error; NS_NAMED_LITERAL_STRING(comma, ", "); nsAutoString colorValue; if (mValue.mColor->HasAlpha()) tmpStr.AssignLiteral("rgba("); else tmpStr.AssignLiteral("rgb("); // get the red component mValue.mColor->Red()->GetCssText(colorValue, error); if (error.Failed()) break; tmpStr.Append(colorValue + comma); // get the green component mValue.mColor->Green()->GetCssText(colorValue, error); if (error.Failed()) break; tmpStr.Append(colorValue + comma); // get the blue component mValue.mColor->Blue()->GetCssText(colorValue, error); if (error.Failed()) break; tmpStr.Append(colorValue); if (mValue.mColor->HasAlpha()) { // get the alpha component mValue.mColor->Alpha()->GetCssText(colorValue, error); if (error.Failed()) break; tmpStr.Append(comma + colorValue); } tmpStr.Append(NS_LITERAL_STRING(")")); break; } case CSS_S : { nsStyleUtil::AppendCSSNumber(mValue.mFloat, tmpStr); tmpStr.AppendLiteral("s"); break; } case CSS_CM : case CSS_MM : case CSS_IN : case CSS_PT : case CSS_PC : case CSS_UNKNOWN : case CSS_EMS : case CSS_EXS : case CSS_MS : case CSS_HZ : case CSS_KHZ : case CSS_DIMENSION : NS_ERROR("We have a bogus value set. This should not happen"); return NS_ERROR_DOM_INVALID_ACCESS_ERR; } if (NS_SUCCEEDED(result)) { aCssText.Assign(tmpStr); } return NS_OK; }
NS_IMETHODIMP FetchDriver::OnStartRequest(nsIRequest* aRequest, nsISupports* aContext) { workers::AssertIsOnMainThread(); // Note, this can be called multiple times if we are doing an opaqueredirect. // In that case we will get a simulated OnStartRequest() and then the real // channel will call in with an errored OnStartRequest(). nsresult rv; aRequest->GetStatus(&rv); if (NS_FAILED(rv)) { FailWithNetworkError(); return rv; } // We should only get to the following code once. MOZ_ASSERT(!mPipeOutputStream); MOZ_ASSERT(mObserver); RefPtr<InternalResponse> response; nsCOMPtr<nsIChannel> channel = do_QueryInterface(aRequest); nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aRequest); // On a successful redirect we perform the following substeps of HTTP Fetch, // step 5, "redirect status", step 11. bool foundOpaqueRedirect = false; if (httpChannel) { uint32_t responseStatus; httpChannel->GetResponseStatus(&responseStatus); if (mozilla::net::nsHttpChannel::IsRedirectStatus(responseStatus)) { if (mRequest->GetRedirectMode() == RequestRedirect::Error) { FailWithNetworkError(); return NS_BINDING_FAILED; } if (mRequest->GetRedirectMode() == RequestRedirect::Manual) { foundOpaqueRedirect = true; } } nsAutoCString statusText; httpChannel->GetResponseStatusText(statusText); response = new InternalResponse(responseStatus, statusText); RefPtr<FillResponseHeaders> visitor = new FillResponseHeaders(response); rv = httpChannel->VisitResponseHeaders(visitor); if (NS_WARN_IF(NS_FAILED(rv))) { NS_WARNING("Failed to visit all headers."); } } else { response = new InternalResponse(200, NS_LITERAL_CSTRING("OK")); ErrorResult result; nsAutoCString contentType; rv = channel->GetContentType(contentType); if (NS_SUCCEEDED(rv) && !contentType.IsEmpty()) { nsAutoCString contentCharset; channel->GetContentCharset(contentCharset); if (NS_SUCCEEDED(rv) && !contentCharset.IsEmpty()) { contentType += NS_LITERAL_CSTRING(";charset=") + contentCharset; } response->Headers()->Append(NS_LITERAL_CSTRING("Content-Type"), contentType, result); MOZ_ASSERT(!result.Failed()); } int64_t contentLength; rv = channel->GetContentLength(&contentLength); if (NS_SUCCEEDED(rv) && contentLength) { nsAutoCString contentLenStr; contentLenStr.AppendInt(contentLength); response->Headers()->Append(NS_LITERAL_CSTRING("Content-Length"), contentLenStr, result); MOZ_ASSERT(!result.Failed()); } } // We open a pipe so that we can immediately set the pipe's read end as the // response's body. Setting the segment size to UINT32_MAX means that the // pipe has infinite space. The nsIChannel will continue to buffer data in // xpcom events even if we block on a fixed size pipe. It might be possible // to suspend the channel and then resume when there is space available, but // for now use an infinite pipe to avoid blocking. nsCOMPtr<nsIInputStream> pipeInputStream; rv = NS_NewPipe(getter_AddRefs(pipeInputStream), getter_AddRefs(mPipeOutputStream), 0, /* default segment size */ UINT32_MAX /* infinite pipe */, true /* non-blocking input, otherwise you deadlock */, false /* blocking output, since the pipe is 'in'finite */ ); if (NS_WARN_IF(NS_FAILED(rv))) { FailWithNetworkError(); // Cancel request. return rv; } response->SetBody(pipeInputStream); response->InitChannelInfo(channel); nsCOMPtr<nsIURI> channelURI; rv = channel->GetURI(getter_AddRefs(channelURI)); if (NS_WARN_IF(NS_FAILED(rv))) { FailWithNetworkError(); // Cancel request. return rv; } nsCOMPtr<nsILoadInfo> loadInfo; rv = channel->GetLoadInfo(getter_AddRefs(loadInfo)); if (NS_WARN_IF(NS_FAILED(rv))) { FailWithNetworkError(); return rv; } // Propagate any tainting from the channel back to our response here. This // step is not reflected in the spec because the spec is written such that // FetchEvent.respondWith() just passes the already-tainted Response back to // the outer fetch(). In gecko, however, we serialize the Response through // the channel and must regenerate the tainting from the channel in the // interception case. mRequest->MaybeIncreaseResponseTainting(loadInfo->GetTainting()); // Resolves fetch() promise which may trigger code running in a worker. Make // sure the Response is fully initialized before calling this. mResponse = BeginAndGetFilteredResponse(response, foundOpaqueRedirect); nsCOMPtr<nsIEventTarget> sts = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID, &rv); if (NS_WARN_IF(NS_FAILED(rv))) { FailWithNetworkError(); // Cancel request. return rv; } // Try to retarget off main thread. if (nsCOMPtr<nsIThreadRetargetableRequest> rr = do_QueryInterface(aRequest)) { NS_WARN_IF(NS_FAILED(rr->RetargetDeliveryTo(sts))); } return NS_OK; }
void MessagePort::PostMessage(JSContext* aCx, JS::Handle<JS::Value> aMessage, const Optional<Sequence<JS::Value>>& aTransferable, ErrorResult& aRv) { // We *must* clone the data here, or the JS::Value could be modified // by script JS::Rooted<JS::Value> transferable(aCx, JS::UndefinedValue()); if (aTransferable.WasPassed()) { const Sequence<JS::Value>& realTransferable = aTransferable.Value(); // Here we want to check if the transerable object list contains // this port. No other checks are done. for (const JS::Value& value : realTransferable) { if (!value.isObject()) { continue; } MessagePort* port = nullptr; nsresult rv = UNWRAP_OBJECT(MessagePort, &value.toObject(), port); if (NS_FAILED(rv)) { continue; } if (port == this) { aRv.Throw(NS_ERROR_DOM_DATA_CLONE_ERR); return; } } // The input sequence only comes from the generated bindings code, which // ensures it is rooted. JS::HandleValueArray elements = JS::HandleValueArray::fromMarkedLocation(realTransferable.Length(), realTransferable.Elements()); JSObject* array = JS_NewArrayObject(aCx, elements); if (!array) { aRv.Throw(NS_ERROR_OUT_OF_MEMORY); return; } transferable.setObject(*array); } RefPtr<SharedMessagePortMessage> data = new SharedMessagePortMessage(); data->Write(aCx, aMessage, transferable, aRv); 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<MessagePortMessage, 1> messages; SharedMessagePortMessage::FromSharedToMessagesChild(mActor, array, messages); mActor->SendPostMessages(messages); }
already_AddRefed<IDBRequest> IDBIndex::GetAllInternal(bool aKeysOnly, JSContext* aCx, JS::Handle<JS::Value> aKey, const Optional<uint32_t>& aLimit, ErrorResult& aRv) { AssertIsOnOwningThread(); IDBTransaction* transaction = mObjectStore->Transaction(); if (!transaction->IsOpen()) { aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR); return nullptr; } nsRefPtr<IDBKeyRange> keyRange; aRv = IDBKeyRange::FromJSVal(aCx, aKey, getter_AddRefs(keyRange)); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } const int64_t objectStoreId = mObjectStore->Id(); const int64_t indexId = Id(); OptionalKeyRange optionalKeyRange; if (keyRange) { SerializedKeyRange serializedKeyRange; keyRange->ToSerialized(serializedKeyRange); optionalKeyRange = serializedKeyRange; } else { optionalKeyRange = void_t(); } const uint32_t limit = aLimit.WasPassed() ? aLimit.Value() : 0; RequestParams params; if (aKeysOnly) { params = IndexGetAllKeysParams(objectStoreId, indexId, optionalKeyRange, limit); } else { params = IndexGetAllParams(objectStoreId, indexId, optionalKeyRange, limit); } nsRefPtr<IDBRequest> request = GenerateRequest(this); MOZ_ASSERT(request); if (aKeysOnly) { IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " "database(%s).transaction(%s).objectStore(%s).index(%s)." "getAllKeys(%s, %s)", "IndexedDB %s: C T[%lld] R[%llu]: IDBIndex.getAllKeys()", IDB_LOG_ID_STRING(), transaction->LoggingSerialNumber(), request->LoggingSerialNumber(), IDB_LOG_STRINGIFY(transaction->Database()), IDB_LOG_STRINGIFY(transaction), IDB_LOG_STRINGIFY(mObjectStore), IDB_LOG_STRINGIFY(this), IDB_LOG_STRINGIFY(keyRange), IDB_LOG_STRINGIFY(aLimit)); } else { IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " "database(%s).transaction(%s).objectStore(%s).index(%s)." "getAll(%s, %s)", "IndexedDB %s: C T[%lld] R[%llu]: IDBIndex.getAll()", IDB_LOG_ID_STRING(), transaction->LoggingSerialNumber(), request->LoggingSerialNumber(), IDB_LOG_STRINGIFY(transaction->Database()), IDB_LOG_STRINGIFY(transaction), IDB_LOG_STRINGIFY(mObjectStore), IDB_LOG_STRINGIFY(this), IDB_LOG_STRINGIFY(keyRange), IDB_LOG_STRINGIFY(aLimit)); } transaction->StartRequest(request, params); return request.forget(); }
void nsDOMFileReader::ReadFileContent(JSContext* aCx, nsIDOMBlob* aFile, const nsAString &aCharset, eDataFormat aDataFormat, ErrorResult& aRv) { MOZ_ASSERT(aFile); //Implicit abort to clear any other activity going on Abort(); mError = nullptr; SetDOMStringToNull(mResult); mTransferred = 0; mTotal = 0; mReadyState = nsIDOMFileReader::EMPTY; FreeFileData(); mFile = aFile; mDataFormat = aDataFormat; CopyUTF16toUTF8(aCharset, mCharset); //Establish a channel with our file { // Hold the internal URL alive only as long as necessary // After the channel is created it will own whatever is backing // the DOMFile. nsDOMFileInternalUrlHolder urlHolder(mFile, mPrincipal); nsCOMPtr<nsIURI> uri; aRv = NS_NewURI(getter_AddRefs(uri), urlHolder.mUrl); NS_ENSURE_SUCCESS_VOID(aRv.ErrorCode()); nsCOMPtr<nsILoadGroup> loadGroup; if (HasOrHasHadOwner()) { if (!GetOwner()) { aRv.Throw(NS_ERROR_FAILURE); return; } nsIDocument* doc = GetOwner()->GetExtantDoc(); if (doc) { loadGroup = doc->GetDocumentLoadGroup(); } } aRv = NS_NewChannel(getter_AddRefs(mChannel), uri, nullptr, loadGroup, nullptr, nsIRequest::LOAD_BACKGROUND); NS_ENSURE_SUCCESS_VOID(aRv.ErrorCode()); } //Obtain the total size of the file before reading mTotal = mozilla::dom::kUnknownSize; mFile->GetSize(&mTotal); aRv = mChannel->AsyncOpen(this, nullptr); NS_ENSURE_SUCCESS_VOID(aRv.ErrorCode()); //FileReader should be in loading state here mReadyState = nsIDOMFileReader::LOADING; DispatchProgressEvent(NS_LITERAL_STRING(LOADSTART_STR)); if (mDataFormat == FILE_AS_ARRAYBUFFER) { RootResultArrayBuffer(); mResultArrayBuffer = JS_NewArrayBuffer(aCx, mTotal); if (!mResultArrayBuffer) { NS_WARNING("Failed to create JS array buffer"); aRv.Throw(NS_ERROR_FAILURE); } } }
already_AddRefed<IDBRequest> IDBIndex::OpenCursorInternal(bool aKeysOnly, JSContext* aCx, JS::Handle<JS::Value> aRange, IDBCursorDirection aDirection, ErrorResult& aRv) { AssertIsOnOwningThread(); IDBTransaction* transaction = mObjectStore->Transaction(); if (!transaction->IsOpen()) { aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR); return nullptr; } nsRefPtr<IDBKeyRange> keyRange; aRv = IDBKeyRange::FromJSVal(aCx, aRange, getter_AddRefs(keyRange)); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } int64_t objectStoreId = mObjectStore->Id(); int64_t indexId = Id(); OptionalKeyRange optionalKeyRange; if (keyRange) { SerializedKeyRange serializedKeyRange; keyRange->ToSerialized(serializedKeyRange); optionalKeyRange = Move(serializedKeyRange); } else { optionalKeyRange = void_t(); } IDBCursor::Direction direction = IDBCursor::ConvertDirection(aDirection); OpenCursorParams params; if (aKeysOnly) { IndexOpenKeyCursorParams openParams; openParams.objectStoreId() = objectStoreId; openParams.indexId() = indexId; openParams.optionalKeyRange() = Move(optionalKeyRange); openParams.direction() = direction; params = Move(openParams); } else { IndexOpenCursorParams openParams; openParams.objectStoreId() = objectStoreId; openParams.indexId() = indexId; openParams.optionalKeyRange() = Move(optionalKeyRange); openParams.direction() = direction; params = Move(openParams); } nsRefPtr<IDBRequest> request = GenerateRequest(this); MOZ_ASSERT(request); if (aKeysOnly) { IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " "database(%s).transaction(%s).objectStore(%s).index(%s)." "openKeyCursor(%s, %s)", "IndexedDB %s: C T[%lld] R[%llu]: IDBIndex.openKeyCursor()", IDB_LOG_ID_STRING(), transaction->LoggingSerialNumber(), request->LoggingSerialNumber(), IDB_LOG_STRINGIFY(transaction->Database()), IDB_LOG_STRINGIFY(transaction), IDB_LOG_STRINGIFY(mObjectStore), IDB_LOG_STRINGIFY(this), IDB_LOG_STRINGIFY(keyRange), IDB_LOG_STRINGIFY(direction)); } else { IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " "database(%s).transaction(%s).objectStore(%s).index(%s)." "openCursor(%s, %s)", "IndexedDB %s: C T[%lld] R[%llu]: " "IDBObjectStore.openKeyCursor()", IDB_LOG_ID_STRING(), transaction->LoggingSerialNumber(), request->LoggingSerialNumber(), IDB_LOG_STRINGIFY(transaction->Database()), IDB_LOG_STRINGIFY(transaction), IDB_LOG_STRINGIFY(mObjectStore), IDB_LOG_STRINGIFY(this), IDB_LOG_STRINGIFY(keyRange), IDB_LOG_STRINGIFY(direction)); } BackgroundCursorChild* actor = new BackgroundCursorChild(request, this, direction); mObjectStore->Transaction()->OpenCursor(actor, params); return request.forget(); }
void IDBCursor::ContinuePrimaryKey(JSContext* aCx, JS::Handle<JS::Value> aKey, JS::Handle<JS::Value> aPrimaryKey, ErrorResult &aRv) { AssertIsOnOwningThread(); if (!mTransaction->IsOpen()) { aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR); return; } if (IsSourceDeleted()) { aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR); return; } if ((mType != Type_Index && mType != Type_IndexKey) || (mDirection != NEXT && mDirection != PREV)) { aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR); return; } if (!mHaveValue || mContinueCalled) { aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR); return; } Key key; aRv = key.SetFromJSVal(aCx, aKey); if (aRv.Failed()) { return; } #ifdef ENABLE_INTL_API if (IsLocaleAware() && !key.IsUnset()) { Key tmp; aRv = key.ToLocaleBasedKey(tmp, mSourceIndex->Locale()); if (aRv.Failed()) { return; } key = tmp; } const Key& sortKey = IsLocaleAware() ? mSortKey : mKey; #else const Key& sortKey = mKey; #endif if (key.IsUnset()) { aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR); return; } Key primaryKey; aRv = primaryKey.SetFromJSVal(aCx, aPrimaryKey); if (aRv.Failed()) { return; } if (primaryKey.IsUnset()) { aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR); return; } switch (mDirection) { case NEXT: if (key < sortKey || (key == sortKey && primaryKey <= mPrimaryKey)) { aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR); return; } break; case PREV: if (key > sortKey || (key == sortKey && primaryKey >= mPrimaryKey)) { aRv.Throw(NS_ERROR_DOM_INDEXEDDB_DATA_ERR); return; } break; default: MOZ_CRASH("Unknown direction type!"); } const uint64_t requestSerialNumber = IDBRequest::NextSerialNumber(); mRequest->SetLoggingSerialNumber(requestSerialNumber); IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " "database(%s).transaction(%s).objectStore(%s)." "index(%s).cursor(%s).continuePrimaryKey(%s, %s)", "IndexedDB %s: C T[%lld] R[%llu]: IDBCursor.continuePrimaryKey()", IDB_LOG_ID_STRING(), mTransaction->LoggingSerialNumber(), requestSerialNumber, IDB_LOG_STRINGIFY(mTransaction->Database()), IDB_LOG_STRINGIFY(mTransaction), IDB_LOG_STRINGIFY(mSourceIndex->ObjectStore()), IDB_LOG_STRINGIFY(mSourceIndex), IDB_LOG_STRINGIFY(mDirection), IDB_LOG_STRINGIFY(key), IDB_LOG_STRINGIFY(primaryKey)); mBackgroundActor->SendContinueInternal(ContinuePrimaryKeyParams(key, primaryKey)); mContinueCalled = true; }
// XXXkhuey the encoding should be off the main thread, but we're lazy. void HTMLCanvasElement::ToBlob(JSContext* aCx, FileCallback& aCallback, const nsAString& aType, const Optional<JS::Handle<JS::Value> >& aParams, ErrorResult& aRv) { // do a trust check if this is a write-only canvas if (mWriteOnly && !nsContentUtils::IsCallerChrome()) { aRv.Throw(NS_ERROR_DOM_SECURITY_ERR); return; } nsAutoString type; aRv = nsContentUtils::ASCIIToLower(aType, type); if (aRv.Failed()) { return; } JS::Value encoderOptions = aParams.WasPassed() ? aParams.Value() : JS::UndefinedValue(); nsAutoString params; bool usingCustomParseOptions; aRv = ParseParams(aCx, type, encoderOptions, params, &usingCustomParseOptions); if (aRv.Failed()) { return; } bool fallbackToPNG = false; nsCOMPtr<nsIInputStream> stream; aRv = ExtractData(type, params, getter_AddRefs(stream), fallbackToPNG); // If there are unrecognized custom parse options, we should fall back to // the default values for the encoder without any options at all. if (aRv.ErrorCode() == NS_ERROR_INVALID_ARG && usingCustomParseOptions) { fallbackToPNG = false; aRv = ExtractData(type, EmptyString(), getter_AddRefs(stream), fallbackToPNG); } if (aRv.Failed()) { return; } if (fallbackToPNG) { type.AssignLiteral("image/png"); } uint64_t imgSize; aRv = stream->Available(&imgSize); if (aRv.Failed()) { return; } if (imgSize > UINT32_MAX) { aRv.Throw(NS_ERROR_FILE_TOO_BIG); return; } void* imgData = nullptr; aRv = NS_ReadInputStreamToBuffer(stream, &imgData, imgSize); if (aRv.Failed()) { return; } // The DOMFile takes ownership of the buffer nsRefPtr<nsDOMMemoryFile> blob = new nsDOMMemoryFile(imgData, imgSize, type); JSContext* cx = nsContentUtils::GetCurrentJSContext(); if (cx) { JS_updateMallocCounter(cx, imgSize); } nsRefPtr<ToBlobRunnable> runnable = new ToBlobRunnable(aCallback, blob); aRv = NS_DispatchToCurrentThread(runnable); }
already_AddRefed<IDBRequest> IDBCursor::Delete(JSContext* aCx, ErrorResult& aRv) { AssertIsOnOwningThread(); if (!mTransaction->IsOpen()) { aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR); return nullptr; } if (!mTransaction->IsWriteAllowed()) { aRv.Throw(NS_ERROR_DOM_INDEXEDDB_READ_ONLY_ERR); return nullptr; } if (IsSourceDeleted() || !mHaveValue || mType == Type_ObjectStoreKey || mType == Type_IndexKey || mContinueCalled) { aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR); return nullptr; } MOZ_ASSERT(mType == Type_ObjectStore || mType == Type_Index); MOZ_ASSERT(!mKey.IsUnset()); IDBObjectStore* objectStore; if (mType == Type_ObjectStore) { objectStore = mSourceObjectStore; } else { objectStore = mSourceIndex->ObjectStore(); } MOZ_ASSERT(objectStore); const Key& primaryKey = (mType == Type_ObjectStore) ? mKey : mPrimaryKey; JS::Rooted<JS::Value> key(aCx); aRv = primaryKey.ToJSVal(aCx, &key); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } RefPtr<IDBRequest> request = objectStore->DeleteInternal(aCx, key, /* aFromCursor */ true, aRv); if (aRv.Failed()) { return nullptr; } request->SetSource(this); if (mType == Type_ObjectStore) { IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " "database(%s).transaction(%s).objectStore(%s)." "cursor(%s).delete(%s)", "IndexedDB %s: C T[%lld] R[%llu]: IDBCursor.delete()", IDB_LOG_ID_STRING(), mTransaction->LoggingSerialNumber(), request->LoggingSerialNumber(), IDB_LOG_STRINGIFY(mTransaction->Database()), IDB_LOG_STRINGIFY(mTransaction), IDB_LOG_STRINGIFY(objectStore), IDB_LOG_STRINGIFY(mDirection), IDB_LOG_STRINGIFY(objectStore, primaryKey)); } else { IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " "database(%s).transaction(%s).objectStore(%s)." "index(%s).cursor(%s).delete(%s)", "IndexedDB %s: C T[%lld] R[%llu]: IDBCursor.delete()", IDB_LOG_ID_STRING(), mTransaction->LoggingSerialNumber(), request->LoggingSerialNumber(), IDB_LOG_STRINGIFY(mTransaction->Database()), IDB_LOG_STRINGIFY(mTransaction), IDB_LOG_STRINGIFY(objectStore), IDB_LOG_STRINGIFY(mSourceIndex), IDB_LOG_STRINGIFY(mDirection), IDB_LOG_STRINGIFY(objectStore, primaryKey)); } return request.forget(); }
bool HTMLRangeAccessible::SetCurValue(double aValue) { ErrorResult er; HTMLInputElement::FromNode(mContent)->SetValueAsNumber(aValue, er); return !er.Failed(); }
// This function implements the "HTTP Fetch" algorithm from the Fetch spec. // Functionality is often split between here, the CORS listener proxy and the // Necko HTTP implementation. nsresult FetchDriver::HttpFetch(const nsACString& aPreferredAlternativeDataType) { MOZ_ASSERT(NS_IsMainThread()); // Step 1. "Let response be null." mResponse = nullptr; mOnStopRequestCalled = false; nsresult rv; nsCOMPtr<nsIIOService> ios = do_GetIOService(&rv); NS_ENSURE_SUCCESS(rv, rv); nsAutoCString url; mRequest->GetURL(url); nsCOMPtr<nsIURI> uri; rv = NS_NewURI(getter_AddRefs(uri), url, nullptr, nullptr, ios); NS_ENSURE_SUCCESS(rv, rv); // Unsafe requests aren't allowed with when using no-core mode. if (mRequest->Mode() == RequestMode::No_cors && mRequest->UnsafeRequest() && (!mRequest->HasSimpleMethod() || !mRequest->Headers()->HasOnlySimpleHeaders())) { MOZ_ASSERT(false, "The API should have caught this"); return NS_ERROR_DOM_BAD_URI; } // non-GET requests aren't allowed for blob. if (IsBlobURI(uri)) { nsAutoCString method; mRequest->GetMethod(method); if (!method.EqualsLiteral("GET")) { return NS_ERROR_DOM_NETWORK_ERR; } } // Step 2 deals with letting ServiceWorkers intercept requests. This is // handled by Necko after the channel is opened. // FIXME(nsm): Bug 1119026: The channel's skip service worker flag should be // set based on the Request's flag. // Step 3.1 "If the CORS preflight flag is set and one of these conditions is // true..." is handled by the CORS proxy. // // Step 3.2 "Set request's skip service worker flag." This isn't required // since Necko will fall back to the network if the ServiceWorker does not // respond with a valid Response. // // NS_StartCORSPreflight() will automatically kick off the original request // if it succeeds, so we need to have everything setup for the original // request too. // Step 3.3 "Let credentials flag be set if one of // - request's credentials mode is "include" // - request's credentials mode is "same-origin" and either the CORS flag // is unset or response tainting is "opaque" // is true, and unset otherwise." // Set skip serviceworker flag. // While the spec also gates on the client being a ServiceWorker, we can't // infer that here. Instead we rely on callers to set the flag correctly. const nsLoadFlags bypassFlag = mRequest->SkipServiceWorker() ? nsIChannel::LOAD_BYPASS_SERVICE_WORKER : 0; nsSecurityFlags secFlags = nsILoadInfo::SEC_ABOUT_BLANK_INHERITS; if (mRequest->Mode() == RequestMode::Cors) { secFlags |= nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS; } else if (mRequest->Mode() == RequestMode::Same_origin || mRequest->Mode() == RequestMode::Navigate) { secFlags |= nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS; } else if (mRequest->Mode() == RequestMode::No_cors) { secFlags |= nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS; } else { MOZ_ASSERT_UNREACHABLE("Unexpected request mode!"); return NS_ERROR_UNEXPECTED; } if (mRequest->GetRedirectMode() != RequestRedirect::Follow) { secFlags |= nsILoadInfo::SEC_DONT_FOLLOW_REDIRECTS; } // This is handles the use credentials flag in "HTTP // network or cache fetch" in the spec and decides whether to transmit // cookies and other identifying information. if (mRequest->GetCredentialsMode() == RequestCredentials::Include) { secFlags |= nsILoadInfo::SEC_COOKIES_INCLUDE; } else if (mRequest->GetCredentialsMode() == RequestCredentials::Omit) { secFlags |= nsILoadInfo::SEC_COOKIES_OMIT; } else if (mRequest->GetCredentialsMode() == RequestCredentials::Same_origin) { secFlags |= nsILoadInfo::SEC_COOKIES_SAME_ORIGIN; } else { MOZ_ASSERT_UNREACHABLE("Unexpected credentials mode!"); return NS_ERROR_UNEXPECTED; } // From here on we create a channel and set its properties with the // information from the InternalRequest. This is an implementation detail. MOZ_ASSERT(mLoadGroup); nsCOMPtr<nsIChannel> chan; nsLoadFlags loadFlags = nsIRequest::LOAD_NORMAL | bypassFlag | nsIChannel::LOAD_CLASSIFY_URI; if (mDocument) { MOZ_ASSERT(mDocument->NodePrincipal() == mPrincipal); rv = NS_NewChannel(getter_AddRefs(chan), uri, mDocument, secFlags, mRequest->ContentPolicyType(), nullptr, /* aPerformanceStorage */ mLoadGroup, nullptr, /* aCallbacks */ loadFlags, ios); } else if (mClientInfo.isSome()) { rv = NS_NewChannel(getter_AddRefs(chan), uri, mPrincipal, mClientInfo.ref(), mController, secFlags, mRequest->ContentPolicyType(), mPerformanceStorage, mLoadGroup, nullptr, /* aCallbacks */ loadFlags, ios); } else { rv = NS_NewChannel(getter_AddRefs(chan), uri, mPrincipal, secFlags, mRequest->ContentPolicyType(), mPerformanceStorage, mLoadGroup, nullptr, /* aCallbacks */ loadFlags, ios); } NS_ENSURE_SUCCESS(rv, rv); // Insert ourselves into the notification callbacks chain so we can set // headers on redirects. #ifdef DEBUG { nsCOMPtr<nsIInterfaceRequestor> notificationCallbacks; chan->GetNotificationCallbacks(getter_AddRefs(notificationCallbacks)); MOZ_ASSERT(!notificationCallbacks); } #endif chan->SetNotificationCallbacks(this); nsCOMPtr<nsIClassOfService> cos(do_QueryInterface(chan)); // Mark channel as urgent-start if the Fetch is triggered by user input // events. if (cos && EventStateManager::IsHandlingUserInput()) { cos->AddClassFlags(nsIClassOfService::UrgentStart); } // Step 3.5 begins "HTTP network or cache fetch". // HTTP network or cache fetch // --------------------------- // Step 1 "Let HTTPRequest..." The channel is the HTTPRequest. nsCOMPtr<nsIHttpChannel> httpChan = do_QueryInterface(chan); if (httpChan) { // Copy the method. nsAutoCString method; mRequest->GetMethod(method); rv = httpChan->SetRequestMethod(method); NS_ENSURE_SUCCESS(rv, rv); // Set the same headers. SetRequestHeaders(httpChan); // Step 5 of https://fetch.spec.whatwg.org/#main-fetch // If request's referrer policy is the empty string and request's client is // non-null, then set request's referrer policy to request's client's // associated referrer policy. // Basically, "client" is not in our implementation, we use // EnvironmentReferrerPolicy of the worker or document context net::ReferrerPolicy net_referrerPolicy = mRequest->GetEnvironmentReferrerPolicy(); if (mRequest->ReferrerPolicy_() == ReferrerPolicy::_empty) { mRequest->SetReferrerPolicy(net_referrerPolicy); } // Step 6 of https://fetch.spec.whatwg.org/#main-fetch // If request’s referrer policy is the empty string, // then set request’s referrer policy to the user-set default policy. if (mRequest->ReferrerPolicy_() == ReferrerPolicy::_empty) { nsCOMPtr<nsILoadInfo> loadInfo = httpChan->GetLoadInfo(); bool isPrivate = loadInfo->GetOriginAttributes().mPrivateBrowsingId > 0; net::ReferrerPolicy referrerPolicy = static_cast<net::ReferrerPolicy>(NS_GetDefaultReferrerPolicy(isPrivate)); mRequest->SetReferrerPolicy(referrerPolicy); } rv = FetchUtil::SetRequestReferrer(mPrincipal, mDocument, httpChan, mRequest); NS_ENSURE_SUCCESS(rv, rv); // Bug 1120722 - Authorization will be handled later. // Auth may require prompting, we don't support it yet. // The next patch in this same bug prevents this from aborting the request. // Credentials checks for CORS are handled by nsCORSListenerProxy, nsCOMPtr<nsIHttpChannelInternal> internalChan = do_QueryInterface(httpChan); // Conversion between enumerations is safe due to static asserts in // dom/workers/ServiceWorkerManager.cpp rv = internalChan->SetCorsMode(static_cast<uint32_t>(mRequest->Mode())); MOZ_ASSERT(NS_SUCCEEDED(rv)); rv = internalChan->SetRedirectMode(static_cast<uint32_t>(mRequest->GetRedirectMode())); MOZ_ASSERT(NS_SUCCEEDED(rv)); mRequest->MaybeSkipCacheIfPerformingRevalidation(); rv = internalChan->SetFetchCacheMode(static_cast<uint32_t>(mRequest->GetCacheMode())); MOZ_ASSERT(NS_SUCCEEDED(rv)); rv = internalChan->SetIntegrityMetadata(mRequest->GetIntegrity()); MOZ_ASSERT(NS_SUCCEEDED(rv)); // Set the initiator type nsCOMPtr<nsITimedChannel> timedChannel(do_QueryInterface(httpChan)); if (timedChannel) { timedChannel->SetInitiatorType(NS_LITERAL_STRING("fetch")); } } // Step 5. Proxy authentication will be handled by Necko. // Continue setting up 'HTTPRequest'. Content-Type and body data. nsCOMPtr<nsIUploadChannel2> uploadChan = do_QueryInterface(chan); if (uploadChan) { nsAutoCString contentType; ErrorResult result; mRequest->Headers()->GetFirst(NS_LITERAL_CSTRING("content-type"), contentType, result); // We don't actually expect "result" to have failed here: that only happens // for invalid header names. But if for some reason it did, just propagate // it out. if (result.Failed()) { return result.StealNSResult(); } // Now contentType is the header that was set in mRequest->Headers(), or a // void string if no header was set. #ifdef DEBUG bool hasContentTypeHeader = mRequest->Headers()->Has(NS_LITERAL_CSTRING("content-type"), result); MOZ_ASSERT(!result.Failed()); MOZ_ASSERT_IF(!hasContentTypeHeader, contentType.IsVoid()); #endif // DEBUG int64_t bodyLength; nsCOMPtr<nsIInputStream> bodyStream; mRequest->GetBody(getter_AddRefs(bodyStream), &bodyLength); if (bodyStream) { nsAutoCString method; mRequest->GetMethod(method); rv = uploadChan->ExplicitSetUploadStream(bodyStream, contentType, bodyLength, method, false /* aStreamHasHeaders */); NS_ENSURE_SUCCESS(rv, rv); } } // If preflight is required, start a "CORS preflight fetch" // https://fetch.spec.whatwg.org/#cors-preflight-fetch-0. All the // implementation is handled by the http channel calling into // nsCORSListenerProxy. We just inform it which unsafe headers are included // in the request. if (mRequest->Mode() == RequestMode::Cors) { AutoTArray<nsCString, 5> unsafeHeaders; mRequest->Headers()->GetUnsafeHeaders(unsafeHeaders); nsCOMPtr<nsILoadInfo> loadInfo = chan->GetLoadInfo(); if (loadInfo) { loadInfo->SetCorsPreflightInfo(unsafeHeaders, false); } } if (mIsTrackingFetch && nsContentUtils::IsTailingEnabled()) { cos->AddClassFlags(nsIClassOfService::Throttleable | nsIClassOfService::Tail); } if (mIsTrackingFetch && nsContentUtils::IsLowerNetworkPriority()) { nsCOMPtr<nsISupportsPriority> p = do_QueryInterface(chan); if (p) { p->SetPriority(nsISupportsPriority::PRIORITY_LOWEST); } } // if the preferred alternative data type in InternalRequest is not empty, set // the data type on the created channel and also create a AlternativeDataStreamListener // to be the stream listener of the channel. if (!aPreferredAlternativeDataType.IsEmpty()) { nsCOMPtr<nsICacheInfoChannel> cic = do_QueryInterface(chan); if (cic) { cic->PreferAlternativeDataType(aPreferredAlternativeDataType); MOZ_ASSERT(!mAltDataListener); mAltDataListener = new AlternativeDataStreamListener(this, chan, aPreferredAlternativeDataType); rv = chan->AsyncOpen2(mAltDataListener); } else { rv = chan->AsyncOpen2(this); } } else { rv = chan->AsyncOpen2(this); } if (NS_FAILED(rv)) { return rv; } // Step 4 onwards of "HTTP Fetch" is handled internally by Necko. mChannel = chan; return NS_OK; }
float nsROCSSPrimitiveValue::GetFloatValue(uint16_t aUnitType, ErrorResult& aRv) { switch(aUnitType) { case CSS_PX : if (mType == CSS_PX) { return nsPresContext::AppUnitsToFloatCSSPixels(mValue.mAppUnits); } break; case CSS_CM : if (mType == CSS_PX) { return mValue.mAppUnits * CM_PER_INCH_FLOAT / nsPresContext::AppUnitsPerCSSInch(); } break; case CSS_MM : if (mType == CSS_PX) { return mValue.mAppUnits * MM_PER_INCH_FLOAT / nsPresContext::AppUnitsPerCSSInch(); } break; case CSS_IN : if (mType == CSS_PX) { return mValue.mAppUnits / nsPresContext::AppUnitsPerCSSInch(); } break; case CSS_PT : if (mType == CSS_PX) { return mValue.mAppUnits * POINTS_PER_INCH_FLOAT / nsPresContext::AppUnitsPerCSSInch(); } break; case CSS_PC : if (mType == CSS_PX) { return mValue.mAppUnits * 6.0f / nsPresContext::AppUnitsPerCSSInch(); } break; case CSS_PERCENTAGE : if (mType == CSS_PERCENTAGE) { return mValue.mFloat * 100; } break; case CSS_NUMBER : if (mType == CSS_NUMBER) { return mValue.mFloat; } break; case CSS_UNKNOWN : case CSS_EMS : case CSS_EXS : case CSS_DEG : case CSS_RAD : case CSS_GRAD : case CSS_MS : case CSS_S : case CSS_HZ : case CSS_KHZ : case CSS_DIMENSION : case CSS_STRING : case CSS_URI : case CSS_IDENT : case CSS_ATTR : case CSS_COUNTER : case CSS_RECT : case CSS_RGBCOLOR : break; } aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR); return 0; }
already_AddRefed<DOMCursor> MobileMessageManager::GetMessages(const MobileMessageFilter& aFilter, bool aReverse, ErrorResult& aRv) { nsCOMPtr<nsIMobileMessageDatabaseService> dbService = do_GetService(MOBILE_MESSAGE_DATABASE_SERVICE_CONTRACTID); if (!dbService) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } bool hasStartDate = !aFilter.mStartDate.IsNull(); uint64_t startDate = 0; if (hasStartDate) { startDate = aFilter.mStartDate.Value(); } bool hasEndDate = !aFilter.mEndDate.IsNull(); uint64_t endDate = 0; if (hasEndDate) { endDate = aFilter.mEndDate.Value(); } UniquePtr<const char16_t*[]> ptrNumbers; uint32_t numbersCount = 0; if (!aFilter.mNumbers.IsNull() && aFilter.mNumbers.Value().Length()) { const FallibleTArray<nsString>& numbers = aFilter.mNumbers.Value(); uint32_t index; numbersCount = numbers.Length(); ptrNumbers = MakeUnique<const char16_t*[]>(numbersCount); for (index = 0; index < numbersCount; index++) { ptrNumbers[index] = numbers[index].get(); } } nsString delivery; delivery.SetIsVoid(true); if (!aFilter.mDelivery.IsNull()) { const uint32_t index = static_cast<uint32_t>(aFilter.mDelivery.Value()); const EnumEntry& entry = MobileMessageFilterDeliveryValues::strings[index]; delivery.AssignASCII(entry.value, entry.length); } bool hasRead = !aFilter.mRead.IsNull(); bool read = false; if (hasRead) { read = aFilter.mRead.Value(); } bool hasThreadId = !aFilter.mThreadId.IsNull(); uint64_t threadId = 0; if (hasThreadId) { threadId = aFilter.mThreadId.Value(); } RefPtr<MobileMessageCursorCallback> cursorCallback = new MobileMessageCursorCallback(); nsCOMPtr<nsICursorContinueCallback> continueCallback; nsresult rv = dbService->CreateMessageCursor(hasStartDate, startDate, hasEndDate, endDate, ptrNumbers.get(), numbersCount, delivery, hasRead, read, hasThreadId, threadId, aReverse, cursorCallback, getter_AddRefs(continueCallback)); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; } nsCOMPtr<nsPIDOMWindowInner> window = GetOwner(); if (!window) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } cursorCallback->mDOMCursor = new MobileMessageCursor(window, continueCallback); RefPtr<DOMCursor> cursor(cursorCallback->mDOMCursor); return cursor.forget(); }
already_AddRefed<nsIDOMCounter> nsROCSSPrimitiveValue::GetCounterValue(ErrorResult& aRv) { aRv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR); return nullptr; }
nsresult nsXMLPrettyPrinter::PrettyPrint(nsIDocument* aDocument, bool* aDidPrettyPrint) { *aDidPrettyPrint = false; // Check for iframe with display:none. Such iframes don't have presshells if (!aDocument->GetShell()) { return NS_OK; } // check if we're in an invisible iframe nsPIDOMWindowOuter *internalWin = aDocument->GetWindow(); nsCOMPtr<Element> frameElem; if (internalWin) { frameElem = internalWin->GetFrameElementInternal(); } if (frameElem) { nsCOMPtr<nsICSSDeclaration> computedStyle; if (nsIDocument* frameOwnerDoc = frameElem->OwnerDoc()) { nsPIDOMWindowOuter* window = frameOwnerDoc->GetDefaultView(); if (window) { nsCOMPtr<nsPIDOMWindowInner> innerWindow = window->GetCurrentInnerWindow(); ErrorResult dummy; computedStyle = innerWindow->GetComputedStyle(*frameElem, EmptyString(), dummy); dummy.SuppressException(); } } if (computedStyle) { nsAutoString visibility; computedStyle->GetPropertyValue(NS_LITERAL_STRING("visibility"), visibility); if (!visibility.EqualsLiteral("visible")) { return NS_OK; } } } // check the pref if (!Preferences::GetBool("layout.xml.prettyprint", true)) { return NS_OK; } // Ok, we should prettyprint. Let's do it! *aDidPrettyPrint = true; nsresult rv = NS_OK; // Load the XSLT nsCOMPtr<nsIURI> xslUri; rv = NS_NewURI(getter_AddRefs(xslUri), NS_LITERAL_CSTRING("chrome://global/content/xml/XMLPrettyPrint.xsl")); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIDOMDocument> xslDocument; rv = nsSyncLoadService::LoadDocument(xslUri, nsIContentPolicy::TYPE_XSLT, nsContentUtils::GetSystemPrincipal(), nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL, nullptr, true, mozilla::net::RP_Default, getter_AddRefs(xslDocument)); NS_ENSURE_SUCCESS(rv, rv); // Transform the document nsCOMPtr<nsIXSLTProcessor> transformer = do_CreateInstance("@mozilla.org/document-transformer;1?type=xslt", &rv); NS_ENSURE_SUCCESS(rv, rv); rv = transformer->ImportStylesheet(xslDocument); NS_ENSURE_SUCCESS(rv, rv); nsCOMPtr<nsIDOMDocumentFragment> resultFragment; nsCOMPtr<nsIDOMDocument> sourceDocument = do_QueryInterface(aDocument); rv = transformer->TransformToFragment(sourceDocument, sourceDocument, getter_AddRefs(resultFragment)); NS_ENSURE_SUCCESS(rv, rv); // // Apply the prettprint XBL binding. // // We take some shortcuts here. In particular, we don't bother invoking the // contstructor (since the binding has no constructor), and we don't bother // calling LoadBindingDocument because it's a chrome:// URI and thus will get // sync loaded no matter what. // // Grab the XBL service. nsXBLService* xblService = nsXBLService::GetInstance(); NS_ENSURE_TRUE(xblService, NS_ERROR_NOT_AVAILABLE); // Compute the binding URI. nsCOMPtr<nsIURI> bindingUri; rv = NS_NewURI(getter_AddRefs(bindingUri), NS_LITERAL_STRING("chrome://global/content/xml/XMLPrettyPrint.xml#prettyprint")); NS_ENSURE_SUCCESS(rv, rv); // Compute the bound element. nsCOMPtr<nsIContent> rootCont = aDocument->GetRootElement(); NS_ENSURE_TRUE(rootCont, NS_ERROR_UNEXPECTED); // Grab the system principal. nsCOMPtr<nsIPrincipal> sysPrincipal; nsContentUtils::GetSecurityManager()-> GetSystemPrincipal(getter_AddRefs(sysPrincipal)); // Load the bindings. RefPtr<nsXBLBinding> unused; bool ignored; rv = xblService->LoadBindings(rootCont, bindingUri, sysPrincipal, getter_AddRefs(unused), &ignored); NS_ENSURE_SUCCESS(rv, rv); // Fire an event at the bound element to pass it |resultFragment|. RefPtr<CustomEvent> event = NS_NewDOMCustomEvent(rootCont, nullptr, nullptr); MOZ_ASSERT(event); nsCOMPtr<nsIWritableVariant> resultFragmentVariant = new nsVariant(); rv = resultFragmentVariant->SetAsISupports(resultFragment); MOZ_ASSERT(NS_SUCCEEDED(rv)); rv = event->InitCustomEvent(NS_LITERAL_STRING("prettyprint-dom-created"), /* bubbles = */ false, /* cancelable = */ false, /* detail = */ resultFragmentVariant); NS_ENSURE_SUCCESS(rv, rv); event->SetTrusted(true); bool dummy; rv = rootCont->DispatchEvent(event, &dummy); NS_ENSURE_SUCCESS(rv, rv); // Observe the document so we know when to switch to "normal" view aDocument->AddObserver(this); mDocument = aDocument; NS_ADDREF_THIS(); return NS_OK; }
void Crypto::Logout(ErrorResult& aRv) { aRv.Throw(NS_ERROR_NOT_IMPLEMENTED); }