Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- Rule EC533 google ads consent

### Changed
- SPRI004: Add rule to avoid use of Tracking Id using TelephonyManager#getDeviceId()
- The embedded Groovy language analyzer was reconfigured to scan only `.gradle` files since it is the files we are interested in for
Expand Down
5 changes: 5 additions & 0 deletions android-plugin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ cd /codenarc-converter/CodeNarc
./gradlew build -x test
```

```sh
cd .\codenarc-converter\CodeNarc\

```

Add custom CodeNarc to Maven dependencies:

```sh
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import io.ecocode.java.checks.environment.power.ChargeAwarenessRule;
import io.ecocode.java.checks.environment.power.SaveModeAwarenessRule;
import io.ecocode.java.checks.environment.sobriety.*;
import io.ecocode.java.checks.social.gdpr.GoogleAndroidAdsConsentRule;
import io.ecocode.java.checks.social.privacy.GoogleTrackerRule;
import io.ecocode.java.checks.social.privacy.TrackingIdRule;
import org.sonar.plugins.java.api.JavaCheck;
Expand All @@ -54,7 +55,8 @@ public static List<Class<? extends JavaCheck>> getChecks() {
public static List<Class<? extends JavaCheck>> getJavaSocialChecks() {
return Collections.unmodifiableList(Arrays.asList(
GoogleTrackerRule.class,
TrackingIdRule.class
TrackingIdRule.class,
GoogleAndroidAdsConsentRule.class
));
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package io.ecocode.java.checks.social.gdpr;

import io.ecocode.java.checks.helpers.TreeHelper;
import org.sonar.check.Rule;
import org.sonar.plugins.java.api.JavaFileScanner;
import org.sonar.plugins.java.api.JavaFileScannerContext;
import org.sonar.plugins.java.api.tree.*;
import org.sonarsource.analyzer.commons.annotations.DeprecatedRuleKey;

/**
* Check the presence of the import com.google.android.ads.consent
* or com.google.android.ump:user-messaging-platform
* <p>
* To support publishers in meeting their duties under the EU User Consent Policy, Google offers a Consent SDK.
* Hence, importing classes from com.google.android.ads.consent or com.google.android.ump:user-messaging-platform is considered as a good practice.
*/
@Rule(key = "EC533", name = "GDPR: Google Consent")
@DeprecatedRuleKey(repositoryKey = "ecoCode-java", ruleKey = "SGDP001")
public class GoogleAndroidAdsConsentRule extends BaseTreeVisitor implements JavaFileScanner {

private static final String INFO_MESSAGE_GOOGLE_ANDROID_ADS_CONSENT_USED = "Good Smell : User Consent";

@Override
public void scanFile(JavaFileScannerContext context) {
CompilationUnitTree cut = context.getTree();

GoogleAndroidAdsConsentImports googleTrackerImport = new GoogleAndroidAdsConsentImports();

boolean isGoogleAdsConsentImported = false;
for (ImportClauseTree importClauseTree : cut.imports()) {
ImportTree importTree = null;

if (importClauseTree.is(Tree.Kind.IMPORT)) {
importTree = (ImportTree) importClauseTree;
}

if (importTree == null) {
continue;
}

if (googleTrackerImport.verifyImportGoogleAdsConsent(importTree)) {
isGoogleAdsConsentImported = true;
break;
}
}

if (isGoogleAdsConsentImported) {
context.addIssueOnProject(this, INFO_MESSAGE_GOOGLE_ANDROID_ADS_CONSENT_USED);
}

scan(cut);
}


/**
* Deprecated : com.google.android.ads.consent
* <p>
* Android 5.0 (API 21) : com.google.android.ump:user-messaging-platform
*/
private static class GoogleAndroidAdsConsentImports {
private static final String STR_GOOGLE_ADS_CONSENT_IMPORT = "com.google.android.ads.consent";
private static final String STR_GOOGLE_ADS_UMP_CONSENT_IMPORT = "com.google.android.ump";

public boolean verifyImportGoogleAdsConsent(ImportTree importTree) {
String importName = TreeHelper.fullQualifiedName(importTree.qualifiedIdentifier());
return importName.startsWith(STR_GOOGLE_ADS_CONSENT_IMPORT) || importName.startsWith(STR_GOOGLE_ADS_UMP_CONSENT_IMPORT);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"EC530",
"EC531",
"EC532",
"EC533",
"EC534"
]
}
10 changes: 10 additions & 0 deletions android-plugin/src/main/resources/io/ecocode/rules/java/EC533.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<img src="http://www.neomades.com/extern/partage/ecoCode/5sur5_1x.png">
<p>
Good Practice !
User consent checked.
</p>
<p>
To support publishers in meeting their duties under the EU User Consent Policy, Google offers a Consent SDK.
Hence, importing classes from <code>com.google.android.ads.consent.*</code> or <code>com.google.android.ump.*</code>
since Android API 21 is considered as a good practice.
</p>
17 changes: 17 additions & 0 deletions android-plugin/src/main/resources/io/ecocode/rules/java/EC533.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"title": "GDPR: Google Consent",
"type": "CODE_SMELL",
"status": "ready",
"remediation": {
"func": "Constant\/Issue",
"constantCost": "0min"
},
"tags": [
"gdpr",
"social",
"ecocode",
"android",
"eco-design"
],
"defaultSeverity": "Info"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import com.google.android.ads.consent.Test;

public class Test {
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,12 @@ private void assertSocialRuleProperties(Repository repository) {
assertThat(trackIdRule.name()).isEqualTo("Privacy: Tracking Id");
assertThat(trackIdRule.debtRemediationFunction().type()).isEqualTo(Type.CONSTANT_ISSUE);
assertThat(trackIdRule.type()).isEqualTo(RuleType.CODE_SMELL);

Rule googleConsentRule = repository.rule("EC533");
assertThat(googleConsentRule).isNotNull();
assertThat(googleConsentRule.name()).isEqualTo("GDPR: Google Consent");
assertThat(googleConsentRule.debtRemediationFunction().type()).isEqualTo(Type.CONSTANT_ISSUE);
assertThat(googleConsentRule.type()).isEqualTo(RuleType.CODE_SMELL);
}

private void assertEnergyRuleProperties(Repository repository) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package io.ecocode.java.checks.social.gdpr;

import org.junit.Test;
import org.sonar.java.checks.verifier.CheckVerifier;

public class GoogleAndroidAdsConsentRuleTest {
@Test
public void verify() {

CheckVerifier.newVerifier().onFile("src/test/files/social/privacy/GoogleTrackerGoogleCheck.java")
.withCheck(new GoogleAndroidAdsConsentRule())
.verifyNoIssues();
CheckVerifier.newVerifier().onFile("src/test/files/social/gdpr/GoogleAndroidAdsConsentCheck.java")
.withCheck(new GoogleAndroidAdsConsentRule())
.verifyIssueOnProject("Good Smell : User Consent");


}
}
2 changes: 1 addition & 1 deletion codenarc-converter/CodeNarc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ CodeNarc requires

## AVAILABLE FROM MAVEN CENTRAL REPOSITORY

For projects built using Gradle or Maven, **CodeNarc** is available from the [Maven Central Repository]((https://mvnrepository.com/artifact/org.codenarc/CodeNarc)).
For projects built using Gradle or Maven, **CodeNarc** is available from the [Maven Central Repository](https://mvnrepository.com/artifact/org.codenarc/CodeNarc).

- groupId = org.codenarc
- artifactId = CodeNarc
Expand Down
Loading