Exemple #1
0
Request* Request::clone(ExceptionState& exceptionState) const
{
    if (bodyUsed()) {
        exceptionState.throwTypeError("Request body is already used");
        return nullptr;
    }

    FetchRequestData* request = m_request->clone();
    if (blobDataHandle() && isBodyConsumed()) {
        // Currently the only methods that can consume body data without
        // setting 'body passed' flag consume entire body (e.g. text()). Thus
        // we can set an empty blob to the new request instead of creating a
        // draining stream.
        // TODO(yhirano): Fix this once Request.body is introduced.
        OwnPtr<BlobData> blobData = BlobData::create();
        blobData->setContentType(blobDataHandle()->type());
        request->setBlobDataHandle(BlobDataHandle::create(blobData.release(), 0));
    }

    Headers* headers = Headers::create(request->headerList());
    headers->setGuard(m_headers->guard());
    Request* r = new Request(executionContext(), request, headers);
    r->suspendIfNeeded();
    return r;
}
Exemple #2
0
void Body::didFinishLoading()
{
    if (!m_resolver->executionContext() || m_resolver->executionContext()->activeDOMObjectsAreStopped())
        return;

    switch (m_responseType) {
    case ResponseAsArrayBuffer:
        m_resolver->resolve(DOMArrayBuffer::create(m_loader->arrayBufferResult()));
        break;
    case ResponseAsBlob: {
        ASSERT(blobDataHandle()->size() == kuint64max);
        OwnPtr<BlobData> blobData = BlobData::create();
        RefPtr<ArrayBuffer> buffer = m_loader->arrayBufferResult();
        blobData->appendArrayBuffer(buffer.get());
        const size_t length = blobData->length();
        m_resolver->resolve(Blob::create(BlobDataHandle::create(blobData.release(), length)));
        break;
    }
    case ResponseAsFormData:
        ASSERT_NOT_REACHED();
        break;
    case ResponseAsJSON:
        resolveJSON();
        break;
    case ResponseAsText:
        m_resolver->resolve(m_loader->stringResult());
        break;
    default:
        ASSERT_NOT_REACHED();
    }
    m_resolver.clear();
}
Exemple #3
0
void Body::pullSource()
{
    if (!m_streamAccessed) {
        // We do not download data unless the user explicitly uses the
        // ReadableStream object in order to avoid performance regression,
        // because currently Chrome cannot handle Streams efficiently
        // especially with ServiceWorker or Blob.
        return;
    }
    if (m_bodyUsed) {
        m_stream->error(DOMException::create(InvalidStateError, "The stream is locked."));
        return;
    }
    ASSERT(!m_loader);
    if (buffer()) {
        // If the body has a body buffer, we read all data from the buffer and
        // create a blob and then put the data from the blob to |m_stream|.
        // FIXME: Put the data directry from the buffer.
        buffer()->readAllAndCreateBlobHandle(contentTypeForBuffer(), new BlobHandleReceiver(this));
        return;
    }
    RefPtr<BlobDataHandle> blobHandle = blobDataHandle();
    if (!blobHandle.get()) {
        blobHandle = BlobDataHandle::create(BlobData::create(), 0);
    }
    readAsyncFromBlob(blobHandle);
}
Exemple #4
0
ScriptPromise Body::readAsync(ScriptState* scriptState, ResponseType type)
{
    if (m_bodyUsed)
        return ScriptPromise::reject(scriptState, V8ThrowException::createTypeError(scriptState->isolate(), "Already read"));

    // When the main thread sends a V8::TerminateExecution() signal to a worker
    // thread, any V8 API on the worker thread starts returning an empty
    // handle. This can happen in Body::readAsync. To avoid the situation, we
    // first check the ExecutionContext and return immediately if it's already
    // gone (which means that the V8::TerminateExecution() signal has been sent
    // to this worker thread).
    ExecutionContext* executionContext = scriptState->executionContext();
    if (!executionContext)
        return ScriptPromise();

    m_bodyUsed = true;
    m_responseType = type;

    ASSERT(!m_resolver);
    m_resolver = ScriptPromiseResolver::create(scriptState);
    ScriptPromise promise = m_resolver->promise();

    if (m_streamAccessed) {
        // 'body' attribute was accessed and the stream source started pulling.
        switch (m_stream->state()) {
        case ReadableStream::Readable:
            readAllFromStream(scriptState);
            return promise;
        case ReadableStream::Waiting:
            // m_loader is working and m_resolver will be resolved when it
            // ends.
            return promise;
        case ReadableStream::Closed:
        case ReadableStream::Errored:
            m_resolver->resolve(m_stream->closed(scriptState).v8Value());
            return promise;
            break;
        }
        ASSERT_NOT_REACHED();
        return promise;
    }

    if (buffer()) {
        buffer()->readAllAndCreateBlobHandle(contentTypeForBuffer(), new BlobHandleReceiver(this));
        return promise;
    }
    readAsyncFromBlob(blobDataHandle());
    return promise;
}
void FetchResponseData::populateWebServiceWorkerResponse(WebServiceWorkerResponse& response)
{
    if (m_internalResponse) {
        m_internalResponse->populateWebServiceWorkerResponse(response);
        response.setResponseType(fetchTypeToWebType(m_type));
        return;
    }

    response.setURL(url());
    response.setStatus(status());
    response.setStatusText(statusMessage());
    response.setResponseType(fetchTypeToWebType(m_type));
    for (size_t i = 0; i < headerList()->size(); ++i) {
        const FetchHeaderList::Header* header = headerList()->list()[i].get();
        response.appendHeader(header->first, header->second);
    }
    response.setBlobDataHandle(blobDataHandle());
}
Exemple #6
0
ScriptPromise Body::readAsync(ScriptState* scriptState, ResponseType type)
{
    if (m_bodyUsed)
        return ScriptPromise::reject(scriptState, V8ThrowException::createTypeError(scriptState->isolate(), "Already read"));

    // When the main thread sends a V8::TerminateExecution() signal to a worker
    // thread, any V8 API on the worker thread starts returning an empty
    // handle. This can happen in Body::readAsync. To avoid the situation, we
    // first check the ExecutionContext and return immediately if it's already
    // gone (which means that the V8::TerminateExecution() signal has been sent
    // to this worker thread).
    ExecutionContext* executionContext = scriptState->executionContext();
    if (!executionContext)
        return ScriptPromise();

    m_bodyUsed = true;
    m_responseType = type;

    ASSERT(!m_resolver);
    m_resolver = ScriptPromiseResolver::create(scriptState);
    ScriptPromise promise = m_resolver->promise();

    FileReaderLoader::ReadType readType = FileReaderLoader::ReadAsText;
    RefPtr<BlobDataHandle> blobHandle = blobDataHandle();
    if (!blobHandle.get()) {
        blobHandle = BlobDataHandle::create(BlobData::create(), 0);
    }
    switch (type) {
    case ResponseAsArrayBuffer:
        readType = FileReaderLoader::ReadAsArrayBuffer;
        break;
    case ResponseAsBlob:
        if (blobHandle->size() != kuint64max) {
            // If the size of |blobHandle| is set correctly, creates Blob from
            // it.
            m_resolver->resolve(Blob::create(blobHandle));
            m_resolver.clear();
            return promise;
        }
        // If the size is not set, read as ArrayBuffer and create a new blob to
        // get the size.
        // FIXME: This workaround is not good for performance.
        // When we will stop using Blob as a base system of Body to support
        // stream, this problem should be solved.
        readType = FileReaderLoader::ReadAsArrayBuffer;
        break;
    case ResponseAsFormData:
        // FIXME: Implement this.
        ASSERT_NOT_REACHED();
        break;
    case ResponseAsJSON:
    case ResponseAsText:
        break;
    default:
        ASSERT_NOT_REACHED();
    }

    m_loader = adoptPtr(new FileReaderLoader(readType, this));
    m_loader->start(executionContext, blobHandle);

    return promise;
}