diff options
Diffstat (limited to 'docshell')
-rw-r--r-- | docshell/base/moz.build | 3 | ||||
-rw-r--r-- | docshell/base/nsAboutRedirector.cpp | 40 | ||||
-rw-r--r-- | docshell/base/nsDSURIContentListener.cpp | 86 | ||||
-rw-r--r-- | docshell/base/nsDSURIContentListener.h | 21 | ||||
-rw-r--r-- | docshell/base/nsDocShell.cpp | 51 | ||||
-rw-r--r-- | docshell/base/nsIRefreshURI.idl | 15 | ||||
-rw-r--r-- | docshell/build/moz.build | 3 | ||||
-rw-r--r-- | docshell/build/nsDocShellModule.cpp | 8 | ||||
-rwxr-xr-x[-rw-r--r--] | docshell/test/chrome/test_bug453650.xul | 4 | ||||
-rw-r--r-- | docshell/test/file_bug1151421.html | 19 | ||||
-rw-r--r-- | docshell/test/mochitest.ini | 2 | ||||
-rw-r--r-- | docshell/test/navigation/file_scrollRestoration.html | 14 | ||||
-rw-r--r-- | docshell/test/test_bug1151421.html | 61 | ||||
-rw-r--r-- | docshell/test/test_bug1186774.html | 2 | ||||
-rw-r--r-- | docshell/test/test_bug590573.html | 16 | ||||
-rw-r--r-- | docshell/test/test_bug653741.html | 4 | ||||
-rw-r--r-- | docshell/test/test_bug662170.html | 2 |
17 files changed, 244 insertions, 107 deletions
diff --git a/docshell/base/moz.build b/docshell/base/moz.build index 1eb04c227..6ea3e6d28 100644 --- a/docshell/base/moz.build +++ b/docshell/base/moz.build @@ -81,8 +81,5 @@ LOCAL_INCLUDES += [ if CONFIG['MOZ_TOOLKIT_SEARCH']: DEFINES['MOZ_TOOLKIT_SEARCH'] = True -if CONFIG['MOZ_DEVTOOLS'] == 'all': - DEFINES['MOZ_DEVTOOLS_ALL'] = True - if CONFIG['GNU_CXX']: CXXFLAGS += ['-Wno-error=shadow'] diff --git a/docshell/base/nsAboutRedirector.cpp b/docshell/base/nsAboutRedirector.cpp index f300e0ce2..e56447296 100644 --- a/docshell/base/nsAboutRedirector.cpp +++ b/docshell/base/nsAboutRedirector.cpp @@ -41,22 +41,21 @@ static RedirEntry kRedirMap[] = { }, { "buildconfig", "chrome://global/content/buildconfig.html", - nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT + nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT | + nsIAboutModule::MAKE_LINKABLE }, { "checkerboard", "chrome://global/content/aboutCheckerboard.xhtml", nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT | - nsIAboutModule::ALLOW_SCRIPT + nsIAboutModule::ALLOW_SCRIPT }, { "config", "chrome://global/content/config.xul", 0 }, -#ifdef MOZ_CRASHREPORTER - { "crashes", "chrome://global/content/crashes.xhtml", 0 }, -#endif { - "credits", "https://www.mozilla.org/credits/", - nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT + "credits", "http://www.palemoon.org/Contributors.shtml", + nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT | + nsIAboutModule::MAKE_LINKABLE }, -#ifdef MOZ_DEVTOOLS_ALL +#ifdef MOZ_DEVTOOLS { "debugging", "chrome://devtools/content/aboutdebugging/aboutdebugging.xhtml", nsIAboutModule::ALLOW_SCRIPT @@ -65,7 +64,7 @@ static RedirEntry kRedirMap[] = { { "license", "chrome://global/content/license.html", nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT | - nsIAboutModule::MAKE_LINKABLE + nsIAboutModule::MAKE_LINKABLE }, { "logo", "chrome://branding/content/about.png", @@ -73,6 +72,13 @@ static RedirEntry kRedirMap[] = { // Linkable for testing reasons. nsIAboutModule::MAKE_LINKABLE }, +#ifdef MOZ_PHOENIX + { + "logopage", "chrome://global/content/logopage.xhtml", + nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT | + nsIAboutModule::HIDE_FROM_ABOUTABOUT + }, +#endif { "memory", "chrome://global/content/aboutMemory.xhtml", nsIAboutModule::ALLOW_SCRIPT @@ -84,9 +90,9 @@ static RedirEntry kRedirMap[] = { { "neterror", "chrome://global/content/netError.xhtml", nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT | - nsIAboutModule::URI_CAN_LOAD_IN_CHILD | - nsIAboutModule::ALLOW_SCRIPT | - nsIAboutModule::HIDE_FROM_ABOUTABOUT + nsIAboutModule::URI_CAN_LOAD_IN_CHILD | + nsIAboutModule::ALLOW_SCRIPT | + nsIAboutModule::HIDE_FROM_ABOUTABOUT }, { "networking", "chrome://global/content/aboutNetworking.xhtml", @@ -95,7 +101,7 @@ static RedirEntry kRedirMap[] = { { "newaddon", "chrome://mozapps/content/extensions/newaddon.xul", nsIAboutModule::ALLOW_SCRIPT | - nsIAboutModule::HIDE_FROM_ABOUTABOUT + nsIAboutModule::HIDE_FROM_ABOUTABOUT }, { "performance", "chrome://global/content/aboutPerformance.xhtml", @@ -122,10 +128,10 @@ static RedirEntry kRedirMap[] = { { "srcdoc", "about:blank", nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT | - nsIAboutModule::HIDE_FROM_ABOUTABOUT | - // Needs to be linkable so content can touch its own srcdoc frames - nsIAboutModule::MAKE_LINKABLE | - nsIAboutModule::URI_CAN_LOAD_IN_CHILD + nsIAboutModule::HIDE_FROM_ABOUTABOUT | + // Needs to be linkable so content can touch its own srcdoc frames + nsIAboutModule::MAKE_LINKABLE | + nsIAboutModule::URI_CAN_LOAD_IN_CHILD }, { "support", "chrome://global/content/aboutSupport.xhtml", diff --git a/docshell/base/nsDSURIContentListener.cpp b/docshell/base/nsDSURIContentListener.cpp index cfac54f7f..93ce3cb26 100644 --- a/docshell/base/nsDSURIContentListener.cpp +++ b/docshell/base/nsDSURIContentListener.cpp @@ -22,6 +22,7 @@ #include "nsIScriptError.h" #include "nsDocShellLoadTypes.h" #include "nsIMultiPartChannel.h" +#include "mozilla/dom/nsCSPUtils.h" using namespace mozilla; @@ -84,14 +85,6 @@ nsDSURIContentListener::DoContent(const nsACString& aContentType, NS_ENSURE_ARG_POINTER(aContentHandler); NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE); - // Check whether X-Frame-Options permits us to load this content in an - // iframe and abort the load (unless we've disabled x-frame-options - // checking). - if (!CheckFrameOptions(aRequest)) { - *aAbortProcess = true; - return NS_OK; - } - *aAbortProcess = false; // determine if the channel has just been retargeted to us... @@ -265,9 +258,10 @@ nsDSURIContentListener::SetParentContentListener( return NS_OK; } -bool +/* static */ bool nsDSURIContentListener::CheckOneFrameOptionsPolicy(nsIHttpChannel* aHttpChannel, - const nsAString& aPolicy) + const nsAString& aPolicy, + nsIDocShell* aDocShell) { static const char allowFrom[] = "allow-from"; const uint32_t allowFromLen = ArrayLength(allowFrom) - 1; @@ -285,7 +279,7 @@ nsDSURIContentListener::CheckOneFrameOptionsPolicy(nsIHttpChannel* aHttpChannel, aHttpChannel->GetURI(getter_AddRefs(uri)); // XXXkhuey when does this happen? Is returning true safe here? - if (!mDocShell) { + if (!aDocShell) { return true; } @@ -293,7 +287,7 @@ nsDSURIContentListener::CheckOneFrameOptionsPolicy(nsIHttpChannel* aHttpChannel, // window, if we're not the top. X-F-O: SAMEORIGIN requires that the // document must be same-origin with top window. X-F-O: DENY requires that // the document must never be framed. - nsCOMPtr<nsPIDOMWindowOuter> thisWindow = mDocShell->GetWindow(); + nsCOMPtr<nsPIDOMWindowOuter> thisWindow = aDocShell->GetWindow(); // If we don't have DOMWindow there is no risk of clickjacking if (!thisWindow) { return true; @@ -313,7 +307,7 @@ nsDSURIContentListener::CheckOneFrameOptionsPolicy(nsIHttpChannel* aHttpChannel, // content-type docshell doesn't work because some chrome documents are // loaded in content docshells (see bug 593387). nsCOMPtr<nsIDocShellTreeItem> thisDocShellItem( - do_QueryInterface(static_cast<nsIDocShell*>(mDocShell))); + do_QueryInterface(static_cast<nsIDocShell*>(aDocShell))); nsCOMPtr<nsIDocShellTreeItem> parentDocShellItem; nsCOMPtr<nsIDocShellTreeItem> curDocShellItem = thisDocShellItem; nsCOMPtr<nsIDocument> topDoc; @@ -402,22 +396,66 @@ nsDSURIContentListener::CheckOneFrameOptionsPolicy(nsIHttpChannel* aHttpChannel, return true; } +// Ignore x-frame-options if CSP with frame-ancestors exists +static bool +ShouldIgnoreFrameOptions(nsIChannel* aChannel, nsIPrincipal* aPrincipal) +{ + NS_ENSURE_TRUE(aChannel, false); + NS_ENSURE_TRUE(aPrincipal, false); + + nsCOMPtr<nsIContentSecurityPolicy> csp; + aPrincipal->GetCsp(getter_AddRefs(csp)); + if (!csp) { + // if there is no CSP, then there is nothing to do here + return false; + } + + bool enforcesFrameAncestors = false; + csp->GetEnforcesFrameAncestors(&enforcesFrameAncestors); + if (!enforcesFrameAncestors) { + // if CSP does not contain frame-ancestors, then there + // is nothing to do here. + return false; + } + + // log warning to console that xfo is ignored because of CSP + nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo(); + uint64_t innerWindowID = loadInfo ? loadInfo->GetInnerWindowID() : 0; + const char16_t* params[] = { u"x-frame-options", + u"frame-ancestors" }; + CSP_LogLocalizedStr(u"IgnoringSrcBecauseOfDirective", + params, ArrayLength(params), + EmptyString(), // no sourcefile + EmptyString(), // no scriptsample + 0, // no linenumber + 0, // no columnnumber + nsIScriptError::warningFlag, + "CSP", innerWindowID); + + return true; +} + // Check if X-Frame-Options permits this document to be loaded as a subdocument. // This will iterate through and check any number of X-Frame-Options policies // in the request (comma-separated in a header, multiple headers, etc). -bool -nsDSURIContentListener::CheckFrameOptions(nsIRequest* aRequest) +/* static */ bool +nsDSURIContentListener::CheckFrameOptions(nsIChannel* aChannel, + nsIDocShell* aDocShell, + nsIPrincipal* aPrincipal) { - nsresult rv; - nsCOMPtr<nsIChannel> chan = do_QueryInterface(aRequest); - if (!chan) { + if (!aChannel || !aDocShell) { return true; } - nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(chan); + if (ShouldIgnoreFrameOptions(aChannel, aPrincipal)) { + return true; + } + + nsresult rv; + nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel); if (!httpChannel) { // check if it is hiding in a multipart channel - rv = mDocShell->GetHttpChannel(chan, getter_AddRefs(httpChannel)); + rv = nsDocShell::Cast(aDocShell)->GetHttpChannel(aChannel, getter_AddRefs(httpChannel)); if (NS_FAILED(rv)) { return false; } @@ -442,11 +480,11 @@ nsDSURIContentListener::CheckFrameOptions(nsIRequest* aRequest) nsCharSeparatedTokenizer tokenizer(xfoHeaderValue, ','); while (tokenizer.hasMoreTokens()) { const nsSubstring& tok = tokenizer.nextToken(); - if (!CheckOneFrameOptionsPolicy(httpChannel, tok)) { + if (!CheckOneFrameOptionsPolicy(httpChannel, tok, aDocShell)) { // cancel the load and display about:blank httpChannel->Cancel(NS_BINDING_ABORTED); - if (mDocShell) { - nsCOMPtr<nsIWebNavigation> webNav(do_QueryObject(mDocShell)); + if (aDocShell) { + nsCOMPtr<nsIWebNavigation> webNav(do_QueryObject(aDocShell)); if (webNav) { webNav->LoadURI(u"about:blank", 0, nullptr, nullptr, nullptr); @@ -459,7 +497,7 @@ nsDSURIContentListener::CheckFrameOptions(nsIRequest* aRequest) return true; } -void +/* static */ void nsDSURIContentListener::ReportXFOViolation(nsIDocShellTreeItem* aTopDocShellItem, nsIURI* aThisURI, XFOHeader aHeader) diff --git a/docshell/base/nsDSURIContentListener.h b/docshell/base/nsDSURIContentListener.h index f33d1c045..432813471 100644 --- a/docshell/base/nsDSURIContentListener.h +++ b/docshell/base/nsDSURIContentListener.h @@ -28,6 +28,12 @@ public: nsresult Init(); + // Determine if X-Frame-Options allows content to be framed + // as a subdocument + static bool CheckFrameOptions(nsIChannel* aChannel, + nsIDocShell* aDocShell, + nsIPrincipal* aPrincipal); + protected: explicit nsDSURIContentListener(nsDocShell* aDocShell); virtual ~nsDSURIContentListener(); @@ -39,12 +45,9 @@ protected: mExistingJPEGStreamListener = nullptr; } - // Determine if X-Frame-Options allows content to be framed - // as a subdocument - bool CheckFrameOptions(nsIRequest* aRequest); - bool CheckOneFrameOptionsPolicy(nsIHttpChannel* aHttpChannel, - const nsAString& aPolicy); - + static bool CheckOneFrameOptionsPolicy(nsIHttpChannel* aHttpChannel, + const nsAString& aPolicy, + nsIDocShell* aDocShell); enum XFOHeader { eDENY, @@ -52,9 +55,9 @@ protected: eALLOWFROM }; - void ReportXFOViolation(nsIDocShellTreeItem* aTopDocShellItem, - nsIURI* aThisURI, - XFOHeader aHeader); + static void ReportXFOViolation(nsIDocShellTreeItem* aTopDocShellItem, + nsIURI* aThisURI, + XFOHeader aHeader); protected: nsDocShell* mDocShell; diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp index ab119a016..58c182cbb 100644 --- a/docshell/base/nsDocShell.cpp +++ b/docshell/base/nsDocShell.cpp @@ -2289,13 +2289,6 @@ nsDocShell::GetUseRemoteTabs(bool* aUseRemoteTabs) NS_IMETHODIMP nsDocShell::SetRemoteTabs(bool aUseRemoteTabs) { -#ifdef MOZ_CRASHREPORTER - if (aUseRemoteTabs) { - CrashReporter::AnnotateCrashReport(NS_LITERAL_CSTRING("DOMIPCEnabled"), - NS_LITERAL_CSTRING("1")); - } -#endif - mUseRemoteTabs = aUseRemoteTabs; return NS_OK; } @@ -6806,9 +6799,17 @@ nsDocShell::ForceRefreshURI(nsIURI* aURI, int32_t aDelay, bool aMetaRefresh, nsI */ loadInfo->SetReferrer(mCurrentURI); - /* Don't ever "guess" on which principal to use to avoid picking - * the current principal. - */ + // Set the triggering pricipal to aPrincipal if available, or current + // document's principal otherwise. + nsCOMPtr<nsIPrincipal> principal = aPrincipal; + if (!principal) { + nsCOMPtr<nsIDocument> doc = GetDocument(); + if (!doc) { + return NS_ERROR_FAILURE; + } + principal = doc->NodePrincipal(); + } + loadInfo->SetTriggeringPrincipal(principal); loadInfo->SetPrincipalIsExplicit(true); /* Check if this META refresh causes a redirection @@ -6836,13 +6837,6 @@ nsDocShell::ForceRefreshURI(nsIURI* aURI, int32_t aDelay, bool aMetaRefresh, nsI loadInfo->SetLoadType(nsIDocShellLoadInfo::loadRefresh); } - // If the principal is null, the refresh will have a triggeringPrincipal - // derived from the referrer URI, or will be set to the system principal - // if there is no refererrer. See LoadURI() - if (aPrincipal) { - loadInfo->SetTriggeringPrincipal(aPrincipal); - } - /* * LoadURI(...) will cancel all refresh timers... This causes the * Timer and its refreshData instance to be released... @@ -11025,6 +11019,29 @@ nsDocShell::DoURILoad(nsIURI* aURI, } } + // Navigational requests that are same origin need to be upgraded in case + // upgrade-insecure-requests is present. Please note that in that case + // the triggeringPrincipal is holding the CSP that potentially + // holds upgrade-insecure-requests. + nsCOMPtr<nsIContentSecurityPolicy> csp; + aTriggeringPrincipal->GetCsp(getter_AddRefs(csp)); + if (csp) { + bool upgradeInsecureRequests = false; + csp->GetUpgradeInsecureRequests(&upgradeInsecureRequests); + if (upgradeInsecureRequests) { + // only upgrade if the navigation is same origin + nsCOMPtr<nsIPrincipal> resultPrincipal; + rv = nsContentUtils::GetSecurityManager()-> + GetChannelResultPrincipal(channel, + getter_AddRefs(resultPrincipal)); + NS_ENSURE_SUCCESS(rv, rv); + if (resultPrincipal->Equals(aTriggeringPrincipal)) { + static_cast<mozilla::LoadInfo*>(loadInfo.get())->SetUpgradeInsecureRequests(); + } + } + } + + nsCOMPtr<nsIApplicationCacheChannel> appCacheChannel = do_QueryInterface(channel); if (appCacheChannel) { diff --git a/docshell/base/nsIRefreshURI.idl b/docshell/base/nsIRefreshURI.idl index 5abd829da..04f18eee0 100644 --- a/docshell/base/nsIRefreshURI.idl +++ b/docshell/base/nsIRefreshURI.idl @@ -19,9 +19,8 @@ interface nsIRefreshURI : nsISupports { * * @param aUri The uri to refresh. * @param aPrincipal The triggeringPrincipal for the refresh load - * May be null, in which case a principal will be built based on the - * referrer URI of the previous docshell load, or will use the system - * principal when there is no referrer. + * May be null, in which case the principal of current document will be + * applied. * @param aMillis The number of milliseconds to wait. * @param aRepeat Flag to indicate if the uri is to be * repeatedly refreshed every aMillis milliseconds. @@ -37,9 +36,8 @@ interface nsIRefreshURI : nsISupports { * * @param aURI The URI to refresh. * @param aPrincipal The triggeringPrincipal for the refresh load - * May be null, in which case a principal will be built based on the - * referrer URI of the previous docshell load, or will use the system - * principal when there is no referrer. + * May be null, in which case the principal of current document will be + * applied. * @param aMillis The number of milliseconds by which this refresh would * be delayed if it were not being forced. * @param aMetaRefresh Flag to indicate if this is a meta refresh. @@ -70,9 +68,8 @@ interface nsIRefreshURI : nsISupports { * * @param aBaseURI base URI to resolve refresh uri with. * @param aPrincipal The triggeringPrincipal for the refresh load - * May be null, in which case a principal will be built based on the - * referrer URI of the previous docshell load, or will use the system - * principal when there is no referrer. + * May be null, in which case the principal of current document will be + * applied. * @param aHeader The meta refresh header string. */ void setupRefreshURIFromHeader(in nsIURI aBaseURI, diff --git a/docshell/build/moz.build b/docshell/build/moz.build index 130ec8736..e47bd89ed 100644 --- a/docshell/build/moz.build +++ b/docshell/build/moz.build @@ -23,6 +23,3 @@ LOCAL_INCLUDES += [ include('/ipc/chromium/chromium-config.mozbuild') FINAL_LIBRARY = 'xul' - -if CONFIG['MOZ_DEVTOOLS'] == 'all': - DEFINES['MOZ_DEVTOOLS_ALL'] = True diff --git a/docshell/build/nsDocShellModule.cpp b/docshell/build/nsDocShellModule.cpp index 1e62e1479..872874012 100644 --- a/docshell/build/nsDocShellModule.cpp +++ b/docshell/build/nsDocShellModule.cpp @@ -165,15 +165,15 @@ const mozilla::Module::ContractIDEntry kDocShellContracts[] = { { NS_ABOUT_MODULE_CONTRACTID_PREFIX "buildconfig", &kNS_ABOUT_REDIRECTOR_MODULE_CID }, { NS_ABOUT_MODULE_CONTRACTID_PREFIX "checkerboard", &kNS_ABOUT_REDIRECTOR_MODULE_CID }, { NS_ABOUT_MODULE_CONTRACTID_PREFIX "config", &kNS_ABOUT_REDIRECTOR_MODULE_CID }, -#ifdef MOZ_CRASHREPORTER - { NS_ABOUT_MODULE_CONTRACTID_PREFIX "crashes", &kNS_ABOUT_REDIRECTOR_MODULE_CID }, -#endif { NS_ABOUT_MODULE_CONTRACTID_PREFIX "credits", &kNS_ABOUT_REDIRECTOR_MODULE_CID }, -#ifdef MOZ_DEVTOOLS_ALL +#ifdef MOZ_DEVTOOLS { NS_ABOUT_MODULE_CONTRACTID_PREFIX "debugging", &kNS_ABOUT_REDIRECTOR_MODULE_CID }, #endif { NS_ABOUT_MODULE_CONTRACTID_PREFIX "license", &kNS_ABOUT_REDIRECTOR_MODULE_CID }, { NS_ABOUT_MODULE_CONTRACTID_PREFIX "logo", &kNS_ABOUT_REDIRECTOR_MODULE_CID }, +#ifdef MOZ_PHOENIX + { NS_ABOUT_MODULE_CONTRACTID_PREFIX "logopage", &kNS_ABOUT_REDIRECTOR_MODULE_CID }, +#endif { NS_ABOUT_MODULE_CONTRACTID_PREFIX "memory", &kNS_ABOUT_REDIRECTOR_MODULE_CID }, { NS_ABOUT_MODULE_CONTRACTID_PREFIX "mozilla", &kNS_ABOUT_REDIRECTOR_MODULE_CID }, { NS_ABOUT_MODULE_CONTRACTID_PREFIX "neterror", &kNS_ABOUT_REDIRECTOR_MODULE_CID }, diff --git a/docshell/test/chrome/test_bug453650.xul b/docshell/test/chrome/test_bug453650.xul index 2837e56d8..04acefe6d 100644..100755 --- a/docshell/test/chrome/test_bug453650.xul +++ b/docshell/test/chrome/test_bug453650.xul @@ -61,7 +61,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=453650 } info("times: " + start + ", " + end); - ok(start < end, "reflow start time lower than end time"); + ok(start <= end, "reflow start time lower than end time"); done(); }, @@ -73,7 +73,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=453650 } info("times: " + start + ", " + end); - ok(start < end, "reflow start time lower than end time"); + ok(start <= end, "reflow start time lower than end time"); done(); }, diff --git a/docshell/test/file_bug1151421.html b/docshell/test/file_bug1151421.html new file mode 100644 index 000000000..7bb8c8f36 --- /dev/null +++ b/docshell/test/file_bug1151421.html @@ -0,0 +1,19 @@ +<html> +<head> +<style> +body, html { + height: 100%; +} +.spacer { + height: 80%; +} +</style> +</head> +<body onload='(parent || opener).childLoad()'> + +<div class="spacer"></div> +<div id="content">content</div> +<div class="spacer"></div> + +</body> +</html> diff --git a/docshell/test/mochitest.ini b/docshell/test/mochitest.ini index 725486b77..7b27908fb 100644 --- a/docshell/test/mochitest.ini +++ b/docshell/test/mochitest.ini @@ -32,6 +32,7 @@ support-files = file_bug680257.html file_bug703855.html file_bug728939.html + file_bug1151421.html file_pushState_after_document_open.html historyframes.html @@ -85,6 +86,7 @@ support-files = file_bug668513.html [test_bug797909.html] [test_bug1045096.html] [test_bug1121701.html] +[test_bug1151421.html] [test_bug1186774.html] [test_forceinheritprincipal_overrule_owner.html] [test_framedhistoryframes.html] diff --git a/docshell/test/navigation/file_scrollRestoration.html b/docshell/test/navigation/file_scrollRestoration.html index 5450c2724..92e43d7fb 100644 --- a/docshell/test/navigation/file_scrollRestoration.html +++ b/docshell/test/navigation/file_scrollRestoration.html @@ -26,7 +26,7 @@ } case 2: { opener.is(event.persisted, false, "Shouldn't have persisted session history entry."); - opener.isnot(window.scrollY, 0, "Should have restored scrolling."); + opener.isnot(Math.round(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. @@ -45,7 +45,7 @@ } 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.isnot(Math.round(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"; @@ -53,7 +53,7 @@ break; } case 5: { - opener.isnot(window.scrollY, 0, "Should have scrolled to #hash."); + opener.isnot(Math.round(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); @@ -70,7 +70,7 @@ 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.isnot(Math.round(window.scrollY), 0, "Should have scrolled back to the state1's position"); opener.is(history.state.state, "state1", "Unexpected state."); history.scrollRestoration = "manual"; @@ -79,17 +79,17 @@ 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(Math.round(window.scrollY), 0, "Shouldn't have scrolled back to the state3's position"); opener.is(history.state.state, "state3", "Unexpected state."); history.pushState({ state: "state5" }, "state5"); history.scrollRestoration = "auto"; document.getElementById("bottom").scrollIntoView(); - opener.isnot(window.scrollY, 0, "Should have scrolled to 'bottom'."); + opener.isnot(Math.round(window.scrollY), 0, "Should have scrolled to 'bottom'."); history.back(); window.scrollTo(0, 0); history.forward(); - opener.isnot(window.scrollY, 0, "Should have scrolled back to the state5's position"); + opener.isnot(Math.round(window.scrollY), 0, "Should have scrolled back to the state5's position"); var ifr = document.createElement("iframe"); ifr.src = "data:text/html,"; diff --git a/docshell/test/test_bug1151421.html b/docshell/test/test_bug1151421.html new file mode 100644 index 000000000..76e34d502 --- /dev/null +++ b/docshell/test/test_bug1151421.html @@ -0,0 +1,61 @@ +<!DOCTYPE HTML> +<html> +<!-- +https://bugzilla.mozilla.org/show_bug.cgi?id=1151421 +--> +<head> + <title>Test for Bug 1151421</title> + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> +</head> +<body> +<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1151421">Mozilla Bug 1151421</a> + +<script type="application/javascript"> + +/** Test for Bug 1151421 **/ +SimpleTest.waitForExplicitFinish(); + +function childLoad() { + // Spin the event loop so we leave the onload handler. + SimpleTest.executeSoon(childLoad2); +} + +function childLoad2() { + let cw = iframe.contentWindow; + let content = cw.document.getElementById("content"); + + // Create a function to calculate an invariant. + let topPlusOffset = function() + { + return Math.round(content.getBoundingClientRect().top + cw.pageYOffset); + } + + let initialTPO = topPlusOffset(); + + // Scroll the iframe to various positions, and check the TPO. + // Scrolling down to the bottom will adjust the page offset by a fractional amount. + let positions = [-100, 0.17, 0, 1.5, 10.41, 1e6, 12.1]; + + // Run some tests with scrollTo() and ensure we have the same invariant after scrolling. + positions.forEach(function(pos) { + cw.scrollTo(0, pos); + is(topPlusOffset(), initialTPO, "Top plus offset should remain invariant across scrolling."); + }); + + positions.reverse().forEach(function(pos) { + cw.scrollTo(0, pos); + is(topPlusOffset(), initialTPO, "(reverse) Top plus offset should remain invariant across scrolling."); + }); + + SimpleTest.finish(); +} + +</script> + +<!-- When the iframe loads, it calls childLoad(). --> +<br> +<iframe height='100px' id='iframe' src='file_bug1151421.html'></iframe> + +</body> +</html> diff --git a/docshell/test/test_bug1186774.html b/docshell/test/test_bug1186774.html index 52ef5f62c..623e7996b 100644 --- a/docshell/test/test_bug1186774.html +++ b/docshell/test/test_bug1186774.html @@ -28,7 +28,7 @@ function runTest() { } child.onpopstate = function() { - is(child.scrollY, 6000, "Shouldn't have scrolled before popstate"); + is(Math.round(child.scrollY), 6000, "Shouldn't have scrolled before popstate"); child.close(); SimpleTest.finish(); } diff --git a/docshell/test/test_bug590573.html b/docshell/test/test_bug590573.html index aa6d3bd79..e218140ea 100644 --- a/docshell/test/test_bug590573.html +++ b/docshell/test/test_bug590573.html @@ -147,21 +147,21 @@ function* testBody() popup.scroll(0, 100); popup.history.pushState('', '', '?pushed'); - is(popup.scrollY, 100, "test 2"); + is(Math.round(popup.scrollY), 100, "test 2"); popup.scroll(0, 200); // set state-2's position to 200 popup.history.back(); - is(popup.scrollY, 100, "test 3"); + is(Math.round(popup.scrollY), 100, "test 3"); popup.scroll(0, 150); // set original page's position to 150 popup.history.forward(); - is(popup.scrollY, 200, "test 4"); + is(Math.round(popup.scrollY), 200, "test 4"); popup.history.back(); - is(popup.scrollY, 150, "test 5"); + is(Math.round(popup.scrollY), 150, "test 5"); popup.history.forward(); - is(popup.scrollY, 200, "test 6"); + is(Math.round(popup.scrollY), 200, "test 6"); // At this point, the history looks like: // PATH POSITION @@ -202,13 +202,13 @@ function* testBody() is(popup.location.search, "?pushed"); ok(popup.document.getElementById('div1'), 'page should have div1.'); - is(popup.scrollY, 200, "test 8"); + is(Math.round(popup.scrollY), 200, "test 8"); popup.history.back(); - is(popup.scrollY, 150, "test 9"); + is(Math.round(popup.scrollY), 150, "test 9"); popup.history.forward(); - is(popup.scrollY, 200, "test 10"); + is(Math.round(popup.scrollY), 200, "test 10"); // Spin one last time... setTimeout(pageLoad, 0); diff --git a/docshell/test/test_bug653741.html b/docshell/test/test_bug653741.html index f4d4587b8..a1faf5e2d 100644 --- a/docshell/test/test_bug653741.html +++ b/docshell/test/test_bug653741.html @@ -27,7 +27,7 @@ function childLoad2() { // Save the Y offset. For sanity's sake, make sure it's not 0, because we // should be at the bottom of the page! - let origYOffset = cw.pageYOffset; + let origYOffset = Math.round(cw.pageYOffset); ok(origYOffset != 0, 'Original Y offset is not 0.'); // Scroll the iframe to the top, then navigate to #bottom again. @@ -37,7 +37,7 @@ function childLoad2() { // bottom again. cw.location = cw.location + ''; - is(cw.pageYOffset, origYOffset, 'Correct offset after reloading page.'); + is(Math.round(cw.pageYOffset), origYOffset, 'Correct offset after reloading page.'); SimpleTest.finish(); } diff --git a/docshell/test/test_bug662170.html b/docshell/test/test_bug662170.html index 514bb55b1..0e626fed4 100644 --- a/docshell/test/test_bug662170.html +++ b/docshell/test/test_bug662170.html @@ -32,7 +32,7 @@ function childLoad2() { cw.scrollTo(0, 300); // Did we actually scroll somewhere? - isnot(cw.pageYOffset, 0, 'Y offset should be non-zero after scrolling.'); + isnot(Math.round(cw.pageYOffset), 0, 'Y offset should be non-zero after scrolling.'); // Now load file_bug662170.html#, which should take us to the top of the // page. |