Merge "Added the subset of partial content support so that we can continue the interrupted request to support streaming the content even with a brief disconnection." into froyo
diff --git a/core/java/android/net/http/Request.java b/core/java/android/net/http/Request.java
index 6dbf325..f1ebb47 100644
--- a/core/java/android/net/http/Request.java
+++ b/core/java/android/net/http/Request.java
@@ -34,6 +34,7 @@
 import org.apache.http.HttpRequest;
 import org.apache.http.HttpResponse;
 import org.apache.http.HttpStatus;
+import org.apache.http.HttpVersion;
 import org.apache.http.ParseException;
 import org.apache.http.ProtocolVersion;
 
@@ -72,6 +73,10 @@
 
     int mFailCount = 0;
 
+    // This will be used to set the Range field if we retry a connection. This
+    // is http/1.1 feature.
+    private int mReceivedBytes = 0;
+
     private InputStream mBodyProvider;
     private int mBodyLength;
 
@@ -241,7 +246,6 @@
 
         StatusLine statusLine = null;
         boolean hasBody = false;
-        boolean reuse = false;
         httpClientConnection.flush();
         int statusCode = 0;
 
@@ -264,6 +268,8 @@
         if (hasBody)
             entity = httpClientConnection.receiveResponseEntity(header);
 
+        boolean supportPartialContent = v.greaterEquals(HttpVersion.HTTP_1_1);
+
         if (entity != null) {
             InputStream is = entity.getContent();
 
@@ -306,6 +312,7 @@
 
                     if (len != -1) {
                         count += len;
+                        if (supportPartialContent) mReceivedBytes += len;
                     }
                     if (len == -1 || count >= lowWater) {
                         if (HttpLog.LOGV) HttpLog.v("Request.readResponse() " + count);
@@ -324,7 +331,13 @@
                 if (HttpLog.LOGV) HttpLog.v( "readResponse() handling " + e);
             } catch(IOException e) {
                 // don't throw if we have a non-OK status code
-                if (statusCode == HttpStatus.SC_OK) {
+                if (statusCode == HttpStatus.SC_OK
+                        || statusCode == HttpStatus.SC_PARTIAL_CONTENT) {
+                    if (supportPartialContent && count > 0) {
+                        // if there is uncommited content, we should commit them
+                        // as we will continue the request
+                        mEventHandler.data(buf, count);
+                    }
                     throw e;
                 }
             } finally {
@@ -411,6 +424,15 @@
             }
             setBodyProvider(mBodyProvider, mBodyLength);
         }
+
+        if (mReceivedBytes > 0) {
+            // reset the fail count as we continue the request
+            mFailCount = 0;
+            // set the "Range" header to indicate that the retry will continue
+            // instead of restarting the request
+            HttpLog.v("*** Request.reset() to range:" + mReceivedBytes);
+            mHttpRequest.setHeader("Range", "bytes=" + mReceivedBytes + "-");
+        }
     }
 
     /**
diff --git a/core/java/android/webkit/LoadListener.java b/core/java/android/webkit/LoadListener.java
index e0f8bc0..e6fa405 100644
--- a/core/java/android/webkit/LoadListener.java
+++ b/core/java/android/webkit/LoadListener.java
@@ -64,6 +64,7 @@
 
     // Standard HTTP status codes in a more representative format
     private static final int HTTP_OK = 200;
+    private static final int HTTP_PARTIAL_CONTENT = 206;
     private static final int HTTP_MOVED_PERMANENTLY = 301;
     private static final int HTTP_FOUND = 302;
     private static final int HTTP_SEE_OTHER = 303;
@@ -328,6 +329,17 @@
     // Does the header parsing work on the WebCore thread.
     private void handleHeaders(Headers headers) {
         if (mCancelled) return;
+
+        // Note: the headers we care in LoadListeners, like
+        // content-type/content-length, should not be updated for partial
+        // content. Just skip here and go ahead with adding data.
+        if (mStatusCode == HTTP_PARTIAL_CONTENT) {
+            // we don't support cache for partial content yet
+            WebViewWorker.getHandler().obtainMessage(
+                    WebViewWorker.MSG_REMOVE_CACHE, this).sendToTarget();
+            return;
+        }
+
         mHeaders = headers;
 
         long contentLength = headers.getContentLength();