LCOV - code coverage report
Current view: directory - embedding/components/windowwatcher/src - nsWindowWatcher.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 944 52 5.5 %
Date: 2012-06-02 Functions: 62 20 32.3 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* vim: set ts=2 sw=2 et tw=78: */
       3                 : /* ***** BEGIN LICENSE BLOCK *****
       4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       5                 :  *
       6                 :  * The contents of this file are subject to the Mozilla Public License Version
       7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       8                 :  * the License. You may obtain a copy of the License at
       9                 :  * http://www.mozilla.org/MPL/
      10                 :  *
      11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      13                 :  * for the specific language governing rights and limitations under the
      14                 :  * License.
      15                 :  *
      16                 :  * The Original Code is mozilla.org code.
      17                 :  *
      18                 :  * The Initial Developer of the Original Code is
      19                 :  * Netscape Communications Corporation.
      20                 :  * Portions created by the Initial Developer are Copyright (C) 2001
      21                 :  * the Initial Developer. All Rights Reserved.
      22                 :  *
      23                 :  * Contributor(s):
      24                 :  *   Harshal Pradhan <keeda@hotpop.com>
      25                 :  *
      26                 :  * Alternatively, the contents of this file may be used under the terms of
      27                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
      28                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      29                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      30                 :  * of those above. If you wish to allow use of your version of this file only
      31                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      32                 :  * use your version of this file under the terms of the MPL, indicate your
      33                 :  * decision by deleting the provisions above and replace them with the notice
      34                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      35                 :  * the provisions above, a recipient may use your version of this file under
      36                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      37                 :  *
      38                 :  * ***** END LICENSE BLOCK ***** */
      39                 : 
      40                 : //#define USEWEAKREFS // (haven't quite figured that out yet)
      41                 : 
      42                 : #include "nsWindowWatcher.h"
      43                 : #include "nsAutoWindowStateHelper.h"
      44                 : 
      45                 : #include "nsCRT.h"
      46                 : #include "nsNetUtil.h"
      47                 : #include "nsJSUtils.h"
      48                 : #include "plstr.h"
      49                 : 
      50                 : #include "nsIBaseWindow.h"
      51                 : #include "nsIDocShell.h"
      52                 : #include "nsIDocShellLoadInfo.h"
      53                 : #include "nsIDocShellTreeItem.h"
      54                 : #include "nsIDocShellTreeOwner.h"
      55                 : #include "nsIDocumentLoader.h"
      56                 : #include "nsIDocument.h"
      57                 : #include "nsIDOMDocument.h"
      58                 : #include "nsIDOMWindow.h"
      59                 : #include "nsIDOMChromeWindow.h"
      60                 : #include "nsIDOMModalContentWindow.h"
      61                 : #include "nsIPrompt.h"
      62                 : #include "nsIScriptObjectPrincipal.h"
      63                 : #include "nsIScreen.h"
      64                 : #include "nsIScreenManager.h"
      65                 : #include "nsIScriptContext.h"
      66                 : #include "nsIJSContextStack.h"
      67                 : #include "nsIObserverService.h"
      68                 : #include "nsIScriptGlobalObject.h"
      69                 : #include "nsIScriptSecurityManager.h"
      70                 : #include "nsXPCOM.h"
      71                 : #include "nsIURI.h"
      72                 : #include "nsIWebBrowser.h"
      73                 : #include "nsIWebBrowserChrome.h"
      74                 : #include "nsIWebNavigation.h"
      75                 : #include "nsIWindowCreator.h"
      76                 : #include "nsIWindowCreator2.h"
      77                 : #include "nsIXPConnect.h"
      78                 : #include "nsPIDOMWindow.h"
      79                 : #include "nsIMarkupDocumentViewer.h"
      80                 : #include "nsIContentViewer.h"
      81                 : #include "nsIWindowProvider.h"
      82                 : #include "nsIMutableArray.h"
      83                 : #include "nsISupportsArray.h"
      84                 : #include "nsIDOMStorageObsolete.h"
      85                 : #include "nsIDOMStorage.h"
      86                 : #include "nsPIDOMStorage.h"
      87                 : #include "nsIWidget.h"
      88                 : #include "nsFocusManager.h"
      89                 : #include "nsIPresShell.h"
      90                 : #include "nsPresContext.h"
      91                 : #include "nsContentUtils.h"
      92                 : #include "nsIPrefBranch.h"
      93                 : #include "nsIPrefService.h"
      94                 : 
      95                 : #ifdef USEWEAKREFS
      96                 : #include "nsIWeakReference.h"
      97                 : #endif
      98                 : 
      99                 : using namespace mozilla;
     100                 : 
     101                 : static const char *sJSStackContractID="@mozilla.org/js/xpc/ContextStack;1";
     102                 : 
     103                 : /****************************************************************
     104                 :  ******************** nsWatcherWindowEntry **********************
     105                 :  ****************************************************************/
     106                 : 
     107                 : class nsWindowWatcher;
     108                 : 
     109                 : struct nsWatcherWindowEntry {
     110                 : 
     111               0 :   nsWatcherWindowEntry(nsIDOMWindow *inWindow, nsIWebBrowserChrome *inChrome) {
     112                 : #ifdef USEWEAKREFS
     113                 :     mWindow = do_GetWeakReference(inWindow);
     114                 : #else
     115               0 :     mWindow = inWindow;
     116                 : #endif
     117               0 :     nsCOMPtr<nsISupportsWeakReference> supportsweak(do_QueryInterface(inChrome));
     118               0 :     if (supportsweak) {
     119               0 :       supportsweak->GetWeakReference(getter_AddRefs(mChromeWeak));
     120                 :     } else {
     121               0 :       mChrome = inChrome;
     122               0 :       mChromeWeak = 0;
     123                 :     }
     124               0 :     ReferenceSelf();
     125               0 :   }
     126               0 :   ~nsWatcherWindowEntry() {}
     127                 : 
     128                 :   void InsertAfter(nsWatcherWindowEntry *inOlder);
     129                 :   void Unlink();
     130                 :   void ReferenceSelf();
     131                 : 
     132                 : #ifdef USEWEAKREFS
     133                 :   nsCOMPtr<nsIWeakReference> mWindow;
     134                 : #else // still not an owning ref
     135                 :   nsIDOMWindow              *mWindow;
     136                 : #endif
     137                 :   nsIWebBrowserChrome       *mChrome;
     138                 :   nsWeakPtr                  mChromeWeak;
     139                 :   // each struct is in a circular, doubly-linked list
     140                 :   nsWatcherWindowEntry      *mYounger, // next younger in sequence
     141                 :                             *mOlder;
     142                 : };
     143                 : 
     144               0 : void nsWatcherWindowEntry::InsertAfter(nsWatcherWindowEntry *inOlder)
     145                 : {
     146               0 :   if (inOlder) {
     147               0 :     mOlder = inOlder;
     148               0 :     mYounger = inOlder->mYounger;
     149               0 :     mOlder->mYounger = this;
     150               0 :     if (mOlder->mOlder == mOlder)
     151               0 :       mOlder->mOlder = this;
     152               0 :     mYounger->mOlder = this;
     153               0 :     if (mYounger->mYounger == mYounger)
     154               0 :       mYounger->mYounger = this;
     155                 :   }
     156               0 : }
     157                 : 
     158               0 : void nsWatcherWindowEntry::Unlink() {
     159                 : 
     160               0 :   mOlder->mYounger = mYounger;
     161               0 :   mYounger->mOlder = mOlder;
     162               0 :   ReferenceSelf();
     163               0 : }
     164                 : 
     165               0 : void nsWatcherWindowEntry::ReferenceSelf() {
     166                 : 
     167               0 :   mYounger = this;
     168               0 :   mOlder = this;
     169               0 : }
     170                 : 
     171                 : /****************************************************************
     172                 :  ****************** nsWatcherWindowEnumerator *******************
     173                 :  ****************************************************************/
     174                 : 
     175                 : class nsWatcherWindowEnumerator : public nsISimpleEnumerator {
     176                 : 
     177                 : public:
     178                 :   nsWatcherWindowEnumerator(nsWindowWatcher *inWatcher);
     179                 :   virtual ~nsWatcherWindowEnumerator();
     180                 :   NS_IMETHOD HasMoreElements(bool *retval);
     181                 :   NS_IMETHOD GetNext(nsISupports **retval);
     182                 : 
     183                 :   NS_DECL_ISUPPORTS
     184                 : 
     185                 : private:
     186                 :   friend class nsWindowWatcher;
     187                 : 
     188                 :   nsWatcherWindowEntry *FindNext();
     189                 :   void WindowRemoved(nsWatcherWindowEntry *inInfo);
     190                 : 
     191                 :   nsWindowWatcher      *mWindowWatcher;
     192                 :   nsWatcherWindowEntry *mCurrentPosition;
     193                 : };
     194                 : 
     195             560 : NS_IMPL_ADDREF(nsWatcherWindowEnumerator)
     196             560 : NS_IMPL_RELEASE(nsWatcherWindowEnumerator)
     197             560 : NS_IMPL_QUERY_INTERFACE1(nsWatcherWindowEnumerator, nsISimpleEnumerator)
     198                 : 
     199             280 : nsWatcherWindowEnumerator::nsWatcherWindowEnumerator(nsWindowWatcher *inWatcher)
     200                 :   : mWindowWatcher(inWatcher),
     201             280 :     mCurrentPosition(inWatcher->mOldestWindow)
     202                 : {
     203             280 :   mWindowWatcher->AddEnumerator(this);
     204             280 :   mWindowWatcher->AddRef();
     205             280 : }
     206                 : 
     207             560 : nsWatcherWindowEnumerator::~nsWatcherWindowEnumerator()
     208                 : {
     209             280 :   mWindowWatcher->RemoveEnumerator(this);
     210             280 :   mWindowWatcher->Release();
     211            1120 : }
     212                 : 
     213                 : NS_IMETHODIMP
     214               0 : nsWatcherWindowEnumerator::HasMoreElements(bool *retval)
     215                 : {
     216               0 :   if (!retval)
     217               0 :     return NS_ERROR_INVALID_ARG;
     218                 : 
     219               0 :   *retval = mCurrentPosition? true : false;
     220               0 :   return NS_OK;
     221                 : }
     222                 :     
     223                 : NS_IMETHODIMP
     224             280 : nsWatcherWindowEnumerator::GetNext(nsISupports **retval)
     225                 : {
     226             280 :   if (!retval)
     227               0 :     return NS_ERROR_INVALID_ARG;
     228                 : 
     229             280 :   *retval = NULL;
     230                 : 
     231                 : #ifdef USEWEAKREFS
     232                 :   while (mCurrentPosition) {
     233                 :     CallQueryReferent(mCurrentPosition->mWindow, retval);
     234                 :     if (*retval) {
     235                 :       mCurrentPosition = FindNext();
     236                 :       break;
     237                 :     } else // window is gone!
     238                 :       mWindowWatcher->RemoveWindow(mCurrentPosition);
     239                 :   }
     240                 :   NS_IF_ADDREF(*retval);
     241                 : #else
     242             280 :   if (mCurrentPosition) {
     243               0 :     CallQueryInterface(mCurrentPosition->mWindow, retval);
     244               0 :     mCurrentPosition = FindNext();
     245                 :   }
     246                 : #endif
     247             280 :   return NS_OK;
     248                 : }
     249                 : 
     250                 : nsWatcherWindowEntry *
     251               0 : nsWatcherWindowEnumerator::FindNext()
     252                 : {
     253                 :   nsWatcherWindowEntry *info;
     254                 : 
     255               0 :   if (!mCurrentPosition)
     256               0 :     return 0;
     257                 : 
     258               0 :   info = mCurrentPosition->mYounger;
     259               0 :   return info == mWindowWatcher->mOldestWindow ? 0 : info;
     260                 : }
     261                 : 
     262                 : // if a window is being removed adjust the iterator's current position
     263               0 : void nsWatcherWindowEnumerator::WindowRemoved(nsWatcherWindowEntry *inInfo) {
     264                 : 
     265               0 :   if (mCurrentPosition == inInfo)
     266                 :     mCurrentPosition = mCurrentPosition != inInfo->mYounger ?
     267               0 :                        inInfo->mYounger : 0;
     268               0 : }
     269                 : 
     270                 : /****************************************************************
     271                 :  ********************** JSContextAutoPopper *********************
     272                 :  ****************************************************************/
     273                 : 
     274                 : class NS_STACK_CLASS JSContextAutoPopper {
     275                 : public:
     276                 :   JSContextAutoPopper();
     277                 :   ~JSContextAutoPopper();
     278                 : 
     279                 :   nsresult   Push(JSContext *cx = nsnull);
     280               0 :   JSContext *get() { return mContext; }
     281                 : 
     282                 : protected:
     283                 :   nsCOMPtr<nsIThreadJSContextStack>  mService;
     284                 :   JSContext                         *mContext;
     285                 :   nsCOMPtr<nsIScriptContext>         mContextKungFuDeathGrip;
     286                 : };
     287                 : 
     288               0 : JSContextAutoPopper::JSContextAutoPopper() : mContext(nsnull)
     289                 : {
     290               0 : }
     291                 : 
     292               0 : JSContextAutoPopper::~JSContextAutoPopper()
     293                 : {
     294                 :   JSContext *cx;
     295                 :   nsresult   rv;
     296                 : 
     297               0 :   if(mContext) {
     298               0 :     rv = mService->Pop(&cx);
     299               0 :     NS_ASSERTION(NS_SUCCEEDED(rv) && cx == mContext, "JSContext push/pop mismatch");
     300                 :   }
     301               0 : }
     302                 : 
     303               0 : nsresult JSContextAutoPopper::Push(JSContext *cx)
     304                 : {
     305               0 :   if (mContext) // only once
     306               0 :     return NS_ERROR_FAILURE;
     307                 : 
     308               0 :   mService = do_GetService(sJSStackContractID);
     309               0 :   if(mService) {
     310                 :     // Get the safe context if we're not provided one.
     311               0 :     if (!cx && NS_FAILED(mService->GetSafeJSContext(&cx))) {
     312               0 :       cx = nsnull;
     313                 :     }
     314                 : 
     315                 :     // Save cx in mContext to indicate need to pop.
     316               0 :     if (cx && NS_SUCCEEDED(mService->Push(cx))) {
     317               0 :       mContext = cx;
     318               0 :       mContextKungFuDeathGrip = nsJSUtils::GetDynamicScriptContext(cx);
     319                 :     }
     320                 :   }
     321               0 :   return mContext ? NS_OK : NS_ERROR_FAILURE;
     322                 : }
     323                 : 
     324                 : /****************************************************************
     325                 :  *********************** nsWindowWatcher ************************
     326                 :  ****************************************************************/
     327                 : 
     328            1057 : NS_IMPL_ADDREF(nsWindowWatcher)
     329            1057 : NS_IMPL_RELEASE(nsWindowWatcher)
     330             304 : NS_IMPL_QUERY_INTERFACE3(nsWindowWatcher,
     331                 :                          nsIWindowWatcher,
     332                 :                          nsIPromptFactory,
     333                 :                          nsPIWindowWatcher)
     334                 : 
     335             103 : nsWindowWatcher::nsWindowWatcher() :
     336                 :         mEnumeratorList(),
     337                 :         mOldestWindow(0),
     338             103 :         mListLock("nsWindowWatcher.mListLock")
     339                 : {
     340             103 : }
     341                 : 
     342             309 : nsWindowWatcher::~nsWindowWatcher()
     343                 : {
     344                 :   // delete data
     345             206 :   while (mOldestWindow)
     346               0 :     RemoveWindow(mOldestWindow);
     347             412 : }
     348                 : 
     349                 : nsresult
     350             103 : nsWindowWatcher::Init()
     351                 : {
     352             103 :   return NS_OK;
     353                 : }
     354                 : 
     355                 : NS_IMETHODIMP
     356               0 : nsWindowWatcher::OpenWindow(nsIDOMWindow *aParent,
     357                 :                             const char *aUrl,
     358                 :                             const char *aName,
     359                 :                             const char *aFeatures,
     360                 :                             nsISupports *aArguments,
     361                 :                             nsIDOMWindow **_retval)
     362                 : {
     363               0 :   nsCOMPtr<nsIArray> argsArray;
     364               0 :   PRUint32 argc = 0;
     365               0 :   if (aArguments) {
     366                 :     // aArguments is allowed to be either an nsISupportsArray or an nsIArray
     367                 :     // (in which case it is treated as argv) or any other COM object (in which
     368                 :     // case it becomes argv[0]).
     369                 :     nsresult rv;
     370                 : 
     371               0 :     nsCOMPtr<nsISupportsArray> supArray(do_QueryInterface(aArguments));
     372               0 :     if (!supArray) {
     373               0 :       nsCOMPtr<nsIArray> array(do_QueryInterface(aArguments));
     374               0 :       if (!array) {
     375               0 :         nsCOMPtr<nsIMutableArray> muteArray;
     376               0 :         argsArray = muteArray = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
     377               0 :         if (NS_FAILED(rv))
     378               0 :           return rv;
     379               0 :         rv = muteArray->AppendElement(aArguments, false);
     380               0 :         if (NS_FAILED(rv))
     381               0 :           return rv;
     382               0 :         argc = 1;
     383                 :       } else {
     384               0 :         rv = array->GetLength(&argc);
     385               0 :         if (NS_FAILED(rv))
     386               0 :           return rv;
     387               0 :         if (argc > 0)
     388               0 :           argsArray = array;
     389                 :       }
     390                 :     } else {
     391                 :       // nsISupports array - copy into nsIArray...
     392               0 :       rv = supArray->Count(&argc);
     393               0 :       if (NS_FAILED(rv))
     394               0 :         return rv;
     395                 :       // But only create an arguments array if there's at least one element in
     396                 :       // the supports array.
     397               0 :       if (argc > 0) {
     398               0 :         nsCOMPtr<nsIMutableArray> muteArray;
     399               0 :         argsArray = muteArray = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
     400               0 :         if (NS_FAILED(rv))
     401               0 :           return rv;
     402               0 :         for (PRUint32 i = 0; i < argc; i++) {
     403               0 :           nsCOMPtr<nsISupports> elt(dont_AddRef(supArray->ElementAt(i)));
     404               0 :           rv = muteArray->AppendElement(elt, false);
     405               0 :           if (NS_FAILED(rv))
     406               0 :             return rv;
     407                 :         }
     408                 :       }
     409                 :     }
     410                 :   }
     411                 : 
     412               0 :   bool dialog = (argc != 0);
     413                 :   return OpenWindowJSInternal(aParent, aUrl, aName, aFeatures, dialog, 
     414               0 :                               argsArray, false, _retval);
     415                 : }
     416                 : 
     417                 : struct SizeSpec {
     418               0 :   SizeSpec() :
     419                 :     mLeftSpecified(false),
     420                 :     mTopSpecified(false),
     421                 :     mOuterWidthSpecified(false),
     422                 :     mOuterHeightSpecified(false),
     423                 :     mInnerWidthSpecified(false),
     424                 :     mInnerHeightSpecified(false),
     425                 :     mUseDefaultWidth(false),
     426               0 :     mUseDefaultHeight(false)
     427               0 :   {}
     428                 :   
     429                 :   PRInt32 mLeft;
     430                 :   PRInt32 mTop;
     431                 :   PRInt32 mOuterWidth;  // Total window width
     432                 :   PRInt32 mOuterHeight; // Total window height
     433                 :   PRInt32 mInnerWidth;  // Content area width
     434                 :   PRInt32 mInnerHeight; // Content area height
     435                 : 
     436                 :   bool mLeftSpecified;
     437                 :   bool mTopSpecified;
     438                 :   bool mOuterWidthSpecified;
     439                 :   bool mOuterHeightSpecified;
     440                 :   bool mInnerWidthSpecified;
     441                 :   bool mInnerHeightSpecified;
     442                 : 
     443                 :   // If these booleans are true, don't look at the corresponding width values
     444                 :   // even if they're specified -- they'll be bogus
     445                 :   bool mUseDefaultWidth;
     446                 :   bool mUseDefaultHeight;
     447                 : 
     448               0 :   bool PositionSpecified() const {
     449               0 :     return mLeftSpecified || mTopSpecified;
     450                 :   }
     451                 :   
     452               0 :   bool SizeSpecified() const {
     453                 :     return mOuterWidthSpecified || mOuterHeightSpecified ||
     454               0 :       mInnerWidthSpecified || mInnerHeightSpecified;
     455                 :   }
     456                 : };
     457                 : 
     458                 : NS_IMETHODIMP
     459               0 : nsWindowWatcher::OpenWindowJS(nsIDOMWindow *aParent,
     460                 :                               const char *aUrl,
     461                 :                               const char *aName,
     462                 :                               const char *aFeatures,
     463                 :                               bool aDialog,
     464                 :                               nsIArray *argv,
     465                 :                               nsIDOMWindow **_retval)
     466                 : {
     467               0 :   if (argv) {
     468                 :     PRUint32 argc;
     469               0 :     nsresult rv = argv->GetLength(&argc);
     470               0 :     NS_ENSURE_SUCCESS(rv, rv);
     471                 : 
     472                 :     // For compatibility with old code, no arguments implies that we shouldn't
     473                 :     // create an arguments object on the new window at all.
     474               0 :     if (argc == 0)
     475               0 :       argv = nsnull;
     476                 :   }
     477                 : 
     478                 :   return OpenWindowJSInternal(aParent, aUrl, aName, aFeatures, aDialog,
     479               0 :                               argv, true, _retval);
     480                 : }
     481                 : 
     482                 : nsresult
     483               0 : nsWindowWatcher::OpenWindowJSInternal(nsIDOMWindow *aParent,
     484                 :                                       const char *aUrl,
     485                 :                                       const char *aName,
     486                 :                                       const char *aFeatures,
     487                 :                                       bool aDialog,
     488                 :                                       nsIArray *argv,
     489                 :                                       bool aCalledFromJS,
     490                 :                                       nsIDOMWindow **_retval)
     491                 : {
     492               0 :   nsresult                        rv = NS_OK;
     493                 :   bool                            nameSpecified,
     494                 :                                   featuresSpecified,
     495               0 :                                   isNewToplevelWindow = false,
     496               0 :                                   windowIsNew = false,
     497               0 :                                   windowNeedsName = false,
     498               0 :                                   windowIsModal = false,
     499               0 :                                   uriToLoadIsChrome = false,
     500               0 :                                   windowIsModalContentDialog = false;
     501                 :   PRUint32                        chromeFlags;
     502               0 :   nsAutoString                    name;             // string version of aName
     503               0 :   nsCAutoString                   features;         // string version of aFeatures
     504               0 :   nsCOMPtr<nsIURI>                uriToLoad;        // from aUrl, if any
     505               0 :   nsCOMPtr<nsIDocShellTreeOwner>  parentTreeOwner;  // from the parent window, if any
     506               0 :   nsCOMPtr<nsIDocShellTreeItem>   newDocShellItem;  // from the new window
     507               0 :   JSContextAutoPopper             callerContextGuard;
     508                 : 
     509               0 :   NS_ENSURE_ARG_POINTER(_retval);
     510               0 :   *_retval = 0;
     511                 : 
     512               0 :   if (!nsContentUtils::IsSafeToRunScript()) {
     513               0 :     return NS_ERROR_FAILURE;
     514                 :   }
     515                 : 
     516               0 :   GetWindowTreeOwner(aParent, getter_AddRefs(parentTreeOwner));
     517                 : 
     518               0 :   if (aUrl) {
     519               0 :     rv = URIfromURL(aUrl, aParent, getter_AddRefs(uriToLoad));
     520               0 :     if (NS_FAILED(rv))
     521               0 :       return rv;
     522               0 :     uriToLoad->SchemeIs("chrome", &uriToLoadIsChrome);
     523                 :   }
     524                 : 
     525               0 :   nameSpecified = false;
     526               0 :   if (aName) {
     527               0 :     CopyUTF8toUTF16(aName, name);
     528               0 :     nameSpecified = true;
     529                 :   }
     530                 : 
     531               0 :   featuresSpecified = false;
     532               0 :   if (aFeatures) {
     533               0 :     features.Assign(aFeatures);
     534               0 :     featuresSpecified = true;
     535               0 :     features.StripWhitespace();
     536                 :   }
     537                 : 
     538                 :   // try to find an extant window with the given name
     539               0 :   nsCOMPtr<nsIDOMWindow> foundWindow;
     540               0 :   SafeGetWindowByName(name, aParent, getter_AddRefs(foundWindow));
     541               0 :   GetWindowTreeItem(foundWindow, getter_AddRefs(newDocShellItem));
     542                 : 
     543                 :   // no extant window? make a new one.
     544                 : 
     545                 :   // If no parent, consider it chrome.
     546               0 :   bool hasChromeParent = true;
     547               0 :   if (aParent) {
     548                 :     // Check if the parent document has chrome privileges.
     549               0 :     nsCOMPtr<nsIDOMDocument> domdoc;
     550               0 :     aParent->GetDocument(getter_AddRefs(domdoc));
     551               0 :     nsCOMPtr<nsIDocument> doc = do_QueryInterface(domdoc);
     552               0 :     hasChromeParent = doc && nsContentUtils::IsChromeDoc(doc);
     553                 :   }
     554                 : 
     555                 :   // Make sure we call CalculateChromeFlags() *before* we push the
     556                 :   // callee context onto the context stack so that
     557                 :   // CalculateChromeFlags() sees the actual caller when doing its
     558                 :   // security checks.
     559                 :   chromeFlags = CalculateChromeFlags(features.get(), featuresSpecified,
     560                 :                                      aDialog, uriToLoadIsChrome,
     561               0 :                                      hasChromeParent);
     562                 : 
     563                 :   // If we're not called through our JS version of the API, and we got
     564                 :   // our internal modal option, treat the window we're opening as a
     565                 :   // modal content window (and set the modal chrome flag).
     566               0 :   if (!aCalledFromJS && argv &&
     567               0 :       WinHasOption(features.get(), "-moz-internal-modal", 0, nsnull)) {
     568               0 :     windowIsModalContentDialog = true;
     569                 : 
     570               0 :     chromeFlags |= nsIWebBrowserChrome::CHROME_MODAL;
     571                 :   }
     572                 : 
     573               0 :   SizeSpec sizeSpec;
     574               0 :   CalcSizeSpec(features.get(), sizeSpec);
     575                 : 
     576                 :   nsCOMPtr<nsIScriptSecurityManager>
     577               0 :     sm(do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID));
     578                 : 
     579               0 :   NS_ENSURE_TRUE(sm, NS_ERROR_FAILURE);
     580                 : 
     581                 :   // Remember who's calling us. This code used to assume a null
     582                 :   // subject principal if it failed to get the principal, but that's
     583                 :   // just not safe, so bail on errors here.
     584               0 :   nsCOMPtr<nsIPrincipal> callerPrincipal;
     585               0 :   rv = sm->GetSubjectPrincipal(getter_AddRefs(callerPrincipal));
     586               0 :   NS_ENSURE_SUCCESS(rv, rv);
     587                 : 
     588               0 :   bool isCallerChrome = true;
     589               0 :   if (callerPrincipal) {
     590               0 :     rv = sm->IsSystemPrincipal(callerPrincipal, &isCallerChrome);
     591               0 :     NS_ENSURE_SUCCESS(rv, rv);
     592                 :   }
     593                 : 
     594               0 :   JSContext *cx = GetJSContextFromWindow(aParent);
     595                 : 
     596               0 :   if (isCallerChrome && !hasChromeParent && cx) {
     597                 :     // open() is called from chrome on a non-chrome window, push
     598                 :     // the context of the callee onto the context stack to
     599                 :     // prevent the caller's priveleges from leaking into code
     600                 :     // that runs while opening the new window.
     601                 : 
     602               0 :     callerContextGuard.Push(cx);
     603                 :   }
     604                 : 
     605               0 :   if (!newDocShellItem) {
     606                 :     // We're going to either open up a new window ourselves or ask a
     607                 :     // nsIWindowProvider for one.  In either case, we'll want to set the right
     608                 :     // name on it.
     609               0 :     windowNeedsName = true;
     610                 : 
     611                 :     // Now check whether it's ok to ask a window provider for a window.  Don't
     612                 :     // do it if we're opening a dialog or if our parent is a chrome window or
     613                 :     // if we're opening something that has modal, dialog, or chrome flags set.
     614               0 :     nsCOMPtr<nsIDOMChromeWindow> chromeWin = do_QueryInterface(aParent);
     615               0 :     if (!aDialog && !chromeWin &&
     616                 :         !(chromeFlags & (nsIWebBrowserChrome::CHROME_MODAL         |
     617                 :                          nsIWebBrowserChrome::CHROME_OPENAS_DIALOG | 
     618               0 :                          nsIWebBrowserChrome::CHROME_OPENAS_CHROME))) {
     619               0 :       nsCOMPtr<nsIWindowProvider> provider = do_GetInterface(parentTreeOwner);
     620               0 :       if (provider) {
     621               0 :         NS_ASSERTION(aParent, "We've _got_ to have a parent here!");
     622                 : 
     623               0 :         nsCOMPtr<nsIDOMWindow> newWindow;
     624               0 :         rv = provider->ProvideWindow(aParent, chromeFlags, aCalledFromJS,
     625               0 :                                      sizeSpec.PositionSpecified(),
     626               0 :                                      sizeSpec.SizeSpecified(),
     627                 :                                      uriToLoad, name, features, &windowIsNew,
     628               0 :                                      getter_AddRefs(newWindow));
     629               0 :         if (NS_SUCCEEDED(rv)) {
     630               0 :           GetWindowTreeItem(newWindow, getter_AddRefs(newDocShellItem));
     631               0 :           if (windowIsNew && newDocShellItem) {
     632                 :             // Make sure to stop any loads happening in this window that the
     633                 :             // window provider might have started.  Otherwise if our caller
     634                 :             // manipulates the window it just opened and then the load
     635                 :             // completes their stuff will get blown away.
     636                 :             nsCOMPtr<nsIWebNavigation> webNav =
     637               0 :               do_QueryInterface(newDocShellItem);
     638               0 :             webNav->Stop(nsIWebNavigation::STOP_NETWORK);
     639                 :           }
     640                 :         }
     641                 :       }
     642                 :     }
     643                 :   }
     644                 :   
     645               0 :   bool newWindowShouldBeModal = false;
     646               0 :   bool parentIsModal = false;
     647               0 :   if (!newDocShellItem) {
     648               0 :     windowIsNew = true;
     649               0 :     isNewToplevelWindow = true;
     650                 : 
     651               0 :     nsCOMPtr<nsIWebBrowserChrome> parentChrome(do_GetInterface(parentTreeOwner));
     652                 : 
     653                 :     // is the parent (if any) modal? if so, we must be, too.
     654               0 :     bool weAreModal = (chromeFlags & nsIWebBrowserChrome::CHROME_MODAL) != 0;
     655               0 :     newWindowShouldBeModal = weAreModal;
     656               0 :     if (!weAreModal && parentChrome) {
     657               0 :       parentChrome->IsWindowModal(&weAreModal);
     658               0 :       parentIsModal = weAreModal;
     659                 :     }
     660                 : 
     661               0 :     if (weAreModal) {
     662               0 :       windowIsModal = true;
     663                 :       // in case we added this because weAreModal
     664                 :       chromeFlags |= nsIWebBrowserChrome::CHROME_MODAL |
     665               0 :         nsIWebBrowserChrome::CHROME_DEPENDENT;
     666                 :     }
     667                 : 
     668                 :     // Make sure to not create modal windows if our parent is invisible and
     669                 :     // isn't a chrome window.  Otherwise we can end up in a bizarre situation
     670                 :     // where we can't shut down because an invisible window is open.  If
     671                 :     // someone tries to do this, throw.
     672               0 :     if (!hasChromeParent && (chromeFlags & nsIWebBrowserChrome::CHROME_MODAL)) {
     673               0 :       bool parentVisible = true;
     674               0 :       nsCOMPtr<nsIBaseWindow> parentWindow(do_GetInterface(parentTreeOwner));
     675               0 :       nsCOMPtr<nsIWidget> parentWidget;
     676               0 :       if (parentWindow)
     677               0 :         parentWindow->GetMainWidget(getter_AddRefs(parentWidget));
     678               0 :       if (parentWidget)
     679               0 :         parentWidget->IsVisible(parentVisible);
     680               0 :       if (!parentVisible) {
     681               0 :         return NS_ERROR_NOT_AVAILABLE;
     682                 :       }
     683                 :     }
     684                 : 
     685               0 :     NS_ASSERTION(mWindowCreator,
     686                 :                  "attempted to open a new window with no WindowCreator");
     687               0 :     rv = NS_ERROR_FAILURE;
     688               0 :     if (mWindowCreator) {
     689               0 :       nsCOMPtr<nsIWebBrowserChrome> newChrome;
     690                 : 
     691                 :       /* If the window creator is an nsIWindowCreator2, we can give it
     692                 :          some hints. The only hint at this time is whether the opening window
     693                 :          is in a situation that's likely to mean this is an unrequested
     694                 :          popup window we're creating. However we're not completely honest:
     695                 :          we clear that indicator if the opener is chrome, so that the
     696                 :          downstream consumer can treat the indicator to mean simply
     697                 :          that the new window is subject to popup control. */
     698               0 :       nsCOMPtr<nsIWindowCreator2> windowCreator2(do_QueryInterface(mWindowCreator));
     699               0 :       if (windowCreator2) {
     700               0 :         PRUint32 contextFlags = 0;
     701               0 :         bool popupConditions = false;
     702                 : 
     703                 :         // is the parent under popup conditions?
     704               0 :         nsCOMPtr<nsPIDOMWindow> piWindow(do_QueryInterface(aParent));
     705               0 :         if (piWindow)
     706               0 :           popupConditions = piWindow->IsLoadingOrRunningTimeout();
     707                 : 
     708                 :         // chrome is always allowed, so clear the flag if the opener is chrome
     709               0 :         if (popupConditions) {
     710               0 :           popupConditions = !isCallerChrome;
     711                 :         }
     712                 : 
     713               0 :         if (popupConditions)
     714               0 :           contextFlags |= nsIWindowCreator2::PARENT_IS_LOADING_OR_RUNNING_TIMEOUT;
     715                 : 
     716               0 :         bool cancel = false;
     717               0 :         rv = windowCreator2->CreateChromeWindow2(parentChrome, chromeFlags,
     718                 :                                                  contextFlags, uriToLoad,
     719                 :                                                  &cancel,
     720               0 :                                                  getter_AddRefs(newChrome));
     721               0 :         if (NS_SUCCEEDED(rv) && cancel) {
     722               0 :           newChrome = 0; // just in case
     723               0 :           rv = NS_ERROR_ABORT;
     724                 :         }
     725                 :       }
     726                 :       else
     727               0 :         rv = mWindowCreator->CreateChromeWindow(parentChrome, chromeFlags,
     728               0 :                                                 getter_AddRefs(newChrome));
     729               0 :       if (newChrome) {
     730                 :         /* It might be a chrome nsXULWindow, in which case it won't have
     731                 :             an nsIDOMWindow (primary content shell). But in that case, it'll
     732                 :             be able to hand over an nsIDocShellTreeItem directly. */
     733               0 :         nsCOMPtr<nsIDOMWindow> newWindow(do_GetInterface(newChrome));
     734               0 :         if (newWindow)
     735               0 :           GetWindowTreeItem(newWindow, getter_AddRefs(newDocShellItem));
     736               0 :         if (!newDocShellItem)
     737               0 :           newDocShellItem = do_GetInterface(newChrome);
     738               0 :         if (!newDocShellItem)
     739               0 :           rv = NS_ERROR_FAILURE;
     740                 :       }
     741                 :     }
     742                 :   }
     743                 : 
     744                 :   // better have a window to use by this point
     745               0 :   if (!newDocShellItem)
     746               0 :     return rv;
     747                 : 
     748               0 :   nsCOMPtr<nsIDocShell> newDocShell(do_QueryInterface(newDocShellItem));
     749               0 :   NS_ENSURE_TRUE(newDocShell, NS_ERROR_UNEXPECTED);
     750                 :   
     751               0 :   rv = ReadyOpenedDocShellItem(newDocShellItem, aParent, windowIsNew, _retval);
     752               0 :   if (NS_FAILED(rv))
     753               0 :     return rv;
     754                 : 
     755                 :   /* disable persistence of size/position in popups (determined by
     756                 :      determining whether the features parameter specifies width or height
     757                 :      in any way). We consider any overriding of the window's size or position
     758                 :      in the open call as disabling persistence of those attributes.
     759                 :      Popup windows (which should not persist size or position) generally set
     760                 :      the size. */
     761               0 :   if (isNewToplevelWindow) {
     762                 :     /* at the moment, the strings "height=" or "width=" never happen
     763                 :        outside a size specification, so we can do this the Q&D way. */
     764                 : 
     765               0 :     if (PL_strcasestr(features.get(), "width=") || PL_strcasestr(features.get(), "height=")) {
     766                 : 
     767               0 :       nsCOMPtr<nsIDocShellTreeOwner> newTreeOwner;
     768               0 :       newDocShellItem->GetTreeOwner(getter_AddRefs(newTreeOwner));
     769               0 :       if (newTreeOwner)
     770               0 :         newTreeOwner->SetPersistence(false, false, false);
     771                 :     }
     772                 :   }
     773                 : 
     774               0 :   if ((aDialog || windowIsModalContentDialog) && argv) {
     775                 :     // Set the args on the new window.
     776               0 :     nsCOMPtr<nsPIDOMWindow> piwin(do_QueryInterface(*_retval));
     777               0 :     NS_ENSURE_TRUE(piwin, NS_ERROR_UNEXPECTED);
     778                 : 
     779               0 :     rv = piwin->SetArguments(argv, callerPrincipal);
     780               0 :     NS_ENSURE_SUCCESS(rv, rv);
     781                 :   }
     782                 : 
     783                 :   /* allow a window that we found by name to keep its name (important for cases
     784                 :      like _self where the given name is different (and invalid)).  Also, _blank
     785                 :      is not a window name. */
     786               0 :   if (windowNeedsName)
     787               0 :     newDocShellItem->SetName(nameSpecified &&
     788               0 :                              !name.LowerCaseEqualsLiteral("_blank") ?
     789               0 :                              name.get() : nsnull);
     790                 : 
     791                 : 
     792                 :   // Inherit the right character set into the new window to use as a fallback
     793                 :   // in the event the document being loaded does not specify a charset.  When
     794                 :   // aCalledFromJS is true, we want to use the character set of the document in
     795                 :   // the caller; otherwise we want to use the character set of aParent's
     796                 :   // docshell. Failing to set this charset is not fatal, so we want to continue
     797                 :   // in the face of errors.
     798               0 :   nsCOMPtr<nsIContentViewer> newCV;
     799               0 :   newDocShell->GetContentViewer(getter_AddRefs(newCV));
     800               0 :   nsCOMPtr<nsIMarkupDocumentViewer> newMuCV = do_QueryInterface(newCV);
     801               0 :   if (newMuCV) {
     802               0 :     nsCOMPtr<nsIDocShellTreeItem> parentItem;
     803               0 :     GetWindowTreeItem(aParent, getter_AddRefs(parentItem));
     804                 : 
     805               0 :     if (aCalledFromJS) {
     806               0 :       nsCOMPtr<nsIDocShellTreeItem> callerItem = GetCallerTreeItem(parentItem);
     807               0 :       nsCOMPtr<nsPIDOMWindow> callerWin = do_GetInterface(callerItem);
     808               0 :       if (callerWin) {
     809                 :         nsCOMPtr<nsIDocument> doc =
     810               0 :           do_QueryInterface(callerWin->GetExtantDocument());
     811               0 :         if (doc) {
     812               0 :           newMuCV->SetDefaultCharacterSet(doc->GetDocumentCharacterSet());
     813                 :         }
     814                 :       }
     815                 :     }
     816                 :     else {
     817               0 :       nsCOMPtr<nsIDocShell> parentDocshell = do_QueryInterface(parentItem);
     818                 :       // parentDocshell may be null if the parent got closed in the meantime
     819               0 :       if (parentDocshell) {
     820               0 :         nsCOMPtr<nsIContentViewer> parentCV;
     821               0 :         parentDocshell->GetContentViewer(getter_AddRefs(parentCV));
     822                 :         nsCOMPtr<nsIMarkupDocumentViewer> parentMuCV =
     823               0 :           do_QueryInterface(parentCV);
     824               0 :         if (parentMuCV) {
     825               0 :           nsCAutoString charset;
     826               0 :           nsresult res = parentMuCV->GetDefaultCharacterSet(charset);
     827               0 :           if (NS_SUCCEEDED(res)) {
     828               0 :             newMuCV->SetDefaultCharacterSet(charset);
     829                 :           }
     830               0 :           res = parentMuCV->GetPrevDocCharacterSet(charset);
     831               0 :           if (NS_SUCCEEDED(res)) {
     832               0 :             newMuCV->SetPrevDocCharacterSet(charset);
     833                 :           }
     834                 :         }
     835                 :       }
     836                 :     }
     837                 :   }
     838                 : 
     839               0 :   if (isNewToplevelWindow) {
     840                 :     // Notify observers that the window is open and ready.
     841                 :     // The window has not yet started to load a document.
     842                 :     nsCOMPtr<nsIObserverService> obsSvc =
     843               0 :       mozilla::services::GetObserverService();
     844               0 :     if (obsSvc)
     845               0 :       obsSvc->NotifyObservers(*_retval, "toplevel-window-ready", nsnull);
     846                 :   }
     847                 : 
     848                 :   // Now we have to set the right opener principal on the new window.  Note
     849                 :   // that we have to do this _before_ starting any URI loads, thanks to the
     850                 :   // sync nature of javascript: loads.  Since this is the only place where we
     851                 :   // set said opener principal, we need to do it for all URIs, including
     852                 :   // chrome ones.  So to deal with the mess that is bug 79775, just press on in
     853                 :   // a reasonable way even if GetSubjectPrincipal fails.  In that case, just
     854                 :   // use a null subjectPrincipal.
     855               0 :   nsCOMPtr<nsIPrincipal> subjectPrincipal;
     856               0 :   if (NS_FAILED(sm->GetSubjectPrincipal(getter_AddRefs(subjectPrincipal)))) {
     857               0 :     subjectPrincipal = nsnull;
     858                 :   }
     859                 : 
     860               0 :   if (windowIsNew) {
     861                 :     // Now set the opener principal on the new window.  Note that we need to do
     862                 :     // this no matter whether we were opened from JS; if there is nothing on
     863                 :     // the JS stack, just use the principal of our parent window.  In those
     864                 :     // cases we do _not_ set the parent window principal as the owner of the
     865                 :     // load--since we really don't know who the owner is, just leave it null.
     866               0 :     nsIPrincipal* newWindowPrincipal = subjectPrincipal;
     867               0 :     if (!newWindowPrincipal && aParent) {
     868               0 :       nsCOMPtr<nsIScriptObjectPrincipal> sop(do_QueryInterface(aParent));
     869               0 :       if (sop) {
     870               0 :         newWindowPrincipal = sop->GetPrincipal();
     871                 :       }
     872                 :     }
     873                 : 
     874                 :     bool isSystem;
     875               0 :     rv = sm->IsSystemPrincipal(newWindowPrincipal, &isSystem);
     876               0 :     if (NS_FAILED(rv) || isSystem) {
     877                 :       // Don't pass this principal along to content windows
     878                 :       PRInt32 itemType;
     879               0 :       rv = newDocShellItem->GetItemType(&itemType);
     880               0 :       if (NS_FAILED(rv) || itemType != nsIDocShellTreeItem::typeChrome) {
     881               0 :         newWindowPrincipal = nsnull;        
     882                 :       }
     883                 :     }
     884                 : 
     885               0 :     nsCOMPtr<nsPIDOMWindow> newWindow = do_QueryInterface(*_retval);
     886                 : #ifdef DEBUG
     887               0 :     nsCOMPtr<nsPIDOMWindow> newDebugWindow = do_GetInterface(newDocShell);
     888               0 :     NS_ASSERTION(newWindow == newDebugWindow, "Different windows??");
     889                 : #endif
     890               0 :     if (newWindow) {
     891               0 :       newWindow->SetOpenerScriptPrincipal(newWindowPrincipal);
     892                 :     }
     893                 :   }
     894                 : 
     895               0 :   if (uriToLoad) { // get the script principal and pass it to docshell
     896               0 :     JSContextAutoPopper contextGuard;
     897                 : 
     898               0 :     cx = GetJSContextFromCallStack();
     899                 : 
     900                 :     // get the security manager
     901               0 :     if (!cx)
     902               0 :       cx = GetJSContextFromWindow(aParent);
     903               0 :     if (!cx) {
     904               0 :       rv = contextGuard.Push();
     905               0 :       if (NS_FAILED(rv))
     906               0 :         return rv;
     907               0 :       cx = contextGuard.get();
     908                 :     }
     909                 : 
     910               0 :     nsCOMPtr<nsIDocShellLoadInfo> loadInfo;
     911               0 :     newDocShell->CreateLoadInfo(getter_AddRefs(loadInfo));
     912               0 :     NS_ENSURE_TRUE(loadInfo, NS_ERROR_FAILURE);
     913                 : 
     914               0 :     if (subjectPrincipal) {
     915               0 :       loadInfo->SetOwner(subjectPrincipal);
     916                 :     }
     917                 : 
     918                 :     // Set the new window's referrer from the calling context's document:
     919                 : 
     920                 :     // get the calling context off the JS context stack
     921               0 :     nsCOMPtr<nsIJSContextStack> stack = do_GetService(sJSStackContractID);
     922                 : 
     923               0 :     JSContext* ccx = nsnull;
     924                 : 
     925                 :     // get its document, if any
     926               0 :     if (stack && NS_SUCCEEDED(stack->Peek(&ccx)) && ccx) {
     927               0 :       nsIScriptGlobalObject *sgo = nsJSUtils::GetDynamicScriptGlobal(ccx);
     928                 : 
     929               0 :       nsCOMPtr<nsPIDOMWindow> w(do_QueryInterface(sgo));
     930               0 :       if (w) {
     931                 :         /* use the URL from the *extant* document, if any. The usual accessor
     932                 :            GetDocument will synchronously create an about:blank document if
     933                 :            it has no better answer, and we only care about a real document.
     934                 :            Also using GetDocument to force document creation seems to
     935                 :            screw up focus in the hidden window; see bug 36016.
     936                 :         */
     937               0 :         nsCOMPtr<nsIDocument> doc(do_QueryInterface(w->GetExtantDocument()));
     938               0 :         if (doc) { 
     939                 :           // Set the referrer
     940               0 :           loadInfo->SetReferrer(doc->GetDocumentURI());
     941                 :         }
     942                 :       }
     943                 :     }
     944                 : 
     945               0 :     newDocShell->LoadURI(uriToLoad,
     946                 :                          loadInfo,
     947                 :                          windowIsNew
     948                 :                            ? static_cast<PRUint32>(nsIWebNavigation::LOAD_FLAGS_FIRST_LOAD)
     949                 :                            : static_cast<PRUint32>(nsIWebNavigation::LOAD_FLAGS_NONE),
     950               0 :                          true);
     951                 :   }
     952                 : 
     953                 :   // Copy the current session storage for the current domain.
     954               0 :   nsCOMPtr<nsPIDOMWindow> piWindow = do_QueryInterface(aParent);
     955               0 :   nsIDocShell* parentDocShell = nsnull;
     956               0 :   if (piWindow)
     957               0 :     parentDocShell = piWindow->GetDocShell();
     958                 : 
     959               0 :   if (subjectPrincipal && parentDocShell) {
     960               0 :     nsCOMPtr<nsIDOMStorage> storage;
     961                 :     parentDocShell->GetSessionStorageForPrincipal(subjectPrincipal,
     962               0 :                                                   EmptyString(), false,
     963               0 :                                                   getter_AddRefs(storage));
     964                 :     nsCOMPtr<nsPIDOMStorage> piStorage =
     965               0 :       do_QueryInterface(storage);
     966               0 :     if (piStorage){
     967               0 :       storage = piStorage->Clone();
     968               0 :       newDocShell->AddSessionStorage(
     969               0 :         piStorage->Principal(),
     970               0 :         storage);
     971                 :     }
     972                 :   }
     973                 : 
     974               0 :   if (isNewToplevelWindow)
     975               0 :     SizeOpenedDocShellItem(newDocShellItem, aParent, sizeSpec);
     976                 : 
     977                 :   // XXXbz isn't windowIsModal always true when windowIsModalContentDialog?
     978               0 :   if (windowIsModal || windowIsModalContentDialog) {
     979               0 :     nsCOMPtr<nsIDocShellTreeOwner> newTreeOwner;
     980               0 :     newDocShellItem->GetTreeOwner(getter_AddRefs(newTreeOwner));
     981               0 :     nsCOMPtr<nsIWebBrowserChrome> newChrome(do_GetInterface(newTreeOwner));
     982                 : 
     983                 :     // Throw an exception here if no web browser chrome is available,
     984                 :     // we need that to show a modal window.
     985               0 :     NS_ENSURE_TRUE(newChrome, NS_ERROR_NOT_AVAILABLE);
     986                 : 
     987               0 :     nsCOMPtr<nsPIDOMWindow> modalContentWindow;
     988                 : 
     989                 :     // Dispatch dialog events etc, but we only want to do that if
     990                 :     // we're opening a modal content window (the helper classes are
     991                 :     // no-ops if given no window), for chrome dialogs we don't want to
     992                 :     // do any of that (it's done elsewhere for us).
     993                 : 
     994               0 :     if (windowIsModalContentDialog) {
     995               0 :       modalContentWindow = do_QueryInterface(*_retval);
     996                 :     }
     997                 : 
     998               0 :     nsAutoWindowStateHelper windowStateHelper(aParent);
     999                 : 
    1000               0 :     if (!windowStateHelper.DefaultEnabled()) {
    1001                 :       // Default to cancel not opening the modal window.
    1002               0 :       NS_RELEASE(*_retval);
    1003                 : 
    1004               0 :       return NS_OK;
    1005                 :     }
    1006                 : 
    1007                 :         
    1008               0 :     if (!newWindowShouldBeModal && parentIsModal) {
    1009               0 :       nsCOMPtr<nsIBaseWindow> parentWindow(do_GetInterface(newTreeOwner));
    1010               0 :       if (parentWindow) {
    1011               0 :         nsCOMPtr<nsIWidget> parentWidget;
    1012               0 :         parentWindow->GetMainWidget(getter_AddRefs(parentWidget));
    1013               0 :         if (parentWidget) {
    1014               0 :           parentWidget->SetModal(true);
    1015                 :         }
    1016               0 :       }
    1017                 :     } else { 
    1018                 :       // Reset popup state while opening a modal dialog, and firing
    1019                 :       // events about the dialog, to prevent the current state from
    1020                 :       // being active the whole time a modal dialog is open.
    1021               0 :       nsAutoPopupStatePusher popupStatePusher(modalContentWindow, openAbused);
    1022                 :   
    1023               0 :       newChrome->ShowAsModal();
    1024                 :     }
    1025                 :   }
    1026                 : 
    1027               0 :   return NS_OK;
    1028                 : }
    1029                 : 
    1030                 : NS_IMETHODIMP
    1031               0 : nsWindowWatcher::RegisterNotification(nsIObserver *aObserver)
    1032                 : {
    1033                 :   // just a convenience method; it delegates to nsIObserverService
    1034                 : 
    1035               0 :   if (!aObserver)
    1036               0 :     return NS_ERROR_INVALID_ARG;
    1037                 :   
    1038               0 :   nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
    1039               0 :   if (!os)
    1040               0 :     return NS_ERROR_FAILURE;
    1041                 : 
    1042               0 :   nsresult rv = os->AddObserver(aObserver, "domwindowopened", false);
    1043               0 :   if (NS_SUCCEEDED(rv))
    1044               0 :     rv = os->AddObserver(aObserver, "domwindowclosed", false);
    1045                 : 
    1046               0 :   return rv;
    1047                 : }
    1048                 : 
    1049                 : NS_IMETHODIMP
    1050               0 : nsWindowWatcher::UnregisterNotification(nsIObserver *aObserver)
    1051                 : {
    1052                 :   // just a convenience method; it delegates to nsIObserverService
    1053                 : 
    1054               0 :   if (!aObserver)
    1055               0 :     return NS_ERROR_INVALID_ARG;
    1056                 :   
    1057               0 :   nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
    1058               0 :   if (!os)
    1059               0 :     return NS_ERROR_FAILURE;
    1060                 : 
    1061               0 :   os->RemoveObserver(aObserver, "domwindowopened");
    1062               0 :   os->RemoveObserver(aObserver, "domwindowclosed");
    1063                 : 
    1064               0 :   return NS_OK;
    1065                 : }
    1066                 : 
    1067                 : NS_IMETHODIMP
    1068             280 : nsWindowWatcher::GetWindowEnumerator(nsISimpleEnumerator** _retval)
    1069                 : {
    1070             280 :   if (!_retval)
    1071               0 :     return NS_ERROR_INVALID_ARG;
    1072                 : 
    1073             560 :   MutexAutoLock lock(mListLock);
    1074             280 :   nsWatcherWindowEnumerator *enumerator = new nsWatcherWindowEnumerator(this);
    1075             280 :   if (enumerator)
    1076             280 :     return CallQueryInterface(enumerator, _retval);
    1077                 : 
    1078               0 :   return NS_ERROR_OUT_OF_MEMORY;
    1079                 : }
    1080                 :     
    1081                 : NS_IMETHODIMP
    1082               1 : nsWindowWatcher::GetNewPrompter(nsIDOMWindow *aParent, nsIPrompt **_retval)
    1083                 : {
    1084                 :   // This is for backwards compat only. Callers should just use the prompt service directly.
    1085                 :   nsresult rv;
    1086               2 :   nsCOMPtr<nsIPromptFactory> factory = do_GetService("@mozilla.org/prompter;1", &rv);
    1087               1 :   NS_ENSURE_SUCCESS(rv, rv);
    1088               1 :   return factory->GetPrompt(aParent, NS_GET_IID(nsIPrompt), reinterpret_cast<void**>(_retval));
    1089                 : }
    1090                 : 
    1091                 : NS_IMETHODIMP
    1092               1 : nsWindowWatcher::GetNewAuthPrompter(nsIDOMWindow *aParent, nsIAuthPrompt **_retval)
    1093                 : {
    1094                 :   // This is for backwards compat only. Callers should just use the prompt service directly.
    1095                 :   nsresult rv;
    1096               2 :   nsCOMPtr<nsIPromptFactory> factory = do_GetService("@mozilla.org/prompter;1", &rv);
    1097               1 :   NS_ENSURE_SUCCESS(rv, rv);
    1098               1 :   return factory->GetPrompt(aParent, NS_GET_IID(nsIAuthPrompt), reinterpret_cast<void**>(_retval));
    1099                 : }
    1100                 : 
    1101                 : NS_IMETHODIMP
    1102               5 : nsWindowWatcher::GetPrompt(nsIDOMWindow *aParent, const nsIID& aIID,
    1103                 :                            void **_retval)
    1104                 : {
    1105                 :   // This is for backwards compat only. Callers should just use the prompt service directly.
    1106                 :   nsresult rv;
    1107              10 :   nsCOMPtr<nsIPromptFactory> factory = do_GetService("@mozilla.org/prompter;1", &rv);
    1108               5 :   NS_ENSURE_SUCCESS(rv, rv);
    1109               5 :   rv = factory->GetPrompt(aParent, aIID, _retval);
    1110                 : 
    1111                 :   // Allow for an embedding implementation to not support nsIAuthPrompt2.
    1112               5 :   if (rv == NS_NOINTERFACE && aIID.Equals(NS_GET_IID(nsIAuthPrompt2))) {
    1113               0 :     nsCOMPtr<nsIAuthPrompt> oldPrompt;
    1114               0 :     rv = factory->GetPrompt(aParent,
    1115                 :                             NS_GET_IID(nsIAuthPrompt),
    1116               0 :                             getter_AddRefs(oldPrompt));
    1117               0 :     NS_ENSURE_SUCCESS(rv, rv);
    1118                 : 
    1119               0 :     NS_WrapAuthPrompt(oldPrompt, reinterpret_cast<nsIAuthPrompt2**>(_retval));
    1120               0 :     if (!*_retval)
    1121               0 :       rv = NS_ERROR_NOT_AVAILABLE;
    1122                 :   }
    1123               5 :   return rv;
    1124                 : }
    1125                 : 
    1126                 : NS_IMETHODIMP
    1127               0 : nsWindowWatcher::SetWindowCreator(nsIWindowCreator *creator)
    1128                 : {
    1129               0 :   mWindowCreator = creator; // it's an nsCOMPtr, so this is an ownership ref
    1130               0 :   return NS_OK;
    1131                 : }
    1132                 : 
    1133                 : NS_IMETHODIMP
    1134               0 : nsWindowWatcher::GetActiveWindow(nsIDOMWindow **aActiveWindow)
    1135                 : {
    1136               0 :   *aActiveWindow = nsnull;
    1137               0 :   nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID);
    1138               0 :   if (fm)
    1139               0 :     return fm->GetActiveWindow(aActiveWindow);
    1140               0 :   return NS_OK;
    1141                 : }
    1142                 : 
    1143                 : NS_IMETHODIMP
    1144               0 : nsWindowWatcher::SetActiveWindow(nsIDOMWindow *aActiveWindow)
    1145                 : {
    1146               0 :   nsCOMPtr<nsIFocusManager> fm = do_GetService(FOCUSMANAGER_CONTRACTID);
    1147               0 :   if (fm)
    1148               0 :     return fm->SetActiveWindow(aActiveWindow);
    1149               0 :   return NS_OK;
    1150                 : }
    1151                 : 
    1152                 : NS_IMETHODIMP
    1153               0 : nsWindowWatcher::AddWindow(nsIDOMWindow *aWindow, nsIWebBrowserChrome *aChrome)
    1154                 : {
    1155               0 :   if (!aWindow)
    1156               0 :     return NS_ERROR_INVALID_ARG;
    1157                 : 
    1158                 : #ifdef DEBUG
    1159                 :   {
    1160               0 :     nsCOMPtr<nsPIDOMWindow> win(do_QueryInterface(aWindow));
    1161                 : 
    1162               0 :     NS_ASSERTION(win->IsOuterWindow(),
    1163                 :                  "Uh, the active window must be an outer window!");
    1164                 :   }
    1165                 : #endif
    1166                 : 
    1167                 :   {
    1168                 :     nsWatcherWindowEntry *info;
    1169               0 :     MutexAutoLock lock(mListLock);
    1170                 : 
    1171                 :     // if we already have an entry for this window, adjust
    1172                 :     // its chrome mapping and return
    1173               0 :     info = FindWindowEntry(aWindow);
    1174               0 :     if (info) {
    1175               0 :       nsCOMPtr<nsISupportsWeakReference> supportsweak(do_QueryInterface(aChrome));
    1176               0 :       if (supportsweak) {
    1177               0 :         supportsweak->GetWeakReference(getter_AddRefs(info->mChromeWeak));
    1178                 :       } else {
    1179               0 :         info->mChrome = aChrome;
    1180               0 :         info->mChromeWeak = 0;
    1181                 :       }
    1182               0 :       return NS_OK;
    1183                 :     }
    1184                 :   
    1185                 :     // create a window info struct and add it to the list of windows
    1186               0 :     info = new nsWatcherWindowEntry(aWindow, aChrome);
    1187               0 :     if (!info)
    1188               0 :       return NS_ERROR_OUT_OF_MEMORY;
    1189                 : 
    1190               0 :     if (mOldestWindow)
    1191               0 :       info->InsertAfter(mOldestWindow->mOlder);
    1192                 :     else
    1193               0 :       mOldestWindow = info;
    1194                 :   } // leave the mListLock
    1195                 : 
    1196                 :   // a window being added to us signifies a newly opened window.
    1197                 :   // send notifications.
    1198               0 :   nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
    1199               0 :   if (!os)
    1200               0 :     return NS_ERROR_FAILURE;
    1201                 : 
    1202               0 :   nsCOMPtr<nsISupports> domwin(do_QueryInterface(aWindow));
    1203               0 :   return os->NotifyObservers(domwin, "domwindowopened", 0);
    1204                 : }
    1205                 : 
    1206                 : NS_IMETHODIMP
    1207               0 : nsWindowWatcher::RemoveWindow(nsIDOMWindow *aWindow)
    1208                 : {
    1209                 :   // find the corresponding nsWatcherWindowEntry, remove it
    1210                 : 
    1211               0 :   if (!aWindow)
    1212               0 :     return NS_ERROR_INVALID_ARG;
    1213                 : 
    1214               0 :   nsWatcherWindowEntry *info = FindWindowEntry(aWindow);
    1215               0 :   if (info) {
    1216               0 :     RemoveWindow(info);
    1217               0 :     return NS_OK;
    1218                 :   }
    1219               0 :   NS_WARNING("requested removal of nonexistent window");
    1220               0 :   return NS_ERROR_INVALID_ARG;
    1221                 : }
    1222                 : 
    1223                 : nsWatcherWindowEntry *
    1224               0 : nsWindowWatcher::FindWindowEntry(nsIDOMWindow *aWindow)
    1225                 : {
    1226                 :   // find the corresponding nsWatcherWindowEntry
    1227                 :   nsWatcherWindowEntry *info,
    1228                 :                        *listEnd;
    1229                 : #ifdef USEWEAKREFS
    1230                 :   nsresult    rv;
    1231                 :   bool        found;
    1232                 : #endif
    1233                 : 
    1234               0 :   info = mOldestWindow;
    1235               0 :   listEnd = 0;
    1236                 : #ifdef USEWEAKREFS
    1237                 :   rv = NS_OK;
    1238                 :   found = false;
    1239                 :   while (info != listEnd && NS_SUCCEEDED(rv)) {
    1240                 :     nsCOMPtr<nsIDOMWindow> infoWindow(do_QueryReferent(info->mWindow));
    1241                 :     if (!infoWindow) { // clean up dangling reference, while we're here
    1242                 :       rv = RemoveWindow(info);
    1243                 :     }
    1244                 :     else if (infoWindow.get() == aWindow)
    1245                 :       return info;
    1246                 : 
    1247                 :     info = info->mYounger;
    1248                 :     listEnd = mOldestWindow;
    1249                 :   }
    1250                 :   return 0;
    1251                 : #else
    1252               0 :   while (info != listEnd) {
    1253               0 :     if (info->mWindow == aWindow)
    1254               0 :       return info;
    1255               0 :     info = info->mYounger;
    1256               0 :     listEnd = mOldestWindow;
    1257                 :   }
    1258               0 :   return 0;
    1259                 : #endif
    1260                 : }
    1261                 : 
    1262               0 : nsresult nsWindowWatcher::RemoveWindow(nsWatcherWindowEntry *inInfo)
    1263                 : {
    1264                 :   PRUint32  ctr,
    1265               0 :             count = mEnumeratorList.Length();
    1266                 : 
    1267                 :   {
    1268                 :     // notify the enumerators
    1269               0 :     MutexAutoLock lock(mListLock);
    1270               0 :     for (ctr = 0; ctr < count; ++ctr) 
    1271               0 :       mEnumeratorList[ctr]->WindowRemoved(inInfo);
    1272                 : 
    1273                 :     // remove the element from the list
    1274               0 :     if (inInfo == mOldestWindow)
    1275               0 :       mOldestWindow = inInfo->mYounger == mOldestWindow ? 0 : inInfo->mYounger;
    1276               0 :     inInfo->Unlink();
    1277                 :   }
    1278                 : 
    1279                 :   // a window being removed from us signifies a newly closed window.
    1280                 :   // send notifications.
    1281               0 :   nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
    1282               0 :   if (os) {
    1283                 : #ifdef USEWEAKREFS
    1284                 :     nsCOMPtr<nsISupports> domwin(do_QueryReferent(inInfo->mWindow));
    1285                 :     if (domwin)
    1286                 :       os->NotifyObservers(domwin, "domwindowclosed", 0);
    1287                 :     // else bummer. since the window is gone, there's nothing to notify with.
    1288                 : #else
    1289               0 :     nsCOMPtr<nsISupports> domwin(do_QueryInterface(inInfo->mWindow));
    1290               0 :     os->NotifyObservers(domwin, "domwindowclosed", 0);
    1291                 : #endif
    1292                 :   }
    1293                 : 
    1294               0 :   delete inInfo;
    1295               0 :   return NS_OK;
    1296                 : }
    1297                 : 
    1298                 : NS_IMETHODIMP
    1299               0 : nsWindowWatcher::GetChromeForWindow(nsIDOMWindow *aWindow, nsIWebBrowserChrome **_retval)
    1300                 : {
    1301               0 :   if (!aWindow || !_retval)
    1302               0 :     return NS_ERROR_INVALID_ARG;
    1303               0 :   *_retval = 0;
    1304                 : 
    1305               0 :   MutexAutoLock lock(mListLock);
    1306               0 :   nsWatcherWindowEntry *info = FindWindowEntry(aWindow);
    1307               0 :   if (info) {
    1308               0 :     if (info->mChromeWeak != nsnull) {
    1309               0 :       return info->mChromeWeak->
    1310                 :                             QueryReferent(NS_GET_IID(nsIWebBrowserChrome),
    1311               0 :                                           reinterpret_cast<void**>(_retval));
    1312                 :     }
    1313               0 :     *_retval = info->mChrome;
    1314               0 :     NS_IF_ADDREF(*_retval);
    1315                 :   }
    1316               0 :   return NS_OK;
    1317                 : }
    1318                 : 
    1319                 : NS_IMETHODIMP
    1320               0 : nsWindowWatcher::GetWindowByName(const PRUnichar *aTargetName, 
    1321                 :                                  nsIDOMWindow *aCurrentWindow,
    1322                 :                                  nsIDOMWindow **aResult)
    1323                 : {
    1324               0 :   if (!aResult) {
    1325               0 :     return NS_ERROR_INVALID_ARG;
    1326                 :   }
    1327                 : 
    1328               0 :   *aResult = nsnull;
    1329                 : 
    1330               0 :   nsCOMPtr<nsIDocShellTreeItem> treeItem;
    1331                 : 
    1332               0 :   nsCOMPtr<nsIDocShellTreeItem> startItem;
    1333               0 :   GetWindowTreeItem(aCurrentWindow, getter_AddRefs(startItem));
    1334               0 :   if (startItem) {
    1335                 :     // Note: original requestor is null here, per idl comments
    1336               0 :     startItem->FindItemWithName(aTargetName, nsnull, nsnull,
    1337               0 :                                 getter_AddRefs(treeItem));
    1338                 :   }
    1339                 :   else {
    1340                 :     // Note: original requestor is null here, per idl comments
    1341               0 :     FindItemWithName(aTargetName, nsnull, nsnull, getter_AddRefs(treeItem));
    1342                 :   }
    1343                 : 
    1344               0 :   nsCOMPtr<nsIDOMWindow> domWindow = do_GetInterface(treeItem);
    1345               0 :   domWindow.swap(*aResult);
    1346                 : 
    1347               0 :   return NS_OK;
    1348                 : }
    1349                 : 
    1350                 : bool
    1351             280 : nsWindowWatcher::AddEnumerator(nsWatcherWindowEnumerator* inEnumerator)
    1352                 : {
    1353                 :   // (requires a lock; assumes it's called by someone holding the lock)
    1354             280 :   return mEnumeratorList.AppendElement(inEnumerator) != nsnull;
    1355                 : }
    1356                 : 
    1357                 : bool
    1358             280 : nsWindowWatcher::RemoveEnumerator(nsWatcherWindowEnumerator* inEnumerator)
    1359                 : {
    1360                 :   // (requires a lock; assumes it's called by someone holding the lock)
    1361             280 :   return mEnumeratorList.RemoveElement(inEnumerator);
    1362                 : }
    1363                 : 
    1364                 : nsresult
    1365               0 : nsWindowWatcher::URIfromURL(const char *aURL,
    1366                 :                             nsIDOMWindow *aParent,
    1367                 :                             nsIURI **aURI)
    1368                 : {
    1369               0 :   nsCOMPtr<nsIDOMWindow> baseWindow;
    1370                 : 
    1371                 :   /* build the URI relative to the calling JS Context, if any.
    1372                 :      (note this is the same context used to make the security check
    1373                 :      in nsGlobalWindow.cpp.) */
    1374               0 :   JSContext *cx = GetJSContextFromCallStack();
    1375               0 :   if (cx) {
    1376               0 :     nsIScriptContext *scriptcx = nsJSUtils::GetDynamicScriptContext(cx);
    1377               0 :     if (scriptcx) {
    1378               0 :       baseWindow = do_QueryInterface(scriptcx->GetGlobalObject());
    1379                 :     }
    1380                 :   }
    1381                 : 
    1382                 :   // failing that, build it relative to the parent window, if possible
    1383               0 :   if (!baseWindow)
    1384               0 :     baseWindow = aParent;
    1385                 : 
    1386                 :   // failing that, use the given URL unmodified. It had better not be relative.
    1387                 : 
    1388               0 :   nsIURI *baseURI = nsnull;
    1389                 : 
    1390                 :   // get baseWindow's document URI
    1391               0 :   if (baseWindow) {
    1392               0 :     nsCOMPtr<nsIDOMDocument> domDoc;
    1393               0 :     baseWindow->GetDocument(getter_AddRefs(domDoc));
    1394               0 :     if (domDoc) {
    1395               0 :       nsCOMPtr<nsIDocument> doc;
    1396               0 :       doc = do_QueryInterface(domDoc);
    1397               0 :       if (doc) {
    1398               0 :         baseURI = doc->GetDocBaseURI();
    1399                 :       }
    1400                 :     }
    1401                 :   }
    1402                 : 
    1403                 :   // build and return the absolute URI
    1404               0 :   return NS_NewURI(aURI, aURL, baseURI);
    1405                 : }
    1406                 : 
    1407                 : #define NS_CALCULATE_CHROME_FLAG_FOR(feature, flag)               \
    1408                 :     prefBranch->GetBoolPref(feature, &forceEnable);               \
    1409                 :     if (forceEnable && !(aDialog && isChrome) &&                  \
    1410                 :         !(isChrome && aHasChromeParent) && !aChromeURL) {         \
    1411                 :       chromeFlags |= flag;                                        \
    1412                 :     } else {                                                      \
    1413                 :       chromeFlags |= WinHasOption(aFeatures, feature,             \
    1414                 :                                   0, &presenceFlag)               \
    1415                 :                      ? flag : 0;                                  \
    1416                 :     }
    1417                 : 
    1418                 : /**
    1419                 :  * Calculate the chrome bitmask from a string list of features.
    1420                 :  * @param aFeatures a string containing a list of named chrome features
    1421                 :  * @param aNullFeatures true if aFeatures was a null pointer (which fact
    1422                 :  *                      is lost by its conversion to a string in the caller)
    1423                 :  * @param aDialog affects the assumptions made about unnamed features
    1424                 :  * @return the chrome bitmask
    1425                 :  */
    1426                 : // static
    1427               0 : PRUint32 nsWindowWatcher::CalculateChromeFlags(const char *aFeatures,
    1428                 :                                                bool aFeaturesSpecified,
    1429                 :                                                bool aDialog,
    1430                 :                                                bool aChromeURL,
    1431                 :                                                bool aHasChromeParent)
    1432                 : {
    1433               0 :    if(!aFeaturesSpecified || !aFeatures) {
    1434               0 :       if(aDialog)
    1435                 :          return nsIWebBrowserChrome::CHROME_ALL | 
    1436                 :                 nsIWebBrowserChrome::CHROME_OPENAS_DIALOG | 
    1437               0 :                 nsIWebBrowserChrome::CHROME_OPENAS_CHROME;
    1438                 :       else
    1439               0 :          return nsIWebBrowserChrome::CHROME_ALL;
    1440                 :    }
    1441                 : 
    1442                 :   /* This function has become complicated since browser windows and
    1443                 :      dialogs diverged. The difference is, browser windows assume all
    1444                 :      chrome not explicitly mentioned is off, if the features string
    1445                 :      is not null. Exceptions are some OS border chrome new with Mozilla.
    1446                 :      Dialogs interpret a (mostly) empty features string to mean
    1447                 :      "OS's choice," and also support an "all" flag explicitly disallowed
    1448                 :      in the standards-compliant window.(normal)open. */
    1449                 : 
    1450               0 :   PRUint32 chromeFlags = 0;
    1451               0 :   bool presenceFlag = false;
    1452                 : 
    1453               0 :   chromeFlags = nsIWebBrowserChrome::CHROME_WINDOW_BORDERS;
    1454               0 :   if (aDialog && WinHasOption(aFeatures, "all", 0, &presenceFlag))
    1455               0 :     chromeFlags = nsIWebBrowserChrome::CHROME_ALL;
    1456                 : 
    1457                 :   /* Next, allow explicitly named options to override the initial settings */
    1458                 : 
    1459                 :   nsCOMPtr<nsIScriptSecurityManager>
    1460               0 :     securityManager(do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID));
    1461               0 :   NS_ENSURE_TRUE(securityManager, NS_ERROR_FAILURE);
    1462                 : 
    1463               0 :   bool isChrome = false;
    1464               0 :   nsresult rv = securityManager->SubjectPrincipalIsSystem(&isChrome);
    1465               0 :   if (NS_FAILED(rv)) {
    1466               0 :     isChrome = false;
    1467                 :   }
    1468                 : 
    1469               0 :   nsCOMPtr<nsIPrefBranch> prefBranch;
    1470               0 :   nsCOMPtr<nsIPrefService> prefs = do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
    1471               0 :   NS_ENSURE_SUCCESS(rv, true);
    1472                 : 
    1473               0 :   rv = prefs->GetBranch("dom.disable_window_open_feature.", getter_AddRefs(prefBranch));
    1474               0 :   NS_ENSURE_SUCCESS(rv, true);
    1475                 : 
    1476               0 :   bool forceEnable = false;
    1477                 : 
    1478               0 :   NS_CALCULATE_CHROME_FLAG_FOR("titlebar",
    1479                 :                                nsIWebBrowserChrome::CHROME_TITLEBAR);
    1480               0 :   NS_CALCULATE_CHROME_FLAG_FOR("close",
    1481                 :                                nsIWebBrowserChrome::CHROME_WINDOW_CLOSE);
    1482               0 :   NS_CALCULATE_CHROME_FLAG_FOR("toolbar",
    1483                 :                                nsIWebBrowserChrome::CHROME_TOOLBAR);
    1484               0 :   NS_CALCULATE_CHROME_FLAG_FOR("location",
    1485                 :                                nsIWebBrowserChrome::CHROME_LOCATIONBAR);
    1486               0 :   NS_CALCULATE_CHROME_FLAG_FOR("personalbar",
    1487                 :                                nsIWebBrowserChrome::CHROME_PERSONAL_TOOLBAR);
    1488               0 :   NS_CALCULATE_CHROME_FLAG_FOR("status",
    1489                 :                                nsIWebBrowserChrome::CHROME_STATUSBAR);
    1490               0 :   NS_CALCULATE_CHROME_FLAG_FOR("menubar",
    1491                 :                                nsIWebBrowserChrome::CHROME_MENUBAR);
    1492               0 :   NS_CALCULATE_CHROME_FLAG_FOR("scrollbars",
    1493                 :                                nsIWebBrowserChrome::CHROME_SCROLLBARS);
    1494               0 :   NS_CALCULATE_CHROME_FLAG_FOR("resizable",
    1495                 :                                nsIWebBrowserChrome::CHROME_WINDOW_RESIZE);
    1496               0 :   NS_CALCULATE_CHROME_FLAG_FOR("minimizable",
    1497                 :                                nsIWebBrowserChrome::CHROME_WINDOW_MIN);
    1498                 : 
    1499               0 :   chromeFlags |= WinHasOption(aFeatures, "popup", 0, &presenceFlag)
    1500               0 :                  ? nsIWebBrowserChrome::CHROME_WINDOW_POPUP : 0; 
    1501                 : 
    1502                 :   /* OK.
    1503                 :      Normal browser windows, in spite of a stated pattern of turning off
    1504                 :      all chrome not mentioned explicitly, will want the new OS chrome (window
    1505                 :      borders, titlebars, closebox) on, unless explicitly turned off.
    1506                 :      Dialogs, on the other hand, take the absence of any explicit settings
    1507                 :      to mean "OS' choice." */
    1508                 : 
    1509                 :   // default titlebar and closebox to "on," if not mentioned at all
    1510               0 :   if (!(chromeFlags & nsIWebBrowserChrome::CHROME_WINDOW_POPUP)) {
    1511               0 :     if (!PL_strcasestr(aFeatures, "titlebar"))
    1512               0 :       chromeFlags |= nsIWebBrowserChrome::CHROME_TITLEBAR;
    1513               0 :     if (!PL_strcasestr(aFeatures, "close"))
    1514               0 :       chromeFlags |= nsIWebBrowserChrome::CHROME_WINDOW_CLOSE;
    1515                 :   }
    1516                 : 
    1517               0 :   if (aDialog && !presenceFlag)
    1518               0 :     chromeFlags = nsIWebBrowserChrome::CHROME_DEFAULT;
    1519                 : 
    1520                 :   /* Finally, once all the above normal chrome has been divined, deal
    1521                 :      with the features that are more operating hints than appearance
    1522                 :      instructions. (Note modality implies dependence.) */
    1523                 : 
    1524               0 :   if (WinHasOption(aFeatures, "alwaysLowered", 0, nsnull) ||
    1525               0 :       WinHasOption(aFeatures, "z-lock", 0, nsnull))
    1526               0 :     chromeFlags |= nsIWebBrowserChrome::CHROME_WINDOW_LOWERED;
    1527               0 :   else if (WinHasOption(aFeatures, "alwaysRaised", 0, nsnull))
    1528               0 :     chromeFlags |= nsIWebBrowserChrome::CHROME_WINDOW_RAISED;
    1529                 : 
    1530               0 :   chromeFlags |= WinHasOption(aFeatures, "macsuppressanimation", 0, nsnull) ?
    1531               0 :     nsIWebBrowserChrome::CHROME_MAC_SUPPRESS_ANIMATION : 0;
    1532                 : 
    1533               0 :   chromeFlags |= WinHasOption(aFeatures, "chrome", 0, nsnull) ?
    1534               0 :     nsIWebBrowserChrome::CHROME_OPENAS_CHROME : 0;
    1535               0 :   chromeFlags |= WinHasOption(aFeatures, "extrachrome", 0, nsnull) ?
    1536               0 :     nsIWebBrowserChrome::CHROME_EXTRA : 0;
    1537               0 :   chromeFlags |= WinHasOption(aFeatures, "centerscreen", 0, nsnull) ?
    1538               0 :     nsIWebBrowserChrome::CHROME_CENTER_SCREEN : 0;
    1539               0 :   chromeFlags |= WinHasOption(aFeatures, "dependent", 0, nsnull) ?
    1540               0 :     nsIWebBrowserChrome::CHROME_DEPENDENT : 0;
    1541               0 :   chromeFlags |= WinHasOption(aFeatures, "modal", 0, nsnull) ?
    1542               0 :     (nsIWebBrowserChrome::CHROME_MODAL | nsIWebBrowserChrome::CHROME_DEPENDENT) : 0;
    1543                 : 
    1544                 :   /* On mobile we want to ignore the dialog window feature, since the mobile UI
    1545                 :      does not provide any affordance for dialog windows. This does not interfere
    1546                 :      with dialog windows created through openDialog. */
    1547               0 :   bool disableDialogFeature = false;
    1548               0 :   nsCOMPtr<nsIPrefBranch> branch = do_QueryInterface(prefs);
    1549               0 :   branch->GetBoolPref("dom.disable_window_open_dialog_feature", &disableDialogFeature);
    1550               0 :   if (!disableDialogFeature) {
    1551               0 :     chromeFlags |= WinHasOption(aFeatures, "dialog", 0, nsnull) ?
    1552               0 :       nsIWebBrowserChrome::CHROME_OPENAS_DIALOG : 0;
    1553                 :   }
    1554                 : 
    1555                 :   /* and dialogs need to have the last word. assume dialogs are dialogs,
    1556                 :      and opened as chrome, unless explicitly told otherwise. */
    1557               0 :   if (aDialog) {
    1558               0 :     if (!PL_strcasestr(aFeatures, "dialog"))
    1559               0 :       chromeFlags |= nsIWebBrowserChrome::CHROME_OPENAS_DIALOG;
    1560               0 :     if (!PL_strcasestr(aFeatures, "chrome"))
    1561               0 :       chromeFlags |= nsIWebBrowserChrome::CHROME_OPENAS_CHROME;
    1562                 :   }
    1563                 : 
    1564                 :   /* missing
    1565                 :      chromeFlags->copy_history
    1566                 :    */
    1567                 : 
    1568                 :   // Check security state for use in determing window dimensions
    1569                 :   bool enabled;
    1570                 :   nsresult res =
    1571               0 :     securityManager->IsCapabilityEnabled("UniversalXPConnect", &enabled);
    1572                 : 
    1573               0 :   if (NS_FAILED(res) || !enabled || (isChrome && !aHasChromeParent)) {
    1574                 :     // If priv check fails (or if we're called from chrome, but the
    1575                 :     // parent is not a chrome window), set all elements to minimum
    1576                 :     // reqs., else leave them alone.
    1577               0 :     chromeFlags |= nsIWebBrowserChrome::CHROME_TITLEBAR;
    1578               0 :     chromeFlags |= nsIWebBrowserChrome::CHROME_WINDOW_CLOSE;
    1579               0 :     chromeFlags &= ~nsIWebBrowserChrome::CHROME_WINDOW_LOWERED;
    1580               0 :     chromeFlags &= ~nsIWebBrowserChrome::CHROME_WINDOW_RAISED;
    1581               0 :     chromeFlags &= ~nsIWebBrowserChrome::CHROME_WINDOW_POPUP;
    1582                 :     /* Untrusted script is allowed to pose modal windows with a chrome
    1583                 :        scheme. This check could stand to be better. But it effectively
    1584                 :        prevents untrusted script from opening modal windows in general
    1585                 :        while still allowing alerts and the like. */
    1586               0 :     if (!aChromeURL)
    1587                 :       chromeFlags &= ~(nsIWebBrowserChrome::CHROME_MODAL |
    1588               0 :                        nsIWebBrowserChrome::CHROME_OPENAS_CHROME);
    1589                 :   }
    1590                 : 
    1591               0 :   if (!(chromeFlags & nsIWebBrowserChrome::CHROME_OPENAS_CHROME)) {
    1592                 :     // Remove the dependent flag if we're not opening as chrome
    1593               0 :     chromeFlags &= ~nsIWebBrowserChrome::CHROME_DEPENDENT;
    1594                 :   }
    1595                 : 
    1596               0 :   return chromeFlags;
    1597                 : }
    1598                 : 
    1599                 : // static
    1600                 : PRInt32
    1601               0 : nsWindowWatcher::WinHasOption(const char *aOptions, const char *aName,
    1602                 :                               PRInt32 aDefault, bool *aPresenceFlag)
    1603                 : {
    1604               0 :   if (!aOptions)
    1605               0 :     return 0;
    1606                 : 
    1607                 :   char *comma, *equal;
    1608               0 :   PRInt32 found = 0;
    1609                 : 
    1610                 : #ifdef DEBUG
    1611               0 :     nsCAutoString options(aOptions);
    1612               0 :     NS_ASSERTION(options.FindCharInSet(" \n\r\t") == kNotFound, 
    1613                 :                   "There should be no whitespace in this string!");
    1614                 : #endif
    1615                 : 
    1616               0 :   while (true) {
    1617               0 :     comma = PL_strchr(aOptions, ',');
    1618               0 :     if (comma)
    1619               0 :       *comma = '\0';
    1620               0 :     equal = PL_strchr(aOptions, '=');
    1621               0 :     if (equal)
    1622               0 :       *equal = '\0';
    1623               0 :     if (nsCRT::strcasecmp(aOptions, aName) == 0) {
    1624               0 :       if (aPresenceFlag)
    1625               0 :         *aPresenceFlag = true;
    1626               0 :       if (equal)
    1627               0 :         if (*(equal + 1) == '*')
    1628               0 :           found = aDefault;
    1629               0 :         else if (nsCRT::strcasecmp(equal + 1, "yes") == 0)
    1630               0 :           found = 1;
    1631                 :         else
    1632               0 :           found = atoi(equal + 1);
    1633                 :       else
    1634               0 :         found = 1;
    1635                 :     }
    1636               0 :     if (equal)
    1637               0 :       *equal = '=';
    1638               0 :     if (comma)
    1639               0 :       *comma = ',';
    1640               0 :     if (found || !comma)
    1641                 :       break;
    1642               0 :     aOptions = comma + 1;
    1643                 :   }
    1644               0 :   return found;
    1645                 : }
    1646                 : 
    1647                 : /* try to find an nsIDocShellTreeItem with the given name in any
    1648                 :    known open window. a failure to find the item will not
    1649                 :    necessarily return a failure method value. check aFoundItem.
    1650                 : */
    1651                 : NS_IMETHODIMP
    1652               0 : nsWindowWatcher::FindItemWithName(const PRUnichar* aName,
    1653                 :                                   nsIDocShellTreeItem* aRequestor,
    1654                 :                                   nsIDocShellTreeItem* aOriginalRequestor,
    1655                 :                                   nsIDocShellTreeItem** aFoundItem)
    1656                 : {
    1657               0 :   *aFoundItem = 0;
    1658                 : 
    1659                 :   /* special cases */
    1660               0 :   if(!aName || !*aName)
    1661               0 :     return NS_OK;
    1662                 : 
    1663               0 :   nsDependentString name(aName);
    1664                 :   
    1665               0 :   nsCOMPtr<nsISimpleEnumerator> windows;
    1666               0 :   GetWindowEnumerator(getter_AddRefs(windows));
    1667               0 :   if (!windows)
    1668               0 :     return NS_ERROR_FAILURE;
    1669                 : 
    1670                 :   bool     more;
    1671               0 :   nsresult rv = NS_OK;
    1672                 : 
    1673               0 :   do {
    1674               0 :     windows->HasMoreElements(&more);
    1675               0 :     if (!more)
    1676               0 :       break;
    1677               0 :     nsCOMPtr<nsISupports> nextSupWindow;
    1678               0 :     windows->GetNext(getter_AddRefs(nextSupWindow));
    1679               0 :     nsCOMPtr<nsIDOMWindow> nextWindow(do_QueryInterface(nextSupWindow));
    1680               0 :     if (nextWindow) {
    1681               0 :       nsCOMPtr<nsIDocShellTreeItem> treeItem;
    1682               0 :       GetWindowTreeItem(nextWindow, getter_AddRefs(treeItem));
    1683               0 :       if (treeItem) {
    1684                 :         // Get the root tree item of same type, since roots are the only
    1685                 :         // things that call into the treeowner to look for named items.
    1686               0 :         nsCOMPtr<nsIDocShellTreeItem> root;
    1687               0 :         treeItem->GetSameTypeRootTreeItem(getter_AddRefs(root));
    1688               0 :         NS_ASSERTION(root, "Must have root tree item of same type");
    1689                 :         // Make sure not to call back into aRequestor
    1690               0 :         if (root != aRequestor) {
    1691                 :           // Get the tree owner so we can pass it in as the requestor so
    1692                 :           // the child knows not to call back up, since we're walking
    1693                 :           // all windows already.
    1694               0 :           nsCOMPtr<nsIDocShellTreeOwner> rootOwner;
    1695                 :           // Note: if we have no aRequestor, then we want to also look for
    1696                 :           // "special" window names, so pass a null requestor.  This will mean
    1697                 :           // that the treeitem calls back up to us, effectively (with a
    1698                 :           // non-null aRequestor), so break the loop immediately after the
    1699                 :           // call in that case.
    1700               0 :           if (aRequestor) {
    1701               0 :             root->GetTreeOwner(getter_AddRefs(rootOwner));
    1702                 :           }
    1703               0 :           rv = root->FindItemWithName(aName, rootOwner, aOriginalRequestor,
    1704               0 :                                       aFoundItem);
    1705               0 :           if (NS_FAILED(rv) || *aFoundItem || !aRequestor)
    1706                 :             break;
    1707                 :         }
    1708                 :       }
    1709                 :     }
    1710                 :   } while(1);
    1711                 : 
    1712               0 :   return rv;
    1713                 : }
    1714                 : 
    1715                 : already_AddRefed<nsIDocShellTreeItem>
    1716               0 : nsWindowWatcher::GetCallerTreeItem(nsIDocShellTreeItem* aParentItem)
    1717                 : {
    1718                 :   nsCOMPtr<nsIJSContextStack> stack =
    1719               0 :     do_GetService(sJSStackContractID);
    1720                 : 
    1721               0 :   JSContext *cx = nsnull;
    1722                 : 
    1723               0 :   if (stack) {
    1724               0 :     stack->Peek(&cx);
    1725                 :   }
    1726                 : 
    1727               0 :   nsIDocShellTreeItem* callerItem = nsnull;
    1728                 : 
    1729               0 :   if (cx) {
    1730                 :     nsCOMPtr<nsIWebNavigation> callerWebNav =
    1731               0 :       do_GetInterface(nsJSUtils::GetDynamicScriptGlobal(cx));
    1732                 : 
    1733               0 :     if (callerWebNav) {
    1734               0 :       CallQueryInterface(callerWebNav, &callerItem);
    1735                 :     }
    1736                 :   }
    1737                 : 
    1738               0 :   if (!callerItem) {
    1739               0 :     NS_IF_ADDREF(callerItem = aParentItem);
    1740                 :   }
    1741                 : 
    1742               0 :   return callerItem;
    1743                 : }
    1744                 : 
    1745                 : nsresult
    1746               0 : nsWindowWatcher::SafeGetWindowByName(const nsAString& aName,
    1747                 :                                      nsIDOMWindow* aCurrentWindow,
    1748                 :                                      nsIDOMWindow** aResult)
    1749                 : {
    1750               0 :   *aResult = nsnull;
    1751                 :   
    1752               0 :   nsCOMPtr<nsIDocShellTreeItem> startItem;
    1753               0 :   GetWindowTreeItem(aCurrentWindow, getter_AddRefs(startItem));
    1754                 : 
    1755               0 :   nsCOMPtr<nsIDocShellTreeItem> callerItem = GetCallerTreeItem(startItem);
    1756                 : 
    1757               0 :   const nsAFlatString& flatName = PromiseFlatString(aName);
    1758                 : 
    1759               0 :   nsCOMPtr<nsIDocShellTreeItem> foundItem;
    1760               0 :   if (startItem) {
    1761               0 :     startItem->FindItemWithName(flatName.get(), nsnull, callerItem,
    1762               0 :                                 getter_AddRefs(foundItem));
    1763                 :   }
    1764                 :   else {
    1765                 :     FindItemWithName(flatName.get(), nsnull, callerItem,
    1766               0 :                      getter_AddRefs(foundItem));
    1767                 :   }
    1768                 : 
    1769               0 :   nsCOMPtr<nsIDOMWindow> foundWin = do_GetInterface(foundItem);
    1770               0 :   foundWin.swap(*aResult);
    1771               0 :   return NS_OK;
    1772                 : }
    1773                 : 
    1774                 : /* Fetch the nsIDOMWindow corresponding to the given nsIDocShellTreeItem.
    1775                 :    This forces the creation of a script context, if one has not already
    1776                 :    been created. Note it also sets the window's opener to the parent,
    1777                 :    if applicable -- because it's just convenient, that's all. null aParent
    1778                 :    is acceptable. */
    1779                 : nsresult
    1780               0 : nsWindowWatcher::ReadyOpenedDocShellItem(nsIDocShellTreeItem *aOpenedItem,
    1781                 :                                          nsIDOMWindow        *aParent,
    1782                 :                                          bool                aWindowIsNew,
    1783                 :                                          nsIDOMWindow        **aOpenedWindow)
    1784                 : {
    1785               0 :   nsresult rv = NS_ERROR_FAILURE;
    1786                 : 
    1787               0 :   *aOpenedWindow = 0;
    1788               0 :   nsCOMPtr<nsPIDOMWindow> piOpenedWindow(do_GetInterface(aOpenedItem));
    1789               0 :   if (piOpenedWindow) {
    1790               0 :     if (aParent) {
    1791               0 :       piOpenedWindow->SetOpenerWindow(aParent, aWindowIsNew); // damnit
    1792                 : 
    1793               0 :       if (aWindowIsNew) {
    1794                 : #ifdef DEBUG
    1795                 :         // Assert that we're not loading things right now.  If we are, when
    1796                 :         // that load completes it will clobber whatever principals we set up
    1797                 :         // on this new window!
    1798                 :         nsCOMPtr<nsIDocumentLoader> docloader =
    1799               0 :           do_QueryInterface(aOpenedItem);
    1800               0 :         NS_ASSERTION(docloader, "How can we not have a docloader here?");
    1801                 : 
    1802               0 :         nsCOMPtr<nsIChannel> chan;
    1803               0 :         docloader->GetDocumentChannel(getter_AddRefs(chan));
    1804               0 :         NS_ASSERTION(!chan, "Why is there a document channel?");
    1805                 : #endif
    1806                 : 
    1807                 :         nsCOMPtr<nsIDocument> doc =
    1808               0 :           do_QueryInterface(piOpenedWindow->GetExtantDocument());
    1809               0 :         if (doc) {
    1810               0 :           doc->SetIsInitialDocument(true);
    1811                 :         }
    1812                 :       }
    1813                 :     }
    1814               0 :     rv = CallQueryInterface(piOpenedWindow, aOpenedWindow);
    1815                 :   }
    1816               0 :   return rv;
    1817                 : }
    1818                 : 
    1819                 : // static
    1820                 : void
    1821               0 : nsWindowWatcher::CalcSizeSpec(const char* aFeatures, SizeSpec& aResult)
    1822                 : {
    1823                 :   // Parse position spec, if any, from aFeatures
    1824                 :   bool    present;
    1825                 :   PRInt32 temp;
    1826                 : 
    1827               0 :   present = false;
    1828               0 :   if ((temp = WinHasOption(aFeatures, "left", 0, &present)) || present)
    1829               0 :     aResult.mLeft = temp;
    1830               0 :   else if ((temp = WinHasOption(aFeatures, "screenX", 0, &present)) || present)
    1831               0 :     aResult.mLeft = temp;
    1832               0 :   aResult.mLeftSpecified = present;
    1833                 : 
    1834               0 :   present = false;
    1835               0 :   if ((temp = WinHasOption(aFeatures, "top", 0, &present)) || present)
    1836               0 :     aResult.mTop = temp;
    1837               0 :   else if ((temp = WinHasOption(aFeatures, "screenY", 0, &present)) || present)
    1838               0 :     aResult.mTop = temp;
    1839               0 :   aResult.mTopSpecified = present;
    1840                 : 
    1841                 :   // Parse size spec, if any. Chrome size overrides content size.
    1842               0 :   if ((temp = WinHasOption(aFeatures, "outerWidth", PR_INT32_MIN, nsnull))) {
    1843               0 :     if (temp == PR_INT32_MIN) {
    1844               0 :       aResult.mUseDefaultWidth = true;
    1845                 :     }
    1846                 :     else {
    1847               0 :       aResult.mOuterWidth = temp;
    1848                 :     }
    1849               0 :     aResult.mOuterWidthSpecified = true;
    1850               0 :   } else if ((temp = WinHasOption(aFeatures, "width", PR_INT32_MIN, nsnull)) ||
    1851                 :              (temp = WinHasOption(aFeatures, "innerWidth", PR_INT32_MIN,
    1852                 :                                   nsnull))) {
    1853               0 :     if (temp == PR_INT32_MIN) {
    1854               0 :       aResult.mUseDefaultWidth = true;
    1855                 :     } else {
    1856               0 :       aResult.mInnerWidth = temp;
    1857                 :     }
    1858               0 :     aResult.mInnerWidthSpecified = true;
    1859                 :   }
    1860                 : 
    1861               0 :   if ((temp = WinHasOption(aFeatures, "outerHeight", PR_INT32_MIN, nsnull))) {
    1862               0 :     if (temp == PR_INT32_MIN) {
    1863               0 :       aResult.mUseDefaultHeight = true;
    1864                 :     }
    1865                 :     else {
    1866               0 :       aResult.mOuterHeight = temp;
    1867                 :     }
    1868               0 :     aResult.mOuterHeightSpecified = true;
    1869               0 :   } else if ((temp = WinHasOption(aFeatures, "height", PR_INT32_MIN,
    1870                 :                                   nsnull)) ||
    1871                 :              (temp = WinHasOption(aFeatures, "innerHeight", PR_INT32_MIN,
    1872                 :                                   nsnull))) {
    1873               0 :     if (temp == PR_INT32_MIN) {
    1874               0 :       aResult.mUseDefaultHeight = true;
    1875                 :     } else {
    1876               0 :       aResult.mInnerHeight = temp;
    1877                 :     }
    1878               0 :     aResult.mInnerHeightSpecified = true;
    1879                 :   }
    1880               0 : }
    1881                 : 
    1882                 : /* Size and position the new window according to aSizeSpec. This method
    1883                 :    is assumed to be called after the window has already been given
    1884                 :    a default position and size; thus its current position and size are
    1885                 :    accurate defaults. The new window is made visible at method end.
    1886                 : */
    1887                 : void
    1888               0 : nsWindowWatcher::SizeOpenedDocShellItem(nsIDocShellTreeItem *aDocShellItem,
    1889                 :                                         nsIDOMWindow *aParent,
    1890                 :                                         const SizeSpec & aSizeSpec)
    1891                 : {
    1892                 :   // position and size of window
    1893               0 :   PRInt32 left = 0,
    1894               0 :           top = 0,
    1895               0 :           width = 100,
    1896               0 :           height = 100;
    1897                 :   // difference between chrome and content size
    1898               0 :   PRInt32 chromeWidth = 0,
    1899               0 :           chromeHeight = 0;
    1900                 :   // whether the window size spec refers to chrome or content
    1901               0 :   bool    sizeChromeWidth = true,
    1902               0 :           sizeChromeHeight = true;
    1903                 : 
    1904                 :   // get various interfaces for aDocShellItem, used throughout this method
    1905               0 :   nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
    1906               0 :   aDocShellItem->GetTreeOwner(getter_AddRefs(treeOwner));
    1907               0 :   nsCOMPtr<nsIBaseWindow> treeOwnerAsWin(do_QueryInterface(treeOwner));
    1908               0 :   if (!treeOwnerAsWin) // we'll need this to actually size the docshell
    1909                 :     return;
    1910                 :     
    1911               0 :   float devPixelsPerCSSPixel = 1.0;
    1912               0 :   if (aParent) {
    1913               0 :     nsCOMPtr<nsIDOMDocument> openerDoc;
    1914               0 :     aParent->GetDocument(getter_AddRefs(openerDoc));
    1915               0 :     if (openerDoc) {
    1916               0 :       nsCOMPtr<nsIDocument> doc = do_QueryInterface(openerDoc);
    1917               0 :       nsIPresShell* shell = doc->GetShell();
    1918               0 :       if (shell) {
    1919               0 :         nsPresContext* presContext = shell->GetPresContext();
    1920               0 :         if (presContext) {
    1921               0 :           devPixelsPerCSSPixel = presContext->CSSPixelsToDevPixels(1.0f);
    1922                 :         }
    1923                 :       }
    1924                 :     }
    1925                 :   }
    1926                 : 
    1927                 :   /* The current position and size will be unchanged if not specified
    1928                 :      (and they fit entirely onscreen). Also, calculate the difference
    1929                 :      between chrome and content sizes on aDocShellItem's window.
    1930                 :      This latter point becomes important if chrome and content
    1931                 :      specifications are mixed in aFeatures, and when bringing the window
    1932                 :      back from too far off the right or bottom edges of the screen. */
    1933                 : 
    1934               0 :   treeOwnerAsWin->GetPositionAndSize(&left, &top, &width, &height);
    1935                 :   { // scope shellWindow why not
    1936               0 :     nsCOMPtr<nsIBaseWindow> shellWindow(do_QueryInterface(aDocShellItem));
    1937               0 :     if (shellWindow) {
    1938                 :       PRInt32 cox, coy;
    1939               0 :       shellWindow->GetSize(&cox, &coy);
    1940               0 :       chromeWidth = width - cox;
    1941               0 :       chromeHeight = height - coy;
    1942                 :     }
    1943                 :   }
    1944                 : 
    1945                 :   // Set up left/top
    1946               0 :   if (aSizeSpec.mLeftSpecified) {
    1947               0 :     left = NSToIntRound(aSizeSpec.mLeft * devPixelsPerCSSPixel);
    1948                 :   }
    1949                 : 
    1950               0 :   if (aSizeSpec.mTopSpecified) {
    1951               0 :     top = NSToIntRound(aSizeSpec.mTop * devPixelsPerCSSPixel);
    1952                 :   }
    1953                 : 
    1954                 :   // Set up width
    1955               0 :   if (aSizeSpec.mOuterWidthSpecified) {
    1956               0 :     if (!aSizeSpec.mUseDefaultWidth) {
    1957               0 :       width = NSToIntRound(aSizeSpec.mOuterWidth * devPixelsPerCSSPixel);
    1958                 :     } // Else specified to default; just use our existing width
    1959                 :   }
    1960               0 :   else if (aSizeSpec.mInnerWidthSpecified) {
    1961               0 :     sizeChromeWidth = false;
    1962               0 :     if (aSizeSpec.mUseDefaultWidth) {
    1963               0 :       width = width - chromeWidth;
    1964                 :     } else {
    1965               0 :       width = NSToIntRound(aSizeSpec.mInnerWidth * devPixelsPerCSSPixel);
    1966                 :     }
    1967                 :   }
    1968                 : 
    1969                 :   // Set up height
    1970               0 :   if (aSizeSpec.mOuterHeightSpecified) {
    1971               0 :     if (!aSizeSpec.mUseDefaultHeight) {
    1972               0 :       height = NSToIntRound(aSizeSpec.mOuterHeight * devPixelsPerCSSPixel);
    1973                 :     } // Else specified to default; just use our existing height
    1974                 :   }
    1975               0 :   else if (aSizeSpec.mInnerHeightSpecified) {
    1976               0 :     sizeChromeHeight = false;
    1977               0 :     if (aSizeSpec.mUseDefaultHeight) {
    1978               0 :       height = height - chromeHeight;
    1979                 :     } else {
    1980               0 :       height = NSToIntRound(aSizeSpec.mInnerHeight * devPixelsPerCSSPixel);
    1981                 :     }
    1982                 :   }
    1983                 : 
    1984               0 :   bool positionSpecified = aSizeSpec.PositionSpecified();
    1985                 :   
    1986                 :   nsresult res;
    1987               0 :   bool enabled = false;
    1988                 : 
    1989                 :   // Check security state for use in determing window dimensions
    1990                 :   nsCOMPtr<nsIScriptSecurityManager>
    1991               0 :     securityManager(do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID));
    1992               0 :   if (securityManager) {
    1993               0 :     res = securityManager->IsCapabilityEnabled("UniversalXPConnect",
    1994               0 :                                                &enabled);
    1995               0 :     if (NS_FAILED(res))
    1996               0 :       enabled = false;
    1997               0 :     else if (enabled && aParent) {
    1998               0 :       nsCOMPtr<nsIDOMChromeWindow> chromeWin(do_QueryInterface(aParent));
    1999                 : 
    2000               0 :       bool isChrome = false;
    2001               0 :       nsresult rv = securityManager->SubjectPrincipalIsSystem(&isChrome);
    2002               0 :       if (NS_FAILED(rv)) {
    2003               0 :         isChrome = false;
    2004                 :       }
    2005                 : 
    2006                 :       // Only enable special priveleges for chrome when chrome calls
    2007                 :       // open() on a chrome window
    2008               0 :       enabled = !(isChrome && chromeWin == nsnull);
    2009                 :     }
    2010                 :   }
    2011                 : 
    2012               0 :   if (!enabled) {
    2013                 : 
    2014                 :     // Security check failed.  Ensure all args meet minimum reqs.
    2015                 : 
    2016               0 :     PRInt32 oldTop = top,
    2017               0 :             oldLeft = left;
    2018                 : 
    2019                 :     // We'll also need the screen dimensions
    2020               0 :     nsCOMPtr<nsIScreen> screen;
    2021                 :     nsCOMPtr<nsIScreenManager> screenMgr(do_GetService(
    2022               0 :                                          "@mozilla.org/gfx/screenmanager;1"));
    2023               0 :     if (screenMgr)
    2024               0 :       screenMgr->ScreenForRect(left, top, width, height,
    2025               0 :                                getter_AddRefs(screen));
    2026               0 :     if (screen) {
    2027                 :       PRInt32 screenLeft, screenTop, screenWidth, screenHeight;
    2028               0 :       PRInt32 winWidth = width + (sizeChromeWidth ? 0 : chromeWidth),
    2029               0 :               winHeight = height + (sizeChromeHeight ? 0 : chromeHeight);
    2030                 : 
    2031               0 :       screen->GetAvailRect(&screenLeft, &screenTop,
    2032               0 :                            &screenWidth, &screenHeight);
    2033                 : 
    2034               0 :       if (aSizeSpec.SizeSpecified()) {
    2035                 :         /* Unlike position, force size out-of-bounds check only if
    2036                 :            size actually was specified. Otherwise, intrinsically sized
    2037                 :            windows are broken. */
    2038               0 :         if (height < 100)
    2039               0 :           height = 100;
    2040               0 :         if (winHeight > screenHeight)
    2041               0 :           height = screenHeight - (sizeChromeHeight ? 0 : chromeHeight);
    2042               0 :         if (width < 100)
    2043               0 :           width = 100;
    2044               0 :         if (winWidth > screenWidth)
    2045               0 :           width = screenWidth - (sizeChromeWidth ? 0 : chromeWidth);
    2046                 :       }
    2047                 : 
    2048               0 :       if (left+winWidth > screenLeft+screenWidth)
    2049               0 :         left = screenLeft+screenWidth - winWidth;
    2050               0 :       if (left < screenLeft)
    2051               0 :         left = screenLeft;
    2052               0 :       if (top+winHeight > screenTop+screenHeight)
    2053               0 :         top = screenTop+screenHeight - winHeight;
    2054               0 :       if (top < screenTop)
    2055               0 :         top = screenTop;
    2056               0 :       if (top != oldTop || left != oldLeft)
    2057               0 :         positionSpecified = true;
    2058                 :     }
    2059                 :   }
    2060                 : 
    2061                 :   // size and position the window
    2062                 : 
    2063               0 :   if (positionSpecified)
    2064               0 :     treeOwnerAsWin->SetPosition(left, top);
    2065               0 :   if (aSizeSpec.SizeSpecified()) {
    2066                 :     /* Prefer to trust the interfaces, which think in terms of pure
    2067                 :        chrome or content sizes. If we have a mix, use the chrome size
    2068                 :        adjusted by the chrome/content differences calculated earlier. */
    2069               0 :     if (!sizeChromeWidth && !sizeChromeHeight)
    2070               0 :       treeOwner->SizeShellTo(aDocShellItem, width, height);
    2071                 :     else {
    2072               0 :       if (!sizeChromeWidth)
    2073               0 :         width += chromeWidth;
    2074               0 :       if (!sizeChromeHeight)
    2075               0 :         height += chromeHeight;
    2076               0 :       treeOwnerAsWin->SetSize(width, height, false);
    2077                 :     }
    2078                 :   }
    2079               0 :   treeOwnerAsWin->SetVisibility(true);
    2080                 : }
    2081                 : 
    2082                 : void
    2083               0 : nsWindowWatcher::GetWindowTreeItem(nsIDOMWindow *inWindow,
    2084                 :                                    nsIDocShellTreeItem **outTreeItem)
    2085                 : {
    2086               0 :   *outTreeItem = 0;
    2087                 : 
    2088               0 :   nsCOMPtr<nsPIDOMWindow> window(do_QueryInterface(inWindow));
    2089               0 :   if (window) {
    2090               0 :     nsIDocShell *docshell = window->GetDocShell();
    2091               0 :     if (docshell)
    2092               0 :       CallQueryInterface(docshell, outTreeItem);
    2093                 :   }
    2094               0 : }
    2095                 : 
    2096                 : void
    2097               0 : nsWindowWatcher::GetWindowTreeOwner(nsIDOMWindow *inWindow,
    2098                 :                                     nsIDocShellTreeOwner **outTreeOwner)
    2099                 : {
    2100               0 :   *outTreeOwner = 0;
    2101                 : 
    2102               0 :   nsCOMPtr<nsIDocShellTreeItem> treeItem;
    2103               0 :   GetWindowTreeItem(inWindow, getter_AddRefs(treeItem));
    2104               0 :   if (treeItem)
    2105               0 :     treeItem->GetTreeOwner(outTreeOwner);
    2106               0 : }
    2107                 : 
    2108                 : JSContext *
    2109               0 : nsWindowWatcher::GetJSContextFromCallStack()
    2110                 : {
    2111               0 :   JSContext *cx = 0;
    2112                 : 
    2113               0 :   nsCOMPtr<nsIThreadJSContextStack> cxStack(do_GetService(sJSStackContractID));
    2114               0 :   if (cxStack)
    2115               0 :     cxStack->Peek(&cx);
    2116                 : 
    2117               0 :   return cx;
    2118                 : }
    2119                 : 
    2120                 : JSContext *
    2121               0 : nsWindowWatcher::GetJSContextFromWindow(nsIDOMWindow *aWindow)
    2122                 : {
    2123               0 :   JSContext *cx = 0;
    2124                 : 
    2125               0 :   if (aWindow) {
    2126               0 :     nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryInterface(aWindow));
    2127               0 :     if (sgo) {
    2128               0 :       nsIScriptContext *scx = sgo->GetContext();
    2129               0 :       if (scx)
    2130               0 :         cx = scx->GetNativeContext();
    2131                 :     }
    2132                 :     /* (off-topic note:) the nsIScriptContext can be retrieved by
    2133                 :     nsCOMPtr<nsIScriptContext> scx;
    2134                 :     nsJSUtils::GetDynamicScriptContext(cx, getter_AddRefs(scx));
    2135                 :     */
    2136                 :   }
    2137                 : 
    2138               0 :   return cx;
    2139                 : }

Generated by: LCOV version 1.7