packages/providers/DownloadProvider
Révision | a2028ed4141075da8199ba04a499be77734a85ae (tree) |
---|---|
l'heure | 2010-02-06 01:16:49 |
Auteur | Leon Scroggins <scroggo@goog...> |
Commiter | Leon Scroggins |
Create a new permission that allows apps to see downloads from other
applications to the SD card.
Necessary for http://b/issue?id=2384554
Also create names for files by default, so they do not display as
<Untitled>. Remove calls to createTitleFromFilename, which are
no longer necessary.
Requires a change to frameworks/base.
@@ -21,6 +21,11 @@ | ||
21 | 21 | android:description="@string/permdesc_downloadCompletedIntent" |
22 | 22 | android:protectionLevel="signature" /> |
23 | 23 | |
24 | + <permission android:name="android.permission.SEE_ALL_EXTERNAL" | |
25 | + android:label="@string/permlab_seeAllExternal" | |
26 | + android:description="@string/permdesc_seeAllExternal" | |
27 | + android:protectionLevel="normal"/> | |
28 | + | |
24 | 29 | <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> |
25 | 30 | <uses-permission android:name="android.permission.ACCESS_DOWNLOAD_MANAGER" /> |
26 | 31 | <uses-permission android:name="android.permission.ACCESS_DRM" /> |
@@ -67,6 +67,12 @@ | ||
67 | 67 | can use this to confuse other applications that download |
68 | 68 | files.</string> |
69 | 69 | |
70 | + <!-- Title for permission to see all downloads to EXTERNAL --> | |
71 | + <string name="permlab_seeAllExternal">See all downloads to SD card</string> | |
72 | + <!-- Description for the permission to see all downloads to EXTERNAL --> | |
73 | + <string name="permdesc_seeAllExternal">Allows the application to see all | |
74 | + downloads to the SD card, regardless of which application downloaded | |
75 | + them.</string> | |
70 | 76 | <!-- This is the title that is used when displaying the notification |
71 | 77 | for a download that doesn't have a title associated with it. --> |
72 | 78 | <string name="download_unknown_title"><Untitled></string> |
@@ -119,7 +119,7 @@ class DownloadNotification { | ||
119 | 119 | Downloads.Impl.COLUMN_NOTIFICATION_CLASS, |
120 | 120 | Downloads.Impl.COLUMN_CURRENT_BYTES, |
121 | 121 | Downloads.Impl.COLUMN_TOTAL_BYTES, |
122 | - Downloads.Impl.COLUMN_STATUS, Downloads.Impl._DATA | |
122 | + Downloads.Impl.COLUMN_STATUS | |
123 | 123 | }, |
124 | 124 | WHERE_RUNNING, null, Downloads.Impl._ID); |
125 | 125 |
@@ -136,7 +136,6 @@ class DownloadNotification { | ||
136 | 136 | final int currentBytesColumn = 5; |
137 | 137 | final int totalBytesColumn = 6; |
138 | 138 | final int statusColumn = 7; |
139 | - final int filenameColumnId = 8; | |
140 | 139 | |
141 | 140 | // Collate the notifications |
142 | 141 | mNotifications.clear(); |
@@ -147,14 +146,8 @@ class DownloadNotification { | ||
147 | 146 | long id = c.getLong(idColumn); |
148 | 147 | String title = c.getString(titleColumn); |
149 | 148 | if (title == null || title.length() == 0) { |
150 | - String filename = c.getString(filenameColumnId); | |
151 | - if (filename == null) { | |
152 | - title = mContext.getResources().getString( | |
153 | - R.string.download_unknown_title); | |
154 | - } else { | |
155 | - title = Downloads.Impl.createTitleFromFilename(mContext, | |
156 | - filename, id); | |
157 | - } | |
149 | + title = mContext.getResources().getString( | |
150 | + R.string.download_unknown_title); | |
158 | 151 | } |
159 | 152 | if (mNotifications.containsKey(packageName)) { |
160 | 153 | mNotifications.get(packageName).addItem(title, progress, max); |
@@ -232,7 +225,6 @@ class DownloadNotification { | ||
232 | 225 | Downloads.Impl.COLUMN_CURRENT_BYTES, |
233 | 226 | Downloads.Impl.COLUMN_TOTAL_BYTES, |
234 | 227 | Downloads.Impl.COLUMN_STATUS, |
235 | - Downloads.Impl._DATA, | |
236 | 228 | Downloads.Impl.COLUMN_LAST_MODIFICATION, |
237 | 229 | Downloads.Impl.COLUMN_DESTINATION |
238 | 230 | }, |
@@ -251,9 +243,8 @@ class DownloadNotification { | ||
251 | 243 | final int currentBytesColumn = 5; |
252 | 244 | final int totalBytesColumn = 6; |
253 | 245 | final int statusColumn = 7; |
254 | - final int filenameColumnId = 8; | |
255 | - final int lastModColumnId = 9; | |
256 | - final int destinationColumnId = 10; | |
246 | + final int lastModColumnId = 8; | |
247 | + final int destinationColumnId = 9; | |
257 | 248 | |
258 | 249 | for (c.moveToFirst(); !c.isAfterLast(); c.moveToNext()) { |
259 | 250 | // Add the notifications |
@@ -263,14 +254,8 @@ class DownloadNotification { | ||
263 | 254 | long id = c.getLong(idColumn); |
264 | 255 | String title = c.getString(titleColumn); |
265 | 256 | if (title == null || title.length() == 0) { |
266 | - String filename = c.getString(filenameColumnId); | |
267 | - if (filename == null) { | |
268 | - title = mContext.getResources().getString( | |
269 | - R.string.download_unknown_title); | |
270 | - } else { | |
271 | - title = Downloads.Impl.createTitleFromFilename(mContext, | |
272 | - filename, id); | |
273 | - } | |
257 | + title = mContext.getResources().getString( | |
258 | + R.string.download_unknown_title); | |
274 | 259 | } |
275 | 260 | Uri contentUri = Uri.parse(Downloads.Impl.CONTENT_URI + "/" + id); |
276 | 261 | String caption; |
@@ -413,23 +413,40 @@ public final class DownloadProvider extends ContentProvider { | ||
413 | 413 | callingUid != mSystemUid && |
414 | 414 | callingUid != mDefContainerUid && |
415 | 415 | Process.supportsProcesses()) { |
416 | - if (!emptyWhere) { | |
417 | - qb.appendWhere(" AND "); | |
418 | - } | |
419 | - qb.appendWhere("( " + Constants.UID + "=" + Binder.getCallingUid() + " OR " | |
420 | - + Downloads.Impl.COLUMN_OTHER_UID + "=" + Binder.getCallingUid() + " )"); | |
421 | - emptyWhere = false; | |
422 | - | |
416 | + boolean canSeeAllExternal; | |
423 | 417 | if (projection == null) { |
424 | 418 | projection = sAppReadableColumnsArray; |
419 | + // sAppReadableColumnsArray includes _DATA, which is not allowed | |
420 | + // to be seen except by the initiating application | |
421 | + canSeeAllExternal = false; | |
425 | 422 | } else { |
423 | + canSeeAllExternal = getContext().checkCallingPermission( | |
424 | + Downloads.Impl.PERMISSION_SEE_ALL_EXTERNAL) | |
425 | + == PackageManager.PERMISSION_GRANTED; | |
426 | 426 | for (int i = 0; i < projection.length; ++i) { |
427 | 427 | if (!sAppReadableColumnsSet.contains(projection[i])) { |
428 | 428 | throw new IllegalArgumentException( |
429 | 429 | "column " + projection[i] + " is not allowed in queries"); |
430 | 430 | } |
431 | + canSeeAllExternal = canSeeAllExternal | |
432 | + && !projection[i].equals(Downloads.Impl._DATA); | |
431 | 433 | } |
432 | 434 | } |
435 | + if (!emptyWhere) { | |
436 | + qb.appendWhere(" AND "); | |
437 | + emptyWhere = false; | |
438 | + } | |
439 | + String validUid = "( " + Constants.UID + "=" | |
440 | + + Binder.getCallingUid() + " OR " | |
441 | + + Downloads.Impl.COLUMN_OTHER_UID + "=" | |
442 | + + Binder.getCallingUid() + " )"; | |
443 | + if (canSeeAllExternal) { | |
444 | + qb.appendWhere("( " + validUid + " OR " | |
445 | + + Downloads.Impl.DESTINATION_EXTERNAL + " = " | |
446 | + + Downloads.Impl.COLUMN_DESTINATION + " )"); | |
447 | + } else { | |
448 | + qb.appendWhere(validUid); | |
449 | + } | |
433 | 450 | } |
434 | 451 | |
435 | 452 | if (Constants.LOGVV) { |
@@ -526,6 +543,16 @@ public final class DownloadProvider extends ContentProvider { | ||
526 | 543 | copyString(Downloads.Impl.COLUMN_DESCRIPTION, values, filteredValues); |
527 | 544 | } else { |
528 | 545 | filteredValues = values; |
546 | + String filename = values.getAsString(Downloads.Impl._DATA); | |
547 | + if (filename != null) { | |
548 | + Cursor c = query(uri, new String[] | |
549 | + { Downloads.Impl.COLUMN_TITLE }, null, null, null); | |
550 | + if (!c.moveToFirst() || c.getString(0) == null) { | |
551 | + values.put(Downloads.Impl.COLUMN_TITLE, | |
552 | + new File(filename).getName()); | |
553 | + } | |
554 | + c.close(); | |
555 | + } | |
529 | 556 | } |
530 | 557 | int match = sURIMatcher.match(uri); |
531 | 558 | switch (match) { |