summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docshell/base/nsDocShell.cpp39
-rw-r--r--docshell/base/nsDocShell.h12
-rw-r--r--dom/locales/en-US/chrome/dom/dom.properties2
3 files changed, 53 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;
diff --git a/dom/locales/en-US/chrome/dom/dom.properties b/dom/locales/en-US/chrome/dom/dom.properties
index 1f43a4389f..60104a63ad 100644
--- a/dom/locales/en-US/chrome/dom/dom.properties
+++ b/dom/locales/en-US/chrome/dom/dom.properties
@@ -318,3 +318,5 @@ LargeAllocationInIFrame=A Large-Allocation header was ignored due to the load oc
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.
+# LOCALIZATION NOTE: Do not translate "Reload"
+ReloadFloodingPrevented=Call to Reload ignored due to excessive calls within a short timeframe.