Chromium Code Reviews| Index: third_party/WebKit/Source/modules/fetch/BytesConsumerForDataConsumerHandle.cpp |
| diff --git a/third_party/WebKit/Source/modules/fetch/BytesConsumerForDataConsumerHandle.cpp b/third_party/WebKit/Source/modules/fetch/BytesConsumerForDataConsumerHandle.cpp |
| index f77611c5b857f3d687c58aac029616abc321e42f..b5e4fa105ff52f49f99196d5d7b33c6f2c177c6a 100644 |
| --- a/third_party/WebKit/Source/modules/fetch/BytesConsumerForDataConsumerHandle.cpp |
| +++ b/third_party/WebKit/Source/modules/fetch/BytesConsumerForDataConsumerHandle.cpp |
| @@ -18,6 +18,7 @@ BytesConsumerForDataConsumerHandle::~BytesConsumerForDataConsumerHandle() {} |
| BytesConsumer::Result BytesConsumerForDataConsumerHandle::read(char* buffer, size_t size, size_t* readSize) |
| { |
| + DCHECK(!m_isInTwoPhaseRead); |
| *readSize = 0; |
| if (m_state == InternalState::Closed) |
| return Result::Done; |
| @@ -45,6 +46,7 @@ BytesConsumer::Result BytesConsumerForDataConsumerHandle::read(char* buffer, siz |
| BytesConsumer::Result BytesConsumerForDataConsumerHandle::beginRead(const char** buffer, size_t* available) |
| { |
| + DCHECK(!m_isInTwoPhaseRead); |
| *buffer = nullptr; |
| *available = 0; |
| if (m_state == InternalState::Closed) |
| @@ -55,6 +57,7 @@ BytesConsumer::Result BytesConsumerForDataConsumerHandle::beginRead(const char** |
| WebDataConsumerHandle::Result r = m_reader->beginRead(reinterpret_cast<const void**>(buffer), WebDataConsumerHandle::FlagNone, available); |
| switch (r) { |
| case WebDataConsumerHandle::Ok: |
| + m_isInTwoPhaseRead = true; |
| return Result::Ok; |
| case WebDataConsumerHandle::ShouldWait: |
| return Result::ShouldWait; |
| @@ -73,12 +76,16 @@ BytesConsumer::Result BytesConsumerForDataConsumerHandle::beginRead(const char** |
| BytesConsumer::Result BytesConsumerForDataConsumerHandle::endRead(size_t read) |
| { |
| + DCHECK(m_isInTwoPhaseRead); |
| + m_isInTwoPhaseRead = false; |
| DCHECK(m_state == InternalState::Readable || m_state == InternalState::Waiting); |
| WebDataConsumerHandle::Result r = m_reader->endRead(read); |
| - if (r == WebDataConsumerHandle::Ok) |
| - return Result::Ok; |
| - error(); |
| - return Result::Error; |
| + if (m_hasPendingError || r != WebDataConsumerHandle::Ok) { |
| + m_hasPendingError = false; |
| + error(); |
| + return Result::Error; |
| + } |
| + return Result::Ok; |
| } |
| PassRefPtr<BlobDataHandle> BytesConsumerForDataConsumerHandle::drainAsBlobDataHandle(BlobSizePolicy policy) |
| @@ -113,17 +120,18 @@ void BytesConsumerForDataConsumerHandle::setClient(BytesConsumer::Client* client |
| { |
| DCHECK(!m_client); |
| DCHECK(client); |
| - m_client = client; |
| + if (m_state == InternalState::Readable || m_state == InternalState::Waiting) |
| + m_client = client; |
| } |
| void BytesConsumerForDataConsumerHandle::clearClient() |
| { |
| - DCHECK(m_client); |
| m_client = nullptr; |
| } |
| void BytesConsumerForDataConsumerHandle::cancel() |
| { |
| + DCHECK(!m_isInTwoPhaseRead); |
| if (m_state == InternalState::Readable || m_state == InternalState::Waiting) { |
| // We don't want the client to be notified in this case. |
| BytesConsumer::Client* client = m_client; |
| @@ -144,23 +152,28 @@ void BytesConsumerForDataConsumerHandle::didGetReadable() |
| // Perform zero-length read to call check handle's status. |
| size_t readSize; |
| WebDataConsumerHandle::Result result = m_reader->read(nullptr, 0, WebDataConsumerHandle::FlagNone, &readSize); |
| + BytesConsumer::Client* client = m_client; |
| switch (result) { |
| case WebDataConsumerHandle::Ok: |
| case WebDataConsumerHandle::ShouldWait: |
| - if (m_client) |
| - m_client->onStateChange(); |
| + if (client) |
| + client->onStateChange(); |
| return; |
| case WebDataConsumerHandle::Done: |
| close(); |
| - if (m_client) |
| - m_client->onStateChange(); |
| + if (client) |
| + client->onStateChange(); |
| return; |
| case WebDataConsumerHandle::Busy: |
| case WebDataConsumerHandle::ResourceExhausted: |
| case WebDataConsumerHandle::UnexpectedError: |
| - error(); |
| - if (m_client) |
| - m_client->onStateChange(); |
| + if (m_isInTwoPhaseRead) { |
|
hiroshige
2016/09/07 09:17:47
Should we do this check before m_reader->read()? w
yhirano
2016/09/07 10:51:34
Done.
|
| + m_hasPendingError = true; |
| + } else { |
| + error(); |
| + if (client) |
| + client->onStateChange(); |
| + } |
| return; |
| } |
| return; |
| @@ -174,21 +187,25 @@ DEFINE_TRACE(BytesConsumerForDataConsumerHandle) |
| void BytesConsumerForDataConsumerHandle::close() |
| { |
| + DCHECK(!m_isInTwoPhaseRead); |
| if (m_state == InternalState::Closed) |
| return; |
| DCHECK(m_state == InternalState::Readable || m_state == InternalState::Waiting); |
| m_state = InternalState::Closed; |
| m_reader = nullptr; |
| + clearClient(); |
| } |
| void BytesConsumerForDataConsumerHandle::error() |
| { |
| + DCHECK(!m_isInTwoPhaseRead); |
| if (m_state == InternalState::Errored) |
| return; |
| DCHECK(m_state == InternalState::Readable || m_state == InternalState::Waiting); |
| m_state = InternalState::Errored; |
| m_reader = nullptr; |
| m_error = Error("error"); |
| + clearClient(); |
| } |
| } // namespace blink |