Loading components/browser/storage-memory/src/main/java/mozilla/components/browser/storage/memory/InMemoryHistoryStorage.kt +5 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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) Loading components/browser/storage-sync/src/main/java/mozilla/components/browser/storage/sync/PlacesHistoryStorage.kt +7 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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 { Loading components/browser/storage-sync/src/main/java/mozilla/components/browser/storage/sync/Types.kt +8 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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 -> { Loading components/browser/storage-sync/src/test/java/mozilla/components/browser/storage/sync/PlacesHistoryStorageTest.kt +42 −0 Original line number Diff line number Diff line Loading @@ -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)) Loading components/concept/storage/src/main/java/mozilla/components/concept/storage/HistoryStorage.kt +20 −0 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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 Loading
components/browser/storage-memory/src/main/java/mozilla/components/browser/storage/memory/InMemoryHistoryStorage.kt +5 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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) Loading
components/browser/storage-sync/src/main/java/mozilla/components/browser/storage/sync/PlacesHistoryStorage.kt +7 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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 { Loading
components/browser/storage-sync/src/main/java/mozilla/components/browser/storage/sync/Types.kt +8 −0 Original line number Diff line number Diff line Loading @@ -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 Loading Loading @@ -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 -> { Loading
components/browser/storage-sync/src/test/java/mozilla/components/browser/storage/sync/PlacesHistoryStorageTest.kt +42 −0 Original line number Diff line number Diff line Loading @@ -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)) Loading
components/concept/storage/src/main/java/mozilla/components/concept/storage/HistoryStorage.kt +20 −0 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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