Index: android_webview/native/input_stream_impl.cc |
diff --git a/android_webview/native/input_stream_impl.cc b/android_webview/native/input_stream_impl.cc |
index 24d7be09930bc734cbd56a55b00686f98513db33..85db3e0192c6fd5bd1f01a74a61b94f8972501d3 100644 |
--- a/android_webview/native/input_stream_impl.cc |
+++ b/android_webview/native/input_stream_impl.cc |
@@ -84,46 +84,46 @@ bool InputStreamImpl::Read(net::IOBuffer* dest, int length, int* bytes_read) { |
return false; |
} |
+ int remaining_length = length; |
+ bool eof = false; |
+ char* dest_write_ptr = dest->data(); |
jbyteArray buffer = buffer_.obj(); |
*bytes_read = 0; |
- const int read_size = std::min(length, kBufferSize); |
- int32_t byte_count; |
- do { |
- // Unfortunately it is valid for the Java InputStream to read 0 bytes some |
- // number of times before returning any more data. Because this method |
- // signals EOF by setting |bytes_read| to 0 and returning true necessary to |
- // call the Java-side read method until it returns something other than 0. |
- byte_count = Java_InputStream_readI_AB_I_I( |
- env, jobject_.obj(), buffer, 0, read_size); |
+ while (remaining_length > 0 && !eof) { |
+ const int max_transfer_length = std::min(remaining_length, kBufferSize); |
+ const int transfer_length = Java_InputStream_readI_AB_I_I( |
+ env, jobject_.obj(), buffer, 0, max_transfer_length); |
if (ClearException(env)) |
return false; |
- } while (byte_count == 0); |
- |
- // We've reached the end of the stream. |
- if (byte_count < 0) |
- return true; |
- |
+ eof = (transfer_length < 0); |
+ // Note: it is possible, yet unlikely, that the Java InputStream returns |
+ // a transfer_length == 0 from time to time. In such cases we just continue |
+ // the read until we get either valid data or reach EOF. |
+ if (!eof) { |
joth
2013/09/18 20:06:00
I'd find this easier as:
if (transfer_length < 0)
mkosiba (inactive)
2013/09/18 21:14:17
+1
Primiano Tucci (use gerrit)
2013/09/19 01:01:05
Hmm to be honest I did find a bit more readable ha
|
#ifndef NDEBUG |
- int32_t buffer_length = env->GetArrayLength(buffer); |
- DCHECK_GE(read_size, byte_count); |
- DCHECK_GE(buffer_length, byte_count); |
+ // These DCHECKs are in place to help Chromium developers in case of bugs. |
mkosiba (inactive)
2013/09/18 21:14:17
nit: you can just remove this comment. everyone kn
|
+ DCHECK_GE(max_transfer_length, transfer_length); |
+ DCHECK_GE(env->GetArrayLength(buffer), transfer_length); |
#endif // NDEBUG |
- // The DCHECKs are in place to help Chromium developers in case of bugs, |
- // this check is to prevent a malicious InputStream implementation from |
- // overrunning the |dest| buffer. |
- if (byte_count > read_size) |
- return false; |
- |
- // Copy the data over to the provided C++ side buffer. |
- DCHECK_GE(length, byte_count); |
- env->GetByteArrayRegion(buffer, 0, byte_count, |
- reinterpret_cast<jbyte*>(dest->data() + *bytes_read)); |
- if (ClearException(env)) |
- return false; |
- |
- *bytes_read = byte_count; |
+ // This check is to prevent a malicious InputStream implementation from |
+ // overrunning the |dest| buffer. |
+ if (transfer_length > max_transfer_length) |
+ return false; |
+ |
+ // Copy the data over to the provided C++ IOBuffer. |
+ DCHECK_GE(remaining_length, transfer_length); |
+ env->GetByteArrayRegion(buffer, 0, transfer_length, |
+ reinterpret_cast<jbyte*>(dest_write_ptr)); |
+ if (ClearException(env)) |
+ return false; |
+ remaining_length -= transfer_length; |
+ dest_write_ptr += transfer_length; |
+ } |
+ } |
+ // bytes_read can be strictly less than the req. length if EOF is encountered. |
mkosiba (inactive)
2013/09/18 21:14:17
maybe add yet another DCHECK as well?
DCHECK(byte
|
+ *bytes_read = length - remaining_length; |
return true; |
} |