Bug 1661480 - Restore scrolling position in new session. r=droeh

When restoring state into a new session, the actor gets recreated after
navigating away from `about:blank` so we have to query for it again to get the
right instance.

Differential Revision: https://phabricator.services.mozilla.com/D89475
This commit is contained in:
Agi Sferro 2020-09-09 05:48:14 +00:00
parent 89ab9ce336
commit 9ba4e16ce3
2 changed files with 50 additions and 10 deletions

View File

@ -38,23 +38,30 @@ class GeckoViewContentParent extends JSWindowActorParent {
return;
}
const self = this;
const progressFilter = Cc[
"@mozilla.org/appshell/component/browser-status-filter;1"
].createInstance(Ci.nsIWebProgress);
const { browser } = this;
const progressListener = {
QueryInterface: ChromeUtils.generateQI(["nsIWebProgressListener"]),
onLocationChange(aWebProgress, aRequest, aLocationURI, aFlags) {
self.sendAsyncMessage("RestoreSessionState", { formdata, scrolldata });
if (!aWebProgress.isTopLevel) {
return;
}
// The actor might get recreated between navigations so we need to
// query it again for the up-to-date instance.
browser.browsingContext.currentWindowGlobal
.getActor("GeckoViewContent")
.sendAsyncMessage("RestoreSessionState", { formdata, scrolldata });
progressFilter.removeProgressListener(this);
self.browser.removeProgressListener(progressFilter);
browser.removeProgressListener(progressFilter);
},
};
const flags = Ci.nsIWebProgress.NOTIFY_LOCATION;
progressFilter.addProgressListener(progressListener, flags);
this.browser.addProgressListener(progressFilter, flags);
browser.addProgressListener(progressFilter, flags);
}
}

View File

@ -293,12 +293,10 @@ class ProgressDelegateTest : BaseSessionTest() {
waitForScroll(offset, timeout, "pageTop")
}
@WithDisplay(width = 400, height = 400)
@Test fun saveAndRestoreState() {
fun collectState(uri: String) : GeckoSession.SessionState {
sessionRule.setPrefsUntilTestEnd(mapOf("dom.visualviewport.enabled" to true))
val startUri = createTestUrl(SAVE_STATE_PATH)
mainSession.loadUri(startUri)
mainSession.loadUri(uri)
sessionRule.waitForPageStop()
mainSession.evaluateJS("document.querySelector('#name').value = 'the name';")
@ -320,11 +318,47 @@ class ProgressDelegateTest : BaseSessionTest() {
})
assertThat("State should not be null", savedState, notNullValue())
return savedState!!
}
@WithDisplay(width = 400, height = 400)
@Test fun saveAndRestoreStateNewSession() {
val startUri = createTestUrl(SAVE_STATE_PATH)
val savedState = collectState(startUri);
val session = sessionRule.createOpenSession()
session.addDisplay(400, 400)
session.restoreState(savedState)
session.waitForPageStop()
session.forCallbacksDuringWait(object : Callbacks.NavigationDelegate {
@AssertCalled
override fun onLocationChange(session: GeckoSession, url: String?) {
assertThat("URI should match", url, equalTo(startUri))
}
})
/* TODO: Reenable when we have a workaround for ContentSessionStore not
saving in response to JS-driven formdata changes.
assertThat("'name' field should match",
mainSession.evaluateJS("$('#name').value").toString(),
equalTo("the name"))*/
assertThat("Scroll position should match",
session.evaluateJS("window.visualViewport.pageTop") as Double,
closeTo(100.0, .5))
}
@WithDisplay(width = 400, height = 400)
@Test fun saveAndRestoreState() {
val startUri = createTestUrl(SAVE_STATE_PATH)
val savedState = collectState(startUri);
mainSession.loadUri("about:blank")
sessionRule.waitForPageStop()
mainSession.restoreState(savedState!!)
mainSession.restoreState(savedState)
sessionRule.waitForPageStop()
sessionRule.forCallbacksDuringWait(object : Callbacks.NavigationDelegate {
@ -343,7 +377,6 @@ class ProgressDelegateTest : BaseSessionTest() {
assertThat("Scroll position should match",
mainSession.evaluateJS("window.visualViewport.pageTop") as Double,
closeTo(100.0, .5))
}
@WithDisplay(width = 400, height = 400)