diff options
author | TreeHugger Robot <treehugger-gerrit@google.com> | 2017-12-08 16:46:08 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2017-12-08 16:46:08 +0000 |
commit | 76a9d9c0d35e8f9a016322d96e09035906ea791d (patch) | |
tree | 1c2d1f8414f3a26627da9491003af67845637bfc | |
parent | 80059ffc2eaa8f6ca96c331bed99e242bd1d9cd2 (diff) | |
parent | d01cef91b09a74b49b359ae637cb02f985269be9 (diff) |
Merge "Add TestablePermissons, which allows basic control"
3 files changed, 325 insertions, 0 deletions
diff --git a/tests/testables/src/android/testing/TestableContext.java b/tests/testables/src/android/testing/TestableContext.java index 498d517c104b..ffe721993a37 100644 --- a/tests/testables/src/android/testing/TestableContext.java +++ b/tests/testables/src/android/testing/TestableContext.java @@ -25,6 +25,7 @@ import android.content.IntentFilter; import android.content.ServiceConnection; import android.content.pm.PackageManager; import android.content.res.Resources; +import android.net.Uri; import android.os.Handler; import android.os.IBinder; import android.os.UserHandle; @@ -69,6 +70,7 @@ public class TestableContext extends ContextWrapper implements TestRule { private LeakCheck.Tracker mService; private LeakCheck.Tracker mComponent; private TestableResources mTestableResources; + private TestablePermissions mTestablePermissions; public TestableContext(Context base) { this(base, null); @@ -302,6 +304,159 @@ public class TestableContext extends ContextWrapper implements TestRule { super.unregisterComponentCallbacks(callback); } + public TestablePermissions getTestablePermissions() { + if (mTestablePermissions == null) { + mTestablePermissions = new TestablePermissions(); + } + return mTestablePermissions; + } + + @Override + public int checkCallingOrSelfPermission(String permission) { + if (mTestablePermissions != null && mTestablePermissions.wantsCall(permission)) { + return mTestablePermissions.check(permission); + } + return super.checkCallingOrSelfPermission(permission); + } + + @Override + public int checkCallingPermission(String permission) { + if (mTestablePermissions != null && mTestablePermissions.wantsCall(permission)) { + return mTestablePermissions.check(permission); + } + return super.checkCallingPermission(permission); + } + + @Override + public int checkPermission(String permission, int pid, int uid) { + if (mTestablePermissions != null && mTestablePermissions.wantsCall(permission)) { + return mTestablePermissions.check(permission); + } + return super.checkPermission(permission, pid, uid); + } + + @Override + public int checkPermission(String permission, int pid, int uid, IBinder callerToken) { + if (mTestablePermissions != null && mTestablePermissions.wantsCall(permission)) { + return mTestablePermissions.check(permission); + } + return super.checkPermission(permission, pid, uid, callerToken); + } + + @Override + public int checkSelfPermission(String permission) { + if (mTestablePermissions != null && mTestablePermissions.wantsCall(permission)) { + return mTestablePermissions.check(permission); + } + return super.checkSelfPermission(permission); + } + + @Override + public void enforceCallingOrSelfPermission(String permission, String message) { + if (mTestablePermissions != null && mTestablePermissions.wantsCall(permission)) { + mTestablePermissions.enforce(permission); + } else { + super.enforceCallingOrSelfPermission(permission, message); + } + } + + @Override + public void enforceCallingPermission(String permission, String message) { + if (mTestablePermissions != null && mTestablePermissions.wantsCall(permission)) { + mTestablePermissions.enforce(permission); + } else { + super.enforceCallingPermission(permission, message); + } + } + + @Override + public void enforcePermission(String permission, int pid, int uid, String message) { + if (mTestablePermissions != null && mTestablePermissions.wantsCall(permission)) { + mTestablePermissions.enforce(permission); + } else { + super.enforcePermission(permission, pid, uid, message); + } + } + + @Override + public int checkCallingOrSelfUriPermission(Uri uri, int modeFlags) { + if (mTestablePermissions != null && mTestablePermissions.wantsCall(uri)) { + return mTestablePermissions.check(uri, modeFlags); + } + return super.checkCallingOrSelfUriPermission(uri, modeFlags); + } + + @Override + public int checkCallingUriPermission(Uri uri, int modeFlags) { + if (mTestablePermissions != null && mTestablePermissions.wantsCall(uri)) { + return mTestablePermissions.check(uri, modeFlags); + } + return super.checkCallingUriPermission(uri, modeFlags); + } + + @Override + public void enforceCallingOrSelfUriPermission(Uri uri, int modeFlags, String message) { + if (mTestablePermissions != null && mTestablePermissions.wantsCall(uri)) { + mTestablePermissions.enforce(uri, modeFlags); + } else { + super.enforceCallingOrSelfUriPermission(uri, modeFlags, message); + } + } + + @Override + public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags) { + if (mTestablePermissions != null && mTestablePermissions.wantsCall(uri)) { + return mTestablePermissions.check(uri, modeFlags); + } + return super.checkUriPermission(uri, pid, uid, modeFlags); + } + + @Override + public int checkUriPermission(Uri uri, int pid, int uid, int modeFlags, IBinder callerToken) { + if (mTestablePermissions != null && mTestablePermissions.wantsCall(uri)) { + return mTestablePermissions.check(uri, modeFlags); + } + return super.checkUriPermission(uri, pid, uid, modeFlags, callerToken); + } + + @Override + public int checkUriPermission(Uri uri, String readPermission, String writePermission, int pid, + int uid, int modeFlags) { + if (mTestablePermissions != null && mTestablePermissions.wantsCall(uri)) { + return mTestablePermissions.check(uri, modeFlags); + } + return super.checkUriPermission(uri, readPermission, writePermission, pid, uid, modeFlags); + } + + @Override + public void enforceCallingUriPermission(Uri uri, int modeFlags, String message) { + if (mTestablePermissions != null && mTestablePermissions.wantsCall(uri)) { + mTestablePermissions.enforce(uri, modeFlags); + } else { + super.enforceCallingUriPermission(uri, modeFlags, message); + } + } + + @Override + public void enforceUriPermission(Uri uri, int pid, int uid, int modeFlags, String message) { + if (mTestablePermissions != null && mTestablePermissions.wantsCall(uri)) { + mTestablePermissions.enforce(uri, modeFlags); + } else { + super.enforceUriPermission(uri, pid, uid, modeFlags, message); + } + } + + @Override + public void enforceUriPermission(Uri uri, String readPermission, String writePermission, + int pid, int uid, int modeFlags, String message) { + if (mTestablePermissions != null && mTestablePermissions.wantsCall(uri)) { + mTestablePermissions.enforce(uri, modeFlags); + } else { + super.enforceUriPermission(uri, readPermission, writePermission, pid, uid, modeFlags, + message); + } + } + @Override public Statement apply(Statement base, Description description) { return new TestWatcher() { diff --git a/tests/testables/src/android/testing/TestablePermissions.java b/tests/testables/src/android/testing/TestablePermissions.java new file mode 100644 index 000000000000..4f009e406ca7 --- /dev/null +++ b/tests/testables/src/android/testing/TestablePermissions.java @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2017 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 android.testing; + +import android.content.pm.PackageManager; +import android.net.Uri; +import android.util.ArrayMap; + +/** + * Simple class for simulating basic permission states for tests. + * + * All enforce* and check* calls on TestableContext are considered the same + * and routed through the same check here. If more fine-grained control is + * required, then either a sub-class or spy on TestableContext is recommended. + */ +public class TestablePermissions { + + private final ArrayMap<String, Integer> mPermissions = new ArrayMap<>(); + private final ArrayMap<Uri, Integer> mUris = new ArrayMap<>(); + + /** + * Sets the return value for checkPermission* calls on TestableContext + * for a specific permission value. For all enforcePermission* calls + * they will throw a security exception if value != PERMISSION_GRANTED. + */ + public void setPermission(String permission, int value) { + mPermissions.put(permission, value); + } + + /** + * Sets the return value for checkUriPermission* calls on TestableContext + * for a specific permission value. For all enforceUriPermission* calls + * they will throw a security exception if value != PERMISSION_GRANTED. + */ + public void setPermission(Uri uri, int value) { + // TODO: Support modeFlags + mUris.put(uri, value); + } + + boolean wantsCall(String permission) { + return mPermissions.containsKey(permission); + } + + boolean wantsCall(Uri uri) { + return mUris.containsKey(uri); + } + + int check(String permission) { + return mPermissions.get(permission); + } + + int check(Uri uri, int modeFlags) { + // TODO: Support modeFlags + return mUris.get(uri); + } + + public void enforce(String permission) { + if (check(permission) != PackageManager.PERMISSION_GRANTED) { + throw new SecurityException(); + } + } + + public void enforce(Uri uri, int modeFlags) { + if (check(uri, modeFlags) != PackageManager.PERMISSION_GRANTED) { + throw new SecurityException(); + } + } +} diff --git a/tests/testables/tests/src/android/testing/TestablePermissionsTest.java b/tests/testables/tests/src/android/testing/TestablePermissionsTest.java new file mode 100644 index 000000000000..c56146e19a40 --- /dev/null +++ b/tests/testables/tests/src/android/testing/TestablePermissionsTest.java @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2017 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 android.testing; + +import static android.content.pm.PackageManager.PERMISSION_DENIED; +import static android.content.pm.PackageManager.PERMISSION_GRANTED; + +import static org.junit.Assert.assertEquals; + +import android.Manifest.permission; +import android.content.pm.PackageManager; +import android.net.Uri; +import android.support.test.InstrumentationRegistry; +import android.support.test.filters.SmallTest; +import android.testing.TestableLooper.RunWithLooper; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +@SmallTest +@RunWith(AndroidTestingRunner.class) +public class TestablePermissionsTest { + + private static final Uri URI_1 = Uri.parse("content://my.authority/path1"); + private static final Uri URI_2 = Uri.parse("content://my.authority/path2"); + + @Rule + public TestableContext mContext = new TestableContext(InstrumentationRegistry.getContext()); + + @Test + public void testCheck() { + mContext.getTestablePermissions().setPermission(permission.INTERACT_ACROSS_USERS, + PERMISSION_GRANTED); + mContext.getTestablePermissions().setPermission(permission.INTERACT_ACROSS_USERS_FULL, + PERMISSION_DENIED); + assertEquals(PERMISSION_GRANTED, + mContext.checkPermission(permission.INTERACT_ACROSS_USERS, 0, 0)); + assertEquals(PERMISSION_DENIED, + mContext.checkPermission(permission.INTERACT_ACROSS_USERS_FULL, 0, 0)); + } + + @Test + public void testCheckUri() { + mContext.getTestablePermissions().setPermission(URI_1, PERMISSION_GRANTED); + mContext.getTestablePermissions().setPermission(URI_2, PERMISSION_DENIED); + + assertEquals(PERMISSION_GRANTED, mContext.checkUriPermission(URI_1, 0, 0, 0)); + assertEquals(PERMISSION_DENIED, mContext.checkUriPermission(URI_2, 0, 0, 0)); + } + + @Test + public void testEnforceNoException() { + mContext.getTestablePermissions().setPermission(permission.INTERACT_ACROSS_USERS, + PERMISSION_GRANTED); + mContext.enforceCallingOrSelfPermission(permission.INTERACT_ACROSS_USERS, ""); + } + + @Test(expected = SecurityException.class) + public void testEnforceWithException() { + mContext.getTestablePermissions().setPermission(permission.INTERACT_ACROSS_USERS, + PERMISSION_DENIED); + mContext.enforceCallingOrSelfPermission(permission.INTERACT_ACROSS_USERS, ""); + } + + @Test + public void testEnforceUriNoException() { + mContext.getTestablePermissions().setPermission(URI_1, PERMISSION_GRANTED); + mContext.enforceUriPermission(URI_1, 0, 0, 0, ""); + } + + @Test(expected = SecurityException.class) + public void testEnforceUriWithException() { + mContext.getTestablePermissions().setPermission(URI_1, PERMISSION_DENIED); + mContext.enforceUriPermission(URI_1, 0, 0, 0, ""); + } + +}
\ No newline at end of file |