diff options
5 files changed, 58 insertions, 24 deletions
diff --git a/AndroidManifest.xml b/AndroidManifest.xml index d6c85d34..8431d1ed 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -25,7 +25,13 @@ <permission android:name="android.permission.DOWNLOAD_CACHE_NON_PURGEABLE" android:label="@string/permlab_downloadCacheNonPurgeable" android:description="@string/permdesc_downloadCacheNonPurgeable" - android:protectionLevel="dangerous"/> + android:protectionLevel="signatureOrSystem"/> + + <!-- Allows to queue downloads without a notification shown while the download runs. --> + <permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" + android:label="@string/permlab_downloadWithoutNotification" + android:description="@string/permdesc_downloadWithoutNotification" + android:protectionLevel="signatureOrSystem"/> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> <uses-permission android:name="android.permission.ACCESS_DOWNLOAD_MANAGER" /> diff --git a/res/values/strings.xml b/res/values/strings.xml index 0bc5c09c..62ba38f7 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -74,13 +74,30 @@ downloads to the SD card, regardless of which application downloaded them.</string> - <string name="permlab_downloadCacheNonPurgeable">Download non-purgeable - files to the cache</string> + <!-- The label for the permission to download files to the download cache + that can't be automatically deleted by the download manager to free up + space [CHAR LIMIT=50] --> + <string name="permlab_downloadCacheNonPurgeable">Reserve space in the + download cache</string> + <!-- The full sentence description for the permission to download files to + the download cache that can't be automatically deleted by the download + manager to free up space [CHAR LIMIT=160] --> <string name="permdesc_downloadCacheNonPurgeable">Allows the application to - download files to the download cache through the public API which will not - be automatically deleted when the download manager needs more space. - Malicious applications can use this to block other applications from using - the download cache.</string> + download files to the download cache which cannot be automatically deleted + when the download manager needs more space.</string> + + <!-- The label for the permission to download files through the download + manager without any notification being shown to the user [CHAR LIMIT=50] --> + <string name="permlab_downloadWithoutNotification">Use download manager + without notification</string> + + <!-- The full sentence description for the permission to download files + through the download manager without any notification being shown to the + user [CHAR LIMIT=160] --> + <string name="permdesc_downloadWithoutNotification">Allows the application + to download files through the download manager without any notification + being shown to the user.</string> + <!-- This is the title that is used when displaying the notification for a download that doesn't have a title associated with it. --> diff --git a/src/com/android/providers/downloads/DownloadProvider.java b/src/com/android/providers/downloads/DownloadProvider.java index 74fd2792..4667b41c 100644 --- a/src/com/android/providers/downloads/DownloadProvider.java +++ b/src/com/android/providers/downloads/DownloadProvider.java @@ -499,8 +499,15 @@ public final class DownloadProvider extends ContentProvider { enforceAllowedValues(values, Downloads.Impl.COLUMN_DESTINATION, Downloads.Impl.DESTINATION_CACHE_PARTITION_PURGEABLE, Downloads.Impl.DESTINATION_FILE_URI); - enforceAllowedValues(values, Downloads.Impl.COLUMN_VISIBILITY, - null, Downloads.Impl.VISIBILITY_VISIBLE); + + if (getContext().checkCallingOrSelfPermission(Downloads.Impl.PERMISSION_NO_NOTIFICATION) + == PackageManager.PERMISSION_GRANTED) { + enforceAllowedValues(values, Downloads.Impl.COLUMN_VISIBILITY, + Downloads.Impl.VISIBILITY_HIDDEN, Downloads.Impl.VISIBILITY_VISIBLE); + } else { + enforceAllowedValues(values, Downloads.Impl.COLUMN_VISIBILITY, + Downloads.Impl.VISIBILITY_VISIBLE); + } // remove the rest of the columns that are allowed (with any value) values.remove(Downloads.Impl.COLUMN_URI); diff --git a/tests/public_api_access/src/com/android/providers/downloads/public_api_access_tests/PublicApiAccessTest.java b/tests/public_api_access/src/com/android/providers/downloads/public_api_access_tests/PublicApiAccessTest.java index aca5791b..4b2ae092 100644 --- a/tests/public_api_access/src/com/android/providers/downloads/public_api_access_tests/PublicApiAccessTest.java +++ b/tests/public_api_access/src/com/android/providers/downloads/public_api_access_tests/PublicApiAccessTest.java @@ -53,7 +53,7 @@ public class PublicApiAccessTest extends AndroidTestCase { @Override protected void tearDown() throws Exception { if (mContentResolver != null) { - mContentResolver.delete(Downloads.CONTENT_URI, null, null); + mContentResolver.delete(Downloads.CONTENT_URI, null, null); } super.tearDown(); } @@ -61,7 +61,7 @@ public class PublicApiAccessTest extends AndroidTestCase { public void testMinimalValidWrite() { mContentResolver.insert(Downloads.Impl.CONTENT_URI, buildValidValues()); } - + public void testMaximalValidWrite() { ContentValues values = buildValidValues(); values.put(Downloads.Impl.COLUMN_TITLE, "foo"); @@ -76,18 +76,19 @@ public class PublicApiAccessTest extends AndroidTestCase { private ContentValues buildValidValues() { ContentValues values = new ContentValues(); values.put(Downloads.Impl.COLUMN_URI, "foo"); - values.put(Downloads.Impl.COLUMN_DESTINATION, + values.put(Downloads.Impl.COLUMN_DESTINATION, Downloads.Impl.DESTINATION_CACHE_PARTITION_PURGEABLE); + values.put(Downloads.Impl.COLUMN_VISIBILITY, Downloads.Impl.VISIBILITY_VISIBLE); values.put(Downloads.Impl.COLUMN_IS_PUBLIC_API, true); return values; } - + public void testNoPublicApi() { ContentValues values = buildValidValues(); values.remove(Downloads.Impl.COLUMN_IS_PUBLIC_API); testInvalidValues(values); } - + public void testInvalidDestination() { ContentValues values = buildValidValues(); values.put(Downloads.Impl.COLUMN_DESTINATION, Downloads.Impl.DESTINATION_EXTERNAL); @@ -95,14 +96,20 @@ public class PublicApiAccessTest extends AndroidTestCase { values.put(Downloads.Impl.COLUMN_DESTINATION, Downloads.Impl.DESTINATION_CACHE_PARTITION); testInvalidValues(values); } - + public void testInvalidVisibility() { ContentValues values = buildValidValues(); - values.put(Downloads.Impl.COLUMN_VISIBILITY, + values.put(Downloads.Impl.COLUMN_VISIBILITY, Downloads.Impl.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); testInvalidValues(values); + + values.put(Downloads.Impl.COLUMN_VISIBILITY, Downloads.Impl.VISIBILITY_HIDDEN); + testInvalidValues(values); + + values.remove(Downloads.Impl.COLUMN_VISIBILITY); + testInvalidValues(values); } - + public void testDisallowedColumns() { for (String column : DISALLOWED_COLUMNS) { ContentValues values = buildValidValues(); @@ -110,7 +117,7 @@ public class PublicApiAccessTest extends AndroidTestCase { testInvalidValues(values); } } - + public void testFileUriWithoutExternalPermission() { ContentValues values = buildValidValues(); values.put(Downloads.Impl.COLUMN_DESTINATION, Downloads.Impl.DESTINATION_FILE_URI); diff --git a/tests/src/com/android/providers/downloads/PublicApiFunctionalTest.java b/tests/src/com/android/providers/downloads/PublicApiFunctionalTest.java index b601846a..840b20ac 100644 --- a/tests/src/com/android/providers/downloads/PublicApiFunctionalTest.java +++ b/tests/src/com/android/providers/downloads/PublicApiFunctionalTest.java @@ -358,8 +358,7 @@ public class PublicApiFunctionalTest extends AbstractPublicApiTest { } public void testNotificationClickedBroadcast() throws Exception { - Download download = enqueueRequest(getRequest().setShowNotification( - DownloadManager.Request.NOTIFICATION_WHEN_RUNNING)); + Download download = enqueueRequest(getRequest()); DownloadReceiver receiver = new DownloadReceiver(); receiver.mSystemFacade = mSystemFacade; @@ -431,15 +430,13 @@ public class PublicApiFunctionalTest extends AbstractPublicApiTest { public void testNotifications() throws Exception { enqueueEmptyResponse(HTTP_OK); - Download download = enqueueRequest(getRequest()); // no visibility requested + Download download = enqueueRequest(getRequest().setShowRunningNotification(false)); download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL); assertEquals(0, mSystemFacade.mActiveNotifications.size()); assertEquals(0, mSystemFacade.mCanceledNotifications.size()); enqueueEmptyResponse(HTTP_OK); - download = enqueueRequest( - getRequest() - .setShowNotification(DownloadManager.Request.NOTIFICATION_WHEN_RUNNING)); + download = enqueueRequest(getRequest()); // notifications by default download.runUntilStatus(DownloadManager.STATUS_SUCCESSFUL); assertEquals(1, mSystemFacade.mActiveNotifications.size()); |