NS_IMETHODIMP HttpChannelParent::OnDataAvailable(nsIRequest *aRequest, nsISupports *aContext, nsIInputStream *aInputStream, PRUint32 aOffset, PRUint32 aCount) { LOG(("HttpChannelParent::OnDataAvailable [this=%x]\n", this)); nsCString data; nsresult rv = NS_ReadInputStreamToString(aInputStream, data, aCount); if (NS_FAILED(rv)) return rv; // OnDataAvailable is always preceded by OnStatus/OnProgress calls that set // mStoredStatus/mStoredProgress(Max) to appropriate values, unless // LOAD_BACKGROUND set. In that case, they'll have garbage values, but // child doesn't use them. if (mIPCClosed || !SendOnTransportAndData(mStoredStatus, mStoredProgress, mStoredProgressMax, data, aOffset, aCount)) { return NS_ERROR_UNEXPECTED; } return NS_OK; }
void WriteStumbleOnThread::Upload() { MOZ_ASSERT(!NS_IsMainThread()); bool b = sIsUploading.exchange(true); if (b) { return; } time_t seconds = time(0); int day = seconds / (60 * 60 * 24); if (sUploadFreqGuard.daySinceEpoch < day) { sUploadFreqGuard.daySinceEpoch = day; sUploadFreqGuard.attempts = 0; } sUploadFreqGuard.attempts++; if (sUploadFreqGuard.attempts > MAX_UPLOAD_ATTEMPTS) { STUMBLER_ERR("Too many upload attempts today"); return; } nsCOMPtr<nsIFile> tmpFile; nsresult rv = nsDumpUtils::OpenTempFile(kOutputFileNameCompleted, getter_AddRefs(tmpFile), kOutputDirName, nsDumpUtils::CREATE); int64_t fileSize; rv = tmpFile->GetFileSize(&fileSize); if (NS_WARN_IF(NS_FAILED(rv))) { STUMBLER_ERR("GetFileSize failed"); sIsUploading = false; return; } STUMBLER_LOG("size : %lld", fileSize); if (fileSize <= 0) { sIsUploading = false; return; } // prepare json into nsIInputStream nsCOMPtr<nsIInputStream> inStream; rv = NS_NewLocalFileInputStream(getter_AddRefs(inStream), tmpFile, -1, -1, nsIFileInputStream::DEFER_OPEN); NS_ENSURE_TRUE_VOID(inStream); nsAutoCString bufStr; rv = NS_ReadInputStreamToString(inStream, bufStr, fileSize); NS_ENSURE_SUCCESS_VOID(rv); nsCOMPtr<nsIRunnable> uploader = new UploadStumbleRunnable(bufStr); NS_DispatchToMainThread(uploader); }
NS_IMETHODIMP PSMContentDownloaderChild::OnDataAvailable(nsIRequest* request, nsISupports* context, nsIInputStream* aIStream, uint64_t aSourceOffset, uint32_t aLength) { nsCString chunk; nsresult rv = NS_ReadInputStreamToString(aIStream, chunk, aLength); if (NS_FAILED(rv)) { return rv; } mozilla::unused << SendOnDataAvailable(chunk, aSourceOffset, aLength); return NS_OK; }
NS_IMETHODIMP PSMContentStreamListener::OnDataAvailable(nsIRequest* request, nsISupports* context, nsIInputStream* aIStream, uint64_t aSourceOffset, uint32_t aLength) { PR_LOG(gPIPNSSLog, PR_LOG_DEBUG, ("CertDownloader::OnDataAvailable\n")); nsCString chunk; nsresult rv = NS_ReadInputStreamToString(aIStream, chunk, aLength); if (NS_FAILED(rv)) { return rv; } mByteData.Append(chunk); return NS_OK; }
NS_IMETHODIMP HttpChannelParent::OnDataAvailable(nsIRequest *aRequest, nsISupports *aContext, nsIInputStream *aInputStream, PRUint32 aOffset, PRUint32 aCount) { LOG(("HttpChannelParent::OnDataAvailable [this=%x]\n", this)); nsCString data; nsresult rv = NS_ReadInputStreamToString(aInputStream, data, aCount); if (NS_FAILED(rv)) return rv; if (mIPCClosed || !SendOnDataAvailable(data, aOffset, aCount)) return NS_ERROR_UNEXPECTED; return NS_OK; }
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; }
NS_IMETHODIMP HttpChannelChild::AsyncOpen(nsIStreamListener *listener, nsISupports *aContext) { LOG(("HttpChannelChild::AsyncOpen [this=%x uri=%s]\n", this, mSpec.get())); if (mCanceled) return mStatus; NS_ENSURE_TRUE(gNeckoChild != nsnull, NS_ERROR_FAILURE); NS_ENSURE_ARG_POINTER(listener); NS_ENSURE_TRUE(!mIsPending, NS_ERROR_IN_PROGRESS); NS_ENSURE_TRUE(!mWasOpened, NS_ERROR_ALREADY_OPENED); // Port checked in parent, but duplicate here so we can return with error // immediately nsresult rv; rv = NS_CheckPortSafety(mURI); if (NS_FAILED(rv)) return rv; // Prepare uploadStream for POST data nsCAutoString uploadStreamData; PRInt32 uploadStreamInfo; if (mUploadStream) { // Read entire POST stream into string: // This is a temporary measure until bug 564553 is implemented: we're doing // a blocking read of a potentially arbitrarily large stream, so this isn't // performant/safe for large file uploads. PRUint32 bytes; mUploadStream->Available(&bytes); if (bytes > 0) { rv = NS_ReadInputStreamToString(mUploadStream, uploadStreamData, bytes); if (NS_FAILED(rv)) return rv; } uploadStreamInfo = mUploadStreamHasHeaders ? eUploadStream_hasHeaders : eUploadStream_hasNoHeaders; } else { uploadStreamInfo = eUploadStream_null; } const char *cookieHeader = mRequestHead.PeekHeader(nsHttp::Cookie); if (cookieHeader) { mUserSetCookieHeader = cookieHeader; } AddCookiesToRequest(); // // NOTE: From now on we must return NS_OK; all errors must be handled via // OnStart/OnStopRequest // // notify "http-on-modify-request" observers gHttpHandler->OnModifyRequest(this); mIsPending = PR_TRUE; mWasOpened = PR_TRUE; mListener = listener; mListenerContext = aContext; // add ourselves to the load group. if (mLoadGroup) mLoadGroup->AddRequest(this, nsnull); if (mCanceled) { // We may have been canceled already, either by on-modify-request // listeners or by load group observers; in that case, don't create IPDL // connection. See nsHttpChannel::AsyncOpen(). // Clear mCanceled here, or we will bail out at top of OnCancel(). mCanceled = false; OnCancel(mStatus); return NS_OK; } // // Send request to the chrome process... // // FIXME: bug 558623: Combine constructor and SendAsyncOpen into one IPC msg mozilla::dom::TabChild* tabChild = nsnull; nsCOMPtr<nsITabChild> iTabChild; GetCallback(iTabChild); if (iTabChild) { tabChild = static_cast<mozilla::dom::TabChild*>(iTabChild.get()); } // The socket transport in the chrome process now holds a logical ref to us // until OnStopRequest, or we do a redirect, or we hit an IPDL error. AddIPDLReference(); gNeckoChild->SendPHttpChannelConstructor(this, tabChild); SendAsyncOpen(IPC::URI(mURI), IPC::URI(mOriginalURI), IPC::URI(mDocumentURI), IPC::URI(mReferrer), mLoadFlags, mRequestHeaders, mRequestHead.Method(), uploadStreamData, uploadStreamInfo, mPriority, mRedirectionLimit, mAllowPipelining, mForceAllowThirdPartyCookie, mSendResumeAt, mStartPos, mEntityID); return NS_OK; }