auto import from //depot/cupcake/@135843
diff --git a/src/com/android/browser/BrowserDownloadPage.java b/src/com/android/browser/BrowserDownloadPage.java
new file mode 100644
index 0000000..4397337
--- /dev/null
+++ b/src/com/android/browser/BrowserDownloadPage.java
@@ -0,0 +1,468 @@
+/*
+ * Copyright (C) 2007 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.content.ActivityNotFoundException;
+import android.content.ContentValues;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.ContentUris;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.provider.Downloads;
+import android.view.ContextMenu;
+import android.view.ContextMenu.ContextMenuInfo;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.MenuInflater;
+import android.view.View;
+import android.view.ViewGroup.LayoutParams;
+import android.widget.AdapterView;
+import android.widget.ListView;
+import android.widget.AdapterView.OnItemClickListener;
+
+import java.io.File;
+import java.util.List;
+
+/**
+ *  View showing the user's current browser downloads
+ */
+public class BrowserDownloadPage extends Activity 
+        implements View.OnCreateContextMenuListener, OnItemClickListener {
+    
+    private ListView                mListView;
+    private Cursor                  mDownloadCursor;
+    private BrowserDownloadAdapter  mDownloadAdapter;
+    private int                     mStatusColumnId;
+    private int                     mIdColumnId;
+    private int                     mTitleColumnId;
+    private int                     mContextMenuPosition;
+    
+    @Override 
+    public void onCreate(Bundle icicle) {
+        super.onCreate(icicle);
+        setContentView(R.layout.browser_downloads_page);
+        
+        setTitle(getText(R.string.download_title));
+
+        mListView = (ListView) findViewById(R.id.list);
+        LayoutInflater factory = LayoutInflater.from(this);
+        View v = factory.inflate(R.layout.no_downloads, null);
+        addContentView(v, new LayoutParams(LayoutParams.FILL_PARENT,
+                LayoutParams.FILL_PARENT));
+        mListView.setEmptyView(v);
+        
+        mDownloadCursor = managedQuery(Downloads.CONTENT_URI, 
+                new String [] {"_id", Downloads.TITLE, Downloads.STATUS,
+                Downloads.TOTAL_BYTES, Downloads.CURRENT_BYTES, 
+                Downloads._DATA, Downloads.DESCRIPTION, 
+                Downloads.MIMETYPE, Downloads.LAST_MODIFICATION,
+                Downloads.VISIBILITY}, 
+                null, null);
+        
+        // only attach everything to the listbox if we can access
+        // the download database. Otherwise, just show it empty
+        if (mDownloadCursor != null) {
+            mStatusColumnId = 
+                    mDownloadCursor.getColumnIndexOrThrow(Downloads.STATUS);
+            mIdColumnId =
+                    mDownloadCursor.getColumnIndexOrThrow(Downloads._ID);
+            mTitleColumnId = 
+                    mDownloadCursor.getColumnIndexOrThrow(Downloads.TITLE);
+            
+            // Create a list "controller" for the data
+            mDownloadAdapter = new BrowserDownloadAdapter(this, 
+                    R.layout.browser_download_item, mDownloadCursor);
+            
+            mListView.setAdapter(mDownloadAdapter);
+            mListView.setScrollBarStyle(View.SCROLLBARS_INSIDE_INSET);
+            mListView.setOnCreateContextMenuListener(this);
+            mListView.setOnItemClickListener(this);
+            
+            Intent intent = getIntent();
+            if (intent != null && intent.getData() != null) {
+                int position = checkStatus(
+                        ContentUris.parseId(intent.getData()));
+                if (position >= 0) {
+                    mListView.setSelection(position);
+                }
+            }
+        }
+    }
+        
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        if (mDownloadCursor != null) {
+            MenuInflater inflater = getMenuInflater();
+            inflater.inflate(R.menu.downloadhistory, menu);
+        }
+        return true;
+    }
+    
+    @Override
+    public boolean onPrepareOptionsMenu(Menu menu) {
+        boolean showCancel = getCancelableCount() > 0;
+        menu.findItem(R.id.download_menu_cancel_all).setEnabled(showCancel);
+        
+        boolean showClear = getClearableCount() > 0;
+        menu.findItem(R.id.download_menu_clear_all).setEnabled(showClear);
+        return super.onPrepareOptionsMenu(menu);
+    }
+    
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        switch (item.getItemId()) {
+            case R.id.download_menu_cancel_all:
+                promptCancelAll();
+                return true;
+                
+            case R.id.download_menu_clear_all:
+                promptClearList();
+                return true;
+        }
+        return false;
+    }
+
+    @Override
+    public boolean onContextItemSelected(MenuItem item) {
+        mDownloadCursor.moveToPosition(mContextMenuPosition);
+        switch (item.getItemId()) {
+            case R.id.download_menu_open:
+                hideCompletedDownload();
+                openCurrentDownload();
+                return true;
+                
+            case R.id.download_menu_clear:
+            case R.id.download_menu_cancel:
+                getContentResolver().delete(
+                        ContentUris.withAppendedId(Downloads.CONTENT_URI,
+                        mDownloadCursor.getLong(mIdColumnId)), null, null);
+                return true;
+        }
+        return false;
+    }
+
+    @Override
+    public void onCreateContextMenu(ContextMenu menu, View v,
+            ContextMenuInfo menuInfo) {
+        if (mDownloadCursor != null) {
+            AdapterView.AdapterContextMenuInfo info = 
+                    (AdapterView.AdapterContextMenuInfo) menuInfo;
+            mDownloadCursor.moveToPosition(info.position);
+            mContextMenuPosition = info.position;
+            menu.setHeaderTitle(mDownloadCursor.getString(mTitleColumnId));
+            
+            MenuInflater inflater = getMenuInflater();
+            int status = mDownloadCursor.getInt(mStatusColumnId);
+            if (Downloads.isStatusSuccess(status)) {
+                inflater.inflate(R.menu.downloadhistorycontextfinished, menu);
+            } else if (Downloads.isStatusError(status)) {
+                inflater.inflate(R.menu.downloadhistorycontextfailed, menu);
+            } else {
+                inflater.inflate(R.menu.downloadhistorycontextrunning, menu);
+            }
+        }
+    }
+
+    /**
+     * This function is called to check the status of the download and if it
+     * has an error show an error dialog.
+     * @param id Row id of the download to check
+     * @return position of item
+     */
+    int checkStatus(final long id) {
+        int position = -1;
+        for (mDownloadCursor.moveToFirst(); !mDownloadCursor.isAfterLast(); 
+                mDownloadCursor.moveToNext()) {
+            if (id == mDownloadCursor.getLong(mIdColumnId)) {
+                position = mDownloadCursor.getPosition();
+                break;
+            }
+            
+        }
+        if (!mDownloadCursor.isAfterLast()) {
+            int status = mDownloadCursor.getInt(mStatusColumnId);
+            if (!Downloads.isStatusError(status)) {
+                return position;
+            }
+            
+            if (status == Downloads.STATUS_FILE_ERROR) {
+                String title = mDownloadCursor.getString(mTitleColumnId);
+                if (title == null || title.length() == 0) {
+                    title = getString(R.string.download_unknown_filename);
+                }
+                String msg = getString(R.string.download_file_error_dlg_msg, 
+                        title);
+                new AlertDialog.Builder(this)
+                        .setTitle(R.string.download_file_error_dlg_title)
+                        .setIcon(android.R.drawable.ic_popup_disk_full)
+                        .setMessage(msg)
+                        .setPositiveButton(R.string.ok, null)
+                        .setNegativeButton(R.string.retry, 
+                                new DialogInterface.OnClickListener() {
+                                    public void onClick(DialogInterface dialog, 
+                                            int whichButton) {
+                                        resumeDownload(id);
+                                    }
+                                })
+                        .show();
+            } else {
+                new AlertDialog.Builder(this)
+                        .setTitle(R.string.download_failed_generic_dlg_title)
+                        .setIcon(R.drawable.ssl_icon)
+                        .setMessage(BrowserDownloadAdapter.getErrorText(status))
+                        .setPositiveButton(R.string.ok, null)
+                        .show();
+            }
+        }
+        return position;
+    }
+    
+    /**
+     * Resume a given download
+     * @param id Row id of the download to resume
+     */
+    private void resumeDownload(final long id) {
+        // the relevant functionality doesn't exist in the download manager
+    }
+    
+    /**
+     * Prompt the user if they would like to clear the download history
+     */
+    private void promptClearList() {
+        new AlertDialog.Builder(this)
+               .setTitle(R.string.download_clear_dlg_title)
+               .setIcon(R.drawable.ssl_icon)
+               .setMessage(R.string.download_clear_dlg_msg)
+               .setPositiveButton(R.string.ok, 
+                       new DialogInterface.OnClickListener() {
+                           public void onClick(DialogInterface dialog, 
+                                   int whichButton) {
+                               clearAllDownloads();
+                           }
+                       })
+                .setNegativeButton(R.string.cancel, null)
+                .show();
+    }
+    
+    /**
+     * Return the number of items in the list that can be canceled.
+     * @return count
+     */
+    private int getCancelableCount() {
+        // Count the number of items that will be canceled.
+        int count = 0;
+        if (mDownloadCursor != null) {
+            for (mDownloadCursor.moveToFirst(); !mDownloadCursor.isAfterLast(); 
+                    mDownloadCursor.moveToNext()) {
+                int status = mDownloadCursor.getInt(mStatusColumnId);
+                if (!Downloads.isStatusCompleted(status)) {
+                    count++;
+                }
+            }
+        }
+        
+        return count;
+    }
+    
+    /**
+     * Prompt the user if they would like to clear the download history
+     */
+    private void promptCancelAll() {
+        int count = getCancelableCount();
+        
+        // If there is nothing to do, just return
+        if (count == 0) {
+            return;
+        }
+        
+        // Don't show the dialog if there is only one download
+        if (count == 1) {
+            cancelAllDownloads();
+            return;
+        }
+        String msg = 
+            getString(R.string.download_cancel_dlg_msg, count);
+        new AlertDialog.Builder(this)
+                .setTitle(R.string.download_cancel_dlg_title)
+                .setIcon(R.drawable.ssl_icon)
+                .setMessage(msg)
+                .setPositiveButton(R.string.ok, 
+                        new DialogInterface.OnClickListener() {
+                            public void onClick(DialogInterface dialog, 
+                                    int whichButton) {
+                                cancelAllDownloads();
+                            }
+                        })
+                 .setNegativeButton(R.string.cancel, null)
+                 .show();
+    }
+    
+    /**
+     * Cancel all downloads. As canceled downloads are not
+     * listed, we removed them from the db. Removing a download
+     * record, cancels the download.
+     */
+    private void cancelAllDownloads() {
+        if (mDownloadCursor.moveToFirst()) {
+            StringBuilder where = new StringBuilder();
+            boolean firstTime = true;
+            while (!mDownloadCursor.isAfterLast()) {
+                int status = mDownloadCursor.getInt(mStatusColumnId);
+                if (!Downloads.isStatusCompleted(status)) {
+                    if (firstTime) {
+                        firstTime = false;
+                    } else {
+                        where.append(" OR ");
+                    }
+                    where.append("( ");
+                    where.append(Downloads._ID);
+                    where.append(" = '");
+                    where.append(mDownloadCursor.getLong(mIdColumnId));
+                    where.append("' )");
+                }
+                mDownloadCursor.moveToNext();
+            }
+            if (!firstTime) {
+                getContentResolver().delete(Downloads.CONTENT_URI,
+                        where.toString(), null);
+            }
+        }
+    }
+    
+    private int getClearableCount() {
+        int count = 0;
+        if (mDownloadCursor.moveToFirst()) {
+            while (!mDownloadCursor.isAfterLast()) {
+                int status = mDownloadCursor.getInt(mStatusColumnId);
+                if (Downloads.isStatusCompleted(status)) {
+                    count++;
+                }
+                mDownloadCursor.moveToNext();
+            }
+        }
+        return count;
+    }
+    
+    /**
+     * Clear all stopped downloads, ie canceled (though should not be
+     * there), error and success download items.
+     */
+    private void clearAllDownloads() {
+        if (mDownloadCursor.moveToFirst()) {
+            StringBuilder where = new StringBuilder();
+            boolean firstTime = true;
+            while (!mDownloadCursor.isAfterLast()) {
+                int status = mDownloadCursor.getInt(mStatusColumnId);
+                if (Downloads.isStatusCompleted(status)) {
+                    if (firstTime) {
+                        firstTime = false;
+                    } else {
+                        where.append(" OR ");
+                    }
+                    where.append("( ");
+                    where.append(Downloads._ID);
+                    where.append(" = '");
+                    where.append(mDownloadCursor.getLong(mIdColumnId));
+                    where.append("' )");
+                }
+                mDownloadCursor.moveToNext();
+            }
+            if (!firstTime) {
+                getContentResolver().delete(Downloads.CONTENT_URI,
+                        where.toString(), null);
+            }
+        }
+    }
+    
+    /**
+     * Open the content where the download db cursor currently is
+     */
+    private void openCurrentDownload() {
+        int filenameColumnId = 
+                mDownloadCursor.getColumnIndexOrThrow(Downloads._DATA);
+        String filename = mDownloadCursor.getString(filenameColumnId);
+        int mimetypeColumnId =
+                mDownloadCursor.getColumnIndexOrThrow(Downloads.MIMETYPE);
+        String mimetype = mDownloadCursor.getString(mimetypeColumnId);
+        Uri path = Uri.parse(filename);
+        // If there is no scheme, then it must be a file
+        if (path.getScheme() == null) {
+            path = Uri.fromFile(new File(filename));
+        }
+        Intent intent = new Intent(Intent.ACTION_VIEW);
+        intent.setDataAndType(path, mimetype);
+        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
+        try {
+            startActivity(intent);
+        } catch (ActivityNotFoundException ex) {
+            new AlertDialog.Builder(this)
+                    .setTitle(R.string.download_failed_generic_dlg_title)
+                    .setIcon(R.drawable.ssl_icon)
+                    .setMessage(R.string.download_no_application)
+                    .setPositiveButton(R.string.ok, null)
+                    .show();
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see android.widget.AdapterView.OnItemClickListener#onItemClick(android.widget.AdapterView, android.view.View, int, long)
+     */
+    public void onItemClick(AdapterView parent, View view, int position, 
+            long id) {
+        // Open the selected item
+        mDownloadCursor.moveToPosition(position);
+        
+        hideCompletedDownload();
+
+        int status = mDownloadCursor.getInt(mStatusColumnId);
+        if (Downloads.isStatusSuccess(status)) {
+            // Open it if it downloaded successfully
+            openCurrentDownload();
+        } else {
+            // Check to see if there is an error.
+            checkStatus(id);
+        }
+    }
+    
+    /**
+     * hides the notification for the download pointed by mDownloadCursor
+     * if the download has completed.
+     */
+    private void hideCompletedDownload() {
+        int status = mDownloadCursor.getInt(mStatusColumnId);
+
+        int visibilityColumn = mDownloadCursor.getColumnIndexOrThrow(Downloads.VISIBILITY);
+        int visibility = mDownloadCursor.getInt(visibilityColumn);
+
+        if (Downloads.isStatusCompleted(status) &&
+                visibility == Downloads.VISIBILITY_VISIBLE_NOTIFY_COMPLETED) {
+            ContentValues values = new ContentValues();
+            values.put(Downloads.VISIBILITY, Downloads.VISIBILITY_VISIBLE);
+            getContentResolver().update(
+                    ContentUris.withAppendedId(Downloads.CONTENT_URI,
+                    mDownloadCursor.getLong(mIdColumnId)), values, null, null);
+        }
+    }
+}