#522: basic window.open=noopener, refactor popup blocker M1267338 M1267339
This commit is contained in:
parent
3660eb7e23
commit
46bf256a1f
|
@ -51,6 +51,7 @@
|
||||||
#include "nsJSUtils.h"
|
#include "nsJSUtils.h"
|
||||||
#include "jsapi.h" // for JSAutoRequest
|
#include "jsapi.h" // for JSAutoRequest
|
||||||
#include "jswrapper.h"
|
#include "jswrapper.h"
|
||||||
|
#include "nsCharSeparatedTokenizer.h"
|
||||||
#include "nsReadableUtils.h"
|
#include "nsReadableUtils.h"
|
||||||
#include "nsDOMClassInfo.h"
|
#include "nsDOMClassInfo.h"
|
||||||
#include "nsJSEnvironment.h"
|
#include "nsJSEnvironment.h"
|
||||||
|
@ -1483,9 +1484,20 @@ void
|
||||||
nsGlobalWindow::MaybeForgiveSpamCount()
|
nsGlobalWindow::MaybeForgiveSpamCount()
|
||||||
{
|
{
|
||||||
if (IsOuterWindow() &&
|
if (IsOuterWindow() &&
|
||||||
IsPopupSpamWindow())
|
IsPopupSpamWindow()) {
|
||||||
{
|
SetIsPopupSpamWindow(false);
|
||||||
SetPopupSpamWindow(false);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
nsGlobalWindow::SetIsPopupSpamWindow(bool aIsPopupSpam)
|
||||||
|
{
|
||||||
|
MOZ_ASSERT(IsOuterWindow());
|
||||||
|
|
||||||
|
mIsPopupSpam = aIsPopupSpam;
|
||||||
|
if (aIsPopupSpam) {
|
||||||
|
++gOpenPopupSpamCount;
|
||||||
|
} else {
|
||||||
--gOpenPopupSpamCount;
|
--gOpenPopupSpamCount;
|
||||||
NS_ASSERTION(gOpenPopupSpamCount >= 0,
|
NS_ASSERTION(gOpenPopupSpamCount >= 0,
|
||||||
"Unbalanced decrement of gOpenPopupSpamCount");
|
"Unbalanced decrement of gOpenPopupSpamCount");
|
||||||
|
@ -5718,11 +5730,18 @@ GetCallerDocShellTreeItem()
|
||||||
|
|
||||||
bool
|
bool
|
||||||
nsGlobalWindow::WindowExists(const nsAString& aName,
|
nsGlobalWindow::WindowExists(const nsAString& aName,
|
||||||
|
bool aForceNoOpener,
|
||||||
bool aLookForCallerOnJSStack)
|
bool aLookForCallerOnJSStack)
|
||||||
{
|
{
|
||||||
NS_PRECONDITION(IsOuterWindow(), "Must be outer window");
|
NS_PRECONDITION(IsOuterWindow(), "Must be outer window");
|
||||||
NS_PRECONDITION(mDocShell, "Must have docshell");
|
NS_PRECONDITION(mDocShell, "Must have docshell");
|
||||||
|
|
||||||
|
if (aForceNoOpener) {
|
||||||
|
return aName.LowerCaseEqualsLiteral("_self") ||
|
||||||
|
aName.LowerCaseEqualsLiteral("_top") ||
|
||||||
|
aName.LowerCaseEqualsLiteral("_parent");
|
||||||
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsIDocShellTreeItem> caller;
|
nsCOMPtr<nsIDocShellTreeItem> caller;
|
||||||
if (aLookForCallerOnJSStack) {
|
if (aLookForCallerOnJSStack) {
|
||||||
caller = GetCallerDocShellTreeItem();
|
caller = GetCallerDocShellTreeItem();
|
||||||
|
@ -7532,14 +7551,6 @@ nsGlobalWindow::FirePopupBlockedEvent(nsIDocument* aDoc,
|
||||||
aDoc->DispatchEvent(event, &defaultActionEnabled);
|
aDoc->DispatchEvent(event, &defaultActionEnabled);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void FirePopupWindowEvent(nsIDocument* aDoc)
|
|
||||||
{
|
|
||||||
// Fire a "PopupWindow" event
|
|
||||||
nsContentUtils::DispatchTrustedEvent(aDoc, aDoc,
|
|
||||||
NS_LITERAL_STRING("PopupWindow"),
|
|
||||||
true, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
// static
|
||||||
bool
|
bool
|
||||||
nsGlobalWindow::CanSetProperty(const char *aPrefName)
|
nsGlobalWindow::CanSetProperty(const char *aPrefName)
|
||||||
|
@ -7608,13 +7619,9 @@ nsGlobalWindow::RevisePopupAbuseLevel(PopupControlState aControl)
|
||||||
return abuse;
|
return abuse;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If a window open is blocked, fire the appropriate DOM events.
|
/* 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
|
void
|
||||||
nsGlobalWindow::FireAbuseEvents(bool aBlocked, bool aWindow,
|
nsGlobalWindow::FireAbuseEvents(const nsAString &aPopupURL,
|
||||||
const nsAString &aPopupURL,
|
|
||||||
const nsAString &aPopupWindowName,
|
const nsAString &aPopupWindowName,
|
||||||
const nsAString &aPopupWindowFeatures)
|
const nsAString &aPopupWindowFeatures)
|
||||||
{
|
{
|
||||||
|
@ -7645,13 +7652,8 @@ nsGlobalWindow::FireAbuseEvents(bool aBlocked, bool aWindow,
|
||||||
ios->NewURI(NS_ConvertUTF16toUTF8(aPopupURL), 0, baseURL,
|
ios->NewURI(NS_ConvertUTF16toUTF8(aPopupURL), 0, baseURL,
|
||||||
getter_AddRefs(popupURI));
|
getter_AddRefs(popupURI));
|
||||||
|
|
||||||
// fire an event chock full of informative URIs
|
FirePopupBlockedEvent(topDoc, popupURI, aPopupWindowName,
|
||||||
if (aBlocked) {
|
aPopupWindowFeatures);
|
||||||
FirePopupBlockedEvent(topDoc, popupURI, aPopupWindowName,
|
|
||||||
aPopupWindowFeatures);
|
|
||||||
}
|
|
||||||
if (aWindow)
|
|
||||||
FirePopupWindowEvent(topDoc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
already_AddRefed<nsIDOMWindow>
|
already_AddRefed<nsIDOMWindow>
|
||||||
|
@ -11333,8 +11335,24 @@ nsGlobalWindow::OpenInternal(const nsAString& aUrl, const nsAString& aName,
|
||||||
nsIPrincipal::APP_STATUS_INSTALLED;
|
nsIPrincipal::APP_STATUS_INSTALLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool forceNoOpener = false;
|
||||||
|
// Unlike other window flags, "noopener" comes from splitting on commas with
|
||||||
|
// HTML whitespace trimming...
|
||||||
|
nsCharSeparatedTokenizerTemplate<nsContentUtils::IsHTMLWhitespace> tok(
|
||||||
|
aOptions, ',');
|
||||||
|
while (tok.hasMoreTokens()) {
|
||||||
|
if (tok.nextToken().EqualsLiteral("noopener")) {
|
||||||
|
forceNoOpener = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXXbz When this gets fixed to not use LegacyIsCallerNativeCode()
|
||||||
|
// (indirectly) maybe we can nix the AutoJSAPI usage OnLinkClickEvent::Run.
|
||||||
|
// But note that if you change this to GetEntryGlobal(), say, then
|
||||||
|
// OnLinkClickEvent::Run will need a full-blown AutoEntryScript.
|
||||||
const bool checkForPopup = !nsContentUtils::LegacyIsCallerChromeOrNativeCode() &&
|
const bool checkForPopup = !nsContentUtils::LegacyIsCallerChromeOrNativeCode() &&
|
||||||
!isApp && !aDialog && !WindowExists(aName, !aCalledNoScript);
|
!isApp && !aDialog && !WindowExists(aName, forceNoOpener, !aCalledNoScript);
|
||||||
|
|
||||||
// Note: it's very important that this be an nsXPIDLCString, since we want
|
// Note: it's very important that this be an nsXPIDLCString, since we want
|
||||||
// .get() on it to return nullptr until we write stuff to it. The window
|
// .get() on it to return nullptr until we write stuff to it. The window
|
||||||
|
@ -11377,7 +11395,7 @@ nsGlobalWindow::OpenInternal(const nsAString& aUrl, const nsAString& aName,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FireAbuseEvents(true, false, aUrl, aName, aOptions);
|
FireAbuseEvents(aUrl, aName, aOptions);
|
||||||
return aDoJSFixups ? NS_OK : NS_ERROR_FAILURE;
|
return aDoJSFixups ? NS_OK : NS_ERROR_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11397,6 +11415,13 @@ nsGlobalWindow::OpenInternal(const nsAString& aUrl, const nsAString& aName,
|
||||||
nsCOMPtr<nsPIWindowWatcher> pwwatch(do_QueryInterface(wwatch));
|
nsCOMPtr<nsPIWindowWatcher> pwwatch(do_QueryInterface(wwatch));
|
||||||
NS_ENSURE_STATE(pwwatch);
|
NS_ENSURE_STATE(pwwatch);
|
||||||
|
|
||||||
|
MOZ_ASSERT_IF(checkForPopup, abuseLevel < openAbused);
|
||||||
|
// At this point we should know for a fact that if checkForPopup then
|
||||||
|
// abuseLevel < openAbused, so we could just check for abuseLevel ==
|
||||||
|
// openControlled. But let's be defensive just in case and treat anything
|
||||||
|
// that fails the above assert as a spam popup too, if it ever happens.
|
||||||
|
bool isPopupSpamWindow = checkForPopup && (abuseLevel >= openControlled);
|
||||||
|
|
||||||
{
|
{
|
||||||
// Reset popup state while opening a window to prevent the
|
// Reset popup state while opening a window to prevent the
|
||||||
// current state from being active the whole time a modal
|
// current state from being active the whole time a modal
|
||||||
|
@ -11409,6 +11434,8 @@ nsGlobalWindow::OpenInternal(const nsAString& aUrl, const nsAString& aName,
|
||||||
rv = pwwatch->OpenWindow2(this, url.get(), name_ptr, options_ptr,
|
rv = pwwatch->OpenWindow2(this, url.get(), name_ptr, options_ptr,
|
||||||
/* aCalledFromScript = */ true,
|
/* aCalledFromScript = */ true,
|
||||||
aDialog, aNavigate, nullptr, argv,
|
aDialog, aNavigate, nullptr, argv,
|
||||||
|
isPopupSpamWindow,
|
||||||
|
forceNoOpener,
|
||||||
getter_AddRefs(domReturn));
|
getter_AddRefs(domReturn));
|
||||||
} else {
|
} else {
|
||||||
// Force a system caller here so that the window watcher won't screw us
|
// Force a system caller here so that the window watcher won't screw us
|
||||||
|
@ -11425,10 +11452,11 @@ nsGlobalWindow::OpenInternal(const nsAString& aUrl, const nsAString& aName,
|
||||||
nojsapi.emplace();
|
nojsapi.emplace();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
rv = pwwatch->OpenWindow2(this, url.get(), name_ptr, options_ptr,
|
rv = pwwatch->OpenWindow2(this, url.get(), name_ptr, options_ptr,
|
||||||
/* aCalledFromScript = */ false,
|
/* aCalledFromScript = */ false,
|
||||||
aDialog, aNavigate, nullptr, aExtraArgument,
|
aDialog, aNavigate, nullptr, aExtraArgument,
|
||||||
|
isPopupSpamWindow,
|
||||||
|
forceNoOpener,
|
||||||
getter_AddRefs(domReturn));
|
getter_AddRefs(domReturn));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -11463,18 +11491,6 @@ nsGlobalWindow::OpenInternal(const nsAString& aUrl, const nsAString& aName,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (checkForPopup) {
|
|
||||||
if (abuseLevel >= openControlled) {
|
|
||||||
nsGlobalWindow *opened = static_cast<nsGlobalWindow *>(*aReturn);
|
|
||||||
if (!opened->IsPopupSpamWindow()) {
|
|
||||||
opened->SetPopupSpamWindow(true);
|
|
||||||
++gOpenPopupSpamCount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (abuseLevel >= openAbused)
|
|
||||||
FireAbuseEvents(false, true, aUrl, aName, aOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1321,6 +1321,7 @@ protected:
|
||||||
// Get the parent, returns null if this is a toplevel window
|
// Get the parent, returns null if this is a toplevel window
|
||||||
nsIDOMWindow* GetParentInternal();
|
nsIDOMWindow* GetParentInternal();
|
||||||
|
|
||||||
|
public:
|
||||||
// popup tracking
|
// popup tracking
|
||||||
bool IsPopupSpamWindow()
|
bool IsPopupSpamWindow()
|
||||||
{
|
{
|
||||||
|
@ -1331,17 +1332,10 @@ protected:
|
||||||
return GetOuterWindowInternal()->mIsPopupSpam;
|
return GetOuterWindowInternal()->mIsPopupSpam;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetPopupSpamWindow(bool aPopup)
|
// Outer windows only.
|
||||||
{
|
void SetIsPopupSpamWindow(bool aIsPopupSpam);
|
||||||
if (IsInnerWindow() && !mOuterWindow) {
|
|
||||||
NS_ERROR("SetPopupSpamWindow() called on inner window w/o an outer!");
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
GetOuterWindowInternal()->mIsPopupSpam = aPopup;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
protected:
|
||||||
// Window Control Functions
|
// Window Control Functions
|
||||||
|
|
||||||
// Outer windows only.
|
// Outer windows only.
|
||||||
|
@ -1471,8 +1465,7 @@ public:
|
||||||
|
|
||||||
bool PopupWhitelisted();
|
bool PopupWhitelisted();
|
||||||
PopupControlState RevisePopupAbuseLevel(PopupControlState);
|
PopupControlState RevisePopupAbuseLevel(PopupControlState);
|
||||||
void FireAbuseEvents(bool aBlocked, bool aWindow,
|
void FireAbuseEvents(const nsAString &aPopupURL,
|
||||||
const nsAString &aPopupURL,
|
|
||||||
const nsAString &aPopupWindowName,
|
const nsAString &aPopupWindowName,
|
||||||
const nsAString &aPopupWindowFeatures);
|
const nsAString &aPopupWindowFeatures);
|
||||||
void FireOfflineStatusEventIfChanged();
|
void FireOfflineStatusEventIfChanged();
|
||||||
|
@ -1538,7 +1531,8 @@ public:
|
||||||
// If aLookForCallerOnJSStack is true, this method will look at the JS stack
|
// If aLookForCallerOnJSStack is true, this method will look at the JS stack
|
||||||
// to determine who the caller is. If it's false, it'll use |this| as the
|
// to determine who the caller is. If it's false, it'll use |this| as the
|
||||||
// caller.
|
// caller.
|
||||||
bool WindowExists(const nsAString& aName, bool aLookForCallerOnJSStack);
|
bool WindowExists(const nsAString& aName, bool aForceNoOpener,
|
||||||
|
bool aLookForCallerOnJSStack);
|
||||||
|
|
||||||
already_AddRefed<nsIWidget> GetMainWidget();
|
already_AddRefed<nsIWidget> GetMainWidget();
|
||||||
nsIWidget* GetNearestWidget() const;
|
nsIWidget* GetNearestWidget() const;
|
||||||
|
|
|
@ -5576,8 +5576,13 @@ ContentParent::RecvCreateWindow(PBrowserParent* aThisTab,
|
||||||
const char* name = aName.IsVoid() ? nullptr : NS_ConvertUTF16toUTF8(aName).get();
|
const char* name = aName.IsVoid() ? nullptr : NS_ConvertUTF16toUTF8(aName).get();
|
||||||
const char* features = aFeatures.IsVoid() ? nullptr : aFeatures.get();
|
const char* features = aFeatures.IsVoid() ? nullptr : aFeatures.get();
|
||||||
|
|
||||||
|
#if(0)
|
||||||
|
// Needs update for issue 522
|
||||||
*aResult = pwwatch->OpenWindow2(parent, uri, name, features, aCalledFromJS,
|
*aResult = pwwatch->OpenWindow2(parent, uri, name, features, aCalledFromJS,
|
||||||
false, false, thisTabParent, nullptr, getter_AddRefs(window));
|
false, false, thisTabParent, nullptr, getter_AddRefs(window));
|
||||||
|
#else
|
||||||
|
MOZ_ASSERT(0);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (NS_WARN_IF(NS_FAILED(*aResult))) {
|
if (NS_WARN_IF(NS_FAILED(*aResult))) {
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -608,6 +608,12 @@ private:
|
||||||
nullptr,
|
nullptr,
|
||||||
nullptr,
|
nullptr,
|
||||||
false, false, true, nullptr, nullptr,
|
false, false, true, nullptr, nullptr,
|
||||||
|
// Not a spammy popup; we got permission, we swear!
|
||||||
|
/* aIsPopupSpam = */ false,
|
||||||
|
// Don't force noopener. We're not passing in an
|
||||||
|
// opener anyway, and we _do_ want the returned
|
||||||
|
// window.
|
||||||
|
/* aForceNoOpener = */ false,
|
||||||
getter_AddRefs(newWindow));
|
getter_AddRefs(newWindow));
|
||||||
nsCOMPtr<nsPIDOMWindow> pwindow = do_QueryInterface(newWindow);
|
nsCOMPtr<nsPIDOMWindow> pwindow = do_QueryInterface(newWindow);
|
||||||
pwindow.forget(aWindow);
|
pwindow.forget(aWindow);
|
||||||
|
|
|
@ -56,6 +56,12 @@ interface nsPIWindowWatcher : nsISupports
|
||||||
nsITabParent is a remote tab belonging to aParent. Can
|
nsITabParent is a remote tab belonging to aParent. Can
|
||||||
be nullptr if this window is not being opened from a tab.
|
be nullptr if this window is not being opened from a tab.
|
||||||
@param aArgs Window argument
|
@param aArgs Window argument
|
||||||
|
@param aIsPopupSpam true if the window is a popup spam window; used for
|
||||||
|
popup blocker internals.
|
||||||
|
@param aForceNoOpener If true, force noopener behavior. This means not
|
||||||
|
looking for existing windows with the given name,
|
||||||
|
not setting an opener on the newly opened window,
|
||||||
|
and returning null from this method.
|
||||||
@return the new window
|
@return the new window
|
||||||
|
|
||||||
@note This method may examine the JS context stack for purposes of
|
@note This method may examine the JS context stack for purposes of
|
||||||
|
@ -70,7 +76,9 @@ interface nsPIWindowWatcher : nsISupports
|
||||||
in string aName, in string aFeatures,
|
in string aName, in string aFeatures,
|
||||||
in boolean aCalledFromScript, in boolean aDialog,
|
in boolean aCalledFromScript, in boolean aDialog,
|
||||||
in boolean aNavigate, in nsITabParent aOpeningTab,
|
in boolean aNavigate, in nsITabParent aOpeningTab,
|
||||||
in nsISupports aArgs);
|
in nsISupports aArgs,
|
||||||
|
in boolean aIsPopupSpam,
|
||||||
|
in boolean aForceNoOpener);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find a named docshell tree item amongst all windows registered
|
* Find a named docshell tree item amongst all windows registered
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "nsJSUtils.h"
|
#include "nsJSUtils.h"
|
||||||
#include "plstr.h"
|
#include "plstr.h"
|
||||||
|
|
||||||
|
#include "nsGlobalWindow.h"
|
||||||
#include "nsIBaseWindow.h"
|
#include "nsIBaseWindow.h"
|
||||||
#include "nsIBrowserDOMWindow.h"
|
#include "nsIBrowserDOMWindow.h"
|
||||||
#include "nsIDocShell.h"
|
#include "nsIDocShell.h"
|
||||||
|
@ -366,7 +367,10 @@ nsWindowWatcher::OpenWindow(nsIDOMWindow* aParent,
|
||||||
|
|
||||||
return OpenWindowInternal(aParent, aUrl, aName, aFeatures,
|
return OpenWindowInternal(aParent, aUrl, aName, aFeatures,
|
||||||
/* calledFromJS = */ false, dialog,
|
/* calledFromJS = */ false, dialog,
|
||||||
/* navigate = */ true, nullptr, argv, aResult);
|
/* navigate = */ true, nullptr, argv,
|
||||||
|
/* aIsPopupSpam = */ false,
|
||||||
|
/* aForceNoOpener = */ false,
|
||||||
|
aResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SizeSpec
|
struct SizeSpec
|
||||||
|
@ -424,6 +428,8 @@ nsWindowWatcher::OpenWindow2(nsIDOMWindow* aParent,
|
||||||
bool aNavigate,
|
bool aNavigate,
|
||||||
nsITabParent* aOpeningTab,
|
nsITabParent* aOpeningTab,
|
||||||
nsISupports* aArguments,
|
nsISupports* aArguments,
|
||||||
|
bool aIsPopupSpam,
|
||||||
|
bool aForceNoOpener,
|
||||||
nsIDOMWindow** aResult)
|
nsIDOMWindow** aResult)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIArray> argv = ConvertArgsToArray(aArguments);
|
nsCOMPtr<nsIArray> argv = ConvertArgsToArray(aArguments);
|
||||||
|
@ -443,7 +449,10 @@ nsWindowWatcher::OpenWindow2(nsIDOMWindow* aParent,
|
||||||
|
|
||||||
return OpenWindowInternal(aParent, aUrl, aName, aFeatures,
|
return OpenWindowInternal(aParent, aUrl, aName, aFeatures,
|
||||||
aCalledFromScript, dialog,
|
aCalledFromScript, dialog,
|
||||||
aNavigate, aOpeningTab, argv, aResult);
|
aNavigate, aOpeningTab, argv,
|
||||||
|
aIsPopupSpam,
|
||||||
|
aForceNoOpener,
|
||||||
|
aResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult
|
nsresult
|
||||||
|
@ -456,6 +465,8 @@ nsWindowWatcher::OpenWindowInternal(nsIDOMWindow* aParent,
|
||||||
bool aNavigate,
|
bool aNavigate,
|
||||||
nsITabParent* aOpeningTab,
|
nsITabParent* aOpeningTab,
|
||||||
nsIArray* aArgv,
|
nsIArray* aArgv,
|
||||||
|
bool aIsPopupSpam,
|
||||||
|
bool aForceNoOpener,
|
||||||
nsIDOMWindow** aResult)
|
nsIDOMWindow** aResult)
|
||||||
{
|
{
|
||||||
nsresult rv = NS_OK;
|
nsresult rv = NS_OK;
|
||||||
|
@ -531,7 +542,8 @@ nsWindowWatcher::OpenWindowInternal(nsIDOMWindow* aParent,
|
||||||
// know or care about names - unless we're opening named windows from chrome.
|
// know or care about names - unless we're opening named windows from chrome.
|
||||||
if (!aOpeningTab) {
|
if (!aOpeningTab) {
|
||||||
// try to find an extant window with the given name
|
// try to find an extant window with the given name
|
||||||
nsCOMPtr<nsIDOMWindow> foundWindow = SafeGetWindowByName(name, aParent);
|
nsCOMPtr<nsIDOMWindow> foundWindow =
|
||||||
|
SafeGetWindowByName(name, aForceNoOpener, aParent);
|
||||||
GetWindowTreeItem(foundWindow, getter_AddRefs(newDocShellItem));
|
GetWindowTreeItem(foundWindow, getter_AddRefs(newDocShellItem));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -828,7 +840,8 @@ nsWindowWatcher::OpenWindowInternal(nsIDOMWindow* aParent,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = ReadyOpenedDocShellItem(newDocShellItem, aParent, windowIsNew, aResult);
|
rv = ReadyOpenedDocShellItem(newDocShellItem, aParent, windowIsNew,
|
||||||
|
aForceNoOpener, aResult);
|
||||||
if (NS_FAILED(rv)) {
|
if (NS_FAILED(rv)) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
@ -900,6 +913,16 @@ nsWindowWatcher::OpenWindowInternal(nsIDOMWindow* aParent,
|
||||||
// SetInitialPrincipalToSubject is safe to call multiple times.
|
// SetInitialPrincipalToSubject is safe to call multiple times.
|
||||||
if (newWindow) {
|
if (newWindow) {
|
||||||
newWindow->SetInitialPrincipalToSubject();
|
newWindow->SetInitialPrincipalToSubject();
|
||||||
|
if (aIsPopupSpam) {
|
||||||
|
nsGlobalWindow* globalWin = static_cast<nsGlobalWindow*>(newWindow.get());
|
||||||
|
MOZ_ASSERT(!globalWin->IsPopupSpamWindow(),
|
||||||
|
"Who marked it as popup spam already???");
|
||||||
|
if (!globalWin->IsPopupSpamWindow()) { // Make sure we don't mess up our
|
||||||
|
// counter even if the above
|
||||||
|
// assert fails.
|
||||||
|
globalWin->SetIsPopupSpamWindow(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1069,6 +1092,10 @@ nsWindowWatcher::OpenWindowInternal(nsIDOMWindow* aParent,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (aForceNoOpener && windowIsNew) {
|
||||||
|
NS_RELEASE(*aResult);
|
||||||
|
}
|
||||||
|
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1857,8 +1884,18 @@ nsWindowWatcher::GetCallerTreeItem(nsIDocShellTreeItem* aParentItem)
|
||||||
|
|
||||||
nsPIDOMWindow*
|
nsPIDOMWindow*
|
||||||
nsWindowWatcher::SafeGetWindowByName(const nsAString& aName,
|
nsWindowWatcher::SafeGetWindowByName(const nsAString& aName,
|
||||||
|
bool aForceNoOpener,
|
||||||
nsIDOMWindow* aCurrentWindow)
|
nsIDOMWindow* aCurrentWindow)
|
||||||
{
|
{
|
||||||
|
if (aForceNoOpener) {
|
||||||
|
if (!aName.LowerCaseEqualsLiteral("_self") &&
|
||||||
|
!aName.LowerCaseEqualsLiteral("_top") &&
|
||||||
|
!aName.LowerCaseEqualsLiteral("_parent")) {
|
||||||
|
// Ignore all other names in the noopener case.
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsIDocShellTreeItem> startItem;
|
nsCOMPtr<nsIDocShellTreeItem> startItem;
|
||||||
GetWindowTreeItem(aCurrentWindow, getter_AddRefs(startItem));
|
GetWindowTreeItem(aCurrentWindow, getter_AddRefs(startItem));
|
||||||
|
|
||||||
|
@ -1887,6 +1924,7 @@ nsresult
|
||||||
nsWindowWatcher::ReadyOpenedDocShellItem(nsIDocShellTreeItem* aOpenedItem,
|
nsWindowWatcher::ReadyOpenedDocShellItem(nsIDocShellTreeItem* aOpenedItem,
|
||||||
nsIDOMWindow* aParent,
|
nsIDOMWindow* aParent,
|
||||||
bool aWindowIsNew,
|
bool aWindowIsNew,
|
||||||
|
bool aForceNoOpener,
|
||||||
nsIDOMWindow** aOpenedWindow)
|
nsIDOMWindow** aOpenedWindow)
|
||||||
{
|
{
|
||||||
nsresult rv = NS_ERROR_FAILURE;
|
nsresult rv = NS_ERROR_FAILURE;
|
||||||
|
@ -1897,7 +1935,9 @@ nsWindowWatcher::ReadyOpenedDocShellItem(nsIDocShellTreeItem* aOpenedItem,
|
||||||
nsCOMPtr<nsPIDOMWindow> piOpenedWindow = aOpenedItem->GetWindow();
|
nsCOMPtr<nsPIDOMWindow> piOpenedWindow = aOpenedItem->GetWindow();
|
||||||
if (piOpenedWindow) {
|
if (piOpenedWindow) {
|
||||||
if (aParent) {
|
if (aParent) {
|
||||||
piOpenedWindow->SetOpenerWindow(aParent, aWindowIsNew); // damnit
|
if (!aForceNoOpener) {
|
||||||
|
piOpenedWindow->SetOpenerWindow(aParent, aWindowIsNew); // damnit
|
||||||
|
}
|
||||||
|
|
||||||
if (aWindowIsNew) {
|
if (aWindowIsNew) {
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
|
|
@ -70,7 +70,9 @@ protected:
|
||||||
|
|
||||||
// Unlike GetWindowByName this will look for a caller on the JS
|
// Unlike GetWindowByName this will look for a caller on the JS
|
||||||
// stack, and then fall back on aCurrentWindow if it can't find one.
|
// stack, and then fall back on aCurrentWindow if it can't find one.
|
||||||
|
// It also knows to not look for things if aForceNoOpener is set.
|
||||||
nsPIDOMWindow* SafeGetWindowByName(const nsAString& aName,
|
nsPIDOMWindow* SafeGetWindowByName(const nsAString& aName,
|
||||||
|
bool aForceNoOpener,
|
||||||
nsIDOMWindow* aCurrentWindow);
|
nsIDOMWindow* aCurrentWindow);
|
||||||
|
|
||||||
// Just like OpenWindowJS, but knows whether it got called via OpenWindowJS
|
// Just like OpenWindowJS, but knows whether it got called via OpenWindowJS
|
||||||
|
@ -84,6 +86,8 @@ protected:
|
||||||
bool aNavigate,
|
bool aNavigate,
|
||||||
nsITabParent* aOpeningTab,
|
nsITabParent* aOpeningTab,
|
||||||
nsIArray* aArgv,
|
nsIArray* aArgv,
|
||||||
|
bool aIsPopupSpam,
|
||||||
|
bool aForceNoOpener,
|
||||||
nsIDOMWindow** aResult);
|
nsIDOMWindow** aResult);
|
||||||
|
|
||||||
static nsresult URIfromURL(const char* aURL,
|
static nsresult URIfromURL(const char* aURL,
|
||||||
|
@ -105,6 +109,7 @@ protected:
|
||||||
static nsresult ReadyOpenedDocShellItem(nsIDocShellTreeItem* aOpenedItem,
|
static nsresult ReadyOpenedDocShellItem(nsIDocShellTreeItem* aOpenedItem,
|
||||||
nsIDOMWindow* aParent,
|
nsIDOMWindow* aParent,
|
||||||
bool aWindowIsNew,
|
bool aWindowIsNew,
|
||||||
|
bool aForceNoOpener,
|
||||||
nsIDOMWindow** aOpenedWindow);
|
nsIDOMWindow** aOpenedWindow);
|
||||||
static void SizeOpenedDocShellItem(nsIDocShellTreeItem* aDocShellItem,
|
static void SizeOpenedDocShellItem(nsIDocShellTreeItem* aDocShellItem,
|
||||||
nsIDOMWindow* aParent,
|
nsIDOMWindow* aParent,
|
||||||
|
|
Loading…
Reference in New Issue