NS_IMETHODIMP nsStreamListenerTee::OnDataAvailable(nsIRequest *request, nsISupports *context, nsIInputStream *input, PRUint32 offset, PRUint32 count) { NS_ENSURE_TRUE(mListener, NS_ERROR_NOT_INITIALIZED); NS_ENSURE_TRUE(mSink, NS_ERROR_NOT_INITIALIZED); nsCOMPtr<nsIInputStream> tee; nsresult rv; if (!mInputTee) { rv = NS_NewInputStreamTee(getter_AddRefs(tee), input, mSink); if (NS_FAILED(rv)) return rv; mInputTee = do_QueryInterface(tee, &rv); if (NS_FAILED(rv)) return rv; } else { // re-initialize the input tee since the input stream may have changed. rv = mInputTee->SetSource(input); if (NS_FAILED(rv)) return rv; tee = do_QueryInterface(mInputTee, &rv); if (NS_FAILED(rv)) return rv; } return mListener->OnDataAvailable(request, context, tee, offset, count); }
NS_IMETHODIMP nsPluginStreamListenerPeer::OnDataAvailable(nsIRequest *request, nsISupports* aContext, nsIInputStream *aIStream, uint64_t sourceOffset, uint32_t aLength) { if (mRequests.IndexOfObject(GetBaseRequest(request)) == -1) { MOZ_ASSERT(false, "Received OnDataAvailable for untracked request."); return NS_ERROR_UNEXPECTED; } if (mRequestFailed) return NS_ERROR_FAILURE; if (mAbort) { uint32_t magicNumber = 0; // set it to something that is not the magic number. nsCOMPtr<nsISupportsPRUint32> container = do_QueryInterface(aContext); if (container) container->GetData(&magicNumber); if (magicNumber != MAGIC_REQUEST_CONTEXT) { // this is not one of our range requests mAbort = false; return NS_BINDING_ABORTED; } } nsresult rv = NS_OK; if (!mPStreamListener) return NS_ERROR_FAILURE; const char * url = nullptr; GetURL(&url); PLUGIN_LOG(PLUGIN_LOG_NOISY, ("nsPluginStreamListenerPeer::OnDataAvailable this=%p request=%p, offset=%llu, length=%u, url=%s\n", this, request, sourceOffset, aLength, url ? url : "no url set")); // if the plugin has requested an AsFileOnly stream, then don't // call OnDataAvailable if (mStreamType != NP_ASFILEONLY) { // get the absolute offset of the request, if one exists. nsCOMPtr<nsIByteRangeRequest> brr = do_QueryInterface(request); if (brr) { if (!mDataForwardToRequest) return NS_ERROR_FAILURE; int64_t absoluteOffset64 = 0; brr->GetStartRange(&absoluteOffset64); // XXX handle 64-bit for real int32_t absoluteOffset = (int32_t)int64_t(absoluteOffset64); // we need to track how much data we have forwarded to the // plugin. // FIXME: http://bugzilla.mozilla.org/show_bug.cgi?id=240130 // // Why couldn't this be tracked on the plugin info, and not in a // *hash table*? int32_t amtForwardToPlugin = mDataForwardToRequest->Get(absoluteOffset); mDataForwardToRequest->Put(absoluteOffset, (amtForwardToPlugin + aLength)); SetStreamOffset(absoluteOffset + amtForwardToPlugin); } nsCOMPtr<nsIInputStream> stream = aIStream; // if we are caching the file ourselves to disk, we want to 'tee' off // the data as the plugin read from the stream. We do this by the magic // of an input stream tee. if (mFileCacheOutputStream) { rv = NS_NewInputStreamTee(getter_AddRefs(stream), aIStream, mFileCacheOutputStream); if (NS_FAILED(rv)) return rv; } rv = mPStreamListener->OnDataAvailable(this, stream, aLength); // if a plugin returns an error, the peer must kill the stream // else the stream and PluginStreamListener leak if (NS_FAILED(rv)) request->Cancel(rv); } else { // if we don't read from the stream, OnStopRequest will never be called char* buffer = new char[aLength]; uint32_t amountRead, amountWrote = 0; rv = aIStream->Read(buffer, aLength, &amountRead); // if we are caching this to disk ourselves, lets write the bytes out. if (mFileCacheOutputStream) { while (amountWrote < amountRead && NS_SUCCEEDED(rv)) { rv = mFileCacheOutputStream->Write(buffer, amountRead, &amountWrote); } } delete [] buffer; } return rv; }