Skip to content
This repository has been archived by the owner on Nov 1, 2022. It is now read-only.

Commit

Permalink
Closes #7023 - Add HistoryState to content state
Browse files Browse the repository at this point in the history
  • Loading branch information
NotWoods committed May 19, 2020
1 parent bd2ca97 commit e42dbe8
Show file tree
Hide file tree
Showing 14 changed files with 182 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import mozilla.components.concept.engine.EngineSessionState
import mozilla.components.concept.engine.HitResult
import mozilla.components.concept.engine.Settings
import mozilla.components.concept.engine.content.blocking.Tracker
import mozilla.components.concept.engine.history.HistoryItem
import mozilla.components.concept.engine.history.HistoryTrackingDelegate
import mozilla.components.concept.engine.manifest.WebAppManifestParser
import mozilla.components.concept.engine.request.RequestInterceptor
Expand Down Expand Up @@ -580,6 +581,14 @@ class GeckoEngineSession(
visits.toBooleanArray()
}
}

override fun onHistoryStateChange(
session: GeckoSession,
historyList: GeckoSession.HistoryDelegate.HistoryList
) {
val items = historyList.map { HistoryItem(title = it.title, uri = it.uri) }
notifyObservers { onHistoryStateChanged(items, historyList.currentIndex) }
}
}

@Suppress("ComplexMethod")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import mozilla.components.concept.engine.EngineSessionState
import mozilla.components.concept.engine.HitResult
import mozilla.components.concept.engine.Settings
import mozilla.components.concept.engine.content.blocking.Tracker
import mozilla.components.concept.engine.history.HistoryItem
import mozilla.components.concept.engine.history.HistoryTrackingDelegate
import mozilla.components.concept.engine.manifest.WebAppManifestParser
import mozilla.components.concept.engine.request.RequestInterceptor
Expand Down Expand Up @@ -592,6 +593,14 @@ class GeckoEngineSession(
visits.toBooleanArray()
}
}

override fun onHistoryStateChange(
session: GeckoSession,
historyList: GeckoSession.HistoryDelegate.HistoryList
) {
val items = historyList.map { HistoryItem(title = it.title, uri = it.uri) }
notifyObservers { onHistoryStateChanged(items, historyList.currentIndex) }
}
}

@Suppress("ComplexMethod")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import mozilla.components.concept.engine.EngineSessionState
import mozilla.components.concept.engine.HitResult
import mozilla.components.concept.engine.Settings
import mozilla.components.concept.engine.content.blocking.Tracker
import mozilla.components.concept.engine.history.HistoryItem
import mozilla.components.concept.engine.history.HistoryTrackingDelegate
import mozilla.components.concept.engine.manifest.WebAppManifestParser
import mozilla.components.concept.engine.request.RequestInterceptor
Expand Down Expand Up @@ -578,6 +579,14 @@ class GeckoEngineSession(
visits.toBooleanArray()
}
}

override fun onHistoryStateChange(
session: GeckoSession,
historyList: GeckoSession.HistoryDelegate.HistoryList
) {
val items = historyList.map { HistoryItem(title = it.title, uri = it.uri) }
notifyObservers { onHistoryStateChanged(items, historyList.currentIndex) }
}
}

@Suppress("ComplexMethod")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import mozilla.components.browser.state.store.BrowserStore
import mozilla.components.concept.engine.EngineSession
import mozilla.components.concept.engine.HitResult
import mozilla.components.concept.engine.content.blocking.Tracker
import mozilla.components.concept.engine.history.HistoryItem
import mozilla.components.concept.engine.manifest.WebAppManifest
import mozilla.components.concept.engine.media.Media
import mozilla.components.concept.engine.media.RecordingDevice
Expand Down Expand Up @@ -285,4 +286,12 @@ internal class EngineObserver(
override fun onRecordingStateChanged(devices: List<RecordingDevice>) {
session.recordingDevices = devices
}

override fun onHistoryStateChanged(historyList: List<HistoryItem>, currentIndex: Int) {
store?.dispatch(ContentAction.UpdateHistoryStateAction(
session.id,
historyList,
currentIndex
))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import mozilla.components.concept.engine.EngineSessionState
import mozilla.components.concept.engine.HitResult
import mozilla.components.concept.engine.Settings
import mozilla.components.concept.engine.content.blocking.Tracker
import mozilla.components.concept.engine.history.HistoryItem
import mozilla.components.concept.engine.manifest.WebAppManifest
import mozilla.components.concept.engine.media.Media
import mozilla.components.concept.engine.permission.PermissionRequest
Expand Down Expand Up @@ -704,4 +705,36 @@ class EngineObserverTest {

assertEquals("", session.searchTerms)
}

@Test
fun `onHistoryStateChanged dispatches UpdateHistoryStateAction`() {
val session = Session("")
val store = mock(BrowserStore::class.java)
val observer = EngineObserver(session, store)
whenever(store.dispatch(any())).thenReturn(mock())

observer.onHistoryStateChanged(emptyList(), 0)
verify(store).dispatch(
ContentAction.UpdateHistoryStateAction(
session.id,
emptyList(),
currentIndex = 0
)
)

observer.onHistoryStateChanged(listOf(
HistoryItem("Firefox", "https://firefox.com"),
HistoryItem("Mozilla", "http://mozilla.org")
), 1)
verify(store).dispatch(
ContentAction.UpdateHistoryStateAction(
session.id,
listOf(
HistoryItem("Firefox", "https://firefox.com"),
HistoryItem("Mozilla", "http://mozilla.org")
),
currentIndex = 1
)
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import mozilla.components.concept.engine.EngineSession
import mozilla.components.concept.engine.EngineSessionState
import mozilla.components.concept.engine.HitResult
import mozilla.components.concept.engine.content.blocking.Tracker
import mozilla.components.concept.engine.history.HistoryItem
import mozilla.components.concept.engine.manifest.WebAppManifest
import mozilla.components.concept.engine.media.Media
import mozilla.components.concept.engine.prompt.PromptRequest
Expand Down Expand Up @@ -288,6 +289,15 @@ sealed class ContentAction : BrowserAction() {
* Removes the [WebAppManifest] of the [ContentState] with the given [sessionId].
*/
data class RemoveWebAppManifestAction(val sessionId: String) : ContentAction()

/**
* Updates the [ContentState] of the given [sessionId] to indicate the current history state.
*/
data class UpdateHistoryStateAction(
val sessionId: String,
val historyList: List<HistoryItem>,
val currentIndex: Int
) : ContentAction()
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import mozilla.components.browser.state.action.ContentAction
import mozilla.components.browser.state.state.BrowserState
import mozilla.components.browser.state.state.ContentState
import mozilla.components.browser.state.state.SessionState
import mozilla.components.browser.state.state.content.HistoryState

internal object ContentStateReducer {
/**
Expand Down Expand Up @@ -120,6 +121,9 @@ internal object ContentStateReducer {
is ContentAction.UpdateFirstContentfulPaintStateAction -> updateContentState(state, action.sessionId) {
it.copy(firstContentfulPaint = action.firstContentfulPaint)
}
is ContentAction.UpdateHistoryStateAction -> updateContentState(state, action.sessionId) {
it.copy(history = HistoryState(action.historyList, action.currentIndex))
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package mozilla.components.browser.state.state
import android.graphics.Bitmap
import mozilla.components.browser.state.state.content.DownloadState
import mozilla.components.browser.state.state.content.FindResultState
import mozilla.components.browser.state.state.content.HistoryState
import mozilla.components.concept.engine.HitResult
import mozilla.components.concept.engine.manifest.WebAppManifest
import mozilla.components.concept.engine.prompt.PromptRequest
Expand Down Expand Up @@ -62,5 +63,6 @@ data class ContentState(
val canGoBack: Boolean = false,
val canGoForward: Boolean = false,
val webAppManifest: WebAppManifest? = null,
val firstContentfulPaint: Boolean = false
val firstContentfulPaint: Boolean = false,
val history: HistoryState = HistoryState()
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package mozilla.components.browser.state.state.content

import mozilla.components.concept.engine.history.HistoryItem

/**
* Value type that represents browser history.
*
* @property items All the items in the browser history.
* @property currentIndex The index of the currently selected [HistoryItem].
* If this is equal to lastIndex, then there are no pages to go "forward" to.
* If this is 0, then there are no pages to go "back" to.
*/
data class HistoryState(
val items: List<HistoryItem> = emptyList(),
val currentIndex: Int = 0
)
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ import mozilla.components.browser.state.state.SecurityInfoState
import mozilla.components.browser.state.state.TabSessionState
import mozilla.components.browser.state.state.content.DownloadState
import mozilla.components.browser.state.state.content.FindResultState
import mozilla.components.browser.state.state.content.HistoryState
import mozilla.components.browser.state.state.createCustomTab
import mozilla.components.browser.state.state.createTab
import mozilla.components.browser.state.store.BrowserStore
import mozilla.components.concept.engine.HitResult
import mozilla.components.concept.engine.history.HistoryItem
import mozilla.components.concept.engine.manifest.WebAppManifest
import mozilla.components.concept.engine.prompt.PromptRequest
import mozilla.components.concept.engine.window.WindowRequest
Expand Down Expand Up @@ -600,4 +602,25 @@ class ContentActionTest {

assertNull(tab.content.webAppManifest)
}

@Test
fun `UpdateHistoryStateAction updates history state`() {
val historyState = HistoryState(
items = listOf(
HistoryItem("Mozilla", "https://mozilla.org"),
HistoryItem("Firefox", "https://firefox.com")
),
currentIndex = 1
)

assertNotEquals(historyState, tab.content.history)
assertNotEquals(historyState, otherTab.content.history)

store.dispatch(
ContentAction.UpdateHistoryStateAction(tab.id, historyState.items, historyState.currentIndex)
).joinBlocking()

assertEquals(historyState, tab.content.history)
assertNotEquals(historyState, otherTab.content.history)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import mozilla.components.concept.engine.EngineSession.TrackingProtectionPolicy.
import mozilla.components.concept.engine.EngineSession.TrackingProtectionPolicy.CookiePolicy.ACCEPT_ALL
import mozilla.components.concept.engine.EngineSession.TrackingProtectionPolicy.CookiePolicy.ACCEPT_NON_TRACKERS
import mozilla.components.concept.engine.content.blocking.Tracker
import mozilla.components.concept.engine.history.HistoryItem
import mozilla.components.concept.engine.manifest.WebAppManifest
import mozilla.components.concept.engine.media.Media
import mozilla.components.concept.engine.media.RecordingDevice
Expand Down Expand Up @@ -122,6 +123,14 @@ abstract class EngineSession(
cookie: String? = null,
userAgent: String? = null
) = Unit

/**
* Event to indicate that this session has changed its history state.
*
* @param historyList The list of items in the session history.
* @param currentIndex Index of the current page in the history list.
*/
fun onHistoryStateChanged(historyList: List<HistoryItem>, currentIndex: Int) = Unit
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

package mozilla.components.concept.engine.history

/**
* A representation of an entry in browser history.
* @property title The title of this history element.
* @property uri The URI of this history element.
*/
data class HistoryItem(
val title: String,
val uri: String
)
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import org.mockito.Mockito.verifyNoMoreInteractions
import org.mockito.Mockito.verifyZeroInteractions
import mozilla.components.concept.engine.EngineSession.TrackingProtectionPolicy.TrackingCategory
import mozilla.components.concept.engine.EngineSession.TrackingProtectionPolicy.CookiePolicy
import mozilla.components.concept.engine.history.HistoryItem
import java.lang.reflect.Modifier

class EngineSessionTest {
Expand Down Expand Up @@ -552,6 +553,28 @@ class EngineSessionTest {
)
}

@Test
fun `registered observer will be notified about history state`() {
val session = spy(DummyEngineSession())

val observer = mock(EngineSession.Observer::class.java)
session.register(observer)

session.notifyInternalObservers {
onHistoryStateChanged(
listOf(HistoryItem("Firefox download", "https://download.mozilla.org")),
currentIndex = 0
)
}

verify(observer).onHistoryStateChanged(
historyList = listOf(
HistoryItem("Firefox download", "https://download.mozilla.org")
),
currentIndex = 0
)
}

@Test
fun `tracking protection policies have correct categories`() {

Expand Down
6 changes: 6 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ permalink: /changelog/
* **feature-media**
* Adds `MediaFullscreenOrientationFeature` to autorotate activity while in fullscreen based on media aspect ratio.

* **concept-engine**
* Adds `onHistoryStateChanged` method and corresponding `HistoryItem` data class.

* **browser-state**
* Adds `history` to `ContentState` to check the back and forward history list.

# 42.0.0

* [Commits](https://github.com/mozilla-mobile/android-components/compare/v41.0.0...42.0.0)
Expand Down

0 comments on commit e42dbe8

Please sign in to comment.