Bug 1221992 - Prevent ServiceWorkerClients.OpenWindow from opening tabs in private mode windows. r=smaug
☠☠ backed out by c6341b8dd280 ☠ ☠
authorCatalin Badea <catalin.badea392@gmail.com>
Thu, 03 Dec 2015 23:19:29 +0200
changeset 275485 6affaa386b9bb2d5b32f2497076269264866dc75
parent 275484 786516f51bc339e623a095389a9bcbff95ed536d
child 275486 bcd90e59103812be30b73d465b5eeef26ed1d4a4
push id68861
push usercatalin.badea392@gmail.com
push dateThu, 03 Dec 2015 21:19:43 +0000
treeherdermozilla-inbound@bcd90e591038 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1221992
milestone45.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1221992 - Prevent ServiceWorkerClients.OpenWindow from opening tabs in private mode windows. r=smaug
dom/base/nsContentUtils.cpp
dom/base/nsContentUtils.h
dom/ipc/ContentParent.cpp
dom/workers/ServiceWorkerClients.cpp
xpfe/appshell/nsIWindowMediator.idl
xpfe/appshell/nsWindowMediator.cpp
xpfe/appshell/nsWindowMediator.h
--- a/dom/base/nsContentUtils.cpp
+++ b/dom/base/nsContentUtils.cpp
@@ -157,16 +157,17 @@
 #include "nsIScriptObjectPrincipal.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIStreamConverterService.h"
 #include "nsIStringBundle.h"
 #include "nsIURI.h"
 #include "nsIURIWithPrincipal.h"
 #include "nsIURL.h"
 #include "nsIWebNavigation.h"
+#include "nsIWindowMediator.h"
 #include "nsIWordBreaker.h"
 #include "nsIXPConnect.h"
 #include "nsJSUtils.h"
 #include "nsLWBrkCIID.h"
 #include "nsNetCID.h"
 #include "nsNetUtil.h"
 #include "nsNodeInfoManager.h"
 #include "nsNullPrincipal.h"
@@ -5163,16 +5164,33 @@ nsContentUtils::RemoveScriptBlocker()
 nsIWindowProvider*
 nsContentUtils::GetWindowProviderForContentProcess()
 {
   MOZ_ASSERT(XRE_IsContentProcess());
   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 */
 void
 nsContentUtils::WarnScriptWasIgnored(nsIDocument* aDocument)
 {
   nsAutoString msg;
   if (aDocument) {
     nsCOMPtr<nsIURI> uri = aDocument->GetDocumentURI();
     if (uri) {
       nsCString spec;
--- a/dom/base/nsContentUtils.h
+++ b/dom/base/nsContentUtils.h
@@ -1661,16 +1661,21 @@ public:
     return sScriptBlockerCount == 0;
   }
 
   // XXXcatalinb: workaround for weird include error when trying to reference
   // ipdl types in WindowWatcher.
   static nsIWindowProvider*
   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
    * (rather than using AddScriptRunner as we usually do). |aDocument| is
    * optional as it is only used for showing the URL in the console.
    */
   static void WarnScriptWasIgnored(nsIDocument* aDocument);
 
   /**
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -142,17 +142,16 @@
 #include "nsIScriptError.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsISiteSecurityService.h"
 #include "nsISpellChecker.h"
 #include "nsISupportsPrimitives.h"
 #include "nsISystemMessagesInternal.h"
 #include "nsITimer.h"
 #include "nsIURIFixup.h"
-#include "nsIWindowMediator.h"
 #include "nsIDocShellTreeOwner.h"
 #include "nsIXULWindow.h"
 #include "nsIDOMChromeWindow.h"
 #include "nsIWindowWatcher.h"
 #include "nsPIWindowWatcher.h"
 #include "nsWindowWatcher.h"
 #include "nsIXULRuntime.h"
 #include "gfxDrawable.h"
@@ -5338,44 +5337,16 @@ ContentParent::AllocPWebBrowserPersistDo
 
 bool
 ContentParent::DeallocPWebBrowserPersistDocumentParent(PWebBrowserPersistDocumentParent* aActor)
 {
   delete aActor;
   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
 ContentParent::RecvCreateWindow(PBrowserParent* aThisTab,
                                 PBrowserParent* aNewTab,
                                 const uint32_t& aChromeFlags,
                                 const bool& aCalledFromJS,
                                 const bool& aPositionSpecified,
                                 const bool& aSizeSpecified,
                                 const nsCString& aURI,
@@ -5439,17 +5410,17 @@ ContentParent::RecvCreateWindow(PBrowser
     nsCOMPtr<nsIBrowserDOMWindow> browserDOMWin;
     if (thisTabParent) {
         browserDOMWin = thisTabParent->GetBrowserDOMWindow();
     }
 
     // If we haven't found a chrome window to open in, just use the most recently
     // opened one.
     if (!parent) {
-        parent = FindMostRecentOpenWindow();
+        parent = nsContentUtils::GetMostRecentNonPBWindow();
         if (NS_WARN_IF(!parent)) {
             *aResult = NS_ERROR_FAILURE;
             return true;
         }
 
         nsCOMPtr<nsIDOMChromeWindow> rootChromeWin = do_QueryInterface(parent);
         if (rootChromeWin) {
             rootChromeWin->GetBrowserDOMWindow(getter_AddRefs(browserDOMWin));
--- a/dom/workers/ServiceWorkerClients.cpp
+++ b/dom/workers/ServiceWorkerClients.cpp
@@ -610,20 +610,19 @@ private:
                            false, false, true, nullptr, nullptr,
                            getter_AddRefs(newWindow));
       nsCOMPtr<nsPIDOMWindow> pwindow = do_QueryInterface(newWindow);
       pwindow.forget(aWindow);
       return NS_OK;
     }
 
     // Find the most recent browser window and open a new tab in it.
-    nsCOMPtr<nsIDOMWindow> browserWindow;
-    rv = wm->GetMostRecentWindow(MOZ_UTF16("navigator:browser"),
-                                 getter_AddRefs(browserWindow));
-    if (NS_WARN_IF(NS_FAILED(rv)) || !browserWindow) {
+    nsCOMPtr<nsPIDOMWindow> browserWindow =
+      nsContentUtils::GetMostRecentNonPBWindow();
+    if (!browserWindow) {
       // It is possible to be running without a browser window on Mac OS, so
       // we need to open a new chrome window.
       // TODO(catalinb): open new chrome window. Bug 1218080
       return NS_ERROR_FAILURE;
     }
 
     nsCOMPtr<nsIDOMChromeWindow> chromeWin = do_QueryInterface(browserWindow);
     if (NS_WARN_IF(!chromeWin)) {
--- a/xpfe/appshell/nsIWindowMediator.idl
+++ b/xpfe/appshell/nsIWindowMediator.idl
@@ -186,8 +186,20 @@ interface nsIWindowMediator: nsISupports
     */
   void addListener(in nsIWindowMediatorListener aListener);
 
   /** Unregister a listener of window status changes.
     * @param aListener the listener to unregister
     */
   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);
+};
--- a/xpfe/appshell/nsWindowMediator.cpp
+++ b/xpfe/appshell/nsWindowMediator.cpp
@@ -270,55 +270,90 @@ nsWindowMediator::GetMostRecentWindow(co
   MOZ_RELEASE_ASSERT(NS_IsMainThread());
   NS_ENSURE_ARG_POINTER(outWindow);
   *outWindow = nullptr;
   if (!mReady)
     return NS_OK;
 
   // Find the most window with the highest time stamp that matches
   // the requested type
-  nsWindowInfo *info = MostRecentWindowInfo(inType);
+  nsWindowInfo* info = MostRecentWindowInfo(inType, false);
   if (info && info->mWindow) {
     nsCOMPtr<nsIDOMWindow> DOMWindow;
     if (NS_SUCCEEDED(GetDOMWindow(info->mWindow, DOMWindow))) {  
       *outWindow = DOMWindow;
       NS_ADDREF(*outWindow);
       return NS_OK;
     }
     return NS_ERROR_FAILURE;
   }
 
   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*
-nsWindowMediator::MostRecentWindowInfo(const char16_t* inType)
+nsWindowMediator::MostRecentWindowInfo(const char16_t* inType, bool aSkipPrivateBrowsing)
 {
+  MOZ_ASSERT(XRE_IsParentProcess());
+
   int32_t       lastTimeStamp = -1;
   nsAutoString  typeString(inType);
   bool          allWindows = !inType || typeString.IsEmpty();
 
-  // Find the most window with the highest time stamp that matches
-  // the requested type
-  nsWindowInfo *searchInfo,
-               *listEnd,
-               *foundInfo = nullptr;
+  // Find the most recent window with the highest time stamp that matches
+  // the requested type and has the correct browsing mode.
+  nsWindowInfo* searchInfo = mOldestWindow;
+  nsWindowInfo* listEnd = nullptr;
+  nsWindowInfo* foundInfo = nullptr;
+  for (; searchInfo != listEnd; searchInfo = searchInfo->mYounger) {
+    listEnd = mOldestWindow;
 
-  searchInfo = mOldestWindow;
-  listEnd = nullptr;
-  while (searchInfo != listEnd) {
-    if ((allWindows || searchInfo->TypeEquals(typeString)) &&
-        searchInfo->mTimeStamp >= lastTimeStamp) {
+    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;
-    }
-    searchInfo = searchInfo->mYounger;
-    listEnd = mOldestWindow;
+    foundInfo = searchInfo;
+    lastTimeStamp = searchInfo->mTimeStamp;
   }
+
   return foundInfo;
 }
 
 NS_IMETHODIMP
 nsWindowMediator::GetOuterWindowWithId(uint64_t aWindowID,
                                        nsIDOMWindow** aWindow)
 {
   *aWindow = nsGlobalWindow::GetOuterWindowWithId(aWindowID);
@@ -736,16 +771,17 @@ nsWindowMediator::SortZOrderBackToFront(
       scan = scan->mHigher;
     }
   } while (!finished);
 
   mSortingZOrder = false;
 }
 
 NS_IMPL_ISUPPORTS(nsWindowMediator,
+  nsIWindowMediator_44,
   nsIWindowMediator,
   nsIObserver,
   nsISupportsWeakReference)
 
 NS_IMETHODIMP
 nsWindowMediator::AddListener(nsIWindowMediatorListener* aListener)
 {
   NS_ENSURE_ARG_POINTER(aListener);
--- a/xpfe/appshell/nsWindowMediator.h
+++ b/xpfe/appshell/nsWindowMediator.h
@@ -20,17 +20,17 @@ class nsASDOMWindowEarlyToLateEnumerator
 class nsASDOMWindowFrontToBackEnumerator;
 class nsASXULWindowFrontToBackEnumerator;
 class nsASDOMWindowBackToFrontEnumerator;
 class nsASXULWindowBackToFrontEnumerator;
 class nsIWindowMediatorListener;
 struct nsWindowInfo;
 
 class nsWindowMediator :
-  public nsIWindowMediator,
+  public nsIWindowMediator_44,
   public nsIObserver,
   public nsSupportsWeakReference
 {
 friend class nsAppShellWindowEnumerator;
 friend class nsASXULWindowEarlyToLateEnumerator;
 friend class nsASDOMWindowEarlyToLateEnumerator;
 friend class nsASDOMWindowFrontToBackEnumerator;
 friend class nsASXULWindowFrontToBackEnumerator;
@@ -42,25 +42,27 @@ protected:
 
 public:
   nsWindowMediator();
 
   nsresult Init();
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIWINDOWMEDIATOR
+  NS_DECL_NSIWINDOWMEDIATOR_44
   NS_DECL_NSIOBSERVER
 
   static nsresult GetDOMWindow(nsIXULWindow* inWindow,
                                nsCOMPtr<nsIDOMWindow>& outDOMWindow);
 
 private:
   int32_t AddEnumerator(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);
   nsWindowInfo *GetInfoFor(nsIXULWindow *aWindow);
   nsWindowInfo *GetInfoFor(nsIWidget *aWindow);
   void          SortZOrderFrontToBack();
   void          SortZOrderBackToFront();
 
   nsTArray<nsAppShellWindowEnumerator*> mEnumeratorList;