mStreamBuffer = (char*) PR_Malloc(mStreamBufferSize); if (!mStreamBuffer) return NS_ERROR_OUT_OF_MEMORY; }   NPP npp; mInst->GetNPP(&npp); PRInt32 streamOffset; pluginInfo->GetStreamOffset(&streamOffset); mPosition = streamOffset; streamOffset += length;          pluginInfo->SetStreamOffset(streamOffset);     if ((PRInt32)mNPStream.end < streamOffset) mNPStream.end = streamOffset;  do { PRUint32 bytesToRead = PR_MIN(length, mStreamBufferSize); PRInt32 amountRead = 0; rv = input->Read(mStreamBuffer, bytesToRead, (PRUint32*)&amountRead); if (amountRead == 0 || NS_FAILED(rv)) { NS_WARNING("input->Read() returns no data, it's almost impossible to get here"); break;
else {   numtowrite = length;
ns4xPluginStreamListener::OnDataAvailable(nsIPluginStreamInfo* pluginInfo,                                          nsIInputStream* input,                                          PRUint32 length){  nsresult rv = NS_ERROR_FAILURE;  if (!mInst || !mInst->IsStarted())    return rv;  const NPPluginFuncs *callbacks = nsnull;  mInst->GetCallbacks(&callbacks);  // check out if plugin implements NPP_Write call  if(!callbacks || !callbacks->write || !length)    return rv; // it'll cancel necko transaction     if (!mStreamBuffer)  {    // to optimize the mem usage & performance we have to allocate mStreamBuffer here    // in first ODA when length of data available in input stream is known.    // mStreamBuffer will be freed in DTOR.    // we also have to remember the size of that buff    // to make safe consecutive Read() calls form input stream into our buff.    if (length >= MAX_PLUGIN_NECKO_BUFFER) {        // ">" is rare case for decoded stream, but lets eat it all        mStreamBufferSize = length;        } else {      PRUint32 contentLength;      pluginInfo->GetLength(&contentLength);      if (contentLength < MAX_PLUGIN_NECKO_BUFFER) {        // this is most common case for contentLength < 16k        mStreamBufferSize = length < contentLength ? contentLength:length;       } else {        mStreamBufferSize = MAX_PLUGIN_NECKO_BUFFER;      }    }    mStreamBuffer = (char*) PR_Malloc(mStreamBufferSize);    if (!mStreamBuffer)      return NS_ERROR_OUT_OF_MEMORY;  }    // prepare NPP_ calls params  NPP npp;      mInst->GetNPP(&npp);  PRInt32 streamOffset;  pluginInfo->GetStreamOffset(&streamOffset);  mPosition = streamOffset;  streamOffset += length;  // Set new stream offset for the next ODA call  // regardless of how following NPP_Write call will behave  // we pretend to consume all data from the input stream.  // It's possible that current steam position will be overwritten  // from NPP_RangeRequest call made from NPP_Write, so  // we cannot call SetStreamOffset after NPP_Write.  // Note: there is a special case when data flow  // should be temporarily stopped if NPP_WriteReady returns 0 (bug #89270)  pluginInfo->SetStreamOffset(streamOffset);  // set new end in case the content is compressed  // initial end is less than end of decompressed stream  // and some plugins (e.g. acrobat) can fail.   if ((PRInt32)mNPStream.end < streamOffset)    mNPStream.end = streamOffset;  do   {    PRUint32 bytesToRead = PR_MIN(length, mStreamBufferSize);    PRInt32 amountRead = 0;    rv = input->Read(mStreamBuffer, bytesToRead, (PRUint32*)&amountRead);    if (amountRead == 0 || NS_FAILED(rv)) {      NS_WARNING("input->Read() returns no data, it's almost impossible to get here");      break;    }    // this loop in general case will end on length <= 0, without extra input->Read() call    length -= amountRead;        char *ptrStreamBuffer = mStreamBuffer; // tmp ptr    // it is possible plugin's NPP_Write() returns 0 byte consumed    // we use zeroBytesWriteCount to count situation like this    // and break the loop    PRInt32 zeroBytesWriteCount = 0;        // amountRead tells us how many bytes were put in the buffer    // WriteReady returns to us how many bytes the plugin is     // ready to handle  - we have to keep calling WriteReady and    // Write until amountRead > 0    for(;;)     { // it breaks on (amountRead <= 0) or on error      PRInt32   numtowrite;      if (callbacks->writeready)      {        NS_TRY_SAFE_CALL_RETURN(numtowrite,           CallNPP_WriteReadyProc(callbacks->writeready, npp, &mNPStream),          mInst->fLibrary, mInst);               NPP_PLUGIN_LOG(PLUGIN_LOG_NOISY,          ("NPP WriteReady called: this=%p, npp=%p, return(towrite)=%d, url=%s\n",          this, npp, numtowrite, mNPStream.url));                // if WriteReady returned 0, the plugin is not ready to handle         // the data, return FAILURE for now        if (numtowrite <= 0) {          NS_ASSERTION(numtowrite,"WriteReady returned Zero");          rv = NS_ERROR_FAILURE;          break;        }        if (numtowrite > amountRead)          numtowrite = amountRead;      }      else      {        // if WriteReady is not supported by the plugin,         // just write the whole buffer        numtowrite = amountRead;      }            PRInt32   writeCount = 0; // bytes consumed by plugin instance            NS_TRY_SAFE_CALL_RETURN(writeCount,         CallNPP_WriteProc(callbacks->write, npp, &mNPStream, mPosition, numtowrite, (void *)ptrStreamBuffer),        mInst->fLibrary, mInst);            NPP_PLUGIN_LOG(PLUGIN_LOG_NOISY,        ("NPP Write called: this=%p, npp=%p, pos=%d, len=%d, buf=%s, return(written)=%d,  url=%s\n",        this, npp, mPosition, numtowrite, (char *)ptrStreamBuffer, writeCount, mNPStream.url));            if (writeCount > 0)      {        mPosition += writeCount;        amountRead -= writeCount;        if (amountRead <= 0)          break; // in common case we'll break for(;;) loop here                 zeroBytesWriteCount = 0;        if (writeCount % sizeof(long)) {          // memmove will take care  about alignment           memmove(ptrStreamBuffer,ptrStreamBuffer+writeCount,amountRead);        } else {          // if aligned we can use ptrStreamBuffer += to eliminate memmove()          ptrStreamBuffer += writeCount;        }      }       else if (writeCount == 0)      {        // if NPP_Write() returns writeCount == 0 lets say 3 times in a raw        // lets consider this as end of ODA call (plugin isn't hungry, or broken) without an error.        if (++zeroBytesWriteCount == 3)        {          length = 0; // break do{}while          rv = NS_OK;          break;        }      }       else      {        length = 0; // break do{}while        rv = NS_ERROR_FAILURE;        break;      }      } // end of for(;;)  } while ((PRInt32)(length) > 0);  return rv == NS_BASE_STREAM_WOULD_BLOCK ? NS_OK:rv;}