summaryrefslogtreecommitdiff
path: root/docshell
diff options
context:
space:
mode:
authorMoonchild <moonchild@palemoon.org>2021-12-08 23:10:14 +0000
committerMoonchild <moonchild@palemoon.org>2022-04-07 23:54:44 +0200
commite0e12932bc933978cf151d038616e6c88f0f2b4c (patch)
treeec7a1b8e6664d786d7c07725130e183b3bfc3584 /docshell
parent9a1e152ba30ab26a5f05326dab5dee0fab6e9b32 (diff)
downloaduxp-e0e12932bc933978cf151d038616e6c88f0f2b4c.tar.gz
[Docshell] Implement reload flood guard
Diffstat (limited to 'docshell')
-rw-r--r--docshell/base/nsDocShell.cpp39
-rw-r--r--docshell/base/nsDocShell.h12
2 files changed, 51 insertions, 0 deletions
diff --git a/docshell/base/nsDocShell.cpp b/docshell/base/nsDocShell.cpp
index f2c7443656..b07cb15ff1 100644
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -821,6 +821,8 @@ nsDocShell::nsDocShell()
, mTouchEventsOverride(nsIDocShell::TOUCHEVENTS_OVERRIDE_NONE)
, mStateFloodGuardCount(0)
, mStateFloodGuardReported(false)
+ , mReloadFloodGuardCount(0)
+ , mReloadFloodGuardReported(false)
{
AssertOriginAttributesMatchPrivateBrowsing();
mHistoryID = ++gDocshellIDCounter;
@@ -5299,6 +5301,25 @@ nsDocShell::LoadErrorPage(nsIURI* aURI, const char16_t* aURL,
nullptr);
}
+bool
+nsDocShell::IsReloadFlooding()
+{
+ if (mReloadFloodGuardCount > kReloadLimit) {
+ TimeStamp now = TimeStamp::Now();
+
+ if (now - mReloadFloodGuardUpdated > TimeDuration::FromSeconds(kReloadTimeSecs)) {
+ mReloadFloodGuardCount = 0;
+ mReloadFloodGuardUpdated = now;
+ mReloadFloodGuardReported = false;
+ return false;
+ }
+ return true;
+ }
+
+ mReloadFloodGuardCount++;
+ return false;
+}
+
NS_IMETHODIMP
nsDocShell::Reload(uint32_t aReloadFlags)
{
@@ -5323,6 +5344,24 @@ nsDocShell::Reload(uint32_t aReloadFlags)
if (rootSH) {
shistInt->NotifyOnHistoryReload(mCurrentURI, aReloadFlags, &canReload);
}
+
+ // If we're being flooded with reload requests, we should abort early
+ // from the reload logic.
+ if (IsReloadFlooding()) {
+ // Report a warning to the console to tell developers why their reload
+ // failed.
+ // Do this only if not yet marked reported so we only report it once per
+ // flood interval.
+ if (!mReloadFloodGuardReported) {
+ nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
+ NS_LITERAL_CSTRING("Reload"),
+ GetDocument(),
+ nsContentUtils::eDOM_PROPERTIES,
+ "ReloadFloodingPrevented");
+ mReloadFloodGuardReported = true;
+ }
+ return NS_OK;
+ }
if (!canReload) {
return NS_OK;
diff --git a/docshell/base/nsDocShell.h b/docshell/base/nsDocShell.h
index bc5c5eed3f..f8fead3ac3 100644
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -1056,6 +1056,15 @@ private:
const int32_t kStateUpdateLimit = 50;
const double kRefreshTimeSecs = 10.0;
+ // Keep track how how many history state changes we're getting, to catch &
+ // prevent flooding.
+ int32_t mReloadFloodGuardCount;
+ mozilla::TimeStamp mReloadFloodGuardUpdated;
+ bool mReloadFloodGuardReported;
+ // We have a limit of reloading 50 times every 10 seconds.
+ const int32_t kReloadLimit = 50;
+ const double kReloadTimeSecs = 10.0;
+
// Separate function to do the actual name (i.e. not _top, _self etc.)
// searching for FindItemWithName.
nsresult DoFindItemWithName(const nsAString& aName,
@@ -1075,6 +1084,9 @@ private:
// ReplaceState.
bool IsStateChangeFlooding();
+ // Helper method for Reload which checks for excessive calls to Reload.
+ bool IsReloadFlooding();
+
#ifdef DEBUG
// We're counting the number of |nsDocShells| to help find leaks
static unsigned long gNumberOfDocShells;