diff --git a/docshell/base/BrowsingContext.cpp b/docshell/base/BrowsingContext.cpp index db5b5b990727..1b97e7d958bc 100644 --- a/docshell/base/BrowsingContext.cpp +++ b/docshell/base/BrowsingContext.cpp @@ -3772,7 +3772,7 @@ bool BrowsingContext::ShouldUpdateSessionHistory(uint32_t aLoadType) { (IsForceReloadType(aLoadType) && IsSubframe())); } -nsresult BrowsingContext::CheckLocationChangeRateLimit(CallerType aCallerType) { +nsresult BrowsingContext::CheckNavigationRateLimit(CallerType aCallerType) { // We only rate limit non system callers if (aCallerType == CallerType::System) { return NS_OK; @@ -3780,9 +3780,9 @@ nsresult BrowsingContext::CheckLocationChangeRateLimit(CallerType aCallerType) { // Fetch rate limiting preferences uint32_t limitCount = - StaticPrefs::dom_navigation_locationChangeRateLimit_count(); + StaticPrefs::dom_navigation_navigationRateLimit_count(); uint32_t timeSpanSeconds = - StaticPrefs::dom_navigation_locationChangeRateLimit_timespan(); + StaticPrefs::dom_navigation_navigationRateLimit_timespan(); // Disable throttling if either of the preferences is set to 0. if (limitCount == 0 || timeSpanSeconds == 0) { @@ -3791,15 +3791,15 @@ nsresult BrowsingContext::CheckLocationChangeRateLimit(CallerType aCallerType) { TimeDuration throttleSpan = TimeDuration::FromSeconds(timeSpanSeconds); - if (mLocationChangeRateLimitSpanStart.IsNull() || - ((TimeStamp::Now() - mLocationChangeRateLimitSpanStart) > throttleSpan)) { + if (mNavigationRateLimitSpanStart.IsNull() || + ((TimeStamp::Now() - mNavigationRateLimitSpanStart) > throttleSpan)) { // Initial call or timespan exceeded, reset counter and timespan. - mLocationChangeRateLimitSpanStart = TimeStamp::Now(); - mLocationChangeRateLimitCount = 1; + mNavigationRateLimitSpanStart = TimeStamp::Now(); + mNavigationRateLimitCount = 1; return NS_OK; } - if (mLocationChangeRateLimitCount >= limitCount) { + if (mNavigationRateLimitCount >= limitCount) { // Rate limit reached Document* doc = GetDocument(); @@ -3812,14 +3812,14 @@ nsresult BrowsingContext::CheckLocationChangeRateLimit(CallerType aCallerType) { return NS_ERROR_DOM_SECURITY_ERR; } - mLocationChangeRateLimitCount++; + mNavigationRateLimitCount++; return NS_OK; } -void BrowsingContext::ResetLocationChangeRateLimit() { +void BrowsingContext::ResetNavigationRateLimit() { // Resetting the timestamp object will cause the check function to // init again and reset the rate limit. - mLocationChangeRateLimitSpanStart = TimeStamp(); + mNavigationRateLimitSpanStart = TimeStamp(); } void BrowsingContext::LocationCreated(dom::Location* aLocation) { diff --git a/docshell/base/BrowsingContext.h b/docshell/base/BrowsingContext.h index 97c633faf806..af7ed888bf10 100644 --- a/docshell/base/BrowsingContext.h +++ b/docshell/base/BrowsingContext.h @@ -898,13 +898,13 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache { // Checks if we reached the rate limit for calls to Location and History API. // The rate limit is controlled by the - // "dom.navigation.locationChangeRateLimit" prefs. + // "dom.navigation.navigationRateLimit" prefs. // Rate limit applies per BrowsingContext. // Returns NS_OK if we are below the rate limit and increments the counter. // Returns NS_ERROR_DOM_SECURITY_ERR if limit is reached. - nsresult CheckLocationChangeRateLimit(CallerType aCallerType); + nsresult CheckNavigationRateLimit(CallerType aCallerType); - void ResetLocationChangeRateLimit(); + void ResetNavigationRateLimit(); mozilla::dom::DisplayMode DisplayMode() { return Top()->GetDisplayMode(); } @@ -1432,9 +1432,9 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache { nsTArray> mDiscardListeners; // Counter and time span for rate limiting Location and History API calls. - // Used by CheckLocationChangeRateLimit. Do not apply cross-process. - uint32_t mLocationChangeRateLimitCount; - mozilla::TimeStamp mLocationChangeRateLimitSpanStart; + // Used by CheckNavigationRateLimit. Do not apply cross-process. + uint32_t mNavigationRateLimitCount; + mozilla::TimeStamp mNavigationRateLimitSpanStart; mozilla::LinkedList mLocations; }; diff --git a/docshell/shistory/ChildSHistory.cpp b/docshell/shistory/ChildSHistory.cpp index 3e3cf09493d7..855d76461779 100644 --- a/docshell/shistory/ChildSHistory.cpp +++ b/docshell/shistory/ChildSHistory.cpp @@ -177,7 +177,7 @@ void ChildSHistory::AsyncGo(int32_t aOffset, bool aRequireUserInteraction, MOZ_LOG(gSHLog, LogLevel::Debug, ("ChildSHistory::AsyncGo(%d), current index = %d", aOffset, index.value())); - nsresult rv = mBrowsingContext->CheckLocationChangeRateLimit(aCallerType); + nsresult rv = mBrowsingContext->CheckNavigationRateLimit(aCallerType); if (NS_FAILED(rv)) { MOZ_LOG(gSHLog, LogLevel::Debug, ("Rejected")); aRv.Throw(rv); diff --git a/docshell/test/navigation/test_rate_limit_location_change.html b/docshell/test/navigation/test_rate_limit_location_change.html index b1b51b92dde2..9fefce12af8b 100644 --- a/docshell/test/navigation/test_rate_limit_location_change.html +++ b/docshell/test/navigation/test_rate_limit_location_change.html @@ -17,8 +17,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1314912 async function setup() { await SpecialPowers.pushPrefEnv({set: [ - ["dom.navigation.locationChangeRateLimit.count", RATE_LIMIT_COUNT], - ["dom.navigation.locationChangeRateLimit.timespan", RATE_LIMIT_TIME_SPAN]]}); + ["dom.navigation.navigationRateLimit.count", RATE_LIMIT_COUNT], + ["dom.navigation.navigationRateLimit.timespan", RATE_LIMIT_TIME_SPAN]]}); } let inc = 0; @@ -26,6 +26,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1314912 const rateLimitedFunctions = (win) => ({ "history.replaceState": () => win.history.replaceState(null, "test", `${win.location.href}#${inc++}`), "history.pushState": () => win.history.pushState(null, "test", `${win.location.href}#${inc++}`), + "history.SetScrollRestoration": () => win.history.scrollRestoration = "auto", "history.back": () => win.history.back(), "history.forward": () => win.history.forward(), "history.go": () => win.history.go(-1), @@ -53,7 +54,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1314912 Object.entries(rateLimitedFunctions(win)).forEach(([name, fn]) => { // Reset the rate limit for the next run. info("Reset rate limit."); - SpecialPowers.wrap(win).browsingContext.resetLocationChangeRateLimit(); + SpecialPowers.wrap(win).browsingContext.resetNavigationRateLimit(); info(`Calling ${name} ${RATE_LIMIT_COUNT} times to reach the rate limit.`); for(let i = 0; i< RATE_LIMIT_COUNT; i++) { @@ -83,7 +84,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1314912 // Cleanup win.close(); - SpecialPowers.wrap(win).browsingContext.resetLocationChangeRateLimit(); + SpecialPowers.wrap(win).browsingContext.resetNavigationRateLimit(); SimpleTest.finish(); } diff --git a/dom/base/Location.cpp b/dom/base/Location.cpp index 9edb9e0b6f8e..11603ce493ec 100644 --- a/dom/base/Location.cpp +++ b/dom/base/Location.cpp @@ -562,7 +562,7 @@ void Location::Reload(bool aForceget, nsIPrincipal& aSubjectPrincipal, ? CallerType::System : CallerType::NonSystem; - nsresult rv = bc->CheckLocationChangeRateLimit(callerType); + nsresult rv = bc->CheckNavigationRateLimit(callerType); if (NS_FAILED(rv)) { aRv.Throw(rv); return; diff --git a/dom/base/LocationBase.cpp b/dom/base/LocationBase.cpp index bdf7edc1341f..1a635cab65ad 100644 --- a/dom/base/LocationBase.cpp +++ b/dom/base/LocationBase.cpp @@ -125,7 +125,7 @@ void LocationBase::SetURI(nsIURI* aURI, nsIPrincipal& aSubjectPrincipal, ? CallerType::System : CallerType::NonSystem; - nsresult rv = bc->CheckLocationChangeRateLimit(callerType); + nsresult rv = bc->CheckNavigationRateLimit(callerType); if (NS_FAILED(rv)) { aRv.Throw(rv); return; diff --git a/dom/base/nsHistory.cpp b/dom/base/nsHistory.cpp index 99994a73ccd8..85b26fc29869 100644 --- a/dom/base/nsHistory.cpp +++ b/dom/base/nsHistory.cpp @@ -72,7 +72,7 @@ uint32_t nsHistory::GetLength(ErrorResult& aRv) const { return len >= 0 ? len : 0; } -ScrollRestoration nsHistory::GetScrollRestoration(mozilla::ErrorResult& aRv) { +ScrollRestoration nsHistory::GetScrollRestoration(mozilla::dom::CallerType aCallerType, mozilla::ErrorResult& aRv) { nsCOMPtr win(do_QueryReferent(mInnerWindow)); if (!win || !win->HasActiveDocument() || !win->GetDocShell()) { aRv.Throw(NS_ERROR_DOM_SECURITY_ERR); @@ -88,6 +88,7 @@ ScrollRestoration nsHistory::GetScrollRestoration(mozilla::ErrorResult& aRv) { } void nsHistory::SetScrollRestoration(mozilla::dom::ScrollRestoration aMode, + mozilla::dom::CallerType aCallerType, mozilla::ErrorResult& aRv) { nsCOMPtr win(do_QueryReferent(mInnerWindow)); if (!win || !win->HasActiveDocument() || !win->GetDocShell()) { @@ -95,6 +96,15 @@ void nsHistory::SetScrollRestoration(mozilla::dom::ScrollRestoration aMode, return; } + BrowsingContext* bc = win->GetBrowsingContext(); + if (bc) { + nsresult rv = bc->CheckNavigationRateLimit(aCallerType); + if (NS_FAILED(rv)) { + aRv.Throw(rv); + return; + } + } + win->GetDocShell()->SetCurrentScrollRestorationIsManual( aMode == mozilla::dom::ScrollRestoration::Manual); } @@ -152,7 +162,7 @@ void nsHistory::Go(int32_t aDelta, nsIPrincipal& aSubjectPrincipal, ? CallerType::System : CallerType::NonSystem; - // AsyncGo throws if we hit the location change rate limit. + // AsyncGo throws if we hit the navigation rate limit. session_history->AsyncGo(aDelta, /* aRequireUserInteraction = */ false, userActivation, callerType, aRv); } @@ -237,7 +247,7 @@ void nsHistory::PushOrReplaceState(JSContext* aCx, JS::Handle aData, BrowsingContext* bc = win->GetBrowsingContext(); if (bc) { - nsresult rv = bc->CheckLocationChangeRateLimit(aCallerType); + nsresult rv = bc->CheckNavigationRateLimit(aCallerType); if (NS_FAILED(rv)) { aRv.Throw(rv); return; diff --git a/dom/base/nsHistory.h b/dom/base/nsHistory.h index 157052fe44ce..039cadb2c0f3 100644 --- a/dom/base/nsHistory.h +++ b/dom/base/nsHistory.h @@ -40,8 +40,10 @@ class nsHistory final : public nsISupports, public nsWrapperCache { uint32_t GetLength(mozilla::ErrorResult& aRv) const; mozilla::dom::ScrollRestoration GetScrollRestoration( + mozilla::dom::CallerType aCallerType, mozilla::ErrorResult& aRv); void SetScrollRestoration(mozilla::dom::ScrollRestoration aMode, + mozilla::dom::CallerType aCallerType, mozilla::ErrorResult& aRv); void GetState(JSContext* aCx, JS::MutableHandle aResult, mozilla::ErrorResult& aRv) const; diff --git a/dom/chrome-webidl/BrowsingContext.webidl b/dom/chrome-webidl/BrowsingContext.webidl index d70f3e18cc8e..ee61699e9a82 100644 --- a/dom/chrome-webidl/BrowsingContext.webidl +++ b/dom/chrome-webidl/BrowsingContext.webidl @@ -264,7 +264,7 @@ interface BrowsingContext { readonly attribute ChildSHistory? childSessionHistory; // Resets the location change rate limit. Used for testing. - undefined resetLocationChangeRateLimit(); + undefined resetNavigationRateLimit(); readonly attribute long childOffset; }; diff --git a/dom/webidl/History.webidl b/dom/webidl/History.webidl index 934214965dca..d0aa7d2c8826 100644 --- a/dom/webidl/History.webidl +++ b/dom/webidl/History.webidl @@ -17,7 +17,7 @@ enum ScrollRestoration { "auto", "manual" }; interface History { [Throws] readonly attribute unsigned long length; - [Throws] + [Throws, NeedsCallerType] attribute ScrollRestoration scrollRestoration; [Throws] readonly attribute any state; diff --git a/modules/libpref/init/StaticPrefList.yaml b/modules/libpref/init/StaticPrefList.yaml index dc07c21c86f0..070b1a58c9f2 100644 --- a/modules/libpref/init/StaticPrefList.yaml +++ b/modules/libpref/init/StaticPrefList.yaml @@ -3165,13 +3165,13 @@ # Limit of location change caused by content scripts in a time span per # BrowsingContext. This includes calls to History and Location APIs. -- name: dom.navigation.locationChangeRateLimit.count +- name: dom.navigation.navigationRateLimit.count type: uint32_t value: 200 mirror: always # Time span in seconds for location change rate limit. -- name: dom.navigation.locationChangeRateLimit.timespan +- name: dom.navigation.navigationRateLimit.timespan type: uint32_t value: 10 mirror: always diff --git a/remote/shared/RecommendedPreferences.sys.mjs b/remote/shared/RecommendedPreferences.sys.mjs index 6c2af7cd25de..605752962719 100644 --- a/remote/shared/RecommendedPreferences.sys.mjs +++ b/remote/shared/RecommendedPreferences.sys.mjs @@ -222,7 +222,7 @@ const COMMON_PREFERENCES = new Map([ ["dom.max_script_run_time", 0], // Disable location change rate limitation - ["dom.navigation.locationChangeRateLimit.count", 0], + ["dom.navigation.navigationRateLimit.count", 0], // DOM Push ["dom.push.connection.enabled", false], diff --git a/testing/marionette/client/marionette_driver/geckoinstance.py b/testing/marionette/client/marionette_driver/geckoinstance.py index d1b4efd2ad49..766f6881579d 100644 --- a/testing/marionette/client/marionette_driver/geckoinstance.py +++ b/testing/marionette/client/marionette_driver/geckoinstance.py @@ -82,8 +82,8 @@ class GeckoInstance(object): # No slow script dialogs "dom.max_chrome_script_run_time": 0, "dom.max_script_run_time": 0, - # Disable location change rate limitation - "dom.navigation.locationChangeRateLimit.count": 0, + # Disable navigation change rate limitation + "dom.navigation.navigationRateLimit.count": 0, # DOM Push "dom.push.connection.enabled": False, # Screen Orientation API diff --git a/tools/@types/lib.gecko.dom.d.ts b/tools/@types/lib.gecko.dom.d.ts index e3d181ec6770..badc5910c812 100644 --- a/tools/@types/lib.gecko.dom.d.ts +++ b/tools/@types/lib.gecko.dom.d.ts @@ -5168,7 +5168,7 @@ interface BrowsingContext extends LoadContextMixin { watchedByDevTools: boolean; readonly window: WindowProxy | null; getAllBrowsingContextsInSubtree(): BrowsingContext[]; - resetLocationChangeRateLimit(): void; + resetNavigationRateLimit(): void; setRDMPaneMaxTouchPoints(maxTouchPoints: number): void; setRDMPaneOrientation(type: OrientationType, rotationAngle: number): void; }