1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.server.pm.test.verify.domain 18 19 import android.content.Intent 20 import android.content.pm.PackageManager 21 import android.net.Uri 22 import com.android.server.pm.verify.domain.DomainVerificationUtils 23 import com.google.common.truth.Truth.assertThat 24 import org.junit.Test 25 import org.junit.runner.RunWith 26 import org.junit.runners.Parameterized 27 28 @RunWith(Parameterized::class) 29 class DomainVerificationValidIntentTest { 30 31 companion object { 32 33 @Parameterized.Parameters(name = "{0}") 34 @JvmStatic 35 fun parameters(): Array<Params> { 36 val succeeding = mutableListOf<Params>() 37 val failing = mutableListOf<Params>() 38 39 // Start with the base intent 40 val base = Params(categorySet = emptySet()).also { succeeding += it } 41 42 // Add all explicit supported categorySet 43 succeeding += base.copy( 44 categorySet = setOf(Intent.CATEGORY_BROWSABLE), 45 matchDefaultOnly = true 46 ) 47 48 failing += base.copy( 49 categorySet = setOf(Intent.CATEGORY_BROWSABLE), 50 matchDefaultOnly = false 51 ) 52 53 succeeding += listOf(true, false).map { 54 base.copy( 55 categorySet = setOf(Intent.CATEGORY_DEFAULT), 56 matchDefaultOnly = it 57 ) 58 } 59 60 succeeding += listOf(true, false).map { 61 base.copy( 62 categorySet = setOf(Intent.CATEGORY_BROWSABLE, Intent.CATEGORY_DEFAULT), 63 matchDefaultOnly = it 64 ) 65 } 66 67 // Fail on unsupported category 68 failing += listOf( 69 emptySet(), 70 setOf(Intent.CATEGORY_BROWSABLE), 71 setOf(Intent.CATEGORY_DEFAULT), 72 setOf(Intent.CATEGORY_BROWSABLE, Intent.CATEGORY_DEFAULT) 73 ).map { base.copy(categorySet = it + "invalid.CATEGORY") } 74 75 // Fail on unsupported action 76 failing += base.copy(action = Intent.ACTION_SEND) 77 78 // Fail on unsupported domain 79 failing += base.copy(domain = "invalid") 80 81 // Fail on empty domains 82 failing += base.copy(domain = "") 83 84 // Fail on missing scheme 85 failing += base.copy( 86 uriFunction = { Uri.Builder().authority("test.com").build() } 87 ) 88 89 // Fail on missing host 90 failing += base.copy( 91 domain = "", 92 uriFunction = { Uri.Builder().scheme("https").build() } 93 ) 94 95 succeeding.forEach { it.expected = true } 96 failing.forEach { it.expected = false } 97 return (succeeding + failing).toTypedArray() 98 } 99 100 data class Params( 101 val action: String = Intent.ACTION_VIEW, 102 val categorySet: Set<String> = mutableSetOf(), 103 val domain: String = "test.com", 104 val matchDefaultOnly: Boolean = true, 105 var expected: Boolean? = null, 106 val uriFunction: (domain: String) -> Uri = { Uri.parse("https://$it") } 107 ) { 108 val intent = Intent(action, uriFunction(domain)).apply { 109 categorySet.forEach(::addCategory) 110 } 111 112 override fun toString() = intent.toShortString(false, false, false, false) + 113 ", matchDefaultOnly = $matchDefaultOnly, expected = $expected" 114 } 115 } 116 117 @Parameterized.Parameter(0) 118 lateinit var params: Params 119 120 @Test 121 fun verify() { 122 val flags = if (params.matchDefaultOnly) PackageManager.MATCH_DEFAULT_ONLY else 0 123 assertThat(DomainVerificationUtils.isDomainVerificationIntent(params.intent, flags)) 124 .isEqualTo(params.expected) 125 } 126 } 127