18233facddcc51865d612a919d450db6954aa48e3Michael Kolb/*
28233facddcc51865d612a919d450db6954aa48e3Michael Kolb * Copyright (C) 2010 The Android Open Source Project
38233facddcc51865d612a919d450db6954aa48e3Michael Kolb *
48233facddcc51865d612a919d450db6954aa48e3Michael Kolb * Licensed under the Apache License, Version 2.0 (the "License");
58233facddcc51865d612a919d450db6954aa48e3Michael Kolb * you may not use this file except in compliance with the License.
68233facddcc51865d612a919d450db6954aa48e3Michael Kolb * You may obtain a copy of the License at
78233facddcc51865d612a919d450db6954aa48e3Michael Kolb *
88233facddcc51865d612a919d450db6954aa48e3Michael Kolb *      http://www.apache.org/licenses/LICENSE-2.0
98233facddcc51865d612a919d450db6954aa48e3Michael Kolb *
108233facddcc51865d612a919d450db6954aa48e3Michael Kolb * Unless required by applicable law or agreed to in writing, software
118233facddcc51865d612a919d450db6954aa48e3Michael Kolb * distributed under the License is distributed on an "AS IS" BASIS,
128233facddcc51865d612a919d450db6954aa48e3Michael Kolb * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138233facddcc51865d612a919d450db6954aa48e3Michael Kolb * See the License for the specific language governing permissions and
148233facddcc51865d612a919d450db6954aa48e3Michael Kolb * limitations under the License.
158233facddcc51865d612a919d450db6954aa48e3Michael Kolb */
168233facddcc51865d612a919d450db6954aa48e3Michael Kolb
178233facddcc51865d612a919d450db6954aa48e3Michael Kolbpackage com.android.browser;
188233facddcc51865d612a919d450db6954aa48e3Michael Kolb
198233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.app.Activity;
208233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.app.AlertDialog;
218233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.app.DownloadManager;
228233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.content.ActivityNotFoundException;
238233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.content.ComponentName;
248233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.content.Context;
258233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.content.Intent;
268233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.content.pm.PackageManager;
278233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.content.pm.ResolveInfo;
288233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.net.Uri;
298233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.net.WebAddress;
308233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.os.Environment;
3163c0266b5d1fca4df859fe4fa3a9555d0783a2b6Leon Scrogginsimport android.text.TextUtils;
328233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.util.Log;
338233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.webkit.CookieManager;
348233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.webkit.URLUtil;
358233facddcc51865d612a919d450db6954aa48e3Michael Kolbimport android.widget.Toast;
368233facddcc51865d612a919d450db6954aa48e3Michael Kolb
378233facddcc51865d612a919d450db6954aa48e3Michael Kolb/**
388233facddcc51865d612a919d450db6954aa48e3Michael Kolb * Handle download requests
398233facddcc51865d612a919d450db6954aa48e3Michael Kolb */
408233facddcc51865d612a919d450db6954aa48e3Michael Kolbpublic class DownloadHandler {
418233facddcc51865d612a919d450db6954aa48e3Michael Kolb
428233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private static final boolean LOGD_ENABLED =
438233facddcc51865d612a919d450db6954aa48e3Michael Kolb            com.android.browser.Browser.LOGD_ENABLED;
448233facddcc51865d612a919d450db6954aa48e3Michael Kolb
458233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private static final String LOGTAG = "DLHandler";
468233facddcc51865d612a919d450db6954aa48e3Michael Kolb
478233facddcc51865d612a919d450db6954aa48e3Michael Kolb    /**
488233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * Notify the host application a download should be done, or that
498233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * the data should be streamed if a streaming viewer is available.
5063c0266b5d1fca4df859fe4fa3a9555d0783a2b6Leon Scroggins     * @param activity Activity requesting the download.
518233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * @param url The full url to the content that should be downloaded
5263c0266b5d1fca4df859fe4fa3a9555d0783a2b6Leon Scroggins     * @param userAgent User agent of the downloading application.
5363c0266b5d1fca4df859fe4fa3a9555d0783a2b6Leon Scroggins     * @param contentDisposition Content-disposition http header, if present.
548233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * @param mimetype The mimetype of the content reported by the server
550b3d66fc2275fb5270cb7166cc991be7dc9d8ff7Selim Gurun     * @param referer The referer associated with the downloaded url
56bc5cc75c302eb49d15258155fc6f672fcbd62842Kristian Monsen     * @param privateBrowsing If the request is coming from a private browsing tab.
578233facddcc51865d612a919d450db6954aa48e3Michael Kolb     */
5863c0266b5d1fca4df859fe4fa3a9555d0783a2b6Leon Scroggins    public static void onDownloadStart(Activity activity, String url,
59bc5cc75c302eb49d15258155fc6f672fcbd62842Kristian Monsen            String userAgent, String contentDisposition, String mimetype,
600b3d66fc2275fb5270cb7166cc991be7dc9d8ff7Selim Gurun            String referer, boolean privateBrowsing) {
618233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // if we're dealing wih A/V content that's not explicitly marked
628233facddcc51865d612a919d450db6954aa48e3Michael Kolb        //     for download, check if it's streamable.
638233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (contentDisposition == null
648233facddcc51865d612a919d450db6954aa48e3Michael Kolb                || !contentDisposition.regionMatches(
658233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        true, 0, "attachment", 0, 10)) {
668233facddcc51865d612a919d450db6954aa48e3Michael Kolb            // query the package manager to see if there's a registered handler
678233facddcc51865d612a919d450db6954aa48e3Michael Kolb            //     that matches.
688233facddcc51865d612a919d450db6954aa48e3Michael Kolb            Intent intent = new Intent(Intent.ACTION_VIEW);
698233facddcc51865d612a919d450db6954aa48e3Michael Kolb            intent.setDataAndType(Uri.parse(url), mimetype);
7063c0266b5d1fca4df859fe4fa3a9555d0783a2b6Leon Scroggins            ResolveInfo info = activity.getPackageManager().resolveActivity(intent,
718233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    PackageManager.MATCH_DEFAULT_ONLY);
728233facddcc51865d612a919d450db6954aa48e3Michael Kolb            if (info != null) {
7363c0266b5d1fca4df859fe4fa3a9555d0783a2b6Leon Scroggins                ComponentName myName = activity.getComponentName();
748233facddcc51865d612a919d450db6954aa48e3Michael Kolb                // If we resolved to ourselves, we don't want to attempt to
758233facddcc51865d612a919d450db6954aa48e3Michael Kolb                // load the url only to try and download it again.
768233facddcc51865d612a919d450db6954aa48e3Michael Kolb                if (!myName.getPackageName().equals(
778233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        info.activityInfo.packageName)
788233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        || !myName.getClassName().equals(
798233facddcc51865d612a919d450db6954aa48e3Michael Kolb                                info.activityInfo.name)) {
808233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    // someone (other than us) knows how to handle this mime
818233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    // type with this scheme, don't download.
828233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    try {
8363c0266b5d1fca4df859fe4fa3a9555d0783a2b6Leon Scroggins                        activity.startActivity(intent);
848233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        return;
858233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    } catch (ActivityNotFoundException ex) {
868233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        if (LOGD_ENABLED) {
878233facddcc51865d612a919d450db6954aa48e3Michael Kolb                            Log.d(LOGTAG, "activity not found for " + mimetype
888233facddcc51865d612a919d450db6954aa48e3Michael Kolb                                    + " over " + Uri.parse(url).getScheme(),
898233facddcc51865d612a919d450db6954aa48e3Michael Kolb                                    ex);
908233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        }
918233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        // Best behavior is to fall back to a download in this
928233facddcc51865d612a919d450db6954aa48e3Michael Kolb                        // case
938233facddcc51865d612a919d450db6954aa48e3Michael Kolb                    }
948233facddcc51865d612a919d450db6954aa48e3Michael Kolb                }
958233facddcc51865d612a919d450db6954aa48e3Michael Kolb            }
968233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
9763c0266b5d1fca4df859fe4fa3a9555d0783a2b6Leon Scroggins        onDownloadStartNoStream(activity, url, userAgent, contentDisposition,
980b3d66fc2275fb5270cb7166cc991be7dc9d8ff7Selim Gurun                mimetype, referer, privateBrowsing);
998233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
1008233facddcc51865d612a919d450db6954aa48e3Michael Kolb
1018233facddcc51865d612a919d450db6954aa48e3Michael Kolb    // This is to work around the fact that java.net.URI throws Exceptions
1028233facddcc51865d612a919d450db6954aa48e3Michael Kolb    // instead of just encoding URL's properly
1038233facddcc51865d612a919d450db6954aa48e3Michael Kolb    // Helper method for onDownloadStartNoStream
1048233facddcc51865d612a919d450db6954aa48e3Michael Kolb    private static String encodePath(String path) {
1058233facddcc51865d612a919d450db6954aa48e3Michael Kolb        char[] chars = path.toCharArray();
1068233facddcc51865d612a919d450db6954aa48e3Michael Kolb
1078233facddcc51865d612a919d450db6954aa48e3Michael Kolb        boolean needed = false;
1088233facddcc51865d612a919d450db6954aa48e3Michael Kolb        for (char c : chars) {
109a770f8d4bd583e9a719af6ce314838db12003b33Selim Gurun            if (c == '[' || c == ']' || c == '|') {
1108233facddcc51865d612a919d450db6954aa48e3Michael Kolb                needed = true;
1118233facddcc51865d612a919d450db6954aa48e3Michael Kolb                break;
1128233facddcc51865d612a919d450db6954aa48e3Michael Kolb            }
1138233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
1148233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (needed == false) {
1158233facddcc51865d612a919d450db6954aa48e3Michael Kolb            return path;
1168233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
1178233facddcc51865d612a919d450db6954aa48e3Michael Kolb
1188233facddcc51865d612a919d450db6954aa48e3Michael Kolb        StringBuilder sb = new StringBuilder("");
1198233facddcc51865d612a919d450db6954aa48e3Michael Kolb        for (char c : chars) {
120a770f8d4bd583e9a719af6ce314838db12003b33Selim Gurun            if (c == '[' || c == ']' || c == '|') {
1218233facddcc51865d612a919d450db6954aa48e3Michael Kolb                sb.append('%');
1228233facddcc51865d612a919d450db6954aa48e3Michael Kolb                sb.append(Integer.toHexString(c));
1238233facddcc51865d612a919d450db6954aa48e3Michael Kolb            } else {
1248233facddcc51865d612a919d450db6954aa48e3Michael Kolb                sb.append(c);
1258233facddcc51865d612a919d450db6954aa48e3Michael Kolb            }
1268233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
1278233facddcc51865d612a919d450db6954aa48e3Michael Kolb
1288233facddcc51865d612a919d450db6954aa48e3Michael Kolb        return sb.toString();
1298233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
1308233facddcc51865d612a919d450db6954aa48e3Michael Kolb
1318233facddcc51865d612a919d450db6954aa48e3Michael Kolb    /**
1328233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * Notify the host application a download should be done, even if there
1338233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * is a streaming viewer available for thise type.
13463c0266b5d1fca4df859fe4fa3a9555d0783a2b6Leon Scroggins     * @param activity Activity requesting the download.
1358233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * @param url The full url to the content that should be downloaded
13663c0266b5d1fca4df859fe4fa3a9555d0783a2b6Leon Scroggins     * @param userAgent User agent of the downloading application.
13763c0266b5d1fca4df859fe4fa3a9555d0783a2b6Leon Scroggins     * @param contentDisposition Content-disposition http header, if present.
1388233facddcc51865d612a919d450db6954aa48e3Michael Kolb     * @param mimetype The mimetype of the content reported by the server
1390b3d66fc2275fb5270cb7166cc991be7dc9d8ff7Selim Gurun     * @param referer The referer associated with the downloaded url
140bc5cc75c302eb49d15258155fc6f672fcbd62842Kristian Monsen     * @param privateBrowsing If the request is coming from a private browsing tab.
1418233facddcc51865d612a919d450db6954aa48e3Michael Kolb     */
14263c0266b5d1fca4df859fe4fa3a9555d0783a2b6Leon Scroggins    /*package */ static void onDownloadStartNoStream(Activity activity,
14363c0266b5d1fca4df859fe4fa3a9555d0783a2b6Leon Scroggins            String url, String userAgent, String contentDisposition,
1440b3d66fc2275fb5270cb7166cc991be7dc9d8ff7Selim Gurun            String mimetype, String referer, boolean privateBrowsing) {
1458233facddcc51865d612a919d450db6954aa48e3Michael Kolb
1468233facddcc51865d612a919d450db6954aa48e3Michael Kolb        String filename = URLUtil.guessFileName(url,
1478233facddcc51865d612a919d450db6954aa48e3Michael Kolb                contentDisposition, mimetype);
1488233facddcc51865d612a919d450db6954aa48e3Michael Kolb
1498233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // Check to see if we have an SDCard
1508233facddcc51865d612a919d450db6954aa48e3Michael Kolb        String status = Environment.getExternalStorageState();
1518233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (!status.equals(Environment.MEDIA_MOUNTED)) {
1528233facddcc51865d612a919d450db6954aa48e3Michael Kolb            int title;
1538233facddcc51865d612a919d450db6954aa48e3Michael Kolb            String msg;
1548233facddcc51865d612a919d450db6954aa48e3Michael Kolb
1558233facddcc51865d612a919d450db6954aa48e3Michael Kolb            // Check to see if the SDCard is busy, same as the music app
1568233facddcc51865d612a919d450db6954aa48e3Michael Kolb            if (status.equals(Environment.MEDIA_SHARED)) {
15763c0266b5d1fca4df859fe4fa3a9555d0783a2b6Leon Scroggins                msg = activity.getString(R.string.download_sdcard_busy_dlg_msg);
1588233facddcc51865d612a919d450db6954aa48e3Michael Kolb                title = R.string.download_sdcard_busy_dlg_title;
1598233facddcc51865d612a919d450db6954aa48e3Michael Kolb            } else {
16063c0266b5d1fca4df859fe4fa3a9555d0783a2b6Leon Scroggins                msg = activity.getString(R.string.download_no_sdcard_dlg_msg, filename);
1618233facddcc51865d612a919d450db6954aa48e3Michael Kolb                title = R.string.download_no_sdcard_dlg_title;
1628233facddcc51865d612a919d450db6954aa48e3Michael Kolb            }
1638233facddcc51865d612a919d450db6954aa48e3Michael Kolb
16463c0266b5d1fca4df859fe4fa3a9555d0783a2b6Leon Scroggins            new AlertDialog.Builder(activity)
1658233facddcc51865d612a919d450db6954aa48e3Michael Kolb                .setTitle(title)
1662aa8ba254d128ca75f97a62b8d48d1305183e93cBjörn Lundén                .setIconAttribute(android.R.attr.alertDialogIcon)
1678233facddcc51865d612a919d450db6954aa48e3Michael Kolb                .setMessage(msg)
1688233facddcc51865d612a919d450db6954aa48e3Michael Kolb                .setPositiveButton(R.string.ok, null)
1698233facddcc51865d612a919d450db6954aa48e3Michael Kolb                .show();
1708233facddcc51865d612a919d450db6954aa48e3Michael Kolb            return;
1718233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
1728233facddcc51865d612a919d450db6954aa48e3Michael Kolb
1738233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // java.net.URI is a lot stricter than KURL so we have to encode some
1748233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // extra characters. Fix for b 2538060 and b 1634719
1758233facddcc51865d612a919d450db6954aa48e3Michael Kolb        WebAddress webAddress;
1768233facddcc51865d612a919d450db6954aa48e3Michael Kolb        try {
1778233facddcc51865d612a919d450db6954aa48e3Michael Kolb            webAddress = new WebAddress(url);
1788233facddcc51865d612a919d450db6954aa48e3Michael Kolb            webAddress.setPath(encodePath(webAddress.getPath()));
1798233facddcc51865d612a919d450db6954aa48e3Michael Kolb        } catch (Exception e) {
1808233facddcc51865d612a919d450db6954aa48e3Michael Kolb            // This only happens for very bad urls, we want to chatch the
1818233facddcc51865d612a919d450db6954aa48e3Michael Kolb            // exception here
1828233facddcc51865d612a919d450db6954aa48e3Michael Kolb            Log.e(LOGTAG, "Exception trying to parse url:" + url);
1838233facddcc51865d612a919d450db6954aa48e3Michael Kolb            return;
1848233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
1858233facddcc51865d612a919d450db6954aa48e3Michael Kolb
1868233facddcc51865d612a919d450db6954aa48e3Michael Kolb        String addressString = webAddress.toString();
1878233facddcc51865d612a919d450db6954aa48e3Michael Kolb        Uri uri = Uri.parse(addressString);
18811e309c58cfbbd2d0d02c0262ad6161fc9ba01ebLeon Scroggins        final DownloadManager.Request request;
18911e309c58cfbbd2d0d02c0262ad6161fc9ba01ebLeon Scroggins        try {
19011e309c58cfbbd2d0d02c0262ad6161fc9ba01ebLeon Scroggins            request = new DownloadManager.Request(uri);
19111e309c58cfbbd2d0d02c0262ad6161fc9ba01ebLeon Scroggins        } catch (IllegalArgumentException e) {
19211e309c58cfbbd2d0d02c0262ad6161fc9ba01ebLeon Scroggins            Toast.makeText(activity, R.string.cannot_download, Toast.LENGTH_SHORT).show();
19311e309c58cfbbd2d0d02c0262ad6161fc9ba01ebLeon Scroggins            return;
19411e309c58cfbbd2d0d02c0262ad6161fc9ba01ebLeon Scroggins        }
1958233facddcc51865d612a919d450db6954aa48e3Michael Kolb        request.setMimeType(mimetype);
196c2df8342039829c868b30ad3bc3f865e26a04b1cVasu Nori        // set downloaded file destination to /sdcard/Download.
197c2df8342039829c868b30ad3bc3f865e26a04b1cVasu Nori        // or, should it be set to one of several Environment.DIRECTORY* dirs depending on mimetype?
198c2df8342039829c868b30ad3bc3f865e26a04b1cVasu Nori        request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, filename);
1998233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // let this downloaded file be scanned by MediaScanner - so that it can
2008233facddcc51865d612a919d450db6954aa48e3Michael Kolb        // show up in Gallery app, for example.
2018233facddcc51865d612a919d450db6954aa48e3Michael Kolb        request.allowScanningByMediaScanner();
2028233facddcc51865d612a919d450db6954aa48e3Michael Kolb        request.setDescription(webAddress.getHost());
20363c0266b5d1fca4df859fe4fa3a9555d0783a2b6Leon Scroggins        // XXX: Have to use the old url since the cookies were stored using the
20463c0266b5d1fca4df859fe4fa3a9555d0783a2b6Leon Scroggins        // old percent-encoded url.
205bc5cc75c302eb49d15258155fc6f672fcbd62842Kristian Monsen        String cookies = CookieManager.getInstance().getCookie(url, privateBrowsing);
2068233facddcc51865d612a919d450db6954aa48e3Michael Kolb        request.addRequestHeader("cookie", cookies);
207d0fc5898276ba5a02c7b8761065040d0a545cac4Patrik Stenkilsson        request.addRequestHeader("User-Agent", userAgent);
2080b3d66fc2275fb5270cb7166cc991be7dc9d8ff7Selim Gurun        request.addRequestHeader("Referer", referer);
2098233facddcc51865d612a919d450db6954aa48e3Michael Kolb        request.setNotificationVisibility(
2108233facddcc51865d612a919d450db6954aa48e3Michael Kolb                DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
2118233facddcc51865d612a919d450db6954aa48e3Michael Kolb        if (mimetype == null) {
21263c0266b5d1fca4df859fe4fa3a9555d0783a2b6Leon Scroggins            if (TextUtils.isEmpty(addressString)) {
21363c0266b5d1fca4df859fe4fa3a9555d0783a2b6Leon Scroggins                return;
21463c0266b5d1fca4df859fe4fa3a9555d0783a2b6Leon Scroggins            }
2158233facddcc51865d612a919d450db6954aa48e3Michael Kolb            // We must have long pressed on a link or image to download it. We
2168233facddcc51865d612a919d450db6954aa48e3Michael Kolb            // are not sure of the mimetype in this case, so do a head request
21763c0266b5d1fca4df859fe4fa3a9555d0783a2b6Leon Scroggins            new FetchUrlMimeType(activity, request, addressString, cookies,
21863c0266b5d1fca4df859fe4fa3a9555d0783a2b6Leon Scroggins                    userAgent).start();
2198233facddcc51865d612a919d450db6954aa48e3Michael Kolb        } else {
22063c0266b5d1fca4df859fe4fa3a9555d0783a2b6Leon Scroggins            final DownloadManager manager
22163c0266b5d1fca4df859fe4fa3a9555d0783a2b6Leon Scroggins                    = (DownloadManager) activity.getSystemService(Context.DOWNLOAD_SERVICE);
22263c0266b5d1fca4df859fe4fa3a9555d0783a2b6Leon Scroggins            new Thread("Browser download") {
22363c0266b5d1fca4df859fe4fa3a9555d0783a2b6Leon Scroggins                public void run() {
22463c0266b5d1fca4df859fe4fa3a9555d0783a2b6Leon Scroggins                    manager.enqueue(request);
22563c0266b5d1fca4df859fe4fa3a9555d0783a2b6Leon Scroggins                }
22663c0266b5d1fca4df859fe4fa3a9555d0783a2b6Leon Scroggins            }.start();
2278233facddcc51865d612a919d450db6954aa48e3Michael Kolb        }
22863c0266b5d1fca4df859fe4fa3a9555d0783a2b6Leon Scroggins        Toast.makeText(activity, R.string.download_pending, Toast.LENGTH_SHORT)
2298233facddcc51865d612a919d450db6954aa48e3Michael Kolb                .show();
2308233facddcc51865d612a919d450db6954aa48e3Michael Kolb    }
2318233facddcc51865d612a919d450db6954aa48e3Michael Kolb
2328233facddcc51865d612a919d450db6954aa48e3Michael Kolb}
233