void
FTPChannelChild::DoOnDataAvailable(const nsCString& data,
                                   const PRUint32& offset,
                                   const PRUint32& count)
{
  LOG(("FTPChannelChild::RecvOnDataAvailable [this=%x]\n", this));

  if (mCanceled)
    return;

  // NOTE: the OnDataAvailable contract requires the client to read all the data
  // in the inputstream.  This code relies on that ('data' will go away after
  // this function).  Apparently the previous, non-e10s behavior was to actually
  // support only reading part of the data, allowing later calls to read the
  // rest.
  nsCOMPtr<nsIInputStream> stringStream;
  nsresult rv = NS_NewByteInputStream(getter_AddRefs(stringStream),
                                      data.get(),
                                      count,
                                      NS_ASSIGNMENT_DEPEND);
  if (NS_FAILED(rv)) {
    Cancel(rv);
    return;
  }

  AutoEventEnqueuer ensureSerialDispatch(this);
  rv = mListener->OnDataAvailable(this, mListenerContext,
                                  stringStream, offset, count);
  if (NS_FAILED(rv))
    Cancel(rv);
  stringStream->Close();
}
示例#2
0
void
DataTransfer::FillInExternalCustomTypes(nsIVariant* aData, uint32_t aIndex,
                                        nsIPrincipal* aPrincipal)
{
  char* chrs;
  uint32_t len = 0;
  nsresult rv = aData->GetAsStringWithSize(&len, &chrs);
  if (NS_FAILED(rv)) {
    return;
  }

  CheckedInt<int32_t> checkedLen(len);
  if (!checkedLen.isValid()) {
    return;
  }

  nsCOMPtr<nsIInputStream> stringStream;
  NS_NewByteInputStream(getter_AddRefs(stringStream), chrs, checkedLen.value(),
                        NS_ASSIGNMENT_ADOPT);

  nsCOMPtr<nsIObjectInputStream> stream =
    NS_NewObjectInputStream(stringStream);

  uint32_t type;
  do {
    rv = stream->Read32(&type);
    NS_ENSURE_SUCCESS_VOID(rv);
    if (type == eCustomClipboardTypeId_String) {
      uint32_t formatLength;
      rv = stream->Read32(&formatLength);
      NS_ENSURE_SUCCESS_VOID(rv);
      char* formatBytes;
      rv = stream->ReadBytes(formatLength, &formatBytes);
      NS_ENSURE_SUCCESS_VOID(rv);
      nsAutoString format;
      format.Adopt(reinterpret_cast<char16_t*>(formatBytes),
                   formatLength / sizeof(char16_t));

      uint32_t dataLength;
      rv = stream->Read32(&dataLength);
      NS_ENSURE_SUCCESS_VOID(rv);
      char* dataBytes;
      rv = stream->ReadBytes(dataLength, &dataBytes);
      NS_ENSURE_SUCCESS_VOID(rv);
      nsAutoString data;
      data.Adopt(reinterpret_cast<char16_t*>(dataBytes),
                 dataLength / sizeof(char16_t));

      RefPtr<nsVariantCC> variant = new nsVariantCC();
      rv = variant->SetAsAString(data);
      NS_ENSURE_SUCCESS_VOID(rv);

      SetDataWithPrincipal(format, variant, aIndex, aPrincipal);
    }
  } while (type != eCustomClipboardTypeId_None);
}
示例#3
0
static nsresult
moz_gdk_pixbuf_to_channel(GdkPixbuf* aPixbuf, nsIURI *aURI,
                          nsIChannel **aChannel)
{
  int width = gdk_pixbuf_get_width(aPixbuf);
  int height = gdk_pixbuf_get_height(aPixbuf);
  NS_ENSURE_TRUE(height < 256 && width < 256 && height > 0 && width > 0 &&
                 gdk_pixbuf_get_colorspace(aPixbuf) == GDK_COLORSPACE_RGB &&
                 gdk_pixbuf_get_bits_per_sample(aPixbuf) == 8 &&
                 gdk_pixbuf_get_has_alpha(aPixbuf) &&
                 gdk_pixbuf_get_n_channels(aPixbuf) == 4,
                 NS_ERROR_UNEXPECTED);

  const int n_channels = 4;
  gsize buf_size = 3 + n_channels * height * width;
  PRUint8 * const buf = (PRUint8*)NS_Alloc(buf_size);
  NS_ENSURE_TRUE(buf, NS_ERROR_OUT_OF_MEMORY);
  PRUint8 *out = buf;

  *(out++) = width;
  *(out++) = height;
  *(out++) = 8; // bits of alpha per pixel
  
  const guchar * const pixels = gdk_pixbuf_get_pixels(aPixbuf);
  int rowextra = gdk_pixbuf_get_rowstride(aPixbuf) - width * n_channels;

  // encode the RGB data and the A data
  const guchar * in = pixels;
  PRUint8 *alpha_out = out + height * width * 3;
#ifdef DEBUG
  PRUint8 * const alpha_start = alpha_out;
#endif
  for (int y = 0; y < height; ++y, in += rowextra) {
    for (int x = 0; x < width; ++x) {
      *(out++) = *(in++); // R
      *(out++) = *(in++); // G
      *(out++) = *(in++); // B
      *(alpha_out++) = *(in++); // A
    }
  }

  NS_ASSERTION(out == alpha_start && alpha_out == buf + buf_size,
               "size miscalculation");

  nsresult rv;
  nsCOMPtr<nsIInputStream> stream;
  rv = NS_NewByteInputStream(getter_AddRefs(stream), (char*)buf, buf_size);
  NS_ENSURE_SUCCESS(rv, rv);

  nsCOMPtr<nsIStringInputStream> sstream = do_QueryInterface(stream);
  sstream->AdoptData((char*)buf, buf_size); // previous call was |ShareData|

  rv = NS_NewInputStreamChannel(aChannel, aURI, stream,
                                NS_LITERAL_CSTRING("image/icon"));
  return rv;
}
示例#4
0
NS_IMETHODIMP
nsJSON::Decode(const nsAString& json)
{
  const PRUnichar *data;
  PRUint32 len = NS_StringGetData(json, &data);
  nsCOMPtr<nsIInputStream> stream;
  nsresult rv = NS_NewByteInputStream(getter_AddRefs(stream),
                                      (const char*) data,
                                      len * sizeof(PRUnichar),
                                      NS_ASSIGNMENT_DEPEND);
  NS_ENSURE_SUCCESS(rv, rv);
  return DecodeInternal(stream, len, PR_FALSE);
}
示例#5
0
NS_IMETHODIMP
nsJSON::LegacyDecode(const nsAString& json, JSContext* cx, JS::Value* aRetval)
{
  const PRUnichar *data;
  uint32_t len = NS_StringGetData(json, &data);
  nsCOMPtr<nsIInputStream> stream;
  nsresult rv = NS_NewByteInputStream(getter_AddRefs(stream),
                                      (const char*) data,
                                      len * sizeof(PRUnichar),
                                      NS_ASSIGNMENT_DEPEND);
  NS_ENSURE_SUCCESS(rv, rv);
  return DecodeInternal(cx, stream, len, false, aRetval, LEGACY);
}
示例#6
0
NS_IMETHODIMP
nsSAXXMLReader::ParseFromString(const nsAString &aStr,
                                const char *aContentType)
{
  // Don't call this in the middle of an async parse
  NS_ENSURE_TRUE(!mIsAsyncParse, NS_ERROR_FAILURE);

  NS_ConvertUTF16toUTF8 data(aStr);

  // The new stream holds a reference to the buffer
  nsCOMPtr<nsIInputStream> stream;
  nsresult rv = NS_NewByteInputStream(getter_AddRefs(stream),
                                      data.get(), data.Length());
  NS_ENSURE_SUCCESS(rv, rv);
  return ParseFromStream(stream, "UTF-8", aContentType);
}
示例#7
0
NS_IMETHODIMP
nsJSON::Decode(const nsAString& json, JSContext* cx, JS::Value* aRetval)
{
  nsresult rv = WarnDeprecatedMethod(DecodeWarning);
  if (NS_FAILED(rv))
    return rv;

  const PRUnichar *data;
  uint32_t len = NS_StringGetData(json, &data);
  nsCOMPtr<nsIInputStream> stream;
  rv = NS_NewByteInputStream(getter_AddRefs(stream),
                             reinterpret_cast<const char*>(data),
                             len * sizeof(PRUnichar),
                             NS_ASSIGNMENT_DEPEND);
  NS_ENSURE_SUCCESS(rv, rv);
  return DecodeInternal(cx, stream, len, false, aRetval);
}
示例#8
0
// static
already_AddRefed<nsIInputStream>
FileHandleBase::GetInputStream(const ArrayBuffer& aValue,
                               uint64_t* aInputLength, ErrorResult& aRv)
{
  aValue.ComputeLengthAndData();
  const char* data = reinterpret_cast<const char*>(aValue.Data());
  uint32_t length = aValue.Length();

  nsCOMPtr<nsIInputStream> stream;
  aRv = NS_NewByteInputStream(getter_AddRefs(stream), data, length,
                              NS_ASSIGNMENT_COPY);
  if (aRv.Failed()) {
    return nullptr;
  }

  *aInputLength = length;
  return stream.forget();
}
示例#9
0
static nsresult
GetBufferDataAsStream(const uint8_t* aData, uint32_t aDataLength,
                      nsIInputStream** aResult, uint64_t* aContentLength,
                      nsACString& aContentType, nsACString& aCharset)
{
  aContentType.SetIsVoid(true);
  aCharset.Truncate();

  *aContentLength = aDataLength;
  const char* data = reinterpret_cast<const char*>(aData);

  nsCOMPtr<nsIInputStream> stream;
  nsresult rv = NS_NewByteInputStream(getter_AddRefs(stream), data, aDataLength,
                                      NS_ASSIGNMENT_COPY);
  NS_ENSURE_SUCCESS(rv, rv);

  stream.forget(aResult);

  return NS_OK;
}
static nsresult
CreateBufferedStream(const uint8_t *aBuffer, uint32_t aBufLen,
                     nsCOMPtr<nsIInputStream> &aResult)
{
    nsCOMPtr<nsIInputStream> stream;
    nsresult rv = NS_NewByteInputStream(getter_AddRefs(stream),
                                        reinterpret_cast<const char *>(aBuffer),
                                        aBufLen, NS_ASSIGNMENT_DEPEND);
    NS_ENSURE_SUCCESS(rv, rv);

    nsCOMPtr<nsIInputStream> aBufferedStream;
    if (!NS_InputStreamIsBuffered(stream)) {
        rv = NS_NewBufferedInputStream(getter_AddRefs(aBufferedStream), stream, 4096);
        NS_ENSURE_SUCCESS(rv, rv);
        stream = aBufferedStream;
    }

    aResult = stream;

    return NS_OK;
}
void
WyciwygChannelChild::OnDataAvailable(const nsCString& data,
                                     const PRUint32& offset)
{
  LOG(("WyciwygChannelChild::RecvOnDataAvailable [this=%x]\n", this));

  if (mCanceled)
    return;

  mState = WCC_ONDATA;

  // NOTE: the OnDataAvailable contract requires the client to read all the data
  // in the inputstream.  This code relies on that ('data' will go away after
  // this function).  Apparently the previous, non-e10s behavior was to actually
  // support only reading part of the data, allowing later calls to read the
  // rest.
  nsCOMPtr<nsIInputStream> stringStream;
  nsresult rv = NS_NewByteInputStream(getter_AddRefs(stringStream),
                                      data.get(),
                                      data.Length(),
                                      NS_ASSIGNMENT_DEPEND);
  if (NS_FAILED(rv)) {
    Cancel(rv);
    return;
  }

  AutoEventEnqueuer ensureSerialDispatch(mEventQ);
  
  rv = mListener->OnDataAvailable(this, mListenerContext,
                                  stringStream, offset, data.Length());
  if (NS_FAILED(rv))
    Cancel(rv);

  if (mProgressSink && NS_SUCCEEDED(rv) && !(mLoadFlags & LOAD_BACKGROUND))
    mProgressSink->OnProgress(this, nsnull, PRUint64(offset + data.Length()),
                              PRUint64(mContentLength));
}
示例#12
0
nsresult nsDeflateConverter::PushAvailableData(nsIRequest *aRequest,
                                               nsISupports *aContext)
{
    uint32_t bytesToWrite = sizeof(mWriteBuffer) - mZstream.avail_out;
    // We don't need to do anything if there isn't any data
    if (bytesToWrite == 0)
        return NS_OK;

    MOZ_ASSERT(bytesToWrite <= INT32_MAX);
    nsCOMPtr<nsIInputStream> stream;
    nsresult rv = NS_NewByteInputStream(getter_AddRefs(stream),
					(char*)mWriteBuffer, bytesToWrite);
    NS_ENSURE_SUCCESS(rv, rv);

    rv = mListener->OnDataAvailable(aRequest, mContext, stream, mOffset,
                                    bytesToWrite);

    // now set the state for 'deflate'
    mZstream.next_out = mWriteBuffer;
    mZstream.avail_out = sizeof(mWriteBuffer);

    mOffset += bytesToWrite;
    return rv;
}
// nsFaviconService::OptimizeFaviconImage
//
// Given a blob of data (a image file already read into a buffer), optimize
// its size by recompressing it as a 16x16 PNG.
nsresult
nsFaviconService::OptimizeFaviconImage(const PRUint8* aData, PRUint32 aDataLen,
                                       const nsACString& aMimeType,
                                       nsACString& aNewData,
                                       nsACString& aNewMimeType)
{
  nsresult rv;
  

  nsCOMPtr<imgITools> imgtool = do_CreateInstance("@mozilla.org/image/tools;1");

  nsCOMPtr<nsIInputStream> stream;
  rv = NS_NewByteInputStream(getter_AddRefs(stream),
                reinterpret_cast<const char*>(aData), aDataLen,
                NS_ASSIGNMENT_DEPEND);
  NS_ENSURE_SUCCESS(rv, rv);

  // decode image
  nsCOMPtr<imgIContainer> container;
  rv = imgtool->DecodeImageData(stream, aMimeType, getter_AddRefs(container));
  NS_ENSURE_SUCCESS(rv, rv);

  aNewMimeType.AssignLiteral("image/png");

  // scale and recompress
  nsCOMPtr<nsIInputStream> iconStream;
  rv = imgtool->EncodeScaledImage(container, aNewMimeType, 16, 16,
                                  getter_AddRefs(iconStream));
  NS_ENSURE_SUCCESS(rv, rv);

  // Read the stream into a new buffer.
  rv = NS_ConsumeStream(iconStream, PR_UINT32_MAX, aNewData);
  NS_ENSURE_SUCCESS(rv, rv);

  return NS_OK;
}
示例#14
0
NS_IMETHODIMP
AsyncFaviconDataReady::OnComplete(nsIURI *aFaviconURI,
                                  uint32_t aDataLen,
                                  const uint8_t *aData, 
                                  const nsACString &aMimeType)
{
  if (!aDataLen || !aData) {
    if (mURLShortcut) {
      OnFaviconDataNotAvailable();
    }
    
    return NS_OK;
  }

  nsCOMPtr<nsIFile> icoFile;
  nsresult rv = FaviconHelper::GetOutputIconPath(mNewURI, icoFile, mURLShortcut);
  NS_ENSURE_SUCCESS(rv, rv);
  
  nsAutoString path;
  rv = icoFile->GetPath(path);
  NS_ENSURE_SUCCESS(rv, rv);

  // Convert the obtained favicon data to an input stream
  nsCOMPtr<nsIInputStream> stream;
  rv = NS_NewByteInputStream(getter_AddRefs(stream),
                             reinterpret_cast<const char*>(aData),
                             aDataLen,
                             NS_ASSIGNMENT_DEPEND);
  NS_ENSURE_SUCCESS(rv, rv);

  // Decode the image from the format it was returned to us in (probably PNG)
  nsAutoCString mimeTypeOfInputData;
  mimeTypeOfInputData.AssignLiteral("image/vnd.microsoft.icon");
  nsCOMPtr<imgIContainer> container;
  nsCOMPtr<imgITools> imgtool = do_CreateInstance("@mozilla.org/image/tools;1");
  rv = imgtool->DecodeImageData(stream, aMimeType,
                                getter_AddRefs(container));
  NS_ENSURE_SUCCESS(rv, rv);

  nsRefPtr<gfxASurface> imgFrame =
    container->GetFrame(imgIContainer::FRAME_FIRST, 0);
  NS_ENSURE_TRUE(imgFrame, NS_ERROR_FAILURE);

  nsRefPtr<gfxImageSurface> imageSurface;
  gfxIntSize size;
  if (mURLShortcut) {
    imageSurface =
      new gfxImageSurface(gfxIntSize(48, 48),
                          gfxImageFormat::ARGB32);
    gfxContext context(imageSurface);
    context.SetOperator(gfxContext::OPERATOR_SOURCE);
    context.SetColor(gfxRGBA(1, 1, 1, 1));
    context.Rectangle(gfxRect(0, 0, 48, 48));
    context.Fill();

    context.Translate(gfxPoint(16, 16));
    context.SetOperator(gfxContext::OPERATOR_OVER);
    context.DrawSurface(imgFrame,  gfxSize(16, 16));
    size = imageSurface->GetSize();
  } else {
    imageSurface = imgFrame->GetAsReadableARGB32ImageSurface();
    size.width = GetSystemMetrics(SM_CXSMICON);
    size.height = GetSystemMetrics(SM_CYSMICON);
    if (!size.width || !size.height) {
      size.width = 16;
      size.height = 16;
    }
  }

  // Allocate a new buffer that we own and can use out of line in 
  // another thread.  Copy the favicon raw data into it.
  const fallible_t fallible = fallible_t();
  uint8_t *data = new (fallible) uint8_t[imageSurface->GetDataSize()];
  if (!data) {
    return NS_ERROR_OUT_OF_MEMORY;
  }
  memcpy(data, imageSurface->Data(), imageSurface->GetDataSize());

  // AsyncEncodeAndWriteIcon takes ownership of the heap allocated buffer
  nsCOMPtr<nsIRunnable> event = new AsyncEncodeAndWriteIcon(path, data,
                                                            imageSurface->GetDataSize(),
                                                            imageSurface->Stride(),
                                                            size.width,
                                                            size.height,
                                                            mURLShortcut);
  mIOThread->Dispatch(event, NS_DISPATCH_NORMAL);

  return NS_OK;
}
示例#15
0
nsresult
imgContainer::ReloadImages(void)
{
  NS_ASSERTION(!mRestoreData.IsEmpty(),
               "imgContainer::ReloadImages(): mRestoreData should not be empty");
  NS_ASSERTION(mRestoreDataDone,
               "imgContainer::ReloadImages(): mRestoreDataDone shoudl be true!");

  mNumFrames = 0;
  NS_ASSERTION(mFrames.Count() == 0,
               "imgContainer::ReloadImages(): mFrames should be empty");

  nsCAutoString decoderCID(NS_LITERAL_CSTRING("@mozilla.org/image/decoder;2?type=") + mDiscardableMimeType);

  nsCOMPtr<imgIDecoder> decoder = do_CreateInstance(decoderCID.get());
  if (!decoder) {
    PR_LOG(gCompressedImageAccountingLog, PR_LOG_WARNING,
           ("CompressedImageAccounting: imgContainer::ReloadImages() could not create decoder for %s",
            mDiscardableMimeType.get()));
    return NS_IMAGELIB_ERROR_NO_DECODER;
  }

  nsCOMPtr<imgILoad> loader = new ContainerLoader();
  if (!loader) {
    PR_LOG(gCompressedImageAccountingLog, PR_LOG_WARNING,
           ("CompressedImageAccounting: imgContainer::ReloadImages() could not allocate ContainerLoader "
            "when reloading the images for container %p",
            this));
    return NS_ERROR_OUT_OF_MEMORY;
  }

  loader->SetImage(this);

  nsresult result = decoder->Init(loader);
  if (NS_FAILED(result)) {
    PR_LOG(gCompressedImageAccountingLog, PR_LOG_WARNING,
           ("CompressedImageAccounting: imgContainer::ReloadImages() image container %p "
            "failed to initialize the decoder (%s)",
            this,
            mDiscardableMimeType.get()));
    return result;
  }

  nsCOMPtr<nsIInputStream> stream;
  result = NS_NewByteInputStream(getter_AddRefs(stream), mRestoreData.Elements(), mRestoreData.Length(), NS_ASSIGNMENT_DEPEND);
  NS_ENSURE_SUCCESS(result, result);

  if (PR_LOG_TEST(gCompressedImageAccountingLog, PR_LOG_DEBUG)) {
    char buf[9];
    get_header_str(buf, mRestoreData.Elements(), mRestoreData.Length());
    PR_LOG(gCompressedImageAccountingLog, PR_LOG_WARNING,
           ("CompressedImageAccounting: imgContainer::ReloadImages() starting to restore images for container %p (%s) - "
            "header %p is 0x%s (length %d)",
            this,
            mDiscardableMimeType.get(),
            mRestoreData.Elements(),
            buf,
            mRestoreData.Length()));
  }

  PRUint32 written;
  result = decoder->WriteFrom(stream, mRestoreData.Length(), &written);
  NS_ENSURE_SUCCESS(result, result);

  result = decoder->Flush();
  NS_ENSURE_SUCCESS(result, result);

  result = decoder->Close();
  NS_ENSURE_SUCCESS(result, result);

  NS_ASSERTION(mFrames.Count() == mNumFrames,
               "imgContainer::ReloadImages(): the restored mFrames.Count() doesn't match mNumFrames!");

  return result;
}
示例#16
0
NS_IMETHODIMP AsyncWriteIconToDisk::Run()
{
  NS_PRECONDITION(!NS_IsMainThread(), "Should not be called on the main thread.");

  // Convert the obtained favicon data to an input stream
  nsCOMPtr<nsIInputStream> stream;
  nsresult rv = NS_NewByteInputStream(getter_AddRefs(stream),
                                      reinterpret_cast<const char*>(mBuffer.get()), 
                                      mBufferLength,
                                      NS_ASSIGNMENT_DEPEND);
  NS_ENSURE_SUCCESS(rv, rv);

  // Decode the image from the format it was returned to us in (probably PNG)
  nsCOMPtr<imgIContainer> container;
  nsCOMPtr<imgITools> imgtool = do_CreateInstance("@mozilla.org/image/tools;1");
  rv = imgtool->DecodeImageData(stream, mMimeTypeOfInputData, 
                                getter_AddRefs(container));
  NS_ENSURE_SUCCESS(rv, rv);

  // Get the recommended icon width and height, or if failure to obtain 
  // these settings, fall back to 16x16 ICOs.  These values can be different
  // if the user has a different DPI setting other than 100%.
  // Windows would scale the 16x16 icon themselves, but it's better
  // we let our ICO encoder do it.
  PRInt32 systemIconWidth = GetSystemMetrics(SM_CXSMICON);
  PRInt32 systemIconHeight = GetSystemMetrics(SM_CYSMICON);
  if (systemIconWidth == 0 || systemIconHeight == 0) {
    systemIconWidth = 16;
    systemIconHeight = 16;
  }
  // Scale the image to the needed size and in ICO format
  mMimeTypeOfInputData.AssignLiteral("image/vnd.microsoft.icon");
  nsCOMPtr<nsIInputStream> iconStream;
  rv = imgtool->EncodeScaledImage(container, mMimeTypeOfInputData,
                                  systemIconWidth,
                                  systemIconHeight,
                                  EmptyString(),
                                  getter_AddRefs(iconStream));
  NS_ENSURE_SUCCESS(rv, rv);

  nsCOMPtr<nsILocalFile> icoFile
    = do_CreateInstance("@mozilla.org/file/local;1");
  NS_ENSURE_TRUE(icoFile, NS_ERROR_FAILURE);
  rv = icoFile->InitWithPath(mIconPath);

  // Setup the output stream for the ICO file on disk
  nsCOMPtr<nsIOutputStream> outputStream;
  rv = NS_NewLocalFileOutputStream(getter_AddRefs(outputStream), icoFile);
  NS_ENSURE_SUCCESS(rv, rv);

  // Obtain the ICO buffer size from the re-encoded ICO stream
  PRUint32 bufSize;
  rv = iconStream->Available(&bufSize);
  NS_ENSURE_SUCCESS(rv, rv);

  // Setup a buffered output stream from the stream object
  // so that we can simply use WriteFrom with the stream object
  nsCOMPtr<nsIOutputStream> bufferedOutputStream;
  rv = NS_NewBufferedOutputStream(getter_AddRefs(bufferedOutputStream),
                                  outputStream, bufSize);
  NS_ENSURE_SUCCESS(rv, rv);

  // Write out the icon stream to disk and make sure we wrote everything
  PRUint32 wrote;
  rv = bufferedOutputStream->WriteFrom(iconStream, bufSize, &wrote);
  NS_ASSERTION(bufSize == wrote, "Icon wrote size should be equal to requested write size");

  // Cleanup
  bufferedOutputStream->Close();
  outputStream->Close();
  return rv;
}
示例#17
0
NS_IMETHODIMP AsyncWriteIconToDisk::Run()
{
  NS_PRECONDITION(!NS_IsMainThread(), "Should not be called on the main thread.");

  // Convert the obtained favicon data to an input stream
  nsCOMPtr<nsIInputStream> stream;
  nsresult rv = 
    NS_NewByteInputStream(getter_AddRefs(stream),
                          reinterpret_cast<const char*>(mBuffer.get()),
                          mBufferLength,
                          NS_ASSIGNMENT_DEPEND);
  NS_ENSURE_SUCCESS(rv, rv);

  // Decode the image from the format it was returned to us in (probably PNG)
  nsCOMPtr<imgIContainer> container;
  nsCOMPtr<imgITools> imgtool = do_CreateInstance("@mozilla.org/image/tools;1");
  rv = imgtool->DecodeImageData(stream, mMimeTypeOfInputData, 
                                getter_AddRefs(container));
  NS_ENSURE_SUCCESS(rv, rv);

  // Get the recommended icon width and height, or if failure to obtain 
  // these settings, fall back to 16x16 ICOs.  These values can be different
  // if the user has a different DPI setting other than 100%.
  // Windows would scale the 16x16 icon themselves, but it's better
  // we let our ICO encoder do it.
  nsCOMPtr<nsIInputStream> iconStream;
  if (!mURLShortcut) {
    int32_t systemIconWidth = GetSystemMetrics(SM_CXSMICON);
    int32_t systemIconHeight = GetSystemMetrics(SM_CYSMICON);
    if ((systemIconWidth == 0 || systemIconHeight == 0)) {
      systemIconWidth = 16;
      systemIconHeight = 16;
    }
    // Scale the image to the needed size and in ICO format
    mMimeTypeOfInputData.AssignLiteral("image/vnd.microsoft.icon");
    rv = imgtool->EncodeScaledImage(container, mMimeTypeOfInputData,
                                    systemIconWidth,
                                    systemIconHeight,
                                    EmptyString(),
                                    getter_AddRefs(iconStream));
    } else {
      nsRefPtr<gfxASurface> s;
      rv = container->GetFrame(imgIContainer::FRAME_FIRST, 0, getter_AddRefs(s));
      NS_ENSURE_SUCCESS(rv, rv);

      gfxImageSurface* surface =
        new gfxImageSurface(gfxIntSize(48, 48),
                            gfxImageSurface::ImageFormatARGB32);
      gfxContext context(surface);
      context.SetOperator(gfxContext::OPERATOR_SOURCE);
      context.SetColor(gfxRGBA(1, 1, 1, 1));
      context.Rectangle(gfxRect(0, 0, 48, 48));
      context.Fill();

      context.Translate(gfxPoint(16, 16));
      context.SetOperator(gfxContext::OPERATOR_OVER);
      context.DrawSurface(s,  gfxSize(16, 16));
      gfxIntSize size = surface->GetSize();

      nsRefPtr<imgIEncoder> encoder = 
        do_CreateInstance("@mozilla.org/image/encoder;2?"
                          "type=image/vnd.microsoft.icon");
      NS_ENSURE_TRUE(encoder, NS_ERROR_FAILURE);
      rv = encoder->InitFromData(surface->Data(), surface->Stride() * size.height,
                            size.width, size.height, surface->Stride(),
                            imgIEncoder::INPUT_FORMAT_HOSTARGB, EmptyString());
      NS_ENSURE_SUCCESS(rv, rv);
      CallQueryInterface(encoder.get(), getter_AddRefs(iconStream));
      if (!iconStream) {
        return NS_ERROR_FAILURE;
      }
  }

  NS_ENSURE_SUCCESS(rv, rv);
  nsCOMPtr<nsIFile> icoFile
    = do_CreateInstance("@mozilla.org/file/local;1");
  NS_ENSURE_TRUE(icoFile, NS_ERROR_FAILURE);
  rv = icoFile->InitWithPath(mIconPath);

  // Setup the output stream for the ICO file on disk
  nsCOMPtr<nsIOutputStream> outputStream;
  rv = NS_NewLocalFileOutputStream(getter_AddRefs(outputStream), icoFile);
  NS_ENSURE_SUCCESS(rv, rv);

  // Obtain the ICO buffer size from the re-encoded ICO stream
  uint64_t bufSize64;
  rv = iconStream->Available(&bufSize64);
  NS_ENSURE_SUCCESS(rv, rv);
  NS_ENSURE_TRUE(bufSize64 <= UINT32_MAX, NS_ERROR_FILE_TOO_BIG);

  uint32_t bufSize = (uint32_t)bufSize64;

  // Setup a buffered output stream from the stream object
  // so that we can simply use WriteFrom with the stream object
  nsCOMPtr<nsIOutputStream> bufferedOutputStream;
  rv = NS_NewBufferedOutputStream(getter_AddRefs(bufferedOutputStream),
                                  outputStream, bufSize);
  NS_ENSURE_SUCCESS(rv, rv);

  // Write out the icon stream to disk and make sure we wrote everything
  uint32_t wrote;
  rv = bufferedOutputStream->WriteFrom(iconStream, bufSize, &wrote);
  NS_ASSERTION(bufSize == wrote, 
              "Icon wrote size should be equal to requested write size");

  // Cleanup
  bufferedOutputStream->Close();
  outputStream->Close();
  if (mURLShortcut) {
    SendMessage(HWND_BROADCAST, WM_SETTINGCHANGE, SPI_SETNONCLIENTMETRICS, 0);
  }
  return rv;
}
示例#18
0
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;
}
nsresult
nsHttpTransaction::Init(PRUint8 caps,
                        nsHttpConnectionInfo *cinfo,
                        nsHttpRequestHead *requestHead,
                        nsIInputStream *requestBody,
                        PRBool requestBodyHasHeaders,
                        nsIEventTarget *target,
                        nsIInterfaceRequestor *callbacks,
                        nsITransportEventSink *eventsink,
                        nsIAsyncInputStream **responseBody)
{
    nsresult rv;

    LOG(("nsHttpTransaction::Init [this=%x caps=%x]\n", this, caps));

    NS_ASSERTION(cinfo, "ouch");
    NS_ASSERTION(requestHead, "ouch");
    NS_ASSERTION(target, "ouch");

    // create transport event sink proxy that coalesces all events
    rv = net_NewTransportEventSinkProxy(getter_AddRefs(mTransportSink),
                                        eventsink, target, PR_TRUE);
    if (NS_FAILED(rv)) return rv;

    // try to get the nsIHttpActivityObserver distributor
    mActivityDistributor = do_GetService(NS_HTTPACTIVITYDISTRIBUTOR_CONTRACTID, &rv);

    // mActivityDistributor may not be valid
    if (NS_SUCCEEDED(rv) && mActivityDistributor) {
        // the service is valid, now check if it is active
        PRBool active;
        rv = mActivityDistributor->GetIsActive(&active);
        if (NS_SUCCEEDED(rv) && active) {
            // the service is valid and active, gather nsISupports
            // for the channel that called Init()
            mChannel = do_QueryInterface(eventsink);
            LOG(("nsHttpTransaction::Init() " \
                 "mActivityDistributor is active " \
                 "this=%x", this));
        } else
            // the interface in valid but not active, so don't use it
            mActivityDistributor = nsnull;
    }

    NS_ADDREF(mConnInfo = cinfo);
    mCallbacks = callbacks;
    mConsumerTarget = target;
    mCaps = caps;

    if (requestHead->Method() == nsHttp::Head)
        mNoContent = PR_TRUE;

    // grab a weak reference to the request head
    mRequestHead = requestHead;

    // make sure we eliminate any proxy specific headers from 
    // the request if we are talking HTTPS via a SSL tunnel.
    PRBool pruneProxyHeaders = cinfo->UsingSSL() &&
                               cinfo->UsingHttpProxy();
    mReqHeaderBuf.Truncate();
    requestHead->Flatten(mReqHeaderBuf, pruneProxyHeaders);

#if defined(PR_LOGGING)
    if (LOG3_ENABLED()) {
        LOG3(("http request [\n"));
        LogHeaders(mReqHeaderBuf.get());
        LOG3(("]\n"));
    }
#endif

    // If the request body does not include headers or if there is no request
    // body, then we must add the header/body separator manually.
    if (!requestBodyHasHeaders || !requestBody)
        mReqHeaderBuf.AppendLiteral("\r\n");

    // report the request header
    if (mActivityDistributor)
        mActivityDistributor->ObserveActivity(
            mChannel,
            NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION,
            NS_HTTP_ACTIVITY_SUBTYPE_REQUEST_HEADER,
            LL_ZERO, LL_ZERO,
            mReqHeaderBuf);

    // Create a string stream for the request header buf (the stream holds
    // a non-owning reference to the request header data, so we MUST keep
    // mReqHeaderBuf around).
    nsCOMPtr<nsIInputStream> headers;
    rv = NS_NewByteInputStream(getter_AddRefs(headers),
                               mReqHeaderBuf.get(),
                               mReqHeaderBuf.Length());
    if (NS_FAILED(rv)) return rv;

    if (requestBody) {
        mHasRequestBody = PR_TRUE;

        // wrap the headers and request body in a multiplexed input stream.
        nsCOMPtr<nsIMultiplexInputStream> multi =
            do_CreateInstance(kMultiplexInputStream, &rv);
        if (NS_FAILED(rv)) return rv;

        rv = multi->AppendStream(headers);
        if (NS_FAILED(rv)) return rv;

        rv = multi->AppendStream(requestBody);
        if (NS_FAILED(rv)) return rv;

        // wrap the multiplexed input stream with a buffered input stream, so
        // that we write data in the largest chunks possible.  this is actually
        // necessary to workaround some common server bugs (see bug 137155).
        rv = NS_NewBufferedInputStream(getter_AddRefs(mRequestStream), multi,
                                       NET_DEFAULT_SEGMENT_SIZE);
        if (NS_FAILED(rv)) return rv;
    }
    else
        mRequestStream = headers;

    rv = mRequestStream->Available(&mRequestSize);
    if (NS_FAILED(rv)) return rv;

    // create pipe for response stream
    rv = NS_NewPipe2(getter_AddRefs(mPipeIn),
                     getter_AddRefs(mPipeOut),
                     PR_TRUE, PR_TRUE,
                     NS_HTTP_SEGMENT_SIZE,
                     NS_HTTP_SEGMENT_COUNT,
                     nsIOService::gBufferCache);
    if (NS_FAILED(rv)) return rv;

    NS_ADDREF(*responseBody = mPipeIn);
    return NS_OK;
}
NS_IMETHODIMP
nsClipboard::GetData(nsITransferable *aTransferable, PRInt32 aWhichClipboard)
{
    if (!aTransferable)
        return NS_ERROR_FAILURE;

    GtkClipboard *clipboard;
    clipboard = gtk_clipboard_get(GetSelectionAtom(aWhichClipboard));

    guchar        *data = NULL;
    gint           length = 0;
    PRBool         foundData = PR_FALSE;
    nsCAutoString  foundFlavor;

    // Get a list of flavors this transferable can import
    nsCOMPtr<nsISupportsArray> flavors;
    nsresult rv;
    rv = aTransferable->FlavorsTransferableCanImport(getter_AddRefs(flavors));
    if (!flavors || NS_FAILED(rv))
        return NS_ERROR_FAILURE;

    PRUint32 count;
    flavors->Count(&count);
    for (PRUint32 i=0; i < count; i++) {
        nsCOMPtr<nsISupports> genericFlavor;
        flavors->GetElementAt(i, getter_AddRefs(genericFlavor));

        nsCOMPtr<nsISupportsCString> currentFlavor;
        currentFlavor = do_QueryInterface(genericFlavor);

        if (currentFlavor) {
            nsXPIDLCString flavorStr;
            currentFlavor->ToString(getter_Copies(flavorStr));

            // Special case text/unicode since we can convert any
            // string into text/unicode
            if (!strcmp(flavorStr, kUnicodeMime)) {
                gchar* new_text = wait_for_text(clipboard);
                if (new_text) {
                    // Convert utf-8 into our unicode format.
                    NS_ConvertUTF8toUTF16 ucs2string(new_text);
                    data = (guchar *)ToNewUnicode(ucs2string);
                    length = ucs2string.Length() * 2;
                    g_free(new_text);
                    foundData = PR_TRUE;
                    foundFlavor = kUnicodeMime;
                    break;
                }
                // If the type was text/unicode and we couldn't get
                // text off the clipboard, run the next loop
                // iteration.
                continue;
            }

            // For images, we must wrap the data in an nsIInputStream then return instead of break,
            // because that code below won't help us.
            if (!strcmp(flavorStr, kJPEGImageMime) || !strcmp(flavorStr, kPNGImageMime) || !strcmp(flavorStr, kGIFImageMime)) {
                GdkAtom atom;
                if (!strcmp(flavorStr, kJPEGImageMime)) // This is image/jpg, but X only understands image/jpeg
                    atom = gdk_atom_intern("image/jpeg", FALSE);
                else
                    atom = gdk_atom_intern(flavorStr, FALSE);

                GtkSelectionData *selectionData = wait_for_contents(clipboard, atom);
                if (!selectionData)
                    continue;

                nsCOMPtr<nsIInputStream> byteStream;
                NS_NewByteInputStream(getter_AddRefs(byteStream), (const char*)selectionData->data,
                                      selectionData->length, NS_ASSIGNMENT_COPY);
                aTransferable->SetTransferData(flavorStr, byteStream, sizeof(nsIInputStream*));
                gtk_selection_data_free(selectionData);
                return NS_OK;
            }

            // Get the atom for this type and try to request it off
            // the clipboard.
            GdkAtom atom = gdk_atom_intern(flavorStr, FALSE);
            GtkSelectionData *selectionData;
            selectionData = wait_for_contents(clipboard, atom);
            if (selectionData) {
                length = selectionData->length;
                // Special case text/html since we can convert into UCS2
                if (!strcmp(flavorStr, kHTMLMime)) {
                    PRUnichar* htmlBody= nsnull;
                    PRInt32 htmlBodyLen = 0;
                    // Convert text/html into our unicode format
                    ConvertHTMLtoUCS2((guchar *)selectionData->data, length,
                                      &htmlBody, htmlBodyLen);
                    // Try next data format?
                    if (!htmlBodyLen)
                        continue;
                    data = (guchar *)htmlBody;
                    length = htmlBodyLen * 2;
                } else {
                    data = (guchar *)nsMemory::Alloc(length);
                    if (!data)
                        break;
                    memcpy(data, selectionData->data, length);
                }
                foundData = PR_TRUE;
                foundFlavor = flavorStr;
                break;
            }
        }
    }

    if (foundData) {
        nsCOMPtr<nsISupports> wrapper;
        nsPrimitiveHelpers::CreatePrimitiveForData(foundFlavor.get(),
                                                   data, length,
                                                   getter_AddRefs(wrapper));
        aTransferable->SetTransferData(foundFlavor.get(),
                                       wrapper, length);
    }

    if (data)
        nsMemory::Free(data);

    return NS_OK;
}
示例#21
0
nsresult
nsHttpTransaction::Init(PRUint8 caps,
                        nsHttpConnectionInfo *cinfo,
                        nsHttpRequestHead *requestHead,
                        nsIInputStream *requestBody,
                        PRBool requestBodyHasHeaders,
                        nsIEventTarget *target,
                        nsIInterfaceRequestor *callbacks,
                        nsITransportEventSink *eventsink,
                        nsIAsyncInputStream **responseBody)
{
    nsresult rv;

    LOG(("nsHttpTransaction::Init [this=%x caps=%x]\n", this, caps));

    NS_ASSERTION(cinfo, "ouch");
    NS_ASSERTION(requestHead, "ouch");
    NS_ASSERTION(target, "ouch");

    // create transport event sink proxy that coalesces all events
    rv = net_NewTransportEventSinkProxy(getter_AddRefs(mTransportSink),
                                        eventsink, target, PR_TRUE);
    if (NS_FAILED(rv)) return rv;

    mActivityDistributor = do_GetService(NS_HTTPACTIVITYDISTRIBUTOR_CONTRACTID, &rv);
    if (NS_FAILED(rv)) return rv;

    PRBool active;
    rv = mActivityDistributor->GetIsActive(&active);
    if (NS_SUCCEEDED(rv) && active) {
        // there are some observers registered at activity distributor, gather
        // nsISupports for the channel that called Init()
        mChannel = do_QueryInterface(eventsink);
        LOG(("nsHttpTransaction::Init() " \
             "mActivityDistributor is active " \
             "this=%x", this));
    } else
        // there is no observer, so don't use it
        mActivityDistributor = nsnull;

    NS_ADDREF(mConnInfo = cinfo);
    mCallbacks = callbacks;
    mConsumerTarget = target;
    mCaps = caps;

    if (requestHead->Method() == nsHttp::Head)
        mNoContent = PR_TRUE;

    // Make sure that there is "Content-Length: 0" header in the requestHead
    // in case of POST and PUT methods when there is no requestBody and
    // requestHead doesn't contain "Transfer-Encoding" header.
    //
    // RFC1945 section 7.2.2:
    //   HTTP/1.0 requests containing an entity body must include a valid
    //   Content-Length header field.
    //
    // RFC2616 section 4.4:
    //   For compatibility with HTTP/1.0 applications, HTTP/1.1 requests
    //   containing a message-body MUST include a valid Content-Length header
    //   field unless the server is known to be HTTP/1.1 compliant.
    if ((requestHead->Method() == nsHttp::Post || requestHead->Method() == nsHttp::Put) &&
        !requestBody && !requestHead->PeekHeader(nsHttp::Transfer_Encoding)) {
        requestHead->SetHeader(nsHttp::Content_Length, NS_LITERAL_CSTRING("0"));
    }

    // grab a weak reference to the request head
    mRequestHead = requestHead;

    // make sure we eliminate any proxy specific headers from 
    // the request if we are talking HTTPS via a SSL tunnel.
    PRBool pruneProxyHeaders = cinfo->UsingSSL() &&
                               cinfo->UsingHttpProxy();
    mReqHeaderBuf.Truncate();
    requestHead->Flatten(mReqHeaderBuf, pruneProxyHeaders);

#if defined(PR_LOGGING)
    if (LOG3_ENABLED()) {
        LOG3(("http request [\n"));
        LogHeaders(mReqHeaderBuf.get());
        LOG3(("]\n"));
    }
#endif

    // If the request body does not include headers or if there is no request
    // body, then we must add the header/body separator manually.
    if (!requestBodyHasHeaders || !requestBody)
        mReqHeaderBuf.AppendLiteral("\r\n");

    // report the request header
    if (mActivityDistributor)
        mActivityDistributor->ObserveActivity(
            mChannel,
            NS_HTTP_ACTIVITY_TYPE_HTTP_TRANSACTION,
            NS_HTTP_ACTIVITY_SUBTYPE_REQUEST_HEADER,
            PR_Now(), LL_ZERO,
            mReqHeaderBuf);

    // Create a string stream for the request header buf (the stream holds
    // a non-owning reference to the request header data, so we MUST keep
    // mReqHeaderBuf around).
    nsCOMPtr<nsIInputStream> headers;
    rv = NS_NewByteInputStream(getter_AddRefs(headers),
                               mReqHeaderBuf.get(),
                               mReqHeaderBuf.Length());
    if (NS_FAILED(rv)) return rv;

    if (requestBody) {
        mHasRequestBody = PR_TRUE;

        // wrap the headers and request body in a multiplexed input stream.
        nsCOMPtr<nsIMultiplexInputStream> multi =
            do_CreateInstance(kMultiplexInputStream, &rv);
        if (NS_FAILED(rv)) return rv;

        rv = multi->AppendStream(headers);
        if (NS_FAILED(rv)) return rv;

        rv = multi->AppendStream(requestBody);
        if (NS_FAILED(rv)) return rv;

        // wrap the multiplexed input stream with a buffered input stream, so
        // that we write data in the largest chunks possible.  this is actually
        // necessary to workaround some common server bugs (see bug 137155).
        rv = NS_NewBufferedInputStream(getter_AddRefs(mRequestStream), multi,
                                       nsIOService::gDefaultSegmentSize);
        if (NS_FAILED(rv)) return rv;
    }
    else
        mRequestStream = headers;

    rv = mRequestStream->Available(&mRequestSize);
    if (NS_FAILED(rv)) return rv;

    // create pipe for response stream
    rv = NS_NewPipe2(getter_AddRefs(mPipeIn),
                     getter_AddRefs(mPipeOut),
                     PR_TRUE, PR_TRUE,
                     nsIOService::gDefaultSegmentSize,
                     nsIOService::gDefaultSegmentCount,
                     nsIOService::gBufferCache);
    if (NS_FAILED(rv)) return rv;

    NS_ADDREF(*responseBody = mPipeIn);
    return NS_OK;
}
示例#22
0
void
HttpChannelChild::OnTransportAndData(const nsresult& status,
                                     const PRUint64 progress,
                                     const PRUint64& progressMax,
                                     const nsCString& data,
                                     const PRUint32& offset,
                                     const PRUint32& count)
{
  LOG(("HttpChannelChild::OnTransportAndData [this=%x]\n", this));

  if (mCanceled)
    return;

  // cache the progress sink so we don't have to query for it each time.
  if (!mProgressSink)
    GetCallback(mProgressSink);

  // Hold queue lock throughout all three calls, else we might process a later
  // necko msg in between them.
  AutoEventEnqueuer ensureSerialDispatch(mEventQ);

  // block status/progress after Cancel or OnStopRequest has been called,
  // or if channel has LOAD_BACKGROUND set.
  // - JDUELL: may not need mStatus/mIsPending checks, given this is always called
  //   during OnDataAvailable, and we've already checked mCanceled.  Code
  //   dupe'd from nsHttpChannel
  if (mProgressSink && NS_SUCCEEDED(mStatus) && mIsPending &&
      !(mLoadFlags & LOAD_BACKGROUND))
  {
    // OnStatus
    //
    NS_ASSERTION(status == nsISocketTransport::STATUS_RECEIVING_FROM ||
                 status == nsITransport::STATUS_READING,
                 "unexpected status code");

    nsCAutoString host;
    mURI->GetHost(host);
    mProgressSink->OnStatus(this, nsnull, status,
                            NS_ConvertUTF8toUTF16(host).get());
    // OnProgress
    //
    if (progress > 0) {
      NS_ASSERTION(progress <= progressMax, "unexpected progress values");
      mProgressSink->OnProgress(this, nsnull, progress, progressMax);
    }
  }

  // OnDataAvailable
  //
  // NOTE: the OnDataAvailable contract requires the client to read all the data
  // in the inputstream.  This code relies on that ('data' will go away after
  // this function).  Apparently the previous, non-e10s behavior was to actually
  // support only reading part of the data, allowing later calls to read the
  // rest.
  nsCOMPtr<nsIInputStream> stringStream;
  nsresult rv = NS_NewByteInputStream(getter_AddRefs(stringStream), data.get(),
                                      count, NS_ASSIGNMENT_DEPEND);
  if (NS_FAILED(rv)) {
    Cancel(rv);
    return;
  }

  rv = mListener->OnDataAvailable(this, mListenerContext,
                                  stringStream, offset, count);
  stringStream->Close();
  if (NS_FAILED(rv)) {
    Cancel(rv);
  }
}