diff options
author | Moonchild <moonchild@palemoon.org> | 2021-12-08 23:10:14 +0000 |
---|---|---|
committer | Moonchild <moonchild@palemoon.org> | 2022-04-07 23:54:44 +0200 |
commit | e0e12932bc933978cf151d038616e6c88f0f2b4c (patch) | |
tree | ec7a1b8e6664d786d7c07725130e183b3bfc3584 /docshell | |
parent | 9a1e152ba30ab26a5f05326dab5dee0fab6e9b32 (diff) | |
download | uxp-e0e12932bc933978cf151d038616e6c88f0f2b4c.tar.gz |
[Docshell] Implement reload flood guard
Diffstat (limited to 'docshell')
-rw-r--r-- | docshell/base/nsDocShell.cpp | 39 | ||||
-rw-r--r-- | docshell/base/nsDocShell.h | 12 |
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; |