Bug 1720926 - Rate limit calls to location.reload. r=smaug

Differential Revision: https://phabricator.services.mozilla.com/D128636
This commit is contained in:
Paul Zuehlcke 2021-10-18 17:27:06 +00:00
Родитель 75d192487c
Коммит a6a4f92ea0
6 изменённых файлов: 40 добавлений и 17 удалений

Просмотреть файл

@ -29,6 +29,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1314912
"history.back": () => win.history.back(),
"history.forward": () => win.history.forward(),
"history.go": () => win.history.go(-1),
"location.href": () => win.location.href = win.location.href + "",
"location.hash": () => win.location.hash = inc++,
"location.host": () => win.location.host = win.location.host + "",
"location.hostname": () => win.location.hostname = win.location.hostname + "",
@ -36,6 +37,9 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=1314912
"location.port": () => win.location.port = win.location.port + "",
"location.protocol": () => win.location.protocol = win.location.protocol + "",
"location.search": () => win.location.search = win.location.search + "",
"location.assign": () => win.location.assign(`${win.location.href}#${inc++}`),
"location.replace": () => win.location.replace(`${win.location.href}#${inc++}`),
"location.reload": () => win.location.reload(),
});
async function test() {

Просмотреть файл

@ -25,6 +25,7 @@
#include "nsGlobalWindow.h"
#include "mozilla/Likely.h"
#include "nsCycleCollectionParticipant.h"
#include "mozilla/BasePrincipal.h"
#include "mozilla/Components.h"
#include "mozilla/NullPrincipal.h"
#include "mozilla/ServoStyleConsts.h"
@ -548,7 +549,13 @@ void Location::SetSearch(const nsAString& aSearch,
SetURI(uri, aSubjectPrincipal, aRv);
}
void Location::Reload(bool aForceget, ErrorResult& aRv) {
void Location::Reload(bool aForceget, nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv) {
if (!CallerSubsumes(&aSubjectPrincipal)) {
aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
return;
}
nsCOMPtr<nsIDocShell> docShell(GetDocShell());
if (!docShell) {
return aRv.Throw(NS_ERROR_FAILURE);
@ -574,6 +581,21 @@ void Location::Reload(bool aForceget, ErrorResult& aRv) {
}
}
RefPtr<BrowsingContext> bc = GetBrowsingContext();
if (!bc || bc->IsDiscarded()) {
return;
}
CallerType callerType = aSubjectPrincipal.IsSystemPrincipal()
? CallerType::System
: CallerType::NonSystem;
nsresult rv = bc->CheckLocationChangeRateLimit(callerType);
if (NS_FAILED(rv)) {
aRv.Throw(rv);
return;
}
uint32_t reloadFlags = nsIWebNavigation::LOAD_FLAGS_NONE;
if (aForceget) {
@ -581,7 +603,7 @@ void Location::Reload(bool aForceget, ErrorResult& aRv) {
nsIWebNavigation::LOAD_FLAGS_BYPASS_PROXY;
}
nsresult rv = nsDocShell::Cast(docShell)->Reload(reloadFlags);
rv = nsDocShell::Cast(docShell)->Reload(reloadFlags);
if (NS_FAILED(rv) && rv != NS_BINDING_ABORTED) {
// NS_BINDING_ABORTED is returned when we attempt to reload a POST result
// and the user says no at the "do you want to reload?" prompt. Don't

Просмотреть файл

@ -43,14 +43,7 @@ class Location final : public nsISupports,
ErrorResult& aError);
void Reload(bool aForceget, nsIPrincipal& aSubjectPrincipal,
ErrorResult& aError) {
if (!CallerSubsumes(&aSubjectPrincipal)) {
aError.Throw(NS_ERROR_DOM_SECURITY_ERR);
return;
}
Reload(aForceget, aError);
}
ErrorResult& aError);
void GetHref(nsAString& aHref, nsIPrincipal& aSubjectPrincipal,
ErrorResult& aError) {
@ -118,8 +111,6 @@ class Location final : public nsISupports,
nsresult ToString(nsAString& aString) { return GetHref(aString); }
void Reload(bool aForceget, ErrorResult& aRv);
protected:
virtual ~Location();

Просмотреть файл

@ -19,6 +19,7 @@
#include "mozilla/dom/Location.h"
#include "mozilla/RefPtr.h"
#include "mozilla/StaticPrefs_dom.h"
#include "mozilla/BasePrincipal.h"
using namespace mozilla;
using namespace mozilla::dom;
@ -137,7 +138,8 @@ void nsHistory::GetState(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
aResult.setNull();
}
void nsHistory::Go(int32_t aDelta, CallerType aCallerType, ErrorResult& aRv) {
void nsHistory::Go(int32_t aDelta, nsIPrincipal& aSubjectPrincipal,
ErrorResult& aRv) {
LOG(("nsHistory::Go(%d)", aDelta));
nsCOMPtr<nsPIDOMWindowInner> win(do_QueryReferent(mInnerWindow));
if (!win || !win->HasActiveDocument()) {
@ -149,7 +151,7 @@ void nsHistory::Go(int32_t aDelta, CallerType aCallerType, ErrorResult& aRv) {
// "When the go(delta) method is invoked, if delta is zero, the user agent
// must act as if the location.reload() method was called instead."
RefPtr<Location> location = win->Location();
return location->Reload(false, aRv);
return location->Reload(false, aSubjectPrincipal, aRv);
}
RefPtr<ChildSHistory> session_history = GetSessionHistory();
@ -163,12 +165,16 @@ void nsHistory::Go(int32_t aDelta, CallerType aCallerType, ErrorResult& aRv) {
? win->GetWindowContext()->HasValidTransientUserGestureActivation()
: false;
CallerType callerType = aSubjectPrincipal.IsSystemPrincipal()
? CallerType::System
: CallerType::NonSystem;
// Ignore the return value from Go(), since returning errors from Go() can
// lead to exceptions and a possible leak of history length
// AsyncGo throws if we hit the location change rate limit.
if (StaticPrefs::dom_window_history_async()) {
session_history->AsyncGo(aDelta, /* aRequireUserInteraction = */ false,
userActivation, aCallerType, aRv);
userActivation, callerType, aRv);
} else {
session_history->Go(aDelta, /* aRequireUserInteraction = */ false,
userActivation, IgnoreErrors());

Просмотреть файл

@ -45,7 +45,7 @@ class nsHistory final : public nsISupports, public nsWrapperCache {
mozilla::ErrorResult& aRv);
void GetState(JSContext* aCx, JS::MutableHandle<JS::Value> aResult,
mozilla::ErrorResult& aRv) const;
void Go(int32_t aDelta, mozilla::dom::CallerType aCallerType,
void Go(int32_t aDelta, nsIPrincipal& aSubjectPrincipal,
mozilla::ErrorResult& aRv);
void Back(mozilla::dom::CallerType aCallerType, mozilla::ErrorResult& aRv);
void Forward(mozilla::dom::CallerType aCallerType, mozilla::ErrorResult& aRv);

Просмотреть файл

@ -21,7 +21,7 @@ interface History {
attribute ScrollRestoration scrollRestoration;
[Throws]
readonly attribute any state;
[Throws, NeedsCallerType]
[Throws, NeedsSubjectPrincipal]
void go(optional long delta = 0);
[Throws, NeedsCallerType]
void back();