Chromium Code Reviews| Index: Source/core/xml/XMLHttpRequest.cpp |
| diff --git a/Source/core/xml/XMLHttpRequest.cpp b/Source/core/xml/XMLHttpRequest.cpp |
| index 34497abe48d105b98a6f34586ee1b6e6b3f01e11..971b8b0f61637d78d46579dd9e9fe5187c6304a0 100644 |
| --- a/Source/core/xml/XMLHttpRequest.cpp |
| +++ b/Source/core/xml/XMLHttpRequest.cpp |
| @@ -26,6 +26,7 @@ |
| #include "bindings/core/v8/ExceptionState.h" |
| #include "core/FetchInitiatorTypeNames.h" |
| #include "core/dom/ContextFeatures.h" |
| +#include "core/dom/DOMException.h" |
| #include "core/dom/DOMImplementation.h" |
| #include "core/dom/ExceptionCode.h" |
| #include "core/dom/XMLDocument.h" |
| @@ -43,7 +44,10 @@ |
| #include "core/inspector/InspectorInstrumentation.h" |
| #include "core/inspector/InspectorTraceEvents.h" |
| #include "core/loader/ThreadableLoader.h" |
| +#include "core/streams/ReadableStream.h" |
| +#include "core/streams/ReadableStreamImpl.h" |
| #include "core/streams/Stream.h" |
| +#include "core/streams/UnderlyingSource.h" |
| #include "core/xml/XMLHttpRequestProgressEvent.h" |
| #include "core/xml/XMLHttpRequestUpload.h" |
| #include "platform/Logging.h" |
| @@ -110,6 +114,31 @@ static void logConsoleError(ExecutionContext* context, const String& message) |
| context->addConsoleMessage(JSMessageSource, ErrorMessageLevel, message); |
| } |
| +namespace { |
| + |
| +class ReadableStreamSource : public GarbageCollectedFinalized<ReadableStreamSource>, public UnderlyingSource { |
| + USING_GARBAGE_COLLECTED_MIXIN(ReadableStreamSource); |
| +public: |
| + ReadableStreamSource(XMLHttpRequest* owner) : m_owner(owner) { } |
| + virtual ~ReadableStreamSource() { } |
| + virtual void pullSource() OVERRIDE { } |
| + virtual ScriptPromise cancelSource(ScriptState* scriptState, ScriptValue reason) OVERRIDE |
| + { |
| + m_owner->abort(); |
| + return ScriptPromise::cast(scriptState, v8::Undefined(scriptState->isolate())); |
| + } |
| + virtual void trace(Visitor* visitor) OVERRIDE |
| + { |
| + UnderlyingSource::trace(visitor); |
| + visitor->trace(m_owner); |
| + } |
| + |
| +private: |
| + RawPtrWillBeMember<XMLHttpRequest> m_owner; |
| +}; |
| + |
| +} // namespace |
| + |
| PassRefPtrWillBeRawPtr<XMLHttpRequest> XMLHttpRequest::create(ExecutionContext* context, PassRefPtr<SecurityOrigin> securityOrigin) |
| { |
| RefPtrWillBeRawPtr<XMLHttpRequest> xmlHttpRequest = adoptRefWillBeRefCountedGarbageCollected(new XMLHttpRequest(context, securityOrigin)); |
| @@ -291,14 +320,23 @@ ArrayBuffer* XMLHttpRequest::responseArrayBuffer() |
| return m_responseArrayBuffer.get(); |
| } |
| -Stream* XMLHttpRequest::responseStream() |
| +Stream* XMLHttpRequest::responseLegacyStream() |
| { |
| ASSERT(m_responseTypeCode == ResponseTypeLegacyStream); |
| if (m_error || (m_state != LOADING && m_state != DONE)) |
| return 0; |
| - return m_responseStream.get(); |
| + return m_responseLegacyStream.get(); |
| +} |
| + |
| +ReadableStream* XMLHttpRequest::responseStream() |
| +{ |
| + ASSERT(m_responseTypeCode == ResponseTypeStream); |
| + if (m_error || (m_state != LOADING && m_state != DONE)) |
| + return nullptr; |
|
tyoshino (SeeGerritForStatus)
2014/08/14 00:38:56
i heard that we're still using 0 for a raw pointer
yhirano
2014/08/14 06:48:53
Done.
|
| + |
| + return m_responseStream; |
| } |
| void XMLHttpRequest::setTimeout(unsigned long timeout, ExceptionState& exceptionState) |
| @@ -352,6 +390,11 @@ void XMLHttpRequest::setResponseType(const String& responseType, ExceptionState& |
| m_responseTypeCode = ResponseTypeLegacyStream; |
| else |
| return; |
| + } else if (responseType == "stream") { |
| + if (RuntimeEnabledFeatures::streamEnabled()) |
| + m_responseTypeCode = ResponseTypeStream; |
| + else |
| + return; |
| } else { |
| ASSERT_NOT_REACHED(); |
| } |
| @@ -374,6 +417,8 @@ String XMLHttpRequest::responseType() |
| return "arraybuffer"; |
| case ResponseTypeLegacyStream: |
| return "legacystream"; |
| + case ResponseTypeStream: |
| + return "stream"; |
| } |
| return ""; |
| } |
| @@ -889,8 +934,15 @@ bool XMLHttpRequest::internalAbort() |
| InspectorInstrumentation::didFailXHRLoading(executionContext(), this, this); |
| - if (m_responseStream && m_state != DONE) |
| - m_responseStream->abort(); |
| + if (m_responseLegacyStream && m_state != DONE) |
| + m_responseLegacyStream->abort(); |
| + |
| + if (m_responseStream) { |
| + // When the stream is already closed (including canceled from the |
| + // user), |error| does nothing. |
| + // FIXME: Create a more specific error. |
|
tyoshino (SeeGerritForStatus)
2014/08/14 00:38:56
yes. internalAbort is used for non-abort() cases,
yhirano
2014/08/14 06:48:53
Done.
|
| + m_responseStream->error(DOMException::create(AbortError, "XMLHttpRequest::abort")); |
| + } |
| if (!m_loader) |
| return true; |
| @@ -932,6 +984,7 @@ void XMLHttpRequest::clearResponse() |
| m_responseBlob = nullptr; |
| m_downloadedBlobLength = 0; |
| + m_responseLegacyStream = nullptr; |
| m_responseStream = nullptr; |
| // These variables may referred by the response accessors. So, we can clear |
| @@ -1212,8 +1265,11 @@ void XMLHttpRequest::didFinishLoading(unsigned long identifier, double) |
| if (m_decoder) |
| m_responseText = m_responseText.concatenateWith(m_decoder->flush()); |
| + if (m_responseLegacyStream) |
| + m_responseLegacyStream->finalize(); |
| + |
| if (m_responseStream) |
| - m_responseStream->finalize(); |
| + m_responseStream->close(); |
| clearVariablesForLoading(); |
| @@ -1309,9 +1365,15 @@ void XMLHttpRequest::didReceiveData(const char* data, int len) |
| m_binaryResponseBuilder = SharedBuffer::create(); |
| m_binaryResponseBuilder->append(data, len); |
| } else if (m_responseTypeCode == ResponseTypeLegacyStream) { |
| - if (!m_responseStream) |
| - m_responseStream = Stream::create(executionContext(), responseMIMEType()); |
| - m_responseStream->addData(data, len); |
| + if (!m_responseLegacyStream) |
| + m_responseLegacyStream = Stream::create(executionContext(), responseMIMEType()); |
| + m_responseLegacyStream->addData(data, len); |
| + } else if (m_responseTypeCode == ResponseTypeStream) { |
| + if (!m_responseStream) { |
| + m_responseStream = new ReadableStreamImpl<ReadableStreamChunkTypeTraits<ArrayBuffer> >(executionContext(), new ReadableStreamSource(this)); |
| + m_responseStream->didSourceStart(); |
| + } |
| + m_responseStream->enqueue(ArrayBuffer::create(data, len)); |
| } |
| if (m_error) |
| @@ -1400,7 +1462,9 @@ ExecutionContext* XMLHttpRequest::executionContext() const |
| void XMLHttpRequest::trace(Visitor* visitor) |
| { |
| visitor->trace(m_responseBlob); |
| + visitor->trace(m_responseLegacyStream); |
| visitor->trace(m_responseStream); |
| + visitor->trace(m_streamSource); |
| visitor->trace(m_responseDocument); |
| visitor->trace(m_progressEventThrottle); |
| visitor->trace(m_upload); |