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