AddonTest.kt (37388B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 package mozilla.components.feature.addons 6 7 import androidx.test.ext.junit.runners.AndroidJUnit4 8 import mozilla.components.browser.engine.gecko.webextension.GeckoWebExtension 9 import mozilla.components.concept.engine.webextension.DisabledFlags 10 import mozilla.components.concept.engine.webextension.Incognito 11 import mozilla.components.concept.engine.webextension.Metadata 12 import mozilla.components.concept.engine.webextension.WebExtension 13 import mozilla.components.feature.addons.Addon.Companion.localizeOptionalPermissions 14 import mozilla.components.support.test.mock 15 import mozilla.components.support.test.robolectric.testContext 16 import mozilla.components.support.test.whenever 17 import org.junit.Assert.assertEquals 18 import org.junit.Assert.assertFalse 19 import org.junit.Assert.assertNotNull 20 import org.junit.Assert.assertNull 21 import org.junit.Assert.assertTrue 22 import org.junit.Test 23 import org.junit.runner.RunWith 24 25 @RunWith(AndroidJUnit4::class) 26 class AddonTest { 27 28 @Test 29 fun `translatePermissions - must return the expected string ids per permission category`() { 30 val addon = Addon( 31 id = "id", 32 downloadUrl = "downloadUrl", 33 version = "version", 34 permissions = listOf( 35 "bookmarks", 36 "browserSettings", 37 "browsingData", 38 "clipboardRead", 39 "clipboardWrite", 40 "declarativeNetRequest", 41 "declarativeNetRequestFeedback", 42 "downloads", 43 "downloads.open", 44 "find", 45 "geolocation", 46 "history", 47 "management", 48 "nativeMessaging", 49 "notifications", 50 "pkcs11", 51 "privacy", 52 "proxy", 53 "sessions", 54 "tabHide", 55 "tabs", 56 "topSites", 57 "trialML", 58 "userScripts", 59 "webNavigation", 60 "devtools", 61 ), 62 createdAt = "", 63 updatedAt = "", 64 ) 65 66 val translatedPermissions = addon.translatePermissions(testContext) 67 val expectedPermissions = listOf( 68 R.string.mozac_feature_addons_permissions_bookmarks_description, 69 R.string.mozac_feature_addons_permissions_browser_setting_description, 70 R.string.mozac_feature_addons_permissions_browser_data_description, 71 R.string.mozac_feature_addons_permissions_clipboard_read_description, 72 R.string.mozac_feature_addons_permissions_clipboard_write_description, 73 R.string.mozac_feature_addons_permissions_declarative_net_request_description, 74 R.string.mozac_feature_addons_permissions_declarative_net_request_feedback_description, 75 R.string.mozac_feature_addons_permissions_downloads_description, 76 R.string.mozac_feature_addons_permissions_downloads_open_description, 77 R.string.mozac_feature_addons_permissions_find_description, 78 R.string.mozac_feature_addons_permissions_geolocation_description, 79 R.string.mozac_feature_addons_permissions_history_description, 80 R.string.mozac_feature_addons_permissions_management_description, 81 R.string.mozac_feature_addons_permissions_native_messaging_description, 82 R.string.mozac_feature_addons_permissions_notifications_description, 83 R.string.mozac_feature_addons_permissions_pkcs11_description, 84 R.string.mozac_feature_addons_permissions_privacy_description, 85 R.string.mozac_feature_addons_permissions_proxy_description, 86 R.string.mozac_feature_addons_permissions_sessions_description, 87 R.string.mozac_feature_addons_permissions_tab_hide_description, 88 R.string.mozac_feature_addons_permissions_tabs_description, 89 R.string.mozac_feature_addons_permissions_top_sites_description, 90 R.string.mozac_feature_addons_permissions_trial_ml_description, 91 R.string.mozac_feature_addons_permissions_user_scripts_description, 92 R.string.mozac_feature_addons_permissions_web_navigation_description, 93 R.string.mozac_feature_addons_permissions_devtools_description, 94 ).map { testContext.getString(it) } 95 assertEquals(expectedPermissions, translatedPermissions) 96 } 97 98 @Test 99 fun `isInstalled - true if installed state present and otherwise false`() { 100 val addon = Addon( 101 id = "id", 102 downloadUrl = "downloadUrl", 103 version = "version", 104 permissions = emptyList(), 105 createdAt = "", 106 updatedAt = "", 107 ) 108 assertFalse(addon.isInstalled()) 109 110 val installedAddon = addon.copy(installedState = Addon.InstalledState("id", "1.0", "")) 111 assertTrue(installedAddon.isInstalled()) 112 } 113 114 @Test 115 fun `isEnabled - true if installed state enabled and otherwise false`() { 116 val addon = Addon( 117 id = "id", 118 downloadUrl = "downloadUrl", 119 version = "version", 120 permissions = emptyList(), 121 createdAt = "", 122 updatedAt = "", 123 ) 124 assertFalse(addon.isEnabled()) 125 126 val installedAddon = addon.copy(installedState = Addon.InstalledState("id", "1.0", "")) 127 assertFalse(installedAddon.isEnabled()) 128 129 val enabledAddon = addon.copy(installedState = Addon.InstalledState("id", "1.0", "", enabled = true)) 130 assertTrue(enabledAddon.isEnabled()) 131 } 132 133 @Test 134 fun `classifyOriginPermissions - normalizes origins and returns HostPermissions`() { 135 val origins = listOf( 136 "https://developer.mozilla.org/", 137 "*://*.developer.mozilla.org/*", 138 "*://developer.mozilla.org/*", 139 "https://wikipedia.org/", 140 "*://*.wikipedia.org/*", 141 "*://wikipedia.org/*", 142 ) 143 144 val hostNormalizationResult = Addon.classifyOriginPermissions(origins) 145 assertNotNull(hostNormalizationResult.getOrNull()) 146 147 val hostPermissions = hostNormalizationResult.getOrNull()!! 148 149 assertEquals(hostPermissions.sites.size, 2) 150 assertEquals(hostPermissions.wildcards.size, 2) 151 152 val displayDomainList = hostPermissions.wildcards + hostPermissions.sites 153 154 assertEquals(displayDomainList.size, 2) 155 156 assertEquals(displayDomainList.first(), "developer.mozilla.org") 157 assertTrue(displayDomainList.contains("wikipedia.org")) 158 } 159 160 @Test 161 fun `permissionsListContainsAllUrls - true if any permission in the list maps to the All Urls permission`() { 162 val permissionsWithoutAllUrls = listOf("privacy", "tabs") 163 val permissionsWithAllUrls = listOf("privacy", "<all_urls>", "tabs") 164 165 val domainsWithoutAllUrls = listOf( 166 "https://www.mozilla.org", 167 "http://testsite.com", 168 "testing.com", 169 "testing.com/*", 170 "*.testing.com/*", 171 ) 172 173 val domainsWithAllUrls = listOf( 174 "testing.com", 175 "*://*/*", 176 ) 177 178 assertFalse( 179 "Found all_urls permission when none exists", 180 Addon.permissionsListContainsAllUrls(permissionsWithoutAllUrls), 181 ) 182 assertTrue( 183 "Did not find the all_urls permission in the list", 184 Addon.permissionsListContainsAllUrls(permissionsWithAllUrls), 185 ) 186 187 assertFalse( 188 "Found all_urls permission when none exists", 189 Addon.permissionsListContainsAllUrls(domainsWithoutAllUrls), 190 ) 191 assertTrue( 192 "Did not find the all_urls permission in the list", 193 Addon.permissionsListContainsAllUrls(domainsWithAllUrls), 194 ) 195 } 196 197 @Test 198 fun `filterTranslations - only keeps specified translations`() { 199 val addon = Addon( 200 id = "id", 201 downloadUrl = "downloadUrl", 202 version = "version", 203 permissions = emptyList(), 204 createdAt = "", 205 updatedAt = "", 206 translatableName = mapOf(Addon.DEFAULT_LOCALE to "name", "de" to "Name", "es" to "nombre"), 207 translatableDescription = mapOf( 208 Addon.DEFAULT_LOCALE to "description", 209 "de" to "Beschreibung", 210 "es" to "descripción", 211 ), 212 translatableSummary = mapOf(Addon.DEFAULT_LOCALE to "summary", "de" to "Kurzfassung", "es" to "resumen"), 213 ) 214 215 val addonEn = addon.filterTranslations(listOf()) 216 assertEquals(1, addonEn.translatableName.size) 217 assertTrue(addonEn.translatableName.contains(addonEn.defaultLocale)) 218 219 val addonEs = addon.filterTranslations(listOf("es")) 220 assertEquals(2, addonEs.translatableName.size) 221 assertTrue(addonEs.translatableName.contains(addonEn.defaultLocale)) 222 assertTrue(addonEs.translatableName.contains("es")) 223 } 224 225 @Test 226 fun `localizeURLAccessPermissions - must translate all_urls access permission`() { 227 val expectedString = testContext.getString(R.string.mozac_feature_addons_permissions_all_urls_description) 228 val permissions = listOf( 229 "webRequest", 230 "webRequestBlocking", 231 "<all_urls>", 232 ) 233 234 val result = Addon.localizeURLAccessPermissions(testContext, permissions).first() 235 236 assertEquals(expectedString, result) 237 } 238 239 @Test 240 fun `localizeURLAccessPermissions - must translate all urls access permission`() { 241 val expectedString = testContext.getString(R.string.mozac_feature_addons_permissions_all_urls_description) 242 val permissions = listOf( 243 "webRequest", 244 "webRequestBlocking", 245 "*://*/*", 246 ) 247 248 val result = Addon.localizeURLAccessPermissions(testContext, permissions).first() 249 250 assertEquals(expectedString, result) 251 } 252 253 @Test 254 fun `localizeURLAccessPermissions - must translate domain access permissions`() { 255 val expectedString = listOf("tweetdeck.twitter.com", "twitter.com").map { 256 testContext.getString(R.string.mozac_feature_addons_permissions_one_site_description, it) 257 } 258 val permissions = listOf( 259 "webRequest", 260 "webRequestBlocking", 261 "*://tweetdeck.twitter.com/*", 262 "*://twitter.com/*", 263 ) 264 265 val result = Addon.localizeURLAccessPermissions(testContext, permissions) 266 267 assertEquals(expectedString, result) 268 } 269 270 @Test 271 fun `localizeURLAccessPermissions - must translate one site access permissions`() { 272 val expectedString = listOf("youtube.com", "youtube-nocookie.com", "vimeo.com").map { 273 testContext.getString(R.string.mozac_feature_addons_permissions_sites_in_domain_description, it) 274 } 275 val permissions = listOf( 276 "webRequest", 277 "*://*.youtube.com/*", 278 "*://*.youtube-nocookie.com/*", 279 "*://*.vimeo.com/*", 280 ) 281 282 val result = Addon.localizeURLAccessPermissions(testContext, permissions) 283 284 assertEquals(expectedString, result) 285 } 286 287 @Test 288 fun `localizeURLAccessPermissions - must collapse host permissions`() { 289 var expectedString = listOf("youtube.com", "youtube-nocookie.com", "vimeo.com", "google.co.ao").map { 290 testContext.getString(R.string.mozac_feature_addons_permissions_sites_in_domain_description, it) 291 } + testContext.getString(R.string.mozac_feature_addons_permissions_one_extra_domain_description_2) 292 293 var permissions = listOf( 294 "webRequest", 295 "*://*.youtube.com/*", 296 "*://*.youtube-nocookie.com/*", 297 "*://*.vimeo.com/*", 298 "*://*.google.co.ao/*", 299 "*://*.google.com.do/*", 300 ) 301 302 var result = Addon.localizeURLAccessPermissions(testContext, permissions) 303 304 // 1 domain permissions must be collapsed 305 assertEquals(expectedString, result) 306 307 expectedString = listOf("youtube.com", "youtube-nocookie.com", "vimeo.com", "google.co.ao").map { 308 testContext.getString(R.string.mozac_feature_addons_permissions_sites_in_domain_description, it) 309 } + testContext.getString(R.string.mozac_feature_addons_permissions_extra_domains_description_plural_2) 310 311 permissions = listOf( 312 "webRequest", 313 "*://*.youtube.com/*", 314 "*://*.youtube-nocookie.com/*", 315 "*://*.vimeo.com/*", 316 "*://*.google.co.ao/*", 317 "*://*.google.com.do/*", 318 "*://*.google.co.ar/*", 319 ) 320 321 result = Addon.localizeURLAccessPermissions(testContext, permissions) 322 323 // 2 domain permissions must be collapsed 324 assertEquals(expectedString, result) 325 326 permissions = listOf( 327 "webRequest", 328 "*://www.youtube.com/*", 329 "*://www.youtube-nocookie.com/*", 330 "*://www.vimeo.com/*", 331 "https://mozilla.org/a/b/c/", 332 "*://www.google.com.do/*", 333 ) 334 335 expectedString = listOf("www.youtube.com", "www.youtube-nocookie.com", "www.vimeo.com", "mozilla.org").map { 336 testContext.getString(R.string.mozac_feature_addons_permissions_one_site_description, it) 337 } + testContext.getString(R.string.mozac_feature_addons_permissions_one_extra_site_description_2) 338 339 result = Addon.localizeURLAccessPermissions(testContext, permissions) 340 341 // 1 site permissions must be Collapsed 342 assertEquals(expectedString, result) 343 344 permissions = listOf( 345 "webRequest", 346 "*://www.youtube.com/*", 347 "*://www.youtube-nocookie.com/*", 348 "*://www.vimeo.com/*", 349 "https://mozilla.org/a/b/c/", 350 "*://www.google.com.do/*", 351 "*://www.google.co.ar/*", 352 ) 353 354 expectedString = listOf("www.youtube.com", "www.youtube-nocookie.com", "www.vimeo.com", "mozilla.org").map { 355 testContext.getString(R.string.mozac_feature_addons_permissions_one_site_description, it) 356 } + testContext.getString(R.string.mozac_feature_addons_permissions_extra_sites_description_2) 357 358 result = Addon.localizeURLAccessPermissions(testContext, permissions) 359 360 // 2 site permissions must be Collapsed 361 assertEquals(expectedString, result) 362 363 permissions = listOf( 364 "webRequest", 365 "*://www.youtube.com/*", 366 "*://www.youtube-nocookie.com/*", 367 "*://www.vimeo.com/*", 368 "https://mozilla.org/a/b/c/", 369 ) 370 371 expectedString = listOf("www.youtube.com", "www.youtube-nocookie.com", "www.vimeo.com", "mozilla.org").map { 372 testContext.getString(R.string.mozac_feature_addons_permissions_one_site_description, it) 373 } 374 375 result = Addon.localizeURLAccessPermissions(testContext, permissions) 376 377 // None permissions must be collapsed 378 assertEquals(expectedString, result) 379 } 380 381 @Test 382 fun `localizeURLAccessPermission - must provide the correct localized string`() { 383 val siteAccess = listOf( 384 "*://twitter.com/*", 385 "*://tweetdeck.twitter.com/*", 386 "https://mozilla.org/a/b/c/", 387 "https://www.google.com.ag/*", 388 "https://www.google.co.ck/*", 389 ) 390 391 siteAccess.forEach { 392 val stringId = Addon.getStringIdForHostPermission(it) 393 assertEquals(R.string.mozac_feature_addons_permissions_one_site_description, stringId) 394 } 395 396 val domainAccess = listOf( 397 "*://*.youtube.com/*", 398 "*://*.youtube.com/*", 399 "*://*.youtube-nocookie.com/*", 400 "*://*.vimeo.com/*", 401 "*://*.facebookcorewwwi.onion/*", 402 ) 403 404 domainAccess.forEach { 405 val stringId = Addon.getStringIdForHostPermission(it) 406 assertEquals(R.string.mozac_feature_addons_permissions_sites_in_domain_description, stringId) 407 } 408 409 val allUrlsAccess = listOf( 410 "*://*/*", 411 "http://*/*", 412 "https://*/*", 413 "file://*/*", 414 "<all_urls>", 415 ) 416 417 allUrlsAccess.forEach { 418 val stringId = Addon.getStringIdForHostPermission(it) 419 assertEquals(R.string.mozac_feature_addons_permissions_all_urls_description, stringId) 420 } 421 } 422 423 @Test 424 fun `localizeOptionalPermissions - should provide LocalizedPermission list`() { 425 val expectedLocalizedPermissions = listOf( 426 Addon.LocalizedPermission( 427 testContext.getString(R.string.mozac_feature_addons_permissions_all_urls_description), 428 Addon.Permission("<all_urls>", false), 429 ), 430 Addon.LocalizedPermission( 431 testContext.getString(R.string.mozac_feature_addons_permissions_web_navigation_description), 432 Addon.Permission("webNavigation", false), 433 ), 434 Addon.LocalizedPermission( 435 testContext.getString(R.string.mozac_feature_addons_permissions_clipboard_read_description), 436 Addon.Permission("clipboardRead", false), 437 ), 438 Addon.LocalizedPermission( 439 testContext.getString(R.string.mozac_feature_addons_permissions_clipboard_write_description), 440 Addon.Permission("clipboardWrite", false), 441 ), 442 ) 443 444 val permissions = listOf( 445 Addon.Permission("<all_urls>", false), 446 Addon.Permission("webNavigation", false), 447 Addon.Permission("clipboardRead", false), 448 Addon.Permission("clipboardWrite", false), 449 ) 450 451 val localizedResult = localizeOptionalPermissions(permissions, testContext) 452 assertEquals(expectedLocalizedPermissions, localizedResult) 453 } 454 455 @Test 456 fun `newFromWebExtension - must return an Addon instance`() { 457 val version = "1.2.3" 458 val permissions = listOf("scripting", "activeTab") 459 val origins = listOf("https://example.org/") 460 val name = "some name" 461 val description = "some description" 462 val extension: WebExtension = mock() 463 val metadata: Metadata = mock() 464 whenever(extension.id).thenReturn("some-id") 465 whenever(extension.url).thenReturn("some-url") 466 whenever(extension.getMetadata()).thenReturn(metadata) 467 whenever(metadata.version).thenReturn(version) 468 whenever(metadata.requiredPermissions).thenReturn(permissions) 469 whenever(metadata.optionalPermissions).thenReturn(listOf("clipboardRead")) 470 whenever(metadata.grantedOptionalPermissions).thenReturn(listOf("clipboardRead")) 471 whenever(metadata.optionalOrigins).thenReturn(listOf("*://*.example.com/*", "*://opt-host-perm.example.com/*")) 472 // NOTE: in grantedOptionalOrigins we are including one host permission that isn't part of the optionaOrigins list 473 // and so it wasn't explicitly listed in the extension manifest.json but something granted by the user on 474 // an extension call to browser.permissions.request (allowed on the Gecko side because "*://sub.example.com" is a 475 // subset of the "*://*.example.com" host permission, which was explicitly included in the manifest). 476 whenever(metadata.grantedOptionalOrigins).thenReturn(listOf("*://*.example.com/*", "*://sub.example.com/*")) 477 whenever(metadata.requiredOrigins).thenReturn(origins) 478 whenever(metadata.name).thenReturn(name) 479 whenever(metadata.description).thenReturn(description) 480 whenever(metadata.disabledFlags).thenReturn(DisabledFlags.select(0)) 481 whenever(metadata.baseUrl).thenReturn("some-base-url") 482 whenever(metadata.developerName).thenReturn("developer-name") 483 whenever(metadata.developerUrl).thenReturn("developer-url") 484 whenever(metadata.fullDescription).thenReturn("fullDescription") 485 whenever(metadata.homepageUrl).thenReturn("some-url") 486 whenever(metadata.downloadUrl).thenReturn("some-download-url") 487 whenever(metadata.updateDate).thenReturn("1970-01-01T00:00:00Z") 488 whenever(metadata.reviewUrl).thenReturn("some-review-url") 489 whenever(metadata.reviewCount).thenReturn(0) 490 whenever(metadata.averageRating).thenReturn(0f) 491 whenever(metadata.detailUrl).thenReturn("detail-url") 492 whenever(metadata.incognito).thenReturn(Incognito.NOT_ALLOWED) 493 494 val addon = Addon.newFromWebExtension(extension) 495 assertEquals("some-id", addon.id) 496 assertEquals("some-url", addon.homepageUrl) 497 assertEquals("some-download-url", addon.downloadUrl) 498 assertEquals(permissions + origins, addon.permissions) 499 assertEquals( 500 listOf(Addon.Permission(name = "clipboardRead", granted = true)), 501 addon.optionalPermissions, 502 ) 503 assertEquals( 504 listOf( 505 Addon.Permission(name = "*://*.example.com/*", granted = true), 506 Addon.Permission(name = "*://opt-host-perm.example.com/*", granted = false), 507 Addon.Permission(name = "*://sub.example.com/*", granted = true), 508 ), 509 addon.optionalOrigins, 510 ) 511 assertEquals("", addon.updatedAt) 512 assertEquals("some name", addon.translatableName[Addon.DEFAULT_LOCALE]) 513 assertEquals("fullDescription", addon.translatableDescription[Addon.DEFAULT_LOCALE]) 514 assertEquals("some description", addon.translatableSummary[Addon.DEFAULT_LOCALE]) 515 assertEquals("developer-name", addon.author?.name) 516 assertEquals("developer-url", addon.author?.url) 517 assertEquals("some-download-url", addon.downloadUrl) 518 assertEquals("some-review-url", addon.ratingUrl) 519 assertEquals(0, addon.rating!!.reviews) 520 assertEquals("detail-url", addon.detailUrl) 521 assertEquals(Addon.Incognito.NOT_ALLOWED, addon.incognito) 522 } 523 524 @Test 525 fun `fromMetadataToAddonDate - must return an valid addon formatted date`() { 526 val expectedDate = "2023-09-28T00:37:43Z" 527 val inputDate = "2023-09-28T00:37:43.983Z" 528 529 val result = Addon.fromMetadataToAddonDate(inputDate) 530 531 assertEquals(expectedDate, result) 532 } 533 534 @Test 535 fun `fromMetadataToAddonDate - must return handle invalid date formats`() { 536 val expectedDate = "" 537 val inputDate = "202xd3-09-28T00:37:43.98993Z" 538 539 val result = Addon.fromMetadataToAddonDate(inputDate) 540 541 assertEquals(expectedDate, result) 542 } 543 544 @Test 545 fun `fromMetadataToAddonDate - must return empty strings`() { 546 val expectedDate = "" 547 val inputDate = "" 548 549 val result = Addon.fromMetadataToAddonDate(inputDate) 550 551 assertEquals(expectedDate, result) 552 } 553 554 @Test 555 fun `isDisabledAsBlocklisted - true if installed state disabled status equals to BLOCKLISTED and otherwise false`() { 556 val addon = Addon(id = "id") 557 val blockListedAddon = addon.copy( 558 installedState = Addon.InstalledState( 559 id = "id", 560 version = "1.0", 561 optionsPageUrl = "", 562 disabledReason = Addon.DisabledReason.BLOCKLISTED, 563 ), 564 ) 565 566 assertFalse(addon.isDisabledAsBlocklisted()) 567 assertTrue(blockListedAddon.isDisabledAsBlocklisted()) 568 } 569 570 @Test 571 fun `isDisabledAsNotCorrectlySigned - true if installed state disabled status equals to NOT_CORRECTLY_SIGNED and otherwise false`() { 572 val addon = Addon(id = "id") 573 val blockListedAddon = addon.copy( 574 installedState = Addon.InstalledState( 575 id = "id", 576 version = "1.0", 577 optionsPageUrl = "", 578 disabledReason = Addon.DisabledReason.NOT_CORRECTLY_SIGNED, 579 ), 580 ) 581 582 assertFalse(addon.isDisabledAsNotCorrectlySigned()) 583 assertTrue(blockListedAddon.isDisabledAsNotCorrectlySigned()) 584 } 585 586 @Test 587 fun `isDisabledAsIncompatible - true if installed state disabled status equals to INCOMPATIBLE and otherwise false`() { 588 val addon = Addon(id = "id") 589 val blockListedAddon = addon.copy( 590 installedState = Addon.InstalledState( 591 id = "id", 592 version = "1.0", 593 optionsPageUrl = "", 594 disabledReason = Addon.DisabledReason.INCOMPATIBLE, 595 ), 596 ) 597 598 assertFalse(addon.isDisabledAsIncompatible()) 599 assertTrue(blockListedAddon.isDisabledAsIncompatible()) 600 } 601 602 @Test 603 fun `provideIcon - should provide the icon from either addon or installedState`() { 604 val addonWithoutIcon = Addon(id = "id") 605 606 assertNull(addonWithoutIcon.icon) 607 assertNull(addonWithoutIcon.installedState?.icon) 608 assertNull(addonWithoutIcon.provideIcon()) 609 610 val addonWithIcon = addonWithoutIcon.copy(icon = mock()) 611 612 assertNotNull(addonWithIcon.icon) 613 assertNull(addonWithIcon.installedState?.icon) 614 assertNotNull(addonWithIcon.provideIcon()) 615 616 val addonWithInstalledStateIcon = addonWithoutIcon.copy( 617 installedState = Addon.InstalledState("id", "1.0", "", icon = mock()), 618 ) 619 620 assertNull(addonWithInstalledStateIcon.icon) 621 assertNotNull(addonWithInstalledStateIcon.installedState?.icon) 622 assertNotNull(addonWithInstalledStateIcon.provideIcon()) 623 } 624 625 @Test 626 fun `isSoftBlocked - true if installed state disabled status equals to SOFT_BLOCKED and otherwise false`() { 627 val addon = Addon(id = "id") 628 val softBlockedAddon = addon.copy( 629 installedState = Addon.InstalledState( 630 id = "id", 631 version = "1.0", 632 optionsPageUrl = "", 633 disabledReason = Addon.DisabledReason.SOFT_BLOCKED, 634 ), 635 ) 636 637 assertFalse(addon.isSoftBlocked()) 638 assertTrue(softBlockedAddon.isSoftBlocked()) 639 } 640 641 @Test 642 fun `localizeDataCollectionPermissions - should return a localized string for each data collection permission`() { 643 // The "none" permission is special and it doesn't get localized strings like the other data permissions. 644 GeckoWebExtension.DATA_COLLECTION_PERMISSIONS.filter { permission -> permission != "none" }.map { permission -> 645 val list = Addon.localizeDataCollectionPermissions(listOf(permission), testContext) 646 assertTrue("expected a localized string for $permission", list.size == 1) 647 } 648 649 assertTrue( 650 "expected non existing entries to be filtered out", 651 Addon.localizeDataCollectionPermissions( 652 listOf("nonExisting", "healthInfo", "locationInfo"), 653 testContext, 654 ).size == 2, 655 ) 656 } 657 658 @Test 659 fun `translateRequiredDataCollectionPermissions - should return localized strings for the required data collection permissions`() { 660 val addon = Addon( 661 id = "addon-id", 662 requiredDataCollectionPermissions = listOf("bookmarksInfo", "browsingActivity"), 663 ) 664 665 assertEquals( 666 listOf( 667 R.string.mozac_feature_addons_permissions_data_collection_bookmarksInfo_short_description, 668 R.string.mozac_feature_addons_permissions_data_collection_browsingActivity_short_description, 669 ).map { testContext.getString(it) }, 670 addon.translateRequiredDataCollectionPermissions(testContext), 671 ) 672 } 673 674 @Test 675 fun `localizeOptionalDataCollectionPermissions - should return a LocalizedPermission for each data collection permission`() { 676 // The "none" permission is special and it doesn't get localized strings like the other data permissions. 677 GeckoWebExtension.DATA_COLLECTION_PERMISSIONS.filter { permission -> permission != "none" }.map { permission -> 678 val list = Addon.localizeOptionalDataCollectionPermissions( 679 listOf(Addon.Permission(permission, false)), 680 testContext, 681 ) 682 assertTrue("expected a localized string for $permission", list.size == 1) 683 } 684 } 685 686 @Test 687 fun `translateOptionalDataCollectionPermissions - should return localized permissions for the optional data collection permissions`() { 688 val addon = Addon( 689 id = "addon-id", 690 optionalDataCollectionPermissions = listOf( 691 Addon.Permission("bookmarksInfo", false), 692 Addon.Permission("browsingActivity", false), 693 ), 694 ) 695 696 assertEquals( 697 listOf( 698 R.string.mozac_feature_addons_permissions_data_collection_bookmarksInfo_long_description, 699 R.string.mozac_feature_addons_permissions_data_collection_browsingActivity_long_description, 700 ).map { testContext.getString(it) }, 701 // Only return the localized name for each LocalizedPermission. 702 addon.translateOptionalDataCollectionPermissions(testContext).map { it.localizedName }, 703 ) 704 } 705 706 @Test 707 fun `localizeURLAccessPermission - must provide the correct localized string for the update notification`() { 708 val siteAccess = listOf( 709 "*://twitter.com/*", 710 "*://tweetdeck.twitter.com/*", 711 "https://mozilla.org/a/b/c/", 712 "https://www.google.com.ag/*", 713 "https://www.google.co.ck/*", 714 ) 715 716 siteAccess.forEach { 717 val stringId = Addon.getStringIdForHostPermission(it, forUpdate = true) 718 assertEquals(R.string.mozac_feature_addons_permissions_one_site_description_for_update, stringId) 719 } 720 721 val domainAccess = listOf( 722 "*://*.youtube.com/*", 723 "*://*.youtube.com/*", 724 "*://*.youtube-nocookie.com/*", 725 "*://*.vimeo.com/*", 726 "*://*.facebookcorewwwi.onion/*", 727 ) 728 729 domainAccess.forEach { 730 val stringId = Addon.getStringIdForHostPermission(it, forUpdate = true) 731 assertEquals(R.string.mozac_feature_addons_permissions_sites_in_domain_description_for_update, stringId) 732 } 733 734 val allUrlsAccess = listOf( 735 "*://*/*", 736 "http://*/*", 737 "https://*/*", 738 "file://*/*", 739 "<all_urls>", 740 ) 741 742 allUrlsAccess.forEach { 743 val stringId = Addon.getStringIdForHostPermission(it, forUpdate = true) 744 assertEquals(R.string.mozac_feature_addons_permissions_all_urls_description_for_update, stringId) 745 } 746 } 747 748 @Test 749 fun `localizeURLAccessPermissions - must collapse host permissions for the update notification`() { 750 var permissions = listOf( 751 "*://*.youtube.com/*", 752 "*://*.google.com.do/*", 753 ) 754 var result = Addon.localizeURLAccessPermissions(testContext, permissions, forUpdate = true) 755 assertEquals( 756 "expected no domain collapsed", 757 listOf("youtube.com", "google.com.do").map { 758 testContext.getString( 759 R.string.mozac_feature_addons_permissions_sites_in_domain_description_for_update, 760 it, 761 ) 762 }, 763 result, 764 ) 765 766 permissions = listOf( 767 "webRequest", 768 "*://www.youtube.com/*", 769 "*://www.youtube-nocookie.com/*", 770 ) 771 result = Addon.localizeURLAccessPermissions(testContext, permissions, forUpdate = true) 772 assertEquals( 773 "expected no site collapsed", 774 listOf("www.youtube.com", "www.youtube-nocookie.com").map { 775 testContext.getString(R.string.mozac_feature_addons_permissions_one_site_description_for_update, it) 776 }, 777 result, 778 ) 779 780 permissions = listOf( 781 "webRequest", 782 "*://*.youtube.com/*", 783 "*://*.vimeo.com/*", 784 "*://*.google.com.do/*", 785 ) 786 result = Addon.localizeURLAccessPermissions(testContext, permissions, forUpdate = true) 787 assertEquals( 788 "expected a single domain collapsed", 789 listOf("youtube.com", "vimeo.com").map { 790 testContext.getString( 791 R.string.mozac_feature_addons_permissions_sites_in_domain_description_for_update, 792 it, 793 ) 794 } + testContext.getString(R.string.mozac_feature_addons_permissions_one_extra_domain_description_for_update), 795 result, 796 ) 797 798 permissions = listOf( 799 "webRequest", 800 "*://*.youtube.com/*", 801 "*://*.vimeo.com/*", 802 "*://*.google.com.do/*", 803 "*://*.google.co.ao/*", 804 ) 805 result = Addon.localizeURLAccessPermissions(testContext, permissions, forUpdate = true) 806 assertEquals( 807 "expected 2 domains collapsed", 808 listOf("youtube.com", "vimeo.com").map { 809 testContext.getString( 810 R.string.mozac_feature_addons_permissions_sites_in_domain_description_for_update, 811 it, 812 ) 813 } + testContext.getString( 814 R.string.mozac_feature_addons_permissions_extra_domains_description_plural_for_update, 815 2, 816 ), 817 result, 818 ) 819 820 permissions = listOf( 821 "webRequest", 822 "*://www.youtube.com/*", 823 "*://www.youtube-nocookie.com/*", 824 "https://mozilla.org/a/b/c/", 825 ) 826 result = Addon.localizeURLAccessPermissions(testContext, permissions, forUpdate = true) 827 assertEquals( 828 "Expected 1 site collapsed", 829 listOf("www.youtube.com", "www.youtube-nocookie.com").map { 830 testContext.getString(R.string.mozac_feature_addons_permissions_one_site_description_for_update, it) 831 } + testContext.getString(R.string.mozac_feature_addons_permissions_one_extra_site_description_for_update), 832 result, 833 ) 834 835 permissions = listOf( 836 "webRequest", 837 "*://www.youtube.com/*", 838 "*://www.youtube-nocookie.com/*", 839 "https://mozilla.org/a/b/c/", 840 "*://www.google.co.ar/*", 841 ) 842 result = Addon.localizeURLAccessPermissions(testContext, permissions, forUpdate = true) 843 assertEquals( 844 "Expected 2 sites collapsed", 845 listOf("www.youtube.com", "www.youtube-nocookie.com").map { 846 testContext.getString(R.string.mozac_feature_addons_permissions_one_site_description_for_update, it) 847 } + testContext.getString( 848 R.string.mozac_feature_addons_permissions_extra_sites_description_for_update, 849 2, 850 ), 851 result, 852 ) 853 } 854 855 @Test 856 fun `localizeURLAccessPermissions - must translate all urls access permission for the update notification`() { 857 val permissions = listOf( 858 "webRequest", 859 "webRequestBlocking", 860 "*://*/*", 861 ) 862 863 val result = Addon.localizeURLAccessPermissions(testContext, permissions, forUpdate = true).first() 864 assertEquals( 865 testContext.getString(R.string.mozac_feature_addons_permissions_all_urls_description_for_update), 866 result, 867 ) 868 } 869 870 @Test 871 fun `localizeURLAccessPermissions - must translate all_urls access permission for the update notification`() { 872 val permissions = listOf( 873 "webRequest", 874 "webRequestBlocking", 875 "<all_urls>", 876 ) 877 878 val result = Addon.localizeURLAccessPermissions(testContext, permissions, forUpdate = true).first() 879 assertEquals( 880 testContext.getString(R.string.mozac_feature_addons_permissions_all_urls_description_for_update), 881 result, 882 ) 883 } 884 885 @Test 886 fun `localizeURLAccessPermissions - must translate domain access permissions for the update notification`() { 887 val expectedString = listOf("tweetdeck.twitter.com", "twitter.com").map { 888 testContext.getString(R.string.mozac_feature_addons_permissions_one_site_description_for_update, it) 889 } 890 val permissions = listOf( 891 "webRequest", 892 "webRequestBlocking", 893 "*://tweetdeck.twitter.com/*", 894 "*://twitter.com/*", 895 ) 896 897 val result = Addon.localizeURLAccessPermissions(testContext, permissions, forUpdate = true) 898 assertEquals(expectedString, result) 899 } 900 901 @Test 902 fun `localizeURLAccessPermissions - must translate one site access permissions for the update notification`() { 903 val expectedString = listOf("youtube.com", "vimeo.com").map { 904 testContext.getString(R.string.mozac_feature_addons_permissions_sites_in_domain_description_for_update, it) 905 } 906 val permissions = listOf( 907 "webRequest", 908 "*://*.youtube.com/*", 909 "*://*.vimeo.com/*", 910 ) 911 912 val result = Addon.localizeURLAccessPermissions(testContext, permissions, forUpdate = true) 913 assertEquals(expectedString, result) 914 } 915 }