Index: Source/modules/fetch/FetchDataLoader.cpp |
diff --git a/Source/modules/fetch/FetchDataLoader.cpp b/Source/modules/fetch/FetchDataLoader.cpp |
index 643042b67f85c7ff31dd5f2ceaf876188ab70a01..34fadd95c28fc43b94cf3d53dd7fdd80005cdfbf 100644 |
--- a/Source/modules/fetch/FetchDataLoader.cpp |
+++ b/Source/modules/fetch/FetchDataLoader.cpp |
@@ -212,6 +212,100 @@ protected: |
OwnPtr<ArrayBufferBuilder> m_rawData; |
}; |
+class FetchDataLoaderAsStream |
+ : public FetchDataLoader |
+ , public WebDataConsumerHandle::Client { |
+public: |
+ explicit FetchDataLoaderAsStream(Stream* outStream) |
+ : m_client(nullptr) |
+ , m_outStream(outStream) { } |
+ |
+ DEFINE_INLINE_VIRTUAL_TRACE() |
+ { |
+ FetchDataLoader::trace(visitor); |
+ visitor->trace(m_client); |
+ visitor->trace(m_outStream); |
+ } |
+ |
+protected: |
+ void start(FetchDataConsumerHandle* handle, FetchDataLoader::Client* client) override |
+ { |
+ ASSERT(!m_client); |
+ ASSERT(!m_reader); |
+ m_client = client; |
+ m_reader = handle->obtainReader(this); |
+ } |
+ |
+ void didGetReadable() override |
+ { |
+ ASSERT(m_client); |
+ ASSERT(m_reader); |
+ |
+ while (true) { |
+ const void* buffer; |
+ size_t available; |
+ WebDataConsumerHandle::Result result = m_reader->beginRead(&buffer, WebDataConsumerHandle::FlagNone, &available); |
+ |
+ bool needToFlush = false; |
+ |
+ switch (result) { |
+ case WebDataConsumerHandle::Ok: |
+ m_outStream->addData(static_cast<const char*>(buffer), available); |
+ m_reader->endRead(available); |
+ break; |
+ |
+ case WebDataConsumerHandle::Done: |
+ m_reader.clear(); |
+ if (needToFlush) |
+ m_outStream->flush(); |
+ m_outStream->finalize(); |
+ m_client->didFetchDataLoadedStream(); |
+ cleanup(); |
+ return; |
+ |
+ case WebDataConsumerHandle::ShouldWait: |
+ if (needToFlush) |
+ m_outStream->flush(); |
+ return; |
+ |
+ case WebDataConsumerHandle::Busy: |
+ case WebDataConsumerHandle::ResourceExhausted: |
+ case WebDataConsumerHandle::UnexpectedError: |
+ // If the stream is aborted soon after the stream is registered |
+ // to the StreamRegistry, ServiceWorkerURLRequestJob may not |
+ // notice the error and continue waiting forever. |
+ // FIXME: Add new message to report the error to the browser |
+ // process. |
+ m_reader.clear(); |
+ if (needToFlush) |
+ m_outStream->flush(); |
+ m_outStream->abort(); |
+ m_client->didFetchDataLoadFailed(); |
+ cleanup(); |
+ return; |
+ } |
+ } |
+ } |
+ |
+ void cancel() override |
+ { |
+ cleanup(); |
+ } |
+ |
+ void cleanup() |
+ { |
+ m_reader.clear(); |
+ m_client.clear(); |
+ m_outStream.clear(); |
+ } |
+ |
+ OwnPtr<FetchDataConsumerHandle::Reader> m_reader; |
+ Member<FetchDataLoader::Client> m_client; |
+ |
+ Member<Stream> m_outStream; |
+}; |
+ |
+ |
} // namespace |
FetchDataLoader* FetchDataLoader::createLoaderAsBlobHandle(const String& mimeType) |
@@ -229,4 +323,9 @@ FetchDataLoader* FetchDataLoader::createLoaderAsString() |
return new FetchDataLoaderAsArrayBufferOrString(FetchDataLoaderAsArrayBufferOrString::LoadAsString); |
} |
+FetchDataLoader* FetchDataLoader::createLoaderAsStream(Stream* outStream) |
+{ |
+ return new FetchDataLoaderAsStream(outStream); |
+} |
+ |
} // namespace blink |