Change SWE app properties back to stock Android

- Changed project package name from com.android.swe.browser
back to com.android.browser along with code references to
old package name.
- Changes to AndroidManifest making it conform closer to stock
browser manifest.
- Changed app and apk name back to Browser.

Change-Id: I778ee1d1197bd50bd4a4850eef6d1d7f4ef0ad0b
diff --git a/src/com/android/browser/DownloadHandler.java b/src/com/android/browser/DownloadHandler.java
new file mode 100644
index 0000000..65c5f85
--- /dev/null
+++ b/src/com/android/browser/DownloadHandler.java
@@ -0,0 +1,629 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.browser;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.app.DownloadManager;
+import android.app.DownloadManager.Request;
+import android.content.ActivityNotFoundException;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Environment;
+import android.os.StatFs;
+import android.os.storage.StorageManager;
+import android.util.Log;
+import org.codeaurora.swe.CookieManager;
+import android.webkit.URLUtil;
+import android.widget.Toast;
+
+import com.android.browser.R;
+import com.android.browser.platformsupport.WebAddress;
+import com.android.browser.reflect.ReflectHelper;
+
+import java.io.File;
+/**
+ * Handle download requests
+ */
+public class DownloadHandler {
+
+    private static final boolean LOGD_ENABLED =
+            com.android.browser.Browser.LOGD_ENABLED;
+
+    private static final String LOGTAG = "DLHandler";
+    private static String mInternalStorage;
+    private static String mExternalStorage;
+    private final static String INVALID_PATH = "/storage";
+
+    public static void startingDownload(Activity activity,
+            String url, String userAgent, String contentDisposition,
+            String mimetype, String referer, boolean privateBrowsing, long contentLength,
+            String filename, String downloadPath) {
+        // java.net.URI is a lot stricter than KURL so we have to encode some
+        // extra characters. Fix for b 2538060 and b 1634719
+        WebAddress webAddress;
+        try {
+            webAddress = new WebAddress(url);
+            webAddress.setPath(encodePath(webAddress.getPath()));
+        } catch (Exception e) {
+            // This only happens for very bad urls, we want to chatch the
+            // exception here
+            Log.e(LOGTAG, "Exception trying to parse url:" + url);
+            return;
+        }
+
+        String addressString = webAddress.toString();
+        Uri uri = Uri.parse(addressString);
+        final DownloadManager.Request request;
+        try {
+            request = new DownloadManager.Request(uri);
+        } catch (IllegalArgumentException e) {
+            Toast.makeText(activity, R.string.cannot_download, Toast.LENGTH_SHORT).show();
+            return;
+        }
+        request.setMimeType(mimetype);
+        // set downloaded file destination to /sdcard/Download.
+        // or, should it be set to one of several Environment.DIRECTORY* dirs
+        // depending on mimetype?
+        try {
+            setDestinationDir(downloadPath, filename, request);
+        } catch (Exception e) {
+            showNoEnoughMemoryDialog(activity);
+            return;
+        }
+        // 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, privateBrowsing);
+        request.addRequestHeader("cookie", cookies);
+        request.addRequestHeader("User-Agent", userAgent);
+        request.addRequestHeader("Referer", referer);
+        request.setNotificationVisibility(
+                DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
+        final DownloadManager manager = (DownloadManager) activity
+                .getSystemService(Context.DOWNLOAD_SERVICE);
+        new Thread("Browser download") {
+            public void run() {
+                manager.enqueue(request);
+            }
+        }.start();
+        showStartDownloadToast(activity);
+    }
+
+    private static boolean isAudioFileType(int fileType){
+        Object[] params  = {Integer.valueOf(fileType)};
+        Class[] type = new Class[] {int.class};
+        Boolean result = (Boolean) ReflectHelper.invokeStaticMethod("android.media.MediaFile",
+                               "isAudioFileType", type, params);
+        return result;
+    }
+
+    private static boolean isVideoFileType(int fileType){
+        Object[] params  = {Integer.valueOf(fileType)};
+        Class[] type = new Class[] {int.class};
+        Boolean result = (Boolean) ReflectHelper.invokeStaticMethod("android.media.MediaFile",
+                             "isVideoFileType", type, params);
+        return result;
+    }
+
+    /**
+     * 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 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 referer The referer associated with the downloaded url
+     * @param privateBrowsing If the request is coming from a private browsing tab.
+     */
+    public static boolean onDownloadStart(final Activity activity, final String url,
+            final String userAgent, final String contentDisposition, final String mimetype,
+            final String referer, final boolean privateBrowsing, final long contentLength) {
+        // if we're dealing wih A/V content that's not explicitly marked
+        //     for download, check if it's streamable.
+        if (contentDisposition == null
+                || !contentDisposition.regionMatches(
+                        true, 0, "attachment", 0, 10)) {
+            // Add for Carrier Feature - When open an audio/video link, prompt a dialog
+            // to let the user choose play or download operation.
+            Uri uri = Uri.parse(url);
+            String scheme = uri.getScheme();
+            Log.v(LOGTAG, "scheme:" + scheme + ", mimetype:" + mimetype);
+            // Some mimetype for audio/video files is not started with "audio" or "video",
+            // such as ogg audio file with mimetype "application/ogg". So we also check
+            // file type by MediaFile.isAudioFileType() and MediaFile.isVideoFileType().
+            // For those file types other than audio or video, download it immediately.
+            Object[] params = {mimetype};
+            Class[] type = new Class[] {String.class};
+            Integer result = (Integer) ReflectHelper.invokeStaticMethod("android.media.MediaFile",
+                                           "getFileTypeForMimeType", type, params);
+            int fileType = result.intValue();
+            if ("http".equalsIgnoreCase(scheme) &&
+                    (mimetype.startsWith("audio/") ||
+                        mimetype.startsWith("video/") ||
+                            isAudioFileType(fileType) ||
+                                isVideoFileType(fileType))) {
+                new AlertDialog.Builder(activity)
+                .setTitle(R.string.application_name)
+                .setIcon(R.drawable.default_video_poster)
+                .setMessage(R.string.http_video_msg)
+                .setPositiveButton(R.string.video_save, new DialogInterface.OnClickListener() {
+                    public void onClick(DialogInterface dialog, int which) {
+                        onDownloadStartNoStream(activity, url, userAgent, contentDisposition,
+                                mimetype, referer, privateBrowsing, contentLength);
+                    }
+                 })
+                .setNegativeButton(R.string.video_play, new DialogInterface.OnClickListener() {
+                    public void onClick(DialogInterface dialog, int which) {
+                        Intent intent = new Intent(Intent.ACTION_VIEW);
+                        intent.setDataAndType(Uri.parse(url), mimetype);
+                        try {
+                            String title = URLUtil.guessFileName(url, contentDisposition, mimetype);
+                            intent.putExtra(Intent.EXTRA_TITLE, title);
+                            activity.startActivity(intent);
+                        } catch (ActivityNotFoundException ex) {
+                            Log.w(LOGTAG, "When http stream play, activity not found for "
+                                    + mimetype + " over " + Uri.parse(url).getScheme(), ex);
+                        }
+                    }
+                }).show();
+
+                return true;
+            }
+            // query the package manager to see if there's a registered handler
+            //     that matches.
+            Intent intent = new Intent(Intent.ACTION_VIEW);
+            intent.setDataAndType(Uri.parse(url), mimetype);
+            ResolveInfo info = activity.getPackageManager().resolveActivity(intent,
+                    PackageManager.MATCH_DEFAULT_ONLY);
+            if (info != null) {
+                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(
+                        info.activityInfo.packageName)
+                        || !myName.getClassName().equals(
+                                info.activityInfo.name)) {
+                    // someone (other than us) knows how to handle this mime
+                    // type with this scheme, don't download.
+                    try {
+                        activity.startActivity(intent);
+                        return false;
+                    } catch (ActivityNotFoundException ex) {
+                        if (LOGD_ENABLED) {
+                            Log.d(LOGTAG, "activity not found for " + mimetype
+                                    + " over " + Uri.parse(url).getScheme(),
+                                    ex);
+                        }
+                        // Best behavior is to fall back to a download in this
+                        // case
+                    }
+                }
+            }
+        }
+        onDownloadStartNoStream(activity, url, userAgent, contentDisposition,
+                mimetype, referer, privateBrowsing, contentLength);
+        return false;
+    }
+
+    // This is to work around the fact that java.net.URI throws Exceptions
+    // instead of just encoding URL's properly
+    // Helper method for onDownloadStartNoStream
+    private static String encodePath(String path) {
+        char[] chars = path.toCharArray();
+
+        boolean needed = false;
+        for (char c : chars) {
+            if (c == '[' || c == ']' || c == '|') {
+                needed = true;
+                break;
+            }
+        }
+        if (needed == false) {
+            return path;
+        }
+
+        StringBuilder sb = new StringBuilder("");
+        for (char c : chars) {
+            if (c == '[' || c == ']' || c == '|') {
+                sb.append('%');
+                sb.append(Integer.toHexString(c));
+            } else {
+                sb.append(c);
+            }
+        }
+
+        return sb.toString();
+    }
+
+    /**
+     * 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 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 referer The referer associated with the downloaded url
+     * @param privateBrowsing If the request is coming from a private browsing tab.
+     */
+    /* package */static void onDownloadStartNoStream(Activity activity,
+            String url, String userAgent, String contentDisposition,
+            String mimetype, String referer, boolean privateBrowsing, long contentLength) {
+
+        initStorageDefaultPath(activity);
+        String filename = URLUtil.guessFileName(url,
+                contentDisposition, mimetype);
+
+        // Check to see if we have an SDCard
+        String status = Environment.getExternalStorageState();
+        if (!status.equals(Environment.MEDIA_MOUNTED)) {
+            int title;
+            String msg;
+
+            // Check to see if the SDCard is busy, same as the music app
+            if (status.equals(Environment.MEDIA_SHARED)) {
+                msg = activity.getString(R.string.download_sdcard_busy_dlg_msg);
+                title = R.string.download_sdcard_busy_dlg_title;
+            } else {
+                msg = activity.getString(R.string.download_no_sdcard_dlg_msg, filename);
+                title = R.string.download_no_sdcard_dlg_title;
+            }
+
+            new AlertDialog.Builder(activity)
+                .setTitle(title)
+                .setIconAttribute(android.R.attr.alertDialogIcon)
+                .setMessage(msg)
+                .setPositiveButton(R.string.ok, null)
+                .show();
+            return;
+        }
+
+        if (mimetype == null) {
+            // 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(activity, url, userAgent, referer,
+                    privateBrowsing, filename).start();
+        } else {
+            startDownloadSettings(activity, url, userAgent, contentDisposition, mimetype, referer,
+                    privateBrowsing, contentLength, filename);
+        }
+
+    }
+
+    public static void initStorageDefaultPath(Context context) {
+        mExternalStorage = getExternalStorageDirectory(context);
+        if (isPhoneStorageSupported()) {
+            mInternalStorage = Environment.getExternalStorageDirectory().getPath();
+        } else {
+            mInternalStorage = null;
+        }
+    }
+
+    public static void startDownloadSettings(Activity activity,
+            String url, String userAgent, String contentDisposition,
+            String mimetype, String referer, boolean privateBrowsing, long contentLength,
+            String filename) {
+        Bundle fileInfo = new Bundle();
+        fileInfo.putString("url", url);
+        fileInfo.putString("userAgent", userAgent);
+        fileInfo.putString("contentDisposition", contentDisposition);
+        fileInfo.putString("mimetype", mimetype);
+        fileInfo.putString("referer", referer);
+        fileInfo.putLong("contentLength", contentLength);
+        fileInfo.putBoolean("privateBrowsing", privateBrowsing);
+        fileInfo.putString("filename", filename);
+        Intent intent = new Intent("android.intent.action.BROWSERDOWNLOAD");
+        intent.putExtras(fileInfo);
+        activity.startActivity(intent);
+    }
+
+    public static void setAppointedFolder(String downloadPath) {
+        File file = new File(downloadPath);
+        if (file.exists()) {
+            if (!file.isDirectory()) {
+                throw new IllegalStateException(file.getAbsolutePath() +
+                        " already exists and is not a directory");
+            }
+        } else {
+            if (!file.mkdir()) {
+                throw new IllegalStateException("Unable to create directory: " +
+                        file.getAbsolutePath());
+            }
+        }
+    }
+
+    private static void setDestinationDir(String downloadPath, String filename, Request request) {
+        File file = new File(downloadPath);
+        if (file.exists()) {
+            if (!file.isDirectory()) {
+                throw new IllegalStateException(file.getAbsolutePath() +
+                        " already exists and is not a directory");
+            }
+        } else {
+            if (!file.mkdir()) {
+                throw new IllegalStateException("Unable to create directory: " +
+                        file.getAbsolutePath());
+            }
+        }
+        setDestinationFromBase(file, filename, request);
+    }
+
+    private static void setDestinationFromBase(File file, String filename, Request request) {
+        if (filename == null) {
+            throw new NullPointerException("filename cannot be null");
+        }
+        request.setDestinationUri(Uri.withAppendedPath(Uri.fromFile(file), filename));
+    }
+
+    public static void fileExistQueryDialog(Activity activity) {
+        new AlertDialog.Builder(activity)
+                .setTitle(R.string.download_file_exist)
+                .setIcon(android.R.drawable.ic_dialog_info)
+                .setMessage(R.string.download_file_exist_msg)
+                // if yes, delete existed file and start new download thread
+                .setPositiveButton(R.string.ok, null)
+                // if no, do nothing at all
+                .show();
+    }
+
+    public static long getAvailableMemory(String root) {
+        StatFs stat = new StatFs(root);
+        final long LEFT10MByte = 2560;
+        long blockSize = stat.getBlockSize();
+        long availableBlocks = stat.getAvailableBlocks() - LEFT10MByte;
+        return availableBlocks * blockSize;
+    }
+
+    public static void showNoEnoughMemoryDialog(Activity mContext) {
+        new AlertDialog.Builder(mContext)
+                .setTitle(R.string.download_no_enough_memory)
+                .setIconAttribute(android.R.attr.alertDialogIcon)
+                .setMessage(R.string.download_no_enough_memory)
+                .setPositiveButton(R.string.ok, null)
+                .show();
+    }
+
+    public static boolean manageNoEnoughMemory(long contentLength, String root) {
+        long mAvailableBytes = getAvailableMemory(root);
+        if (mAvailableBytes > 0) {
+            if (contentLength > mAvailableBytes) {
+                return true;
+            }
+        } else {
+            return true;
+        }
+        return false;
+    }
+
+    public static void showStartDownloadToast(Activity activity) {
+        Intent intent = new Intent(DownloadManager.ACTION_VIEW_DOWNLOADS);
+        activity.startActivity(intent);
+        Toast.makeText(activity, R.string.download_pending, Toast.LENGTH_SHORT)
+                .show();
+    }
+
+    /**
+     * wheather the storage status OK for download file
+     *
+     * @param activity
+     * @param filename the download file's name
+     * @param downloadPath the download file's path will be in
+     * @return boolean true is ok,and false is not
+     */
+    public static boolean isStorageStatusOK(Activity activity, String filename, String downloadPath) {
+        if (downloadPath.equals(INVALID_PATH)) {
+            new AlertDialog.Builder(activity)
+                    .setTitle(R.string.path_wrong)
+                    .setIcon(android.R.drawable.ic_dialog_alert)
+                    .setMessage(R.string.invalid_path)
+                    .setPositiveButton(R.string.ok, null)
+                    .show();
+            return false;
+        }
+
+        if (!(isPhoneStorageSupported() && downloadPath.contains(mInternalStorage))) {
+            String status = getExternalStorageState(activity);
+            if (!status.equals(Environment.MEDIA_MOUNTED)) {
+                int title;
+                String msg;
+
+                // Check to see if the SDCard is busy, same as the music app
+                if (status.equals(Environment.MEDIA_SHARED)) {
+                    msg = activity.getString(R.string.download_sdcard_busy_dlg_msg);
+                    title = R.string.download_sdcard_busy_dlg_title;
+                } else {
+                    msg = activity.getString(R.string.download_no_sdcard_dlg_msg, filename);
+                    title = R.string.download_no_sdcard_dlg_title;
+                }
+
+                new AlertDialog.Builder(activity)
+                        .setTitle(title)
+                        .setIcon(android.R.drawable.ic_dialog_alert)
+                        .setMessage(msg)
+                        .setPositiveButton(R.string.ok, null)
+                        .show();
+                return false;
+            }
+        } else {
+            String status = Environment.getExternalStorageState();
+            if (!status.equals(Environment.MEDIA_MOUNTED)) {
+                int mTitle = R.string.download_path_unavailable_dlg_title;
+                String mMsg = activity.getString(R.string.download_path_unavailable_dlg_msg);
+                new AlertDialog.Builder(activity)
+                        .setTitle(mTitle)
+                        .setIcon(android.R.drawable.ic_dialog_alert)
+                        .setMessage(mMsg)
+                        .setPositiveButton(R.string.ok, null)
+                        .show();
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * wheather support Phone Storage
+     *
+     * @return boolean true support Phone Storage ,false will be not
+     */
+    public static boolean isPhoneStorageSupported() {
+        return true;
+    }
+
+    /**
+     * show Dialog to warn filename is null
+     *
+     * @param activity
+     */
+    public static void showFilenameEmptyDialog(Activity activity) {
+        new AlertDialog.Builder(activity)
+                .setTitle(R.string.filename_empty_title)
+                .setIcon(android.R.drawable.ic_dialog_alert)
+                .setMessage(R.string.filename_empty_msg)
+                .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
+                    public void onClick(DialogInterface dialog, int which) {
+                    }
+                })
+                .show();
+    }
+
+    /**
+     * get the filename except the suffix and dot
+     *
+     * @return String the filename except suffix and dot
+     */
+    public static String getFilenameBase(String filename) {
+        int dotindex = filename.lastIndexOf('.');
+        if (dotindex != -1) {
+            return filename.substring(0, dotindex);
+        } else {
+            return "";
+        }
+    }
+
+    /**
+     * get the filename's extension from filename
+     *
+     * @param filename the download filename, may be the user entered
+     * @return String the filename's extension
+     */
+    public static String getFilenameExtension(String filename) {
+        int dotindex = filename.lastIndexOf('.');
+        if (dotindex != -1) {
+            return filename.substring(dotindex + 1);
+        } else {
+            return "";
+        }
+    }
+
+    public static String getDefaultDownloadPath(Context context) {
+        String defaultDownloadPath;
+
+        String defaultStorage;
+        if (isPhoneStorageSupported()) {
+            defaultStorage = Environment.getExternalStorageDirectory().getPath();
+        } else {
+            defaultStorage = getExternalStorageDirectory(context);
+        }
+
+        defaultDownloadPath = defaultStorage + context.getString(R.string.download_default_path);
+        Log.e(LOGTAG, "defaultStorage directory is : " + defaultDownloadPath);
+        return defaultDownloadPath;
+    }
+
+    /**
+     * translate the directory name into a name which is easy to know for user
+     *
+     * @param activity
+     * @param downloadPath
+     * @return String
+     */
+    public static String getDownloadPathForUser(Activity activity, String downloadPath) {
+        if (downloadPath == null) {
+            return downloadPath;
+        }
+        final String phoneStorageDir;
+        final String sdCardDir = getExternalStorageDirectory(activity);
+        if (isPhoneStorageSupported()) {
+            phoneStorageDir = Environment.getExternalStorageDirectory().getPath();
+        } else {
+            phoneStorageDir = null;
+        }
+
+        if (sdCardDir != null && downloadPath.startsWith(sdCardDir)) {
+            String sdCardLabel = activity.getResources().getString(
+                    R.string.download_path_sd_card_label);
+            downloadPath = downloadPath.replace(sdCardDir, sdCardLabel);
+        } else if ((phoneStorageDir != null) && downloadPath.startsWith(phoneStorageDir)) {
+            String phoneStorageLabel = activity.getResources().getString(
+                    R.string.download_path_phone_storage_label);
+            downloadPath = downloadPath.replace(phoneStorageDir, phoneStorageLabel);
+        }
+        return downloadPath;
+    }
+
+    private static boolean isRemovable(Object obj) {
+        return (Boolean) ReflectHelper.invokeMethod(obj,
+                "isRemovable", null, null);
+    }
+
+    private static boolean allowMassStorage(Object obj) {
+        return (Boolean) ReflectHelper.invokeMethod(obj,
+                "allowMassStorage", null, null);
+    }
+
+    private static String getPath(Object obj) {
+        return (String) ReflectHelper.invokeMethod(obj,
+                "getPath", null, null);
+    }
+
+    private static String getExternalStorageDirectory(Context context) {
+        String sd = null;
+        StorageManager mStorageManager = (StorageManager) context
+                .getSystemService(Context.STORAGE_SERVICE);
+        Object[] volumes = (Object[]) ReflectHelper.invokeMethod(
+                                 mStorageManager, "getVolumeList", null, null);
+        for (int i = 0; i < volumes.length; i++) {
+            if (isRemovable(volumes[i]) && allowMassStorage(volumes[i])) {
+                sd = getPath(volumes[i]);
+            }
+        }
+        return sd;
+    }
+
+    private static String getExternalStorageState(Context context) {
+        StorageManager mStorageManager = (StorageManager) context
+                .getSystemService(Context.STORAGE_SERVICE);
+        String path = getExternalStorageDirectory(context);
+        Object[] params  = {path};
+        Class[] type = new Class[] {String.class};
+        return (String) ReflectHelper.invokeMethod("android.os.storage.StorageManager",
+                "getVolumeState", type, params);
+    }
+}