mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-08-15 08:53:07 +09:00
Issue #1688 - Add flood guard to state change logic.
This commit is contained in:
parent
d6c1cc53ba
commit
51c4b1838c
3 changed files with 56 additions and 0 deletions
|
|
@ -820,6 +820,8 @@ nsDocShell::nsDocShell()
|
|||
, mParentCharsetSource(0)
|
||||
, mJSRunToCompletionDepth(0)
|
||||
, mTouchEventsOverride(nsIDocShell::TOUCHEVENTS_OVERRIDE_NONE)
|
||||
, mStateFloodGuardCount(0)
|
||||
, mStateFloodGuardReported(false)
|
||||
{
|
||||
AssertOriginAttributesMatchPrivateBrowsing();
|
||||
mHistoryID = ++gDocshellIDCounter;
|
||||
|
|
@ -11833,6 +11835,27 @@ nsDocShell::SetReferrerPolicy(uint32_t aReferrerPolicy)
|
|||
// nsDocShell: Session History
|
||||
//*****************************************************************************
|
||||
|
||||
bool
|
||||
nsDocShell::IsStateChangeFlooding()
|
||||
{
|
||||
// Issue #1688: Let's copy Firefox's strategy for state flooding here, so
|
||||
// that our implementations are interoperable.
|
||||
if (mStateFloodGuardCount > kStateUpdateLimit) {
|
||||
TimeStamp now = TimeStamp::Now();
|
||||
|
||||
if (now - mStateFloodGuardUpdated > TimeDuration::FromSeconds(kRefreshTimeSecs)) {
|
||||
mStateFloodGuardCount = 0;
|
||||
mStateFloodGuardUpdated = now;
|
||||
mStateFloodGuardReported = false;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
mStateFloodGuardCount++;
|
||||
return false;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDocShell::AddState(JS::Handle<JS::Value> aData, const nsAString& aTitle,
|
||||
const nsAString& aURL, bool aReplace, JSContext* aCx)
|
||||
|
|
@ -11897,6 +11920,24 @@ nsDocShell::AddState(JS::Handle<JS::Value> aData, const nsAString& aTitle,
|
|||
nsCOMPtr<nsIDocument> document = GetDocument();
|
||||
NS_ENSURE_TRUE(document, NS_ERROR_FAILURE);
|
||||
|
||||
// If we're being flooded with state change requests, we should abort early
|
||||
// from the state change logic.
|
||||
if (IsStateChangeFlooding()) {
|
||||
// Report a warning to the console to tell developers why their navigations
|
||||
// failed.
|
||||
// Do this only if not yet marked reported so we only report it once per
|
||||
// flood interval.
|
||||
if (!mStateFloodGuardReported) {
|
||||
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
|
||||
NS_LITERAL_CSTRING("PushState"),
|
||||
document,
|
||||
nsContentUtils::eDOM_PROPERTIES,
|
||||
"PushStateFloodingPrevented");
|
||||
mStateFloodGuardReported = true;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Step A: Serialize aData using structured clone.
|
||||
// https://html.spec.whatwg.org/multipage/history.html#dom-history-pushstate
|
||||
// step 5.
|
||||
|
|
|
|||
|
|
@ -1049,6 +1049,15 @@ private:
|
|||
// as constants in the nsIDocShell.idl file.
|
||||
uint32_t mTouchEventsOverride;
|
||||
|
||||
// Keep track how how many history state changes we're getting, to catch &
|
||||
// prevent flooding.
|
||||
int32_t mStateFloodGuardCount;
|
||||
mozilla::TimeStamp mStateFloodGuardUpdated;
|
||||
bool mStateFloodGuardReported;
|
||||
// We have a limit of pushing 50 states to history every 10 seconds.
|
||||
const int32_t kStateUpdateLimit = 50;
|
||||
const double kRefreshTimeSecs = 10.0;
|
||||
|
||||
// Separate function to do the actual name (i.e. not _top, _self etc.)
|
||||
// searching for FindItemWithName.
|
||||
nsresult DoFindItemWithName(const nsAString& aName,
|
||||
|
|
@ -1064,6 +1073,10 @@ private:
|
|||
void MaybeNotifyKeywordSearchLoading(const nsString& aProvider,
|
||||
const nsString& aKeyword);
|
||||
|
||||
// Helper method for AddState which checks for excessive calls to PushState or
|
||||
// ReplaceState.
|
||||
bool IsStateChangeFlooding();
|
||||
|
||||
#ifdef DEBUG
|
||||
// We're counting the number of |nsDocShells| to help find leaks
|
||||
static unsigned long gNumberOfDocShells;
|
||||
|
|
|
|||
|
|
@ -316,3 +316,5 @@ LargeAllocationRelatedBrowsingContexts=A Large-Allocation header was ignored due
|
|||
LargeAllocationInIFrame=A Large-Allocation header was ignored due to the load occuring within an iframe.
|
||||
# LOCALIZATION NOTE: Do not translate "Large-Allocation", as it is a literal header name
|
||||
LargeAllocationNonE10S=A Large-Allocation header was ignored due to the document not being loaded out of process.
|
||||
# LOCALIZATION NOTE: Do not translate "pushState" and "replaceState"
|
||||
PushStateFloodingPrevented=Call to pushState or replaceState ignored due to excessive calls within a short timeframe.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue