Exemplo n.º 1
0
void
FetchStreamReader::ResolvedCallback(JSContext* aCx,
                                    JS::Handle<JS::Value> aValue)
{
  if (mStreamClosed) {
    return;
  }

  // This promise should be resolved with { done: boolean, value: something },
  // "value" is interesting only if done is false.

  // We don't want to play with JS api, let's WebIDL bindings doing it for us.
  // FetchReadableStreamReadDataDone is a dictionary with just a boolean, if the
  // parsing succeeded, we can proceed with the parsing of the "value", which it
  // must be a Uint8Array.
  FetchReadableStreamReadDataDone valueDone;
  if (!valueDone.Init(aCx, aValue)) {
    JS_ClearPendingException(aCx);
    CloseAndRelease(aCx, NS_ERROR_DOM_INVALID_STATE_ERR);
    return;
  }

  if (valueDone.mDone) {
    // Stream is completed.
    CloseAndRelease(aCx, NS_BASE_STREAM_CLOSED);
    return;
  }

  UniquePtr<FetchReadableStreamReadDataArray> value(
    new FetchReadableStreamReadDataArray);
  if (!value->Init(aCx, aValue) || !value->mValue.WasPassed()) {
    JS_ClearPendingException(aCx);
    CloseAndRelease(aCx, NS_ERROR_DOM_INVALID_STATE_ERR);
    return;
  }

  Uint8Array& array = value->mValue.Value();
  array.ComputeLengthAndData();
  uint32_t len = array.Length();

  if (len == 0) {
    // If there is nothing to read, let's do another reading.
    OnOutputStreamReady(mPipeOut);
    return;
  }

  MOZ_DIAGNOSTIC_ASSERT(!mBuffer);
  mBuffer = Move(value);

  mBufferOffset = 0;
  mBufferRemaining = len;

  nsresult rv = WriteBuffer();
  if (NS_FAILED(rv)) {
    // DOMException only understands errors from domerr.msg, so we normalize to
    // identifying an abort if the write fails.
    CloseAndRelease(aCx, NS_ERROR_DOM_ABORT_ERR);
  }
}
Exemplo n.º 2
0
void
HttpServer::Connection::QueueResponse(InternalResponse* aResponse)
{
  bool chunked = false;

  RefPtr<InternalHeaders> headers = new InternalHeaders(*aResponse->Headers());
  {
    ErrorResult res;
    headers->SetGuard(HeadersGuardEnum::None, res);
  }
  nsCOMPtr<nsIInputStream> body;
  int64_t bodySize;
  aResponse->GetBody(getter_AddRefs(body), &bodySize);

  if (body && bodySize >= 0) {
    nsCString sizeStr;
    sizeStr.AppendInt(bodySize);

    LOG_V("HttpServer::Connection::QueueResponse(%p) - "
          "Setting content-length to %s",
          this, sizeStr.get());

    ErrorResult res;
    headers->Set(NS_LITERAL_CSTRING("content-length"), sizeStr, res);
  } else if (body) {
    // Use chunked transfer encoding
    LOG_V("HttpServer::Connection::QueueResponse(%p) - Chunked transfer-encoding",
          this);

    ErrorResult res;
    headers->Set(NS_LITERAL_CSTRING("transfer-encoding"),
                 NS_LITERAL_CSTRING("chunked"),
                 res);
    headers->Delete(NS_LITERAL_CSTRING("content-length"), res);
    chunked = true;

  } else {
    LOG_V("HttpServer::Connection::QueueResponse(%p) - "
          "No body - setting content-length to 0", this);

    ErrorResult res;
    headers->Set(NS_LITERAL_CSTRING("content-length"),
                 NS_LITERAL_CSTRING("0"), res);
  }

  nsCString head(NS_LITERAL_CSTRING("HTTP/1.1 "));
  head.AppendInt(aResponse->GetStatus());
  // XXX is the statustext security checked?
  head.Append(NS_LITERAL_CSTRING(" ") +
              aResponse->GetStatusText() +
              NS_LITERAL_CSTRING("\r\n"));

  AutoTArray<InternalHeaders::Entry, 16> entries;
  headers->GetEntries(entries);

  for (auto header : entries) {
    head.Append(header.mName +
                NS_LITERAL_CSTRING(": ") +
                header.mValue +
                NS_LITERAL_CSTRING("\r\n"));
  }

  head.Append(NS_LITERAL_CSTRING("\r\n"));

  mOutputBuffers.AppendElement()->mString = head;
  if (body) {
    OutputBuffer* bodyBuffer = mOutputBuffers.AppendElement();
    bodyBuffer->mStream = body;
    bodyBuffer->mChunked = chunked;
  }

  OnOutputStreamReady(mOutput);
}