already_AddRefed<InternalResponse>
InternalResponse::Clone()
{
    nsRefPtr<InternalResponse> clone = CreateIncompleteCopy();

    clone->mHeaders = new InternalHeaders(*mHeaders);
    if (mWrappedResponse) {
        clone->mWrappedResponse = mWrappedResponse->Clone();
        MOZ_ASSERT(!mBody);
        return clone.forget();
    }

    if (!mBody) {
        return clone.forget();
    }

    nsCOMPtr<nsIInputStream> clonedBody;
    nsCOMPtr<nsIInputStream> replacementBody;

    nsresult rv = NS_CloneInputStream(mBody, getter_AddRefs(clonedBody),
                                      getter_AddRefs(replacementBody));
    if (NS_WARN_IF(NS_FAILED(rv))) {
        return nullptr;
    }

    clone->mBody.swap(clonedBody);
    if (replacementBody) {
        mBody.swap(replacementBody);
    }

    return clone.forget();
}
TEST(CloneInputStream, NonCloneableInput_NoFallback)
{
  nsTArray<char> inputData;
  testing::CreateData(4 * 1024, inputData);
  nsDependentCSubstring inputString(inputData.Elements(), inputData.Length());

  nsCOMPtr<nsIInputStream> base;
  nsresult rv = NS_NewCStringInputStream(getter_AddRefs(base), inputString);
  ASSERT_TRUE(NS_SUCCEEDED(rv));

  // Take advantage of nsBufferedInputStream being non-cloneable right
  // now.  If this changes in the future, then we need a different stream
  // type in this test.
  nsCOMPtr<nsIInputStream> stream;
  rv = NS_NewBufferedInputStream(getter_AddRefs(stream), base, 4096);
  ASSERT_TRUE(NS_SUCCEEDED(rv));

  nsCOMPtr<nsICloneableInputStream> cloneable = do_QueryInterface(stream);
  ASSERT_TRUE(cloneable == nullptr);

  nsCOMPtr<nsIInputStream> clone;
  rv = NS_CloneInputStream(stream, getter_AddRefs(clone));
  ASSERT_TRUE(NS_FAILED(rv));
  ASSERT_TRUE(clone == nullptr);

  testing::ConsumeAndValidateStream(stream, inputString);
}
TEST(CloneInputStream, InvalidInput)
{
  nsCOMPtr<nsIInputStream> clone;
  nsresult rv = NS_CloneInputStream(nullptr, getter_AddRefs(clone));
  ASSERT_TRUE(NS_FAILED(rv));
  ASSERT_FALSE(clone);
}
示例#4
0
TEST(CloneInputStream, CloneMultiplexStreamPartial)
{
  nsCOMPtr<nsIMultiplexInputStream> stream =
    do_CreateInstance("@mozilla.org/io/multiplex-input-stream;1");
  ASSERT_TRUE(stream);

  nsTArray<char> inputData;
  testing::CreateData(1024, inputData);
  for (uint32_t i = 0; i < 2; ++i) {
    nsCString inputString(inputData.Elements(), inputData.Length());

    nsCOMPtr<nsIInputStream> base;
    nsresult rv = NS_NewCStringInputStream(getter_AddRefs(base), inputString);
    ASSERT_TRUE(NS_SUCCEEDED(rv));

    rv = stream->AppendStream(base);
    ASSERT_TRUE(NS_SUCCEEDED(rv));
  }

  // Fail when first stream read, but second hasn't been started.
  nsAutoPtr<char> buffer(new char[1024]);
  uint32_t read;
  nsresult rv = stream->Read(buffer, 1024, &read);
  ASSERT_TRUE(NS_SUCCEEDED(rv));

  nsCOMPtr<nsIInputStream> clone;
  rv = NS_CloneInputStream(stream, getter_AddRefs(clone));
  ASSERT_TRUE(NS_FAILED(rv));

  // Fail after beginning read of second stream.
  rv = stream->Read(buffer, 512, &read);
  ASSERT_TRUE(NS_SUCCEEDED(rv) && read == 512);

  rv = NS_CloneInputStream(stream, getter_AddRefs(clone));
  ASSERT_TRUE(NS_FAILED(rv));

  // Fail at the end.
  nsAutoCString consumed;
  rv = NS_ConsumeStream(stream, UINT32_MAX, consumed);
  ASSERT_TRUE(NS_SUCCEEDED(rv));

  rv = NS_CloneInputStream(stream, getter_AddRefs(clone));
  ASSERT_TRUE(NS_FAILED(rv));
}
示例#5
0
TEST(CloneInputStream, CloneMultiplexStream)
{
  nsCOMPtr<nsIMultiplexInputStream> stream =
    do_CreateInstance("@mozilla.org/io/multiplex-input-stream;1");
  ASSERT_TRUE(stream);

  nsTArray<char> inputData;
  testing::CreateData(1024, inputData);
  for (uint32_t i = 0; i < 2; ++i) {
    nsCString inputString(inputData.Elements(), inputData.Length());

    nsCOMPtr<nsIInputStream> base;
    nsresult rv = NS_NewCStringInputStream(getter_AddRefs(base), inputString);
    ASSERT_TRUE(NS_SUCCEEDED(rv));

    rv = stream->AppendStream(base);
    ASSERT_TRUE(NS_SUCCEEDED(rv));
  }

  // Unread stream should clone successfully.
  nsTArray<char> doubled;
  doubled.AppendElements(inputData);
  doubled.AppendElements(inputData);

  nsCOMPtr<nsIInputStream> clone;
  nsresult rv = NS_CloneInputStream(stream, getter_AddRefs(clone));
  ASSERT_TRUE(NS_SUCCEEDED(rv));
  testing::ConsumeAndValidateStream(clone, doubled);

  // Stream that has been read should fail.
  nsAutoPtr<char> buffer(new char[512]);
  uint32_t read;
  rv = stream->Read(buffer, 512, &read);
  ASSERT_TRUE(NS_SUCCEEDED(rv));

  nsCOMPtr<nsIInputStream> clone2;
  rv = NS_CloneInputStream(stream, getter_AddRefs(clone2));
  ASSERT_TRUE(NS_FAILED(rv));
}
示例#6
0
TEST(CloneInputStream, CloneableInput)
{
  nsTArray<char> inputData;
  testing::CreateData(4 * 1024, inputData);
  nsDependentCSubstring inputString(inputData.Elements(), inputData.Length());

  nsCOMPtr<nsIInputStream> stream;
  nsresult rv = NS_NewCStringInputStream(getter_AddRefs(stream), inputString);
  ASSERT_TRUE(NS_SUCCEEDED(rv));

  nsCOMPtr<nsIInputStream> clone;
  rv = NS_CloneInputStream(stream, getter_AddRefs(clone));
  ASSERT_TRUE(NS_SUCCEEDED(rv));

  testing::ConsumeAndValidateStream(stream, inputString);
  testing::ConsumeAndValidateStream(clone, inputString);
}
示例#7
0
TEST(CloneInputStream, NonCloneableInput_Fallback)
{
  nsTArray<char> inputData;
  testing::CreateData(4 * 1024, inputData);
  nsDependentCSubstring inputString(inputData.Elements(), inputData.Length());

  nsCOMPtr<nsIInputStream> base;
  nsresult rv = NS_NewCStringInputStream(getter_AddRefs(base), inputString);
  ASSERT_TRUE(NS_SUCCEEDED(rv));

  // Take advantage of nsBufferedInputStream being non-cloneable right
  // now.  If this changes in the future, then we need a different stream
  // type in this test.
  nsCOMPtr<nsIInputStream> stream;
  rv = NS_NewBufferedInputStream(getter_AddRefs(stream), base, 4096);
  ASSERT_TRUE(NS_SUCCEEDED(rv));

  nsCOMPtr<nsICloneableInputStream> cloneable = do_QueryInterface(stream);
  ASSERT_TRUE(cloneable == nullptr);

  nsCOMPtr<nsIInputStream> clone;
  nsCOMPtr<nsIInputStream> replacement;
  rv = NS_CloneInputStream(stream, getter_AddRefs(clone),
                           getter_AddRefs(replacement));
  ASSERT_TRUE(NS_SUCCEEDED(rv));
  ASSERT_TRUE(clone != nullptr);
  ASSERT_TRUE(replacement != nullptr);
  ASSERT_TRUE(stream.get() != replacement.get());
  ASSERT_TRUE(clone.get() != replacement.get());

  stream = replacement.forget();

  // The stream is being copied asynchronously on the STS event target.  Spin
  // a yield loop here until the data is available.  Yes, this is a bit hacky,
  // but AFAICT, gtest does not support async test completion.
  uint64_t available;
  do {
    mozilla::unused << PR_Sleep(PR_INTERVAL_NO_WAIT);
    rv = stream->Available(&available);
    ASSERT_TRUE(NS_SUCCEEDED(rv));
  } while(available < inputString.Length());

  testing::ConsumeAndValidateStream(stream, inputString);
  testing::ConsumeAndValidateStream(clone, inputString);
}
示例#8
0
void
BlobImplStream::GetInternalStream(nsIInputStream** aStream, ErrorResult& aRv)
{
  nsCOMPtr<nsIInputStream> clonedStream;
  nsCOMPtr<nsIInputStream> replacementStream;

  aRv = NS_CloneInputStream(mInputStream, getter_AddRefs(clonedStream),
                            getter_AddRefs(replacementStream));
  if (NS_WARN_IF(aRv.Failed())) {
    return;
  }

  if (replacementStream) {
    mInputStream = replacementStream.forget();
  }

  clonedStream.forget(aStream);
}
already_AddRefed<InternalRequest>
InternalRequest::Clone()
{
  RefPtr<InternalRequest> clone = new InternalRequest(*this);

  if (!mBodyStream) {
    return clone.forget();
  }

  nsCOMPtr<nsIInputStream> clonedBody;
  nsCOMPtr<nsIInputStream> replacementBody;

  nsresult rv = NS_CloneInputStream(mBodyStream, getter_AddRefs(clonedBody),
                                    getter_AddRefs(replacementBody));
  if (NS_WARN_IF(NS_FAILED(rv))) { return nullptr; }

  clone->mBodyStream.swap(clonedBody);
  if (replacementBody) {
    mBodyStream.swap(replacementBody);
  }
  return clone.forget();
}