Commit 555a2f33 authored by Gabriel Luong's avatar Gabriel Luong
Browse files

Issue #7094: Add getTopFrecentSiteInfos history API

parent ba7a2383
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@ import mozilla.components.concept.storage.PageObservation
import mozilla.components.concept.storage.SearchResult
import mozilla.components.concept.storage.PageVisit
import mozilla.components.concept.storage.RedirectSource
import mozilla.components.concept.storage.TopFrecentSiteInfo
import mozilla.components.concept.storage.VisitInfo
import mozilla.components.concept.storage.VisitType
import mozilla.components.support.utils.StorageUtils.levenshteinDistance
@@ -93,6 +94,10 @@ class InMemoryHistoryStorage : HistoryStorage {
        return visits
    }

    override suspend fun getTopFrecentSites(numItems: Int): List<TopFrecentSiteInfo> {
        throw UnsupportedOperationException("getTopFrecentSites is not yet supported by the in-memory history storage")
    }

    override fun getSuggestions(query: String, limit: Int): List<SearchResult> = synchronized(pages + pageMeta) {
        data class Hit(val url: String, val score: Int)

+7 −0
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@ import mozilla.components.concept.storage.PageObservation
import mozilla.components.concept.storage.PageVisit
import mozilla.components.concept.storage.SearchResult
import mozilla.components.concept.storage.RedirectSource
import mozilla.components.concept.storage.TopFrecentSiteInfo
import mozilla.components.concept.storage.VisitInfo
import mozilla.components.concept.storage.VisitType
import mozilla.components.concept.sync.SyncAuthInfo
@@ -97,6 +98,12 @@ open class PlacesHistoryStorage(context: Context) : PlacesStorage(context), Hist
        }
    }

    override suspend fun getTopFrecentSites(numItems: Int): List<TopFrecentSiteInfo> {
        return withContext(scope.coroutineContext) {
            places.reader().getTopFrecentSiteInfos(numItems).map { it.into() }
        }
    }

    override fun getSuggestions(query: String, limit: Int): List<SearchResult> {
        require(limit >= 0) { "Limit must be a positive integer" }
        return places.reader().queryAutocomplete(query, limit = limit).map {
+8 −0
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@ import mozilla.appservices.places.BookmarkTreeNode
import mozilla.appservices.places.SyncAuthInfo
import mozilla.components.concept.storage.BookmarkNode
import mozilla.components.concept.storage.BookmarkNodeType
import mozilla.components.concept.storage.TopFrecentSiteInfo
import mozilla.components.concept.storage.VisitInfo
import mozilla.components.concept.storage.VisitType

@@ -68,6 +69,13 @@ internal fun mozilla.appservices.places.VisitInfo.into(): VisitInfo {
    )
}

internal fun mozilla.appservices.places.TopFrecentSiteInfo.into(): TopFrecentSiteInfo {
    return TopFrecentSiteInfo(
        url = this.url,
        title = this.title
    )
}

internal fun BookmarkTreeNode.asBookmarkNode(): BookmarkNode {
    return when (this) {
        is BookmarkItem -> {
+42 −0
Original line number Diff line number Diff line
@@ -139,6 +139,48 @@ class PlacesHistoryStorageTest {
        assertEquals("Mozilla", recordedVisits[0].title)
    }

    @Test
    fun `store can be used to query top frecent site information`() = runBlocking {
        val toAdd = listOf(
            "https://www.example.com/123",
            "https://www.example.com/123",
            "https://www.example.com/12345",
            "https://www.mozilla.com/foo/bar/baz",
            "https://www.mozilla.com/foo/bar/baz",
            "https://mozilla.com/a1/b2/c3",
            "https://news.ycombinator.com/",
            "https://www.mozilla.com/foo/bar/baz"
        )

        for (url in toAdd) {
            history.recordVisit(url, PageVisit(VisitType.LINK, RedirectSource.NOT_A_SOURCE))
        }

        var infos = history.getTopFrecentSites(0)
        assertEquals(0, infos.size)

        infos = history.getTopFrecentSites(3)
        assertEquals(3, infos.size)
        assertEquals("https://www.mozilla.com/foo/bar/baz", infos[0].url)
        assertEquals("https://www.example.com/123", infos[1].url)

        infos = history.getTopFrecentSites(5)
        assertEquals(5, infos.size)
        assertEquals("https://www.mozilla.com/foo/bar/baz", infos[0].url)
        assertEquals("https://www.example.com/123", infos[1].url)
        assertEquals("https://news.ycombinator.com/", infos[2].url)
        assertEquals("https://mozilla.com/a1/b2/c3", infos[3].url)
        assertEquals("https://www.example.com/12345", infos[4].url)

        infos = history.getTopFrecentSites(100)
        assertEquals(5, infos.size)
        assertEquals("https://www.mozilla.com/foo/bar/baz", infos[0].url)
        assertEquals("https://www.example.com/123", infos[1].url)
        assertEquals("https://news.ycombinator.com/", infos[2].url)
        assertEquals("https://mozilla.com/a1/b2/c3", infos[3].url)
        assertEquals("https://www.example.com/12345", infos[4].url)
    }

    @Test
    fun `store can be used to query detailed visit information`() = runBlocking {
        history.recordVisit("http://www.mozilla.org", PageVisit(VisitType.LINK, RedirectSource.NOT_A_SOURCE))
+20 −0
Original line number Diff line number Diff line
@@ -68,6 +68,15 @@ interface HistoryStorage : Storage {
        excludeTypes: List<VisitType> = listOf()
    ): List<VisitInfo>

    /**
     * Returns a list of the top frecent site infos limited by the given number of items
     * sorted by most to least frecent.
     *
     * @param numItems the number of top frecent sites to return in the list.
     * @return a list of the [TopFrecentSiteInfo], most frecent first.
     */
    suspend fun getTopFrecentSites(numItems: Int): List<TopFrecentSiteInfo>

    /**
     * Retrieves suggestions matching the [query].
     * @param query A query by which to search the underlying store.
@@ -145,6 +154,17 @@ enum class RedirectSource {

data class PageObservation(val title: String?)

/**
 * Information about a top frecent site. This represents a most frequently visited site.
 *
 * @property url The URL of the page that was visited.
 * @property title The title of the page that was visited, if known.
 */
data class TopFrecentSiteInfo(
    val url: String,
    val title: String?
)

/**
 * Information about a history visit.
 *
Loading