diff --git a/dom/base/nsDOMWindowUtils.cpp b/dom/base/nsDOMWindowUtils.cpp index dd652cce03b7..03ed40d7ad2a 100644 --- a/dom/base/nsDOMWindowUtils.cpp +++ b/dom/base/nsDOMWindowUtils.cpp @@ -2969,3 +2969,15 @@ nsDOMWindowUtils::GetIsHandlingUserInput(bool* aHandlingUserInput) return NS_OK; } + +NS_IMETHODIMP +nsDOMWindowUtils::AllowScriptsToClose() +{ + if (!IsUniversalXPConnectCapable()) { + return NS_ERROR_DOM_SECURITY_ERR; + } + nsCOMPtr window = do_QueryReferent(mWindow); + NS_ENSURE_STATE(window); + static_cast(window.get())->AllowScriptsToClose(); + return NS_OK; +} diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index 214101a3197f..f5260a4787ee 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -699,6 +699,7 @@ nsGlobalWindow::nsGlobalWindow(nsGlobalWindow *aOuterWindow) mShowFocusRingForContent(false), mFocusByKeyOccurred(false), mNotifiedIDDestroyed(false), + mAllowScriptsToClose(false), mTimeoutInsertionPoint(nullptr), mTimeoutPublicIdCounter(1), mTimeoutFiringDepth(0), @@ -6584,7 +6585,7 @@ nsGlobalWindow::Close() // opened by script. if (!mDocShell->GetIsApp() && !mHadOriginalOpener && !nsContentUtils::IsCallerTrustedForWrite()) { - bool allowClose = + bool allowClose = mAllowScriptsToClose || Preferences::GetBool("dom.allow_scripts_to_close_windows", true); if (!allowClose) { // We're blocking the close operation diff --git a/dom/base/nsGlobalWindow.h b/dom/base/nsGlobalWindow.h index 9017711d4e3e..b70d43e2c91e 100644 --- a/dom/base/nsGlobalWindow.h +++ b/dom/base/nsGlobalWindow.h @@ -604,6 +604,10 @@ public: bool ContainsIdleObserver(nsIIdleObserver* aIdleObserver, uint32_t timeInS); void HandleIdleObserverCallback(); + void AllowScriptsToClose() + { + mAllowScriptsToClose = true; + } protected: // Array of idle observers that are notified of idle events. nsTObserverArray mIdleObservers; @@ -996,6 +1000,9 @@ protected: // whether we've sent the destroy notification for our window id bool mNotifiedIDDestroyed : 1; + // whether scripts may close the window, + // even if "dom.allow_scripts_to_close_windows" is false. + bool mAllowScriptsToClose : 1; nsCOMPtr mContext; nsWeakPtr mOpener; diff --git a/dom/interfaces/base/nsIDOMWindowUtils.idl b/dom/interfaces/base/nsIDOMWindowUtils.idl index 49c9bc99e4d6..c4bac825f745 100644 --- a/dom/interfaces/base/nsIDOMWindowUtils.idl +++ b/dom/interfaces/base/nsIDOMWindowUtils.idl @@ -40,7 +40,7 @@ interface nsIDOMTouch; interface nsIDOMClientRect; interface nsIURI; -[scriptable, uuid(a76927b7-4aca-4cd1-9c2b-a6b4789b88c3)] +[scriptable, uuid(f5b9883b-2ab9-426c-8fc1-7296cb6bc1d2)] interface nsIDOMWindowUtils : nsISupports { /** @@ -1277,4 +1277,10 @@ interface nsIDOMWindowUtils : nsISupports { * This calls nsEventStateManager::IsHandlingUserInput(). */ readonly attribute boolean isHandlingUserInput; + + /** + * After calling the method, the window for which this DOMWindowUtils + * was created can be closed using scripts. + */ + void allowScriptsToClose(); };