1616
1717package com.duckduckgo.app.browser
1818
19+ import android.graphics.Bitmap
1920import android.net.Uri
2021import android.view.MenuItem
2122import android.view.View
@@ -44,7 +45,7 @@ import com.duckduckgo.app.browser.LongPressHandler.RequiredAction.DownloadFile
4445import com.duckduckgo.app.browser.LongPressHandler.RequiredAction.OpenInNewTab
4546import com.duckduckgo.app.browser.addtohome.AddToHomeCapabilityDetector
4647import com.duckduckgo.app.browser.downloader.FileDownloader
47- import com.duckduckgo.app.browser.favicon.FaviconDownloader
48+ import com.duckduckgo.app.browser.favicon.FaviconManager
4849import com.duckduckgo.app.browser.logindetection.LoginDetected
4950import com.duckduckgo.app.browser.logindetection.NavigationAwareLoginDetector
5051import com.duckduckgo.app.browser.logindetection.NavigationEvent.LoginAttempt
@@ -103,14 +104,14 @@ import com.duckduckgo.app.trackerdetection.model.TrackingEvent
103104import com.duckduckgo.app.usage.search.SearchCountDao
104105import com.duckduckgo.app.widget.ui.WidgetCapabilities
105106import com.nhaarman.mockitokotlin2.*
107+ import dagger.Lazy
106108import io.reactivex.Observable
107109import io.reactivex.Single
108110import kotlinx.coroutines.ExperimentalCoroutinesApi
109111import kotlinx.coroutines.flow.emptyFlow
110112import kotlinx.coroutines.runBlocking
111113import kotlinx.coroutines.test.runBlockingTest
112114import org.junit.After
113- import org.junit.Assert
114115import org.junit.Assert.*
115116import org.junit.Before
116117import org.junit.Rule
@@ -119,6 +120,7 @@ import org.mockito.*
119120import org.mockito.ArgumentMatchers.anyString
120121import org.mockito.Mockito.never
121122import org.mockito.Mockito.verify
123+ import java.io.File
122124import java.util.concurrent.TimeUnit
123125
124126@ExperimentalCoroutinesApi
@@ -168,7 +170,7 @@ class BrowserTabViewModelTest {
168170 private lateinit var webViewSessionStorage: WebViewSessionStorage
169171
170172 @Mock
171- private lateinit var mockFaviconDownloader : FaviconDownloader
173+ private lateinit var mockFaviconManager : FaviconManager
172174
173175 @Mock
174176 private lateinit var mockAddToHomeCapabilityDetector: AddToHomeCapabilityDetector
@@ -221,6 +223,8 @@ class BrowserTabViewModelTest {
221223 @Mock
222224 private lateinit var geoLocationPermissions: GeoLocationPermissions
223225
226+ private val lazyFaviconManager = Lazy { mockFaviconManager }
227+
224228 private lateinit var mockAutoCompleteApi: AutoCompleteApi
225229
226230 private lateinit var ctaViewModel: CtaViewModel
@@ -295,14 +299,18 @@ class BrowserTabViewModelTest {
295299 longPressHandler = mockLongPressHandler,
296300 webViewSessionStorage = webViewSessionStorage,
297301 specialUrlDetector = SpecialUrlDetectorImpl (),
298- faviconDownloader = mockFaviconDownloader ,
302+ faviconManager = mockFaviconManager ,
299303 addToHomeCapabilityDetector = mockAddToHomeCapabilityDetector,
300304 ctaViewModel = ctaViewModel,
301305 searchCountDao = mockSearchCountDao,
302306 pixel = mockPixel,
303307 dispatchers = coroutineRule.testDispatcherProvider,
304- fireproofWebsiteRepository = FireproofWebsiteRepository (fireproofWebsiteDao, coroutineRule.testDispatcherProvider),
305- locationPermissionsRepository = LocationPermissionsRepository (locationPermissionsDao, coroutineRule.testDispatcherProvider),
308+ fireproofWebsiteRepository = FireproofWebsiteRepository (fireproofWebsiteDao, coroutineRule.testDispatcherProvider, lazyFaviconManager),
309+ locationPermissionsRepository = LocationPermissionsRepository (
310+ locationPermissionsDao,
311+ lazyFaviconManager,
312+ coroutineRule.testDispatcherProvider
313+ ),
306314 geoLocationPermissions = geoLocationPermissions,
307315 navigationAwareLoginDetector = mockNavigationAwareLoginDetector,
308316 userEventsStore = mockUserEventsStore,
@@ -2541,7 +2549,7 @@ class BrowserTabViewModelTest {
25412549
25422550 verify(mockPixel).fire(Pixel .PixelName .PRECISE_LOCATION_SYSTEM_DIALOG_NEVER )
25432551 verify(geoLocationPermissions).clear(domain)
2544- Assert . assertEquals(locationPermissionsDao.getPermission(domain)!! .permission, LocationPermissionType .DENY_ALWAYS )
2552+ assertEquals(locationPermissionsDao.getPermission(domain)!! .permission, LocationPermissionType .DENY_ALWAYS )
25452553 }
25462554
25472555 @Test
@@ -2673,6 +2681,163 @@ class BrowserTabViewModelTest {
26732681 verify(mockSettingsStore).appLocationPermissionDeniedForever = false
26742682 }
26752683
2684+ @Test
2685+ fun whenPrefetchFaviconThenPrefetchToTemp () = coroutineRule.runBlocking {
2686+ val url = " https://www.example.com/"
2687+ givenCurrentSite(url)
2688+ testee.prefetchFavicon(url)
2689+
2690+ verify(mockFaviconManager).prefetchToTemp(" TAB_ID" , url)
2691+ }
2692+
2693+ @Test
2694+ fun whenPrefetchFaviconAndFaviconExistsThenUpdateTabFavicon () = coroutineRule.runBlocking {
2695+ val url = " https://www.example.com/"
2696+ val file = File (" test" )
2697+ givenCurrentSite(url)
2698+ whenever(mockFaviconManager.prefetchToTemp(any(), any())).thenReturn(file)
2699+
2700+ testee.prefetchFavicon(url)
2701+
2702+ verify(mockTabsRepository).updateTabFavicon(" TAB_ID" , file.name)
2703+ }
2704+
2705+ @Test
2706+ fun whenPrefetchFaviconAndFaviconDoesNotExistThenDoNotCallUpdateTabFavicon () = coroutineRule.runBlocking {
2707+ whenever(mockFaviconManager.prefetchToTemp(any(), any())).thenReturn(null )
2708+
2709+ testee.prefetchFavicon(" url" )
2710+
2711+ verify(mockTabsRepository, never()).updateTabFavicon(any(), any())
2712+ }
2713+
2714+ @Test
2715+ fun whenIconReceivedThenSaveToTemp () = coroutineRule.runBlocking {
2716+ givenOneActiveTabSelected()
2717+ val bitmap: Bitmap = Bitmap .createBitmap(1 , 1 , Bitmap .Config .RGB_565 )
2718+
2719+ testee.iconReceived(bitmap)
2720+
2721+ verify(mockFaviconManager).saveToTemp(" TAB_ID" , bitmap, " https://example.com" )
2722+ }
2723+
2724+ @Test
2725+ fun whenIconReceivedIfCorrectlySavedThenUpdateTabFavicon () = coroutineRule.runBlocking {
2726+ givenOneActiveTabSelected()
2727+ val bitmap: Bitmap = Bitmap .createBitmap(1 , 1 , Bitmap .Config .RGB_565 )
2728+ val file = File (" test" )
2729+ whenever(mockFaviconManager.saveToTemp(any(), any(), any())).thenReturn(file)
2730+
2731+ testee.iconReceived(bitmap)
2732+
2733+ verify(mockTabsRepository).updateTabFavicon(" TAB_ID" , file.name)
2734+ }
2735+
2736+ @Test
2737+ fun whenIconReceivedIfNotCorrectlySavedThenDoNotUpdateTabFavicon () = coroutineRule.runBlocking {
2738+ givenOneActiveTabSelected()
2739+ val bitmap: Bitmap = Bitmap .createBitmap(1 , 1 , Bitmap .Config .RGB_565 )
2740+ whenever(mockFaviconManager.saveToTemp(any(), any(), any())).thenReturn(null )
2741+
2742+ testee.iconReceived(bitmap)
2743+
2744+ verify(mockTabsRepository, never()).updateTabFavicon(any(), any())
2745+ }
2746+
2747+ @Test
2748+ fun whenOnSiteLocationPermissionSelectedAndPermissionIsAllowAlwaysThenPersistFavicon () = coroutineRule.runBlocking {
2749+ val url = " http://example.com"
2750+ val permission = LocationPermissionType .ALLOW_ALWAYS
2751+ givenNewPermissionRequestFromDomain(url)
2752+
2753+ testee.onSiteLocationPermissionSelected(url, permission)
2754+
2755+ verify(mockFaviconManager).persistFavicon(any(), eq(url))
2756+ }
2757+
2758+ @Test
2759+ fun whenOnSiteLocationPermissionSelectedAndPermissionIsDenyAlwaysThenPersistFavicon () = coroutineRule.runBlocking {
2760+ val url = " http://example.com"
2761+ val permission = LocationPermissionType .DENY_ALWAYS
2762+ givenNewPermissionRequestFromDomain(url)
2763+
2764+ testee.onSiteLocationPermissionSelected(url, permission)
2765+
2766+ verify(mockFaviconManager).persistFavicon(any(), eq(url))
2767+ }
2768+
2769+ @Test
2770+ fun whenOnSystemLocationPermissionNeverAllowedThenPersistFavicon () = coroutineRule.runBlocking {
2771+ val url = " http://example.com"
2772+ givenNewPermissionRequestFromDomain(url)
2773+
2774+ testee.onSystemLocationPermissionNeverAllowed()
2775+
2776+ verify(mockFaviconManager).persistFavicon(any(), eq(url))
2777+ }
2778+
2779+ @Test
2780+ fun whenBookmarkAddedThenPersistFavicon () = coroutineRule.runBlocking {
2781+ val url = " http://example.com"
2782+ loadUrl(url, " A title" )
2783+
2784+ testee.onBookmarkAddRequested()
2785+
2786+ verify(mockFaviconManager).persistFavicon(any(), eq(url))
2787+ }
2788+
2789+ @Test
2790+ fun whenBookmarkAddedButUrlIsNullThenDoNotPersistFavicon () = coroutineRule.runBlocking {
2791+ loadUrl(null , " A title" )
2792+
2793+ testee.onBookmarkAddRequested()
2794+
2795+ verify(mockFaviconManager, never()).persistFavicon(any(), any())
2796+ }
2797+
2798+ @Test
2799+ fun whenFireproofWebsiteAddedThenPersistFavicon () = coroutineRule.runBlocking {
2800+ val url = " http://example.com"
2801+ loadUrl(url, isBrowserShowing = true )
2802+
2803+ testee.onFireproofWebsiteMenuClicked()
2804+
2805+ assertCommandIssued<Command .ShowFireproofWebSiteConfirmation > {
2806+ verify(mockFaviconManager).persistFavicon(any(), eq(this .fireproofWebsiteEntity.domain))
2807+ }
2808+ }
2809+
2810+ @Test
2811+ fun whenOnPinPageToHomeSelectedThenAddHomeShortcutCommandIssuedWithFavicon () = coroutineRule.runBlocking {
2812+ val url = " http://example.com"
2813+ val bitmap: Bitmap = Bitmap .createBitmap(1 , 1 , Bitmap .Config .RGB_565 )
2814+ whenever(mockFaviconManager.loadFromTemp(any(), any())).thenReturn(bitmap)
2815+ loadUrl(url, " A title" )
2816+
2817+ testee.onPinPageToHomeSelected()
2818+
2819+ assertCommandIssued<Command .AddHomeShortcut > {
2820+ assertEquals(bitmap, this .icon)
2821+ assertEquals(url, this .url)
2822+ assertEquals(" example.com" , this .title)
2823+ }
2824+ }
2825+
2826+ @Test
2827+ fun whenOnPinPageToHomeSelectedAndFaviconDoesNotExistThenAddHomeShortcutCommandIssuedWithoutFavicon () = coroutineRule.runBlocking {
2828+ val url = " http://example.com"
2829+ whenever(mockFaviconManager.loadFromTemp(any(), any())).thenReturn(null )
2830+ loadUrl(url, " A title" )
2831+
2832+ testee.onPinPageToHomeSelected()
2833+
2834+ assertCommandIssued<Command .AddHomeShortcut > {
2835+ assertNull(this .icon)
2836+ assertEquals(url, this .url)
2837+ assertEquals(" example.com" , this .title)
2838+ }
2839+ }
2840+
26762841 private fun givenNewPermissionRequestFromDomain (domain : String ) {
26772842 testee.onSiteLocationPermissionRequested(domain, StubPermissionCallback ())
26782843 }
0 commit comments