blob: cf949e906127e3072d5715491d035671b8aa21ce [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_FETCH_BODY_STREAM_BUFFER_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_FETCH_BODY_STREAM_BUFFER_H_
#include <memory>
#include "base/types/pass_key.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "services/network/public/mojom/chunked_data_pipe_getter.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/dom/abort_signal.h"
#include "third_party/blink/renderer/core/dom/dom_exception.h"
#include "third_party/blink/renderer/core/fetch/fetch_data_loader.h"
#include "third_party/blink/renderer/core/streams/underlying_source_base.h"
#include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h"
#include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/loader/fetch/bytes_consumer.h"
namespace blink {
class BytesUploader;
class EncodedFormData;
class ExceptionState;
class ReadableStream;
class ScriptState;
class ScriptCachedMetadataHandler;
class CORE_EXPORT BodyStreamBuffer final : public UnderlyingSourceBase,
public BytesConsumer::Client {
public:
using PassKey = base::PassKey<BodyStreamBuffer>;
// Create a BodyStreamBuffer for |consumer|.
// |consumer| must not have a client.
// This function must be called after entering an appropriate V8 context.
// |signal| should be non-null when this BodyStreamBuffer is associated with a
// Response that was created by fetch().
static BodyStreamBuffer* Create(
ScriptState*,
BytesConsumer* consumer,
AbortSignal* signal,
ScriptCachedMetadataHandler* cached_metadata_handler,
scoped_refptr<BlobDataHandle> side_data_blob = nullptr);
// Create() should be used instead of calling this constructor directly.
BodyStreamBuffer(PassKey,
ScriptState*,
BytesConsumer* consumer,
AbortSignal* signal,
ScriptCachedMetadataHandler* cached_metadata_handler,
scoped_refptr<BlobDataHandle> side_data_blob);
BodyStreamBuffer(ScriptState*,
ReadableStream* stream,
ScriptCachedMetadataHandler* cached_metadata_handler,
scoped_refptr<BlobDataHandle> side_data_blob = nullptr);
ReadableStream* Stream() { return stream_; }
// Callable only when neither locked nor disturbed.
scoped_refptr<BlobDataHandle> DrainAsBlobDataHandle(
BytesConsumer::BlobSizePolicy);
scoped_refptr<EncodedFormData> DrainAsFormData();
void DrainAsChunkedDataPipeGetter(
ScriptState*,
mojo::PendingReceiver<network::mojom::blink::ChunkedDataPipeGetter>);
void StartLoading(FetchDataLoader*,
FetchDataLoader::Client* /* client */,
ExceptionState&);
void Tee(BodyStreamBuffer**, BodyStreamBuffer**, ExceptionState&);
// UnderlyingSourceBase
ScriptPromise pull(ScriptState*) override;
ScriptPromise Cancel(ScriptState*, ScriptValue reason) override;
bool HasPendingActivity() const override;
void ContextDestroyed() override;
// BytesConsumer::Client
void OnStateChange() override;
String DebugName() const override { return "BodyStreamBuffer"; }
bool IsStreamReadable() const;
bool IsStreamClosed() const;
bool IsStreamErrored() const;
bool IsStreamLocked() const;
bool IsStreamDisturbed() const;
// Closes the stream if necessary, and then locks and disturbs it. Should not
// be called if |stream_broken_| is true.
void CloseAndLockAndDisturb();
ScriptState* GetScriptState() { return script_state_; }
bool IsAborted();
// Returns the ScriptCachedMetadataHandler associated with the contents of
// this stream. This can return nullptr. Streams' ownership model applies, so
// this function is expected to be called by the owner of this stream.
ScriptCachedMetadataHandler* GetCachedMetadataHandler() {
DCHECK(!IsStreamLocked());
DCHECK(!IsStreamDisturbed());
return cached_metadata_handler_;
}
// Take the blob representing any side data associated with this body
// stream. This must be called before the body is drained or begins
// loading.
scoped_refptr<BlobDataHandle> TakeSideDataBlob();
scoped_refptr<BlobDataHandle> GetSideDataBlobForTest() const {
return side_data_blob_;
}
bool IsMadeFromReadableStream() const { return made_from_readable_stream_; }
void Trace(Visitor*) const override;
private:
class LoaderClient;
// This method exists to avoid re-entrancy inside the BodyStreamBuffer
// constructor. It is called by Create(). It should not be called after
// using the ReadableStream* constructor.
void Init();
BytesConsumer* ReleaseHandle(ExceptionState&);
void Abort();
void Close();
void GetError();
void CancelConsumer();
void ProcessData();
void EndLoading();
void StopLoading();
Member<ScriptState> script_state_;
Member<ReadableStream> stream_;
Member<BytesUploader> stream_uploader_;
Member<BytesConsumer> consumer_;
// We need this member to keep it alive while loading.
Member<FetchDataLoader> loader_;
// We need this to ensure that we detect that abort has been signalled
// correctly.
Member<AbortSignal> signal_;
// CachedMetadata handler used for loading compiled WASM code.
Member<ScriptCachedMetadataHandler> cached_metadata_handler_;
// Additional side data associated with this body stream. It should only be
// retained until the body is drained or starts loading. Client code, such
// as service workers, can call TakeSideDataBlob() prior to consumption.
scoped_refptr<BlobDataHandle> side_data_blob_;
bool stream_needs_more_ = false;
bool made_from_readable_stream_;
bool in_process_data_ = false;
// TODO(ricea): Remove remaining uses of |stream_broken_|.
bool stream_broken_ = false;
DISALLOW_COPY_AND_ASSIGN(BodyStreamBuffer);
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_FETCH_BODY_STREAM_BUFFER_H_