LCOV - code coverage report
Current view: directory - dom/base - nsGlobalWindow.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 4594 34 0.7 %
Date: 2012-06-02 Functions: 426 7 1.6 %

       1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2                 : /* vim: set sw=2 ts=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) 1998
      21                 :  * the Initial Developer. All Rights Reserved.
      22                 :  *
      23                 :  * Contributor(s):
      24                 :  *   Travis Bogard <travis@netscape.com>
      25                 :  *   Brendan Eich <brendan@mozilla.org>
      26                 :  *   David Hyatt (hyatt@netscape.com)
      27                 :  *   Dan Rosen <dr@netscape.com>
      28                 :  *   Vidur Apparao <vidur@netscape.com>
      29                 :  *   Johnny Stenback <jst@netscape.com>
      30                 :  *   Mark Hammond <mhammond@skippinet.com.au>
      31                 :  *   Ryan Jones <sciguyryan@gmail.com>
      32                 :  *   Jeff Walden <jwalden+code@mit.edu>
      33                 :  *   Ben Bucksch <ben.bucksch  beonex.com>
      34                 :  *   Emanuele Costa <emanuele.costa@gmail.com>
      35                 :  *
      36                 :  * Alternatively, the contents of this file may be used under the terms of
      37                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      38                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      39                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      40                 :  * of those above. If you wish to allow use of your version of this file only
      41                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      42                 :  * use your version of this file under the terms of the MPL, indicate your
      43                 :  * decision by deleting the provisions above and replace them with the notice
      44                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      45                 :  * the provisions above, a recipient may use your version of this file under
      46                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      47                 :  *
      48                 :  * ***** END LICENSE BLOCK ***** */
      49                 : 
      50                 : #include "base/basictypes.h"
      51                 : 
      52                 : /* This must occur *after* base/basictypes.h to avoid typedefs conflicts. */
      53                 : #include "mozilla/Util.h"
      54                 : 
      55                 : // Local Includes
      56                 : #include "nsGlobalWindow.h"
      57                 : #include "Navigator.h"
      58                 : #include "nsScreen.h"
      59                 : #include "nsHistory.h"
      60                 : #include "nsPerformance.h"
      61                 : #include "nsDOMNavigationTiming.h"
      62                 : #include "nsBarProps.h"
      63                 : #include "nsDOMStorage.h"
      64                 : #include "nsDOMOfflineResourceList.h"
      65                 : #include "nsDOMError.h"
      66                 : 
      67                 : // Helper Classes
      68                 : #include "nsXPIDLString.h"
      69                 : #include "nsJSUtils.h"
      70                 : #include "prmem.h"
      71                 : #include "jsapi.h"              // for JSAutoRequest
      72                 : #include "jsdbgapi.h"           // for JS_ClearWatchPointsForObject
      73                 : #include "jsfriendapi.h"        // for JS_GetGlobalForFrame
      74                 : #include "nsReadableUtils.h"
      75                 : #include "nsDOMClassInfo.h"
      76                 : #include "nsJSEnvironment.h"
      77                 : #include "nsCharSeparatedTokenizer.h" // for Accept-Language parsing
      78                 : #include "nsUnicharUtils.h"
      79                 : #include "mozilla/Preferences.h"
      80                 : 
      81                 : // Other Classes
      82                 : #include "nsEventListenerManager.h"
      83                 : #include "nsEscape.h"
      84                 : #include "nsStyleCoord.h"
      85                 : #include "nsMimeTypeArray.h"
      86                 : #include "nsNetUtil.h"
      87                 : #include "nsICachingChannel.h"
      88                 : #include "nsPluginArray.h"
      89                 : #include "nsIPluginHost.h"
      90                 : #include "nsPluginHost.h"
      91                 : #include "nsIPluginInstanceOwner.h"
      92                 : #include "nsGeolocation.h"
      93                 : #include "nsDesktopNotification.h"
      94                 : #include "nsContentCID.h"
      95                 : #include "nsLayoutStatics.h"
      96                 : #include "nsCycleCollector.h"
      97                 : #include "nsCCUncollectableMarker.h"
      98                 : #include "nsAutoJSValHolder.h"
      99                 : #include "nsDOMMediaQueryList.h"
     100                 : #include "mozilla/dom/workers/Workers.h"
     101                 : 
     102                 : // Interfaces Needed
     103                 : #include "nsIFrame.h"
     104                 : #include "nsCanvasFrame.h"
     105                 : #include "nsIWidget.h"
     106                 : #include "nsIBaseWindow.h"
     107                 : #include "nsDeviceMotion.h"
     108                 : #include "nsIContent.h"
     109                 : #include "nsIContentViewerEdit.h"
     110                 : #include "nsIDocShell.h"
     111                 : #include "nsIDocShellLoadInfo.h"
     112                 : #include "nsIDocShellTreeItem.h"
     113                 : #include "nsIDocShellTreeNode.h"
     114                 : #include "nsIEditorDocShell.h"
     115                 : #include "nsIDocCharset.h"
     116                 : #include "nsIDocument.h"
     117                 : #include "nsIHTMLDocument.h"
     118                 : #include "nsIDOMHTMLDocument.h"
     119                 : #include "nsIDOMHTMLElement.h"
     120                 : #ifndef MOZ_DISABLE_DOMCRYPTO
     121                 : #include "nsIDOMCrypto.h"
     122                 : #endif
     123                 : #include "nsIDOMDocument.h"
     124                 : #include "nsIDOMElement.h"
     125                 : #include "nsIDOMEvent.h"
     126                 : #include "nsIDOMHTMLAnchorElement.h"
     127                 : #include "nsIDOMKeyEvent.h"
     128                 : #include "nsIDOMMessageEvent.h"
     129                 : #include "nsIDOMPopupBlockedEvent.h"
     130                 : #include "nsIDOMPopStateEvent.h"
     131                 : #include "nsIDOMHashChangeEvent.h"
     132                 : #include "nsIDOMOfflineResourceList.h"
     133                 : #include "nsIDOMGeoGeolocation.h"
     134                 : #include "nsIDOMDesktopNotification.h"
     135                 : #include "nsPIDOMStorage.h"
     136                 : #include "nsDOMString.h"
     137                 : #include "nsIEmbeddingSiteWindow2.h"
     138                 : #include "nsThreadUtils.h"
     139                 : #include "nsEventStateManager.h"
     140                 : #include "nsIHttpProtocolHandler.h"
     141                 : #include "nsIJSContextStack.h"
     142                 : #include "nsIJSRuntimeService.h"
     143                 : #include "nsIMarkupDocumentViewer.h"
     144                 : #include "nsIPrefBranch.h"
     145                 : #include "nsIPresShell.h"
     146                 : #include "nsIPrivateDOMEvent.h"
     147                 : #include "nsIProgrammingLanguage.h"
     148                 : #include "nsIServiceManager.h"
     149                 : #include "nsIScriptGlobalObjectOwner.h"
     150                 : #include "nsIScriptSecurityManager.h"
     151                 : #include "nsIScrollableFrame.h"
     152                 : #include "nsIView.h"
     153                 : #include "nsIViewManager.h"
     154                 : #include "nsISelectionController.h"
     155                 : #include "nsISelection.h"
     156                 : #include "nsIPrompt.h"
     157                 : #include "nsIPromptService.h"
     158                 : #include "nsIPromptFactory.h"
     159                 : #include "nsIWritablePropertyBag2.h"
     160                 : #include "nsIWebNavigation.h"
     161                 : #include "nsIWebBrowser.h"
     162                 : #include "nsIWebBrowserChrome.h"
     163                 : #include "nsIWebBrowserFind.h"  // For window.find()
     164                 : #include "nsIWebContentHandlerRegistrar.h"
     165                 : #include "nsIWindowMediator.h"  // For window.find()
     166                 : #include "nsComputedDOMStyle.h"
     167                 : #include "nsIEntropyCollector.h"
     168                 : #include "nsDOMCID.h"
     169                 : #include "nsDOMError.h"
     170                 : #include "nsDOMWindowUtils.h"
     171                 : #include "nsIWindowWatcher.h"
     172                 : #include "nsPIWindowWatcher.h"
     173                 : #include "nsIContentViewer.h"
     174                 : #include "nsIJSNativeInitializer.h"
     175                 : #include "nsIScriptError.h"
     176                 : #include "nsIConsoleService.h"
     177                 : #include "nsIControllers.h"
     178                 : #include "nsIControllerContext.h"
     179                 : #include "nsGlobalWindowCommands.h"
     180                 : #include "nsAutoPtr.h"
     181                 : #include "nsContentUtils.h"
     182                 : #include "nsCSSProps.h"
     183                 : #include "nsBlobProtocolHandler.h"
     184                 : #include "nsIDOMFile.h"
     185                 : #include "nsIDOMFileList.h"
     186                 : #include "nsIURIFixup.h"
     187                 : #include "mozilla/FunctionTimer.h"
     188                 : #include "nsCDefaultURIFixup.h"
     189                 : #include "nsEventDispatcher.h"
     190                 : #include "nsIObserverService.h"
     191                 : #include "nsIXULAppInfo.h"
     192                 : #include "nsNetUtil.h"
     193                 : #include "nsFocusManager.h"
     194                 : #include "nsIXULWindow.h"
     195                 : #include "nsEventStateManager.h"
     196                 : #include "nsITimedChannel.h"
     197                 : #include "nsICookiePermission.h"
     198                 : #include "nsServiceManagerUtils.h"
     199                 : #ifdef MOZ_XUL
     200                 : #include "nsXULPopupManager.h"
     201                 : #include "nsIDOMXULControlElement.h"
     202                 : #include "nsMenuPopupFrame.h"
     203                 : #endif
     204                 : 
     205                 : #include "xpcprivate.h"
     206                 : 
     207                 : #ifdef NS_PRINTING
     208                 : #include "nsIPrintSettings.h"
     209                 : #include "nsIPrintSettingsService.h"
     210                 : #include "nsIWebBrowserPrint.h"
     211                 : #endif
     212                 : 
     213                 : #include "nsWindowRoot.h"
     214                 : #include "nsNetCID.h"
     215                 : #include "nsIArray.h"
     216                 : #include "nsIScriptRuntime.h"
     217                 : 
     218                 : // XXX An unfortunate dependency exists here (two XUL files).
     219                 : #include "nsIDOMXULDocument.h"
     220                 : #include "nsIDOMXULCommandDispatcher.h"
     221                 : 
     222                 : #include "nsBindingManager.h"
     223                 : #include "nsIXBLService.h"
     224                 : 
     225                 : // used for popup blocking, needs to be converted to something
     226                 : // belonging to the back-end like nsIContentPolicy
     227                 : #include "nsIPopupWindowManager.h"
     228                 : 
     229                 : #include "nsIDragService.h"
     230                 : #include "mozilla/dom/Element.h"
     231                 : #include "nsFrameLoader.h"
     232                 : #include "nsISupportsPrimitives.h"
     233                 : #include "nsXPCOMCID.h"
     234                 : 
     235                 : #include "mozilla/FunctionTimer.h"
     236                 : #include "mozIThirdPartyUtil.h"
     237                 : 
     238                 : #ifdef MOZ_LOGGING
     239                 : // so we can get logging even in release builds
     240                 : #define FORCE_PR_LOG 1
     241                 : #endif
     242                 : #include "prlog.h"
     243                 : #include "prenv.h"
     244                 : 
     245                 : #include "mozilla/dom/indexedDB/IDBFactory.h"
     246                 : #include "mozilla/dom/indexedDB/IndexedDatabaseManager.h"
     247                 : 
     248                 : #include "mozilla/dom/StructuredCloneTags.h"
     249                 : 
     250                 : #include "nsRefreshDriver.h"
     251                 : #include "mozAutoDocUpdate.h"
     252                 : 
     253                 : #include "mozilla/Telemetry.h"
     254                 : #include "nsLocation.h"
     255                 : #include "nsWrapperCacheInlines.h"
     256                 : #include "nsDOMEventTargetHelper.h"
     257                 : 
     258                 : #ifdef ANDROID
     259                 : #include <android/log.h>
     260                 : #endif
     261                 : 
     262                 : #ifdef PR_LOGGING
     263                 : static PRLogModuleInfo* gDOMLeakPRLog;
     264                 : #endif
     265                 : 
     266                 : static const char kStorageEnabled[] = "dom.storage.enabled";
     267                 : 
     268                 : using namespace mozilla;
     269                 : using namespace mozilla::dom;
     270                 : using mozilla::TimeStamp;
     271                 : using mozilla::TimeDuration;
     272                 : 
     273                 : nsGlobalWindow::WindowByIdTable *nsGlobalWindow::sWindowsById = nsnull;
     274                 : bool nsGlobalWindow::sWarnedAboutWindowInternal = false;
     275                 : 
     276                 : static nsIEntropyCollector *gEntropyCollector          = nsnull;
     277                 : static PRInt32              gRefCnt                    = 0;
     278                 : static PRInt32              gOpenPopupSpamCount        = 0;
     279                 : static PopupControlState    gPopupControlState         = openAbused;
     280                 : static PRInt32              gRunningTimeoutDepth       = 0;
     281                 : static bool                 gMouseDown                 = false;
     282                 : static bool                 gDragServiceDisabled       = false;
     283                 : static FILE                *gDumpFile                  = nsnull;
     284                 : static PRUint64             gNextWindowID              = 0;
     285                 : static PRUint32             gSerialCounter             = 0;
     286                 : static PRUint32             gTimeoutsRecentlySet       = 0;
     287            1464 : static TimeStamp            gLastRecordedRecentTimeouts;
     288                 : #define STATISTICS_INTERVAL (30 * PR_MSEC_PER_SEC)
     289                 : 
     290                 : #ifdef DEBUG_jst
     291                 : PRInt32 gTimeoutCnt                                    = 0;
     292                 : #endif
     293                 : 
     294                 : #if !(defined(NS_DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
     295                 : static bool                 gDOMWindowDumpEnabled      = false;
     296                 : #endif
     297                 : 
     298                 : #if defined(DEBUG_bryner) || defined(DEBUG_chb)
     299                 : #define DEBUG_PAGE_CACHE
     300                 : #endif
     301                 : 
     302                 : #define DOM_TOUCH_LISTENER_ADDED "dom-touch-listener-added"
     303                 : 
     304                 : // The default shortest interval/timeout we permit
     305                 : #define DEFAULT_MIN_TIMEOUT_VALUE 4 // 4ms
     306                 : #define DEFAULT_MIN_BACKGROUND_TIMEOUT_VALUE 1000 // 1000ms
     307                 : static PRInt32 gMinTimeoutValue;
     308                 : static PRInt32 gMinBackgroundTimeoutValue;
     309                 : inline PRInt32
     310               0 : nsGlobalWindow::DOMMinTimeoutValue() const {
     311               0 :   bool isBackground = !mOuterWindow || mOuterWindow->IsBackground();
     312                 :   return
     313               0 :     NS_MAX(isBackground ? gMinBackgroundTimeoutValue : gMinTimeoutValue, 0);
     314                 : }
     315                 : 
     316                 : // The number of nested timeouts before we start clamping. HTML5 says 1, WebKit
     317                 : // uses 5.
     318                 : #define DOM_CLAMP_TIMEOUT_NESTING_LEVEL 5
     319                 : 
     320                 : // The longest interval (as PRIntervalTime) we permit, or that our
     321                 : // timer code can handle, really. See DELAY_INTERVAL_LIMIT in
     322                 : // nsTimerImpl.h for details.
     323                 : #define DOM_MAX_TIMEOUT_VALUE    DELAY_INTERVAL_LIMIT
     324                 : 
     325                 : #define FORWARD_TO_OUTER(method, args, err_rval)                              \
     326                 :   PR_BEGIN_MACRO                                                              \
     327                 :   if (IsInnerWindow()) {                                                      \
     328                 :     nsGlobalWindow *outer = GetOuterWindowInternal();                         \
     329                 :     if (!outer) {                                                             \
     330                 :       NS_WARNING("No outer window available!");                               \
     331                 :       return err_rval;                                                        \
     332                 :     }                                                                         \
     333                 :     return outer->method args;                                                \
     334                 :   }                                                                           \
     335                 :   PR_END_MACRO
     336                 : 
     337                 : #define FORWARD_TO_OUTER_VOID(method, args)                                   \
     338                 :   PR_BEGIN_MACRO                                                              \
     339                 :   if (IsInnerWindow()) {                                                      \
     340                 :     nsGlobalWindow *outer = GetOuterWindowInternal();                         \
     341                 :     if (!outer) {                                                             \
     342                 :       NS_WARNING("No outer window available!");                               \
     343                 :       return;                                                                 \
     344                 :     }                                                                         \
     345                 :     outer->method args;                                                       \
     346                 :     return;                                                                   \
     347                 :   }                                                                           \
     348                 :   PR_END_MACRO
     349                 : 
     350                 : #define FORWARD_TO_OUTER_CHROME(method, args, err_rval)                       \
     351                 :   PR_BEGIN_MACRO                                                              \
     352                 :   if (IsInnerWindow()) {                                                      \
     353                 :     nsGlobalWindow *outer = GetOuterWindowInternal();                         \
     354                 :     if (!outer) {                                                             \
     355                 :       NS_WARNING("No outer window available!");                               \
     356                 :       return err_rval;                                                        \
     357                 :     }                                                                         \
     358                 :     return ((nsGlobalChromeWindow *)outer)->method args;                      \
     359                 :   }                                                                           \
     360                 :   PR_END_MACRO
     361                 : 
     362                 : #define FORWARD_TO_INNER_CHROME(method, args, err_rval)                       \
     363                 :   PR_BEGIN_MACRO                                                              \
     364                 :   if (IsOuterWindow()) {                                                      \
     365                 :     if (!mInnerWindow) {                                                      \
     366                 :       NS_WARNING("No inner window available!");                               \
     367                 :       return err_rval;                                                        \
     368                 :     }                                                                         \
     369                 :     return ((nsGlobalChromeWindow *)mInnerWindow)->method args;               \
     370                 :   }                                                                           \
     371                 :   PR_END_MACRO
     372                 : 
     373                 : #define FORWARD_TO_OUTER_MODAL_CONTENT_WINDOW(method, args, err_rval)         \
     374                 :   PR_BEGIN_MACRO                                                              \
     375                 :   if (IsInnerWindow()) {                                                      \
     376                 :     nsGlobalWindow *outer = GetOuterWindowInternal();                         \
     377                 :     if (!outer) {                                                             \
     378                 :       NS_WARNING("No outer window available!");                               \
     379                 :       return err_rval;                                                        \
     380                 :     }                                                                         \
     381                 :     return ((nsGlobalModalWindow *)outer)->method args;                       \
     382                 :   }                                                                           \
     383                 :   PR_END_MACRO
     384                 : 
     385                 : #define FORWARD_TO_INNER(method, args, err_rval)                              \
     386                 :   PR_BEGIN_MACRO                                                              \
     387                 :   if (IsOuterWindow()) {                                                      \
     388                 :     if (!mInnerWindow) {                                                      \
     389                 :       NS_WARNING("No inner window available!");                               \
     390                 :       return err_rval;                                                        \
     391                 :     }                                                                         \
     392                 :     return GetCurrentInnerWindowInternal()->method args;                      \
     393                 :   }                                                                           \
     394                 :   PR_END_MACRO
     395                 : 
     396                 : #define FORWARD_TO_INNER_MODAL_CONTENT_WINDOW(method, args, err_rval)         \
     397                 :   PR_BEGIN_MACRO                                                              \
     398                 :   if (IsOuterWindow()) {                                                      \
     399                 :     if (!mInnerWindow) {                                                      \
     400                 :       NS_WARNING("No inner window available!");                               \
     401                 :       return err_rval;                                                        \
     402                 :     }                                                                         \
     403                 :     return ((nsGlobalModalWindow*)GetCurrentInnerWindowInternal())->method args; \
     404                 :   }                                                                           \
     405                 :   PR_END_MACRO
     406                 : 
     407                 : #define FORWARD_TO_INNER_VOID(method, args)                                   \
     408                 :   PR_BEGIN_MACRO                                                              \
     409                 :   if (IsOuterWindow()) {                                                      \
     410                 :     if (!mInnerWindow) {                                                      \
     411                 :       NS_WARNING("No inner window available!");                               \
     412                 :       return;                                                                 \
     413                 :     }                                                                         \
     414                 :     GetCurrentInnerWindowInternal()->method args;                             \
     415                 :     return;                                                                   \
     416                 :   }                                                                           \
     417                 :   PR_END_MACRO
     418                 : 
     419                 : // Same as FORWARD_TO_INNER, but this will create a fresh inner if an
     420                 : // inner doesn't already exists.
     421                 : #define FORWARD_TO_INNER_CREATE(method, args, err_rval)                       \
     422                 :   PR_BEGIN_MACRO                                                              \
     423                 :   if (IsOuterWindow()) {                                                      \
     424                 :     if (!mInnerWindow) {                                                      \
     425                 :       if (mIsClosed) {                                                        \
     426                 :         return err_rval;                                                      \
     427                 :       }                                                                       \
     428                 :       nsCOMPtr<nsIDOMDocument> doc;                                           \
     429                 :       nsresult fwdic_nr = GetDocument(getter_AddRefs(doc));                   \
     430                 :       NS_ENSURE_SUCCESS(fwdic_nr, err_rval);                                  \
     431                 :       if (!mInnerWindow) {                                                    \
     432                 :         return err_rval;                                                      \
     433                 :       }                                                                       \
     434                 :     }                                                                         \
     435                 :     return GetCurrentInnerWindowInternal()->method args;                      \
     436                 :   }                                                                           \
     437                 :   PR_END_MACRO
     438                 : 
     439                 : // CIDs
     440                 : static NS_DEFINE_CID(kXULControllersCID, NS_XULCONTROLLERS_CID);
     441                 : 
     442                 : static const char sJSStackContractID[] = "@mozilla.org/js/xpc/ContextStack;1";
     443                 : #ifndef MOZ_DISABLE_DOMCRYPTO
     444                 : static const char kCryptoContractID[] = NS_CRYPTO_CONTRACTID;
     445                 : static const char kPkcs11ContractID[] = NS_PKCS11_CONTRACTID;
     446                 : #endif
     447                 : static const char sPopStatePrefStr[] = "browser.history.allowPopState";
     448                 : 
     449                 : class nsDummyJavaPluginOwner : public nsIPluginInstanceOwner
     450               0 : {
     451                 : public:
     452               0 :   nsDummyJavaPluginOwner(nsIDocument *aDocument)
     453               0 :     : mDocument(aDocument)
     454                 :   {
     455               0 :   }
     456                 : 
     457                 :   void Destroy();
     458                 : 
     459               0 :   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
     460                 :   NS_DECL_NSIPLUGININSTANCEOWNER
     461                 : 
     462                 :   NS_IMETHOD GetURL(const char *aURL, const char *aTarget,
     463                 :                     nsIInputStream *aPostStream,
     464                 :                     void *aHeadersData, PRUint32 aHeadersDataLen);
     465                 :   NS_IMETHOD ShowStatus(const PRUnichar *aStatusMsg);
     466                 :   NPError ShowNativeContextMenu(NPMenu* menu, void* event);
     467                 :   NPBool ConvertPoint(double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
     468                 :                       double *destX, double *destY, NPCoordinateSpace destSpace);
     469                 :   void SendIdleEvent();
     470                 :   
     471               0 :   NPError InitAsyncSurface(NPSize *size, NPImageFormat format,
     472                 :                            void *initData, NPAsyncSurface *surface)
     473               0 :   { return NPERR_GENERIC_ERROR; }
     474                 : 
     475               0 :   NPError FinalizeAsyncSurface(NPAsyncSurface *surface) { return NPERR_GENERIC_ERROR; }
     476               0 :   void SetCurrentAsyncSurface(NPAsyncSurface *surface, NPRect *changed) { return; }
     477                 : 
     478            1464 :   NS_DECL_CYCLE_COLLECTION_CLASS(nsDummyJavaPluginOwner)
     479                 : 
     480                 : private:
     481                 :   nsRefPtr<nsNPAPIPluginInstance> mInstance;
     482                 :   nsCOMPtr<nsIDocument> mDocument;
     483                 : };
     484                 : 
     485            1464 : NS_IMPL_CYCLE_COLLECTION_2(nsDummyJavaPluginOwner, mDocument, mInstance)
     486                 : 
     487                 : // QueryInterface implementation for nsDummyJavaPluginOwner
     488               0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDummyJavaPluginOwner)
     489               0 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
     490               0 :   NS_INTERFACE_MAP_ENTRY(nsIPluginInstanceOwner)
     491               0 : NS_INTERFACE_MAP_END
     492                 : 
     493               0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDummyJavaPluginOwner)
     494               0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDummyJavaPluginOwner)
     495                 : 
     496                 : 
     497                 : void
     498               0 : nsDummyJavaPluginOwner::Destroy()
     499                 : {
     500                 :   // If we have a plugin instance, stop it and destroy it now.
     501               0 :   if (mInstance) {
     502               0 :     mInstance->Stop();
     503               0 :     mInstance->InvalidateOwner();
     504               0 :     mInstance = nsnull;
     505                 :   }
     506                 : 
     507               0 :   mDocument = nsnull;
     508               0 : }
     509                 : 
     510                 : NS_IMETHODIMP
     511               0 : nsDummyJavaPluginOwner::SetInstance(nsNPAPIPluginInstance *aInstance)
     512                 : {
     513                 :   // If we're going to null out mInstance after use, be sure to call
     514                 :   // mInstance->InvalidateOwner() here, since it now won't be called
     515                 :   // from nsDummyJavaPluginOwner::Destroy().
     516               0 :   if (mInstance && !aInstance)
     517               0 :     mInstance->InvalidateOwner();
     518                 : 
     519               0 :   mInstance = aInstance;
     520                 : 
     521               0 :   return NS_OK;
     522                 : }
     523                 : 
     524                 : NS_IMETHODIMP
     525               0 : nsDummyJavaPluginOwner::GetInstance(nsNPAPIPluginInstance **aInstance)
     526                 : {
     527               0 :   *aInstance = mInstance;
     528               0 :   NS_IF_ADDREF(*aInstance);
     529                 : 
     530               0 :   return NS_OK;
     531                 : }
     532                 : 
     533                 : NS_IMETHODIMP
     534               0 : nsDummyJavaPluginOwner::GetWindow(NPWindow *&aWindow)
     535                 : {
     536               0 :   aWindow = nsnull;
     537                 : 
     538               0 :   return NS_OK;
     539                 : }
     540                 : 
     541                 : NS_IMETHODIMP
     542               0 : nsDummyJavaPluginOwner::CallSetWindow()
     543                 : {
     544               0 :   return NS_ERROR_NOT_IMPLEMENTED;
     545                 : }
     546                 : 
     547                 : NS_IMETHODIMP
     548               0 : nsDummyJavaPluginOwner::GetMode(PRInt32 *aMode)
     549                 : {
     550                 :   // This is wrong, but there's no better alternative.
     551               0 :   *aMode = NP_EMBED;
     552                 : 
     553               0 :   return NS_ERROR_NOT_IMPLEMENTED;
     554                 : }
     555                 : 
     556                 : NS_IMETHODIMP
     557               0 : nsDummyJavaPluginOwner::CreateWidget(void)
     558                 : {
     559               0 :   return NS_ERROR_NOT_IMPLEMENTED;
     560                 : }
     561                 : 
     562                 : NS_IMETHODIMP
     563               0 : nsDummyJavaPluginOwner::GetURL(const char *aURL, const char *aTarget,
     564                 :                                nsIInputStream *aPostStream,
     565                 :                                void *aHeadersData, PRUint32 aHeadersDataLen)
     566                 : {
     567               0 :   return NS_ERROR_NOT_IMPLEMENTED;
     568                 : }
     569                 : 
     570                 : NS_IMETHODIMP
     571               0 : nsDummyJavaPluginOwner::ShowStatus(const char *aStatusMsg)
     572                 : {
     573               0 :   return NS_ERROR_NOT_IMPLEMENTED;
     574                 : }
     575                 : 
     576                 : NS_IMETHODIMP
     577               0 : nsDummyJavaPluginOwner::ShowStatus(const PRUnichar *aStatusMsg)
     578                 : {
     579               0 :   return NS_ERROR_NOT_IMPLEMENTED;
     580                 : }
     581                 : 
     582                 : NPError
     583               0 : nsDummyJavaPluginOwner::ShowNativeContextMenu(NPMenu* menu, void* event)
     584                 : {
     585               0 :   return NPERR_GENERIC_ERROR;
     586                 : }
     587                 : 
     588                 : NPBool
     589               0 : nsDummyJavaPluginOwner::ConvertPoint(double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
     590                 :                                      double *destX, double *destY, NPCoordinateSpace destSpace)
     591                 : {
     592               0 :   return false;
     593                 : }
     594                 : 
     595                 : NS_IMETHODIMP
     596               0 : nsDummyJavaPluginOwner::GetDocument(nsIDocument **aDocument)
     597                 : {
     598               0 :   NS_IF_ADDREF(*aDocument = mDocument);
     599                 : 
     600               0 :   return NS_OK;
     601                 : }
     602                 : 
     603                 : NS_IMETHODIMP
     604               0 : nsDummyJavaPluginOwner::InvalidateRect(NPRect *invalidRect)
     605                 : {
     606               0 :   return NS_ERROR_NOT_IMPLEMENTED;
     607                 : }
     608                 : 
     609                 : NS_IMETHODIMP
     610               0 : nsDummyJavaPluginOwner::InvalidateRegion(NPRegion invalidRegion)
     611                 : {
     612               0 :   return NS_ERROR_NOT_IMPLEMENTED;
     613                 : }
     614                 : 
     615                 : NS_IMETHODIMP
     616               0 : nsDummyJavaPluginOwner::RedrawPlugin()
     617                 : {
     618               0 :   return NS_ERROR_NOT_IMPLEMENTED;
     619                 : }
     620                 : 
     621                 : NS_IMETHODIMP
     622               0 : nsDummyJavaPluginOwner::GetNetscapeWindow(void *value)
     623                 : {
     624               0 :   return NS_ERROR_NOT_IMPLEMENTED;
     625                 : }
     626                 : 
     627                 : NS_IMETHODIMP
     628               0 : nsDummyJavaPluginOwner::SetEventModel(PRInt32 eventModel)
     629                 : {
     630               0 :   return NS_ERROR_NOT_IMPLEMENTED;
     631                 : }
     632                 : 
     633                 : void
     634               0 : nsDummyJavaPluginOwner::SendIdleEvent()
     635                 : {
     636               0 : }
     637                 : 
     638                 : /**
     639                 :  * An object implementing the window.URL property.
     640                 :  */
     641                 : class nsDOMMozURLProperty : public nsIDOMMozURLProperty
     642                 : {
     643                 : public:
     644               0 :   nsDOMMozURLProperty(nsGlobalWindow* aWindow)
     645               0 :     : mWindow(aWindow)
     646                 :   {
     647               0 :   }
     648                 : 
     649                 :   NS_DECL_ISUPPORTS
     650                 :   NS_DECL_NSIDOMMOZURLPROPERTY
     651                 : 
     652               0 :   void ClearWindowReference() {
     653               0 :     mWindow = nsnull;
     654               0 :   }
     655                 : private:
     656                 :   nsGlobalWindow* mWindow;
     657                 : };
     658                 : 
     659                 : DOMCI_DATA(MozURLProperty, nsDOMMozURLProperty)
     660               0 : NS_IMPL_ADDREF(nsDOMMozURLProperty)
     661               0 : NS_IMPL_RELEASE(nsDOMMozURLProperty)
     662               0 : NS_INTERFACE_MAP_BEGIN(nsDOMMozURLProperty)
     663               0 :     NS_INTERFACE_MAP_ENTRY(nsIDOMMozURLProperty)
     664               0 :     NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMMozURLProperty)
     665               0 :     NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MozURLProperty)
     666               0 : NS_INTERFACE_MAP_END
     667                 : 
     668                 : NS_IMETHODIMP
     669               0 : nsDOMMozURLProperty::CreateObjectURL(nsIDOMBlob* aBlob, nsAString& aURL)
     670                 : {
     671               0 :   NS_PRECONDITION(!mWindow || mWindow->IsInnerWindow(),
     672                 :                   "Should be inner window");
     673                 : 
     674               0 :   NS_ENSURE_STATE(mWindow && mWindow->mDoc);
     675               0 :   NS_ENSURE_ARG_POINTER(aBlob);
     676                 : 
     677               0 :   nsIDocument* doc = mWindow->mDoc;
     678                 : 
     679               0 :   nsresult rv = aBlob->GetInternalUrl(doc->NodePrincipal(), aURL);
     680               0 :   NS_ENSURE_SUCCESS(rv, rv);
     681                 : 
     682               0 :   doc->RegisterFileDataUri(NS_LossyConvertUTF16toASCII(aURL));
     683                 : 
     684               0 :   return NS_OK;
     685                 : }
     686                 : 
     687                 : NS_IMETHODIMP
     688               0 : nsDOMMozURLProperty::RevokeObjectURL(const nsAString& aURL)
     689                 : {
     690               0 :   NS_PRECONDITION(!mWindow || mWindow->IsInnerWindow(),
     691                 :                   "Should be inner window");
     692                 : 
     693               0 :   NS_ENSURE_STATE(mWindow);
     694                 : 
     695               0 :   NS_LossyConvertUTF16toASCII asciiurl(aURL);
     696                 : 
     697               0 :   nsIPrincipal* winPrincipal = mWindow->GetPrincipal();
     698               0 :   if (!winPrincipal) {
     699               0 :     return NS_OK;
     700                 :   }
     701                 : 
     702                 :   nsIPrincipal* principal =
     703               0 :     nsBlobProtocolHandler::GetFileDataEntryPrincipal(asciiurl);
     704                 :   bool subsumes;
     705               0 :   if (principal && winPrincipal &&
     706               0 :       NS_SUCCEEDED(winPrincipal->Subsumes(principal, &subsumes)) &&
     707                 :       subsumes) {
     708               0 :     if (mWindow->mDoc) {
     709               0 :       mWindow->mDoc->UnregisterFileDataUri(asciiurl);
     710                 :     }
     711               0 :     nsBlobProtocolHandler::RemoveFileDataEntry(asciiurl);
     712                 :   }
     713                 : 
     714               0 :   return NS_OK;
     715                 : }
     716                 : 
     717                 : /**
     718                 :  * An indirect observer object that means we don't have to implement nsIObserver
     719                 :  * on nsGlobalWindow, where any script could see it.
     720                 :  */
     721                 : class nsGlobalWindowObserver : public nsIObserver {
     722                 : public:
     723               0 :   nsGlobalWindowObserver(nsGlobalWindow* aWindow) : mWindow(aWindow) {}
     724                 :   NS_DECL_ISUPPORTS
     725               0 :   NS_IMETHOD Observe(nsISupports* aSubject, const char* aTopic, const PRUnichar* aData)
     726                 :   {
     727               0 :     if (!mWindow)
     728               0 :       return NS_OK;
     729               0 :     return mWindow->Observe(aSubject, aTopic, aData);
     730                 :   }
     731               0 :   void Forget() { mWindow = nsnull; }
     732                 : private:
     733                 :   nsGlobalWindow* mWindow;
     734                 : };
     735                 : 
     736               0 : NS_IMPL_ISUPPORTS1(nsGlobalWindowObserver, nsIObserver)
     737                 : 
     738               0 : nsTimeout::nsTimeout()
     739                 : {
     740                 : #ifdef DEBUG_jst
     741                 :   {
     742                 :     extern int gTimeoutCnt;
     743                 : 
     744                 :     ++gTimeoutCnt;
     745                 :   }
     746                 : #endif
     747                 : 
     748               0 :   memset(this, 0, sizeof(*this));
     749                 : 
     750               0 :   MOZ_COUNT_CTOR(nsTimeout);
     751               0 : }
     752                 : 
     753               0 : nsTimeout::~nsTimeout()
     754                 : {
     755                 : #ifdef DEBUG_jst
     756                 :   {
     757                 :     extern int gTimeoutCnt;
     758                 : 
     759                 :     --gTimeoutCnt;
     760                 :   }
     761                 : #endif
     762                 : 
     763               0 :   MOZ_COUNT_DTOR(nsTimeout);
     764               0 : }
     765                 : 
     766            1464 : NS_IMPL_CYCLE_COLLECTION_CLASS(nsTimeout)
     767               0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_NATIVE_0(nsTimeout)
     768               0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_BEGIN(nsTimeout)
     769               0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mWindow,
     770                 :                                                        nsIScriptGlobalObject)
     771               0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mPrincipal)
     772               0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mScriptHandler)
     773               0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
     774               0 : NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsTimeout, AddRef)
     775               0 : NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsTimeout, Release)
     776                 : 
     777               0 : nsPIDOMWindow::nsPIDOMWindow(nsPIDOMWindow *aOuterWindow)
     778                 : : mFrameElement(nsnull), mDocShell(nsnull), mModalStateDepth(0),
     779                 :   mRunningTimeout(nsnull), mMutationBits(0), mIsDocumentLoaded(false),
     780                 :   mIsHandlingResizeEvent(false), mIsInnerWindow(aOuterWindow != nsnull),
     781                 :   mMayHavePaintEventListener(false), mMayHaveTouchEventListener(false),
     782                 :   mMayHaveMouseEnterLeaveEventListener(false),
     783                 :   mIsModalContentWindow(false),
     784                 :   mIsActive(false), mIsBackground(false),
     785                 :   mInnerWindow(nsnull), mOuterWindow(aOuterWindow),
     786                 :   // Make sure no actual window ends up with mWindowID == 0
     787               0 :   mWindowID(++gNextWindowID), mHasNotifiedGlobalCreated(false)
     788               0 :  {}
     789                 : 
     790               0 : nsPIDOMWindow::~nsPIDOMWindow() {}
     791                 : 
     792                 : //*****************************************************************************
     793                 : // nsOuterWindowProxy: Outer Window Proxy
     794                 : //*****************************************************************************
     795                 : 
     796                 : JSString *
     797               0 : nsOuterWindowProxy::obj_toString(JSContext *cx, JSObject *proxy)
     798                 : {
     799               0 :     JS_ASSERT(js::IsProxy(proxy));
     800                 : 
     801               0 :     return JS_NewStringCopyZ(cx, "[object Window]");
     802                 : }
     803                 : 
     804                 : void
     805               0 : nsOuterWindowProxy::finalize(JSContext *cx, JSObject *proxy)
     806                 : {
     807                 :   nsISupports *global =
     808               0 :     static_cast<nsISupports*>(js::GetProxyExtra(proxy, 0).toPrivate());
     809               0 :   if (global) {
     810                 :     nsWrapperCache *cache;
     811               0 :     CallQueryInterface(global, &cache);
     812               0 :     cache->ClearWrapperIfProxy();
     813                 :   }
     814               0 : }
     815                 : 
     816                 : nsOuterWindowProxy
     817            1464 : nsOuterWindowProxy::singleton;
     818                 : 
     819                 : JSObject *
     820               0 : NS_NewOuterWindowProxy(JSContext *cx, JSObject *parent)
     821                 : {
     822               0 :   JSAutoEnterCompartment ac;
     823               0 :   if (!ac.enter(cx, parent)) {
     824               0 :     return nsnull;
     825                 :   }
     826                 : 
     827                 :   JSObject *obj = js::Wrapper::New(cx, parent, js::GetObjectProto(parent), parent,
     828               0 :                                    &nsOuterWindowProxy::singleton);
     829               0 :   NS_ASSERTION(js::GetObjectClass(obj)->ext.innerObject, "bad class");
     830               0 :   return obj;
     831                 : }
     832                 : 
     833                 : //*****************************************************************************
     834                 : //***    nsGlobalWindow: Object Management
     835                 : //*****************************************************************************
     836                 : 
     837               0 : nsGlobalWindow::nsGlobalWindow(nsGlobalWindow *aOuterWindow)
     838                 :   : nsPIDOMWindow(aOuterWindow),
     839                 :     mIsFrozen(false),
     840                 :     mDidInitJavaProperties(false),
     841                 :     mFullScreen(false),
     842                 :     mIsClosed(false), 
     843                 :     mInClose(false), 
     844                 :     mHavePendingClose(false),
     845                 :     mHadOriginalOpener(false),
     846                 :     mIsPopupSpam(false),
     847                 :     mBlockScriptedClosingFlag(false),
     848                 :     mFireOfflineStatusChangeEventOnThaw(false),
     849                 :     mCreatingInnerWindow(false),
     850                 :     mIsChrome(false),
     851                 :     mCleanMessageManager(false),
     852                 :     mNeedsFocus(true),
     853                 :     mHasFocus(false),
     854                 : #if defined(XP_MACOSX)
     855                 :     mShowAccelerators(false),
     856                 :     mShowFocusRings(false),
     857                 : #else
     858                 :     mShowAccelerators(true),
     859                 :     mShowFocusRings(true),
     860                 : #endif
     861                 :     mShowFocusRingForContent(false),
     862                 :     mFocusByKeyOccurred(false),
     863                 :     mHasDeviceMotion(false),
     864                 :     mNotifiedIDDestroyed(false),
     865                 :     mTimeoutInsertionPoint(nsnull),
     866                 :     mTimeoutPublicIdCounter(1),
     867                 :     mTimeoutFiringDepth(0),
     868                 :     mJSObject(nsnull),
     869                 :     mPendingStorageEventsObsolete(nsnull),
     870                 :     mTimeoutsSuspendDepth(0),
     871                 :     mFocusMethod(0),
     872                 :     mSerial(0),
     873                 : #ifdef DEBUG
     874                 :     mSetOpenerWindowCalled(false),
     875                 : #endif
     876                 :     mCleanedUp(false),
     877                 :     mCallCleanUpAfterModalDialogCloses(false),
     878                 :     mDialogAbuseCount(0),
     879               0 :     mDialogDisabled(false)
     880                 : {
     881               0 :   nsLayoutStatics::AddRef();
     882                 : 
     883                 :   // Initialize the PRCList (this).
     884               0 :   PR_INIT_CLIST(this);
     885                 : 
     886                 :   // Initialize timeout storage
     887               0 :   PR_INIT_CLIST(&mTimeouts);
     888                 : 
     889               0 :   if (aOuterWindow) {
     890                 :     // |this| is an inner window, add this inner window to the outer
     891                 :     // window list of inners.
     892               0 :     PR_INSERT_AFTER(this, aOuterWindow);
     893                 : 
     894               0 :     mObserver = new nsGlobalWindowObserver(this);
     895               0 :     if (mObserver) {
     896               0 :       NS_ADDREF(mObserver);
     897               0 :       nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
     898               0 :       if (os) {
     899                 :         // Watch for online/offline status changes so we can fire events. Use
     900                 :         // a strong reference.
     901               0 :         os->AddObserver(mObserver, NS_IOSERVICE_OFFLINE_STATUS_TOPIC,
     902               0 :                         false);
     903                 : 
     904                 :         // Watch for dom-storage-changed so we can fire storage
     905                 :         // events. Use a strong reference.
     906               0 :         os->AddObserver(mObserver, "dom-storage2-changed", false);
     907               0 :         os->AddObserver(mObserver, "dom-storage-changed", false);
     908                 :       }
     909                 :     }
     910                 :   } else {
     911                 :     // |this| is an outer window. Outer windows start out frozen and
     912                 :     // remain frozen until they get an inner window, so freeze this
     913                 :     // outer window here.
     914               0 :     Freeze();
     915                 : 
     916               0 :     mObserver = nsnull;
     917               0 :     SetIsProxy();
     918                 :   }
     919                 : 
     920                 :   // We could have failed the first time through trying
     921                 :   // to create the entropy collector, so we should
     922                 :   // try to get one until we succeed.
     923                 : 
     924               0 :   gRefCnt++;
     925                 : 
     926               0 :   if (gRefCnt == 1) {
     927                 : #if !(defined(NS_DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
     928                 :     Preferences::AddBoolVarCache(&gDOMWindowDumpEnabled,
     929                 :                                  "browser.dom.window.dump.enabled");
     930                 : #endif
     931                 :     Preferences::AddIntVarCache(&gMinTimeoutValue,
     932                 :                                 "dom.min_timeout_value",
     933               0 :                                 DEFAULT_MIN_TIMEOUT_VALUE);
     934                 :     Preferences::AddIntVarCache(&gMinBackgroundTimeoutValue,
     935                 :                                 "dom.min_background_timeout_value",
     936               0 :                                 DEFAULT_MIN_BACKGROUND_TIMEOUT_VALUE);
     937                 :   }
     938                 : 
     939               0 :   if (gDumpFile == nsnull) {
     940                 :     const nsAdoptingCString& fname =
     941               0 :       Preferences::GetCString("browser.dom.window.dump.file");
     942               0 :     if (!fname.IsEmpty()) {
     943                 :       // if this fails to open, Dump() knows to just go to stdout
     944                 :       // on null.
     945               0 :       gDumpFile = fopen(fname, "wb+");
     946                 :     } else {
     947               0 :       gDumpFile = stdout;
     948                 :     }
     949                 :   }
     950                 : 
     951               0 :   mSerial = ++gSerialCounter;
     952                 : 
     953                 : #ifdef DEBUG
     954               0 :   if (!PR_GetEnv("MOZ_QUIET")) {
     955                 :     printf("++DOMWINDOW == %d (%p) [serial = %d] [outer = %p]\n", gRefCnt,
     956                 :            static_cast<void*>(static_cast<nsIScriptGlobalObject*>(this)),
     957               0 :            gSerialCounter, static_cast<void*>(aOuterWindow));
     958                 :   }
     959                 : #endif
     960                 : 
     961                 : #ifdef PR_LOGGING
     962               0 :   if (gDOMLeakPRLog)
     963               0 :     PR_LOG(gDOMLeakPRLog, PR_LOG_DEBUG,
     964                 :            ("DOMWINDOW %p created outer=%p", this, aOuterWindow));
     965                 : #endif
     966                 : 
     967               0 :   NS_ASSERTION(sWindowsById, "Windows hash table must be created!");
     968               0 :   NS_ASSERTION(!sWindowsById->Get(mWindowID),
     969                 :                "This window shouldn't be in the hash table yet!");
     970               0 :   sWindowsById->Put(mWindowID, this);
     971                 : 
     972               0 :   mEventTargetObjects.Init();
     973               0 : }
     974                 : 
     975                 : /* static */
     976                 : void
     977            1404 : nsGlobalWindow::Init()
     978                 : {
     979            1404 :   CallGetService(NS_ENTROPYCOLLECTOR_CONTRACTID, &gEntropyCollector);
     980            1404 :   NS_ASSERTION(gEntropyCollector,
     981                 :                "gEntropyCollector should have been initialized!");
     982                 : 
     983                 : #ifdef PR_LOGGING
     984            1404 :   gDOMLeakPRLog = PR_NewLogModule("DOMLeak");
     985            1404 :   NS_ASSERTION(gDOMLeakPRLog, "gDOMLeakPRLog should have been initialized!");
     986                 : #endif
     987                 : 
     988            1404 :   sWindowsById = new WindowByIdTable();
     989                 :   // There are two reasons to have Init() failing: if we were not able to
     990                 :   // alloc the memory or if the size we want to init is too high. None of them
     991                 :   // should happen.
     992                 : #ifdef DEBUG
     993            1404 :   NS_ASSERTION(sWindowsById->Init(), "Init() should not fail!");
     994                 : #else
     995                 :   sWindowsById->Init();
     996                 : #endif
     997            1404 : }
     998                 : 
     999                 : static PLDHashOperator
    1000               0 : DisconnectEventTargetObjects(nsPtrHashKey<nsDOMEventTargetHelper>* aKey,
    1001                 :                              void* aClosure)
    1002                 : {
    1003               0 :   nsRefPtr<nsDOMEventTargetHelper> target = aKey->GetKey();
    1004               0 :   target->DisconnectFromOwner();
    1005               0 :   return PL_DHASH_NEXT;
    1006                 : }
    1007                 : 
    1008               0 : nsGlobalWindow::~nsGlobalWindow()
    1009                 : {
    1010               0 :   mEventTargetObjects.EnumerateEntries(DisconnectEventTargetObjects, nsnull);
    1011               0 :   mEventTargetObjects.Clear();
    1012                 : 
    1013                 :   // We have to check if sWindowsById isn't null because ::Shutdown might have
    1014                 :   // been called.
    1015               0 :   if (sWindowsById) {
    1016               0 :     NS_ASSERTION(sWindowsById->Get(mWindowID),
    1017                 :                  "This window should be in the hash table");
    1018               0 :     sWindowsById->Remove(mWindowID);
    1019                 :   }
    1020                 : 
    1021               0 :   --gRefCnt;
    1022                 : 
    1023                 : #ifdef DEBUG
    1024               0 :   if (!PR_GetEnv("MOZ_QUIET")) {
    1025               0 :     nsCAutoString url;
    1026               0 :     if (mLastOpenedURI) {
    1027               0 :       mLastOpenedURI->GetSpec(url);
    1028                 :     }
    1029                 : 
    1030                 :     printf("--DOMWINDOW == %d (%p) [serial = %d] [outer = %p] [url = %s]\n",
    1031                 :            gRefCnt, static_cast<void*>(static_cast<nsIScriptGlobalObject*>(this)),
    1032               0 :            mSerial, static_cast<void*>(mOuterWindow.get()), url.get());
    1033                 :   }
    1034                 : #endif
    1035                 : 
    1036                 : #ifdef PR_LOGGING
    1037               0 :   if (gDOMLeakPRLog)
    1038               0 :     PR_LOG(gDOMLeakPRLog, PR_LOG_DEBUG,
    1039                 :            ("DOMWINDOW %p destroyed", this));
    1040                 : #endif
    1041                 : 
    1042               0 :   if (IsOuterWindow()) {
    1043               0 :     JSObject *proxy = GetWrapperPreserveColor();
    1044               0 :     if (proxy) {
    1045               0 :       js::SetProxyExtra(proxy, 0, js::PrivateValue(NULL));
    1046                 :     }
    1047                 : 
    1048                 :     // An outer window is destroyed with inner windows still possibly
    1049                 :     // alive, iterate through the inner windows and null out their
    1050                 :     // back pointer to this outer, and pull them out of the list of
    1051                 :     // inner windows.
    1052                 : 
    1053                 :     nsGlobalWindow *w;
    1054               0 :     while ((w = (nsGlobalWindow *)PR_LIST_HEAD(this)) != this) {
    1055               0 :       PR_REMOVE_AND_INIT_LINK(w);
    1056                 :     }
    1057                 :   } else {
    1058                 :     Telemetry::Accumulate(Telemetry::INNERWINDOWS_WITH_MUTATION_LISTENERS,
    1059               0 :                           mMutationBits ? 1 : 0);
    1060                 : 
    1061               0 :     if (mListenerManager) {
    1062               0 :       mListenerManager->Disconnect();
    1063               0 :       mListenerManager = nsnull;
    1064                 :     }
    1065                 : 
    1066                 :     // An inner window is destroyed, pull it out of the outer window's
    1067                 :     // list if inner windows.
    1068                 : 
    1069               0 :     PR_REMOVE_LINK(this);
    1070                 : 
    1071                 :     // If our outer window's inner window is this window, null out the
    1072                 :     // outer window's reference to this window that's being deleted.
    1073               0 :     nsGlobalWindow *outer = GetOuterWindowInternal();
    1074               0 :     if (outer && outer->mInnerWindow == this) {
    1075               0 :       outer->mInnerWindow = nsnull;
    1076                 :     }
    1077                 :   }
    1078                 : 
    1079               0 :   mDocument = nsnull;           // Forces Release
    1080               0 :   mDoc = nsnull;
    1081                 : 
    1082               0 :   NS_ASSERTION(!mArguments, "mArguments wasn't cleaned up properly!");
    1083                 : 
    1084               0 :   CleanUp(true);
    1085                 : 
    1086                 : #ifdef DEBUG
    1087               0 :   nsCycleCollector_DEBUG_wasFreed(static_cast<nsIScriptGlobalObject*>(this));
    1088                 : #endif
    1089                 : 
    1090               0 :   if (mURLProperty) {
    1091               0 :     mURLProperty->ClearWindowReference();
    1092                 :   }
    1093                 : 
    1094               0 :   DisableDeviceMotionUpdates();
    1095               0 :   mHasDeviceMotion = false;
    1096                 : 
    1097               0 :   nsLayoutStatics::Release();
    1098               0 : }
    1099                 : 
    1100                 : void
    1101               0 : nsGlobalWindow::AddEventTargetObject(nsDOMEventTargetHelper* aObject)
    1102                 : {
    1103               0 :   mEventTargetObjects.PutEntry(aObject);
    1104               0 : }
    1105                 : 
    1106                 : void
    1107               0 : nsGlobalWindow::RemoveEventTargetObject(nsDOMEventTargetHelper* aObject)
    1108                 : {
    1109               0 :   mEventTargetObjects.RemoveEntry(aObject);
    1110               0 : }
    1111                 : 
    1112                 : // static
    1113                 : void
    1114            1453 : nsGlobalWindow::ShutDown()
    1115                 : {
    1116            1453 :   if (gDumpFile && gDumpFile != stdout) {
    1117               0 :     fclose(gDumpFile);
    1118                 :   }
    1119            1453 :   gDumpFile = nsnull;
    1120                 : 
    1121            1453 :   NS_IF_RELEASE(gEntropyCollector);
    1122                 : 
    1123            1453 :   delete sWindowsById;
    1124            1453 :   sWindowsById = nsnull;
    1125            1453 : }
    1126                 : 
    1127                 : // static
    1128                 : void
    1129               0 : nsGlobalWindow::CleanupCachedXBLHandlers(nsGlobalWindow* aWindow)
    1130                 : {
    1131               0 :   if (aWindow->mCachedXBLPrototypeHandlers.IsInitialized() &&
    1132               0 :       aWindow->mCachedXBLPrototypeHandlers.Count() > 0) {
    1133               0 :     aWindow->mCachedXBLPrototypeHandlers.Clear();
    1134                 : 
    1135                 :     nsISupports* supports;
    1136                 :     aWindow->QueryInterface(NS_GET_IID(nsCycleCollectionISupports),
    1137               0 :                             reinterpret_cast<void**>(&supports));
    1138               0 :     NS_ASSERTION(supports, "Failed to QI to nsCycleCollectionISupports?!");
    1139                 : 
    1140               0 :     nsContentUtils::DropJSObjects(supports);
    1141                 :   }
    1142               0 : }
    1143                 : 
    1144                 : void
    1145               0 : nsGlobalWindow::MaybeForgiveSpamCount()
    1146                 : {
    1147               0 :   if (IsOuterWindow() &&
    1148               0 :       IsPopupSpamWindow())
    1149                 :   {
    1150               0 :     SetPopupSpamWindow(false);
    1151               0 :     --gOpenPopupSpamCount;
    1152               0 :     NS_ASSERTION(gOpenPopupSpamCount >= 0,
    1153                 :                  "Unbalanced decrement of gOpenPopupSpamCount");
    1154                 :   }
    1155               0 : }
    1156                 : 
    1157                 : void
    1158               0 : nsGlobalWindow::CleanUp(bool aIgnoreModalDialog)
    1159                 : {
    1160               0 :   if (IsOuterWindow() && !aIgnoreModalDialog) {
    1161               0 :     nsGlobalWindow* inner = GetCurrentInnerWindowInternal();
    1162               0 :     nsCOMPtr<nsIDOMModalContentWindow> dlg(do_QueryObject(inner));
    1163               0 :     if (dlg) {
    1164                 :       // The window we're trying to clean up is the outer window of a
    1165                 :       // modal dialog.  Defer cleanup until the window closes, and let
    1166                 :       // ShowModalDialog take care of calling CleanUp.
    1167               0 :       mCallCleanUpAfterModalDialogCloses = true;
    1168                 :       return;
    1169                 :     }
    1170                 :   }
    1171                 : 
    1172                 :   // Guarantee idempotence.
    1173               0 :   if (mCleanedUp)
    1174               0 :     return;
    1175               0 :   mCleanedUp = true;
    1176                 :   
    1177               0 :   mEventTargetObjects.EnumerateEntries(DisconnectEventTargetObjects, nsnull);
    1178               0 :   mEventTargetObjects.Clear();
    1179                 : 
    1180               0 :   if (mObserver) {
    1181               0 :     nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
    1182               0 :     if (os) {
    1183               0 :       os->RemoveObserver(mObserver, NS_IOSERVICE_OFFLINE_STATUS_TOPIC);
    1184               0 :       os->RemoveObserver(mObserver, "dom-storage2-changed");
    1185               0 :       os->RemoveObserver(mObserver, "dom-storage-changed");
    1186                 :     }
    1187                 : 
    1188                 :     // Drop its reference to this dying window, in case for some bogus reason
    1189                 :     // the object stays around.
    1190               0 :     mObserver->Forget();
    1191               0 :     NS_RELEASE(mObserver);
    1192                 :   }
    1193                 : 
    1194               0 :   mNavigator = nsnull;
    1195               0 :   mScreen = nsnull;
    1196               0 :   mMenubar = nsnull;
    1197               0 :   mToolbar = nsnull;
    1198               0 :   mLocationbar = nsnull;
    1199               0 :   mPersonalbar = nsnull;
    1200               0 :   mStatusbar = nsnull;
    1201               0 :   mScrollbars = nsnull;
    1202               0 :   mLocation = nsnull;
    1203               0 :   mHistory = nsnull;
    1204               0 :   mFrames = nsnull;
    1205               0 :   mApplicationCache = nsnull;
    1206               0 :   mIndexedDB = nsnull;
    1207               0 :   mPendingStorageEventsObsolete = nsnull;
    1208                 : 
    1209               0 :   mPerformance = nsnull;
    1210                 : 
    1211               0 :   ClearControllers();
    1212                 : 
    1213               0 :   mOpener = nsnull;             // Forces Release
    1214               0 :   if (mContext) {
    1215                 : #ifdef DEBUG
    1216               0 :     nsCycleCollector_DEBUG_shouldBeFreed(mContext);
    1217                 : #endif
    1218               0 :     mContext = nsnull;            // Forces Release
    1219                 :   }
    1220               0 :   mChromeEventHandler = nsnull; // Forces Release
    1221               0 :   mParentTarget = nsnull;
    1222                 : 
    1223               0 :   nsGlobalWindow *inner = GetCurrentInnerWindowInternal();
    1224                 : 
    1225               0 :   if (inner) {
    1226               0 :     inner->CleanUp(aIgnoreModalDialog);
    1227                 :   }
    1228                 : 
    1229               0 :   if (mCleanMessageManager) {
    1230               0 :     NS_ABORT_IF_FALSE(mIsChrome, "only chrome should have msg manager cleaned");
    1231               0 :     nsGlobalChromeWindow *asChrome = static_cast<nsGlobalChromeWindow*>(this);
    1232               0 :     if (asChrome->mMessageManager) {
    1233                 :       static_cast<nsFrameMessageManager*>(
    1234               0 :         asChrome->mMessageManager.get())->Disconnect();
    1235                 :     }
    1236                 :   }
    1237                 : 
    1238               0 :   mInnerWindowHolder = nsnull;
    1239               0 :   mArguments = nsnull;
    1240               0 :   mArgumentsLast = nsnull;
    1241               0 :   mArgumentsOrigin = nsnull;
    1242                 : 
    1243               0 :   CleanupCachedXBLHandlers(this);
    1244                 : 
    1245                 : #ifdef DEBUG
    1246               0 :   nsCycleCollector_DEBUG_shouldBeFreed(static_cast<nsIScriptGlobalObject*>(this));
    1247                 : #endif
    1248                 : }
    1249                 : 
    1250                 : void
    1251               0 : nsGlobalWindow::ClearControllers()
    1252                 : {
    1253               0 :   if (mControllers) {
    1254                 :     PRUint32 count;
    1255               0 :     mControllers->GetControllerCount(&count);
    1256                 : 
    1257               0 :     while (count--) {
    1258               0 :       nsCOMPtr<nsIController> controller;
    1259               0 :       mControllers->GetControllerAt(count, getter_AddRefs(controller));
    1260                 : 
    1261               0 :       nsCOMPtr<nsIControllerContext> context = do_QueryInterface(controller);
    1262               0 :       if (context)
    1263               0 :         context->SetCommandContext(nsnull);
    1264                 :     }
    1265                 : 
    1266               0 :     mControllers = nsnull;
    1267                 :   }
    1268               0 : }
    1269                 : 
    1270                 : void
    1271               0 : nsGlobalWindow::FreeInnerObjects()
    1272                 : {
    1273               0 :   NS_ASSERTION(IsInnerWindow(), "Don't free inner objects on an outer window");
    1274                 : 
    1275                 :   // Make sure that this is called before we null out the document and
    1276                 :   // other members that the window destroyed observers could
    1277                 :   // re-create.
    1278               0 :   NotifyDOMWindowDestroyed(this);
    1279                 : 
    1280                 :   // Kill all of the workers for this window.
    1281               0 :   nsIScriptContext *scx = GetContextInternal();
    1282               0 :   JSContext *cx = scx ? scx->GetNativeContext() : nsnull;
    1283               0 :   mozilla::dom::workers::CancelWorkersForWindow(cx, this);
    1284                 : 
    1285                 :   // Close all IndexedDB databases for this window.
    1286                 :   indexedDB::IndexedDatabaseManager* idbManager =
    1287               0 :     indexedDB::IndexedDatabaseManager::Get();
    1288               0 :   if (idbManager) {
    1289               0 :     idbManager->AbortCloseDatabasesForWindow(this);
    1290                 :   }
    1291                 : 
    1292               0 :   ClearAllTimeouts();
    1293                 : 
    1294               0 :   mChromeEventHandler = nsnull;
    1295                 : 
    1296               0 :   if (mListenerManager) {
    1297               0 :     mListenerManager->Disconnect();
    1298               0 :     mListenerManager = nsnull;
    1299                 :   }
    1300                 : 
    1301               0 :   mLocation = nsnull;
    1302               0 :   mHistory = nsnull;
    1303                 : 
    1304               0 :   if (mNavigator) {
    1305               0 :     mNavigator->Invalidate();
    1306               0 :     mNavigator = nsnull;
    1307                 :   }
    1308                 : 
    1309               0 :   if (mDocument) {
    1310               0 :     NS_ASSERTION(mDoc, "Why is mDoc null?");
    1311                 : 
    1312                 :     // Remember the document's principal.
    1313               0 :     mDocumentPrincipal = mDoc->NodePrincipal();
    1314                 :   }
    1315                 : 
    1316                 : #ifdef DEBUG
    1317               0 :   if (mDocument)
    1318               0 :     nsCycleCollector_DEBUG_shouldBeFreed(nsCOMPtr<nsISupports>(do_QueryInterface(mDocument)));
    1319                 : #endif
    1320                 : 
    1321                 :   // Remove our reference to the document and the document principal.
    1322               0 :   mDocument = nsnull;
    1323               0 :   mDoc = nsnull;
    1324               0 :   mFocusedNode = nsnull;
    1325                 : 
    1326               0 :   if (mApplicationCache) {
    1327               0 :     static_cast<nsDOMOfflineResourceList*>(mApplicationCache.get())->Disconnect();
    1328               0 :     mApplicationCache = nsnull;
    1329                 :   }
    1330                 : 
    1331               0 :   mIndexedDB = nsnull;
    1332                 : 
    1333               0 :   NotifyWindowIDDestroyed("inner-window-destroyed");
    1334                 : 
    1335               0 :   if (mDummyJavaPluginOwner) {
    1336                 :     // Tear down the dummy java plugin.
    1337                 : 
    1338                 :     // XXXjst: On a general note, should windows with java stuff in
    1339                 :     // them ever even make it into the fast-back cache?
    1340                 : 
    1341               0 :     mDummyJavaPluginOwner->Destroy();
    1342               0 :     mDummyJavaPluginOwner = nsnull;
    1343               0 :     mDidInitJavaProperties = false;
    1344                 :   }
    1345                 : 
    1346               0 :   CleanupCachedXBLHandlers(this);
    1347                 : 
    1348                 : #ifdef DEBUG
    1349               0 :   nsCycleCollector_DEBUG_shouldBeFreed(static_cast<nsIScriptGlobalObject*>(this));
    1350                 : #endif
    1351               0 : }
    1352                 : 
    1353                 : //*****************************************************************************
    1354                 : // nsGlobalWindow::nsISupports
    1355                 : //*****************************************************************************
    1356                 : 
    1357                 : #define OUTER_WINDOW_ONLY                                                     \
    1358                 :   if (IsOuterWindow()) {
    1359                 : 
    1360                 : #define END_OUTER_WINDOW_ONLY                                                 \
    1361                 :     foundInterface = 0;                                                       \
    1362                 :   } else
    1363                 : 
    1364            1464 : NS_IMPL_CYCLE_COLLECTION_CLASS(nsGlobalWindow)
    1365                 : 
    1366                 : DOMCI_DATA(Window, nsGlobalWindow)
    1367                 : 
    1368                 : // QueryInterface implementation for nsGlobalWindow
    1369               0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsGlobalWindow)
    1370                 :   // Make sure this matches the cast in nsGlobalWindow::FromWrapper()
    1371               0 :   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIScriptGlobalObject)
    1372               0 :   NS_INTERFACE_MAP_ENTRY(nsIDOMWindow)
    1373               0 :   NS_INTERFACE_MAP_ENTRY(nsIDOMJSWindow)
    1374               0 :   if (aIID.Equals(NS_GET_IID(nsIDOMWindowInternal))) {
    1375               0 :     foundInterface = static_cast<nsIDOMWindowInternal*>(this);
    1376               0 :     if (!sWarnedAboutWindowInternal) {
    1377               0 :       sWarnedAboutWindowInternal = true;
    1378                 :       nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
    1379                 :                                       "Extensions", mDoc,
    1380                 :                                       nsContentUtils::eDOM_PROPERTIES,
    1381               0 :                                       "nsIDOMWindowInternalWarning");
    1382                 :     }
    1383                 :   } else
    1384               0 :   NS_INTERFACE_MAP_ENTRY(nsIScriptGlobalObject)
    1385               0 :   NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal)
    1386               0 :   NS_INTERFACE_MAP_ENTRY(nsIDOMEventTarget)
    1387               0 :   NS_INTERFACE_MAP_ENTRY(nsPIDOMWindow)
    1388               0 :   NS_INTERFACE_MAP_ENTRY(nsIDOMStorageIndexedDB)
    1389               0 :   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
    1390               0 :   NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
    1391               0 :   NS_INTERFACE_MAP_ENTRY(nsIDOMWindowPerformance)
    1392               0 :   NS_INTERFACE_MAP_ENTRY(nsITouchEventReceiver)
    1393               0 :   NS_INTERFACE_MAP_ENTRY(nsIInlineEventHandlers)
    1394               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Window)
    1395               0 :   OUTER_WINDOW_ONLY
    1396               0 :     NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
    1397               0 :   END_OUTER_WINDOW_ONLY
    1398               0 : NS_INTERFACE_MAP_END
    1399                 : 
    1400                 : 
    1401               0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsGlobalWindow)
    1402               0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsGlobalWindow)
    1403                 : 
    1404                 : static PLDHashOperator
    1405               0 : MarkXBLHandlers(const void* aKey, JSObject* aData, void* aClosure)
    1406                 : {
    1407               0 :   xpc_UnmarkGrayObject(aData);
    1408               0 :   return PL_DHASH_NEXT;
    1409                 : }
    1410                 : 
    1411               0 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_BEGIN(nsGlobalWindow)
    1412               0 :   if (tmp->IsBlackForCC()) {
    1413               0 :     if (tmp->mCachedXBLPrototypeHandlers.IsInitialized()) {
    1414               0 :       tmp->mCachedXBLPrototypeHandlers.EnumerateRead(MarkXBLHandlers, nsnull);
    1415                 :     }
    1416               0 :     return true;
    1417                 :   }
    1418               0 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_END
    1419                 : 
    1420               0 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_BEGIN(nsGlobalWindow)
    1421               0 :   return tmp->IsBlackForCC();
    1422                 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_IN_CC_END
    1423                 : 
    1424               0 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_BEGIN(nsGlobalWindow)
    1425               0 :   return tmp->IsBlackForCC();
    1426                 : NS_IMPL_CYCLE_COLLECTION_CAN_SKIP_THIS_END
    1427                 : 
    1428               0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsGlobalWindow)
    1429               0 :   if (!cb.WantAllTraces() && tmp->IsBlackForCC()) {
    1430               0 :     return NS_SUCCESS_INTERRUPTED_TRAVERSE;
    1431                 :   }
    1432                 : 
    1433               0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mContext)
    1434                 : 
    1435               0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mControllers)
    1436               0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mArguments)
    1437               0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mArgumentsLast)
    1438                 : 
    1439               0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mInnerWindowHolder)
    1440               0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOuterWindow)
    1441                 : 
    1442               0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOpenerScriptPrincipal)
    1443               0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_MEMBER(mListenerManager,
    1444                 :                                                   nsEventListenerManager)
    1445                 : 
    1446               0 :   for (nsTimeout* timeout = tmp->FirstTimeout();
    1447               0 :        tmp->IsTimeout(timeout);
    1448                 :        timeout = timeout->Next()) {
    1449               0 :     cb.NoteNativeChild(timeout, &NS_CYCLE_COLLECTION_NAME(nsTimeout));
    1450                 :   }
    1451                 : 
    1452               0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mSessionStorage)
    1453               0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mApplicationCache)
    1454               0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDocumentPrincipal)
    1455               0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDoc)
    1456                 : 
    1457                 :   // Traverse stuff from nsPIDOMWindow
    1458               0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mChromeEventHandler)
    1459               0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mParentTarget)
    1460               0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDocument)
    1461               0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFrameElement)
    1462                 : 
    1463                 :   // Traverse mDummyJavaPluginOwner
    1464               0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDummyJavaPluginOwner)
    1465                 : 
    1466               0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFocusedNode)
    1467                 : 
    1468               0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMARRAY(mPendingStorageEvents)
    1469                 : 
    1470               0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
    1471                 : 
    1472               0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindow)
    1473               0 :   nsGlobalWindow::CleanupCachedXBLHandlers(tmp);
    1474                 : 
    1475               0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mContext)
    1476                 : 
    1477               0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mControllers)
    1478               0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mArguments)
    1479               0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mArgumentsLast)
    1480                 : 
    1481               0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mInnerWindowHolder)
    1482               0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOuterWindow)
    1483                 : 
    1484               0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOpenerScriptPrincipal)
    1485               0 :   if (tmp->mListenerManager) {
    1486               0 :     tmp->mListenerManager->Disconnect();
    1487               0 :     NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mListenerManager)
    1488                 :   }
    1489               0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mSessionStorage)
    1490               0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mApplicationCache)
    1491               0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDocumentPrincipal)
    1492               0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDoc)
    1493                 : 
    1494                 :   // Unlink stuff from nsPIDOMWindow
    1495               0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mChromeEventHandler)
    1496               0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mParentTarget)
    1497               0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDocument)
    1498               0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFrameElement)
    1499                 : 
    1500                 :   // Unlink mDummyJavaPluginOwner
    1501               0 :   if (tmp->mDummyJavaPluginOwner) {
    1502               0 :     tmp->mDummyJavaPluginOwner->Destroy();
    1503               0 :     NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDummyJavaPluginOwner)
    1504               0 :     tmp->mDidInitJavaProperties = false;
    1505                 :   }
    1506                 : 
    1507               0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFocusedNode)
    1508                 : 
    1509               0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMARRAY(mPendingStorageEvents)
    1510                 : 
    1511               0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
    1512                 : 
    1513                 : struct TraceData
    1514                 : {
    1515               0 :   TraceData(TraceCallback& aCallback, void* aClosure) :
    1516               0 :     callback(aCallback), closure(aClosure) {}
    1517                 : 
    1518                 :   TraceCallback& callback;
    1519                 :   void* closure;
    1520                 : };
    1521                 : 
    1522                 : static PLDHashOperator
    1523               0 : TraceXBLHandlers(const void* aKey, JSObject* aData, void* aClosure)
    1524                 : {
    1525               0 :   TraceData* data = static_cast<TraceData*>(aClosure);
    1526                 :   data->callback(nsIProgrammingLanguage::JAVASCRIPT, aData,
    1527               0 :                  "Cached XBL prototype handler", data->closure);
    1528               0 :   return PL_DHASH_NEXT;
    1529                 : }
    1530                 : 
    1531               0 : NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsGlobalWindow)
    1532               0 :   if (tmp->mCachedXBLPrototypeHandlers.IsInitialized()) {
    1533               0 :     TraceData data(aCallback, aClosure);
    1534               0 :     tmp->mCachedXBLPrototypeHandlers.EnumerateRead(TraceXBLHandlers, &data);
    1535                 :   }
    1536               0 : NS_IMPL_CYCLE_COLLECTION_TRACE_END
    1537                 : 
    1538                 : bool
    1539               0 : nsGlobalWindow::IsBlackForCC()
    1540                 : {
    1541                 :   return
    1542                 :     (mDoc &&
    1543               0 :      nsCCUncollectableMarker::InGeneration(mDoc->GetMarkedCCGeneration())) ||
    1544               0 :     (nsCCUncollectableMarker::sGeneration && IsBlack());
    1545                 : }
    1546                 : 
    1547                 : void
    1548               0 : nsGlobalWindow::UnmarkGrayTimers()
    1549                 : {
    1550               0 :   for (nsTimeout* timeout = FirstTimeout();
    1551               0 :        timeout && IsTimeout(timeout);
    1552                 :        timeout = timeout->Next()) {
    1553               0 :     if (timeout->mScriptHandler) {
    1554               0 :       JSObject* o = timeout->mScriptHandler->GetScriptObject();
    1555               0 :       xpc_UnmarkGrayObject(o);
    1556                 :     }
    1557                 :   }
    1558               0 : }
    1559                 : 
    1560                 : //*****************************************************************************
    1561                 : // nsGlobalWindow::nsIScriptGlobalObject
    1562                 : //*****************************************************************************
    1563                 : 
    1564                 : nsresult
    1565               0 : nsGlobalWindow::SetScriptContext(PRUint32 lang_id, nsIScriptContext *aScriptContext)
    1566                 : {
    1567               0 :   NS_ASSERTION(lang_id == nsIProgrammingLanguage::JAVASCRIPT,
    1568                 :                "We don't support this language ID");
    1569               0 :   NS_ASSERTION(IsOuterWindow(), "Uh, SetScriptContext() called on inner window!");
    1570                 : 
    1571               0 :   NS_ASSERTION(!aScriptContext || !mContext, "Bad call to SetContext()!");
    1572                 : 
    1573               0 :   if (aScriptContext) {
    1574                 :     // should probably assert the context is clean???
    1575               0 :     aScriptContext->WillInitializeContext();
    1576                 : 
    1577               0 :     nsresult rv = aScriptContext->InitContext();
    1578               0 :     NS_ENSURE_SUCCESS(rv, rv);
    1579                 : 
    1580               0 :     if (IsFrame()) {
    1581                 :       // This window is a [i]frame, don't bother GC'ing when the
    1582                 :       // frame's context is destroyed since a GC will happen when the
    1583                 :       // frameset or host document is destroyed anyway.
    1584                 : 
    1585               0 :       aScriptContext->SetGCOnDestruction(false);
    1586                 :     }
    1587                 :   }
    1588                 : 
    1589               0 :   mContext = aScriptContext;
    1590               0 :   return NS_OK;
    1591                 : }
    1592                 : 
    1593                 : nsresult
    1594               0 : nsGlobalWindow::EnsureScriptEnvironment(PRUint32 aLangID)
    1595                 : {
    1596               0 :   NS_ASSERTION(aLangID == nsIProgrammingLanguage::JAVASCRIPT,
    1597                 :                "We don't support this language ID");
    1598               0 :   FORWARD_TO_OUTER(EnsureScriptEnvironment, (aLangID), NS_ERROR_NOT_INITIALIZED);
    1599                 : 
    1600               0 :   if (mJSObject)
    1601               0 :       return NS_OK;
    1602                 : 
    1603               0 :   NS_ASSERTION(!GetCurrentInnerWindowInternal(),
    1604                 :                "mJSObject is null, but we have an inner window?");
    1605                 : 
    1606               0 :   nsCOMPtr<nsIScriptRuntime> scriptRuntime;
    1607               0 :   nsresult rv = NS_GetScriptRuntimeByID(aLangID, getter_AddRefs(scriptRuntime));
    1608               0 :   NS_ENSURE_SUCCESS(rv, rv);
    1609                 : 
    1610               0 :   nsCOMPtr<nsIScriptContext> context = scriptRuntime->CreateContext();
    1611               0 :   return SetScriptContext(aLangID, context);
    1612                 : }
    1613                 : 
    1614                 : nsIScriptContext *
    1615               0 : nsGlobalWindow::GetScriptContext(PRUint32 lang)
    1616                 : {
    1617               0 :   NS_ASSERTION(lang == nsIProgrammingLanguage::JAVASCRIPT,
    1618                 :                "We don't support this language ID");
    1619                 : 
    1620               0 :   FORWARD_TO_OUTER(GetScriptContext, (lang), nsnull);
    1621               0 :   return mContext;
    1622                 : }
    1623                 : 
    1624                 : nsIScriptContext *
    1625               0 : nsGlobalWindow::GetContext()
    1626                 : {
    1627               0 :   FORWARD_TO_OUTER(GetContext, (), nsnull);
    1628                 : 
    1629                 :   // check GetContext is indeed identical to GetScriptContext()
    1630               0 :   NS_ASSERTION(mContext == GetScriptContext(nsIProgrammingLanguage::JAVASCRIPT),
    1631                 :                "GetContext confused?");
    1632               0 :   return mContext;
    1633                 : }
    1634                 : 
    1635                 : JSObject *
    1636               0 : nsGlobalWindow::GetGlobalJSObject()
    1637                 : {
    1638               0 :   return FastGetGlobalJSObject();
    1639                 : }
    1640                 : 
    1641                 : bool
    1642               0 : nsGlobalWindow::WouldReuseInnerWindow(nsIDocument *aNewDocument)
    1643                 : {
    1644                 :   // We reuse the inner window when:
    1645                 :   // a. We are currently at our original document.
    1646                 :   // b. At least one of the following conditions are true:
    1647                 :   // -- We are not currently a content window (i.e., we're currently a chrome
    1648                 :   //    window).
    1649                 :   // -- The new document is the same as the old document. This means that we're
    1650                 :   //    getting called from document.open().
    1651                 :   // -- The new document has the same origin as what we have loaded right now.
    1652                 : 
    1653               0 :   if (!mDoc || !aNewDocument) {
    1654               0 :     return false;
    1655                 :   }
    1656                 : 
    1657               0 :   if (!mDoc->IsInitialDocument()) {
    1658               0 :     return false;
    1659                 :   }
    1660                 :   
    1661               0 :   NS_ASSERTION(NS_IsAboutBlank(mDoc->GetDocumentURI()),
    1662                 :                "How'd this happen?");
    1663                 :   
    1664                 :   // Great, we're the original document, check for one of the other
    1665                 :   // conditions.
    1666               0 :   if (mDoc == aNewDocument) {
    1667               0 :     return true;
    1668                 :   }
    1669                 : 
    1670                 :   bool equal;
    1671               0 :   if (NS_SUCCEEDED(mDoc->NodePrincipal()->Equals(aNewDocument->NodePrincipal(),
    1672                 :                                                  &equal)) &&
    1673                 :       equal) {
    1674                 :     // The origin is the same.
    1675               0 :     return true;
    1676                 :   }
    1677                 : 
    1678               0 :   nsCOMPtr<nsIDocShellTreeItem> treeItem(do_QueryInterface(mDocShell));
    1679                 : 
    1680               0 :   if (treeItem) {
    1681               0 :     PRInt32 itemType = nsIDocShellTreeItem::typeContent;
    1682               0 :     treeItem->GetItemType(&itemType);
    1683                 : 
    1684                 :     // If we're a chrome window, then we want to reuse the inner window.
    1685               0 :     return itemType == nsIDocShellTreeItem::typeChrome;
    1686                 :   }
    1687                 : 
    1688                 :   // No treeItem: don't reuse the current inner window.
    1689               0 :   return false;
    1690                 : }
    1691                 : 
    1692                 : void
    1693               0 : nsGlobalWindow::SetOpenerScriptPrincipal(nsIPrincipal* aPrincipal)
    1694                 : {
    1695               0 :   FORWARD_TO_OUTER_VOID(SetOpenerScriptPrincipal, (aPrincipal));
    1696                 : 
    1697               0 :   if (mDoc) {
    1698               0 :     if (!mDoc->IsInitialDocument()) {
    1699                 :       // We have a document already, and it's not the original one.  Bail out.
    1700                 :       // Do NOT set mOpenerScriptPrincipal in this case, just to be safe.
    1701               0 :       return;
    1702                 :     }
    1703                 : 
    1704                 : #ifdef DEBUG
    1705                 :     // We better have an about:blank document loaded at this point.  Otherwise,
    1706                 :     // something is really weird.
    1707               0 :     nsCOMPtr<nsIURI> uri;
    1708               0 :     mDoc->NodePrincipal()->GetURI(getter_AddRefs(uri));
    1709               0 :     NS_ASSERTION(uri && NS_IsAboutBlank(uri) &&
    1710                 :                  NS_IsAboutBlank(mDoc->GetDocumentURI()),
    1711                 :                  "Unexpected original document");
    1712                 : #endif
    1713                 : 
    1714               0 :     GetDocShell()->CreateAboutBlankContentViewer(aPrincipal);
    1715               0 :     mDoc->SetIsInitialDocument(true);
    1716                 : 
    1717               0 :     nsCOMPtr<nsIPresShell> shell;
    1718               0 :     GetDocShell()->GetPresShell(getter_AddRefs(shell));
    1719                 : 
    1720               0 :     if (shell && !shell->DidInitialReflow()) {
    1721                 :       // Ensure that if someone plays with this document they will get
    1722                 :       // layout happening.
    1723               0 :       nsRect r = shell->GetPresContext()->GetVisibleArea();
    1724               0 :       shell->InitialReflow(r.width, r.height);
    1725                 :     }
    1726                 :   }
    1727                 : }
    1728                 : 
    1729                 : nsIPrincipal*
    1730               0 : nsGlobalWindow::GetOpenerScriptPrincipal()
    1731                 : {
    1732               0 :   FORWARD_TO_OUTER(GetOpenerScriptPrincipal, (), nsnull);
    1733                 : 
    1734               0 :   return mOpenerScriptPrincipal;
    1735                 : }
    1736                 : 
    1737                 : PopupControlState
    1738            8232 : PushPopupControlState(PopupControlState aState, bool aForce)
    1739                 : {
    1740            8232 :   PopupControlState oldState = gPopupControlState;
    1741                 : 
    1742            8232 :   if (aState < gPopupControlState || aForce) {
    1743               0 :     gPopupControlState = aState;
    1744                 :   }
    1745                 : 
    1746            8232 :   return oldState;
    1747                 : }
    1748                 : 
    1749                 : void
    1750            8232 : PopPopupControlState(PopupControlState aState)
    1751                 : {
    1752            8232 :   gPopupControlState = aState;
    1753            8232 : }
    1754                 : 
    1755                 : PopupControlState
    1756               0 : nsGlobalWindow::PushPopupControlState(PopupControlState aState,
    1757                 :                                       bool aForce) const
    1758                 : {
    1759               0 :   return ::PushPopupControlState(aState, aForce);
    1760                 : }
    1761                 : 
    1762                 : void
    1763               0 : nsGlobalWindow::PopPopupControlState(PopupControlState aState) const
    1764                 : {
    1765               0 :   ::PopPopupControlState(aState);
    1766               0 : }
    1767                 : 
    1768                 : PopupControlState
    1769               0 : nsGlobalWindow::GetPopupControlState() const
    1770                 : {
    1771               0 :   return gPopupControlState;
    1772                 : }
    1773                 : 
    1774                 : #define WINDOWSTATEHOLDER_IID \
    1775                 : {0x0b917c3e, 0xbd50, 0x4683, {0xaf, 0xc9, 0xc7, 0x81, 0x07, 0xae, 0x33, 0x26}}
    1776                 : 
    1777                 : class WindowStateHolder : public nsISupports
    1778                 : {
    1779                 : public:
    1780                 :   NS_DECLARE_STATIC_IID_ACCESSOR(WINDOWSTATEHOLDER_IID)
    1781                 :   NS_DECL_ISUPPORTS
    1782                 : 
    1783                 :   WindowStateHolder(nsGlobalWindow *aWindow,
    1784                 :                     nsIXPConnectJSObjectHolder *aHolder,
    1785                 :                     nsIXPConnectJSObjectHolder *aOuterProto,
    1786                 :                     nsIXPConnectJSObjectHolder *aOuterRealProto);
    1787                 : 
    1788               0 :   nsGlobalWindow* GetInnerWindow() { return mInnerWindow; }
    1789               0 :   nsIXPConnectJSObjectHolder *GetInnerWindowHolder()
    1790               0 :   { return mInnerWindowHolder; }
    1791                 : 
    1792                 :   nsIXPConnectJSObjectHolder* GetOuterProto() { return mOuterProto; }
    1793               0 :   nsIXPConnectJSObjectHolder* GetOuterRealProto() { return mOuterRealProto; }
    1794                 : 
    1795               0 :   void DidRestoreWindow()
    1796                 :   {
    1797               0 :     mInnerWindow = nsnull;
    1798                 : 
    1799               0 :     mInnerWindowHolder = nsnull;
    1800               0 :     mOuterProto = nsnull;
    1801               0 :     mOuterRealProto = nsnull;
    1802               0 :   }
    1803                 : 
    1804                 : protected:
    1805                 :   ~WindowStateHolder();
    1806                 : 
    1807                 :   nsGlobalWindow *mInnerWindow;
    1808                 :   // We hold onto this to make sure the inner window doesn't go away. The outer
    1809                 :   // window ends up recalculating it anyway.
    1810                 :   nsCOMPtr<nsIXPConnectJSObjectHolder> mInnerWindowHolder;
    1811                 :   nsCOMPtr<nsIXPConnectJSObjectHolder> mOuterProto;
    1812                 :   nsCOMPtr<nsIXPConnectJSObjectHolder> mOuterRealProto;
    1813                 : };
    1814                 : 
    1815                 : NS_DEFINE_STATIC_IID_ACCESSOR(WindowStateHolder, WINDOWSTATEHOLDER_IID)
    1816                 : 
    1817               0 : WindowStateHolder::WindowStateHolder(nsGlobalWindow *aWindow,
    1818                 :                                      nsIXPConnectJSObjectHolder *aHolder,
    1819                 :                                      nsIXPConnectJSObjectHolder *aOuterProto,
    1820                 :                                      nsIXPConnectJSObjectHolder *aOuterRealProto)
    1821                 :   : mInnerWindow(aWindow),
    1822                 :     mOuterProto(aOuterProto),
    1823               0 :     mOuterRealProto(aOuterRealProto)
    1824                 : {
    1825               0 :   NS_PRECONDITION(aWindow, "null window");
    1826               0 :   NS_PRECONDITION(aWindow->IsInnerWindow(), "Saving an outer window");
    1827                 : 
    1828               0 :   mInnerWindowHolder = aHolder;
    1829                 : 
    1830               0 :   aWindow->SuspendTimeouts();
    1831               0 : }
    1832                 : 
    1833               0 : WindowStateHolder::~WindowStateHolder()
    1834                 : {
    1835               0 :   if (mInnerWindow) {
    1836                 :     // This window was left in the bfcache and is now going away. We need to
    1837                 :     // free it up.
    1838                 :     // Note that FreeInnerObjects may already have been called on the
    1839                 :     // inner window if its outer has already had SetDocShell(null)
    1840                 :     // called.
    1841               0 :     mInnerWindow->FreeInnerObjects();
    1842                 :   }
    1843               0 : }
    1844                 : 
    1845               0 : NS_IMPL_ISUPPORTS1(WindowStateHolder, WindowStateHolder)
    1846                 : 
    1847                 : 
    1848                 : struct ReparentWaiverClosure
    1849                 : {
    1850                 :   JSContext *mCx;
    1851                 :   JSObject *mNewInner;
    1852                 : };
    1853                 : 
    1854                 : static JSDHashOperator
    1855               0 : ReparentWaiverWrappers(JSDHashTable *table, JSDHashEntryHdr *hdr,
    1856                 :                        uint32 number, void *arg)
    1857                 : {
    1858               0 :     ReparentWaiverClosure *closure = static_cast<ReparentWaiverClosure*>(arg);
    1859               0 :     JSObject *value = static_cast<JSObject2JSObjectMap::Entry *>(hdr)->value;
    1860                 : 
    1861                 :     // We reparent wrappers that have as their parent an inner window whose
    1862                 :     // outer has the new inner window as its current inner.
    1863               0 :     JSObject *parent = JS_GetParent(value);
    1864               0 :     JSObject *outer = JS_ObjectToOuterObject(closure->mCx, parent);
    1865               0 :     if (outer) {
    1866               0 :       JSObject *inner = JS_ObjectToInnerObject(closure->mCx, outer);
    1867               0 :       if (inner == closure->mNewInner && inner != parent)
    1868               0 :         JS_SetParent(closure->mCx, value, closure->mNewInner);
    1869                 :     } else {
    1870               0 :       JS_ClearPendingException(closure->mCx);
    1871                 :     }
    1872               0 :     return JS_DHASH_NEXT;
    1873                 : }
    1874                 : 
    1875                 : nsresult
    1876               0 : nsGlobalWindow::SetNewDocument(nsIDocument* aDocument,
    1877                 :                                nsISupports* aState,
    1878                 :                                bool aForceReuseInnerWindow)
    1879                 : {
    1880                 :   NS_TIME_FUNCTION;
    1881                 : 
    1882               0 :   NS_PRECONDITION(mDocumentPrincipal == nsnull,
    1883                 :                   "mDocumentPrincipal prematurely set!");
    1884                 : 
    1885               0 :   if (!aDocument) {
    1886               0 :     NS_ERROR("SetNewDocument(null) called!");
    1887                 : 
    1888               0 :     return NS_ERROR_INVALID_ARG;
    1889                 :   }
    1890                 : 
    1891               0 :   if (IsInnerWindow()) {
    1892               0 :     if (!mOuterWindow) {
    1893               0 :       return NS_ERROR_NOT_INITIALIZED;
    1894                 :     }
    1895                 : 
    1896                 :     // Refuse to set a new document if the call came from an inner
    1897                 :     // window that's not the current inner window.
    1898               0 :     if (mOuterWindow->GetCurrentInnerWindow() != this) {
    1899               0 :       return NS_ERROR_NOT_AVAILABLE;
    1900                 :     }
    1901                 : 
    1902               0 :     return GetOuterWindowInternal()->SetNewDocument(aDocument, aState,
    1903               0 :                                                     aForceReuseInnerWindow);
    1904                 :   }
    1905                 : 
    1906               0 :   NS_PRECONDITION(IsOuterWindow(), "Must only be called on outer windows");
    1907                 : 
    1908               0 :   if (IsFrozen()) {
    1909                 :     // This outer is now getting its first inner, thaw the outer now
    1910                 :     // that it's ready and is getting an inner window.
    1911                 : 
    1912               0 :     Thaw();
    1913                 :   }
    1914                 : 
    1915               0 :   NS_ASSERTION(!GetCurrentInnerWindow() ||
    1916                 :                GetCurrentInnerWindow()->GetExtantDocument() == mDocument,
    1917                 :                "Uh, mDocument doesn't match the current inner window "
    1918                 :                "document!");
    1919                 : 
    1920               0 :   bool wouldReuseInnerWindow = WouldReuseInnerWindow(aDocument);
    1921               0 :   if (aForceReuseInnerWindow &&
    1922               0 :       !wouldReuseInnerWindow &&
    1923               0 :       mDoc &&
    1924               0 :       mDoc->NodePrincipal() != aDocument->NodePrincipal()) {
    1925               0 :     NS_ERROR("Attempted forced inner window reuse while changing principal");
    1926               0 :     return NS_ERROR_UNEXPECTED;
    1927                 :   }
    1928                 : 
    1929               0 :   nsCOMPtr<nsIDocument> oldDoc(do_QueryInterface(mDocument));
    1930                 : 
    1931               0 :   nsIScriptContext *scx = GetContextInternal();
    1932               0 :   NS_ENSURE_TRUE(scx, NS_ERROR_NOT_INITIALIZED);
    1933                 : 
    1934               0 :   JSContext *cx = scx->GetNativeContext();
    1935                 : #ifndef MOZ_DISABLE_DOMCRYPTO
    1936                 :   // clear smartcard events, our document has gone away.
    1937               0 :   if (mCrypto) {
    1938               0 :     mCrypto->SetEnableSmartCardEvents(false);
    1939                 :   }
    1940                 : #endif
    1941               0 :   if (!mDocument) {
    1942                 :     // First document load.
    1943                 : 
    1944                 :     // Get our private root. If it is equal to us, then we need to
    1945                 :     // attach our global key bindings that handles browser scrolling
    1946                 :     // and other browser commands.
    1947               0 :     nsIDOMWindow* privateRoot = nsGlobalWindow::GetPrivateRoot();
    1948                 : 
    1949               0 :     if (privateRoot == static_cast<nsIDOMWindow*>(this)) {
    1950               0 :       nsCOMPtr<nsIXBLService> xblService = do_GetService("@mozilla.org/xbl;1");
    1951               0 :       if (xblService) {
    1952               0 :         xblService->AttachGlobalKeyHandler(mChromeEventHandler);
    1953                 :       }
    1954                 :     }
    1955                 :   }
    1956                 : 
    1957                 :   /* No mDocShell means we're already been partially closed down.  When that
    1958                 :      happens, setting status isn't a big requirement, so don't. (Doesn't happen
    1959                 :      under normal circumstances, but bug 49615 describes a case.) */
    1960                 : 
    1961                 :   nsContentUtils::AddScriptRunner(
    1962               0 :     NS_NewRunnableMethod(this, &nsGlobalWindow::ClearStatus));
    1963                 : 
    1964               0 :   bool reUseInnerWindow = aForceReuseInnerWindow || wouldReuseInnerWindow;
    1965                 : 
    1966               0 :   nsresult rv = NS_OK;
    1967                 : 
    1968                 :   // Set mDocument even if this is an outer window to avoid
    1969                 :   // having to *always* reach into the inner window to find the
    1970                 :   // document.
    1971               0 :   mDocument = do_QueryInterface(aDocument);
    1972               0 :   mDoc = aDocument;
    1973                 : 
    1974                 : #ifdef DEBUG
    1975               0 :   mLastOpenedURI = aDocument->GetDocumentURI();
    1976                 : #endif
    1977                 : 
    1978               0 :   mContext->WillInitializeContext();
    1979                 : 
    1980               0 :   nsGlobalWindow *currentInner = GetCurrentInnerWindowInternal();
    1981                 : 
    1982               0 :   nsRefPtr<nsGlobalWindow> newInnerWindow;
    1983               0 :   bool createdInnerWindow = false;
    1984                 : 
    1985               0 :   bool thisChrome = IsChromeWindow();
    1986                 : 
    1987               0 :   bool isChrome = false;
    1988                 : 
    1989               0 :   nsCxPusher cxPusher;
    1990               0 :   if (!cxPusher.Push(cx)) {
    1991               0 :     return NS_ERROR_FAILURE;
    1992                 :   }
    1993                 : 
    1994               0 :   JSAutoRequest ar(cx);
    1995                 : 
    1996               0 :   nsCOMPtr<WindowStateHolder> wsh = do_QueryInterface(aState);
    1997               0 :   NS_ASSERTION(!aState || wsh, "What kind of weird state are you giving me here?");
    1998                 : 
    1999               0 :   if (reUseInnerWindow) {
    2000                 :     // We're reusing the current inner window.
    2001               0 :     NS_ASSERTION(!currentInner->IsFrozen(),
    2002                 :                  "We should never be reusing a shared inner window");
    2003               0 :     newInnerWindow = currentInner;
    2004                 : 
    2005               0 :     if (aDocument != oldDoc) {
    2006               0 :       nsWindowSH::InvalidateGlobalScopePolluter(cx, currentInner->mJSObject);
    2007                 :     }
    2008                 : 
    2009                 :     // The API we're really looking for here is to go clear all of the
    2010                 :     // Xray wrappers associated with our outer window. However, we
    2011                 :     // don't expose that API because the implementation would be
    2012                 :     // identical to that of JS_TransplantObject, so we just call that
    2013                 :     // instead.
    2014               0 :     if (!JS_TransplantObject(cx, mJSObject, mJSObject)) {
    2015               0 :       return NS_ERROR_FAILURE;
    2016                 :     }
    2017                 :   } else {
    2018               0 :     if (aState) {
    2019               0 :       newInnerWindow = wsh->GetInnerWindow();
    2020               0 :       mInnerWindowHolder = wsh->GetInnerWindowHolder();
    2021                 : 
    2022               0 :       NS_ASSERTION(newInnerWindow, "Got a state without inner window");
    2023               0 :     } else if (thisChrome) {
    2024               0 :       newInnerWindow = new nsGlobalChromeWindow(this);
    2025               0 :       isChrome = true;
    2026               0 :     } else if (mIsModalContentWindow) {
    2027               0 :       newInnerWindow = new nsGlobalModalWindow(this);
    2028                 :     } else {
    2029               0 :       newInnerWindow = new nsGlobalWindow(this);
    2030                 :     }
    2031                 : 
    2032               0 :     if (!aState) {
    2033                 :       // This is redundant if we're restoring from a previous inner window.
    2034                 :       nsIScriptGlobalObject *sgo =
    2035               0 :         (nsIScriptGlobalObject *)newInnerWindow.get();
    2036                 : 
    2037                 :       // Freeze the outer window and null out the inner window so
    2038                 :       // that initializing classes on the new inner doesn't end up
    2039                 :       // reaching into the old inner window for classes etc.
    2040                 :       //
    2041                 :       // [This happens with Object.prototype when XPConnect creates
    2042                 :       // a temporary global while initializing classes; the reason
    2043                 :       // being that xpconnect creates the temp global w/o a parent
    2044                 :       // and proto, which makes the JS engine look up classes in
    2045                 :       // cx->globalObject, i.e. this outer window].
    2046                 : 
    2047               0 :       mInnerWindow = nsnull;
    2048                 : 
    2049               0 :       Freeze();
    2050               0 :       mCreatingInnerWindow = true;
    2051                 :       // Every script context we are initialized with must create a
    2052                 :       // new global.
    2053               0 :       nsCOMPtr<nsIXPConnectJSObjectHolder> &holder = mInnerWindowHolder;
    2054               0 :       rv = mContext->CreateNativeGlobalForInner(sgo, isChrome,
    2055                 :                                                 aDocument->NodePrincipal(),
    2056               0 :                                                 &newInnerWindow->mJSObject,
    2057               0 :                                                 getter_AddRefs(holder));
    2058               0 :       NS_ASSERTION(NS_SUCCEEDED(rv) && newInnerWindow->mJSObject && holder,
    2059                 :                    "Failed to get script global and holder");
    2060                 : 
    2061               0 :       mCreatingInnerWindow = false;
    2062               0 :       createdInnerWindow = true;
    2063               0 :       Thaw();
    2064                 : 
    2065               0 :       NS_ENSURE_SUCCESS(rv, rv);
    2066                 :     }
    2067                 : 
    2068               0 :     if (currentInner && currentInner->mJSObject) {
    2069               0 :       if (oldDoc == aDocument) {
    2070                 :         // Move the navigator from the old inner window to the new one since
    2071                 :         // this is a document.write. This is safe from a same-origin point of
    2072                 :         // view because document.write can only be used by the same origin.
    2073               0 :         newInnerWindow->mNavigator = currentInner->mNavigator;
    2074               0 :         currentInner->mNavigator = nsnull;
    2075               0 :         if (newInnerWindow->mNavigator) {
    2076               0 :           newInnerWindow->mNavigator->SetWindow(newInnerWindow);
    2077                 :         }
    2078                 :       }
    2079                 : 
    2080                 :       // Don't free objects on our current inner window if it's going to be
    2081                 :       // held in the bfcache.
    2082               0 :       if (!currentInner->IsFrozen()) {
    2083               0 :         currentInner->FreeInnerObjects();
    2084                 :       }
    2085                 :     }
    2086                 : 
    2087               0 :     mInnerWindow = newInnerWindow;
    2088                 : 
    2089               0 :     if (!mJSObject) {
    2090               0 :       mContext->CreateOuterObject(this, newInnerWindow);
    2091               0 :       mContext->DidInitializeContext();
    2092                 : 
    2093               0 :       mJSObject = mContext->GetNativeGlobal();
    2094               0 :       SetWrapper(mJSObject);
    2095                 :     } else {
    2096                 :       JSObject *outerObject =
    2097               0 :         NS_NewOuterWindowProxy(cx, newInnerWindow->mJSObject);
    2098               0 :       if (!outerObject) {
    2099               0 :         NS_ERROR("out of memory");
    2100               0 :         return NS_ERROR_FAILURE;
    2101                 :       }
    2102                 : 
    2103               0 :       js::SetProxyExtra(mJSObject, 0, js::PrivateValue(NULL));
    2104                 : 
    2105               0 :       outerObject = JS_TransplantObject(cx, mJSObject, outerObject);
    2106               0 :       if (!outerObject) {
    2107               0 :         NS_ERROR("unable to transplant wrappers, probably OOM");
    2108               0 :         return NS_ERROR_FAILURE;
    2109                 :       }
    2110                 : 
    2111               0 :       nsIScriptGlobalObject *global = static_cast<nsIScriptGlobalObject*>(this);
    2112               0 :       js::SetProxyExtra(outerObject, 0, js::PrivateValue(global));
    2113                 : 
    2114               0 :       mJSObject = outerObject;
    2115               0 :       SetWrapper(mJSObject);
    2116                 : 
    2117                 :       {
    2118               0 :         JSAutoEnterCompartment ac;
    2119               0 :         if (!ac.enter(cx, mJSObject)) {
    2120               0 :           NS_ERROR("unable to enter a compartment");
    2121               0 :           return NS_ERROR_FAILURE;
    2122                 :         }
    2123                 : 
    2124               0 :         JS_SetParent(cx, mJSObject, newInnerWindow->mJSObject);
    2125                 : 
    2126               0 :         mContext->SetOuterObject(mJSObject);
    2127                 : 
    2128               0 :         JSCompartment *compartment = js::GetObjectCompartment(mJSObject);
    2129                 :         xpc::CompartmentPrivate *priv =
    2130               0 :           static_cast<xpc::CompartmentPrivate*>(JS_GetCompartmentPrivate(compartment));
    2131               0 :         if (priv && priv->waiverWrapperMap) {
    2132               0 :           NS_ASSERTION(!JS_IsExceptionPending(cx),
    2133                 :                        "We might overwrite a pending exception!");
    2134                 :           ReparentWaiverClosure closure = {
    2135                 :             cx,
    2136               0 :             newInnerWindow->mJSObject
    2137               0 :           };
    2138               0 :           priv->waiverWrapperMap->Enumerate(ReparentWaiverWrappers, &closure);
    2139                 :         }
    2140                 :       }
    2141                 :     }
    2142                 : 
    2143                 :     // If we created a new inner window above, we need to do the last little bit
    2144                 :     // of initialization now that the dust has settled.
    2145               0 :     if (createdInnerWindow) {
    2146               0 :       nsIXPConnect *xpc = nsContentUtils::XPConnect();
    2147               0 :       nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
    2148               0 :       nsresult rv = xpc->GetWrappedNativeOfJSObject(cx, newInnerWindow->mJSObject,
    2149               0 :                                                     getter_AddRefs(wrapper));
    2150               0 :       NS_ENSURE_SUCCESS(rv, rv);
    2151               0 :       NS_ABORT_IF_FALSE(wrapper, "bad wrapper");
    2152               0 :       rv = wrapper->FinishInitForWrappedGlobal();
    2153               0 :       NS_ENSURE_SUCCESS(rv, rv);
    2154                 :     }
    2155                 : 
    2156               0 :     JSAutoEnterCompartment ac;
    2157               0 :     if (!ac.enter(cx, mJSObject)) {
    2158               0 :       NS_ERROR("unable to enter a compartment");
    2159               0 :       return NS_ERROR_FAILURE;
    2160                 :     }
    2161                 : 
    2162                 :     // XXX Not sure if this is needed.
    2163               0 :     if (aState) {
    2164                 :       JSObject *proto;
    2165               0 :       if (nsIXPConnectJSObjectHolder *holder = wsh->GetOuterRealProto()) {
    2166               0 :         holder->GetJSObject(&proto);
    2167                 :       } else {
    2168               0 :         proto = nsnull;
    2169                 :       }
    2170                 : 
    2171               0 :       if (!JS_SetPrototype(cx, mJSObject, proto)) {
    2172               0 :         NS_ERROR("can't set prototype");
    2173               0 :         return NS_ERROR_FAILURE;
    2174                 :       }
    2175                 :     } else {
    2176               0 :       if (!JS_DefineProperty(cx, newInnerWindow->mJSObject, "window",
    2177               0 :                              OBJECT_TO_JSVAL(mJSObject),
    2178                 :                              JS_PropertyStub, JS_StrictPropertyStub,
    2179               0 :                              JSPROP_ENUMERATE | JSPROP_READONLY | JSPROP_PERMANENT)) {
    2180               0 :         NS_ERROR("can't create the 'window' property");
    2181               0 :         return NS_ERROR_FAILURE;
    2182                 :       }
    2183                 :     }
    2184                 :   }
    2185                 : 
    2186               0 :   JSAutoEnterCompartment ac;
    2187               0 :   if (!ac.enter(cx, mJSObject)) {
    2188               0 :     NS_ERROR("unable to enter a compartment");
    2189               0 :     return NS_ERROR_FAILURE;
    2190                 :   }
    2191                 : 
    2192               0 :   if (!aState && !reUseInnerWindow) {
    2193                 :     // Loading a new page and creating a new inner window, *not*
    2194                 :     // restoring from session history.
    2195                 : 
    2196                 :     // Now that both the the inner and outer windows are initialized
    2197                 :     // let the script context do its magic to hook them together.
    2198               0 :     mContext->ConnectToInner(newInnerWindow, mJSObject);
    2199                 : 
    2200               0 :     nsCOMPtr<nsIContent> frame = do_QueryInterface(GetFrameElementInternal());
    2201               0 :     if (frame && frame->OwnerDoc()) {
    2202               0 :       nsPIDOMWindow* parentWindow = frame->OwnerDoc()->GetWindow();
    2203               0 :       if (parentWindow && parentWindow->TimeoutSuspendCount()) {
    2204               0 :         SuspendTimeouts(parentWindow->TimeoutSuspendCount());
    2205                 :       }
    2206                 :     }
    2207                 :   }
    2208                 : 
    2209                 :   // Add an extra ref in case we release mContext during GC.
    2210               0 :   nsCOMPtr<nsIScriptContext> kungFuDeathGrip(mContext);
    2211                 : 
    2212                 :   // Now that the prototype is all set up, install the global scope
    2213                 :   // polluter. This must happen after the above prototype fixup. If
    2214                 :   // the GSP was to be installed on the inner window's real
    2215                 :   // prototype (as it would be if this was done before the prototype
    2216                 :   // fixup above) we would end up holding the GSP alive (through
    2217                 :   // XPConnect's internal marking of wrapper prototypes) as long as
    2218                 :   // the inner window was around, and if the GSP had properties on
    2219                 :   // it that held an element alive we'd hold the document alive,
    2220                 :   // which could hold event handlers alive, which hold the context
    2221                 :   // alive etc.
    2222                 : 
    2223               0 :   if ((!reUseInnerWindow || aDocument != oldDoc) && !aState) {
    2224               0 :     nsCOMPtr<nsIHTMLDocument> html_doc(do_QueryInterface(mDocument));
    2225               0 :     nsWindowSH::InstallGlobalScopePolluter(cx, newInnerWindow->mJSObject,
    2226               0 :                                            html_doc);
    2227                 :   }
    2228                 : 
    2229               0 :   if (aDocument) {
    2230               0 :     aDocument->SetScriptGlobalObject(newInnerWindow);
    2231                 :   }
    2232                 : 
    2233               0 :   if (!aState) {
    2234               0 :     if (reUseInnerWindow) {
    2235               0 :       if (newInnerWindow->mDoc != aDocument) {
    2236               0 :         newInnerWindow->mDocument = do_QueryInterface(aDocument);
    2237               0 :         newInnerWindow->mDoc = aDocument;
    2238                 : 
    2239                 :         // We're reusing the inner window for a new document. In this
    2240                 :         // case we don't clear the inner window's scope, but we must
    2241                 :         // make sure the cached document property gets updated.
    2242                 : 
    2243                 :         // XXXmarkh - tell other languages about this?
    2244               0 :         ::JS_DeleteProperty(cx, currentInner->mJSObject, "document");
    2245                 : 
    2246               0 :         if (mDummyJavaPluginOwner) {
    2247                 :           // Since we're reusing the inner window, tear down the
    2248                 :           // dummy Java plugin we created for the old document in
    2249                 :           // this window.
    2250               0 :           mDummyJavaPluginOwner->Destroy();
    2251               0 :           mDummyJavaPluginOwner = nsnull;
    2252                 : 
    2253               0 :           mDidInitJavaProperties = false;
    2254                 :         }
    2255                 :       }
    2256                 :     } else {
    2257               0 :       rv = newInnerWindow->InnerSetNewDocument(aDocument);
    2258               0 :       NS_ENSURE_SUCCESS(rv, rv);
    2259                 : 
    2260                 :       // Initialize DOM classes etc on the inner window.
    2261               0 :       rv = mContext->InitClasses(newInnerWindow->mJSObject);
    2262               0 :       NS_ENSURE_SUCCESS(rv, rv);
    2263                 :     }
    2264                 : 
    2265               0 :     if (mArguments) {
    2266               0 :       newInnerWindow->DefineArgumentsProperty(mArguments);
    2267               0 :       newInnerWindow->mArguments = mArguments;
    2268               0 :       newInnerWindow->mArgumentsOrigin = mArgumentsOrigin;
    2269                 : 
    2270               0 :       mArguments = nsnull;
    2271               0 :       mArgumentsOrigin = nsnull;
    2272                 :     }
    2273                 : 
    2274                 :     // Give the new inner window our chrome event handler (since it
    2275                 :     // doesn't have one).
    2276               0 :     newInnerWindow->mChromeEventHandler = mChromeEventHandler;
    2277                 :   }
    2278                 : 
    2279               0 :   mContext->GC(js::gcreason::SET_NEW_DOCUMENT);
    2280               0 :   mContext->DidInitializeContext();
    2281                 : 
    2282               0 :   if (newInnerWindow && !newInnerWindow->mHasNotifiedGlobalCreated && mDoc) {
    2283                 :     // We should probably notify. However if this is the, arguably bad,
    2284                 :     // situation when we're creating a temporary non-chrome-about-blank
    2285                 :     // document in a chrome docshell, don't notify just yet. Instead wait
    2286                 :     // until we have a real chrome doc.
    2287               0 :     nsCOMPtr<nsIDocShellTreeItem> treeItem(do_QueryInterface(mDocShell));
    2288               0 :     PRInt32 itemType = nsIDocShellTreeItem::typeContent;
    2289               0 :     if (treeItem) {
    2290               0 :       treeItem->GetItemType(&itemType);
    2291                 :     }
    2292                 : 
    2293               0 :     if (itemType != nsIDocShellTreeItem::typeChrome ||
    2294               0 :         nsContentUtils::IsSystemPrincipal(mDoc->NodePrincipal())) {
    2295               0 :       newInnerWindow->mHasNotifiedGlobalCreated = true;
    2296                 :       nsContentUtils::AddScriptRunner(
    2297               0 :         NS_NewRunnableMethod(this, &nsGlobalWindow::DispatchDOMWindowCreated));
    2298                 :     }
    2299                 :   }
    2300                 : 
    2301               0 :   return NS_OK;
    2302                 : }
    2303                 : 
    2304                 : void
    2305               0 : nsGlobalWindow::DispatchDOMWindowCreated()
    2306                 : {
    2307               0 :   if (!mDoc || !mDocument) {
    2308               0 :     return;
    2309                 :   }
    2310                 : 
    2311                 :   // Fire DOMWindowCreated at chrome event listeners
    2312               0 :   nsContentUtils::DispatchChromeEvent(mDoc, mDocument, NS_LITERAL_STRING("DOMWindowCreated"),
    2313                 :                                       true /* bubbles */,
    2314               0 :                                       false /* not cancellable */);
    2315                 : 
    2316                 :   nsCOMPtr<nsIObserverService> observerService =
    2317               0 :     mozilla::services::GetObserverService();
    2318               0 :   if (observerService) {
    2319               0 :     nsAutoString origin;
    2320               0 :     nsIPrincipal* principal = mDoc->NodePrincipal();
    2321               0 :     nsContentUtils::GetUTFOrigin(principal, origin);
    2322               0 :     observerService->
    2323                 :       NotifyObservers(static_cast<nsIDOMWindow*>(this),
    2324               0 :                       nsContentUtils::IsSystemPrincipal(principal) ?
    2325                 :                         "chrome-document-global-created" :
    2326                 :                         "content-document-global-created",
    2327               0 :                       origin.get());
    2328                 :   }
    2329                 : }
    2330                 : 
    2331                 : void
    2332               0 : nsGlobalWindow::ClearStatus()
    2333                 : {
    2334               0 :   SetStatus(EmptyString());
    2335               0 :   SetDefaultStatus(EmptyString());
    2336               0 : }
    2337                 : 
    2338                 : nsresult
    2339               0 : nsGlobalWindow::InnerSetNewDocument(nsIDocument* aDocument)
    2340                 : {
    2341               0 :   NS_PRECONDITION(IsInnerWindow(), "Must only be called on inner windows");
    2342                 : 
    2343                 : #ifdef PR_LOGGING
    2344               0 :   if (aDocument && gDOMLeakPRLog &&
    2345                 :       PR_LOG_TEST(gDOMLeakPRLog, PR_LOG_DEBUG)) {
    2346               0 :     nsIURI *uri = aDocument->GetDocumentURI();
    2347               0 :     nsCAutoString spec;
    2348               0 :     if (uri)
    2349               0 :       uri->GetSpec(spec);
    2350               0 :     PR_LogPrint("DOMWINDOW %p SetNewDocument %s", this, spec.get());
    2351                 :   }
    2352                 : #endif
    2353                 : 
    2354               0 :   mDocument = do_QueryInterface(aDocument);
    2355               0 :   mDoc = aDocument;
    2356               0 :   mFocusedNode = nsnull;
    2357               0 :   mLocalStorage = nsnull;
    2358               0 :   mSessionStorage = nsnull;
    2359                 : 
    2360                 : #ifdef DEBUG
    2361               0 :   mLastOpenedURI = aDocument->GetDocumentURI();
    2362                 : #endif
    2363                 : 
    2364                 :   Telemetry::Accumulate(Telemetry::INNERWINDOWS_WITH_MUTATION_LISTENERS,
    2365               0 :                         mMutationBits ? 1 : 0);
    2366                 : 
    2367                 :   // Clear our mutation bitfield.
    2368               0 :   mMutationBits = 0;
    2369                 : 
    2370               0 :   return NS_OK;
    2371                 : }
    2372                 : 
    2373                 : void
    2374               0 : nsGlobalWindow::SetDocShell(nsIDocShell* aDocShell)
    2375                 : {
    2376               0 :   NS_ASSERTION(IsOuterWindow(), "Uh, SetDocShell() called on inner window!");
    2377                 : 
    2378               0 :   if (aDocShell == mDocShell)
    2379               0 :     return;
    2380                 : 
    2381                 :   // SetDocShell(nsnull) means the window is being torn down. Drop our
    2382                 :   // reference to the script context, allowing it to be deleted
    2383                 :   // later. Meanwhile, keep our weak reference to the script object
    2384                 :   // (mJSObject) so that it can be retrieved later (until it is
    2385                 :   // finalized by the JS GC).
    2386                 : 
    2387               0 :   if (!aDocShell) {
    2388               0 :     NS_ASSERTION(PR_CLIST_IS_EMPTY(&mTimeouts),
    2389                 :                  "Uh, outer window holds timeouts!");
    2390                 : 
    2391                 :     // Call FreeInnerObjects on all inner windows, not just the current
    2392                 :     // one, since some could be held by WindowStateHolder objects that
    2393                 :     // are GC-owned.
    2394               0 :     for (nsRefPtr<nsGlobalWindow> inner = (nsGlobalWindow *)PR_LIST_HEAD(this);
    2395                 :          inner != this;
    2396               0 :          inner = (nsGlobalWindow*)PR_NEXT_LINK(inner)) {
    2397               0 :       NS_ASSERTION(!inner->mOuterWindow || inner->mOuterWindow == this,
    2398                 :                    "bad outer window pointer");
    2399               0 :       inner->FreeInnerObjects();
    2400                 :     }
    2401                 : 
    2402                 :     // Make sure that this is called before we null out the document.
    2403               0 :     NotifyDOMWindowDestroyed(this);
    2404                 : 
    2405               0 :     NotifyWindowIDDestroyed("outer-window-destroyed");
    2406                 : 
    2407               0 :     nsGlobalWindow *currentInner = GetCurrentInnerWindowInternal();
    2408                 : 
    2409               0 :     if (currentInner) {
    2410               0 :       NS_ASSERTION(mDoc, "Must have doc!");
    2411                 :       
    2412                 :       // Remember the document's principal.
    2413               0 :       mDocumentPrincipal = mDoc->NodePrincipal();
    2414                 : 
    2415                 :       // Release our document reference
    2416               0 :       mDocument = nsnull;
    2417               0 :       mDoc = nsnull;
    2418               0 :       mFocusedNode = nsnull;
    2419                 :     }
    2420                 : 
    2421               0 :     ClearControllers();
    2422                 : 
    2423               0 :     mChromeEventHandler = nsnull; // force release now
    2424                 : 
    2425               0 :     if (mArguments) { 
    2426                 :       // We got no new document after someone called
    2427                 :       // SetArguments(), drop our reference to the arguments.
    2428               0 :       mArguments = nsnull;
    2429               0 :       mArgumentsLast = nsnull;
    2430               0 :       mArgumentsOrigin = nsnull;
    2431                 :     }
    2432                 : 
    2433               0 :     if (mContext) {
    2434               0 :       mContext->GC(js::gcreason::SET_DOC_SHELL);
    2435               0 :       mContext = nsnull;
    2436                 :     }
    2437                 : 
    2438                 : #ifdef DEBUG
    2439               0 :     nsCycleCollector_DEBUG_shouldBeFreed(mContext);
    2440               0 :     nsCycleCollector_DEBUG_shouldBeFreed(static_cast<nsIScriptGlobalObject*>(this));
    2441                 : #endif
    2442                 :   }
    2443                 : 
    2444               0 :   mDocShell = aDocShell;        // Weak Reference
    2445                 : 
    2446               0 :   NS_ASSERTION(!mNavigator, "Non-null mNavigator in outer window!");
    2447                 : 
    2448               0 :   if (mFrames)
    2449               0 :     mFrames->SetDocShell(aDocShell);
    2450               0 :   if (mScreen)
    2451               0 :     mScreen->SetDocShell(aDocShell);
    2452                 : 
    2453               0 :   if (!mDocShell) {
    2454               0 :     MaybeForgiveSpamCount();
    2455               0 :     CleanUp(false);
    2456                 :   } else {
    2457                 :     // Get our enclosing chrome shell and retrieve its global window impl, so
    2458                 :     // that we can do some forwarding to the chrome document.
    2459               0 :     nsCOMPtr<nsIDOMEventTarget> chromeEventHandler;
    2460               0 :     mDocShell->GetChromeEventHandler(getter_AddRefs(chromeEventHandler));
    2461               0 :     mChromeEventHandler = do_QueryInterface(chromeEventHandler);
    2462               0 :     if (!mChromeEventHandler) {
    2463                 :       // We have no chrome event handler. If we have a parent,
    2464                 :       // get our chrome event handler from the parent. If
    2465                 :       // we don't have a parent, then we need to make a new
    2466                 :       // window root object that will function as a chrome event
    2467                 :       // handler and receive all events that occur anywhere inside
    2468                 :       // our window.
    2469               0 :       nsCOMPtr<nsIDOMWindow> parentWindow;
    2470               0 :       GetParent(getter_AddRefs(parentWindow));
    2471               0 :       if (parentWindow.get() != static_cast<nsIDOMWindow*>(this)) {
    2472               0 :         nsCOMPtr<nsPIDOMWindow> piWindow(do_QueryInterface(parentWindow));
    2473               0 :         mChromeEventHandler = piWindow->GetChromeEventHandler();
    2474                 :       }
    2475               0 :       else NS_NewWindowRoot(this, getter_AddRefs(mChromeEventHandler));
    2476                 :     }
    2477                 : 
    2478                 :     bool docShellActive;
    2479               0 :     mDocShell->GetIsActive(&docShellActive);
    2480               0 :     mIsBackground = !docShellActive;
    2481                 :   }
    2482                 : }
    2483                 : 
    2484                 : void
    2485               0 : nsGlobalWindow::SetOpenerWindow(nsIDOMWindow* aOpener,
    2486                 :                                 bool aOriginalOpener)
    2487                 : {
    2488               0 :   FORWARD_TO_OUTER_VOID(SetOpenerWindow, (aOpener, aOriginalOpener));
    2489                 : 
    2490               0 :   NS_ASSERTION(!aOriginalOpener || !mSetOpenerWindowCalled,
    2491                 :                "aOriginalOpener is true, but not first call to "
    2492                 :                "SetOpenerWindow!");
    2493               0 :   NS_ASSERTION(aOpener || !aOriginalOpener,
    2494                 :                "Shouldn't set mHadOriginalOpener if aOpener is null");
    2495                 : 
    2496               0 :   mOpener = do_GetWeakReference(aOpener);
    2497               0 :   NS_ASSERTION(mOpener || !aOpener, "Opener must support weak references!");
    2498                 : 
    2499               0 :   if (aOriginalOpener) {
    2500               0 :     mHadOriginalOpener = true;
    2501                 :   }
    2502                 : 
    2503                 : #ifdef DEBUG
    2504               0 :   mSetOpenerWindowCalled = true;
    2505                 : #endif
    2506                 : }
    2507                 : 
    2508                 : void
    2509               0 : nsGlobalWindow::UpdateParentTarget()
    2510                 : {
    2511               0 :   nsCOMPtr<nsIFrameLoaderOwner> flo = do_QueryInterface(mChromeEventHandler);
    2512               0 :   if (flo) {
    2513               0 :     nsRefPtr<nsFrameLoader> fl = flo->GetFrameLoader();
    2514               0 :     if (fl) {
    2515               0 :       mParentTarget = fl->GetTabChildGlobalAsEventTarget();
    2516                 :     }
    2517                 :   }
    2518               0 :   if (!mParentTarget) {
    2519               0 :     mParentTarget = mChromeEventHandler;
    2520                 :   }
    2521               0 : }
    2522                 : 
    2523                 : bool
    2524               0 : nsGlobalWindow::GetIsTabModalPromptAllowed()
    2525                 : {
    2526               0 :   bool allowTabModal = true;
    2527               0 :   if (mDocShell) {
    2528               0 :     nsCOMPtr<nsIContentViewer> cv;
    2529               0 :     mDocShell->GetContentViewer(getter_AddRefs(cv));
    2530               0 :     cv->GetIsTabModalPromptAllowed(&allowTabModal);
    2531                 :   }
    2532                 : 
    2533               0 :   return allowTabModal;
    2534                 : }
    2535                 : 
    2536                 : nsIDOMEventTarget*
    2537               0 : nsGlobalWindow::GetTargetForDOMEvent()
    2538                 : {
    2539               0 :   return static_cast<nsIDOMEventTarget*>(GetOuterWindowInternal());
    2540                 : }
    2541                 : 
    2542                 : nsIDOMEventTarget*
    2543               0 : nsGlobalWindow::GetTargetForEventTargetChain()
    2544                 : {
    2545               0 :   return IsInnerWindow() ?
    2546               0 :     this : static_cast<nsIDOMEventTarget*>(GetCurrentInnerWindowInternal());
    2547                 : }
    2548                 : 
    2549                 : nsresult
    2550               0 : nsGlobalWindow::WillHandleEvent(nsEventChainPostVisitor& aVisitor)
    2551                 : {
    2552               0 :   return NS_OK;
    2553                 : }
    2554                 : 
    2555                 : JSContext*
    2556               0 : nsGlobalWindow::GetJSContextForEventHandlers()
    2557                 : {
    2558               0 :   return nsnull;
    2559                 : }
    2560                 : 
    2561                 : nsresult
    2562               0 : nsGlobalWindow::PreHandleEvent(nsEventChainPreVisitor& aVisitor)
    2563                 : {
    2564               0 :   NS_PRECONDITION(IsInnerWindow(), "PreHandleEvent is used on outer window!?");
    2565                 :   static PRUint32 count = 0;
    2566               0 :   PRUint32 msg = aVisitor.mEvent->message;
    2567                 : 
    2568               0 :   aVisitor.mCanHandle = true;
    2569               0 :   aVisitor.mForceContentDispatch = true; //FIXME! Bug 329119
    2570               0 :   if ((msg == NS_MOUSE_MOVE) && gEntropyCollector) {
    2571                 :     //Chances are this counter will overflow during the life of the
    2572                 :     //process, but that's OK for our case. Means we get a little
    2573                 :     //more entropy.
    2574               0 :     if (count++ % 100 == 0) {
    2575                 :       //Since the high bits seem to be zero's most of the time,
    2576                 :       //let's only take the lowest half of the point structure.
    2577                 :       PRInt16 myCoord[2];
    2578                 : 
    2579               0 :       myCoord[0] = aVisitor.mEvent->refPoint.x;
    2580               0 :       myCoord[1] = aVisitor.mEvent->refPoint.y;
    2581               0 :       gEntropyCollector->RandomUpdate((void*)myCoord, sizeof(myCoord));
    2582                 :       gEntropyCollector->RandomUpdate((void*)&(aVisitor.mEvent->time),
    2583               0 :                                       sizeof(PRUint32));
    2584               0 :     }
    2585               0 :   } else if (msg == NS_RESIZE_EVENT) {
    2586               0 :     mIsHandlingResizeEvent = true;
    2587               0 :   } else if (msg == NS_MOUSE_BUTTON_DOWN &&
    2588                 :              NS_IS_TRUSTED_EVENT(aVisitor.mEvent)) {
    2589               0 :     gMouseDown = true;
    2590               0 :   } else if ((msg == NS_MOUSE_BUTTON_UP ||
    2591                 :               msg == NS_DRAGDROP_END) &&
    2592                 :              NS_IS_TRUSTED_EVENT(aVisitor.mEvent)) {
    2593               0 :     gMouseDown = false;
    2594               0 :     if (gDragServiceDisabled) {
    2595                 :       nsCOMPtr<nsIDragService> ds =
    2596               0 :         do_GetService("@mozilla.org/widget/dragservice;1");
    2597               0 :       if (ds) {
    2598               0 :         gDragServiceDisabled = false;
    2599               0 :         ds->Unsuppress();
    2600                 :       }
    2601                 :     }
    2602                 :   }
    2603                 : 
    2604               0 :   aVisitor.mParentTarget = GetParentTarget();
    2605               0 :   return NS_OK;
    2606                 : }
    2607                 : 
    2608                 : bool
    2609               0 : nsGlobalWindow::DialogOpenAttempted()
    2610                 : {
    2611               0 :   nsGlobalWindow *topWindow = GetTop();
    2612               0 :   if (!topWindow) {
    2613               0 :     NS_ERROR("DialogOpenAttempted() called without a top window?");
    2614                 : 
    2615               0 :     return false;
    2616                 :   }
    2617                 : 
    2618               0 :   topWindow = topWindow->GetCurrentInnerWindowInternal();
    2619               0 :   if (!topWindow ||
    2620               0 :       topWindow->mLastDialogQuitTime.IsNull() ||
    2621               0 :       nsContentUtils::CallerHasUniversalXPConnect()) {
    2622               0 :     return false;
    2623                 :   }
    2624                 : 
    2625                 :   TimeDuration dialogDuration(TimeStamp::Now() -
    2626               0 :                               topWindow->mLastDialogQuitTime);
    2627                 : 
    2628               0 :   if (dialogDuration.ToSeconds() <
    2629                 :         Preferences::GetInt("dom.successive_dialog_time_limit",
    2630               0 :                             SUCCESSIVE_DIALOG_TIME_LIMIT)) {
    2631               0 :     topWindow->mDialogAbuseCount++;
    2632                 : 
    2633               0 :     return (topWindow->GetPopupControlState() > openAllowed ||
    2634               0 :             topWindow->mDialogAbuseCount > MAX_DIALOG_COUNT);
    2635                 :   }
    2636                 : 
    2637               0 :   topWindow->mDialogAbuseCount = 0;
    2638                 : 
    2639               0 :   return false;
    2640                 : }
    2641                 : 
    2642                 : bool
    2643               0 : nsGlobalWindow::AreDialogsBlocked()
    2644                 : {
    2645               0 :   nsGlobalWindow *topWindow = GetTop();
    2646               0 :   if (!topWindow) {
    2647               0 :     NS_ASSERTION(!mDocShell, "AreDialogsBlocked() called without a top window?");
    2648                 : 
    2649               0 :     return true;
    2650                 :   }
    2651                 : 
    2652               0 :   topWindow = topWindow->GetCurrentInnerWindowInternal();
    2653                 : 
    2654                 :   return !topWindow ||
    2655                 :          (topWindow->mDialogDisabled &&
    2656               0 :           (topWindow->GetPopupControlState() > openAllowed ||
    2657               0 :            topWindow->mDialogAbuseCount >= MAX_DIALOG_COUNT));
    2658                 : }
    2659                 : 
    2660                 : bool
    2661               0 : nsGlobalWindow::ConfirmDialogAllowed()
    2662                 : {
    2663               0 :   FORWARD_TO_OUTER(ConfirmDialogAllowed, (), false);
    2664                 : 
    2665               0 :   NS_ENSURE_TRUE(mDocShell, false);
    2666                 :   nsCOMPtr<nsIPromptService> promptSvc =
    2667               0 :     do_GetService("@mozilla.org/embedcomp/prompt-service;1");
    2668                 : 
    2669               0 :   if (!DialogOpenAttempted() || !promptSvc) {
    2670               0 :     return true;
    2671                 :   }
    2672                 : 
    2673                 :   // Reset popup state while opening a modal dialog, and firing events
    2674                 :   // about the dialog, to prevent the current state from being active
    2675                 :   // the whole time a modal dialog is open.
    2676               0 :   nsAutoPopupStatePusher popupStatePusher(openAbused, true);
    2677                 : 
    2678               0 :   bool disableDialog = false;
    2679               0 :   nsXPIDLString label, title;
    2680                 :   nsContentUtils::GetLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES,
    2681               0 :                                      "ScriptDialogLabel", label);
    2682                 :   nsContentUtils::GetLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES,
    2683               0 :                                      "ScriptDialogPreventTitle", title);
    2684               0 :   promptSvc->Confirm(this, title.get(), label.get(), &disableDialog);
    2685               0 :   if (disableDialog) {
    2686               0 :     PreventFurtherDialogs();
    2687               0 :     return false;
    2688                 :   }
    2689                 : 
    2690               0 :   return true;
    2691                 : }
    2692                 : 
    2693                 : void
    2694               0 : nsGlobalWindow::PreventFurtherDialogs()
    2695                 : {
    2696               0 :   nsGlobalWindow *topWindow = GetTop();
    2697               0 :   if (!topWindow) {
    2698               0 :     NS_ERROR("PreventFurtherDialogs() called without a top window?");
    2699                 : 
    2700               0 :     return;
    2701                 :   }
    2702                 : 
    2703               0 :   topWindow = topWindow->GetCurrentInnerWindowInternal();
    2704                 : 
    2705               0 :   if (topWindow)
    2706               0 :     topWindow->mDialogDisabled = true;
    2707                 : }
    2708                 : 
    2709                 : nsresult
    2710               0 : nsGlobalWindow::PostHandleEvent(nsEventChainPostVisitor& aVisitor)
    2711                 : {
    2712               0 :   NS_PRECONDITION(IsInnerWindow(), "PostHandleEvent is used on outer window!?");
    2713                 : 
    2714                 :   // Return early if there is nothing to do.
    2715               0 :   switch (aVisitor.mEvent->message) {
    2716                 :     case NS_RESIZE_EVENT:
    2717                 :     case NS_PAGE_UNLOAD:
    2718                 :     case NS_LOAD:
    2719                 :       break;
    2720                 :     default:
    2721               0 :       return NS_OK;
    2722                 :   }
    2723                 : 
    2724                 :   /* mChromeEventHandler and mContext go dangling in the middle of this
    2725                 :    function under some circumstances (events that destroy the window)
    2726                 :    without this addref. */
    2727               0 :   nsCOMPtr<nsIDOMEventTarget> kungFuDeathGrip1(mChromeEventHandler);
    2728               0 :   nsCOMPtr<nsIScriptContext> kungFuDeathGrip2(GetContextInternal());
    2729                 : 
    2730               0 :   if (aVisitor.mEvent->message == NS_RESIZE_EVENT) {
    2731               0 :     mIsHandlingResizeEvent = false;
    2732               0 :   } else if (aVisitor.mEvent->message == NS_PAGE_UNLOAD &&
    2733                 :              NS_IS_TRUSTED_EVENT(aVisitor.mEvent)) {
    2734                 :     // Execute bindingdetached handlers before we tear ourselves
    2735                 :     // down.
    2736               0 :     if (mDocument) {
    2737               0 :       NS_ASSERTION(mDoc, "Must have doc");
    2738               0 :       mDoc->BindingManager()->ExecuteDetachedHandlers();
    2739                 :     }
    2740               0 :     mIsDocumentLoaded = false;
    2741               0 :   } else if (aVisitor.mEvent->message == NS_LOAD &&
    2742                 :              NS_IS_TRUSTED_EVENT(aVisitor.mEvent)) {
    2743                 :     // This is page load event since load events don't propagate to |window|.
    2744                 :     // @see nsDocument::PreHandleEvent.
    2745               0 :     mIsDocumentLoaded = true;
    2746                 : 
    2747               0 :     nsCOMPtr<nsIContent> content(do_QueryInterface(GetFrameElementInternal()));
    2748                 :     nsCOMPtr<nsIDocShellTreeItem> treeItem =
    2749               0 :       do_QueryInterface(GetDocShell());
    2750                 : 
    2751               0 :     PRInt32 itemType = nsIDocShellTreeItem::typeChrome;
    2752                 : 
    2753               0 :     if (treeItem) {
    2754               0 :       treeItem->GetItemType(&itemType);
    2755                 :     }
    2756                 : 
    2757               0 :     if (content && GetParentInternal() &&
    2758                 :         itemType != nsIDocShellTreeItem::typeChrome) {
    2759                 :       // If we're not in chrome, or at a chrome boundary, fire the
    2760                 :       // onload event for the frame element.
    2761                 : 
    2762               0 :       nsEventStatus status = nsEventStatus_eIgnore;
    2763               0 :       nsEvent event(NS_IS_TRUSTED_EVENT(aVisitor.mEvent), NS_LOAD);
    2764               0 :       event.flags |= NS_EVENT_FLAG_CANT_BUBBLE;
    2765                 : 
    2766                 :       // Most of the time we could get a pres context to pass in here,
    2767                 :       // but not always (i.e. if this window is not shown there won't
    2768                 :       // be a pres context available). Since we're not firing a GUI
    2769                 :       // event we don't need a pres context anyway so we just pass
    2770                 :       // null as the pres context all the time here.
    2771               0 :       nsEventDispatcher::Dispatch(content, nsnull, &event, nsnull, &status);
    2772                 :     }
    2773                 :   }
    2774                 : 
    2775               0 :   return NS_OK;
    2776                 : }
    2777                 : 
    2778                 : nsresult
    2779               0 : nsGlobalWindow::DispatchDOMEvent(nsEvent* aEvent,
    2780                 :                                  nsIDOMEvent* aDOMEvent,
    2781                 :                                  nsPresContext* aPresContext,
    2782                 :                                  nsEventStatus* aEventStatus)
    2783                 : {
    2784                 :   return
    2785                 :     nsEventDispatcher::DispatchDOMEvent(static_cast<nsPIDOMWindow*>(this),
    2786                 :                                        aEvent, aDOMEvent, aPresContext,
    2787               0 :                                        aEventStatus);
    2788                 : }
    2789                 : 
    2790                 : void
    2791               0 : nsGlobalWindow::OnFinalize(JSObject* aObject)
    2792                 : {
    2793               0 :   if (aObject == mJSObject) {
    2794               0 :     mJSObject = NULL;
    2795                 :   }
    2796               0 : }
    2797                 : 
    2798                 : void
    2799               0 : nsGlobalWindow::SetScriptsEnabled(bool aEnabled, bool aFireTimeouts)
    2800                 : {
    2801               0 :   FORWARD_TO_INNER_VOID(SetScriptsEnabled, (aEnabled, aFireTimeouts));
    2802                 : 
    2803               0 :   if (aEnabled && aFireTimeouts) {
    2804                 :     // Scripts are enabled (again?) on this context, run timeouts that
    2805                 :     // fired on this context while scripts were disabled.
    2806               0 :     void (nsGlobalWindow::*run)() = &nsGlobalWindow::RunTimeout;
    2807               0 :     NS_DispatchToCurrentThread(NS_NewRunnableMethod(this, run));
    2808                 :   }
    2809                 : }
    2810                 : 
    2811                 : nsresult
    2812               0 : nsGlobalWindow::SetArguments(nsIArray *aArguments, nsIPrincipal *aOrigin)
    2813                 : {
    2814               0 :   FORWARD_TO_OUTER(SetArguments, (aArguments, aOrigin),
    2815                 :                    NS_ERROR_NOT_INITIALIZED);
    2816                 : 
    2817                 :   // Hold on to the arguments so that we can re-set them once the next
    2818                 :   // document is loaded.
    2819               0 :   mArguments = aArguments;
    2820               0 :   mArgumentsOrigin = aOrigin;
    2821                 : 
    2822               0 :   nsGlobalWindow *currentInner = GetCurrentInnerWindowInternal();
    2823                 : 
    2824               0 :   if (!mIsModalContentWindow) {
    2825               0 :     mArgumentsLast = aArguments;
    2826               0 :   } else if (currentInner) {
    2827                 :     // SetArguments() is being called on a modal content window that
    2828                 :     // already has an inner window. This can happen when loading
    2829                 :     // javascript: URIs as modal content dialogs. In this case, we'll
    2830                 :     // set up the dialog window, both inner and outer, before we call
    2831                 :     // SetArguments() on the window, so to deal with that, make sure
    2832                 :     // here that the arguments are propagated to the inner window.
    2833                 : 
    2834               0 :     currentInner->mArguments = aArguments;
    2835               0 :     currentInner->mArgumentsOrigin = aOrigin;
    2836                 :   }
    2837                 : 
    2838                 :   return currentInner ?
    2839               0 :     currentInner->DefineArgumentsProperty(aArguments) : NS_OK;
    2840                 : }
    2841                 : 
    2842                 : nsresult
    2843               0 : nsGlobalWindow::DefineArgumentsProperty(nsIArray *aArguments)
    2844                 : {
    2845                 :   JSContext *cx;
    2846               0 :   nsIScriptContext *ctx = GetOuterWindowInternal()->mContext;
    2847               0 :   NS_ENSURE_TRUE(aArguments && ctx &&
    2848                 :                  (cx = ctx->GetNativeContext()),
    2849                 :                  NS_ERROR_NOT_INITIALIZED);
    2850                 : 
    2851               0 :   if (mIsModalContentWindow) {
    2852                 :     // Modal content windows don't have an "arguments" property, they
    2853                 :     // have a "dialogArguments" property which is handled
    2854                 :     // separately. See nsWindowSH::NewResolve().
    2855                 : 
    2856               0 :     return NS_OK;
    2857                 :   }
    2858                 : 
    2859               0 :   return GetContextInternal()->SetProperty(mJSObject, "arguments", aArguments);
    2860                 : }
    2861                 : 
    2862                 : //*****************************************************************************
    2863                 : // nsGlobalWindow::nsIScriptObjectPrincipal
    2864                 : //*****************************************************************************
    2865                 : 
    2866                 : nsIPrincipal*
    2867               0 : nsGlobalWindow::GetPrincipal()
    2868                 : {
    2869               0 :   if (mDoc) {
    2870                 :     // If we have a document, get the principal from the document
    2871               0 :     return mDoc->NodePrincipal();
    2872                 :   }
    2873                 : 
    2874               0 :   if (mDocumentPrincipal) {
    2875               0 :     return mDocumentPrincipal;
    2876                 :   }
    2877                 : 
    2878                 :   // If we don't have a principal and we don't have a document we
    2879                 :   // ask the parent window for the principal. This can happen when
    2880                 :   // loading a frameset that has a <frame src="javascript:xxx">, in
    2881                 :   // that case the global window is used in JS before we've loaded
    2882                 :   // a document into the window.
    2883                 : 
    2884                 :   nsCOMPtr<nsIScriptObjectPrincipal> objPrincipal =
    2885               0 :     do_QueryInterface(GetParentInternal());
    2886                 : 
    2887               0 :   if (objPrincipal) {
    2888               0 :     return objPrincipal->GetPrincipal();
    2889                 :   }
    2890                 : 
    2891               0 :   return nsnull;
    2892                 : }
    2893                 : 
    2894                 : //*****************************************************************************
    2895                 : // nsGlobalWindow::nsIDOMWindow
    2896                 : //*****************************************************************************
    2897                 : 
    2898                 : NS_IMETHODIMP
    2899               0 : nsGlobalWindow::GetDocument(nsIDOMDocument** aDocument)
    2900                 : {
    2901                 :   // This method *should* forward calls to the outer window, but since
    2902                 :   // there's nothing here that *depends* on anything in the outer
    2903                 :   // (GetDocShell() eliminates that dependency), we won't do that to
    2904                 :   // avoid the extra virtual function call.
    2905                 : 
    2906                 :   // lazily instantiate an about:blank document if necessary, and if
    2907                 :   // we have what it takes to do so. Note that domdoc here is the same
    2908                 :   // thing as our mDocument, but we don't have to explicitly set the
    2909                 :   // member variable because the docshell has already called
    2910                 :   // SetNewDocument().
    2911                 :   nsIDocShell *docShell;
    2912               0 :   if (!mDocument && (docShell = GetDocShell()))
    2913               0 :     nsCOMPtr<nsIDOMDocument> domdoc(do_GetInterface(docShell));
    2914                 : 
    2915               0 :   NS_IF_ADDREF(*aDocument = mDocument);
    2916                 : 
    2917               0 :   return NS_OK;
    2918                 : }
    2919                 : 
    2920                 : NS_IMETHODIMP
    2921               0 : nsGlobalWindow::GetWindow(nsIDOMWindow** aWindow)
    2922                 : {
    2923               0 :   FORWARD_TO_OUTER(GetWindow, (aWindow), NS_ERROR_NOT_INITIALIZED);
    2924                 : 
    2925               0 :   *aWindow = static_cast<nsIDOMWindow*>(this);
    2926               0 :   NS_ADDREF(*aWindow);
    2927               0 :   return NS_OK;
    2928                 : }
    2929                 : 
    2930                 : NS_IMETHODIMP
    2931               0 : nsGlobalWindow::GetSelf(nsIDOMWindow** aWindow)
    2932                 : {
    2933               0 :   FORWARD_TO_OUTER(GetSelf, (aWindow), NS_ERROR_NOT_INITIALIZED);
    2934                 : 
    2935               0 :   *aWindow = static_cast<nsIDOMWindow*>(this);
    2936               0 :   NS_ADDREF(*aWindow);
    2937               0 :   return NS_OK;
    2938                 : }
    2939                 : 
    2940                 : NS_IMETHODIMP
    2941               0 : nsGlobalWindow::GetNavigator(nsIDOMNavigator** aNavigator)
    2942                 : {
    2943               0 :   FORWARD_TO_INNER(GetNavigator, (aNavigator), NS_ERROR_NOT_INITIALIZED);
    2944                 : 
    2945               0 :   *aNavigator = nsnull;
    2946                 : 
    2947               0 :   if (!mNavigator) {
    2948               0 :     mNavigator = new Navigator(this);
    2949                 :   }
    2950                 : 
    2951               0 :   NS_ADDREF(*aNavigator = mNavigator);
    2952                 : 
    2953               0 :   return NS_OK;
    2954                 : }
    2955                 : 
    2956                 : NS_IMETHODIMP
    2957               0 : nsGlobalWindow::GetScreen(nsIDOMScreen** aScreen)
    2958                 : {
    2959               0 :   FORWARD_TO_OUTER(GetScreen, (aScreen), NS_ERROR_NOT_INITIALIZED);
    2960                 : 
    2961               0 :   *aScreen = nsnull;
    2962                 : 
    2963               0 :   if (!mScreen && mDocShell) {
    2964               0 :     mScreen = new nsScreen(mDocShell);
    2965               0 :     if (!mScreen) {
    2966               0 :       return NS_ERROR_OUT_OF_MEMORY;
    2967                 :     }
    2968                 :   }
    2969                 : 
    2970               0 :   NS_IF_ADDREF(*aScreen = mScreen);
    2971                 : 
    2972               0 :   return NS_OK;
    2973                 : }
    2974                 : 
    2975                 : NS_IMETHODIMP
    2976               0 : nsGlobalWindow::GetHistory(nsIDOMHistory** aHistory)
    2977                 : {
    2978               0 :   FORWARD_TO_INNER(GetHistory, (aHistory), NS_ERROR_NOT_INITIALIZED);
    2979                 : 
    2980               0 :   *aHistory = nsnull;
    2981                 : 
    2982               0 :   if (!mHistory) {
    2983               0 :     mHistory = new nsHistory(this);
    2984               0 :     if (!mHistory) {
    2985               0 :       return NS_ERROR_OUT_OF_MEMORY;
    2986                 :     }
    2987                 :   }
    2988                 : 
    2989               0 :   NS_IF_ADDREF(*aHistory = mHistory);
    2990               0 :   return NS_OK;
    2991                 : }
    2992                 : 
    2993                 : NS_IMETHODIMP
    2994               0 : nsGlobalWindow::GetPerformance(nsIDOMPerformance** aPerformance)
    2995                 : {
    2996               0 :   FORWARD_TO_INNER(GetPerformance, (aPerformance), NS_ERROR_NOT_INITIALIZED);
    2997                 : 
    2998               0 :   *aPerformance = nsnull;
    2999                 : 
    3000               0 :   if (nsGlobalWindow::HasPerformanceSupport()) {
    3001               0 :     if (!mPerformance) {
    3002               0 :       if (!mDoc) {
    3003               0 :         return NS_OK;
    3004                 :       }
    3005               0 :       nsRefPtr<nsDOMNavigationTiming> timing = mDoc->GetNavigationTiming();
    3006               0 :       nsCOMPtr<nsITimedChannel> timedChannel(do_QueryInterface(mDoc->GetChannel()));
    3007               0 :       bool timingEnabled = false;
    3008               0 :       if (!timedChannel ||
    3009               0 :           !NS_SUCCEEDED(timedChannel->GetTimingEnabled(&timingEnabled)) ||
    3010               0 :           !timingEnabled) {
    3011               0 :         timedChannel = nsnull;
    3012                 :       }
    3013               0 :       if (timing) {
    3014               0 :         mPerformance = new nsPerformance(timing, timedChannel);
    3015                 :       }
    3016                 :     }
    3017               0 :     NS_IF_ADDREF(*aPerformance = mPerformance);
    3018                 :   }
    3019               0 :   return NS_OK;
    3020                 : }
    3021                 : 
    3022                 : /**
    3023                 :  * GetScriptableParent is called when script reads window.parent.
    3024                 :  *
    3025                 :  * In contrast to GetRealParent, GetScriptableParent respects <iframe
    3026                 :  * mozbrowser> boundaries, so if |this| is contained by an <iframe
    3027                 :  * mozbrowser>, we will return |this| as its own parent.
    3028                 :  */
    3029                 : NS_IMETHODIMP
    3030               0 : nsGlobalWindow::GetScriptableParent(nsIDOMWindow** aParent)
    3031                 : {
    3032               0 :   FORWARD_TO_OUTER(GetScriptableParent, (aParent), NS_ERROR_NOT_INITIALIZED);
    3033                 : 
    3034               0 :   *aParent = NULL;
    3035               0 :   if (!mDocShell) {
    3036               0 :     return NS_OK;
    3037                 :   }
    3038                 : 
    3039               0 :   bool isMozBrowser = false;
    3040               0 :   mDocShell->GetIsBrowserFrame(&isMozBrowser);
    3041               0 :   if (isMozBrowser) {
    3042               0 :     nsCOMPtr<nsIDOMWindow> parent = static_cast<nsIDOMWindow*>(this);
    3043               0 :     parent.swap(*aParent);
    3044               0 :     return NS_OK;
    3045                 :   }
    3046                 : 
    3047               0 :   return GetRealParent(aParent);
    3048                 : }
    3049                 : 
    3050                 : /**
    3051                 :  * nsIDOMWindow::GetParent (when called from C++) is just a wrapper around
    3052                 :  * GetRealParent.
    3053                 :  */
    3054                 : NS_IMETHODIMP
    3055               0 : nsGlobalWindow::GetRealParent(nsIDOMWindow** aParent)
    3056                 : {
    3057               0 :   FORWARD_TO_OUTER(GetRealParent, (aParent), NS_ERROR_NOT_INITIALIZED);
    3058                 : 
    3059               0 :   *aParent = nsnull;
    3060               0 :   if (!mDocShell) {
    3061               0 :     return NS_OK;
    3062                 :   }
    3063                 : 
    3064               0 :   nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(do_QueryInterface(mDocShell));
    3065               0 :   NS_ENSURE_TRUE(docShellAsItem, NS_ERROR_FAILURE);
    3066                 : 
    3067               0 :   nsCOMPtr<nsIDocShellTreeItem> parent;
    3068               0 :   docShellAsItem->GetSameTypeParent(getter_AddRefs(parent));
    3069                 : 
    3070               0 :   if (parent) {
    3071               0 :     nsCOMPtr<nsIScriptGlobalObject> globalObject(do_GetInterface(parent));
    3072               0 :     NS_ENSURE_SUCCESS(CallQueryInterface(globalObject.get(), aParent),
    3073                 :                       NS_ERROR_FAILURE);
    3074                 :   }
    3075                 :   else {
    3076               0 :     *aParent = static_cast<nsIDOMWindow*>(this);
    3077               0 :     NS_ADDREF(*aParent);
    3078                 :   }
    3079               0 :   return NS_OK;
    3080                 : }
    3081                 : 
    3082                 : /**
    3083                 :  * GetScriptableTop is called when script reads window.top.
    3084                 :  *
    3085                 :  * In contrast to GetRealTop, GetScriptableTop respects <iframe mozbrowser>
    3086                 :  * boundaries.  If we encounter a window owned by an <iframe mozbrowser> while
    3087                 :  * walking up the window hierarchy, we'll stop and return that window.
    3088                 :  */
    3089                 : NS_IMETHODIMP
    3090               0 : nsGlobalWindow::GetScriptableTop(nsIDOMWindow **aTop)
    3091                 : {
    3092               0 :   return GetTopImpl(aTop, /* aScriptable = */ true);
    3093                 : }
    3094                 : 
    3095                 : /**
    3096                 :  * nsIDOMWindow::GetTop (when called from C++) is just a wrapper around
    3097                 :  * GetRealTop.
    3098                 :  */
    3099                 : NS_IMETHODIMP
    3100               0 : nsGlobalWindow::GetRealTop(nsIDOMWindow** aTop)
    3101                 : {
    3102               0 :   return GetTopImpl(aTop, /* aScriptable = */ false);
    3103                 : }
    3104                 : 
    3105                 : nsresult
    3106               0 : nsGlobalWindow::GetTopImpl(nsIDOMWindow** aTop, bool aScriptable)
    3107                 : {
    3108               0 :   FORWARD_TO_OUTER(GetTopImpl, (aTop, aScriptable), NS_ERROR_NOT_INITIALIZED);
    3109               0 :   *aTop = nsnull;
    3110                 : 
    3111                 :   // Walk up the parent chain.
    3112                 : 
    3113               0 :   nsCOMPtr<nsIDOMWindow> prevParent = this;
    3114               0 :   nsCOMPtr<nsIDOMWindow> parent = this;
    3115               0 :   do {
    3116               0 :     if (!parent) {
    3117               0 :       break;
    3118                 :     }
    3119                 : 
    3120               0 :     prevParent = parent;
    3121                 : 
    3122               0 :     nsCOMPtr<nsIDOMWindow> newParent;
    3123                 :     nsresult rv;
    3124               0 :     if (aScriptable) {
    3125               0 :       rv = parent->GetScriptableParent(getter_AddRefs(newParent));
    3126                 :     }
    3127                 :     else {
    3128               0 :       rv = parent->GetParent(getter_AddRefs(newParent));
    3129                 :     }
    3130               0 :     NS_ENSURE_SUCCESS(rv, rv);
    3131                 : 
    3132               0 :     parent = newParent;
    3133                 : 
    3134                 :   } while (parent != prevParent);
    3135                 : 
    3136               0 :   if (parent) {
    3137               0 :     parent.swap(*aTop);
    3138                 :   }
    3139                 : 
    3140               0 :   return NS_OK;
    3141                 : }
    3142                 : 
    3143                 : NS_IMETHODIMP
    3144               0 : nsGlobalWindow::GetContent(nsIDOMWindow** aContent)
    3145                 : {
    3146               0 :   FORWARD_TO_OUTER(GetContent, (aContent), NS_ERROR_NOT_INITIALIZED);
    3147                 : 
    3148               0 :   *aContent = nsnull;
    3149                 : 
    3150               0 :   nsCOMPtr<nsIDocShellTreeItem> primaryContent;
    3151                 : 
    3152               0 :   if (!nsContentUtils::IsCallerChrome()) {
    3153                 :     // If we're called by non-chrome code, make sure we don't return
    3154                 :     // the primary content window if the calling tab is hidden. In
    3155                 :     // such a case we return the same-type root in the hidden tab,
    3156                 :     // which is "good enough", for now.
    3157               0 :     nsCOMPtr<nsIBaseWindow> baseWin(do_QueryInterface(mDocShell));
    3158                 : 
    3159               0 :     if (baseWin) {
    3160               0 :       bool visible = false;
    3161               0 :       baseWin->GetVisibility(&visible);
    3162                 : 
    3163               0 :       if (!visible) {
    3164               0 :         nsCOMPtr<nsIDocShellTreeItem> treeItem(do_QueryInterface(mDocShell));
    3165                 : 
    3166               0 :         treeItem->GetSameTypeRootTreeItem(getter_AddRefs(primaryContent));
    3167                 :       }
    3168                 :     }
    3169                 :   }
    3170                 : 
    3171               0 :   if (!primaryContent) {
    3172               0 :     nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
    3173               0 :     GetTreeOwner(getter_AddRefs(treeOwner));
    3174               0 :     NS_ENSURE_TRUE(treeOwner, NS_ERROR_FAILURE);
    3175                 : 
    3176               0 :     treeOwner->GetPrimaryContentShell(getter_AddRefs(primaryContent));
    3177                 :   }
    3178                 : 
    3179               0 :   nsCOMPtr<nsIDOMWindow> domWindow(do_GetInterface(primaryContent));
    3180               0 :   NS_IF_ADDREF(*aContent = domWindow);
    3181                 : 
    3182               0 :   return NS_OK;
    3183                 : }
    3184                 : 
    3185                 : NS_IMETHODIMP
    3186               0 : nsGlobalWindow::GetPrompter(nsIPrompt** aPrompt)
    3187                 : {
    3188               0 :   FORWARD_TO_OUTER(GetPrompter, (aPrompt), NS_ERROR_NOT_INITIALIZED);
    3189                 : 
    3190               0 :   if (!mDocShell)
    3191               0 :     return NS_ERROR_FAILURE;
    3192                 : 
    3193               0 :   nsCOMPtr<nsIPrompt> prompter(do_GetInterface(mDocShell));
    3194               0 :   NS_ENSURE_TRUE(prompter, NS_ERROR_NO_INTERFACE);
    3195                 : 
    3196               0 :   NS_ADDREF(*aPrompt = prompter);
    3197               0 :   return NS_OK;
    3198                 : }
    3199                 : 
    3200                 : NS_IMETHODIMP
    3201               0 : nsGlobalWindow::GetMenubar(nsIDOMBarProp** aMenubar)
    3202                 : {
    3203               0 :   FORWARD_TO_OUTER(GetMenubar, (aMenubar), NS_ERROR_NOT_INITIALIZED);
    3204                 : 
    3205               0 :   *aMenubar = nsnull;
    3206                 : 
    3207               0 :   if (!mMenubar) {
    3208               0 :     mMenubar = new nsMenubarProp(this);
    3209               0 :     if (!mMenubar) {
    3210               0 :       return NS_ERROR_OUT_OF_MEMORY;
    3211                 :     }
    3212                 :   }
    3213                 : 
    3214               0 :   NS_ADDREF(*aMenubar = mMenubar);
    3215                 : 
    3216               0 :   return NS_OK;
    3217                 : }
    3218                 : 
    3219                 : NS_IMETHODIMP
    3220               0 : nsGlobalWindow::GetToolbar(nsIDOMBarProp** aToolbar)
    3221                 : {
    3222               0 :   FORWARD_TO_OUTER(GetToolbar, (aToolbar), NS_ERROR_NOT_INITIALIZED);
    3223                 : 
    3224               0 :   *aToolbar = nsnull;
    3225                 : 
    3226               0 :   if (!mToolbar) {
    3227               0 :     mToolbar = new nsToolbarProp(this);
    3228               0 :     if (!mToolbar) {
    3229               0 :       return NS_ERROR_OUT_OF_MEMORY;
    3230                 :     }
    3231                 :   }
    3232                 : 
    3233               0 :   NS_ADDREF(*aToolbar = mToolbar);
    3234                 : 
    3235               0 :   return NS_OK;
    3236                 : }
    3237                 : 
    3238                 : NS_IMETHODIMP
    3239               0 : nsGlobalWindow::GetLocationbar(nsIDOMBarProp** aLocationbar)
    3240                 : {
    3241               0 :   FORWARD_TO_OUTER(GetLocationbar, (aLocationbar), NS_ERROR_NOT_INITIALIZED);
    3242                 : 
    3243               0 :   *aLocationbar = nsnull;
    3244                 : 
    3245               0 :   if (!mLocationbar) {
    3246               0 :     mLocationbar = new nsLocationbarProp(this);
    3247               0 :     if (!mLocationbar) {
    3248               0 :       return NS_ERROR_OUT_OF_MEMORY;
    3249                 :     }
    3250                 :   }
    3251                 : 
    3252               0 :   NS_ADDREF(*aLocationbar = mLocationbar);
    3253                 : 
    3254               0 :   return NS_OK;
    3255                 : }
    3256                 : 
    3257                 : NS_IMETHODIMP
    3258               0 : nsGlobalWindow::GetPersonalbar(nsIDOMBarProp** aPersonalbar)
    3259                 : {
    3260               0 :   FORWARD_TO_OUTER(GetPersonalbar, (aPersonalbar), NS_ERROR_NOT_INITIALIZED);
    3261                 : 
    3262               0 :   *aPersonalbar = nsnull;
    3263                 : 
    3264               0 :   if (!mPersonalbar) {
    3265               0 :     mPersonalbar = new nsPersonalbarProp(this);
    3266               0 :     if (!mPersonalbar) {
    3267               0 :       return NS_ERROR_OUT_OF_MEMORY;
    3268                 :     }
    3269                 :   }
    3270                 : 
    3271               0 :   NS_ADDREF(*aPersonalbar = mPersonalbar);
    3272                 : 
    3273               0 :   return NS_OK;
    3274                 : }
    3275                 : 
    3276                 : NS_IMETHODIMP
    3277               0 : nsGlobalWindow::GetStatusbar(nsIDOMBarProp** aStatusbar)
    3278                 : {
    3279               0 :   FORWARD_TO_OUTER(GetStatusbar, (aStatusbar), NS_ERROR_NOT_INITIALIZED);
    3280                 : 
    3281               0 :   *aStatusbar = nsnull;
    3282                 : 
    3283               0 :   if (!mStatusbar) {
    3284               0 :     mStatusbar = new nsStatusbarProp(this);
    3285               0 :     if (!mStatusbar) {
    3286               0 :       return NS_ERROR_OUT_OF_MEMORY;
    3287                 :     }
    3288                 :   }
    3289                 : 
    3290               0 :   NS_ADDREF(*aStatusbar = mStatusbar);
    3291                 : 
    3292               0 :   return NS_OK;
    3293                 : }
    3294                 : 
    3295                 : NS_IMETHODIMP
    3296               0 : nsGlobalWindow::GetScrollbars(nsIDOMBarProp** aScrollbars)
    3297                 : {
    3298               0 :   FORWARD_TO_OUTER(GetScrollbars, (aScrollbars), NS_ERROR_NOT_INITIALIZED);
    3299                 : 
    3300               0 :   *aScrollbars = nsnull;
    3301                 : 
    3302               0 :   if (!mScrollbars) {
    3303               0 :     mScrollbars = new nsScrollbarsProp(this);
    3304               0 :     if (!mScrollbars) {
    3305               0 :       return NS_ERROR_OUT_OF_MEMORY;
    3306                 :     }
    3307                 :   }
    3308                 : 
    3309               0 :   NS_ADDREF(*aScrollbars = mScrollbars);
    3310                 : 
    3311               0 :   return NS_OK;
    3312                 : }
    3313                 : 
    3314                 : NS_IMETHODIMP
    3315               0 : nsGlobalWindow::GetClosed(bool* aClosed)
    3316                 : {
    3317               0 :   FORWARD_TO_OUTER(GetClosed, (aClosed), NS_ERROR_NOT_INITIALIZED);
    3318                 : 
    3319                 :   // If someone called close(), or if we don't have a docshell, we're
    3320                 :   // closed.
    3321               0 :   *aClosed = mIsClosed || !mDocShell;
    3322                 : 
    3323               0 :   return NS_OK;
    3324                 : }
    3325                 : 
    3326                 : NS_IMETHODIMP
    3327               0 : nsGlobalWindow::GetFrames(nsIDOMWindowCollection** aFrames)
    3328                 : {
    3329               0 :   FORWARD_TO_OUTER(GetFrames, (aFrames), NS_ERROR_NOT_INITIALIZED);
    3330                 : 
    3331               0 :   *aFrames = nsnull;
    3332                 : 
    3333               0 :   if (!mFrames && mDocShell) {
    3334               0 :     mFrames = new nsDOMWindowList(mDocShell);
    3335               0 :     if (!mFrames) {
    3336               0 :       return NS_ERROR_OUT_OF_MEMORY;
    3337                 :     }
    3338                 :   }
    3339                 : 
    3340               0 :   *aFrames = static_cast<nsIDOMWindowCollection *>(mFrames);
    3341               0 :   NS_IF_ADDREF(*aFrames);
    3342               0 :   return NS_OK;
    3343                 : }
    3344                 : 
    3345                 : NS_IMETHODIMP
    3346               0 : nsGlobalWindow::GetApplicationCache(nsIDOMOfflineResourceList **aApplicationCache)
    3347                 : {
    3348               0 :   FORWARD_TO_INNER(GetApplicationCache, (aApplicationCache), NS_ERROR_UNEXPECTED);
    3349                 : 
    3350               0 :   NS_ENSURE_ARG_POINTER(aApplicationCache);
    3351                 : 
    3352               0 :   if (!mApplicationCache) {
    3353               0 :     nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(GetDocShell()));
    3354               0 :     if (!webNav) {
    3355               0 :       return NS_ERROR_FAILURE;
    3356                 :     }
    3357                 : 
    3358               0 :     nsCOMPtr<nsIURI> uri;
    3359               0 :     nsresult rv = webNav->GetCurrentURI(getter_AddRefs(uri));
    3360               0 :     NS_ENSURE_SUCCESS(rv, rv);
    3361                 : 
    3362               0 :     nsCOMPtr<nsIDocument> doc = do_QueryInterface(mDocument);
    3363               0 :     nsCOMPtr<nsIURI> manifestURI;
    3364               0 :     nsContentUtils::GetOfflineAppManifest(doc, getter_AddRefs(manifestURI));
    3365                 : 
    3366                 :     nsRefPtr<nsDOMOfflineResourceList> applicationCache =
    3367               0 :       new nsDOMOfflineResourceList(manifestURI, uri, this);
    3368               0 :     NS_ENSURE_TRUE(applicationCache, NS_ERROR_OUT_OF_MEMORY);
    3369                 : 
    3370               0 :     applicationCache->Init();
    3371                 : 
    3372               0 :     mApplicationCache = applicationCache;
    3373                 :   }
    3374                 : 
    3375               0 :   NS_IF_ADDREF(*aApplicationCache = mApplicationCache);
    3376                 : 
    3377               0 :   return NS_OK;
    3378                 : }
    3379                 : 
    3380                 : NS_IMETHODIMP
    3381               0 : nsGlobalWindow::GetCrypto(nsIDOMCrypto** aCrypto)
    3382                 : {
    3383                 : #ifdef MOZ_DISABLE_DOMCRYPTO
    3384                 :   return NS_ERROR_NOT_IMPLEMENTED;
    3385                 : #else
    3386               0 :   FORWARD_TO_OUTER(GetCrypto, (aCrypto), NS_ERROR_NOT_INITIALIZED);
    3387                 : 
    3388               0 :   if (!mCrypto) {
    3389               0 :     mCrypto = do_CreateInstance(kCryptoContractID);
    3390                 :   }
    3391                 : 
    3392               0 :   NS_IF_ADDREF(*aCrypto = mCrypto);
    3393                 : 
    3394               0 :   return NS_OK;
    3395                 : #endif
    3396                 : }
    3397                 : 
    3398                 : NS_IMETHODIMP
    3399               0 : nsGlobalWindow::GetPkcs11(nsIDOMPkcs11** aPkcs11)
    3400                 : {
    3401               0 :   *aPkcs11 = nsnull;
    3402               0 :   return NS_OK;
    3403                 : }
    3404                 : 
    3405                 : NS_IMETHODIMP
    3406               0 : nsGlobalWindow::GetControllers(nsIControllers** aResult)
    3407                 : {
    3408               0 :   FORWARD_TO_OUTER(GetControllers, (aResult), NS_ERROR_NOT_INITIALIZED);
    3409                 : 
    3410               0 :   if (!mControllers) {
    3411                 :     nsresult rv;
    3412               0 :     mControllers = do_CreateInstance(kXULControllersCID, &rv);
    3413               0 :     NS_ENSURE_SUCCESS(rv, rv);
    3414                 : 
    3415                 :     // Add in the default controller
    3416                 :     nsCOMPtr<nsIController> controller = do_CreateInstance(
    3417               0 :                                NS_WINDOWCONTROLLER_CONTRACTID, &rv);
    3418               0 :     NS_ENSURE_SUCCESS(rv, rv);
    3419                 :     
    3420               0 :     mControllers->InsertControllerAt(0, controller);
    3421               0 :     nsCOMPtr<nsIControllerContext> controllerContext = do_QueryInterface(controller);
    3422               0 :     if (!controllerContext) return NS_ERROR_FAILURE;
    3423                 : 
    3424               0 :     controllerContext->SetCommandContext(static_cast<nsIDOMWindow*>(this));
    3425                 :   }
    3426                 : 
    3427               0 :   *aResult = mControllers;
    3428               0 :   NS_ADDREF(*aResult);
    3429               0 :   return NS_OK;
    3430                 : }
    3431                 : 
    3432                 : NS_IMETHODIMP
    3433               0 : nsGlobalWindow::GetOpener(nsIDOMWindow** aOpener)
    3434                 : {
    3435               0 :   FORWARD_TO_OUTER(GetOpener, (aOpener), NS_ERROR_NOT_INITIALIZED);
    3436                 : 
    3437               0 :   *aOpener = nsnull;
    3438                 : 
    3439               0 :   nsCOMPtr<nsPIDOMWindow> opener = do_QueryReferent(mOpener);
    3440               0 :   if (!opener) {
    3441               0 :     return NS_OK;
    3442                 :   }
    3443                 : 
    3444                 :   // First, check if we were called from a privileged chrome script
    3445               0 :   if (nsContentUtils::IsCallerTrustedForRead()) {
    3446               0 :     NS_ADDREF(*aOpener = opener);
    3447               0 :     return NS_OK;
    3448                 :   }
    3449                 : 
    3450               0 :   nsCOMPtr<nsPIDOMWindow> openerPwin(do_QueryInterface(opener));
    3451               0 :   if (!openerPwin) {
    3452               0 :     return NS_OK;
    3453                 :   }
    3454                 : 
    3455                 :   // First, ensure that we're not handing back a chrome window.
    3456               0 :   nsGlobalWindow *win = static_cast<nsGlobalWindow *>(openerPwin.get());
    3457               0 :   if (win->IsChromeWindow()) {
    3458               0 :     return NS_OK;
    3459                 :   }
    3460                 : 
    3461                 :   // We don't want to reveal the opener if the opener is a mail window,
    3462                 :   // because opener can be used to spoof the contents of a message (bug 105050).
    3463                 :   // So, we look in the opener's root docshell to see if it's a mail window.
    3464                 :   nsCOMPtr<nsIDocShellTreeItem> docShellAsItem =
    3465               0 :     do_QueryInterface(openerPwin->GetDocShell());
    3466                 : 
    3467               0 :   if (docShellAsItem) {
    3468               0 :     nsCOMPtr<nsIDocShellTreeItem> openerRootItem;
    3469               0 :     docShellAsItem->GetRootTreeItem(getter_AddRefs(openerRootItem));
    3470               0 :     nsCOMPtr<nsIDocShell> openerRootDocShell(do_QueryInterface(openerRootItem));
    3471               0 :     if (openerRootDocShell) {
    3472                 :       PRUint32 appType;
    3473               0 :       nsresult rv = openerRootDocShell->GetAppType(&appType);
    3474               0 :       if (NS_SUCCEEDED(rv) && appType != nsIDocShell::APP_TYPE_MAIL) {
    3475               0 :         *aOpener = opener;
    3476                 :       }
    3477                 :     }
    3478                 :   }
    3479                 : 
    3480               0 :   NS_IF_ADDREF(*aOpener);
    3481               0 :   return NS_OK;
    3482                 : }
    3483                 : 
    3484                 : NS_IMETHODIMP
    3485               0 : nsGlobalWindow::SetOpener(nsIDOMWindow* aOpener)
    3486                 : {
    3487                 :   // check if we were called from a privileged chrome script.
    3488                 :   // If not, opener is settable only to null.
    3489               0 :   if (aOpener && !nsContentUtils::IsCallerTrustedForWrite()) {
    3490               0 :     return NS_OK;
    3491                 :   }
    3492                 : 
    3493               0 :   SetOpenerWindow(aOpener, false);
    3494                 : 
    3495               0 :   return NS_OK;
    3496                 : }
    3497                 : 
    3498                 : NS_IMETHODIMP
    3499               0 : nsGlobalWindow::GetStatus(nsAString& aStatus)
    3500                 : {
    3501               0 :   FORWARD_TO_OUTER(GetStatus, (aStatus), NS_ERROR_NOT_INITIALIZED);
    3502                 : 
    3503               0 :   aStatus = mStatus;
    3504               0 :   return NS_OK;
    3505                 : }
    3506                 : 
    3507                 : NS_IMETHODIMP
    3508               0 : nsGlobalWindow::SetStatus(const nsAString& aStatus)
    3509                 : {
    3510               0 :   FORWARD_TO_OUTER(SetStatus, (aStatus), NS_ERROR_NOT_INITIALIZED);
    3511                 : 
    3512                 :   /*
    3513                 :    * If caller is not chrome and dom.disable_window_status_change is true,
    3514                 :    * prevent setting window.status by exiting early
    3515                 :    */
    3516                 : 
    3517               0 :   if (!CanSetProperty("dom.disable_window_status_change")) {
    3518               0 :     return NS_OK;
    3519                 :   }
    3520                 : 
    3521               0 :   mStatus = aStatus;
    3522                 : 
    3523               0 :   nsCOMPtr<nsIWebBrowserChrome> browserChrome;
    3524               0 :   GetWebBrowserChrome(getter_AddRefs(browserChrome));
    3525               0 :   if(browserChrome) {
    3526               0 :     browserChrome->SetStatus(nsIWebBrowserChrome::STATUS_SCRIPT,
    3527               0 :                              PromiseFlatString(aStatus).get());
    3528                 :   }
    3529                 : 
    3530               0 :   return NS_OK;
    3531                 : }
    3532                 : 
    3533                 : NS_IMETHODIMP
    3534               0 : nsGlobalWindow::GetDefaultStatus(nsAString& aDefaultStatus)
    3535                 : {
    3536               0 :   FORWARD_TO_OUTER(GetDefaultStatus, (aDefaultStatus),
    3537                 :                    NS_ERROR_NOT_INITIALIZED);
    3538                 : 
    3539               0 :   aDefaultStatus = mDefaultStatus;
    3540               0 :   return NS_OK;
    3541                 : }
    3542                 : 
    3543                 : NS_IMETHODIMP
    3544               0 : nsGlobalWindow::SetDefaultStatus(const nsAString& aDefaultStatus)
    3545                 : {
    3546               0 :   FORWARD_TO_OUTER(SetDefaultStatus, (aDefaultStatus),
    3547                 :                    NS_ERROR_NOT_INITIALIZED);
    3548                 : 
    3549                 :   /*
    3550                 :    * If caller is not chrome and dom.disable_window_status_change is true,
    3551                 :    * prevent setting window.defaultStatus by exiting early
    3552                 :    */
    3553                 : 
    3554               0 :   if (!CanSetProperty("dom.disable_window_status_change")) {
    3555               0 :     return NS_OK;
    3556                 :   }
    3557                 : 
    3558               0 :   mDefaultStatus = aDefaultStatus;
    3559                 : 
    3560               0 :   nsCOMPtr<nsIWebBrowserChrome> browserChrome;
    3561               0 :   GetWebBrowserChrome(getter_AddRefs(browserChrome));
    3562               0 :   if (browserChrome) {
    3563               0 :     browserChrome->SetStatus(nsIWebBrowserChrome::STATUS_SCRIPT_DEFAULT,
    3564               0 :                              PromiseFlatString(aDefaultStatus).get());
    3565                 :   }
    3566                 : 
    3567               0 :   return NS_OK;
    3568                 : }
    3569                 : 
    3570                 : NS_IMETHODIMP
    3571               0 : nsGlobalWindow::GetName(nsAString& aName)
    3572                 : {
    3573               0 :   FORWARD_TO_OUTER(GetName, (aName), NS_ERROR_NOT_INITIALIZED);
    3574                 : 
    3575               0 :   nsXPIDLString name;
    3576               0 :   nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(do_QueryInterface(mDocShell));
    3577               0 :   if (docShellAsItem)
    3578               0 :     docShellAsItem->GetName(getter_Copies(name));
    3579                 : 
    3580               0 :   aName.Assign(name);
    3581               0 :   return NS_OK;
    3582                 : }
    3583                 : 
    3584                 : NS_IMETHODIMP
    3585               0 : nsGlobalWindow::SetName(const nsAString& aName)
    3586                 : {
    3587               0 :   FORWARD_TO_OUTER(SetName, (aName), NS_ERROR_NOT_INITIALIZED);
    3588                 : 
    3589               0 :   nsresult result = NS_OK;
    3590               0 :   nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(do_QueryInterface(mDocShell));
    3591               0 :   if (docShellAsItem)
    3592               0 :     result = docShellAsItem->SetName(PromiseFlatString(aName).get());
    3593               0 :   return result;
    3594                 : }
    3595                 : 
    3596                 : // Helper functions used by many methods below.
    3597                 : PRInt32
    3598               0 : nsGlobalWindow::DevToCSSIntPixels(PRInt32 px)
    3599                 : {
    3600               0 :   if (!mDocShell)
    3601               0 :     return px; // assume 1:1
    3602                 : 
    3603               0 :   nsRefPtr<nsPresContext> presContext;
    3604               0 :   mDocShell->GetPresContext(getter_AddRefs(presContext));
    3605               0 :   if (!presContext)
    3606               0 :     return px;
    3607                 : 
    3608               0 :   return presContext->DevPixelsToIntCSSPixels(px);
    3609                 : }
    3610                 : 
    3611                 : PRInt32
    3612               0 : nsGlobalWindow::CSSToDevIntPixels(PRInt32 px)
    3613                 : {
    3614               0 :   if (!mDocShell)
    3615               0 :     return px; // assume 1:1
    3616                 : 
    3617               0 :   nsRefPtr<nsPresContext> presContext;
    3618               0 :   mDocShell->GetPresContext(getter_AddRefs(presContext));
    3619               0 :   if (!presContext)
    3620               0 :     return px;
    3621                 : 
    3622               0 :   return presContext->CSSPixelsToDevPixels(px);
    3623                 : }
    3624                 : 
    3625                 : nsIntSize
    3626               0 : nsGlobalWindow::DevToCSSIntPixels(nsIntSize px)
    3627                 : {
    3628               0 :   if (!mDocShell)
    3629               0 :     return px; // assume 1:1
    3630                 : 
    3631               0 :   nsRefPtr<nsPresContext> presContext;
    3632               0 :   mDocShell->GetPresContext(getter_AddRefs(presContext));
    3633               0 :   if (!presContext)
    3634               0 :     return px;
    3635                 : 
    3636                 :   return nsIntSize(
    3637                 :       presContext->DevPixelsToIntCSSPixels(px.width),
    3638               0 :       presContext->DevPixelsToIntCSSPixels(px.height));
    3639                 : }
    3640                 : 
    3641                 : nsIntSize
    3642               0 : nsGlobalWindow::CSSToDevIntPixels(nsIntSize px)
    3643                 : {
    3644               0 :   if (!mDocShell)
    3645               0 :     return px; // assume 1:1
    3646                 : 
    3647               0 :   nsRefPtr<nsPresContext> presContext;
    3648               0 :   mDocShell->GetPresContext(getter_AddRefs(presContext));
    3649               0 :   if (!presContext)
    3650               0 :     return px;
    3651                 : 
    3652                 :   return nsIntSize(
    3653                 :     presContext->CSSPixelsToDevPixels(px.width),
    3654               0 :     presContext->CSSPixelsToDevPixels(px.height));
    3655                 : }
    3656                 : 
    3657                 : 
    3658                 : NS_IMETHODIMP
    3659               0 : nsGlobalWindow::GetInnerWidth(PRInt32* aInnerWidth)
    3660                 : {
    3661               0 :   FORWARD_TO_OUTER(GetInnerWidth, (aInnerWidth), NS_ERROR_NOT_INITIALIZED);
    3662                 : 
    3663               0 :   NS_ENSURE_STATE(mDocShell);
    3664                 : 
    3665               0 :   EnsureSizeUpToDate();
    3666                 : 
    3667               0 :   nsRefPtr<nsPresContext> presContext;
    3668               0 :   mDocShell->GetPresContext(getter_AddRefs(presContext));
    3669                 : 
    3670               0 :   if (presContext) {
    3671               0 :     nsRect shellArea = presContext->GetVisibleArea();
    3672               0 :     *aInnerWidth = nsPresContext::AppUnitsToIntCSSPixels(shellArea.width);
    3673                 :   } else {
    3674               0 :     *aInnerWidth = 0;
    3675                 :   }
    3676                 : 
    3677               0 :   return NS_OK;
    3678                 : }
    3679                 : 
    3680                 : NS_IMETHODIMP
    3681               0 : nsGlobalWindow::SetInnerWidth(PRInt32 aInnerWidth)
    3682                 : {
    3683               0 :   FORWARD_TO_OUTER(SetInnerWidth, (aInnerWidth), NS_ERROR_NOT_INITIALIZED);
    3684                 : 
    3685               0 :   NS_ENSURE_STATE(mDocShell);
    3686                 : 
    3687                 :   /*
    3688                 :    * If caller is not chrome and the user has not explicitly exempted the site,
    3689                 :    * prevent setting window.innerWidth by exiting early
    3690                 :    */
    3691               0 :   if (!CanMoveResizeWindows() || IsFrame()) {
    3692               0 :     return NS_OK;
    3693                 :   }
    3694                 : 
    3695               0 :   NS_ENSURE_SUCCESS(CheckSecurityWidthAndHeight(&aInnerWidth, nsnull),
    3696                 :                     NS_ERROR_FAILURE);
    3697                 : 
    3698                 : 
    3699               0 :   nsRefPtr<nsIPresShell> presShell;
    3700               0 :   mDocShell->GetPresShell(getter_AddRefs(presShell));
    3701                 : 
    3702               0 :   if (presShell && presShell->GetIsViewportOverridden())
    3703                 :   {
    3704               0 :     nscoord height = 0;
    3705               0 :     nscoord width  = 0;
    3706                 : 
    3707               0 :     nsRefPtr<nsPresContext> presContext;
    3708               0 :     presContext = presShell->GetPresContext();
    3709                 : 
    3710               0 :     nsRect shellArea = presContext->GetVisibleArea();
    3711               0 :     height = shellArea.height;
    3712               0 :     width  = nsPresContext::CSSPixelsToAppUnits(aInnerWidth);
    3713               0 :     return SetCSSViewportWidthAndHeight(width, height);
    3714                 :   }
    3715                 :   else
    3716                 :   {
    3717               0 :     PRInt32 height = 0;
    3718               0 :     PRInt32 width  = 0;
    3719                 : 
    3720               0 :     nsCOMPtr<nsIBaseWindow> docShellAsWin(do_QueryInterface(mDocShell));
    3721               0 :     docShellAsWin->GetSize(&width, &height);
    3722               0 :     width  = CSSToDevIntPixels(aInnerWidth);
    3723               0 :     return SetDocShellWidthAndHeight(width, height);
    3724                 :   }
    3725                 : }
    3726                 : 
    3727                 : NS_IMETHODIMP
    3728               0 : nsGlobalWindow::GetInnerHeight(PRInt32* aInnerHeight)
    3729                 : {
    3730               0 :   FORWARD_TO_OUTER(GetInnerHeight, (aInnerHeight), NS_ERROR_NOT_INITIALIZED);
    3731                 : 
    3732               0 :   NS_ENSURE_STATE(mDocShell);
    3733                 : 
    3734               0 :   EnsureSizeUpToDate();
    3735                 : 
    3736               0 :   nsRefPtr<nsPresContext> presContext;
    3737               0 :   mDocShell->GetPresContext(getter_AddRefs(presContext));
    3738                 : 
    3739               0 :   if (presContext) {
    3740               0 :     nsRect shellArea = presContext->GetVisibleArea();
    3741               0 :     *aInnerHeight = nsPresContext::AppUnitsToIntCSSPixels(shellArea.height);
    3742                 :   } else {
    3743               0 :     *aInnerHeight = 0;
    3744                 :   }
    3745               0 :   return NS_OK;
    3746                 : }
    3747                 : 
    3748                 : NS_IMETHODIMP
    3749               0 : nsGlobalWindow::SetInnerHeight(PRInt32 aInnerHeight)
    3750                 : {
    3751               0 :   FORWARD_TO_OUTER(SetInnerHeight, (aInnerHeight), NS_ERROR_NOT_INITIALIZED);
    3752                 : 
    3753               0 :   NS_ENSURE_STATE(mDocShell);
    3754                 : 
    3755                 :   /*
    3756                 :    * If caller is not chrome and the user has not explicitly exempted the site,
    3757                 :    * prevent setting window.innerHeight by exiting early
    3758                 :    */
    3759               0 :   if (!CanMoveResizeWindows() || IsFrame()) {
    3760               0 :     return NS_OK;
    3761                 :   }
    3762                 : 
    3763               0 :   NS_ENSURE_SUCCESS(CheckSecurityWidthAndHeight(nsnull, &aInnerHeight),
    3764                 :                     NS_ERROR_FAILURE);
    3765                 : 
    3766               0 :   nsRefPtr<nsIPresShell> presShell;
    3767               0 :   mDocShell->GetPresShell(getter_AddRefs(presShell));
    3768                 : 
    3769               0 :   if (presShell && presShell->GetIsViewportOverridden())
    3770                 :   {
    3771               0 :     nscoord height = 0;
    3772               0 :     nscoord width  = 0;
    3773                 : 
    3774               0 :     nsRefPtr<nsPresContext> presContext;
    3775               0 :     presContext = presShell->GetPresContext();
    3776                 : 
    3777               0 :     nsRect shellArea = presContext->GetVisibleArea();
    3778               0 :     width = shellArea.width;
    3779               0 :     height  = nsPresContext::CSSPixelsToAppUnits(aInnerHeight);
    3780               0 :     return SetCSSViewportWidthAndHeight(width, height);
    3781                 :   }
    3782                 :   else
    3783                 :   {
    3784               0 :     PRInt32 height = 0;
    3785               0 :     PRInt32 width  = 0;
    3786                 : 
    3787               0 :     nsCOMPtr<nsIBaseWindow> docShellAsWin(do_QueryInterface(mDocShell));
    3788               0 :     docShellAsWin->GetSize(&width, &height);
    3789               0 :     height  = CSSToDevIntPixels(aInnerHeight);
    3790               0 :     return SetDocShellWidthAndHeight(width, height);
    3791                 :   }
    3792                 : }
    3793                 : 
    3794                 : nsresult
    3795               0 : nsGlobalWindow::GetOuterSize(nsIntSize* aSizeCSSPixels)
    3796                 : {
    3797               0 :   nsCOMPtr<nsIBaseWindow> treeOwnerAsWin;
    3798               0 :   GetTreeOwner(getter_AddRefs(treeOwnerAsWin));
    3799               0 :   NS_ENSURE_TRUE(treeOwnerAsWin, NS_ERROR_FAILURE);
    3800                 : 
    3801                 :   nsGlobalWindow* rootWindow =
    3802               0 :     static_cast<nsGlobalWindow *>(GetPrivateRoot());
    3803               0 :   if (rootWindow) {
    3804               0 :     rootWindow->FlushPendingNotifications(Flush_Layout);
    3805                 :   }
    3806                 : 
    3807               0 :   nsIntSize sizeDevPixels;
    3808               0 :   NS_ENSURE_SUCCESS(treeOwnerAsWin->GetSize(&sizeDevPixels.width,
    3809                 :                                             &sizeDevPixels.height),
    3810                 :                     NS_ERROR_FAILURE);
    3811                 : 
    3812               0 :   *aSizeCSSPixels = DevToCSSIntPixels(sizeDevPixels);
    3813               0 :   return NS_OK;
    3814                 : }
    3815                 : 
    3816                 : NS_IMETHODIMP
    3817               0 : nsGlobalWindow::GetOuterWidth(PRInt32* aOuterWidth)
    3818                 : {
    3819               0 :   FORWARD_TO_OUTER(GetOuterWidth, (aOuterWidth), NS_ERROR_NOT_INITIALIZED);
    3820                 : 
    3821               0 :   nsIntSize sizeCSSPixels;
    3822               0 :   nsresult rv = GetOuterSize(&sizeCSSPixels);
    3823               0 :   NS_ENSURE_SUCCESS(rv, rv);
    3824                 : 
    3825               0 :   *aOuterWidth = sizeCSSPixels.width;
    3826               0 :   return NS_OK;
    3827                 : }
    3828                 : 
    3829                 : NS_IMETHODIMP
    3830               0 : nsGlobalWindow::GetOuterHeight(PRInt32* aOuterHeight)
    3831                 : {
    3832               0 :   FORWARD_TO_OUTER(GetOuterHeight, (aOuterHeight), NS_ERROR_NOT_INITIALIZED);
    3833                 : 
    3834               0 :   nsIntSize sizeCSSPixels;
    3835               0 :   nsresult rv = GetOuterSize(&sizeCSSPixels);
    3836               0 :   NS_ENSURE_SUCCESS(rv, rv);
    3837                 : 
    3838               0 :   *aOuterHeight = sizeCSSPixels.height;
    3839               0 :   return NS_OK;
    3840                 : }
    3841                 : 
    3842                 : nsresult
    3843               0 : nsGlobalWindow::SetOuterSize(PRInt32 aLengthCSSPixels, bool aIsWidth)
    3844                 : {
    3845                 :   /*
    3846                 :    * If caller is not chrome and the user has not explicitly exempted the site,
    3847                 :    * prevent setting window.outerWidth by exiting early
    3848                 :    */
    3849                 : 
    3850               0 :   if (!CanMoveResizeWindows() || IsFrame()) {
    3851               0 :     return NS_OK;
    3852                 :   }
    3853                 : 
    3854               0 :   nsCOMPtr<nsIBaseWindow> treeOwnerAsWin;
    3855               0 :   GetTreeOwner(getter_AddRefs(treeOwnerAsWin));
    3856               0 :   NS_ENSURE_TRUE(treeOwnerAsWin, NS_ERROR_FAILURE);
    3857                 : 
    3858               0 :   NS_ENSURE_SUCCESS(CheckSecurityWidthAndHeight(
    3859                 :                         aIsWidth ? &aLengthCSSPixels : nsnull,
    3860                 :                         aIsWidth ? nsnull : &aLengthCSSPixels),
    3861                 :                     NS_ERROR_FAILURE);
    3862                 : 
    3863                 :   PRInt32 width, height;
    3864               0 :   NS_ENSURE_SUCCESS(treeOwnerAsWin->GetSize(&width, &height), NS_ERROR_FAILURE);
    3865                 : 
    3866               0 :   PRInt32 lengthDevPixels = CSSToDevIntPixels(aLengthCSSPixels);
    3867               0 :   if (aIsWidth) {
    3868               0 :     width = lengthDevPixels;
    3869                 :   } else {
    3870               0 :     height = lengthDevPixels;
    3871                 :   }
    3872               0 :   return treeOwnerAsWin->SetSize(width, height, true);    
    3873                 : }
    3874                 : 
    3875                 : NS_IMETHODIMP
    3876               0 : nsGlobalWindow::SetOuterWidth(PRInt32 aOuterWidth)
    3877                 : {
    3878               0 :   FORWARD_TO_OUTER(SetOuterWidth, (aOuterWidth), NS_ERROR_NOT_INITIALIZED);
    3879                 : 
    3880               0 :   return SetOuterSize(aOuterWidth, true);
    3881                 : }
    3882                 : 
    3883                 : NS_IMETHODIMP
    3884               0 : nsGlobalWindow::SetOuterHeight(PRInt32 aOuterHeight)
    3885                 : {
    3886               0 :   FORWARD_TO_OUTER(SetOuterHeight, (aOuterHeight), NS_ERROR_NOT_INITIALIZED);
    3887                 : 
    3888               0 :   return SetOuterSize(aOuterHeight, false);
    3889                 : }
    3890                 : 
    3891                 : NS_IMETHODIMP
    3892               0 : nsGlobalWindow::GetScreenX(PRInt32* aScreenX)
    3893                 : {
    3894               0 :   FORWARD_TO_OUTER(GetScreenX, (aScreenX), NS_ERROR_NOT_INITIALIZED);
    3895                 : 
    3896               0 :   nsCOMPtr<nsIBaseWindow> treeOwnerAsWin;
    3897               0 :   GetTreeOwner(getter_AddRefs(treeOwnerAsWin));
    3898               0 :   NS_ENSURE_TRUE(treeOwnerAsWin, NS_ERROR_FAILURE);
    3899                 : 
    3900                 :   PRInt32 x, y;
    3901                 : 
    3902               0 :   NS_ENSURE_SUCCESS(treeOwnerAsWin->GetPosition(&x, &y),
    3903                 :                     NS_ERROR_FAILURE);
    3904                 : 
    3905               0 :   *aScreenX = DevToCSSIntPixels(x);
    3906               0 :   return NS_OK;
    3907                 : }
    3908                 : 
    3909                 : nsRect
    3910               0 : nsGlobalWindow::GetInnerScreenRect()
    3911                 : {
    3912               0 :   if (!mDocShell)
    3913               0 :     return nsRect();
    3914                 : 
    3915                 :   nsGlobalWindow* rootWindow =
    3916               0 :     static_cast<nsGlobalWindow*>(GetPrivateRoot());
    3917               0 :   if (rootWindow) {
    3918               0 :     rootWindow->FlushPendingNotifications(Flush_Layout);
    3919                 :   }
    3920                 : 
    3921               0 :   nsCOMPtr<nsIPresShell> presShell;
    3922               0 :   mDocShell->GetPresShell(getter_AddRefs(presShell));
    3923               0 :   if (!presShell)
    3924               0 :     return nsRect();
    3925               0 :   nsIFrame* rootFrame = presShell->GetRootFrame();
    3926               0 :   if (!rootFrame)
    3927               0 :     return nsRect();
    3928                 : 
    3929               0 :   return rootFrame->GetScreenRectInAppUnits();
    3930                 : }
    3931                 : 
    3932                 : NS_IMETHODIMP
    3933               0 : nsGlobalWindow::GetMozInnerScreenX(float* aScreenX)
    3934                 : {
    3935               0 :   FORWARD_TO_OUTER(GetMozInnerScreenX, (aScreenX), NS_ERROR_NOT_INITIALIZED);
    3936                 : 
    3937               0 :   nsRect r = GetInnerScreenRect();
    3938               0 :   *aScreenX = nsPresContext::AppUnitsToFloatCSSPixels(r.x);
    3939               0 :   return NS_OK;
    3940                 : }
    3941                 : 
    3942                 : NS_IMETHODIMP
    3943               0 : nsGlobalWindow::GetMozInnerScreenY(float* aScreenY)
    3944                 : {
    3945               0 :   FORWARD_TO_OUTER(GetMozInnerScreenY, (aScreenY), NS_ERROR_NOT_INITIALIZED);
    3946                 : 
    3947               0 :   nsRect r = GetInnerScreenRect();
    3948               0 :   *aScreenY = nsPresContext::AppUnitsToFloatCSSPixels(r.y);
    3949               0 :   return NS_OK;
    3950                 : }
    3951                 : 
    3952                 : NS_IMETHODIMP
    3953               0 : nsGlobalWindow::GetMozPaintCount(PRUint64* aResult)
    3954                 : {
    3955               0 :   FORWARD_TO_OUTER(GetMozPaintCount, (aResult), NS_ERROR_NOT_INITIALIZED);
    3956                 : 
    3957               0 :   *aResult = 0;
    3958                 : 
    3959               0 :   if (!mDocShell)
    3960               0 :     return NS_OK;
    3961                 : 
    3962               0 :   nsCOMPtr<nsIPresShell> presShell;
    3963               0 :   mDocShell->GetPresShell(getter_AddRefs(presShell));
    3964               0 :   if (!presShell)
    3965               0 :     return NS_OK;
    3966                 : 
    3967               0 :   *aResult = presShell->GetPaintCount();
    3968               0 :   return NS_OK;
    3969                 : }
    3970                 : 
    3971                 : NS_IMETHODIMP
    3972               0 : nsGlobalWindow::MozRequestAnimationFrame(nsIFrameRequestCallback* aCallback,
    3973                 :                                          PRInt32 *aHandle)
    3974                 : {
    3975               0 :   FORWARD_TO_INNER(MozRequestAnimationFrame, (aCallback, aHandle),
    3976                 :                    NS_ERROR_NOT_INITIALIZED);
    3977                 : 
    3978               0 :   if (!mDoc) {
    3979               0 :     return NS_OK;
    3980                 :   }
    3981                 : 
    3982               0 :   if (!aCallback) {
    3983               0 :     mDoc->WarnOnceAbout(nsIDocument::eMozBeforePaint);
    3984               0 :     return NS_ERROR_XPC_BAD_CONVERT_JS;
    3985                 :   }
    3986                 : 
    3987               0 :   return mDoc->ScheduleFrameRequestCallback(aCallback, aHandle);
    3988                 : }
    3989                 : 
    3990                 : NS_IMETHODIMP
    3991               0 : nsGlobalWindow::MozCancelRequestAnimationFrame(PRInt32 aHandle)
    3992                 : {
    3993               0 :   return MozCancelAnimationFrame(aHandle);
    3994                 : }
    3995                 : 
    3996                 : NS_IMETHODIMP
    3997               0 : nsGlobalWindow::MozCancelAnimationFrame(PRInt32 aHandle)
    3998                 : {
    3999               0 :   FORWARD_TO_INNER(MozCancelAnimationFrame, (aHandle),
    4000                 :                    NS_ERROR_NOT_INITIALIZED);
    4001                 : 
    4002               0 :   if (!mDoc) {
    4003               0 :     return NS_OK;
    4004                 :   }
    4005                 : 
    4006               0 :   mDoc->CancelFrameRequestCallback(aHandle);
    4007               0 :   return NS_OK;
    4008                 : }
    4009                 : 
    4010                 : NS_IMETHODIMP
    4011               0 : nsGlobalWindow::GetMozAnimationStartTime(PRInt64 *aTime)
    4012                 : {
    4013               0 :   FORWARD_TO_INNER(GetMozAnimationStartTime, (aTime), NS_ERROR_NOT_INITIALIZED);
    4014                 : 
    4015               0 :   if (mDoc) {
    4016               0 :     nsIPresShell* presShell = mDoc->GetShell();
    4017               0 :     if (presShell) {
    4018                 :       *aTime = presShell->GetPresContext()->RefreshDriver()->
    4019               0 :         MostRecentRefreshEpochTime() / PR_USEC_PER_MSEC;
    4020               0 :       return NS_OK;
    4021                 :     }
    4022                 :   }
    4023                 : 
    4024                 :   // If all else fails, just be compatible with Date.now()
    4025               0 :   *aTime = JS_Now() / PR_USEC_PER_MSEC;
    4026               0 :   return NS_OK;
    4027                 : }
    4028                 : 
    4029                 : NS_IMETHODIMP
    4030               0 : nsGlobalWindow::MatchMedia(const nsAString& aMediaQueryList,
    4031                 :                            nsIDOMMediaQueryList** aResult)
    4032                 : {
    4033                 :   // FIXME: This whole forward-to-outer and then get a pres
    4034                 :   // shell/context off the docshell dance is sort of silly; it'd make
    4035                 :   // more sense to forward to the inner, but it's what everyone else
    4036                 :   // (GetSelection, GetScrollXY, etc.) does around here.
    4037               0 :   FORWARD_TO_OUTER(MatchMedia, (aMediaQueryList, aResult),
    4038                 :                    NS_ERROR_NOT_INITIALIZED);
    4039                 : 
    4040               0 :   *aResult = nsnull;
    4041                 : 
    4042               0 :   if (!mDocShell)
    4043               0 :     return NS_OK;
    4044                 : 
    4045               0 :   nsRefPtr<nsPresContext> presContext;
    4046               0 :   mDocShell->GetPresContext(getter_AddRefs(presContext));
    4047                 : 
    4048               0 :   if (!presContext)
    4049               0 :     return NS_OK;
    4050                 : 
    4051               0 :   presContext->MatchMedia(aMediaQueryList, aResult);
    4052               0 :   return NS_OK;
    4053                 : }
    4054                 : 
    4055                 : NS_IMETHODIMP
    4056               0 : nsGlobalWindow::SetScreenX(PRInt32 aScreenX)
    4057                 : {
    4058               0 :   FORWARD_TO_OUTER(SetScreenX, (aScreenX), NS_ERROR_NOT_INITIALIZED);
    4059                 : 
    4060                 :   /*
    4061                 :    * If caller is not chrome and the user has not explicitly exempted the site,
    4062                 :    * prevent setting window.screenX by exiting early
    4063                 :    */
    4064                 : 
    4065               0 :   if (!CanMoveResizeWindows() || IsFrame()) {
    4066               0 :     return NS_OK;
    4067                 :   }
    4068                 : 
    4069               0 :   nsCOMPtr<nsIBaseWindow> treeOwnerAsWin;
    4070               0 :   GetTreeOwner(getter_AddRefs(treeOwnerAsWin));
    4071               0 :   NS_ENSURE_TRUE(treeOwnerAsWin, NS_ERROR_FAILURE);
    4072                 : 
    4073               0 :   NS_ENSURE_SUCCESS(CheckSecurityLeftAndTop(&aScreenX, nsnull),
    4074                 :                     NS_ERROR_FAILURE);
    4075                 : 
    4076                 :   PRInt32 x, y;
    4077               0 :   NS_ENSURE_SUCCESS(treeOwnerAsWin->GetPosition(&x, &y),
    4078                 :                     NS_ERROR_FAILURE);
    4079                 : 
    4080               0 :   x = CSSToDevIntPixels(aScreenX);
    4081                 : 
    4082               0 :   NS_ENSURE_SUCCESS(treeOwnerAsWin->SetPosition(x, y),
    4083                 :                     NS_ERROR_FAILURE);
    4084                 : 
    4085               0 :   return NS_OK;
    4086                 : }
    4087                 : 
    4088                 : NS_IMETHODIMP
    4089               0 : nsGlobalWindow::GetScreenY(PRInt32* aScreenY)
    4090                 : {
    4091               0 :   FORWARD_TO_OUTER(GetScreenY, (aScreenY), NS_ERROR_NOT_INITIALIZED);
    4092                 : 
    4093               0 :   nsCOMPtr<nsIBaseWindow> treeOwnerAsWin;
    4094               0 :   GetTreeOwner(getter_AddRefs(treeOwnerAsWin));
    4095               0 :   NS_ENSURE_TRUE(treeOwnerAsWin, NS_ERROR_FAILURE);
    4096                 : 
    4097                 :   PRInt32 x, y;
    4098                 : 
    4099               0 :   NS_ENSURE_SUCCESS(treeOwnerAsWin->GetPosition(&x, &y),
    4100                 :                     NS_ERROR_FAILURE);
    4101                 : 
    4102               0 :   *aScreenY = DevToCSSIntPixels(y);
    4103               0 :   return NS_OK;
    4104                 : }
    4105                 : 
    4106                 : NS_IMETHODIMP
    4107               0 : nsGlobalWindow::SetScreenY(PRInt32 aScreenY)
    4108                 : {
    4109               0 :   FORWARD_TO_OUTER(SetScreenY, (aScreenY), NS_ERROR_NOT_INITIALIZED);
    4110                 : 
    4111                 :   /*
    4112                 :    * If caller is not chrome and the user has not explicitly exempted the site,
    4113                 :    * prevent setting window.screenY by exiting early
    4114                 :    */
    4115                 : 
    4116               0 :   if (!CanMoveResizeWindows() || IsFrame()) {
    4117               0 :     return NS_OK;
    4118                 :   }
    4119                 : 
    4120               0 :   nsCOMPtr<nsIBaseWindow> treeOwnerAsWin;
    4121               0 :   GetTreeOwner(getter_AddRefs(treeOwnerAsWin));
    4122               0 :   NS_ENSURE_TRUE(treeOwnerAsWin, NS_ERROR_FAILURE);
    4123                 : 
    4124               0 :   NS_ENSURE_SUCCESS(CheckSecurityLeftAndTop(nsnull, &aScreenY),
    4125                 :                     NS_ERROR_FAILURE);
    4126                 : 
    4127                 :   PRInt32 x, y;
    4128               0 :   NS_ENSURE_SUCCESS(treeOwnerAsWin->GetPosition(&x, &y),
    4129                 :                     NS_ERROR_FAILURE);
    4130                 : 
    4131               0 :   y = CSSToDevIntPixels(aScreenY);
    4132                 : 
    4133               0 :   NS_ENSURE_SUCCESS(treeOwnerAsWin->SetPosition(x, y),
    4134                 :                     NS_ERROR_FAILURE);
    4135                 : 
    4136               0 :   return NS_OK;
    4137                 : }
    4138                 : 
    4139                 : // NOTE: Arguments to this function should have values scaled to
    4140                 : // CSS pixels, not device pixels.
    4141                 : nsresult
    4142               0 : nsGlobalWindow::CheckSecurityWidthAndHeight(PRInt32* aWidth, PRInt32* aHeight)
    4143                 : {
    4144                 : #ifdef MOZ_XUL
    4145               0 :   if (!nsContentUtils::IsCallerTrustedForWrite()) {
    4146                 :     // if attempting to resize the window, hide any open popups
    4147               0 :     nsCOMPtr<nsIDocument> doc(do_QueryInterface(mDocument));
    4148               0 :     nsContentUtils::HidePopupsInDocument(doc);
    4149                 :   }
    4150                 : #endif
    4151                 : 
    4152                 :   // This one is easy. Just ensure the variable is greater than 100;
    4153               0 :   if ((aWidth && *aWidth < 100) || (aHeight && *aHeight < 100)) {
    4154                 :     // Check security state for use in determing window dimensions
    4155                 : 
    4156               0 :     if (!nsContentUtils::IsCallerTrustedForWrite()) {
    4157                 :       //sec check failed
    4158               0 :       if (aWidth && *aWidth < 100) {
    4159               0 :         *aWidth = 100;
    4160                 :       }
    4161               0 :       if (aHeight && *aHeight < 100) {
    4162               0 :         *aHeight = 100;
    4163                 :       }
    4164                 :     }
    4165                 :   }
    4166                 : 
    4167               0 :   return NS_OK;
    4168                 : }
    4169                 : 
    4170                 : // NOTE: Arguments to this function should have values in device pixels
    4171                 : nsresult
    4172               0 : nsGlobalWindow::SetDocShellWidthAndHeight(PRInt32 aInnerWidth, PRInt32 aInnerHeight)
    4173                 : {
    4174               0 :   nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(do_QueryInterface(mDocShell));
    4175               0 :   NS_ENSURE_TRUE(docShellAsItem, NS_ERROR_FAILURE);
    4176                 : 
    4177               0 :   nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
    4178               0 :   docShellAsItem->GetTreeOwner(getter_AddRefs(treeOwner));
    4179               0 :   NS_ENSURE_TRUE(treeOwner, NS_ERROR_FAILURE);
    4180                 : 
    4181               0 :   NS_ENSURE_SUCCESS(treeOwner->SizeShellTo(docShellAsItem, aInnerWidth, aInnerHeight),
    4182                 :                     NS_ERROR_FAILURE);
    4183                 : 
    4184               0 :   return NS_OK;
    4185                 : }
    4186                 : 
    4187                 : // NOTE: Arguments to this function should have values in app units
    4188                 : nsresult
    4189               0 : nsGlobalWindow::SetCSSViewportWidthAndHeight(nscoord aInnerWidth, nscoord aInnerHeight)
    4190                 : {
    4191               0 :   nsRefPtr<nsPresContext> presContext;
    4192               0 :   mDocShell->GetPresContext(getter_AddRefs(presContext));
    4193                 : 
    4194               0 :   nsRect shellArea = presContext->GetVisibleArea();
    4195               0 :   shellArea.height = aInnerHeight;
    4196               0 :   shellArea.width = aInnerWidth;
    4197                 : 
    4198               0 :   presContext->SetVisibleArea(shellArea);
    4199               0 :   return NS_OK;
    4200                 : }
    4201                 : 
    4202                 : // NOTE: Arguments to this function should have values scaled to
    4203                 : // CSS pixels, not device pixels.
    4204                 : nsresult
    4205               0 : nsGlobalWindow::CheckSecurityLeftAndTop(PRInt32* aLeft, PRInt32* aTop)
    4206                 : {
    4207                 :   // This one is harder. We have to get the screen size and window dimensions.
    4208                 : 
    4209                 :   // Check security state for use in determing window dimensions
    4210                 : 
    4211               0 :   if (!nsContentUtils::IsCallerTrustedForWrite()) {
    4212                 : #ifdef MOZ_XUL
    4213                 :     // if attempting to move the window, hide any open popups
    4214               0 :     nsCOMPtr<nsIDocument> doc(do_QueryInterface(mDocument));
    4215               0 :     nsContentUtils::HidePopupsInDocument(doc);
    4216                 : #endif
    4217                 : 
    4218                 :     nsGlobalWindow* rootWindow =
    4219               0 :       static_cast<nsGlobalWindow*>(GetPrivateRoot());
    4220               0 :     if (rootWindow) {
    4221               0 :       rootWindow->FlushPendingNotifications(Flush_Layout);
    4222                 :     }
    4223                 : 
    4224               0 :     nsCOMPtr<nsIBaseWindow> treeOwner;
    4225               0 :     GetTreeOwner(getter_AddRefs(treeOwner));
    4226                 : 
    4227               0 :     nsCOMPtr<nsIDOMScreen> screen;
    4228               0 :     GetScreen(getter_AddRefs(screen));
    4229                 : 
    4230               0 :     if (treeOwner && screen) {
    4231                 :       PRInt32 screenLeft, screenTop, screenWidth, screenHeight;
    4232                 :       PRInt32 winLeft, winTop, winWidth, winHeight;
    4233                 : 
    4234                 :       // Get the window size
    4235               0 :       treeOwner->GetPositionAndSize(&winLeft, &winTop, &winWidth, &winHeight);
    4236                 : 
    4237                 :       // convert those values to CSS pixels
    4238                 :       // XXX four separate retrievals of the prescontext
    4239               0 :       winLeft   = DevToCSSIntPixels(winLeft);
    4240               0 :       winTop    = DevToCSSIntPixels(winTop);
    4241               0 :       winWidth  = DevToCSSIntPixels(winWidth);
    4242               0 :       winHeight = DevToCSSIntPixels(winHeight);
    4243                 : 
    4244                 :       // Get the screen dimensions
    4245                 :       // XXX This should use nsIScreenManager once it's fully fleshed out.
    4246               0 :       screen->GetAvailLeft(&screenLeft);
    4247               0 :       screen->GetAvailWidth(&screenWidth);
    4248               0 :       screen->GetAvailHeight(&screenHeight);
    4249                 : #if defined(XP_MACOSX)
    4250                 :       /* The mac's coordinate system is different from the assumed Windows'
    4251                 :          system. It offsets by the height of the menubar so that a window
    4252                 :          placed at (0,0) will be entirely visible. Unfortunately that
    4253                 :          correction is made elsewhere (in Widget) and the meaning of
    4254                 :          the Avail... coordinates is overloaded. Here we allow a window
    4255                 :          to be placed at (0,0) because it does make sense to do so.
    4256                 :       */
    4257                 :       screen->GetTop(&screenTop);
    4258                 : #else
    4259               0 :       screen->GetAvailTop(&screenTop);
    4260                 : #endif
    4261                 : 
    4262               0 :       if (aLeft) {
    4263               0 :         if (screenLeft+screenWidth < *aLeft+winWidth)
    4264               0 :           *aLeft = screenLeft+screenWidth - winWidth;
    4265               0 :         if (screenLeft > *aLeft)
    4266               0 :           *aLeft = screenLeft;
    4267                 :       }
    4268               0 :       if (aTop) {
    4269               0 :         if (screenTop+screenHeight < *aTop+winHeight)
    4270               0 :           *aTop = screenTop+screenHeight - winHeight;
    4271               0 :         if (screenTop > *aTop)
    4272               0 :           *aTop = screenTop;
    4273                 :       }
    4274                 :     } else {
    4275               0 :       if (aLeft)
    4276               0 :         *aLeft = 0;
    4277               0 :       if (aTop)
    4278               0 :         *aTop = 0;
    4279                 :     }
    4280                 :   }
    4281                 : 
    4282               0 :   return NS_OK;
    4283                 : }
    4284                 : 
    4285                 : NS_IMETHODIMP
    4286               0 : nsGlobalWindow::GetPageXOffset(PRInt32* aPageXOffset)
    4287                 : {
    4288               0 :   return GetScrollX(aPageXOffset);
    4289                 : }
    4290                 : 
    4291                 : NS_IMETHODIMP
    4292               0 : nsGlobalWindow::GetPageYOffset(PRInt32* aPageYOffset)
    4293                 : {
    4294               0 :   return GetScrollY(aPageYOffset);
    4295                 : }
    4296                 : 
    4297                 : nsresult
    4298               0 : nsGlobalWindow::GetScrollMaxXY(PRInt32* aScrollMaxX, PRInt32* aScrollMaxY)
    4299                 : {
    4300               0 :   FORWARD_TO_OUTER(GetScrollMaxXY, (aScrollMaxX, aScrollMaxY),
    4301                 :                    NS_ERROR_NOT_INITIALIZED);
    4302                 : 
    4303               0 :   FlushPendingNotifications(Flush_Layout);
    4304               0 :   nsIScrollableFrame *sf = GetScrollFrame();
    4305               0 :   if (!sf)
    4306               0 :     return NS_OK;
    4307                 : 
    4308               0 :   nsRect scrollRange = sf->GetScrollRange();
    4309                 : 
    4310               0 :   if (aScrollMaxX)
    4311                 :     *aScrollMaxX = NS_MAX(0,
    4312               0 :       (PRInt32)floor(nsPresContext::AppUnitsToFloatCSSPixels(scrollRange.XMost())));
    4313               0 :   if (aScrollMaxY)
    4314                 :     *aScrollMaxY = NS_MAX(0,
    4315               0 :       (PRInt32)floor(nsPresContext::AppUnitsToFloatCSSPixels(scrollRange.YMost())));
    4316                 : 
    4317               0 :   return NS_OK;
    4318                 : }
    4319                 : 
    4320                 : NS_IMETHODIMP
    4321               0 : nsGlobalWindow::GetScrollMaxX(PRInt32* aScrollMaxX)
    4322                 : {
    4323               0 :   NS_ENSURE_ARG_POINTER(aScrollMaxX);
    4324               0 :   *aScrollMaxX = 0;
    4325               0 :   return GetScrollMaxXY(aScrollMaxX, nsnull);
    4326                 : }
    4327                 : 
    4328                 : NS_IMETHODIMP
    4329               0 : nsGlobalWindow::GetScrollMaxY(PRInt32* aScrollMaxY)
    4330                 : {
    4331               0 :   NS_ENSURE_ARG_POINTER(aScrollMaxY);
    4332               0 :   *aScrollMaxY = 0;
    4333               0 :   return GetScrollMaxXY(nsnull, aScrollMaxY);
    4334                 : }
    4335                 : 
    4336                 : nsresult
    4337               0 : nsGlobalWindow::GetScrollXY(PRInt32* aScrollX, PRInt32* aScrollY,
    4338                 :                             bool aDoFlush)
    4339                 : {
    4340               0 :   FORWARD_TO_OUTER(GetScrollXY, (aScrollX, aScrollY, aDoFlush),
    4341                 :                    NS_ERROR_NOT_INITIALIZED);
    4342                 : 
    4343               0 :   if (aDoFlush) {
    4344               0 :     FlushPendingNotifications(Flush_Layout);
    4345                 :   } else {
    4346               0 :     EnsureSizeUpToDate();
    4347                 :   }
    4348                 : 
    4349               0 :   nsIScrollableFrame *sf = GetScrollFrame();
    4350               0 :   if (!sf)
    4351               0 :     return NS_OK;
    4352                 : 
    4353               0 :   nsPoint scrollPos = sf->GetScrollPosition();
    4354               0 :   if (scrollPos != nsPoint(0,0) && !aDoFlush) {
    4355                 :     // Oh, well.  This is the expensive case -- the window is scrolled and we
    4356                 :     // didn't actually flush yet.  Repeat, but with a flush, since the content
    4357                 :     // may get shorter and hence our scroll position may decrease.
    4358               0 :     return GetScrollXY(aScrollX, aScrollY, true);
    4359                 :   }
    4360                 : 
    4361               0 :   if (aScrollX)
    4362               0 :     *aScrollX = nsPresContext::AppUnitsToIntCSSPixels(scrollPos.x);
    4363               0 :   if (aScrollY)
    4364               0 :     *aScrollY = nsPresContext::AppUnitsToIntCSSPixels(scrollPos.y);
    4365                 : 
    4366               0 :   return NS_OK;
    4367                 : }
    4368                 : 
    4369                 : NS_IMETHODIMP
    4370               0 : nsGlobalWindow::GetScrollX(PRInt32* aScrollX)
    4371                 : {
    4372               0 :   NS_ENSURE_ARG_POINTER(aScrollX);
    4373               0 :   *aScrollX = 0;
    4374               0 :   return GetScrollXY(aScrollX, nsnull, false);
    4375                 : }
    4376                 : 
    4377                 : NS_IMETHODIMP
    4378               0 : nsGlobalWindow::GetScrollY(PRInt32* aScrollY)
    4379                 : {
    4380               0 :   NS_ENSURE_ARG_POINTER(aScrollY);
    4381               0 :   *aScrollY = 0;
    4382               0 :   return GetScrollXY(nsnull, aScrollY, false);
    4383                 : }
    4384                 : 
    4385                 : NS_IMETHODIMP
    4386               0 : nsGlobalWindow::GetLength(PRUint32* aLength)
    4387                 : {
    4388               0 :   nsCOMPtr<nsIDOMWindowCollection> frames;
    4389               0 :   if (NS_SUCCEEDED(GetFrames(getter_AddRefs(frames))) && frames) {
    4390               0 :     return frames->GetLength(aLength);
    4391                 :   }
    4392               0 :   return NS_ERROR_FAILURE;
    4393                 : }
    4394                 : 
    4395                 : bool
    4396               0 : nsGlobalWindow::DispatchCustomEvent(const char *aEventName)
    4397                 : {
    4398               0 :   bool defaultActionEnabled = true;
    4399               0 :   nsCOMPtr<nsIDocument> doc(do_QueryInterface(mDocument));
    4400                 :   nsContentUtils::DispatchTrustedEvent(doc,
    4401               0 :                                        GetOuterWindow(),
    4402               0 :                                        NS_ConvertASCIItoUTF16(aEventName),
    4403               0 :                                        true, true, &defaultActionEnabled);
    4404                 : 
    4405               0 :   return defaultActionEnabled;
    4406                 : }
    4407                 : 
    4408                 : static already_AddRefed<nsIDocShellTreeItem>
    4409               0 : GetCallerDocShellTreeItem()
    4410                 : {
    4411               0 :   JSContext *cx = nsContentUtils::GetCurrentJSContext();
    4412               0 :   nsIDocShellTreeItem *callerItem = nsnull;
    4413                 : 
    4414               0 :   if (cx) {
    4415                 :     nsCOMPtr<nsIWebNavigation> callerWebNav =
    4416               0 :       do_GetInterface(nsJSUtils::GetDynamicScriptGlobal(cx));
    4417                 : 
    4418               0 :     if (callerWebNav) {
    4419               0 :       CallQueryInterface(callerWebNav, &callerItem);
    4420                 :     }
    4421                 :   }
    4422                 : 
    4423               0 :   return callerItem;
    4424                 : }
    4425                 : 
    4426                 : bool
    4427               0 : nsGlobalWindow::WindowExists(const nsAString& aName,
    4428                 :                              bool aLookForCallerOnJSStack)
    4429                 : {
    4430               0 :   NS_PRECONDITION(IsOuterWindow(), "Must be outer window");
    4431               0 :   NS_PRECONDITION(mDocShell, "Must have docshell");
    4432                 : 
    4433               0 :   nsCOMPtr<nsIDocShellTreeItem> caller;
    4434               0 :   if (aLookForCallerOnJSStack) {
    4435               0 :     caller = GetCallerDocShellTreeItem();
    4436                 :   }
    4437                 : 
    4438               0 :   nsCOMPtr<nsIDocShellTreeItem> docShell = do_QueryInterface(mDocShell);
    4439               0 :   NS_ASSERTION(docShell,
    4440                 :                "Docshell doesn't implement nsIDocShellTreeItem?");
    4441                 : 
    4442               0 :   if (!caller) {
    4443               0 :     caller = docShell;
    4444                 :   }
    4445                 : 
    4446               0 :   nsCOMPtr<nsIDocShellTreeItem> namedItem;
    4447               0 :   docShell->FindItemWithName(PromiseFlatString(aName).get(), nsnull, caller,
    4448               0 :                              getter_AddRefs(namedItem));
    4449               0 :   return namedItem != nsnull;
    4450                 : }
    4451                 : 
    4452                 : already_AddRefed<nsIWidget>
    4453               0 : nsGlobalWindow::GetMainWidget()
    4454                 : {
    4455               0 :   nsCOMPtr<nsIBaseWindow> treeOwnerAsWin;
    4456               0 :   GetTreeOwner(getter_AddRefs(treeOwnerAsWin));
    4457                 : 
    4458               0 :   nsIWidget *widget = nsnull;
    4459                 : 
    4460               0 :   if (treeOwnerAsWin) {
    4461               0 :     treeOwnerAsWin->GetMainWidget(&widget);
    4462                 :   }
    4463                 : 
    4464               0 :   return widget;
    4465                 : }
    4466                 : 
    4467                 : nsIWidget*
    4468               0 : nsGlobalWindow::GetNearestWidget()
    4469                 : {
    4470               0 :   nsIDocShell* docShell = GetDocShell();
    4471               0 :   NS_ENSURE_TRUE(docShell, nsnull);
    4472               0 :   nsCOMPtr<nsIPresShell> presShell;
    4473               0 :   docShell->GetPresShell(getter_AddRefs(presShell));
    4474               0 :   NS_ENSURE_TRUE(presShell, nsnull);
    4475               0 :   nsIFrame* rootFrame = presShell->GetRootFrame();
    4476               0 :   NS_ENSURE_TRUE(rootFrame, nsnull);
    4477               0 :   return rootFrame->GetView()->GetNearestWidget(nsnull);
    4478                 : }
    4479                 : 
    4480                 : NS_IMETHODIMP
    4481               0 : nsGlobalWindow::SetFullScreen(bool aFullScreen)
    4482                 : {
    4483               0 :   return SetFullScreenInternal(aFullScreen, true);
    4484                 : }
    4485                 : 
    4486                 : nsresult
    4487               0 : nsGlobalWindow::SetFullScreenInternal(bool aFullScreen, bool aRequireTrust)
    4488                 : {
    4489               0 :   FORWARD_TO_OUTER(SetFullScreen, (aFullScreen), NS_ERROR_NOT_INITIALIZED);
    4490                 : 
    4491               0 :   NS_ENSURE_TRUE(mDocShell, NS_ERROR_FAILURE);
    4492                 : 
    4493                 :   bool rootWinFullScreen;
    4494               0 :   GetFullScreen(&rootWinFullScreen);
    4495                 :   // Only chrome can change our fullScreen mode, unless we're running in
    4496                 :   // untrusted mode.
    4497               0 :   if (aFullScreen == rootWinFullScreen || 
    4498               0 :       (aRequireTrust && !nsContentUtils::IsCallerTrustedForWrite())) {
    4499               0 :     return NS_OK;
    4500                 :   }
    4501                 : 
    4502                 :   // SetFullScreen needs to be called on the root window, so get that
    4503                 :   // via the DocShell tree, and if we are not already the root,
    4504                 :   // call SetFullScreen on that window instead.
    4505               0 :   nsCOMPtr<nsIDocShellTreeItem> treeItem = do_QueryInterface(mDocShell);
    4506               0 :   nsCOMPtr<nsIDocShellTreeItem> rootItem;
    4507               0 :   treeItem->GetRootTreeItem(getter_AddRefs(rootItem));
    4508               0 :   nsCOMPtr<nsPIDOMWindow> window = do_GetInterface(rootItem);
    4509               0 :   if (!window)
    4510               0 :     return NS_ERROR_FAILURE;
    4511               0 :   if (rootItem != treeItem)
    4512               0 :     return window->SetFullScreenInternal(aFullScreen, aRequireTrust);
    4513                 : 
    4514                 :   // make sure we don't try to set full screen on a non-chrome window,
    4515                 :   // which might happen in embedding world
    4516                 :   PRInt32 itemType;
    4517               0 :   treeItem->GetItemType(&itemType);
    4518               0 :   if (itemType != nsIDocShellTreeItem::typeChrome)
    4519               0 :     return NS_ERROR_FAILURE;
    4520                 : 
    4521                 :   // If we are already in full screen mode, just return.
    4522               0 :   if (mFullScreen == aFullScreen)
    4523               0 :     return NS_OK;
    4524                 : 
    4525                 :   // dispatch a "fullscreen" DOM event so that XUL apps can
    4526                 :   // respond visually if we are kicked into full screen mode
    4527               0 :   if (!DispatchCustomEvent("fullscreen")) {
    4528               0 :     return NS_OK;
    4529                 :   }
    4530                 : 
    4531                 :   // Prevent chrome documents which are still loading from resizing
    4532                 :   // the window after we set fullscreen mode.
    4533               0 :   nsCOMPtr<nsIBaseWindow> treeOwnerAsWin;
    4534               0 :   GetTreeOwner(getter_AddRefs(treeOwnerAsWin));
    4535               0 :   nsCOMPtr<nsIXULWindow> xulWin(do_GetInterface(treeOwnerAsWin));
    4536               0 :   if (aFullScreen && xulWin) {
    4537               0 :     xulWin->SetIntrinsicallySized(false);
    4538                 :   }
    4539                 : 
    4540                 :   // Set this before so if widget sends an event indicating its
    4541                 :   // gone full screen, the state trap above works.
    4542               0 :   mFullScreen = aFullScreen;
    4543                 : 
    4544               0 :   nsCOMPtr<nsIWidget> widget = GetMainWidget();
    4545               0 :   if (widget)
    4546               0 :     widget->MakeFullScreen(aFullScreen);
    4547                 : 
    4548               0 :   if (!mFullScreen) {
    4549                 :     // Force exit from DOM full-screen mode. This is so that if we're in
    4550                 :     // DOM full-screen mode and the user exits full-screen mode with
    4551                 :     // the browser full-screen mode toggle keyboard-shortcut, we'll detect
    4552                 :     // that and leave DOM API full-screen mode too.
    4553               0 :     nsIDocument::ExitFullScreen(false);
    4554                 :   }
    4555                 : 
    4556               0 :   return NS_OK;
    4557                 : }
    4558                 : 
    4559                 : NS_IMETHODIMP
    4560               0 : nsGlobalWindow::GetFullScreen(bool* aFullScreen)
    4561                 : {
    4562               0 :   FORWARD_TO_OUTER(GetFullScreen, (aFullScreen), NS_ERROR_NOT_INITIALIZED);
    4563                 : 
    4564                 :   // Get the fullscreen value of the root window, to always have the value
    4565                 :   // accurate, even when called from content.
    4566               0 :   nsCOMPtr<nsIDocShellTreeItem> treeItem = do_QueryInterface(mDocShell);
    4567               0 :   if (treeItem) {
    4568               0 :     nsCOMPtr<nsIDocShellTreeItem> rootItem;
    4569               0 :     treeItem->GetRootTreeItem(getter_AddRefs(rootItem));
    4570               0 :     if (rootItem != treeItem) {
    4571               0 :       nsCOMPtr<nsIDOMWindow> window = do_GetInterface(rootItem);
    4572               0 :       if (window)
    4573               0 :         return window->GetFullScreen(aFullScreen);
    4574                 :     }
    4575                 :   }
    4576                 : 
    4577                 :   // We are the root window, or something went wrong. Return our internal value.
    4578               0 :   *aFullScreen = mFullScreen;
    4579               0 :   return NS_OK;
    4580                 : }
    4581                 : 
    4582                 : bool
    4583               0 : nsGlobalWindow::DOMWindowDumpEnabled()
    4584                 : {
    4585                 : #if !(defined(NS_DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
    4586                 :   // In optimized builds we check a pref that controls if we should
    4587                 :   // enable output from dump() or not, in debug builds it's always
    4588                 :   // enabled.
    4589                 :   return gDOMWindowDumpEnabled;
    4590                 : #else
    4591               0 :   return true;
    4592                 : #endif
    4593                 : }
    4594                 : 
    4595                 : NS_IMETHODIMP
    4596               0 : nsGlobalWindow::Dump(const nsAString& aStr)
    4597                 : {
    4598               0 :   if (!DOMWindowDumpEnabled()) {
    4599               0 :     return NS_OK;
    4600                 :   }
    4601                 : 
    4602               0 :   char *cstr = ToNewUTF8String(aStr);
    4603                 : 
    4604                 : #if defined(XP_MACOSX)
    4605                 :   // have to convert \r to \n so that printing to the console works
    4606                 :   char *c = cstr, *cEnd = cstr + strlen(cstr);
    4607                 :   while (c < cEnd) {
    4608                 :     if (*c == '\r')
    4609                 :       *c = '\n';
    4610                 :     c++;
    4611                 :   }
    4612                 : #endif
    4613                 : 
    4614               0 :   if (cstr) {
    4615                 : #ifdef ANDROID
    4616                 :     __android_log_write(ANDROID_LOG_INFO, "GeckoDump", cstr);
    4617                 : #endif
    4618               0 :     FILE *fp = gDumpFile ? gDumpFile : stdout;
    4619               0 :     fputs(cstr, fp);
    4620               0 :     fflush(fp);
    4621               0 :     nsMemory::Free(cstr);
    4622                 :   }
    4623                 : 
    4624               0 :   return NS_OK;
    4625                 : }
    4626                 : 
    4627                 : void
    4628               0 : nsGlobalWindow::EnsureReflowFlushAndPaint()
    4629                 : {
    4630               0 :   NS_ASSERTION(IsOuterWindow(), "EnsureReflowFlushAndPaint() must be called on"
    4631                 :                "the outer window");
    4632               0 :   NS_ASSERTION(mDocShell, "EnsureReflowFlushAndPaint() called with no "
    4633                 :                "docshell!");
    4634                 : 
    4635               0 :   if (!mDocShell)
    4636               0 :     return;
    4637                 : 
    4638               0 :   nsCOMPtr<nsIPresShell> presShell;
    4639               0 :   mDocShell->GetPresShell(getter_AddRefs(presShell));
    4640                 : 
    4641               0 :   if (!presShell)
    4642                 :     return;
    4643                 : 
    4644                 :   // Flush pending reflows.
    4645               0 :   if (mDoc) {
    4646               0 :     mDoc->FlushPendingNotifications(Flush_Layout);
    4647                 :   }
    4648                 : 
    4649                 :   // Unsuppress painting.
    4650               0 :   presShell->UnsuppressPainting();
    4651                 : }
    4652                 : 
    4653                 : NS_IMETHODIMP
    4654               0 : nsGlobalWindow::GetTextZoom(float *aZoom)
    4655                 : {
    4656               0 :   FORWARD_TO_OUTER(GetTextZoom, (aZoom), NS_ERROR_NOT_INITIALIZED);
    4657                 : 
    4658               0 :   if (mDocShell) {
    4659               0 :     nsCOMPtr<nsIContentViewer> contentViewer;
    4660               0 :     mDocShell->GetContentViewer(getter_AddRefs(contentViewer));
    4661               0 :     nsCOMPtr<nsIMarkupDocumentViewer> markupViewer(do_QueryInterface(contentViewer));
    4662                 : 
    4663               0 :     if (markupViewer) {
    4664               0 :       return markupViewer->GetTextZoom(aZoom);
    4665                 :     }
    4666                 :   }
    4667               0 :   return NS_ERROR_FAILURE;
    4668                 : }
    4669                 : 
    4670                 : NS_IMETHODIMP
    4671               0 : nsGlobalWindow::SetTextZoom(float aZoom)
    4672                 : {
    4673               0 :   FORWARD_TO_OUTER(SetTextZoom, (aZoom), NS_ERROR_NOT_INITIALIZED);
    4674                 : 
    4675               0 :   if (mDocShell) {
    4676               0 :     nsCOMPtr<nsIContentViewer> contentViewer;
    4677               0 :     mDocShell->GetContentViewer(getter_AddRefs(contentViewer));
    4678               0 :     nsCOMPtr<nsIMarkupDocumentViewer> markupViewer(do_QueryInterface(contentViewer));
    4679                 : 
    4680               0 :     if (markupViewer)
    4681               0 :       return markupViewer->SetTextZoom(aZoom);
    4682                 :   }
    4683               0 :   return NS_ERROR_FAILURE;
    4684                 : }
    4685                 : 
    4686                 : // static
    4687                 : void
    4688               0 : nsGlobalWindow::MakeScriptDialogTitle(nsAString &aOutTitle)
    4689                 : {
    4690               0 :   aOutTitle.Truncate();
    4691                 : 
    4692                 :   // Try to get a host from the running principal -- this will do the
    4693                 :   // right thing for javascript: and data: documents.
    4694                 : 
    4695               0 :   nsresult rv = NS_OK;
    4696               0 :   NS_ASSERTION(nsContentUtils::GetSecurityManager(),
    4697                 :     "Global Window has no security manager!");
    4698               0 :   if (nsContentUtils::GetSecurityManager()) {
    4699               0 :     nsCOMPtr<nsIPrincipal> principal;
    4700               0 :     rv = nsContentUtils::GetSecurityManager()->
    4701               0 :       GetSubjectPrincipal(getter_AddRefs(principal));
    4702                 : 
    4703               0 :     if (NS_SUCCEEDED(rv) && principal) {
    4704               0 :       nsCOMPtr<nsIURI> uri;
    4705               0 :       rv = principal->GetURI(getter_AddRefs(uri));
    4706                 : 
    4707               0 :       if (NS_SUCCEEDED(rv) && uri) {
    4708                 :         // remove user:pass for privacy and spoof prevention
    4709                 : 
    4710               0 :         nsCOMPtr<nsIURIFixup> fixup(do_GetService(NS_URIFIXUP_CONTRACTID));
    4711               0 :         if (fixup) {
    4712               0 :           nsCOMPtr<nsIURI> fixedURI;
    4713               0 :           rv = fixup->CreateExposableURI(uri, getter_AddRefs(fixedURI));
    4714               0 :           if (NS_SUCCEEDED(rv) && fixedURI) {
    4715               0 :             nsCAutoString host;
    4716               0 :             fixedURI->GetHost(host);
    4717                 : 
    4718               0 :             if (!host.IsEmpty()) {
    4719                 :               // if this URI has a host we'll show it. For other
    4720                 :               // schemes (e.g. file:) we fall back to the localized
    4721                 :               // generic string
    4722                 : 
    4723               0 :               nsCAutoString prepath;
    4724               0 :               fixedURI->GetPrePath(prepath);
    4725                 : 
    4726               0 :               NS_ConvertUTF8toUTF16 ucsPrePath(prepath);
    4727               0 :               const PRUnichar *formatStrings[] = { ucsPrePath.get() };
    4728               0 :               nsXPIDLString tempString;
    4729                 :               nsContentUtils::FormatLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES,
    4730                 :                                                     "ScriptDlgHeading",
    4731                 :                                                     formatStrings,
    4732               0 :                                                     tempString);
    4733               0 :               aOutTitle = tempString;
    4734                 :             }
    4735                 :           }
    4736                 :         }
    4737                 :       }
    4738                 :     }
    4739                 :     else { // failed to get subject principal
    4740               0 :       NS_WARNING("No script principal? Who is calling alert/confirm/prompt?!");
    4741                 :     }
    4742                 :   }
    4743                 : 
    4744               0 :   if (aOutTitle.IsEmpty()) {
    4745                 :     // We didn't find a host so use the generic heading
    4746               0 :     nsXPIDLString tempString;
    4747                 :     nsContentUtils::GetLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES,
    4748                 :                                        "ScriptDlgGenericHeading",
    4749               0 :                                        tempString);
    4750               0 :     aOutTitle = tempString;
    4751                 :   }
    4752                 : 
    4753                 :   // Just in case
    4754               0 :   if (aOutTitle.IsEmpty()) {
    4755               0 :     NS_WARNING("could not get ScriptDlgGenericHeading string from string bundle");
    4756               0 :     aOutTitle.AssignLiteral("[Script]");
    4757                 :   }
    4758               0 : }
    4759                 : 
    4760                 : bool
    4761               0 : nsGlobalWindow::CanMoveResizeWindows()
    4762                 : {
    4763                 :   // When called from chrome, we can avoid the following checks.
    4764               0 :   if (!nsContentUtils::IsCallerTrustedForWrite()) {
    4765                 :     // Don't allow scripts to move or resize windows that were not opened by a
    4766                 :     // script.
    4767               0 :     if (!mHadOriginalOpener) {
    4768               0 :       return false;
    4769                 :     }
    4770                 : 
    4771               0 :     if (!CanSetProperty("dom.disable_window_move_resize")) {
    4772               0 :       return false;
    4773                 :     }
    4774                 : 
    4775                 :     // Ignore the request if we have more than one tab in the window.
    4776               0 :     nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
    4777               0 :     GetTreeOwner(getter_AddRefs(treeOwner));
    4778               0 :     if (treeOwner) {
    4779                 :       PRUint32 itemCount;
    4780               0 :       if (NS_SUCCEEDED(treeOwner->GetTargetableShellCount(&itemCount)) &&
    4781                 :           itemCount > 1) {
    4782               0 :         return false;
    4783                 :       }
    4784                 :     }
    4785                 :   }
    4786                 : 
    4787               0 :   if (mDocShell) {
    4788                 :     bool allow;
    4789               0 :     nsresult rv = mDocShell->GetAllowWindowControl(&allow);
    4790               0 :     if (NS_SUCCEEDED(rv) && !allow)
    4791               0 :       return false;
    4792                 :   }
    4793                 : 
    4794               0 :   if (gMouseDown && !gDragServiceDisabled) {
    4795                 :     nsCOMPtr<nsIDragService> ds =
    4796               0 :       do_GetService("@mozilla.org/widget/dragservice;1");
    4797               0 :     if (ds) {
    4798               0 :       gDragServiceDisabled = true;
    4799               0 :       ds->Suppress();
    4800                 :     }
    4801                 :   }
    4802               0 :   return true;
    4803                 : }
    4804                 : 
    4805                 : NS_IMETHODIMP
    4806               0 : nsGlobalWindow::Alert(const nsAString& aString)
    4807                 : {
    4808               0 :   FORWARD_TO_OUTER(Alert, (aString), NS_ERROR_NOT_INITIALIZED);
    4809                 : 
    4810               0 :   if (AreDialogsBlocked())
    4811               0 :     return NS_ERROR_NOT_AVAILABLE;
    4812                 : 
    4813                 :   // We have to capture this now so as not to get confused with the
    4814                 :   // popup state we push next
    4815               0 :   bool shouldEnableDisableDialog = DialogOpenAttempted();
    4816                 : 
    4817                 :   // Reset popup state while opening a modal dialog, and firing events
    4818                 :   // about the dialog, to prevent the current state from being active
    4819                 :   // the whole time a modal dialog is open.
    4820               0 :   nsAutoPopupStatePusher popupStatePusher(openAbused, true);
    4821                 : 
    4822                 :   // Special handling for alert(null) in JS for backwards
    4823                 :   // compatibility.
    4824                 : 
    4825               0 :   NS_NAMED_LITERAL_STRING(null_str, "null");
    4826                 : 
    4827               0 :   const nsAString *str = DOMStringIsNull(aString) ? &null_str : &aString;
    4828                 : 
    4829                 :   // Before bringing up the window, unsuppress painting and flush
    4830                 :   // pending reflows.
    4831               0 :   EnsureReflowFlushAndPaint();
    4832                 : 
    4833               0 :   nsAutoString title;
    4834               0 :   MakeScriptDialogTitle(title);
    4835                 : 
    4836                 :   // Remove non-terminating null characters from the 
    4837                 :   // string. See bug #310037. 
    4838               0 :   nsAutoString final;
    4839               0 :   nsContentUtils::StripNullChars(*str, final);
    4840                 : 
    4841                 :   // Check if we're being called at a point where we can't use tab-modal
    4842                 :   // prompts, because something doesn't want reentrancy.
    4843               0 :   bool allowTabModal = GetIsTabModalPromptAllowed();
    4844                 : 
    4845                 :   nsresult rv;
    4846                 :   nsCOMPtr<nsIPromptFactory> promptFac =
    4847               0 :     do_GetService("@mozilla.org/prompter;1", &rv);
    4848               0 :   NS_ENSURE_SUCCESS(rv, rv);
    4849                 : 
    4850               0 :   nsCOMPtr<nsIPrompt> prompt;
    4851               0 :   rv = promptFac->GetPrompt(this, NS_GET_IID(nsIPrompt),
    4852               0 :                             reinterpret_cast<void**>(&prompt));
    4853               0 :   NS_ENSURE_SUCCESS(rv, rv);
    4854                 : 
    4855               0 :   nsCOMPtr<nsIWritablePropertyBag2> promptBag = do_QueryInterface(prompt);
    4856               0 :   if (promptBag)
    4857               0 :     promptBag->SetPropertyAsBool(NS_LITERAL_STRING("allowTabModal"), allowTabModal);
    4858                 : 
    4859               0 :   if (shouldEnableDisableDialog) {
    4860               0 :     bool disallowDialog = false;
    4861               0 :     nsXPIDLString label;
    4862                 :     nsContentUtils::GetLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES,
    4863               0 :                                        "ScriptDialogLabel", label);
    4864                 : 
    4865               0 :     rv = prompt->AlertCheck(title.get(), final.get(), label.get(),
    4866               0 :                             &disallowDialog);
    4867               0 :     if (disallowDialog)
    4868               0 :       PreventFurtherDialogs();
    4869                 :   } else {
    4870               0 :     rv = prompt->Alert(title.get(), final.get());
    4871                 :   }
    4872                 : 
    4873               0 :   return rv;
    4874                 : }
    4875                 : 
    4876                 : NS_IMETHODIMP
    4877               0 : nsGlobalWindow::Confirm(const nsAString& aString, bool* aReturn)
    4878                 : {
    4879               0 :   FORWARD_TO_OUTER(Confirm, (aString, aReturn), NS_ERROR_NOT_INITIALIZED);
    4880                 : 
    4881               0 :   if (AreDialogsBlocked())
    4882               0 :     return NS_ERROR_NOT_AVAILABLE;
    4883                 : 
    4884                 :   // We have to capture this now so as not to get confused with the popup state
    4885                 :   // we push next
    4886               0 :   bool shouldEnableDisableDialog = DialogOpenAttempted();
    4887                 : 
    4888                 :   // Reset popup state while opening a modal dialog, and firing events
    4889                 :   // about the dialog, to prevent the current state from being active
    4890                 :   // the whole time a modal dialog is open.
    4891               0 :   nsAutoPopupStatePusher popupStatePusher(openAbused, true);
    4892                 : 
    4893               0 :   *aReturn = false;
    4894                 : 
    4895                 :   // Before bringing up the window, unsuppress painting and flush
    4896                 :   // pending reflows.
    4897               0 :   EnsureReflowFlushAndPaint();
    4898                 : 
    4899               0 :   nsAutoString title;
    4900               0 :   MakeScriptDialogTitle(title);
    4901                 : 
    4902                 :   // Remove non-terminating null characters from the 
    4903                 :   // string. See bug #310037. 
    4904               0 :   nsAutoString final;
    4905               0 :   nsContentUtils::StripNullChars(aString, final);
    4906                 : 
    4907                 :   // Check if we're being called at a point where we can't use tab-modal
    4908                 :   // prompts, because something doesn't want reentrancy.
    4909               0 :   bool allowTabModal = GetIsTabModalPromptAllowed();
    4910                 : 
    4911                 :   nsresult rv;
    4912                 :   nsCOMPtr<nsIPromptFactory> promptFac =
    4913               0 :     do_GetService("@mozilla.org/prompter;1", &rv);
    4914               0 :   NS_ENSURE_SUCCESS(rv, rv);
    4915                 : 
    4916               0 :   nsCOMPtr<nsIPrompt> prompt;
    4917               0 :   rv = promptFac->GetPrompt(this, NS_GET_IID(nsIPrompt),
    4918               0 :                             reinterpret_cast<void**>(&prompt));
    4919               0 :   NS_ENSURE_SUCCESS(rv, rv);
    4920                 : 
    4921               0 :   nsCOMPtr<nsIWritablePropertyBag2> promptBag = do_QueryInterface(prompt);
    4922               0 :   if (promptBag)
    4923               0 :     promptBag->SetPropertyAsBool(NS_LITERAL_STRING("allowTabModal"), allowTabModal);
    4924                 : 
    4925               0 :   if (shouldEnableDisableDialog) {
    4926               0 :     bool disallowDialog = false;
    4927               0 :     nsXPIDLString label;
    4928                 :     nsContentUtils::GetLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES,
    4929               0 :                                        "ScriptDialogLabel", label);
    4930                 : 
    4931               0 :     rv = prompt->ConfirmCheck(title.get(), final.get(), label.get(),
    4932               0 :                               &disallowDialog, aReturn);
    4933               0 :     if (disallowDialog)
    4934               0 :       PreventFurtherDialogs();
    4935                 :   } else {
    4936               0 :     rv = prompt->Confirm(title.get(), final.get(), aReturn);
    4937                 :   }
    4938                 : 
    4939               0 :   return rv;
    4940                 : }
    4941                 : 
    4942                 : NS_IMETHODIMP
    4943               0 : nsGlobalWindow::Prompt(const nsAString& aMessage, const nsAString& aInitial,
    4944                 :                        nsAString& aReturn)
    4945                 : {
    4946               0 :   FORWARD_TO_OUTER(Prompt, (aMessage, aInitial, aReturn),
    4947                 :                    NS_ERROR_NOT_INITIALIZED);
    4948                 : 
    4949               0 :   SetDOMStringToNull(aReturn);
    4950                 : 
    4951               0 :   if (AreDialogsBlocked())
    4952               0 :     return NS_ERROR_NOT_AVAILABLE;
    4953                 : 
    4954                 :   // We have to capture this now so as not to get confused with the popup state
    4955                 :   // we push next
    4956               0 :   bool shouldEnableDisableDialog = DialogOpenAttempted();
    4957                 : 
    4958                 :   // Reset popup state while opening a modal dialog, and firing events
    4959                 :   // about the dialog, to prevent the current state from being active
    4960                 :   // the whole time a modal dialog is open.
    4961               0 :   nsAutoPopupStatePusher popupStatePusher(openAbused, true);
    4962                 : 
    4963                 :   // Before bringing up the window, unsuppress painting and flush
    4964                 :   // pending reflows.
    4965               0 :   EnsureReflowFlushAndPaint();
    4966                 : 
    4967               0 :   nsAutoString title;
    4968               0 :   MakeScriptDialogTitle(title);
    4969                 :   
    4970                 :   // Remove non-terminating null characters from the 
    4971                 :   // string. See bug #310037. 
    4972               0 :   nsAutoString fixedMessage, fixedInitial;
    4973               0 :   nsContentUtils::StripNullChars(aMessage, fixedMessage);
    4974               0 :   nsContentUtils::StripNullChars(aInitial, fixedInitial);
    4975                 : 
    4976                 :   // Check if we're being called at a point where we can't use tab-modal
    4977                 :   // prompts, because something doesn't want reentrancy.
    4978               0 :   bool allowTabModal = GetIsTabModalPromptAllowed();
    4979                 : 
    4980                 :   nsresult rv;
    4981                 :   nsCOMPtr<nsIPromptFactory> promptFac =
    4982               0 :     do_GetService("@mozilla.org/prompter;1", &rv);
    4983               0 :   NS_ENSURE_SUCCESS(rv, rv);
    4984                 : 
    4985               0 :   nsCOMPtr<nsIPrompt> prompt;
    4986               0 :   rv = promptFac->GetPrompt(this, NS_GET_IID(nsIPrompt),
    4987               0 :                             reinterpret_cast<void**>(&prompt));
    4988               0 :   NS_ENSURE_SUCCESS(rv, rv);
    4989                 : 
    4990               0 :   nsCOMPtr<nsIWritablePropertyBag2> promptBag = do_QueryInterface(prompt);
    4991               0 :   if (promptBag)
    4992               0 :     promptBag->SetPropertyAsBool(NS_LITERAL_STRING("allowTabModal"), allowTabModal);
    4993                 : 
    4994                 :   // Pass in the default value, if any.
    4995               0 :   PRUnichar *inoutValue = ToNewUnicode(fixedInitial);
    4996               0 :   bool disallowDialog = false;
    4997                 : 
    4998               0 :   nsXPIDLString label;
    4999               0 :   if (shouldEnableDisableDialog) {
    5000                 :     nsContentUtils::GetLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES,
    5001               0 :                                        "ScriptDialogLabel", label);
    5002                 :   }
    5003                 : 
    5004                 :   bool ok;
    5005               0 :   rv = prompt->Prompt(title.get(), fixedMessage.get(),
    5006               0 :                       &inoutValue, label.get(), &disallowDialog, &ok);
    5007                 : 
    5008               0 :   if (disallowDialog) {
    5009               0 :     PreventFurtherDialogs();
    5010                 :   }
    5011                 : 
    5012               0 :   NS_ENSURE_SUCCESS(rv, rv);
    5013                 : 
    5014               0 :   nsAdoptingString outValue(inoutValue);
    5015                 : 
    5016               0 :   if (ok && outValue) {
    5017               0 :     aReturn.Assign(outValue);
    5018                 :   }
    5019                 : 
    5020               0 :   return rv;
    5021                 : }
    5022                 : 
    5023                 : NS_IMETHODIMP
    5024               0 : nsGlobalWindow::Focus()
    5025                 : {
    5026               0 :   FORWARD_TO_OUTER(Focus, (), NS_ERROR_NOT_INITIALIZED);
    5027                 : 
    5028               0 :   nsIFocusManager* fm = nsFocusManager::GetFocusManager();
    5029               0 :   if (!fm)
    5030               0 :     return NS_OK;
    5031                 : 
    5032               0 :   nsCOMPtr<nsIBaseWindow> baseWin = do_QueryInterface(mDocShell);
    5033                 : 
    5034               0 :   bool isVisible = false;
    5035               0 :   if (baseWin) {
    5036               0 :     baseWin->GetVisibility(&isVisible);
    5037                 :   }
    5038                 : 
    5039               0 :   if (!isVisible) {
    5040                 :     // A hidden tab is being focused, ignore this call.
    5041               0 :     return NS_OK;
    5042                 :   }
    5043                 : 
    5044               0 :   nsIDOMWindow *caller = nsContentUtils::GetWindowFromCaller();
    5045               0 :   nsCOMPtr<nsIDOMWindow> opener;
    5046               0 :   GetOpener(getter_AddRefs(opener));
    5047                 : 
    5048                 :   // Enforce dom.disable_window_flip (for non-chrome), but still allow the
    5049                 :   // window which opened us to raise us at times when popups are allowed
    5050                 :   // (bugs 355482 and 369306).
    5051               0 :   bool canFocus = CanSetProperty("dom.disable_window_flip") ||
    5052               0 :                     (opener == caller &&
    5053               0 :                      RevisePopupAbuseLevel(gPopupControlState) < openAbused);
    5054                 : 
    5055               0 :   nsCOMPtr<nsIDOMWindow> activeWindow;
    5056               0 :   fm->GetActiveWindow(getter_AddRefs(activeWindow));
    5057                 : 
    5058               0 :   nsCOMPtr<nsIDocShellTreeItem> treeItem = do_QueryInterface(mDocShell);
    5059               0 :   NS_ASSERTION(treeItem, "What happened?");
    5060               0 :   nsCOMPtr<nsIDocShellTreeItem> rootItem;
    5061               0 :   treeItem->GetRootTreeItem(getter_AddRefs(rootItem));
    5062               0 :   nsCOMPtr<nsIDOMWindow> rootWin = do_GetInterface(rootItem);
    5063               0 :   bool isActive = (rootWin == activeWindow);
    5064                 : 
    5065               0 :   nsCOMPtr<nsIBaseWindow> treeOwnerAsWin;
    5066               0 :   GetTreeOwner(getter_AddRefs(treeOwnerAsWin));
    5067               0 :   if (treeOwnerAsWin && (canFocus || isActive)) {
    5068               0 :     bool isEnabled = true;
    5069               0 :     if (NS_SUCCEEDED(treeOwnerAsWin->GetEnabled(&isEnabled)) && !isEnabled) {
    5070               0 :       NS_WARNING( "Should not try to set the focus on a disabled window" );
    5071               0 :       return NS_OK;
    5072                 :     }
    5073                 : 
    5074                 :     // XXXndeakin not sure what this is for or if it should go somewhere else
    5075               0 :     nsCOMPtr<nsIEmbeddingSiteWindow> embeddingWin(do_GetInterface(treeOwnerAsWin));
    5076               0 :     if (embeddingWin)
    5077               0 :       embeddingWin->SetFocus();
    5078                 :   }
    5079                 : 
    5080               0 :   if (!mDocShell)
    5081               0 :     return NS_OK;
    5082                 : 
    5083               0 :   nsCOMPtr<nsIPresShell> presShell;
    5084                 :   // Don't look for a presshell if we're a root chrome window that's got
    5085                 :   // about:blank loaded.  We don't want to focus our widget in that case.
    5086                 :   // XXXbz should we really be checking for IsInitialDocument() instead?
    5087               0 :   bool lookForPresShell = true;
    5088               0 :   PRInt32 itemType = nsIDocShellTreeItem::typeContent;
    5089               0 :   treeItem->GetItemType(&itemType);
    5090               0 :   if (itemType == nsIDocShellTreeItem::typeChrome &&
    5091               0 :       GetPrivateRoot() == static_cast<nsIDOMWindow*>(this) &&
    5092               0 :       mDocument) {
    5093               0 :     nsCOMPtr<nsIDocument> doc(do_QueryInterface(mDocument));
    5094               0 :     NS_ASSERTION(doc, "Bogus doc?");
    5095               0 :     nsIURI* ourURI = doc->GetDocumentURI();
    5096               0 :     if (ourURI) {
    5097               0 :       lookForPresShell = !NS_IsAboutBlank(ourURI);
    5098                 :     }
    5099                 :   }
    5100                 : 
    5101               0 :   if (lookForPresShell) {
    5102               0 :     mDocShell->GetEldestPresShell(getter_AddRefs(presShell));
    5103                 :   }
    5104                 : 
    5105               0 :   nsCOMPtr<nsIDocShellTreeItem> parentDsti;
    5106               0 :   treeItem->GetParent(getter_AddRefs(parentDsti));
    5107                 : 
    5108                 :   // set the parent's current focus to the frame containing this window.
    5109               0 :   nsCOMPtr<nsIDOMWindow> parent(do_GetInterface(parentDsti));
    5110               0 :   if (parent) {
    5111               0 :     nsCOMPtr<nsIDOMDocument> parentdomdoc;
    5112               0 :     parent->GetDocument(getter_AddRefs(parentdomdoc));
    5113                 : 
    5114               0 :     nsCOMPtr<nsIDocument> parentdoc = do_QueryInterface(parentdomdoc);
    5115               0 :     if (!parentdoc)
    5116               0 :       return NS_OK;
    5117                 : 
    5118               0 :     nsCOMPtr<nsIDocument> doc = do_QueryInterface(mDocument);
    5119               0 :     nsIContent* frame = parentdoc->FindContentForSubDocument(doc);
    5120               0 :     nsCOMPtr<nsIDOMElement> frameElement = do_QueryInterface(frame);
    5121               0 :     if (frameElement) {
    5122               0 :       PRUint32 flags = nsIFocusManager::FLAG_NOSCROLL;
    5123               0 :       if (canFocus)
    5124               0 :         flags |= nsIFocusManager::FLAG_RAISE;
    5125               0 :       return fm->SetFocus(frameElement, flags);
    5126                 :     }
    5127                 :   }
    5128               0 :   else if (canFocus) {
    5129                 :     // if there is no parent, this must be a toplevel window, so raise the
    5130                 :     // window if canFocus is true
    5131               0 :     return fm->SetActiveWindow(this);
    5132                 :   }
    5133                 : 
    5134               0 :   return NS_OK;
    5135                 : }
    5136                 : 
    5137                 : NS_IMETHODIMP
    5138               0 : nsGlobalWindow::Blur()
    5139                 : {
    5140               0 :   FORWARD_TO_OUTER(Blur, (), NS_ERROR_NOT_INITIALIZED);
    5141                 : 
    5142                 :   // If dom.disable_window_flip == true, then content should not be allowed
    5143                 :   // to call this function (this would allow popunders, bug 369306)
    5144               0 :   if (!CanSetProperty("dom.disable_window_flip")) {
    5145               0 :     return NS_OK;
    5146                 :   }
    5147                 : 
    5148                 :   // If embedding apps don't implement nsIEmbeddingSiteWindow2, we
    5149                 :   // shouldn't throw exceptions to web content.
    5150               0 :   nsresult rv = NS_OK;
    5151                 : 
    5152               0 :   nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
    5153               0 :   GetTreeOwner(getter_AddRefs(treeOwner));
    5154               0 :   nsCOMPtr<nsIEmbeddingSiteWindow2> siteWindow(do_GetInterface(treeOwner));
    5155               0 :   if (siteWindow) {
    5156                 :     // This method call may cause mDocShell to become nsnull.
    5157               0 :     rv = siteWindow->Blur();
    5158                 : 
    5159                 :     // if the root is focused, clear the focus
    5160               0 :     nsIFocusManager* fm = nsFocusManager::GetFocusManager();
    5161               0 :     nsCOMPtr<nsIDocument> doc = do_QueryInterface(mDocument);
    5162               0 :     if (fm && mDocument) {
    5163               0 :       nsCOMPtr<nsIDOMElement> element;
    5164               0 :       fm->GetFocusedElementForWindow(this, false, nsnull, getter_AddRefs(element));
    5165               0 :       nsCOMPtr<nsIContent> content = do_QueryInterface(element);
    5166               0 :       if (content == doc->GetRootElement())
    5167               0 :         fm->ClearFocus(this);
    5168                 :     }
    5169                 :   }
    5170                 : 
    5171               0 :   return rv;
    5172                 : }
    5173                 : 
    5174                 : NS_IMETHODIMP
    5175               0 : nsGlobalWindow::Back()
    5176                 : {
    5177               0 :   FORWARD_TO_OUTER(Back, (), NS_ERROR_NOT_INITIALIZED);
    5178                 : 
    5179               0 :   nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(mDocShell));
    5180               0 :   NS_ENSURE_TRUE(webNav, NS_ERROR_FAILURE);
    5181                 : 
    5182               0 :   return webNav->GoBack();
    5183                 : }
    5184                 : 
    5185                 : NS_IMETHODIMP
    5186               0 : nsGlobalWindow::Forward()
    5187                 : {
    5188               0 :   FORWARD_TO_OUTER(Forward, (), NS_ERROR_NOT_INITIALIZED);
    5189                 : 
    5190               0 :   nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(mDocShell));
    5191               0 :   NS_ENSURE_TRUE(webNav, NS_ERROR_FAILURE);
    5192                 : 
    5193               0 :   return webNav->GoForward();
    5194                 : }
    5195                 : 
    5196                 : NS_IMETHODIMP
    5197               0 : nsGlobalWindow::Home()
    5198                 : {
    5199               0 :   FORWARD_TO_OUTER(Home, (), NS_ERROR_NOT_INITIALIZED);
    5200                 : 
    5201               0 :   if (!mDocShell)
    5202               0 :     return NS_OK;
    5203                 : 
    5204                 :   nsAdoptingString homeURL =
    5205               0 :     Preferences::GetLocalizedString(PREF_BROWSER_STARTUP_HOMEPAGE);
    5206                 : 
    5207               0 :   if (homeURL.IsEmpty()) {
    5208                 :     // if all else fails, use this
    5209                 : #ifdef DEBUG_seth
    5210                 :     printf("all else failed.  using %s as the home page\n", DEFAULT_HOME_PAGE);
    5211                 : #endif
    5212               0 :     CopyASCIItoUTF16(DEFAULT_HOME_PAGE, homeURL);
    5213                 :   }
    5214                 : 
    5215                 : #ifdef MOZ_PHOENIX
    5216                 :   {
    5217                 :     // Firefox lets the user specify multiple home pages to open in
    5218                 :     // individual tabs by separating them with '|'. Since we don't
    5219                 :     // have the machinery in place to easily open new tabs from here,
    5220                 :     // simply truncate the homeURL at the first '|' character to
    5221                 :     // prevent any possibilities of leaking the users list of home
    5222                 :     // pages to the first home page.
    5223                 :     //
    5224                 :     // Once bug https://bugzilla.mozilla.org/show_bug.cgi?id=221445 is
    5225                 :     // fixed we can revisit this.
    5226               0 :     PRInt32 firstPipe = homeURL.FindChar('|');
    5227                 : 
    5228               0 :     if (firstPipe > 0) {
    5229               0 :       homeURL.Truncate(firstPipe);
    5230                 :     }
    5231                 :   }
    5232                 : #endif
    5233                 : 
    5234                 :   nsresult rv;
    5235               0 :   nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(mDocShell));
    5236               0 :   NS_ENSURE_TRUE(webNav, NS_ERROR_FAILURE);
    5237               0 :   rv = webNav->LoadURI(homeURL.get(),
    5238                 :                        nsIWebNavigation::LOAD_FLAGS_NONE,
    5239                 :                        nsnull,
    5240                 :                        nsnull,
    5241               0 :                        nsnull);
    5242               0 :   NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
    5243               0 :   return NS_OK;
    5244                 : }
    5245                 : 
    5246                 : NS_IMETHODIMP
    5247               0 : nsGlobalWindow::Stop()
    5248                 : {
    5249               0 :   FORWARD_TO_OUTER(Stop, (), NS_ERROR_NOT_INITIALIZED);
    5250                 : 
    5251               0 :   nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(mDocShell));
    5252               0 :   if (!webNav)
    5253               0 :     return NS_OK;
    5254                 : 
    5255               0 :   return webNav->Stop(nsIWebNavigation::STOP_ALL);
    5256                 : }
    5257                 : 
    5258                 : NS_IMETHODIMP
    5259               0 : nsGlobalWindow::Print()
    5260                 : {
    5261                 : #ifdef NS_PRINTING
    5262               0 :   FORWARD_TO_OUTER(Print, (), NS_ERROR_NOT_INITIALIZED);
    5263                 : 
    5264               0 :   if (AreDialogsBlocked() || !ConfirmDialogAllowed())
    5265               0 :     return NS_ERROR_NOT_AVAILABLE;
    5266                 : 
    5267               0 :   nsCOMPtr<nsIWebBrowserPrint> webBrowserPrint;
    5268               0 :   if (NS_SUCCEEDED(GetInterface(NS_GET_IID(nsIWebBrowserPrint),
    5269                 :                                 getter_AddRefs(webBrowserPrint)))) {
    5270                 : 
    5271                 :     nsCOMPtr<nsIPrintSettingsService> printSettingsService = 
    5272               0 :       do_GetService("@mozilla.org/gfx/printsettings-service;1");
    5273                 : 
    5274               0 :     nsCOMPtr<nsIPrintSettings> printSettings;
    5275               0 :     if (printSettingsService) {
    5276                 :       bool printSettingsAreGlobal =
    5277               0 :         Preferences::GetBool("print.use_global_printsettings", false);
    5278                 : 
    5279               0 :       if (printSettingsAreGlobal) {
    5280               0 :         printSettingsService->GetGlobalPrintSettings(getter_AddRefs(printSettings));
    5281                 : 
    5282               0 :         nsXPIDLString printerName;
    5283               0 :         printSettings->GetPrinterName(getter_Copies(printerName));
    5284               0 :         if (printerName.IsEmpty()) {
    5285               0 :           printSettingsService->GetDefaultPrinterName(getter_Copies(printerName));
    5286               0 :           printSettings->SetPrinterName(printerName);
    5287                 :         }
    5288               0 :         printSettingsService->InitPrintSettingsFromPrinter(printerName, printSettings);
    5289               0 :         printSettingsService->InitPrintSettingsFromPrefs(printSettings, 
    5290                 :                                                          true, 
    5291               0 :                                                          nsIPrintSettings::kInitSaveAll);
    5292                 :       } else {
    5293               0 :         printSettingsService->GetNewPrintSettings(getter_AddRefs(printSettings));
    5294                 :       }
    5295                 : 
    5296               0 :       nsCOMPtr<nsIDOMWindow> callerWin = EnterModalState();
    5297               0 :       webBrowserPrint->Print(printSettings, nsnull);
    5298               0 :       LeaveModalState(callerWin);
    5299                 : 
    5300                 :       bool savePrintSettings =
    5301               0 :         Preferences::GetBool("print.save_print_settings", false);
    5302               0 :       if (printSettingsAreGlobal && savePrintSettings) {
    5303               0 :         printSettingsService->
    5304                 :           SavePrintSettingsToPrefs(printSettings,
    5305                 :                                    true,
    5306               0 :                                    nsIPrintSettings::kInitSaveAll);
    5307               0 :         printSettingsService->
    5308                 :           SavePrintSettingsToPrefs(printSettings,
    5309                 :                                    false,
    5310               0 :                                    nsIPrintSettings::kInitSavePrinterName);
    5311                 :       }
    5312                 :     } else {
    5313               0 :       webBrowserPrint->GetGlobalPrintSettings(getter_AddRefs(printSettings));
    5314               0 :       webBrowserPrint->Print(printSettings, nsnull);
    5315                 :     }
    5316                 :   }
    5317                 : #endif //NS_PRINTING
    5318                 : 
    5319               0 :   return NS_OK;
    5320                 : }
    5321                 : 
    5322                 : NS_IMETHODIMP
    5323               0 : nsGlobalWindow::MoveTo(PRInt32 aXPos, PRInt32 aYPos)
    5324                 : {
    5325               0 :   FORWARD_TO_OUTER(MoveTo, (aXPos, aYPos), NS_ERROR_NOT_INITIALIZED);
    5326                 : 
    5327                 :   /*
    5328                 :    * If caller is not chrome and the user has not explicitly exempted the site,
    5329                 :    * prevent window.moveTo() by exiting early
    5330                 :    */
    5331                 : 
    5332               0 :   if (!CanMoveResizeWindows() || IsFrame()) {
    5333               0 :     return NS_OK;
    5334                 :   }
    5335                 : 
    5336               0 :   nsCOMPtr<nsIBaseWindow> treeOwnerAsWin;
    5337               0 :   GetTreeOwner(getter_AddRefs(treeOwnerAsWin));
    5338               0 :   NS_ENSURE_TRUE(treeOwnerAsWin, NS_ERROR_FAILURE);
    5339                 : 
    5340               0 :   NS_ENSURE_SUCCESS(CheckSecurityLeftAndTop(&aXPos, &aYPos),
    5341                 :                     NS_ERROR_FAILURE);
    5342                 : 
    5343                 :   // mild abuse of a "size" object so we don't need more helper functions
    5344               0 :   nsIntSize devPos(CSSToDevIntPixels(nsIntSize(aXPos, aYPos)));
    5345                 : 
    5346               0 :   NS_ENSURE_SUCCESS(treeOwnerAsWin->SetPosition(devPos.width, devPos.height),
    5347                 :                     NS_ERROR_FAILURE);
    5348                 : 
    5349               0 :   return NS_OK;
    5350                 : }
    5351                 : 
    5352                 : NS_IMETHODIMP
    5353               0 : nsGlobalWindow::MoveBy(PRInt32 aXDif, PRInt32 aYDif)
    5354                 : {
    5355               0 :   FORWARD_TO_OUTER(MoveBy, (aXDif, aYDif), NS_ERROR_NOT_INITIALIZED);
    5356                 : 
    5357                 :   /*
    5358                 :    * If caller is not chrome and the user has not explicitly exempted the site,
    5359                 :    * prevent window.moveBy() by exiting early
    5360                 :    */
    5361                 : 
    5362               0 :   if (!CanMoveResizeWindows() || IsFrame()) {
    5363               0 :     return NS_OK;
    5364                 :   }
    5365                 : 
    5366               0 :   nsCOMPtr<nsIBaseWindow> treeOwnerAsWin;
    5367               0 :   GetTreeOwner(getter_AddRefs(treeOwnerAsWin));
    5368               0 :   NS_ENSURE_TRUE(treeOwnerAsWin, NS_ERROR_FAILURE);
    5369                 : 
    5370                 :   // To do this correctly we have to convert what we get from GetPosition
    5371                 :   // into CSS pixels, add the arguments, do the security check, and
    5372                 :   // then convert back to device pixels for the call to SetPosition.
    5373                 : 
    5374                 :   PRInt32 x, y;
    5375               0 :   NS_ENSURE_SUCCESS(treeOwnerAsWin->GetPosition(&x, &y), NS_ERROR_FAILURE);
    5376                 : 
    5377                 :   // mild abuse of a "size" object so we don't need more helper functions
    5378               0 :   nsIntSize cssPos(DevToCSSIntPixels(nsIntSize(x, y)));
    5379                 : 
    5380               0 :   cssPos.width += aXDif;
    5381               0 :   cssPos.height += aYDif;
    5382                 :   
    5383               0 :   NS_ENSURE_SUCCESS(CheckSecurityLeftAndTop(&cssPos.width,
    5384                 :                                             &cssPos.height),
    5385                 :                     NS_ERROR_FAILURE);
    5386                 : 
    5387               0 :   nsIntSize newDevPos(CSSToDevIntPixels(cssPos));
    5388                 : 
    5389               0 :   NS_ENSURE_SUCCESS(treeOwnerAsWin->SetPosition(newDevPos.width,
    5390                 :                                                 newDevPos.height),
    5391                 :                     NS_ERROR_FAILURE);
    5392                 : 
    5393               0 :   return NS_OK;
    5394                 : }
    5395                 : 
    5396                 : NS_IMETHODIMP
    5397               0 : nsGlobalWindow::ResizeTo(PRInt32 aWidth, PRInt32 aHeight)
    5398                 : {
    5399               0 :   FORWARD_TO_OUTER(ResizeTo, (aWidth, aHeight), NS_ERROR_NOT_INITIALIZED);
    5400                 : 
    5401                 :   /*
    5402                 :    * If caller is not chrome and the user has not explicitly exempted the site,
    5403                 :    * prevent window.resizeTo() by exiting early
    5404                 :    */
    5405                 : 
    5406               0 :   if (!CanMoveResizeWindows() || IsFrame()) {
    5407               0 :     return NS_OK;
    5408                 :   }
    5409                 : 
    5410               0 :   nsCOMPtr<nsIBaseWindow> treeOwnerAsWin;
    5411               0 :   GetTreeOwner(getter_AddRefs(treeOwnerAsWin));
    5412               0 :   NS_ENSURE_TRUE(treeOwnerAsWin, NS_ERROR_FAILURE);
    5413                 :   
    5414               0 :   NS_ENSURE_SUCCESS(CheckSecurityWidthAndHeight(&aWidth, &aHeight),
    5415                 :                     NS_ERROR_FAILURE);
    5416                 : 
    5417               0 :   nsIntSize devSz(CSSToDevIntPixels(nsIntSize(aWidth, aHeight)));
    5418                 : 
    5419               0 :   NS_ENSURE_SUCCESS(treeOwnerAsWin->SetSize(devSz.width, devSz.height, true),
    5420                 :                     NS_ERROR_FAILURE);
    5421                 : 
    5422               0 :   return NS_OK;
    5423                 : }
    5424                 : 
    5425                 : NS_IMETHODIMP
    5426               0 : nsGlobalWindow::ResizeBy(PRInt32 aWidthDif, PRInt32 aHeightDif)
    5427                 : {
    5428               0 :   FORWARD_TO_OUTER(ResizeBy, (aWidthDif, aHeightDif), NS_ERROR_NOT_INITIALIZED);
    5429                 : 
    5430                 :   /*
    5431                 :    * If caller is not chrome and the user has not explicitly exempted the site,
    5432                 :    * prevent window.resizeBy() by exiting early
    5433                 :    */
    5434                 : 
    5435               0 :   if (!CanMoveResizeWindows() || IsFrame()) {
    5436               0 :     return NS_OK;
    5437                 :   }
    5438                 : 
    5439               0 :   nsCOMPtr<nsIBaseWindow> treeOwnerAsWin;
    5440               0 :   GetTreeOwner(getter_AddRefs(treeOwnerAsWin));
    5441               0 :   NS_ENSURE_TRUE(treeOwnerAsWin, NS_ERROR_FAILURE);
    5442                 : 
    5443                 :   PRInt32 width, height;
    5444               0 :   NS_ENSURE_SUCCESS(treeOwnerAsWin->GetSize(&width, &height), NS_ERROR_FAILURE);
    5445                 : 
    5446                 :   // To do this correctly we have to convert what we got from GetSize
    5447                 :   // into CSS pixels, add the arguments, do the security check, and
    5448                 :   // then convert back to device pixels for the call to SetSize.
    5449                 : 
    5450               0 :   nsIntSize cssSize(DevToCSSIntPixels(nsIntSize(width, height)));
    5451                 : 
    5452               0 :   cssSize.width += aWidthDif;
    5453               0 :   cssSize.height += aHeightDif;
    5454                 : 
    5455               0 :   NS_ENSURE_SUCCESS(CheckSecurityWidthAndHeight(&cssSize.width,
    5456                 :                                                 &cssSize.height),
    5457                 :                     NS_ERROR_FAILURE);
    5458                 : 
    5459               0 :   nsIntSize newDevSize(CSSToDevIntPixels(cssSize));
    5460                 : 
    5461               0 :   NS_ENSURE_SUCCESS(treeOwnerAsWin->SetSize(newDevSize.width,
    5462                 :                                             newDevSize.height,
    5463                 :                                             true),
    5464                 :                     NS_ERROR_FAILURE);
    5465                 : 
    5466               0 :   return NS_OK;
    5467                 : }
    5468                 : 
    5469                 : NS_IMETHODIMP
    5470               0 : nsGlobalWindow::SizeToContent()
    5471                 : {
    5472               0 :   FORWARD_TO_OUTER(SizeToContent, (), NS_ERROR_NOT_INITIALIZED);
    5473                 : 
    5474               0 :   if (!mDocShell) {
    5475               0 :     return NS_OK;
    5476                 :   }
    5477                 : 
    5478                 :   /*
    5479                 :    * If caller is not chrome and the user has not explicitly exempted the site,
    5480                 :    * prevent window.sizeToContent() by exiting early
    5481                 :    */
    5482                 : 
    5483               0 :   if (!CanMoveResizeWindows() || IsFrame()) {
    5484               0 :     return NS_OK;
    5485                 :   }
    5486                 : 
    5487                 :   // The content viewer does a check to make sure that it's a content
    5488                 :   // viewer for a toplevel docshell.
    5489                 :   
    5490               0 :   nsCOMPtr<nsIContentViewer> cv;
    5491               0 :   mDocShell->GetContentViewer(getter_AddRefs(cv));
    5492               0 :   nsCOMPtr<nsIMarkupDocumentViewer> markupViewer(do_QueryInterface(cv));
    5493               0 :   NS_ENSURE_TRUE(markupViewer, NS_ERROR_FAILURE);
    5494               0 :   NS_ENSURE_SUCCESS(markupViewer->SizeToContent(), NS_ERROR_FAILURE);
    5495                 : 
    5496               0 :   return NS_OK;
    5497                 : }
    5498                 : 
    5499                 : NS_IMETHODIMP
    5500               0 : nsGlobalWindow::GetWindowRoot(nsIDOMEventTarget **aWindowRoot)
    5501                 : {
    5502               0 :   nsCOMPtr<nsPIWindowRoot> root = GetTopWindowRoot();
    5503               0 :   return CallQueryInterface(root, aWindowRoot);
    5504                 : }
    5505                 : 
    5506                 : already_AddRefed<nsPIWindowRoot>
    5507               0 : nsGlobalWindow::GetTopWindowRoot()
    5508                 : {
    5509               0 :   nsIDOMWindow *rootWindow = GetPrivateRoot();
    5510               0 :   nsCOMPtr<nsPIDOMWindow> piWin(do_QueryInterface(rootWindow));
    5511               0 :   if (!piWin)
    5512               0 :     return nsnull;
    5513                 : 
    5514               0 :   nsCOMPtr<nsPIWindowRoot> window = do_QueryInterface(piWin->GetChromeEventHandler());
    5515               0 :   return window.forget();
    5516                 : }
    5517                 : 
    5518                 : NS_IMETHODIMP
    5519               0 : nsGlobalWindow::Scroll(PRInt32 aXScroll, PRInt32 aYScroll)
    5520                 : {
    5521               0 :   return ScrollTo(aXScroll, aYScroll);
    5522                 : }
    5523                 : 
    5524                 : NS_IMETHODIMP
    5525               0 : nsGlobalWindow::ScrollTo(PRInt32 aXScroll, PRInt32 aYScroll)
    5526                 : {
    5527               0 :   FlushPendingNotifications(Flush_Layout);
    5528               0 :   nsIScrollableFrame *sf = GetScrollFrame();
    5529                 : 
    5530               0 :   if (sf) {
    5531                 :     // Here we calculate what the max pixel value is that we can
    5532                 :     // scroll to, we do this by dividing maxint with the pixel to
    5533                 :     // twips conversion factor, and substracting 4, the 4 comes from
    5534                 :     // experimenting with this value, anything less makes the view
    5535                 :     // code not scroll correctly, I have no idea why. -- jst
    5536               0 :     const PRInt32 maxpx = nsPresContext::AppUnitsToIntCSSPixels(0x7fffffff) - 4;
    5537                 : 
    5538               0 :     if (aXScroll > maxpx) {
    5539               0 :       aXScroll = maxpx;
    5540                 :     }
    5541                 : 
    5542               0 :     if (aYScroll > maxpx) {
    5543               0 :       aYScroll = maxpx;
    5544                 :     }
    5545                 :     sf->ScrollTo(nsPoint(nsPresContext::CSSPixelsToAppUnits(aXScroll),
    5546                 :                          nsPresContext::CSSPixelsToAppUnits(aYScroll)),
    5547               0 :                  nsIScrollableFrame::INSTANT);
    5548                 :   }
    5549                 : 
    5550               0 :   return NS_OK;
    5551                 : }
    5552                 : 
    5553                 : NS_IMETHODIMP
    5554               0 : nsGlobalWindow::ScrollBy(PRInt32 aXScrollDif, PRInt32 aYScrollDif)
    5555                 : {
    5556               0 :   FlushPendingNotifications(Flush_Layout);
    5557               0 :   nsIScrollableFrame *sf = GetScrollFrame();
    5558                 : 
    5559               0 :   if (sf) {
    5560               0 :     nsPoint scrollPos = sf->GetScrollPosition();
    5561                 :     // It seems like it would make more sense for ScrollBy to use
    5562                 :     // SMOOTH mode, but tests seem to depend on the synchronous behaviour.
    5563                 :     // Perhaps Web content does too.
    5564               0 :     return ScrollTo(nsPresContext::AppUnitsToIntCSSPixels(scrollPos.x) + aXScrollDif,
    5565               0 :                     nsPresContext::AppUnitsToIntCSSPixels(scrollPos.y) + aYScrollDif);
    5566                 :   }
    5567                 : 
    5568               0 :   return NS_OK;
    5569                 : }
    5570                 : 
    5571                 : NS_IMETHODIMP
    5572               0 : nsGlobalWindow::ScrollByLines(PRInt32 numLines)
    5573                 : {
    5574               0 :   FlushPendingNotifications(Flush_Layout);
    5575               0 :   nsIScrollableFrame *sf = GetScrollFrame();
    5576               0 :   if (sf) {
    5577                 :     // It seems like it would make more sense for ScrollByLines to use
    5578                 :     // SMOOTH mode, but tests seem to depend on the synchronous behaviour.
    5579                 :     // Perhaps Web content does too.
    5580                 :     sf->ScrollBy(nsIntPoint(0, numLines), nsIScrollableFrame::LINES,
    5581               0 :                  nsIScrollableFrame::INSTANT);
    5582                 :   }
    5583                 : 
    5584               0 :   return NS_OK;
    5585                 : }
    5586                 : 
    5587                 : NS_IMETHODIMP
    5588               0 : nsGlobalWindow::ScrollByPages(PRInt32 numPages)
    5589                 : {
    5590               0 :   FlushPendingNotifications(Flush_Layout);
    5591               0 :   nsIScrollableFrame *sf = GetScrollFrame();
    5592               0 :   if (sf) {
    5593                 :     // It seems like it would make more sense for ScrollByPages to use
    5594                 :     // SMOOTH mode, but tests seem to depend on the synchronous behaviour.
    5595                 :     // Perhaps Web content does too.
    5596                 :     sf->ScrollBy(nsIntPoint(0, numPages), nsIScrollableFrame::PAGES,
    5597               0 :                  nsIScrollableFrame::INSTANT);
    5598                 :   }
    5599                 : 
    5600               0 :   return NS_OK;
    5601                 : }
    5602                 : 
    5603                 : NS_IMETHODIMP
    5604               0 : nsGlobalWindow::ClearTimeout(PRInt32 aHandle)
    5605                 : {
    5606               0 :   if (aHandle <= 0) {
    5607               0 :     return NS_OK;
    5608                 :   }
    5609                 : 
    5610               0 :   return ClearTimeoutOrInterval(aHandle);
    5611                 : }
    5612                 : 
    5613                 : NS_IMETHODIMP
    5614               0 : nsGlobalWindow::ClearInterval(PRInt32 aHandle)
    5615                 : {
    5616               0 :   if (aHandle <= 0) {
    5617               0 :     return NS_OK;
    5618                 :   }
    5619                 : 
    5620               0 :   return ClearTimeoutOrInterval(aHandle);
    5621                 : }
    5622                 : 
    5623                 : NS_IMETHODIMP
    5624               0 : nsGlobalWindow::SetTimeout(PRInt32 *_retval)
    5625                 : {
    5626               0 :   return SetTimeoutOrInterval(false, _retval);
    5627                 : }
    5628                 : 
    5629                 : NS_IMETHODIMP
    5630               0 : nsGlobalWindow::SetInterval(PRInt32 *_retval)
    5631                 : {
    5632               0 :   return SetTimeoutOrInterval(true, _retval);
    5633                 : }
    5634                 : 
    5635                 : NS_IMETHODIMP
    5636               0 : nsGlobalWindow::SetResizable(bool aResizable)
    5637                 : {
    5638                 :   // nop
    5639                 : 
    5640               0 :   return NS_OK;
    5641                 : }
    5642                 : 
    5643                 : static void
    5644               0 : ReportUseOfDeprecatedMethod(nsGlobalWindow* aWindow, const char* aWarning)
    5645                 : {
    5646               0 :   nsCOMPtr<nsIDocument> doc = do_QueryInterface(aWindow->GetExtantDocument());
    5647                 :   nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
    5648                 :                                   "DOM Events", doc,
    5649                 :                                   nsContentUtils::eDOM_PROPERTIES,
    5650               0 :                                   aWarning);
    5651               0 : }
    5652                 : 
    5653                 : NS_IMETHODIMP
    5654               0 : nsGlobalWindow::CaptureEvents(PRInt32 aEventFlags)
    5655                 : {
    5656               0 :   ReportUseOfDeprecatedMethod(this, "UseOfCaptureEventsWarning");
    5657               0 :   return NS_OK;
    5658                 : }
    5659                 : 
    5660                 : NS_IMETHODIMP
    5661               0 : nsGlobalWindow::ReleaseEvents(PRInt32 aEventFlags)
    5662                 : {
    5663               0 :   ReportUseOfDeprecatedMethod(this, "UseOfReleaseEventsWarning");
    5664               0 :   return NS_OK;
    5665                 : }
    5666                 : 
    5667                 : NS_IMETHODIMP
    5668               0 : nsGlobalWindow::RouteEvent(nsIDOMEvent* aEvt)
    5669                 : {
    5670               0 :   ReportUseOfDeprecatedMethod(this, "UseOfRouteEventWarning");
    5671               0 :   return NS_OK;
    5672                 : }
    5673                 : 
    5674                 : NS_IMETHODIMP
    5675               0 : nsGlobalWindow::EnableExternalCapture()
    5676                 : {
    5677               0 :   return NS_ERROR_FAILURE;
    5678                 : }
    5679                 : 
    5680                 : NS_IMETHODIMP
    5681               0 : nsGlobalWindow::DisableExternalCapture()
    5682                 : {
    5683               0 :   return NS_ERROR_FAILURE;
    5684                 : }
    5685                 : 
    5686                 : static
    5687               0 : bool IsPopupBlocked(nsIDOMDocument* aDoc)
    5688                 : {
    5689                 :   nsCOMPtr<nsIPopupWindowManager> pm =
    5690               0 :     do_GetService(NS_POPUPWINDOWMANAGER_CONTRACTID);
    5691                 : 
    5692               0 :   if (!pm) {
    5693               0 :     return false;
    5694                 :   }
    5695                 : 
    5696               0 :   bool blocked = true;
    5697               0 :   nsCOMPtr<nsIDocument> doc(do_QueryInterface(aDoc));
    5698                 : 
    5699               0 :   if (doc) {
    5700               0 :     PRUint32 permission = nsIPopupWindowManager::ALLOW_POPUP;
    5701               0 :     pm->TestPermission(doc->GetDocumentURI(), &permission);
    5702               0 :     blocked = (permission == nsIPopupWindowManager::DENY_POPUP);
    5703                 :   }
    5704               0 :   return blocked;
    5705                 : }
    5706                 : 
    5707                 : /* static */
    5708                 : void 
    5709               0 : nsGlobalWindow::FirePopupBlockedEvent(nsIDOMDocument* aDoc,
    5710                 :                                       nsIDOMWindow *aRequestingWindow, nsIURI *aPopupURI,
    5711                 :                                       const nsAString &aPopupWindowName,
    5712                 :                                       const nsAString &aPopupWindowFeatures)
    5713                 : {
    5714               0 :   if (aDoc) {
    5715                 :     // Fire a "DOMPopupBlocked" event so that the UI can hear about
    5716                 :     // blocked popups.
    5717               0 :     nsCOMPtr<nsIDOMEvent> event;
    5718               0 :     aDoc->CreateEvent(NS_LITERAL_STRING("PopupBlockedEvents"),
    5719               0 :                       getter_AddRefs(event));
    5720               0 :     if (event) {
    5721               0 :       nsCOMPtr<nsIDOMPopupBlockedEvent> pbev(do_QueryInterface(event));
    5722               0 :       pbev->InitPopupBlockedEvent(NS_LITERAL_STRING("DOMPopupBlocked"),
    5723                 :                                   true, true, aRequestingWindow,
    5724                 :                                   aPopupURI, aPopupWindowName,
    5725               0 :                                   aPopupWindowFeatures);
    5726               0 :       nsCOMPtr<nsIPrivateDOMEvent> privateEvent(do_QueryInterface(event));
    5727               0 :       privateEvent->SetTrusted(true);
    5728                 : 
    5729               0 :       nsCOMPtr<nsIDOMEventTarget> targ(do_QueryInterface(aDoc));
    5730                 :       bool defaultActionEnabled;
    5731               0 :       targ->DispatchEvent(event, &defaultActionEnabled);
    5732                 :     }
    5733                 :   }
    5734               0 : }
    5735                 : 
    5736               0 : void FirePopupWindowEvent(nsIDOMDocument* aDoc)
    5737                 : {
    5738                 :   // Fire a "PopupWindow" event
    5739               0 :   nsCOMPtr<nsIDocument> doc(do_QueryInterface(aDoc));
    5740                 :   nsContentUtils::DispatchTrustedEvent(doc, aDoc,
    5741               0 :                                        NS_LITERAL_STRING("PopupWindow"),
    5742               0 :                                        true, true);
    5743               0 : }
    5744                 : 
    5745                 : // static
    5746                 : bool
    5747               0 : nsGlobalWindow::CanSetProperty(const char *aPrefName)
    5748                 : {
    5749                 :   // Chrome can set any property.
    5750               0 :   if (nsContentUtils::IsCallerTrustedForWrite()) {
    5751               0 :     return true;
    5752                 :   }
    5753                 : 
    5754                 :   // If the pref is set to true, we can not set the property
    5755                 :   // and vice versa.
    5756               0 :   return !Preferences::GetBool(aPrefName, true);
    5757                 : }
    5758                 : 
    5759                 : bool
    5760               0 : nsGlobalWindow::PopupWhitelisted()
    5761                 : {
    5762               0 :   if (!IsPopupBlocked(mDocument))
    5763               0 :     return true;
    5764                 : 
    5765               0 :   nsCOMPtr<nsIDOMWindow> parent;
    5766                 : 
    5767               0 :   if (NS_FAILED(GetParent(getter_AddRefs(parent))) ||
    5768               0 :       parent == static_cast<nsIDOMWindow*>(this))
    5769                 :   {
    5770               0 :     return false;
    5771                 :   }
    5772                 : 
    5773                 :   return static_cast<nsGlobalWindow*>
    5774                 :                     (static_cast<nsIDOMWindow*>
    5775               0 :                                 (parent.get()))->PopupWhitelisted();
    5776                 : }
    5777                 : 
    5778                 : /*
    5779                 :  * Examine the current document state to see if we're in a way that is
    5780                 :  * typically abused by web designers. The window.open code uses this
    5781                 :  * routine to determine whether to allow the new window.
    5782                 :  * Returns a value from the PopupControlState enum.
    5783                 :  */
    5784                 : PopupControlState
    5785               0 : nsGlobalWindow::RevisePopupAbuseLevel(PopupControlState aControl)
    5786                 : {
    5787               0 :   FORWARD_TO_OUTER(RevisePopupAbuseLevel, (aControl), aControl);
    5788                 : 
    5789               0 :   NS_ASSERTION(mDocShell, "Must have docshell");
    5790                 :   
    5791               0 :   nsCOMPtr<nsIDocShellTreeItem> item(do_QueryInterface(mDocShell));
    5792                 : 
    5793               0 :   NS_ASSERTION(item, "Docshell doesn't implement nsIDocShellTreeItem?");
    5794                 : 
    5795               0 :   PRInt32 type = nsIDocShellTreeItem::typeChrome;
    5796               0 :   item->GetItemType(&type);
    5797               0 :   if (type != nsIDocShellTreeItem::typeContent)
    5798               0 :     return openAllowed;
    5799                 : 
    5800               0 :   PopupControlState abuse = aControl;
    5801               0 :   switch (abuse) {
    5802                 :   case openControlled:
    5803                 :   case openAbused:
    5804                 :   case openOverridden:
    5805               0 :     if (PopupWhitelisted())
    5806               0 :       abuse = PopupControlState(abuse - 1);
    5807               0 :   case openAllowed: break;
    5808                 :   default:
    5809               0 :     NS_WARNING("Strange PopupControlState!");
    5810                 :   }
    5811                 : 
    5812                 :   // limit the number of simultaneously open popups
    5813               0 :   if (abuse == openAbused || abuse == openControlled) {
    5814               0 :     PRInt32 popupMax = Preferences::GetInt("dom.popup_maximum", -1);
    5815               0 :     if (popupMax >= 0 && gOpenPopupSpamCount >= popupMax)
    5816               0 :       abuse = openOverridden;
    5817                 :   }
    5818                 : 
    5819               0 :   return abuse;
    5820                 : }
    5821                 : 
    5822                 : /* If a window open is blocked, fire the appropriate DOM events.
    5823                 :    aBlocked signifies we just blocked a popup.
    5824                 :    aWindow signifies we just opened what is probably a popup.
    5825                 : */
    5826                 : void
    5827               0 : nsGlobalWindow::FireAbuseEvents(bool aBlocked, bool aWindow,
    5828                 :                                 const nsAString &aPopupURL,
    5829                 :                                 const nsAString &aPopupWindowName,
    5830                 :                                 const nsAString &aPopupWindowFeatures)
    5831                 : {
    5832                 :   // fetch the URI of the window requesting the opened window
    5833                 : 
    5834               0 :   nsCOMPtr<nsIDOMWindow> topWindow;
    5835               0 :   GetTop(getter_AddRefs(topWindow));
    5836               0 :   if (!topWindow)
    5837                 :     return;
    5838                 : 
    5839               0 :   nsCOMPtr<nsIDOMDocument> topDoc;
    5840               0 :   topWindow->GetDocument(getter_AddRefs(topDoc));
    5841                 : 
    5842               0 :   nsCOMPtr<nsIURI> popupURI;
    5843                 : 
    5844                 :   // build the URI of the would-have-been popup window
    5845                 :   // (see nsWindowWatcher::URIfromURL)
    5846                 : 
    5847                 :   // first, fetch the opener's base URI
    5848                 : 
    5849               0 :   nsIURI *baseURL = 0;
    5850                 : 
    5851               0 :   JSContext *cx = nsContentUtils::GetCurrentJSContext();
    5852               0 :   nsCOMPtr<nsIDOMWindow> contextWindow;
    5853                 : 
    5854               0 :   if (cx) {
    5855               0 :     nsIScriptContext *currentCX = nsJSUtils::GetDynamicScriptContext(cx);
    5856               0 :     if (currentCX) {
    5857               0 :       contextWindow = do_QueryInterface(currentCX->GetGlobalObject());
    5858                 :     }
    5859                 :   }
    5860               0 :   if (!contextWindow)
    5861               0 :     contextWindow = static_cast<nsIDOMWindow*>(this);
    5862                 : 
    5863               0 :   nsCOMPtr<nsIDOMDocument> domdoc;
    5864               0 :   contextWindow->GetDocument(getter_AddRefs(domdoc));
    5865               0 :   nsCOMPtr<nsIDocument> doc(do_QueryInterface(domdoc));
    5866               0 :   if (doc)
    5867               0 :     baseURL = doc->GetDocBaseURI();
    5868                 : 
    5869                 :   // use the base URI to build what would have been the popup's URI
    5870               0 :   nsCOMPtr<nsIIOService> ios(do_GetService(NS_IOSERVICE_CONTRACTID));
    5871               0 :   if (ios)
    5872               0 :     ios->NewURI(NS_ConvertUTF16toUTF8(aPopupURL), 0, baseURL,
    5873               0 :                 getter_AddRefs(popupURI));
    5874                 : 
    5875                 :   // fire an event chock full of informative URIs
    5876               0 :   if (aBlocked)
    5877                 :     FirePopupBlockedEvent(topDoc, this, popupURI, aPopupWindowName,
    5878               0 :                           aPopupWindowFeatures);
    5879               0 :   if (aWindow)
    5880               0 :     FirePopupWindowEvent(topDoc);
    5881                 : }
    5882                 : 
    5883                 : NS_IMETHODIMP
    5884               0 : nsGlobalWindow::Open(const nsAString& aUrl, const nsAString& aName,
    5885                 :                      const nsAString& aOptions, nsIDOMWindow **_retval)
    5886                 : {
    5887                 :   return OpenInternal(aUrl, aName, aOptions,
    5888                 :                       false,          // aDialog
    5889                 :                       false,          // aContentModal
    5890                 :                       true,           // aCalledNoScript
    5891                 :                       false,          // aDoJSFixups
    5892                 :                       nsnull, nsnull,    // No args
    5893               0 :                       GetPrincipal(),    // aCalleePrincipal
    5894                 :                       nsnull,            // aJSCallerContext
    5895               0 :                       _retval);
    5896                 : }
    5897                 : 
    5898                 : NS_IMETHODIMP
    5899               0 : nsGlobalWindow::OpenJS(const nsAString& aUrl, const nsAString& aName,
    5900                 :                        const nsAString& aOptions, nsIDOMWindow **_retval)
    5901                 : {
    5902                 :   return OpenInternal(aUrl, aName, aOptions,
    5903                 :                       false,          // aDialog
    5904                 :                       false,          // aContentModal
    5905                 :                       false,          // aCalledNoScript
    5906                 :                       true,           // aDoJSFixups
    5907                 :                       nsnull, nsnull,    // No args
    5908               0 :                       GetPrincipal(),    // aCalleePrincipal
    5909                 :                       nsContentUtils::GetCurrentJSContext(), // aJSCallerContext
    5910               0 :                       _retval);
    5911                 : }
    5912                 : 
    5913                 : // like Open, but attaches to the new window any extra parameters past
    5914                 : // [features] as a JS property named "arguments"
    5915                 : NS_IMETHODIMP
    5916               0 : nsGlobalWindow::OpenDialog(const nsAString& aUrl, const nsAString& aName,
    5917                 :                            const nsAString& aOptions,
    5918                 :                            nsISupports* aExtraArgument, nsIDOMWindow** _retval)
    5919                 : {
    5920                 :   return OpenInternal(aUrl, aName, aOptions,
    5921                 :                       true,                    // aDialog
    5922                 :                       false,                   // aContentModal
    5923                 :                       true,                    // aCalledNoScript
    5924                 :                       false,                   // aDoJSFixups
    5925                 :                       nsnull, aExtraArgument,     // Arguments
    5926               0 :                       GetPrincipal(),             // aCalleePrincipal
    5927                 :                       nsnull,                     // aJSCallerContext
    5928               0 :                       _retval);
    5929                 : }
    5930                 : 
    5931                 : NS_IMETHODIMP
    5932               0 : nsGlobalWindow::OpenDialog(const nsAString& aUrl, const nsAString& aName,
    5933                 :                            const nsAString& aOptions, nsIDOMWindow** _retval)
    5934                 : {
    5935               0 :   if (!nsContentUtils::IsCallerTrustedForWrite()) {
    5936               0 :     return NS_ERROR_DOM_SECURITY_ERR;
    5937                 :   }
    5938                 : 
    5939               0 :   nsAXPCNativeCallContext *ncc = nsnull;
    5940               0 :   nsresult rv = nsContentUtils::XPConnect()->
    5941               0 :     GetCurrentNativeCallContext(&ncc);
    5942               0 :   NS_ENSURE_SUCCESS(rv, rv);
    5943                 : 
    5944               0 :   if (!ncc)
    5945               0 :     return NS_ERROR_NOT_AVAILABLE;
    5946                 : 
    5947               0 :   JSContext *cx = nsnull;
    5948                 : 
    5949               0 :   rv = ncc->GetJSContext(&cx);
    5950               0 :   NS_ENSURE_SUCCESS(rv, rv);
    5951                 : 
    5952                 :   PRUint32 argc;
    5953               0 :   jsval *argv = nsnull;
    5954                 : 
    5955                 :   // XXX - need to get this as nsISupports?
    5956               0 :   ncc->GetArgc(&argc);
    5957               0 :   ncc->GetArgvPtr(&argv);
    5958                 : 
    5959                 :   // Strip the url, name and options from the args seen by scripts.
    5960               0 :   PRUint32 argOffset = argc < 3 ? argc : 3;
    5961               0 :   nsCOMPtr<nsIJSArgArray> argvArray;
    5962               0 :   rv = NS_CreateJSArgv(cx, argc - argOffset, argv + argOffset,
    5963               0 :                        getter_AddRefs(argvArray));
    5964               0 :   NS_ENSURE_SUCCESS(rv, rv);
    5965                 : 
    5966                 :   return OpenInternal(aUrl, aName, aOptions,
    5967                 :                       true,             // aDialog
    5968                 :                       false,            // aContentModal
    5969                 :                       false,            // aCalledNoScript
    5970                 :                       false,            // aDoJSFixups
    5971                 :                       argvArray, nsnull,   // Arguments
    5972               0 :                       GetPrincipal(),      // aCalleePrincipal
    5973                 :                       cx,                  // aJSCallerContext
    5974               0 :                       _retval);
    5975                 : }
    5976                 : 
    5977                 : NS_IMETHODIMP
    5978               0 : nsGlobalWindow::GetFrames(nsIDOMWindow** aFrames)
    5979                 : {
    5980               0 :   FORWARD_TO_OUTER(GetFrames, (aFrames), NS_ERROR_NOT_INITIALIZED);
    5981                 : 
    5982               0 :   *aFrames = this;
    5983               0 :   NS_ADDREF(*aFrames);
    5984                 : 
    5985               0 :   FlushPendingNotifications(Flush_ContentAndNotify);
    5986                 : 
    5987               0 :   return NS_OK;
    5988                 : }
    5989                 : 
    5990                 : nsGlobalWindow*
    5991               0 : nsGlobalWindow::CallerInnerWindow()
    5992                 : {
    5993               0 :   JSContext *cx = nsContentUtils::GetCurrentJSContext();
    5994               0 :   if (!cx) {
    5995               0 :     NS_ERROR("Please don't call this method from C++!");
    5996                 : 
    5997               0 :     return nsnull;
    5998                 :   }
    5999                 : 
    6000               0 :   JSObject *scope = nsnull;
    6001               0 :   JSStackFrame *fp = nsnull;
    6002               0 :   JS_FrameIterator(cx, &fp);
    6003               0 :   if (fp) {
    6004               0 :     while (!JS_IsScriptFrame(cx, fp)) {
    6005               0 :       if (!JS_FrameIterator(cx, &fp))
    6006               0 :         break;
    6007                 :     }
    6008                 : 
    6009               0 :     if (fp)
    6010               0 :       scope = JS_GetGlobalForFrame(fp);
    6011                 :   }
    6012                 : 
    6013               0 :   if (!scope)
    6014               0 :     scope = JS_GetGlobalForScopeChain(cx);
    6015                 : 
    6016               0 :   JSAutoEnterCompartment ac;
    6017               0 :   if (!ac.enter(cx, scope))
    6018               0 :     return nsnull;
    6019                 : 
    6020               0 :   nsCOMPtr<nsIXPConnectWrappedNative> wrapper;
    6021               0 :   nsContentUtils::XPConnect()->
    6022               0 :     GetWrappedNativeOfJSObject(cx, scope, getter_AddRefs(wrapper));
    6023               0 :   if (!wrapper)
    6024               0 :     return nsnull;
    6025                 : 
    6026                 :   // The calling window must be holding a reference, so we can just return a
    6027                 :   // raw pointer here and let the QI's addref be balanced by the nsCOMPtr
    6028                 :   // destructor's release.
    6029               0 :   nsCOMPtr<nsPIDOMWindow> win = do_QueryWrappedNative(wrapper);
    6030               0 :   if (!win)
    6031               0 :     return GetCurrentInnerWindowInternal();
    6032               0 :   return static_cast<nsGlobalWindow*>(win.get());
    6033                 : }
    6034                 : 
    6035                 : /**
    6036                 :  * Class used to represent events generated by calls to Window.postMessage,
    6037                 :  * which asynchronously creates and dispatches events.
    6038                 :  */
    6039                 : class PostMessageEvent : public nsRunnable
    6040                 : {
    6041                 :   public:
    6042                 :     NS_DECL_NSIRUNNABLE
    6043                 : 
    6044               0 :     PostMessageEvent(nsGlobalWindow* aSource,
    6045                 :                      const nsAString& aCallerOrigin,
    6046                 :                      nsGlobalWindow* aTargetWindow,
    6047                 :                      nsIURI* aProvidedOrigin,
    6048                 :                      bool aTrustedCaller)
    6049                 :     : mSource(aSource),
    6050                 :       mCallerOrigin(aCallerOrigin),
    6051                 :       mMessage(nsnull),
    6052                 :       mMessageLen(0),
    6053                 :       mTargetWindow(aTargetWindow),
    6054                 :       mProvidedOrigin(aProvidedOrigin),
    6055               0 :       mTrustedCaller(aTrustedCaller)
    6056                 :     {
    6057               0 :       MOZ_COUNT_CTOR(PostMessageEvent);
    6058               0 :     }
    6059                 :     
    6060               0 :     ~PostMessageEvent()
    6061               0 :     {
    6062               0 :       NS_ASSERTION(!mMessage, "Message should have been deserialized!");
    6063               0 :       MOZ_COUNT_DTOR(PostMessageEvent);
    6064               0 :     }
    6065                 : 
    6066               0 :     void SetJSData(JSAutoStructuredCloneBuffer& aBuffer)
    6067                 :     {
    6068               0 :       NS_ASSERTION(!mMessage && mMessageLen == 0, "Don't call twice!");
    6069               0 :       aBuffer.steal(&mMessage, &mMessageLen);
    6070               0 :     }
    6071                 : 
    6072               0 :     bool StoreISupports(nsISupports* aSupports)
    6073                 :     {
    6074               0 :       mSupportsArray.AppendElement(aSupports);
    6075               0 :       return true;
    6076                 :     }
    6077                 : 
    6078                 :   private:
    6079                 :     nsRefPtr<nsGlobalWindow> mSource;
    6080                 :     nsString mCallerOrigin;
    6081                 :     uint64_t* mMessage;
    6082                 :     size_t mMessageLen;
    6083                 :     nsRefPtr<nsGlobalWindow> mTargetWindow;
    6084                 :     nsCOMPtr<nsIURI> mProvidedOrigin;
    6085                 :     bool mTrustedCaller;
    6086                 :     nsTArray<nsCOMPtr<nsISupports> > mSupportsArray;
    6087                 : };
    6088                 : 
    6089                 : namespace {
    6090                 : 
    6091                 : struct StructuredCloneInfo {
    6092                 :   PostMessageEvent* event;
    6093                 :   bool subsumes;
    6094                 : };
    6095                 : 
    6096                 : static JSObject*
    6097               0 : PostMessageReadStructuredClone(JSContext* cx,
    6098                 :                                JSStructuredCloneReader* reader,
    6099                 :                                uint32 tag,
    6100                 :                                uint32 data,
    6101                 :                                void* closure)
    6102                 : {
    6103               0 :   NS_ASSERTION(closure, "Must have closure!");
    6104                 : 
    6105               0 :   if (tag == SCTAG_DOM_BLOB || tag == SCTAG_DOM_FILELIST) {
    6106               0 :     NS_ASSERTION(!data, "Data should be empty");
    6107                 : 
    6108                 :     nsISupports* supports;
    6109               0 :     if (JS_ReadBytes(reader, &supports, sizeof(supports))) {
    6110               0 :       JSObject* global = JS_GetGlobalForScopeChain(cx);
    6111               0 :       if (global) {
    6112                 :         jsval val;
    6113               0 :         nsCOMPtr<nsIXPConnectJSObjectHolder> wrapper;
    6114               0 :         if (NS_SUCCEEDED(nsContentUtils::WrapNative(cx, global, supports,
    6115                 :                                                     &val,
    6116                 :                                                     getter_AddRefs(wrapper)))) {
    6117               0 :           return JSVAL_TO_OBJECT(val);
    6118                 :         }
    6119                 :       }
    6120                 :     }
    6121                 :   }
    6122                 : 
    6123                 :   const JSStructuredCloneCallbacks* runtimeCallbacks =
    6124               0 :     js::GetContextStructuredCloneCallbacks(cx);
    6125                 : 
    6126               0 :   if (runtimeCallbacks) {
    6127               0 :     return runtimeCallbacks->read(cx, reader, tag, data, nsnull);
    6128                 :   }
    6129                 : 
    6130               0 :   return JS_FALSE;
    6131                 : }
    6132                 : 
    6133                 : static JSBool
    6134               0 : PostMessageWriteStructuredClone(JSContext* cx,
    6135                 :                                 JSStructuredCloneWriter* writer,
    6136                 :                                 JSObject* obj,
    6137                 :                                 void *closure)
    6138                 : {
    6139               0 :   StructuredCloneInfo* scInfo = static_cast<StructuredCloneInfo*>(closure);
    6140               0 :   NS_ASSERTION(scInfo, "Must have scInfo!");
    6141                 : 
    6142               0 :   nsCOMPtr<nsIXPConnectWrappedNative> wrappedNative;
    6143               0 :   nsContentUtils::XPConnect()->
    6144               0 :     GetWrappedNativeOfJSObject(cx, obj, getter_AddRefs(wrappedNative));
    6145               0 :   if (wrappedNative) {
    6146               0 :     PRUint32 scTag = 0;
    6147               0 :     nsISupports* supports = wrappedNative->Native();
    6148                 : 
    6149               0 :     nsCOMPtr<nsIDOMBlob> blob = do_QueryInterface(supports);
    6150               0 :     if (blob && scInfo->subsumes)
    6151               0 :       scTag = SCTAG_DOM_BLOB;
    6152                 : 
    6153               0 :     nsCOMPtr<nsIDOMFileList> list = do_QueryInterface(supports);
    6154               0 :     if (list && scInfo->subsumes)
    6155               0 :       scTag = SCTAG_DOM_FILELIST;
    6156                 : 
    6157               0 :     if (scTag)
    6158               0 :       return JS_WriteUint32Pair(writer, scTag, 0) &&
    6159               0 :              JS_WriteBytes(writer, &supports, sizeof(supports)) &&
    6160               0 :              scInfo->event->StoreISupports(supports);
    6161                 :   }
    6162                 : 
    6163                 :   const JSStructuredCloneCallbacks* runtimeCallbacks =
    6164               0 :     js::GetContextStructuredCloneCallbacks(cx);
    6165                 : 
    6166               0 :   if (runtimeCallbacks) {
    6167               0 :     return runtimeCallbacks->write(cx, writer, obj, nsnull);
    6168                 :   }
    6169                 : 
    6170               0 :   return JS_FALSE;
    6171                 : }
    6172                 : 
    6173                 : JSStructuredCloneCallbacks kPostMessageCallbacks = {
    6174                 :   PostMessageReadStructuredClone,
    6175                 :   PostMessageWriteStructuredClone,
    6176                 :   nsnull
    6177                 : };
    6178                 : 
    6179                 : } // anonymous namespace
    6180                 : 
    6181                 : NS_IMETHODIMP
    6182               0 : PostMessageEvent::Run()
    6183                 : {
    6184               0 :   NS_ABORT_IF_FALSE(mTargetWindow->IsOuterWindow(),
    6185                 :                     "should have been passed an outer window!");
    6186               0 :   NS_ABORT_IF_FALSE(!mSource || mSource->IsOuterWindow(),
    6187                 :                     "should have been passed an outer window!");
    6188                 : 
    6189                 :   // Get the JSContext for the target window
    6190               0 :   JSContext* cx = nsnull;
    6191               0 :   nsIScriptContext* scriptContext = mTargetWindow->GetContext();
    6192               0 :   if (scriptContext) {
    6193               0 :     cx = scriptContext->GetNativeContext();
    6194                 :   }
    6195                 : 
    6196               0 :   if (!cx) {
    6197                 :     // This can happen if mTargetWindow has been closed.  To avoid leaking,
    6198                 :     // we need to find a JSContext.
    6199               0 :     nsIThreadJSContextStack* cxStack = nsContentUtils::ThreadJSContextStack();
    6200               0 :     if (cxStack) {
    6201               0 :       cxStack->GetSafeJSContext(&cx);
    6202                 :     }
    6203                 : 
    6204               0 :     if (!cx) {
    6205               0 :       NS_WARNING("Cannot find a JSContext!  Leaking PostMessage buffer.");
    6206               0 :       return NS_ERROR_FAILURE;
    6207                 :     }
    6208                 :   }
    6209                 : 
    6210                 :   // If we bailed before this point we're going to leak mMessage, but
    6211                 :   // that's probably better than crashing.
    6212                 : 
    6213                 :   // Ensure that the buffer is freed even if we fail to post the message
    6214               0 :   JSAutoStructuredCloneBuffer buffer;
    6215               0 :   buffer.adopt(mMessage, mMessageLen);
    6216               0 :   mMessage = nsnull;
    6217               0 :   mMessageLen = 0;
    6218                 : 
    6219               0 :   nsRefPtr<nsGlobalWindow> targetWindow;
    6220               0 :   if (mTargetWindow->IsClosedOrClosing() ||
    6221               0 :       !(targetWindow = mTargetWindow->GetCurrentInnerWindowInternal()) ||
    6222               0 :       targetWindow->IsClosedOrClosing())
    6223               0 :     return NS_OK;
    6224                 : 
    6225               0 :   NS_ABORT_IF_FALSE(targetWindow->IsInnerWindow(),
    6226                 :                     "we ordered an inner window!");
    6227                 : 
    6228                 :   // Ensure that any origin which might have been provided is the origin of this
    6229                 :   // window's document.  Note that we do this *now* instead of when postMessage
    6230                 :   // is called because the target window might have been navigated to a
    6231                 :   // different location between then and now.  If this check happened when
    6232                 :   // postMessage was called, it would be fairly easy for a malicious webpage to
    6233                 :   // intercept messages intended for another site by carefully timing navigation
    6234                 :   // of the target window so it changed location after postMessage but before
    6235                 :   // now.
    6236               0 :   if (mProvidedOrigin) {
    6237                 :     // Get the target's origin either from its principal or, in the case the
    6238                 :     // principal doesn't carry a URI (e.g. the system principal), the target's
    6239                 :     // document.
    6240               0 :     nsIPrincipal* targetPrin = targetWindow->GetPrincipal();
    6241               0 :     if (!targetPrin)
    6242               0 :       return NS_OK;
    6243               0 :     nsCOMPtr<nsIURI> targetURI;
    6244               0 :     if (NS_FAILED(targetPrin->GetURI(getter_AddRefs(targetURI))))
    6245               0 :       return NS_OK;
    6246               0 :     if (!targetURI) {
    6247               0 :       targetURI = targetWindow->mDoc->GetDocumentURI();
    6248               0 :       if (!targetURI)
    6249               0 :         return NS_OK;
    6250                 :     }
    6251                 : 
    6252                 :     // Note: This is contrary to the spec with respect to file: URLs, which
    6253                 :     //       the spec groups into a single origin, but given we intentionally
    6254                 :     //       don't do that in other places it seems better to hold the line for
    6255                 :     //       now.  Long-term, we want HTML5 to address this so that we can
    6256                 :     //       be compliant while being safer.
    6257               0 :     nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
    6258                 :     nsresult rv =
    6259               0 :       ssm->CheckSameOriginURI(mProvidedOrigin, targetURI, true);
    6260               0 :     if (NS_FAILED(rv))
    6261               0 :       return NS_OK;
    6262                 :   }
    6263                 : 
    6264                 :   // Deserialize the structured clone data
    6265                 :   jsval messageData;
    6266                 :   {
    6267               0 :     JSAutoRequest ar(cx);
    6268                 :     StructuredCloneInfo scInfo;
    6269               0 :     scInfo.event = this;
    6270                 : 
    6271               0 :     if (!buffer.read(cx, &messageData, &kPostMessageCallbacks, &scInfo))
    6272               0 :       return NS_ERROR_DOM_DATA_CLONE_ERR;
    6273                 :   }
    6274                 : 
    6275                 :   // Create the event
    6276               0 :   nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(targetWindow->mDocument);
    6277               0 :   if (!domDoc)
    6278               0 :     return NS_OK;
    6279               0 :   nsCOMPtr<nsIDOMEvent> event;
    6280               0 :   domDoc->CreateEvent(NS_LITERAL_STRING("MessageEvent"),
    6281               0 :                       getter_AddRefs(event));
    6282               0 :   if (!event)
    6283               0 :     return NS_OK;
    6284                 : 
    6285               0 :   nsCOMPtr<nsIDOMMessageEvent> message = do_QueryInterface(event);
    6286               0 :   nsresult rv = message->InitMessageEvent(NS_LITERAL_STRING("message"),
    6287                 :                                           false /* non-bubbling */,
    6288                 :                                           true /* cancelable */,
    6289                 :                                           messageData,
    6290                 :                                           mCallerOrigin,
    6291               0 :                                           EmptyString(),
    6292               0 :                                           mSource);
    6293               0 :   if (NS_FAILED(rv))
    6294               0 :     return NS_OK;
    6295                 : 
    6296                 : 
    6297                 :   // We can't simply call dispatchEvent on the window because doing so ends
    6298                 :   // up flipping the trusted bit on the event, and we don't want that to
    6299                 :   // happen because then untrusted content can call postMessage on a chrome
    6300                 :   // window if it can get a reference to it.
    6301                 : 
    6302               0 :   nsIPresShell *shell = targetWindow->mDoc->GetShell();
    6303               0 :   nsRefPtr<nsPresContext> presContext;
    6304               0 :   if (shell)
    6305               0 :     presContext = shell->GetPresContext();
    6306                 : 
    6307               0 :   nsCOMPtr<nsIPrivateDOMEvent> privEvent = do_QueryInterface(message);
    6308               0 :   privEvent->SetTrusted(mTrustedCaller);
    6309               0 :   nsEvent *internalEvent = privEvent->GetInternalNSEvent();
    6310                 : 
    6311               0 :   nsEventStatus status = nsEventStatus_eIgnore;
    6312               0 :   nsEventDispatcher::Dispatch(static_cast<nsPIDOMWindow*>(mTargetWindow),
    6313                 :                               presContext,
    6314                 :                               internalEvent,
    6315                 :                               message,
    6316               0 :                               &status);
    6317               0 :   return NS_OK;
    6318                 : }
    6319                 : 
    6320                 : NS_IMETHODIMP
    6321               0 : nsGlobalWindow::PostMessageMoz(const jsval& aMessage,
    6322                 :                                const nsAString& aOrigin,
    6323                 :                                JSContext* aCx)
    6324                 : {
    6325               0 :   FORWARD_TO_OUTER(PostMessageMoz, (aMessage, aOrigin, aCx),
    6326                 :                    NS_ERROR_NOT_INITIALIZED);
    6327                 : 
    6328                 :   //
    6329                 :   // Window.postMessage is an intentional subversion of the same-origin policy.
    6330                 :   // As such, this code must be particularly careful in the information it
    6331                 :   // exposes to calling code.
    6332                 :   //
    6333                 :   // http://www.whatwg.org/specs/web-apps/current-work/multipage/section-crossDocumentMessages.html
    6334                 :   //
    6335                 : 
    6336                 :   // First, get the caller's window
    6337               0 :   nsRefPtr<nsGlobalWindow> callerInnerWin = CallerInnerWindow();
    6338               0 :   if (!callerInnerWin)
    6339               0 :     return NS_OK;
    6340               0 :   NS_ABORT_IF_FALSE(callerInnerWin->IsInnerWindow(),
    6341                 :                     "should have gotten an inner window here");
    6342                 : 
    6343                 :   // Compute the caller's origin either from its principal or, in the case the
    6344                 :   // principal doesn't carry a URI (e.g. the system principal), the caller's
    6345                 :   // document.  We must get this now instead of when the event is created and
    6346                 :   // dispatched, because ultimately it is the identity of the calling window
    6347                 :   // *now* that determines who sent the message (and not an identity which might
    6348                 :   // have changed due to intervening navigations).
    6349               0 :   nsIPrincipal* callerPrin = callerInnerWin->GetPrincipal();
    6350               0 :   if (!callerPrin)
    6351               0 :     return NS_OK;
    6352                 :   
    6353               0 :   nsCOMPtr<nsIURI> callerOuterURI;
    6354               0 :   if (NS_FAILED(callerPrin->GetURI(getter_AddRefs(callerOuterURI))))
    6355               0 :     return NS_OK;
    6356                 : 
    6357               0 :   nsAutoString origin;
    6358               0 :   if (callerOuterURI) {
    6359                 :     // if the principal has a URI, use that to generate the origin
    6360               0 :     nsContentUtils::GetUTFOrigin(callerPrin, origin);
    6361                 :   }
    6362                 :   else {
    6363                 :     // otherwise use the URI of the document to generate origin
    6364               0 :     nsCOMPtr<nsIDocument> doc = do_QueryInterface(callerInnerWin->mDocument);
    6365               0 :     if (!doc)
    6366               0 :       return NS_OK;
    6367               0 :     callerOuterURI = doc->GetDocumentURI();
    6368                 :     // if the principal has a URI, use that to generate the origin
    6369               0 :     nsContentUtils::GetUTFOrigin(callerOuterURI, origin);
    6370                 :   }
    6371                 : 
    6372                 :   // Convert the provided origin string into a URI for comparison purposes.
    6373                 :   // "*" indicates no specific origin is required.
    6374               0 :   nsCOMPtr<nsIURI> providedOrigin;
    6375               0 :   if (!aOrigin.EqualsASCII("*")) {
    6376               0 :     if (NS_FAILED(NS_NewURI(getter_AddRefs(providedOrigin), aOrigin)))
    6377               0 :       return NS_ERROR_DOM_SYNTAX_ERR;
    6378               0 :     if (NS_FAILED(providedOrigin->SetUserPass(EmptyCString())) ||
    6379               0 :         NS_FAILED(providedOrigin->SetPath(EmptyCString())))
    6380               0 :       return NS_OK;
    6381                 :   }
    6382                 : 
    6383                 :   // Create and asynchronously dispatch a runnable which will handle actual DOM
    6384                 :   // event creation and dispatch.
    6385                 :   nsRefPtr<PostMessageEvent> event =
    6386               0 :     new PostMessageEvent(nsContentUtils::IsCallerChrome()
    6387                 :                          ? nsnull
    6388               0 :                          : callerInnerWin->GetOuterWindowInternal(),
    6389                 :                          origin,
    6390                 :                          this,
    6391                 :                          providedOrigin,
    6392               0 :                          nsContentUtils::IsCallerTrustedForWrite());
    6393                 : 
    6394                 :   // We *must* clone the data here, or the jsval could be modified
    6395                 :   // by script
    6396               0 :   JSAutoStructuredCloneBuffer buffer;
    6397                 :   StructuredCloneInfo scInfo;
    6398               0 :   scInfo.event = event;
    6399                 : 
    6400               0 :   nsIPrincipal* principal = GetPrincipal();
    6401               0 :   if (NS_FAILED(callerPrin->Subsumes(principal, &scInfo.subsumes)))
    6402               0 :     return NS_ERROR_DOM_DATA_CLONE_ERR;
    6403                 : 
    6404               0 :   if (!buffer.write(aCx, aMessage, &kPostMessageCallbacks, &scInfo))
    6405               0 :     return NS_ERROR_DOM_DATA_CLONE_ERR;
    6406                 : 
    6407               0 :   event->SetJSData(buffer);
    6408                 : 
    6409               0 :   return NS_DispatchToCurrentThread(event);
    6410                 : }
    6411                 : 
    6412               0 : class nsCloseEvent : public nsRunnable {
    6413                 : 
    6414                 :   nsRefPtr<nsGlobalWindow> mWindow;
    6415                 : 
    6416               0 :   nsCloseEvent(nsGlobalWindow *aWindow)
    6417               0 :     : mWindow(aWindow)
    6418               0 :   {}
    6419                 : 
    6420                 : public:
    6421                 : 
    6422                 :   static nsresult
    6423               0 :   PostCloseEvent(nsGlobalWindow* aWindow) {
    6424               0 :     nsCOMPtr<nsIRunnable> ev = new nsCloseEvent(aWindow);
    6425               0 :     nsresult rv = NS_DispatchToCurrentThread(ev);
    6426               0 :     if (NS_SUCCEEDED(rv))
    6427               0 :       aWindow->MaybeForgiveSpamCount();
    6428               0 :     return rv;
    6429                 :   }
    6430                 : 
    6431               0 :   NS_IMETHOD Run() {
    6432               0 :     if (mWindow)
    6433               0 :       mWindow->ReallyCloseWindow();
    6434               0 :     return NS_OK;
    6435                 :   }
    6436                 : 
    6437                 : };
    6438                 : 
    6439                 : bool
    6440               0 : nsGlobalWindow::CanClose()
    6441                 : {
    6442               0 :   if (!mDocShell)
    6443               0 :     return true;
    6444                 : 
    6445                 :   // Ask the content viewer whether the toplevel window can close.
    6446                 :   // If the content viewer returns false, it is responsible for calling
    6447                 :   // Close() as soon as it is possible for the window to close.
    6448                 :   // This allows us to not close the window while printing is happening.
    6449                 : 
    6450               0 :   nsCOMPtr<nsIContentViewer> cv;
    6451               0 :   mDocShell->GetContentViewer(getter_AddRefs(cv));
    6452               0 :   if (cv) {
    6453                 :     bool canClose;
    6454               0 :     nsresult rv = cv->PermitUnload(false, &canClose);
    6455               0 :     if (NS_SUCCEEDED(rv) && !canClose)
    6456               0 :       return false;
    6457                 : 
    6458               0 :     rv = cv->RequestWindowClose(&canClose);
    6459               0 :     if (NS_SUCCEEDED(rv) && !canClose)
    6460               0 :       return false;
    6461                 :   }
    6462                 : 
    6463               0 :   return true;
    6464                 : }
    6465                 : 
    6466                 : NS_IMETHODIMP
    6467               0 : nsGlobalWindow::Close()
    6468                 : {
    6469               0 :   FORWARD_TO_OUTER(Close, (), NS_ERROR_NOT_INITIALIZED);
    6470                 : 
    6471               0 :   if (IsFrame() || !mDocShell || IsInModalState()) {
    6472                 :     // window.close() is called on a frame in a frameset, on a window
    6473                 :     // that's already closed, or on a window for which there's
    6474                 :     // currently a modal dialog open. Ignore such calls.
    6475                 : 
    6476               0 :     return NS_OK;
    6477                 :   }
    6478                 : 
    6479               0 :   if (mHavePendingClose) {
    6480                 :     // We're going to be closed anyway; do nothing since we don't want
    6481                 :     // to double-close
    6482               0 :     return NS_OK;
    6483                 :   }
    6484                 : 
    6485               0 :   if (mBlockScriptedClosingFlag)
    6486                 :   {
    6487                 :     // A script's popup has been blocked and we don't want
    6488                 :     // the window to be closed directly after this event,
    6489                 :     // so the user can see that there was a blocked popup.
    6490               0 :     return NS_OK;
    6491                 :   }
    6492                 : 
    6493                 :   // Don't allow scripts from content to close windows
    6494                 :   // that were not opened by script
    6495               0 :   if (!mHadOriginalOpener && !nsContentUtils::IsCallerTrustedForWrite()) {
    6496                 :     bool allowClose =
    6497               0 :       Preferences::GetBool("dom.allow_scripts_to_close_windows", true);
    6498               0 :     if (!allowClose) {
    6499                 :       // We're blocking the close operation
    6500                 :       // report localized error msg in JS console
    6501                 :       nsContentUtils::ReportToConsole(
    6502                 :           nsIScriptError::warningFlag,
    6503                 :           "DOM Window", mDoc,  // Better name for the category?
    6504                 :           nsContentUtils::eDOM_PROPERTIES,
    6505               0 :           "WindowCloseBlockedWarning");
    6506                 : 
    6507               0 :       return NS_OK;
    6508                 :     }
    6509                 :   }
    6510                 : 
    6511               0 :   if (!mInClose && !mIsClosed && !CanClose())
    6512               0 :     return NS_OK;
    6513                 : 
    6514                 :   // Fire a DOM event notifying listeners that this window is about to
    6515                 :   // be closed. The tab UI code may choose to cancel the default
    6516                 :   // action for this event, if so, we won't actually close the window
    6517                 :   // (since the tab UI code will close the tab in stead). Sure, this
    6518                 :   // could be abused by content code, but do we care? I don't think
    6519                 :   // so...
    6520                 : 
    6521               0 :   bool wasInClose = mInClose;
    6522               0 :   mInClose = true;
    6523                 : 
    6524               0 :   if (!DispatchCustomEvent("DOMWindowClose")) {
    6525                 :     // Someone chose to prevent the default action for this event, if
    6526                 :     // so, let's not close this window after all...
    6527                 : 
    6528               0 :     mInClose = wasInClose;
    6529               0 :     return NS_OK;
    6530                 :   }
    6531                 : 
    6532               0 :   return FinalClose();
    6533                 : }
    6534                 : 
    6535                 : nsresult
    6536               0 : nsGlobalWindow::ForceClose()
    6537                 : {
    6538               0 :   if (IsFrame() || !mDocShell) {
    6539                 :     // This may be a frame in a frameset, or a window that's already closed.
    6540                 :     // Ignore such calls.
    6541                 : 
    6542               0 :     return NS_OK;
    6543                 :   }
    6544                 : 
    6545               0 :   if (mHavePendingClose) {
    6546                 :     // We're going to be closed anyway; do nothing since we don't want
    6547                 :     // to double-close
    6548               0 :     return NS_OK;
    6549                 :   }
    6550                 : 
    6551               0 :   mInClose = true;
    6552                 : 
    6553               0 :   DispatchCustomEvent("DOMWindowClose");
    6554                 : 
    6555               0 :   return FinalClose();
    6556                 : }
    6557                 : 
    6558                 : nsresult
    6559               0 : nsGlobalWindow::FinalClose()
    6560                 : {
    6561                 :   // Flag that we were closed.
    6562               0 :   mIsClosed = true;
    6563                 : 
    6564                 :   nsCOMPtr<nsIJSContextStack> stack =
    6565               0 :     do_GetService(sJSStackContractID);
    6566                 : 
    6567               0 :   JSContext *cx = nsnull;
    6568                 : 
    6569               0 :   if (stack) {
    6570               0 :     stack->Peek(&cx);
    6571                 :   }
    6572                 : 
    6573               0 :   if (cx) {
    6574               0 :     nsIScriptContext *currentCX = nsJSUtils::GetDynamicScriptContext(cx);
    6575                 : 
    6576               0 :     if (currentCX && currentCX == GetContextInternal()) {
    6577               0 :       currentCX->SetTerminationFunction(CloseWindow, this);
    6578               0 :       mHavePendingClose = true;
    6579               0 :       return NS_OK;
    6580                 :     }
    6581                 :   }
    6582                 : 
    6583                 :   // We may have plugins on the page that have issued this close from their
    6584                 :   // event loop and because we currently destroy the plugin window with
    6585                 :   // frames, we crash. So, if we are called from Javascript, post an event
    6586                 :   // to really close the window.
    6587               0 :   if (nsContentUtils::IsCallerChrome() ||
    6588               0 :       NS_FAILED(nsCloseEvent::PostCloseEvent(this))) {
    6589               0 :     ReallyCloseWindow();
    6590                 :   } else {
    6591               0 :     mHavePendingClose = true;
    6592                 :   }
    6593                 : 
    6594               0 :   return NS_OK;
    6595                 : }
    6596                 : 
    6597                 : 
    6598                 : void
    6599               0 : nsGlobalWindow::ReallyCloseWindow()
    6600                 : {
    6601               0 :   FORWARD_TO_OUTER_VOID(ReallyCloseWindow, ());
    6602                 : 
    6603                 :   // Make sure we never reenter this method.
    6604               0 :   mHavePendingClose = true;
    6605                 : 
    6606               0 :   nsCOMPtr<nsIBaseWindow> treeOwnerAsWin;
    6607               0 :   GetTreeOwner(getter_AddRefs(treeOwnerAsWin));
    6608                 : 
    6609                 :   // If there's no treeOwnerAsWin, this window must already be closed.
    6610                 : 
    6611               0 :   if (treeOwnerAsWin) {
    6612                 : 
    6613                 :     // but if we're a browser window we could be in some nasty
    6614                 :     // self-destroying cascade that we should mostly ignore
    6615                 : 
    6616               0 :     nsCOMPtr<nsIDocShellTreeItem> docItem(do_QueryInterface(mDocShell));
    6617               0 :     if (docItem) {
    6618               0 :       nsCOMPtr<nsIBrowserDOMWindow> bwin;
    6619               0 :       nsCOMPtr<nsIDocShellTreeItem> rootItem;
    6620               0 :       docItem->GetRootTreeItem(getter_AddRefs(rootItem));
    6621               0 :       nsCOMPtr<nsIDOMWindow> rootWin(do_GetInterface(rootItem));
    6622               0 :       nsCOMPtr<nsIDOMChromeWindow> chromeWin(do_QueryInterface(rootWin));
    6623               0 :       if (chromeWin)
    6624               0 :         chromeWin->GetBrowserDOMWindow(getter_AddRefs(bwin));
    6625                 : 
    6626               0 :       if (rootWin) {
    6627                 :         /* Normally we destroy the entire window, but not if
    6628                 :            this DOM window belongs to a tabbed browser and doesn't
    6629                 :            correspond to a tab. This allows a well-behaved tab
    6630                 :            to destroy the container as it should but is a final measure
    6631                 :            to prevent an errant tab from doing so when it shouldn't.
    6632                 :            This works because we reach this code when we shouldn't only
    6633                 :            in the particular circumstance that we belong to a tab
    6634                 :            that has just been closed (and is therefore already missing
    6635                 :            from the list of browsers) (and has an unload handler
    6636                 :            that closes the window). */
    6637                 :         // XXXbz now that we have mHavePendingClose, is this needed?
    6638               0 :         bool isTab = false;
    6639               0 :         if (rootWin == this ||
    6640               0 :             !bwin || (bwin->IsTabContentWindow(GetOuterWindowInternal(),
    6641               0 :                                                &isTab), isTab))
    6642               0 :           treeOwnerAsWin->Destroy();
    6643                 :       }
    6644                 :     }
    6645                 : 
    6646               0 :     CleanUp(false);
    6647                 :   }
    6648                 : }
    6649                 : 
    6650                 : nsIDOMWindow *
    6651               0 : nsGlobalWindow::EnterModalState()
    6652                 : {
    6653               0 :   nsGlobalWindow* topWin = GetTop();
    6654                 : 
    6655               0 :   if (!topWin) {
    6656               0 :     NS_ERROR("Uh, EnterModalState() called w/o a reachable top window?");
    6657                 : 
    6658               0 :     return nsnull;
    6659                 :   }
    6660                 : 
    6661                 :   // If there is an active ESM in this window, clear it. Otherwise, this can
    6662                 :   // cause a problem if a modal state is entered during a mouseup event.
    6663                 :   nsEventStateManager* activeESM =
    6664               0 :     static_cast<nsEventStateManager*>(nsEventStateManager::GetActiveEventStateManager());
    6665               0 :   if (activeESM && activeESM->GetPresContext()) {
    6666               0 :     nsIPresShell* activeShell = activeESM->GetPresContext()->GetPresShell();
    6667               0 :     if (activeShell && (
    6668               0 :         nsContentUtils::ContentIsCrossDocDescendantOf(activeShell->GetDocument(), mDoc) ||
    6669               0 :         nsContentUtils::ContentIsCrossDocDescendantOf(mDoc, activeShell->GetDocument()))) {
    6670               0 :       nsEventStateManager::ClearGlobalActiveContent(activeESM);
    6671                 : 
    6672               0 :       activeShell->SetCapturingContent(nsnull, 0);
    6673                 : 
    6674               0 :       if (activeShell) {
    6675               0 :         nsRefPtr<nsFrameSelection> frameSelection = activeShell->FrameSelection();
    6676               0 :         frameSelection->SetMouseDownState(false);
    6677                 :       }
    6678                 :     }
    6679                 :   }
    6680                 : 
    6681               0 :   if (topWin->mModalStateDepth == 0) {
    6682               0 :     NS_ASSERTION(!mSuspendedDoc, "Shouldn't have mSuspendedDoc here!");
    6683                 : 
    6684               0 :     mSuspendedDoc = do_QueryInterface(topWin->GetExtantDocument());
    6685               0 :     if (mSuspendedDoc && mSuspendedDoc->EventHandlingSuppressed()) {
    6686               0 :       mSuspendedDoc->SuppressEventHandling();
    6687                 :     } else {
    6688               0 :       mSuspendedDoc = nsnull;
    6689                 :     }
    6690                 :   }
    6691               0 :   topWin->mModalStateDepth++;
    6692                 : 
    6693               0 :   JSContext *cx = nsContentUtils::GetCurrentJSContext();
    6694                 : 
    6695               0 :   nsCOMPtr<nsIDOMWindow> callerWin;
    6696                 :   nsIScriptContext *scx;
    6697               0 :   if (cx && (scx = GetScriptContextFromJSContext(cx))) {
    6698               0 :     scx->EnterModalState();
    6699               0 :     callerWin = do_QueryInterface(nsJSUtils::GetDynamicScriptGlobal(cx));
    6700                 :   }
    6701                 : 
    6702               0 :   if (mContext) {
    6703               0 :     mContext->EnterModalState();
    6704                 :   }
    6705                 : 
    6706               0 :   return callerWin;
    6707                 : }
    6708                 : 
    6709                 : // static
    6710                 : void
    6711               0 : nsGlobalWindow::RunPendingTimeoutsRecursive(nsGlobalWindow *aTopWindow,
    6712                 :                                             nsGlobalWindow *aWindow)
    6713                 : {
    6714                 :   nsGlobalWindow *inner;
    6715                 : 
    6716                 :   // Return early if we're frozen or have no inner window.
    6717               0 :   if (!(inner = aWindow->GetCurrentInnerWindowInternal()) ||
    6718               0 :       inner->IsFrozen()) {
    6719               0 :     return;
    6720                 :   }
    6721                 : 
    6722               0 :   inner->RunTimeout(nsnull);
    6723                 : 
    6724                 :   // Check again if we're frozen since running pending timeouts
    6725                 :   // could've frozen us.
    6726               0 :   if (inner->IsFrozen()) {
    6727               0 :     return;
    6728                 :   }
    6729                 : 
    6730               0 :   nsCOMPtr<nsIDOMWindowCollection> frames;
    6731               0 :   aWindow->GetFrames(getter_AddRefs(frames));
    6732                 : 
    6733               0 :   if (!frames) {
    6734                 :     return;
    6735                 :   }
    6736                 : 
    6737                 :   PRUint32 i, length;
    6738               0 :   if (NS_FAILED(frames->GetLength(&length)) || !length) {
    6739                 :     return;
    6740                 :   }
    6741                 : 
    6742               0 :   for (i = 0; i < length && aTopWindow->mModalStateDepth == 0; i++) {
    6743               0 :     nsCOMPtr<nsIDOMWindow> child;
    6744               0 :     frames->Item(i, getter_AddRefs(child));
    6745                 : 
    6746               0 :     if (!child) {
    6747                 :       return;
    6748                 :     }
    6749                 : 
    6750                 :     nsGlobalWindow *childWin =
    6751                 :       static_cast<nsGlobalWindow *>
    6752                 :                  (static_cast<nsIDOMWindow *>
    6753               0 :                              (child.get()));
    6754                 : 
    6755               0 :     RunPendingTimeoutsRecursive(aTopWindow, childWin);
    6756                 :   }
    6757                 : }
    6758                 : 
    6759                 : class nsPendingTimeoutRunner : public nsRunnable
    6760               0 : {
    6761                 : public:
    6762               0 :   nsPendingTimeoutRunner(nsGlobalWindow *aWindow)
    6763               0 :     : mWindow(aWindow)
    6764                 :   {
    6765               0 :     NS_ASSERTION(mWindow, "mWindow is null.");
    6766               0 :   }
    6767                 : 
    6768               0 :   NS_IMETHOD Run()
    6769                 :   {
    6770               0 :     nsGlobalWindow::RunPendingTimeoutsRecursive(mWindow, mWindow);
    6771                 : 
    6772               0 :     return NS_OK;
    6773                 :   }
    6774                 : 
    6775                 : private:
    6776                 :   nsRefPtr<nsGlobalWindow> mWindow;
    6777                 : };
    6778                 : 
    6779                 : void
    6780               0 : nsGlobalWindow::LeaveModalState(nsIDOMWindow *aCallerWin)
    6781                 : {
    6782               0 :   nsGlobalWindow *topWin = GetTop();
    6783                 : 
    6784               0 :   if (!topWin) {
    6785               0 :     NS_ERROR("Uh, LeaveModalState() called w/o a reachable top window?");
    6786               0 :     return;
    6787                 :   }
    6788                 : 
    6789               0 :   topWin->mModalStateDepth--;
    6790                 : 
    6791               0 :   if (topWin->mModalStateDepth == 0) {
    6792               0 :     nsCOMPtr<nsIRunnable> runner = new nsPendingTimeoutRunner(topWin);
    6793               0 :     if (NS_FAILED(NS_DispatchToCurrentThread(runner)))
    6794               0 :       NS_WARNING("failed to dispatch pending timeout runnable");
    6795                 : 
    6796               0 :     if (mSuspendedDoc) {
    6797                 :       nsCOMPtr<nsIDocument> currentDoc =
    6798               0 :         do_QueryInterface(topWin->GetExtantDocument());
    6799               0 :       mSuspendedDoc->UnsuppressEventHandlingAndFireEvents(currentDoc == mSuspendedDoc);
    6800               0 :       mSuspendedDoc = nsnull;
    6801                 :     }
    6802                 :   }
    6803                 : 
    6804               0 :   if (aCallerWin) {
    6805               0 :     nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryInterface(aCallerWin));
    6806               0 :     nsIScriptContext *scx = sgo->GetContext();
    6807               0 :     if (scx)
    6808               0 :       scx->LeaveModalState();
    6809                 :   }
    6810                 : 
    6811               0 :   if (mContext) {
    6812               0 :     mContext->LeaveModalState();
    6813                 :   }
    6814                 : 
    6815                 :   // Remember the time of the last dialog quit.
    6816               0 :   nsGlobalWindow *inner = topWin->GetCurrentInnerWindowInternal();
    6817               0 :   if (inner)
    6818               0 :     inner->mLastDialogQuitTime = TimeStamp::Now();
    6819                 : }
    6820                 : 
    6821                 : bool
    6822               0 : nsGlobalWindow::IsInModalState()
    6823                 : {
    6824               0 :   nsGlobalWindow *topWin = GetTop();
    6825                 : 
    6826               0 :   if (!topWin) {
    6827               0 :     NS_ERROR("Uh, IsInModalState() called w/o a reachable top window?");
    6828                 : 
    6829               0 :     return false;
    6830                 :   }
    6831                 : 
    6832               0 :   return topWin->mModalStateDepth != 0;
    6833                 : }
    6834                 : 
    6835                 : // static
    6836                 : void
    6837               0 : nsGlobalWindow::NotifyDOMWindowDestroyed(nsGlobalWindow* aWindow) {
    6838                 :   nsCOMPtr<nsIObserverService> observerService =
    6839               0 :     services::GetObserverService();
    6840               0 :   if (observerService) {
    6841               0 :     observerService->
    6842               0 :       NotifyObservers(static_cast<nsIScriptGlobalObject*>(aWindow),
    6843               0 :                       DOM_WINDOW_DESTROYED_TOPIC, nsnull);
    6844                 :   }
    6845               0 : }
    6846                 : 
    6847                 : class WindowDestroyedEvent : public nsRunnable
    6848               0 : {
    6849                 : public:
    6850               0 :   WindowDestroyedEvent(PRUint64 aID, const char* aTopic) :
    6851               0 :     mID(aID), mTopic(aTopic) {}
    6852                 : 
    6853               0 :   NS_IMETHOD Run()
    6854                 :   {
    6855                 :     nsCOMPtr<nsIObserverService> observerService =
    6856               0 :       do_GetService("@mozilla.org/observer-service;1");
    6857               0 :     if (observerService) {
    6858                 :       nsCOMPtr<nsISupportsPRUint64> wrapper =
    6859               0 :         do_CreateInstance(NS_SUPPORTS_PRUINT64_CONTRACTID);
    6860               0 :       if (wrapper) {
    6861               0 :         wrapper->SetData(mID);
    6862               0 :         observerService->NotifyObservers(wrapper, mTopic.get(), nsnull);
    6863                 :       }
    6864                 :     }
    6865               0 :     return NS_OK;
    6866                 :   }
    6867                 : 
    6868                 : private:
    6869                 :   PRUint64 mID;
    6870                 :   nsCString mTopic;
    6871                 : };
    6872                 : 
    6873                 : void
    6874               0 : nsGlobalWindow::NotifyWindowIDDestroyed(const char* aTopic)
    6875                 : {
    6876               0 :   nsRefPtr<nsIRunnable> runnable = new WindowDestroyedEvent(mWindowID, aTopic);
    6877               0 :   nsresult rv = NS_DispatchToCurrentThread(runnable);
    6878               0 :   if (NS_SUCCEEDED(rv)) {
    6879               0 :     mNotifiedIDDestroyed = true;
    6880                 :   }
    6881               0 : }
    6882                 : 
    6883                 : // static
    6884                 : void
    6885               0 : nsGlobalWindow::NotifyDOMWindowFrozen(nsGlobalWindow* aWindow) {
    6886               0 :   if (aWindow && aWindow->IsInnerWindow()) {
    6887                 :     nsCOMPtr<nsIObserverService> observerService =
    6888               0 :       services::GetObserverService();
    6889               0 :     if (observerService) {
    6890               0 :       observerService->
    6891               0 :         NotifyObservers(static_cast<nsIScriptGlobalObject*>(aWindow),
    6892               0 :                         DOM_WINDOW_FROZEN_TOPIC, nsnull);
    6893                 :     }
    6894                 :   }
    6895               0 : }
    6896                 : 
    6897                 : // static
    6898                 : void
    6899               0 : nsGlobalWindow::NotifyDOMWindowThawed(nsGlobalWindow* aWindow) {
    6900               0 :   if (aWindow && aWindow->IsInnerWindow()) {
    6901                 :     nsCOMPtr<nsIObserverService> observerService =
    6902               0 :       services::GetObserverService();
    6903               0 :     if (observerService) {
    6904               0 :       observerService->
    6905               0 :         NotifyObservers(static_cast<nsIScriptGlobalObject*>(aWindow),
    6906               0 :                         DOM_WINDOW_THAWED_TOPIC, nsnull);
    6907                 :     }
    6908                 :   }
    6909               0 : }
    6910                 : 
    6911                 : void
    6912               0 : nsGlobalWindow::InitJavaProperties()
    6913                 : {
    6914               0 :   nsIScriptContext *scx = GetContextInternal();
    6915                 : 
    6916               0 :   if (mDidInitJavaProperties || IsOuterWindow() || !scx || !mJSObject) {
    6917               0 :     return;
    6918                 :   }
    6919                 : 
    6920                 :   // Set mDidInitJavaProperties to true here even if initialization
    6921                 :   // can fail. If it fails, we won't try again...
    6922               0 :   mDidInitJavaProperties = true;
    6923                 : 
    6924               0 :   mDummyJavaPluginOwner = new nsDummyJavaPluginOwner(mDoc);
    6925               0 :   if (!mDummyJavaPluginOwner) {
    6926               0 :     return;
    6927                 :   }
    6928                 : 
    6929               0 :   nsCOMPtr<nsIPluginHost> pluginHostCOM(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID));
    6930               0 :   nsPluginHost *pluginHost = static_cast<nsPluginHost*>(pluginHostCOM.get());
    6931               0 :   if (!pluginHost) {
    6932                 :     return;
    6933                 :   }  
    6934               0 :   pluginHost->InstantiateDummyJavaPlugin(mDummyJavaPluginOwner);
    6935                 : 
    6936                 :   // It's possible for us (or the Java plugin, rather) to process
    6937                 :   // events during the above call, which can lead to this window being
    6938                 :   // torn down or what not, so re-check that the dummy plugin is still
    6939                 :   // around.
    6940               0 :   if (!mDummyJavaPluginOwner) {
    6941                 :     return;
    6942                 :   }
    6943                 : 
    6944               0 :   nsRefPtr<nsNPAPIPluginInstance> dummyPlugin;
    6945               0 :   mDummyJavaPluginOwner->GetInstance(getter_AddRefs(dummyPlugin));
    6946                 : 
    6947               0 :   if (dummyPlugin) {
    6948                 :     // A dummy plugin was instantiated. This means we have a Java
    6949                 :     // plugin that supports NPRuntime. For such a plugin, the plugin
    6950                 :     // instantiation code defines the Java properties for us, so we're
    6951                 :     // done here.
    6952                 : 
    6953                 :     return;
    6954                 :   }
    6955                 : 
    6956                 :   // No NPRuntime enabled Java plugin found, null out the owner we
    6957                 :   // would have used in that case as it's no longer needed.
    6958               0 :   mDummyJavaPluginOwner = nsnull;
    6959                 : }
    6960                 : 
    6961                 : JSObject*
    6962               0 : nsGlobalWindow::GetCachedXBLPrototypeHandler(nsXBLPrototypeHandler* aKey)
    6963                 : {
    6964               0 :   JSObject* handler = nsnull;
    6965               0 :   if (mCachedXBLPrototypeHandlers.IsInitialized()) {
    6966               0 :     mCachedXBLPrototypeHandlers.Get(aKey, &handler);
    6967                 :   }
    6968               0 :   return handler;
    6969                 : }
    6970                 : 
    6971                 : void
    6972               0 : nsGlobalWindow::CacheXBLPrototypeHandler(nsXBLPrototypeHandler* aKey,
    6973                 :                                          nsScriptObjectHolder<JSObject>& aHandler)
    6974                 : {
    6975               0 :   if (!mCachedXBLPrototypeHandlers.IsInitialized() &&
    6976               0 :       !mCachedXBLPrototypeHandlers.Init()) {
    6977               0 :     NS_ERROR("Failed to initiailize hashtable!");
    6978               0 :     return;
    6979                 :   }
    6980                 : 
    6981               0 :   if (!mCachedXBLPrototypeHandlers.Count()) {
    6982                 :     // Can't use macros to get the participant because nsGlobalChromeWindow also
    6983                 :     // runs through this code. Use QueryInterface to get the correct objects.
    6984                 :     nsXPCOMCycleCollectionParticipant* participant;
    6985               0 :     CallQueryInterface(this, &participant);
    6986               0 :     NS_ASSERTION(participant,
    6987                 :                  "Failed to QI to nsXPCOMCycleCollectionParticipant!");
    6988                 : 
    6989                 :     nsISupports* thisSupports;
    6990                 :     QueryInterface(NS_GET_IID(nsCycleCollectionISupports),
    6991               0 :                    reinterpret_cast<void**>(&thisSupports));
    6992               0 :     NS_ASSERTION(thisSupports, "Failed to QI to nsCycleCollectionISupports!");
    6993                 : 
    6994               0 :     nsresult rv = nsContentUtils::HoldJSObjects(thisSupports, participant);
    6995               0 :     if (NS_FAILED(rv)) {
    6996               0 :       NS_ERROR("nsContentUtils::HoldJSObjects failed!");
    6997               0 :       return;
    6998                 :     }
    6999                 :   }
    7000                 : 
    7001               0 :   mCachedXBLPrototypeHandlers.Put(aKey, aHandler.get());
    7002                 : }
    7003                 : 
    7004                 : /**
    7005                 :  * GetScriptableFrameElement is called when script reads
    7006                 :  * nsIGlobalWindow::frameElement.
    7007                 :  *
    7008                 :  * In contrast to GetRealFrameElement, GetScriptableFrameElement says that the
    7009                 :  * window contained by an <iframe mozbrowser> has no frame element
    7010                 :  * (effectively treating a mozbrowser the same as a content/chrome boundary).
    7011                 :  */
    7012                 : NS_IMETHODIMP
    7013               0 : nsGlobalWindow::GetScriptableFrameElement(nsIDOMElement** aFrameElement)
    7014                 : {
    7015               0 :   FORWARD_TO_OUTER(GetScriptableFrameElement, (aFrameElement), NS_ERROR_NOT_INITIALIZED);
    7016               0 :   *aFrameElement = NULL;
    7017                 : 
    7018               0 :   if (!mDocShell) {
    7019               0 :     return NS_OK;
    7020                 :   }
    7021                 : 
    7022               0 :   bool isMozBrowser = false;
    7023               0 :   mDocShell->GetIsBrowserFrame(&isMozBrowser);
    7024               0 :   if (isMozBrowser) {
    7025               0 :     return NS_OK;
    7026                 :   }
    7027                 : 
    7028               0 :   return GetFrameElement(aFrameElement);
    7029                 : }
    7030                 : 
    7031                 : /**
    7032                 :  * nsIGlobalWindow::GetFrameElement (when called from C++) is just a wrapper
    7033                 :  * around GetRealFrameElement.
    7034                 :  */
    7035                 : NS_IMETHODIMP
    7036               0 : nsGlobalWindow::GetRealFrameElement(nsIDOMElement** aFrameElement)
    7037                 : {
    7038               0 :   FORWARD_TO_OUTER(GetRealFrameElement, (aFrameElement), NS_ERROR_NOT_INITIALIZED);
    7039                 : 
    7040               0 :   *aFrameElement = NULL;
    7041                 : 
    7042               0 :   nsCOMPtr<nsIDocShellTreeItem> docShellTI(do_QueryInterface(mDocShell));
    7043                 : 
    7044               0 :   if (!docShellTI) {
    7045               0 :     return NS_OK;
    7046                 :   }
    7047                 : 
    7048               0 :   nsCOMPtr<nsIDocShellTreeItem> parent;
    7049               0 :   docShellTI->GetSameTypeParent(getter_AddRefs(parent));
    7050                 : 
    7051               0 :   if (!parent || parent == docShellTI) {
    7052                 :     // We're at a chrome boundary, don't expose the chrome iframe
    7053                 :     // element to content code.
    7054                 : 
    7055               0 :     return NS_OK;
    7056                 :   }
    7057                 : 
    7058               0 :   *aFrameElement = mFrameElement;
    7059               0 :   NS_IF_ADDREF(*aFrameElement);
    7060                 : 
    7061               0 :   return NS_OK;
    7062                 : }
    7063                 : 
    7064                 : // Helper for converting window.showModalDialog() options (list of ';'
    7065                 : // separated name (:|=) value pairs) to a format that's parsable by
    7066                 : // our normal window opening code.
    7067                 : 
    7068                 : void
    7069               0 : ConvertDialogOptions(const nsAString& aOptions, nsAString& aResult)
    7070                 : {
    7071               0 :   nsAString::const_iterator end;
    7072               0 :   aOptions.EndReading(end);
    7073                 : 
    7074               0 :   nsAString::const_iterator iter;
    7075               0 :   aOptions.BeginReading(iter);
    7076                 : 
    7077               0 :   while (iter != end) {
    7078                 :     // Skip whitespace.
    7079               0 :     while (nsCRT::IsAsciiSpace(*iter) && iter != end) {
    7080               0 :       ++iter;
    7081                 :     }
    7082                 : 
    7083               0 :     nsAString::const_iterator name_start = iter;
    7084                 : 
    7085                 :     // Skip characters until we find whitespace, ';', ':', or '='
    7086               0 :     while (iter != end && !nsCRT::IsAsciiSpace(*iter) &&
    7087               0 :            *iter != ';' &&
    7088               0 :            *iter != ':' &&
    7089               0 :            *iter != '=') {
    7090               0 :       ++iter;
    7091                 :     }
    7092                 : 
    7093               0 :     nsAString::const_iterator name_end = iter;
    7094                 : 
    7095                 :     // Skip whitespace.
    7096               0 :     while (nsCRT::IsAsciiSpace(*iter) && iter != end) {
    7097               0 :       ++iter;
    7098                 :     }
    7099                 : 
    7100               0 :     if (*iter == ';') {
    7101                 :       // No value found, skip the ';' and keep going.
    7102               0 :       ++iter;
    7103                 : 
    7104               0 :       continue;
    7105                 :     }
    7106                 : 
    7107               0 :     nsAString::const_iterator value_start = iter;
    7108               0 :     nsAString::const_iterator value_end = iter;
    7109                 : 
    7110               0 :     if (*iter == ':' || *iter == '=') {
    7111                 :       // We found name followed by ':' or '='. Look for a value.
    7112                 : 
    7113               0 :       iter++; // Skip the ':' or '='
    7114                 : 
    7115                 :       // Skip whitespace.
    7116               0 :       while (nsCRT::IsAsciiSpace(*iter) && iter != end) {
    7117               0 :         ++iter;
    7118                 :       }
    7119                 : 
    7120               0 :       value_start = iter;
    7121                 : 
    7122                 :       // Skip until we find whitespace, or ';'.
    7123               0 :       while (iter != end && !nsCRT::IsAsciiSpace(*iter) &&
    7124               0 :              *iter != ';') {
    7125               0 :         ++iter;
    7126                 :       }
    7127                 : 
    7128               0 :       value_end = iter;
    7129                 : 
    7130                 :       // Skip whitespace.
    7131               0 :       while (nsCRT::IsAsciiSpace(*iter) && iter != end) {
    7132               0 :         ++iter;
    7133                 :       }
    7134                 :     }
    7135                 : 
    7136               0 :     const nsDependentSubstring& name = Substring(name_start, name_end);
    7137               0 :     const nsDependentSubstring& value = Substring(value_start, value_end);
    7138                 : 
    7139               0 :     if (name.LowerCaseEqualsLiteral("center")) {
    7140               0 :       if (value.LowerCaseEqualsLiteral("on")  ||
    7141               0 :           value.LowerCaseEqualsLiteral("yes") ||
    7142               0 :           value.LowerCaseEqualsLiteral("1")) {
    7143               0 :         aResult.AppendLiteral(",centerscreen=1");
    7144                 :       }
    7145               0 :     } else if (name.LowerCaseEqualsLiteral("dialogwidth")) {
    7146               0 :       if (!value.IsEmpty()) {
    7147               0 :         aResult.AppendLiteral(",width=");
    7148               0 :         aResult.Append(value);
    7149                 :       }
    7150               0 :     } else if (name.LowerCaseEqualsLiteral("dialogheight")) {
    7151               0 :       if (!value.IsEmpty()) {
    7152               0 :         aResult.AppendLiteral(",height=");
    7153               0 :         aResult.Append(value);
    7154                 :       }
    7155               0 :     } else if (name.LowerCaseEqualsLiteral("dialogtop")) {
    7156               0 :       if (!value.IsEmpty()) {
    7157               0 :         aResult.AppendLiteral(",top=");
    7158               0 :         aResult.Append(value);
    7159                 :       }
    7160               0 :     } else if (name.LowerCaseEqualsLiteral("dialogleft")) {
    7161               0 :       if (!value.IsEmpty()) {
    7162               0 :         aResult.AppendLiteral(",left=");
    7163               0 :         aResult.Append(value);
    7164                 :       }
    7165               0 :     } else if (name.LowerCaseEqualsLiteral("resizable")) {
    7166               0 :       if (value.LowerCaseEqualsLiteral("on")  ||
    7167               0 :           value.LowerCaseEqualsLiteral("yes") ||
    7168               0 :           value.LowerCaseEqualsLiteral("1")) {
    7169               0 :         aResult.AppendLiteral(",resizable=1");
    7170                 :       }
    7171               0 :     } else if (name.LowerCaseEqualsLiteral("scroll")) {
    7172               0 :       if (value.LowerCaseEqualsLiteral("off")  ||
    7173               0 :           value.LowerCaseEqualsLiteral("no") ||
    7174               0 :           value.LowerCaseEqualsLiteral("0")) {
    7175               0 :         aResult.AppendLiteral(",scrollbars=0");
    7176                 :       }
    7177                 :     }
    7178                 : 
    7179               0 :     if (iter == end) {
    7180                 :       break;
    7181                 :     }
    7182                 : 
    7183               0 :     iter++;
    7184                 :   }
    7185               0 : }
    7186                 : 
    7187                 : NS_IMETHODIMP
    7188               0 : nsGlobalWindow::ShowModalDialog(const nsAString& aURI, nsIVariant *aArgs,
    7189                 :                                 const nsAString& aOptions,
    7190                 :                                 nsIVariant **aRetVal)
    7191                 : {
    7192               0 :   FORWARD_TO_OUTER(ShowModalDialog, (aURI, aArgs, aOptions, aRetVal),
    7193                 :                    NS_ERROR_NOT_INITIALIZED);
    7194                 : 
    7195               0 :   *aRetVal = nsnull;
    7196                 : 
    7197                 :   // Before bringing up the window/dialog, unsuppress painting and flush
    7198                 :   // pending reflows.
    7199               0 :   EnsureReflowFlushAndPaint();
    7200                 : 
    7201               0 :   if (AreDialogsBlocked() || !ConfirmDialogAllowed())
    7202               0 :     return NS_ERROR_NOT_AVAILABLE;
    7203                 : 
    7204               0 :   nsCOMPtr<nsIDOMWindow> dlgWin;
    7205               0 :   nsAutoString options(NS_LITERAL_STRING("-moz-internal-modal=1,status=1"));
    7206                 : 
    7207               0 :   ConvertDialogOptions(aOptions, options);
    7208                 : 
    7209               0 :   options.AppendLiteral(",scrollbars=1,centerscreen=1,resizable=0");
    7210                 : 
    7211               0 :   nsCOMPtr<nsIDOMWindow> callerWin = EnterModalState();
    7212               0 :   nsresult rv = OpenInternal(aURI, EmptyString(), options,
    7213                 :                              false,          // aDialog
    7214                 :                              true,           // aContentModal
    7215                 :                              true,           // aCalledNoScript
    7216                 :                              true,           // aDoJSFixups
    7217                 :                              nsnull, aArgs,     // args
    7218               0 :                              GetPrincipal(),    // aCalleePrincipal
    7219                 :                              nsnull,            // aJSCallerContext
    7220               0 :                              getter_AddRefs(dlgWin));
    7221               0 :   LeaveModalState(callerWin);
    7222                 : 
    7223               0 :   NS_ENSURE_SUCCESS(rv, rv);
    7224                 :   
    7225               0 :   if (dlgWin) {
    7226               0 :     nsCOMPtr<nsIPrincipal> subjectPrincipal;
    7227               0 :     rv = nsContentUtils::GetSecurityManager()->
    7228               0 :       GetSubjectPrincipal(getter_AddRefs(subjectPrincipal));
    7229               0 :     if (NS_FAILED(rv)) {
    7230               0 :       return rv;
    7231                 :     }
    7232                 : 
    7233               0 :     bool canAccess = true;
    7234                 : 
    7235               0 :     if (subjectPrincipal) {
    7236                 :       nsCOMPtr<nsIScriptObjectPrincipal> objPrincipal =
    7237               0 :         do_QueryInterface(dlgWin);
    7238               0 :       nsCOMPtr<nsIPrincipal> dialogPrincipal;
    7239                 : 
    7240               0 :       if (objPrincipal) {
    7241               0 :         dialogPrincipal = objPrincipal->GetPrincipal();
    7242                 : 
    7243               0 :         rv = subjectPrincipal->Subsumes(dialogPrincipal, &canAccess);
    7244               0 :         NS_ENSURE_SUCCESS(rv, rv);
    7245                 :       } else {
    7246                 :         // Uh, not sure what kind of dialog this is. Prevent access to
    7247                 :         // be on the safe side...
    7248                 : 
    7249               0 :         canAccess = false;
    7250                 :       }
    7251                 :     }
    7252                 : 
    7253               0 :     nsCOMPtr<nsPIDOMWindow> win(do_QueryInterface(dlgWin));
    7254                 : 
    7255               0 :     if (canAccess) {
    7256               0 :       nsPIDOMWindow *inner = win->GetCurrentInnerWindow();
    7257                 : 
    7258               0 :       nsCOMPtr<nsIDOMModalContentWindow> dlgInner(do_QueryInterface(inner));
    7259                 : 
    7260               0 :       if (dlgInner) {
    7261               0 :         dlgInner->GetReturnValue(aRetVal);
    7262                 :       }
    7263                 :     }
    7264                 : 
    7265                 :     nsRefPtr<nsGlobalWindow> winInternal =
    7266               0 :       static_cast<nsGlobalWindow*>(win.get());
    7267               0 :     if (winInternal->mCallCleanUpAfterModalDialogCloses) {
    7268               0 :       winInternal->mCallCleanUpAfterModalDialogCloses = false;
    7269               0 :       winInternal->CleanUp(true);
    7270                 :     }
    7271                 :   }
    7272                 :   
    7273               0 :   return NS_OK;
    7274                 : }
    7275                 : 
    7276                 : class CommandDispatcher : public nsRunnable
    7277               0 : {
    7278                 : public:
    7279               0 :   CommandDispatcher(nsIDOMXULCommandDispatcher* aDispatcher,
    7280                 :                     const nsAString& aAction)
    7281               0 :   : mDispatcher(aDispatcher), mAction(aAction) {}
    7282                 : 
    7283               0 :   NS_IMETHOD Run()
    7284                 :   {
    7285               0 :     return mDispatcher->UpdateCommands(mAction);
    7286                 :   }
    7287                 : 
    7288                 :   nsCOMPtr<nsIDOMXULCommandDispatcher> mDispatcher;
    7289                 :   nsString                             mAction;
    7290                 : };
    7291                 : 
    7292                 : NS_IMETHODIMP
    7293               0 : nsGlobalWindow::UpdateCommands(const nsAString& anAction)
    7294                 : {
    7295               0 :   nsPIDOMWindow *rootWindow = nsGlobalWindow::GetPrivateRoot();
    7296               0 :   if (!rootWindow)
    7297               0 :     return NS_OK;
    7298                 : 
    7299                 :   nsCOMPtr<nsIDOMXULDocument> xulDoc =
    7300               0 :     do_QueryInterface(rootWindow->GetExtantDocument());
    7301                 :   // See if we contain a XUL document.
    7302               0 :   if (xulDoc) {
    7303                 :     // Retrieve the command dispatcher and call updateCommands on it.
    7304               0 :     nsCOMPtr<nsIDOMXULCommandDispatcher> xulCommandDispatcher;
    7305               0 :     xulDoc->GetCommandDispatcher(getter_AddRefs(xulCommandDispatcher));
    7306               0 :     if (xulCommandDispatcher) {
    7307                 :       nsContentUtils::AddScriptRunner(new CommandDispatcher(xulCommandDispatcher,
    7308               0 :                                                             anAction));
    7309                 :     }
    7310                 :   }
    7311                 : 
    7312               0 :   return NS_OK;
    7313                 : }
    7314                 : 
    7315                 : NS_IMETHODIMP
    7316               0 : nsGlobalWindow::GetSelection(nsISelection** aSelection)
    7317                 : {
    7318               0 :   FORWARD_TO_OUTER(GetSelection, (aSelection), NS_ERROR_NOT_INITIALIZED);
    7319                 : 
    7320               0 :   NS_ENSURE_ARG_POINTER(aSelection);
    7321               0 :   *aSelection = nsnull;
    7322                 : 
    7323               0 :   if (!mDocShell)
    7324               0 :     return NS_OK;
    7325                 : 
    7326               0 :   nsCOMPtr<nsIPresShell> presShell;
    7327               0 :   mDocShell->GetPresShell(getter_AddRefs(presShell));
    7328                 : 
    7329               0 :   if (!presShell)
    7330               0 :     return NS_OK;
    7331                 :     
    7332               0 :   *aSelection = presShell->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL);
    7333                 :   
    7334               0 :   NS_IF_ADDREF(*aSelection);
    7335                 : 
    7336               0 :   return NS_OK;
    7337                 : }
    7338                 : 
    7339                 : NS_IMETHODIMP
    7340               0 : nsGlobalWindow::Find(const nsAString& aStr, bool aCaseSensitive,
    7341                 :                      bool aBackwards, bool aWrapAround, bool aWholeWord,
    7342                 :                      bool aSearchInFrames, bool aShowDialog,
    7343                 :                      bool *aDidFind)
    7344                 : {
    7345               0 :   FORWARD_TO_OUTER(Find, (aStr, aCaseSensitive, aBackwards, aWrapAround,
    7346                 :                           aWholeWord, aSearchInFrames, aShowDialog, aDidFind),
    7347                 :                    NS_ERROR_NOT_INITIALIZED);
    7348                 : 
    7349               0 :   nsresult rv = NS_OK;
    7350               0 :   *aDidFind = false;
    7351                 : 
    7352               0 :   nsCOMPtr<nsIWebBrowserFind> finder(do_GetInterface(mDocShell));
    7353               0 :   NS_ENSURE_TRUE(finder, NS_ERROR_FAILURE);
    7354                 : 
    7355                 :   // Set the options of the search
    7356               0 :   rv = finder->SetSearchString(PromiseFlatString(aStr).get());
    7357               0 :   NS_ENSURE_SUCCESS(rv, rv);
    7358               0 :   finder->SetMatchCase(aCaseSensitive);
    7359               0 :   finder->SetFindBackwards(aBackwards);
    7360               0 :   finder->SetWrapFind(aWrapAround);
    7361               0 :   finder->SetEntireWord(aWholeWord);
    7362               0 :   finder->SetSearchFrames(aSearchInFrames);
    7363                 : 
    7364                 :   // the nsIWebBrowserFind is initialized to use this window
    7365                 :   // as the search root, but uses focus to set the current search
    7366                 :   // frame. If we're being called from JS (as here), this window
    7367                 :   // should be the current search frame.
    7368               0 :   nsCOMPtr<nsIWebBrowserFindInFrames> framesFinder(do_QueryInterface(finder));
    7369               0 :   if (framesFinder) {
    7370               0 :     framesFinder->SetRootSearchFrame(this);   // paranoia
    7371               0 :     framesFinder->SetCurrentSearchFrame(this);
    7372                 :   }
    7373                 :   
    7374                 :   // The Find API does not accept empty strings. Launch the Find Dialog.
    7375               0 :   if (aStr.IsEmpty() || aShowDialog) {
    7376                 :     // See if the find dialog is already up using nsIWindowMediator
    7377                 :     nsCOMPtr<nsIWindowMediator> windowMediator =
    7378               0 :       do_GetService(NS_WINDOWMEDIATOR_CONTRACTID);
    7379                 : 
    7380               0 :     nsCOMPtr<nsIDOMWindow> findDialog;
    7381                 : 
    7382               0 :     if (windowMediator) {
    7383               0 :       windowMediator->GetMostRecentWindow(NS_LITERAL_STRING("findInPage").get(),
    7384               0 :                                           getter_AddRefs(findDialog));
    7385                 :     }
    7386                 : 
    7387               0 :     if (findDialog) {
    7388                 :       // The Find dialog is already open, bring it to the top.
    7389               0 :       rv = findDialog->Focus();
    7390                 :     } else { // Open a Find dialog
    7391               0 :       if (finder) {
    7392               0 :         nsCOMPtr<nsIDOMWindow> dialog;
    7393               0 :         rv = OpenDialog(NS_LITERAL_STRING("chrome://global/content/finddialog.xul"),
    7394               0 :                         NS_LITERAL_STRING("_blank"),
    7395               0 :                         NS_LITERAL_STRING("chrome, resizable=no, dependent=yes"),
    7396               0 :                         finder, getter_AddRefs(dialog));
    7397                 :       }
    7398                 :     }
    7399                 :   } else {
    7400                 :     // Launch the search with the passed in search string
    7401               0 :     rv = finder->FindNext(aDidFind);
    7402               0 :     NS_ENSURE_SUCCESS(rv, rv);
    7403                 :   }
    7404                 : 
    7405               0 :   return rv;
    7406                 : }
    7407                 : 
    7408                 : NS_IMETHODIMP
    7409               0 : nsGlobalWindow::Atob(const nsAString& aAsciiBase64String,
    7410                 :                      nsAString& aBinaryData)
    7411                 : {
    7412               0 :   return nsContentUtils::Atob(aAsciiBase64String, aBinaryData);
    7413                 : }
    7414                 : 
    7415                 : NS_IMETHODIMP
    7416               0 : nsGlobalWindow::Btoa(const nsAString& aBinaryData,
    7417                 :                      nsAString& aAsciiBase64String)
    7418                 : {
    7419               0 :   return nsContentUtils::Btoa(aBinaryData, aAsciiBase64String);
    7420                 : }
    7421                 : 
    7422                 : //*****************************************************************************
    7423                 : // nsGlobalWindow::nsIDOMEventTarget
    7424                 : //*****************************************************************************
    7425                 : 
    7426                 : NS_IMETHODIMP
    7427               0 : nsGlobalWindow::RemoveEventListener(const nsAString& aType,
    7428                 :                                     nsIDOMEventListener* aListener,
    7429                 :                                     bool aUseCapture)
    7430                 : {
    7431               0 :   nsRefPtr<nsEventListenerManager> elm = GetListenerManager(false);
    7432               0 :   if (elm) {
    7433               0 :     elm->RemoveEventListener(aType, aListener, aUseCapture);
    7434                 :   }
    7435               0 :   return NS_OK;
    7436                 : }
    7437                 : 
    7438               0 : NS_IMPL_REMOVE_SYSTEM_EVENT_LISTENER(nsGlobalWindow)
    7439                 : 
    7440                 : NS_IMETHODIMP
    7441               0 : nsGlobalWindow::DispatchEvent(nsIDOMEvent* aEvent, bool* aRetVal)
    7442                 : {
    7443               0 :   FORWARD_TO_INNER(DispatchEvent, (aEvent, aRetVal), NS_OK);
    7444                 : 
    7445               0 :   if (!mDoc) {
    7446               0 :     return NS_ERROR_FAILURE;
    7447                 :   }
    7448                 : 
    7449                 :   // Obtain a presentation shell
    7450               0 :   nsIPresShell *shell = mDoc->GetShell();
    7451               0 :   nsRefPtr<nsPresContext> presContext;
    7452               0 :   if (shell) {
    7453                 :     // Retrieve the context
    7454               0 :     presContext = shell->GetPresContext();
    7455                 :   }
    7456                 : 
    7457               0 :   nsEventStatus status = nsEventStatus_eIgnore;
    7458                 :   nsresult rv =
    7459               0 :     nsEventDispatcher::DispatchDOMEvent(GetOuterWindow(), nsnull, aEvent,
    7460               0 :                                         presContext, &status);
    7461                 : 
    7462               0 :   *aRetVal = (status != nsEventStatus_eConsumeNoDefault);
    7463               0 :   return rv;
    7464                 : }
    7465                 : 
    7466                 : NS_IMETHODIMP
    7467               0 : nsGlobalWindow::AddEventListener(const nsAString& aType,
    7468                 :                                  nsIDOMEventListener *aListener,
    7469                 :                                  bool aUseCapture, bool aWantsUntrusted,
    7470                 :                                  PRUint8 aOptionalArgc)
    7471                 : {
    7472               0 :   NS_ASSERTION(!aWantsUntrusted || aOptionalArgc > 1,
    7473                 :                "Won't check if this is chrome, you want to set "
    7474                 :                "aWantsUntrusted to false or make the aWantsUntrusted "
    7475                 :                "explicit by making optional_argc non-zero.");
    7476                 : 
    7477               0 :   if (IsOuterWindow() && mInnerWindow &&
    7478               0 :       !nsContentUtils::CanCallerAccess(mInnerWindow)) {
    7479               0 :     return NS_ERROR_DOM_SECURITY_ERR;
    7480                 :   }
    7481                 : 
    7482               0 :   if (!aWantsUntrusted &&
    7483               0 :       (aOptionalArgc < 2 && !nsContentUtils::IsChromeDoc(mDoc))) {
    7484               0 :     aWantsUntrusted = true;
    7485                 :   }
    7486                 : 
    7487               0 :   nsEventListenerManager* manager = GetListenerManager(true);
    7488               0 :   NS_ENSURE_STATE(manager);
    7489               0 :   manager->AddEventListener(aType, aListener, aUseCapture, aWantsUntrusted);
    7490               0 :   return NS_OK;
    7491                 : }
    7492                 : 
    7493                 : NS_IMETHODIMP
    7494               0 : nsGlobalWindow::AddSystemEventListener(const nsAString& aType,
    7495                 :                                        nsIDOMEventListener *aListener,
    7496                 :                                        bool aUseCapture,
    7497                 :                                        bool aWantsUntrusted,
    7498                 :                                        PRUint8 aOptionalArgc)
    7499                 : {
    7500               0 :   NS_ASSERTION(!aWantsUntrusted || aOptionalArgc > 1,
    7501                 :                "Won't check if this is chrome, you want to set "
    7502                 :                "aWantsUntrusted to false or make the aWantsUntrusted "
    7503                 :                "explicit by making optional_argc non-zero.");
    7504                 : 
    7505               0 :   if (IsOuterWindow() && mInnerWindow &&
    7506               0 :       !nsContentUtils::CanCallerAccess(mInnerWindow)) {
    7507               0 :     return NS_ERROR_DOM_SECURITY_ERR;
    7508                 :   }
    7509                 : 
    7510               0 :   if (!aWantsUntrusted &&
    7511               0 :       (aOptionalArgc < 2 && !nsContentUtils::IsChromeDoc(mDoc))) {
    7512               0 :     aWantsUntrusted = true;
    7513                 :   }
    7514                 : 
    7515                 :   return NS_AddSystemEventListener(this, aType, aListener, aUseCapture,
    7516               0 :                                    aWantsUntrusted);
    7517                 : }
    7518                 : 
    7519                 : nsEventListenerManager*
    7520               0 : nsGlobalWindow::GetListenerManager(bool aCreateIfNotFound)
    7521                 : {
    7522               0 :   FORWARD_TO_INNER_CREATE(GetListenerManager, (aCreateIfNotFound), nsnull);
    7523                 : 
    7524               0 :   if (!mListenerManager && aCreateIfNotFound) {
    7525                 :     mListenerManager =
    7526               0 :       new nsEventListenerManager(static_cast<nsIDOMEventTarget*>(this));
    7527                 :   }
    7528                 : 
    7529               0 :   return mListenerManager;
    7530                 : }
    7531                 : 
    7532                 : nsIScriptContext*
    7533               0 : nsGlobalWindow::GetContextForEventHandlers(nsresult* aRv)
    7534                 : {
    7535               0 :   *aRv = NS_ERROR_UNEXPECTED;
    7536               0 :   if (IsInnerWindow()) {
    7537               0 :     nsPIDOMWindow* outer = GetOuterWindow();
    7538               0 :     NS_ENSURE_TRUE(outer && outer->GetCurrentInnerWindow() == this, nsnull);
    7539                 :   }
    7540                 : 
    7541                 :   nsIScriptContext* scx;
    7542               0 :   if ((scx = GetContext())) {
    7543               0 :     *aRv = NS_OK;
    7544               0 :     return scx;
    7545                 :   }
    7546               0 :   return nsnull;
    7547                 : }
    7548                 : 
    7549                 : //*****************************************************************************
    7550                 : // nsGlobalWindow::nsPIDOMWindow
    7551                 : //*****************************************************************************
    7552                 : 
    7553                 : nsPIDOMWindow*
    7554               0 : nsGlobalWindow::GetPrivateParent()
    7555                 : {
    7556               0 :   FORWARD_TO_OUTER(GetPrivateParent, (), nsnull);
    7557                 : 
    7558               0 :   nsCOMPtr<nsIDOMWindow> parent;
    7559               0 :   GetParent(getter_AddRefs(parent));
    7560                 : 
    7561               0 :   if (static_cast<nsIDOMWindow *>(this) == parent.get()) {
    7562               0 :     nsCOMPtr<nsIContent> chromeElement(do_QueryInterface(mChromeEventHandler));
    7563               0 :     if (!chromeElement)
    7564               0 :       return nsnull;             // This is ok, just means a null parent.
    7565                 : 
    7566               0 :     nsIDocument* doc = chromeElement->GetDocument();
    7567               0 :     if (!doc)
    7568               0 :       return nsnull;             // This is ok, just means a null parent.
    7569                 : 
    7570               0 :     nsIScriptGlobalObject *globalObject = doc->GetScriptGlobalObject();
    7571               0 :     if (!globalObject)
    7572               0 :       return nsnull;             // This is ok, just means a null parent.
    7573                 : 
    7574               0 :     parent = do_QueryInterface(globalObject);
    7575                 :   }
    7576                 : 
    7577               0 :   if (parent) {
    7578                 :     return static_cast<nsGlobalWindow *>
    7579               0 :                       (static_cast<nsIDOMWindow*>(parent.get()));
    7580                 :   }
    7581                 : 
    7582               0 :   return nsnull;
    7583                 : }
    7584                 : 
    7585                 : nsPIDOMWindow*
    7586               0 : nsGlobalWindow::GetPrivateRoot()
    7587                 : {
    7588               0 :   FORWARD_TO_OUTER(GetPrivateRoot, (), nsnull);
    7589                 : 
    7590               0 :   nsCOMPtr<nsIDOMWindow> top;
    7591               0 :   GetTop(getter_AddRefs(top));
    7592                 : 
    7593               0 :   nsCOMPtr<nsPIDOMWindow> ptop = do_QueryInterface(top);
    7594               0 :   NS_ASSERTION(ptop, "cannot get ptop");
    7595               0 :   if (!ptop)
    7596               0 :     return nsnull;
    7597                 : 
    7598               0 :   nsIDocShell *docShell = ptop->GetDocShell();
    7599                 : 
    7600                 :   // Get the chrome event handler from the doc shell, since we only
    7601                 :   // want to deal with XUL chrome handlers and not the new kind of
    7602                 :   // window root handler.
    7603               0 :   nsCOMPtr<nsIDOMEventTarget> chromeEventHandler;
    7604               0 :   docShell->GetChromeEventHandler(getter_AddRefs(chromeEventHandler));
    7605                 : 
    7606               0 :   nsCOMPtr<nsIContent> chromeElement(do_QueryInterface(mChromeEventHandler));
    7607               0 :   if (chromeElement) {
    7608               0 :     nsIDocument* doc = chromeElement->GetDocument();
    7609               0 :     if (doc) {
    7610               0 :       nsIDOMWindow *parent = doc->GetWindow();
    7611               0 :       if (parent) {
    7612               0 :         parent->GetTop(getter_AddRefs(top));
    7613                 :       }
    7614                 :     }
    7615                 :   }
    7616                 : 
    7617                 :   return static_cast<nsGlobalWindow *>
    7618               0 :                     (static_cast<nsIDOMWindow *>(top));
    7619                 : }
    7620                 : 
    7621                 : 
    7622                 : NS_IMETHODIMP
    7623               0 : nsGlobalWindow::GetLocation(nsIDOMLocation ** aLocation)
    7624                 : {
    7625               0 :   FORWARD_TO_INNER(GetLocation, (aLocation), NS_ERROR_NOT_INITIALIZED);
    7626                 : 
    7627               0 :   *aLocation = nsnull;
    7628                 : 
    7629               0 :   nsIDocShell *docShell = GetDocShell();
    7630               0 :   if (!mLocation && docShell) {
    7631               0 :     mLocation = new nsLocation(docShell);
    7632               0 :     if (!mLocation) {
    7633               0 :       return NS_ERROR_OUT_OF_MEMORY;
    7634                 :     }
    7635                 :   }
    7636                 : 
    7637               0 :   NS_IF_ADDREF(*aLocation = mLocation);
    7638                 : 
    7639               0 :   return NS_OK;
    7640                 : }
    7641                 : 
    7642                 : void
    7643               0 : nsGlobalWindow::ActivateOrDeactivate(bool aActivate)
    7644                 : {
    7645                 :   // Set / unset mIsActive on the top level window, which is used for the
    7646                 :   // :-moz-window-inactive pseudoclass.
    7647               0 :   nsCOMPtr<nsIWidget> mainWidget = GetMainWidget();
    7648               0 :   if (!mainWidget)
    7649                 :     return;
    7650                 : 
    7651                 :   // Get the top level widget (if the main widget is a sheet, this will
    7652                 :   // be the sheet's top (non-sheet) parent).
    7653               0 :   nsCOMPtr<nsIWidget> topLevelWidget = mainWidget->GetSheetWindowParent();
    7654               0 :   if (!topLevelWidget) {
    7655               0 :     topLevelWidget = mainWidget;
    7656                 :   }
    7657                 : 
    7658                 :   // Get the top level widget's nsGlobalWindow
    7659               0 :   nsCOMPtr<nsIDOMWindow> topLevelWindow;
    7660               0 :   if (topLevelWidget == mainWidget) {
    7661               0 :     topLevelWindow = static_cast<nsIDOMWindow*>(this);
    7662                 :   } else {
    7663                 :     // This is a workaround for the following problem:
    7664                 :     // When a window with an open sheet loses focus, only the sheet window
    7665                 :     // receives the NS_DEACTIVATE event. However, it's not the sheet that
    7666                 :     // should lose the active styling, but the containing top level window.
    7667                 :     void* clientData;
    7668               0 :     topLevelWidget->GetClientData(clientData); // clientData is nsXULWindow
    7669               0 :     nsISupports* data = static_cast<nsISupports*>(clientData);
    7670               0 :     nsCOMPtr<nsIInterfaceRequestor> req(do_QueryInterface(data));
    7671               0 :     topLevelWindow = do_GetInterface(req);
    7672                 :   }
    7673               0 :   if (topLevelWindow) {
    7674               0 :     nsCOMPtr<nsPIDOMWindow> piWin(do_QueryInterface(topLevelWindow));
    7675               0 :     piWin->SetActive(aActivate);
    7676                 :   }
    7677                 : }
    7678                 : 
    7679                 : static bool
    7680               0 : NotifyDocumentTree(nsIDocument* aDocument, void* aData)
    7681                 : {
    7682               0 :   aDocument->EnumerateSubDocuments(NotifyDocumentTree, nsnull);
    7683               0 :   aDocument->DocumentStatesChanged(NS_DOCUMENT_STATE_WINDOW_INACTIVE);
    7684               0 :   return true;
    7685                 : }
    7686                 : 
    7687                 : void
    7688               0 : nsGlobalWindow::SetActive(bool aActive)
    7689                 : {
    7690               0 :   nsPIDOMWindow::SetActive(aActive);
    7691               0 :   NotifyDocumentTree(mDoc, nsnull);
    7692               0 : }
    7693                 : 
    7694               0 : void nsGlobalWindow::SetIsBackground(bool aIsBackground)
    7695                 : {
    7696               0 :   bool resetTimers = (!aIsBackground && IsBackground());
    7697               0 :   nsPIDOMWindow::SetIsBackground(aIsBackground);
    7698               0 :   if (resetTimers) {
    7699               0 :     ResetTimersForNonBackgroundWindow();
    7700                 :   }
    7701               0 : }
    7702                 : 
    7703               0 : void nsGlobalWindow::MaybeUpdateTouchState()
    7704                 : {
    7705               0 :   FORWARD_TO_INNER_VOID(MaybeUpdateTouchState, ());
    7706                 : 
    7707               0 :   nsIFocusManager* fm = nsFocusManager::GetFocusManager();
    7708                 : 
    7709               0 :   nsCOMPtr<nsIDOMWindow> focusedWindow;
    7710               0 :   fm->GetFocusedWindow(getter_AddRefs(focusedWindow));
    7711                 : 
    7712               0 :   if(this == focusedWindow) {
    7713               0 :     UpdateTouchState();
    7714                 :   }
    7715                 : 
    7716               0 :   if (mMayHaveTouchEventListener) {
    7717                 :     nsCOMPtr<nsIObserverService> observerService =
    7718               0 :       do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
    7719                 : 
    7720               0 :     if (observerService) {
    7721               0 :       observerService->NotifyObservers(static_cast<nsIDOMWindow*>(this),
    7722                 :                                        DOM_TOUCH_LISTENER_ADDED,
    7723               0 :                                        nsnull);
    7724                 :     }
    7725                 :   }
    7726                 : }
    7727                 : 
    7728               0 : void nsGlobalWindow::UpdateTouchState()
    7729                 : {
    7730               0 :   FORWARD_TO_INNER_VOID(UpdateTouchState, ());
    7731                 : 
    7732               0 :   nsCOMPtr<nsIWidget> mainWidget = GetMainWidget();
    7733               0 :   if (!mainWidget) {
    7734                 :     return;
    7735                 :   }
    7736                 : 
    7737               0 :   if (mMayHaveTouchEventListener) {
    7738               0 :     mainWidget->RegisterTouchWindow();
    7739                 :   } else {
    7740               0 :     mainWidget->UnregisterTouchWindow();
    7741                 :   }
    7742                 : }
    7743                 : 
    7744                 : void
    7745               0 : nsGlobalWindow::EnableDeviceMotionUpdates()
    7746                 : {
    7747               0 :   if (mHasDeviceMotion) {
    7748                 :     nsCOMPtr<nsIDeviceMotion> ac =
    7749               0 :       do_GetService(NS_DEVICE_MOTION_CONTRACTID);
    7750               0 :     if (ac) {
    7751               0 :       ac->AddWindowListener(this);
    7752                 :     }
    7753                 :   }
    7754               0 : }
    7755                 : 
    7756                 : void
    7757               0 : nsGlobalWindow::DisableDeviceMotionUpdates()
    7758                 : {
    7759               0 :   if (mHasDeviceMotion) {
    7760                 :     nsCOMPtr<nsIDeviceMotion> ac =
    7761               0 :       do_GetService(NS_DEVICE_MOTION_CONTRACTID);
    7762               0 :     if (ac) {
    7763               0 :       ac->RemoveWindowListener(this);
    7764                 :     }
    7765                 :   }
    7766               0 : }
    7767                 : 
    7768                 : void
    7769               0 : nsGlobalWindow::SetChromeEventHandler(nsIDOMEventTarget* aChromeEventHandler)
    7770                 : {
    7771               0 :   SetChromeEventHandlerInternal(aChromeEventHandler);
    7772               0 :   if (IsOuterWindow()) {
    7773                 :     // update the chrome event handler on all our inner windows
    7774               0 :     for (nsGlobalWindow *inner = (nsGlobalWindow *)PR_LIST_HEAD(this);
    7775                 :          inner != this;
    7776               0 :          inner = (nsGlobalWindow*)PR_NEXT_LINK(inner)) {
    7777               0 :       NS_ASSERTION(!inner->mOuterWindow || inner->mOuterWindow == this,
    7778                 :                    "bad outer window pointer");
    7779               0 :       inner->SetChromeEventHandlerInternal(aChromeEventHandler);
    7780                 :     }
    7781               0 :   } else if (mOuterWindow) {
    7782                 :     // Need the cast to be able to call the protected method on a
    7783                 :     // superclass. We could make the method public instead, but it's really
    7784                 :     // better this way.
    7785               0 :     static_cast<nsGlobalWindow*>(mOuterWindow.get())->
    7786               0 :       SetChromeEventHandlerInternal(aChromeEventHandler);
    7787                 :   }
    7788               0 : }
    7789                 : 
    7790               0 : static bool IsLink(nsIContent* aContent)
    7791                 : {
    7792               0 :   nsCOMPtr<nsIDOMHTMLAnchorElement> anchor = do_QueryInterface(aContent);
    7793                 :   return (anchor || (aContent &&
    7794                 :                      aContent->AttrValueIs(kNameSpaceID_XLink, nsGkAtoms::type,
    7795               0 :                                            nsGkAtoms::simple, eCaseMatters)));
    7796                 : }
    7797                 : 
    7798                 : void
    7799               0 : nsGlobalWindow::SetFocusedNode(nsIContent* aNode,
    7800                 :                                PRUint32 aFocusMethod,
    7801                 :                                bool aNeedsFocus)
    7802                 : {
    7803               0 :   FORWARD_TO_INNER_VOID(SetFocusedNode, (aNode, aFocusMethod, aNeedsFocus));
    7804                 : 
    7805               0 :   if (aNode && aNode->GetCurrentDoc() != mDoc) {
    7806               0 :     NS_WARNING("Trying to set focus to a node from a wrong document");
    7807               0 :     return;
    7808                 :   }
    7809                 : 
    7810               0 :   if (mCleanedUp) {
    7811               0 :     NS_ASSERTION(!aNode, "Trying to focus cleaned up window!");
    7812               0 :     aNode = nsnull;
    7813               0 :     aNeedsFocus = false;
    7814                 :   }
    7815               0 :   if (mFocusedNode != aNode) {
    7816               0 :     UpdateCanvasFocus(false, aNode);
    7817               0 :     mFocusedNode = aNode;
    7818               0 :     mFocusMethod = aFocusMethod & FOCUSMETHOD_MASK;
    7819               0 :     mShowFocusRingForContent = false;
    7820                 :   }
    7821                 : 
    7822               0 :   if (mFocusedNode) {
    7823                 :     // if a node was focused by a keypress, turn on focus rings for the
    7824                 :     // window.
    7825               0 :     if (mFocusMethod & nsIFocusManager::FLAG_BYKEY) {
    7826               0 :       mFocusByKeyOccurred = true;
    7827               0 :     } else if (
    7828                 :       // otherwise, we set mShowFocusRingForContent, as we don't want this to
    7829                 :       // be permanent for the window. On Windows, focus rings are only shown
    7830                 :       // when the FLAG_SHOWRING flag is used. On other platforms, focus rings
    7831                 :       // are only hidden for clicks on links.
    7832                 : #ifndef XP_WIN
    7833               0 :       !(mFocusMethod & nsIFocusManager::FLAG_BYMOUSE) || !IsLink(aNode) ||
    7834                 : #endif
    7835                 :       aFocusMethod & nsIFocusManager::FLAG_SHOWRING) {
    7836               0 :         mShowFocusRingForContent = true;
    7837                 :     }
    7838                 :   }
    7839                 : 
    7840               0 :   if (aNeedsFocus)
    7841               0 :     mNeedsFocus = aNeedsFocus;
    7842                 : }
    7843                 : 
    7844                 : PRUint32
    7845               0 : nsGlobalWindow::GetFocusMethod()
    7846                 : {
    7847               0 :   FORWARD_TO_INNER(GetFocusMethod, (), 0);
    7848                 : 
    7849               0 :   return mFocusMethod;
    7850                 : }
    7851                 : 
    7852                 : bool
    7853               0 : nsGlobalWindow::ShouldShowFocusRing()
    7854                 : {
    7855               0 :   FORWARD_TO_INNER(ShouldShowFocusRing, (), false);
    7856                 : 
    7857               0 :   return mShowFocusRings || mShowFocusRingForContent || mFocusByKeyOccurred;
    7858                 : }
    7859                 : 
    7860                 : void
    7861               0 : nsGlobalWindow::SetKeyboardIndicators(UIStateChangeType aShowAccelerators,
    7862                 :                                       UIStateChangeType aShowFocusRings)
    7863                 : {
    7864               0 :   FORWARD_TO_INNER_VOID(SetKeyboardIndicators, (aShowAccelerators, aShowFocusRings));
    7865                 : 
    7866               0 :   bool oldShouldShowFocusRing = ShouldShowFocusRing();
    7867                 : 
    7868                 :   // only change the flags that have been modified
    7869               0 :   if (aShowAccelerators != UIStateChangeType_NoChange)
    7870               0 :     mShowAccelerators = aShowAccelerators == UIStateChangeType_Set;
    7871               0 :   if (aShowFocusRings != UIStateChangeType_NoChange)
    7872               0 :     mShowFocusRings = aShowFocusRings == UIStateChangeType_Set;
    7873                 : 
    7874                 :   // propagate the indicators to child windows
    7875               0 :   nsCOMPtr<nsIDocShellTreeNode> node = do_QueryInterface(GetDocShell());
    7876               0 :   if (node) {
    7877               0 :     PRInt32 childCount = 0;
    7878               0 :     node->GetChildCount(&childCount);
    7879                 : 
    7880               0 :     for (PRInt32 i = 0; i < childCount; ++i) {
    7881               0 :       nsCOMPtr<nsIDocShellTreeItem> childShell;
    7882               0 :       node->GetChildAt(i, getter_AddRefs(childShell));
    7883               0 :       nsCOMPtr<nsPIDOMWindow> childWindow = do_GetInterface(childShell);
    7884               0 :       if (childWindow) {
    7885               0 :         childWindow->SetKeyboardIndicators(aShowAccelerators, aShowFocusRings);
    7886                 :       }
    7887                 :     }
    7888                 :   }
    7889                 : 
    7890               0 :   bool newShouldShowFocusRing = ShouldShowFocusRing();
    7891               0 :   if (mHasFocus && mFocusedNode &&
    7892                 :       oldShouldShowFocusRing != newShouldShowFocusRing &&
    7893               0 :       mFocusedNode->IsElement()) {
    7894                 :     // Update mFocusedNode's state.
    7895               0 :     if (newShouldShowFocusRing) {
    7896               0 :       mFocusedNode->AsElement()->AddStates(NS_EVENT_STATE_FOCUSRING);
    7897                 :     } else {
    7898               0 :       mFocusedNode->AsElement()->RemoveStates(NS_EVENT_STATE_FOCUSRING);
    7899                 :     }
    7900                 :   }
    7901                 : }
    7902                 : 
    7903                 : void
    7904               0 : nsGlobalWindow::GetKeyboardIndicators(bool* aShowAccelerators,
    7905                 :                                       bool* aShowFocusRings)
    7906                 : {
    7907               0 :   FORWARD_TO_INNER_VOID(GetKeyboardIndicators, (aShowAccelerators, aShowFocusRings));
    7908                 : 
    7909               0 :   *aShowAccelerators = mShowAccelerators;
    7910               0 :   *aShowFocusRings = mShowFocusRings;
    7911                 : }
    7912                 : 
    7913                 : bool
    7914               0 : nsGlobalWindow::TakeFocus(bool aFocus, PRUint32 aFocusMethod)
    7915                 : {
    7916               0 :   FORWARD_TO_INNER(TakeFocus, (aFocus, aFocusMethod), false);
    7917                 : 
    7918               0 :   if (mCleanedUp) {
    7919               0 :     return false;
    7920                 :   }
    7921                 :   
    7922               0 :   if (aFocus)
    7923               0 :     mFocusMethod = aFocusMethod & FOCUSMETHOD_MASK;
    7924                 : 
    7925               0 :   if (mHasFocus != aFocus) {
    7926               0 :     mHasFocus = aFocus;
    7927               0 :     UpdateCanvasFocus(true, mFocusedNode);
    7928                 :   }
    7929                 : 
    7930                 :   // if mNeedsFocus is true, then the document has not yet received a
    7931                 :   // document-level focus event. If there is a root content node, then return
    7932                 :   // true to tell the calling focus manager that a focus event is expected. If
    7933                 :   // there is no root content node, the document hasn't loaded enough yet, or
    7934                 :   // there isn't one and there is no point in firing a focus event.
    7935               0 :   if (aFocus && mNeedsFocus && mDoc && mDoc->GetRootElement() != nsnull) {
    7936               0 :     mNeedsFocus = false;
    7937               0 :     return true;
    7938                 :   }
    7939                 : 
    7940               0 :   mNeedsFocus = false;
    7941               0 :   return false;
    7942                 : }
    7943                 : 
    7944                 : void
    7945               0 : nsGlobalWindow::SetReadyForFocus()
    7946                 : {
    7947               0 :   FORWARD_TO_INNER_VOID(SetReadyForFocus, ());
    7948                 : 
    7949               0 :   bool oldNeedsFocus = mNeedsFocus;
    7950               0 :   mNeedsFocus = false;
    7951                 : 
    7952                 :   // update whether focus rings need to be shown using the state from the
    7953                 :   // root window
    7954               0 :   nsPIDOMWindow* root = GetPrivateRoot();
    7955               0 :   if (root) {
    7956                 :     bool showAccelerators, showFocusRings;
    7957               0 :     root->GetKeyboardIndicators(&showAccelerators, &showFocusRings);
    7958               0 :     mShowFocusRings = showFocusRings;
    7959                 :   }
    7960                 : 
    7961               0 :   nsIFocusManager* fm = nsFocusManager::GetFocusManager();
    7962               0 :   if (fm)
    7963               0 :     fm->WindowShown(this, oldNeedsFocus);
    7964                 : }
    7965                 : 
    7966                 : void
    7967               0 : nsGlobalWindow::PageHidden()
    7968                 : {
    7969               0 :   FORWARD_TO_INNER_VOID(PageHidden, ());
    7970                 : 
    7971                 :   // the window is being hidden, so tell the focus manager that the frame is
    7972                 :   // no longer valid. Use the persisted field to determine if the document
    7973                 :   // is being destroyed.
    7974                 : 
    7975               0 :   nsIFocusManager* fm = nsFocusManager::GetFocusManager();
    7976               0 :   if (fm)
    7977               0 :     fm->WindowHidden(this);
    7978                 : 
    7979               0 :   mNeedsFocus = true;
    7980                 : }
    7981                 : 
    7982                 : class HashchangeCallback : public nsRunnable
    7983               0 : {
    7984                 : public:
    7985               0 :   HashchangeCallback(const nsAString &aOldURL,
    7986                 :                      const nsAString &aNewURL,
    7987                 :                      nsGlobalWindow* aWindow)
    7988               0 :     : mWindow(aWindow)
    7989                 :   {
    7990               0 :     mOldURL.Assign(aOldURL);
    7991               0 :     mNewURL.Assign(aNewURL);
    7992               0 :   }
    7993                 : 
    7994               0 :   NS_IMETHOD Run()
    7995                 :   {
    7996               0 :     NS_PRECONDITION(NS_IsMainThread(), "Should be called on the main thread.");
    7997               0 :     return mWindow->FireHashchange(mOldURL, mNewURL);
    7998                 :   }
    7999                 : 
    8000                 : private:
    8001                 :   nsString mOldURL;
    8002                 :   nsString mNewURL;
    8003                 :   nsRefPtr<nsGlobalWindow> mWindow;
    8004                 : };
    8005                 : 
    8006                 : nsresult
    8007               0 : nsGlobalWindow::DispatchAsyncHashchange(nsIURI *aOldURI, nsIURI *aNewURI)
    8008                 : {
    8009               0 :   FORWARD_TO_INNER(DispatchAsyncHashchange, (aOldURI, aNewURI), NS_OK);
    8010                 : 
    8011                 :   // Make sure that aOldURI and aNewURI are identical up to the '#', and that
    8012                 :   // their hashes are different.
    8013               0 :   nsCAutoString oldBeforeHash, oldHash, newBeforeHash, newHash;
    8014               0 :   nsContentUtils::SplitURIAtHash(aOldURI, oldBeforeHash, oldHash);
    8015               0 :   nsContentUtils::SplitURIAtHash(aNewURI, newBeforeHash, newHash);
    8016                 : 
    8017               0 :   NS_ENSURE_STATE(oldBeforeHash.Equals(newBeforeHash));
    8018               0 :   NS_ENSURE_STATE(!oldHash.Equals(newHash));
    8019                 : 
    8020               0 :   nsCAutoString oldSpec, newSpec;
    8021               0 :   aOldURI->GetSpec(oldSpec);
    8022               0 :   aNewURI->GetSpec(newSpec);
    8023                 : 
    8024               0 :   NS_ConvertUTF8toUTF16 oldWideSpec(oldSpec);
    8025               0 :   NS_ConvertUTF8toUTF16 newWideSpec(newSpec);
    8026                 : 
    8027                 :   nsCOMPtr<nsIRunnable> callback =
    8028               0 :     new HashchangeCallback(oldWideSpec, newWideSpec, this);
    8029               0 :   return NS_DispatchToMainThread(callback);
    8030                 : }
    8031                 : 
    8032                 : nsresult
    8033               0 : nsGlobalWindow::FireHashchange(const nsAString &aOldURL,
    8034                 :                                const nsAString &aNewURL)
    8035                 : {
    8036               0 :   NS_ENSURE_TRUE(IsInnerWindow(), NS_ERROR_FAILURE);
    8037                 : 
    8038                 :   // Don't do anything if the window is frozen.
    8039               0 :   if (IsFrozen())
    8040               0 :     return NS_OK;
    8041                 : 
    8042                 :   // Get a presentation shell for use in creating the hashchange event.
    8043               0 :   NS_ENSURE_STATE(mDoc);
    8044                 : 
    8045               0 :   nsIPresShell *shell = mDoc->GetShell();
    8046               0 :   nsRefPtr<nsPresContext> presContext;
    8047               0 :   if (shell) {
    8048               0 :     presContext = shell->GetPresContext();
    8049                 :   }
    8050                 : 
    8051                 :   // Create a new hashchange event.
    8052               0 :   nsCOMPtr<nsIDOMEvent> domEvent;
    8053                 :   nsresult rv =
    8054                 :     nsEventDispatcher::CreateEvent(presContext, nsnull,
    8055               0 :                                    NS_LITERAL_STRING("hashchangeevent"),
    8056               0 :                                    getter_AddRefs(domEvent));
    8057               0 :   NS_ENSURE_SUCCESS(rv, rv);
    8058                 : 
    8059               0 :   nsCOMPtr<nsIPrivateDOMEvent> privateEvent = do_QueryInterface(domEvent);
    8060               0 :   NS_ENSURE_TRUE(privateEvent, NS_ERROR_UNEXPECTED);
    8061                 : 
    8062               0 :   nsCOMPtr<nsIDOMHashChangeEvent> hashchangeEvent = do_QueryInterface(domEvent);
    8063               0 :   NS_ENSURE_TRUE(hashchangeEvent, NS_ERROR_UNEXPECTED);
    8064                 : 
    8065                 :   // The hashchange event bubbles and isn't cancellable.
    8066               0 :   rv = hashchangeEvent->InitHashChangeEvent(NS_LITERAL_STRING("hashchange"),
    8067                 :                                             true, false,
    8068               0 :                                             aOldURL, aNewURL);
    8069               0 :   NS_ENSURE_SUCCESS(rv, rv);
    8070                 : 
    8071               0 :   rv = privateEvent->SetTrusted(true);
    8072               0 :   NS_ENSURE_SUCCESS(rv, rv);
    8073                 : 
    8074                 :   bool dummy;
    8075               0 :   return DispatchEvent(hashchangeEvent, &dummy);
    8076                 : }
    8077                 : 
    8078                 : nsresult
    8079               0 : nsGlobalWindow::DispatchSyncPopState()
    8080                 : {
    8081               0 :   FORWARD_TO_INNER(DispatchSyncPopState, (), NS_OK);
    8082                 : 
    8083               0 :   NS_ASSERTION(nsContentUtils::IsSafeToRunScript(),
    8084                 :                "Must be safe to run script here.");
    8085                 : 
    8086                 :   // Check that PopState hasn't been pref'ed off.
    8087               0 :   if (!Preferences::GetBool(sPopStatePrefStr, false)) {
    8088               0 :     return NS_OK;
    8089                 :   }
    8090                 : 
    8091               0 :   nsresult rv = NS_OK;
    8092                 : 
    8093                 :   // Bail if the window is frozen.
    8094               0 :   if (IsFrozen()) {
    8095               0 :     return NS_OK;
    8096                 :   }
    8097                 : 
    8098                 :   // Get the document's pending state object -- it contains the data we're
    8099                 :   // going to send along with the popstate event.  The object is serialized
    8100                 :   // using structured clone.
    8101               0 :   nsCOMPtr<nsIVariant> stateObj;
    8102               0 :   rv = mDoc->GetStateObject(getter_AddRefs(stateObj));
    8103               0 :   NS_ENSURE_SUCCESS(rv, rv);
    8104                 : 
    8105                 :   // Obtain a presentation shell for use in creating a popstate event.
    8106               0 :   nsIPresShell *shell = mDoc->GetShell();
    8107               0 :   nsRefPtr<nsPresContext> presContext;
    8108               0 :   if (shell) {
    8109               0 :     presContext = shell->GetPresContext();
    8110                 :   }
    8111                 : 
    8112                 :   // Create a new popstate event
    8113               0 :   nsCOMPtr<nsIDOMEvent> domEvent;
    8114                 :   rv = nsEventDispatcher::CreateEvent(presContext, nsnull,
    8115               0 :                                       NS_LITERAL_STRING("popstateevent"),
    8116               0 :                                       getter_AddRefs(domEvent));
    8117               0 :   NS_ENSURE_SUCCESS(rv, rv);
    8118                 : 
    8119               0 :   nsCOMPtr<nsIPrivateDOMEvent> privateEvent = do_QueryInterface(domEvent);
    8120               0 :   NS_ENSURE_TRUE(privateEvent, NS_ERROR_FAILURE);
    8121                 : 
    8122                 :   // Initialize the popstate event, which does bubble but isn't cancellable.
    8123               0 :   nsCOMPtr<nsIDOMPopStateEvent> popstateEvent = do_QueryInterface(domEvent);
    8124               0 :   rv = popstateEvent->InitPopStateEvent(NS_LITERAL_STRING("popstate"),
    8125                 :                                         true, false,
    8126               0 :                                         stateObj);
    8127               0 :   NS_ENSURE_SUCCESS(rv, rv);
    8128                 : 
    8129               0 :   rv = privateEvent->SetTrusted(true);
    8130               0 :   NS_ENSURE_SUCCESS(rv, rv);
    8131                 : 
    8132                 :   nsCOMPtr<nsIDOMEventTarget> outerWindow =
    8133               0 :     do_QueryInterface(GetOuterWindow());
    8134               0 :   NS_ENSURE_TRUE(outerWindow, NS_ERROR_UNEXPECTED);
    8135                 : 
    8136               0 :   rv = privateEvent->SetTarget(outerWindow);
    8137               0 :   NS_ENSURE_SUCCESS(rv, rv);
    8138                 : 
    8139                 :   bool dummy; // default action
    8140               0 :   return DispatchEvent(popstateEvent, &dummy);
    8141                 : }
    8142                 : 
    8143                 : // Find an nsICanvasFrame under aFrame.  Only search the principal
    8144                 : // child lists.  aFrame must be non-null.
    8145               0 : static nsCanvasFrame* FindCanvasFrame(nsIFrame* aFrame)
    8146                 : {
    8147               0 :     nsCanvasFrame* canvasFrame = do_QueryFrame(aFrame);
    8148               0 :     if (canvasFrame) {
    8149               0 :         return canvasFrame;
    8150                 :     }
    8151                 : 
    8152               0 :     nsIFrame* kid = aFrame->GetFirstPrincipalChild();
    8153               0 :     while (kid) {
    8154               0 :         canvasFrame = FindCanvasFrame(kid);
    8155               0 :         if (canvasFrame) {
    8156               0 :             return canvasFrame;
    8157                 :         }
    8158               0 :         kid = kid->GetNextSibling();
    8159                 :     }
    8160                 : 
    8161               0 :     return nsnull;
    8162                 : }
    8163                 : 
    8164                 : //-------------------------------------------------------
    8165                 : // Tells the HTMLFrame/CanvasFrame that is now has focus
    8166                 : void
    8167               0 : nsGlobalWindow::UpdateCanvasFocus(bool aFocusChanged, nsIContent* aNewContent)
    8168                 : {
    8169                 :   // this is called from the inner window so use GetDocShell
    8170               0 :   nsIDocShell* docShell = GetDocShell();
    8171               0 :   if (!docShell)
    8172               0 :     return;
    8173                 : 
    8174               0 :   nsCOMPtr<nsIEditorDocShell> editorDocShell = do_QueryInterface(docShell);
    8175               0 :   if (editorDocShell) {
    8176                 :     bool editable;
    8177               0 :     editorDocShell->GetEditable(&editable);
    8178               0 :     if (editable)
    8179                 :       return;
    8180                 :   }
    8181                 : 
    8182               0 :   nsCOMPtr<nsIPresShell> presShell;
    8183               0 :   docShell->GetPresShell(getter_AddRefs(presShell));
    8184               0 :   if (!presShell || !mDocument)
    8185                 :     return;
    8186                 : 
    8187               0 :   nsCOMPtr<nsIDocument> doc(do_QueryInterface(mDocument));
    8188               0 :   Element *rootElement = doc->GetRootElement();
    8189               0 :   if (rootElement) {
    8190               0 :       if ((mHasFocus || aFocusChanged) &&
    8191               0 :           (mFocusedNode == rootElement || aNewContent == rootElement)) {
    8192               0 :           nsIFrame* frame = rootElement->GetPrimaryFrame();
    8193               0 :           if (frame) {
    8194               0 :               frame = frame->GetParent();
    8195               0 :               nsCanvasFrame* canvasFrame = do_QueryFrame(frame);
    8196               0 :               if (canvasFrame) {
    8197               0 :                   canvasFrame->SetHasFocus(mHasFocus && rootElement == aNewContent);
    8198                 :               }
    8199                 :           }
    8200                 :       }
    8201                 :   } else {
    8202                 :       // Look for the frame the hard way
    8203               0 :       nsIFrame* frame = presShell->GetRootFrame();
    8204               0 :       if (frame) {
    8205               0 :           nsCanvasFrame* canvasFrame = FindCanvasFrame(frame);
    8206               0 :           if (canvasFrame) {
    8207               0 :               canvasFrame->SetHasFocus(false);
    8208                 :           }
    8209                 :       }      
    8210                 :   }
    8211                 : }
    8212                 : 
    8213                 : NS_IMETHODIMP
    8214               0 : nsGlobalWindow::GetComputedStyle(nsIDOMElement* aElt,
    8215                 :                                  const nsAString& aPseudoElt,
    8216                 :                                  nsIDOMCSSStyleDeclaration** aReturn)
    8217                 : {
    8218               0 :   FORWARD_TO_OUTER(GetComputedStyle, (aElt, aPseudoElt, aReturn),
    8219                 :                    NS_ERROR_NOT_INITIALIZED);
    8220                 : 
    8221               0 :   NS_ENSURE_ARG_POINTER(aReturn);
    8222               0 :   *aReturn = nsnull;
    8223                 : 
    8224               0 :   if (!aElt) {
    8225               0 :     return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
    8226                 :   }
    8227                 : 
    8228               0 :   if (!mDocShell) {
    8229               0 :     return NS_OK;
    8230                 :   }
    8231                 : 
    8232               0 :   nsCOMPtr<nsIPresShell> presShell;
    8233               0 :   mDocShell->GetPresShell(getter_AddRefs(presShell));
    8234                 : 
    8235               0 :   if (!presShell) {
    8236               0 :     return NS_OK;
    8237                 :   }
    8238                 : 
    8239               0 :   nsRefPtr<nsComputedDOMStyle> compStyle;
    8240                 :   nsresult rv = NS_NewComputedDOMStyle(aElt, aPseudoElt, presShell,
    8241               0 :                                        getter_AddRefs(compStyle));
    8242               0 :   NS_ENSURE_SUCCESS(rv, rv);
    8243                 : 
    8244               0 :   *aReturn = compStyle.forget().get();
    8245                 : 
    8246               0 :   return NS_OK;
    8247                 : }
    8248                 : 
    8249                 : NS_IMETHODIMP
    8250               0 : nsGlobalWindow::GetSessionStorage(nsIDOMStorage ** aSessionStorage)
    8251                 : {
    8252               0 :   FORWARD_TO_INNER(GetSessionStorage, (aSessionStorage), NS_ERROR_UNEXPECTED);
    8253                 : 
    8254               0 :   nsIPrincipal *principal = GetPrincipal();
    8255               0 :   nsIDocShell* docShell = GetDocShell();
    8256                 : 
    8257               0 :   if (!principal || !docShell) {
    8258               0 :     *aSessionStorage = nsnull;
    8259               0 :     return NS_OK;
    8260                 :   }
    8261                 : 
    8262               0 :   if (!Preferences::GetBool(kStorageEnabled)) {
    8263               0 :     *aSessionStorage = nsnull;
    8264               0 :     return NS_OK;
    8265                 :   }
    8266                 : 
    8267               0 :   if (mSessionStorage) {
    8268                 : #ifdef PR_LOGGING
    8269               0 :     if (PR_LOG_TEST(gDOMLeakPRLog, PR_LOG_DEBUG)) {
    8270               0 :       PR_LogPrint("nsGlobalWindow %p has %p sessionStorage", this, mSessionStorage.get());
    8271                 :     }
    8272                 : #endif
    8273               0 :     nsCOMPtr<nsPIDOMStorage> piStorage = do_QueryInterface(mSessionStorage);
    8274               0 :     if (piStorage) {
    8275               0 :       bool canAccess = piStorage->CanAccess(principal);
    8276               0 :       NS_ASSERTION(canAccess,
    8277                 :                    "window %x owned sessionStorage "
    8278                 :                    "that could not be accessed!");
    8279               0 :       if (!canAccess) {
    8280               0 :           mSessionStorage = nsnull;
    8281                 :       }
    8282                 :     }
    8283                 :   }
    8284                 : 
    8285               0 :   if (!mSessionStorage) {
    8286               0 :     *aSessionStorage = nsnull;
    8287                 : 
    8288               0 :     nsString documentURI;
    8289               0 :     if (mDocument) {
    8290               0 :       mDocument->GetDocumentURI(documentURI);
    8291                 :     }
    8292                 : 
    8293                 :     nsresult rv = docShell->GetSessionStorageForPrincipal(principal,
    8294                 :                                                           documentURI,
    8295                 :                                                           true,
    8296               0 :                                                           getter_AddRefs(mSessionStorage));
    8297               0 :     NS_ENSURE_SUCCESS(rv, rv);
    8298                 : 
    8299                 : #ifdef PR_LOGGING
    8300               0 :     if (PR_LOG_TEST(gDOMLeakPRLog, PR_LOG_DEBUG)) {
    8301               0 :       PR_LogPrint("nsGlobalWindow %p tried to get a new sessionStorage %p", this, mSessionStorage.get());
    8302                 :     }
    8303                 : #endif
    8304                 : 
    8305               0 :     if (!mSessionStorage) {
    8306               0 :       return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
    8307                 :     }
    8308                 :   }
    8309                 : 
    8310                 : #ifdef PR_LOGGING
    8311               0 :     if (PR_LOG_TEST(gDOMLeakPRLog, PR_LOG_DEBUG)) {
    8312               0 :       PR_LogPrint("nsGlobalWindow %p returns %p sessionStorage", this, mSessionStorage.get());
    8313                 :     }
    8314                 : #endif
    8315                 : 
    8316               0 :   NS_ADDREF(*aSessionStorage = mSessionStorage);
    8317               0 :   return NS_OK;
    8318                 : }
    8319                 : 
    8320                 : NS_IMETHODIMP
    8321               0 : nsGlobalWindow::GetLocalStorage(nsIDOMStorage ** aLocalStorage)
    8322                 : {
    8323               0 :   FORWARD_TO_INNER(GetLocalStorage, (aLocalStorage), NS_ERROR_UNEXPECTED);
    8324                 : 
    8325               0 :   NS_ENSURE_ARG(aLocalStorage);
    8326                 : 
    8327               0 :   if (!Preferences::GetBool(kStorageEnabled)) {
    8328               0 :     *aLocalStorage = nsnull;
    8329               0 :     return NS_OK;
    8330                 :   }
    8331                 : 
    8332               0 :   if (!mLocalStorage) {
    8333               0 :     *aLocalStorage = nsnull;
    8334                 : 
    8335                 :     nsresult rv;
    8336                 : 
    8337                 :     bool unused;
    8338               0 :     if (!nsDOMStorage::CanUseStorage(&unused))
    8339               0 :       return NS_ERROR_DOM_SECURITY_ERR;
    8340                 : 
    8341               0 :     nsIPrincipal *principal = GetPrincipal();
    8342               0 :     if (!principal)
    8343               0 :       return NS_OK;
    8344                 : 
    8345                 :     nsCOMPtr<nsIDOMStorageManager> storageManager =
    8346               0 :       do_GetService("@mozilla.org/dom/storagemanager;1", &rv);
    8347               0 :     NS_ENSURE_SUCCESS(rv, rv);
    8348                 : 
    8349               0 :     nsString documentURI;
    8350               0 :     if (mDocument) {
    8351               0 :       mDocument->GetDocumentURI(documentURI);
    8352                 :     }
    8353                 : 
    8354               0 :     rv = storageManager->GetLocalStorageForPrincipal(principal,
    8355                 :                                                      documentURI,
    8356               0 :                                                      getter_AddRefs(mLocalStorage));
    8357               0 :     NS_ENSURE_SUCCESS(rv, rv);
    8358                 :   }
    8359                 : 
    8360               0 :   NS_ADDREF(*aLocalStorage = mLocalStorage);
    8361               0 :   return NS_OK;
    8362                 : }
    8363                 : 
    8364                 : //*****************************************************************************
    8365                 : // nsGlobalWindow::nsIDOMStorageIndexedDB
    8366                 : //*****************************************************************************
    8367                 : 
    8368                 : NS_IMETHODIMP
    8369               0 : nsGlobalWindow::GetMozIndexedDB(nsIIDBFactory** _retval)
    8370                 : {
    8371               0 :   if (!mIndexedDB) {
    8372               0 :     if (!IsChromeWindow()) {
    8373                 :       nsCOMPtr<mozIThirdPartyUtil> thirdPartyUtil =
    8374               0 :         do_GetService(THIRDPARTYUTIL_CONTRACTID);
    8375               0 :       NS_ENSURE_TRUE(thirdPartyUtil, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
    8376                 : 
    8377                 :       bool isThirdParty;
    8378               0 :       nsresult rv = thirdPartyUtil->IsThirdPartyWindow(this, nsnull,
    8379               0 :                                                        &isThirdParty);
    8380               0 :       NS_ENSURE_SUCCESS(rv, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
    8381                 : 
    8382               0 :       if (isThirdParty) {
    8383               0 :         NS_WARNING("IndexedDB is not permitted in a third-party window.");
    8384               0 :         *_retval = nsnull;
    8385               0 :         return NS_OK;
    8386                 :       }
    8387                 :     }
    8388                 : 
    8389               0 :     mIndexedDB = indexedDB::IDBFactory::Create(this);
    8390               0 :     NS_ENSURE_TRUE(mIndexedDB, NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
    8391                 :   }
    8392                 : 
    8393               0 :   nsCOMPtr<nsIIDBFactory> request(mIndexedDB);
    8394               0 :   request.forget(_retval);
    8395               0 :   return NS_OK;
    8396                 : }
    8397                 : 
    8398                 : //*****************************************************************************
    8399                 : // nsGlobalWindow::nsIInterfaceRequestor
    8400                 : //*****************************************************************************
    8401                 : 
    8402                 : NS_IMETHODIMP
    8403               0 : nsGlobalWindow::GetInterface(const nsIID & aIID, void **aSink)
    8404                 : {
    8405               0 :   NS_ENSURE_ARG_POINTER(aSink);
    8406               0 :   *aSink = nsnull;
    8407                 : 
    8408               0 :   if (aIID.Equals(NS_GET_IID(nsIDocCharset))) {
    8409               0 :     FORWARD_TO_OUTER(GetInterface, (aIID, aSink), NS_ERROR_NOT_INITIALIZED);
    8410                 : 
    8411               0 :     if (mDocShell) {
    8412               0 :       nsCOMPtr<nsIDocCharset> docCharset(do_QueryInterface(mDocShell));
    8413               0 :       if (docCharset) {
    8414               0 :         NS_WARNING("Using deprecated nsIDocCharset: use nsIDocShell.GetCharset() instead ");
    8415               0 :         *aSink = docCharset;
    8416               0 :         NS_ADDREF(((nsISupports *) *aSink));
    8417                 :       }
    8418                 :     }
    8419                 :   }
    8420               0 :   else if (aIID.Equals(NS_GET_IID(nsIWebNavigation))) {
    8421               0 :     FORWARD_TO_OUTER(GetInterface, (aIID, aSink), NS_ERROR_NOT_INITIALIZED);
    8422                 : 
    8423               0 :     if (mDocShell) {
    8424               0 :       nsCOMPtr<nsIWebNavigation> webNav(do_QueryInterface(mDocShell));
    8425               0 :       if (webNav) {
    8426               0 :         *aSink = webNav;
    8427               0 :         NS_ADDREF(((nsISupports *) *aSink));
    8428                 :       }
    8429                 :     }
    8430                 :   }
    8431                 : #ifdef NS_PRINTING
    8432               0 :   else if (aIID.Equals(NS_GET_IID(nsIWebBrowserPrint))) {
    8433               0 :     FORWARD_TO_OUTER(GetInterface, (aIID, aSink), NS_ERROR_NOT_INITIALIZED);
    8434                 : 
    8435               0 :     if (mDocShell) {
    8436               0 :       nsCOMPtr<nsIContentViewer> viewer;
    8437               0 :       mDocShell->GetContentViewer(getter_AddRefs(viewer));
    8438               0 :       if (viewer) {
    8439               0 :         nsCOMPtr<nsIWebBrowserPrint> webBrowserPrint(do_QueryInterface(viewer));
    8440               0 :         if (webBrowserPrint) {
    8441               0 :           *aSink = webBrowserPrint;
    8442               0 :           NS_ADDREF(((nsISupports *) *aSink));
    8443                 :         }
    8444                 :       }
    8445                 :     }
    8446                 :   }
    8447                 : #endif
    8448               0 :   else if (aIID.Equals(NS_GET_IID(nsIDOMWindowUtils))) {
    8449               0 :     FORWARD_TO_OUTER(GetInterface, (aIID, aSink), NS_ERROR_NOT_INITIALIZED);
    8450                 : 
    8451               0 :     nsCOMPtr<nsISupports> utils(do_QueryReferent(mWindowUtils));
    8452               0 :     if (utils) {
    8453               0 :       *aSink = utils;
    8454               0 :       NS_ADDREF(((nsISupports *) *aSink));
    8455                 :     } else {
    8456               0 :       nsDOMWindowUtils *utilObj = new nsDOMWindowUtils(this);
    8457                 :       nsCOMPtr<nsISupports> utilsIfc =
    8458               0 :                               NS_ISUPPORTS_CAST(nsIDOMWindowUtils *, utilObj);
    8459               0 :       if (utilsIfc) {
    8460               0 :         mWindowUtils = do_GetWeakReference(utilsIfc);
    8461               0 :         *aSink = utilsIfc;
    8462               0 :         NS_ADDREF(((nsISupports *) *aSink));
    8463                 :       }
    8464                 :     }
    8465                 :   }
    8466                 :   else {
    8467               0 :     return QueryInterface(aIID, aSink);
    8468                 :   }
    8469                 : 
    8470               0 :   return *aSink ? NS_OK : NS_ERROR_NO_INTERFACE;
    8471                 : }
    8472                 : 
    8473                 : void
    8474               0 : nsGlobalWindow::FireOfflineStatusEvent()
    8475                 : {
    8476               0 :   if (!mDoc)
    8477               0 :     return;
    8478               0 :   nsAutoString name;
    8479               0 :   if (NS_IsOffline()) {
    8480               0 :     name.AssignLiteral("offline");
    8481                 :   } else {
    8482               0 :     name.AssignLiteral("online");
    8483                 :   }
    8484                 :   // The event is fired at the body element, or if there is no body element,
    8485                 :   // at the document.
    8486               0 :   nsCOMPtr<nsISupports> eventTarget = mDoc.get();
    8487               0 :   nsCOMPtr<nsIDOMHTMLDocument> htmlDoc = do_QueryInterface(mDoc);
    8488               0 :   if (htmlDoc) {
    8489               0 :     nsCOMPtr<nsIDOMHTMLElement> body;
    8490               0 :     htmlDoc->GetBody(getter_AddRefs(body));
    8491               0 :     if (body) {
    8492               0 :       eventTarget = body;
    8493                 :     }
    8494                 :   }
    8495                 :   else {
    8496               0 :     nsCOMPtr<nsIDOMElement> documentElement;
    8497               0 :     mDocument->GetDocumentElement(getter_AddRefs(documentElement));
    8498               0 :     if(documentElement) {        
    8499               0 :       eventTarget = documentElement;
    8500                 :     }
    8501                 :   }
    8502               0 :   nsContentUtils::DispatchTrustedEvent(mDoc, eventTarget, name, true, false);
    8503                 : }
    8504                 : 
    8505                 : nsresult
    8506               0 : nsGlobalWindow::Observe(nsISupports* aSubject, const char* aTopic,
    8507                 :                         const PRUnichar* aData)
    8508                 : {
    8509               0 :   if (!nsCRT::strcmp(aTopic, NS_IOSERVICE_OFFLINE_STATUS_TOPIC)) {
    8510               0 :     if (IsFrozen()) {
    8511                 :       // if an even number of notifications arrive while we're frozen,
    8512                 :       // we don't need to fire.
    8513               0 :       mFireOfflineStatusChangeEventOnThaw = !mFireOfflineStatusChangeEventOnThaw;
    8514                 :     } else {
    8515               0 :       FireOfflineStatusEvent();
    8516                 :     }
    8517               0 :     return NS_OK;
    8518                 :   }
    8519                 : 
    8520               0 :   if (IsInnerWindow() && !nsCRT::strcmp(aTopic, "dom-storage-changed")) {
    8521                 :     nsIPrincipal *principal;
    8522                 :     nsresult rv;
    8523                 : 
    8524               0 :     principal = GetPrincipal();
    8525               0 :     if (principal) {
    8526                 :       // A global storage object changed, check to see if it's one
    8527                 :       // this window can access.
    8528                 : 
    8529               0 :       nsCOMPtr<nsIURI> codebase;
    8530               0 :       principal->GetURI(getter_AddRefs(codebase));
    8531                 : 
    8532               0 :       if (!codebase) {
    8533               0 :         return NS_OK;
    8534                 :       }
    8535                 : 
    8536               0 :       nsCAutoString currentDomain;
    8537               0 :       rv = codebase->GetAsciiHost(currentDomain);
    8538               0 :       if (NS_FAILED(rv)) {
    8539               0 :         return NS_OK;
    8540                 :       }
    8541                 : 
    8542               0 :       if (!nsDOMStorageList::CanAccessDomain(NS_ConvertUTF16toUTF8(aData),
    8543               0 :                                              currentDomain)) {
    8544                 :         // This window can't reach the global storage object for the
    8545                 :         // domain for which the change happened, so don't fire any
    8546                 :         // events in this window.
    8547                 : 
    8548               0 :         return NS_OK;
    8549                 :       }
    8550                 :     }
    8551                 : 
    8552               0 :     nsAutoString domain(aData);
    8553                 : 
    8554               0 :     if (IsFrozen()) {
    8555                 :       // This window is frozen, rather than firing the events here,
    8556                 :       // store the domain in which the change happened and fire the
    8557                 :       // events if we're ever thawed.
    8558                 : 
    8559               0 :       if (!mPendingStorageEventsObsolete) {
    8560               0 :         mPendingStorageEventsObsolete = new nsDataHashtable<nsStringHashKey, bool>;
    8561               0 :         NS_ENSURE_TRUE(mPendingStorageEventsObsolete, NS_ERROR_OUT_OF_MEMORY);
    8562                 : 
    8563               0 :         rv = mPendingStorageEventsObsolete->Init();
    8564               0 :         NS_ENSURE_SUCCESS(rv, rv);
    8565                 :       }
    8566                 : 
    8567               0 :       mPendingStorageEventsObsolete->Put(domain, true);
    8568                 : 
    8569               0 :       return NS_OK;
    8570                 :     }
    8571                 : 
    8572               0 :     nsRefPtr<nsDOMStorageEventObsolete> event = new nsDOMStorageEventObsolete();
    8573               0 :     NS_ENSURE_TRUE(event, NS_ERROR_OUT_OF_MEMORY);
    8574                 : 
    8575               0 :     rv = event->InitStorageEvent(NS_LITERAL_STRING("storage"), false, false, domain);
    8576               0 :     NS_ENSURE_SUCCESS(rv, rv);
    8577                 : 
    8578               0 :     nsCOMPtr<nsIDOMHTMLDocument> htmlDoc(do_QueryInterface(mDocument));
    8579                 : 
    8580               0 :     nsCOMPtr<nsIDOMEventTarget> target;
    8581                 : 
    8582               0 :     if (htmlDoc) {
    8583               0 :       nsCOMPtr<nsIDOMHTMLElement> body;
    8584               0 :       htmlDoc->GetBody(getter_AddRefs(body));
    8585                 : 
    8586               0 :       target = do_QueryInterface(body);
    8587                 :     }
    8588                 : 
    8589               0 :     if (!target) {
    8590               0 :       target = this;
    8591                 :     }
    8592                 : 
    8593                 :     bool defaultActionEnabled;
    8594               0 :     target->DispatchEvent((nsIDOMStorageEventObsolete *)event, &defaultActionEnabled);
    8595                 : 
    8596               0 :     return NS_OK;
    8597                 :   }
    8598                 : 
    8599               0 :   if (IsInnerWindow() && !nsCRT::strcmp(aTopic, "dom-storage2-changed")) {
    8600                 :     nsIPrincipal *principal;
    8601                 :     nsresult rv;
    8602                 : 
    8603               0 :     nsCOMPtr<nsIDOMStorageEvent> event = do_QueryInterface(aSubject, &rv);
    8604               0 :     NS_ENSURE_SUCCESS(rv, rv);
    8605                 : 
    8606               0 :     nsCOMPtr<nsIDOMStorage> changingStorage;
    8607               0 :     rv = event->GetStorageArea(getter_AddRefs(changingStorage));
    8608               0 :     NS_ENSURE_SUCCESS(rv, rv);
    8609                 : 
    8610               0 :     nsCOMPtr<nsPIDOMStorage> pistorage = do_QueryInterface(changingStorage);
    8611               0 :     nsPIDOMStorage::nsDOMStorageType storageType = pistorage->StorageType();
    8612                 : 
    8613               0 :     principal = GetPrincipal();
    8614               0 :     switch (storageType)
    8615                 :     {
    8616                 :     case nsPIDOMStorage::SessionStorage:
    8617                 :     {
    8618               0 :       if (SameCOMIdentity(mSessionStorage, changingStorage)) {
    8619                 :         // Do not fire any events for the same storage object, it's not shared
    8620                 :         // among windows, see nsGlobalWindow::GetSessionStoarge()
    8621               0 :         return NS_OK;
    8622                 :       }
    8623                 : 
    8624               0 :       nsCOMPtr<nsIDOMStorage> storage = mSessionStorage;
    8625               0 :       if (!storage) {
    8626               0 :         nsIDocShell* docShell = GetDocShell();
    8627               0 :         if (principal && docShell) {
    8628                 :           // No need to pass documentURI here, it's only needed when we want
    8629                 :           // to create a new storage, the third paramater would be true
    8630                 :           docShell->GetSessionStorageForPrincipal(principal,
    8631               0 :                                                   EmptyString(),
    8632                 :                                                   false,
    8633               0 :                                                   getter_AddRefs(storage));
    8634                 :         }
    8635                 :       }
    8636                 : 
    8637               0 :       if (!pistorage->IsForkOf(storage)) {
    8638                 :         // This storage event is coming from a different doc shell,
    8639                 :         // i.e. it is a clone, ignore this event.
    8640               0 :         return NS_OK;
    8641                 :       }
    8642                 : 
    8643                 : #ifdef PR_LOGGING
    8644               0 :       if (PR_LOG_TEST(gDOMLeakPRLog, PR_LOG_DEBUG)) {
    8645               0 :         PR_LogPrint("nsGlobalWindow %p with sessionStorage %p passing event from %p", this, mSessionStorage.get(), pistorage.get());
    8646                 :       }
    8647                 : #endif
    8648                 : 
    8649               0 :       break;
    8650                 :     }
    8651                 :     case nsPIDOMStorage::LocalStorage:
    8652                 :     {
    8653               0 :       if (SameCOMIdentity(mLocalStorage, changingStorage)) {
    8654                 :         // Do not fire any events for the same storage object, it's not shared
    8655                 :         // among windows, see nsGlobalWindow::GetLocalStoarge()
    8656               0 :         return NS_OK;
    8657                 :       }
    8658                 : 
    8659                 :       // Allow event fire only for the same principal storages
    8660                 :       // XXX We have to use EqualsIgnoreDomain after bug 495337 lands
    8661               0 :       nsIPrincipal *storagePrincipal = pistorage->Principal();
    8662                 :       bool equals;
    8663                 : 
    8664               0 :       rv = storagePrincipal->Equals(principal, &equals);
    8665               0 :       NS_ENSURE_SUCCESS(rv, rv);
    8666                 : 
    8667               0 :       if (!equals)
    8668               0 :         return NS_OK;
    8669                 : 
    8670               0 :       break;
    8671                 :     }
    8672                 :     default:
    8673               0 :       return NS_OK;
    8674                 :     }
    8675                 : 
    8676               0 :     if (IsFrozen()) {
    8677                 :       // This window is frozen, rather than firing the events here,
    8678                 :       // store the domain in which the change happened and fire the
    8679                 :       // events if we're ever thawed.
    8680                 : 
    8681               0 :       mPendingStorageEvents.AppendObject(event);
    8682               0 :       return NS_OK;
    8683                 :     }
    8684                 : 
    8685                 :     bool defaultActionEnabled;
    8686               0 :     DispatchEvent((nsIDOMStorageEvent *)event, &defaultActionEnabled);
    8687                 : 
    8688               0 :     return NS_OK;
    8689                 :   }
    8690                 : 
    8691               0 :   if (!nsCRT::strcmp(aTopic, "offline-cache-update-added")) {
    8692               0 :     if (mApplicationCache)
    8693               0 :       return NS_OK;
    8694                 : 
    8695                 :     // Instantiate the application object now. It observes update belonging to
    8696                 :     // this window's document and correctly updates the applicationCache object
    8697                 :     // state.
    8698               0 :     nsCOMPtr<nsIDOMOfflineResourceList> applicationCache;
    8699               0 :     GetApplicationCache(getter_AddRefs(applicationCache));
    8700               0 :     nsCOMPtr<nsIObserver> observer = do_QueryInterface(applicationCache);
    8701               0 :     if (observer)
    8702               0 :       observer->Observe(aSubject, aTopic, aData);
    8703                 : 
    8704               0 :     return NS_OK;
    8705                 :   }
    8706                 : 
    8707               0 :   NS_WARNING("unrecognized topic in nsGlobalWindow::Observe");
    8708               0 :   return NS_ERROR_FAILURE;
    8709                 : }
    8710                 : 
    8711                 : static PLDHashOperator
    8712               0 : FirePendingStorageEvents(const nsAString& aKey, bool aData, void *userArg)
    8713                 : {
    8714               0 :   nsGlobalWindow *win = static_cast<nsGlobalWindow *>(userArg);
    8715                 : 
    8716               0 :   nsCOMPtr<nsIDOMStorage> storage;
    8717               0 :   win->GetSessionStorage(getter_AddRefs(storage));
    8718                 : 
    8719               0 :   if (storage) {
    8720                 :     win->Observe(storage, "dom-storage-changed",
    8721               0 :                  aKey.IsEmpty() ? nsnull : PromiseFlatString(aKey).get());
    8722                 :   }
    8723                 : 
    8724               0 :   return PL_DHASH_NEXT;
    8725                 : }
    8726                 : 
    8727                 : nsresult
    8728               0 : nsGlobalWindow::FireDelayedDOMEvents()
    8729                 : {
    8730               0 :   FORWARD_TO_INNER(FireDelayedDOMEvents, (), NS_ERROR_UNEXPECTED);
    8731                 : 
    8732               0 :   for (PRInt32 i = 0; i < mPendingStorageEvents.Count(); ++i) {
    8733               0 :     Observe(mPendingStorageEvents[i], "dom-storage2-changed", nsnull);
    8734                 :   }
    8735                 : 
    8736               0 :   if (mPendingStorageEventsObsolete) {
    8737                 :     // Fire pending storage events.
    8738               0 :     mPendingStorageEventsObsolete->EnumerateRead(FirePendingStorageEvents, this);
    8739               0 :     mPendingStorageEventsObsolete = nsnull;
    8740                 :   }
    8741                 : 
    8742               0 :   if (mApplicationCache) {
    8743               0 :     static_cast<nsDOMOfflineResourceList*>(mApplicationCache.get())->FirePendingEvents();
    8744                 :   }
    8745                 : 
    8746               0 :   if (mFireOfflineStatusChangeEventOnThaw) {
    8747               0 :     mFireOfflineStatusChangeEventOnThaw = false;
    8748               0 :     FireOfflineStatusEvent();
    8749                 :   }
    8750                 : 
    8751                 :   nsCOMPtr<nsIDocShellTreeNode> node =
    8752               0 :     do_QueryInterface(GetDocShell());
    8753               0 :   if (node) {
    8754               0 :     PRInt32 childCount = 0;
    8755               0 :     node->GetChildCount(&childCount);
    8756                 : 
    8757               0 :     for (PRInt32 i = 0; i < childCount; ++i) {
    8758               0 :       nsCOMPtr<nsIDocShellTreeItem> childShell;
    8759               0 :       node->GetChildAt(i, getter_AddRefs(childShell));
    8760               0 :       NS_ASSERTION(childShell, "null child shell");
    8761                 : 
    8762               0 :       nsCOMPtr<nsPIDOMWindow> pWin = do_GetInterface(childShell);
    8763               0 :       if (pWin) {
    8764                 :         nsGlobalWindow *win =
    8765                 :           static_cast<nsGlobalWindow*>
    8766               0 :                      (static_cast<nsPIDOMWindow*>(pWin));
    8767               0 :         win->FireDelayedDOMEvents();
    8768                 :       }
    8769                 :     }
    8770                 :   }
    8771                 : 
    8772               0 :   return NS_OK;
    8773                 : }
    8774                 : 
    8775                 : //*****************************************************************************
    8776                 : // nsGlobalWindow: Window Control Functions
    8777                 : //*****************************************************************************
    8778                 : 
    8779                 : nsIDOMWindow *
    8780               0 : nsGlobalWindow::GetParentInternal()
    8781                 : {
    8782               0 :   FORWARD_TO_OUTER(GetParentInternal, (), nsnull);
    8783                 : 
    8784               0 :   nsCOMPtr<nsIDOMWindow> parent;
    8785               0 :   GetParent(getter_AddRefs(parent));
    8786                 : 
    8787               0 :   if (parent && parent != static_cast<nsIDOMWindow *>(this)) {
    8788               0 :     return parent;
    8789                 :   }
    8790                 : 
    8791               0 :   return NULL;
    8792                 : }
    8793                 : 
    8794                 : // static
    8795                 : void
    8796               0 : nsGlobalWindow::CloseBlockScriptTerminationFunc(nsISupports *aRef)
    8797                 : {
    8798                 :   nsGlobalWindow* pwin = static_cast<nsGlobalWindow*>
    8799               0 :                                     (static_cast<nsPIDOMWindow*>(aRef));
    8800               0 :   pwin->mBlockScriptedClosingFlag = false;
    8801               0 : }
    8802                 : 
    8803                 : nsresult
    8804               0 : nsGlobalWindow::OpenInternal(const nsAString& aUrl, const nsAString& aName,
    8805                 :                              const nsAString& aOptions, bool aDialog,
    8806                 :                              bool aContentModal, bool aCalledNoScript,
    8807                 :                              bool aDoJSFixups, nsIArray *argv,
    8808                 :                              nsISupports *aExtraArgument,
    8809                 :                              nsIPrincipal *aCalleePrincipal,
    8810                 :                              JSContext *aJSCallerContext,
    8811                 :                              nsIDOMWindow **aReturn)
    8812                 : {
    8813               0 :   FORWARD_TO_OUTER(OpenInternal, (aUrl, aName, aOptions, aDialog,
    8814                 :                                   aContentModal, aCalledNoScript, aDoJSFixups,
    8815                 :                                   argv, aExtraArgument, aCalleePrincipal,
    8816                 :                                   aJSCallerContext, aReturn),
    8817                 :                    NS_ERROR_NOT_INITIALIZED);
    8818                 : 
    8819                 : #ifdef NS_DEBUG
    8820               0 :   PRUint32 argc = 0;
    8821               0 :   if (argv)
    8822               0 :       argv->GetLength(&argc);
    8823                 : #endif
    8824               0 :   NS_PRECONDITION(!aExtraArgument || (!argv && argc == 0),
    8825                 :                   "Can't pass in arguments both ways");
    8826               0 :   NS_PRECONDITION(!aCalledNoScript || (!argv && argc == 0),
    8827                 :                   "Can't pass JS args when called via the noscript methods");
    8828               0 :   NS_PRECONDITION(!aJSCallerContext || !aCalledNoScript,
    8829                 :                   "Shouldn't have caller context when called noscript");
    8830                 : 
    8831               0 :   *aReturn = nsnull;
    8832                 : 
    8833               0 :   nsCOMPtr<nsIWebBrowserChrome> chrome;
    8834               0 :   GetWebBrowserChrome(getter_AddRefs(chrome));
    8835               0 :   if (!chrome) {
    8836                 :     // No chrome means we don't want to go through with this open call
    8837                 :     // -- see nsIWindowWatcher.idl
    8838               0 :     return NS_ERROR_NOT_AVAILABLE;
    8839                 :   }
    8840                 : 
    8841               0 :   NS_ASSERTION(mDocShell, "Must have docshell here");
    8842                 : 
    8843               0 :   const bool checkForPopup = !nsContentUtils::IsCallerChrome() &&
    8844               0 :     !aDialog && !WindowExists(aName, !aCalledNoScript);
    8845                 : 
    8846                 :   // Note: it's very important that this be an nsXPIDLCString, since we want
    8847                 :   // .get() on it to return nsnull until we write stuff to it.  The window
    8848                 :   // watcher expects a null URL string if there is no URL to load.
    8849               0 :   nsXPIDLCString url;
    8850               0 :   nsresult rv = NS_OK;
    8851                 : 
    8852                 :   // It's important to do this security check before determining whether this
    8853                 :   // window opening should be blocked, to ensure that we don't FireAbuseEvents
    8854                 :   // for a window opening that wouldn't have succeeded in the first place.
    8855               0 :   if (!aUrl.IsEmpty()) {
    8856               0 :     AppendUTF16toUTF8(aUrl, url);
    8857                 : 
    8858                 :     /* Check whether the URI is allowed, but not for dialogs --
    8859                 :        see bug 56851. The security of this function depends on
    8860                 :        window.openDialog being inaccessible from web scripts */
    8861               0 :     if (url.get() && !aDialog)
    8862               0 :       rv = SecurityCheckURL(url.get());
    8863                 :   }
    8864                 : 
    8865               0 :   if (NS_FAILED(rv))
    8866               0 :     return rv;
    8867                 : 
    8868               0 :   PopupControlState abuseLevel = gPopupControlState;
    8869               0 :   if (checkForPopup) {
    8870               0 :     abuseLevel = RevisePopupAbuseLevel(abuseLevel);
    8871               0 :     if (abuseLevel >= openAbused) {
    8872               0 :       if (aJSCallerContext) {
    8873                 :         // If script in some other window is doing a window.open on us and
    8874                 :         // it's being blocked, then it's OK to close us afterwards, probably.
    8875                 :         // But if we're doing a window.open on ourselves and block the popup,
    8876                 :         // prevent this window from closing until after this script terminates
    8877                 :         // so that whatever popup blocker UI the app has will be visible.
    8878               0 :         if (mContext == GetScriptContextFromJSContext(aJSCallerContext)) {
    8879               0 :           mBlockScriptedClosingFlag = true;
    8880               0 :           mContext->SetTerminationFunction(CloseBlockScriptTerminationFunc,
    8881               0 :                                            this);
    8882                 :         }
    8883                 :       }
    8884                 : 
    8885               0 :       FireAbuseEvents(true, false, aUrl, aName, aOptions);
    8886               0 :       return aDoJSFixups ? NS_OK : NS_ERROR_FAILURE;
    8887                 :     }
    8888                 :   }    
    8889                 : 
    8890               0 :   nsCOMPtr<nsIDOMWindow> domReturn;
    8891                 : 
    8892                 :   nsCOMPtr<nsIWindowWatcher> wwatch =
    8893               0 :     do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv);
    8894               0 :   NS_ENSURE_TRUE(wwatch, rv);
    8895                 : 
    8896               0 :   NS_ConvertUTF16toUTF8 options(aOptions);
    8897               0 :   NS_ConvertUTF16toUTF8 name(aName);
    8898                 : 
    8899               0 :   const char *options_ptr = aOptions.IsEmpty() ? nsnull : options.get();
    8900               0 :   const char *name_ptr = aName.IsEmpty() ? nsnull : name.get();
    8901                 : 
    8902                 :   {
    8903                 :     // Reset popup state while opening a window to prevent the
    8904                 :     // current state from being active the whole time a modal
    8905                 :     // dialog is open.
    8906               0 :     nsAutoPopupStatePusher popupStatePusher(openAbused, true);
    8907                 : 
    8908               0 :     if (!aCalledNoScript) {
    8909               0 :       nsCOMPtr<nsPIWindowWatcher> pwwatch(do_QueryInterface(wwatch));
    8910               0 :       NS_ASSERTION(pwwatch,
    8911                 :                    "Unable to open windows from JS because window watcher "
    8912                 :                    "is broken");
    8913               0 :       NS_ENSURE_TRUE(pwwatch, NS_ERROR_UNEXPECTED);
    8914                 :         
    8915               0 :       rv = pwwatch->OpenWindowJS(this, url.get(), name_ptr, options_ptr,
    8916                 :                                  aDialog, argv,
    8917               0 :                                  getter_AddRefs(domReturn));
    8918                 :     } else {
    8919                 :       // Push a null JSContext here so that the window watcher won't screw us
    8920                 :       // up.  We do NOT want this case looking at the JS context on the stack
    8921                 :       // when searching.  Compare comments on
    8922                 :       // nsIDOMWindow::OpenWindow and nsIWindowWatcher::OpenWindow.
    8923               0 :       nsCOMPtr<nsIJSContextStack> stack;
    8924                 : 
    8925               0 :       if (!aContentModal) {
    8926               0 :         stack = do_GetService(sJSStackContractID);
    8927                 :       }
    8928                 : 
    8929               0 :       if (stack) {
    8930               0 :         rv = stack->Push(nsnull);
    8931               0 :         NS_ENSURE_SUCCESS(rv, rv);
    8932                 :       }
    8933                 :         
    8934               0 :       rv = wwatch->OpenWindow(this, url.get(), name_ptr, options_ptr,
    8935               0 :                               aExtraArgument, getter_AddRefs(domReturn));
    8936                 : 
    8937               0 :       if (stack) {
    8938                 :         JSContext* cx;
    8939               0 :         stack->Pop(&cx);
    8940               0 :         NS_ASSERTION(!cx, "Unexpected JSContext popped!");
    8941                 :       }
    8942                 :     }
    8943                 :   }
    8944                 : 
    8945               0 :   NS_ENSURE_SUCCESS(rv, rv);
    8946                 : 
    8947                 :   // success!
    8948                 : 
    8949               0 :   domReturn.swap(*aReturn);
    8950                 : 
    8951               0 :   if (aDoJSFixups) {      
    8952               0 :     nsCOMPtr<nsIDOMChromeWindow> chrome_win(do_QueryInterface(*aReturn));
    8953               0 :     if (!chrome_win) {
    8954                 :       // A new non-chrome window was created from a call to
    8955                 :       // window.open() from JavaScript, make sure there's a document in
    8956                 :       // the new window. We do this by simply asking the new window for
    8957                 :       // its document, this will synchronously create an empty document
    8958                 :       // if there is no document in the window.
    8959                 :       // XXXbz should this just use EnsureInnerWindow()?
    8960                 : #ifdef DEBUG_jst
    8961                 :       {
    8962                 :         nsCOMPtr<nsPIDOMWindow> pidomwin(do_QueryInterface(*aReturn));
    8963                 : 
    8964                 :         nsIDOMDocument *temp = pidomwin->GetExtantDocument();
    8965                 : 
    8966                 :         NS_ASSERTION(temp, "No document in new window!!!");
    8967                 :       }
    8968                 : #endif
    8969                 : 
    8970               0 :       nsCOMPtr<nsIDOMDocument> doc;
    8971               0 :       (*aReturn)->GetDocument(getter_AddRefs(doc));
    8972                 :     }
    8973                 :   }
    8974                 :     
    8975               0 :   if (checkForPopup) {
    8976               0 :     if (abuseLevel >= openControlled) {
    8977               0 :       nsGlobalWindow *opened = static_cast<nsGlobalWindow *>(*aReturn);
    8978               0 :       if (!opened->IsPopupSpamWindow()) {
    8979               0 :         opened->SetPopupSpamWindow(true);
    8980               0 :         ++gOpenPopupSpamCount;
    8981                 :       }
    8982                 :     }
    8983               0 :     if (abuseLevel >= openAbused)
    8984               0 :       FireAbuseEvents(false, true, aUrl, aName, aOptions);
    8985                 :   }
    8986                 : 
    8987               0 :   return rv;
    8988                 : }
    8989                 : 
    8990                 : // static
    8991                 : void
    8992               0 : nsGlobalWindow::CloseWindow(nsISupports *aWindow)
    8993                 : {
    8994               0 :   nsCOMPtr<nsPIDOMWindow> win(do_QueryInterface(aWindow));
    8995                 : 
    8996                 :   nsGlobalWindow* globalWin =
    8997                 :     static_cast<nsGlobalWindow *>
    8998               0 :                (static_cast<nsPIDOMWindow*>(win));
    8999                 : 
    9000                 :   // Need to post an event for closing, otherwise window and 
    9001                 :   // presshell etc. may get destroyed while creating frames, bug 338897.
    9002               0 :   nsCloseEvent::PostCloseEvent(globalWin);
    9003                 :   // else if OOM, better not to close. That might cause a crash.
    9004               0 : }
    9005                 : 
    9006                 : //*****************************************************************************
    9007                 : // nsGlobalWindow: Timeout Functions
    9008                 : //*****************************************************************************
    9009                 : 
    9010                 : PRUint32 sNestingLevel;
    9011                 : 
    9012                 : nsresult
    9013               0 : nsGlobalWindow::SetTimeoutOrInterval(nsIScriptTimeoutHandler *aHandler,
    9014                 :                                      PRInt32 interval,
    9015                 :                                      bool aIsInterval, PRInt32 *aReturn)
    9016                 : {
    9017               0 :   FORWARD_TO_INNER(SetTimeoutOrInterval, (aHandler, interval, aIsInterval, aReturn),
    9018                 :                    NS_ERROR_NOT_INITIALIZED);
    9019                 : 
    9020                 :   // If we don't have a document (we could have been unloaded since
    9021                 :   // the call to setTimeout was made), do nothing.
    9022               0 :   if (!mDocument) {
    9023               0 :     return NS_OK;
    9024                 :   }
    9025                 : 
    9026                 :   // Disallow negative intervals.  If aIsInterval also disallow 0,
    9027                 :   // because we use that as a "don't repeat" flag.
    9028               0 :   interval = NS_MAX(aIsInterval ? 1 : 0, interval);
    9029                 : 
    9030                 :   // Make sure we don't proceed with an interval larger than our timer
    9031                 :   // code can handle. (Note: we already forced |interval| to be non-negative,
    9032                 :   // so the PRUint32 cast (to avoid compiler warnings) is ok.)
    9033               0 :   PRUint32 maxTimeoutMs = PR_IntervalToMilliseconds(DOM_MAX_TIMEOUT_VALUE);
    9034               0 :   if (static_cast<PRUint32>(interval) > maxTimeoutMs) {
    9035               0 :     interval = maxTimeoutMs;
    9036                 :   }
    9037                 : 
    9038               0 :   nsRefPtr<nsTimeout> timeout = new nsTimeout();
    9039               0 :   timeout->mIsInterval = aIsInterval;
    9040               0 :   timeout->mInterval = interval;
    9041               0 :   timeout->mScriptHandler = aHandler;
    9042                 : 
    9043                 :   // Now clamp the actual interval we will use for the timer based on
    9044               0 :   PRUint32 nestingLevel = sNestingLevel + 1;
    9045               0 :   PRInt32 realInterval = interval;
    9046               0 :   if (aIsInterval || nestingLevel >= DOM_CLAMP_TIMEOUT_NESTING_LEVEL) {
    9047                 :     // Don't allow timeouts less than DOMMinTimeoutValue() from
    9048                 :     // now...
    9049               0 :     realInterval = NS_MAX(realInterval, DOMMinTimeoutValue());
    9050                 :   }
    9051                 : 
    9052                 :   // Get principal of currently executing code, save for execution of timeout.
    9053                 :   // If our principals subsume the subject principal then use the subject
    9054                 :   // principal. Otherwise, use our principal to avoid running script in
    9055                 :   // elevated principals.
    9056                 : 
    9057               0 :   nsCOMPtr<nsIPrincipal> subjectPrincipal;
    9058                 :   nsresult rv;
    9059               0 :   rv = nsContentUtils::GetSecurityManager()->
    9060               0 :     GetSubjectPrincipal(getter_AddRefs(subjectPrincipal));
    9061               0 :   if (NS_FAILED(rv)) {
    9062               0 :     return NS_ERROR_FAILURE;
    9063                 :   }
    9064                 : 
    9065               0 :   bool subsumes = false;
    9066               0 :   nsCOMPtr<nsIPrincipal> ourPrincipal = GetPrincipal();
    9067                 : 
    9068                 :   // Note the direction of this test: We don't allow setTimeouts running with
    9069                 :   // chrome privileges on content windows, but we do allow setTimeouts running
    9070                 :   // with content privileges on chrome windows (where they can't do very much,
    9071                 :   // of course).
    9072               0 :   rv = ourPrincipal->Subsumes(subjectPrincipal, &subsumes);
    9073               0 :   if (NS_FAILED(rv)) {
    9074               0 :     return NS_ERROR_FAILURE;
    9075                 :   }
    9076                 : 
    9077               0 :   if (subsumes) {
    9078               0 :     timeout->mPrincipal = subjectPrincipal;
    9079                 :   } else {
    9080               0 :     timeout->mPrincipal = ourPrincipal;
    9081                 :   }
    9082                 : 
    9083               0 :   ++gTimeoutsRecentlySet;
    9084               0 :   TimeDuration delta = TimeDuration::FromMilliseconds(realInterval);
    9085                 : 
    9086               0 :   if (!IsFrozen() && !mTimeoutsSuspendDepth) {
    9087                 :     // If we're not currently frozen, then we set timeout->mWhen to be the
    9088                 :     // actual firing time of the timer (i.e., now + delta). We also actually
    9089                 :     // create a timer and fire it off.
    9090                 : 
    9091               0 :     timeout->mWhen = TimeStamp::Now() + delta;
    9092                 : 
    9093               0 :     timeout->mTimer = do_CreateInstance("@mozilla.org/timer;1", &rv);
    9094               0 :     if (NS_FAILED(rv)) {
    9095               0 :       return rv;
    9096                 :     }
    9097                 : 
    9098               0 :     nsRefPtr<nsTimeout> copy = timeout;
    9099                 : 
    9100               0 :     rv = timeout->mTimer->InitWithFuncCallback(TimerCallback, timeout,
    9101                 :                                                realInterval,
    9102               0 :                                                nsITimer::TYPE_ONE_SHOT);
    9103               0 :     if (NS_FAILED(rv)) {
    9104               0 :       return rv;
    9105                 :     }
    9106                 : 
    9107                 :     // The timeout is now also held in the timer's closure.
    9108               0 :     copy.forget();
    9109                 :   } else {
    9110                 :     // If we are frozen, however, then we instead simply set
    9111                 :     // timeout->mTimeRemaining to be the "time remaining" in the timeout (i.e.,
    9112                 :     // the interval itself). We don't create a timer for it, since that will
    9113                 :     // happen when we are thawed and the timeout will then get a timer and run
    9114                 :     // to completion.
    9115                 : 
    9116               0 :     timeout->mTimeRemaining = delta;
    9117                 :   }
    9118                 : 
    9119               0 :   timeout->mWindow = this;
    9120                 : 
    9121               0 :   if (!aIsInterval) {
    9122               0 :     timeout->mNestingLevel = nestingLevel;
    9123                 :   }
    9124                 : 
    9125                 :   // No popups from timeouts by default
    9126               0 :   timeout->mPopupState = openAbused;
    9127                 : 
    9128               0 :   if (gRunningTimeoutDepth == 0 && gPopupControlState < openAbused) {
    9129                 :     // This timeout is *not* set from another timeout and it's set
    9130                 :     // while popups are enabled. Propagate the state to the timeout if
    9131                 :     // its delay (interval) is equal to or less than what
    9132                 :     // "dom.disable_open_click_delay" is set to (in ms).
    9133                 : 
    9134                 :     PRInt32 delay =
    9135               0 :       Preferences::GetInt("dom.disable_open_click_delay");
    9136                 : 
    9137                 :     // This is checking |interval|, not realInterval, on purpose,
    9138                 :     // because our lower bound for |realInterval| could be pretty high
    9139                 :     // in some cases.
    9140               0 :     if (interval <= delay) {
    9141               0 :       timeout->mPopupState = gPopupControlState;
    9142                 :     }
    9143                 :   }
    9144                 : 
    9145               0 :   InsertTimeoutIntoList(timeout);
    9146                 : 
    9147               0 :   timeout->mPublicId = ++mTimeoutPublicIdCounter;
    9148               0 :   *aReturn = timeout->mPublicId;
    9149                 : 
    9150               0 :   return NS_OK;
    9151                 : 
    9152                 : }
    9153                 : 
    9154                 : nsresult
    9155               0 : nsGlobalWindow::SetTimeoutOrInterval(bool aIsInterval, PRInt32 *aReturn)
    9156                 : {
    9157                 :   // This needs to forward to the inner window, but since the current
    9158                 :   // inner may not be the inner in the calling scope, we need to treat
    9159                 :   // this specially here as we don't want timeouts registered in a
    9160                 :   // dying inner window to get registered and run on the current inner
    9161                 :   // window. To get this right, we need to forward this call to the
    9162                 :   // inner window that's calling window.setTimeout().
    9163                 : 
    9164               0 :   if (IsOuterWindow()) {
    9165               0 :     nsGlobalWindow* callerInner = CallerInnerWindow();
    9166               0 :     NS_ENSURE_TRUE(callerInner, NS_ERROR_NOT_AVAILABLE);
    9167                 : 
    9168                 :     // If the caller and the callee share the same outer window,
    9169                 :     // forward to the callee inner. Else, we forward to the current
    9170                 :     // inner (e.g. someone is calling setTimeout() on a reference to
    9171                 :     // some other window).
    9172                 : 
    9173               0 :     if (callerInner->GetOuterWindow() == this &&
    9174               0 :         callerInner->IsInnerWindow()) {
    9175               0 :       return callerInner->SetTimeoutOrInterval(aIsInterval, aReturn);
    9176                 :     }
    9177                 : 
    9178               0 :     FORWARD_TO_INNER(SetTimeoutOrInterval, (aIsInterval, aReturn),
    9179                 :                      NS_ERROR_NOT_INITIALIZED);
    9180                 :   }
    9181                 : 
    9182               0 :   PRInt32 interval = 0;
    9183               0 :   bool isInterval = aIsInterval;
    9184               0 :   nsCOMPtr<nsIScriptTimeoutHandler> handler;
    9185                 :   nsresult rv = NS_CreateJSTimeoutHandler(this,
    9186                 :                                           &isInterval,
    9187                 :                                           &interval,
    9188               0 :                                           getter_AddRefs(handler));
    9189               0 :   if (NS_FAILED(rv))
    9190               0 :     return (rv == NS_ERROR_DOM_TYPE_ERR) ? NS_OK : rv;
    9191                 : 
    9192               0 :   return SetTimeoutOrInterval(handler, interval, isInterval, aReturn);
    9193                 : }
    9194                 : 
    9195                 : // static
    9196                 : void
    9197               0 : nsGlobalWindow::RunTimeout(nsTimeout *aTimeout)
    9198                 : {
    9199                 :   // If a modal dialog is open for this window, return early. Pending
    9200                 :   // timeouts will run when the modal dialog is dismissed.
    9201               0 :   if (IsInModalState() || mTimeoutsSuspendDepth) {
    9202               0 :     return;
    9203                 :   }
    9204                 : 
    9205                 :   NS_TIME_FUNCTION;
    9206                 : 
    9207               0 :   NS_ASSERTION(IsInnerWindow(), "Timeout running on outer window!");
    9208               0 :   NS_ASSERTION(!IsFrozen(), "Timeout running on a window in the bfcache!");
    9209                 : 
    9210                 :   nsTimeout *nextTimeout, *timeout;
    9211                 :   nsTimeout *last_expired_timeout, *last_insertion_point;
    9212               0 :   nsTimeout dummy_timeout;
    9213               0 :   PRUint32 firingDepth = mTimeoutFiringDepth + 1;
    9214                 : 
    9215                 :   // Make sure that the window and the script context don't go away as
    9216                 :   // a result of running timeouts
    9217               0 :   nsCOMPtr<nsIScriptGlobalObject> windowKungFuDeathGrip(this);
    9218                 : 
    9219                 :   // A native timer has gone off. See which of our timeouts need
    9220                 :   // servicing
    9221               0 :   TimeStamp now = TimeStamp::Now();
    9222               0 :   TimeStamp deadline;
    9223                 : 
    9224               0 :   if (aTimeout && aTimeout->mWhen > now) {
    9225                 :     // The OS timer fired early (yikes!), and possibly out of order
    9226                 :     // too. Set |deadline| to be the time when the OS timer *should*
    9227                 :     // have fired so that any timers that *should* have fired before
    9228                 :     // aTimeout *will* be fired now. This happens most of the time on
    9229                 :     // Win2k.
    9230                 : 
    9231               0 :     deadline = aTimeout->mWhen;
    9232                 :   } else {
    9233               0 :     deadline = now;
    9234                 :   }
    9235                 : 
    9236                 :   // The timeout list is kept in deadline order. Discover the latest
    9237                 :   // timeout whose deadline has expired. On some platforms, native
    9238                 :   // timeout events fire "early", so we need to test the timer as well
    9239                 :   // as the deadline.
    9240               0 :   last_expired_timeout = nsnull;
    9241               0 :   for (timeout = FirstTimeout(); IsTimeout(timeout); timeout = timeout->Next()) {
    9242               0 :     if (((timeout == aTimeout) || (timeout->mWhen <= deadline)) &&
    9243                 :         (timeout->mFiringDepth == 0)) {
    9244                 :       // Mark any timeouts that are on the list to be fired with the
    9245                 :       // firing depth so that we can reentrantly run timeouts
    9246               0 :       timeout->mFiringDepth = firingDepth;
    9247               0 :       last_expired_timeout = timeout;
    9248                 :     }
    9249                 :   }
    9250                 : 
    9251                 :   // Maybe the timeout that the event was fired for has been deleted
    9252                 :   // and there are no others timeouts with deadlines that make them
    9253                 :   // eligible for execution yet. Go away.
    9254               0 :   if (!last_expired_timeout) {
    9255                 :     return;
    9256                 :   }
    9257                 : 
    9258                 :   // Record telemetry information about timers set recently.
    9259               0 :   TimeDuration recordingInterval = TimeDuration::FromMilliseconds(STATISTICS_INTERVAL);
    9260               0 :   if (gLastRecordedRecentTimeouts.IsNull() ||
    9261               0 :       now - gLastRecordedRecentTimeouts > recordingInterval) {
    9262               0 :     PRUint32 count = gTimeoutsRecentlySet;
    9263               0 :     gTimeoutsRecentlySet = 0;
    9264               0 :     Telemetry::Accumulate(Telemetry::DOM_TIMERS_RECENTLY_SET, count);
    9265               0 :     gLastRecordedRecentTimeouts = now;
    9266                 :   }
    9267                 : 
    9268                 :   // Insert a dummy timeout into the list of timeouts between the
    9269                 :   // portion of the list that we are about to process now and those
    9270                 :   // timeouts that will be processed in a future call to
    9271                 :   // win_run_timeout(). This dummy timeout serves as the head of the
    9272                 :   // list for any timeouts inserted as a result of running a timeout.
    9273               0 :   dummy_timeout.mFiringDepth = firingDepth;
    9274               0 :   dummy_timeout.mWhen = now;
    9275               0 :   PR_INSERT_AFTER(&dummy_timeout, last_expired_timeout);
    9276                 : 
    9277                 :   // Don't let ClearWindowTimeouts throw away our stack-allocated
    9278                 :   // dummy timeout.
    9279               0 :   dummy_timeout.AddRef();
    9280               0 :   dummy_timeout.AddRef();
    9281                 : 
    9282               0 :   last_insertion_point = mTimeoutInsertionPoint;
    9283                 :   // If we ever start setting mTimeoutInsertionPoint to a non-dummy timeout,
    9284                 :   // the logic in ResetTimersForNonBackgroundWindow will need to change.
    9285               0 :   mTimeoutInsertionPoint = &dummy_timeout;
    9286                 : 
    9287               0 :   Telemetry::AutoCounter<Telemetry::DOM_TIMERS_FIRED_PER_NATIVE_TIMEOUT> timeoutsRan;
    9288                 : 
    9289               0 :   for (timeout = FirstTimeout();
    9290               0 :        timeout != &dummy_timeout && !IsFrozen();
    9291                 :        timeout = nextTimeout) {
    9292               0 :     nextTimeout = timeout->Next();
    9293                 : 
    9294               0 :     if (timeout->mFiringDepth != firingDepth) {
    9295                 :       // We skip the timeout since it's on the list to run at another
    9296                 :       // depth.
    9297                 : 
    9298               0 :       continue;
    9299                 :     }
    9300                 : 
    9301               0 :     if (mTimeoutsSuspendDepth) {
    9302                 :       // Some timer did suspend us. Make sure the
    9303                 :       // rest of the timers get executed later.
    9304               0 :       timeout->mFiringDepth = 0;
    9305               0 :       continue;
    9306                 :     }
    9307                 : 
    9308                 :     // The timeout is on the list to run at this depth, go ahead and
    9309                 :     // process it.
    9310                 : 
    9311                 :     // Get the script context (a strong ref to prevent it going away)
    9312                 :     // for this timeout and ensure the script language is enabled.
    9313                 :     nsCOMPtr<nsIScriptContext> scx = GetScriptContextInternal(
    9314               0 :                                 timeout->mScriptHandler->GetScriptTypeID());
    9315                 : 
    9316               0 :     if (!scx) {
    9317                 :       // No context means this window was closed or never properly
    9318                 :       // initialized for this language.
    9319               0 :       continue;
    9320                 :     }
    9321                 : 
    9322                 :     // The "scripts disabled" concept is still a little vague wrt
    9323                 :     // multiple languages.  Prepare for the day when languages can be
    9324                 :     // disabled independently of the other languages...
    9325               0 :     if (!scx->GetScriptsEnabled()) {
    9326                 :       // Scripts were enabled once in this window (unless aTimeout ==
    9327                 :       // nsnull) but now scripts are disabled (we might be in
    9328                 :       // print-preview, for instance), this means we shouldn't run any
    9329                 :       // timeouts at this point.
    9330                 :       //
    9331                 :       // If scripts are enabled for this language in this window again
    9332                 :       // we'll fire the timeouts that are due at that point.
    9333               0 :       continue;
    9334                 :     }
    9335                 : 
    9336                 :     // This timeout is good to run
    9337               0 :     nsTimeout *last_running_timeout = mRunningTimeout;
    9338               0 :     mRunningTimeout = timeout;
    9339               0 :     timeout->mRunning = true;
    9340               0 :     ++timeoutsRan;
    9341                 : 
    9342                 :     // Push this timeout's popup control state, which should only be
    9343                 :     // eabled the first time a timeout fires that was created while
    9344                 :     // popups were enabled and with a delay less than
    9345                 :     // "dom.disable_open_click_delay".
    9346               0 :     nsAutoPopupStatePusher popupStatePusher(timeout->mPopupState);
    9347                 : 
    9348                 :     // Clear the timeout's popup state, if any, to prevent interval
    9349                 :     // timeouts from repeatedly opening poups.
    9350               0 :     timeout->mPopupState = openAbused;
    9351                 : 
    9352                 :     // Hold on to the timeout in case mExpr or mFunObj releases its
    9353                 :     // doc.
    9354               0 :     timeout->AddRef();
    9355                 : 
    9356               0 :     ++gRunningTimeoutDepth;
    9357               0 :     ++mTimeoutFiringDepth;
    9358                 : 
    9359               0 :     bool trackNestingLevel = !timeout->mIsInterval;
    9360                 :     PRUint32 nestingLevel;
    9361               0 :     if (trackNestingLevel) {
    9362               0 :       nestingLevel = sNestingLevel;
    9363               0 :       sNestingLevel = timeout->mNestingLevel;
    9364                 :     }
    9365                 : 
    9366               0 :     nsCOMPtr<nsIScriptTimeoutHandler> handler(timeout->mScriptHandler);
    9367               0 :     JSObject* scriptObject = handler->GetScriptObject();
    9368               0 :     if (!scriptObject) {
    9369                 :       // Evaluate the timeout expression.
    9370               0 :       const PRUnichar *script = handler->GetHandlerText();
    9371               0 :       NS_ASSERTION(script, "timeout has no script nor handler text!");
    9372                 : 
    9373               0 :       const char *filename = nsnull;
    9374               0 :       PRUint32 lineNo = 0;
    9375               0 :       handler->GetLocation(&filename, &lineNo);
    9376                 : 
    9377                 :       NS_TIME_FUNCTION_MARK("(file: %s, line: %d)", filename, lineNo);
    9378                 : 
    9379                 :       bool is_undefined;
    9380               0 :       scx->EvaluateString(nsDependentString(script), FastGetGlobalJSObject(),
    9381                 :                           timeout->mPrincipal, timeout->mPrincipal,
    9382                 :                           filename, lineNo,
    9383               0 :                           handler->GetScriptVersion(), nsnull,
    9384               0 :                           &is_undefined);
    9385                 :     } else {
    9386               0 :       nsCOMPtr<nsIVariant> dummy;
    9387               0 :       nsCOMPtr<nsISupports> me(static_cast<nsIDOMWindow *>(this));
    9388               0 :       scx->CallEventHandler(me, FastGetGlobalJSObject(),
    9389               0 :                             scriptObject, handler->GetArgv(),
    9390                 :                             // XXXmarkh - consider allowing CallEventHandler to
    9391                 :                             // accept nsnull?
    9392               0 :                             getter_AddRefs(dummy));
    9393                 : 
    9394                 :     }
    9395               0 :     handler = nsnull; // drop reference before dropping timeout refs.
    9396                 : 
    9397               0 :     if (trackNestingLevel) {
    9398               0 :       sNestingLevel = nestingLevel;
    9399                 :     }
    9400                 : 
    9401               0 :     --mTimeoutFiringDepth;
    9402               0 :     --gRunningTimeoutDepth;
    9403                 : 
    9404               0 :     mRunningTimeout = last_running_timeout;
    9405               0 :     timeout->mRunning = false;
    9406                 : 
    9407                 :     // We ignore any failures from calling EvaluateString() or
    9408                 :     // CallEventHandler() on the context here since we're in a loop
    9409                 :     // where we're likely to be running timeouts whose OS timers
    9410                 :     // didn't fire in time and we don't want to not fire those timers
    9411                 :     // now just because execution of one timer failed. We can't
    9412                 :     // propagate the error to anyone who cares about it from this
    9413                 :     // point anyway, and the script context should have already reported
    9414                 :     // the script error in the usual way - so we just drop it.
    9415                 : 
    9416                 :     // If all timeouts were cleared and |timeout != aTimeout| then
    9417                 :     // |timeout| may be the last reference to the timeout so check if
    9418                 :     // it was cleared before releasing it.
    9419               0 :     bool timeout_was_cleared = timeout->mCleared;
    9420                 : 
    9421               0 :     timeout->Release();
    9422                 : 
    9423               0 :     if (timeout_was_cleared) {
    9424                 :       // The running timeout's window was cleared, this means that
    9425                 :       // ClearAllTimeouts() was called from a *nested* call, possibly
    9426                 :       // through a timeout that fired while a modal (to this window)
    9427                 :       // dialog was open or through other non-obvious paths.
    9428                 : 
    9429               0 :       mTimeoutInsertionPoint = last_insertion_point;
    9430                 : 
    9431                 :       return;
    9432                 :     }
    9433                 : 
    9434               0 :     bool isInterval = false;
    9435                 : 
    9436                 :     // If we have a regular interval timer, we re-schedule the
    9437                 :     // timeout, accounting for clock drift.
    9438               0 :     if (timeout->mIsInterval) {
    9439                 :       // Compute time to next timeout for interval timer.
    9440                 :       // Make sure nextInterval is at least DOMMinTimeoutValue().
    9441                 :       TimeDuration nextInterval =
    9442                 :         TimeDuration::FromMilliseconds(NS_MAX(timeout->mInterval,
    9443               0 :                                               PRUint32(DOMMinTimeoutValue())));
    9444                 : 
    9445                 :       // If we're running pending timeouts because they've been temporarily
    9446                 :       // disabled (!aTimeout), set the next interval to be relative to "now",
    9447                 :       // and not to when the timeout that was pending should have fired.
    9448               0 :       TimeStamp firingTime;
    9449               0 :       if (!aTimeout)
    9450               0 :         firingTime = now + nextInterval;
    9451                 :       else
    9452               0 :         firingTime = timeout->mWhen + nextInterval;
    9453                 : 
    9454               0 :       TimeStamp currentNow = TimeStamp::Now();
    9455               0 :       TimeDuration delay = firingTime - currentNow;
    9456                 : 
    9457                 :       // And make sure delay is nonnegative; that might happen if the timer
    9458                 :       // thread is firing our timers somewhat early or if they're taking a long
    9459                 :       // time to run the callback.
    9460               0 :       if (delay < TimeDuration(0)) {
    9461               0 :         delay = TimeDuration(0);
    9462                 :       }
    9463                 : 
    9464               0 :       if (timeout->mTimer) {
    9465               0 :         timeout->mWhen = currentNow + delay; // firingTime unless delay got
    9466                 :                                              // clamped, in which case it's
    9467                 :                                              // currentNow.
    9468                 : 
    9469                 :         // Reschedule the OS timer. Don't bother returning any error
    9470                 :         // codes if this fails since the callers of this method
    9471                 :         // doesn't care about them nobody who cares about them
    9472                 :         // anyways.
    9473                 : 
    9474                 :         // Make sure to cast the unsigned PR_USEC_PER_MSEC to signed
    9475                 :         // PRTime to make the division do the right thing on 64-bit
    9476                 :         // platforms whether delay is positive or negative (which we
    9477                 :         // know is always positive here, but cast anyways for
    9478                 :         // consistency).
    9479               0 :         nsresult rv = timeout->mTimer->
    9480                 :           InitWithFuncCallback(TimerCallback, timeout,
    9481               0 :                                delay.ToMilliseconds(),
    9482               0 :                                nsITimer::TYPE_ONE_SHOT);
    9483                 : 
    9484               0 :         if (NS_FAILED(rv)) {
    9485               0 :           NS_ERROR("Error initializing timer for DOM timeout!");
    9486                 : 
    9487                 :           // We failed to initialize the new OS timer, this timer does
    9488                 :           // us no good here so we just cancel it (just in case) and
    9489                 :           // null out the pointer to the OS timer, this will release the
    9490                 :           // OS timer. As we continue executing the code below we'll end
    9491                 :           // up deleting the timeout since it's not an interval timeout
    9492                 :           // any more (since timeout->mTimer == nsnull).
    9493               0 :           timeout->mTimer->Cancel();
    9494               0 :           timeout->mTimer = nsnull;
    9495                 : 
    9496                 :           // Now that the OS timer no longer has a reference to the
    9497                 :           // timeout we need to drop that reference.
    9498               0 :           timeout->Release();
    9499                 :         }
    9500                 :       } else {
    9501               0 :         NS_ASSERTION(IsFrozen() || mTimeoutsSuspendDepth,
    9502                 :                      "How'd our timer end up null if we're not frozen or "
    9503                 :                      "suspended?");
    9504                 : 
    9505               0 :         timeout->mTimeRemaining = delay;
    9506               0 :         isInterval = true;
    9507                 :       }
    9508                 :     }
    9509                 : 
    9510               0 :     if (timeout->mTimer) {
    9511               0 :       if (timeout->mIsInterval) {
    9512               0 :         isInterval = true;
    9513                 :       } else {
    9514                 :         // The timeout still has an OS timer, and it's not an
    9515                 :         // interval, that means that the OS timer could still fire (if
    9516                 :         // it didn't already, i.e. aTimeout == timeout), cancel the OS
    9517                 :         // timer and release its reference to the timeout.
    9518               0 :         timeout->mTimer->Cancel();
    9519               0 :         timeout->mTimer = nsnull;
    9520                 : 
    9521               0 :         timeout->Release();
    9522                 :       }
    9523                 :     }
    9524                 : 
    9525                 :     // Running a timeout can cause another timeout to be deleted, so
    9526                 :     // we need to reset the pointer to the following timeout.
    9527               0 :     nextTimeout = timeout->Next();
    9528                 : 
    9529               0 :     PR_REMOVE_LINK(timeout);
    9530                 : 
    9531               0 :     if (isInterval) {
    9532                 :       // Reschedule an interval timeout. Insert interval timeout
    9533                 :       // onto list sorted in deadline order.
    9534                 :       // AddRefs timeout.
    9535               0 :       InsertTimeoutIntoList(timeout);
    9536                 :     }
    9537                 : 
    9538                 :     // Release the timeout struct since it's possibly out of the list
    9539               0 :     timeout->Release();
    9540                 :   }
    9541                 : 
    9542                 :   // Take the dummy timeout off the head of the list
    9543               0 :   PR_REMOVE_LINK(&dummy_timeout);
    9544                 : 
    9545               0 :   mTimeoutInsertionPoint = last_insertion_point;
    9546                 : }
    9547                 : 
    9548                 : nsrefcnt
    9549               0 : nsTimeout::Release()
    9550                 : {
    9551               0 :   if (--mRefCnt > 0)
    9552               0 :     return mRefCnt;
    9553                 : 
    9554                 :   // language specific cleanup done as mScriptHandler destructs...
    9555                 : 
    9556                 :   // Kill the timer if it is still alive.
    9557               0 :   if (mTimer) {
    9558               0 :     mTimer->Cancel();
    9559               0 :     mTimer = nsnull;
    9560                 :   }
    9561                 : 
    9562               0 :   delete this;
    9563               0 :   return 0;
    9564                 : }
    9565                 : 
    9566                 : nsrefcnt
    9567               0 : nsTimeout::AddRef()
    9568                 : {
    9569               0 :   return ++mRefCnt;
    9570                 : }
    9571                 : 
    9572                 : 
    9573                 : nsresult
    9574               0 : nsGlobalWindow::ClearTimeoutOrInterval(PRInt32 aTimerID)
    9575                 : {
    9576               0 :   FORWARD_TO_INNER(ClearTimeoutOrInterval, (aTimerID), NS_ERROR_NOT_INITIALIZED);
    9577                 : 
    9578               0 :   PRUint32 public_id = (PRUint32)aTimerID;
    9579                 :   nsTimeout *timeout;
    9580                 : 
    9581               0 :   for (timeout = FirstTimeout();
    9582               0 :        IsTimeout(timeout);
    9583                 :        timeout = timeout->Next()) {
    9584               0 :     if (timeout->mPublicId == public_id) {
    9585               0 :       if (timeout->mRunning) {
    9586                 :         /* We're running from inside the timeout. Mark this
    9587                 :            timeout for deferred deletion by the code in
    9588                 :            RunTimeout() */
    9589               0 :         timeout->mIsInterval = false;
    9590                 :       }
    9591                 :       else {
    9592                 :         /* Delete the timeout from the pending timeout list */
    9593               0 :         PR_REMOVE_LINK(timeout);
    9594                 : 
    9595               0 :         if (timeout->mTimer) {
    9596               0 :           timeout->mTimer->Cancel();
    9597               0 :           timeout->mTimer = nsnull;
    9598               0 :           timeout->Release();
    9599                 :         }
    9600               0 :         timeout->Release();
    9601                 :       }
    9602               0 :       break;
    9603                 :     }
    9604                 :   }
    9605                 : 
    9606               0 :   return NS_OK;
    9607                 : }
    9608                 : 
    9609               0 : nsresult nsGlobalWindow::ResetTimersForNonBackgroundWindow()
    9610                 : {
    9611               0 :   FORWARD_TO_INNER(ResetTimersForNonBackgroundWindow, (),
    9612                 :                    NS_ERROR_NOT_INITIALIZED);
    9613                 : 
    9614               0 :   if (IsFrozen() || mTimeoutsSuspendDepth) {
    9615               0 :     return NS_OK;
    9616                 :   }
    9617                 : 
    9618               0 :   TimeStamp now = TimeStamp::Now();
    9619                 : 
    9620                 :   // If mTimeoutInsertionPoint is non-null, we're in the middle of firing
    9621                 :   // timers and the timers we're planning to fire all come before
    9622                 :   // mTimeoutInsertionPoint; mTimeoutInsertionPoint itself is a dummy timeout
    9623                 :   // with an mWhen that may be semi-bogus.  In that case, we don't need to do
    9624                 :   // anything with mTimeoutInsertionPoint or anything before it, so should
    9625                 :   // start at the timer after mTimeoutInsertionPoint, if there is one.
    9626                 :   // Otherwise, start at the beginning of the list.
    9627               0 :   for (nsTimeout *timeout = mTimeoutInsertionPoint ?
    9628               0 :          mTimeoutInsertionPoint->Next() : FirstTimeout();
    9629               0 :        IsTimeout(timeout); ) {
    9630                 :     // It's important that this check be <= so that we guarantee that
    9631                 :     // taking NS_MAX with |now| won't make a quantity equal to
    9632                 :     // timeout->mWhen below.
    9633               0 :     if (timeout->mWhen <= now) {
    9634               0 :       timeout = timeout->Next();
    9635               0 :       continue;
    9636                 :     }
    9637                 : 
    9638               0 :     if (timeout->mWhen - now >
    9639               0 :         TimeDuration::FromMilliseconds(gMinBackgroundTimeoutValue)) {
    9640                 :       // No need to loop further.  Timeouts are sorted in mWhen order
    9641                 :       // and the ones after this point were all set up for at least
    9642                 :       // gMinBackgroundTimeoutValue ms and hence were not clamped.
    9643               0 :       break;
    9644                 :     }
    9645                 : 
    9646                 :     /* We switched from background. Re-init the timer appropriately */
    9647                 :     // Compute the interval the timer should have had if it had not been set in a
    9648                 :     // background window
    9649                 :     TimeDuration interval =
    9650                 :       TimeDuration::FromMilliseconds(NS_MAX(timeout->mInterval,
    9651               0 :                                             PRUint32(DOMMinTimeoutValue())));
    9652               0 :     PRUint32 oldIntervalMillisecs = 0;
    9653               0 :     timeout->mTimer->GetDelay(&oldIntervalMillisecs);
    9654               0 :     TimeDuration oldInterval = TimeDuration::FromMilliseconds(oldIntervalMillisecs);
    9655               0 :     if (oldInterval > interval) {
    9656                 :       // unclamp
    9657                 :       TimeStamp firingTime =
    9658               0 :         NS_MAX(timeout->mWhen - oldInterval + interval, now);
    9659                 : 
    9660               0 :       NS_ASSERTION(firingTime < timeout->mWhen,
    9661                 :                    "Our firing time should strictly decrease!");
    9662                 : 
    9663               0 :       TimeDuration delay = firingTime - now;
    9664               0 :       timeout->mWhen = firingTime;
    9665                 : 
    9666                 :       // Since we reset mWhen we need to move |timeout| to the right
    9667                 :       // place in the list so that it remains sorted by mWhen.
    9668                 :       
    9669                 :       // Get the pointer to the next timeout now, before we move the
    9670                 :       // current timeout in the list.
    9671               0 :       nsTimeout* nextTimeout = timeout->Next();
    9672                 : 
    9673                 :       // It is safe to remove and re-insert because mWhen is now
    9674                 :       // strictly smaller than it used to be, so we know we'll insert
    9675                 :       // |timeout| before nextTimeout.
    9676               0 :       NS_ASSERTION(!IsTimeout(nextTimeout) ||
    9677                 :                    timeout->mWhen < nextTimeout->mWhen, "How did that happen?");
    9678               0 :       PR_REMOVE_LINK(timeout);
    9679                 :       // InsertTimeoutIntoList will addref |timeout| and reset
    9680                 :       // mFiringDepth.  Make sure to undo that after calling it.
    9681               0 :       PRUint32 firingDepth = timeout->mFiringDepth;
    9682               0 :       InsertTimeoutIntoList(timeout);
    9683               0 :       timeout->mFiringDepth = firingDepth;
    9684               0 :       timeout->Release();
    9685                 : 
    9686                 :       nsresult rv =
    9687               0 :         timeout->mTimer->InitWithFuncCallback(TimerCallback,
    9688                 :                                               timeout,
    9689               0 :                                               delay.ToMilliseconds(),
    9690               0 :                                               nsITimer::TYPE_ONE_SHOT);
    9691                 : 
    9692               0 :       if (NS_FAILED(rv)) {
    9693               0 :         NS_WARNING("Error resetting non background timer for DOM timeout!");
    9694               0 :         return rv;
    9695                 :       }
    9696                 : 
    9697               0 :       timeout = nextTimeout;
    9698                 :     } else {
    9699               0 :       timeout = timeout->Next();
    9700                 :     }
    9701                 :   }
    9702                 : 
    9703               0 :   return NS_OK;
    9704                 : }
    9705                 : 
    9706                 : void
    9707               0 : nsGlobalWindow::ClearAllTimeouts()
    9708                 : {
    9709                 :   nsTimeout *timeout, *nextTimeout;
    9710                 : 
    9711               0 :   for (timeout = FirstTimeout(); IsTimeout(timeout); timeout = nextTimeout) {
    9712                 :     /* If RunTimeout() is higher up on the stack for this
    9713                 :        window, e.g. as a result of document.write from a timeout,
    9714                 :        then we need to reset the list insertion point for
    9715                 :        newly-created timeouts in case the user adds a timeout,
    9716                 :        before we pop the stack back to RunTimeout. */
    9717               0 :     if (mRunningTimeout == timeout)
    9718               0 :       mTimeoutInsertionPoint = nsnull;
    9719                 : 
    9720               0 :     nextTimeout = timeout->Next();
    9721                 : 
    9722               0 :     if (timeout->mTimer) {
    9723               0 :       timeout->mTimer->Cancel();
    9724               0 :       timeout->mTimer = nsnull;
    9725                 : 
    9726                 :       // Drop the count since the timer isn't going to hold on
    9727                 :       // anymore.
    9728               0 :       timeout->Release();
    9729                 :     }
    9730                 : 
    9731                 :     // Set timeout->mCleared to true to indicate that the timeout was
    9732                 :     // cleared and taken out of the list of timeouts
    9733               0 :     timeout->mCleared = true;
    9734                 : 
    9735                 :     // Drop the count since we're removing it from the list.
    9736               0 :     timeout->Release();
    9737                 :   }
    9738                 : 
    9739                 :   // Clear out our list
    9740               0 :   PR_INIT_CLIST(&mTimeouts);
    9741               0 : }
    9742                 : 
    9743                 : void
    9744               0 : nsGlobalWindow::InsertTimeoutIntoList(nsTimeout *aTimeout)
    9745                 : {
    9746               0 :   NS_ASSERTION(IsInnerWindow(),
    9747                 :                "InsertTimeoutIntoList() called on outer window!");
    9748                 : 
    9749                 :   // Start at mLastTimeout and go backwards.  Don't go further than
    9750                 :   // mTimeoutInsertionPoint, though.  This optimizes for the common case of
    9751                 :   // insertion at the end.
    9752                 :   nsTimeout* prevSibling;
    9753               0 :   for (prevSibling = LastTimeout();
    9754               0 :        IsTimeout(prevSibling) && prevSibling != mTimeoutInsertionPoint &&
    9755                 :          // This condition needs to match the one in SetTimeoutOrInterval that
    9756                 :          // determines whether to set mWhen or mTimeRemaining.
    9757               0 :          ((IsFrozen() || mTimeoutsSuspendDepth) ?
    9758               0 :           prevSibling->mTimeRemaining > aTimeout->mTimeRemaining :
    9759               0 :           prevSibling->mWhen > aTimeout->mWhen);
    9760                 :        prevSibling = prevSibling->Prev()) {
    9761                 :     /* Do nothing; just searching */
    9762                 :   }
    9763                 : 
    9764                 :   // Now link in aTimeout after prevSibling.
    9765               0 :   PR_INSERT_AFTER(aTimeout, prevSibling);
    9766                 : 
    9767               0 :   aTimeout->mFiringDepth = 0;
    9768                 : 
    9769                 :   // Increment the timeout's reference count since it's now held on to
    9770                 :   // by the list
    9771               0 :   aTimeout->AddRef();
    9772               0 : }
    9773                 : 
    9774                 : // static
    9775                 : void
    9776               0 : nsGlobalWindow::TimerCallback(nsITimer *aTimer, void *aClosure)
    9777                 : {
    9778               0 :   nsRefPtr<nsTimeout> timeout = (nsTimeout *)aClosure;
    9779                 : 
    9780               0 :   timeout->mWindow->RunTimeout(timeout);
    9781               0 : }
    9782                 : 
    9783                 : //*****************************************************************************
    9784                 : // nsGlobalWindow: Helper Functions
    9785                 : //*****************************************************************************
    9786                 : 
    9787                 : nsresult
    9788               0 : nsGlobalWindow::GetTreeOwner(nsIDocShellTreeOwner **aTreeOwner)
    9789                 : {
    9790               0 :   FORWARD_TO_OUTER(GetTreeOwner, (aTreeOwner), NS_ERROR_NOT_INITIALIZED);
    9791                 : 
    9792               0 :   nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(do_QueryInterface(mDocShell));
    9793                 : 
    9794                 :   // If there's no docShellAsItem, this window must have been closed,
    9795                 :   // in that case there is no tree owner.
    9796                 : 
    9797               0 :   if (!docShellAsItem) {
    9798               0 :     *aTreeOwner = nsnull;
    9799                 : 
    9800               0 :     return NS_OK;
    9801                 :   }
    9802                 : 
    9803               0 :   return docShellAsItem->GetTreeOwner(aTreeOwner);
    9804                 : }
    9805                 : 
    9806                 : nsresult
    9807               0 : nsGlobalWindow::GetTreeOwner(nsIBaseWindow **aTreeOwner)
    9808                 : {
    9809               0 :   FORWARD_TO_OUTER(GetTreeOwner, (aTreeOwner), NS_ERROR_NOT_INITIALIZED);
    9810                 : 
    9811               0 :   nsCOMPtr<nsIDocShellTreeItem> docShellAsItem(do_QueryInterface(mDocShell));
    9812               0 :   nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
    9813                 : 
    9814                 :   // If there's no docShellAsItem, this window must have been closed,
    9815                 :   // in that case there is no tree owner.
    9816                 : 
    9817               0 :   if (docShellAsItem) {
    9818               0 :     docShellAsItem->GetTreeOwner(getter_AddRefs(treeOwner));
    9819                 :   }
    9820                 : 
    9821               0 :   if (!treeOwner) {
    9822               0 :     *aTreeOwner = nsnull;
    9823               0 :     return NS_OK;
    9824                 :   }
    9825                 : 
    9826               0 :   return CallQueryInterface(treeOwner, aTreeOwner);
    9827                 : }
    9828                 : 
    9829                 : nsresult
    9830               0 : nsGlobalWindow::GetWebBrowserChrome(nsIWebBrowserChrome **aBrowserChrome)
    9831                 : {
    9832               0 :   nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
    9833               0 :   GetTreeOwner(getter_AddRefs(treeOwner));
    9834                 : 
    9835               0 :   nsCOMPtr<nsIWebBrowserChrome> browserChrome(do_GetInterface(treeOwner));
    9836               0 :   NS_IF_ADDREF(*aBrowserChrome = browserChrome);
    9837                 : 
    9838               0 :   return NS_OK;
    9839                 : }
    9840                 : 
    9841                 : nsIScrollableFrame *
    9842               0 : nsGlobalWindow::GetScrollFrame()
    9843                 : {
    9844               0 :   FORWARD_TO_OUTER(GetScrollFrame, (), nsnull);
    9845                 : 
    9846               0 :   if (!mDocShell) {
    9847               0 :     return nsnull;
    9848                 :   }
    9849                 : 
    9850               0 :   nsCOMPtr<nsIPresShell> presShell;
    9851               0 :   mDocShell->GetPresShell(getter_AddRefs(presShell));
    9852               0 :   if (presShell) {
    9853               0 :     return presShell->GetRootScrollFrameAsScrollable();
    9854                 :   }
    9855               0 :   return nsnull;
    9856                 : }
    9857                 : 
    9858                 : nsresult
    9859               0 : nsGlobalWindow::BuildURIfromBase(const char *aURL, nsIURI **aBuiltURI,
    9860                 :                                  bool *aFreeSecurityPass,
    9861                 :                                  JSContext **aCXused)
    9862                 : {
    9863               0 :   nsIScriptContext *scx = GetContextInternal();
    9864               0 :   JSContext *cx = nsnull;
    9865                 : 
    9866               0 :   *aBuiltURI = nsnull;
    9867               0 :   *aFreeSecurityPass = false;
    9868               0 :   if (aCXused)
    9869               0 :     *aCXused = nsnull;
    9870                 : 
    9871                 :   // get JSContext
    9872               0 :   NS_ASSERTION(scx, "opening window missing its context");
    9873               0 :   NS_ASSERTION(mDocument, "opening window missing its document");
    9874               0 :   if (!scx || !mDocument)
    9875               0 :     return NS_ERROR_FAILURE;
    9876                 : 
    9877               0 :   nsCOMPtr<nsIDOMChromeWindow> chrome_win = do_QueryObject(this);
    9878                 : 
    9879               0 :   if (nsContentUtils::IsCallerChrome() && !chrome_win) {
    9880                 :     // If open() is called from chrome on a non-chrome window, we'll
    9881                 :     // use the context from the window on which open() is being called
    9882                 :     // to prevent giving chrome priveleges to new windows opened in
    9883                 :     // such a way. This also makes us get the appropriate base URI for
    9884                 :     // the below URI resolution code.
    9885                 : 
    9886               0 :     cx = scx->GetNativeContext();
    9887                 :   } else {
    9888                 :     // get the JSContext from the call stack
    9889               0 :     nsCOMPtr<nsIThreadJSContextStack> stack(do_GetService(sJSStackContractID));
    9890               0 :     if (stack)
    9891               0 :       stack->Peek(&cx);
    9892                 :   }
    9893                 : 
    9894                 :   /* resolve the URI, which could be relative to the calling window
    9895                 :      (note the algorithm to get the base URI should match the one
    9896                 :      used to actually kick off the load in nsWindowWatcher.cpp). */
    9897               0 :   nsCAutoString charset(NS_LITERAL_CSTRING("UTF-8")); // default to utf-8
    9898               0 :   nsIURI* baseURI = nsnull;
    9899               0 :   nsCOMPtr<nsIURI> uriToLoad;
    9900               0 :   nsCOMPtr<nsIDOMWindow> sourceWindow;
    9901                 : 
    9902               0 :   if (cx) {
    9903               0 :     nsIScriptContext *scriptcx = nsJSUtils::GetDynamicScriptContext(cx);
    9904               0 :     if (scriptcx)
    9905               0 :       sourceWindow = do_QueryInterface(scriptcx->GetGlobalObject());
    9906                 :   }
    9907                 : 
    9908               0 :   if (!sourceWindow) {
    9909               0 :     sourceWindow = do_QueryInterface(NS_ISUPPORTS_CAST(nsIDOMWindow *, this));
    9910               0 :     *aFreeSecurityPass = true;
    9911                 :   }
    9912                 : 
    9913               0 :   if (sourceWindow) {
    9914               0 :     nsCOMPtr<nsIDOMDocument> domDoc;
    9915               0 :     sourceWindow->GetDocument(getter_AddRefs(domDoc));
    9916               0 :     nsCOMPtr<nsIDocument> doc(do_QueryInterface(domDoc));
    9917               0 :     if (doc) {
    9918               0 :       baseURI = doc->GetDocBaseURI();
    9919               0 :       charset = doc->GetDocumentCharacterSet();
    9920                 :     }
    9921                 :   }
    9922                 : 
    9923               0 :   if (aCXused)
    9924               0 :     *aCXused = cx;
    9925               0 :   return NS_NewURI(aBuiltURI, nsDependentCString(aURL), charset.get(), baseURI);
    9926                 : }
    9927                 : 
    9928                 : nsresult
    9929               0 : nsGlobalWindow::SecurityCheckURL(const char *aURL)
    9930                 : {
    9931                 :   JSContext       *cx;
    9932                 :   bool             freePass;
    9933               0 :   nsCOMPtr<nsIURI> uri;
    9934                 : 
    9935               0 :   if (NS_FAILED(BuildURIfromBase(aURL, getter_AddRefs(uri), &freePass, &cx)))
    9936               0 :     return NS_ERROR_FAILURE;
    9937                 : 
    9938               0 :   if (!freePass && NS_FAILED(nsContentUtils::GetSecurityManager()->
    9939                 :         CheckLoadURIFromScript(cx, uri)))
    9940               0 :     return NS_ERROR_FAILURE;
    9941                 : 
    9942               0 :   return NS_OK;
    9943                 : }
    9944                 : 
    9945                 : void
    9946               0 : nsGlobalWindow::FlushPendingNotifications(mozFlushType aType)
    9947                 : {
    9948               0 :   if (mDoc) {
    9949               0 :     mDoc->FlushPendingNotifications(aType);
    9950                 :   }
    9951               0 : }
    9952                 : 
    9953                 : void
    9954               0 : nsGlobalWindow::EnsureSizeUpToDate()
    9955                 : {
    9956                 :   // If we're a subframe, make sure our size is up to date.  It's OK that this
    9957                 :   // crosses the content/chrome boundary, since chrome can have pending reflows
    9958                 :   // too.
    9959                 :   nsGlobalWindow *parent =
    9960               0 :     static_cast<nsGlobalWindow *>(GetPrivateParent());
    9961               0 :   if (parent) {
    9962               0 :     parent->FlushPendingNotifications(Flush_Layout);
    9963                 :   }
    9964               0 : }
    9965                 : 
    9966                 : nsresult
    9967               0 : nsGlobalWindow::SaveWindowState(nsISupports **aState)
    9968                 : {
    9969               0 :   NS_PRECONDITION(IsOuterWindow(), "Can't save the inner window's state");
    9970                 : 
    9971               0 :   *aState = nsnull;
    9972                 : 
    9973               0 :   if (!mContext || !mJSObject) {
    9974                 :     // The window may be getting torn down; don't bother saving state.
    9975               0 :     return NS_OK;
    9976                 :   }
    9977                 : 
    9978               0 :   nsGlobalWindow *inner = GetCurrentInnerWindowInternal();
    9979               0 :   NS_ASSERTION(inner, "No inner window to save");
    9980                 : 
    9981                 :   // Don't do anything else to this inner window! After this point, all
    9982                 :   // calls to SetTimeoutOrInterval will create entries in the timeout
    9983                 :   // list that will only run after this window has come out of the bfcache.
    9984                 :   // Also, while we're frozen, we won't dispatch online/offline events
    9985                 :   // to the page.
    9986               0 :   inner->Freeze();
    9987                 : 
    9988                 :   // Remember the outer window's prototype.
    9989               0 :   JSContext *cx = mContext->GetNativeContext();
    9990               0 :   JSAutoRequest req(cx);
    9991                 : 
    9992               0 :   nsIXPConnect *xpc = nsContentUtils::XPConnect();
    9993                 : 
    9994                 :   nsCOMPtr<nsIClassInfo> ci =
    9995               0 :     do_QueryInterface((nsIScriptGlobalObject *)this);
    9996               0 :   nsCOMPtr<nsIXPConnectJSObjectHolder> proto;
    9997                 :   nsresult rv = xpc->GetWrappedNativePrototype(cx, mJSObject, ci,
    9998               0 :                                                getter_AddRefs(proto));
    9999               0 :   NS_ENSURE_SUCCESS(rv, rv);
   10000                 : 
   10001               0 :   JSObject *realProto = JS_GetPrototype(mJSObject);
   10002               0 :   nsCOMPtr<nsIXPConnectJSObjectHolder> realProtoHolder;
   10003               0 :   if (realProto) {
   10004               0 :     rv = xpc->HoldObject(cx, realProto, getter_AddRefs(realProtoHolder));
   10005               0 :     NS_ENSURE_SUCCESS(rv, rv);
   10006                 :   }
   10007                 : 
   10008                 :   nsCOMPtr<nsISupports> state = new WindowStateHolder(inner,
   10009                 :                                                       mInnerWindowHolder,
   10010                 :                                                       proto,
   10011               0 :                                                       realProtoHolder);
   10012               0 :   NS_ENSURE_TRUE(state, NS_ERROR_OUT_OF_MEMORY);
   10013                 : 
   10014                 :   JSObject *wnProto;
   10015               0 :   proto->GetJSObject(&wnProto);
   10016               0 :   if (!JS_SetPrototype(cx, mJSObject, wnProto)) {
   10017               0 :     return NS_ERROR_FAILURE;
   10018                 :   }
   10019                 : 
   10020                 : #ifdef DEBUG_PAGE_CACHE
   10021                 :   printf("saving window state, state = %p\n", (void*)state);
   10022                 : #endif
   10023                 : 
   10024               0 :   state.swap(*aState);
   10025               0 :   return NS_OK;
   10026                 : }
   10027                 : 
   10028                 : nsresult
   10029               0 : nsGlobalWindow::RestoreWindowState(nsISupports *aState)
   10030                 : {
   10031               0 :   NS_ASSERTION(IsOuterWindow(), "Cannot restore an inner window");
   10032                 : 
   10033               0 :   if (!mContext || !mJSObject) {
   10034                 :     // The window may be getting torn down; don't bother restoring state.
   10035               0 :     return NS_OK;
   10036                 :   }
   10037                 : 
   10038               0 :   nsCOMPtr<WindowStateHolder> holder = do_QueryInterface(aState);
   10039               0 :   NS_ENSURE_TRUE(holder, NS_ERROR_FAILURE);
   10040                 : 
   10041                 : #ifdef DEBUG_PAGE_CACHE
   10042                 :   printf("restoring window state, state = %p\n", (void*)holder);
   10043                 : #endif
   10044                 : 
   10045                 :   // And we're ready to go!
   10046               0 :   nsGlobalWindow *inner = GetCurrentInnerWindowInternal();
   10047                 : 
   10048                 :   // if a link is focused, refocus with the FLAG_SHOWRING flag set. This makes
   10049                 :   // it easy to tell which link was last clicked when going back a page.
   10050               0 :   nsIContent* focusedNode = inner->GetFocusedNode();
   10051               0 :   if (IsLink(focusedNode)) {
   10052               0 :     nsIFocusManager* fm = nsFocusManager::GetFocusManager();
   10053               0 :     if (fm) {
   10054               0 :       nsCOMPtr<nsIDOMElement> focusedElement(do_QueryInterface(focusedNode));
   10055                 :       fm->SetFocus(focusedElement, nsIFocusManager::FLAG_NOSCROLL |
   10056               0 :                                    nsIFocusManager::FLAG_SHOWRING);
   10057                 :     }
   10058                 :   }
   10059                 : 
   10060               0 :   inner->Thaw();
   10061                 : 
   10062               0 :   holder->DidRestoreWindow();
   10063                 : 
   10064               0 :   return NS_OK;
   10065                 : }
   10066                 : 
   10067                 : void
   10068               0 : nsGlobalWindow::SuspendTimeouts(PRUint32 aIncrease,
   10069                 :                                 bool aFreezeChildren)
   10070                 : {
   10071               0 :   FORWARD_TO_INNER_VOID(SuspendTimeouts, (aIncrease, aFreezeChildren));
   10072                 : 
   10073               0 :   bool suspended = (mTimeoutsSuspendDepth != 0);
   10074               0 :   mTimeoutsSuspendDepth += aIncrease;
   10075                 : 
   10076               0 :   if (!suspended) {
   10077               0 :     DisableDeviceMotionUpdates();
   10078                 : 
   10079                 :     // Suspend all of the workers for this window.
   10080               0 :     nsIScriptContext *scx = GetContextInternal();
   10081               0 :     JSContext *cx = scx ? scx->GetNativeContext() : nsnull;
   10082               0 :     mozilla::dom::workers::SuspendWorkersForWindow(cx, this);
   10083                 : 
   10084               0 :     TimeStamp now = TimeStamp::Now();
   10085               0 :     for (nsTimeout *t = FirstTimeout(); IsTimeout(t); t = t->Next()) {
   10086                 :       // Set mTimeRemaining to be the time remaining for this timer.
   10087               0 :       if (t->mWhen > now)
   10088               0 :         t->mTimeRemaining = t->mWhen - now;
   10089                 :       else
   10090               0 :         t->mTimeRemaining = TimeDuration(0);
   10091                 :   
   10092                 :       // Drop the XPCOM timer; we'll reschedule when restoring the state.
   10093               0 :       if (t->mTimer) {
   10094               0 :         t->mTimer->Cancel();
   10095               0 :         t->mTimer = nsnull;
   10096                 :   
   10097                 :         // Drop the reference that the timer's closure had on this timeout, we'll
   10098                 :         // add it back in ResumeTimeouts. Note that it shouldn't matter that we're
   10099                 :         // passing null for the context, since this shouldn't actually release this
   10100                 :         // timeout.
   10101               0 :         t->Release();
   10102                 :       }
   10103                 :     }
   10104                 :   }
   10105                 : 
   10106                 :   // Suspend our children as well.
   10107               0 :   nsCOMPtr<nsIDocShellTreeNode> node(do_QueryInterface(GetDocShell()));
   10108               0 :   if (node) {
   10109               0 :     PRInt32 childCount = 0;
   10110               0 :     node->GetChildCount(&childCount);
   10111                 : 
   10112               0 :     for (PRInt32 i = 0; i < childCount; ++i) {
   10113               0 :       nsCOMPtr<nsIDocShellTreeItem> childShell;
   10114               0 :       node->GetChildAt(i, getter_AddRefs(childShell));
   10115               0 :       NS_ASSERTION(childShell, "null child shell");
   10116                 : 
   10117               0 :       nsCOMPtr<nsPIDOMWindow> pWin = do_GetInterface(childShell);
   10118               0 :       if (pWin) {
   10119                 :         nsGlobalWindow *win =
   10120                 :           static_cast<nsGlobalWindow*>
   10121               0 :                      (static_cast<nsPIDOMWindow*>(pWin));
   10122               0 :         NS_ASSERTION(win->IsOuterWindow(), "Expected outer window");
   10123               0 :         nsGlobalWindow* inner = win->GetCurrentInnerWindowInternal();
   10124                 : 
   10125                 :         // This is a bit hackish. Only freeze/suspend windows which are truly our
   10126                 :         // subwindows.
   10127               0 :         nsCOMPtr<nsIContent> frame = do_QueryInterface(pWin->GetFrameElementInternal());
   10128               0 :         if (!mDoc || !frame || mDoc != frame->OwnerDoc() || !inner) {
   10129               0 :           continue;
   10130                 :         }
   10131                 : 
   10132               0 :         win->SuspendTimeouts(aIncrease, aFreezeChildren);
   10133                 : 
   10134               0 :         if (inner && aFreezeChildren) {
   10135               0 :           inner->Freeze();
   10136                 :         }
   10137                 :       }
   10138                 :     }
   10139                 :   }
   10140                 : }
   10141                 : 
   10142                 : nsresult
   10143               0 : nsGlobalWindow::ResumeTimeouts(bool aThawChildren)
   10144                 : {
   10145               0 :   FORWARD_TO_INNER(ResumeTimeouts, (), NS_ERROR_NOT_INITIALIZED);
   10146                 : 
   10147               0 :   NS_ASSERTION(mTimeoutsSuspendDepth, "Mismatched calls to ResumeTimeouts!");
   10148               0 :   --mTimeoutsSuspendDepth;
   10149               0 :   bool shouldResume = (mTimeoutsSuspendDepth == 0);
   10150                 :   nsresult rv;
   10151                 : 
   10152               0 :   if (shouldResume) {
   10153               0 :     EnableDeviceMotionUpdates();
   10154                 : 
   10155                 :     // Resume all of the workers for this window.
   10156               0 :     nsIScriptContext *scx = GetContextInternal();
   10157               0 :     JSContext *cx = scx ? scx->GetNativeContext() : nsnull;
   10158               0 :     mozilla::dom::workers::ResumeWorkersForWindow(cx, this);
   10159                 : 
   10160                 :     // Restore all of the timeouts, using the stored time remaining
   10161                 :     // (stored in timeout->mTimeRemaining).
   10162                 : 
   10163               0 :     TimeStamp now = TimeStamp::Now();
   10164                 : 
   10165                 : #ifdef DEBUG
   10166               0 :     bool _seenDummyTimeout = false;
   10167                 : #endif
   10168                 : 
   10169               0 :     for (nsTimeout *t = FirstTimeout(); IsTimeout(t); t = t->Next()) {
   10170                 :       // There's a chance we're being called with RunTimeout on the stack in which
   10171                 :       // case we have a dummy timeout in the list that *must not* be resumed. It
   10172                 :       // can be identified by a null mWindow.
   10173               0 :       if (!t->mWindow) {
   10174                 : #ifdef DEBUG
   10175               0 :         NS_ASSERTION(!_seenDummyTimeout, "More than one dummy timeout?!");
   10176               0 :         _seenDummyTimeout = true;
   10177                 : #endif
   10178               0 :         continue;
   10179                 :       }
   10180                 : 
   10181                 :       // XXXbz the combination of the way |delay| and |t->mWhen| are set here
   10182                 :       // makes no sense.  Are we trying to impose that min timeout value or
   10183                 :       // not???
   10184                 :       PRUint32 delay =
   10185               0 :         NS_MAX(PRInt32(t->mTimeRemaining.ToMilliseconds()),
   10186               0 :                DOMMinTimeoutValue());
   10187                 : 
   10188                 :       // Set mWhen back to the time when the timer is supposed to
   10189                 :       // fire.
   10190               0 :       t->mWhen = now + t->mTimeRemaining;
   10191                 : 
   10192               0 :       t->mTimer = do_CreateInstance("@mozilla.org/timer;1");
   10193               0 :       NS_ENSURE_TRUE(t->mTimer, NS_ERROR_OUT_OF_MEMORY);
   10194                 : 
   10195               0 :       rv = t->mTimer->InitWithFuncCallback(TimerCallback, t, delay,
   10196               0 :                                            nsITimer::TYPE_ONE_SHOT);
   10197               0 :       if (NS_FAILED(rv)) {
   10198               0 :         t->mTimer = nsnull;
   10199               0 :         return rv;
   10200                 :       }
   10201                 : 
   10202                 :       // Add a reference for the new timer's closure.
   10203               0 :       t->AddRef();
   10204                 :     }
   10205                 :   }
   10206                 : 
   10207                 :   // Resume our children as well.
   10208                 :   nsCOMPtr<nsIDocShellTreeNode> node =
   10209               0 :     do_QueryInterface(GetDocShell());
   10210               0 :   if (node) {
   10211               0 :     PRInt32 childCount = 0;
   10212               0 :     node->GetChildCount(&childCount);
   10213                 : 
   10214               0 :     for (PRInt32 i = 0; i < childCount; ++i) {
   10215               0 :       nsCOMPtr<nsIDocShellTreeItem> childShell;
   10216               0 :       node->GetChildAt(i, getter_AddRefs(childShell));
   10217               0 :       NS_ASSERTION(childShell, "null child shell");
   10218                 : 
   10219               0 :       nsCOMPtr<nsPIDOMWindow> pWin = do_GetInterface(childShell);
   10220               0 :       if (pWin) {
   10221                 :         nsGlobalWindow *win =
   10222                 :           static_cast<nsGlobalWindow*>
   10223               0 :                      (static_cast<nsPIDOMWindow*>(pWin));
   10224                 : 
   10225               0 :         NS_ASSERTION(win->IsOuterWindow(), "Expected outer window");
   10226               0 :         nsGlobalWindow* inner = win->GetCurrentInnerWindowInternal();
   10227                 : 
   10228                 :         // This is a bit hackish. Only thaw/resume windows which are truly our
   10229                 :         // subwindows.
   10230               0 :         nsCOMPtr<nsIContent> frame = do_QueryInterface(pWin->GetFrameElementInternal());
   10231               0 :         if (!mDoc || !frame || mDoc != frame->OwnerDoc() || !inner) {
   10232               0 :           continue;
   10233                 :         }
   10234                 : 
   10235               0 :         if (inner && aThawChildren) {
   10236               0 :           inner->Thaw();
   10237                 :         }
   10238                 : 
   10239               0 :         rv = win->ResumeTimeouts(aThawChildren);
   10240               0 :         NS_ENSURE_SUCCESS(rv, rv);
   10241                 :       }
   10242                 :     }
   10243                 :   }
   10244                 : 
   10245               0 :   return NS_OK;
   10246                 : }
   10247                 : 
   10248                 : PRUint32
   10249               0 : nsGlobalWindow::TimeoutSuspendCount()
   10250                 : {
   10251               0 :   FORWARD_TO_INNER(TimeoutSuspendCount, (), 0);
   10252               0 :   return mTimeoutsSuspendDepth;
   10253                 : }
   10254                 : 
   10255                 : void
   10256               0 : nsGlobalWindow::SetHasOrientationEventListener()
   10257                 : {
   10258               0 :   mHasDeviceMotion = true;
   10259               0 :   EnableDeviceMotionUpdates();
   10260               0 : }
   10261                 : 
   10262                 : void
   10263               0 : nsGlobalWindow::RemoveOrientationEventListener() {
   10264               0 :   DisableDeviceMotionUpdates();
   10265               0 : }
   10266                 : 
   10267                 : NS_IMETHODIMP
   10268               0 : nsGlobalWindow::GetURL(nsIDOMMozURLProperty** aURL)
   10269                 : {
   10270               0 :   FORWARD_TO_INNER(GetURL, (aURL), NS_ERROR_UNEXPECTED);
   10271                 : 
   10272               0 :   if (!mURLProperty) {
   10273               0 :     mURLProperty = new nsDOMMozURLProperty(this);
   10274                 :   }
   10275                 : 
   10276               0 :   NS_ADDREF(*aURL = mURLProperty);
   10277                 : 
   10278               0 :   return NS_OK;
   10279                 : }
   10280                 : 
   10281                 : // static
   10282                 : bool
   10283             612 : nsGlobalWindow::HasIndexedDBSupport()
   10284                 : {
   10285             612 :   return Preferences::GetBool("indexedDB.feature.enabled", true);
   10286                 : }
   10287                 : 
   10288                 : // static
   10289                 : bool
   10290            1836 : nsGlobalWindow::HasPerformanceSupport() 
   10291                 : {
   10292            1836 :   return Preferences::GetBool("dom.enable_performance", false);
   10293                 : }
   10294                 : 
   10295                 : void
   10296               0 : nsGlobalWindow::SizeOfIncludingThis(nsWindowSizes* aWindowSizes) const
   10297                 : {
   10298               0 :   aWindowSizes->mDOM += aWindowSizes->mMallocSizeOf(this);
   10299                 : 
   10300               0 :   if (IsInnerWindow()) {
   10301                 :     nsEventListenerManager* elm =
   10302               0 :       const_cast<nsGlobalWindow*>(this)->GetListenerManager(false);
   10303               0 :     if (elm) {
   10304                 :       aWindowSizes->mDOM +=
   10305               0 :         elm->SizeOfIncludingThis(aWindowSizes->mMallocSizeOf);
   10306                 :     }
   10307               0 :     if (mDoc) {
   10308               0 :       mDoc->DocSizeOfIncludingThis(aWindowSizes);
   10309                 :     }
   10310                 :   }
   10311                 : 
   10312                 :   aWindowSizes->mDOM +=
   10313                 :     mNavigator ?
   10314               0 :       mNavigator->SizeOfIncludingThis(aWindowSizes->mMallocSizeOf) : 0;
   10315               0 : }
   10316                 : 
   10317                 : // nsGlobalChromeWindow implementation
   10318                 : 
   10319            1464 : NS_IMPL_CYCLE_COLLECTION_CLASS(nsGlobalChromeWindow)
   10320               0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsGlobalChromeWindow,
   10321                 :                                                   nsGlobalWindow)
   10322               0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mBrowserDOMWindow)
   10323               0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mMessageManager)
   10324               0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
   10325                 : 
   10326                 : 
   10327               0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsGlobalChromeWindow,
   10328                 :                                                 nsGlobalWindow)
   10329               0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mBrowserDOMWindow)
   10330               0 :   if (tmp->mMessageManager) {
   10331                 :     static_cast<nsFrameMessageManager*>(
   10332               0 :       tmp->mMessageManager.get())->Disconnect();
   10333               0 :     NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mMessageManager)
   10334                 :   }
   10335               0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
   10336                 : 
   10337                 : DOMCI_DATA(ChromeWindow, nsGlobalChromeWindow)
   10338                 : 
   10339                 : // QueryInterface implementation for nsGlobalChromeWindow
   10340               0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsGlobalChromeWindow)
   10341               0 :   NS_INTERFACE_MAP_ENTRY(nsIDOMChromeWindow)
   10342               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(ChromeWindow)
   10343               0 : NS_INTERFACE_MAP_END_INHERITING(nsGlobalWindow)
   10344                 : 
   10345               0 : NS_IMPL_ADDREF_INHERITED(nsGlobalChromeWindow, nsGlobalWindow)
   10346               0 : NS_IMPL_RELEASE_INHERITED(nsGlobalChromeWindow, nsGlobalWindow)
   10347                 : 
   10348                 : NS_IMETHODIMP
   10349               0 : nsGlobalChromeWindow::GetWindowState(PRUint16* aWindowState)
   10350                 : {
   10351               0 :   *aWindowState = nsIDOMChromeWindow::STATE_NORMAL;
   10352                 : 
   10353               0 :   nsCOMPtr<nsIWidget> widget = GetMainWidget();
   10354                 : 
   10355               0 :   PRInt32 aMode = 0;
   10356                 : 
   10357               0 :   if (widget) {
   10358               0 :     nsresult rv = widget->GetSizeMode(&aMode);
   10359               0 :     NS_ENSURE_SUCCESS(rv, rv);
   10360                 :   }
   10361                 : 
   10362               0 :   switch (aMode) {
   10363                 :     case nsSizeMode_Minimized:
   10364               0 :       *aWindowState = nsIDOMChromeWindow::STATE_MINIMIZED;
   10365               0 :       break;
   10366                 :     case nsSizeMode_Maximized:
   10367               0 :       *aWindowState = nsIDOMChromeWindow::STATE_MAXIMIZED;
   10368               0 :       break;
   10369                 :     case nsSizeMode_Fullscreen:
   10370               0 :       *aWindowState = nsIDOMChromeWindow::STATE_FULLSCREEN;
   10371               0 :       break;
   10372                 :     case nsSizeMode_Normal:
   10373               0 :       *aWindowState = nsIDOMChromeWindow::STATE_NORMAL;
   10374               0 :       break;
   10375                 :     default:
   10376               0 :       NS_WARNING("Illegal window state for this chrome window");
   10377               0 :       break;
   10378                 :   }
   10379                 : 
   10380               0 :   return NS_OK;
   10381                 : }
   10382                 : 
   10383                 : NS_IMETHODIMP
   10384               0 : nsGlobalChromeWindow::Maximize()
   10385                 : {
   10386               0 :   nsCOMPtr<nsIWidget> widget = GetMainWidget();
   10387               0 :   nsresult rv = NS_OK;
   10388                 : 
   10389               0 :   if (widget) {
   10390               0 :     rv = widget->SetSizeMode(nsSizeMode_Maximized);
   10391                 :   }
   10392                 : 
   10393               0 :   return rv;
   10394                 : }
   10395                 : 
   10396                 : NS_IMETHODIMP
   10397               0 : nsGlobalChromeWindow::Minimize()
   10398                 : {
   10399               0 :   nsCOMPtr<nsIWidget> widget = GetMainWidget();
   10400               0 :   nsresult rv = NS_OK;
   10401                 : 
   10402               0 :   if (widget)
   10403               0 :     rv = widget->SetSizeMode(nsSizeMode_Minimized);
   10404                 : 
   10405               0 :   return rv;
   10406                 : }
   10407                 : 
   10408                 : NS_IMETHODIMP
   10409               0 : nsGlobalChromeWindow::Restore()
   10410                 : {
   10411               0 :   nsCOMPtr<nsIWidget> widget = GetMainWidget();
   10412               0 :   nsresult rv = NS_OK;
   10413                 : 
   10414               0 :   if (widget) {
   10415               0 :     rv = widget->SetSizeMode(nsSizeMode_Normal);
   10416                 :   }
   10417                 : 
   10418               0 :   return rv;
   10419                 : }
   10420                 : 
   10421                 : NS_IMETHODIMP
   10422               0 : nsGlobalChromeWindow::GetAttention()
   10423                 : {
   10424               0 :   return GetAttentionWithCycleCount(-1);
   10425                 : }
   10426                 : 
   10427                 : NS_IMETHODIMP
   10428               0 : nsGlobalChromeWindow::GetAttentionWithCycleCount(PRInt32 aCycleCount)
   10429                 : {
   10430               0 :   nsCOMPtr<nsIWidget> widget = GetMainWidget();
   10431               0 :   nsresult rv = NS_OK;
   10432                 : 
   10433               0 :   if (widget) {
   10434               0 :     rv = widget->GetAttention(aCycleCount);
   10435                 :   }
   10436                 : 
   10437               0 :   return rv;
   10438                 : }
   10439                 : 
   10440                 : NS_IMETHODIMP
   10441               0 : nsGlobalChromeWindow::BeginWindowMove(nsIDOMEvent *aMouseDownEvent, nsIDOMElement* aPanel)
   10442                 : {
   10443               0 :   nsCOMPtr<nsIWidget> widget;
   10444                 : 
   10445                 :   // if a panel was supplied, use its widget instead.
   10446                 : #ifdef MOZ_XUL
   10447               0 :   if (aPanel) {
   10448               0 :     nsCOMPtr<nsIContent> panel = do_QueryInterface(aPanel);
   10449               0 :     NS_ENSURE_TRUE(panel, NS_ERROR_FAILURE);
   10450                 : 
   10451               0 :     nsIFrame* frame = panel->GetPrimaryFrame();
   10452               0 :     NS_ENSURE_TRUE(frame && frame->GetType() == nsGkAtoms::menuPopupFrame, NS_OK);
   10453                 : 
   10454               0 :     widget = (static_cast<nsMenuPopupFrame*>(frame))->GetWidget();
   10455                 :   }
   10456                 :   else {
   10457                 : #endif
   10458               0 :     widget = GetMainWidget();
   10459                 : #ifdef MOZ_XUL
   10460                 :   }
   10461                 : #endif
   10462                 : 
   10463               0 :   if (!widget) {
   10464               0 :     return NS_OK;
   10465                 :   }
   10466                 : 
   10467               0 :   nsCOMPtr<nsIPrivateDOMEvent> privEvent = do_QueryInterface(aMouseDownEvent);
   10468               0 :   NS_ENSURE_TRUE(privEvent, NS_ERROR_FAILURE);
   10469               0 :   nsEvent *internalEvent = privEvent->GetInternalNSEvent();
   10470               0 :   NS_ENSURE_TRUE(internalEvent &&
   10471                 :                  internalEvent->eventStructType == NS_MOUSE_EVENT,
   10472                 :                  NS_ERROR_FAILURE);
   10473               0 :   nsMouseEvent *mouseEvent = static_cast<nsMouseEvent*>(internalEvent);
   10474                 : 
   10475               0 :   return widget->BeginMoveDrag(mouseEvent);
   10476                 : }
   10477                 : 
   10478                 : //Note: This call will lock the cursor, it will not change as it moves.
   10479                 : //To unlock, the cursor must be set back to CURSOR_AUTO.
   10480                 : NS_IMETHODIMP
   10481               0 : nsGlobalChromeWindow::SetCursor(const nsAString& aCursor)
   10482                 : {
   10483               0 :   FORWARD_TO_OUTER_CHROME(SetCursor, (aCursor), NS_ERROR_NOT_INITIALIZED);
   10484                 : 
   10485               0 :   nsresult rv = NS_OK;
   10486                 :   PRInt32 cursor;
   10487                 : 
   10488                 :   // use C strings to keep the code/data size down
   10489               0 :   NS_ConvertUTF16toUTF8 cursorString(aCursor);
   10490                 : 
   10491               0 :   if (cursorString.Equals("auto"))
   10492               0 :     cursor = NS_STYLE_CURSOR_AUTO;
   10493                 :   else {
   10494               0 :     nsCSSKeyword keyword = nsCSSKeywords::LookupKeyword(aCursor);
   10495               0 :     if (eCSSKeyword_UNKNOWN == keyword ||
   10496               0 :         !nsCSSProps::FindKeyword(keyword, nsCSSProps::kCursorKTable, cursor)) {
   10497                 :       // XXX remove the following three values (leave return NS_OK) after 1.8
   10498                 :       // XXX since they should have been -moz- prefixed (covered by FindKeyword).
   10499                 :       // XXX (also remove |cursorString| at that point?).
   10500               0 :       if (cursorString.Equals("grab"))
   10501               0 :         cursor = NS_STYLE_CURSOR_GRAB;
   10502               0 :       else if (cursorString.Equals("grabbing"))
   10503               0 :         cursor = NS_STYLE_CURSOR_GRABBING;
   10504               0 :       else if (cursorString.Equals("spinning"))
   10505               0 :         cursor = NS_STYLE_CURSOR_SPINNING;
   10506                 :       else
   10507               0 :         return NS_OK;
   10508                 :     }
   10509                 :   }
   10510                 : 
   10511               0 :   nsRefPtr<nsPresContext> presContext;
   10512               0 :   if (mDocShell) {
   10513               0 :     mDocShell->GetPresContext(getter_AddRefs(presContext));
   10514                 :   }
   10515                 : 
   10516               0 :   if (presContext) {
   10517                 :     // Need root widget.
   10518               0 :     nsCOMPtr<nsIPresShell> presShell;
   10519               0 :     mDocShell->GetPresShell(getter_AddRefs(presShell));
   10520               0 :     NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
   10521                 : 
   10522               0 :     nsIViewManager* vm = presShell->GetViewManager();
   10523               0 :     NS_ENSURE_TRUE(vm, NS_ERROR_FAILURE);
   10524                 : 
   10525               0 :     nsIView* rootView = vm->GetRootView();
   10526               0 :     NS_ENSURE_TRUE(rootView, NS_ERROR_FAILURE);
   10527                 : 
   10528               0 :     nsIWidget* widget = rootView->GetNearestWidget(nsnull);
   10529               0 :     NS_ENSURE_TRUE(widget, NS_ERROR_FAILURE);
   10530                 : 
   10531                 :     // Call esm and set cursor.
   10532                 :     rv = presContext->EventStateManager()->SetCursor(cursor, nsnull,
   10533                 :                                                      false, 0.0f, 0.0f,
   10534               0 :                                                      widget, true);
   10535                 :   }
   10536                 : 
   10537               0 :   return rv;
   10538                 : }
   10539                 : 
   10540                 : NS_IMETHODIMP
   10541               0 : nsGlobalChromeWindow::GetBrowserDOMWindow(nsIBrowserDOMWindow **aBrowserWindow)
   10542                 : {
   10543               0 :   FORWARD_TO_OUTER_CHROME(GetBrowserDOMWindow, (aBrowserWindow),
   10544                 :                           NS_ERROR_NOT_INITIALIZED);
   10545                 : 
   10546               0 :   NS_ENSURE_ARG_POINTER(aBrowserWindow);
   10547                 : 
   10548               0 :   *aBrowserWindow = mBrowserDOMWindow;
   10549               0 :   NS_IF_ADDREF(*aBrowserWindow);
   10550               0 :   return NS_OK;
   10551                 : }
   10552                 : 
   10553                 : NS_IMETHODIMP
   10554               0 : nsGlobalChromeWindow::SetBrowserDOMWindow(nsIBrowserDOMWindow *aBrowserWindow)
   10555                 : {
   10556               0 :   FORWARD_TO_OUTER_CHROME(SetBrowserDOMWindow, (aBrowserWindow),
   10557                 :                           NS_ERROR_NOT_INITIALIZED);
   10558                 : 
   10559               0 :   mBrowserDOMWindow = aBrowserWindow;
   10560               0 :   return NS_OK;
   10561                 : }
   10562                 : 
   10563                 : NS_IMETHODIMP
   10564               0 : nsGlobalChromeWindow::NotifyDefaultButtonLoaded(nsIDOMElement* aDefaultButton)
   10565                 : {
   10566                 : #ifdef MOZ_XUL
   10567               0 :   NS_ENSURE_ARG(aDefaultButton);
   10568                 : 
   10569                 :   // Don't snap to a disabled button.
   10570                 :   nsCOMPtr<nsIDOMXULControlElement> xulControl =
   10571               0 :                                       do_QueryInterface(aDefaultButton);
   10572               0 :   NS_ENSURE_TRUE(xulControl, NS_ERROR_FAILURE);
   10573                 :   bool disabled;
   10574               0 :   nsresult rv = xulControl->GetDisabled(&disabled);
   10575               0 :   NS_ENSURE_SUCCESS(rv, rv);
   10576               0 :   if (disabled)
   10577               0 :     return NS_OK;
   10578                 : 
   10579                 :   // Get the button rect in screen coordinates.
   10580               0 :   nsCOMPtr<nsIContent> content(do_QueryInterface(aDefaultButton));
   10581               0 :   NS_ENSURE_TRUE(content, NS_ERROR_FAILURE);
   10582               0 :   nsIFrame *frame = content->GetPrimaryFrame();
   10583               0 :   NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
   10584               0 :   nsIntRect buttonRect = frame->GetScreenRect();
   10585                 : 
   10586                 :   // Get the widget rect in screen coordinates.
   10587               0 :   nsIWidget *widget = GetNearestWidget();
   10588               0 :   NS_ENSURE_TRUE(widget, NS_ERROR_FAILURE);
   10589               0 :   nsIntRect widgetRect;
   10590               0 :   rv = widget->GetScreenBounds(widgetRect);
   10591               0 :   NS_ENSURE_SUCCESS(rv, rv);
   10592                 : 
   10593                 :   // Convert the buttonRect coordinates from screen to the widget.
   10594               0 :   buttonRect -= widgetRect.TopLeft();
   10595               0 :   rv = widget->OnDefaultButtonLoaded(buttonRect);
   10596               0 :   if (rv == NS_ERROR_NOT_IMPLEMENTED)
   10597               0 :     return NS_OK;
   10598               0 :   return rv;
   10599                 : #else
   10600                 :   return NS_ERROR_NOT_IMPLEMENTED;
   10601                 : #endif
   10602                 : }
   10603                 : 
   10604                 : NS_IMETHODIMP
   10605               0 : nsGlobalChromeWindow::GetMessageManager(nsIChromeFrameMessageManager** aManager)
   10606                 : {
   10607               0 :   FORWARD_TO_INNER_CHROME(GetMessageManager, (aManager), NS_ERROR_FAILURE);
   10608               0 :   if (!mMessageManager) {
   10609               0 :     nsIScriptContext* scx = GetContextInternal();
   10610               0 :     NS_ENSURE_STATE(scx);
   10611               0 :     JSContext* cx = scx->GetNativeContext();
   10612               0 :     NS_ENSURE_STATE(cx);
   10613                 :     nsCOMPtr<nsIChromeFrameMessageManager> globalMM =
   10614               0 :       do_GetService("@mozilla.org/globalmessagemanager;1");
   10615                 :     mMessageManager =
   10616                 :       new nsFrameMessageManager(true,
   10617                 :                                 nsnull,
   10618                 :                                 nsnull,
   10619                 :                                 nsnull,
   10620                 :                                 nsnull,
   10621               0 :                                 static_cast<nsFrameMessageManager*>(globalMM.get()),
   10622               0 :                                 cx);
   10623               0 :     NS_ENSURE_TRUE(mMessageManager, NS_ERROR_OUT_OF_MEMORY);
   10624                 :   }
   10625               0 :   CallQueryInterface(mMessageManager, aManager);
   10626               0 :   return NS_OK;
   10627                 : }
   10628                 : 
   10629                 : // nsGlobalModalWindow implementation
   10630                 : 
   10631                 : // QueryInterface implementation for nsGlobalModalWindow
   10632            1464 : NS_IMPL_CYCLE_COLLECTION_CLASS(nsGlobalModalWindow)
   10633               0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsGlobalModalWindow,
   10634                 :                                                   nsGlobalWindow)
   10635               0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mReturnValue)
   10636               0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
   10637                 : 
   10638                 : DOMCI_DATA(ModalContentWindow, nsGlobalModalWindow)
   10639                 : 
   10640               0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsGlobalModalWindow)
   10641               0 :   NS_INTERFACE_MAP_ENTRY(nsIDOMModalContentWindow)
   10642               0 :   NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(ModalContentWindow)
   10643               0 : NS_INTERFACE_MAP_END_INHERITING(nsGlobalWindow)
   10644                 : 
   10645               0 : NS_IMPL_ADDREF_INHERITED(nsGlobalModalWindow, nsGlobalWindow)
   10646               0 : NS_IMPL_RELEASE_INHERITED(nsGlobalModalWindow, nsGlobalWindow)
   10647                 : 
   10648                 : 
   10649               0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsGlobalModalWindow,
   10650                 :                                                 nsGlobalWindow)
   10651               0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mReturnValue)
   10652               0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
   10653                 : 
   10654                 : 
   10655                 : NS_IMETHODIMP
   10656               0 : nsGlobalModalWindow::GetDialogArguments(nsIArray **aArguments)
   10657                 : {
   10658               0 :   FORWARD_TO_INNER_MODAL_CONTENT_WINDOW(GetDialogArguments, (aArguments),
   10659                 :                                         NS_ERROR_NOT_INITIALIZED);
   10660                 : 
   10661               0 :   bool subsumes = false;
   10662               0 :   nsIPrincipal *self = GetPrincipal();
   10663               0 :   if (self && NS_SUCCEEDED(self->Subsumes(mArgumentsOrigin, &subsumes)) &&
   10664                 :       subsumes) {
   10665               0 :     NS_IF_ADDREF(*aArguments = mArguments);
   10666                 :   } else {
   10667               0 :     *aArguments = nsnull;
   10668                 :   }
   10669                 : 
   10670               0 :   return NS_OK;
   10671                 : }
   10672                 : 
   10673                 : NS_IMETHODIMP
   10674               0 : nsGlobalModalWindow::GetReturnValue(nsIVariant **aRetVal)
   10675                 : {
   10676               0 :   FORWARD_TO_OUTER_MODAL_CONTENT_WINDOW(GetReturnValue, (aRetVal), NS_OK);
   10677                 : 
   10678               0 :   NS_IF_ADDREF(*aRetVal = mReturnValue);
   10679                 : 
   10680               0 :   return NS_OK;
   10681                 : }
   10682                 : 
   10683                 : NS_IMETHODIMP
   10684               0 : nsGlobalModalWindow::SetReturnValue(nsIVariant *aRetVal)
   10685                 : {
   10686               0 :   FORWARD_TO_OUTER_MODAL_CONTENT_WINDOW(SetReturnValue, (aRetVal), NS_OK);
   10687                 : 
   10688               0 :   mReturnValue = aRetVal;
   10689                 : 
   10690               0 :   return NS_OK;
   10691                 : }
   10692                 : 
   10693                 : nsresult
   10694               0 : nsGlobalModalWindow::SetNewDocument(nsIDocument *aDocument,
   10695                 :                                     nsISupports *aState,
   10696                 :                                     bool aForceReuseInnerWindow)
   10697                 : {
   10698                 :   // If we're loading a new document into a modal dialog, clear the
   10699                 :   // return value that was set, if any, by the current document.
   10700               0 :   if (aDocument) {
   10701               0 :     mReturnValue = nsnull;
   10702                 :   }
   10703                 : 
   10704                 :   return nsGlobalWindow::SetNewDocument(aDocument, aState,
   10705               0 :                                         aForceReuseInnerWindow);
   10706                 : }
   10707                 : 
   10708                 : void
   10709               0 : nsGlobalWindow::SetHasAudioAvailableEventListeners()
   10710                 : {
   10711               0 :   if (mDoc) {
   10712               0 :     mDoc->NotifyAudioAvailableListener();
   10713                 :   }
   10714               0 : }
   10715                 : 
   10716                 : //*****************************************************************************
   10717                 : // nsGlobalWindow: Creator Function (This should go away)
   10718                 : //*****************************************************************************
   10719                 : 
   10720                 : nsresult
   10721               0 : NS_NewScriptGlobalObject(bool aIsChrome, bool aIsModalContentWindow,
   10722                 :                          nsIScriptGlobalObject **aResult)
   10723                 : {
   10724               0 :   *aResult = nsnull;
   10725                 : 
   10726                 :   nsGlobalWindow *global;
   10727                 : 
   10728               0 :   if (aIsChrome) {
   10729               0 :     global = new nsGlobalChromeWindow(nsnull);
   10730               0 :   } else if (aIsModalContentWindow) {
   10731               0 :     global = new nsGlobalModalWindow(nsnull);
   10732                 :   } else {
   10733               0 :     global = new nsGlobalWindow(nsnull);
   10734                 :   }
   10735                 : 
   10736               0 :   NS_ENSURE_TRUE(global, NS_ERROR_OUT_OF_MEMORY);
   10737                 : 
   10738               0 :   NS_ADDREF(*aResult = global);
   10739                 : 
   10740               0 :   return NS_OK;
   10741                 : }
   10742                 : 
   10743                 : #define EVENT(name_, id_, type_, struct_)                                    \
   10744                 :   NS_IMETHODIMP nsGlobalWindow::GetOn##name_(JSContext *cx,                  \
   10745                 :                                              jsval *vp) {                    \
   10746                 :     nsEventListenerManager *elm = GetListenerManager(false);              \
   10747                 :     if (elm) {                                                               \
   10748                 :       elm->GetJSEventListener(nsGkAtoms::on##name_, vp);                     \
   10749                 :     } else {                                                                 \
   10750                 :       *vp = JSVAL_NULL;                                                      \
   10751                 :     }                                                                        \
   10752                 :     return NS_OK;                                                            \
   10753                 :   }                                                                          \
   10754                 :   NS_IMETHODIMP nsGlobalWindow::SetOn##name_(JSContext *cx,                  \
   10755                 :                                              const jsval &v) {               \
   10756                 :     nsEventListenerManager *elm = GetListenerManager(true);               \
   10757                 :     if (!elm) {                                                              \
   10758                 :       return NS_ERROR_OUT_OF_MEMORY;                                         \
   10759                 :     }                                                                        \
   10760                 :                                                                              \
   10761                 :     JSObject *obj = mJSObject;                                               \
   10762                 :     if (!obj) {                                                              \
   10763                 :       return NS_ERROR_UNEXPECTED;                                            \
   10764                 :     }                                                                        \
   10765                 :     return elm->SetJSEventListenerToJsval(nsGkAtoms::on##name_, cx, obj, v); \
   10766                 :   }
   10767                 : #define WINDOW_ONLY_EVENT EVENT
   10768                 : #define TOUCH_EVENT EVENT
   10769                 : #include "nsEventNameList.h"
   10770                 : #undef TOUCH_EVENT
   10771                 : #undef WINDOW_ONLY_EVENT
   10772                 : #undef EVENT
   10773                 : 

Generated by: LCOV version 1.7