summaryrefslogtreecommitdiff
path: root/docshell/base/nsDocShell.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'docshell/base/nsDocShell.cpp')
-rw-r--r--docshell/base/nsDocShell.cpp41
1 files changed, 41 insertions, 0 deletions
diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
index e1f023b105..0ceb70a304 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.