diff options
author | 2022-04-06 10:17:31 +0000 | |
---|---|---|
committer | 2022-04-07 00:10:48 +0000 | |
commit | 17bdb43b6d79e7550bcfff7eba0f0dc1d947702a (patch) | |
tree | 9742fd953e895bed4452d0f363c6c43ba90dbdbf | |
parent | 9fc61018e915e3474a860585dcac290fafd262bc (diff) |
Add schema validation to custom lint check
Test: atest ConfigLintCheckerTest --host
Test: m
out/soong/.intermediates/packages/modules/Permission/SafetyCenter/Resources/SafetyCenterResources/android_common/lint/lint-report.html
Bug: 220722371
Change-Id: Ia778bb86b33e0aeabc3c0949aa51d7c418df4024
-rw-r--r-- | SafetyCenter/ConfigLintChecker/Android.bp | 1 | ||||
-rw-r--r-- | SafetyCenter/ConfigLintChecker/java/android/safetycenter/lint/ConfigLintCheckerIssueRegistry.kt | 1 | ||||
-rw-r--r-- | SafetyCenter/ConfigLintChecker/java/android/safetycenter/lint/ConfigSchemaDetector.kt | 86 | ||||
-rw-r--r-- | SafetyCenter/ConfigLintChecker/tests/java/android/safetycenter/lint/test/ConfigSchemaDetectorTest.kt | 79 | ||||
-rw-r--r-- | framework-s/Android.bp | 7 | ||||
-rw-r--r-- | framework-s/java/android/safetycenter/config/safety_center_config.xsd (renamed from SafetyCenter/Config/safety_center_config.xsd) | 16 |
6 files changed, 182 insertions, 8 deletions
diff --git a/SafetyCenter/ConfigLintChecker/Android.bp b/SafetyCenter/ConfigLintChecker/Android.bp index 4b5053f19..0206af797 100644 --- a/SafetyCenter/ConfigLintChecker/Android.bp +++ b/SafetyCenter/ConfigLintChecker/Android.bp @@ -33,6 +33,7 @@ java_library_host { "layoutlib_api-prebuilt", // For com.android.resources.ResourceFolderType "lint_api", ], + java_resources: [":safetycenter-config-schema"], jarjar_rules: "jarjar-rules.txt", } diff --git a/SafetyCenter/ConfigLintChecker/java/android/safetycenter/lint/ConfigLintCheckerIssueRegistry.kt b/SafetyCenter/ConfigLintChecker/java/android/safetycenter/lint/ConfigLintCheckerIssueRegistry.kt index 536769160..8b9148dfb 100644 --- a/SafetyCenter/ConfigLintChecker/java/android/safetycenter/lint/ConfigLintCheckerIssueRegistry.kt +++ b/SafetyCenter/ConfigLintChecker/java/android/safetycenter/lint/ConfigLintCheckerIssueRegistry.kt @@ -25,6 +25,7 @@ import com.google.auto.service.AutoService @Suppress("UnstableApiUsage") class ConfigLintCheckerIssueRegistry : IssueRegistry() { override val issues = listOf( + ConfigSchemaDetector.ISSUE, ParserExceptionDetector.ISSUE ) diff --git a/SafetyCenter/ConfigLintChecker/java/android/safetycenter/lint/ConfigSchemaDetector.kt b/SafetyCenter/ConfigLintChecker/java/android/safetycenter/lint/ConfigSchemaDetector.kt new file mode 100644 index 000000000..ed58e5341 --- /dev/null +++ b/SafetyCenter/ConfigLintChecker/java/android/safetycenter/lint/ConfigSchemaDetector.kt @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2022 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.safetycenter.lint + +import com.android.resources.ResourceFolderType +import com.android.tools.lint.detector.api.Category +import com.android.tools.lint.detector.api.Context +import com.android.tools.lint.detector.api.Detector +import com.android.tools.lint.detector.api.Implementation +import com.android.tools.lint.detector.api.Issue +import com.android.tools.lint.detector.api.Location +import com.android.tools.lint.detector.api.OtherFileScanner +import com.android.tools.lint.detector.api.Scope +import com.android.tools.lint.detector.api.Severity +import java.io.IOException +import javax.xml.XMLConstants +import javax.xml.transform.stream.StreamSource +import javax.xml.validation.SchemaFactory +import org.xml.sax.SAXException + +/** Lint check for detecting invalid Safety Center configs */ +class ConfigSchemaDetector : Detector(), OtherFileScanner { + + companion object { + val ISSUE = Issue.create( + id = "InvalidSafetyCenterConfigSchema", + briefDescription = "The Safety Center config does not meet the schema requirements", + explanation = """The Safety Center config must follow all constraints defined in \ + safety_center_config.xsd. Either the config is invalid or the schema is not up to + date.""", + category = Category.CORRECTNESS, + severity = Severity.ERROR, + implementation = Implementation( + ConfigSchemaDetector::class.java, + Scope.OTHER_SCOPE + ), + androidSpecific = true + ) + } + + override fun appliesTo(folderType: ResourceFolderType): Boolean { + return folderType == ResourceFolderType.RAW + } + + override fun run(context: Context) { + if (context.file.name != "safety_center_config.xml") { + return + } + val xsd = StreamSource( + ConfigSchemaDetector::class.java.getResourceAsStream("/safety_center_config.xsd") + ) + val xml = StreamSource(context.file.inputStream()) + val schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI) + try { + val schema = schemaFactory.newSchema(xsd) + val validator = schema.newValidator() + validator.validate(xml) + } catch (e: SAXException) { + context.report( + ISSUE, + Location.create(context.file), + e.message!! + ) + } catch (e: IOException) { + context.report( + ISSUE, + Location.create(context.file), + e.message!! + ) + } + } +}
\ No newline at end of file diff --git a/SafetyCenter/ConfigLintChecker/tests/java/android/safetycenter/lint/test/ConfigSchemaDetectorTest.kt b/SafetyCenter/ConfigLintChecker/tests/java/android/safetycenter/lint/test/ConfigSchemaDetectorTest.kt new file mode 100644 index 000000000..0dd4afbd2 --- /dev/null +++ b/SafetyCenter/ConfigLintChecker/tests/java/android/safetycenter/lint/test/ConfigSchemaDetectorTest.kt @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2022 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.safetycenter.lint.test + +import android.safetycenter.lint.ConfigSchemaDetector +import com.android.tools.lint.checks.infrastructure.LintDetectorTest +import com.android.tools.lint.checks.infrastructure.TestLintTask +import com.android.tools.lint.detector.api.Detector +import com.android.tools.lint.detector.api.Issue +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 + +@Suppress("UnstableApiUsage") +@RunWith(JUnit4::class) +class ConfigSchemaDetectorTest : LintDetectorTest() { + override fun getDetector(): Detector = ConfigSchemaDetector() + + override fun getIssues(): List<Issue> = listOf(ConfigSchemaDetector.ISSUE) + + override fun lint(): TestLintTask = super.lint().allowMissingSdk(true) + + @Test + fun validConfig_doesNotThrow() { + lint().files(( + xml("res/raw/safety_center_config.xml", + """ +<safety-center-config> + <safety-sources-config> + <safety-sources-group + id="group" + title="@package:string/reference" + summary="@package:string/reference"> + <static-safety-source + id="source" + title="@package:string/reference" + summary="@package:string/reference" + intentAction="intent" + profile="primary_profile_only"/> + </safety-sources-group> + </safety-sources-config> +</safety-center-config> + """))).run().expectClean() + } + + @Test + fun invalidConfig_throws() { + lint().files((xml("res/raw/safety_center_config.xml", "<invalid-root/>"))) + .run().expect("res/raw/safety_center_config.xml: Error: cvc-elt.1.a: Cannot find the " + + "declaration of element 'invalid-root'. [InvalidSafetyCenterConfigSchema]\n1 " + + "errors, 0 warnings") + } + + @Test + fun unrelatedFile_doesNotThrow() { + lint().files((xml("res/raw/some_other_config.xml", "<some-other-root/>"))) + .run().expectClean() + } + + @Test + fun unrelatedFolder_doesNotThrow() { + lint().files((xml("res/values/strings.xml", "<some-other-root/>"))) + .run().expectClean() + } +} diff --git a/framework-s/Android.bp b/framework-s/Android.bp index 6be71d416..ec33f13ee 100644 --- a/framework-s/Android.bp +++ b/framework-s/Android.bp @@ -33,6 +33,13 @@ filegroup { visibility: ["//packages/modules/Permission/SafetyCenter/ConfigLintChecker"], } +filegroup { + name: "safetycenter-config-schema", + srcs: ["java/android/safetycenter/config/safety_center_config.xsd"], + path: "java/android/safetycenter/config/", + visibility: ["//packages/modules/Permission/SafetyCenter/ConfigLintChecker"], +} + java_library { name: "framework-permission-s-shared", srcs: [":framework-permission-s-shared-srcs"], diff --git a/SafetyCenter/Config/safety_center_config.xsd b/framework-s/java/android/safetycenter/config/safety_center_config.xsd index 5a3576dd5..1c5590c58 100644 --- a/SafetyCenter/Config/safety_center_config.xsd +++ b/framework-s/java/android/safetycenter/config/safety_center_config.xsd @@ -54,13 +54,13 @@ <xsd:attribute name="packageName" type="xsd:string" use="required"/> <!-- title is required if initialDisplayState is not set to hidden --> <!-- title is prohibited if initialDisplayState is set to hidden --> - <xsd:attribute name="title" type="xsd:string"/> + <xsd:attribute name="title" type="stringResourceName"/> <!-- titleForWork is required if profile is set to all_profiles and initialDisplayState is not set to hidden --> <!-- titleForWork is prohibited if profile is set to primary_profile_only or initialDisplayState is set to hidden --> - <xsd:attribute name="titleForWork" type="xsd:string"/> + <xsd:attribute name="titleForWork" type="stringResourceName"/> <!-- summary is required if initialDisplayState is not set to hidden --> <!-- summary is prohibited if initialDisplayState is set to hidden --> - <xsd:attribute name="summary" type="xsd:string"/> + <xsd:attribute name="summary" type="stringResourceName"/> <!-- intentAction is required if initialDisplayState is set to enabled --> <!-- intentAction is optional if initialDisplayState is set to disabled --> <!-- intentAction is prohibited if initialDisplayState is set to hidden --> @@ -68,7 +68,7 @@ <xsd:attribute name="profile" type="profile" use="required"/> <xsd:attribute name="initialDisplayState" type="initialDisplayState" default="enabled"/> <xsd:attribute name="maxSeverityLevel" type="xsd:int" default="2147483647"/> - <xsd:attribute name="searchTerms" type="xsd:string"/> + <xsd:attribute name="searchTerms" type="stringResourceName"/> <xsd:attribute name="loggingAllowed" type="xsd:boolean" default="true"/> <xsd:attribute name="refreshOnPageOpenAllowed" type="xsd:boolean" default="false"/> </xsd:complexType> @@ -86,14 +86,14 @@ <xsd:complexType name="static-safety-source"> <!-- id must be unique among safety sources --> <xsd:attribute name="id" type="xsd:string" use="required"/> - <xsd:attribute name="title" type="xsd:string" use="required"/> + <xsd:attribute name="title" type="stringResourceName" use="required"/> <!-- titleForWork is required if profile is set to all_profiles --> <!-- titleForWork is prohibited if profile is set to primary_profile_only --> - <xsd:attribute name="titleForWork" type="xsd:string"/> - <xsd:attribute name="summary" type="xsd:string" use="required"/> + <xsd:attribute name="titleForWork" type="stringResourceName"/> + <xsd:attribute name="summary" type="stringResourceName" use="required"/> <xsd:attribute name="intentAction" type="xsd:string" use="required"/> <xsd:attribute name="profile" type="profile" use="required"/> - <xsd:attribute name="searchTerms" type="xsd:string"/> + <xsd:attribute name="searchTerms" type="stringResourceName"/> </xsd:complexType> <xsd:simpleType name="statelessIconType"> |