Bug 1588720 - Part 2: Track number of popup spam through BrowsingContext; r=smaug

Differential Revision: https://phabricator.services.mozilla.com/D49276

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Edgar Chen 2019-10-18 03:04:55 +00:00
parent 661494aa9a
commit e6da573de1
7 changed files with 67 additions and 6 deletions

View File

@ -16,6 +16,7 @@
#include "mozilla/dom/Element.h"
#include "mozilla/dom/Location.h"
#include "mozilla/dom/LocationBinding.h"
#include "mozilla/dom/PopupBlocker.h"
#include "mozilla/dom/StructuredCloneTags.h"
#include "mozilla/dom/UserActivationIPCUtils.h"
#include "mozilla/dom/WindowBinding.h"
@ -308,6 +309,10 @@ void BrowsingContext::Attach(bool aFromIPC) {
children->AppendElement(this);
if (mIsPopupSpam) {
PopupBlocker::RegisterOpenPopupSpam();
}
if (!aFromIPC) {
// Send attach to our parent if we need to.
if (XRE_IsContentProcess()) {
@ -358,6 +363,13 @@ void BrowsingContext::Detach(bool aFromIPC) {
// automatically by calls to Detach()
mClosed = true;
if (mIsPopupSpam) {
PopupBlocker::UnregisterOpenPopupSpam();
// NOTE: Doesn't use SetIsPopupSpam, as it will be set all processes
// automatically.
mIsPopupSpam = false;
}
if (!aFromIPC && XRE_IsContentProcess()) {
auto cc = ContentChild::GetSingleton();
MOZ_DIAGNOSTIC_ASSERT(cc);
@ -747,6 +759,13 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(BrowsingContext)
sBrowsingContexts->Remove(tmp->Id());
}
if (tmp->mIsPopupSpam) {
PopupBlocker::UnregisterOpenPopupSpam();
// NOTE: Doesn't use SetIsPopupSpam, as it will be set all processes
// automatically.
tmp->mIsPopupSpam = false;
}
NS_IMPL_CYCLE_COLLECTION_UNLINK(mDocShell, mChildren, mParent, mGroup,
mEmbedderElement)
if (XRE_IsParentProcess()) {
@ -1242,6 +1261,19 @@ bool BrowsingContext::MaySetEmbedderInnerWindowId(const uint64_t& aValue,
return true;
}
bool BrowsingContext::MaySetIsPopupSpam(const bool& aValue,
ContentParent* aSource) {
// Ensure that we only mark a browsing context as popup spam once and never
// unmark it.
return aValue && !mIsPopupSpam;
}
void BrowsingContext::DidSetIsPopupSpam() {
if (mIsPopupSpam) {
PopupBlocker::RegisterOpenPopupSpam();
}
}
} // namespace dom
namespace ipc {

View File

@ -543,6 +543,10 @@ class BrowsingContext : public nsWrapperCache, public BrowsingContextBase {
bool MaySetEmbedderInnerWindowId(const uint64_t& aValue,
ContentParent* aSource);
bool MaySetIsPopupSpam(const bool& aValue, ContentParent* aSource);
void DidSetIsPopupSpam();
// Type of BrowsingContent
const Type mType;

View File

@ -26,6 +26,8 @@ MOZ_BC_FIELD(EmbedderInnerWindowId, uint64_t)
MOZ_BC_FIELD(HadOriginalOpener, bool)
MOZ_BC_FIELD(IsPopupSpam, bool)
// This field controls whether the browsing context is currently considered to
// be activated by a gesture.
MOZ_BC_FIELD(UserActivationState, UserActivation::State)

View File

@ -31,6 +31,8 @@ static TimeStamp sLastAllowedExternalProtocolIFrameTimeStamp;
// is set to true.
static bool sUnusedPopupToken = false;
static uint32_t sOpenPopupSpamCount = 0;
void PopupAllowedEventsChanged() {
if (sPopupAllowedEvents) {
free(sPopupAllowedEvents);
@ -407,6 +409,8 @@ void PopupBlocker::Initialize() {
/* static */
void PopupBlocker::Shutdown() {
MOZ_ASSERT(sOpenPopupSpamCount == 0);
if (sPopupAllowedEvents) {
free(sPopupAllowedEvents);
}
@ -442,6 +446,18 @@ void PopupBlocker::ResetLastExternalProtocolIframeAllowed() {
sLastAllowedExternalProtocolIFrameTimeStamp = TimeStamp();
}
/* static */
void PopupBlocker::RegisterOpenPopupSpam() { sOpenPopupSpamCount++; }
/* static */
void PopupBlocker::UnregisterOpenPopupSpam() {
MOZ_ASSERT(sOpenPopupSpamCount);
sOpenPopupSpamCount--;
}
/* static */
uint32_t PopupBlocker::GetOpenPopupSpamCount() { return sOpenPopupSpamCount; }
} // namespace dom
} // namespace mozilla

View File

@ -64,6 +64,11 @@ class PopupBlocker final {
// Reset the last external protocol iframe timestamp.
static void ResetLastExternalProtocolIframeAllowed();
// These method track the number of popup which is considered as a spam popup.
static void RegisterOpenPopupSpam();
static void UnregisterOpenPopupSpam();
static uint32_t GetOpenPopupSpamCount();
static void Initialize();
static void Shutdown();
};

View File

@ -5699,8 +5699,10 @@ PopupBlocker::PopupControlState nsGlobalWindowOuter::RevisePopupAbuseLevel(
if (abuse == PopupBlocker::openAbused || abuse == PopupBlocker::openBlocked ||
abuse == PopupBlocker::openControlled) {
int32_t popupMax = StaticPrefs::dom_popup_maximum();
if (popupMax >= 0 && gOpenPopupSpamCount >= popupMax)
if (popupMax >= 0 &&
PopupBlocker::GetOpenPopupSpamCount() >= (uint32_t)popupMax) {
abuse = PopupBlocker::openOverridden;
}
}
// If this popup is allowed, let's block any other for this event, forcing

View File

@ -1104,12 +1104,12 @@ nsresult nsWindowWatcher::OpenWindowInternal(
win->SetInitialPrincipalToSubject(cspToInheritForAboutBlank);
if (aIsPopupSpam) {
MOZ_ASSERT(!win->IsPopupSpamWindow(),
MOZ_ASSERT(!newBC->GetIsPopupSpam(),
"Who marked it as popup spam already???");
if (!win->IsPopupSpamWindow()) { // Make sure we don't mess up
// our counter even if the above
// assert fails.
win->SetIsPopupSpamWindow(true);
// Make sure we don't mess up our counter even if the above assert
// fails.
if (!newBC->GetIsPopupSpam()) {
newBC->SetIsPopupSpam(true);
}
}
}