Implement file downloads for Chrome HTTP stack (Java side)

This just adds an extra entrypoint to BrowserFrame. It delegates
directly to the identical method in CallbackProxy, and from there
downloads are handled in the same way as before.

See matching C++ change in external/webkit (I81300400)

Change-Id: I87e71debe475d0d24e13a5763fbe803e3cd78cf5
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
index ad5765b..6e588b9 100644
--- a/core/java/android/webkit/BrowserFrame.java
+++ b/core/java/android/webkit/BrowserFrame.java
@@ -1079,6 +1079,20 @@
         mCallbackProxy.onReceivedHttpAuthRequest(handler, host, realm);
     }
 
+    /**
+     * Called by JNI when the native HTTP stack needs to download a file.
+     *
+     * We delegate the request to CallbackProxy, which owns the current app's
+     * DownloadListener.
+     */
+    private void downloadStart(String url, String userAgent,
+            String contentDisposition, String mimeType, long contentLength) {
+        mimeType = MimeTypeMap.getSingleton().remapGenericMimeType(
+                mimeType, url, contentDisposition);
+        mCallbackProxy.onDownloadStart(url, userAgent,
+                contentDisposition, mimeType, contentLength);
+    }
+
     //==========================================================================
     // native functions
     //==========================================================================
diff --git a/core/java/android/webkit/LoadListener.java b/core/java/android/webkit/LoadListener.java
index 92971bd..33f5655 100644
--- a/core/java/android/webkit/LoadListener.java
+++ b/core/java/android/webkit/LoadListener.java
@@ -354,36 +354,8 @@
         String contentType = headers.getContentType();
         if (contentType != null) {
             parseContentTypeHeader(contentType);
-
-            // If we have one of "generic" MIME types, try to deduce
-            // the right MIME type from the file extension (if any):
-            if (mMimeType.equals("text/plain") ||
-                    mMimeType.equals("application/octet-stream")) {
-
-                // for attachment, use the filename in the Content-Disposition
-                // to guess the mimetype
-                String contentDisposition = headers.getContentDisposition();
-                String url = null;
-                if (contentDisposition != null) {
-                    url = URLUtil.parseContentDisposition(contentDisposition);
-                }
-                if (url == null) {
-                    url = mUrl;
-                }
-                String newMimeType = guessMimeTypeFromExtension(url);
-                if (newMimeType != null) {
-                    mMimeType = newMimeType;
-                }
-            } else if (mMimeType.equals("text/vnd.wap.wml")) {
-                // As we don't support wml, render it as plain text
-                mMimeType = "text/plain";
-            } else {
-                // It seems that xhtml+xml and vnd.wap.xhtml+xml mime
-                // subtypes are used interchangeably. So treat them the same.
-                if (mMimeType.equals("application/vnd.wap.xhtml+xml")) {
-                    mMimeType = "application/xhtml+xml";
-                }
-            }
+            mMimeType = MimeTypeMap.getSingleton().remapGenericMimeType(
+                    mMimeType, mUrl, headers.getContentDisposition());
         } else {
             /* Often when servers respond with 304 Not Modified or a
                Redirect, then they don't specify a MIMEType. When this
diff --git a/core/java/android/webkit/MimeTypeMap.java b/core/java/android/webkit/MimeTypeMap.java
index f00005b..ecce2ce 100644
--- a/core/java/android/webkit/MimeTypeMap.java
+++ b/core/java/android/webkit/MimeTypeMap.java
@@ -109,6 +109,50 @@
     }
 
     /**
+     * If the given MIME type is null, or one of the "generic" types (text/plain
+     * or application/octet-stream) map it to a type that Android can deal with.
+     * If the given type is not generic, return it unchanged.
+     *
+     * @param mimeType MIME type provided by the server.
+     * @param url URL of the data being loaded.
+     * @param contentDisposition Content-disposition header given by the server.
+     * @return The MIME type that should be used for this data.
+     */
+    /* package */ String remapGenericMimeType(String mimeType, String url,
+            String contentDisposition) {
+        // If we have one of "generic" MIME types, try to deduce
+        // the right MIME type from the file extension (if any):
+        if ("text/plain".equals(mimeType) ||
+                "application/octet-stream".equals(mimeType)) {
+
+            // for attachment, use the filename in the Content-Disposition
+            // to guess the mimetype
+            String filename = null;
+            if (contentDisposition != null) {
+                filename = URLUtil.parseContentDisposition(contentDisposition);
+            }
+            if (filename != null) {
+                url = filename;
+            }
+            String extension = getFileExtensionFromUrl(url);
+            String newMimeType = getMimeTypeFromExtension(extension);
+            if (newMimeType != null) {
+                mimeType = newMimeType;
+            }
+        } else if ("text/vnd.wap.wml".equals(mimeType)) {
+            // As we don't support wml, render it as plain text
+            mimeType = "text/plain";
+        } else {
+            // It seems that xhtml+xml and vnd.wap.xhtml+xml mime
+            // subtypes are used interchangeably. So treat them the same.
+            if ("application/vnd.wap.xhtml+xml".equals(mimeType)) {
+                mimeType = "application/xhtml+xml";
+            }
+        }
+        return mimeType;
+    }
+
+    /**
      * Get the singleton instance of MimeTypeMap.
      * @return The singleton instance of the MIME-type map.
      */