also check for popup window abuse in the internal Open method. bug 210560 r=brendan,jst

This commit is contained in:
danm%netscape.com 2003-06-25 23:38:45 +00:00
Родитель a5a1140ff7
Коммит b6c4ce13d2
2 изменённых файлов: 80 добавлений и 49 удалений

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

@ -3043,14 +3043,86 @@ GlobalWindowImpl::CheckForAbusePoint ()
return PR_FALSE;
}
/* Allow or deny a window open based on whether popups are suppressed.
This method assumes we're in a popup situation; otherwise why call it?
Returns PR_TRUE if the window should be opened. */
PRBool GlobalWindowImpl::CheckOpenAllow(const nsAString &aName)
{
PRBool allowWindow = PR_TRUE;
if (IsPopupBlocked(mDocument)) {
allowWindow = PR_FALSE;
// However it might still not be blocked.
// Special case items that don't actually open new windows.
nsAutoString name(aName);
if (!name.IsEmpty() &&
!name.EqualsIgnoreCase("_top") &&
!name.EqualsIgnoreCase("_self") &&
!name.EqualsIgnoreCase("_content")) {
nsCOMPtr<nsIWindowWatcher> wwatch =
do_GetService(NS_WINDOWWATCHER_CONTRACTID);
if (wwatch) {
nsCOMPtr<nsIDOMWindow> namedWindow;
wwatch->GetWindowByName(PromiseFlatString(aName).get(), this,
getter_AddRefs(namedWindow));
if (namedWindow)
allowWindow = PR_TRUE;
}
}
}
return allowWindow;
}
/* If a window open is blocked, fire the appropriate DOM events.
aBlocked signifies we just blocked a popup.
aWindow signifies we just opened what is probably a popup.
*/
void
GlobalWindowImpl::FireAbuseEvents(PRBool aBlocked, PRBool aWindow,
const nsAString &aPopupURL)
{
nsCOMPtr<nsIDOMWindow> topWindow;
GetTop(getter_AddRefs(topWindow));
nsCOMPtr<nsIDOMDocument> topDoc;
topWindow->GetDocument(getter_AddRefs(topDoc));
nsCOMPtr<nsIURI> requestingURI;
nsCOMPtr<nsIURI> popupURI;
nsCOMPtr<nsIWebNavigation> webNav(do_GetInterface(topWindow));
nsCOMPtr<nsIIOService> ios(do_GetService(NS_IOSERVICE_CONTRACTID));
if (webNav)
webNav->GetCurrentURI(getter_AddRefs(requestingURI));
if (ios)
ios->NewURI(NS_ConvertUCS2toUTF8(aPopupURL), 0, 0,
getter_AddRefs(popupURI));
if (aBlocked)
FirePopupBlockedEvent(topDoc, requestingURI, popupURI);
if (aWindow)
FirePopupWindowEvent(topDoc);
}
NS_IMETHODIMP
GlobalWindowImpl::Open(const nsAString& aUrl,
const nsAString& aName,
const nsAString& aOptions,
nsIDOMWindow **_retval)
{
return OpenInternal(aUrl, aName, aOptions, PR_FALSE, nsnull, 0, nsnull,
PRBool abusedWindow = CheckForAbusePoint();
nsresult rv;
if (abusedWindow && !CheckOpenAllow(aName)) {
FireAbuseEvents(PR_TRUE, PR_FALSE, aUrl);
return NS_ERROR_FAILURE; // unlike the public Open method, return an error
}
rv = OpenInternal(aUrl, aName, aOptions, PR_FALSE, nsnull, 0, nsnull,
_retval);
if (NS_SUCCEEDED(rv) && abusedWindow)
FireAbuseEvents(PR_FALSE, PR_TRUE, aUrl);
return rv;
}
NS_IMETHODIMP
@ -3094,54 +3166,10 @@ GlobalWindowImpl::Open(nsIDOMWindow **_retval)
}
}
/*
* If we're in a commonly abused state (top level script, running a timeout,
* or onload/onunload), and the preference is enabled, prevent window.open().
*/
PRBool abusedWindow = CheckForAbusePoint();
nsCOMPtr<nsIDOMWindow> topWindow;
GetTop(getter_AddRefs(topWindow));
nsCOMPtr<nsIDOMDocument> topDoc;
topWindow->GetDocument(getter_AddRefs(topDoc));
if (abusedWindow) {
if (IsPopupBlocked(mDocument)) {
nsCOMPtr<nsIURI> requestingURI;
nsCOMPtr<nsIURI> popupURI;
nsCOMPtr<nsIWebNavigation> webNav(do_GetInterface(topWindow));
nsCOMPtr<nsIIOService> ios(do_GetService(NS_IOSERVICE_CONTRACTID));
if (webNav)
webNav->GetCurrentURI(getter_AddRefs(requestingURI));
if (ios)
ios->NewURI(NS_ConvertUCS2toUTF8(url), 0, 0,
getter_AddRefs(popupURI));
if (name.IsEmpty()) {
FirePopupBlockedEvent(topDoc, requestingURI, popupURI);
return NS_OK;
}
// Special case items that don't actually open new windows.
if (!name.EqualsIgnoreCase("_top") &&
!name.EqualsIgnoreCase("_self") &&
!name.EqualsIgnoreCase("_content")) {
nsCOMPtr<nsIWindowWatcher> wwatch =
do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv);
// If getting a window watcher fails, we'd fail downstream anyway
// when trying to open a new window so just bail here.
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIDOMWindow> namedWindow;
wwatch->GetWindowByName(name.get(), this,
getter_AddRefs(namedWindow));
if (!namedWindow) {
FirePopupBlockedEvent(topDoc, requestingURI, popupURI);
return NS_OK;
}
}
}
if (abusedWindow && !CheckOpenAllow(name)) {
FireAbuseEvents(PR_TRUE, PR_FALSE, url);
return NS_OK; // don't open the window, but also don't throw a JS exception
}
rv = OpenInternal(url, name, options, PR_FALSE, nsnull, 0, nsnull, _retval);
@ -3172,7 +3200,7 @@ GlobalWindowImpl::Open(nsIDOMWindow **_retval)
}
if (abusedWindow)
FirePopupWindowEvent(topDoc);
FireAbuseEvents(PR_FALSE, PR_TRUE, url);
}
return rv;

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

@ -244,6 +244,9 @@ protected:
float* aT2P);
nsresult SecurityCheckURL(const char *aURL);
PRBool CheckForAbusePoint();
PRBool CheckOpenAllow(const nsAString &aName);
void FireAbuseEvents(PRBool aBlocked, PRBool aWindow,
const nsAString &aPopupURL);
void FlushPendingNotifications(PRBool aFlushReflows);
void EnsureReflowFlushAndPaint();