Skip to content

Commit d34bd46

Browse files
MozLandopocmojonalmeidaandlzr
committed
6381: Issue mozilla-mobile#5529: Restore engine state of tabs in tab collections. r=csadilek a=pocmo Changes here: - `TabCollection` and `Tab` return a `Snapshot.Item` instead of only a `Session` - `SessionManager.add()` allows to pass in an `EngineSessionState` - `SessionManager.restore()` helper functions to restore a `Tab`/`TabCollection` 6391: Closes mozilla-mobile#6288: Update docs for local development [ci skip] r=Amejia481 a=jonalmeida 6398: Fix for #6155 - Back button from migration complete notification routes back to migration screen r=Amejia481 a=jonalmeida Co-authored-by: Sebastian Kaspari <[email protected]> Co-authored-by: Jonathan Almeida <[email protected]> Co-authored-by: Sparky93 <[email protected]>
4 parents 30c1b44 + d7dd95b + 5d49f3e + 15efe65 commit d34bd46

File tree

13 files changed

+181
-34
lines changed

13 files changed

+181
-34
lines changed

components/browser/session/src/main/java/mozilla/components/browser/session/LegacySessionManager.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,9 +137,10 @@ class LegacySessionManager(
137137
session: Session,
138138
selected: Boolean = false,
139139
engineSession: EngineSession? = null,
140+
engineSessionState: EngineSessionState? = null,
140141
parent: Session? = null
141142
) = synchronized(values) {
142-
addInternal(session, selected, engineSession, parent = parent, viaRestore = false)
143+
addInternal(session, selected, engineSession, engineSessionState, parent = parent, viaRestore = false)
143144
}
144145

145146
@Suppress("LongParameterList", "ComplexMethod")

components/browser/session/src/main/java/mozilla/components/browser/session/SessionManager.kt

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,10 +147,12 @@ class SessionManager(
147147
session: Session,
148148
selected: Boolean = false,
149149
engineSession: EngineSession? = null,
150+
engineSessionState: EngineSessionState? = null,
150151
parent: Session? = null
151152
) {
152153
// Add store to Session so that it can dispatch actions whenever it changes.
153154
session.store = store
155+
154156
if (parent != null) {
155157
require(all.contains(parent)) { "The parent does not exist" }
156158
session.parentId = parent.id
@@ -171,7 +173,17 @@ class SessionManager(
171173
)
172174
}
173175

174-
delegate.add(session, selected, engineSession, parent)
176+
if (engineSessionState != null && engineSession == null) {
177+
// If the caller passed us an engine session state then also notify the store. We only
178+
// do this if there is no engine session, because this mirrors the behavior in
179+
// LegacySessionManager, which will either link an engine session or keep its state.
180+
store?.syncDispatch(UpdateEngineSessionStateAction(
181+
session.id,
182+
engineSessionState
183+
))
184+
}
185+
186+
delegate.add(session, selected, engineSession, engineSessionState, parent)
175187
}
176188

177189
/**

components/browser/session/src/test/java/mozilla/components/browser/session/SessionManagerMigrationTest.kt

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1281,6 +1281,58 @@ class SessionManagerMigrationTest {
12811281
verify(engineSession3, never()).close()
12821282
verify(engineSession4, never()).close()
12831283
}
1284+
1285+
@Test
1286+
fun `Adding session with engine session state`() {
1287+
val store = BrowserStore()
1288+
val manager = SessionManager(engine = mock(), store = store)
1289+
1290+
val state: EngineSessionState = mock()
1291+
val session = Session("https://www.mozilla.org")
1292+
1293+
manager.add(session, engineSessionState = state)
1294+
1295+
assertEquals(state, session.engineSessionHolder.engineSessionState)
1296+
assertNull(session.engineSessionHolder.engineSession)
1297+
1298+
assertEquals(state, store.state.tabs[0].engineState.engineSessionState)
1299+
assertNull(store.state.tabs[0].engineState.engineSession)
1300+
}
1301+
1302+
@Test
1303+
fun `Adding session with engine session and engine session state`() {
1304+
val store = BrowserStore()
1305+
val manager = SessionManager(engine = mock(), store = store)
1306+
1307+
val state: EngineSessionState = mock()
1308+
val engineSession: EngineSession = mock()
1309+
val session = Session("https://www.mozilla.org")
1310+
1311+
manager.add(session, engineSession = engineSession, engineSessionState = state)
1312+
1313+
assertNull(session.engineSessionHolder.engineSessionState)
1314+
assertEquals(engineSession, session.engineSessionHolder.engineSession)
1315+
1316+
assertNull(store.state.tabs[0].engineState.engineSessionState)
1317+
assertEquals(engineSession, session.engineSessionHolder.engineSession)
1318+
}
1319+
1320+
@Test
1321+
fun `Adding session with engine session`() {
1322+
val store = BrowserStore()
1323+
val manager = SessionManager(engine = mock(), store = store)
1324+
1325+
val engineSession: EngineSession = mock()
1326+
val session = Session("https://www.mozilla.org")
1327+
1328+
manager.add(session, engineSession = engineSession)
1329+
1330+
assertNull(session.engineSessionHolder.engineSessionState)
1331+
assertEquals(engineSession, session.engineSessionHolder.engineSession)
1332+
1333+
assertNull(store.state.tabs[0].engineState.engineSessionState)
1334+
assertEquals(engineSession, session.engineSessionHolder.engineSession)
1335+
}
12841336
}
12851337

12861338
private fun createMockEngineSessionWithState(): EngineSession {

components/feature/customtabs/src/test/java/mozilla/components/feature/customtabs/CustomTabIntentProcessorTest.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ class CustomTabIntentProcessorTest {
6363
whenever(intent.putExtra(any<String>(), any<String>())).thenReturn(intent)
6464

6565
handler.process(intent)
66-
verify(sessionManager).add(anySession(), eq(false), eq(null), eq(null))
66+
verify(sessionManager).add(anySession(), eq(false), eq(null), eq(null), eq(null))
6767
verify(engineSession).loadUrl("http://mozilla.org", flags = LoadUrlFlags.external())
6868
verify(intent).putExtra(eq(EXTRA_SESSION_ID), any<String>())
6969

@@ -92,7 +92,7 @@ class CustomTabIntentProcessorTest {
9292
whenever(intent.putExtra(any<String>(), any<String>())).thenReturn(intent)
9393

9494
handler.process(intent)
95-
verify(sessionManager).add(anySession(), eq(false), eq(null), eq(null))
95+
verify(sessionManager).add(anySession(), eq(false), eq(null), eq(null), eq(null))
9696
verify(engineSession).loadUrl("http://mozilla.org", flags = LoadUrlFlags.external())
9797
verify(intent).putExtra(eq(EXTRA_SESSION_ID), any<String>())
9898

components/feature/search/src/test/java/mozilla/components/feature/search/SearchUseCasesTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ class SearchUseCasesTest {
107107
useCases.newPrivateTabSearch.invoke(searchTerms)
108108

109109
val captor = argumentCaptor<Session>()
110-
verify(sessionManager).add(captor.capture(), eq(true), eq(null), eq(null))
110+
verify(sessionManager).add(captor.capture(), eq(true), eq(null), eq(null), eq(null))
111111
assertTrue(captor.value.private)
112112
verify(engineSession).loadUrl(searchUrl)
113113
}

components/feature/tab-collections/src/androidTest/java/mozilla/components/feature/tab/collections/TabCollectionStorageTest.kt

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -191,8 +191,8 @@ class TabCollectionStorageTest {
191191
assertEquals(session1, sessions[0])
192192
assertEquals(session2, sessions[1])
193193

194-
assertEquals(session1.id, sessions[0].id)
195-
assertEquals(session2.id, sessions[1].id)
194+
assertEquals(session1.id, sessions[0].session.id)
195+
assertEquals(session2.id, sessions[1].session.id)
196196
}
197197

198198
getAllCollections().let { collections ->
@@ -207,14 +207,14 @@ class TabCollectionStorageTest {
207207
assertNotEquals(session1, sessions[0])
208208
assertNotEquals(session2, sessions[1])
209209

210-
assertNotEquals(session1.id, sessions[0].id)
211-
assertNotEquals(session2.id, sessions[1].id)
210+
assertNotEquals(session1.id, sessions[0].session.id)
211+
assertNotEquals(session2.id, sessions[1].session.id)
212212

213-
assertEquals(session1.url, sessions[0].url)
214-
assertEquals(session2.url, sessions[1].url)
213+
assertEquals(session1.url, sessions[0].session.url)
214+
assertEquals(session2.url, sessions[1].session.url)
215215

216-
assertEquals(session1.title, sessions[0].title)
217-
assertEquals(session2.title, sessions[1].title)
216+
assertEquals(session1.title, sessions[0].session.title)
217+
assertEquals(session2.title, sessions[1].session.title)
218218
}
219219
}
220220

components/feature/tab-collections/src/main/java/mozilla/components/feature/tab/collections/Tab.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package mozilla.components.feature.tab.collections
66

77
import android.content.Context
88
import mozilla.components.browser.session.Session
9+
import mozilla.components.browser.session.SessionManager
910
import mozilla.components.concept.engine.Engine
1011

1112
/**
@@ -37,7 +38,6 @@ interface Tab {
3738
fun restore(
3839
context: Context,
3940
engine: Engine,
40-
tab: Tab,
4141
restoreSessionId: Boolean = false
42-
): Session?
42+
): SessionManager.Snapshot.Item?
4343
}

components/feature/tab-collections/src/main/java/mozilla/components/feature/tab/collections/TabCollection.kt

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package mozilla.components.feature.tab.collections
66

77
import android.content.Context
88
import mozilla.components.browser.session.Session
9+
import mozilla.components.browser.session.SessionManager
910
import mozilla.components.concept.engine.Engine
1011

1112
/**
@@ -28,7 +29,8 @@ interface TabCollection {
2829
val tabs: List<Tab>
2930

3031
/**
31-
* Restores all tabs in this collection and returns a matching list of [Session] objects.
32+
* Restores all tabs in this collection and returns a matching list of
33+
* [SessionManager.Snapshot.Item] objects.
3234
*
3335
* @param restoreSessionId If true the original [Session.id] of [Session]s will be restored. Otherwise a new ID
3436
* will be generated. An app may prefer to use a new ID if it expects sessions to get restored multiple times -
@@ -38,10 +40,11 @@ interface TabCollection {
3840
context: Context,
3941
engine: Engine,
4042
restoreSessionId: Boolean = false
41-
): List<Session>
43+
): List<SessionManager.Snapshot.Item>
4244

4345
/**
44-
* Restores a subset of the tabs in this collection and returns a matching list of [Session] objects.
46+
* Restores a subset of the tabs in this collection and returns a matching list of
47+
* [SessionManager.Snapshot.Item] objects.
4548
*
4649
* @param restoreSessionId If true the original [Session.id] of [Session]s will be restored. Otherwise a new ID
4750
* will be generated. An app may prefer to use a new ID if it expects sessions to get restored multiple times -
@@ -52,5 +55,5 @@ interface TabCollection {
5255
engine: Engine,
5356
tabs: List<Tab>,
5457
restoreSessionId: Boolean = false
55-
): List<Session>
58+
): List<SessionManager.Snapshot.Item>
5659
}

components/feature/tab-collections/src/main/java/mozilla/components/feature/tab/collections/adapter/TabAdapter.kt

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
package mozilla.components.feature.tab.collections.adapter
66

77
import android.content.Context
8-
import mozilla.components.browser.session.Session
98
import mozilla.components.browser.session.SessionManager
109
import mozilla.components.browser.session.ext.readSnapshotItem
1110
import mozilla.components.concept.engine.Engine
@@ -24,18 +23,13 @@ internal class TabAdapter(
2423
override val url: String
2524
get() = entity.url
2625

27-
/**
28-
* Restores a single tab from this collection and returns a matching [SessionManager.Snapshot].
29-
*/
3026
override fun restore(
3127
context: Context,
3228
engine: Engine,
33-
tab: Tab,
3429
restoreSessionId: Boolean
35-
): Session? {
30+
): SessionManager.Snapshot.Item? {
3631
return entity.getStateFile(context.filesDir)
3732
.readSnapshotItem(engine, restoreSessionId, false)
38-
?.session
3933
}
4034

4135
override fun equals(other: Any?): Boolean {

components/feature/tab-collections/src/main/java/mozilla/components/feature/tab/collections/adapter/TabCollectionAdapter.kt

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
package mozilla.components.feature.tab.collections.adapter
66

77
import android.content.Context
8-
import mozilla.components.browser.session.Session
8+
import mozilla.components.browser.session.SessionManager
99
import mozilla.components.browser.session.ext.readSnapshotItem
1010
import mozilla.components.concept.engine.Engine
1111
import mozilla.components.feature.tab.collections.Tab
@@ -29,7 +29,11 @@ internal class TabCollectionAdapter(
2929
override val id: Long
3030
get() = entity.collection.id!!
3131

32-
override fun restore(context: Context, engine: Engine, restoreSessionId: Boolean): List<Session> {
32+
override fun restore(
33+
context: Context,
34+
engine: Engine,
35+
restoreSessionId: Boolean
36+
): List<SessionManager.Snapshot.Item> {
3337
return restore(context, engine, entity.tabs, restoreSessionId)
3438
}
3539

@@ -38,7 +42,7 @@ internal class TabCollectionAdapter(
3842
engine: Engine,
3943
tabs: List<Tab>,
4044
restoreSessionId: Boolean
41-
): List<Session> {
45+
): List<SessionManager.Snapshot.Item> {
4246
val entities = entity.tabs.filter {
4347
candidate -> tabs.find { tab -> tab.id == candidate.id } != null
4448
}
@@ -50,9 +54,9 @@ internal class TabCollectionAdapter(
5054
engine: Engine,
5155
tabs: List<TabEntity>,
5256
restoreSessionId: Boolean
53-
): List<Session> {
57+
): List<SessionManager.Snapshot.Item> {
5458
return tabs.mapNotNull { tab ->
55-
tab.getStateFile(context.filesDir).readSnapshotItem(engine, restoreSessionId)?.session
59+
tab.getStateFile(context.filesDir).readSnapshotItem(engine, restoreSessionId)
5660
}
5761
}
5862

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
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.tab.collections.ext
6+
7+
import android.content.Context
8+
import mozilla.components.browser.session.SessionManager
9+
import mozilla.components.concept.engine.Engine
10+
import mozilla.components.feature.tab.collections.Tab
11+
import mozilla.components.feature.tab.collections.TabCollection
12+
13+
/**
14+
* Restores the given [Tab] from a [TabCollection]. Will invoke [onTabRestored] on successful restore
15+
* and [onFailure] otherwise.
16+
*/
17+
fun SessionManager.restore(
18+
context: Context,
19+
engine: Engine,
20+
tab: Tab,
21+
onTabRestored: () -> Unit,
22+
onFailure: () -> Unit
23+
) {
24+
val item = tab.restore(
25+
context = context,
26+
engine = engine,
27+
restoreSessionId = false
28+
)
29+
30+
if (item == null) {
31+
// We were unable to restore the tab. Let the app know so that it can workaround that
32+
onFailure()
33+
} else {
34+
add(
35+
session = item.session,
36+
selected = true,
37+
engineSessionState = item.engineSessionState
38+
)
39+
onTabRestored()
40+
}
41+
}
42+
43+
/**
44+
* Restores the given [TabCollection]. Will invoke [onFailure] if restoring a single [Tab] of the
45+
* collection failed. The URL of the tab will be passed to [onFailure].
46+
*/
47+
fun SessionManager.restore(
48+
context: Context,
49+
engine: Engine,
50+
collection: TabCollection,
51+
onFailure: (String) -> Unit
52+
) {
53+
collection.tabs.reversed().forEach { tab ->
54+
val item = tab.restore(
55+
context = context,
56+
engine = engine,
57+
restoreSessionId = false
58+
)
59+
60+
if (item == null) {
61+
// We were unable to restore the tab. Let the app know so that it can workaround that
62+
onFailure(tab.url)
63+
} else {
64+
add(
65+
session = item.session,
66+
selected = selectedSession == null,
67+
engineSessionState = item.engineSessionState
68+
)
69+
}
70+
}
71+
}

components/support/migration/src/main/java/mozilla/components/support/migration/AbstractMigrationService.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ abstract class AbstractMigrationService : Service() {
124124
.setContentTitle(getString(titleRes))
125125
.setContentText(getString(contentRes))
126126
.setContentIntent(PendingIntent.getActivity(this, 0,
127-
Intent(this, migrationDecisionActivity), 0))
127+
Intent(this, migrationDecisionActivity).setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP), 0))
128128
.setPriority(NotificationCompat.PRIORITY_LOW)
129129
.setCategory(NotificationCompat.CATEGORY_PROGRESS)
130130
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)

0 commit comments

Comments
 (0)