| Index: Source/modules/fetch/BodyStreamBuffer.h | 
| diff --git a/Source/modules/fetch/BodyStreamBuffer.h b/Source/modules/fetch/BodyStreamBuffer.h | 
| index 9a23a9ddf5eaef8267f5c36e93c84391e6b2a41f..d3790d3eedc4be102acd7a64c2a566b0db28e2af 100644 | 
| --- a/Source/modules/fetch/BodyStreamBuffer.h | 
| +++ b/Source/modules/fetch/BodyStreamBuffer.h | 
| @@ -6,89 +6,90 @@ | 
| #define BodyStreamBuffer_h | 
|  | 
| #include "core/dom/DOMException.h" | 
| +#include "core/streams/ReadableByteStream.h" | 
| +#include "core/streams/ReadableByteStreamReader.h" | 
| +#include "core/streams/UnderlyingSource.h" | 
| #include "modules/ModulesExport.h" | 
| -#include "modules/fetch/DataConsumerHandleUtil.h" | 
| #include "modules/fetch/FetchDataConsumerHandle.h" | 
| #include "modules/fetch/FetchDataLoader.h" | 
| -#include "platform/blob/BlobData.h" | 
| -#include "platform/heap/Heap.h" | 
| +#include "platform/heap/Handle.h" | 
| #include "public/platform/WebDataConsumerHandle.h" | 
| -#include "wtf/Deque.h" | 
| -#include "wtf/RefPtr.h" | 
| -#include "wtf/text/WTFString.h" | 
| +#include "wtf/OwnPtr.h" | 
| +#include "wtf/PassOwnPtr.h" | 
|  | 
| namespace blink { | 
|  | 
| -class DrainingBodyStreamBuffer; | 
| +class ExecutionContext; | 
|  | 
| -class MODULES_EXPORT BodyStreamBuffer final : public GarbageCollectedFinalized<BodyStreamBuffer> { | 
| +// A BodyStreamBuffer constructed with a null handle is said to have null body. | 
| +// One can observe if a buffer has null body by calling |hasBody| function. | 
| +// |stream| function returns a non-null stream even when the buffer has null | 
| +// body. | 
| +class MODULES_EXPORT BodyStreamBuffer final : public GarbageCollectedFinalized<BodyStreamBuffer>, public UnderlyingSource, public WebDataConsumerHandle::Client { | 
| +    WTF_MAKE_NONCOPYABLE(BodyStreamBuffer); | 
| +    USING_GARBAGE_COLLECTED_MIXIN(BodyStreamBuffer); | 
| public: | 
| -    static BodyStreamBuffer* create(PassOwnPtr<FetchDataConsumerHandle> handle) { return new BodyStreamBuffer(handle); } | 
| -    static BodyStreamBuffer* createEmpty(); | 
| +    BodyStreamBuffer() : BodyStreamBuffer(nullptr) {} | 
| +    // |handle| can be null, but cannot be locked. | 
| +    explicit BodyStreamBuffer(PassOwnPtr<FetchDataConsumerHandle> /* handle */); | 
|  | 
| -    FetchDataConsumerHandle* handle() const; | 
| -    PassOwnPtr<FetchDataConsumerHandle> releaseHandle(); | 
| +    ReadableByteStream* stream() { return m_stream; } | 
|  | 
| -    class MODULES_EXPORT DrainingStreamNotificationClient : public GarbageCollectedMixin { | 
| -    public: | 
| -        virtual ~DrainingStreamNotificationClient() { } | 
| -        // Called after FetchDataLoader::Client methods. | 
| -        virtual void didFetchDataLoadFinishedFromDrainingStream() = 0; | 
| -    }; | 
| - | 
| -    DEFINE_INLINE_TRACE() | 
| -    { | 
| -        visitor->trace(m_fetchDataLoader); | 
| -        visitor->trace(m_drainingStreamNotificationClient); | 
| -    } | 
| +    // Callable only when not locked. | 
| +    PassRefPtr<BlobDataHandle> drainAsBlobDataHandle(FetchDataConsumerHandle::Reader::BlobSizePolicy); | 
|  | 
| -    void didFetchDataLoadFinished(); | 
| +    // Callable only when not locked. Returns a non-null handle even when | 
| +    // having null body. | 
| +    // Note: There is a case that calling |lock| doesn't make the buffer | 
| +    // locked. |unlock| should be called even in such cases when a user finishes | 
| +    // to use the returned handle, in order to maintain hasPendingActivity(). | 
| +    PassOwnPtr<FetchDataConsumerHandle> lock(ExecutionContext*); | 
|  | 
| -private: | 
| -    explicit BodyStreamBuffer(PassOwnPtr<FetchDataConsumerHandle> handle) : m_handle(handle) { } | 
| +    // This function will lock |this| object. |client| cannot be null. | 
| +    void startLoading(ExecutionContext*, FetchDataLoader*, FetchDataLoader::Client* /* client */); | 
|  | 
| -    void setDrainingStreamNotificationClient(DrainingStreamNotificationClient*); | 
| +    bool isLocked() const { return m_stream->isLocked(); } | 
| +    bool hasBody() const { return m_hasBody; } | 
| +    bool hasPendingActivity() const { return isLocked() || m_lockLevel > 0; } | 
|  | 
| -    void startLoading(FetchDataLoader*, FetchDataLoader::Client*); | 
| -    // Call DrainingStreamNotificationClient. | 
| -    void doDrainingStreamNotification(); | 
| -    // Clear DrainingStreamNotificationClient without calling. | 
| -    void clearDrainingStreamNotification(); | 
| +    // UnderlyingSource | 
| +    void pullSource() override; | 
| +    ScriptPromise cancelSource(ScriptState*, ScriptValue reason) override; | 
|  | 
| -    friend class DrainingBodyStreamBuffer; | 
| +    // WebDataConsumerHandle::Client | 
| +    void didGetReadable() override; | 
|  | 
| -    OwnPtr<FetchDataConsumerHandle> m_handle; | 
| -    Member<FetchDataLoader> m_fetchDataLoader; | 
| -    Member<DrainingStreamNotificationClient> m_drainingStreamNotificationClient; | 
| -}; | 
| - | 
| -// DrainingBodyStreamBuffer wraps BodyStreamBuffer returned from | 
| -// Body::createDrainingStream() and calls DrainingStreamNotificationClient | 
| -// callbacks unless leakBuffer() is called: | 
| -// - If startLoading() is called, the callback is called after loading finished. | 
| -// - If drainAsBlobDataHandle() is called, the callback is called immediately. | 
| -// - If leakBuffer() is called, the callback is no longer called. | 
| -// Any calls to DrainingBodyStreamBuffer methods after a call to either of | 
| -// methods above is no-op. | 
| -// After calling one of the methods above, we don't have to keep | 
| -// DrainingBodyStreamBuffer alive. | 
| -// If DrainingBodyStreamBuffer is destructed before any of above is called, | 
| -// the callback is called at destruction. | 
| -class MODULES_EXPORT DrainingBodyStreamBuffer final { | 
| -public: | 
| -    static PassOwnPtr<DrainingBodyStreamBuffer> create(BodyStreamBuffer* buffer, BodyStreamBuffer::DrainingStreamNotificationClient* client) | 
| +    DEFINE_INLINE_TRACE() | 
| { | 
| -        return adoptPtr(new DrainingBodyStreamBuffer(buffer, client)); | 
| +        visitor->trace(m_stream); | 
| +        visitor->trace(m_streamReader); | 
| +        visitor->trace(m_loaders); | 
| +        UnderlyingSource::trace(visitor); | 
| } | 
| -    ~DrainingBodyStreamBuffer(); | 
| -    void startLoading(FetchDataLoader*, FetchDataLoader::Client*); | 
| -    BodyStreamBuffer* leakBuffer(); | 
| -    PassRefPtr<BlobDataHandle> drainAsBlobDataHandle(FetchDataConsumerHandle::Reader::BlobSizePolicy); | 
|  | 
| private: | 
| -    DrainingBodyStreamBuffer(BodyStreamBuffer*, BodyStreamBuffer::DrainingStreamNotificationClient*); | 
| +    class LoaderHolder; | 
| +    enum EndLoadingMode { | 
| +        EndLoadingDone, | 
| +        EndLoadingErrored, | 
| +    }; | 
| +    void close(); | 
| +    void error(); | 
| +    void processData(); | 
| +    void unlock(); | 
| +    void endLoading(FetchDataLoader::Client*, EndLoadingMode); | 
|  | 
| -    Persistent<BodyStreamBuffer> m_buffer; | 
| +    OwnPtr<FetchDataConsumerHandle> m_handle; | 
| +    OwnPtr<FetchDataConsumerHandle::Reader> m_reader; | 
| +    Member<ReadableByteStream> m_stream; | 
| +    Member<ReadableByteStreamReader> m_streamReader; | 
| +    HeapHashSet<Member<FetchDataLoader::Client>> m_loaders; | 
| +    // We need this variable because we cannot lock closed or erroed stream | 
| +    // although we should return true for hasPendingActivity() when someone | 
| +    // calls |startLoading| but the loding is not yet done. | 
| +    unsigned m_lockLevel; | 
| +    const bool m_hasBody; | 
| +    bool m_streamNeedsMore; | 
| }; | 
|  | 
| } // namespace blink | 
|  |