Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "modules/fetch/BodyStreamBuffer.h" | 5 #include "modules/fetch/BodyStreamBuffer.h" |
| 6 | 6 |
| 7 #include "bindings/core/v8/ScriptState.h" | 7 #include "bindings/core/v8/ScriptState.h" |
| 8 #include "bindings/core/v8/V8HiddenValue.h" | 8 #include "bindings/core/v8/V8HiddenValue.h" |
| 9 #include "bindings/core/v8/WorkerOrWorkletScriptController.h" | 9 #include "bindings/core/v8/WorkerOrWorkletScriptController.h" |
| 10 #include "core/dom/DOMArrayBuffer.h" | 10 #include "core/dom/DOMArrayBuffer.h" |
| 11 #include "core/dom/DOMTypedArray.h" | 11 #include "core/dom/DOMTypedArray.h" |
| 12 #include "core/dom/ExceptionCode.h" | 12 #include "core/dom/ExceptionCode.h" |
| 13 #include "core/streams/ReadableStreamController.h" | 13 #include "core/streams/ReadableStreamController.h" |
| 14 #include "core/streams/ReadableStreamOperations.h" | 14 #include "core/streams/ReadableStreamOperations.h" |
| 15 #include "core/workers/WorkerGlobalScope.h" | 15 #include "core/workers/WorkerGlobalScope.h" |
| 16 #include "modules/fetch/Body.h" | 16 #include "modules/fetch/Body.h" |
| 17 #include "modules/fetch/BytesConsumerForDataConsumerHandle.h" | 17 #include "modules/fetch/BytesConsumerForDataConsumerHandle.h" |
| 18 #include "modules/fetch/DataConsumerHandleUtil.h" | 18 #include "modules/fetch/DataConsumerHandleUtil.h" |
| 19 #include "modules/fetch/DataConsumerTee.h" | |
| 20 #include "modules/fetch/ReadableStreamDataConsumerHandle.h" | 19 #include "modules/fetch/ReadableStreamDataConsumerHandle.h" |
| 21 #include "platform/blob/BlobData.h" | 20 #include "platform/blob/BlobData.h" |
| 22 #include "platform/network/EncodedFormData.h" | 21 #include "platform/network/EncodedFormData.h" |
| 23 #include <memory> | 22 #include <memory> |
| 24 | 23 |
| 25 namespace blink { | 24 namespace blink { |
| 26 | 25 |
| 27 namespace { | 26 namespace { |
| 28 | 27 |
| 29 bool isTerminating(ScriptState* scriptState) | 28 bool isTerminating(ScriptState* scriptState) |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 92 void stop() override | 91 void stop() override |
| 93 { | 92 { |
| 94 m_buffer->stopLoading(); | 93 m_buffer->stopLoading(); |
| 95 } | 94 } |
| 96 | 95 |
| 97 Member<BodyStreamBuffer> m_buffer; | 96 Member<BodyStreamBuffer> m_buffer; |
| 98 Member<FetchDataLoader::Client> m_client; | 97 Member<FetchDataLoader::Client> m_client; |
| 99 }; | 98 }; |
| 100 | 99 |
| 101 BodyStreamBuffer::BodyStreamBuffer(ScriptState* scriptState, std::unique_ptr<Fet chDataConsumerHandle> handle) | 100 BodyStreamBuffer::BodyStreamBuffer(ScriptState* scriptState, std::unique_ptr<Fet chDataConsumerHandle> handle) |
| 101 : BodyStreamBuffer(scriptState, new BytesConsumerForDataConsumerHandle(std:: move(handle))) | |
| 102 { | |
| 103 } | |
| 104 | |
| 105 BodyStreamBuffer::BodyStreamBuffer(ScriptState* scriptState, BytesConsumer* cons umer) | |
| 102 : UnderlyingSourceBase(scriptState) | 106 : UnderlyingSourceBase(scriptState) |
| 103 , m_scriptState(scriptState) | 107 , m_scriptState(scriptState) |
| 104 , m_handle(std::move(handle)) | 108 , m_consumer(consumer) |
| 105 , m_reader(m_handle->obtainFetchDataReader(this)) | |
| 106 , m_madeFromReadableStream(false) | 109 , m_madeFromReadableStream(false) |
| 107 { | 110 { |
| 108 if (isTerminating(scriptState)) { | 111 if (isTerminating(scriptState)) { |
| 109 m_reader = nullptr; | 112 m_consumer->cancel(); |
| 110 m_handle = nullptr; | |
| 111 return; | 113 return; |
| 112 } | 114 } |
| 113 v8::Local<v8::Value> bodyValue = toV8(this, scriptState); | 115 v8::Local<v8::Value> bodyValue = toV8(this, scriptState); |
| 114 if (bodyValue.IsEmpty()) { | 116 if (bodyValue.IsEmpty()) { |
| 115 DCHECK(isTerminating(scriptState)); | 117 DCHECK(isTerminating(scriptState)); |
| 116 m_reader = nullptr; | 118 m_consumer->cancel(); |
| 117 m_handle = nullptr; | |
| 118 return; | 119 return; |
| 119 } | 120 } |
| 120 DCHECK(bodyValue->IsObject()); | 121 DCHECK(bodyValue->IsObject()); |
| 121 v8::Local<v8::Object> body = bodyValue.As<v8::Object>(); | 122 v8::Local<v8::Object> body = bodyValue.As<v8::Object>(); |
| 122 | 123 |
| 123 ScriptValue readableStream = ReadableStreamOperations::createReadableStream( | 124 ScriptValue readableStream = ReadableStreamOperations::createReadableStream( |
| 124 scriptState, this, ReadableStreamOperations::createCountQueuingStrategy( scriptState, 0)); | 125 scriptState, this, ReadableStreamOperations::createCountQueuingStrategy( scriptState, 0)); |
| 125 if (isTerminating(scriptState)) { | 126 if (isTerminating(scriptState)) { |
| 126 m_reader = nullptr; | 127 m_consumer->cancel(); |
| 127 m_handle = nullptr; | |
| 128 return; | 128 return; |
| 129 } | 129 } |
| 130 V8HiddenValue::setHiddenValue(scriptState, body, V8HiddenValue::internalBody Stream(scriptState->isolate()), readableStream.v8Value()); | 130 V8HiddenValue::setHiddenValue(scriptState, body, V8HiddenValue::internalBody Stream(scriptState->isolate()), readableStream.v8Value()); |
| 131 m_consumer->setClient(this); | |
| 131 } | 132 } |
| 132 | 133 |
| 133 BodyStreamBuffer::BodyStreamBuffer(ScriptState* scriptState, ScriptValue stream) | 134 BodyStreamBuffer::BodyStreamBuffer(ScriptState* scriptState, ScriptValue stream) |
| 134 : UnderlyingSourceBase(scriptState) | 135 : UnderlyingSourceBase(scriptState) |
| 135 , m_scriptState(scriptState) | 136 , m_scriptState(scriptState) |
| 136 , m_madeFromReadableStream(true) | 137 , m_madeFromReadableStream(true) |
| 137 { | 138 { |
| 138 DCHECK(ReadableStreamOperations::isReadableStream(scriptState, stream)); | 139 DCHECK(ReadableStreamOperations::isReadableStream(scriptState, stream)); |
| 139 if (isTerminating(scriptState)) | 140 if (isTerminating(scriptState)) |
| 140 return; | 141 return; |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 157 v8::Local<v8::Value> bodyValue = toV8(this, m_scriptState.get()); | 158 v8::Local<v8::Value> bodyValue = toV8(this, m_scriptState.get()); |
| 158 if (bodyValue.IsEmpty()) { | 159 if (bodyValue.IsEmpty()) { |
| 159 DCHECK(isTerminating(m_scriptState.get())); | 160 DCHECK(isTerminating(m_scriptState.get())); |
| 160 return ScriptValue(); | 161 return ScriptValue(); |
| 161 } | 162 } |
| 162 DCHECK(bodyValue->IsObject()); | 163 DCHECK(bodyValue->IsObject()); |
| 163 v8::Local<v8::Object> body = bodyValue.As<v8::Object>(); | 164 v8::Local<v8::Object> body = bodyValue.As<v8::Object>(); |
| 164 return ScriptValue(m_scriptState.get(), V8HiddenValue::getHiddenValue(m_scri ptState.get(), body, V8HiddenValue::internalBodyStream(m_scriptState->isolate()) )); | 165 return ScriptValue(m_scriptState.get(), V8HiddenValue::getHiddenValue(m_scri ptState.get(), body, V8HiddenValue::internalBodyStream(m_scriptState->isolate()) )); |
| 165 } | 166 } |
| 166 | 167 |
| 167 PassRefPtr<BlobDataHandle> BodyStreamBuffer::drainAsBlobDataHandle(FetchDataCons umerHandle::Reader::BlobSizePolicy policy) | 168 PassRefPtr<BlobDataHandle> BodyStreamBuffer::drainAsBlobDataHandle(BytesConsumer ::BlobSizePolicy policy) |
| 168 { | 169 { |
| 169 ASSERT(!isStreamLocked()); | 170 ASSERT(!isStreamLocked()); |
| 170 ASSERT(!isStreamDisturbed()); | 171 ASSERT(!isStreamDisturbed()); |
| 171 if (isStreamClosed() || isStreamErrored()) | 172 if (isStreamClosed() || isStreamErrored()) |
| 172 return nullptr; | 173 return nullptr; |
| 173 | 174 |
| 174 if (m_madeFromReadableStream) | 175 if (m_madeFromReadableStream) |
| 175 return nullptr; | 176 return nullptr; |
| 176 | 177 |
| 177 RefPtr<BlobDataHandle> blobDataHandle = m_reader->drainAsBlobDataHandle(poli cy); | 178 RefPtr<BlobDataHandle> blobDataHandle = m_consumer->drainAsBlobDataHandle(po licy); |
| 178 if (blobDataHandle) { | 179 if (blobDataHandle) { |
| 179 closeAndLockAndDisturb(); | 180 closeAndLockAndDisturb(); |
| 180 return blobDataHandle.release(); | 181 return blobDataHandle.release(); |
| 181 } | 182 } |
| 182 return nullptr; | 183 return nullptr; |
| 183 } | 184 } |
| 184 | 185 |
| 185 PassRefPtr<EncodedFormData> BodyStreamBuffer::drainAsFormData() | 186 PassRefPtr<EncodedFormData> BodyStreamBuffer::drainAsFormData() |
| 186 { | 187 { |
| 187 ASSERT(!isStreamLocked()); | 188 ASSERT(!isStreamLocked()); |
| 188 ASSERT(!isStreamDisturbed()); | 189 ASSERT(!isStreamDisturbed()); |
| 189 if (isStreamClosed() || isStreamErrored()) | 190 if (isStreamClosed() || isStreamErrored()) |
| 190 return nullptr; | 191 return nullptr; |
| 191 | 192 |
| 192 if (m_madeFromReadableStream) | 193 if (m_madeFromReadableStream) |
| 193 return nullptr; | 194 return nullptr; |
| 194 | 195 |
| 195 RefPtr<EncodedFormData> formData = m_reader->drainAsFormData(); | 196 RefPtr<EncodedFormData> formData = m_consumer->drainAsFormData(); |
| 196 if (formData) { | 197 if (formData) { |
| 197 closeAndLockAndDisturb(); | 198 closeAndLockAndDisturb(); |
| 198 return formData.release(); | 199 return formData.release(); |
| 199 } | 200 } |
| 200 return nullptr; | 201 return nullptr; |
| 201 } | 202 } |
| 202 | 203 |
| 203 void BodyStreamBuffer::startLoading(FetchDataLoader* loader, FetchDataLoader::Cl ient* client) | 204 void BodyStreamBuffer::startLoading(FetchDataLoader* loader, FetchDataLoader::Cl ient* client) |
| 204 { | 205 { |
| 205 ASSERT(!m_loader); | 206 ASSERT(!m_loader); |
| 206 ASSERT(m_scriptState->contextIsValid()); | 207 ASSERT(m_scriptState->contextIsValid()); |
| 207 std::unique_ptr<FetchDataConsumerHandle> handle = releaseHandle(); | |
| 208 m_loader = loader; | 208 m_loader = loader; |
| 209 loader->start(new BytesConsumerForDataConsumerHandle(std::move(handle)), new LoaderClient(m_scriptState->getExecutionContext(), this, client)); | 209 loader->start(releaseHandle(), new LoaderClient(m_scriptState->getExecutionC ontext(), this, client)); |
| 210 } | 210 } |
| 211 | 211 |
| 212 void BodyStreamBuffer::tee(BodyStreamBuffer** branch1, BodyStreamBuffer** branch 2) | 212 void BodyStreamBuffer::tee(BodyStreamBuffer** branch1, BodyStreamBuffer** branch 2) |
| 213 { | 213 { |
| 214 DCHECK(!isStreamLocked()); | 214 DCHECK(!isStreamLocked()); |
| 215 DCHECK(!isStreamDisturbed()); | 215 DCHECK(!isStreamDisturbed()); |
| 216 *branch1 = nullptr; | 216 *branch1 = nullptr; |
| 217 *branch2 = nullptr; | 217 *branch2 = nullptr; |
| 218 | 218 |
| 219 if (m_madeFromReadableStream) { | 219 if (m_madeFromReadableStream) { |
| 220 ScriptValue stream1, stream2; | 220 ScriptValue stream1, stream2; |
| 221 ReadableStreamOperations::tee(m_scriptState.get(), stream(), &stream1, & stream2); | 221 ReadableStreamOperations::tee(m_scriptState.get(), stream(), &stream1, & stream2); |
| 222 *branch1 = new BodyStreamBuffer(m_scriptState.get(), stream1); | 222 *branch1 = new BodyStreamBuffer(m_scriptState.get(), stream1); |
| 223 *branch2 = new BodyStreamBuffer(m_scriptState.get(), stream2); | 223 *branch2 = new BodyStreamBuffer(m_scriptState.get(), stream2); |
| 224 return; | 224 return; |
| 225 } | 225 } |
| 226 std::unique_ptr<FetchDataConsumerHandle> handle = releaseHandle(); | 226 BytesConsumer* dest1 = nullptr; |
| 227 std::unique_ptr<FetchDataConsumerHandle> handle1, handle2; | 227 BytesConsumer* dest2 = nullptr; |
| 228 DataConsumerTee::create(m_scriptState->getExecutionContext(), std::move(hand le), &handle1, &handle2); | 228 BytesConsumer::tee(m_scriptState->getExecutionContext(), releaseHandle(), &d est1, &dest2); |
| 229 *branch1 = new BodyStreamBuffer(m_scriptState.get(), std::move(handle1)); | 229 *branch1 = new BodyStreamBuffer(m_scriptState.get(), dest1); |
| 230 *branch2 = new BodyStreamBuffer(m_scriptState.get(), std::move(handle2)); | 230 *branch2 = new BodyStreamBuffer(m_scriptState.get(), dest2); |
| 231 } | 231 } |
| 232 | 232 |
| 233 ScriptPromise BodyStreamBuffer::pull(ScriptState* scriptState) | 233 ScriptPromise BodyStreamBuffer::pull(ScriptState* scriptState) |
| 234 { | 234 { |
| 235 ASSERT(scriptState == m_scriptState.get()); | 235 ASSERT(scriptState == m_scriptState.get()); |
| 236 if (m_streamNeedsMore) | 236 if (m_streamNeedsMore) |
| 237 return ScriptPromise::castUndefined(scriptState); | 237 return ScriptPromise::castUndefined(scriptState); |
| 238 m_streamNeedsMore = true; | 238 m_streamNeedsMore = true; |
| 239 processData(); | 239 processData(); |
| 240 return ScriptPromise::castUndefined(scriptState); | 240 return ScriptPromise::castUndefined(scriptState); |
| 241 } | 241 } |
| 242 | 242 |
| 243 ScriptPromise BodyStreamBuffer::cancel(ScriptState* scriptState, ScriptValue rea son) | 243 ScriptPromise BodyStreamBuffer::cancel(ScriptState* scriptState, ScriptValue rea son) |
| 244 { | 244 { |
| 245 ASSERT(scriptState == m_scriptState.get()); | 245 ASSERT(scriptState == m_scriptState.get()); |
| 246 close(); | 246 close(); |
| 247 return ScriptPromise::castUndefined(scriptState); | 247 return ScriptPromise::castUndefined(scriptState); |
| 248 } | 248 } |
| 249 | 249 |
| 250 void BodyStreamBuffer::didGetReadable() | 250 void BodyStreamBuffer::onStateChange() |
| 251 { | 251 { |
| 252 if (!m_reader || !getExecutionContext() || getExecutionContext()->activeDOMO bjectsAreStopped()) | 252 if (!m_consumer || !getExecutionContext() || getExecutionContext()->activeDO MObjectsAreStopped()) |
| 253 return; | 253 return; |
| 254 | 254 |
| 255 if (!m_streamNeedsMore) { | 255 switch (m_consumer->getPublicState()) { |
| 256 // Perform zero-length read to call close()/error() early. | 256 case BytesConsumer::PublicState::ReadableOrWaiting: |
| 257 size_t readSize; | 257 break; |
| 258 WebDataConsumerHandle::Result result = m_reader->read(nullptr, 0, WebDat aConsumerHandle::FlagNone, &readSize); | 258 case BytesConsumer::PublicState::Closed: |
| 259 switch (result) { | 259 close(); |
| 260 case WebDataConsumerHandle::Ok: | 260 return; |
| 261 case WebDataConsumerHandle::ShouldWait: | 261 case BytesConsumer::PublicState::Errored: |
| 262 return; | 262 error(); |
| 263 case WebDataConsumerHandle::Done: | |
| 264 close(); | |
| 265 return; | |
| 266 case WebDataConsumerHandle::Busy: | |
| 267 case WebDataConsumerHandle::ResourceExhausted: | |
| 268 case WebDataConsumerHandle::UnexpectedError: | |
| 269 error(); | |
| 270 return; | |
| 271 } | |
| 272 return; | 263 return; |
| 273 } | 264 } |
| 274 processData(); | 265 processData(); |
| 275 } | 266 } |
| 276 | 267 |
| 277 bool BodyStreamBuffer::hasPendingActivity() const | 268 bool BodyStreamBuffer::hasPendingActivity() const |
| 278 { | 269 { |
| 279 if (m_loader) | 270 if (m_loader) |
| 280 return true; | 271 return true; |
| 281 return UnderlyingSourceBase::hasPendingActivity(); | 272 return UnderlyingSourceBase::hasPendingActivity(); |
| 282 } | 273 } |
| 283 | 274 |
| 284 void BodyStreamBuffer::stop() | 275 void BodyStreamBuffer::stop() |
| 285 { | 276 { |
| 286 m_reader = nullptr; | 277 if (m_consumer) |
| 287 m_handle = nullptr; | 278 m_consumer->cancel(); |
| 279 m_consumer = nullptr; | |
| 288 UnderlyingSourceBase::stop(); | 280 UnderlyingSourceBase::stop(); |
| 289 } | 281 } |
| 290 | 282 |
| 291 bool BodyStreamBuffer::isStreamReadable() | 283 bool BodyStreamBuffer::isStreamReadable() |
| 292 { | 284 { |
| 293 ScriptState::Scope scope(m_scriptState.get()); | 285 ScriptState::Scope scope(m_scriptState.get()); |
| 294 return ReadableStreamOperations::isReadable(m_scriptState.get(), stream()); | 286 return ReadableStreamOperations::isReadable(m_scriptState.get(), stream()); |
| 295 } | 287 } |
| 296 | 288 |
| 297 bool BodyStreamBuffer::isStreamClosed() | 289 bool BodyStreamBuffer::isStreamClosed() |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 328 | 320 |
| 329 ScriptState::Scope scope(m_scriptState.get()); | 321 ScriptState::Scope scope(m_scriptState.get()); |
| 330 NonThrowableExceptionState exceptionState; | 322 NonThrowableExceptionState exceptionState; |
| 331 ScriptValue reader = ReadableStreamOperations::getReader(m_scriptState.get() , stream(), exceptionState); | 323 ScriptValue reader = ReadableStreamOperations::getReader(m_scriptState.get() , stream(), exceptionState); |
| 332 ReadableStreamOperations::defaultReaderRead(m_scriptState.get(), reader); | 324 ReadableStreamOperations::defaultReaderRead(m_scriptState.get(), reader); |
| 333 } | 325 } |
| 334 | 326 |
| 335 void BodyStreamBuffer::close() | 327 void BodyStreamBuffer::close() |
| 336 { | 328 { |
| 337 controller()->close(); | 329 controller()->close(); |
| 338 m_reader = nullptr; | 330 if (m_consumer) { |
| 339 m_handle = nullptr; | 331 m_consumer->cancel(); |
| 332 m_consumer = nullptr; | |
| 333 } | |
| 340 } | 334 } |
| 341 | 335 |
| 342 void BodyStreamBuffer::error() | 336 void BodyStreamBuffer::error() |
| 343 { | 337 { |
| 344 controller()->error(DOMException::create(NetworkError, "network error")); | 338 controller()->error(DOMException::create(NetworkError, "network error")); |
| 345 m_reader = nullptr; | 339 if (m_consumer) { |
| 346 m_handle = nullptr; | 340 m_consumer->cancel(); |
| 341 m_consumer = nullptr; | |
| 342 } | |
| 347 } | 343 } |
| 348 | 344 |
| 349 void BodyStreamBuffer::processData() | 345 void BodyStreamBuffer::processData() |
| 350 { | 346 { |
| 351 ASSERT(m_reader); | 347 DCHECK(m_consumer); |
| 352 while (m_streamNeedsMore) { | 348 while (m_streamNeedsMore) { |
| 353 const void* buffer; | 349 const char* buffer = nullptr; |
| 354 size_t available; | 350 size_t available = 0; |
| 355 WebDataConsumerHandle::Result result = m_reader->beginRead(&buffer, WebD ataConsumerHandle::FlagNone, &available); | 351 |
| 356 switch (result) { | 352 switch (m_consumer->beginRead(&buffer, &available)) { |
| 357 case WebDataConsumerHandle::Ok: { | 353 case BytesConsumer::Result::Ok: { |
| 358 DOMUint8Array* array = DOMUint8Array::create(static_cast<const unsig ned char*>(buffer), available); | 354 DOMUint8Array* array = DOMUint8Array::create(reinterpret_cast<const unsigned char*>(buffer), available); |
| 359 m_reader->endRead(available); | 355 m_consumer->endRead(available); |
|
hiroshige
2016/09/07 09:25:54
We have to check the return value of endRead().
yhirano
2016/09/08 01:41:05
Done.
| |
| 360 // Clear m_streamNeedsMore in order to detect a pull call. | 356 // Clear m_streamNeedsMore in order to detect a pull call. |
| 361 m_streamNeedsMore = false; | 357 m_streamNeedsMore = false; |
| 362 controller()->enqueue(array); | 358 controller()->enqueue(array); |
| 363 // If m_streamNeedsMore is true, it means that pull is called and | 359 // If m_streamNeedsMore is true, it means that pull is called and |
| 364 // the stream needs more data even if the desired size is not | 360 // the stream needs more data even if the desired size is not |
| 365 // positive. | 361 // positive. |
| 366 if (!m_streamNeedsMore) | 362 if (!m_streamNeedsMore) |
| 367 m_streamNeedsMore = controller()->desiredSize() > 0; | 363 m_streamNeedsMore = controller()->desiredSize() > 0; |
| 368 break; | 364 break; |
| 369 } | 365 } |
| 370 case WebDataConsumerHandle::Done: | 366 case BytesConsumer::Result::ShouldWait: |
| 367 return; | |
| 368 case BytesConsumer::Result::Done: | |
| 371 close(); | 369 close(); |
| 372 return; | 370 return; |
| 373 | 371 case BytesConsumer::Result::Error: |
| 374 case WebDataConsumerHandle::ShouldWait: | |
| 375 return; | |
| 376 | |
| 377 case WebDataConsumerHandle::Busy: | |
| 378 case WebDataConsumerHandle::ResourceExhausted: | |
| 379 case WebDataConsumerHandle::UnexpectedError: | |
| 380 error(); | 372 error(); |
| 381 return; | 373 return; |
| 382 } | 374 } |
| 383 } | 375 } |
| 384 } | 376 } |
| 385 | 377 |
| 386 void BodyStreamBuffer::endLoading() | 378 void BodyStreamBuffer::endLoading() |
| 387 { | 379 { |
| 388 ASSERT(m_loader); | 380 ASSERT(m_loader); |
| 389 m_loader = nullptr; | 381 m_loader = nullptr; |
| 390 } | 382 } |
| 391 | 383 |
| 392 void BodyStreamBuffer::stopLoading() | 384 void BodyStreamBuffer::stopLoading() |
| 393 { | 385 { |
| 394 if (!m_loader) | 386 if (!m_loader) |
| 395 return; | 387 return; |
| 396 m_loader->cancel(); | 388 m_loader->cancel(); |
| 397 m_loader = nullptr; | 389 m_loader = nullptr; |
| 398 } | 390 } |
| 399 | 391 |
| 400 std::unique_ptr<FetchDataConsumerHandle> BodyStreamBuffer::releaseHandle() | 392 BytesConsumer* BodyStreamBuffer::releaseHandle() |
| 401 { | 393 { |
| 402 DCHECK(!isStreamLocked()); | 394 DCHECK(!isStreamLocked()); |
| 403 DCHECK(!isStreamDisturbed()); | 395 DCHECK(!isStreamDisturbed()); |
| 404 | 396 |
| 405 if (m_madeFromReadableStream) { | 397 if (m_madeFromReadableStream) { |
| 406 ScriptState::Scope scope(m_scriptState.get()); | 398 ScriptState::Scope scope(m_scriptState.get()); |
| 407 // We need to have |reader| alive by some means (as written in | 399 // We need to have |reader| alive by some means (as written in |
| 408 // ReadableStreamDataConsumerHandle). Based on the following facts | 400 // ReadableStreamDataConsumerHandle). Based on the following facts |
| 409 // - This function is used only from tee and startLoading. | 401 // - This function is used only from tee and startLoading. |
| 410 // - This branch cannot be taken when called from tee. | 402 // - This branch cannot be taken when called from tee. |
| 411 // - startLoading makes hasPendingActivity return true while loading. | 403 // - startLoading makes hasPendingActivity return true while loading. |
| 412 // , we don't need to keep the reader explicitly. | 404 // , we don't need to keep the reader explicitly. |
| 413 NonThrowableExceptionState exceptionState; | 405 NonThrowableExceptionState exceptionState; |
| 414 ScriptValue reader = ReadableStreamOperations::getReader(m_scriptState.g et(), stream(), exceptionState); | 406 ScriptValue reader = ReadableStreamOperations::getReader(m_scriptState.g et(), stream(), exceptionState); |
| 415 return ReadableStreamDataConsumerHandle::create(m_scriptState.get(), rea der); | 407 return new BytesConsumerForDataConsumerHandle(ReadableStreamDataConsumer Handle::create(m_scriptState.get(), reader)); |
| 416 } | 408 } |
| 417 // We need to call these before calling closeAndLockAndDisturb. | 409 // We need to call these before calling closeAndLockAndDisturb. |
| 418 const bool isClosed = isStreamClosed(); | 410 const bool isClosed = isStreamClosed(); |
| 419 const bool isErrored = isStreamErrored(); | 411 const bool isErrored = isStreamErrored(); |
| 420 std::unique_ptr<FetchDataConsumerHandle> handle = std::move(m_handle); | 412 BytesConsumer* consumer = m_consumer.release(); |
| 421 | 413 |
| 422 closeAndLockAndDisturb(); | 414 closeAndLockAndDisturb(); |
| 423 | 415 |
| 424 if (isClosed) { | 416 if (isClosed) { |
| 425 // Note that the stream cannot be "draining", because it doesn't have | 417 // Note that the stream cannot be "draining", because it doesn't have |
| 426 // the internal buffer. | 418 // the internal buffer. |
| 427 return createFetchDataConsumerHandleFromWebHandle(createDoneDataConsumer Handle()); | 419 return new BytesConsumerForDataConsumerHandle(createFetchDataConsumerHan dleFromWebHandle(createDoneDataConsumerHandle())); |
| 428 } | 420 } |
| 429 if (isErrored) | 421 if (isErrored) |
| 430 return createFetchDataConsumerHandleFromWebHandle(createUnexpectedErrorD ataConsumerHandle()); | 422 return new BytesConsumerForDataConsumerHandle(createFetchDataConsumerHan dleFromWebHandle(createUnexpectedErrorDataConsumerHandle())); |
| 431 | 423 |
| 432 DCHECK(handle); | 424 DCHECK(consumer); |
| 433 return handle; | 425 consumer->clearClient(); |
| 426 return consumer; | |
| 434 } | 427 } |
| 435 | 428 |
| 436 } // namespace blink | 429 } // namespace blink |
| OLD | NEW |