зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1155730, implement History.scrollRestoration r=jst
This commit is contained in:
Родитель
8b2a176dce
Коммит
2b2b2cc690
|
@ -154,10 +154,14 @@ var SessionHistoryInternal = {
|
||||||
if (shEntry.contentType)
|
if (shEntry.contentType)
|
||||||
entry.contentType = shEntry.contentType;
|
entry.contentType = shEntry.contentType;
|
||||||
|
|
||||||
|
if (shEntry.scrollRestorationIsManual) {
|
||||||
|
entry.scrollRestorationIsManual = true;
|
||||||
|
} else {
|
||||||
let x = {}, y = {};
|
let x = {}, y = {};
|
||||||
shEntry.getScrollPosition(x, y);
|
shEntry.getScrollPosition(x, y);
|
||||||
if (x.value != 0 || y.value != 0)
|
if (x.value != 0 || y.value != 0)
|
||||||
entry.scroll = x.value + "," + y.value;
|
entry.scroll = x.value + "," + y.value;
|
||||||
|
}
|
||||||
|
|
||||||
// Collect owner data for the current history entry.
|
// Collect owner data for the current history entry.
|
||||||
try {
|
try {
|
||||||
|
@ -338,7 +342,9 @@ var SessionHistoryInternal = {
|
||||||
entry.structuredCloneVersion);
|
entry.structuredCloneVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entry.scroll) {
|
if (entry.scrollRestorationIsManual) {
|
||||||
|
shEntry.scrollRestorationIsManual = true;
|
||||||
|
} else if (entry.scroll) {
|
||||||
var scrollPos = (entry.scroll || "0,0").split(",");
|
var scrollPos = (entry.scroll || "0,0").split(",");
|
||||||
scrollPos = [parseInt(scrollPos[0]) || 0, parseInt(scrollPos[1]) || 0];
|
scrollPos = [parseInt(scrollPos[0]) || 0, parseInt(scrollPos[1]) || 0];
|
||||||
shEntry.setScrollPosition(scrollPos[0], scrollPos[1]);
|
shEntry.setScrollPosition(scrollPos[0], scrollPos[1]);
|
||||||
|
|
|
@ -10043,9 +10043,11 @@ nsDocShell::InternalLoad(nsIURI* aURI,
|
||||||
nsCOMPtr<nsIInputStream> postData;
|
nsCOMPtr<nsIInputStream> postData;
|
||||||
nsCOMPtr<nsISupports> cacheKey;
|
nsCOMPtr<nsISupports> cacheKey;
|
||||||
|
|
||||||
|
bool scrollRestorationIsManual = false;
|
||||||
if (mOSHE) {
|
if (mOSHE) {
|
||||||
/* save current position of scroller(s) (bug 59774) */
|
/* save current position of scroller(s) (bug 59774) */
|
||||||
mOSHE->SetScrollPosition(cx, cy);
|
mOSHE->SetScrollPosition(cx, cy);
|
||||||
|
mOSHE->GetScrollRestorationIsManual(&scrollRestorationIsManual);
|
||||||
// Get the postdata and page ident from the current page, if
|
// Get the postdata and page ident from the current page, if
|
||||||
// the new load is being done via normal means. Note that
|
// the new load is being done via normal means. Note that
|
||||||
// "normal means" can be checked for just by checking for
|
// "normal means" can be checked for just by checking for
|
||||||
|
@ -10060,6 +10062,11 @@ nsDocShell::InternalLoad(nsIURI* aURI,
|
||||||
// cache data, since the two SHEntries correspond to the
|
// cache data, since the two SHEntries correspond to the
|
||||||
// same document.
|
// same document.
|
||||||
if (mLSHE) {
|
if (mLSHE) {
|
||||||
|
if (!aSHEntry) {
|
||||||
|
// If we're not doing a history load, scroll restoration
|
||||||
|
// should be inherited from the previous session history entry.
|
||||||
|
mLSHE->SetScrollRestorationIsManual(scrollRestorationIsManual);
|
||||||
|
}
|
||||||
mLSHE->AdoptBFCacheEntry(mOSHE);
|
mLSHE->AdoptBFCacheEntry(mOSHE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10132,10 +10139,12 @@ nsDocShell::InternalLoad(nsIURI* aURI,
|
||||||
/* restore previous position of scroller(s), if we're moving
|
/* restore previous position of scroller(s), if we're moving
|
||||||
* back in history (bug 59774)
|
* back in history (bug 59774)
|
||||||
*/
|
*/
|
||||||
nscoord bx, by;
|
nscoord bx = 0;
|
||||||
|
nscoord by = 0;
|
||||||
bool needsScrollPosUpdate = false;
|
bool needsScrollPosUpdate = false;
|
||||||
if (mOSHE && (aLoadType == LOAD_HISTORY ||
|
if (mOSHE && (aLoadType == LOAD_HISTORY ||
|
||||||
aLoadType == LOAD_RELOAD_NORMAL)) {
|
aLoadType == LOAD_RELOAD_NORMAL) &&
|
||||||
|
!scrollRestorationIsManual) {
|
||||||
needsScrollPosUpdate = true;
|
needsScrollPosUpdate = true;
|
||||||
mOSHE->GetScrollPosition(&bx, &by);
|
mOSHE->GetScrollPosition(&bx, &by);
|
||||||
}
|
}
|
||||||
|
@ -11624,6 +11633,9 @@ nsDocShell::AddState(JS::Handle<JS::Value> aData, const nsAString& aTitle,
|
||||||
GetCurScrollPos(ScrollOrientation_Y, &cy);
|
GetCurScrollPos(ScrollOrientation_Y, &cy);
|
||||||
mOSHE->SetScrollPosition(cx, cy);
|
mOSHE->SetScrollPosition(cx, cy);
|
||||||
|
|
||||||
|
bool scrollRestorationIsManual = false;
|
||||||
|
mOSHE->GetScrollRestorationIsManual(&scrollRestorationIsManual);
|
||||||
|
|
||||||
// Since we're not changing which page we have loaded, pass
|
// Since we're not changing which page we have loaded, pass
|
||||||
// true for aCloneChildren.
|
// true for aCloneChildren.
|
||||||
rv = AddToSessionHistory(newURI, nullptr, nullptr, true,
|
rv = AddToSessionHistory(newURI, nullptr, nullptr, true,
|
||||||
|
@ -11632,6 +11644,10 @@ nsDocShell::AddState(JS::Handle<JS::Value> aData, const nsAString& aTitle,
|
||||||
|
|
||||||
NS_ENSURE_TRUE(newSHEntry, NS_ERROR_FAILURE);
|
NS_ENSURE_TRUE(newSHEntry, NS_ERROR_FAILURE);
|
||||||
|
|
||||||
|
// Session history entries created by pushState inherit scroll restoration
|
||||||
|
// mode from the current entry.
|
||||||
|
newSHEntry->SetScrollRestorationIsManual(scrollRestorationIsManual);
|
||||||
|
|
||||||
// Link the new SHEntry to the old SHEntry's BFCache entry, since the
|
// Link the new SHEntry to the old SHEntry's BFCache entry, since the
|
||||||
// two entries correspond to the same document.
|
// two entries correspond to the same document.
|
||||||
NS_ENSURE_SUCCESS(newSHEntry->AdoptBFCacheEntry(oldOSHE), NS_ERROR_FAILURE);
|
NS_ENSURE_SUCCESS(newSHEntry->AdoptBFCacheEntry(oldOSHE), NS_ERROR_FAILURE);
|
||||||
|
@ -11740,6 +11756,27 @@ nsDocShell::AddState(JS::Handle<JS::Value> aData, const nsAString& aTitle,
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsDocShell::GetCurrentScrollRestorationIsManual(bool* aIsManual)
|
||||||
|
{
|
||||||
|
*aIsManual = false;
|
||||||
|
if (mOSHE) {
|
||||||
|
mOSHE->GetScrollRestorationIsManual(aIsManual);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsDocShell::SetCurrentScrollRestorationIsManual(bool aIsManual)
|
||||||
|
{
|
||||||
|
if (mOSHE) {
|
||||||
|
mOSHE->SetScrollRestorationIsManual(aIsManual);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
nsDocShell::ShouldAddToSessionHistory(nsIURI* aURI)
|
nsDocShell::ShouldAddToSessionHistory(nsIURI* aURI)
|
||||||
{
|
{
|
||||||
|
@ -12140,10 +12177,21 @@ nsDocShell::PersistLayoutHistoryState()
|
||||||
nsresult rv = NS_OK;
|
nsresult rv = NS_OK;
|
||||||
|
|
||||||
if (mOSHE) {
|
if (mOSHE) {
|
||||||
|
bool scrollRestorationIsManual = false;
|
||||||
|
mOSHE->GetScrollRestorationIsManual(&scrollRestorationIsManual);
|
||||||
|
|
||||||
nsCOMPtr<nsIPresShell> shell = GetPresShell();
|
nsCOMPtr<nsIPresShell> shell = GetPresShell();
|
||||||
if (shell) {
|
|
||||||
nsCOMPtr<nsILayoutHistoryState> layoutState;
|
nsCOMPtr<nsILayoutHistoryState> layoutState;
|
||||||
|
if (shell) {
|
||||||
rv = shell->CaptureHistoryState(getter_AddRefs(layoutState));
|
rv = shell->CaptureHistoryState(getter_AddRefs(layoutState));
|
||||||
|
} else if (scrollRestorationIsManual) {
|
||||||
|
// Even if we don't have layout anymore, we may want to reset the current
|
||||||
|
// scroll state in layout history.
|
||||||
|
GetLayoutHistoryState(getter_AddRefs(layoutState));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (scrollRestorationIsManual && layoutState) {
|
||||||
|
layoutState->ResetScrollState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,7 +43,7 @@ interface nsITabParent;
|
||||||
|
|
||||||
typedef unsigned long nsLoadFlags;
|
typedef unsigned long nsLoadFlags;
|
||||||
|
|
||||||
[scriptable, builtinclass, uuid(bc3524bd-023c-4fc8-ace1-472bc999fb12)]
|
[scriptable, builtinclass, uuid(811aa3e1-7c4d-45ae-89da-ea1b107c60ed)]
|
||||||
interface nsIDocShell : nsIDocShellTreeItem
|
interface nsIDocShell : nsIDocShellTreeItem
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
@ -1090,4 +1090,10 @@ interface nsIDocShell : nsIDocShellTreeItem
|
||||||
* top level chrome docshell.
|
* top level chrome docshell.
|
||||||
*/
|
*/
|
||||||
attribute boolean windowDraggingAllowed;
|
attribute boolean windowDraggingAllowed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets/gets the current scroll restoration mode.
|
||||||
|
* @see https://html.spec.whatwg.org/#dom-history-scroll-restoration
|
||||||
|
*/
|
||||||
|
attribute boolean currentScrollRestorationIsManual;
|
||||||
};
|
};
|
||||||
|
|
|
@ -30,7 +30,7 @@ class nsSHEntryShared;
|
||||||
[ptr] native nsDocShellEditorDataPtr(nsDocShellEditorData);
|
[ptr] native nsDocShellEditorDataPtr(nsDocShellEditorData);
|
||||||
[ptr] native nsSHEntryShared(nsSHEntryShared);
|
[ptr] native nsSHEntryShared(nsSHEntryShared);
|
||||||
|
|
||||||
[scriptable, uuid(3a5e5fa0-5364-4fbb-a87a-3f12a6b51903)]
|
[scriptable, uuid(0dad26b8-a259-42c7-93f1-2fa7fc076e45)]
|
||||||
interface nsISHEntry : nsISupports
|
interface nsISHEntry : nsISupports
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
@ -301,6 +301,12 @@ interface nsISHEntry : nsISupports
|
||||||
* for example with view-source.
|
* for example with view-source.
|
||||||
*/
|
*/
|
||||||
attribute nsIURI baseURI;
|
attribute nsIURI baseURI;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets/gets the current scroll restoration state,
|
||||||
|
* if true == "manual", false == "auto".
|
||||||
|
*/
|
||||||
|
attribute boolean scrollRestorationIsManual;
|
||||||
};
|
};
|
||||||
|
|
||||||
[scriptable, uuid(bb66ac35-253b-471f-a317-3ece940f04c5)]
|
[scriptable, uuid(bb66ac35-253b-471f-a317-3ece940f04c5)]
|
||||||
|
|
|
@ -33,6 +33,7 @@ nsSHEntry::nsSHEntry()
|
||||||
, mParent(nullptr)
|
, mParent(nullptr)
|
||||||
, mURIWasModified(false)
|
, mURIWasModified(false)
|
||||||
, mIsSrcdocEntry(false)
|
, mIsSrcdocEntry(false)
|
||||||
|
, mScrollRestorationIsManual(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,6 +54,7 @@ nsSHEntry::nsSHEntry(const nsSHEntry& aOther)
|
||||||
, mURIWasModified(aOther.mURIWasModified)
|
, mURIWasModified(aOther.mURIWasModified)
|
||||||
, mStateData(aOther.mStateData)
|
, mStateData(aOther.mStateData)
|
||||||
, mIsSrcdocEntry(aOther.mIsSrcdocEntry)
|
, mIsSrcdocEntry(aOther.mIsSrcdocEntry)
|
||||||
|
, mScrollRestorationIsManual(false)
|
||||||
, mSrcdocData(aOther.mSrcdocData)
|
, mSrcdocData(aOther.mSrcdocData)
|
||||||
, mBaseURI(aOther.mBaseURI)
|
, mBaseURI(aOther.mBaseURI)
|
||||||
{
|
{
|
||||||
|
@ -598,6 +600,20 @@ nsSHEntry::SetBaseURI(nsIURI* aBaseURI)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsSHEntry::GetScrollRestorationIsManual(bool* aIsManual)
|
||||||
|
{
|
||||||
|
*aIsManual = mScrollRestorationIsManual;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsSHEntry::SetScrollRestorationIsManual(bool aIsManual)
|
||||||
|
{
|
||||||
|
mScrollRestorationIsManual = aIsManual;
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsSHEntry::GetChildCount(int32_t* aCount)
|
nsSHEntry::GetChildCount(int32_t* aCount)
|
||||||
{
|
{
|
||||||
|
|
|
@ -64,6 +64,7 @@ private:
|
||||||
bool mURIWasModified;
|
bool mURIWasModified;
|
||||||
nsCOMPtr<nsIStructuredCloneContainer> mStateData;
|
nsCOMPtr<nsIStructuredCloneContainer> mStateData;
|
||||||
bool mIsSrcdocEntry;
|
bool mIsSrcdocEntry;
|
||||||
|
bool mScrollRestorationIsManual;
|
||||||
nsString mSrcdocData;
|
nsString mSrcdocData;
|
||||||
nsCOMPtr<nsIURI> mBaseURI;
|
nsCOMPtr<nsIURI> mBaseURI;
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,128 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<script>
|
||||||
|
var oldHistoryObject = null;
|
||||||
|
|
||||||
|
function test(event) {
|
||||||
|
if (!opener.scrollRestorationTest) {
|
||||||
|
opener.scrollRestorationTest = 0;
|
||||||
|
}
|
||||||
|
++opener.scrollRestorationTest;
|
||||||
|
|
||||||
|
switch (opener.scrollRestorationTest) {
|
||||||
|
case 1: {
|
||||||
|
opener.is(event.persisted, false, "Shouldn't have persisted session history entry.");
|
||||||
|
opener.ok(history.scrollRestoration, "History object has scrollRestoration property.");
|
||||||
|
opener.ok(history.scrollRestoration, "auto", "history.scrollRestoration's default value should be 'auto'.");
|
||||||
|
history.scrollRestoration = "foobar";
|
||||||
|
opener.ok(history.scrollRestoration, "auto", "Invalid enum value should not change the value of an attribute.");
|
||||||
|
history.scrollRestoration = "manual";
|
||||||
|
opener.ok(history.scrollRestoration, "manual", "Valid enum value should change the value of an attribute.");
|
||||||
|
history.scrollRestoration = "auto";
|
||||||
|
opener.ok(history.scrollRestoration, "auto", "Valid enum value should change the value of an attribute.");
|
||||||
|
document.getElementById("bottom").scrollIntoView();
|
||||||
|
window.location.reload(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2: {
|
||||||
|
opener.is(event.persisted, false, "Shouldn't have persisted session history entry.");
|
||||||
|
opener.isnot(window.scrollY, 0, "Should have restored scrolling.");
|
||||||
|
opener.is(history.scrollRestoration, "auto", "Should have the same scrollRestoration as before reload.");
|
||||||
|
history.scrollRestoration = "manual";
|
||||||
|
window.onunload = function() {} // Disable bfcache.
|
||||||
|
window.location.reload(false);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 3: {
|
||||||
|
opener.is(event.persisted, false, "Shouldn't have persisted session history entry.");
|
||||||
|
opener.is(window.scrollY, 0, "Should not have restored scrolling.");
|
||||||
|
opener.is(history.scrollRestoration, "manual", "Should have the same scrollRestoration as before reload.");
|
||||||
|
document.getElementById("bottom").scrollIntoView();
|
||||||
|
window.onunload = null; // Should get bfcache behavior.
|
||||||
|
opener.setTimeout("testWindow.history.back();", 250);
|
||||||
|
window.location.href = 'data:text/html,';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 4: {
|
||||||
|
opener.is(event.persisted, true, "Should have persisted session history entry.");
|
||||||
|
opener.isnot(window.scrollY, 0, "Should have kept the old scroll position.");
|
||||||
|
opener.is(history.scrollRestoration, "manual", "Should have the same scrollRestoration as before reload.");
|
||||||
|
window.scrollTo(0, 0);
|
||||||
|
window.location.hash = "hash";
|
||||||
|
requestAnimationFrame(test);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 5: {
|
||||||
|
opener.isnot(window.scrollY, 0, "Should have scrolled to #hash.");
|
||||||
|
opener.is(history.scrollRestoration, "manual", "Should have the same scrollRestoration mode as before fragment navigation.");
|
||||||
|
window.onunload = function() {} // Disable bfcache.
|
||||||
|
opener.setTimeout("is(testWindow.history.scrollRestoration, 'auto'); testWindow.history.back();", 250);
|
||||||
|
window.location.href = 'data:text/html,';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 6: {
|
||||||
|
opener.is(event.persisted, false, "Shouldn't have persisted session history entry.");
|
||||||
|
opener.is(window.scrollY, 0, "Shouldn't have kept the old scroll position.");
|
||||||
|
opener.is(history.scrollRestoration, "manual", "Should have the same scrollRestoration mode as before fragment navigation.");
|
||||||
|
history.scrollRestoration = "auto";
|
||||||
|
document.getElementById("bottom").scrollIntoView();
|
||||||
|
history.pushState({ state: "state1" }, "state1");
|
||||||
|
history.pushState({ state: "state2" }, "state2");
|
||||||
|
window.scrollTo(0, 0);
|
||||||
|
history.back();
|
||||||
|
opener.isnot(window.scrollY, 0, "Should have scrolled back to the state1's position");
|
||||||
|
opener.is(history.state.state, "state1", "Unexpected state.");
|
||||||
|
|
||||||
|
history.scrollRestoration = "manual";
|
||||||
|
document.getElementById("bottom").scrollIntoView();
|
||||||
|
history.pushState({ state: "state3" }, "state3");
|
||||||
|
history.pushState({ state: "state4" }, "state4");
|
||||||
|
window.scrollTo(0, 0);
|
||||||
|
history.back();
|
||||||
|
opener.is(window.scrollY, 0, "Shouldn't have scrolled back to the state3's position");
|
||||||
|
opener.is(history.state.state, "state3", "Unexpected state.");
|
||||||
|
|
||||||
|
var ifr = document.createElement("iframe");
|
||||||
|
ifr.src = "data:text/html,";
|
||||||
|
document.body.appendChild(ifr);
|
||||||
|
ifr.onload = test;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 7: {
|
||||||
|
oldHistoryObject = event.target.contentWindow.history;
|
||||||
|
event.target.src = "about:blank";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 8: {
|
||||||
|
try {
|
||||||
|
var sr = oldHistoryObject.scrollRestoration;
|
||||||
|
opener.ok(false, "Should have thrown an exception.");
|
||||||
|
} catch(ex) {
|
||||||
|
opener.isnot(ex, null, "Did get an exception");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
oldHistoryObject.scrollRestoration = "auto";
|
||||||
|
opener.ok(false, "Should have thrown an exception.");
|
||||||
|
} catch(ex) {
|
||||||
|
opener.isnot(ex, null, "Did get an exception");
|
||||||
|
}
|
||||||
|
opener.nextTest();
|
||||||
|
window.close();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener("pageshow",
|
||||||
|
function(e) {
|
||||||
|
setTimeout(test, 0, e);
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div style="border: 1px solid black; height: 5000px;">
|
||||||
|
</div>
|
||||||
|
<div id="bottom">Hello world</div>
|
||||||
|
<a href="#hash" name="hash">hash</a>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -10,6 +10,7 @@ support-files =
|
||||||
file_document_write_1.html
|
file_document_write_1.html
|
||||||
file_fragment_handling_during_load.html
|
file_fragment_handling_during_load.html
|
||||||
file_nested_frames.html
|
file_nested_frames.html
|
||||||
|
file_scrollRestoration.html
|
||||||
file_shiftReload_and_pushState.html
|
file_shiftReload_and_pushState.html
|
||||||
file_static_and_dynamic_1.html
|
file_static_and_dynamic_1.html
|
||||||
frame0.html
|
frame0.html
|
||||||
|
|
|
@ -29,7 +29,8 @@ var testFiles =
|
||||||
"file_bug534178.html", // Session history transaction clean-up.
|
"file_bug534178.html", // Session history transaction clean-up.
|
||||||
"file_fragment_handling_during_load.html",
|
"file_fragment_handling_during_load.html",
|
||||||
"file_nested_frames.html",
|
"file_nested_frames.html",
|
||||||
"file_shiftReload_and_pushState.html"
|
"file_shiftReload_and_pushState.html",
|
||||||
|
"file_scrollRestoration.html"
|
||||||
];
|
];
|
||||||
var testCount = 0; // Used by the test files.
|
var testCount = 0; // Used by the test files.
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
#include "nsHistory.h"
|
#include "nsHistory.h"
|
||||||
|
|
||||||
#include "jsapi.h"
|
#include "jsapi.h"
|
||||||
#include "mozilla/dom/HistoryBinding.h"
|
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
#include "nsPIDOMWindow.h"
|
#include "nsPIDOMWindow.h"
|
||||||
#include "nsIDocument.h"
|
#include "nsIDocument.h"
|
||||||
|
@ -96,6 +95,38 @@ nsHistory::GetLength(ErrorResult& aRv) const
|
||||||
return len >= 0 ? len : 0;
|
return len >= 0 ? len : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ScrollRestoration
|
||||||
|
nsHistory::GetScrollRestoration(mozilla::ErrorResult& aRv)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsPIDOMWindow> win(do_QueryReferent(mInnerWindow));
|
||||||
|
if (!win || !win->HasActiveDocument() || !win->GetDocShell()) {
|
||||||
|
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
||||||
|
return mozilla::dom::ScrollRestoration::Auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool currentScrollRestorationIsManual = false;
|
||||||
|
win->GetDocShell()->
|
||||||
|
GetCurrentScrollRestorationIsManual(¤tScrollRestorationIsManual);
|
||||||
|
return currentScrollRestorationIsManual ?
|
||||||
|
mozilla::dom::ScrollRestoration::Manual :
|
||||||
|
mozilla::dom::ScrollRestoration::Auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsHistory::SetScrollRestoration(mozilla::dom::ScrollRestoration aMode,
|
||||||
|
mozilla::ErrorResult& aRv)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsPIDOMWindow> win(do_QueryReferent(mInnerWindow));
|
||||||
|
if (!win || !win->HasActiveDocument() || !win->GetDocShell()) {
|
||||||
|
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
win->GetDocShell()->
|
||||||
|
SetCurrentScrollRestorationIsManual(
|
||||||
|
aMode == mozilla::dom::ScrollRestoration::Manual);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsHistory::GetState(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
|
nsHistory::GetState(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
|
||||||
ErrorResult& aRv) const
|
ErrorResult& aRv) const
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
|
|
||||||
#include "mozilla/Attributes.h"
|
#include "mozilla/Attributes.h"
|
||||||
#include "mozilla/ErrorResult.h"
|
#include "mozilla/ErrorResult.h"
|
||||||
|
#include "mozilla/dom/HistoryBinding.h"
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
#include "nsCycleCollectionParticipant.h"
|
#include "nsCycleCollectionParticipant.h"
|
||||||
#include "nsIDOMHistory.h"
|
#include "nsIDOMHistory.h"
|
||||||
|
@ -36,6 +37,9 @@ public:
|
||||||
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
|
||||||
|
|
||||||
uint32_t GetLength(mozilla::ErrorResult& aRv) const;
|
uint32_t GetLength(mozilla::ErrorResult& aRv) const;
|
||||||
|
mozilla::dom::ScrollRestoration GetScrollRestoration(mozilla::ErrorResult& aRv);
|
||||||
|
void SetScrollRestoration(mozilla::dom::ScrollRestoration aMode,
|
||||||
|
mozilla::ErrorResult& aRv);
|
||||||
void GetState(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
|
void GetState(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
|
||||||
mozilla::ErrorResult& aRv) const;
|
mozilla::ErrorResult& aRv) const;
|
||||||
void Go(int32_t aDelta, mozilla::ErrorResult& aRv);
|
void Go(int32_t aDelta, mozilla::ErrorResult& aRv);
|
||||||
|
|
|
@ -11,10 +11,14 @@
|
||||||
* and create derivative works of this document.
|
* and create derivative works of this document.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
enum ScrollRestoration { "auto", "manual" };
|
||||||
|
|
||||||
interface History {
|
interface History {
|
||||||
[Throws]
|
[Throws]
|
||||||
readonly attribute unsigned long length;
|
readonly attribute unsigned long length;
|
||||||
[Throws]
|
[Throws]
|
||||||
|
attribute ScrollRestoration scrollRestoration;
|
||||||
|
[Throws]
|
||||||
readonly attribute any state;
|
readonly attribute any state;
|
||||||
[Throws, UnsafeInPrerendering]
|
[Throws, UnsafeInPrerendering]
|
||||||
void go(optional long delta = 0);
|
void go(optional long delta = 0);
|
||||||
|
|
|
@ -2084,6 +2084,11 @@ nsDocumentViewer::Hide(void)
|
||||||
|
|
||||||
nsCOMPtr<nsIDocShell> docShell(mContainer);
|
nsCOMPtr<nsIDocShell> docShell(mContainer);
|
||||||
if (docShell) {
|
if (docShell) {
|
||||||
|
#ifdef DEBUG
|
||||||
|
nsCOMPtr<nsIContentViewer> currentViewer;
|
||||||
|
docShell->GetContentViewer(getter_AddRefs(currentViewer));
|
||||||
|
MOZ_ASSERT(currentViewer == this);
|
||||||
|
#endif
|
||||||
nsCOMPtr<nsILayoutHistoryState> layoutState;
|
nsCOMPtr<nsILayoutHistoryState> layoutState;
|
||||||
mPresShell->CaptureHistoryState(getter_AddRefs(layoutState));
|
mPresShell->CaptureHistoryState(getter_AddRefs(layoutState));
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,8 +18,8 @@ class nsPresState;
|
||||||
template<typename> struct already_AddRefed;
|
template<typename> struct already_AddRefed;
|
||||||
|
|
||||||
#define NS_ILAYOUTHISTORYSTATE_IID \
|
#define NS_ILAYOUTHISTORYSTATE_IID \
|
||||||
{ 0x5208993e, 0xd812, 0x431e, \
|
{ 0xaef27cb3, 0x4df9, 0x4eeb, \
|
||||||
{ 0x95, 0x9c, 0xc3, 0x84, 0x5b, 0x6e, 0x5a, 0xce } }
|
{ 0xb0, 0xb0, 0xac, 0x56, 0xcf, 0x86, 0x1d, 0x04 } }
|
||||||
|
|
||||||
class nsILayoutHistoryState : public nsISupports {
|
class nsILayoutHistoryState : public nsISupports {
|
||||||
public:
|
public:
|
||||||
|
@ -53,6 +53,11 @@ class nsILayoutHistoryState : public nsISupports {
|
||||||
* or all possible history
|
* or all possible history
|
||||||
*/
|
*/
|
||||||
virtual void SetScrollPositionOnly(const bool aFlag) = 0;
|
virtual void SetScrollPositionOnly(const bool aFlag) = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets nsPresState::GetScrollState of all nsPresState objects to 0,0.
|
||||||
|
*/
|
||||||
|
virtual void ResetScrollState() = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
NS_DEFINE_STATIC_IID_ACCESSOR(nsILayoutHistoryState,
|
NS_DEFINE_STATIC_IID_ACCESSOR(nsILayoutHistoryState,
|
||||||
|
|
|
@ -36,7 +36,8 @@ public:
|
||||||
HasStates() const override;
|
HasStates() const override;
|
||||||
virtual void
|
virtual void
|
||||||
SetScrollPositionOnly(const bool aFlag) override;
|
SetScrollPositionOnly(const bool aFlag) override;
|
||||||
|
virtual void
|
||||||
|
ResetScrollState() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
~nsLayoutHistoryState() {}
|
~nsLayoutHistoryState() {}
|
||||||
|
@ -94,3 +95,14 @@ nsLayoutHistoryState::SetScrollPositionOnly(const bool aFlag)
|
||||||
{
|
{
|
||||||
mScrollPositionOnly = aFlag;
|
mScrollPositionOnly = aFlag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsLayoutHistoryState::ResetScrollState()
|
||||||
|
{
|
||||||
|
for (auto iter = mStates.Iter(); !iter.Done(); iter.Next()) {
|
||||||
|
nsPresState* state = iter.UserData();
|
||||||
|
if (state) {
|
||||||
|
state->SetScrollState(nsPoint(0, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -756,11 +756,15 @@ SessionStore.prototype = {
|
||||||
entry.contentType = aEntry.contentType;
|
entry.contentType = aEntry.contentType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (aEntry.scrollRestorationIsManual) {
|
||||||
|
entry.scrollRestorationIsManual = true;
|
||||||
|
} else {
|
||||||
let x = {}, y = {};
|
let x = {}, y = {};
|
||||||
aEntry.getScrollPosition(x, y);
|
aEntry.getScrollPosition(x, y);
|
||||||
if (x.value != 0 || y.value != 0) {
|
if (x.value != 0 || y.value != 0) {
|
||||||
entry.scroll = x.value + "," + y.value;
|
entry.scroll = x.value + "," + y.value;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (aEntry.owner) {
|
if (aEntry.owner) {
|
||||||
try {
|
try {
|
||||||
|
@ -862,7 +866,9 @@ SessionStore.prototype = {
|
||||||
shEntry.stateData.initFromBase64(aEntry.structuredCloneState, aEntry.structuredCloneVersion);
|
shEntry.stateData.initFromBase64(aEntry.structuredCloneState, aEntry.structuredCloneVersion);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aEntry.scroll) {
|
if (aEntry.scrollRestorationIsManual) {
|
||||||
|
shEntry.scrollRestorationIsManual = true;
|
||||||
|
} else if (aEntry.scroll) {
|
||||||
let scrollPos = aEntry.scroll.split(",");
|
let scrollPos = aEntry.scroll.split(",");
|
||||||
scrollPos = [parseInt(scrollPos[0]) || 0, parseInt(scrollPos[1]) || 0];
|
scrollPos = [parseInt(scrollPos[0]) || 0, parseInt(scrollPos[1]) || 0];
|
||||||
shEntry.setScrollPosition(scrollPos[0], scrollPos[1]);
|
shEntry.setScrollPosition(scrollPos[0], scrollPos[1]);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче