diff --git a/urbanairship-core/src/main/java/com/urbanairship/iam/AudienceChecks.java b/urbanairship-core/src/main/java/com/urbanairship/iam/AudienceChecks.java index 09cc5aea6..c5cd71e72 100644 --- a/urbanairship-core/src/main/java/com/urbanairship/iam/AudienceChecks.java +++ b/urbanairship-core/src/main/java/com/urbanairship/iam/AudienceChecks.java @@ -9,13 +9,17 @@ import android.support.v4.os.ConfigurationCompat; import android.support.v4.os.LocaleListCompat; +import com.urbanairship.Logger; import com.urbanairship.UAirship; import com.urbanairship.util.VersionUtils; import com.urbanairship.location.UALocationManager; import com.urbanairship.push.PushManager; import com.urbanairship.util.UAStringUtil; +import java.util.ArrayList; import java.util.Arrays; +import java.util.HashSet; +import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; @@ -143,6 +147,26 @@ private static boolean isAppVersionConditionMet(@NonNull Audience audience) { return audience.getVersionPredicate().apply(VersionUtils.createVersionObject()); } + private static Set sanitizeLanguageTags(List languageTags) { + HashSet sanitizedLanguageTags = new HashSet<>(); + + for (String languageTag : languageTags) { + // Remove trailing dashes and underscores + if (!UAStringUtil.isEmpty(languageTag)) { + if (languageTag.endsWith("_") || languageTag.endsWith("-")) { + Logger.debug("Sanitizing malformed language tag: " + languageTag); + sanitizedLanguageTags.add(languageTag.substring(0, languageTag.length() - 1)); + } else { + sanitizedLanguageTags.add(languageTag); + } + } + } + + // Remove duplicates + return sanitizedLanguageTags; + } + + /** * Helper method to check the locales. * @@ -166,23 +190,29 @@ private static boolean isLocaleConditionMet(@NonNull Context context, @NonNull A // getFirstMatch will return the default language if none of the specified locales are found, // so we still have to verify the locale exists in the audience conditions - String tags = UAStringUtil.join(audience.getLanguageTags(), ","); - LocaleListCompat audienceLocales = LocaleListCompat.forLanguageTags(tags); - for (int i = 0; i < audienceLocales.size(); i++) { - Locale audienceLocale = audienceLocales.get(i); + // Sanitize language tags in case any happen to be malformed + Set languageTags = sanitizeLanguageTags(audience.getLanguageTags()); - if (!locale.getLanguage().equals(audienceLocale.getLanguage())) { - continue; - } + try { + String joinedTags = UAStringUtil.join(languageTags, ","); + LocaleListCompat audienceLocales = LocaleListCompat.forLanguageTags(joinedTags); + for (int i = 0; i < audienceLocales.size(); i++) { + Locale audienceLocale = audienceLocales.get(i); - if (!UAStringUtil.isEmpty(audienceLocale.getCountry()) && !audienceLocale.getCountry().equals(locale.getCountry())) { - continue; - } + if (!locale.getLanguage().equals(audienceLocale.getLanguage())) { + continue; + } - return true; + if (!UAStringUtil.isEmpty(audienceLocale.getCountry()) && !audienceLocale.getCountry().equals(locale.getCountry())) { + continue; + } + + return true; + } + } catch (Exception e) { + Logger.error("Unable to construct locale list: ", e); } return false; } - } diff --git a/urbanairship-core/src/test/java/com/urbanairship/iam/AudienceChecksTest.java b/urbanairship-core/src/test/java/com/urbanairship/iam/AudienceChecksTest.java index b79513b45..90aa90292 100644 --- a/urbanairship-core/src/test/java/com/urbanairship/iam/AudienceChecksTest.java +++ b/urbanairship-core/src/test/java/com/urbanairship/iam/AudienceChecksTest.java @@ -27,6 +27,7 @@ import java.util.Set; import static com.urbanairship.iam.tags.TestUtils.tagSet; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; @@ -222,4 +223,18 @@ public void testAppVersion() { when(applicationMetrics.getCurrentAppVersion()).thenReturn(3); assertFalse(AudienceChecks.checkAudience(context, audience)); } + + @Test + public void testSanitizeLocalesInChecks() { + Audience audience = Audience.newBuilder() + .addLanguageTag("en-") + .addLanguageTag("en_") + .addLanguageTag("en") + .addLanguageTag("-") + .addLanguageTag("_") + .addLanguageTag("") + .build(); + + assertTrue(AudienceChecks.checkAudience(context, audience)); + } } \ No newline at end of file