Bug 1221992 - Prevent ServiceWorkerClients.OpenWindow from opening tabs in private mode windows. r=smaug

This commit is contained in:
Catalin Badea 2015-12-11 13:32:15 -05:00
parent 15df0b5e2b
commit 54a27691d4
7 changed files with 95 additions and 54 deletions

View File

@ -162,6 +162,7 @@
#include "nsIURIWithPrincipal.h" #include "nsIURIWithPrincipal.h"
#include "nsIURL.h" #include "nsIURL.h"
#include "nsIWebNavigation.h" #include "nsIWebNavigation.h"
#include "nsIWindowMediator.h"
#include "nsIWordBreaker.h" #include "nsIWordBreaker.h"
#include "nsIXPConnect.h" #include "nsIXPConnect.h"
#include "nsJSUtils.h" #include "nsJSUtils.h"
@ -5167,6 +5168,23 @@ nsContentUtils::GetWindowProviderForContentProcess()
return ContentChild::GetSingleton(); return ContentChild::GetSingleton();
} }
/* static */
already_AddRefed<nsPIDOMWindow>
nsContentUtils::GetMostRecentNonPBWindow()
{
nsCOMPtr<nsIWindowMediator> windowMediator =
do_GetService(NS_WINDOWMEDIATOR_CONTRACTID);
nsCOMPtr<nsIWindowMediator_44> wm = do_QueryInterface(windowMediator);
nsCOMPtr<nsIDOMWindow> window;
wm->GetMostRecentNonPBWindow(MOZ_UTF16("navigator:browser"),
getter_AddRefs(window));
nsCOMPtr<nsPIDOMWindow> pwindow;
pwindow = do_QueryInterface(window);
return pwindow.forget();
}
/* static */ /* static */
void void
nsContentUtils::WarnScriptWasIgnored(nsIDocument* aDocument) nsContentUtils::WarnScriptWasIgnored(nsIDocument* aDocument)

View File

@ -1666,6 +1666,11 @@ public:
static nsIWindowProvider* static nsIWindowProvider*
GetWindowProviderForContentProcess(); GetWindowProviderForContentProcess();
// Returns the browser window with the most recent time stamp that is
// not in private browsing mode.
static already_AddRefed<nsPIDOMWindow>
GetMostRecentNonPBWindow();
/** /**
* Call this function if !IsSafeToRunScript() and we fail to run the script * Call this function if !IsSafeToRunScript() and we fail to run the script
* (rather than using AddScriptRunner as we usually do). |aDocument| is * (rather than using AddScriptRunner as we usually do). |aDocument| is

View File

@ -148,7 +148,6 @@
#include "nsISystemMessagesInternal.h" #include "nsISystemMessagesInternal.h"
#include "nsITimer.h" #include "nsITimer.h"
#include "nsIURIFixup.h" #include "nsIURIFixup.h"
#include "nsIWindowMediator.h"
#include "nsIDocShellTreeOwner.h" #include "nsIDocShellTreeOwner.h"
#include "nsIXULWindow.h" #include "nsIXULWindow.h"
#include "nsIDOMChromeWindow.h" #include "nsIDOMChromeWindow.h"
@ -5410,34 +5409,6 @@ ContentParent::DeallocPWebBrowserPersistDocumentParent(PWebBrowserPersistDocumen
return true; return true;
} }
static already_AddRefed<nsPIDOMWindow>
FindMostRecentOpenWindow()
{
nsCOMPtr<nsIWindowMediator> windowMediator =
do_GetService(NS_WINDOWMEDIATOR_CONTRACTID);
nsCOMPtr<nsISimpleEnumerator> windowEnumerator;
windowMediator->GetEnumerator(MOZ_UTF16("navigator:browser"),
getter_AddRefs(windowEnumerator));
nsCOMPtr<nsPIDOMWindow> latest;
bool hasMore = false;
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(windowEnumerator->HasMoreElements(&hasMore)));
while (hasMore) {
nsCOMPtr<nsISupports> item;
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(windowEnumerator->GetNext(getter_AddRefs(item))));
nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(item);
if (window && !window->Closed()) {
latest = window;
}
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(windowEnumerator->HasMoreElements(&hasMore)));
}
return latest.forget();
}
bool bool
ContentParent::RecvCreateWindow(PBrowserParent* aThisTab, ContentParent::RecvCreateWindow(PBrowserParent* aThisTab,
PBrowserParent* aNewTab, PBrowserParent* aNewTab,
@ -5511,7 +5482,7 @@ ContentParent::RecvCreateWindow(PBrowserParent* aThisTab,
// If we haven't found a chrome window to open in, just use the most recently // If we haven't found a chrome window to open in, just use the most recently
// opened one. // opened one.
if (!parent) { if (!parent) {
parent = FindMostRecentOpenWindow(); parent = nsContentUtils::GetMostRecentNonPBWindow();
if (NS_WARN_IF(!parent)) { if (NS_WARN_IF(!parent)) {
*aResult = NS_ERROR_FAILURE; *aResult = NS_ERROR_FAILURE;
return true; return true;

View File

@ -615,10 +615,9 @@ private:
} }
// Find the most recent browser window and open a new tab in it. // Find the most recent browser window and open a new tab in it.
nsCOMPtr<nsIDOMWindow> browserWindow; nsCOMPtr<nsPIDOMWindow> browserWindow =
rv = wm->GetMostRecentWindow(MOZ_UTF16("navigator:browser"), nsContentUtils::GetMostRecentNonPBWindow();
getter_AddRefs(browserWindow)); if (!browserWindow) {
if (NS_WARN_IF(NS_FAILED(rv)) || !browserWindow) {
// It is possible to be running without a browser window on Mac OS, so // It is possible to be running without a browser window on Mac OS, so
// we need to open a new chrome window. // we need to open a new chrome window.
// TODO(catalinb): open new chrome window. Bug 1218080 // TODO(catalinb): open new chrome window. Bug 1218080

View File

@ -191,3 +191,15 @@ interface nsIWindowMediator: nsISupports
*/ */
void removeListener(in nsIWindowMediatorListener aListener); void removeListener(in nsIWindowMediatorListener aListener);
}; };
// XXXcatalinb: This should be merged to nsIWindowMediator. Using this
// to avoid UUID change in aurora.
[scriptable, uuid(88b54988-7f3c-40d2-a625-7e42a9c196c2)]
interface nsIWindowMediator_44 : nsIWindowMediator
{
/**
* Same as getMostRecentWindow, but ignores private browsing
* windows.
*/
nsIDOMWindow getMostRecentNonPBWindow(in wstring aWindowType);
};

View File

@ -275,7 +275,7 @@ nsWindowMediator::GetMostRecentWindow(const char16_t* inType, nsIDOMWindow** out
// Find the most window with the highest time stamp that matches // Find the most window with the highest time stamp that matches
// the requested type // the requested type
nsWindowInfo *info = MostRecentWindowInfo(inType); nsWindowInfo* info = MostRecentWindowInfo(inType, false);
if (info && info->mWindow) { if (info && info->mWindow) {
nsCOMPtr<nsIDOMWindow> DOMWindow; nsCOMPtr<nsIDOMWindow> DOMWindow;
if (NS_SUCCEEDED(GetDOMWindow(info->mWindow, DOMWindow))) { if (NS_SUCCEEDED(GetDOMWindow(info->mWindow, DOMWindow))) {
@ -289,31 +289,64 @@ nsWindowMediator::GetMostRecentWindow(const char16_t* inType, nsIDOMWindow** out
return NS_OK; return NS_OK;
} }
NS_IMETHODIMP
nsWindowMediator::GetMostRecentNonPBWindow(const char16_t* aType, nsIDOMWindow** aWindow)
{
MOZ_RELEASE_ASSERT(NS_IsMainThread());
NS_ENSURE_ARG_POINTER(aWindow);
*aWindow = nullptr;
nsWindowInfo *info = MostRecentWindowInfo(aType, true);
nsCOMPtr<nsIDOMWindow> domWindow;
if (info && info->mWindow) {
GetDOMWindow(info->mWindow, domWindow);
}
if (!domWindow) {
return NS_ERROR_FAILURE;
}
domWindow.forget(aWindow);
return NS_OK;
}
nsWindowInfo* nsWindowInfo*
nsWindowMediator::MostRecentWindowInfo(const char16_t* inType) nsWindowMediator::MostRecentWindowInfo(const char16_t* inType, bool aSkipPrivateBrowsing)
{ {
int32_t lastTimeStamp = -1; int32_t lastTimeStamp = -1;
nsAutoString typeString(inType); nsAutoString typeString(inType);
bool allWindows = !inType || typeString.IsEmpty(); bool allWindows = !inType || typeString.IsEmpty();
// Find the most window with the highest time stamp that matches // Find the most recent window with the highest time stamp that matches
// the requested type // the requested type and has the correct browsing mode.
nsWindowInfo *searchInfo, nsWindowInfo* searchInfo = mOldestWindow;
*listEnd, nsWindowInfo* listEnd = nullptr;
*foundInfo = nullptr; nsWindowInfo* foundInfo = nullptr;
for (; searchInfo != listEnd; searchInfo = searchInfo->mYounger) {
searchInfo = mOldestWindow;
listEnd = nullptr;
while (searchInfo != listEnd) {
if ((allWindows || searchInfo->TypeEquals(typeString)) &&
searchInfo->mTimeStamp >= lastTimeStamp) {
foundInfo = searchInfo;
lastTimeStamp = searchInfo->mTimeStamp;
}
searchInfo = searchInfo->mYounger;
listEnd = mOldestWindow; listEnd = mOldestWindow;
if (!allWindows && !searchInfo->TypeEquals(typeString)) {
continue;
}
if (searchInfo->mTimeStamp < lastTimeStamp) {
continue;
}
if (!searchInfo->mWindow) {
continue;
}
if (aSkipPrivateBrowsing) {
nsCOMPtr<nsIDocShell> docShell;
searchInfo->mWindow->GetDocShell(getter_AddRefs(docShell));
nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(docShell);
if (!loadContext || loadContext->UsePrivateBrowsing()) {
continue;
}
}
foundInfo = searchInfo;
lastTimeStamp = searchInfo->mTimeStamp;
} }
return foundInfo; return foundInfo;
} }
@ -741,6 +774,7 @@ nsWindowMediator::SortZOrderBackToFront()
} }
NS_IMPL_ISUPPORTS(nsWindowMediator, NS_IMPL_ISUPPORTS(nsWindowMediator,
nsIWindowMediator_44,
nsIWindowMediator, nsIWindowMediator,
nsIObserver, nsIObserver,
nsISupportsWeakReference) nsISupportsWeakReference)

View File

@ -25,7 +25,7 @@ class nsIWindowMediatorListener;
struct nsWindowInfo; struct nsWindowInfo;
class nsWindowMediator : class nsWindowMediator :
public nsIWindowMediator, public nsIWindowMediator_44,
public nsIObserver, public nsIObserver,
public nsSupportsWeakReference public nsSupportsWeakReference
{ {
@ -47,6 +47,7 @@ public:
NS_DECL_ISUPPORTS NS_DECL_ISUPPORTS
NS_DECL_NSIWINDOWMEDIATOR NS_DECL_NSIWINDOWMEDIATOR
NS_DECL_NSIWINDOWMEDIATOR_44
NS_DECL_NSIOBSERVER NS_DECL_NSIOBSERVER
static nsresult GetDOMWindow(nsIXULWindow* inWindow, static nsresult GetDOMWindow(nsIXULWindow* inWindow,
@ -55,7 +56,8 @@ public:
private: private:
int32_t AddEnumerator(nsAppShellWindowEnumerator* inEnumerator); int32_t AddEnumerator(nsAppShellWindowEnumerator* inEnumerator);
int32_t RemoveEnumerator(nsAppShellWindowEnumerator* inEnumerator); int32_t RemoveEnumerator(nsAppShellWindowEnumerator* inEnumerator);
nsWindowInfo *MostRecentWindowInfo(const char16_t* inType); nsWindowInfo* MostRecentWindowInfo(const char16_t* inType,
bool aSkipPrivateBrowsing = false);
nsresult UnregisterWindow(nsWindowInfo *inInfo); nsresult UnregisterWindow(nsWindowInfo *inInfo);
nsWindowInfo *GetInfoFor(nsIXULWindow *aWindow); nsWindowInfo *GetInfoFor(nsIXULWindow *aWindow);