nsresult LoadInfoToLoadInfoArgs(nsILoadInfo *aLoadInfo, mozilla::net::LoadInfoArgs* aLoadInfoArgs) { nsresult rv = NS_OK; if (aLoadInfo) { rv = PrincipalToPrincipalInfo(aLoadInfo->LoadingPrincipal(), &aLoadInfoArgs->requestingPrincipalInfo()); NS_ENSURE_SUCCESS(rv, rv); rv = PrincipalToPrincipalInfo(aLoadInfo->TriggeringPrincipal(), &aLoadInfoArgs->triggeringPrincipalInfo()); NS_ENSURE_SUCCESS(rv, rv); aLoadInfoArgs->securityFlags() = aLoadInfo->GetSecurityFlags(); aLoadInfoArgs->contentPolicyType() = aLoadInfo->GetContentPolicyType(); aLoadInfoArgs->innerWindowID() = aLoadInfo->GetInnerWindowID(); aLoadInfoArgs->outerWindowID() = aLoadInfo->GetOuterWindowID(); aLoadInfoArgs->parentOuterWindowID() = aLoadInfo->GetParentOuterWindowID(); return NS_OK; } // use default values if no loadInfo is provided rv = PrincipalToPrincipalInfo(nsContentUtils::GetSystemPrincipal(), &aLoadInfoArgs->requestingPrincipalInfo()); NS_ENSURE_SUCCESS(rv, rv); rv = PrincipalToPrincipalInfo(nsContentUtils::GetSystemPrincipal(), &aLoadInfoArgs->triggeringPrincipalInfo()); NS_ENSURE_SUCCESS(rv, rv); aLoadInfoArgs->securityFlags() = nsILoadInfo::SEC_NORMAL; aLoadInfoArgs->contentPolicyType() = nsIContentPolicy::TYPE_OTHER; aLoadInfoArgs->innerWindowID() = 0; aLoadInfoArgs->outerWindowID() = 0; aLoadInfoArgs->parentOuterWindowID() = 0; return NS_OK; }
nsresult LoadInfoToLoadInfoArgs(nsILoadInfo *aLoadInfo, OptionalLoadInfoArgs* aOptionalLoadInfoArgs) { if (!aLoadInfo) { // if there is no loadInfo, then there is nothing to serialize *aOptionalLoadInfoArgs = void_t(); return NS_OK; } nsresult rv = NS_OK; PrincipalInfo requestingPrincipalInfo; rv = PrincipalToPrincipalInfo(aLoadInfo->LoadingPrincipal(), &requestingPrincipalInfo); NS_ENSURE_SUCCESS(rv, rv); PrincipalInfo triggeringPrincipalInfo; rv = PrincipalToPrincipalInfo(aLoadInfo->TriggeringPrincipal(), &triggeringPrincipalInfo); *aOptionalLoadInfoArgs = LoadInfoArgs( requestingPrincipalInfo, triggeringPrincipalInfo, aLoadInfo->GetSecurityFlags(), aLoadInfo->GetContentPolicyType(), aLoadInfo->GetUpgradeInsecureRequests(), aLoadInfo->GetInnerWindowID(), aLoadInfo->GetOuterWindowID(), aLoadInfo->GetParentOuterWindowID()); return NS_OK; }
nsresult LoadInfoToLoadInfoArgs(nsILoadInfo *aLoadInfo, OptionalLoadInfoArgs* aOptionalLoadInfoArgs) { if (!aLoadInfo) { // if there is no loadInfo, then there is nothing to serialize *aOptionalLoadInfoArgs = void_t(); return NS_OK; } nsresult rv = NS_OK; PrincipalInfo requestingPrincipalInfo; rv = PrincipalToPrincipalInfo(aLoadInfo->LoadingPrincipal(), &requestingPrincipalInfo); NS_ENSURE_SUCCESS(rv, rv); PrincipalInfo triggeringPrincipalInfo; rv = PrincipalToPrincipalInfo(aLoadInfo->TriggeringPrincipal(), &triggeringPrincipalInfo); nsTArray<PrincipalInfo> redirectChainIncludingInternalRedirects; for (const nsCOMPtr<nsIPrincipal>& principal : aLoadInfo->RedirectChainIncludingInternalRedirects()) { rv = PrincipalToPrincipalInfo(principal, redirectChainIncludingInternalRedirects.AppendElement()); NS_ENSURE_SUCCESS(rv, rv); } nsTArray<PrincipalInfo> redirectChain; for (const nsCOMPtr<nsIPrincipal>& principal : aLoadInfo->RedirectChain()) { rv = PrincipalToPrincipalInfo(principal, redirectChain.AppendElement()); NS_ENSURE_SUCCESS(rv, rv); } *aOptionalLoadInfoArgs = LoadInfoArgs( requestingPrincipalInfo, triggeringPrincipalInfo, aLoadInfo->GetSecurityFlags(), aLoadInfo->InternalContentPolicyType(), aLoadInfo->GetUpgradeInsecureRequests(), aLoadInfo->GetUpgradeInsecurePreloads(), aLoadInfo->GetInnerWindowID(), aLoadInfo->GetOuterWindowID(), aLoadInfo->GetParentOuterWindowID(), aLoadInfo->GetEnforceSecurity(), aLoadInfo->GetInitialSecurityCheckDone(), aLoadInfo->GetIsInThirdPartyContext(), aLoadInfo->GetOriginAttributes(), redirectChainIncludingInternalRedirects, redirectChain); return NS_OK; }
// static nsresult IDBFactory::CreateForMainThreadJS(JSContext* aCx, JS::Handle<JSObject*> aOwningObject, IDBFactory** aFactory) { MOZ_ASSERT(NS_IsMainThread()); nsAutoPtr<PrincipalInfo> principalInfo(new PrincipalInfo()); nsIPrincipal* principal = nsContentUtils::ObjectPrincipal(aOwningObject); MOZ_ASSERT(principal); bool isSystem; if (!AllowedForPrincipal(principal, &isSystem)) { return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR; } nsresult rv = PrincipalToPrincipalInfo(principal, principalInfo); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } rv = CreateForMainThreadJSInternal(aCx, aOwningObject, principalInfo, aFactory); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } MOZ_ASSERT(!principalInfo); return NS_OK; }
bool MainThreadRun() override { MOZ_ASSERT(NS_IsMainThread()); nsIPrincipal* principal = GetPrincipalFromWorkerPrivate(mWorkerPrivate); if (!principal) { mRv.Throw(NS_ERROR_FAILURE); return true; } bool isNullPrincipal; mRv = principal->GetIsNullPrincipal(&isNullPrincipal); if (NS_WARN_IF(mRv.Failed())) { return true; } if (NS_WARN_IF(isNullPrincipal)) { mRv.Throw(NS_ERROR_FAILURE); return true; } mRv = PrincipalToPrincipalInfo(principal, &mPrincipalInfo); if (NS_WARN_IF(mRv.Failed())) { return true; } mRv = principal->GetOrigin(mOrigin); if (NS_WARN_IF(mRv.Failed())) { return true; } // Walk up to our containing page WorkerPrivate* wp = mWorkerPrivate; while (wp->GetParent()) { wp = wp->GetParent(); } // Window doesn't exist for some kind of workers (eg: SharedWorkers) nsPIDOMWindow* window = wp->GetWindow(); if (!window) { return true; } nsIDocument* doc = window->GetExtantDoc(); if (doc) { mPrivateBrowsing = nsContentUtils::IsInPrivateBrowsing(doc); // No bfcache when BroadcastChannel is used. doc->DisallowBFCaching(); } return true; }
nsresult FetchDriver::Fetch(AbortSignal* aSignal, FetchDriverObserver* aObserver) { AssertIsOnMainThread(); #ifdef DEBUG MOZ_ASSERT(!mFetchCalled); mFetchCalled = true; #endif mObserver = aObserver; Telemetry::Accumulate(Telemetry::SERVICE_WORKER_REQUEST_PASSTHROUGH, mRequest->WasCreatedByFetchEvent()); // FIXME(nsm): Deal with HSTS. MOZ_RELEASE_ASSERT(!mRequest->IsSynchronous(), "Synchronous fetch not supported"); UniquePtr<mozilla::ipc::PrincipalInfo> principalInfo(new mozilla::ipc::PrincipalInfo()); nsresult rv = PrincipalToPrincipalInfo(mPrincipal, principalInfo.get()); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } mRequest->SetPrincipalInfo(std::move(principalInfo)); // If the signal is aborted, it's time to inform the observer and terminate // the operation. if (aSignal) { if (aSignal->Aborted()) { Abort(); return NS_OK; } Follow(aSignal); } rv = HttpFetch(mRequest->GetPreferredAlternativeDataType()); if (NS_FAILED(rv)) { FailWithNetworkError(rv); } // Any failure is handled by FailWithNetworkError notifying the aObserver. return NS_OK; }
bool MainThreadRun() override { MOZ_ASSERT(NS_IsMainThread()); nsIPrincipal* principal = GetPrincipalFromWorkerPrivate(mWorkerPrivate); if (!principal) { mRv.Throw(NS_ERROR_FAILURE); return true; } bool isNullPrincipal; mRv = principal->GetIsNullPrincipal(&isNullPrincipal); if (NS_WARN_IF(mRv.Failed())) { return true; } if (NS_WARN_IF(isNullPrincipal)) { mRv.Throw(NS_ERROR_FAILURE); return true; } mRv = PrincipalToPrincipalInfo(principal, &mPrincipalInfo); if (NS_WARN_IF(mRv.Failed())) { return true; } mRv = principal->GetOrigin(mOrigin); if (NS_WARN_IF(mRv.Failed())) { return true; } // Walk up to our containing page WorkerPrivate* wp = mWorkerPrivate; while (wp->GetParent()) { wp = wp->GetParent(); } // Window doesn't exist for some kind of workers (eg: SharedWorkers) nsPIDOMWindowInner* window = wp->GetWindow(); if (!window) { return true; } return true; }
nsresult CheckedPrincipalToPrincipalInfo(nsIPrincipal* aPrincipal, PrincipalInfo& aPrincipalInfo) { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(aPrincipal); nsresult rv = PrincipalToPrincipalInfo(aPrincipal, &aPrincipalInfo); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } if (NS_WARN_IF(!QuotaManager::IsPrincipalInfoValid(aPrincipalInfo))) { return NS_ERROR_FAILURE; } if (aPrincipalInfo.type() != PrincipalInfo::TContentPrincipalInfo && aPrincipalInfo.type() != PrincipalInfo::TSystemPrincipalInfo) { return NS_ERROR_UNEXPECTED; } return NS_OK; }
/* static */ already_AddRefed<BroadcastChannel> BroadcastChannel::Constructor(const GlobalObject& aGlobal, const nsAString& aChannel, ErrorResult& aRv) { nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobal.GetAsSupports()); // Window is null in workers. RefPtr<BroadcastChannel> bc = new BroadcastChannel(window, aChannel); nsAutoCString origin; PrincipalInfo principalInfo; 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; } aRv = principal->GetOrigin(origin); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } aRv = PrincipalToPrincipalInfo(principal, &principalInfo); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } } else { JSContext* cx = aGlobal.Context(); WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(cx); MOZ_ASSERT(workerPrivate); RefPtr<StrongWorkerRef> workerRef = StrongWorkerRef::Create(workerPrivate, "BroadcastChannel", [bc] () { bc->Shutdown(); }); // We are already shutting down the worker. Let's return a non-active // object. if (NS_WARN_IF(!workerRef)) { aRv.Throw(NS_ERROR_FAILURE); return nullptr; } RefPtr<ThreadSafeWorkerRef> tsr = new ThreadSafeWorkerRef(workerRef); RefPtr<InitializeRunnable> runnable = new InitializeRunnable(tsr, origin, principalInfo, aRv); runnable->Dispatch(Canceling, aRv); if (aRv.Failed()) { return nullptr; } bc->mWorkerRef = Move(workerRef); } // Register this component to PBackground. PBackgroundChild* actorChild = BackgroundChild::GetOrCreateForCurrentThread(); if (NS_WARN_IF(!actorChild)) { // Firefox is probably shutting down. Let's return a 'generic' error. aRv.Throw(NS_ERROR_FAILURE); return nullptr; } PBroadcastChannelChild* actor = actorChild->SendPBroadcastChannelConstructor(principalInfo, origin, nsString(aChannel)); bc->mActor = static_cast<BroadcastChannelChild*>(actor); MOZ_ASSERT(bc->mActor); bc->mActor->SetParent(bc); return bc.forget(); }
already_AddRefed<IDBOpenDBRequest> IDBFactory::OpenInternal(JSContext* aCx, 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()) { 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_SUCCEEDS(uuidGen->GenerateUUIDInPlace(&id)); newIDBThreadLocal = idbThreadLocal = new ThreadLocal(id); } if (PBackgroundChild* actor = BackgroundChild::GetForCurrentThread()) { BackgroundActorCreated(actor, idbThreadLocal->GetLoggingInfo()); } else { // We need to start the sequence to create a background actor for this // thread. RefPtr<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(); } } RefPtr<IDBOpenDBRequest> request; if (mWindow) { JS::Rooted<JSObject*> scriptOwner(aCx, nsGlobalWindow::Cast(mWindow.get())->FastGetGlobalJSObject()); MOZ_ASSERT(scriptOwner); request = IDBOpenDBRequest::CreateForWindow(aCx, this, mWindow, scriptOwner); } else { JS::Rooted<JSObject*> scriptOwner(aCx, mOwningObject); request = IDBOpenDBRequest::CreateForJS(aCx, 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(); }
/*static*/ already_AddRefed<Response> Response::Constructor( const GlobalObject& aGlobal, const Optional<Nullable<fetch::ResponseBodyInit>>& aBody, const ResponseInit& aInit, ErrorResult& aRv) { nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports()); if (NS_WARN_IF(!global)) { aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); return nullptr; } if (aInit.mStatus < 200 || aInit.mStatus > 599) { aRv.ThrowRangeError<MSG_INVALID_RESPONSE_STATUSCODE_ERROR>(); return nullptr; } // Check if the status text contains illegal characters nsACString::const_iterator start, end; aInit.mStatusText.BeginReading(start); aInit.mStatusText.EndReading(end); if (FindCharInReadable('\r', start, end)) { aRv.ThrowTypeError<MSG_RESPONSE_INVALID_STATUSTEXT_ERROR>(); return nullptr; } // Reset iterator since FindCharInReadable advances it. aInit.mStatusText.BeginReading(start); if (FindCharInReadable('\n', start, end)) { aRv.ThrowTypeError<MSG_RESPONSE_INVALID_STATUSTEXT_ERROR>(); return nullptr; } RefPtr<InternalResponse> internalResponse = new InternalResponse(aInit.mStatus, aInit.mStatusText); UniquePtr<mozilla::ipc::PrincipalInfo> principalInfo; // Grab a valid channel info from the global so this response is 'valid' for // interception. if (NS_IsMainThread()) { ChannelInfo info; nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(global); if (window) { Document* doc = window->GetExtantDoc(); MOZ_ASSERT(doc); info.InitFromDocument(doc); principalInfo.reset(new mozilla::ipc::PrincipalInfo()); nsresult rv = PrincipalToPrincipalInfo(doc->NodePrincipal(), principalInfo.get()); if (NS_WARN_IF(NS_FAILED(rv))) { aRv.ThrowTypeError<MSG_FETCH_BODY_CONSUMED_ERROR>(); return nullptr; } internalResponse->InitChannelInfo(info); } else if (nsContentUtils::IsSystemPrincipal(global->PrincipalOrNull())) { info.InitFromChromeGlobal(global); internalResponse->InitChannelInfo(info); } /** * The channel info is left uninitialized if neither the above `if` nor * `else if` statements are executed; this could be because we're in a * WebExtensions content script, where the global (i.e. `global`) is a * wrapper, and the principal is an expanded principal. In this case, * as far as I can tell, there's no way to get the security info, but we'd * like the `Response` to be successfully constructed. */ } else { WorkerPrivate* worker = GetCurrentThreadWorkerPrivate(); MOZ_ASSERT(worker); internalResponse->InitChannelInfo(worker->GetChannelInfo()); principalInfo = MakeUnique<mozilla::ipc::PrincipalInfo>(worker->GetPrincipalInfo()); } internalResponse->SetPrincipalInfo(std::move(principalInfo)); RefPtr<Response> r = new Response(global, internalResponse, nullptr); if (aInit.mHeaders.WasPassed()) { internalResponse->Headers()->Clear(); // Instead of using Fill, create an object to allow the constructor to // unwrap the HeadersInit. RefPtr<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() && !aBody.Value().IsNull()) { if (aInit.mStatus == 204 || aInit.mStatus == 205 || aInit.mStatus == 304) { aRv.ThrowTypeError<MSG_RESPONSE_NULL_STATUS_WITH_BODY>(); return nullptr; } nsCString contentTypeWithCharset; nsCOMPtr<nsIInputStream> bodyStream; int64_t bodySize = InternalResponse::UNKNOWN_BODY_SIZE; const fetch::ResponseBodyInit& body = aBody.Value().Value(); if (body.IsReadableStream()) { aRv.MightThrowJSException(); JSContext* cx = aGlobal.Context(); const ReadableStream& readableStream = body.GetAsReadableStream(); JS::Rooted<JSObject*> readableStreamObj(cx, readableStream.Obj()); bool disturbed; bool locked; if (!JS::ReadableStreamIsDisturbed(cx, readableStreamObj, &disturbed) || !JS::ReadableStreamIsLocked(cx, readableStreamObj, &locked)) { aRv.StealExceptionFromJSContext(cx); return nullptr; } if (disturbed || locked) { aRv.ThrowTypeError<MSG_FETCH_BODY_CONSUMED_ERROR>(); return nullptr; } r->SetReadableStreamBody(cx, readableStreamObj); JS::ReadableStreamMode streamMode; if (!JS::ReadableStreamGetMode(cx, readableStreamObj, &streamMode)) { aRv.StealExceptionFromJSContext(cx); return nullptr; } if (streamMode == JS::ReadableStreamMode::ExternalSource) { // If this is a DOM generated ReadableStream, we can extract the // inputStream directly. JS::ReadableStreamUnderlyingSource* underlyingSource = nullptr; if (!JS::ReadableStreamGetExternalUnderlyingSource( cx, readableStreamObj, &underlyingSource)) { aRv.StealExceptionFromJSContext(cx); return nullptr; } MOZ_ASSERT(underlyingSource); aRv = FetchStream::RetrieveInputStream(underlyingSource, getter_AddRefs(bodyStream)); // The releasing of the external source is needed in order to avoid an // extra stream lock. if (!JS::ReadableStreamReleaseExternalUnderlyingSource( cx, readableStreamObj)) { aRv.StealExceptionFromJSContext(cx); return nullptr; } if (NS_WARN_IF(aRv.Failed())) { return nullptr; } } else { // If this is a JS-created ReadableStream, let's create a // FetchStreamReader. aRv = FetchStreamReader::Create(aGlobal.Context(), global, getter_AddRefs(r->mFetchStreamReader), getter_AddRefs(bodyStream)); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } } } else { uint64_t size = 0; aRv = ExtractByteStreamFromBody(body, getter_AddRefs(bodyStream), contentTypeWithCharset, size); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } bodySize = size; } internalResponse->SetBody(bodyStream, bodySize); if (!contentTypeWithCharset.IsVoid() && !internalResponse->Headers()->Has(NS_LITERAL_CSTRING("Content-Type"), aRv)) { // Ignore Append() failing here. ErrorResult error; internalResponse->Headers()->Append(NS_LITERAL_CSTRING("Content-Type"), contentTypeWithCharset, error); error.SuppressException(); } if (aRv.Failed()) { return nullptr; } } r->SetMimeType(); return r.forget(); }
nsresult LoadInfoToLoadInfoArgs(nsILoadInfo *aLoadInfo, OptionalLoadInfoArgs* aOptionalLoadInfoArgs) { if (!aLoadInfo) { // if there is no loadInfo, then there is nothing to serialize *aOptionalLoadInfoArgs = void_t(); return NS_OK; } nsresult rv = NS_OK; OptionalPrincipalInfo loadingPrincipalInfo = mozilla::void_t(); if (aLoadInfo->LoadingPrincipal()) { PrincipalInfo loadingPrincipalInfoTemp; rv = PrincipalToPrincipalInfo(aLoadInfo->LoadingPrincipal(), &loadingPrincipalInfoTemp); NS_ENSURE_SUCCESS(rv, rv); loadingPrincipalInfo = loadingPrincipalInfoTemp; } PrincipalInfo triggeringPrincipalInfo; rv = PrincipalToPrincipalInfo(aLoadInfo->TriggeringPrincipal(), &triggeringPrincipalInfo); nsTArray<PrincipalInfo> redirectChainIncludingInternalRedirects; for (const nsCOMPtr<nsIPrincipal>& principal : aLoadInfo->RedirectChainIncludingInternalRedirects()) { rv = PrincipalToPrincipalInfo(principal, redirectChainIncludingInternalRedirects.AppendElement()); NS_ENSURE_SUCCESS(rv, rv); } nsTArray<PrincipalInfo> redirectChain; for (const nsCOMPtr<nsIPrincipal>& principal : aLoadInfo->RedirectChain()) { rv = PrincipalToPrincipalInfo(principal, redirectChain.AppendElement()); NS_ENSURE_SUCCESS(rv, rv); } *aOptionalLoadInfoArgs = LoadInfoArgs( loadingPrincipalInfo, triggeringPrincipalInfo, aLoadInfo->GetSecurityFlags(), aLoadInfo->InternalContentPolicyType(), static_cast<uint32_t>(aLoadInfo->GetTainting()), aLoadInfo->GetUpgradeInsecureRequests(), aLoadInfo->GetVerifySignedContent(), aLoadInfo->GetEnforceSRI(), aLoadInfo->GetForceInheritPrincipalDropped(), aLoadInfo->GetInnerWindowID(), aLoadInfo->GetOuterWindowID(), aLoadInfo->GetParentOuterWindowID(), aLoadInfo->GetFrameOuterWindowID(), aLoadInfo->GetEnforceSecurity(), aLoadInfo->GetInitialSecurityCheckDone(), aLoadInfo->GetIsInThirdPartyContext(), aLoadInfo->GetOriginAttributes(), redirectChainIncludingInternalRedirects, redirectChain, aLoadInfo->CorsUnsafeHeaders(), aLoadInfo->GetForcePreflight(), aLoadInfo->GetIsPreflight()); return NS_OK; }
nsresult PrincipalToPrincipalInfo(nsIPrincipal* aPrincipal, PrincipalInfo* aPrincipalInfo) { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(aPrincipal); MOZ_ASSERT(aPrincipalInfo); bool isNullPrin; nsresult rv = aPrincipal->GetIsNullPrincipal(&isNullPrin); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } if (isNullPrin) { *aPrincipalInfo = NullPrincipalInfo(BasePrincipal::Cast(aPrincipal)->OriginAttributesRef()); return NS_OK; } nsCOMPtr<nsIScriptSecurityManager> secMan = do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } bool isSystemPrincipal; rv = secMan->IsSystemPrincipal(aPrincipal, &isSystemPrincipal); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } if (isSystemPrincipal) { *aPrincipalInfo = SystemPrincipalInfo(); return NS_OK; } // might be an expanded principal nsCOMPtr<nsIExpandedPrincipal> expanded = do_QueryInterface(aPrincipal); if (expanded) { nsTArray<PrincipalInfo> whitelistInfo; PrincipalInfo info; nsTArray< nsCOMPtr<nsIPrincipal> >* whitelist; MOZ_ALWAYS_SUCCEEDS(expanded->GetWhiteList(&whitelist)); for (uint32_t i = 0; i < whitelist->Length(); i++) { rv = PrincipalToPrincipalInfo((*whitelist)[i], &info); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } // append that spec to the whitelist whitelistInfo.AppendElement(info); } *aPrincipalInfo = ExpandedPrincipalInfo(BasePrincipal::Cast(aPrincipal)->OriginAttributesRef(), Move(whitelistInfo)); return NS_OK; } // must be a content principal nsCOMPtr<nsIURI> uri; rv = aPrincipal->GetURI(getter_AddRefs(uri)); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } if (NS_WARN_IF(!uri)) { return NS_ERROR_FAILURE; } nsCString spec; rv = uri->GetSpec(spec); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } *aPrincipalInfo = ContentPrincipalInfo(BasePrincipal::Cast(aPrincipal)->OriginAttributesRef(), spec); return NS_OK; }
already_AddRefed<IDBOpenDBRequest> IDBFactory::OpenInternal(JSContext* aCx, nsIPrincipal* aPrincipal, const nsAString& aName, const Optional<uint64_t>& aVersion, const Optional<StorageType>& aStorageType, bool aDeleting, CallerType aCallerType, ErrorResult& aRv) { MOZ_ASSERT(mWindow || mOwningObject); MOZ_ASSERT_IF(!mWindow, !mPrivateBrowsingMode); CommonFactoryRequestParams commonParams; PrincipalInfo& principalInfo = commonParams.principalInfo(); if (aPrincipal) { if (!NS_IsMainThread()) { MOZ_CRASH("Figure out security checks for workers! What's this " "aPrincipal we have on a worker thread?"); } MOZ_ASSERT(aCallerType == CallerType::System); MOZ_DIAGNOSTIC_ASSERT(mPrivateBrowsingMode == (aPrincipal->GetPrivateBrowsingId() > 0)); 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; bool isInternal = principalInfo.type() == PrincipalInfo::TSystemPrincipalInfo; if (!isInternal && principalInfo.type() == PrincipalInfo::TContentPrincipalInfo) { nsCString origin = principalInfo.get_ContentPrincipalInfo().originNoSuffix(); isInternal = QuotaManager::IsOriginInternal(origin); } // Allow storage attributes for add-ons independent of the pref. // This works in the main thread only, workers don't have the principal. bool isAddon = false; if (NS_IsMainThread()) { // aPrincipal is passed inconsistently, so even when we are already on // the main thread, we may have been passed a null aPrincipal. nsCOMPtr<nsIPrincipal> principal = PrincipalInfoToPrincipal(principalInfo); if (principal) { nsAutoString addonId; Unused << NS_WARN_IF(NS_FAILED(principal->GetAddonId(addonId))); isAddon = !addonId.IsEmpty(); } } if (isInternal) { // Chrome privilege and internal origins always get persistent storage. persistenceType = PERSISTENCE_TYPE_PERSISTENT; } else if (isAddon || DOMPrefs::IndexedDBStorageOptionsEnabled()) { persistenceType = PersistenceTypeFromStorage(aStorageType); } else { persistenceType = PERSISTENCE_TYPE_DEFAULT; } 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) { 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_SUCCEEDS(uuidGen->GenerateUUIDInPlace(&id)); newIDBThreadLocal = idbThreadLocal = new ThreadLocal(id); } PBackgroundChild* backgroundActor = BackgroundChild::GetOrCreateForCurrentThread(); if (NS_WARN_IF(!backgroundActor)) { IDB_REPORT_INTERNAL_ERR(); aRv.Throw(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR); return nullptr; } { BackgroundFactoryChild* actor = new BackgroundFactoryChild(this); // Set EventTarget for the top-level actor. // All child actors created later inherit the same event target. backgroundActor->SetEventTargetForActor(actor, EventTarget()); MOZ_ASSERT(actor->GetActorEventTarget()); mBackgroundActor = static_cast<BackgroundFactoryChild*>( backgroundActor->SendPBackgroundIDBFactoryConstructor(actor, idbThreadLocal->GetLoggingInfo())); if (NS_WARN_IF(!mBackgroundActor)) { mBackgroundActorFailed = true; 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(); } } RefPtr<IDBOpenDBRequest> request; if (mWindow) { JS::Rooted<JSObject*> scriptOwner(aCx, nsGlobalWindowInner::Cast(mWindow.get())->FastGetGlobalJSObject()); MOZ_ASSERT(scriptOwner); request = IDBOpenDBRequest::CreateForWindow(aCx, this, mWindow, scriptOwner); } else { JS::Rooted<JSObject*> scriptOwner(aCx, mOwningObject); request = IDBOpenDBRequest::CreateForJS(aCx, 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)); } 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; } return request.forget(); }
nsresult PrincipalToPrincipalInfo(nsIPrincipal* aPrincipal, PrincipalInfo* aPrincipalInfo) { MOZ_ASSERT(NS_IsMainThread()); MOZ_ASSERT(aPrincipal); MOZ_ASSERT(aPrincipalInfo); bool isNullPointer; nsresult rv = aPrincipal->GetIsNullPrincipal(&isNullPointer); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } if (isNullPointer) { *aPrincipalInfo = NullPrincipalInfo(); return NS_OK; } nsCOMPtr<nsIScriptSecurityManager> secMan = do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } bool isSystemPrincipal; rv = secMan->IsSystemPrincipal(aPrincipal, &isSystemPrincipal); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } if (isSystemPrincipal) { *aPrincipalInfo = SystemPrincipalInfo(); return NS_OK; } // might be an expanded principal nsCOMPtr<nsIExpandedPrincipal> expanded = do_QueryInterface(aPrincipal); if (expanded) { nsTArray<PrincipalInfo> whitelistInfo; PrincipalInfo info; nsTArray< nsCOMPtr<nsIPrincipal> >* whitelist; MOZ_ALWAYS_TRUE(NS_SUCCEEDED(expanded->GetWhiteList(&whitelist))); for (uint32_t i = 0; i < whitelist->Length(); i++) { rv = PrincipalToPrincipalInfo((*whitelist)[i], &info); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } // append that spec to the whitelist whitelistInfo.AppendElement(info); } *aPrincipalInfo = ExpandedPrincipalInfo(Move(whitelistInfo)); return NS_OK; } // must be a content principal nsCOMPtr<nsIURI> uri; rv = aPrincipal->GetURI(getter_AddRefs(uri)); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } if (NS_WARN_IF(!uri)) { return NS_ERROR_FAILURE; } nsCString spec; rv = uri->GetSpec(spec); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } bool isUnknownAppId; rv = aPrincipal->GetUnknownAppId(&isUnknownAppId); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } uint32_t appId; if (isUnknownAppId) { appId = nsIScriptSecurityManager::UNKNOWN_APP_ID; } else { rv = aPrincipal->GetAppId(&appId); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } } bool isInBrowserElement; rv = aPrincipal->GetIsInBrowserElement(&isInBrowserElement); if (NS_WARN_IF(NS_FAILED(rv))) { return rv; } *aPrincipalInfo = ContentPrincipalInfo(appId, isInBrowserElement, spec); return NS_OK; }
/* static */ already_AddRefed<BroadcastChannel> BroadcastChannel::Constructor(const GlobalObject& aGlobal, const nsAString& aChannel, ErrorResult& aRv) { nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobal.GetAsSupports()); // Window is null in workers. nsAutoCString origin; PrincipalInfo principalInfo; 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; } aRv = principal->GetOrigin(origin); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } aRv = PrincipalToPrincipalInfo(principal, &principalInfo); if (NS_WARN_IF(aRv.Failed())) { return nullptr; } } else { JSContext* cx = aGlobal.Context(); workerPrivate = GetWorkerPrivateFromContext(cx); MOZ_ASSERT(workerPrivate); RefPtr<InitializeRunnable> runnable = new InitializeRunnable(workerPrivate, origin, principalInfo, aRv); runnable->Dispatch(Closing, aRv); } if (aRv.Failed()) { return nullptr; } RefPtr<BroadcastChannel> bc = new BroadcastChannel(window, principalInfo, origin, aChannel); // 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->mWorkerHolder = new BroadcastChannelWorkerHolder(bc); if (NS_WARN_IF(!bc->mWorkerHolder->HoldWorker(workerPrivate, Closing))) { bc->mWorkerHolder = nullptr; aRv.Throw(NS_ERROR_FAILURE); return nullptr; } } return bc.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(); }