/* static */ already_AddRefed<URL> URL::Constructor(const GlobalObject& aGlobal, const nsAString& aUrl, const nsAString& aBase, ErrorResult& aRv) { nsresult rv; nsCOMPtr<nsIIOService> ioService(do_GetService(NS_IOSERVICE_CONTRACTID, &rv)); if (NS_FAILED(rv)) { aRv.Throw(rv); return nullptr; } nsCOMPtr<nsIURI> baseUri; rv = ioService->NewURI(NS_ConvertUTF16toUTF8(aBase), nullptr, nullptr, getter_AddRefs(baseUri)); if (NS_FAILED(rv)) { nsAutoString label(aBase); aRv.ThrowTypeError(MSG_INVALID_URL, &label); return nullptr; } nsCOMPtr<nsIURI> uri; rv = ioService->NewURI(NS_ConvertUTF16toUTF8(aUrl), nullptr, baseUri, getter_AddRefs(uri)); if (NS_FAILED(rv)) { nsAutoString label(aUrl); aRv.ThrowTypeError(MSG_INVALID_URL, &label); return nullptr; } nsRefPtr<URL> url = new URL(uri); return url.forget(); }
already_AddRefed<Promise> ServiceWorkerContainer::Register(const nsAString& aScriptURL, const RegistrationOptions& aOptions, ErrorResult& aRv) { nsCOMPtr<nsISupports> promise; nsCOMPtr<nsIServiceWorkerManager> swm = mozilla::services::GetServiceWorkerManager(); if (!swm) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } nsCOMPtr<nsPIDOMWindow> window = GetOwner(); MOZ_ASSERT(window); nsresult rv; nsCOMPtr<nsIURI> scriptURI; rv = NS_NewURI(getter_AddRefs(scriptURI), aScriptURL, nullptr, window->GetDocBaseURI()); if (NS_WARN_IF(NS_FAILED(rv))) { aRv.ThrowTypeError(MSG_INVALID_URL, &aScriptURL); return nullptr; } // In ServiceWorkerContainer.register() the scope argument is parsed against // different base URLs depending on whether it was passed or not. nsCOMPtr<nsIURI> scopeURI; // Step 4. If none passed, parse against script's URL if (!aOptions.mScope.WasPassed()) { nsresult rv = NS_NewURI(getter_AddRefs(scopeURI), NS_LITERAL_CSTRING("./"), nullptr, scriptURI); MOZ_ALWAYS_TRUE(NS_SUCCEEDED(rv)); } else { // Step 5. Parse against entry settings object's base URL. nsresult rv = NS_NewURI(getter_AddRefs(scopeURI), aOptions.mScope.Value(), nullptr, window->GetDocBaseURI()); if (NS_WARN_IF(NS_FAILED(rv))) { aRv.ThrowTypeError(MSG_INVALID_URL, &aOptions.mScope.Value()); return nullptr; } } aRv = swm->Register(window, scopeURI, scriptURI, getter_AddRefs(promise)); if (aRv.Failed()) { return nullptr; } nsRefPtr<Promise> ret = static_cast<Promise*>(promise.get()); MOZ_ASSERT(ret); return ret.forget(); }
USING_FILE_NAMESPACE /* static */ already_AddRefed<ArchiveReader> ArchiveReader::Constructor(const GlobalObject& aGlobal, nsIDOMBlob* aBlob, const ArchiveReaderOptions& aOptions, ErrorResult& aError) { MOZ_ASSERT(aBlob); nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(aGlobal.GetAsSupports()); if (!window) { aError.Throw(NS_ERROR_UNEXPECTED); return nullptr; } nsAutoCString encoding; if (!EncodingUtils::FindEncodingForLabel(aOptions.mEncoding, encoding) || encoding.EqualsLiteral("replacement")) { aError.ThrowTypeError(MSG_ENCODING_NOT_SUPPORTED, &aOptions.mEncoding); return nullptr; } nsRefPtr<ArchiveReader> reader = new ArchiveReader(aBlob, window, encoding); return reader.forget(); }
void TypeUtils::ToCacheResponse(CacheResponse& aOut, Response& aIn, ErrorResult& aRv) { if (aIn.BodyUsed()) { aRv.ThrowTypeError(MSG_FETCH_BODY_CONSUMED_ERROR); return; } nsRefPtr<InternalResponse> ir = aIn.GetInternalResponse(); ToCacheResponseWithoutBody(aOut, *ir, aRv); if (NS_WARN_IF(aRv.Failed())) { return; } nsCOMPtr<nsIInputStream> stream; ir->GetInternalBody(getter_AddRefs(stream)); if (stream) { aIn.SetBodyUsed(); } SerializeCacheStream(stream, &aOut.body(), aRv); if (NS_WARN_IF(aRv.Failed())) { return; } }
void TypeUtils::ToCacheResponseWithoutBody(CacheResponse& aOut, InternalResponse& aIn, ErrorResult& aRv) { aOut.type() = aIn.Type(); aIn.GetUrl(aOut.url()); if (aOut.url() != EmptyCString()) { // Pass all Response URL schemes through... The spec only requires we take // action on invalid schemes for Request objects. ProcessURL(aOut.url(), nullptr, nullptr, nullptr, aRv); if (aRv.Failed()) { return; } } aOut.status() = aIn.GetStatus(); aOut.statusText() = aIn.GetStatusText(); nsRefPtr<InternalHeaders> headers = aIn.UnfilteredHeaders(); MOZ_ASSERT(headers); if (HasVaryStar(headers)) { aRv.ThrowTypeError(MSG_RESPONSE_HAS_VARY_STAR); return; } ToHeadersEntryList(aOut.headers(), headers); aOut.headersGuard() = headers->Guard(); aOut.channelInfo() = aIn.GetChannelInfo().AsIPCChannelInfo(); if (aIn.GetPrincipalInfo()) { aOut.principalInfo() = *aIn.GetPrincipalInfo(); } else { aOut.principalInfo() = void_t(); } }
void Fail() { ErrorResult rv; rv.ThrowTypeError(MSG_FETCH_FAILED); mPromise->MaybeReject(rv); }
void TypeUtils::ToPCacheRequest(PCacheRequest& aOut, InternalRequest* aIn, BodyAction aBodyAction, ReferrerAction aReferrerAction, SchemeAction aSchemeAction, ErrorResult& aRv) { MOZ_ASSERT(aIn); aIn->GetMethod(aOut.method()); nsAutoCString url; aIn->GetURL(url); CopyUTF8toUTF16(url, aOut.url()); bool schemeValid; ProcessURL(aOut.url(), &schemeValid, &aOut.urlWithoutQuery(), aRv); if (aRv.Failed()) { return; } if (!schemeValid) { if (aSchemeAction == TypeErrorOnInvalidScheme) { NS_NAMED_LITERAL_STRING(label, "Request"); aRv.ThrowTypeError(MSG_INVALID_URL_SCHEME, &label, &aOut.url()); return; } if (aSchemeAction == NetworkErrorOnInvalidScheme) { aRv.Throw(NS_ERROR_DOM_NETWORK_ERR); return; } } if (aReferrerAction == ExpandReferrer) { UpdateRequestReferrer(GetGlobalObject(), aIn); } aIn->GetReferrer(aOut.referrer()); nsRefPtr<InternalHeaders> headers = aIn->Headers(); MOZ_ASSERT(headers); headers->GetPHeaders(aOut.headers()); aOut.headersGuard() = headers->Guard(); aOut.mode() = aIn->Mode(); aOut.credentials() = aIn->GetCredentialsMode(); aOut.context() = aIn->ContentPolicyType(); if (aBodyAction == IgnoreBody) { aOut.body() = void_t(); return; } // BodyUsed flag is checked and set previously in ToInternalRequest() nsCOMPtr<nsIInputStream> stream; aIn->GetBody(getter_AddRefs(stream)); SerializeCacheStream(stream, &aOut.body(), aRv); if (NS_WARN_IF(aRv.Failed())) { return; } }
already_AddRefed<IDBFileRequest> IDBFileHandle::GetMetadata(const IDBFileMetadataParameters& aParameters, ErrorResult& aRv) { MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!"); // Common state checking if (!CheckState(aRv)) { return nullptr; } // Do nothing if the window is closed if (!CheckWindow()) { return nullptr; } nsRefPtr<MetadataParameters> params = new MetadataParameters(aParameters.mSize, aParameters.mLastModified); if (!params->IsConfigured()) { aRv.ThrowTypeError(MSG_METADATA_NOT_CONFIGURED); return nullptr; } nsRefPtr<FileRequestBase> fileRequest = GenerateFileRequest(); nsRefPtr<MetadataHelper> helper = new MetadataHelper(this, fileRequest, params); if (NS_WARN_IF(NS_FAILED(helper->Enqueue()))) { aRv.Throw(NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR); return nullptr; } return fileRequest.forget().downcast<IDBFileRequest>(); }
void URL::SetHref(const nsAString& aHref, ErrorResult& aRv) { nsCString href = NS_ConvertUTF16toUTF8(aHref); nsresult rv; nsCOMPtr<nsIIOService> ioService(do_GetService(NS_IOSERVICE_CONTRACTID, &rv)); if (NS_FAILED(rv)) { aRv.Throw(rv); return; } nsCOMPtr<nsIURI> uri; rv = ioService->NewURI(href, nullptr, nullptr, getter_AddRefs(uri)); if (NS_FAILED(rv)) { nsAutoString label(aHref); aRv.ThrowTypeError(MSG_INVALID_URL, &label); return; } aRv = mURI->SetSpec(href); if (mSearchParams) { mSearchParams->Invalidate(); } }
void TextDecoder::Decode(const char* aInput, const int32_t aLength, const bool aStream, nsAString& aOutDecodedString, ErrorResult& aRv) { aOutDecodedString.Truncate(); // Run or resume the decoder algorithm of the decoder object's encoder. int32_t outLen; nsresult rv = mDecoder->GetMaxLength(aInput, aLength, &outLen); if (NS_FAILED(rv)) { aRv.Throw(rv); return; } // Need a fallible allocator because the caller may be a content // and the content can specify the length of the string. nsAutoArrayPtr<char16_t> buf(new (fallible) char16_t[outLen + 1]); if (!buf) { aRv.Throw(NS_ERROR_OUT_OF_MEMORY); return; } int32_t length = aLength; rv = mDecoder->Convert(aInput, &length, buf, &outLen); MOZ_ASSERT(mFatal || rv != NS_ERROR_ILLEGAL_INPUT); buf[outLen] = 0; aOutDecodedString.Append(buf, outLen); // If the internal streaming flag of the decoder object is not set, // then reset the encoding algorithm state to the default values if (!aStream) { mDecoder->Reset(); if (rv == NS_OK_UDEC_MOREINPUT) { if (mFatal) { aRv.ThrowTypeError(MSG_DOM_DECODING_FAILED); } else { // Need to emit a decode error manually // to simulate the EOF handling of the Encoding spec. aOutDecodedString.Append(kReplacementChar); } } } if (NS_FAILED(rv)) { aRv.ThrowTypeError(MSG_DOM_DECODING_FAILED); } }
void IDBCursor::Advance(uint32_t aCount, ErrorResult &aRv) { AssertIsOnOwningThread(); if (!aCount) { aRv.ThrowTypeError(MSG_INVALID_ADVANCE_COUNT); return; } if (!mTransaction->IsOpen()) { aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR); return; } if (IsSourceDeleted() || !mHaveValue || mContinueCalled) { aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR); return; } const uint64_t requestSerialNumber = IDBRequest::NextSerialNumber(); mRequest->SetLoggingSerialNumber(requestSerialNumber); if (mType == Type_ObjectStore || mType == Type_ObjectStoreKey) { IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " "database(%s).transaction(%s).objectStore(%s)." "cursor(%s).advance(%ld)", "IndexedDB %s: C T[%lld] R[%llu]: IDBCursor.advance()", IDB_LOG_ID_STRING(), mTransaction->LoggingSerialNumber(), requestSerialNumber, IDB_LOG_STRINGIFY(mTransaction->Database()), IDB_LOG_STRINGIFY(mTransaction), IDB_LOG_STRINGIFY(mSourceObjectStore), IDB_LOG_STRINGIFY(mDirection), aCount); } else { IDB_LOG_MARK("IndexedDB %s: Child Transaction[%lld] Request[%llu]: " "database(%s).transaction(%s).objectStore(%s)." "index(%s).cursor(%s).advance(%ld)", "IndexedDB %s: C T[%lld] R[%llu]: IDBCursor.advance()", 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), aCount); } mBackgroundActor->SendContinueInternal(AdvanceParams(aCount)); mContinueCalled = true; }
bool WindowNamedPropertiesHandler::defineProperty(JSContext* aCx, JS::Handle<JSObject*> aProxy, JS::Handle<jsid> aId, JS::MutableHandle<JSPropertyDescriptor> aDesc) const { ErrorResult rv; rv.ThrowTypeError(MSG_DEFINEPROPERTY_ON_GSP); rv.ReportTypeError(aCx); return false; }
already_AddRefed<Response> Response::Clone(ErrorResult& aRv) const { if (BodyUsed()) { aRv.ThrowTypeError(MSG_FETCH_BODY_CONSUMED_ERROR); return nullptr; } nsRefPtr<InternalResponse> ir = mInternalResponse->Clone(); nsRefPtr<Response> response = new Response(mOwner, ir); return response.forget(); }
void TypeUtils::ToCacheRequest(CacheRequest& aOut, InternalRequest* aIn, BodyAction aBodyAction, SchemeAction aSchemeAction, ErrorResult& aRv) { MOZ_ASSERT(aIn); aIn->GetMethod(aOut.method()); nsAutoCString url; aIn->GetURL(url); bool schemeValid; ProcessURL(url, &schemeValid, &aOut.urlWithoutQuery(), &aOut.urlQuery(), aRv); if (aRv.Failed()) { return; } if (!schemeValid) { if (aSchemeAction == TypeErrorOnInvalidScheme) { NS_NAMED_LITERAL_STRING(label, "Request"); NS_ConvertUTF8toUTF16 urlUTF16(url); aRv.ThrowTypeError(MSG_INVALID_URL_SCHEME, &label, &urlUTF16); return; } } aIn->GetReferrer(aOut.referrer()); nsRefPtr<InternalHeaders> headers = aIn->Headers(); MOZ_ASSERT(headers); ToHeadersEntryList(aOut.headers(), headers); aOut.headersGuard() = headers->Guard(); aOut.mode() = aIn->Mode(); aOut.credentials() = aIn->GetCredentialsMode(); aOut.contentPolicyType() = aIn->ContentPolicyType(); aOut.requestCache() = aIn->GetCacheMode(); if (aBodyAction == IgnoreBody) { aOut.body() = void_t(); return; } // BodyUsed flag is checked and set previously in ToInternalRequest() nsCOMPtr<nsIInputStream> stream; aIn->GetBody(getter_AddRefs(stream)); SerializeCacheStream(stream, &aOut.body(), aRv); if (NS_WARN_IF(aRv.Failed())) { return; } }
void IDBCursor::Advance(uint32_t aCount, ErrorResult &aRv) { AssertIsOnOwningThread(); if (!mTransaction->IsOpen()) { aRv.Throw(NS_ERROR_DOM_INDEXEDDB_TRANSACTION_INACTIVE_ERR); return; } if (!mHaveValue || mContinueCalled) { aRv.Throw(NS_ERROR_DOM_INDEXEDDB_NOT_ALLOWED_ERR); return; } if (!aCount) { aRv.ThrowTypeError(MSG_INVALID_ADVANCE_COUNT); return; } mBackgroundActor->SendContinueInternal(AdvanceParams(aCount)); mContinueCalled = true; #ifdef IDB_PROFILER_USE_MARKS { if (mType == Type_ObjectStore || mType == Type_ObjectStoreKey) { IDB_PROFILER_MARK("IndexedDB Request %llu: " "database(%s).transaction(%s).objectStore(%s)." "cursor(%s).advance(%ld)", "IDBRequest[%llu] MT IDBCursor.advance()", Request()->GetSerialNumber(), IDB_PROFILER_STRING(Transaction()->Database()), IDB_PROFILER_STRING(Transaction()), IDB_PROFILER_STRING(mSourceObjectStore), IDB_PROFILER_STRING(mDirection), aCount); } else { IDB_PROFILER_MARK("IndexedDB Request %llu: " "database(%s).transaction(%s).objectStore(%s)." "index(%s).cursor(%s).advance(%ld)", "IDBRequest[%llu] MT IDBCursor.advance()", Request()->GetSerialNumber(), IDB_PROFILER_STRING(Transaction()->Database()), IDB_PROFILER_STRING(Transaction()), IDB_PROFILER_STRING(mSourceIndex->ObjectStore()), IDB_PROFILER_STRING(mSourceIndex), IDB_PROFILER_STRING(mDirection), aCount); } } #endif }
/* static */ already_AddRefed<URL> URL::Constructor(const nsAString& aUrl, nsIURI* aBase, ErrorResult& aRv) { nsCOMPtr<nsIURI> uri; nsresult rv = NS_NewURI(getter_AddRefs(uri), aUrl, nullptr, aBase, nsContentUtils::GetIOService()); if (NS_WARN_IF(NS_FAILED(rv))) { aRv.ThrowTypeError(MSG_INVALID_URL, &aUrl); return nullptr; } nsRefPtr<URL> url = new URL(uri.forget()); return url.forget(); }
void TextEncoder::Init(const nsAString& aEncoding, ErrorResult& aRv) { nsAutoString label(aEncoding); EncodingUtils::TrimSpaceCharacters(label); // Let encoding be the result of getting an encoding from label. // If encoding is failure, or is none of utf-8, utf-16, and utf-16be, // throw a TypeError. if (!EncodingUtils::FindEncodingForLabel(label, mEncoding)) { aRv.ThrowTypeError(MSG_ENCODING_NOT_SUPPORTED, &label); return; } if (!mEncoding.EqualsLiteral("UTF-8") && !mEncoding.EqualsLiteral("UTF-16LE") && !mEncoding.EqualsLiteral("UTF-16BE")) { aRv.ThrowTypeError(MSG_DOM_ENCODING_NOT_UTF); return; } // Create an encoder object for mEncoding. mEncoder = EncodingUtils::EncoderForEncoding(mEncoding); }
void MainThreadFetchResolver::OnResponseAvailableInternal(InternalResponse* aResponse) { NS_ASSERT_OWNINGTHREAD(MainThreadFetchResolver); AssertIsOnMainThread(); if (aResponse->Type() != ResponseType::Error) { nsCOMPtr<nsIGlobalObject> go = mPromise->GetParentObject(); mResponse = new Response(go, aResponse); mPromise->MaybeResolve(mResponse); } else { ErrorResult result; result.ThrowTypeError(MSG_FETCH_FAILED); mPromise->MaybeReject(result); } }
void TextDecoder::Init(const nsAString& aLabel, const bool aFatal, ErrorResult& aRv) { nsAutoString label(aLabel); EncodingUtils::TrimSpaceCharacters(label); nsAutoCString encoding; // Let encoding be the result of getting an encoding from label. // If encoding is failure or replacement, throw a TypeError. if (!EncodingUtils::FindEncodingForLabel(label, encoding) || encoding.EqualsLiteral("replacement")) { aRv.ThrowTypeError(MSG_ENCODING_NOT_SUPPORTED, &label); return; } InitWithEncoding(encoding, aFatal); }
bool WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override { MOZ_ASSERT(aWorkerPrivate); aWorkerPrivate->AssertIsOnWorkerThread(); nsRefPtr<Promise> promise = mResolver->mPromiseProxy->WorkerPromise(); if (mInternalResponse->Type() != ResponseType::Error) { nsRefPtr<nsIGlobalObject> global = aWorkerPrivate->GlobalScope(); nsRefPtr<Response> response = new Response(global, mInternalResponse); promise->MaybeResolve(response); } else { ErrorResult result; result.ThrowTypeError(MSG_FETCH_FAILED); promise->MaybeReject(result); } return true; }
void TypeUtils::CheckAndSetBodyUsed(Request* aRequest, BodyAction aBodyAction, ErrorResult& aRv) { MOZ_ASSERT(aRequest); if (aBodyAction == IgnoreBody) { return; } if (aRequest->BodyUsed()) { aRv.ThrowTypeError(MSG_FETCH_BODY_CONSUMED_ERROR); return; } nsCOMPtr<nsIInputStream> stream; aRequest->GetBody(getter_AddRefs(stream)); if (stream) { aRequest->SetBodyUsed(); } }
bool FileHandleBase::CheckStateAndArgumentsForRead(uint64_t aSize, ErrorResult& aRv) { // Common state checking if (!CheckState(aRv)) { return false; } // Additional state checking for read if (mLocation == UINT64_MAX) { aRv.Throw(NS_ERROR_DOM_FILEHANDLE_NOT_ALLOWED_ERR); return false; } // Argument checking for read if (!aSize) { aRv.ThrowTypeError(MSG_INVALID_READ_SIZE); return false; } return true; }
// Notification API extension. already_AddRefed<Promise> ServiceWorkerRegistrationMainThread::ShowNotification(JSContext* aCx, const nsAString& aTitle, const NotificationOptions& aOptions, ErrorResult& aRv) { AssertIsOnMainThread(); MOZ_ASSERT(GetOwner()); nsCOMPtr<nsPIDOMWindow> window = GetOwner(); if (NS_WARN_IF(!window)) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } nsCOMPtr<nsIDocument> doc = window->GetExtantDoc(); if (NS_WARN_IF(!doc)) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } nsRefPtr<workers::ServiceWorker> worker = GetActive(); if (!worker) { aRv.ThrowTypeError(MSG_NO_ACTIVE_WORKER, &mScope); return nullptr; } nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(window); nsRefPtr<Promise> p = Notification::ShowPersistentNotification(global, mScope, aTitle, aOptions, aRv); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } return p.forget(); }
/*static*/ already_AddRefed<Response> Response::Constructor(const GlobalObject& aGlobal, const Optional<ArrayBufferOrArrayBufferViewOrBlobOrFormDataOrUSVStringOrURLSearchParams>& aBody, const ResponseInit& aInit, ErrorResult& aRv) { nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports()); if (aInit.mStatus < 200 || aInit.mStatus > 599) { aRv.ThrowRangeError(MSG_INVALID_RESPONSE_STATUSCODE_ERROR); return nullptr; } nsCString statusText; if (aInit.mStatusText.WasPassed()) { statusText = aInit.mStatusText.Value(); nsACString::const_iterator start, end; statusText.BeginReading(start); statusText.EndReading(end); if (FindCharInReadable('\r', start, end)) { aRv.ThrowTypeError(MSG_RESPONSE_INVALID_STATUSTEXT_ERROR); return nullptr; } // Reset iterator since FindCharInReadable advances it. statusText.BeginReading(start); if (FindCharInReadable('\n', start, end)) { aRv.ThrowTypeError(MSG_RESPONSE_INVALID_STATUSTEXT_ERROR); return nullptr; } } else { // Since we don't support default values for ByteString. statusText = NS_LITERAL_CSTRING("OK"); } nsRefPtr<InternalResponse> internalResponse = new InternalResponse(aInit.mStatus, statusText); nsRefPtr<Response> r = new Response(global, internalResponse); if (aInit.mHeaders.WasPassed()) { internalResponse->Headers()->Clear(); // Instead of using Fill, create an object to allow the constructor to // unwrap the HeadersInit. nsRefPtr<Headers> headers = Headers::Create(global, aInit.mHeaders.Value(), aRv); if (aRv.Failed()) { return nullptr; } internalResponse->Headers()->Fill(*headers->GetInternalHeaders(), aRv); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } } if (aBody.WasPassed()) { nsCOMPtr<nsIInputStream> bodyStream; nsCString contentType; aRv = ExtractByteStreamFromBody(aBody.Value(), getter_AddRefs(bodyStream), contentType); internalResponse->SetBody(bodyStream); if (!contentType.IsVoid() && !internalResponse->Headers()->Has(NS_LITERAL_CSTRING("Content-Type"), aRv)) { internalResponse->Headers()->Append(NS_LITERAL_CSTRING("Content-Type"), contentType, aRv); } if (aRv.Failed()) { return nullptr; } } r->SetMimeType(); return r.forget(); }
already_AddRefed<IDBOpenDBRequest> IDBFactory::OpenInternal(nsIPrincipal* aPrincipal, const nsAString& aName, const Optional<uint64_t>& aVersion, const Optional<StorageType>& aStorageType, bool aDeleting, ErrorResult& aRv) { MOZ_ASSERT(mWindow || mOwningObject); MOZ_ASSERT_IF(!mWindow, !mPrivateBrowsingMode); CommonFactoryRequestParams commonParams; commonParams.privateBrowsingMode() = mPrivateBrowsingMode; PrincipalInfo& principalInfo = commonParams.principalInfo(); if (aPrincipal) { if (!NS_IsMainThread()) { MOZ_CRASH("Figure out security checks for workers!"); } MOZ_ASSERT(nsContentUtils::IsCallerChrome()); if (NS_WARN_IF(NS_FAILED(PrincipalToPrincipalInfo(aPrincipal, &principalInfo)))) { IDB_REPORT_INTERNAL_ERR(); aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); return nullptr; } if (principalInfo.type() != PrincipalInfo::TContentPrincipalInfo && principalInfo.type() != PrincipalInfo::TSystemPrincipalInfo) { IDB_REPORT_INTERNAL_ERR(); aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); return nullptr; } } else { principalInfo = *mPrincipalInfo; } uint64_t version = 0; if (!aDeleting && aVersion.WasPassed()) { if (aVersion.Value() < 1) { aRv.ThrowTypeError(MSG_INVALID_VERSION); return nullptr; } version = aVersion.Value(); } // Nothing can be done here if we have previously failed to create a // background actor. if (mBackgroundActorFailed) { IDB_REPORT_INTERNAL_ERR(); aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); return nullptr; } PersistenceType persistenceType; if (principalInfo.type() == PrincipalInfo::TSystemPrincipalInfo) { // Chrome privilege always gets persistent storage. persistenceType = PERSISTENCE_TYPE_PERSISTENT; } else { persistenceType = PersistenceTypeFromStorage(aStorageType); } DatabaseMetadata& metadata = commonParams.metadata(); metadata.name() = aName; metadata.persistenceType() = persistenceType; FactoryRequestParams params; if (aDeleting) { metadata.version() = 0; params = DeleteDatabaseRequestParams(commonParams); } else { metadata.version() = version; params = OpenDatabaseRequestParams(commonParams); } if (!mBackgroundActor && mPendingRequests.IsEmpty()) { // We need to start the sequence to create a background actor for this // thread. BackgroundChildImpl::ThreadLocal* threadLocal = BackgroundChildImpl::GetThreadLocalForCurrentThread(); nsAutoPtr<ThreadLocal> newIDBThreadLocal; ThreadLocal* idbThreadLocal; if (threadLocal && threadLocal->mIndexedDBThreadLocal) { idbThreadLocal = threadLocal->mIndexedDBThreadLocal; } else { nsCOMPtr<nsIUUIDGenerator> uuidGen = do_GetService("@mozilla.org/uuid-generator;1"); MOZ_ASSERT(uuidGen); nsID id; MOZ_ALWAYS_TRUE(NS_SUCCEEDED(uuidGen->GenerateUUIDInPlace(&id))); newIDBThreadLocal = idbThreadLocal = new ThreadLocal(id); } nsRefPtr<BackgroundCreateCallback> cb = new BackgroundCreateCallback(this, idbThreadLocal->GetLoggingInfo()); if (NS_WARN_IF(!BackgroundChild::GetOrCreateForCurrentThread(cb))) { IDB_REPORT_INTERNAL_ERR(); aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); return nullptr; } if (newIDBThreadLocal) { if (!threadLocal) { threadLocal = BackgroundChildImpl::GetThreadLocalForCurrentThread(); } MOZ_ASSERT(threadLocal); MOZ_ASSERT(!threadLocal->mIndexedDBThreadLocal); threadLocal->mIndexedDBThreadLocal = newIDBThreadLocal.forget(); } } AutoJSAPI autoJS; nsRefPtr<IDBOpenDBRequest> request; if (mWindow) { AutoJSContext cx; if (NS_WARN_IF(!autoJS.Init(mWindow, cx))) { IDB_REPORT_INTERNAL_ERR(); aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); return nullptr; } JS::Rooted<JSObject*> scriptOwner(cx, static_cast<nsGlobalWindow*>(mWindow.get())->FastGetGlobalJSObject()); MOZ_ASSERT(scriptOwner); request = IDBOpenDBRequest::CreateForWindow(this, mWindow, scriptOwner); } else { autoJS.Init(mOwningObject.get()); JS::Rooted<JSObject*> scriptOwner(autoJS.cx(), mOwningObject); request = IDBOpenDBRequest::CreateForJS(this, scriptOwner); if (!request) { MOZ_ASSERT(!NS_IsMainThread()); aRv.ThrowUncatchableException(); return nullptr; } } MOZ_ASSERT(request); if (aDeleting) { IDB_LOG_MARK("IndexedDB %s: Child Request[%llu]: " "indexedDB.deleteDatabase(\"%s\")", "IndexedDB %s: C R[%llu]: IDBFactory.deleteDatabase()", IDB_LOG_ID_STRING(), request->LoggingSerialNumber(), NS_ConvertUTF16toUTF8(aName).get()); } else { IDB_LOG_MARK("IndexedDB %s: Child Request[%llu]: " "indexedDB.open(\"%s\", %s)", "IndexedDB %s: C R[%llu]: IDBFactory.open()", IDB_LOG_ID_STRING(), request->LoggingSerialNumber(), NS_ConvertUTF16toUTF8(aName).get(), IDB_LOG_STRINGIFY(aVersion)); } // If we already have a background actor then we can start this request now. if (mBackgroundActor) { nsresult rv = InitiateRequest(request, params); if (NS_WARN_IF(NS_FAILED(rv))) { IDB_REPORT_INTERNAL_ERR(); aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); return nullptr; } } else { mPendingRequests.AppendElement(new PendingRequestInfo(request, params)); } return request.forget(); }
already_AddRefed<Promise> Request::ConsumeBody(ConsumeType aType, ErrorResult& aRv) { nsRefPtr<Promise> promise = Promise::Create(mOwner, aRv); if (aRv.Failed()) { return nullptr; } if (BodyUsed()) { aRv.ThrowTypeError(MSG_REQUEST_BODY_CONSUMED_ERROR); return nullptr; } SetBodyUsed(); // While the spec says to do this asynchronously, all the body constructors // right now only accept bodies whose streams are backed by an in-memory // buffer that can be read without blocking. So I think this is fine. nsCOMPtr<nsIInputStream> stream; mRequest->GetBody(getter_AddRefs(stream)); if (!stream) { aRv = NS_NewByteInputStream(getter_AddRefs(stream), "", 0, NS_ASSIGNMENT_COPY); if (aRv.Failed()) { return nullptr; } } AutoJSAPI api; api.Init(mOwner); JSContext* cx = api.cx(); // We can make this assertion because for now we only support memory backed // structures for the body argument for a Request. MOZ_ASSERT(NS_InputStreamIsBuffered(stream)); nsCString buffer; uint64_t len; aRv = stream->Available(&len); if (aRv.Failed()) { return nullptr; } aRv = NS_ReadInputStreamToString(stream, buffer, len); if (aRv.Failed()) { return nullptr; } buffer.SetLength(len); switch (aType) { case CONSUME_ARRAYBUFFER: { JS::Rooted<JSObject*> arrayBuffer(cx); arrayBuffer = ArrayBuffer::Create(cx, buffer.Length(), reinterpret_cast<const uint8_t*>(buffer.get())); JS::Rooted<JS::Value> val(cx); val.setObjectOrNull(arrayBuffer); promise->MaybeResolve(cx, val); return promise.forget(); } case CONSUME_BLOB: { // XXXnsm it is actually possible to avoid these duplicate allocations // for the Blob case by having the Blob adopt the stream's memory // directly, but I've not added a special case for now. // // This is similar to nsContentUtils::CreateBlobBuffer, but also deals // with worker wrapping. uint32_t blobLen = buffer.Length(); void* blobData = moz_malloc(blobLen); nsRefPtr<File> blob; if (blobData) { memcpy(blobData, buffer.BeginReading(), blobLen); blob = File::CreateMemoryFile(GetParentObject(), blobData, blobLen, NS_ConvertUTF8toUTF16(mMimeType)); } else { aRv = NS_ERROR_OUT_OF_MEMORY; return nullptr; } promise->MaybeResolve(blob); return promise.forget(); } case CONSUME_JSON: { nsString decoded; aRv = DecodeUTF8(buffer, decoded); if (aRv.Failed()) { return nullptr; } JS::Rooted<JS::Value> json(cx); if (!JS_ParseJSON(cx, decoded.get(), decoded.Length(), &json)) { JS::Rooted<JS::Value> exn(cx); if (JS_GetPendingException(cx, &exn)) { JS_ClearPendingException(cx); promise->MaybeReject(cx, exn); } } promise->MaybeResolve(cx, json); return promise.forget(); } case CONSUME_TEXT: { nsString decoded; aRv = DecodeUTF8(buffer, decoded); if (aRv.Failed()) { return nullptr; } promise->MaybeResolve(decoded); return promise.forget(); } } NS_NOTREACHED("Unexpected consume body type"); // Silence warnings. return nullptr; }