Merge "Improve revoking access to content providers."

This commit is contained in:
Dianne Hackborn
2013-01-30 19:09:06 +00:00
committed by Android (Google) Code Review

View File

@ -191,11 +191,8 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
String selection, String[] selectionArgs, String sortOrder, String selection, String[] selectionArgs, String sortOrder,
ICancellationSignal cancellationSignal) { ICancellationSignal cancellationSignal) {
if (enforceReadPermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) { if (enforceReadPermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
// The read is not allowed... to fake it out, we replace the given return rejectQuery(uri, projection, selection, selectionArgs, sortOrder,
// selection statement with a dummy one that will always be false. CancellationSignal.fromTransport(cancellationSignal));
// This way we will get a cursor back that has the correct structure
// but contains no rows.
selection = "'A' = 'B'";
} }
return ContentProvider.this.query(uri, projection, selection, selectionArgs, sortOrder, return ContentProvider.this.query(uri, projection, selection, selectionArgs, sortOrder,
CancellationSignal.fromTransport(cancellationSignal)); CancellationSignal.fromTransport(cancellationSignal));
@ -209,12 +206,7 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
@Override @Override
public Uri insert(String callingPkg, Uri uri, ContentValues initialValues) { public Uri insert(String callingPkg, Uri uri, ContentValues initialValues) {
if (enforceWritePermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) { if (enforceWritePermission(callingPkg, uri) != AppOpsManager.MODE_ALLOWED) {
// If not allowed, we need to return some reasonable URI. Maybe the return rejectInsert(uri, initialValues);
// content provider should be responsible for this, but for now we
// will just return the base URI with a dummy '0' tagged on to it.
// You shouldn't be able to read if you can't write, anyway, so it
// shouldn't matter much what is returned.
return uri.buildUpon().appendPath("0").build();
} }
return ContentProvider.this.insert(uri, initialValues); return ContentProvider.this.insert(uri, initialValues);
} }
@ -591,6 +583,31 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
public void onTrimMemory(int level) { public void onTrimMemory(int level) {
} }
/**
* @hide
* Implementation when a caller has performed a query on the content
* provider, but that call has been rejected for the operation given
* to {@link #setAppOps(int, int)}. The default implementation
* rewrites the <var>selection</var> argument to include a condition
* that is never true (so will always result in an empty cursor)
* and calls through to {@link #query(android.net.Uri, String[], String, String[],
* String, android.os.CancellationSignal)} with that.
*/
public Cursor rejectQuery(Uri uri, String[] projection,
String selection, String[] selectionArgs, String sortOrder,
CancellationSignal cancellationSignal) {
// The read is not allowed... to fake it out, we replace the given
// selection statement with a dummy one that will always be false.
// This way we will get a cursor back that has the correct structure
// but contains no rows.
if (selection == null) {
selection = "'A' = 'B'";
} else {
selection = "'A' = 'B' AND (" + selection + ")";
}
return query(uri, projection, selection, selectionArgs, sortOrder, cancellationSignal);
}
/** /**
* Implement this to handle query requests from clients. * Implement this to handle query requests from clients.
* This method can be called from multiple threads, as described in * This method can be called from multiple threads, as described in
@ -738,6 +755,23 @@ public abstract class ContentProvider implements ComponentCallbacks2 {
*/ */
public abstract String getType(Uri uri); public abstract String getType(Uri uri);
/**
* @hide
* Implementation when a caller has performed an insert on the content
* provider, but that call has been rejected for the operation given
* to {@link #setAppOps(int, int)}. The default implementation simply
* returns a dummy URI that is the base URI with a 0 path element
* appended.
*/
public Uri rejectInsert(Uri uri, ContentValues values) {
// If not allowed, we need to return some reasonable URI. Maybe the
// content provider should be responsible for this, but for now we
// will just return the base URI with a dummy '0' tagged on to it.
// You shouldn't be able to read if you can't write, anyway, so it
// shouldn't matter much what is returned.
return uri.buildUpon().appendPath("0").build();
}
/** /**
* Implement this to handle requests to insert a new row. * Implement this to handle requests to insert a new row.
* As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()} * As a courtesy, call {@link ContentResolver#notifyChange(android.net.Uri ,android.database.ContentObserver) notifyChange()}