Bug 1221992 - Prevent ServiceWorkerClients.OpenWindow from opening tabs in private mode windows. r=smaug
☠☠ backed out by 5b71c7baa255 ☠ ☠
authorCatalin Badea <catalin.badea392@gmail.com>
Fri, 04 Dec 2015 19:14:44 +0200
changeset 309882 7cdcda3e65fb4ee83c223b60fcbec876fb92925c
parent 309881 a42590c2a8bf36bc766621cb0362dff28de037df
child 309883 ad20808dd3c4cf475b1c7b71a2df15aabf2f3166
push id5513
push userraliiev@mozilla.com
push dateMon, 25 Jan 2016 13:55:34 +0000
treeherdermozilla-beta@5ee97dd05b5c [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
@@ -143,17 +143,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"
@@ -5384,44 +5383,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,
@@ -5485,17 +5456,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,88 @@ 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)
 {
   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 +769,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;