@Test public void testAutocryptStatus_noData() throws Exception { Cursor cursor = contentResolver.query( AutocryptStatus.CONTENT_URI, new String[] { AutocryptStatus.ADDRESS, AutocryptStatus.UID_KEY_STATUS, AutocryptStatus.UID_ADDRESS, AutocryptStatus.AUTOCRYPT_PEER_STATE, AutocryptStatus.AUTOCRYPT_KEY_STATUS }, null, new String [] { AUTOCRYPT_PEER }, null ); assertNotNull(cursor); assertTrue(cursor.moveToFirst()); assertEquals("tid", cursor.getString(0)); assertEquals(KeychainExternalContract.KEY_STATUS_UNAVAILABLE, cursor.getInt(1)); assertEquals(null, cursor.getString(2)); assertEquals(AutocryptStatus.AUTOCRYPT_PEER_DISABLED, cursor.getInt(3)); assertTrue(cursor.isNull(4)); assertFalse(cursor.moveToNext()); }
@Override public Cursor query(@NonNull Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { Timber.v("query(uri=" + uri + ", proj=" + Arrays.toString(projection) + ")"); Context context = getContext(); if (context == null) { throw new IllegalStateException(); } String callingPackageName = apiPermissionHelper.getCurrentCallingPackage(); int match = uriMatcher.match(uri); switch (match) { case EMAIL_STATUS: { Toast.makeText(context, "This API is no longer supported by OpenKeychain!", Toast.LENGTH_SHORT).show(); return new MatrixCursor(projection); } case AUTOCRYPT_STATUS_INTERNAL: if (!BuildConfig.APPLICATION_ID.equals(callingPackageName)) { throw new AccessControlException("This URI can only be called internally!"); } callingPackageName = uri.getLastPathSegment(); case AUTOCRYPT_STATUS: { boolean callerIsAllowed = (match == AUTOCRYPT_STATUS_INTERNAL) || apiPermissionHelper.isAllowedIgnoreErrors(); if (!callerIsAllowed) { throw new AccessControlException("An application must register before use of KeychainExternalProvider!"); } if (projection == null) { throw new IllegalArgumentException("Please provide a projection!"); } List<String> plist = Arrays.asList(projection); boolean isWildcardSelector = selectionArgs.length == 1 && selectionArgs[0].contains("%"); boolean queriesUidResult = plist.contains(AutocryptStatus.UID_KEY_STATUS) || plist.contains(AutocryptStatus.UID_ADDRESS) || plist.contains(AutocryptStatus.UID_MASTER_KEY_ID) || plist.contains(AutocryptStatus.UID_CANDIDATES); boolean queriesAutocryptResult = plist.contains(AutocryptStatus.AUTOCRYPT_PEER_STATE) || plist.contains(AutocryptStatus.AUTOCRYPT_MASTER_KEY_ID) || plist.contains(AutocryptStatus.AUTOCRYPT_KEY_STATUS); if (isWildcardSelector && queriesAutocryptResult) { throw new UnsupportedOperationException("Cannot wildcard-query autocrypt results!"); } Map<String, UidStatus> uidStatuses = queriesUidResult ? loadUidStatusMap(selectionArgs, isWildcardSelector) : Collections.emptyMap(); Map<String, AutocryptRecommendationResult> autocryptStates = queriesAutocryptResult ? loadAutocryptRecommendationMap(selectionArgs, callingPackageName) : Collections.emptyMap(); MatrixCursor cursor = mapResultsToProjectedMatrixCursor(projection, selectionArgs, uidStatuses, autocryptStates); uri = DatabaseNotifyManager.getNotifyUriAllKeys(); cursor.setNotificationUri(context.getContentResolver(), uri); return cursor; } default: { throw new IllegalArgumentException("Unknown URI " + uri + " (" + match + ")"); } } }
KeychainExternalProvider extends ContentProvider { @Override public Cursor query(@NonNull Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { Timber.v("query(uri=" + uri + ", proj=" + Arrays.toString(projection) + ")"); Context context = getContext(); if (context == null) { throw new IllegalStateException(); } String callingPackageName = apiPermissionHelper.getCurrentCallingPackage(); int match = uriMatcher.match(uri); switch (match) { case EMAIL_STATUS: { Toast.makeText(context, "This API is no longer supported by OpenKeychain!", Toast.LENGTH_SHORT).show(); return new MatrixCursor(projection); } case AUTOCRYPT_STATUS_INTERNAL: if (!BuildConfig.APPLICATION_ID.equals(callingPackageName)) { throw new AccessControlException("This URI can only be called internally!"); } callingPackageName = uri.getLastPathSegment(); case AUTOCRYPT_STATUS: { boolean callerIsAllowed = (match == AUTOCRYPT_STATUS_INTERNAL) || apiPermissionHelper.isAllowedIgnoreErrors(); if (!callerIsAllowed) { throw new AccessControlException("An application must register before use of KeychainExternalProvider!"); } if (projection == null) { throw new IllegalArgumentException("Please provide a projection!"); } List<String> plist = Arrays.asList(projection); boolean isWildcardSelector = selectionArgs.length == 1 && selectionArgs[0].contains("%"); boolean queriesUidResult = plist.contains(AutocryptStatus.UID_KEY_STATUS) || plist.contains(AutocryptStatus.UID_ADDRESS) || plist.contains(AutocryptStatus.UID_MASTER_KEY_ID) || plist.contains(AutocryptStatus.UID_CANDIDATES); boolean queriesAutocryptResult = plist.contains(AutocryptStatus.AUTOCRYPT_PEER_STATE) || plist.contains(AutocryptStatus.AUTOCRYPT_MASTER_KEY_ID) || plist.contains(AutocryptStatus.AUTOCRYPT_KEY_STATUS); if (isWildcardSelector && queriesAutocryptResult) { throw new UnsupportedOperationException("Cannot wildcard-query autocrypt results!"); } Map<String, UidStatus> uidStatuses = queriesUidResult ? loadUidStatusMap(selectionArgs, isWildcardSelector) : Collections.emptyMap(); Map<String, AutocryptRecommendationResult> autocryptStates = queriesAutocryptResult ? loadAutocryptRecommendationMap(selectionArgs, callingPackageName) : Collections.emptyMap(); MatrixCursor cursor = mapResultsToProjectedMatrixCursor(projection, selectionArgs, uidStatuses, autocryptStates); uri = DatabaseNotifyManager.getNotifyUriAllKeys(); cursor.setNotificationUri(context.getContentResolver(), uri); return cursor; } default: { throw new IllegalArgumentException("Unknown URI " + uri + " (" + match + ")"); } } } }
KeychainExternalProvider extends ContentProvider { @Override public Cursor query(@NonNull Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { Timber.v("query(uri=" + uri + ", proj=" + Arrays.toString(projection) + ")"); Context context = getContext(); if (context == null) { throw new IllegalStateException(); } String callingPackageName = apiPermissionHelper.getCurrentCallingPackage(); int match = uriMatcher.match(uri); switch (match) { case EMAIL_STATUS: { Toast.makeText(context, "This API is no longer supported by OpenKeychain!", Toast.LENGTH_SHORT).show(); return new MatrixCursor(projection); } case AUTOCRYPT_STATUS_INTERNAL: if (!BuildConfig.APPLICATION_ID.equals(callingPackageName)) { throw new AccessControlException("This URI can only be called internally!"); } callingPackageName = uri.getLastPathSegment(); case AUTOCRYPT_STATUS: { boolean callerIsAllowed = (match == AUTOCRYPT_STATUS_INTERNAL) || apiPermissionHelper.isAllowedIgnoreErrors(); if (!callerIsAllowed) { throw new AccessControlException("An application must register before use of KeychainExternalProvider!"); } if (projection == null) { throw new IllegalArgumentException("Please provide a projection!"); } List<String> plist = Arrays.asList(projection); boolean isWildcardSelector = selectionArgs.length == 1 && selectionArgs[0].contains("%"); boolean queriesUidResult = plist.contains(AutocryptStatus.UID_KEY_STATUS) || plist.contains(AutocryptStatus.UID_ADDRESS) || plist.contains(AutocryptStatus.UID_MASTER_KEY_ID) || plist.contains(AutocryptStatus.UID_CANDIDATES); boolean queriesAutocryptResult = plist.contains(AutocryptStatus.AUTOCRYPT_PEER_STATE) || plist.contains(AutocryptStatus.AUTOCRYPT_MASTER_KEY_ID) || plist.contains(AutocryptStatus.AUTOCRYPT_KEY_STATUS); if (isWildcardSelector && queriesAutocryptResult) { throw new UnsupportedOperationException("Cannot wildcard-query autocrypt results!"); } Map<String, UidStatus> uidStatuses = queriesUidResult ? loadUidStatusMap(selectionArgs, isWildcardSelector) : Collections.emptyMap(); Map<String, AutocryptRecommendationResult> autocryptStates = queriesAutocryptResult ? loadAutocryptRecommendationMap(selectionArgs, callingPackageName) : Collections.emptyMap(); MatrixCursor cursor = mapResultsToProjectedMatrixCursor(projection, selectionArgs, uidStatuses, autocryptStates); uri = DatabaseNotifyManager.getNotifyUriAllKeys(); cursor.setNotificationUri(context.getContentResolver(), uri); return cursor; } default: { throw new IllegalArgumentException("Unknown URI " + uri + " (" + match + ")"); } } }  }
KeychainExternalProvider extends ContentProvider { @Override public Cursor query(@NonNull Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { Timber.v("query(uri=" + uri + ", proj=" + Arrays.toString(projection) + ")"); Context context = getContext(); if (context == null) { throw new IllegalStateException(); } String callingPackageName = apiPermissionHelper.getCurrentCallingPackage(); int match = uriMatcher.match(uri); switch (match) { case EMAIL_STATUS: { Toast.makeText(context, "This API is no longer supported by OpenKeychain!", Toast.LENGTH_SHORT).show(); return new MatrixCursor(projection); } case AUTOCRYPT_STATUS_INTERNAL: if (!BuildConfig.APPLICATION_ID.equals(callingPackageName)) { throw new AccessControlException("This URI can only be called internally!"); } callingPackageName = uri.getLastPathSegment(); case AUTOCRYPT_STATUS: { boolean callerIsAllowed = (match == AUTOCRYPT_STATUS_INTERNAL) || apiPermissionHelper.isAllowedIgnoreErrors(); if (!callerIsAllowed) { throw new AccessControlException("An application must register before use of KeychainExternalProvider!"); } if (projection == null) { throw new IllegalArgumentException("Please provide a projection!"); } List<String> plist = Arrays.asList(projection); boolean isWildcardSelector = selectionArgs.length == 1 && selectionArgs[0].contains("%"); boolean queriesUidResult = plist.contains(AutocryptStatus.UID_KEY_STATUS) || plist.contains(AutocryptStatus.UID_ADDRESS) || plist.contains(AutocryptStatus.UID_MASTER_KEY_ID) || plist.contains(AutocryptStatus.UID_CANDIDATES); boolean queriesAutocryptResult = plist.contains(AutocryptStatus.AUTOCRYPT_PEER_STATE) || plist.contains(AutocryptStatus.AUTOCRYPT_MASTER_KEY_ID) || plist.contains(AutocryptStatus.AUTOCRYPT_KEY_STATUS); if (isWildcardSelector && queriesAutocryptResult) { throw new UnsupportedOperationException("Cannot wildcard-query autocrypt results!"); } Map<String, UidStatus> uidStatuses = queriesUidResult ? loadUidStatusMap(selectionArgs, isWildcardSelector) : Collections.emptyMap(); Map<String, AutocryptRecommendationResult> autocryptStates = queriesAutocryptResult ? loadAutocryptRecommendationMap(selectionArgs, callingPackageName) : Collections.emptyMap(); MatrixCursor cursor = mapResultsToProjectedMatrixCursor(projection, selectionArgs, uidStatuses, autocryptStates); uri = DatabaseNotifyManager.getNotifyUriAllKeys(); cursor.setNotificationUri(context.getContentResolver(), uri); return cursor; } default: { throw new IllegalArgumentException("Unknown URI " + uri + " (" + match + ")"); } } }  @Override boolean onCreate(); @Override Cursor query(@NonNull Uri uri, String[] projection, String selection, String[] selectionArgs,
                        String sortOrder); @Override String getType(@NonNull Uri uri); @Override Uri insert(@NonNull Uri uri, ContentValues values); @Override int delete(@NonNull Uri uri, String selection, String[] selectionArgs); @Override int update(@NonNull Uri uri, ContentValues values, String selection, String[] selectionArgs); }
KeychainExternalProvider extends ContentProvider { @Override public Cursor query(@NonNull Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) { Timber.v("query(uri=" + uri + ", proj=" + Arrays.toString(projection) + ")"); Context context = getContext(); if (context == null) { throw new IllegalStateException(); } String callingPackageName = apiPermissionHelper.getCurrentCallingPackage(); int match = uriMatcher.match(uri); switch (match) { case EMAIL_STATUS: { Toast.makeText(context, "This API is no longer supported by OpenKeychain!", Toast.LENGTH_SHORT).show(); return new MatrixCursor(projection); } case AUTOCRYPT_STATUS_INTERNAL: if (!BuildConfig.APPLICATION_ID.equals(callingPackageName)) { throw new AccessControlException("This URI can only be called internally!"); } callingPackageName = uri.getLastPathSegment(); case AUTOCRYPT_STATUS: { boolean callerIsAllowed = (match == AUTOCRYPT_STATUS_INTERNAL) || apiPermissionHelper.isAllowedIgnoreErrors(); if (!callerIsAllowed) { throw new AccessControlException("An application must register before use of KeychainExternalProvider!"); } if (projection == null) { throw new IllegalArgumentException("Please provide a projection!"); } List<String> plist = Arrays.asList(projection); boolean isWildcardSelector = selectionArgs.length == 1 && selectionArgs[0].contains("%"); boolean queriesUidResult = plist.contains(AutocryptStatus.UID_KEY_STATUS) || plist.contains(AutocryptStatus.UID_ADDRESS) || plist.contains(AutocryptStatus.UID_MASTER_KEY_ID) || plist.contains(AutocryptStatus.UID_CANDIDATES); boolean queriesAutocryptResult = plist.contains(AutocryptStatus.AUTOCRYPT_PEER_STATE) || plist.contains(AutocryptStatus.AUTOCRYPT_MASTER_KEY_ID) || plist.contains(AutocryptStatus.AUTOCRYPT_KEY_STATUS); if (isWildcardSelector && queriesAutocryptResult) { throw new UnsupportedOperationException("Cannot wildcard-query autocrypt results!"); } Map<String, UidStatus> uidStatuses = queriesUidResult ? loadUidStatusMap(selectionArgs, isWildcardSelector) : Collections.emptyMap(); Map<String, AutocryptRecommendationResult> autocryptStates = queriesAutocryptResult ? loadAutocryptRecommendationMap(selectionArgs, callingPackageName) : Collections.emptyMap(); MatrixCursor cursor = mapResultsToProjectedMatrixCursor(projection, selectionArgs, uidStatuses, autocryptStates); uri = DatabaseNotifyManager.getNotifyUriAllKeys(); cursor.setNotificationUri(context.getContentResolver(), uri); return cursor; } default: { throw new IllegalArgumentException("Unknown URI " + uri + " (" + match + ")"); } } }  @Override boolean onCreate(); @Override Cursor query(@NonNull Uri uri, String[] projection, String selection, String[] selectionArgs,
                        String sortOrder); @Override String getType(@NonNull Uri uri); @Override Uri insert(@NonNull Uri uri, ContentValues values); @Override int delete(@NonNull Uri uri, String selection, String[] selectionArgs); @Override int update(@NonNull Uri uri, ContentValues values, String selection, String[] selectionArgs);  }