Move download requests to the background.

Bug:3189668

Do not create a DownloadHandler since the methods can all be
static.

Do not pass the length to DownloadHandler, since it is no longer
used.

Change-Id: I280160f62906d1acb263b45fde57062210005a0a
diff --git a/src/com/android/browser/Controller.java b/src/com/android/browser/Controller.java
index caaa2c2..63f104a 100644
--- a/src/com/android/browser/Controller.java
+++ b/src/com/android/browser/Controller.java
@@ -139,7 +139,6 @@
     private UrlHandler mUrlHandler;
     private UploadHandler mUploadHandler;
     private IntentHandler mIntentHandler;
-    private DownloadHandler mDownloadHandler;
     private PageDialogsHandler mPageDialogsHandler;
     private NetworkStateHandler mNetworkHandler;
 
@@ -213,7 +212,6 @@
 
         mUrlHandler = new UrlHandler(this);
         mIntentHandler = new IntentHandler(mActivity, this);
-        mDownloadHandler = new DownloadHandler(mActivity);
         mPageDialogsHandler = new PageDialogsHandler(mActivity, this);
 
         PowerManager pm = (PowerManager) mActivity
@@ -405,8 +403,8 @@
                                 break;
                             case R.id.save_link_context_menu_id:
                             case R.id.download_context_menu_id:
-                                mDownloadHandler
-                                    .onDownloadStartNoStream(url, null, null, null, -1);
+                                DownloadHandler.onDownloadStartNoStream(
+                                        mActivity, url, null, null, null);
                                 break;
                         }
                         break;
@@ -909,8 +907,8 @@
     @Override
     public void onDownloadStart(Tab tab, String url, String userAgent,
             String contentDisposition, String mimetype, long contentLength) {
-        mDownloadHandler.onDownloadStart(url, userAgent, contentDisposition,
-                mimetype, contentLength);
+        DownloadHandler.onDownloadStart(mActivity, url, userAgent,
+                contentDisposition, mimetype);
         if (tab.getWebView().copyBackForwardList().getSize() == 0) {
             // This Tab was opened for the sole purpose of downloading a
             // file. Remove it.
@@ -1271,7 +1269,7 @@
                 menu.findItem(R.id.view_image_context_menu_id).setIntent(
                         new Intent(Intent.ACTION_VIEW, Uri.parse(extra)));
                 menu.findItem(R.id.download_context_menu_id).
-                        setOnMenuItemClickListener(new Download(extra));
+                        setOnMenuItemClickListener(new Download(mActivity, extra));
                 menu.findItem(R.id.set_wallpaper_context_menu_id).
                         setOnMenuItemClickListener(new WallpaperHandler(mActivity,
                                 extra));
@@ -1862,15 +1860,18 @@
         }
     }
 
-    private class Download implements OnMenuItemClickListener {
+    private static class Download implements OnMenuItemClickListener {
+        private Activity mActivity;
         private String mText;
 
         public boolean onMenuItemClick(MenuItem item) {
-            mDownloadHandler.onDownloadStartNoStream(mText, null, null, null, -1);
+            DownloadHandler.onDownloadStartNoStream(mActivity, mText, null,
+                    null, null);
             return true;
         }
 
-        public Download(String toDownload) {
+        public Download(Activity activity, String toDownload) {
+            mActivity = activity;
             mText = toDownload;
         }
     }
diff --git a/src/com/android/browser/DownloadHandler.java b/src/com/android/browser/DownloadHandler.java
index b833bd7..cbf26f4 100644
--- a/src/com/android/browser/DownloadHandler.java
+++ b/src/com/android/browser/DownloadHandler.java
@@ -29,6 +29,7 @@
 import android.net.Uri;
 import android.net.WebAddress;
 import android.os.Environment;
+import android.text.TextUtils;
 import android.util.Log;
 import android.webkit.CookieManager;
 import android.webkit.URLUtil;
@@ -44,23 +45,17 @@
 
     private static final String LOGTAG = "DLHandler";
 
-    Activity mActivity;
-
-    public DownloadHandler(Activity activity) {
-        mActivity = activity;
-    }
-
     /**
      * Notify the host application a download should be done, or that
      * the data should be streamed if a streaming viewer is available.
+     * @param activity Activity requesting the download.
      * @param url The full url to the content that should be downloaded
-     * @param contentDisposition Content-disposition http header, if
-     *                           present.
+     * @param userAgent User agent of the downloading application.
+     * @param contentDisposition Content-disposition http header, if present.
      * @param mimetype The mimetype of the content reported by the server
-     * @param contentLength The file size reported by the server
      */
-    public void onDownloadStart(String url, String userAgent,
-            String contentDisposition, String mimetype, long contentLength) {
+    public static void onDownloadStart(Activity activity, String url,
+            String userAgent, String contentDisposition, String mimetype) {
         // if we're dealing wih A/V content that's not explicitly marked
         //     for download, check if it's streamable.
         if (contentDisposition == null
@@ -70,10 +65,10 @@
             //     that matches.
             Intent intent = new Intent(Intent.ACTION_VIEW);
             intent.setDataAndType(Uri.parse(url), mimetype);
-            ResolveInfo info = mActivity.getPackageManager().resolveActivity(intent,
+            ResolveInfo info = activity.getPackageManager().resolveActivity(intent,
                     PackageManager.MATCH_DEFAULT_ONLY);
             if (info != null) {
-                ComponentName myName = mActivity.getComponentName();
+                ComponentName myName = activity.getComponentName();
                 // If we resolved to ourselves, we don't want to attempt to
                 // load the url only to try and download it again.
                 if (!myName.getPackageName().equals(
@@ -83,7 +78,7 @@
                     // someone (other than us) knows how to handle this mime
                     // type with this scheme, don't download.
                     try {
-                        mActivity.startActivity(intent);
+                        activity.startActivity(intent);
                         return;
                     } catch (ActivityNotFoundException ex) {
                         if (LOGD_ENABLED) {
@@ -97,7 +92,8 @@
                 }
             }
         }
-        onDownloadStartNoStream(url, userAgent, contentDisposition, mimetype, contentLength);
+        onDownloadStartNoStream(activity, url, userAgent, contentDisposition,
+                mimetype);
     }
 
     // This is to work around the fact that java.net.URI throws Exceptions
@@ -133,14 +129,15 @@
     /**
      * Notify the host application a download should be done, even if there
      * is a streaming viewer available for thise type.
+     * @param activity Activity requesting the download.
      * @param url The full url to the content that should be downloaded
-     * @param contentDisposition Content-disposition http header, if
-     *                           present.
+     * @param userAgent User agent of the downloading application.
+     * @param contentDisposition Content-disposition http header, if present.
      * @param mimetype The mimetype of the content reported by the server
-     * @param contentLength The file size reported by the server
      */
-    /*package */ void onDownloadStartNoStream(String url, String userAgent,
-            String contentDisposition, String mimetype, long contentLength) {
+    /*package */ static void onDownloadStartNoStream(Activity activity,
+            String url, String userAgent, String contentDisposition,
+            String mimetype) {
 
         String filename = URLUtil.guessFileName(url,
                 contentDisposition, mimetype);
@@ -153,14 +150,14 @@
 
             // Check to see if the SDCard is busy, same as the music app
             if (status.equals(Environment.MEDIA_SHARED)) {
-                msg = mActivity.getString(R.string.download_sdcard_busy_dlg_msg);
+                msg = activity.getString(R.string.download_sdcard_busy_dlg_msg);
                 title = R.string.download_sdcard_busy_dlg_title;
             } else {
-                msg = mActivity.getString(R.string.download_no_sdcard_dlg_msg, filename);
+                msg = activity.getString(R.string.download_no_sdcard_dlg_msg, filename);
                 title = R.string.download_no_sdcard_dlg_title;
             }
 
-            new AlertDialog.Builder(mActivity)
+            new AlertDialog.Builder(activity)
                 .setTitle(title)
                 .setIcon(android.R.drawable.ic_dialog_alert)
                 .setMessage(msg)
@@ -184,34 +181,37 @@
 
         String addressString = webAddress.toString();
         Uri uri = Uri.parse(addressString);
-        DownloadManager.Request request = new DownloadManager.Request(uri);
+        final DownloadManager.Request request = new DownloadManager.Request(uri);
         request.setMimeType(mimetype);
-        request.setDestinationInExternalFilesDir(mActivity, null, filename);
+        request.setDestinationInExternalFilesDir(activity, null, filename);
         // let this downloaded file be scanned by MediaScanner - so that it can 
         // show up in Gallery app, for example.
         request.allowScanningByMediaScanner();
         request.setDescription(webAddress.getHost());
+        // XXX: Have to use the old url since the cookies were stored using the
+        // old percent-encoded url.
         String cookies = CookieManager.getInstance().getCookie(url);
         request.addRequestHeader("cookie", cookies);
         request.setNotificationVisibility(
                 DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
         if (mimetype == null) {
-            ContentValues values = new ContentValues();
-            values.put(FetchUrlMimeType.URI, addressString);
-            // XXX: Have to use the old url since the cookies were stored using the
-            // old percent-encoded url.
-            values.put(FetchUrlMimeType.COOKIE_DATA, cookies);
-            values.put(FetchUrlMimeType.USER_AGENT, userAgent);
-
+            if (TextUtils.isEmpty(addressString)) {
+                return;
+            }
             // We must have long pressed on a link or image to download it. We
             // are not sure of the mimetype in this case, so do a head request
-            new FetchUrlMimeType(mActivity, request).execute(values);
+            new FetchUrlMimeType(activity, request, addressString, cookies,
+                    userAgent).start();
         } else {
-            DownloadManager manager
-                    = (DownloadManager) mActivity.getSystemService(Context.DOWNLOAD_SERVICE);
-            manager.enqueue(request);
+            final DownloadManager manager
+                    = (DownloadManager) activity.getSystemService(Context.DOWNLOAD_SERVICE);
+            new Thread("Browser download") {
+                public void run() {
+                    manager.enqueue(request);
+                }
+            }.start();
         }
-        Toast.makeText(mActivity, R.string.download_pending, Toast.LENGTH_SHORT)
+        Toast.makeText(activity, R.string.download_pending, Toast.LENGTH_SHORT)
                 .show();
     }
 
diff --git a/src/com/android/browser/FetchUrlMimeType.java b/src/com/android/browser/FetchUrlMimeType.java
index 0481806..2538d90 100644
--- a/src/com/android/browser/FetchUrlMimeType.java
+++ b/src/com/android/browser/FetchUrlMimeType.java
@@ -24,11 +24,9 @@
 
 import android.app.Activity;
 import android.app.DownloadManager;
-import android.content.ContentValues;
 import android.content.Context;
 import android.net.Proxy;
 import android.net.http.AndroidHttpClient;
-import android.os.AsyncTask;
 import android.webkit.MimeTypeMap;
 import android.webkit.URLUtil;
 
@@ -37,59 +35,48 @@
 /**
  * This class is used to pull down the http headers of a given URL so that
  * we can analyse the mimetype and make any correction needed before we give
- * the URL to the download manager. The ContentValues class holds the
- * content that would be provided to the download manager, so that on
- * completion of checking the mimetype, we can issue the download to
- * the download manager.
+ * the URL to the download manager.
  * This operation is needed when the user long-clicks on a link or image and
  * we don't know the mimetype. If the user just clicks on the link, we will
  * do the same steps of correcting the mimetype down in
  * android.os.webkit.LoadListener rather than handling it here.
  *
  */
-class FetchUrlMimeType extends AsyncTask<ContentValues, String, ContentValues> {
+class FetchUrlMimeType extends Thread {
 
-    public static final String URI = "uri";
-    public static final String USER_AGENT = "user_agent";
-    public static final String COOKIE_DATA = "cookie_data";
+    private Activity mActivity;
+    private DownloadManager.Request mRequest;
+    private String mUri;
+    private String mCookies;
+    private String mUserAgent;
 
-    Activity mActivity;
-    ContentValues mValues;
-    DownloadManager.Request mRequest;
-
-    public FetchUrlMimeType(Activity activity,
-            DownloadManager.Request request) {
+    public FetchUrlMimeType(Activity activity, DownloadManager.Request request,
+            String uri, String cookies, String userAgent) {
         mActivity = activity;
         mRequest = request;
+        mUri = uri;
+        mCookies = cookies;
+        mUserAgent = userAgent;
     }
 
     @Override
-    public ContentValues doInBackground(ContentValues... values) {
-        mValues = values[0];
-
-        // Check to make sure we have a URI to download
-        String uri = mValues.getAsString(URI);
-        if (uri == null || uri.length() == 0) {
-            return null;
-        }
-
+    public void run() {
         // User agent is likely to be null, though the AndroidHttpClient
         // seems ok with that.
-        AndroidHttpClient client = AndroidHttpClient.newInstance(
-                mValues.getAsString(USER_AGENT));
-        HttpHost httpHost = Proxy.getPreferredHttpHost(mActivity, uri);
+        AndroidHttpClient client = AndroidHttpClient.newInstance(mUserAgent);
+        HttpHost httpHost = Proxy.getPreferredHttpHost(mActivity, mUri);
         if (httpHost != null) {
             ConnRouteParams.setDefaultProxy(client.getParams(), httpHost);
         }
-        HttpHead request = new HttpHead(uri);
+        HttpHead request = new HttpHead(mUri);
 
-        String cookie = mValues.getAsString(COOKIE_DATA);
-        if (cookie != null && cookie.length() > 0) {
-            request.addHeader("Cookie", cookie);
+        if (mCookies != null && mCookies.length() > 0) {
+            request.addHeader("Cookie", mCookies);
         }
 
         HttpResponse response;
-        ContentValues result = new ContentValues();
+        String mimeType = null;
+        String contentDisposition = null;
         try {
             response = client.execute(request);
             // We could get a redirect here, but if we do lets let
@@ -98,16 +85,15 @@
             if (response.getStatusLine().getStatusCode() == 200) {
                 Header header = response.getFirstHeader("Content-Type");
                 if (header != null) {
-                    String mimeType = header.getValue();
+                    mimeType = header.getValue();
                     final int semicolonIndex = mimeType.indexOf(';');
                     if (semicolonIndex != -1) {
                         mimeType = mimeType.substring(0, semicolonIndex);
                     }
-                    result.put("Content-Type", mimeType);
                 }
                 Header contentDispositionHeader = response.getFirstHeader("Content-Disposition");
                 if (contentDispositionHeader != null) {
-                    result.put("Content-Disposition", contentDispositionHeader.getValue());
+                    contentDisposition = contentDispositionHeader.getValue();
                 }
             }
         } catch (IllegalArgumentException ex) {
@@ -118,26 +104,18 @@
             client.close();
         }
 
-        return result;
-    }
-
-   @Override
-    public void onPostExecute(ContentValues values) {
-       final String mimeType = values.getAsString("Content-Type");
-       final String contentDisposition = values.getAsString("Content-Disposition");
        if (mimeType != null) {
-           String url = mValues.getAsString(URI);
            if (mimeType.equalsIgnoreCase("text/plain") ||
                    mimeType.equalsIgnoreCase("application/octet-stream")) {
                String newMimeType =
                        MimeTypeMap.getSingleton().getMimeTypeFromExtension(
-                           MimeTypeMap.getFileExtensionFromUrl(url));
+                           MimeTypeMap.getFileExtensionFromUrl(mUri));
                if (newMimeType != null) {
                    mRequest.setMimeType(newMimeType);
                }
            }
-           String filename = URLUtil.guessFileName(url,
-                   contentDisposition, mimeType);
+           String filename = URLUtil.guessFileName(mUri, contentDisposition,
+                mimeType);
            mRequest.setDestinationInExternalFilesDir(mActivity, null, filename);
        }