Bug 1967520 - Add WindowMediatorFilter r=asuth

Differential Revision: https://phabricator.services.mozilla.com/D250305
This commit is contained in:
Kagami Sascha Rosylight
2025-05-23 16:35:01 +00:00
committed by krosylight@mozilla.com
parent e3a4c6903b
commit 85d13ee19d
6 changed files with 91 additions and 8 deletions

View File

@@ -6858,6 +6858,20 @@ nsContentUtils::GetMostRecentNonPBWindow() {
return pwindow.forget();
}
/* static */
already_AddRefed<nsPIDOMWindowOuter> nsContentUtils::GetMostRecentWindowBy(
WindowMediatorFilter aFilter) {
nsCOMPtr<nsIWindowMediator> wm = do_GetService(NS_WINDOWMEDIATOR_CONTRACTID);
nsCOMPtr<mozIDOMWindowProxy> window;
wm->GetMostRecentWindowBy(u"navigator:browser", static_cast<uint8_t>(aFilter),
getter_AddRefs(window));
nsCOMPtr<nsPIDOMWindowOuter> pwindow;
pwindow = do_QueryInterface(window);
return pwindow.forget();
}
/* static */
void nsContentUtils::WarnScriptWasIgnored(Document* aDocument) {
nsAutoString msg;

View File

@@ -121,6 +121,7 @@ class nsPresContext;
class nsTextFragment;
class nsView;
class nsWrapperCache;
enum class WindowMediatorFilter : uint8_t;
struct JSContext;
struct nsPoint;
@@ -2297,6 +2298,11 @@ class nsContentUtils {
// not in private browsing mode.
static already_AddRefed<nsPIDOMWindowOuter> GetMostRecentNonPBWindow();
// Returns the browser window with the most recent time stamp, filtered by the
// parameter.
static already_AddRefed<nsPIDOMWindowOuter> GetMostRecentWindowBy(
WindowMediatorFilter aFilter);
/**
* Call this function if !IsSafeToRunScript() and we fail to run the script
* (rather than using AddScriptRunner as we usually do). |aDocument| is

View File

@@ -23,6 +23,7 @@
#include "nsIBrowser.h"
#include "nsIWebProgress.h"
#include "nsIWebProgressListener.h"
#include "nsIWindowMediator.h"
#include "nsIWindowWatcher.h"
#include "nsIXPConnect.h"
#include "nsNetUtil.h"
@@ -214,8 +215,14 @@ void OpenWindow(const ClientOpenWindowArgsParsed& aArgsValidated,
// [[6.1 Open Window]]
// Find the most recent browser window and open a new tab in it.
WindowMediatorFilter filter = WindowMediatorFilter::SkipClosed;
if (aArgsValidated.principal->GetIsInPrivateBrowsing()) {
filter |= WindowMediatorFilter::SkipNonPrivateBrowsing;
} else {
filter |= WindowMediatorFilter::SkipPrivateBrowsing;
}
nsCOMPtr<nsPIDOMWindowOuter> browserWindow =
nsContentUtils::GetMostRecentNonPBWindow();
nsContentUtils::GetMostRecentWindowBy(filter);
if (!browserWindow) {
// It is possible to be running without a browser window on Mac OS, so
// we need to open a new chrome window.

View File

@@ -13,6 +13,15 @@
#define NS_WINDOWMEDIATOR_CONTRACTID \
"@mozilla.org/appshell/window-mediator;1"
enum class WindowMediatorFilter : uint8_t {
None = 0,
SkipPrivateBrowsing = 1 << 0,
SkipClosed = 1 << 1,
SkipNonPrivateBrowsing = 1 << 2,
};
MOZ_MAKE_ENUM_CLASS_BITWISE_OPERATORS(WindowMediatorFilter)
%}
interface mozIDOMWindow;
@@ -79,6 +88,14 @@ interface nsIWindowMediator: nsISupports
*/
mozIDOMWindowProxy getMostRecentNonPBWindow(in wstring aWindowType);
/**
* Same as getMostRecentWindow, but filters out based on the parameter.
* @param aFilter The value based on the enum WindowMediatorFilter.
*
* (Not using WindowMediatorFilter directly it requires [builtinclass])
*/
mozIDOMWindowProxy getMostRecentWindowBy(in wstring aWindowType, in uint8_t aFilter);
/**
* Return the outer window with the given ID, if any. Can return null.
*/

View File

@@ -236,7 +236,7 @@ nsWindowMediator::GetMostRecentWindow(const char16_t* inType,
// Find the most window with the highest time stamp that matches
// the requested type
nsWindowInfo* info = MostRecentWindowInfo(inType, false);
nsWindowInfo* info = MostRecentWindowInfo(inType, WindowMediatorFilter::None);
if (info && info->mWindow) {
nsCOMPtr<nsPIDOMWindowOuter> DOMWindow;
if (NS_SUCCEEDED(GetDOMWindow(info->mWindow, DOMWindow))) {
@@ -278,7 +278,31 @@ nsWindowMediator::GetMostRecentNonPBWindow(const char16_t* aType,
NS_ENSURE_ARG_POINTER(aWindow);
*aWindow = nullptr;
nsWindowInfo* info = MostRecentWindowInfo(aType, true);
nsWindowInfo* info =
MostRecentWindowInfo(aType, WindowMediatorFilter::SkipPrivateBrowsing |
WindowMediatorFilter::SkipClosed);
nsCOMPtr<nsPIDOMWindowOuter> domWindow;
if (info && info->mWindow) {
GetDOMWindow(info->mWindow, domWindow);
}
if (!domWindow) {
return NS_ERROR_FAILURE;
}
domWindow.forget(aWindow);
return NS_OK;
}
NS_IMETHODIMP
nsWindowMediator::GetMostRecentWindowBy(const char16_t* aType, uint8_t aFilter,
mozIDOMWindowProxy** aWindow) {
MOZ_RELEASE_ASSERT(NS_IsMainThread());
NS_ENSURE_ARG_POINTER(aWindow);
*aWindow = nullptr;
nsWindowInfo* info =
MostRecentWindowInfo(aType, static_cast<WindowMediatorFilter>(aFilter));
nsCOMPtr<nsPIDOMWindowOuter> domWindow;
if (info && info->mWindow) {
GetDOMWindow(info->mWindow, domWindow);
@@ -293,7 +317,7 @@ nsWindowMediator::GetMostRecentNonPBWindow(const char16_t* aType,
}
nsWindowInfo* nsWindowMediator::MostRecentWindowInfo(
const char16_t* inType, bool aSkipPrivateBrowsingOrClosed) {
const char16_t* inType, WindowMediatorFilter aFilter) {
int32_t lastTimeStamp = -1;
nsAutoString typeString(inType);
bool allWindows = !inType || typeString.IsEmpty();
@@ -315,16 +339,30 @@ nsWindowInfo* nsWindowMediator::MostRecentWindowInfo(
if (!searchInfo->mWindow) {
continue;
}
if (aSkipPrivateBrowsingOrClosed) {
if (aFilter != WindowMediatorFilter::None) {
nsCOMPtr<nsIDocShell> docShell;
searchInfo->mWindow->GetDocShell(getter_AddRefs(docShell));
nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(docShell);
if (!loadContext || loadContext->UsePrivateBrowsing()) {
if (!loadContext) {
continue;
}
if ((aFilter & WindowMediatorFilter::SkipNonPrivateBrowsing) &&
!loadContext->UsePrivateBrowsing()) {
continue;
}
if ((aFilter & WindowMediatorFilter::SkipPrivateBrowsing) &&
loadContext->UsePrivateBrowsing()) {
continue;
}
nsCOMPtr<nsPIDOMWindowOuter> piwindow = docShell->GetWindow();
if (!piwindow || piwindow->Closed()) {
if (!piwindow) {
continue;
}
if ((aFilter & WindowMediatorFilter::SkipClosed) && piwindow->Closed()) {
continue;
}
}

View File

@@ -50,8 +50,9 @@ class nsWindowMediator : public nsIWindowMediator,
private:
void AddEnumerator(nsAppShellWindowEnumerator* inEnumerator);
int32_t RemoveEnumerator(nsAppShellWindowEnumerator* inEnumerator);
nsWindowInfo* MostRecentWindowInfo(const char16_t* inType,
bool aSkipPrivateBrowsingOrClosed = false);
WindowMediatorFilter aFilter);
nsresult UnregisterWindow(nsWindowInfo* inInfo);
nsWindowInfo* GetInfoFor(nsIAppWindow* aWindow);