summaryrefslogtreecommitdiffstats
path: root/docshell
diff options
context:
space:
mode:
authorMoonchild <moonchild@palemoon.org>2021-02-25 01:03:57 +0000
committerMoonchild <moonchild@palemoon.org>2021-02-25 01:03:57 +0000
commitceadffab6b357723981a429e11222daf6cd6dcfb (patch)
tree5603053048d6a460f79b22bdf165fb74d32d39b0 /docshell
parent14fb2f966e9b54598c451e3cb35b4aa0480dafed (diff)
parentad5a13bd501e379517da1a944c104a11d951a3f5 (diff)
downloadUXP-RC_20210225.tar
UXP-RC_20210225.tar.gz
UXP-RC_20210225.tar.lz
UXP-RC_20210225.tar.xz
UXP-RC_20210225.zip
Merge branch 'master' into releaseRC_20210225
Diffstat (limited to 'docshell')
-rw-r--r--docshell/base/nsDocShell.cpp41
-rw-r--r--docshell/base/nsDocShell.h13
2 files changed, 54 insertions, 0 deletions
diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
index e1f023b10..0ceb70a30 100644
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -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.
diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h
index 93a1ba68d..019a7e4ab 100644
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -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;