Bug 1922677 - Rate limit every navigation. r=smaug,zcorpan,firefox-style-system-reviewers,emilio
Differential Revision: https://phabricator.services.mozilla.com/D300744
This commit is contained in:
committed by
afarre@mozilla.com
parent
eca98b505f
commit
73a7bc0a7a
@@ -2617,15 +2617,6 @@ void BrowsingContext::Navigate(
|
||||
dom::NavigationAPIMethodTracker* aNavigationAPIMethodTracker) {
|
||||
MOZ_LOG_FMT(gNavigationAPILog, LogLevel::Debug, "Navigate to {} as {}", *aURI,
|
||||
aHistoryHandling);
|
||||
CallerType callerType = aSubjectPrincipal.IsSystemPrincipal()
|
||||
? CallerType::System
|
||||
: CallerType::NonSystem;
|
||||
|
||||
nsresult rv = CheckNavigationRateLimit(callerType);
|
||||
if (NS_FAILED(rv)) {
|
||||
aRv.Throw(rv);
|
||||
return;
|
||||
}
|
||||
|
||||
RefPtr<nsDocShellLoadState> loadState =
|
||||
CheckURLAndCreateLoadState(aURI, aSubjectPrincipal, aSourceDocument, aRv);
|
||||
@@ -2677,7 +2668,7 @@ void BrowsingContext::Navigate(
|
||||
loadState->SetNavigationAPIState(aNavigationAPIState);
|
||||
loadState->SetNavigationAPIMethodTracker(aNavigationAPIMethodTracker);
|
||||
|
||||
rv = LoadURI(loadState);
|
||||
nsresult rv = LoadURI(loadState);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
if (rv == NS_ERROR_DOM_BAD_CROSS_ORIGIN_URI &&
|
||||
loadState->URI()->SchemeIs("javascript")) {
|
||||
@@ -4638,10 +4629,10 @@ bool BrowsingContext::ShouldUpdateSessionHistory(uint32_t aLoadType) {
|
||||
(IsForceReloadType(aLoadType) && IsSubframe()));
|
||||
}
|
||||
|
||||
nsresult BrowsingContext::CheckNavigationRateLimit(CallerType aCallerType) {
|
||||
bool BrowsingContext::CheckNavigationRateLimit(CallerType aCallerType) {
|
||||
// We only rate limit non system callers
|
||||
if (aCallerType == CallerType::System) {
|
||||
return NS_OK;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Fetch rate limiting preferences
|
||||
@@ -4651,7 +4642,7 @@ nsresult BrowsingContext::CheckNavigationRateLimit(CallerType aCallerType) {
|
||||
|
||||
// Disable throttling if either of the preferences is set to 0.
|
||||
if (limitCount == 0 || timeSpanSeconds == 0) {
|
||||
return NS_OK;
|
||||
return true;
|
||||
}
|
||||
|
||||
TimeDuration throttleSpan = TimeDuration::FromSeconds(timeSpanSeconds);
|
||||
@@ -4661,24 +4652,24 @@ nsresult BrowsingContext::CheckNavigationRateLimit(CallerType aCallerType) {
|
||||
// Initial call or timespan exceeded, reset counter and timespan.
|
||||
mNavigationRateLimitSpanStart = TimeStamp::Now();
|
||||
mNavigationRateLimitCount = 1;
|
||||
return NS_OK;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (mNavigationRateLimitCount >= limitCount) {
|
||||
if (NS_WARN_IF(mNavigationRateLimitCount >= limitCount)) {
|
||||
// Rate limit reached
|
||||
|
||||
Document* doc = GetDocument();
|
||||
if (doc) {
|
||||
nsContentUtils::ReportToConsole(nsIScriptError::errorFlag, "DOM"_ns, doc,
|
||||
PropertiesFile::DOM_PROPERTIES,
|
||||
"LocChangeFloodingPrevented");
|
||||
"NavigationChangeFloodingPrevented");
|
||||
}
|
||||
|
||||
return NS_ERROR_DOM_SECURITY_ERR;
|
||||
return false;
|
||||
}
|
||||
|
||||
mNavigationRateLimitCount++;
|
||||
return NS_OK;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void BrowsingContext::ResetNavigationRateLimit() {
|
||||
|
||||
@@ -1054,13 +1054,13 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
|
||||
|
||||
bool ShouldUpdateSessionHistory(uint32_t aLoadType);
|
||||
|
||||
// Checks if we reached the rate limit for calls to Location and History API.
|
||||
// The rate limit is controlled by the
|
||||
// "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 CheckNavigationRateLimit(CallerType aCallerType);
|
||||
// Checks if we reached the rate limit for navigations, which includes calls
|
||||
// to the Location and History APIs.
|
||||
// The rate limit is controlled by the "dom.navigation.navigationRateLimit"
|
||||
// prefs. Rate limit applies per BrowsingContext. Returns true if we are below
|
||||
// the rate limit and increments the counter. Returns false if the limit is
|
||||
// reached
|
||||
bool CheckNavigationRateLimit(CallerType aCallerType);
|
||||
|
||||
void ResetNavigationRateLimit();
|
||||
|
||||
|
||||
@@ -8725,6 +8725,15 @@ nsresult nsDocShell::InternalLoad(nsDocShellLoadState* aLoadState,
|
||||
}
|
||||
}
|
||||
|
||||
CallerType callerType = aLoadState->TriggeringPrincipal()->IsSystemPrincipal()
|
||||
? CallerType::System
|
||||
: CallerType::NonSystem;
|
||||
|
||||
if (!aLoadState->LoadIsFromSessionHistory() &&
|
||||
!mBrowsingContext->CheckNavigationRateLimit(callerType)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// See if this is actually a load between two history entries for the same
|
||||
// document. If the process fails, or if we successfully navigate within the
|
||||
// same document, return.
|
||||
@@ -10897,9 +10906,10 @@ bool nsDocShell::CollectWireframe() {
|
||||
// nsDocShell: Session History
|
||||
//*****************************************************************************
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::AddState(JS::Handle<JS::Value> aData, const nsAString& aTitle,
|
||||
const nsAString& aURL, bool aReplace, JSContext* aCx) {
|
||||
nsresult nsDocShell::AddState(JS::Handle<JS::Value> aData,
|
||||
const nsAString& aTitle, const nsAString& aURL,
|
||||
CallerType aCallerType, bool aReplace,
|
||||
JSContext* aCx) {
|
||||
MOZ_LOG(gSHLog, LogLevel::Debug,
|
||||
("nsDocShell[%p]: AddState(..., %s, %s, %d)", this,
|
||||
NS_ConvertUTF16toUTF8(aTitle).get(),
|
||||
@@ -11062,6 +11072,10 @@ nsDocShell::AddState(JS::Handle<JS::Value> aData, const nsAString& aTitle,
|
||||
|
||||
} // end of same-origin check
|
||||
|
||||
if (!mBrowsingContext->CheckNavigationRateLimit(aCallerType)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/#shared-history-push/replace-state-steps
|
||||
// Step 8
|
||||
if (nsCOMPtr<nsPIDOMWindowInner> window = document->GetInnerWindow()) {
|
||||
|
||||
@@ -1096,7 +1096,16 @@ class nsDocShell final : public nsDocLoader,
|
||||
void MaybeDisconnectChildListenersOnPageHide();
|
||||
|
||||
/**
|
||||
* Helper for addState and document.open that does just the
|
||||
* Do either a history.pushState() or history.replaceState() operation,
|
||||
* depending on the value of aReplace.
|
||||
*/
|
||||
MOZ_CAN_RUN_SCRIPT
|
||||
nsresult AddState(JS::Handle<JS::Value> aData, const nsAString& aTitle,
|
||||
const nsAString& aURL, mozilla::dom::CallerType aCallerType,
|
||||
bool aReplace, JSContext* aCx);
|
||||
|
||||
/**
|
||||
* Helper for AddState and document.open that does just the
|
||||
* history-manipulation guts.
|
||||
*
|
||||
* Arguments the spec defines:
|
||||
|
||||
@@ -101,14 +101,6 @@ interface nsIDocShell : nsIDocShellTreeItem
|
||||
*/
|
||||
[noscript]void loadURI(in nsDocShellLoadStatePtr aLoadState, in boolean aSetNavigating);
|
||||
|
||||
/**
|
||||
* Do either a history.pushState() or history.replaceState() operation,
|
||||
* depending on the value of aReplace.
|
||||
*/
|
||||
[implicit_jscontext, can_run_script]
|
||||
void addState(in jsval aData, in AString aTitle,
|
||||
in AString aURL, in boolean aReplace);
|
||||
|
||||
/**
|
||||
* Reset state to a new content model within the current document and the document
|
||||
* viewer. Called by the document before initiating an out of band document.write().
|
||||
|
||||
@@ -264,6 +264,8 @@ skip-if = [
|
||||
|
||||
["test_rate_limit_location_change.html"]
|
||||
|
||||
["test_rate_limit_same_document_navigation.html"]
|
||||
|
||||
["test_recursive_frames.html"]
|
||||
skip-if = [
|
||||
"http2",
|
||||
|
||||
@@ -44,6 +44,23 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1314912
|
||||
"location.reload": () => win.location.reload(),
|
||||
});
|
||||
|
||||
// pushState is rate limited and takes effect synchronously, which makes it
|
||||
// usable as a probe for whether the rate limit is currently in effect.
|
||||
function isRateLimited(win) {
|
||||
const before = win.location.href;
|
||||
win.history.pushState(null, "test", `#probe${inc++}`);
|
||||
return win.location.href == before;
|
||||
}
|
||||
|
||||
function mustNotThrow(fn, name) {
|
||||
try {
|
||||
fn();
|
||||
ok(true, `${name} must not throw.`);
|
||||
} catch (error) {
|
||||
ok(false, `${name} must not throw, but threw ${error}.`);
|
||||
}
|
||||
}
|
||||
|
||||
async function test() {
|
||||
await setup();
|
||||
|
||||
@@ -61,27 +78,21 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1314912
|
||||
for(let i = 0; i< RATE_LIMIT_COUNT; i++) {
|
||||
fn.call(this);
|
||||
}
|
||||
// Next calls should throw because we're above the rate limit
|
||||
// Next calls are above the rate limit, and should be silently ignored.
|
||||
for(let i = 0; i < 5; i++) {
|
||||
SimpleTest.doesThrow(() => fn.call(this), `Call #${RATE_LIMIT_COUNT + i + 1} to ${name} should throw.`);
|
||||
mustNotThrow(() => fn.call(this), `Call #${RATE_LIMIT_COUNT + i + 1} to ${name}`);
|
||||
}
|
||||
|
||||
ok(isRateLimited(win), `Calling ${name} should reach the rate limit.`);
|
||||
})
|
||||
|
||||
// We didn't reset the rate limit after the last loop iteration above.
|
||||
// Wait for the rate limit timer to expire.
|
||||
SimpleTest.requestFlakyTimeout("Waiting to trigger rate limit reset.");
|
||||
await new Promise((resolve) => setTimeout(resolve, 5000));
|
||||
await new Promise((resolve) => setTimeout(resolve, (RATE_LIMIT_TIME_SPAN + 2) * 1000));
|
||||
|
||||
// Calls should be allowed again.
|
||||
Object.entries(rateLimitedFunctions(win)).forEach(([name, fn]) => {
|
||||
let didThrow = false;
|
||||
try {
|
||||
fn.call(this);
|
||||
} catch(error) {
|
||||
didThrow = true;
|
||||
}
|
||||
is(didThrow, false, `Call to ${name} must not throw.`)
|
||||
});
|
||||
// Navigations should be allowed again.
|
||||
ok(!isRateLimited(win), "The rate limit should be lifted after the time span.");
|
||||
|
||||
// Cleanup
|
||||
win.close();
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=1922677
|
||||
-->
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Test for Bug 1922677</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
<script type="application/javascript">
|
||||
|
||||
/** Test for Bug 1922677 */
|
||||
|
||||
const RATE_LIMIT_COUNT = 5;
|
||||
// Long enough that the rate limit never resets on its own during the test.
|
||||
const RATE_LIMIT_TIME_SPAN = 100;
|
||||
|
||||
// Time to wait for a hashchange event that we expect to never be fired.
|
||||
const NO_HASH_CHANGE_TIMEOUT = 500;
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
SimpleTest.requestFlakyTimeout(
|
||||
"Waiting for a hashchange event that should not be fired.");
|
||||
|
||||
async function setup() {
|
||||
await SpecialPowers.pushPrefEnv({set: [
|
||||
["dom.navigation.navigationRateLimit.count", RATE_LIMIT_COUNT],
|
||||
["dom.navigation.navigationRateLimit.timespan", RATE_LIMIT_TIME_SPAN]]});
|
||||
}
|
||||
|
||||
function nextHashChange(aWin) {
|
||||
return new Promise((resolve) => {
|
||||
aWin.addEventListener("hashchange", resolve, {once: true});
|
||||
});
|
||||
}
|
||||
|
||||
// Resolves to false if no hashchange event was fired in aWin within
|
||||
// NO_HASH_CHANGE_TIMEOUT, and to true if one was fired.
|
||||
function noHashChange(aWin) {
|
||||
return new Promise((resolve) => {
|
||||
const listener = () => {
|
||||
clearTimeout(timer);
|
||||
resolve(true);
|
||||
};
|
||||
aWin.addEventListener("hashchange", listener, {once: true});
|
||||
const timer = setTimeout(() => {
|
||||
aWin.removeEventListener("hashchange", listener);
|
||||
resolve(false);
|
||||
}, NO_HASH_CHANGE_TIMEOUT);
|
||||
});
|
||||
}
|
||||
|
||||
async function test() {
|
||||
await setup();
|
||||
|
||||
const iframe = document.getElementById("iframe");
|
||||
await new Promise((resolve) => {
|
||||
iframe.addEventListener("load", resolve, {once: true});
|
||||
iframe.src = "blank.html";
|
||||
});
|
||||
|
||||
const win = iframe.contentWindow;
|
||||
const link = win.document.createElement("a");
|
||||
win.document.body.appendChild(link);
|
||||
|
||||
const clickFragment = (aFragment) => {
|
||||
link.setAttribute("href", `#${aFragment}`);
|
||||
link.click();
|
||||
};
|
||||
|
||||
// Loading the iframe counted towards the rate limit.
|
||||
SpecialPowers.wrap(win).browsingContext.resetNavigationRateLimit();
|
||||
|
||||
for (let i = 1; i <= RATE_LIMIT_COUNT; ++i) {
|
||||
const hashChanged = nextHashChange(win);
|
||||
clickFragment(i);
|
||||
await hashChanged;
|
||||
is(win.location.hash, `#${i}`, `Fragment navigation #${i} to #${i}.`);
|
||||
}
|
||||
|
||||
const noHashChanged = noHashChange(win);
|
||||
clickFragment("blocked");
|
||||
ok(!await noHashChanged,
|
||||
"Fragment navigation above the rate limit should not be performed.");
|
||||
is(win.location.hash, `#${RATE_LIMIT_COUNT}`,
|
||||
"Fragment should be left untouched by the rate limited navigation.");
|
||||
|
||||
// Once the rate limit is reset, fragment navigations should work again.
|
||||
SpecialPowers.wrap(win).browsingContext.resetNavigationRateLimit();
|
||||
|
||||
const hashChangedAgain = nextHashChange(win);
|
||||
clickFragment("allowed");
|
||||
await hashChangedAgain;
|
||||
is(win.location.hash, "#allowed",
|
||||
"Fragment navigation should be performed after resetting the limit.");
|
||||
|
||||
SpecialPowers.wrap(win).browsingContext.resetNavigationRateLimit();
|
||||
SimpleTest.finish();
|
||||
}
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body onload="setTimeout(test, 0);">
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1922677">Mozilla Bug 1922677</a>
|
||||
<iframe id="iframe"></iframe>
|
||||
</body>
|
||||
</html>
|
||||
@@ -595,9 +595,7 @@ void Location::Reload(JSContext* aCx, bool aForceget,
|
||||
? CallerType::System
|
||||
: CallerType::NonSystem;
|
||||
|
||||
nsresult rv = bc->CheckNavigationRateLimit(callerType);
|
||||
if (NS_FAILED(rv)) {
|
||||
aRv.Throw(rv);
|
||||
if (!bc->CheckNavigationRateLimit(callerType)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -612,8 +610,8 @@ void Location::Reload(JSContext* aCx, bool aForceget,
|
||||
callerType == CallerType::System ? UserNavigationInvolvement::BrowserUI
|
||||
: UserNavigationInvolvement::None;
|
||||
|
||||
rv = docShell->ReloadNavigable(Some(WrapNotNull(aCx)), reloadFlags, nullptr,
|
||||
userInvolvement);
|
||||
nsresult rv = docShell->ReloadNavigable(Some(WrapNotNull(aCx)), reloadFlags,
|
||||
nullptr, userInvolvement);
|
||||
if (NS_FAILED(rv) && rv != NS_BINDING_ABORTED) {
|
||||
// NS_BINDING_ABORTED is returned when we attempt to reload a POST result
|
||||
// and the user says no at the "do you want to reload?" prompt. Don't
|
||||
|
||||
+10
-19
@@ -24,13 +24,9 @@ extern LazyLogModule gSHistoryLog;
|
||||
#define LOG(format) MOZ_LOG(gSHistoryLog, mozilla::LogLevel::Debug, format)
|
||||
|
||||
static bool CheckNavigationRateLimit(BrowsingContext* aContext,
|
||||
CallerType aCallerType, ErrorResult& aRv) {
|
||||
CallerType aCallerType) {
|
||||
if (aContext) {
|
||||
nsresult rv = aContext->CheckNavigationRateLimit(aCallerType);
|
||||
if (NS_FAILED(rv)) {
|
||||
aRv.Throw(rv);
|
||||
return false;
|
||||
}
|
||||
return aContext->CheckNavigationRateLimit(aCallerType);
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -105,7 +101,7 @@ void nsHistory::SetScrollRestoration(mozilla::dom::ScrollRestoration aMode,
|
||||
return;
|
||||
}
|
||||
|
||||
if (!CheckNavigationRateLimit(win->GetBrowsingContext(), aCallerType, aRv)) {
|
||||
if (!CheckNavigationRateLimit(win->GetBrowsingContext(), aCallerType)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -175,19 +171,15 @@ void nsHistory::PushOrReplaceState(JSContext* aCx, JS::Handle<JS::Value> aData,
|
||||
return;
|
||||
}
|
||||
|
||||
if (!win->HasActiveDocument()) {
|
||||
if (!win->IsFullyActive()) {
|
||||
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!CheckNavigationRateLimit(win->GetBrowsingContext(), aCallerType, aRv)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// AddState might run scripts, so we need to hold a strong reference to the
|
||||
// docShell here to keep it from going away.
|
||||
nsCOMPtr<nsIDocShell> docShell = win->GetDocShell();
|
||||
RefPtr docShell = nsDocShell::Cast(win->GetDocShell());
|
||||
|
||||
if (!docShell) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
@@ -197,8 +189,7 @@ void nsHistory::PushOrReplaceState(JSContext* aCx, JS::Handle<JS::Value> aData,
|
||||
|
||||
// The "replace" argument tells the docshell to whether to add a new
|
||||
// history entry or modify the current one.
|
||||
|
||||
aRv = docShell->AddState(aData, aTitle, aUrl, aReplace, aCx);
|
||||
aRv = docShell->AddState(aData, aTitle, aUrl, aCallerType, aReplace, aCx);
|
||||
}
|
||||
|
||||
already_AddRefed<ChildSHistory> nsHistory::GetSessionHistory() const {
|
||||
@@ -226,12 +217,12 @@ void nsHistory::DeltaTraverse(mozilla::Maybe<NotNull<JSContext*>> aCx,
|
||||
return;
|
||||
}
|
||||
|
||||
if (!CheckNavigationRateLimit(win->GetBrowsingContext(), aCallerType, aRv)) {
|
||||
MOZ_LOG(gSHistoryLog, LogLevel::Debug, ("Rejected"));
|
||||
// Step 3
|
||||
if (!CheckNavigationRateLimit(win->GetBrowsingContext(), aCallerType)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Step 3
|
||||
// Step 4
|
||||
if (!aDelta) {
|
||||
MOZ_DIAGNOSTIC_ASSERT(aCx);
|
||||
RefPtr<nsDocShell> docShell = nsDocShell::Cast(win->GetDocShell());
|
||||
@@ -244,7 +235,7 @@ void nsHistory::DeltaTraverse(mozilla::Maybe<NotNull<JSContext*>> aCx,
|
||||
return;
|
||||
}
|
||||
|
||||
// Step 4 is the remainder of this method.
|
||||
// Step 5 is the remainder of this method.
|
||||
RefPtr<ChildSHistory> session_history = GetSessionHistory();
|
||||
if (!session_history) {
|
||||
aRv.Throw(NS_ERROR_FAILURE);
|
||||
|
||||
@@ -4,6 +4,7 @@ prefs = [
|
||||
"formhelper.autozoom.force-disable.test-only=true",
|
||||
"network.http.referer.sendFromRefresh=false",
|
||||
"plugins.rewrite_youtube_embeds=true",
|
||||
"dom.navigation.navigationRateLimit.count=0",
|
||||
]
|
||||
support-files = [
|
||||
"audio.ogg",
|
||||
|
||||
@@ -4,6 +4,7 @@ prefs = [
|
||||
"formhelper.autozoom.force-disable.test-only=true",
|
||||
"network.http.referer.sendFromRefresh=false",
|
||||
"plugins.rewrite_youtube_embeds=true",
|
||||
"dom.navigation.navigationRateLimit.count=0",
|
||||
]
|
||||
support-files = [
|
||||
"audio.ogg",
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
defaults pref(dom.navigation.navigationRateLimit.count,0)
|
||||
|
||||
load 68912-1.html
|
||||
load 257818-1.html
|
||||
load 285166-1.html
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
[DEFAULT]
|
||||
prefs = ["gfx.font_loader.delay=0"]
|
||||
prefs = [
|
||||
"gfx.font_loader.delay=0",
|
||||
"dom.navigation.navigationRateLimit.count=0",
|
||||
]
|
||||
support-files = [
|
||||
"347174transform.xsl",
|
||||
"347174transformable.xml",
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
[DEFAULT]
|
||||
prefs = ["gfx.font_loader.delay=0"]
|
||||
prefs = [
|
||||
"apz.zoom-to-focused-input.enabled=false",
|
||||
"gfx.font_loader.delay=0",
|
||||
"dom.navigation.navigationRateLimit.count=0",
|
||||
]
|
||||
support-files = [
|
||||
"347174transform.xsl",
|
||||
"347174transformable.xml",
|
||||
|
||||
@@ -454,7 +454,7 @@ RequestStorageAccessPermissionsPolicy=document.requestStorageAccess() may not be
|
||||
# LOCALIZATION NOTE: Do not translate document.requestStorageAccess()
|
||||
RequestStorageAccessNotSecureContext=document.requestStorageAccess() may only grant access to secure contexts.
|
||||
# LOCALIZATION NOTE: Do not translate "Location" and "History".
|
||||
LocChangeFloodingPrevented=Too many calls to Location or History APIs within a short timeframe.
|
||||
NavigationChangeFloodingPrevented=Too many attempts to navigate or modify history within a short timeframe.
|
||||
FolderUploadPrompt.title = Confirm Upload
|
||||
# LOCALIZATION NOTE: %S is the name of the folder the user selected in the file picker.
|
||||
FolderUploadPrompt.message = Are you sure you want to upload all files from “%S”? Only do this if you trust the site.
|
||||
|
||||
@@ -253,6 +253,7 @@ support-files = [
|
||||
]
|
||||
prefs = [
|
||||
"security.mixed_content.upgrade_display_content=false",
|
||||
"dom.navigation.navigationRateLimit.count=0",
|
||||
]
|
||||
|
||||
["test_301_redirect.html"]
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
[DEFAULT]
|
||||
prefs = ["dom.navigation.navigationRateLimit.count=0"]
|
||||
support-files = [
|
||||
"DOMTestCase.js",
|
||||
"activity-home.css",
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
[DEFAULT]
|
||||
prefs = ["dom.navigation.navigationRateLimit.count=0"]
|
||||
support-files = [
|
||||
"DOMTestCase.js",
|
||||
"activity-home.css",
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
[DEFAULT]
|
||||
prefs = ["dom.navigation.navigationRateLimit.count=0"]
|
||||
support-files = [
|
||||
"DOMTestCase.js",
|
||||
"exclusions.js",
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
[DEFAULT]
|
||||
prefs = ["dom.navigation.navigationRateLimit.count=0"]
|
||||
support-files = [
|
||||
"DOMTestCase.js",
|
||||
"files/anchor.html",
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
[DEFAULT]
|
||||
prefs = ["dom.navigation.navigationRateLimit.count=0"]
|
||||
support-files = [
|
||||
"DOMTestCase.js",
|
||||
"files/anchor.html",
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
[DEFAULT]
|
||||
prefs = ["dom.navigation.navigationRateLimit.count=0"]
|
||||
support-files = [
|
||||
"DOMTestCase.js",
|
||||
"files/anchor.html",
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
[DEFAULT]
|
||||
prefs = ["dom.navigation.navigationRateLimit.count=0"]
|
||||
support-files = [
|
||||
"DOMTestCase.js",
|
||||
"files/anchor.html",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
[DEFAULT]
|
||||
prefs = [
|
||||
"apz.zoom-to-focused-input.enabled=false",
|
||||
"dom.navigation.navigationRateLimit.count=0",
|
||||
"test.ime_content_observer.assert_invalid_cache=true",
|
||||
"ui.dragThresholdX=4", # Bug 1873142
|
||||
"ui.dragThresholdY=4", # Bug 1873142
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
[DEFAULT]
|
||||
prefs = [
|
||||
"dom.navigation.navigationRateLimit.count=0",
|
||||
"gfx.omta.background-color=true",
|
||||
"gfx.font_loader.delay=0",
|
||||
"layout.css.motion-path-url.enabled=true",
|
||||
@@ -17,7 +18,7 @@ prefs = [
|
||||
"layout.css.text-decoration-inset-percentage.enabled=true",
|
||||
"layout.css.link-parameters.enabled=true",
|
||||
"layout.css.ellipse-corners.enabled=true",
|
||||
"layout.css.calc-typed-arithmetic.enabled=true"
|
||||
"layout.css.calc-typed-arithmetic.enabled=true",
|
||||
]
|
||||
support-files = [
|
||||
"animation_utils.js",
|
||||
|
||||
@@ -4008,14 +4008,14 @@
|
||||
value: false
|
||||
mirror: always
|
||||
|
||||
# Limit of location change caused by content scripts in a time span per
|
||||
# Limit of navigations initiated by content in a time span per
|
||||
# BrowsingContext. This includes calls to History and Location APIs.
|
||||
- name: dom.navigation.navigationRateLimit.count
|
||||
type: uint32_t
|
||||
value: 1000
|
||||
value: 200
|
||||
mirror: always
|
||||
|
||||
# Time span in seconds for location change rate limit.
|
||||
# Time span in seconds for the navigation rate limit.
|
||||
- name: dom.navigation.navigationRateLimit.timespan
|
||||
type: uint32_t
|
||||
value: 10
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
[DEFAULT]
|
||||
prefs = ["dom.navigation.navigationRateLimit.count=0"]
|
||||
support-files = [
|
||||
"bug_502091_iframe.html",
|
||||
"file_bug102699.sjs",
|
||||
|
||||
-3
@@ -1,6 +1,3 @@
|
||||
[navigate_too_many_calls.optional.html]
|
||||
[fragment navigations through navigate are ignored after too many calls]
|
||||
expected: FAIL
|
||||
|
||||
[rate-limited navigations cancel pending lazy-load iframe navigations]
|
||||
expected: FAIL
|
||||
|
||||
-11
@@ -1,11 +0,0 @@
|
||||
[history_go_too_many_calls.optional.html]
|
||||
expected:
|
||||
if (os == "mac") and not debug: TIMEOUT
|
||||
[history go too many calls]
|
||||
expected:
|
||||
if (os == "mac") and not debug: TIMEOUT
|
||||
FAIL
|
||||
|
||||
[fully active check should be before rate limit check]
|
||||
expected:
|
||||
if (os == "mac") and not debug: NOTRUN
|
||||
-3
@@ -1,3 +0,0 @@
|
||||
[history_pushstate_too_many_calls.optional.html]
|
||||
[history pushState too many calls]
|
||||
expected: FAIL
|
||||
-12
@@ -1,12 +0,0 @@
|
||||
[history_pushstate_too_many_calls_ordering.optional.html]
|
||||
[pushState serializes state before checking the rate limit]
|
||||
expected: FAIL
|
||||
|
||||
[pushState parses the URL before checking the rate limit]
|
||||
expected: FAIL
|
||||
|
||||
[pushState checks whether the URL can be rewritten before checking the rate limit]
|
||||
expected: FAIL
|
||||
|
||||
[pushState checks fully active before checking the rate limit]
|
||||
expected: FAIL
|
||||
-3
@@ -1,3 +0,0 @@
|
||||
[history_replacestate_too_many_calls.optional.html]
|
||||
[history replaceState too many calls]
|
||||
expected: FAIL
|
||||
-12
@@ -1,12 +0,0 @@
|
||||
[history_replacestate_too_many_calls_ordering.optional.html]
|
||||
[replaceState serializes state before checking the rate limit]
|
||||
expected: FAIL
|
||||
|
||||
[replaceState parses the URL before checking the rate limit]
|
||||
expected: FAIL
|
||||
|
||||
[replaceState checks whether the URL can be rewritten before checking the rate limit]
|
||||
expected: FAIL
|
||||
|
||||
[replaceState checks fully active before checking the rate limit]
|
||||
expected: FAIL
|
||||
Reference in New Issue
Block a user