diff options
author | Steve Howard <showard@google.com> | 2010-09-12 18:53:31 -0700 |
---|---|---|
committer | Steve Howard <showard@google.com> | 2010-09-14 19:00:40 -0700 |
commit | 3d55d829c03fe78ad8cdab119293efb6c6e49c64 (patch) | |
tree | fb8feb9c23b83108546048b0488033279de63635 /ui/src/com/android/providers/downloads/ui | |
parent | 33671e9c1e9ffa3776ed987bddeb70a04daa7cfe (diff) | |
download | android_packages_providers_DownloadProvider-3d55d829c03fe78ad8cdab119293efb6c6e49c64.tar.gz android_packages_providers_DownloadProvider-3d55d829c03fe78ad8cdab119293efb6c6e49c64.tar.bz2 android_packages_providers_DownloadProvider-3d55d829c03fe78ad8cdab119293efb6c6e49c64.zip |
New URI structure with "my_downloads" and "all_downloads"
This change introduces a second view into the download manager
database via a set of URIs starting with /all_downloads, renaming the
original /download URIs to /my_downloads. In addition to making
things more clear, this change allows the downloads UI to grant
permissions on individual downloads to viewer apps.
The old semantics were:
* for ordinary callers, /download included only downloads initiated by
the calling UID
* for intraprocess calls or calls by root, /download included all
downloads
The new semantics are
* /my_downloads always includes only downloads initiated by the
calling UID, and requires only INTERNET permission. It could just
as well require no permission, but that's not possible in the
framework, since path-permissions can only broaden access, not
tighten it. It doesn't matter, because these URIs are useless
without INTERNET permission -- if a user can't initiate downloads,
there's no reason to read this.
* /all_downloads always includes all downloads on the system, and
requires the new permission ACCESS_ALL_DOWNLOADS. This permission
is currently protectionLevel=signature -- this could be relaxed
later to support third-party download managers.
All download manager code has been changed to use /all_downloads URIs,
except when passing a URI to another app. In making this change
across the download manager code, I've taken some liberties in
cleaning things up. Other apps are unchanged and will use
/my_downloads.
Finally, this incorporates changes to DownloadManager to return a
content URI for /cache downloads -- the download UI no longer assumes
it's a file URI, and it grants permissions to the receiver of the VIEW
intent. The public API test has also been updated.
I've also fixed some null cursor checking in DownloadManager.
Change-Id: I05a501eb4388249fe80c43724405657c950d7238
Diffstat (limited to 'ui/src/com/android/providers/downloads/ui')
-rw-r--r-- | ui/src/com/android/providers/downloads/ui/DownloadList.java | 36 |
1 files changed, 25 insertions, 11 deletions
diff --git a/ui/src/com/android/providers/downloads/ui/DownloadList.java b/ui/src/com/android/providers/downloads/ui/DownloadList.java index dd9a6083..fce2f162 100644 --- a/ui/src/com/android/providers/downloads/ui/DownloadList.java +++ b/ui/src/com/android/providers/downloads/ui/DownloadList.java @@ -30,6 +30,7 @@ import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.provider.Downloads; +import android.util.Log; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; @@ -47,7 +48,8 @@ import android.widget.Toast; import com.android.providers.downloads.ui.DownloadItem.DownloadSelectListener; -import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; import java.util.HashSet; import java.util.Iterator; import java.util.Set; @@ -58,6 +60,8 @@ import java.util.Set; public class DownloadList extends Activity implements OnChildClickListener, OnItemClickListener, DownloadSelectListener, OnClickListener, OnCancelListener { + private static final String LOG_TAG = "DownloadList"; + private ExpandableListView mDateOrderedListView; private ListView mSizeOrderedListView; private View mEmptyView; @@ -103,6 +107,7 @@ public class DownloadList extends Activity setupViews(); mDownloadManager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE); + mDownloadManager.setAccessAllDownloads(true); DownloadManager.Query baseQuery = new DownloadManager.Query() .setOnlyIncludeVisibleInDownloadsUi(true); mDateSortedCursor = mDownloadManager.query(baseQuery); @@ -112,7 +117,7 @@ public class DownloadList extends Activity // only attach everything to the listbox if we can access the download database. Otherwise, // just show it empty - if (mDateSortedCursor != null && mSizeSortedCursor != null) { + if (haveCursors()) { startManagingCursor(mDateSortedCursor); startManagingCursor(mSizeSortedCursor); @@ -160,19 +165,23 @@ public class DownloadList extends Activity ((Button) findViewById(R.id.deselect_all)).setOnClickListener(this); } + private boolean haveCursors() { + return mDateSortedCursor != null && mSizeSortedCursor != null; + } + @Override protected void onResume() { super.onResume(); - if (mDateSortedCursor != null) { + if (haveCursors()) { mDateSortedCursor.registerContentObserver(mContentObserver); + refresh(); } - refresh(); } @Override protected void onPause() { super.onPause(); - if (mDateSortedCursor != null) { + if (haveCursors()) { mDateSortedCursor.unregisterContentObserver(mContentObserver); } } @@ -207,7 +216,7 @@ public class DownloadList extends Activity @Override public boolean onCreateOptionsMenu(Menu menu) { - if (mDateSortedCursor != null) { + if (haveCursors()) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.download_menu, menu); } @@ -243,7 +252,7 @@ public class DownloadList extends Activity mDateOrderedListView.setVisibility(View.GONE); mSizeOrderedListView.setVisibility(View.GONE); - if (mDateSortedCursor.getCount() == 0) { + if (mDateSortedCursor == null || mDateSortedCursor.getCount() == 0) { mEmptyView.setVisibility(View.VISIBLE); } else { mEmptyView.setVisibility(View.GONE); @@ -290,15 +299,20 @@ public class DownloadList extends Activity * Send an Intent to open the download currently pointed to by the given cursor. */ private void openCurrentDownload(Cursor cursor) { - Uri fileUri = Uri.parse(cursor.getString(mLocalUriColumnId)); - if (!new File(fileUri.getPath()).exists()) { + Uri localUri = Uri.parse(cursor.getString(mLocalUriColumnId)); + try { + getContentResolver().openFileDescriptor(localUri, "r").close(); + } catch (FileNotFoundException exc) { + Log.d(LOG_TAG, "Failed to open download " + cursor.getLong(mIdColumnId), exc); showFailedDialog(cursor.getLong(mIdColumnId), R.string.dialog_file_missing_body); return; + } catch (IOException exc) { + // close() failed, not a problem } Intent intent = new Intent(Intent.ACTION_VIEW); - intent.setDataAndType(fileUri, cursor.getString(mMediaTypeColumnId)); - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + intent.setDataAndType(localUri, cursor.getString(mMediaTypeColumnId)); + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_GRANT_READ_URI_PERMISSION); try { startActivity(intent); } catch (ActivityNotFoundException ex) { |