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
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/
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
16 * The Original Code is mozilla.org code.
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.
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>
34 * Alternatively, the contents of this file may be used under the terms of
35 * either of the GNU General Public License Version 2 or later (the "GPL"),
36 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
37 * in which case the provisions of the GPL or the LGPL are applicable instead
38 * of those above. If you wish to allow use of your version of this file only
39 * under the terms of either the GPL or the LGPL, and not to allow others to
40 * use your version of this file under the terms of the MPL, indicate your
41 * decision by deleting the provisions above and replace them with the notice
42 * and other provisions required by the GPL or the LGPL. If you do not delete
43 * the provisions above, a recipient may use your version of this file under
44 * the terms of any one of the MPL, the GPL or the LGPL.
46 * ***** END LICENSE BLOCK ***** */
49 #include "base/basictypes.h"
53 #include "nsGlobalWindow.h"
55 #include "nsHistory.h"
56 #include "nsBarProps.h"
57 #include "nsDOMStorage.h"
58 #include "nsDOMOfflineResourceList.h"
59 #include "nsDOMError.h"
62 #include "nsXPIDLString.h"
63 #include "nsJSUtils.h"
65 #include "jsapi.h" // for JSAutoRequest
66 #include "jsdbgapi.h" // for JS_ClearWatchPointsForObject
67 #include "nsReadableUtils.h"
68 #include "nsDOMClassInfo.h"
69 #include "nsContentUtils.h"
72 #include "nsIEventListenerManager.h"
74 #include "nsStyleCoord.h"
75 #include "nsMimeTypeArray.h"
76 #include "nsNetUtil.h"
77 #include "nsICachingChannel.h"
78 #include "nsPluginArray.h"
79 #include "nsIPluginHost.h"
80 #include "nsGeolocation.h"
81 #include "nsContentCID.h"
82 #include "nsLayoutStatics.h"
83 #include "nsCycleCollector.h"
84 #include "nsCCUncollectableMarker.h"
85 #include "nsDOMThreadService.h"
86 #include "nsAutoJSValHolder.h"
90 #include "nsCanvasFrame.h"
91 #include "nsIWidget.h"
92 #include "nsIBaseWindow.h"
93 #include "nsAccelerometer.h"
94 #include "nsIContent.h"
95 #include "nsIContentViewerEdit.h"
96 #include "nsIDocShell.h"
97 #include "nsIDocShellLoadInfo.h"
98 #include "nsIDocShellTreeItem.h"
99 #include "nsIDocShellTreeNode.h"
100 #include "nsIEditorDocShell.h"
101 #include "nsIDocCharset.h"
102 #include "nsIDocument.h"
103 #include "nsIHTMLDocument.h"
104 #include "nsIDOMHTMLDocument.h"
105 #include "nsIDOMHTMLElement.h"
106 #include "nsIDOMCrypto.h"
107 #include "nsIDOMDocument.h"
108 #include "nsIDOM3Document.h"
109 #include "nsIDOMNSDocument.h"
110 #include "nsIDOMDocumentView.h"
111 #include "nsIDOMElement.h"
112 #include "nsIDOMDocumentEvent.h"
113 #include "nsIDOMEvent.h"
114 #include "nsIDOMHTMLAnchorElement.h"
115 #include "nsIDOMKeyEvent.h"
116 #include "nsIDOMMessageEvent.h"
117 #include "nsIDOMPopupBlockedEvent.h"
118 #include "nsIDOMPopStateEvent.h"
119 #include "nsIDOMOfflineResourceList.h"
120 #include "nsIDOMGeoGeolocation.h"
121 #include "nsPIDOMStorage.h"
122 #include "nsDOMString.h"
123 #include "nsIEmbeddingSiteWindow2.h"
124 #include "nsThreadUtils.h"
125 #include "nsIEventStateManager.h"
126 #include "nsIHttpProtocolHandler.h"
127 #include "nsIJSContextStack.h"
128 #include "nsIJSRuntimeService.h"
129 #include "nsIMarkupDocumentViewer.h"
130 #include "nsIPrefBranch.h"
131 #include "nsIPresShell.h"
132 #include "nsIPrivateDOMEvent.h"
133 #include "nsIProgrammingLanguage.h"
134 #include "nsIServiceManager.h"
135 #include "nsIScriptGlobalObjectOwner.h"
136 #include "nsIScriptSecurityManager.h"
137 #include "nsIScrollableFrame.h"
139 #include "nsIViewManager.h"
140 #include "nsISelectionController.h"
141 #include "nsISelection.h"
142 #include "nsIPrompt.h"
143 #include "nsIPromptService.h"
144 #include "nsIWebNavigation.h"
145 #include "nsIWebBrowser.h"
146 #include "nsIWebBrowserChrome.h"
147 #include "nsIWebBrowserFind.h" // For window.find()
148 #include "nsIWebContentHandlerRegistrar.h"
149 #include "nsIWindowMediator.h" // For window.find()
150 #include "nsComputedDOMStyle.h"
151 #include "nsIEntropyCollector.h"
152 #include "nsDOMCID.h"
153 #include "nsDOMError.h"
154 #include "nsDOMWindowUtils.h"
155 #include "nsIWindowWatcher.h"
156 #include "nsPIWindowWatcher.h"
157 #include "nsIContentViewer.h"
158 #include "nsDOMClassInfo.h"
159 #include "nsIJSNativeInitializer.h"
160 #include "nsIScriptError.h"
161 #include "nsIScriptEventManager.h" // For GetInterface()
162 #include "nsIConsoleService.h"
163 #include "nsIControllers.h"
164 #include "nsIControllerContext.h"
165 #include "nsGlobalWindowCommands.h"
166 #include "nsAutoPtr.h"
167 #include "nsContentUtils.h"
168 #include "nsCSSProps.h"
169 #include "nsIURIFixup.h"
170 #include "mozilla/FunctionTimer.h"
171 #include "nsCDefaultURIFixup.h"
172 #include "nsEventDispatcher.h"
173 #include "nsIObserverService.h"
174 #include "nsIXULAppInfo.h"
175 #include "nsNetUtil.h"
176 #include "nsFocusManager.h"
178 #include "nsIXULWindow.h"
180 #include "nsXULPopupManager.h"
181 #include "nsIDOMXULControlElement.h"
182 #include "nsIFrame.h"
185 #include "plbase64.h"
188 #include "nsIPrintSettings.h"
189 #include "nsIPrintSettingsService.h"
190 #include "nsIWebBrowserPrint.h"
193 #include "nsWindowRoot.h"
194 #include "nsNetCID.h"
195 #include "nsIArray.h"
196 #include "nsIScriptRuntime.h"
198 // XXX An unfortunate dependency exists here (two XUL files).
199 #include "nsIDOMXULDocument.h"
200 #include "nsIDOMXULCommandDispatcher.h"
202 #include "nsBindingManager.h"
203 #include "nsIXBLService.h"
205 // used for popup blocking, needs to be converted to something
206 // belonging to the back-end like nsIContentPolicy
207 #include "nsIPopupWindowManager.h"
209 #include "nsIDragService.h"
210 #include "mozilla/dom/Element.h"
211 #include "nsFrameLoader.h"
212 #include "nsISupportsPrimitives.h"
213 #include "nsXPCOMCID.h"
215 #include "mozilla/FunctionTimer.h"
218 // so we can get logging even in release builds
219 #define FORCE_PR_LOG 1
223 #include "mozilla/dom/indexedDB/IDBFactory.h"
226 static PRLogModuleInfo
* gDOMLeakPRLog
;
229 using namespace mozilla::dom
;
231 nsIDOMStorageList
*nsGlobalWindow::sGlobalStorageList
= nsnull
;
233 static nsIEntropyCollector
*gEntropyCollector
= nsnull
;
234 static PRInt32 gRefCnt
= 0;
235 static PRInt32 gOpenPopupSpamCount
= 0;
236 static PopupControlState gPopupControlState
= openAbused
;
237 static PRInt32 gRunningTimeoutDepth
= 0;
238 static PRPackedBool gMouseDown
= PR_FALSE
;
239 static PRPackedBool gDragServiceDisabled
= PR_FALSE
;
240 static FILE *gDumpFile
= nsnull
;
241 static PRUint64 gNextWindowID
= 0;
244 static PRUint32 gSerialCounter
= 0;
248 PRInt32 gTimeoutCnt
= 0;
251 #if !(defined(NS_DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
252 static PRBool gDOMWindowDumpEnabled
= PR_FALSE
;
255 #if defined(DEBUG_bryner) || defined(DEBUG_chb)
256 #define DEBUG_PAGE_CACHE
259 // The shortest interval/timeout we permit
260 #define DOM_MIN_TIMEOUT_VALUE 10 // 10ms
262 // The number of nested timeouts before we start clamping. HTML5 says 1, WebKit
264 #define DOM_CLAMP_TIMEOUT_NESTING_LEVEL 5
266 // The longest interval (as PRIntervalTime) we permit, or that our
267 // timer code can handle, really. See DELAY_INTERVAL_LIMIT in
268 // nsTimerImpl.h for details.
269 #define DOM_MAX_TIMEOUT_VALUE PR_BIT(8 * sizeof(PRIntervalTime) - 1)
271 #define FORWARD_TO_OUTER(method, args, err_rval) \
273 if (IsInnerWindow()) { \
274 nsGlobalWindow *outer = GetOuterWindowInternal(); \
276 NS_WARNING("No outer window available!"); \
279 return outer->method args; \
283 #define FORWARD_TO_OUTER_VOID(method, args) \
285 if (IsInnerWindow()) { \
286 nsGlobalWindow *outer = GetOuterWindowInternal(); \
288 NS_WARNING("No outer window available!"); \
291 outer->method args; \
296 #define FORWARD_TO_OUTER_CHROME(method, args, err_rval) \
298 if (IsInnerWindow()) { \
299 nsGlobalWindow *outer = GetOuterWindowInternal(); \
301 NS_WARNING("No outer window available!"); \
304 return ((nsGlobalChromeWindow *)outer)->method args; \
308 #define FORWARD_TO_INNER_CHROME(method, args, err_rval) \
310 if (IsOuterWindow()) { \
311 if (!mInnerWindow) { \
312 NS_WARNING("No inner window available!"); \
315 return ((nsGlobalChromeWindow *)mInnerWindow)->method args; \
319 #define FORWARD_TO_OUTER_MODAL_CONTENT_WINDOW(method, args, err_rval) \
321 if (IsInnerWindow()) { \
322 nsGlobalWindow *outer = GetOuterWindowInternal(); \
324 NS_WARNING("No outer window available!"); \
327 return ((nsGlobalModalWindow *)outer)->method args; \
331 #define FORWARD_TO_INNER(method, args, err_rval) \
333 if (IsOuterWindow()) { \
334 if (!mInnerWindow) { \
335 NS_WARNING("No inner window available!"); \
338 return GetCurrentInnerWindowInternal()->method args; \
342 #define FORWARD_TO_INNER_MODAL_CONTENT_WINDOW(method, args, err_rval) \
344 if (IsOuterWindow()) { \
345 if (!mInnerWindow) { \
346 NS_WARNING("No inner window available!"); \
349 return ((nsGlobalModalWindow*)GetCurrentInnerWindowInternal())->method args; \
353 #define FORWARD_TO_INNER_VOID(method, args) \
355 if (IsOuterWindow()) { \
356 if (!mInnerWindow) { \
357 NS_WARNING("No inner window available!"); \
360 GetCurrentInnerWindowInternal()->method args; \
365 // Same as FORWARD_TO_INNER, but this will create a fresh inner if an
366 // inner doesn't already exists.
367 #define FORWARD_TO_INNER_CREATE(method, args, err_rval) \
369 if (IsOuterWindow()) { \
370 if (!mInnerWindow) { \
374 nsCOMPtr<nsIDOMDocument> doc; \
375 nsresult fwdic_nr = GetDocument(getter_AddRefs(doc)); \
376 NS_ENSURE_SUCCESS(fwdic_nr, err_rval); \
377 if (!mInnerWindow) { \
381 return GetCurrentInnerWindowInternal()->method args; \
386 static NS_DEFINE_CID(kXULControllersCID
, NS_XULCONTROLLERS_CID
);
388 static const char sJSStackContractID
[] = "@mozilla.org/js/xpc/ContextStack;1";
390 static const char kCryptoContractID
[] = NS_CRYPTO_CONTRACTID
;
391 static const char kPkcs11ContractID
[] = NS_PKCS11_CONTRACTID
;
393 static const char sPopStatePrefStr
[] = "browser.history.allowPopState";
396 IsAboutBlank(nsIURI
* aURI
)
398 NS_PRECONDITION(aURI
, "Must have URI");
400 // GetSpec can be expensive for some URIs, so check the scheme first.
401 PRBool isAbout
= PR_FALSE
;
402 if (NS_FAILED(aURI
->SchemeIs("about", &isAbout
)) || !isAbout
) {
408 return str
.EqualsLiteral("about:blank");
411 class nsDummyJavaPluginOwner
: public nsIPluginInstanceOwner
414 nsDummyJavaPluginOwner(nsIDocument
*aDocument
)
415 : mDocument(aDocument
)
421 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
422 NS_DECL_NSIPLUGININSTANCEOWNER
424 NS_IMETHOD
GetURL(const char *aURL
, const char *aTarget
,
425 nsIInputStream
*aPostStream
,
426 void *aHeadersData
, PRUint32 aHeadersDataLen
);
427 NS_IMETHOD
ShowStatus(const PRUnichar
*aStatusMsg
);
428 NPError
ShowNativeContextMenu(NPMenu
* menu
, void* event
);
429 NPBool
ConvertPoint(double sourceX
, double sourceY
, NPCoordinateSpace sourceSpace
,
430 double *destX
, double *destY
, NPCoordinateSpace destSpace
);
431 void SendIdleEvent();
433 NS_DECL_CYCLE_COLLECTION_CLASS(nsDummyJavaPluginOwner
)
436 nsCOMPtr
<nsIPluginInstance
> mInstance
;
437 nsCOMPtr
<nsIDocument
> mDocument
;
440 NS_IMPL_CYCLE_COLLECTION_2(nsDummyJavaPluginOwner
, mDocument
, mInstance
)
442 // QueryInterface implementation for nsDummyJavaPluginOwner
443 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDummyJavaPluginOwner
)
444 NS_INTERFACE_MAP_ENTRY(nsISupports
)
445 NS_INTERFACE_MAP_ENTRY(nsIPluginInstanceOwner
)
448 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDummyJavaPluginOwner
)
449 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDummyJavaPluginOwner
)
453 nsDummyJavaPluginOwner::Destroy()
455 // If we have a plugin instance, stop it and destroy it now.
458 mInstance
->InvalidateOwner();
466 nsDummyJavaPluginOwner::SetInstance(nsIPluginInstance
*aInstance
)
468 mInstance
= aInstance
;
474 nsDummyJavaPluginOwner::GetInstance(nsIPluginInstance
*&aInstance
)
476 NS_IF_ADDREF(aInstance
= mInstance
);
482 nsDummyJavaPluginOwner::GetWindow(NPWindow
*&aWindow
)
490 nsDummyJavaPluginOwner::GetMode(PRInt32
*aMode
)
492 // This is wrong, but there's no better alternative.
495 return NS_ERROR_NOT_IMPLEMENTED
;
499 nsDummyJavaPluginOwner::CreateWidget(void)
501 return NS_ERROR_NOT_IMPLEMENTED
;
505 nsDummyJavaPluginOwner::GetURL(const char *aURL
, const char *aTarget
,
506 nsIInputStream
*aPostStream
,
507 void *aHeadersData
, PRUint32 aHeadersDataLen
)
509 return NS_ERROR_NOT_IMPLEMENTED
;
513 nsDummyJavaPluginOwner::ShowStatus(const char *aStatusMsg
)
515 return NS_ERROR_NOT_IMPLEMENTED
;
519 nsDummyJavaPluginOwner::ShowStatus(const PRUnichar
*aStatusMsg
)
521 return NS_ERROR_NOT_IMPLEMENTED
;
525 nsDummyJavaPluginOwner::ShowNativeContextMenu(NPMenu
* menu
, void* event
)
527 return NPERR_GENERIC_ERROR
;
531 nsDummyJavaPluginOwner::ConvertPoint(double sourceX
, double sourceY
, NPCoordinateSpace sourceSpace
,
532 double *destX
, double *destY
, NPCoordinateSpace destSpace
)
538 nsDummyJavaPluginOwner::GetDocument(nsIDocument
**aDocument
)
540 NS_IF_ADDREF(*aDocument
= mDocument
);
546 nsDummyJavaPluginOwner::InvalidateRect(NPRect
*invalidRect
)
548 return NS_ERROR_NOT_IMPLEMENTED
;
552 nsDummyJavaPluginOwner::InvalidateRegion(NPRegion invalidRegion
)
554 return NS_ERROR_NOT_IMPLEMENTED
;
558 nsDummyJavaPluginOwner::ForceRedraw()
560 return NS_ERROR_NOT_IMPLEMENTED
;
564 nsDummyJavaPluginOwner::GetNetscapeWindow(void *value
)
566 return NS_ERROR_NOT_IMPLEMENTED
;
570 nsDummyJavaPluginOwner::SetEventModel(PRInt32 eventModel
)
572 return NS_ERROR_NOT_IMPLEMENTED
;
576 nsDummyJavaPluginOwner::SendIdleEvent()
581 * An indirect observer object that means we don't have to implement nsIObserver
582 * on nsGlobalWindow, where any script could see it.
584 class nsGlobalWindowObserver
: public nsIObserver
{
586 nsGlobalWindowObserver(nsGlobalWindow
* aWindow
) : mWindow(aWindow
) {}
588 NS_IMETHOD
Observe(nsISupports
* aSubject
, const char* aTopic
, const PRUnichar
* aData
)
592 return mWindow
->Observe(aSubject
, aTopic
, aData
);
594 void Forget() { mWindow
= nsnull
; }
596 nsGlobalWindow
* mWindow
;
599 NS_IMPL_ISUPPORTS1(nsGlobalWindowObserver
, nsIObserver
)
601 nsTimeout::nsTimeout()
605 extern int gTimeoutCnt
;
611 memset(this, 0, sizeof(*this));
613 MOZ_COUNT_CTOR(nsTimeout
);
616 nsTimeout::~nsTimeout()
620 extern int gTimeoutCnt
;
626 MOZ_COUNT_DTOR(nsTimeout
);
629 NS_IMPL_CYCLE_COLLECTION_CLASS(nsTimeout
)
630 NS_IMPL_CYCLE_COLLECTION_UNLINK_NATIVE_0(nsTimeout
)
631 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_BEGIN(nsTimeout
)
632 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mWindow
,
633 nsIScriptGlobalObject
)
634 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mPrincipal
)
635 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mScriptHandler
)
636 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
637 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsTimeout
, AddRef
)
638 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsTimeout
, Release
)
640 nsPIDOMWindow::nsPIDOMWindow(nsPIDOMWindow
*aOuterWindow
)
641 : mFrameElement(nsnull
), mDocShell(nsnull
), mModalStateDepth(0),
642 mRunningTimeout(nsnull
), mMutationBits(0), mIsDocumentLoaded(PR_FALSE
),
643 mIsHandlingResizeEvent(PR_FALSE
), mIsInnerWindow(aOuterWindow
!= nsnull
),
644 mMayHavePaintEventListener(PR_FALSE
),
645 mIsModalContentWindow(PR_FALSE
), mIsActive(PR_FALSE
),
646 mInnerWindow(nsnull
), mOuterWindow(aOuterWindow
) {}
648 nsPIDOMWindow::~nsPIDOMWindow() {}
650 //*****************************************************************************
651 //*** nsGlobalWindow: Object Management
652 //*****************************************************************************
654 nsGlobalWindow::nsGlobalWindow(nsGlobalWindow
*aOuterWindow
)
655 : nsPIDOMWindow(aOuterWindow
),
657 mDidInitJavaProperties(PR_FALSE
),
658 mFullScreen(PR_FALSE
),
661 mHavePendingClose(PR_FALSE
),
662 mHadOriginalOpener(PR_FALSE
),
663 mIsPopupSpam(PR_FALSE
),
664 mBlockScriptedClosingFlag(PR_FALSE
),
665 mFireOfflineStatusChangeEventOnThaw(PR_FALSE
),
666 mCreatingInnerWindow(PR_FALSE
),
668 mNeedsFocus(PR_TRUE
),
670 #if defined(XP_MAC) || defined(XP_MACOSX)
671 mShowAccelerators(PR_FALSE
),
672 mShowFocusRings(PR_FALSE
),
674 mShowAccelerators(PR_TRUE
),
675 mShowFocusRings(PR_TRUE
),
677 mShowFocusRingForContent(PR_FALSE
),
678 mFocusByKeyOccurred(PR_FALSE
),
679 mHasAcceleration(PR_FALSE
),
680 mNotifiedIDDestroyed(PR_FALSE
),
681 mTimeoutInsertionPoint(nsnull
),
682 mTimeoutPublicIdCounter(1),
683 mTimeoutFiringDepth(0),
685 mPendingStorageEventsObsolete(nsnull
),
686 mTimeoutsSuspendDepth(0),
689 , mSetOpenerWindowCalled(PR_FALSE
)
691 , mCleanedUp(PR_FALSE
)
692 , mCallCleanUpAfterModalDialogCloses(PR_FALSE
)
693 , mWindowID(gNextWindowID
++)
695 nsLayoutStatics::AddRef();
697 // Initialize the PRCList (this).
700 // Initialize timeout storage
701 PR_INIT_CLIST(&mTimeouts
);
704 // |this| is an inner window, add this inner window to the outer
705 // window list of inners.
706 PR_INSERT_AFTER(this, aOuterWindow
);
708 mObserver
= new nsGlobalWindowObserver(this);
710 NS_ADDREF(mObserver
);
711 nsCOMPtr
<nsIObserverService
> os
= mozilla::services::GetObserverService();
713 // Watch for online/offline status changes so we can fire events. Use
714 // a strong reference.
715 os
->AddObserver(mObserver
, NS_IOSERVICE_OFFLINE_STATUS_TOPIC
,
718 // Watch for dom-storage-changed so we can fire storage
719 // events. Use a strong reference.
720 os
->AddObserver(mObserver
, "dom-storage2-changed", PR_FALSE
);
721 os
->AddObserver(mObserver
, "dom-storage-changed", PR_FALSE
);
725 // |this| is an outer window. Outer windows start out frozen and
726 // remain frozen until they get an inner window, so freeze this
727 // outer window here.
733 // We could have failed the first time through trying
734 // to create the entropy collector, so we should
735 // try to get one until we succeed.
739 #if !(defined(NS_DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
741 static const char* prefName
= "browser.dom.window.dump.enabled";
742 nsContentUtils::AddBoolPrefVarCache(prefName
, &gDOMWindowDumpEnabled
);
743 gDOMWindowDumpEnabled
= nsContentUtils::GetBoolPref(prefName
);
747 if (gDumpFile
== nsnull
) {
748 const nsAdoptingCString
& fname
=
749 nsContentUtils::GetCharPref("browser.dom.window.dump.file");
750 if (!fname
.IsEmpty()) {
751 // if this fails to open, Dump() knows to just go to stdout
753 gDumpFile
= fopen(fname
, "wb+");
759 if (!gEntropyCollector
) {
760 CallGetService(NS_ENTROPYCOLLECTOR_CONTRACTID
, &gEntropyCollector
);
764 printf("++DOMWINDOW == %d (%p) [serial = %d] [outer = %p]\n", gRefCnt
,
765 static_cast<void*>(static_cast<nsIScriptGlobalObject
*>(this)),
766 ++gSerialCounter
, static_cast<void*>(aOuterWindow
));
767 mSerial
= gSerialCounter
;
772 gDOMLeakPRLog
= PR_NewLogModule("DOMLeak");
775 PR_LOG(gDOMLeakPRLog
, PR_LOG_DEBUG
,
776 ("DOMWINDOW %p created outer=%p", this, aOuterWindow
));
780 nsGlobalWindow::~nsGlobalWindow()
783 NS_IF_RELEASE(gEntropyCollector
);
787 if (mLastOpenedURI
) {
788 mLastOpenedURI
->GetSpec(url
);
791 printf("--DOMWINDOW == %d (%p) [serial = %d] [outer = %p] [url = %s]\n",
792 gRefCnt
, static_cast<void*>(static_cast<nsIScriptGlobalObject
*>(this)),
793 mSerial
, static_cast<void*>(mOuterWindow
), url
.get());
798 PR_LOG(gDOMLeakPRLog
, PR_LOG_DEBUG
,
799 ("DOMWINDOW %p destroyed", this));
803 nsCOMPtr
<nsIObserverService
> os
= mozilla::services::GetObserverService();
805 os
->RemoveObserver(mObserver
, NS_IOSERVICE_OFFLINE_STATUS_TOPIC
);
806 os
->RemoveObserver(mObserver
, "dom-storage2-changed");
807 os
->RemoveObserver(mObserver
, "dom-storage-changed");
810 // Drop its reference to this dying window, in case for some bogus reason
811 // the object stays around.
813 NS_RELEASE(mObserver
);
816 if (IsOuterWindow()) {
817 // An outer window is destroyed with inner windows still possibly
818 // alive, iterate through the inner windows and null out their
819 // back pointer to this outer, and pull them out of the list of
823 while ((w
= (nsGlobalWindow
*)PR_LIST_HEAD(this)) != this) {
824 NS_ASSERTION(w
->mOuterWindow
== this, "Uh, bad outer window pointer?");
826 w
->mOuterWindow
= nsnull
;
828 PR_REMOVE_AND_INIT_LINK(w
);
831 if (mListenerManager
) {
832 mListenerManager
->Disconnect();
833 mListenerManager
= nsnull
;
836 // An inner window is destroyed, pull it out of the outer window's
837 // list if inner windows.
839 PR_REMOVE_LINK(this);
841 // If our outer window's inner window is this window, null out the
842 // outer window's reference to this window that's being deleted.
843 nsGlobalWindow
*outer
= GetOuterWindowInternal();
844 if (outer
&& outer
->mInnerWindow
== this) {
845 outer
->mInnerWindow
= nsnull
;
849 mDocument
= nsnull
; // Forces Release
852 NS_ASSERTION(!mArguments
, "mArguments wasn't cleaned up properly!");
857 nsCycleCollector_DEBUG_wasFreed(static_cast<nsIScriptGlobalObject
*>(this));
860 delete mPendingStorageEventsObsolete
;
862 nsLayoutStatics::Release();
867 nsGlobalWindow::ShutDown()
869 NS_IF_RELEASE(sGlobalStorageList
);
871 if (gDumpFile
&& gDumpFile
!= stdout
) {
879 nsGlobalWindow::CleanupCachedXBLHandlers(nsGlobalWindow
* aWindow
)
881 if (aWindow
->mCachedXBLPrototypeHandlers
.IsInitialized() &&
882 aWindow
->mCachedXBLPrototypeHandlers
.Count() > 0) {
883 aWindow
->mCachedXBLPrototypeHandlers
.Clear();
885 nsCOMPtr
<nsISupports
> supports
;
886 aWindow
->QueryInterface(NS_GET_IID(nsCycleCollectionISupports
),
887 getter_AddRefs(supports
));
888 NS_ASSERTION(supports
, "Failed to QI to nsCycleCollectionISupports?!");
890 nsContentUtils::DropJSObjects(supports
);
895 nsGlobalWindow::MaybeForgiveSpamCount()
897 if (IsOuterWindow() &&
900 SetPopupSpamWindow(PR_FALSE
);
901 --gOpenPopupSpamCount
;
902 NS_ASSERTION(gOpenPopupSpamCount
>= 0,
903 "Unbalanced decrement of gOpenPopupSpamCount");
908 nsGlobalWindow::CleanUp(PRBool aIgnoreModalDialog
)
910 if (IsOuterWindow() && !aIgnoreModalDialog
) {
911 nsGlobalWindow
* inner
= GetCurrentInnerWindowInternal();
912 nsCOMPtr
<nsIDOMModalContentWindow
>
913 dlg(do_QueryInterface(static_cast<nsPIDOMWindow
*>(inner
)));
915 // The window we're trying to clean up is the outer window of a
916 // modal dialog. Defer cleanup until the window closes, and let
917 // ShowModalDialog take care of calling CleanUp.
918 mCallCleanUpAfterModalDialogCloses
= PR_TRUE
;
923 // Guarantee idempotence.
926 mCleanedUp
= PR_TRUE
;
933 mLocationbar
= nsnull
;
934 mPersonalbar
= nsnull
;
936 mScrollbars
= nsnull
;
939 mApplicationCache
= nsnull
;
944 mOpener
= nsnull
; // Forces Release
947 nsCycleCollector_DEBUG_shouldBeFreed(mContext
);
949 mContext
= nsnull
; // Forces Release
951 mChromeEventHandler
= nsnull
; // Forces Release
952 mParentTarget
= nsnull
;
954 nsGlobalWindow
*inner
= GetCurrentInnerWindowInternal();
957 inner
->CleanUp(aIgnoreModalDialog
);
960 if (mHasAcceleration
) {
961 nsCOMPtr
<nsIAccelerometer
> ac
= do_GetService(NS_ACCELEROMETER_CONTRACTID
);
963 ac
->RemoveWindowListener(this);
966 if (mIsChrome
&& static_cast<nsGlobalChromeWindow
*>(this)->mMessageManager
) {
967 static_cast<nsFrameMessageManager
*>(
968 static_cast<nsGlobalChromeWindow
*>(
969 this)->mMessageManager
.get())->Disconnect();
972 mInnerWindowHolder
= nsnull
;
974 mArgumentsLast
= nsnull
;
975 mArgumentsOrigin
= nsnull
;
977 CleanupCachedXBLHandlers(this);
980 nsCycleCollector_DEBUG_shouldBeFreed(static_cast<nsIScriptGlobalObject
*>(this));
985 nsGlobalWindow::ClearControllers()
989 mControllers
->GetControllerCount(&count
);
992 nsCOMPtr
<nsIController
> controller
;
993 mControllers
->GetControllerAt(count
, getter_AddRefs(controller
));
995 nsCOMPtr
<nsIControllerContext
> context
= do_QueryInterface(controller
);
997 context
->SetCommandContext(nsnull
);
1000 mControllers
= nsnull
;
1004 class ClearScopeEvent
: public nsRunnable
1007 ClearScopeEvent(nsGlobalWindow
*innerWindow
)
1008 : mInnerWindow(innerWindow
) {
1013 mInnerWindow
->ReallyClearScope(this);
1018 nsRefPtr
<nsGlobalWindow
> mInnerWindow
;
1022 nsGlobalWindow::ReallyClearScope(nsRunnable
*aRunnable
)
1024 NS_ASSERTION(IsInnerWindow(), "Must be an inner window");
1026 nsIScriptContext
*jsscx
= GetContextInternal();
1027 if (jsscx
&& jsscx
->GetExecutingScript()) {
1029 aRunnable
= new ClearScopeEvent(this);
1031 // The only reason that we clear scope here is to try to prevent
1032 // leaks. Failing to clear scope might mean that we'll leak more
1033 // but if we don't have enough memory to allocate a ClearScopeEvent
1034 // we probably don't have to worry about this anyway.
1039 NS_DispatchToMainThread(aRunnable
);
1043 NotifyWindowIDDestroyed("inner-window-destroyed");
1044 nsIScriptContext
*scx
= GetContextInternal();
1046 scx
->ClearScope(mJSObject
, PR_TRUE
);
1051 nsGlobalWindow::FreeInnerObjects(PRBool aClearScope
)
1053 NS_ASSERTION(IsInnerWindow(), "Don't free inner objects on an outer window");
1055 // Kill all of the workers for this window.
1056 nsDOMThreadService
* dts
= nsDOMThreadService::get();
1058 nsIScriptContext
*scx
= GetContextInternal();
1060 JSContext
*cx
= scx
? (JSContext
*)scx
->GetNativeContext() : nsnull
;
1062 // Have to suspend this request here because CancelWorkersForGlobal will
1063 // lock until the worker has died and that could cause a deadlock.
1064 JSAutoSuspendRequest
asr(cx
);
1066 dts
->CancelWorkersForGlobal(static_cast<nsIScriptGlobalObject
*>(this));
1071 mChromeEventHandler
= nsnull
;
1073 if (mListenerManager
) {
1074 mListenerManager
->Disconnect();
1075 mListenerManager
= nsnull
;
1079 NS_ASSERTION(mDoc
, "Why is mDoc null?");
1081 // Remember the document's principal.
1082 mDocumentPrincipal
= mDoc
->NodePrincipal();
1087 nsCycleCollector_DEBUG_shouldBeFreed(nsCOMPtr
<nsISupports
>(do_QueryInterface(mDocument
)));
1090 // Make sure that this is called before we null out the document.
1091 NotifyDOMWindowDestroyed(this);
1093 // Remove our reference to the document and the document principal.
1097 if (mApplicationCache
) {
1098 static_cast<nsDOMOfflineResourceList
*>(mApplicationCache
.get())->Disconnect();
1099 mApplicationCache
= nsnull
;
1102 mIndexedDB
= nsnull
;
1105 // NB: This might not clear our scope, but fire an event to do so
1107 ReallyClearScope(nsnull
);
1110 if (mDummyJavaPluginOwner
) {
1111 // Tear down the dummy java plugin.
1113 // XXXjst: On a general note, should windows with java stuff in
1114 // them ever even make it into the fast-back cache?
1116 mDummyJavaPluginOwner
->Destroy();
1118 mDummyJavaPluginOwner
= nsnull
;
1121 CleanupCachedXBLHandlers(this);
1124 nsCycleCollector_DEBUG_shouldBeFreed(static_cast<nsIScriptGlobalObject
*>(this));
1128 //*****************************************************************************
1129 // nsGlobalWindow::nsISupports
1130 //*****************************************************************************
1132 #define WINDOW_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(_class) \
1133 if (aIID.Equals(NS_GET_IID(nsIClassInfo)) || \
1134 aIID.Equals(NS_GET_IID(nsXPCClassInfo))) { \
1135 foundInterface = NS_GetDOMClassInfoInstance(IsInnerWindow() \
1136 ? eDOMClassInfo_Inner##_class##_id \
1137 : eDOMClassInfo_##_class##_id);\
1138 if (!foundInterface) { \
1139 *aInstancePtr = nsnull; \
1140 return NS_ERROR_OUT_OF_MEMORY; \
1144 NS_IMPL_CYCLE_COLLECTION_CLASS(nsGlobalWindow
)
1146 DOMCI_DATA(Window
, nsGlobalWindow
)
1147 DOMCI_DATA(InnerWindow
, nsGlobalWindow
)
1149 // QueryInterface implementation for nsGlobalWindow
1150 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsGlobalWindow
)
1151 // Make sure this matches the cast in nsGlobalWindow::FromWrapper()
1152 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIScriptGlobalObject
)
1153 NS_INTERFACE_MAP_ENTRY(nsIDOMWindowInternal
)
1154 NS_INTERFACE_MAP_ENTRY(nsIDOMWindow
)
1155 NS_INTERFACE_MAP_ENTRY(nsIDOMWindow2
)
1156 NS_INTERFACE_MAP_ENTRY(nsIDOMJSWindow
)
1157 NS_INTERFACE_MAP_ENTRY(nsIScriptGlobalObject
)
1158 NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal
)
1159 NS_INTERFACE_MAP_ENTRY(nsPIDOMEventTarget
)
1160 NS_INTERFACE_MAP_ENTRY(nsIDOMEventTarget
)
1161 NS_INTERFACE_MAP_ENTRY(nsIDOM3EventTarget
)
1162 NS_INTERFACE_MAP_ENTRY(nsIDOMNSEventTarget
)
1163 NS_INTERFACE_MAP_ENTRY(nsPIDOMWindow
)
1164 NS_INTERFACE_MAP_ENTRY(nsIDOMViewCSS
)
1165 NS_INTERFACE_MAP_ENTRY(nsIDOMAbstractView
)
1166 NS_INTERFACE_MAP_ENTRY(nsIDOMStorageWindow
)
1167 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference
)
1168 NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor
)
1169 WINDOW_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Window
)
1170 NS_INTERFACE_MAP_END
1173 NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsGlobalWindow
, nsIScriptGlobalObject
)
1174 NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(nsGlobalWindow
,
1175 nsIScriptGlobalObject
)
1178 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsGlobalWindow
)
1179 if (tmp
->mDoc
&& nsCCUncollectableMarker::InGeneration(
1180 cb
, tmp
->mDoc
->GetMarkedCCGeneration())) {
1181 return NS_SUCCESS_INTERRUPTED_TRAVERSE
;
1184 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mContext
)
1186 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mControllers
)
1187 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mArguments
)
1188 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mArgumentsLast
)
1190 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mInnerWindowHolder
)
1192 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOpenerScriptPrincipal
)
1193 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mListenerManager
)
1195 for (nsTimeout
* timeout
= tmp
->FirstTimeout();
1196 tmp
->IsTimeout(timeout
);
1197 timeout
= timeout
->Next()) {
1198 cb
.NoteNativeChild(timeout
, &NS_CYCLE_COLLECTION_NAME(nsTimeout
));
1201 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mSessionStorage
)
1202 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mApplicationCache
)
1203 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDocumentPrincipal
)
1204 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDoc
)
1206 // Traverse stuff from nsPIDOMWindow
1207 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mChromeEventHandler
)
1208 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mParentTarget
)
1209 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDocument
)
1210 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFrameElement
)
1212 // Traverse mDummyJavaPluginOwner
1213 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDummyJavaPluginOwner
)
1215 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFocusedNode
)
1217 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
1219 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindow
)
1220 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mContext
)
1222 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mControllers
)
1223 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mArguments
)
1224 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mArgumentsLast
)
1226 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mInnerWindowHolder
)
1228 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOpenerScriptPrincipal
)
1229 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mListenerManager
)
1230 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mSessionStorage
)
1231 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mApplicationCache
)
1232 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDocumentPrincipal
)
1234 // Unlink stuff from nsPIDOMWindow
1235 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mChromeEventHandler
)
1236 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mParentTarget
)
1237 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDocument
)
1238 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFrameElement
)
1240 // Unlink mDummyJavaPluginOwner
1241 if (tmp
->mDummyJavaPluginOwner
) {
1242 tmp
->mDummyJavaPluginOwner
->Destroy();
1243 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDummyJavaPluginOwner
)
1246 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFocusedNode
)
1248 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
1252 TraceData(TraceCallback
& aCallback
, void* aClosure
) :
1253 callback(aCallback
), closure(aClosure
) {}
1255 TraceCallback
& callback
;
1259 static PLDHashOperator
1260 TraceXBLHandlers(const void* aKey
, void* aData
, void* aClosure
)
1262 TraceData
* data
= static_cast<TraceData
*>(aClosure
);
1263 data
->callback(nsIProgrammingLanguage::JAVASCRIPT
, aData
, data
->closure
);
1264 return PL_DHASH_NEXT
;
1267 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsGlobalWindow
)
1268 if (tmp
->mCachedXBLPrototypeHandlers
.IsInitialized()) {
1269 TraceData
data(aCallback
, aClosure
);
1270 tmp
->mCachedXBLPrototypeHandlers
.EnumerateRead(TraceXBLHandlers
, &data
);
1272 NS_IMPL_CYCLE_COLLECTION_TRACE_END
1274 NS_IMPL_CYCLE_COLLECTION_ROOT_BEGIN(nsGlobalWindow
)
1275 nsGlobalWindow::CleanupCachedXBLHandlers(tmp
);
1276 NS_IMPL_CYCLE_COLLECTION_ROOT_END
1278 //*****************************************************************************
1279 // nsGlobalWindow::nsIScriptGlobalObject
1280 //*****************************************************************************
1283 nsGlobalWindow::SetScriptContext(PRUint32 lang_id
, nsIScriptContext
*aScriptContext
)
1285 NS_ASSERTION(lang_id
== nsIProgrammingLanguage::JAVASCRIPT
,
1286 "We don't support this language ID");
1287 NS_ASSERTION(IsOuterWindow(), "Uh, SetScriptContext() called on inner window!");
1289 if (!aScriptContext
) {
1290 NS_WARNING("Possibly early removal of script object, see bug #41608");
1292 // should probably assert the context is clean???
1293 aScriptContext
->WillInitializeContext();
1295 // Bind the script context and the global object
1296 nsresult rv
= aScriptContext
->InitContext(this);
1297 NS_ENSURE_SUCCESS(rv
, rv
);
1300 NS_ASSERTION(!aScriptContext
|| !mContext
, "Bad call to SetContext()!");
1302 void *script_glob
= nsnull
;
1304 if (aScriptContext
) {
1306 // This window is a [i]frame, don't bother GC'ing when the
1307 // frame's context is destroyed since a GC will happen when the
1308 // frameset or host document is destroyed anyway.
1310 aScriptContext
->SetGCOnDestruction(PR_FALSE
);
1313 aScriptContext
->DidInitializeContext();
1314 script_glob
= aScriptContext
->GetNativeGlobal();
1315 NS_ASSERTION(script_glob
, "GetNativeGlobal returned NULL!");
1318 mContext
= aScriptContext
;
1319 mJSObject
= (JSObject
*)script_glob
;
1324 nsGlobalWindow::EnsureScriptEnvironment(PRUint32 aLangID
)
1326 NS_ASSERTION(aLangID
== nsIProgrammingLanguage::JAVASCRIPT
,
1327 "We don't support this language ID");
1328 FORWARD_TO_OUTER(EnsureScriptEnvironment
, (aLangID
), NS_ERROR_NOT_INITIALIZED
);
1333 NS_ASSERTION(!GetCurrentInnerWindowInternal(), "Huh?");
1335 nsCOMPtr
<nsIScriptRuntime
> scriptRuntime
;
1336 nsresult rv
= NS_GetScriptRuntimeByID(aLangID
, getter_AddRefs(scriptRuntime
));
1337 NS_ENSURE_SUCCESS(rv
, rv
);
1339 nsCOMPtr
<nsIScriptContext
> context
;
1340 rv
= scriptRuntime
->CreateContext(getter_AddRefs(context
));
1341 NS_ENSURE_SUCCESS(rv
, rv
);
1343 return SetScriptContext(aLangID
, context
);
1347 nsGlobalWindow::GetScriptContext(PRUint32 lang
)
1349 NS_ASSERTION(lang
== nsIProgrammingLanguage::JAVASCRIPT
,
1350 "We don't support this language ID");
1352 FORWARD_TO_OUTER(GetScriptContext
, (lang
), nsnull
);
1357 nsGlobalWindow::GetScriptGlobal(PRUint32 lang
)
1359 NS_ASSERTION(lang
== nsIProgrammingLanguage::JAVASCRIPT
,
1360 "We don't support this language ID");
1365 nsGlobalWindow::GetContext()
1367 FORWARD_TO_OUTER(GetContext
, (), nsnull
);
1369 // check GetContext is indeed identical to GetScriptContext()
1370 NS_ASSERTION(mContext
== GetScriptContext(nsIProgrammingLanguage::JAVASCRIPT
),
1371 "GetContext confused?");
1376 nsGlobalWindow::GetGlobalJSObject()
1378 NS_ASSERTION(mJSObject
== GetScriptGlobal(nsIProgrammingLanguage::JAVASCRIPT
),
1379 "GetGlobalJSObject confused?");
1380 return FastGetGlobalJSObject();
1384 nsGlobalWindow::WouldReuseInnerWindow(nsIDocument
*aNewDocument
)
1386 // We reuse the inner window when:
1387 // a. We are currently at our original document.
1388 // b. At least one of the following conditions are true:
1389 // -- We are not currently a content window (i.e., we're currently a chrome
1391 // -- The new document is the same as the old document. This means that we're
1392 // getting called from document.open().
1393 // -- The new document has the same origin as what we have loaded right now.
1395 if (!mDoc
|| !aNewDocument
) {
1399 if (!mDoc
->IsInitialDocument()) {
1403 NS_ASSERTION(IsAboutBlank(mDoc
->GetDocumentURI()),
1404 "How'd this happen?");
1406 // Great, we're the original document, check for one of the other
1408 if (mDoc
== aNewDocument
) {
1409 // aClearScopeHint is false.
1414 if (NS_SUCCEEDED(mDoc
->NodePrincipal()->Equals(aNewDocument
->NodePrincipal(),
1417 // The origin is the same.
1421 nsCOMPtr
<nsIDocShellTreeItem
> treeItem(do_QueryInterface(mDocShell
));
1424 PRInt32 itemType
= nsIDocShellTreeItem::typeContent
;
1425 treeItem
->GetItemType(&itemType
);
1427 // If we're a chrome window, then we want to reuse the inner window.
1428 return itemType
== nsIDocShellTreeItem::typeChrome
;
1431 // No treeItem: don't reuse the current inner window.
1436 nsGlobalWindow::SetOpenerScriptPrincipal(nsIPrincipal
* aPrincipal
)
1438 FORWARD_TO_OUTER_VOID(SetOpenerScriptPrincipal
, (aPrincipal
));
1441 if (!mDoc
->IsInitialDocument()) {
1442 // We have a document already, and it's not the original one. Bail out.
1443 // Do NOT set mOpenerScriptPrincipal in this case, just to be safe.
1448 // We better have an about:blank document loaded at this point. Otherwise,
1449 // something is really weird.
1450 nsCOMPtr
<nsIURI
> uri
;
1451 mDoc
->NodePrincipal()->GetURI(getter_AddRefs(uri
));
1452 NS_ASSERTION(uri
&& IsAboutBlank(uri
) &&
1453 IsAboutBlank(mDoc
->GetDocumentURI()),
1454 "Unexpected original document");
1457 // Set the opener principal on our document; given the above check, this
1459 mDoc
->SetPrincipal(aPrincipal
);
1462 mOpenerScriptPrincipal
= aPrincipal
;
1466 nsGlobalWindow::GetOpenerScriptPrincipal()
1468 FORWARD_TO_OUTER(GetOpenerScriptPrincipal
, (), nsnull
);
1470 return mOpenerScriptPrincipal
;
1474 PushPopupControlState(PopupControlState aState
, PRBool aForce
)
1476 PopupControlState oldState
= gPopupControlState
;
1478 if (aState
< gPopupControlState
|| aForce
) {
1479 gPopupControlState
= aState
;
1486 PopPopupControlState(PopupControlState aState
)
1488 gPopupControlState
= aState
;
1492 nsGlobalWindow::PushPopupControlState(PopupControlState aState
,
1493 PRBool aForce
) const
1495 return ::PushPopupControlState(aState
, aForce
);
1499 nsGlobalWindow::PopPopupControlState(PopupControlState aState
) const
1501 ::PopPopupControlState(aState
);
1505 nsGlobalWindow::GetPopupControlState() const
1507 return gPopupControlState
;
1510 #define WINDOWSTATEHOLDER_IID \
1511 {0x0b917c3e, 0xbd50, 0x4683, {0xaf, 0xc9, 0xc7, 0x81, 0x07, 0xae, 0x33, 0x26}}
1513 class WindowStateHolder
: public nsISupports
1516 NS_DECLARE_STATIC_IID_ACCESSOR(WINDOWSTATEHOLDER_IID
)
1519 WindowStateHolder(nsGlobalWindow
*aWindow
,
1520 nsIXPConnectJSObjectHolder
*aHolder
,
1521 nsNavigator
*aNavigator
,
1522 nsLocation
*aLocation
,
1523 nsIXPConnectJSObjectHolder
*aOuterProto
);
1525 nsGlobalWindow
* GetInnerWindow() { return mInnerWindow
; }
1526 nsIXPConnectJSObjectHolder
*GetInnerWindowHolder()
1527 { return mInnerWindowHolder
; }
1529 nsNavigator
* GetNavigator() { return mNavigator
; }
1530 nsLocation
* GetLocation() { return mLocation
; }
1531 nsIXPConnectJSObjectHolder
* GetOuterProto() { return mOuterProto
; }
1533 void DidRestoreWindow()
1535 mInnerWindow
= nsnull
;
1537 mInnerWindowHolder
= nsnull
;
1538 mNavigator
= nsnull
;
1540 mOuterProto
= nsnull
;
1544 ~WindowStateHolder();
1546 nsGlobalWindow
*mInnerWindow
;
1547 // We hold onto this to make sure the inner window doesn't go away. The outer
1548 // window ends up recalculating it anyway.
1549 nsCOMPtr
<nsIXPConnectJSObjectHolder
> mInnerWindowHolder
;
1550 nsRefPtr
<nsNavigator
> mNavigator
;
1551 nsRefPtr
<nsLocation
> mLocation
;
1552 nsCOMPtr
<nsIXPConnectJSObjectHolder
> mOuterProto
;
1555 NS_DEFINE_STATIC_IID_ACCESSOR(WindowStateHolder
, WINDOWSTATEHOLDER_IID
)
1557 WindowStateHolder::WindowStateHolder(nsGlobalWindow
*aWindow
,
1558 nsIXPConnectJSObjectHolder
*aHolder
,
1559 nsNavigator
*aNavigator
,
1560 nsLocation
*aLocation
,
1561 nsIXPConnectJSObjectHolder
*aOuterProto
)
1562 : mInnerWindow(aWindow
),
1563 mNavigator(aNavigator
),
1564 mLocation(aLocation
),
1565 mOuterProto(aOuterProto
)
1567 NS_PRECONDITION(aWindow
, "null window");
1568 NS_PRECONDITION(aWindow
->IsInnerWindow(), "Saving an outer window");
1570 mInnerWindowHolder
= aHolder
;
1572 aWindow
->SuspendTimeouts();
1575 WindowStateHolder::~WindowStateHolder()
1578 // This window was left in the bfcache and is now going away. We need to
1580 // Note that FreeInnerObjects may already have been called on the
1581 // inner window if its outer has already had SetDocShell(null)
1582 // called. In this case the contexts will all be null and the
1583 // PR_TRUE for aClearScope won't do anything; this is OK since
1584 // SetDocShell(null) already did it.
1585 mInnerWindow
->FreeInnerObjects(PR_TRUE
);
1589 NS_IMPL_ISUPPORTS1(WindowStateHolder
, WindowStateHolder
)
1592 nsGlobalWindow::SetNewDocument(nsIDocument
* aDocument
,
1593 nsISupports
* aState
)
1597 NS_PRECONDITION(mDocumentPrincipal
== nsnull
,
1598 "mDocumentPrincipal prematurely set!");
1601 NS_ERROR("SetNewDocument(null) called!");
1603 return NS_ERROR_INVALID_ARG
;
1606 if (IsInnerWindow()) {
1607 if (!mOuterWindow
) {
1608 return NS_ERROR_NOT_INITIALIZED
;
1611 // Refuse to set a new document if the call came from an inner
1612 // window that's not the current inner window.
1613 if (mOuterWindow
->GetCurrentInnerWindow() != this) {
1614 return NS_ERROR_NOT_AVAILABLE
;
1617 return GetOuterWindowInternal()->SetNewDocument(aDocument
, aState
);
1620 NS_PRECONDITION(IsOuterWindow(), "Must only be called on outer windows");
1623 // This outer is now getting its first inner, thaw the outer now
1624 // that it's ready and is getting an inner window.
1628 NS_ASSERTION(!GetCurrentInnerWindow() ||
1629 GetCurrentInnerWindow()->GetExtantDocument() == mDocument
,
1630 "Uh, mDocument doesn't match the current inner window "
1633 nsresult rv
= NS_OK
;
1635 nsCOMPtr
<nsIDocument
> oldDoc(do_QueryInterface(mDocument
));
1637 nsIScriptContext
*scx
= GetContextInternal();
1638 NS_ENSURE_TRUE(scx
, NS_ERROR_NOT_INITIALIZED
);
1640 JSContext
*cx
= (JSContext
*)scx
->GetNativeContext();
1642 // clear smartcard events, our document has gone away.
1644 mCrypto
->SetEnableSmartCardEvents(PR_FALSE
);
1648 // First document load.
1650 // Get our private root. If it is equal to us, then we need to
1651 // attach our global key bindings that handles browser scrolling
1652 // and other browser commands.
1653 nsIDOMWindowInternal
*internal
= nsGlobalWindow::GetPrivateRoot();
1655 if (internal
== static_cast<nsIDOMWindowInternal
*>(this)) {
1656 nsCOMPtr
<nsIXBLService
> xblService
= do_GetService("@mozilla.org/xbl;1");
1658 nsCOMPtr
<nsPIDOMEventTarget
> piTarget
=
1659 do_QueryInterface(mChromeEventHandler
);
1660 xblService
->AttachGlobalKeyHandler(piTarget
);
1665 /* No mDocShell means we're already been partially closed down. When that
1666 happens, setting status isn't a big requirement, so don't. (Doesn't happen
1667 under normal circumstances, but bug 49615 describes a case.) */
1669 nsContentUtils::AddScriptRunner(
1670 NS_NewRunnableMethod(this, &nsGlobalWindow::ClearStatus
));
1672 PRBool reUseInnerWindow
= WouldReuseInnerWindow(aDocument
);
1674 // Remember the old document's principal.
1675 nsIPrincipal
*oldPrincipal
= nsnull
;
1677 oldPrincipal
= oldDoc
->NodePrincipal();
1680 // Drop our reference to the navigator object unless we're reusing
1681 // the existing inner window or the new document is from the same
1682 // origin as the old document.
1683 if (!reUseInnerWindow
&& mNavigator
&& oldPrincipal
) {
1685 rv
= oldPrincipal
->Equals(aDocument
->NodePrincipal(), &equal
);
1687 if (NS_FAILED(rv
) || !equal
) {
1688 // Different origins. Release the navigator object so it gets
1689 // recreated for the new document. The plugins or mime types
1690 // arrays may have changed. See bug 150087.
1691 mNavigator
->SetDocShell(nsnull
);
1693 mNavigator
= nsnull
;
1697 if (mNavigator
&& aDocument
!= oldDoc
) {
1698 // We didn't drop our reference to our old navigator object and
1699 // we're loading a new document. Notify the navigator object about
1700 // the new document load so that it can make sure it is ready for
1701 // the new document.
1703 mNavigator
->LoadingNewDocument();
1706 // Set mDocument even if this is an outer window to avoid
1707 // having to *always* reach into the inner window to find the
1709 mDocument
= do_QueryInterface(aDocument
);
1713 mLastOpenedURI
= aDocument
->GetDocumentURI();
1716 mContext
->WillInitializeContext();
1718 nsGlobalWindow
*currentInner
= GetCurrentInnerWindowInternal();
1720 nsRefPtr
<nsGlobalWindow
> newInnerWindow
;
1722 PRBool thisChrome
= IsChromeWindow();
1723 nsCOMPtr
<nsIXPConnectJSObjectHolder
> navigatorHolder
;
1726 PRBool isChrome
= PR_FALSE
;
1728 nsCxPusher cxPusher
;
1729 if (!cxPusher
.Push(cx
)) {
1730 return NS_ERROR_FAILURE
;
1733 JSAutoRequest
ar(cx
);
1735 // Make sure to clear scope on the outer window *before* we
1736 // initialize the new inner window. If we don't, things
1737 // (Object.prototype etc) could leak from the old outer to the new
1739 mContext
->ClearScope(mJSObject
, PR_FALSE
);
1741 if (reUseInnerWindow
) {
1742 // We're reusing the current inner window.
1743 NS_ASSERTION(!currentInner
->IsFrozen(),
1744 "We should never be reusing a shared inner window");
1745 newInnerWindow
= currentInner
;
1747 if (aDocument
!= oldDoc
) {
1748 nsWindowSH::InvalidateGlobalScopePolluter(cx
, currentInner
->mJSObject
);
1752 nsCOMPtr
<WindowStateHolder
> wsh
= do_QueryInterface(aState
);
1753 NS_ASSERTION(wsh
, "What kind of weird state are you giving me here?");
1755 newInnerWindow
= wsh
->GetInnerWindow();
1756 mInnerWindowHolder
= wsh
->GetInnerWindowHolder();
1758 // These assignments addref.
1759 mNavigator
= wsh
->GetNavigator();
1760 mLocation
= wsh
->GetLocation();
1763 // Update mNavigator's docshell pointer now.
1764 mNavigator
->SetDocShell(mDocShell
);
1765 mNavigator
->LoadingNewDocument();
1769 newInnerWindow
= new nsGlobalChromeWindow(this);
1773 if (mIsModalContentWindow
) {
1774 newInnerWindow
= new nsGlobalModalWindow(this);
1776 newInnerWindow
= new nsGlobalWindow(this);
1783 if (!newInnerWindow
) {
1784 return NS_ERROR_OUT_OF_MEMORY
;
1787 if (currentInner
&& currentInner
->mJSObject
) {
1788 if (mNavigator
&& !aState
) {
1789 // Hold on to the navigator wrapper so that we can set
1790 // window.navigator in the new window to point to the same
1791 // object (assuming we didn't change origins etc). See bug
1792 // 163645 for more on why we need this.
1794 nsIDOMNavigator
* navigator
=
1795 static_cast<nsIDOMNavigator
*>(mNavigator
.get());
1796 nsContentUtils::WrapNative(cx
, currentInner
->mJSObject
, navigator
,
1797 &NS_GET_IID(nsIDOMNavigator
), &nav
,
1798 getter_AddRefs(navigatorHolder
));
1803 // This is redundant if we're restoring from a previous inner window.
1804 nsIScriptGlobalObject
*sgo
=
1805 (nsIScriptGlobalObject
*)newInnerWindow
.get();
1807 // Freeze the outer window and null out the inner window so
1808 // that initializing classes on the new inner doesn't end up
1809 // reaching into the old inner window for classes etc.
1811 // [This happens with Object.prototype when XPConnect creates
1812 // a temporary global while initializing classes; the reason
1813 // being that xpconnect creates the temp global w/o a parent
1814 // and proto, which makes the JS engine look up classes in
1815 // cx->globalObject, i.e. this outer window].
1817 mInnerWindow
= nsnull
;
1820 mCreatingInnerWindow
= PR_TRUE
;
1821 // Every script context we are initialized with must create a
1823 void *&newGlobal
= (void *&)newInnerWindow
->mJSObject
;
1824 nsCOMPtr
<nsIXPConnectJSObjectHolder
> &holder
= mInnerWindowHolder
;
1825 rv
= mContext
->CreateNativeGlobalForInner(sgo
, isChrome
,
1827 getter_AddRefs(holder
));
1828 NS_ASSERTION(NS_SUCCEEDED(rv
) && newGlobal
&& holder
,
1829 "Failed to get script global and holder");
1830 newInnerWindow
->mJSObject
= (JSObject
*)newGlobal
;
1832 mCreatingInnerWindow
= PR_FALSE
;
1835 NS_ENSURE_SUCCESS(rv
, rv
);
1838 if (currentInner
&& currentInner
->mJSObject
) {
1839 PRBool termFuncSet
= PR_FALSE
;
1841 if (oldDoc
== aDocument
) {
1842 // Suspend the current context's request before Pop() resumes the old
1843 // context's request.
1844 JSAutoSuspendRequest
asr(cx
);
1846 // Pop our context here so that we get the correct one for the
1847 // termination function.
1850 JSContext
*oldCx
= nsContentUtils::GetCurrentJSContext();
1852 nsIScriptContext
*callerScx
;
1853 if (oldCx
&& (callerScx
= GetScriptContextFromJSContext(oldCx
))) {
1854 // We're called from document.open() (and document.open() is
1855 // called from JS), clear the scope etc in a termination
1856 // function on the calling context to prevent clearing the
1858 NS_ASSERTION(!currentInner
->IsFrozen(),
1859 "How does this opened window get into session history");
1861 JSAutoRequest
ar(oldCx
);
1863 callerScx
->SetTerminationFunction(ClearWindowScope
,
1864 static_cast<nsIDOMWindow
*>
1867 termFuncSet
= PR_TRUE
;
1870 // Re-push our context.
1874 // Don't clear scope on our current inner window if it's going to be
1875 // held in the bfcache.
1876 if (!currentInner
->IsFrozen()) {
1877 // Skip the ClearScope if we set a termination function to do
1878 // it ourselves, later.
1879 currentInner
->FreeInnerObjects(!termFuncSet
);
1883 mInnerWindow
= newInnerWindow
;
1886 if (!aState
&& !reUseInnerWindow
) {
1887 // Loading a new page and creating a new inner window, *not*
1888 // restoring from session history.
1890 // InitClassesWithNewWrappedGlobal() (via CreateNativeGlobalForInner)
1891 // for the new inner window
1892 // sets the global object in cx to be the new wrapped global. We
1893 // don't want that, but re-initializing the outer window will
1894 // fix that for us. And perhaps more importantly, this will
1895 // ensure that the outer window gets a new prototype so we don't
1896 // leak prototype properties from the old inner window to the
1898 JS_BeginRequest((JSContext
*)mContext
->GetNativeContext());
1899 mContext
->InitContext(this);
1901 // Now that both the the inner and outer windows are initialized
1902 // let the script context do its magic to hook them together.
1903 mContext
->ConnectToInner(newInnerWindow
, mJSObject
);
1904 JS_EndRequest((JSContext
*)mContext
->GetNativeContext());
1906 nsCOMPtr
<nsIContent
> frame
= do_QueryInterface(GetFrameElementInternal());
1907 if (frame
&& frame
->GetOwnerDoc()) {
1908 nsPIDOMWindow
* parentWindow
= frame
->GetOwnerDoc()->GetWindow();
1909 if (parentWindow
&& parentWindow
->TimeoutSuspendCount()) {
1910 SuspendTimeouts(parentWindow
->TimeoutSuspendCount());
1915 // Tell the contexts we have completed setting up the doc.
1916 // Add an extra ref in case we release mContext during GC.
1917 nsCOMPtr
<nsIScriptContext
> kungFuDeathGrip(mContext
);
1918 nsCOMPtr
<nsIDOMDocument
> dd(do_QueryInterface(aDocument
));
1919 mContext
->DidSetDocument(dd
, newInnerWindow
->mJSObject
);
1921 // Now that the prototype is all set up, install the global scope
1922 // polluter. This must happen after the above prototype fixup. If
1923 // the GSP was to be installed on the inner window's real
1924 // prototype (as it would be if this was done before the prototype
1925 // fixup above) we would end up holding the GSP alive (through
1926 // XPConnect's internal marking of wrapper prototypes) as long as
1927 // the inner window was around, and if the GSP had properties on
1928 // it that held an element alive we'd hold the document alive,
1929 // which could hold event handlers alive, which hold the context
1932 if ((!reUseInnerWindow
|| aDocument
!= oldDoc
) && !aState
) {
1933 nsCOMPtr
<nsIHTMLDocument
> html_doc(do_QueryInterface(mDocument
));
1934 nsWindowSH::InstallGlobalScopePolluter(cx
, newInnerWindow
->mJSObject
,
1938 // This code should not be called during shutdown any more (now that
1939 // we don't ever call SetNewDocument(nsnull), so no need to null
1941 nsIXPConnect
*xpc
= nsContentUtils::XPConnect();
1943 nsCOMPtr
<nsIXPConnectWrappedNative
> wrapper
;
1945 // Restoring from session history.
1947 nsCOMPtr
<WindowStateHolder
> wsh
= do_QueryInterface(aState
);
1948 NS_ASSERTION(wsh
, "What kind of weird state are you giving me here?");
1950 // Restore the prototype for the Window/ChromeWindow class in
1951 // the outer window scope.
1952 nsCOMPtr
<nsIClassInfo
> ci
=
1953 do_QueryInterface((nsIScriptGlobalObject
*)this);
1955 rv
= xpc
->RestoreWrappedNativePrototype(cx
, mJSObject
, ci
,
1956 wsh
->GetOuterProto());
1957 NS_ENSURE_SUCCESS(rv
, rv
);
1959 // Refresh the outer window's prototype to what it was when the
1960 // window state was saved. This will make the outer window
1961 // object (and wrapper) pick up the prototype it had when the
1962 // window state was saved. This means Object.prototype etc from
1963 // the old inner will again be on the outer window's prototype
1966 rv
= xpc
->GetWrappedNativeOfJSObject(cx
, mJSObject
,
1967 getter_AddRefs(wrapper
));
1968 NS_ENSURE_SUCCESS(rv
, rv
);
1970 rv
= wrapper
->RefreshPrototype();
1971 NS_ENSURE_SUCCESS(rv
, rv
);
1975 aDocument
->SetScriptGlobalObject(newInnerWindow
);
1979 if (reUseInnerWindow
) {
1980 if (newInnerWindow
->mDoc
!= aDocument
) {
1981 newInnerWindow
->mDocument
= do_QueryInterface(aDocument
);
1982 newInnerWindow
->mDoc
= aDocument
;
1984 // We're reusing the inner window for a new document. In this
1985 // case we don't clear the inner window's scope, but we must
1986 // make sure the cached document property gets updated.
1988 // XXXmarkh - tell other languages about this?
1989 JSAutoRequest
ar(cx
);
1990 ::JS_DeleteProperty(cx
, currentInner
->mJSObject
, "document");
1993 rv
= newInnerWindow
->InnerSetNewDocument(aDocument
);
1994 NS_ENSURE_SUCCESS(rv
, rv
);
1996 // Initialize DOM classes etc on the inner window.
1997 rv
= mContext
->InitClasses(mJSObject
);
1998 NS_ENSURE_SUCCESS(rv
, rv
);
2000 if (navigatorHolder
) {
2001 // Restore window.navigator onto the new inner window.
2002 JSAutoRequest
ar(cx
);
2004 ::JS_DefineProperty(cx
, newInnerWindow
->mJSObject
, "navigator",
2005 nav
, nsnull
, nsnull
,
2006 JSPROP_ENUMERATE
| JSPROP_PERMANENT
|
2009 // The Navigator's prototype object keeps a reference to the
2010 // window in which it was first created and can thus cause that
2011 // window to stay alive for too long. Reparenting it here allows
2012 // the window to be collected sooner.
2013 nsIDOMNavigator
* navigator
=
2014 static_cast<nsIDOMNavigator
*>(mNavigator
);
2017 ReparentWrappedNativeIfFound(cx
, JSVAL_TO_OBJECT(nav
),
2018 newInnerWindow
->mJSObject
,
2020 getter_AddRefs(navigatorHolder
));
2025 newInnerWindow
->DefineArgumentsProperty(mArguments
);
2026 newInnerWindow
->mArguments
= mArguments
;
2027 newInnerWindow
->mArgumentsOrigin
= mArgumentsOrigin
;
2029 mArguments
= nsnull
;
2030 mArgumentsOrigin
= nsnull
;
2033 // Give the new inner window our chrome event handler (since it
2034 // doesn't have one).
2035 newInnerWindow
->mChromeEventHandler
= mChromeEventHandler
;
2039 mContext
->DidInitializeContext();
2042 rv
= xpc
->GetWrappedNativeOfJSObject(cx
, mJSObject
,
2043 getter_AddRefs(wrapper
));
2044 NS_ENSURE_SUCCESS(rv
, rv
);
2047 rv
= xpc
->UpdateXOWs((JSContext
*)GetContextInternal()->GetNativeContext(),
2048 wrapper
, nsIXPConnect::XPC_XOW_NAVIGATED
);
2049 NS_ENSURE_SUCCESS(rv
, rv
);
2051 nsContentUtils::AddScriptRunner(
2052 NS_NewRunnableMethod(this, &nsGlobalWindow::DispatchDOMWindowCreated
));
2058 nsGlobalWindow::DispatchDOMWindowCreated()
2060 if (!mDoc
|| !mDocument
) {
2064 // Fire DOMWindowCreated at chrome event listeners
2065 nsContentUtils::DispatchChromeEvent(mDoc
, mDocument
, NS_LITERAL_STRING("DOMWindowCreated"),
2066 PR_TRUE
/* bubbles */,
2067 PR_FALSE
/* not cancellable */);
2069 nsCOMPtr
<nsIObserverService
> observerService
=
2070 mozilla::services::GetObserverService();
2071 if (observerService
) {
2072 nsAutoString origin
;
2073 nsIPrincipal
* principal
= mDoc
->NodePrincipal();
2074 nsContentUtils::GetUTFOrigin(principal
, origin
);
2076 NotifyObservers(static_cast<nsIDOMWindow
*>(this),
2077 nsContentUtils::IsSystemPrincipal(principal
) ?
2078 "chrome-document-global-created" :
2079 "content-document-global-created",
2085 nsGlobalWindow::ClearStatus()
2087 SetStatus(EmptyString());
2088 SetDefaultStatus(EmptyString());
2092 nsGlobalWindow::InnerSetNewDocument(nsIDocument
* aDocument
)
2094 NS_PRECONDITION(IsInnerWindow(), "Must only be called on inner windows");
2097 if (aDocument
&& gDOMLeakPRLog
&&
2098 PR_LOG_TEST(gDOMLeakPRLog
, PR_LOG_DEBUG
)) {
2099 nsIURI
*uri
= aDocument
->GetDocumentURI();
2103 PR_LogPrint("DOMWINDOW %p SetNewDocument %s", this, spec
.get());
2107 mDocument
= do_QueryInterface(aDocument
);
2109 mLocalStorage
= nsnull
;
2110 mSessionStorage
= nsnull
;
2113 mLastOpenedURI
= aDocument
->GetDocumentURI();
2116 // Clear our mutation bitfield.
2123 nsGlobalWindow::SetDocShell(nsIDocShell
* aDocShell
)
2125 NS_ASSERTION(IsOuterWindow(), "Uh, SetDocShell() called on inner window!");
2127 if (aDocShell
== mDocShell
)
2130 // SetDocShell(nsnull) means the window is being torn down. Drop our
2131 // reference to the script context, allowing it to be deleted
2132 // later. Meanwhile, keep our weak reference to the script object
2133 // (mJSObject) so that it can be retrieved later (until it is
2134 // finalized by the JS GC).
2137 NS_ASSERTION(PR_CLIST_IS_EMPTY(&mTimeouts
),
2138 "Uh, outer window holds timeouts!");
2140 // Call FreeInnerObjects on all inner windows, not just the current
2141 // one, since some could be held by WindowStateHolder objects that
2143 for (nsRefPtr
<nsGlobalWindow
> inner
= (nsGlobalWindow
*)PR_LIST_HEAD(this);
2145 inner
= (nsGlobalWindow
*)PR_NEXT_LINK(inner
)) {
2146 NS_ASSERTION(inner
->mOuterWindow
== this, "bad outer window pointer");
2147 inner
->FreeInnerObjects(PR_TRUE
);
2150 // Make sure that this is called before we null out the document.
2151 NotifyDOMWindowDestroyed(this);
2153 NotifyWindowIDDestroyed("outer-window-destroyed");
2155 nsGlobalWindow
*currentInner
= GetCurrentInnerWindowInternal();
2158 NS_ASSERTION(mDoc
, "Must have doc!");
2160 // Remember the document's principal.
2161 mDocumentPrincipal
= mDoc
->NodePrincipal();
2163 // Release our document reference
2168 mContext
->ClearScope(mJSObject
, PR_TRUE
);
2172 mChromeEventHandler
= nsnull
; // force release now
2175 // We got no new document after someone called
2176 // SetArguments(), drop our reference to the arguments.
2177 mArguments
= nsnull
;
2178 mArgumentsLast
= nsnull
;
2179 mArgumentsOrigin
= nsnull
;
2183 mContext
->FinalizeContext();
2187 nsCycleCollector_DEBUG_shouldBeFreed(mContext
);
2188 nsCycleCollector_DEBUG_shouldBeFreed(static_cast<nsIScriptGlobalObject
*>(this));
2192 mDocShell
= aDocShell
; // Weak Reference
2195 mNavigator
->SetDocShell(aDocShell
);
2197 mLocation
->SetDocShell(aDocShell
);
2199 mHistory
->SetDocShell(aDocShell
);
2201 mFrames
->SetDocShell(aDocShell
);
2203 mScreen
->SetDocShell(aDocShell
);
2206 MaybeForgiveSpamCount();
2209 // tell our member elements about the new browserwindow
2211 nsCOMPtr
<nsIWebBrowserChrome
> browserChrome
;
2212 GetWebBrowserChrome(getter_AddRefs(browserChrome
));
2213 mMenubar
->SetWebBrowserChrome(browserChrome
);
2216 // Get our enclosing chrome shell and retrieve its global window impl, so
2217 // that we can do some forwarding to the chrome document.
2218 nsCOMPtr
<nsIDOMEventTarget
> chromeEventHandler
;
2219 mDocShell
->GetChromeEventHandler(getter_AddRefs(chromeEventHandler
));
2220 mChromeEventHandler
= do_QueryInterface(chromeEventHandler
);
2221 if (!mChromeEventHandler
) {
2222 // We have no chrome event handler. If we have a parent,
2223 // get our chrome event handler from the parent. If
2224 // we don't have a parent, then we need to make a new
2225 // window root object that will function as a chrome event
2226 // handler and receive all events that occur anywhere inside
2228 nsCOMPtr
<nsIDOMWindow
> parentWindow
;
2229 GetParent(getter_AddRefs(parentWindow
));
2230 if (parentWindow
.get() != static_cast<nsIDOMWindow
*>(this)) {
2231 nsCOMPtr
<nsPIDOMWindow
> piWindow(do_QueryInterface(parentWindow
));
2232 mChromeEventHandler
= piWindow
->GetChromeEventHandler();
2234 else NS_NewWindowRoot(this, getter_AddRefs(mChromeEventHandler
));
2240 nsGlobalWindow::SetOpenerWindow(nsIDOMWindowInternal
* aOpener
,
2241 PRBool aOriginalOpener
)
2243 FORWARD_TO_OUTER_VOID(SetOpenerWindow
, (aOpener
, aOriginalOpener
));
2245 NS_ASSERTION(!aOriginalOpener
|| !mSetOpenerWindowCalled
,
2246 "aOriginalOpener is true, but not first call to "
2247 "SetOpenerWindow!");
2248 NS_ASSERTION(aOpener
|| !aOriginalOpener
,
2249 "Shouldn't set mHadOriginalOpener if aOpener is null");
2251 mOpener
= do_GetWeakReference(aOpener
);
2252 NS_ASSERTION(mOpener
|| !aOpener
, "Opener must support weak references!");
2254 if (aOriginalOpener
) {
2255 mHadOriginalOpener
= PR_TRUE
;
2259 mSetOpenerWindowCalled
= PR_TRUE
;
2264 nsGlobalWindow::UpdateParentTarget()
2266 nsCOMPtr
<nsIFrameLoaderOwner
> flo
= do_QueryInterface(mChromeEventHandler
);
2268 nsRefPtr
<nsFrameLoader
> fl
= flo
->GetFrameLoader();
2270 mParentTarget
= fl
->GetTabChildGlobalAsEventTarget();
2273 if (!mParentTarget
) {
2274 mParentTarget
= mChromeEventHandler
;
2279 nsGlobalWindow::PreHandleEvent(nsEventChainPreVisitor
& aVisitor
)
2281 NS_PRECONDITION(IsInnerWindow(), "PreHandleEvent is used on outer window!?");
2282 static PRUint32 count
= 0;
2283 PRUint32 msg
= aVisitor
.mEvent
->message
;
2285 aVisitor
.mCanHandle
= PR_TRUE
;
2286 aVisitor
.mForceContentDispatch
= PR_TRUE
; //FIXME! Bug 329119
2287 if ((msg
== NS_MOUSE_MOVE
) && gEntropyCollector
) {
2288 //Chances are this counter will overflow during the life of the
2289 //process, but that's OK for our case. Means we get a little
2291 if (count
++ % 100 == 0) {
2292 //Since the high bits seem to be zero's most of the time,
2293 //let's only take the lowest half of the point structure.
2296 myCoord
[0] = aVisitor
.mEvent
->refPoint
.x
;
2297 myCoord
[1] = aVisitor
.mEvent
->refPoint
.y
;
2298 gEntropyCollector
->RandomUpdate((void*)myCoord
, sizeof(myCoord
));
2299 gEntropyCollector
->RandomUpdate((void*)&(aVisitor
.mEvent
->time
),
2302 } else if (msg
== NS_RESIZE_EVENT
) {
2303 mIsHandlingResizeEvent
= PR_TRUE
;
2304 } else if (msg
== NS_MOUSE_BUTTON_DOWN
&&
2305 NS_IS_TRUSTED_EVENT(aVisitor
.mEvent
)) {
2306 gMouseDown
= PR_TRUE
;
2307 } else if (msg
== NS_MOUSE_BUTTON_UP
&&
2308 NS_IS_TRUSTED_EVENT(aVisitor
.mEvent
)) {
2309 gMouseDown
= PR_FALSE
;
2310 if (gDragServiceDisabled
) {
2311 nsCOMPtr
<nsIDragService
> ds
=
2312 do_GetService("@mozilla.org/widget/dragservice;1");
2314 gDragServiceDisabled
= PR_FALSE
;
2320 aVisitor
.mParentTarget
= GetParentTarget();
2325 nsGlobalWindow::PostHandleEvent(nsEventChainPostVisitor
& aVisitor
)
2327 NS_PRECONDITION(IsInnerWindow(), "PostHandleEvent is used on outer window!?");
2329 // Return early if there is nothing to do.
2330 switch (aVisitor
.mEvent
->message
) {
2331 case NS_RESIZE_EVENT
:
2332 case NS_PAGE_UNLOAD
:
2339 /* mChromeEventHandler and mContext go dangling in the middle of this
2340 function under some circumstances (events that destroy the window)
2341 without this addref. */
2342 nsCOMPtr
<nsPIDOMEventTarget
> kungFuDeathGrip1(mChromeEventHandler
);
2343 nsCOMPtr
<nsIScriptContext
> kungFuDeathGrip2(GetContextInternal());
2345 if (aVisitor
.mEvent
->message
== NS_RESIZE_EVENT
) {
2346 mIsHandlingResizeEvent
= PR_FALSE
;
2347 } else if (aVisitor
.mEvent
->message
== NS_PAGE_UNLOAD
&&
2348 NS_IS_TRUSTED_EVENT(aVisitor
.mEvent
)) {
2349 // Execute bindingdetached handlers before we tear ourselves
2352 NS_ASSERTION(mDoc
, "Must have doc");
2353 mDoc
->BindingManager()->ExecuteDetachedHandlers();
2355 mIsDocumentLoaded
= PR_FALSE
;
2356 } else if (aVisitor
.mEvent
->message
== NS_LOAD
&&
2357 NS_IS_TRUSTED_EVENT(aVisitor
.mEvent
)) {
2358 // This is page load event since load events don't propagate to |window|.
2359 // @see nsDocument::PreHandleEvent.
2360 mIsDocumentLoaded
= PR_TRUE
;
2362 nsCOMPtr
<nsIContent
> content(do_QueryInterface(GetFrameElementInternal()));
2363 nsCOMPtr
<nsIDocShellTreeItem
> treeItem
=
2364 do_QueryInterface(GetDocShell());
2366 PRInt32 itemType
= nsIDocShellTreeItem::typeChrome
;
2369 treeItem
->GetItemType(&itemType
);
2372 if (content
&& GetParentInternal() &&
2373 itemType
!= nsIDocShellTreeItem::typeChrome
) {
2374 // If we're not in chrome, or at a chrome boundary, fire the
2375 // onload event for the frame element.
2377 nsEventStatus status
= nsEventStatus_eIgnore
;
2378 nsEvent
event(NS_IS_TRUSTED_EVENT(aVisitor
.mEvent
), NS_LOAD
);
2379 event
.flags
|= NS_EVENT_FLAG_CANT_BUBBLE
;
2381 // Most of the time we could get a pres context to pass in here,
2382 // but not always (i.e. if this window is not shown there won't
2383 // be a pres context available). Since we're not firing a GUI
2384 // event we don't need a pres context anyway so we just pass
2385 // null as the pres context all the time here.
2387 nsEventDispatcher::Dispatch(content
, nsnull
, &event
, nsnull
, &status
);
2395 nsGlobalWindow::DispatchDOMEvent(nsEvent
* aEvent
,
2396 nsIDOMEvent
* aDOMEvent
,
2397 nsPresContext
* aPresContext
,
2398 nsEventStatus
* aEventStatus
)
2401 nsEventDispatcher::DispatchDOMEvent(static_cast<nsPIDOMWindow
*>(this),
2402 aEvent
, aDOMEvent
, aPresContext
,
2407 nsGlobalWindow::OnFinalize(PRUint32 aLangID
, void *aObject
)
2409 NS_ASSERTION(aLangID
== nsIProgrammingLanguage::JAVASCRIPT
,
2410 "We don't support this language ID");
2412 if (aObject
== mJSObject
) {
2418 nsGlobalWindow::SetScriptsEnabled(PRBool aEnabled
, PRBool aFireTimeouts
)
2420 FORWARD_TO_INNER_VOID(SetScriptsEnabled
, (aEnabled
, aFireTimeouts
));
2422 if (aEnabled
&& aFireTimeouts
) {
2423 // Scripts are enabled (again?) on this context, run timeouts that
2424 // fired on this context while scripts were disabled.
2425 void (nsGlobalWindow::*run
)() = &nsGlobalWindow::RunTimeout
;
2426 NS_DispatchToCurrentThread(NS_NewRunnableMethod(this, run
));
2431 nsGlobalWindow::SetArguments(nsIArray
*aArguments
, nsIPrincipal
*aOrigin
)
2433 FORWARD_TO_OUTER(SetArguments
, (aArguments
, aOrigin
),
2434 NS_ERROR_NOT_INITIALIZED
);
2436 // Hold on to the arguments so that we can re-set them once the next
2437 // document is loaded.
2438 mArguments
= aArguments
;
2439 mArgumentsOrigin
= aOrigin
;
2441 nsGlobalWindow
*currentInner
= GetCurrentInnerWindowInternal();
2443 if (!mIsModalContentWindow
) {
2444 mArgumentsLast
= aArguments
;
2445 } else if (currentInner
) {
2446 // SetArguments() is being called on a modal content window that
2447 // already has an inner window. This can happen when loading
2448 // javascript: URIs as modal content dialogs. In this case, we'll
2449 // set up the dialog window, both inner and outer, before we call
2450 // SetArguments() on the window, so to deal with that, make sure
2451 // here that the arguments are propagated to the inner window.
2453 currentInner
->mArguments
= aArguments
;
2454 currentInner
->mArgumentsOrigin
= aOrigin
;
2457 return currentInner
?
2458 currentInner
->DefineArgumentsProperty(aArguments
) : NS_OK
;
2462 nsGlobalWindow::DefineArgumentsProperty(nsIArray
*aArguments
)
2465 nsIScriptContext
*ctx
= GetOuterWindowInternal()->mContext
;
2466 NS_ENSURE_TRUE(aArguments
&& ctx
&&
2467 (cx
= (JSContext
*)ctx
->GetNativeContext()),
2468 NS_ERROR_NOT_INITIALIZED
);
2470 if (mIsModalContentWindow
) {
2471 // Modal content windows don't have an "arguments" property, they
2472 // have a "dialogArguments" property which is handled
2473 // separately. See nsWindowSH::NewResolve().
2478 return GetContextInternal()->SetProperty(mJSObject
, "arguments", aArguments
);
2481 //*****************************************************************************
2482 // nsGlobalWindow::nsIScriptObjectPrincipal
2483 //*****************************************************************************
2486 nsGlobalWindow::GetPrincipal()
2489 // If we have a document, get the principal from the document
2490 return mDoc
->NodePrincipal();
2493 if (mDocumentPrincipal
) {
2494 return mDocumentPrincipal
;
2497 // If we don't have a principal and we don't have a document we
2498 // ask the parent window for the principal. This can happen when
2499 // loading a frameset that has a <frame src="javascript:xxx">, in
2500 // that case the global window is used in JS before we've loaded
2501 // a document into the window.
2503 nsCOMPtr
<nsIScriptObjectPrincipal
> objPrincipal
=
2504 do_QueryInterface(GetParentInternal());
2507 return objPrincipal
->GetPrincipal();
2513 //*****************************************************************************
2514 // nsGlobalWindow::nsIDOMWindow
2515 //*****************************************************************************
2518 nsGlobalWindow::GetDocument(nsIDOMDocument
** aDocument
)
2520 // This method *should* forward calls to the outer window, but since
2521 // there's nothing here that *depends* on anything in the outer
2522 // (GetDocShell() eliminates that dependency), we won't do that to
2523 // avoid the extra virtual function call.
2525 // lazily instantiate an about:blank document if necessary, and if
2526 // we have what it takes to do so. Note that domdoc here is the same
2527 // thing as our mDocument, but we don't have to explicitly set the
2528 // member variable because the docshell has already called
2529 // SetNewDocument().
2530 nsIDocShell
*docShell
;
2531 if (!mDocument
&& (docShell
= GetDocShell()))
2532 nsCOMPtr
<nsIDOMDocument
> domdoc(do_GetInterface(docShell
));
2534 NS_IF_ADDREF(*aDocument
= mDocument
);
2539 //*****************************************************************************
2540 // nsGlobalWindow::nsIDOMWindowInternal
2541 //*****************************************************************************
2544 nsGlobalWindow::GetWindow(nsIDOMWindowInternal
** aWindow
)
2546 FORWARD_TO_OUTER(GetWindow
, (aWindow
), NS_ERROR_NOT_INITIALIZED
);
2548 *aWindow
= static_cast<nsIDOMWindowInternal
*>(this);
2549 NS_ADDREF(*aWindow
);
2554 nsGlobalWindow::GetSelf(nsIDOMWindowInternal
** aWindow
)
2556 FORWARD_TO_OUTER(GetSelf
, (aWindow
), NS_ERROR_NOT_INITIALIZED
);
2558 *aWindow
= static_cast<nsIDOMWindowInternal
*>(this);
2559 NS_ADDREF(*aWindow
);
2564 nsGlobalWindow::GetNavigator(nsIDOMNavigator
** aNavigator
)
2566 FORWARD_TO_OUTER(GetNavigator
, (aNavigator
), NS_ERROR_NOT_INITIALIZED
);
2568 *aNavigator
= nsnull
;
2571 mNavigator
= new nsNavigator(mDocShell
);
2573 return NS_ERROR_OUT_OF_MEMORY
;
2577 NS_ADDREF(*aNavigator
= mNavigator
);
2583 nsGlobalWindow::GetScreen(nsIDOMScreen
** aScreen
)
2585 FORWARD_TO_OUTER(GetScreen
, (aScreen
), NS_ERROR_NOT_INITIALIZED
);
2589 if (!mScreen
&& mDocShell
) {
2590 mScreen
= new nsScreen(mDocShell
);
2592 return NS_ERROR_OUT_OF_MEMORY
;
2596 NS_IF_ADDREF(*aScreen
= mScreen
);
2602 nsGlobalWindow::GetHistory(nsIDOMHistory
** aHistory
)
2604 FORWARD_TO_OUTER(GetHistory
, (aHistory
), NS_ERROR_NOT_INITIALIZED
);
2608 if (!mHistory
&& mDocShell
) {
2609 mHistory
= new nsHistory(mDocShell
);
2611 return NS_ERROR_OUT_OF_MEMORY
;
2615 NS_IF_ADDREF(*aHistory
= mHistory
);
2620 nsGlobalWindow::GetParent(nsIDOMWindow
** aParent
)
2622 FORWARD_TO_OUTER(GetParent
, (aParent
), NS_ERROR_NOT_INITIALIZED
);
2628 nsCOMPtr
<nsIDocShellTreeItem
> docShellAsItem(do_QueryInterface(mDocShell
));
2629 NS_ENSURE_TRUE(docShellAsItem
, NS_ERROR_FAILURE
);
2631 nsCOMPtr
<nsIDocShellTreeItem
> parent
;
2632 docShellAsItem
->GetSameTypeParent(getter_AddRefs(parent
));
2635 nsCOMPtr
<nsIScriptGlobalObject
> globalObject(do_GetInterface(parent
));
2636 NS_ENSURE_SUCCESS(CallQueryInterface(globalObject
.get(), aParent
),
2640 *aParent
= static_cast<nsIDOMWindowInternal
*>(this);
2641 NS_ADDREF(*aParent
);
2647 nsGlobalWindow::GetTop(nsIDOMWindow
** aTop
)
2649 FORWARD_TO_OUTER(GetTop
, (aTop
), NS_ERROR_NOT_INITIALIZED
);
2651 nsresult ret
= NS_OK
;
2655 nsCOMPtr
<nsIDocShellTreeItem
> docShellAsItem(do_QueryInterface(mDocShell
));
2656 nsCOMPtr
<nsIDocShellTreeItem
> root
;
2657 docShellAsItem
->GetSameTypeRootTreeItem(getter_AddRefs(root
));
2660 nsCOMPtr
<nsIScriptGlobalObject
> globalObject(do_GetInterface(root
));
2661 CallQueryInterface(globalObject
.get(), aTop
);
2669 nsGlobalWindow::GetContent(nsIDOMWindow
** aContent
)
2671 FORWARD_TO_OUTER(GetContent
, (aContent
), NS_ERROR_NOT_INITIALIZED
);
2675 nsCOMPtr
<nsIDocShellTreeItem
> primaryContent
;
2677 if (!nsContentUtils::IsCallerChrome()) {
2678 // If we're called by non-chrome code, make sure we don't return
2679 // the primary content window if the calling tab is hidden. In
2680 // such a case we return the same-type root in the hidden tab,
2681 // which is "good enough", for now.
2682 nsCOMPtr
<nsIBaseWindow
> baseWin(do_QueryInterface(mDocShell
));
2685 PRBool visible
= PR_FALSE
;
2686 baseWin
->GetVisibility(&visible
);
2689 nsCOMPtr
<nsIDocShellTreeItem
> treeItem(do_QueryInterface(mDocShell
));
2691 treeItem
->GetSameTypeRootTreeItem(getter_AddRefs(primaryContent
));
2696 if (!primaryContent
) {
2697 nsCOMPtr
<nsIDocShellTreeOwner
> treeOwner
;
2698 GetTreeOwner(getter_AddRefs(treeOwner
));
2699 NS_ENSURE_TRUE(treeOwner
, NS_ERROR_FAILURE
);
2701 treeOwner
->GetPrimaryContentShell(getter_AddRefs(primaryContent
));
2704 nsCOMPtr
<nsIDOMWindowInternal
> domWindow(do_GetInterface(primaryContent
));
2705 NS_IF_ADDREF(*aContent
= domWindow
);
2711 nsGlobalWindow::GetPrompter(nsIPrompt
** aPrompt
)
2713 FORWARD_TO_OUTER(GetPrompter
, (aPrompt
), NS_ERROR_NOT_INITIALIZED
);
2716 return NS_ERROR_FAILURE
;
2718 nsCOMPtr
<nsIPrompt
> prompter(do_GetInterface(mDocShell
));
2719 NS_ENSURE_TRUE(prompter
, NS_ERROR_NO_INTERFACE
);
2721 NS_ADDREF(*aPrompt
= prompter
);
2726 nsGlobalWindow::GetMenubar(nsIDOMBarProp
** aMenubar
)
2728 FORWARD_TO_OUTER(GetMenubar
, (aMenubar
), NS_ERROR_NOT_INITIALIZED
);
2733 mMenubar
= new nsMenubarProp();
2735 return NS_ERROR_OUT_OF_MEMORY
;
2738 nsCOMPtr
<nsIWebBrowserChrome
> browserChrome
;
2739 GetWebBrowserChrome(getter_AddRefs(browserChrome
));
2741 mMenubar
->SetWebBrowserChrome(browserChrome
);
2744 NS_ADDREF(*aMenubar
= mMenubar
);
2750 nsGlobalWindow::GetToolbar(nsIDOMBarProp
** aToolbar
)
2752 FORWARD_TO_OUTER(GetToolbar
, (aToolbar
), NS_ERROR_NOT_INITIALIZED
);
2757 mToolbar
= new nsToolbarProp();
2759 return NS_ERROR_OUT_OF_MEMORY
;
2762 nsCOMPtr
<nsIWebBrowserChrome
> browserChrome
;
2763 GetWebBrowserChrome(getter_AddRefs(browserChrome
));
2765 mToolbar
->SetWebBrowserChrome(browserChrome
);
2768 NS_ADDREF(*aToolbar
= mToolbar
);
2774 nsGlobalWindow::GetLocationbar(nsIDOMBarProp
** aLocationbar
)
2776 FORWARD_TO_OUTER(GetLocationbar
, (aLocationbar
), NS_ERROR_NOT_INITIALIZED
);
2778 *aLocationbar
= nsnull
;
2780 if (!mLocationbar
) {
2781 mLocationbar
= new nsLocationbarProp();
2782 if (!mLocationbar
) {
2783 return NS_ERROR_OUT_OF_MEMORY
;
2786 nsCOMPtr
<nsIWebBrowserChrome
> browserChrome
;
2787 GetWebBrowserChrome(getter_AddRefs(browserChrome
));
2789 mLocationbar
->SetWebBrowserChrome(browserChrome
);
2792 NS_ADDREF(*aLocationbar
= mLocationbar
);
2798 nsGlobalWindow::GetPersonalbar(nsIDOMBarProp
** aPersonalbar
)
2800 FORWARD_TO_OUTER(GetPersonalbar
, (aPersonalbar
), NS_ERROR_NOT_INITIALIZED
);
2802 *aPersonalbar
= nsnull
;
2804 if (!mPersonalbar
) {
2805 mPersonalbar
= new nsPersonalbarProp();
2806 if (!mPersonalbar
) {
2807 return NS_ERROR_OUT_OF_MEMORY
;
2810 nsCOMPtr
<nsIWebBrowserChrome
> browserChrome
;
2811 GetWebBrowserChrome(getter_AddRefs(browserChrome
));
2813 mPersonalbar
->SetWebBrowserChrome(browserChrome
);
2816 NS_ADDREF(*aPersonalbar
= mPersonalbar
);
2822 nsGlobalWindow::GetStatusbar(nsIDOMBarProp
** aStatusbar
)
2824 FORWARD_TO_OUTER(GetStatusbar
, (aStatusbar
), NS_ERROR_NOT_INITIALIZED
);
2826 *aStatusbar
= nsnull
;
2829 mStatusbar
= new nsStatusbarProp();
2831 return NS_ERROR_OUT_OF_MEMORY
;
2834 nsCOMPtr
<nsIWebBrowserChrome
> browserChrome
;
2835 GetWebBrowserChrome(getter_AddRefs(browserChrome
));
2837 mStatusbar
->SetWebBrowserChrome(browserChrome
);
2840 NS_ADDREF(*aStatusbar
= mStatusbar
);
2846 nsGlobalWindow::GetScrollbars(nsIDOMBarProp
** aScrollbars
)
2848 FORWARD_TO_OUTER(GetScrollbars
, (aScrollbars
), NS_ERROR_NOT_INITIALIZED
);
2850 *aScrollbars
= nsnull
;
2853 mScrollbars
= new nsScrollbarsProp(this);
2855 return NS_ERROR_OUT_OF_MEMORY
;
2858 nsCOMPtr
<nsIWebBrowserChrome
> browserChrome
;
2859 GetWebBrowserChrome(getter_AddRefs(browserChrome
));
2861 mScrollbars
->SetWebBrowserChrome(browserChrome
);
2864 NS_ADDREF(*aScrollbars
= mScrollbars
);
2870 nsGlobalWindow::GetClosed(PRBool
* aClosed
)
2872 FORWARD_TO_OUTER(GetClosed
, (aClosed
), NS_ERROR_NOT_INITIALIZED
);
2874 // If someone called close(), or if we don't have a docshell, we're
2876 *aClosed
= mIsClosed
|| !mDocShell
;
2882 nsGlobalWindow::GetFrames(nsIDOMWindowCollection
** aFrames
)
2884 FORWARD_TO_OUTER(GetFrames
, (aFrames
), NS_ERROR_NOT_INITIALIZED
);
2888 if (!mFrames
&& mDocShell
) {
2889 mFrames
= new nsDOMWindowList(mDocShell
);
2891 return NS_ERROR_OUT_OF_MEMORY
;
2895 *aFrames
= static_cast<nsIDOMWindowCollection
*>(mFrames
);
2896 NS_IF_ADDREF(*aFrames
);
2901 nsGlobalWindow::GetApplicationCache(nsIDOMOfflineResourceList
**aApplicationCache
)
2903 FORWARD_TO_INNER(GetApplicationCache
, (aApplicationCache
), NS_ERROR_UNEXPECTED
);
2905 NS_ENSURE_ARG_POINTER(aApplicationCache
);
2907 if (!mApplicationCache
) {
2908 nsCOMPtr
<nsIWebNavigation
> webNav(do_QueryInterface(GetDocShell()));
2910 return NS_ERROR_FAILURE
;
2913 nsCOMPtr
<nsIURI
> uri
;
2914 nsresult rv
= webNav
->GetCurrentURI(getter_AddRefs(uri
));
2915 NS_ENSURE_SUCCESS(rv
, rv
);
2917 nsCOMPtr
<nsIDocument
> doc
= do_QueryInterface(mDocument
);
2918 nsCOMPtr
<nsIURI
> manifestURI
;
2919 nsContentUtils::GetOfflineAppManifest(doc
, getter_AddRefs(manifestURI
));
2921 nsIScriptContext
* scriptContext
= GetContext();
2922 NS_ENSURE_STATE(scriptContext
);
2924 nsRefPtr
<nsDOMOfflineResourceList
> applicationCache
=
2925 new nsDOMOfflineResourceList(manifestURI
, uri
, this, scriptContext
);
2926 NS_ENSURE_TRUE(applicationCache
, NS_ERROR_OUT_OF_MEMORY
);
2928 applicationCache
->Init();
2930 mApplicationCache
= applicationCache
;
2933 NS_IF_ADDREF(*aApplicationCache
= mApplicationCache
);
2939 nsGlobalWindow::GetCrypto(nsIDOMCrypto
** aCrypto
)
2941 FORWARD_TO_OUTER(GetCrypto
, (aCrypto
), NS_ERROR_NOT_INITIALIZED
);
2944 mCrypto
= do_CreateInstance(kCryptoContractID
);
2947 NS_IF_ADDREF(*aCrypto
= mCrypto
);
2953 nsGlobalWindow::GetPkcs11(nsIDOMPkcs11
** aPkcs11
)
2960 nsGlobalWindow::GetControllers(nsIControllers
** aResult
)
2962 FORWARD_TO_OUTER(GetControllers
, (aResult
), NS_ERROR_NOT_INITIALIZED
);
2964 if (!mControllers
) {
2966 mControllers
= do_CreateInstance(kXULControllersCID
, &rv
);
2967 NS_ENSURE_SUCCESS(rv
, rv
);
2969 // Add in the default controller
2970 nsCOMPtr
<nsIController
> controller
= do_CreateInstance(
2971 NS_WINDOWCONTROLLER_CONTRACTID
, &rv
);
2972 NS_ENSURE_SUCCESS(rv
, rv
);
2974 mControllers
->InsertControllerAt(0, controller
);
2975 nsCOMPtr
<nsIControllerContext
> controllerContext
= do_QueryInterface(controller
);
2976 if (!controllerContext
) return NS_ERROR_FAILURE
;
2978 controllerContext
->SetCommandContext(static_cast<nsIDOMWindow
*>(this));
2981 *aResult
= mControllers
;
2982 NS_ADDREF(*aResult
);
2987 nsGlobalWindow::GetOpener(nsIDOMWindowInternal
** aOpener
)
2989 FORWARD_TO_OUTER(GetOpener
, (aOpener
), NS_ERROR_NOT_INITIALIZED
);
2993 nsCOMPtr
<nsPIDOMWindow
> opener
= do_QueryReferent(mOpener
);
2998 // First, check if we were called from a privileged chrome script
2999 if (nsContentUtils::IsCallerTrustedForRead()) {
3000 NS_ADDREF(*aOpener
= opener
);
3004 nsCOMPtr
<nsPIDOMWindow
> openerPwin(do_QueryInterface(opener
));
3009 // First, ensure that we're not handing back a chrome window.
3010 nsGlobalWindow
*win
= static_cast<nsGlobalWindow
*>(openerPwin
.get());
3011 if (win
->IsChromeWindow()) {
3015 // We don't want to reveal the opener if the opener is a mail window,
3016 // because opener can be used to spoof the contents of a message (bug 105050).
3017 // So, we look in the opener's root docshell to see if it's a mail window.
3018 nsCOMPtr
<nsIDocShellTreeItem
> docShellAsItem
=
3019 do_QueryInterface(openerPwin
->GetDocShell());
3021 if (docShellAsItem
) {
3022 nsCOMPtr
<nsIDocShellTreeItem
> openerRootItem
;
3023 docShellAsItem
->GetRootTreeItem(getter_AddRefs(openerRootItem
));
3024 nsCOMPtr
<nsIDocShell
> openerRootDocShell(do_QueryInterface(openerRootItem
));
3025 if (openerRootDocShell
) {
3027 nsresult rv
= openerRootDocShell
->GetAppType(&appType
);
3028 if (NS_SUCCEEDED(rv
) && appType
!= nsIDocShell::APP_TYPE_MAIL
) {
3034 NS_IF_ADDREF(*aOpener
);
3039 nsGlobalWindow::SetOpener(nsIDOMWindowInternal
* aOpener
)
3041 // check if we were called from a privileged chrome script.
3042 // If not, opener is settable only to null.
3043 if (aOpener
&& !nsContentUtils::IsCallerTrustedForWrite()) {
3047 SetOpenerWindow(aOpener
, PR_FALSE
);
3053 nsGlobalWindow::GetStatus(nsAString
& aStatus
)
3055 FORWARD_TO_OUTER(GetStatus
, (aStatus
), NS_ERROR_NOT_INITIALIZED
);
3062 nsGlobalWindow::SetStatus(const nsAString
& aStatus
)
3064 FORWARD_TO_OUTER(SetStatus
, (aStatus
), NS_ERROR_NOT_INITIALIZED
);
3067 * If caller is not chrome and dom.disable_window_status_change is true,
3068 * prevent setting window.status by exiting early
3071 if (!CanSetProperty("dom.disable_window_status_change")) {
3077 nsCOMPtr
<nsIWebBrowserChrome
> browserChrome
;
3078 GetWebBrowserChrome(getter_AddRefs(browserChrome
));
3080 browserChrome
->SetStatus(nsIWebBrowserChrome::STATUS_SCRIPT
,
3081 PromiseFlatString(aStatus
).get());
3088 nsGlobalWindow::GetDefaultStatus(nsAString
& aDefaultStatus
)
3090 FORWARD_TO_OUTER(GetDefaultStatus
, (aDefaultStatus
),
3091 NS_ERROR_NOT_INITIALIZED
);
3093 aDefaultStatus
= mDefaultStatus
;
3098 nsGlobalWindow::SetDefaultStatus(const nsAString
& aDefaultStatus
)
3100 FORWARD_TO_OUTER(SetDefaultStatus
, (aDefaultStatus
),
3101 NS_ERROR_NOT_INITIALIZED
);
3104 * If caller is not chrome and dom.disable_window_status_change is true,
3105 * prevent setting window.defaultStatus by exiting early
3108 if (!CanSetProperty("dom.disable_window_status_change")) {
3112 mDefaultStatus
= aDefaultStatus
;
3114 nsCOMPtr
<nsIWebBrowserChrome
> browserChrome
;
3115 GetWebBrowserChrome(getter_AddRefs(browserChrome
));
3116 if (browserChrome
) {
3117 browserChrome
->SetStatus(nsIWebBrowserChrome::STATUS_SCRIPT_DEFAULT
,
3118 PromiseFlatString(aDefaultStatus
).get());
3125 nsGlobalWindow::GetName(nsAString
& aName
)
3127 FORWARD_TO_OUTER(GetName
, (aName
), NS_ERROR_NOT_INITIALIZED
);
3130 nsCOMPtr
<nsIDocShellTreeItem
> docShellAsItem(do_QueryInterface(mDocShell
));
3132 docShellAsItem
->GetName(getter_Copies(name
));
3139 nsGlobalWindow::SetName(const nsAString
& aName
)
3141 FORWARD_TO_OUTER(SetName
, (aName
), NS_ERROR_NOT_INITIALIZED
);
3143 nsresult result
= NS_OK
;
3144 nsCOMPtr
<nsIDocShellTreeItem
> docShellAsItem(do_QueryInterface(mDocShell
));
3146 result
= docShellAsItem
->SetName(PromiseFlatString(aName
).get());
3150 // Helper functions used by many methods below.
3152 nsGlobalWindow::DevToCSSIntPixels(PRInt32 px
)
3155 return px
; // assume 1:1
3157 nsRefPtr
<nsPresContext
> presContext
;
3158 mDocShell
->GetPresContext(getter_AddRefs(presContext
));
3162 return presContext
->DevPixelsToIntCSSPixels(px
);
3166 nsGlobalWindow::CSSToDevIntPixels(PRInt32 px
)
3169 return px
; // assume 1:1
3171 nsRefPtr
<nsPresContext
> presContext
;
3172 mDocShell
->GetPresContext(getter_AddRefs(presContext
));
3176 return presContext
->CSSPixelsToDevPixels(px
);
3180 nsGlobalWindow::DevToCSSIntPixels(nsIntSize px
)
3183 return px
; // assume 1:1
3185 nsRefPtr
<nsPresContext
> presContext
;
3186 mDocShell
->GetPresContext(getter_AddRefs(presContext
));
3191 presContext
->DevPixelsToIntCSSPixels(px
.width
),
3192 presContext
->DevPixelsToIntCSSPixels(px
.height
));
3196 nsGlobalWindow::CSSToDevIntPixels(nsIntSize px
)
3199 return px
; // assume 1:1
3201 nsRefPtr
<nsPresContext
> presContext
;
3202 mDocShell
->GetPresContext(getter_AddRefs(presContext
));
3207 presContext
->CSSPixelsToDevPixels(px
.width
),
3208 presContext
->CSSPixelsToDevPixels(px
.height
));
3213 nsGlobalWindow::GetInnerWidth(PRInt32
* aInnerWidth
)
3215 FORWARD_TO_OUTER(GetInnerWidth
, (aInnerWidth
), NS_ERROR_NOT_INITIALIZED
);
3217 NS_ENSURE_STATE(mDocShell
);
3219 EnsureSizeUpToDate();
3221 nsCOMPtr
<nsIBaseWindow
> docShellWin(do_QueryInterface(mDocShell
));
3222 nsRefPtr
<nsPresContext
> presContext
;
3223 mDocShell
->GetPresContext(getter_AddRefs(presContext
));
3225 if (docShellWin
&& presContext
) {
3226 PRInt32 width
, notused
;
3227 docShellWin
->GetSize(&width
, ¬used
);
3228 *aInnerWidth
= nsPresContext::
3229 AppUnitsToIntCSSPixels(presContext
->DevPixelsToAppUnits(width
));
3238 nsGlobalWindow::SetInnerWidth(PRInt32 aInnerWidth
)
3240 FORWARD_TO_OUTER(SetInnerWidth
, (aInnerWidth
), NS_ERROR_NOT_INITIALIZED
);
3242 NS_ENSURE_STATE(mDocShell
);
3245 * If caller is not chrome and the user has not explicitly exempted the site,
3246 * prevent setting window.innerWidth by exiting early
3249 if (!CanMoveResizeWindows() || IsFrame()) {
3253 nsCOMPtr
<nsIDocShellTreeItem
> docShellAsItem(do_QueryInterface(mDocShell
));
3254 NS_ENSURE_TRUE(docShellAsItem
, NS_ERROR_FAILURE
);
3256 nsCOMPtr
<nsIDocShellTreeOwner
> treeOwner
;
3257 docShellAsItem
->GetTreeOwner(getter_AddRefs(treeOwner
));
3258 NS_ENSURE_TRUE(treeOwner
, NS_ERROR_FAILURE
);
3260 NS_ENSURE_SUCCESS(CheckSecurityWidthAndHeight(&aInnerWidth
, nsnull
),
3263 PRInt32 width
= CSSToDevIntPixels(aInnerWidth
);
3265 nsCOMPtr
<nsIBaseWindow
> docShellAsWin(do_QueryInterface(mDocShell
));
3266 PRInt32 notused
, height
= 0;
3267 docShellAsWin
->GetSize(¬used
, &height
);
3269 NS_ENSURE_SUCCESS(treeOwner
->SizeShellTo(docShellAsItem
, width
, height
),
3276 nsGlobalWindow::GetInnerHeight(PRInt32
* aInnerHeight
)
3278 FORWARD_TO_OUTER(GetInnerHeight
, (aInnerHeight
), NS_ERROR_NOT_INITIALIZED
);
3280 NS_ENSURE_STATE(mDocShell
);
3282 EnsureSizeUpToDate();
3284 nsCOMPtr
<nsIBaseWindow
> docShellWin(do_QueryInterface(mDocShell
));
3285 nsRefPtr
<nsPresContext
> presContext
;
3286 mDocShell
->GetPresContext(getter_AddRefs(presContext
));
3288 if (docShellWin
&& presContext
) {
3289 PRInt32 height
, notused
;
3290 docShellWin
->GetSize(¬used
, &height
);
3291 *aInnerHeight
= nsPresContext::
3292 AppUnitsToIntCSSPixels(presContext
->DevPixelsToAppUnits(height
));
3300 nsGlobalWindow::SetInnerHeight(PRInt32 aInnerHeight
)
3302 FORWARD_TO_OUTER(SetInnerHeight
, (aInnerHeight
), NS_ERROR_NOT_INITIALIZED
);
3304 NS_ENSURE_STATE(mDocShell
);
3307 * If caller is not chrome and the user has not explicitly exempted the site,
3308 * prevent setting window.innerHeight by exiting early
3311 if (!CanMoveResizeWindows() || IsFrame()) {
3315 nsCOMPtr
<nsIDocShellTreeItem
> docShellAsItem(do_QueryInterface(mDocShell
));
3316 NS_ENSURE_TRUE(docShellAsItem
, NS_ERROR_FAILURE
);
3318 nsCOMPtr
<nsIDocShellTreeOwner
> treeOwner
;
3319 docShellAsItem
->GetTreeOwner(getter_AddRefs(treeOwner
));
3320 NS_ENSURE_TRUE(treeOwner
, NS_ERROR_FAILURE
);
3322 NS_ENSURE_SUCCESS(CheckSecurityWidthAndHeight(nsnull
, &aInnerHeight
),
3325 PRInt32 height
= CSSToDevIntPixels(aInnerHeight
);
3327 nsCOMPtr
<nsIBaseWindow
> docShellAsWin(do_QueryInterface(mDocShell
));
3328 PRInt32 width
= 0, notused
;
3329 docShellAsWin
->GetSize(&width
, ¬used
);
3331 NS_ENSURE_SUCCESS(treeOwner
->SizeShellTo(docShellAsItem
, width
, height
),
3338 nsGlobalWindow::GetOuterSize(nsIntSize
* aSizeCSSPixels
)
3340 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
3341 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
3342 NS_ENSURE_TRUE(treeOwnerAsWin
, NS_ERROR_FAILURE
);
3344 nsGlobalWindow
* rootWindow
=
3345 static_cast<nsGlobalWindow
*>(GetPrivateRoot());
3347 rootWindow
->FlushPendingNotifications(Flush_Layout
);
3350 nsIntSize sizeDevPixels
;
3351 NS_ENSURE_SUCCESS(treeOwnerAsWin
->GetSize(&sizeDevPixels
.width
,
3352 &sizeDevPixels
.height
),
3355 *aSizeCSSPixels
= DevToCSSIntPixels(sizeDevPixels
);
3360 nsGlobalWindow::GetOuterWidth(PRInt32
* aOuterWidth
)
3362 FORWARD_TO_OUTER(GetOuterWidth
, (aOuterWidth
), NS_ERROR_NOT_INITIALIZED
);
3364 nsIntSize sizeCSSPixels
;
3365 nsresult rv
= GetOuterSize(&sizeCSSPixels
);
3366 NS_ENSURE_SUCCESS(rv
, rv
);
3368 *aOuterWidth
= sizeCSSPixels
.width
;
3373 nsGlobalWindow::GetOuterHeight(PRInt32
* aOuterHeight
)
3375 FORWARD_TO_OUTER(GetOuterHeight
, (aOuterHeight
), NS_ERROR_NOT_INITIALIZED
);
3377 nsIntSize sizeCSSPixels
;
3378 nsresult rv
= GetOuterSize(&sizeCSSPixels
);
3379 NS_ENSURE_SUCCESS(rv
, rv
);
3381 *aOuterHeight
= sizeCSSPixels
.height
;
3386 nsGlobalWindow::SetOuterSize(PRInt32 aLengthCSSPixels
, PRBool aIsWidth
)
3389 * If caller is not chrome and the user has not explicitly exempted the site,
3390 * prevent setting window.outerWidth by exiting early
3393 if (!CanMoveResizeWindows() || IsFrame()) {
3397 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
3398 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
3399 NS_ENSURE_TRUE(treeOwnerAsWin
, NS_ERROR_FAILURE
);
3401 NS_ENSURE_SUCCESS(CheckSecurityWidthAndHeight(
3402 aIsWidth
? &aLengthCSSPixels
: nsnull
,
3403 aIsWidth
? nsnull
: &aLengthCSSPixels
),
3406 PRInt32 width
, height
;
3407 NS_ENSURE_SUCCESS(treeOwnerAsWin
->GetSize(&width
, &height
), NS_ERROR_FAILURE
);
3409 PRInt32 lengthDevPixels
= CSSToDevIntPixels(aLengthCSSPixels
);
3411 width
= lengthDevPixels
;
3413 height
= lengthDevPixels
;
3415 return treeOwnerAsWin
->SetSize(width
, height
, PR_TRUE
);
3419 nsGlobalWindow::SetOuterWidth(PRInt32 aOuterWidth
)
3421 FORWARD_TO_OUTER(SetOuterWidth
, (aOuterWidth
), NS_ERROR_NOT_INITIALIZED
);
3423 return SetOuterSize(aOuterWidth
, PR_TRUE
);
3427 nsGlobalWindow::SetOuterHeight(PRInt32 aOuterHeight
)
3429 FORWARD_TO_OUTER(SetOuterHeight
, (aOuterHeight
), NS_ERROR_NOT_INITIALIZED
);
3431 return SetOuterSize(aOuterHeight
, PR_FALSE
);
3435 nsGlobalWindow::GetScreenX(PRInt32
* aScreenX
)
3437 FORWARD_TO_OUTER(GetScreenX
, (aScreenX
), NS_ERROR_NOT_INITIALIZED
);
3439 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
3440 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
3441 NS_ENSURE_TRUE(treeOwnerAsWin
, NS_ERROR_FAILURE
);
3445 NS_ENSURE_SUCCESS(treeOwnerAsWin
->GetPosition(&x
, &y
),
3448 *aScreenX
= DevToCSSIntPixels(x
);
3453 nsGlobalWindow::GetInnerScreenRect()
3458 nsGlobalWindow
* rootWindow
=
3459 static_cast<nsGlobalWindow
*>(GetPrivateRoot());
3461 rootWindow
->FlushPendingNotifications(Flush_Layout
);
3464 nsCOMPtr
<nsIPresShell
> presShell
;
3465 mDocShell
->GetPresShell(getter_AddRefs(presShell
));
3468 nsIFrame
* rootFrame
= presShell
->GetRootFrame();
3472 return rootFrame
->GetScreenRectInAppUnits();
3476 nsGlobalWindow::GetMozInnerScreenX(float* aScreenX
)
3478 FORWARD_TO_OUTER(GetMozInnerScreenX
, (aScreenX
), NS_ERROR_NOT_INITIALIZED
);
3480 nsRect r
= GetInnerScreenRect();
3481 *aScreenX
= nsPresContext::AppUnitsToFloatCSSPixels(r
.x
);
3486 nsGlobalWindow::GetMozInnerScreenY(float* aScreenY
)
3488 FORWARD_TO_OUTER(GetMozInnerScreenY
, (aScreenY
), NS_ERROR_NOT_INITIALIZED
);
3490 nsRect r
= GetInnerScreenRect();
3491 *aScreenY
= nsPresContext::AppUnitsToFloatCSSPixels(r
.y
);
3496 nsGlobalWindow::GetMozPaintCount(PRUint64
* aResult
)
3498 FORWARD_TO_OUTER(GetMozPaintCount
, (aResult
), NS_ERROR_NOT_INITIALIZED
);
3505 nsCOMPtr
<nsIPresShell
> presShell
;
3506 mDocShell
->GetPresShell(getter_AddRefs(presShell
));
3510 *aResult
= presShell
->GetPaintCount();
3515 nsGlobalWindow::SetScreenX(PRInt32 aScreenX
)
3517 FORWARD_TO_OUTER(SetScreenX
, (aScreenX
), NS_ERROR_NOT_INITIALIZED
);
3520 * If caller is not chrome and the user has not explicitly exempted the site,
3521 * prevent setting window.screenX by exiting early
3524 if (!CanMoveResizeWindows() || IsFrame()) {
3528 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
3529 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
3530 NS_ENSURE_TRUE(treeOwnerAsWin
, NS_ERROR_FAILURE
);
3532 NS_ENSURE_SUCCESS(CheckSecurityLeftAndTop(&aScreenX
, nsnull
),
3536 NS_ENSURE_SUCCESS(treeOwnerAsWin
->GetPosition(&x
, &y
),
3539 x
= CSSToDevIntPixels(aScreenX
);
3541 NS_ENSURE_SUCCESS(treeOwnerAsWin
->SetPosition(x
, y
),
3548 nsGlobalWindow::GetScreenY(PRInt32
* aScreenY
)
3550 FORWARD_TO_OUTER(GetScreenY
, (aScreenY
), NS_ERROR_NOT_INITIALIZED
);
3552 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
3553 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
3554 NS_ENSURE_TRUE(treeOwnerAsWin
, NS_ERROR_FAILURE
);
3558 NS_ENSURE_SUCCESS(treeOwnerAsWin
->GetPosition(&x
, &y
),
3561 *aScreenY
= DevToCSSIntPixels(y
);
3566 nsGlobalWindow::SetScreenY(PRInt32 aScreenY
)
3568 FORWARD_TO_OUTER(SetScreenY
, (aScreenY
), NS_ERROR_NOT_INITIALIZED
);
3571 * If caller is not chrome and the user has not explicitly exempted the site,
3572 * prevent setting window.screenY by exiting early
3575 if (!CanMoveResizeWindows() || IsFrame()) {
3579 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
3580 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
3581 NS_ENSURE_TRUE(treeOwnerAsWin
, NS_ERROR_FAILURE
);
3583 NS_ENSURE_SUCCESS(CheckSecurityLeftAndTop(nsnull
, &aScreenY
),
3587 NS_ENSURE_SUCCESS(treeOwnerAsWin
->GetPosition(&x
, &y
),
3590 y
= CSSToDevIntPixels(aScreenY
);
3592 NS_ENSURE_SUCCESS(treeOwnerAsWin
->SetPosition(x
, y
),
3598 // NOTE: Arguments to this function should have values scaled to
3599 // CSS pixels, not device pixels.
3601 nsGlobalWindow::CheckSecurityWidthAndHeight(PRInt32
* aWidth
, PRInt32
* aHeight
)
3604 if (!nsContentUtils::IsCallerTrustedForWrite()) {
3605 // if attempting to resize the window, hide any open popups
3606 nsCOMPtr
<nsIDocument
> doc(do_QueryInterface(mDocument
));
3607 nsContentUtils::HidePopupsInDocument(doc
);
3611 // This one is easy. Just ensure the variable is greater than 100;
3612 if ((aWidth
&& *aWidth
< 100) || (aHeight
&& *aHeight
< 100)) {
3613 // Check security state for use in determing window dimensions
3615 if (!nsContentUtils::IsCallerTrustedForWrite()) {
3617 if (aWidth
&& *aWidth
< 100) {
3620 if (aHeight
&& *aHeight
< 100) {
3629 // NOTE: Arguments to this function should have values scaled to
3630 // CSS pixels, not device pixels.
3632 nsGlobalWindow::CheckSecurityLeftAndTop(PRInt32
* aLeft
, PRInt32
* aTop
)
3634 // This one is harder. We have to get the screen size and window dimensions.
3636 // Check security state for use in determing window dimensions
3638 if (!nsContentUtils::IsCallerTrustedForWrite()) {
3640 // if attempting to move the window, hide any open popups
3641 nsCOMPtr
<nsIDocument
> doc(do_QueryInterface(mDocument
));
3642 nsContentUtils::HidePopupsInDocument(doc
);
3645 nsGlobalWindow
* rootWindow
=
3646 static_cast<nsGlobalWindow
*>(GetPrivateRoot());
3648 rootWindow
->FlushPendingNotifications(Flush_Layout
);
3651 nsCOMPtr
<nsIBaseWindow
> treeOwner
;
3652 GetTreeOwner(getter_AddRefs(treeOwner
));
3654 nsCOMPtr
<nsIDOMScreen
> screen
;
3655 GetScreen(getter_AddRefs(screen
));
3657 if (treeOwner
&& screen
) {
3658 PRInt32 screenLeft
, screenTop
, screenWidth
, screenHeight
;
3659 PRInt32 winLeft
, winTop
, winWidth
, winHeight
;
3661 // Get the window size
3662 treeOwner
->GetPositionAndSize(&winLeft
, &winTop
, &winWidth
, &winHeight
);
3664 // convert those values to CSS pixels
3665 // XXX four separate retrievals of the prescontext
3666 winLeft
= DevToCSSIntPixels(winLeft
);
3667 winTop
= DevToCSSIntPixels(winTop
);
3668 winWidth
= DevToCSSIntPixels(winWidth
);
3669 winHeight
= DevToCSSIntPixels(winHeight
);
3671 // Get the screen dimensions
3672 // XXX This should use nsIScreenManager once it's fully fleshed out.
3673 screen
->GetAvailLeft(&screenLeft
);
3674 screen
->GetAvailWidth(&screenWidth
);
3675 screen
->GetAvailHeight(&screenHeight
);
3676 #if defined(XP_MAC) || defined(XP_MACOSX)
3677 /* The mac's coordinate system is different from the assumed Windows'
3678 system. It offsets by the height of the menubar so that a window
3679 placed at (0,0) will be entirely visible. Unfortunately that
3680 correction is made elsewhere (in Widget) and the meaning of
3681 the Avail... coordinates is overloaded. Here we allow a window
3682 to be placed at (0,0) because it does make sense to do so.
3684 screen
->GetTop(&screenTop
);
3686 screen
->GetAvailTop(&screenTop
);
3690 if (screenLeft
+screenWidth
< *aLeft
+winWidth
)
3691 *aLeft
= screenLeft
+screenWidth
- winWidth
;
3692 if (screenLeft
> *aLeft
)
3693 *aLeft
= screenLeft
;
3696 if (screenTop
+screenHeight
< *aTop
+winHeight
)
3697 *aTop
= screenTop
+screenHeight
- winHeight
;
3698 if (screenTop
> *aTop
)
3713 nsGlobalWindow::GetPageXOffset(PRInt32
* aPageXOffset
)
3715 return GetScrollX(aPageXOffset
);
3719 nsGlobalWindow::GetPageYOffset(PRInt32
* aPageYOffset
)
3721 return GetScrollY(aPageYOffset
);
3725 nsGlobalWindow::GetScrollMaxXY(PRInt32
* aScrollMaxX
, PRInt32
* aScrollMaxY
)
3727 FORWARD_TO_OUTER(GetScrollMaxXY
, (aScrollMaxX
, aScrollMaxY
),
3728 NS_ERROR_NOT_INITIALIZED
);
3730 FlushPendingNotifications(Flush_Layout
);
3731 nsIScrollableFrame
*sf
= GetScrollFrame();
3735 nsRect scrollRange
= sf
->GetScrollRange();
3738 *aScrollMaxX
= NS_MAX(0,
3739 (PRInt32
)floor(nsPresContext::AppUnitsToFloatCSSPixels(scrollRange
.XMost())));
3741 *aScrollMaxY
= NS_MAX(0,
3742 (PRInt32
)floor(nsPresContext::AppUnitsToFloatCSSPixels(scrollRange
.YMost())));
3748 nsGlobalWindow::GetScrollMaxX(PRInt32
* aScrollMaxX
)
3750 NS_ENSURE_ARG_POINTER(aScrollMaxX
);
3752 return GetScrollMaxXY(aScrollMaxX
, nsnull
);
3756 nsGlobalWindow::GetScrollMaxY(PRInt32
* aScrollMaxY
)
3758 NS_ENSURE_ARG_POINTER(aScrollMaxY
);
3760 return GetScrollMaxXY(nsnull
, aScrollMaxY
);
3764 nsGlobalWindow::GetScrollXY(PRInt32
* aScrollX
, PRInt32
* aScrollY
,
3767 FORWARD_TO_OUTER(GetScrollXY
, (aScrollX
, aScrollY
, aDoFlush
),
3768 NS_ERROR_NOT_INITIALIZED
);
3771 FlushPendingNotifications(Flush_Layout
);
3773 EnsureSizeUpToDate();
3776 nsIScrollableFrame
*sf
= GetScrollFrame();
3780 nsPoint scrollPos
= sf
->GetScrollPosition();
3781 if (scrollPos
!= nsPoint(0,0) && !aDoFlush
) {
3782 // Oh, well. This is the expensive case -- the window is scrolled and we
3783 // didn't actually flush yet. Repeat, but with a flush, since the content
3784 // may get shorter and hence our scroll position may decrease.
3785 return GetScrollXY(aScrollX
, aScrollY
, PR_TRUE
);
3789 *aScrollX
= nsPresContext::AppUnitsToIntCSSPixels(scrollPos
.x
);
3791 *aScrollY
= nsPresContext::AppUnitsToIntCSSPixels(scrollPos
.y
);
3797 nsGlobalWindow::GetScrollX(PRInt32
* aScrollX
)
3799 NS_ENSURE_ARG_POINTER(aScrollX
);
3801 return GetScrollXY(aScrollX
, nsnull
, PR_FALSE
);
3805 nsGlobalWindow::GetScrollY(PRInt32
* aScrollY
)
3807 NS_ENSURE_ARG_POINTER(aScrollY
);
3809 return GetScrollXY(nsnull
, aScrollY
, PR_FALSE
);
3813 nsGlobalWindow::GetLength(PRUint32
* aLength
)
3815 nsCOMPtr
<nsIDOMWindowCollection
> frames
;
3816 if (NS_SUCCEEDED(GetFrames(getter_AddRefs(frames
))) && frames
) {
3817 return frames
->GetLength(aLength
);
3819 return NS_ERROR_FAILURE
;
3823 nsGlobalWindow::DispatchCustomEvent(const char *aEventName
)
3825 PRBool defaultActionEnabled
= PR_TRUE
;
3826 nsCOMPtr
<nsIDocument
> doc(do_QueryInterface(mDocument
));
3827 nsContentUtils::DispatchTrustedEvent(doc
,
3828 static_cast<nsIScriptGlobalObject
*>(this),
3829 NS_ConvertASCIItoUTF16(aEventName
),
3830 PR_TRUE
, PR_TRUE
, &defaultActionEnabled
);
3832 return defaultActionEnabled
;
3835 static already_AddRefed
<nsIDocShellTreeItem
>
3836 GetCallerDocShellTreeItem()
3838 JSContext
*cx
= nsContentUtils::GetCurrentJSContext();
3839 nsIDocShellTreeItem
*callerItem
= nsnull
;
3842 nsCOMPtr
<nsIWebNavigation
> callerWebNav
=
3843 do_GetInterface(nsJSUtils::GetDynamicScriptGlobal(cx
));
3846 CallQueryInterface(callerWebNav
, &callerItem
);
3854 nsGlobalWindow::WindowExists(const nsAString
& aName
,
3855 PRBool aLookForCallerOnJSStack
)
3857 NS_PRECONDITION(IsOuterWindow(), "Must be outer window");
3858 NS_PRECONDITION(mDocShell
, "Must have docshell");
3860 nsCOMPtr
<nsIDocShellTreeItem
> caller
;
3861 if (aLookForCallerOnJSStack
) {
3862 caller
= GetCallerDocShellTreeItem();
3865 nsCOMPtr
<nsIDocShellTreeItem
> docShell
= do_QueryInterface(mDocShell
);
3866 NS_ASSERTION(docShell
,
3867 "Docshell doesn't implement nsIDocShellTreeItem?");
3873 nsCOMPtr
<nsIDocShellTreeItem
> namedItem
;
3874 docShell
->FindItemWithName(PromiseFlatString(aName
).get(), nsnull
, caller
,
3875 getter_AddRefs(namedItem
));
3876 return namedItem
!= nsnull
;
3879 already_AddRefed
<nsIWidget
>
3880 nsGlobalWindow::GetMainWidget()
3882 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
3883 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
3885 nsIWidget
*widget
= nsnull
;
3887 if (treeOwnerAsWin
) {
3888 treeOwnerAsWin
->GetMainWidget(&widget
);
3895 nsGlobalWindow::GetNearestWidget()
3897 nsIDocShell
* docShell
= GetDocShell();
3898 NS_ENSURE_TRUE(docShell
, nsnull
);
3899 nsCOMPtr
<nsIPresShell
> presShell
;
3900 docShell
->GetPresShell(getter_AddRefs(presShell
));
3901 NS_ENSURE_TRUE(presShell
, nsnull
);
3902 nsIFrame
* rootFrame
= presShell
->GetRootFrame();
3903 NS_ENSURE_TRUE(rootFrame
, nsnull
);
3904 return rootFrame
->GetView()->GetNearestWidget(nsnull
);
3908 nsGlobalWindow::SetFullScreen(PRBool aFullScreen
)
3910 FORWARD_TO_OUTER(SetFullScreen
, (aFullScreen
), NS_ERROR_NOT_INITIALIZED
);
3912 NS_ENSURE_TRUE(mDocShell
, NS_ERROR_FAILURE
);
3914 PRBool rootWinFullScreen
;
3915 GetFullScreen(&rootWinFullScreen
);
3916 // Only chrome can change our fullScreen mode.
3917 if (aFullScreen
== rootWinFullScreen
||
3918 !nsContentUtils::IsCallerTrustedForWrite()) {
3922 // SetFullScreen needs to be called on the root window, so get that
3923 // via the DocShell tree, and if we are not already the root,
3924 // call SetFullScreen on that window instead.
3925 nsCOMPtr
<nsIDocShellTreeItem
> treeItem
= do_QueryInterface(mDocShell
);
3926 nsCOMPtr
<nsIDocShellTreeItem
> rootItem
;
3927 treeItem
->GetRootTreeItem(getter_AddRefs(rootItem
));
3928 nsCOMPtr
<nsIDOMWindowInternal
> window
= do_GetInterface(rootItem
);
3930 return NS_ERROR_FAILURE
;
3931 if (rootItem
!= treeItem
)
3932 return window
->SetFullScreen(aFullScreen
);
3934 // make sure we don't try to set full screen on a non-chrome window,
3935 // which might happen in embedding world
3937 treeItem
->GetItemType(&itemType
);
3938 if (itemType
!= nsIDocShellTreeItem::typeChrome
)
3939 return NS_ERROR_FAILURE
;
3941 // dispatch a "fullscreen" DOM event so that XUL apps can
3942 // respond visually if we are kicked into full screen mode
3943 if (!DispatchCustomEvent("fullscreen")) {
3947 // Prevent chrome documents which are still loading from resizing
3948 // the window after we set fullscreen mode.
3949 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
3950 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
3951 nsCOMPtr
<nsIXULWindow
> xulWin(do_GetInterface(treeOwnerAsWin
));
3952 if (aFullScreen
&& xulWin
) {
3953 xulWin
->SetIntrinsicallySized(PR_FALSE
);
3956 nsCOMPtr
<nsIWidget
> widget
= GetMainWidget();
3958 widget
->MakeFullScreen(aFullScreen
);
3960 mFullScreen
= aFullScreen
;
3966 nsGlobalWindow::GetFullScreen(PRBool
* aFullScreen
)
3968 FORWARD_TO_OUTER(GetFullScreen
, (aFullScreen
), NS_ERROR_NOT_INITIALIZED
);
3970 // Get the fullscreen value of the root window, to always have the value
3971 // accurate, even when called from content.
3972 nsCOMPtr
<nsIDocShellTreeItem
> treeItem
= do_QueryInterface(mDocShell
);
3974 nsCOMPtr
<nsIDocShellTreeItem
> rootItem
;
3975 treeItem
->GetRootTreeItem(getter_AddRefs(rootItem
));
3976 if (rootItem
!= treeItem
) {
3977 nsCOMPtr
<nsIDOMWindowInternal
> window
= do_GetInterface(rootItem
);
3979 return window
->GetFullScreen(aFullScreen
);
3983 // We are the root window, or something went wrong. Return our internal value.
3984 *aFullScreen
= mFullScreen
;
3989 nsGlobalWindow::DOMWindowDumpEnabled()
3991 #if !(defined(NS_DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
3992 // In optimized builds we check a pref that controls if we should
3993 // enable output from dump() or not, in debug builds it's always
3995 return gDOMWindowDumpEnabled
;
4002 nsGlobalWindow::Dump(const nsAString
& aStr
)
4004 if (!DOMWindowDumpEnabled()) {
4008 char *cstr
= ToNewUTF8String(aStr
);
4010 #if defined(XP_MAC) || defined(XP_MACOSX)
4011 // have to convert \r to \n so that printing to the console works
4012 char *c
= cstr
, *cEnd
= cstr
+ strlen(cstr
);
4021 FILE *fp
= gDumpFile
? gDumpFile
: stdout
;
4024 nsMemory::Free(cstr
);
4031 nsGlobalWindow::EnsureReflowFlushAndPaint()
4033 NS_ASSERTION(mDocShell
, "EnsureReflowFlushAndPaint() called with no "
4039 nsCOMPtr
<nsIPresShell
> presShell
;
4040 mDocShell
->GetPresShell(getter_AddRefs(presShell
));
4045 // Flush pending reflows.
4047 mDoc
->FlushPendingNotifications(Flush_Layout
);
4050 // Unsuppress painting.
4051 presShell
->UnsuppressPainting();
4055 nsGlobalWindow::GetTextZoom(float *aZoom
)
4057 FORWARD_TO_OUTER(GetTextZoom
, (aZoom
), NS_ERROR_NOT_INITIALIZED
);
4060 nsCOMPtr
<nsIContentViewer
> contentViewer
;
4061 mDocShell
->GetContentViewer(getter_AddRefs(contentViewer
));
4062 nsCOMPtr
<nsIMarkupDocumentViewer
> markupViewer(do_QueryInterface(contentViewer
));
4065 return markupViewer
->GetTextZoom(aZoom
);
4068 return NS_ERROR_FAILURE
;
4072 nsGlobalWindow::SetTextZoom(float aZoom
)
4074 FORWARD_TO_OUTER(SetTextZoom
, (aZoom
), NS_ERROR_NOT_INITIALIZED
);
4077 nsCOMPtr
<nsIContentViewer
> contentViewer
;
4078 mDocShell
->GetContentViewer(getter_AddRefs(contentViewer
));
4079 nsCOMPtr
<nsIMarkupDocumentViewer
> markupViewer(do_QueryInterface(contentViewer
));
4082 return markupViewer
->SetTextZoom(aZoom
);
4084 return NS_ERROR_FAILURE
;
4089 nsGlobalWindow::MakeScriptDialogTitle(nsAString
&aOutTitle
)
4091 aOutTitle
.Truncate();
4093 // Try to get a host from the running principal -- this will do the
4094 // right thing for javascript: and data: documents.
4096 nsresult rv
= NS_OK
;
4097 NS_ASSERTION(nsContentUtils::GetSecurityManager(),
4098 "Global Window has no security manager!");
4099 if (nsContentUtils::GetSecurityManager()) {
4100 nsCOMPtr
<nsIPrincipal
> principal
;
4101 rv
= nsContentUtils::GetSecurityManager()->
4102 GetSubjectPrincipal(getter_AddRefs(principal
));
4104 if (NS_SUCCEEDED(rv
) && principal
) {
4105 nsCOMPtr
<nsIURI
> uri
;
4106 rv
= principal
->GetURI(getter_AddRefs(uri
));
4108 if (NS_SUCCEEDED(rv
) && uri
) {
4109 // remove user:pass for privacy and spoof prevention
4111 nsCOMPtr
<nsIURIFixup
> fixup(do_GetService(NS_URIFIXUP_CONTRACTID
));
4113 nsCOMPtr
<nsIURI
> fixedURI
;
4114 rv
= fixup
->CreateExposableURI(uri
, getter_AddRefs(fixedURI
));
4115 if (NS_SUCCEEDED(rv
) && fixedURI
) {
4117 fixedURI
->GetHost(host
);
4119 if (!host
.IsEmpty()) {
4120 // if this URI has a host we'll show it. For other
4121 // schemes (e.g. file:) we fall back to the localized
4124 nsCAutoString prepath
;
4125 fixedURI
->GetPrePath(prepath
);
4127 NS_ConvertUTF8toUTF16
ucsPrePath(prepath
);
4128 const PRUnichar
*formatStrings
[] = { ucsPrePath
.get() };
4129 nsXPIDLString tempString
;
4130 nsContentUtils::FormatLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES
,
4132 formatStrings
, NS_ARRAY_LENGTH(formatStrings
),
4134 aOutTitle
= tempString
;
4140 else { // failed to get subject principal
4141 NS_WARNING("No script principal? Who is calling alert/confirm/prompt?!");
4145 if (aOutTitle
.IsEmpty()) {
4146 // We didn't find a host so use the generic heading
4147 nsXPIDLString tempString
;
4148 nsContentUtils::GetLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES
,
4149 "ScriptDlgGenericHeading",
4151 aOutTitle
= tempString
;
4155 if (aOutTitle
.IsEmpty()) {
4156 NS_WARNING("could not get ScriptDlgGenericHeading string from string bundle");
4157 aOutTitle
.AssignLiteral("[Script]");
4163 nsGlobalWindow::CanMoveResizeWindows()
4165 if (!CanSetProperty("dom.disable_window_move_resize"))
4168 if (gMouseDown
&& !gDragServiceDisabled
) {
4169 nsCOMPtr
<nsIDragService
> ds
=
4170 do_GetService("@mozilla.org/widget/dragservice;1");
4172 gDragServiceDisabled
= PR_TRUE
;
4180 nsGlobalWindow::Alert(const nsAString
& aString
)
4182 FORWARD_TO_OUTER(Alert
, (aString
), NS_ERROR_NOT_INITIALIZED
);
4184 // Reset popup state while opening a modal dialog, and firing events
4185 // about the dialog, to prevent the current state from being active
4186 // the whole time a modal dialog is open.
4187 nsAutoPopupStatePusher
popupStatePusher(openAbused
, PR_TRUE
);
4189 // Special handling for alert(null) in JS for backwards
4192 NS_NAMED_LITERAL_STRING(null_str
, "null");
4194 const nsAString
*str
= DOMStringIsNull(aString
) ? &null_str
: &aString
;
4196 // Before bringing up the window, unsuppress painting and flush
4198 EnsureReflowFlushAndPaint();
4201 MakeScriptDialogTitle(title
);
4203 // Remove non-terminating null characters from the
4204 // string. See bug #310037.
4206 nsContentUtils::StripNullChars(*str
, final
);
4209 nsCOMPtr
<nsIPromptService
> promptSvc
= do_GetService("@mozilla.org/embedcomp/prompt-service;1", &rv
);
4210 NS_ENSURE_SUCCESS(rv
, rv
);
4212 return promptSvc
->Alert(this, title
.get(), final
.get());
4216 nsGlobalWindow::Confirm(const nsAString
& aString
, PRBool
* aReturn
)
4218 FORWARD_TO_OUTER(Confirm
, (aString
, aReturn
), NS_ERROR_NOT_INITIALIZED
);
4220 // Reset popup state while opening a modal dialog, and firing events
4221 // about the dialog, to prevent the current state from being active
4222 // the whole time a modal dialog is open.
4223 nsAutoPopupStatePusher
popupStatePusher(openAbused
, PR_TRUE
);
4225 *aReturn
= PR_FALSE
;
4227 // Before bringing up the window, unsuppress painting and flush
4229 EnsureReflowFlushAndPaint();
4232 MakeScriptDialogTitle(title
);
4234 // Remove non-terminating null characters from the
4235 // string. See bug #310037.
4237 nsContentUtils::StripNullChars(aString
, final
);
4240 nsCOMPtr
<nsIPromptService
> promptSvc
= do_GetService("@mozilla.org/embedcomp/prompt-service;1", &rv
);
4241 NS_ENSURE_SUCCESS(rv
, rv
);
4243 return promptSvc
->Confirm(this, title
.get(), final
.get(), aReturn
);
4247 nsGlobalWindow::Prompt(const nsAString
& aMessage
, const nsAString
& aInitial
,
4250 SetDOMStringToNull(aReturn
);
4252 // Reset popup state while opening a modal dialog, and firing events
4253 // about the dialog, to prevent the current state from being active
4254 // the whole time a modal dialog is open.
4255 nsAutoPopupStatePusher
popupStatePusher(openAbused
, PR_TRUE
);
4257 // Before bringing up the window, unsuppress painting and flush
4259 EnsureReflowFlushAndPaint();
4262 MakeScriptDialogTitle(title
);
4264 // Remove non-terminating null characters from the
4265 // string. See bug #310037.
4266 nsAutoString fixedMessage
, fixedInitial
;
4267 nsContentUtils::StripNullChars(aMessage
, fixedMessage
);
4268 nsContentUtils::StripNullChars(aInitial
, fixedInitial
);
4271 nsCOMPtr
<nsIPromptService
> promptSvc
= do_GetService("@mozilla.org/embedcomp/prompt-service;1", &rv
);
4272 NS_ENSURE_SUCCESS(rv
, rv
);
4274 // Pass in the default value, if any.
4275 PRUnichar
*inoutValue
= ToNewUnicode(fixedInitial
);
4278 rv
= promptSvc
->Prompt(this, title
.get(), fixedMessage
.get(),
4279 &inoutValue
, nsnull
, &dummy
, &ok
);
4280 NS_ENSURE_SUCCESS(rv
, rv
);
4282 nsAdoptingString
outValue(inoutValue
);
4284 if (ok
&& outValue
) {
4285 aReturn
.Assign(outValue
);
4292 nsGlobalWindow::Focus()
4294 FORWARD_TO_OUTER(Focus
, (), NS_ERROR_NOT_INITIALIZED
);
4296 nsIFocusManager
* fm
= nsFocusManager::GetFocusManager();
4300 nsCOMPtr
<nsIBaseWindow
> baseWin
= do_QueryInterface(mDocShell
);
4302 PRBool isVisible
= PR_FALSE
;
4304 baseWin
->GetVisibility(&isVisible
);
4308 // A hidden tab is being focused, ignore this call.
4313 * If caller is not chrome and dom.disable_window_flip is true,
4314 * prevent bringing a window to the front if the window is not the
4315 * currently active window, but do change the currently focused
4316 * window in the focus controller so that focus is in the right
4317 * place when the window is activated again.
4321 CanSetProperty("dom.disable_window_flip") ||
4322 RevisePopupAbuseLevel(gPopupControlState
) < openAbused
;
4324 nsCOMPtr
<nsIDOMWindow
> activeWindow
;
4325 fm
->GetActiveWindow(getter_AddRefs(activeWindow
));
4327 nsCOMPtr
<nsIDocShellTreeItem
> treeItem
= do_QueryInterface(mDocShell
);
4328 NS_ASSERTION(treeItem
, "What happened?");
4329 nsCOMPtr
<nsIDocShellTreeItem
> rootItem
;
4330 treeItem
->GetRootTreeItem(getter_AddRefs(rootItem
));
4331 nsCOMPtr
<nsIDOMWindow
> rootWin
= do_GetInterface(rootItem
);
4332 PRBool isActive
= (rootWin
== activeWindow
);
4334 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
4335 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
4336 if (treeOwnerAsWin
&& (canFocus
|| isActive
)) {
4337 PRBool isEnabled
= PR_TRUE
;
4338 if (NS_SUCCEEDED(treeOwnerAsWin
->GetEnabled(&isEnabled
)) && !isEnabled
) {
4339 NS_WARNING( "Should not try to set the focus on a disabled window" );
4343 // XXXndeakin not sure what this is for or if it should go somewhere else
4344 nsCOMPtr
<nsIEmbeddingSiteWindow
> embeddingWin(do_GetInterface(treeOwnerAsWin
));
4346 embeddingWin
->SetFocus();
4352 nsCOMPtr
<nsIPresShell
> presShell
;
4353 // Don't look for a presshell if we're a root chrome window that's got
4354 // about:blank loaded. We don't want to focus our widget in that case.
4355 // XXXbz should we really be checking for IsInitialDocument() instead?
4356 PRBool lookForPresShell
= PR_TRUE
;
4357 PRInt32 itemType
= nsIDocShellTreeItem::typeContent
;
4358 treeItem
->GetItemType(&itemType
);
4359 if (itemType
== nsIDocShellTreeItem::typeChrome
&&
4360 GetPrivateRoot() == static_cast<nsIDOMWindowInternal
*>(this) &&
4362 nsCOMPtr
<nsIDocument
> doc(do_QueryInterface(mDocument
));
4363 NS_ASSERTION(doc
, "Bogus doc?");
4364 nsIURI
* ourURI
= doc
->GetDocumentURI();
4366 lookForPresShell
= !IsAboutBlank(ourURI
);
4370 if (lookForPresShell
) {
4371 mDocShell
->GetEldestPresShell(getter_AddRefs(presShell
));
4374 nsCOMPtr
<nsIDocShellTreeItem
> parentDsti
;
4375 treeItem
->GetParent(getter_AddRefs(parentDsti
));
4377 // set the parent's current focus to the frame containing this window.
4378 nsCOMPtr
<nsIDOMWindow
> parent(do_GetInterface(parentDsti
));
4380 nsCOMPtr
<nsIDOMDocument
> parentdomdoc
;
4381 parent
->GetDocument(getter_AddRefs(parentdomdoc
));
4383 nsCOMPtr
<nsIDocument
> parentdoc
= do_QueryInterface(parentdomdoc
);
4387 nsCOMPtr
<nsIDocument
> doc
= do_QueryInterface(mDocument
);
4388 nsIContent
* frame
= parentdoc
->FindContentForSubDocument(doc
);
4389 nsCOMPtr
<nsIDOMElement
> frameElement
= do_QueryInterface(frame
);
4391 PRUint32 flags
= nsIFocusManager::FLAG_NOSCROLL
;
4393 flags
|= nsIFocusManager::FLAG_RAISE
;
4394 return fm
->SetFocus(frameElement
, flags
);
4397 else if (canFocus
) {
4398 // if there is no parent, this must be a toplevel window, so raise the
4399 // window if canFocus is true
4400 return fm
->SetActiveWindow(this);
4407 nsGlobalWindow::Blur()
4409 FORWARD_TO_OUTER(Blur
, (), NS_ERROR_NOT_INITIALIZED
);
4411 // If embedding apps don't implement nsIEmbeddingSiteWindow2, we
4412 // shouldn't throw exceptions to web content.
4413 nsresult rv
= NS_OK
;
4415 nsCOMPtr
<nsIDocShellTreeOwner
> treeOwner
;
4416 GetTreeOwner(getter_AddRefs(treeOwner
));
4417 nsCOMPtr
<nsIEmbeddingSiteWindow2
> siteWindow(do_GetInterface(treeOwner
));
4419 // This method call may cause mDocShell to become nsnull.
4420 rv
= siteWindow
->Blur();
4422 // if the root is focused, clear the focus
4423 nsIFocusManager
* fm
= nsFocusManager::GetFocusManager();
4424 nsCOMPtr
<nsIDocument
> doc
= do_QueryInterface(mDocument
);
4425 if (fm
&& mDocument
) {
4426 nsCOMPtr
<nsIDOMElement
> element
;
4427 fm
->GetFocusedElementForWindow(this, PR_FALSE
, nsnull
, getter_AddRefs(element
));
4428 nsCOMPtr
<nsIContent
> content
= do_QueryInterface(element
);
4429 if (content
== doc
->GetRootElement())
4430 fm
->ClearFocus(this);
4438 nsGlobalWindow::Back()
4440 FORWARD_TO_OUTER(Back
, (), NS_ERROR_NOT_INITIALIZED
);
4442 nsCOMPtr
<nsIWebNavigation
> webNav(do_QueryInterface(mDocShell
));
4443 NS_ENSURE_TRUE(webNav
, NS_ERROR_FAILURE
);
4445 return webNav
->GoBack();
4449 nsGlobalWindow::Forward()
4451 FORWARD_TO_OUTER(Forward
, (), NS_ERROR_NOT_INITIALIZED
);
4453 nsCOMPtr
<nsIWebNavigation
> webNav(do_QueryInterface(mDocShell
));
4454 NS_ENSURE_TRUE(webNav
, NS_ERROR_FAILURE
);
4456 return webNav
->GoForward();
4460 nsGlobalWindow::Home()
4462 FORWARD_TO_OUTER(Home
, (), NS_ERROR_NOT_INITIALIZED
);
4467 nsAdoptingString homeURL
=
4468 nsContentUtils::GetLocalizedStringPref(PREF_BROWSER_STARTUP_HOMEPAGE
);
4470 if (homeURL
.IsEmpty()) {
4471 // if all else fails, use this
4473 printf("all else failed. using %s as the home page\n", DEFAULT_HOME_PAGE
);
4475 CopyASCIItoUTF16(DEFAULT_HOME_PAGE
, homeURL
);
4480 // Firefox lets the user specify multiple home pages to open in
4481 // individual tabs by separating them with '|'. Since we don't
4482 // have the machinery in place to easily open new tabs from here,
4483 // simply truncate the homeURL at the first '|' character to
4484 // prevent any possibilities of leaking the users list of home
4485 // pages to the first home page.
4487 // Once bug https://bugzilla.mozilla.org/show_bug.cgi?id=221445 is
4488 // fixed we can revisit this.
4489 PRInt32 firstPipe
= homeURL
.FindChar('|');
4491 if (firstPipe
> 0) {
4492 homeURL
.Truncate(firstPipe
);
4498 nsCOMPtr
<nsIWebNavigation
> webNav(do_QueryInterface(mDocShell
));
4499 NS_ENSURE_TRUE(webNav
, NS_ERROR_FAILURE
);
4500 rv
= webNav
->LoadURI(homeURL
.get(),
4501 nsIWebNavigation::LOAD_FLAGS_NONE
,
4505 NS_ENSURE_SUCCESS(rv
, NS_ERROR_FAILURE
);
4510 nsGlobalWindow::Stop()
4512 FORWARD_TO_OUTER(Stop
, (), NS_ERROR_NOT_INITIALIZED
);
4514 nsCOMPtr
<nsIWebNavigation
> webNav(do_QueryInterface(mDocShell
));
4518 return webNav
->Stop(nsIWebNavigation::STOP_ALL
);
4522 nsGlobalWindow::Print()
4525 FORWARD_TO_OUTER(Print
, (), NS_ERROR_NOT_INITIALIZED
);
4527 nsCOMPtr
<nsIWebBrowserPrint
> webBrowserPrint
;
4528 if (NS_SUCCEEDED(GetInterface(NS_GET_IID(nsIWebBrowserPrint
),
4529 getter_AddRefs(webBrowserPrint
)))) {
4531 nsCOMPtr
<nsIPrintSettingsService
> printSettingsService
=
4532 do_GetService("@mozilla.org/gfx/printsettings-service;1");
4534 nsCOMPtr
<nsIPrintSettings
> printSettings
;
4535 if (printSettingsService
) {
4536 PRBool printSettingsAreGlobal
=
4537 nsContentUtils::GetBoolPref("print.use_global_printsettings", PR_FALSE
);
4539 if (printSettingsAreGlobal
) {
4540 printSettingsService
->GetGlobalPrintSettings(getter_AddRefs(printSettings
));
4542 nsXPIDLString printerName
;
4543 printSettings
->GetPrinterName(getter_Copies(printerName
));
4544 if (printerName
.IsEmpty()) {
4545 printSettingsService
->GetDefaultPrinterName(getter_Copies(printerName
));
4546 printSettings
->SetPrinterName(printerName
);
4548 printSettingsService
->InitPrintSettingsFromPrinter(printerName
, printSettings
);
4549 printSettingsService
->InitPrintSettingsFromPrefs(printSettings
,
4551 nsIPrintSettings::kInitSaveAll
);
4553 printSettingsService
->GetNewPrintSettings(getter_AddRefs(printSettings
));
4557 webBrowserPrint
->Print(printSettings
, nsnull
);
4560 PRBool savePrintSettings
=
4561 nsContentUtils::GetBoolPref("print.save_print_settings", PR_FALSE
);
4562 if (printSettingsAreGlobal
&& savePrintSettings
) {
4563 printSettingsService
->
4564 SavePrintSettingsToPrefs(printSettings
,
4566 nsIPrintSettings::kInitSaveAll
);
4567 printSettingsService
->
4568 SavePrintSettingsToPrefs(printSettings
,
4570 nsIPrintSettings::kInitSavePrinterName
);
4573 webBrowserPrint
->GetGlobalPrintSettings(getter_AddRefs(printSettings
));
4574 webBrowserPrint
->Print(printSettings
, nsnull
);
4577 #endif //NS_PRINTING
4583 nsGlobalWindow::MoveTo(PRInt32 aXPos
, PRInt32 aYPos
)
4585 FORWARD_TO_OUTER(MoveTo
, (aXPos
, aYPos
), NS_ERROR_NOT_INITIALIZED
);
4588 * If caller is not chrome and the user has not explicitly exempted the site,
4589 * prevent window.moveTo() by exiting early
4592 if (!CanMoveResizeWindows() || IsFrame()) {
4596 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
4597 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
4598 NS_ENSURE_TRUE(treeOwnerAsWin
, NS_ERROR_FAILURE
);
4600 NS_ENSURE_SUCCESS(CheckSecurityLeftAndTop(&aXPos
, &aYPos
),
4603 // mild abuse of a "size" object so we don't need more helper functions
4604 nsIntSize
devPos(CSSToDevIntPixels(nsIntSize(aXPos
, aYPos
)));
4606 NS_ENSURE_SUCCESS(treeOwnerAsWin
->SetPosition(devPos
.width
, devPos
.height
),
4613 nsGlobalWindow::MoveBy(PRInt32 aXDif
, PRInt32 aYDif
)
4615 FORWARD_TO_OUTER(MoveBy
, (aXDif
, aYDif
), NS_ERROR_NOT_INITIALIZED
);
4618 * If caller is not chrome and the user has not explicitly exempted the site,
4619 * prevent window.moveBy() by exiting early
4622 if (!CanMoveResizeWindows() || IsFrame()) {
4626 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
4627 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
4628 NS_ENSURE_TRUE(treeOwnerAsWin
, NS_ERROR_FAILURE
);
4630 // To do this correctly we have to convert what we get from GetPosition
4631 // into CSS pixels, add the arguments, do the security check, and
4632 // then convert back to device pixels for the call to SetPosition.
4635 NS_ENSURE_SUCCESS(treeOwnerAsWin
->GetPosition(&x
, &y
), NS_ERROR_FAILURE
);
4637 // mild abuse of a "size" object so we don't need more helper functions
4638 nsIntSize
cssPos(DevToCSSIntPixels(nsIntSize(x
, y
)));
4640 cssPos
.width
+= aXDif
;
4641 cssPos
.height
+= aYDif
;
4643 NS_ENSURE_SUCCESS(CheckSecurityLeftAndTop(&cssPos
.width
,
4647 nsIntSize
newDevPos(CSSToDevIntPixels(cssPos
));
4649 NS_ENSURE_SUCCESS(treeOwnerAsWin
->SetPosition(newDevPos
.width
,
4657 nsGlobalWindow::ResizeTo(PRInt32 aWidth
, PRInt32 aHeight
)
4659 FORWARD_TO_OUTER(ResizeTo
, (aWidth
, aHeight
), NS_ERROR_NOT_INITIALIZED
);
4662 * If caller is not chrome and the user has not explicitly exempted the site,
4663 * prevent window.resizeTo() by exiting early
4666 if (!CanMoveResizeWindows() || IsFrame()) {
4670 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
4671 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
4672 NS_ENSURE_TRUE(treeOwnerAsWin
, NS_ERROR_FAILURE
);
4674 NS_ENSURE_SUCCESS(CheckSecurityWidthAndHeight(&aWidth
, &aHeight
),
4677 nsIntSize
devSz(CSSToDevIntPixels(nsIntSize(aWidth
, aHeight
)));
4679 NS_ENSURE_SUCCESS(treeOwnerAsWin
->SetSize(devSz
.width
, devSz
.height
, PR_TRUE
),
4686 nsGlobalWindow::ResizeBy(PRInt32 aWidthDif
, PRInt32 aHeightDif
)
4688 FORWARD_TO_OUTER(ResizeBy
, (aWidthDif
, aHeightDif
), NS_ERROR_NOT_INITIALIZED
);
4691 * If caller is not chrome and the user has not explicitly exempted the site,
4692 * prevent window.resizeBy() by exiting early
4695 if (!CanMoveResizeWindows() || IsFrame()) {
4699 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
4700 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
4701 NS_ENSURE_TRUE(treeOwnerAsWin
, NS_ERROR_FAILURE
);
4703 PRInt32 width
, height
;
4704 NS_ENSURE_SUCCESS(treeOwnerAsWin
->GetSize(&width
, &height
), NS_ERROR_FAILURE
);
4706 // To do this correctly we have to convert what we got from GetSize
4707 // into CSS pixels, add the arguments, do the security check, and
4708 // then convert back to device pixels for the call to SetSize.
4710 nsIntSize
cssSize(DevToCSSIntPixels(nsIntSize(width
, height
)));
4712 cssSize
.width
+= aWidthDif
;
4713 cssSize
.height
+= aHeightDif
;
4715 NS_ENSURE_SUCCESS(CheckSecurityWidthAndHeight(&cssSize
.width
,
4719 nsIntSize
newDevSize(CSSToDevIntPixels(cssSize
));
4721 NS_ENSURE_SUCCESS(treeOwnerAsWin
->SetSize(newDevSize
.width
,
4730 nsGlobalWindow::SizeToContent()
4732 FORWARD_TO_OUTER(SizeToContent
, (), NS_ERROR_NOT_INITIALIZED
);
4739 * If caller is not chrome and the user has not explicitly exempted the site,
4740 * prevent window.sizeToContent() by exiting early
4743 if (!CanMoveResizeWindows() || IsFrame()) {
4747 // The content viewer does a check to make sure that it's a content
4748 // viewer for a toplevel docshell.
4750 nsCOMPtr
<nsIContentViewer
> cv
;
4751 mDocShell
->GetContentViewer(getter_AddRefs(cv
));
4752 nsCOMPtr
<nsIMarkupDocumentViewer
> markupViewer(do_QueryInterface(cv
));
4753 NS_ENSURE_TRUE(markupViewer
, NS_ERROR_FAILURE
);
4754 NS_ENSURE_SUCCESS(markupViewer
->SizeToContent(), NS_ERROR_FAILURE
);
4760 nsGlobalWindow::GetWindowRoot(nsIDOMEventTarget
**aWindowRoot
)
4762 nsCOMPtr
<nsPIWindowRoot
> root
= GetTopWindowRoot();
4763 return CallQueryInterface(root
, aWindowRoot
);
4766 already_AddRefed
<nsPIWindowRoot
>
4767 nsGlobalWindow::GetTopWindowRoot()
4769 nsIDOMWindowInternal
*rootWindow
= GetPrivateRoot();
4770 nsCOMPtr
<nsPIDOMWindow
> piWin(do_QueryInterface(rootWindow
));
4774 nsCOMPtr
<nsPIWindowRoot
> window
= do_QueryInterface(piWin
->GetChromeEventHandler());
4775 return window
.forget();
4779 nsGlobalWindow::Scroll(PRInt32 aXScroll
, PRInt32 aYScroll
)
4781 return ScrollTo(aXScroll
, aYScroll
);
4785 nsGlobalWindow::ScrollTo(PRInt32 aXScroll
, PRInt32 aYScroll
)
4787 FlushPendingNotifications(Flush_Layout
);
4788 nsIScrollableFrame
*sf
= GetScrollFrame();
4791 // Here we calculate what the max pixel value is that we can
4792 // scroll to, we do this by dividing maxint with the pixel to
4793 // twips conversion factor, and substracting 4, the 4 comes from
4794 // experimenting with this value, anything less makes the view
4795 // code not scroll correctly, I have no idea why. -- jst
4796 const PRInt32 maxpx
= nsPresContext::AppUnitsToIntCSSPixels(0x7fffffff) - 4;
4798 if (aXScroll
> maxpx
) {
4802 if (aYScroll
> maxpx
) {
4805 sf
->ScrollTo(nsPoint(nsPresContext::CSSPixelsToAppUnits(aXScroll
),
4806 nsPresContext::CSSPixelsToAppUnits(aYScroll
)),
4807 nsIScrollableFrame::INSTANT
);
4814 nsGlobalWindow::ScrollBy(PRInt32 aXScrollDif
, PRInt32 aYScrollDif
)
4816 FlushPendingNotifications(Flush_Layout
);
4817 nsIScrollableFrame
*sf
= GetScrollFrame();
4820 nsPoint scrollPos
= sf
->GetScrollPosition();
4821 // It seems like it would make more sense for ScrollBy to use
4822 // SMOOTH mode, but tests seem to depend on the synchronous behaviour.
4823 // Perhaps Web content does too.
4824 return ScrollTo(nsPresContext::AppUnitsToIntCSSPixels(scrollPos
.x
) + aXScrollDif
,
4825 nsPresContext::AppUnitsToIntCSSPixels(scrollPos
.y
) + aYScrollDif
);
4832 nsGlobalWindow::ScrollByLines(PRInt32 numLines
)
4834 FlushPendingNotifications(Flush_Layout
);
4835 nsIScrollableFrame
*sf
= GetScrollFrame();
4837 // It seems like it would make more sense for ScrollByLines to use
4838 // SMOOTH mode, but tests seem to depend on the synchronous behaviour.
4839 // Perhaps Web content does too.
4840 sf
->ScrollBy(nsIntPoint(0, numLines
), nsIScrollableFrame::LINES
,
4841 nsIScrollableFrame::INSTANT
);
4848 nsGlobalWindow::ScrollByPages(PRInt32 numPages
)
4850 FlushPendingNotifications(Flush_Layout
);
4851 nsIScrollableFrame
*sf
= GetScrollFrame();
4853 // It seems like it would make more sense for ScrollByPages to use
4854 // SMOOTH mode, but tests seem to depend on the synchronous behaviour.
4855 // Perhaps Web content does too.
4856 sf
->ScrollBy(nsIntPoint(0, numPages
), nsIScrollableFrame::PAGES
,
4857 nsIScrollableFrame::INSTANT
);
4864 nsGlobalWindow::ClearTimeout()
4866 return ClearTimeoutOrInterval();
4870 nsGlobalWindow::ClearInterval()
4872 return ClearTimeoutOrInterval();
4876 nsGlobalWindow::SetTimeout(PRInt32
*_retval
)
4878 return SetTimeoutOrInterval(PR_FALSE
, _retval
);
4882 nsGlobalWindow::SetInterval(PRInt32
*_retval
)
4884 return SetTimeoutOrInterval(PR_TRUE
, _retval
);
4888 nsGlobalWindow::SetResizable(PRBool aResizable
)
4896 ReportUseOfDeprecatedMethod(nsGlobalWindow
* aWindow
, const char* aWarning
)
4898 nsCOMPtr
<nsIDocument
> doc
= do_QueryInterface(aWindow
->GetExtantDocument());
4899 nsContentUtils::ReportToConsole(nsContentUtils::eDOM_PROPERTIES
,
4902 doc
? doc
->GetDocumentURI() : nsnull
,
4903 EmptyString(), 0, 0,
4904 nsIScriptError::warningFlag
,
4909 nsGlobalWindow::CaptureEvents(PRInt32 aEventFlags
)
4911 ReportUseOfDeprecatedMethod(this, "UseOfCaptureEventsWarning");
4916 nsGlobalWindow::ReleaseEvents(PRInt32 aEventFlags
)
4918 ReportUseOfDeprecatedMethod(this, "UseOfReleaseEventsWarning");
4923 nsGlobalWindow::RouteEvent(nsIDOMEvent
* aEvt
)
4925 ReportUseOfDeprecatedMethod(this, "UseOfRouteEventWarning");
4930 nsGlobalWindow::EnableExternalCapture()
4932 return NS_ERROR_FAILURE
;
4936 nsGlobalWindow::DisableExternalCapture()
4938 return NS_ERROR_FAILURE
;
4942 PRBool
IsPopupBlocked(nsIDOMDocument
* aDoc
)
4944 nsCOMPtr
<nsIPopupWindowManager
> pm
=
4945 do_GetService(NS_POPUPWINDOWMANAGER_CONTRACTID
);
4951 PRBool blocked
= PR_TRUE
;
4952 nsCOMPtr
<nsIDocument
> doc(do_QueryInterface(aDoc
));
4955 PRUint32 permission
= nsIPopupWindowManager::ALLOW_POPUP
;
4956 pm
->TestPermission(doc
->GetDocumentURI(), &permission
);
4957 blocked
= (permission
== nsIPopupWindowManager::DENY_POPUP
);
4963 void FirePopupBlockedEvent(nsIDOMDocument
* aDoc
,
4964 nsIDOMWindow
*aRequestingWindow
, nsIURI
*aPopupURI
,
4965 const nsAString
&aPopupWindowName
,
4966 const nsAString
&aPopupWindowFeatures
)
4969 // Fire a "DOMPopupBlocked" event so that the UI can hear about
4971 nsCOMPtr
<nsIDOMDocumentEvent
> docEvent(do_QueryInterface(aDoc
));
4972 nsCOMPtr
<nsIDOMEvent
> event
;
4973 docEvent
->CreateEvent(NS_LITERAL_STRING("PopupBlockedEvents"),
4974 getter_AddRefs(event
));
4976 nsCOMPtr
<nsIDOMPopupBlockedEvent
> pbev(do_QueryInterface(event
));
4977 pbev
->InitPopupBlockedEvent(NS_LITERAL_STRING("DOMPopupBlocked"),
4978 PR_TRUE
, PR_TRUE
, aRequestingWindow
,
4979 aPopupURI
, aPopupWindowName
,
4980 aPopupWindowFeatures
);
4981 nsCOMPtr
<nsIPrivateDOMEvent
> privateEvent(do_QueryInterface(event
));
4982 privateEvent
->SetTrusted(PR_TRUE
);
4984 nsCOMPtr
<nsIDOMEventTarget
> targ(do_QueryInterface(aDoc
));
4985 PRBool defaultActionEnabled
;
4986 targ
->DispatchEvent(event
, &defaultActionEnabled
);
4991 void FirePopupWindowEvent(nsIDOMDocument
* aDoc
)
4993 // Fire a "PopupWindow" event
4994 nsCOMPtr
<nsIDocument
> doc(do_QueryInterface(aDoc
));
4995 nsContentUtils::DispatchTrustedEvent(doc
, aDoc
,
4996 NS_LITERAL_STRING("PopupWindow"),
5002 nsGlobalWindow::CanSetProperty(const char *aPrefName
)
5004 // Chrome can set any property.
5005 if (nsContentUtils::IsCallerTrustedForWrite()) {
5009 // If the pref is set to true, we can not set the property
5011 return !nsContentUtils::GetBoolPref(aPrefName
, PR_TRUE
);
5015 nsGlobalWindow::PopupWhitelisted()
5017 if (!IsPopupBlocked(mDocument
))
5020 nsCOMPtr
<nsIDOMWindow
> parent
;
5022 if (NS_FAILED(GetParent(getter_AddRefs(parent
))) ||
5023 parent
== static_cast<nsIDOMWindow
*>(this))
5028 return static_cast<nsGlobalWindow
*>
5029 (static_cast<nsIDOMWindow
*>
5030 (parent
.get()))->PopupWhitelisted();
5034 * Examine the current document state to see if we're in a way that is
5035 * typically abused by web designers. The window.open code uses this
5036 * routine to determine whether to allow the new window.
5037 * Returns a value from the PopupControlState enum.
5040 nsGlobalWindow::RevisePopupAbuseLevel(PopupControlState aControl
)
5042 FORWARD_TO_OUTER(RevisePopupAbuseLevel
, (aControl
), aControl
);
5044 NS_ASSERTION(mDocShell
, "Must have docshell");
5046 nsCOMPtr
<nsIDocShellTreeItem
> item(do_QueryInterface(mDocShell
));
5048 NS_ASSERTION(item
, "Docshell doesn't implement nsIDocShellTreeItem?");
5050 PRInt32 type
= nsIDocShellTreeItem::typeChrome
;
5051 item
->GetItemType(&type
);
5052 if (type
!= nsIDocShellTreeItem::typeContent
)
5055 PopupControlState abuse
= aControl
;
5057 case openControlled
:
5059 case openOverridden
:
5060 if (PopupWhitelisted())
5061 abuse
= PopupControlState(abuse
- 1);
5062 case openAllowed
: break;
5064 NS_WARNING("Strange PopupControlState!");
5067 // limit the number of simultaneously open popups
5068 if (abuse
== openAbused
|| abuse
== openControlled
) {
5069 PRInt32 popupMax
= nsContentUtils::GetIntPref("dom.popup_maximum", -1);
5070 if (popupMax
>= 0 && gOpenPopupSpamCount
>= popupMax
)
5071 abuse
= openOverridden
;
5077 /* If a window open is blocked, fire the appropriate DOM events.
5078 aBlocked signifies we just blocked a popup.
5079 aWindow signifies we just opened what is probably a popup.
5082 nsGlobalWindow::FireAbuseEvents(PRBool aBlocked
, PRBool aWindow
,
5083 const nsAString
&aPopupURL
,
5084 const nsAString
&aPopupWindowName
,
5085 const nsAString
&aPopupWindowFeatures
)
5087 // fetch the URI of the window requesting the opened window
5089 nsCOMPtr
<nsIDOMWindow
> topWindow
;
5090 GetTop(getter_AddRefs(topWindow
));
5094 nsCOMPtr
<nsIDOMDocument
> topDoc
;
5095 topWindow
->GetDocument(getter_AddRefs(topDoc
));
5097 nsCOMPtr
<nsIURI
> popupURI
;
5099 // build the URI of the would-have-been popup window
5100 // (see nsWindowWatcher::URIfromURL)
5102 // first, fetch the opener's base URI
5104 nsIURI
*baseURL
= 0;
5106 JSContext
*cx
= nsContentUtils::GetCurrentJSContext();
5107 nsCOMPtr
<nsIDOMWindow
> contextWindow
;
5110 nsIScriptContext
*currentCX
= nsJSUtils::GetDynamicScriptContext(cx
);
5112 contextWindow
= do_QueryInterface(currentCX
->GetGlobalObject());
5116 contextWindow
= static_cast<nsIDOMWindow
*>(this);
5118 nsCOMPtr
<nsIDOMDocument
> domdoc
;
5119 contextWindow
->GetDocument(getter_AddRefs(domdoc
));
5120 nsCOMPtr
<nsIDocument
> doc(do_QueryInterface(domdoc
));
5122 baseURL
= doc
->GetDocBaseURI();
5124 // use the base URI to build what would have been the popup's URI
5125 nsCOMPtr
<nsIIOService
> ios(do_GetService(NS_IOSERVICE_CONTRACTID
));
5127 ios
->NewURI(NS_ConvertUTF16toUTF8(aPopupURL
), 0, baseURL
,
5128 getter_AddRefs(popupURI
));
5130 // fire an event chock full of informative URIs
5132 FirePopupBlockedEvent(topDoc
, this, popupURI
, aPopupWindowName
,
5133 aPopupWindowFeatures
);
5135 FirePopupWindowEvent(topDoc
);
5139 nsGlobalWindow::Open(const nsAString
& aUrl
, const nsAString
& aName
,
5140 const nsAString
& aOptions
, nsIDOMWindow
**_retval
)
5142 return OpenInternal(aUrl
, aName
, aOptions
,
5143 PR_FALSE
, // aDialog
5144 PR_FALSE
, // aContentModal
5145 PR_TRUE
, // aCalledNoScript
5146 PR_FALSE
, // aDoJSFixups
5147 nsnull
, nsnull
, // No args
5148 GetPrincipal(), // aCalleePrincipal
5149 nsnull
, // aJSCallerContext
5154 nsGlobalWindow::OpenJS(const nsAString
& aUrl
, const nsAString
& aName
,
5155 const nsAString
& aOptions
, nsIDOMWindow
**_retval
)
5157 return OpenInternal(aUrl
, aName
, aOptions
,
5158 PR_FALSE
, // aDialog
5159 PR_FALSE
, // aContentModal
5160 PR_FALSE
, // aCalledNoScript
5161 PR_TRUE
, // aDoJSFixups
5162 nsnull
, nsnull
, // No args
5163 GetPrincipal(), // aCalleePrincipal
5164 nsContentUtils::GetCurrentJSContext(), // aJSCallerContext
5168 // like Open, but attaches to the new window any extra parameters past
5169 // [features] as a JS property named "arguments"
5171 nsGlobalWindow::OpenDialog(const nsAString
& aUrl
, const nsAString
& aName
,
5172 const nsAString
& aOptions
,
5173 nsISupports
* aExtraArgument
, nsIDOMWindow
** _retval
)
5175 return OpenInternal(aUrl
, aName
, aOptions
,
5177 PR_FALSE
, // aContentModal
5178 PR_TRUE
, // aCalledNoScript
5179 PR_FALSE
, // aDoJSFixups
5180 nsnull
, aExtraArgument
, // Arguments
5181 GetPrincipal(), // aCalleePrincipal
5182 nsnull
, // aJSCallerContext
5187 nsGlobalWindow::OpenDialog(const nsAString
& aUrl
, const nsAString
& aName
,
5188 const nsAString
& aOptions
, nsIDOMWindow
** _retval
)
5190 if (!nsContentUtils::IsCallerTrustedForWrite()) {
5191 return NS_ERROR_DOM_SECURITY_ERR
;
5194 nsAXPCNativeCallContext
*ncc
= nsnull
;
5195 nsresult rv
= nsContentUtils::XPConnect()->
5196 GetCurrentNativeCallContext(&ncc
);
5197 NS_ENSURE_SUCCESS(rv
, rv
);
5200 return NS_ERROR_NOT_AVAILABLE
;
5202 JSContext
*cx
= nsnull
;
5204 rv
= ncc
->GetJSContext(&cx
);
5205 NS_ENSURE_SUCCESS(rv
, rv
);
5208 jsval
*argv
= nsnull
;
5210 // XXX - need to get this as nsISupports?
5211 ncc
->GetArgc(&argc
);
5212 ncc
->GetArgvPtr(&argv
);
5214 // Strip the url, name and options from the args seen by scripts.
5215 PRUint32 argOffset
= argc
< 3 ? argc
: 3;
5216 nsCOMPtr
<nsIArray
> argvArray
;
5217 rv
= NS_CreateJSArgv(cx
, argc
- argOffset
, argv
+ argOffset
,
5218 getter_AddRefs(argvArray
));
5219 NS_ENSURE_SUCCESS(rv
, rv
);
5221 return OpenInternal(aUrl
, aName
, aOptions
,
5223 PR_FALSE
, // aContentModal
5224 PR_FALSE
, // aCalledNoScript
5225 PR_FALSE
, // aDoJSFixups
5226 argvArray
, nsnull
, // Arguments
5227 GetPrincipal(), // aCalleePrincipal
5228 cx
, // aJSCallerContext
5233 nsGlobalWindow::GetFrames(nsIDOMWindow
** aFrames
)
5235 FORWARD_TO_OUTER(GetFrames
, (aFrames
), NS_ERROR_NOT_INITIALIZED
);
5238 NS_ADDREF(*aFrames
);
5240 FlushPendingNotifications(Flush_ContentAndNotify
);
5246 nsGlobalWindow::CallerInnerWindow()
5248 JSContext
*cx
= nsContentUtils::GetCurrentJSContext();
5250 NS_ERROR("Please don't call this method from C++!");
5255 JSObject
*scope
= ::JS_GetScopeChain(cx
);
5259 nsCOMPtr
<nsIXPConnectWrappedNative
> wrapper
;
5260 nsContentUtils::XPConnect()->
5261 GetWrappedNativeOfJSObject(cx
, ::JS_GetGlobalForObject(cx
, scope
),
5262 getter_AddRefs(wrapper
));
5266 // The calling window must be holding a reference, so we can just return a
5267 // raw pointer here and let the QI's addref be balanced by the nsCOMPtr
5268 // destructor's release.
5269 nsCOMPtr
<nsPIDOMWindow
> win
= do_QueryWrappedNative(wrapper
);
5271 return GetCurrentInnerWindowInternal();
5272 return static_cast<nsGlobalWindow
*>(win
.get());
5277 * Class used to represent events generated by calls to Window.postMessage,
5278 * which asynchronously creates and dispatches events.
5280 class PostMessageEvent
: public nsRunnable
5285 PostMessageEvent(nsGlobalWindow
* aSource
,
5286 const nsAString
& aCallerOrigin
,
5287 const nsAString
& aMessage
,
5288 nsGlobalWindow
* aTargetWindow
,
5289 nsIURI
* aProvidedOrigin
,
5290 PRBool aTrustedCaller
)
5292 mCallerOrigin(aCallerOrigin
),
5294 mTargetWindow(aTargetWindow
),
5295 mProvidedOrigin(aProvidedOrigin
),
5296 mTrustedCaller(aTrustedCaller
)
5298 MOZ_COUNT_CTOR(PostMessageEvent
);
5303 MOZ_COUNT_DTOR(PostMessageEvent
);
5307 nsRefPtr
<nsGlobalWindow
> mSource
;
5308 nsString mCallerOrigin
;
5310 nsRefPtr
<nsGlobalWindow
> mTargetWindow
;
5311 nsCOMPtr
<nsIURI
> mProvidedOrigin
;
5312 PRBool mTrustedCaller
;
5316 PostMessageEvent::Run()
5318 NS_ABORT_IF_FALSE(mTargetWindow
->IsOuterWindow(),
5319 "should have been passed an outer window!");
5320 NS_ABORT_IF_FALSE(!mSource
|| mSource
->IsOuterWindow(),
5321 "should have been passed an outer window!");
5323 nsRefPtr
<nsGlobalWindow
> targetWindow
;
5324 if (mTargetWindow
->IsClosedOrClosing() ||
5325 !(targetWindow
= mTargetWindow
->GetCurrentInnerWindowInternal()) ||
5326 targetWindow
->IsClosedOrClosing())
5329 NS_ABORT_IF_FALSE(targetWindow
->IsInnerWindow(),
5330 "we ordered an inner window!");
5332 // Ensure that any origin which might have been provided is the origin of this
5333 // window's document. Note that we do this *now* instead of when postMessage
5334 // is called because the target window might have been navigated to a
5335 // different location between then and now. If this check happened when
5336 // postMessage was called, it would be fairly easy for a malicious webpage to
5337 // intercept messages intended for another site by carefully timing navigation
5338 // of the target window so it changed location after postMessage but before
5340 if (mProvidedOrigin
) {
5341 // Get the target's origin either from its principal or, in the case the
5342 // principal doesn't carry a URI (e.g. the system principal), the target's
5344 nsIPrincipal
* targetPrin
= targetWindow
->GetPrincipal();
5347 nsCOMPtr
<nsIURI
> targetURI
;
5348 if (NS_FAILED(targetPrin
->GetURI(getter_AddRefs(targetURI
))))
5351 targetURI
= targetWindow
->mDoc
->GetDocumentURI();
5356 // Note: This is contrary to the spec with respect to file: URLs, which
5357 // the spec groups into a single origin, but given we intentionally
5358 // don't do that in other places it seems better to hold the line for
5359 // now. Long-term, we want HTML5 to address this so that we can
5360 // be compliant while being safer.
5361 nsIScriptSecurityManager
* ssm
= nsContentUtils::GetSecurityManager();
5363 ssm
->CheckSameOriginURI(mProvidedOrigin
, targetURI
, PR_TRUE
);
5370 nsCOMPtr
<nsIDOMDocumentEvent
> docEvent
=
5371 do_QueryInterface(targetWindow
->mDocument
);
5374 nsCOMPtr
<nsIDOMEvent
> event
;
5375 docEvent
->CreateEvent(NS_LITERAL_STRING("MessageEvent"),
5376 getter_AddRefs(event
));
5380 nsCOMPtr
<nsIDOMMessageEvent
> message
= do_QueryInterface(event
);
5381 nsresult rv
= message
->InitMessageEvent(NS_LITERAL_STRING("message"),
5382 PR_FALSE
/* non-bubbling */,
5383 PR_TRUE
/* cancelable */,
5392 // We can't simply call dispatchEvent on the window because doing so ends
5393 // up flipping the trusted bit on the event, and we don't want that to
5394 // happen because then untrusted content can call postMessage on a chrome
5395 // window if it can get a reference to it.
5397 nsIPresShell
*shell
= targetWindow
->mDoc
->GetShell();
5398 nsRefPtr
<nsPresContext
> presContext
;
5400 presContext
= shell
->GetPresContext();
5402 nsCOMPtr
<nsIPrivateDOMEvent
> privEvent
= do_QueryInterface(message
);
5403 privEvent
->SetTrusted(mTrustedCaller
);
5404 nsEvent
*internalEvent
= privEvent
->GetInternalNSEvent();
5406 nsEventStatus status
= nsEventStatus_eIgnore
;
5407 nsEventDispatcher::Dispatch(static_cast<nsPIDOMWindow
*>(mTargetWindow
),
5416 nsGlobalWindow::PostMessageMoz(const nsAString
& aMessage
, const nsAString
& aOrigin
)
5418 // NB: Since much of what this method does must happen at event dispatch time,
5419 // this method does not forward to the inner window, unlike most other
5420 // methods. We do this because the only time we need to refer to this
5421 // window, we need a reference to the outer window (the PostMessageEvent
5422 // ctor call), and we don't want to pay the price of forwarding to the
5423 // inner window for no actual benefit. Furthermore, this function must
5424 // only be called from script anyway, which should only have references to
5425 // outer windows (and if script has an inner window we've already lost).
5426 NS_ABORT_IF_FALSE(IsOuterWindow(), "only call this method on outer windows");
5429 // Window.postMessage is an intentional subversion of the same-origin policy.
5430 // As such, this code must be particularly careful in the information it
5431 // exposes to calling code.
5433 // http://www.whatwg.org/specs/web-apps/current-work/multipage/section-crossDocumentMessages.html
5436 // First, get the caller's window
5437 nsRefPtr
<nsGlobalWindow
> callerInnerWin
= CallerInnerWindow();
5438 if (!callerInnerWin
)
5440 NS_ABORT_IF_FALSE(callerInnerWin
->IsInnerWindow(),
5441 "should have gotten an inner window here");
5443 // Compute the caller's origin either from its principal or, in the case the
5444 // principal doesn't carry a URI (e.g. the system principal), the caller's
5445 // document. We must get this now instead of when the event is created and
5446 // dispatched, because ultimately it is the identity of the calling window
5447 // *now* that determines who sent the message (and not an identity which might
5448 // have changed due to intervening navigations).
5449 nsIPrincipal
* callerPrin
= callerInnerWin
->GetPrincipal();
5453 nsCOMPtr
<nsIURI
> callerOuterURI
;
5454 if (NS_FAILED(callerPrin
->GetURI(getter_AddRefs(callerOuterURI
))))
5457 nsAutoString origin
;
5458 if (callerOuterURI
) {
5459 // if the principal has a URI, use that to generate the origin
5460 nsContentUtils::GetUTFOrigin(callerPrin
, origin
);
5463 // otherwise use the URI of the document to generate origin
5464 nsCOMPtr
<nsIDocument
> doc
= do_QueryInterface(callerInnerWin
->mDocument
);
5467 callerOuterURI
= doc
->GetDocumentURI();
5468 // if the principal has a URI, use that to generate the origin
5469 nsContentUtils::GetUTFOrigin(callerOuterURI
, origin
);
5472 // Convert the provided origin string into a URI for comparison purposes.
5473 // "*" indicates no specific origin is required.
5474 nsCOMPtr
<nsIURI
> providedOrigin
;
5475 if (!aOrigin
.EqualsASCII("*")) {
5476 if (NS_FAILED(NS_NewURI(getter_AddRefs(providedOrigin
), aOrigin
)))
5477 return NS_ERROR_DOM_SYNTAX_ERR
;
5478 if (NS_FAILED(providedOrigin
->SetUserPass(EmptyCString())) ||
5479 NS_FAILED(providedOrigin
->SetPath(EmptyCString())))
5483 // Create and asynchronously dispatch a runnable which will handle actual DOM
5484 // event creation and dispatch.
5485 nsRefPtr
<PostMessageEvent
> event
=
5486 new PostMessageEvent(nsContentUtils::IsCallerChrome()
5488 : callerInnerWin
->GetOuterWindowInternal(),
5493 nsContentUtils::IsCallerTrustedForWrite());
5494 return NS_DispatchToCurrentThread(event
);
5497 class nsCloseEvent
: public nsRunnable
{
5499 nsRefPtr
<nsGlobalWindow
> mWindow
;
5501 nsCloseEvent(nsGlobalWindow
*aWindow
)
5508 PostCloseEvent(nsGlobalWindow
* aWindow
) {
5509 nsCOMPtr
<nsIRunnable
> ev
= new nsCloseEvent(aWindow
);
5510 nsresult rv
= NS_DispatchToCurrentThread(ev
);
5511 if (NS_SUCCEEDED(rv
))
5512 aWindow
->MaybeForgiveSpamCount();
5518 mWindow
->ReallyCloseWindow();
5525 nsGlobalWindow::CanClose()
5530 // Ask the content viewer whether the toplevel window can close.
5531 // If the content viewer returns false, it is responsible for calling
5532 // Close() as soon as it is possible for the window to close.
5533 // This allows us to not close the window while printing is happening.
5535 nsCOMPtr
<nsIContentViewer
> cv
;
5536 mDocShell
->GetContentViewer(getter_AddRefs(cv
));
5539 nsresult rv
= cv
->PermitUnload(PR_FALSE
, &canClose
);
5540 if (NS_SUCCEEDED(rv
) && !canClose
)
5543 rv
= cv
->RequestWindowClose(&canClose
);
5544 if (NS_SUCCEEDED(rv
) && !canClose
)
5552 nsGlobalWindow::Close()
5554 FORWARD_TO_OUTER(Close
, (), NS_ERROR_NOT_INITIALIZED
);
5556 if (IsFrame() || !mDocShell
|| IsInModalState()) {
5557 // window.close() is called on a frame in a frameset, on a window
5558 // that's already closed, or on a window for which there's
5559 // currently a modal dialog open. Ignore such calls.
5564 if (mHavePendingClose
) {
5565 // We're going to be closed anyway; do nothing since we don't want
5570 if (mBlockScriptedClosingFlag
)
5572 // A script's popup has been blocked and we don't want
5573 // the window to be closed directly after this event,
5574 // so the user can see that there was a blocked popup.
5578 // Don't allow scripts from content to close windows
5579 // that were not opened by script
5580 if (!mHadOriginalOpener
&& !nsContentUtils::IsCallerTrustedForWrite()) {
5582 nsContentUtils::GetBoolPref("dom.allow_scripts_to_close_windows",
5585 // We're blocking the close operation
5586 // report localized error msg in JS console
5587 nsContentUtils::ReportToConsole(
5588 nsContentUtils::eDOM_PROPERTIES
,
5589 "WindowCloseBlockedWarning",
5590 nsnull
, 0, // No params
5591 nsnull
, // No URI. Not clear which URI we should be using
5593 EmptyString(), 0, 0, // No source, or column/line number
5594 nsIScriptError::warningFlag
,
5595 "DOM Window"); // Better name for the category?
5601 if (!mInClose
&& !mIsClosed
&& !CanClose())
5604 // Fire a DOM event notifying listeners that this window is about to
5605 // be closed. The tab UI code may choose to cancel the default
5606 // action for this event, if so, we won't actually close the window
5607 // (since the tab UI code will close the tab in stead). Sure, this
5608 // could be abused by content code, but do we care? I don't think
5611 PRBool wasInClose
= mInClose
;
5614 if (!DispatchCustomEvent("DOMWindowClose")) {
5615 // Someone chose to prevent the default action for this event, if
5616 // so, let's not close this window after all...
5618 mInClose
= wasInClose
;
5622 return FinalClose();
5626 nsGlobalWindow::ForceClose()
5628 if (IsFrame() || !mDocShell
) {
5629 // This may be a frame in a frameset, or a window that's already closed.
5630 // Ignore such calls.
5635 if (mHavePendingClose
) {
5636 // We're going to be closed anyway; do nothing since we don't want
5643 DispatchCustomEvent("DOMWindowClose");
5645 return FinalClose();
5649 nsGlobalWindow::FinalClose()
5652 // Flag that we were closed.
5653 mIsClosed
= PR_TRUE
;
5655 nsCOMPtr
<nsIJSContextStack
> stack
=
5656 do_GetService(sJSStackContractID
);
5658 JSContext
*cx
= nsnull
;
5665 nsIScriptContext
*currentCX
= nsJSUtils::GetDynamicScriptContext(cx
);
5667 if (currentCX
&& currentCX
== GetContextInternal()) {
5668 // We ignore the return value here. If setting the termination function
5669 // fails, it's better to fail to close the window than it is to crash
5670 // (which is what would tend to happen if we did this synchronously
5672 rv
= currentCX
->SetTerminationFunction(CloseWindow
,
5673 static_cast<nsIDOMWindow
*>
5675 if (NS_SUCCEEDED(rv
)) {
5676 mHavePendingClose
= PR_TRUE
;
5683 // We may have plugins on the page that have issued this close from their
5684 // event loop and because we currently destroy the plugin window with
5685 // frames, we crash. So, if we are called from Javascript, post an event
5686 // to really close the window.
5687 rv
= NS_ERROR_FAILURE
;
5688 if (!nsContentUtils::IsCallerChrome()) {
5689 rv
= nsCloseEvent::PostCloseEvent(this);
5692 if (NS_FAILED(rv
)) {
5693 ReallyCloseWindow();
5696 mHavePendingClose
= PR_TRUE
;
5704 nsGlobalWindow::ReallyCloseWindow()
5706 FORWARD_TO_OUTER_VOID(ReallyCloseWindow
, ());
5708 // Make sure we never reenter this method.
5709 mHavePendingClose
= PR_TRUE
;
5711 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
5712 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
5714 // If there's no treeOwnerAsWin, this window must already be closed.
5716 if (treeOwnerAsWin
) {
5718 // but if we're a browser window we could be in some nasty
5719 // self-destroying cascade that we should mostly ignore
5721 nsCOMPtr
<nsIDocShellTreeItem
> docItem(do_QueryInterface(mDocShell
));
5723 nsCOMPtr
<nsIBrowserDOMWindow
> bwin
;
5724 nsCOMPtr
<nsIDocShellTreeItem
> rootItem
;
5725 docItem
->GetRootTreeItem(getter_AddRefs(rootItem
));
5726 nsCOMPtr
<nsIDOMWindow
> rootWin(do_GetInterface(rootItem
));
5727 nsCOMPtr
<nsIDOMChromeWindow
> chromeWin(do_QueryInterface(rootWin
));
5729 chromeWin
->GetBrowserDOMWindow(getter_AddRefs(bwin
));
5732 /* Normally we destroy the entire window, but not if
5733 this DOM window belongs to a tabbed browser and doesn't
5734 correspond to a tab. This allows a well-behaved tab
5735 to destroy the container as it should but is a final measure
5736 to prevent an errant tab from doing so when it shouldn't.
5737 This works because we reach this code when we shouldn't only
5738 in the particular circumstance that we belong to a tab
5739 that has just been closed (and is therefore already missing
5740 from the list of browsers) (and has an unload handler
5741 that closes the window). */
5742 // XXXbz now that we have mHavePendingClose, is this needed?
5743 PRBool isTab
= PR_FALSE
;
5744 if (rootWin
== this ||
5745 !bwin
|| (bwin
->IsTabContentWindow(GetOuterWindowInternal(),
5747 treeOwnerAsWin
->Destroy();
5756 nsGlobalWindow::EnterModalState()
5758 nsCOMPtr
<nsIDOMWindow
> top
;
5759 GetTop(getter_AddRefs(top
));
5762 NS_ERROR("Uh, EnterModalState() called w/o a reachable top window?");
5767 nsGlobalWindow
* topWin
=
5768 static_cast<nsGlobalWindow
*>(static_cast<nsIDOMWindow
*>(top
.get()));
5769 if (topWin
->mModalStateDepth
== 0) {
5770 NS_ASSERTION(!mSuspendedDoc
, "Shouldn't have mSuspendedDoc here!");
5772 mSuspendedDoc
= do_QueryInterface(topWin
->GetExtantDocument());
5773 if (mSuspendedDoc
&& mSuspendedDoc
->EventHandlingSuppressed()) {
5774 mSuspendedDoc
->SuppressEventHandling();
5776 mSuspendedDoc
= nsnull
;
5779 topWin
->mModalStateDepth
++;
5781 JSContext
*cx
= nsContentUtils::GetCurrentJSContext();
5783 nsIScriptContext
*scx
;
5784 if (cx
&& (scx
= GetScriptContextFromJSContext(cx
))) {
5785 scx
->EnterModalState();
5791 nsGlobalWindow::RunPendingTimeoutsRecursive(nsGlobalWindow
*aTopWindow
,
5792 nsGlobalWindow
*aWindow
)
5794 nsGlobalWindow
*inner
;
5796 // Return early if we're frozen or have no inner window.
5797 if (!(inner
= aWindow
->GetCurrentInnerWindowInternal()) ||
5798 inner
->IsFrozen()) {
5802 inner
->RunTimeout(nsnull
);
5804 // Check again if we're frozen since running pending timeouts
5805 // could've frozen us.
5806 if (inner
->IsFrozen()) {
5810 nsCOMPtr
<nsIDOMWindowCollection
> frames
;
5811 aWindow
->GetFrames(getter_AddRefs(frames
));
5818 if (NS_FAILED(frames
->GetLength(&length
)) || !length
) {
5822 for (i
= 0; i
< length
&& aTopWindow
->mModalStateDepth
== 0; i
++) {
5823 nsCOMPtr
<nsIDOMWindow
> child
;
5824 frames
->Item(i
, getter_AddRefs(child
));
5830 nsGlobalWindow
*childWin
=
5831 static_cast<nsGlobalWindow
*>
5832 (static_cast<nsIDOMWindow
*>
5835 RunPendingTimeoutsRecursive(aTopWindow
, childWin
);
5839 class nsPendingTimeoutRunner
: public nsRunnable
5842 nsPendingTimeoutRunner(nsGlobalWindow
*aWindow
)
5845 NS_ASSERTION(mWindow
, "mWindow is null.");
5850 nsGlobalWindow::RunPendingTimeoutsRecursive(mWindow
, mWindow
);
5856 nsRefPtr
<nsGlobalWindow
> mWindow
;
5860 nsGlobalWindow::LeaveModalState()
5862 nsCOMPtr
<nsIDOMWindow
> top
;
5863 GetTop(getter_AddRefs(top
));
5866 NS_ERROR("Uh, LeaveModalState() called w/o a reachable top window?");
5871 nsGlobalWindow
*topWin
=
5872 static_cast<nsGlobalWindow
*>
5873 (static_cast<nsIDOMWindow
*>
5876 topWin
->mModalStateDepth
--;
5878 if (topWin
->mModalStateDepth
== 0) {
5879 nsCOMPtr
<nsIRunnable
> runner
= new nsPendingTimeoutRunner(topWin
);
5880 if (NS_FAILED(NS_DispatchToCurrentThread(runner
)))
5881 NS_WARNING("failed to dispatch pending timeout runnable");
5883 if (mSuspendedDoc
) {
5884 nsCOMPtr
<nsIDocument
> currentDoc
=
5885 do_QueryInterface(topWin
->GetExtantDocument());
5886 mSuspendedDoc
->UnsuppressEventHandlingAndFireEvents(currentDoc
== mSuspendedDoc
);
5887 mSuspendedDoc
= nsnull
;
5891 JSContext
*cx
= nsContentUtils::GetCurrentJSContext();
5893 nsIScriptContext
*scx
;
5894 if (cx
&& (scx
= GetScriptContextFromJSContext(cx
))) {
5895 scx
->LeaveModalState();
5900 nsGlobalWindow::IsInModalState()
5902 nsCOMPtr
<nsIDOMWindow
> top
;
5903 GetTop(getter_AddRefs(top
));
5906 NS_ERROR("Uh, IsInModalState() called w/o a reachable top window?");
5911 return static_cast<nsGlobalWindow
*>
5912 (static_cast<nsIDOMWindow
*>
5913 (top
.get()))->mModalStateDepth
!= 0;
5918 nsGlobalWindow::NotifyDOMWindowDestroyed(nsGlobalWindow
* aWindow
) {
5919 nsCOMPtr
<nsIObserverService
> observerService
=
5920 do_GetService(NS_OBSERVERSERVICE_CONTRACTID
);
5921 if (observerService
) {
5923 NotifyObservers(static_cast<nsIScriptGlobalObject
*>(aWindow
),
5924 DOM_WINDOW_DESTROYED_TOPIC
, nsnull
);
5928 class WindowDestroyedEvent
: public nsRunnable
5931 WindowDestroyedEvent(PRUint64 aID
, const char* aTopic
) :
5932 mID(aID
), mTopic(aTopic
) {}
5936 nsCOMPtr
<nsIObserverService
> observerService
=
5937 do_GetService("@mozilla.org/observer-service;1");
5938 if (observerService
) {
5939 nsCOMPtr
<nsISupportsPRUint64
> wrapper
=
5940 do_CreateInstance(NS_SUPPORTS_PRUINT64_CONTRACTID
);
5942 wrapper
->SetData(mID
);
5943 observerService
->NotifyObservers(wrapper
, mTopic
.get(), nsnull
);
5955 nsGlobalWindow::NotifyWindowIDDestroyed(const char* aTopic
)
5957 nsRefPtr
<nsIRunnable
> runnable
= new WindowDestroyedEvent(mWindowID
, aTopic
);
5958 nsresult rv
= NS_DispatchToCurrentThread(runnable
);
5959 if (NS_SUCCEEDED(rv
)) {
5960 mNotifiedIDDestroyed
= PR_TRUE
;
5965 nsGlobalWindow::InitJavaProperties()
5967 nsIScriptContext
*scx
= GetContextInternal();
5969 if (mDidInitJavaProperties
|| IsOuterWindow() || !scx
|| !mJSObject
) {
5973 // Set mDidInitJavaProperties to true here even if initialization
5974 // can fail. If it fails, we won't try again...
5975 mDidInitJavaProperties
= PR_TRUE
;
5977 // Check whether the plugin supports NPRuntime, if so, init through
5980 nsCOMPtr
<nsIPluginHost
> host(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID
));
5985 mDummyJavaPluginOwner
= new nsDummyJavaPluginOwner(mDoc
);
5986 if (!mDummyJavaPluginOwner
) {
5990 host
->InstantiateDummyJavaPlugin(mDummyJavaPluginOwner
);
5992 // It's possible for us (or the Java plugin, rather) to process
5993 // events during the above call, which can lead to this window being
5994 // torn down or what not, so re-check that the dummy plugin is still
5996 if (!mDummyJavaPluginOwner
) {
6000 nsCOMPtr
<nsIPluginInstance
> dummyPlugin
;
6001 mDummyJavaPluginOwner
->GetInstance(*getter_AddRefs(dummyPlugin
));
6004 // A dummy plugin was instantiated. This means we have a Java
6005 // plugin that supports NPRuntime. For such a plugin, the plugin
6006 // instantiation code defines the Java properties for us, so we're
6012 // No NPRuntime enabled Java plugin found, null out the owner we
6013 // would have used in that case as it's no longer needed.
6014 mDummyJavaPluginOwner
= nsnull
;
6018 nsGlobalWindow::GetCachedXBLPrototypeHandler(nsXBLPrototypeHandler
* aKey
)
6020 void* handler
= nsnull
;
6021 if (mCachedXBLPrototypeHandlers
.IsInitialized()) {
6022 mCachedXBLPrototypeHandlers
.Get(aKey
, &handler
);
6028 nsGlobalWindow::CacheXBLPrototypeHandler(nsXBLPrototypeHandler
* aKey
,
6029 nsScriptObjectHolder
& aHandler
)
6031 if (!mCachedXBLPrototypeHandlers
.IsInitialized() &&
6032 !mCachedXBLPrototypeHandlers
.Init()) {
6033 NS_ERROR("Failed to initiailize hashtable!");
6037 if (!mCachedXBLPrototypeHandlers
.Count()) {
6038 // Can't use macros to get the participant because nsGlobalChromeWindow also
6039 // runs through this code. Use QueryInterface to get the correct objects.
6040 nsXPCOMCycleCollectionParticipant
* participant
;
6041 CallQueryInterface(this, &participant
);
6042 NS_ASSERTION(participant
,
6043 "Failed to QI to nsXPCOMCycleCollectionParticipant!");
6045 nsCOMPtr
<nsISupports
> thisSupports
;
6046 QueryInterface(NS_GET_IID(nsCycleCollectionISupports
),
6047 getter_AddRefs(thisSupports
));
6048 NS_ASSERTION(thisSupports
, "Failed to QI to nsCycleCollectionISupports!");
6050 nsresult rv
= nsContentUtils::HoldJSObjects(thisSupports
, participant
);
6051 if (NS_FAILED(rv
)) {
6052 NS_ERROR("nsContentUtils::HoldJSObjects failed!");
6057 mCachedXBLPrototypeHandlers
.Put(aKey
, aHandler
);
6061 nsGlobalWindow::GetFrameElement(nsIDOMElement
** aFrameElement
)
6063 FORWARD_TO_OUTER(GetFrameElement
, (aFrameElement
), NS_ERROR_NOT_INITIALIZED
);
6065 *aFrameElement
= nsnull
;
6067 nsCOMPtr
<nsIDocShellTreeItem
> docShellTI(do_QueryInterface(mDocShell
));
6073 nsCOMPtr
<nsIDocShellTreeItem
> parent
;
6074 docShellTI
->GetSameTypeParent(getter_AddRefs(parent
));
6076 if (!parent
|| parent
== docShellTI
) {
6077 // We're at a chrome boundary, don't expose the chrome iframe
6078 // element to content code.
6083 *aFrameElement
= mFrameElement
;
6084 NS_IF_ADDREF(*aFrameElement
);
6089 // Helper for converting window.showModalDialog() options (list of ';'
6090 // separated name (:|=) value pairs) to a format that's parsable by
6091 // our normal window opening code.
6094 ConvertDialogOptions(const nsAString
& aOptions
, nsAString
& aResult
)
6096 nsAString::const_iterator end
;
6097 aOptions
.EndReading(end
);
6099 nsAString::const_iterator iter
;
6100 aOptions
.BeginReading(iter
);
6102 while (iter
!= end
) {
6104 while (nsCRT::IsAsciiSpace(*iter
) && iter
!= end
) {
6108 nsAString::const_iterator name_start
= iter
;
6110 // Skip characters until we find whitespace, ';', ':', or '='
6111 while (iter
!= end
&& !nsCRT::IsAsciiSpace(*iter
) &&
6118 nsAString::const_iterator name_end
= iter
;
6121 while (nsCRT::IsAsciiSpace(*iter
) && iter
!= end
) {
6126 // No value found, skip the ';' and keep going.
6132 nsAString::const_iterator value_start
= iter
;
6133 nsAString::const_iterator value_end
= iter
;
6135 if (*iter
== ':' || *iter
== '=') {
6136 // We found name followed by ':' or '='. Look for a value.
6138 iter
++; // Skip the ':' or '='
6141 while (nsCRT::IsAsciiSpace(*iter
) && iter
!= end
) {
6147 // Skip until we find whitespace, or ';'.
6148 while (iter
!= end
&& !nsCRT::IsAsciiSpace(*iter
) &&
6156 while (nsCRT::IsAsciiSpace(*iter
) && iter
!= end
) {
6161 const nsDependentSubstring
& name
= Substring(name_start
, name_end
);
6162 const nsDependentSubstring
& value
= Substring(value_start
, value_end
);
6164 if (name
.LowerCaseEqualsLiteral("center")) {
6165 if (value
.LowerCaseEqualsLiteral("on") ||
6166 value
.LowerCaseEqualsLiteral("yes") ||
6167 value
.LowerCaseEqualsLiteral("1")) {
6168 aResult
.AppendLiteral(",centerscreen=1");
6170 } else if (name
.LowerCaseEqualsLiteral("dialogwidth")) {
6171 if (!value
.IsEmpty()) {
6172 aResult
.AppendLiteral(",width=");
6173 aResult
.Append(value
);
6175 } else if (name
.LowerCaseEqualsLiteral("dialogheight")) {
6176 if (!value
.IsEmpty()) {
6177 aResult
.AppendLiteral(",height=");
6178 aResult
.Append(value
);
6180 } else if (name
.LowerCaseEqualsLiteral("dialogtop")) {
6181 if (!value
.IsEmpty()) {
6182 aResult
.AppendLiteral(",top=");
6183 aResult
.Append(value
);
6185 } else if (name
.LowerCaseEqualsLiteral("dialogleft")) {
6186 if (!value
.IsEmpty()) {
6187 aResult
.AppendLiteral(",left=");
6188 aResult
.Append(value
);
6190 } else if (name
.LowerCaseEqualsLiteral("resizable")) {
6191 if (value
.LowerCaseEqualsLiteral("on") ||
6192 value
.LowerCaseEqualsLiteral("yes") ||
6193 value
.LowerCaseEqualsLiteral("1")) {
6194 aResult
.AppendLiteral(",resizable=1");
6196 } else if (name
.LowerCaseEqualsLiteral("scroll")) {
6197 if (value
.LowerCaseEqualsLiteral("off") ||
6198 value
.LowerCaseEqualsLiteral("no") ||
6199 value
.LowerCaseEqualsLiteral("0")) {
6200 aResult
.AppendLiteral(",scrollbars=0");
6213 nsGlobalWindow::ShowModalDialog(const nsAString
& aURI
, nsIVariant
*aArgs
,
6214 const nsAString
& aOptions
,
6215 nsIVariant
**aRetVal
)
6219 NS_ENSURE_TRUE(mDocShell
, NS_ERROR_FAILURE
);
6221 nsCOMPtr
<nsIDOMWindow
> dlgWin
;
6222 nsAutoString
options(NS_LITERAL_STRING("-moz-internal-modal=1,status=1"));
6224 ConvertDialogOptions(aOptions
, options
);
6226 options
.AppendLiteral(",scrollbars=1,centerscreen=1,resizable=0");
6228 // Before bringing up the window, unsuppress painting and flush
6230 EnsureReflowFlushAndPaint();
6232 nsresult rv
= OpenInternal(aURI
, EmptyString(), options
,
6233 PR_FALSE
, // aDialog
6234 PR_TRUE
, // aContentModal
6235 PR_TRUE
, // aCalledNoScript
6236 PR_TRUE
, // aDoJSFixups
6237 nsnull
, aArgs
, // args
6238 GetPrincipal(), // aCalleePrincipal
6239 nsnull
, // aJSCallerContext
6240 getter_AddRefs(dlgWin
));
6242 NS_ENSURE_SUCCESS(rv
, rv
);
6245 nsCOMPtr
<nsIPrincipal
> subjectPrincipal
;
6246 rv
= nsContentUtils::GetSecurityManager()->
6247 GetSubjectPrincipal(getter_AddRefs(subjectPrincipal
));
6248 if (NS_FAILED(rv
)) {
6252 PRBool canAccess
= PR_TRUE
;
6254 if (subjectPrincipal
) {
6255 nsCOMPtr
<nsIScriptObjectPrincipal
> objPrincipal
=
6256 do_QueryInterface(dlgWin
);
6257 nsCOMPtr
<nsIPrincipal
> dialogPrincipal
;
6260 dialogPrincipal
= objPrincipal
->GetPrincipal();
6262 rv
= subjectPrincipal
->Subsumes(dialogPrincipal
, &canAccess
);
6263 NS_ENSURE_SUCCESS(rv
, rv
);
6265 // Uh, not sure what kind of dialog this is. Prevent access to
6266 // be on the safe side...
6268 canAccess
= PR_FALSE
;
6272 nsCOMPtr
<nsPIDOMWindow
> win(do_QueryInterface(dlgWin
));
6275 nsPIDOMWindow
*inner
= win
->GetCurrentInnerWindow();
6277 nsCOMPtr
<nsIDOMModalContentWindow
> dlgInner(do_QueryInterface(inner
));
6280 dlgInner
->GetReturnValue(aRetVal
);
6284 nsRefPtr
<nsGlobalWindow
> winInternal
=
6285 static_cast<nsGlobalWindow
*>(win
.get());
6286 if (winInternal
->mCallCleanUpAfterModalDialogCloses
) {
6287 winInternal
->mCallCleanUpAfterModalDialogCloses
= PR_FALSE
;
6288 winInternal
->CleanUp(PR_TRUE
);
6295 class CommandDispatcher
: public nsRunnable
6298 CommandDispatcher(nsIDOMXULCommandDispatcher
* aDispatcher
,
6299 const nsAString
& aAction
)
6300 : mDispatcher(aDispatcher
), mAction(aAction
) {}
6304 return mDispatcher
->UpdateCommands(mAction
);
6307 nsCOMPtr
<nsIDOMXULCommandDispatcher
> mDispatcher
;
6312 nsGlobalWindow::UpdateCommands(const nsAString
& anAction
)
6314 nsPIDOMWindow
*rootWindow
= nsGlobalWindow::GetPrivateRoot();
6318 nsCOMPtr
<nsIDOMXULDocument
> xulDoc
=
6319 do_QueryInterface(rootWindow
->GetExtantDocument());
6320 // See if we contain a XUL document.
6322 // Retrieve the command dispatcher and call updateCommands on it.
6323 nsCOMPtr
<nsIDOMXULCommandDispatcher
> xulCommandDispatcher
;
6324 xulDoc
->GetCommandDispatcher(getter_AddRefs(xulCommandDispatcher
));
6325 if (xulCommandDispatcher
) {
6326 nsContentUtils::AddScriptRunner(new CommandDispatcher(xulCommandDispatcher
,
6335 nsGlobalWindow::GetBlurSuppression()
6337 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
6338 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
6339 PRBool suppress
= PR_FALSE
;
6341 treeOwnerAsWin
->GetBlurSuppression(&suppress
);
6346 nsGlobalWindow::GetSelection(nsISelection
** aSelection
)
6348 FORWARD_TO_OUTER(GetSelection
, (aSelection
), NS_ERROR_NOT_INITIALIZED
);
6350 NS_ENSURE_ARG_POINTER(aSelection
);
6351 *aSelection
= nsnull
;
6356 nsCOMPtr
<nsIPresShell
> presShell
;
6357 mDocShell
->GetPresShell(getter_AddRefs(presShell
));
6362 *aSelection
= presShell
->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL
);
6364 NS_IF_ADDREF(*aSelection
);
6370 nsGlobalWindow::Find(const nsAString
& aStr
, PRBool aCaseSensitive
,
6371 PRBool aBackwards
, PRBool aWrapAround
, PRBool aWholeWord
,
6372 PRBool aSearchInFrames
, PRBool aShowDialog
,
6375 FORWARD_TO_OUTER(Find
, (aStr
, aCaseSensitive
, aBackwards
, aWrapAround
,
6376 aWholeWord
, aSearchInFrames
, aShowDialog
, aDidFind
),
6377 NS_ERROR_NOT_INITIALIZED
);
6379 nsresult rv
= NS_OK
;
6380 *aDidFind
= PR_FALSE
;
6382 nsCOMPtr
<nsIWebBrowserFind
> finder(do_GetInterface(mDocShell
));
6383 NS_ENSURE_TRUE(finder
, NS_ERROR_FAILURE
);
6385 // Set the options of the search
6386 rv
= finder
->SetSearchString(PromiseFlatString(aStr
).get());
6387 NS_ENSURE_SUCCESS(rv
, rv
);
6388 finder
->SetMatchCase(aCaseSensitive
);
6389 finder
->SetFindBackwards(aBackwards
);
6390 finder
->SetWrapFind(aWrapAround
);
6391 finder
->SetEntireWord(aWholeWord
);
6392 finder
->SetSearchFrames(aSearchInFrames
);
6394 // the nsIWebBrowserFind is initialized to use this window
6395 // as the search root, but uses focus to set the current search
6396 // frame. If we're being called from JS (as here), this window
6397 // should be the current search frame.
6398 nsCOMPtr
<nsIWebBrowserFindInFrames
> framesFinder(do_QueryInterface(finder
));
6400 framesFinder
->SetRootSearchFrame(this); // paranoia
6401 framesFinder
->SetCurrentSearchFrame(this);
6404 // The Find API does not accept empty strings. Launch the Find Dialog.
6405 if (aStr
.IsEmpty() || aShowDialog
) {
6406 // See if the find dialog is already up using nsIWindowMediator
6407 nsCOMPtr
<nsIWindowMediator
> windowMediator
=
6408 do_GetService(NS_WINDOWMEDIATOR_CONTRACTID
);
6410 nsCOMPtr
<nsIDOMWindowInternal
> findDialog
;
6412 if (windowMediator
) {
6413 windowMediator
->GetMostRecentWindow(NS_LITERAL_STRING("findInPage").get(),
6414 getter_AddRefs(findDialog
));
6418 // The Find dialog is already open, bring it to the top.
6419 rv
= findDialog
->Focus();
6420 } else { // Open a Find dialog
6422 nsCOMPtr
<nsIDOMWindow
> dialog
;
6423 rv
= OpenDialog(NS_LITERAL_STRING("chrome://global/content/finddialog.xul"),
6424 NS_LITERAL_STRING("_blank"),
6425 NS_LITERAL_STRING("chrome, resizable=no, dependent=yes"),
6426 finder
, getter_AddRefs(dialog
));
6430 // Launch the search with the passed in search string
6431 rv
= finder
->FindNext(aDidFind
);
6432 NS_ENSURE_SUCCESS(rv
, rv
);
6439 Is8bit(const nsAString
& aString
)
6441 static const PRUnichar EIGHT_BIT
= PRUnichar(~0x00FF);
6443 nsAString::const_iterator done_reading
;
6444 aString
.EndReading(done_reading
);
6446 // for each chunk of |aString|...
6447 PRUint32 fragmentLength
= 0;
6448 nsAString::const_iterator iter
;
6449 for (aString
.BeginReading(iter
); iter
!= done_reading
;
6450 iter
.advance(PRInt32(fragmentLength
))) {
6451 fragmentLength
= PRUint32(iter
.size_forward());
6452 const PRUnichar
* c
= iter
.get();
6453 const PRUnichar
* fragmentEnd
= c
+ fragmentLength
;
6455 // for each character in this chunk...
6456 while (c
< fragmentEnd
)
6457 if (*c
++ & EIGHT_BIT
)
6465 nsGlobalWindow::Atob(const nsAString
& aAsciiBase64String
,
6466 nsAString
& aBinaryData
)
6468 aBinaryData
.Truncate();
6470 if (!Is8bit(aAsciiBase64String
)) {
6471 return NS_ERROR_DOM_INVALID_CHARACTER_ERR
;
6474 PRUint32 dataLen
= aAsciiBase64String
.Length();
6476 NS_LossyConvertUTF16toASCII
base64(aAsciiBase64String
);
6477 if (base64
.Length() != dataLen
) {
6478 return NS_ERROR_OUT_OF_MEMORY
;
6481 PRInt32 resultLen
= dataLen
;
6482 if (!base64
.IsEmpty() && base64
[dataLen
- 1] == '=') {
6483 if (base64
.Length() > 1 && base64
[dataLen
- 2] == '=') {
6484 resultLen
= dataLen
- 2;
6486 resultLen
= dataLen
- 1;
6490 resultLen
= ((resultLen
* 3) / 4);
6491 // Add 4 extra bytes (one is needed for sure for null termination)
6492 // to the malloc size just to make sure we don't end up writing past
6493 // the allocated memory (the PL_Base64Decode API should really
6494 // provide a guaranteed way to figure this out w/o needing to do the
6496 char *dest
= static_cast<char *>(nsMemory::Alloc(resultLen
+ 4));
6498 return NS_ERROR_OUT_OF_MEMORY
;
6501 char *bin_data
= PL_Base64Decode(base64
.get(), dataLen
, dest
);
6503 nsresult rv
= NS_OK
;
6506 CopyASCIItoUTF16(Substring(bin_data
, bin_data
+ resultLen
), aBinaryData
);
6508 rv
= NS_ERROR_DOM_INVALID_CHARACTER_ERR
;
6511 nsMemory::Free(dest
);
6517 nsGlobalWindow::Btoa(const nsAString
& aBinaryData
,
6518 nsAString
& aAsciiBase64String
)
6520 aAsciiBase64String
.Truncate();
6522 if (!Is8bit(aBinaryData
)) {
6523 return NS_ERROR_DOM_INVALID_CHARACTER_ERR
;
6526 char *bin_data
= ToNewCString(aBinaryData
);
6528 return NS_ERROR_OUT_OF_MEMORY
;
6531 PRInt32 resultLen
= ((aBinaryData
.Length() + 2) / 3) * 4;
6533 char *base64
= PL_Base64Encode(bin_data
, aBinaryData
.Length(), nsnull
);
6535 nsMemory::Free(bin_data
);
6537 return NS_ERROR_OUT_OF_MEMORY
;
6540 CopyASCIItoUTF16(nsDependentCString(base64
, resultLen
), aAsciiBase64String
);
6543 nsMemory::Free(bin_data
);
6548 //*****************************************************************************
6549 // nsGlobalWindow::nsIDOMEventTarget
6550 //*****************************************************************************
6553 nsGlobalWindow::AddEventListener(const nsAString
& aType
,
6554 nsIDOMEventListener
* aListener
,
6557 FORWARD_TO_INNER_CREATE(AddEventListener
, (aType
, aListener
, aUseCapture
),
6558 NS_ERROR_NOT_AVAILABLE
);
6560 return AddEventListener(aType
, aListener
, aUseCapture
, PR_FALSE
, 0);
6564 nsGlobalWindow::RemoveEventListener(const nsAString
& aType
,
6565 nsIDOMEventListener
* aListener
,
6568 return RemoveGroupedEventListener(aType
, aListener
, aUseCapture
, nsnull
);
6572 nsGlobalWindow::DispatchEvent(nsIDOMEvent
* aEvent
, PRBool
* _retval
)
6574 FORWARD_TO_INNER(DispatchEvent
, (aEvent
, _retval
), NS_OK
);
6577 return NS_ERROR_FAILURE
;
6580 // Obtain a presentation shell
6581 nsIPresShell
*shell
= mDoc
->GetShell();
6582 nsRefPtr
<nsPresContext
> presContext
;
6584 // Retrieve the context
6585 presContext
= shell
->GetPresContext();
6588 nsEventStatus status
= nsEventStatus_eIgnore
;
6590 nsEventDispatcher::DispatchDOMEvent(GetOuterWindow(), nsnull
, aEvent
,
6591 presContext
, &status
);
6593 *_retval
= (status
!= nsEventStatus_eConsumeNoDefault
);
6597 //*****************************************************************************
6598 // nsGlobalWindow::nsIDOM3EventTarget
6599 //*****************************************************************************
6602 nsGlobalWindow::AddGroupedEventListener(const nsAString
& aType
,
6603 nsIDOMEventListener
*aListener
,
6605 nsIDOMEventGroup
*aEvtGrp
)
6607 FORWARD_TO_INNER_CREATE(AddGroupedEventListener
,
6608 (aType
, aListener
, aUseCapture
, aEvtGrp
),
6609 NS_ERROR_NOT_AVAILABLE
);
6611 nsIEventListenerManager
* manager
= GetListenerManager(PR_TRUE
);
6612 NS_ENSURE_STATE(manager
);
6613 PRInt32 flags
= aUseCapture
? NS_EVENT_FLAG_CAPTURE
: NS_EVENT_FLAG_BUBBLE
;
6614 return manager
->AddEventListenerByType(aListener
, aType
, flags
, aEvtGrp
);
6618 nsGlobalWindow::RemoveGroupedEventListener(const nsAString
& aType
,
6619 nsIDOMEventListener
*aListener
,
6621 nsIDOMEventGroup
*aEvtGrp
)
6623 FORWARD_TO_INNER(RemoveGroupedEventListener
,
6624 (aType
, aListener
, aUseCapture
, aEvtGrp
),
6625 NS_ERROR_NOT_INITIALIZED
);
6627 if (mListenerManager
) {
6628 PRInt32 flags
= aUseCapture
? NS_EVENT_FLAG_CAPTURE
: NS_EVENT_FLAG_BUBBLE
;
6630 mListenerManager
->RemoveEventListenerByType(aListener
, aType
, flags
,
6637 nsGlobalWindow::CanTrigger(const nsAString
& type
, PRBool
*_retval
)
6639 return NS_ERROR_NOT_IMPLEMENTED
;
6643 nsGlobalWindow::IsRegisteredHere(const nsAString
& type
, PRBool
*_retval
)
6645 return NS_ERROR_NOT_IMPLEMENTED
;
6649 nsGlobalWindow::AddEventListener(const nsAString
& aType
,
6650 nsIDOMEventListener
*aListener
,
6651 PRBool aUseCapture
, PRBool aWantsUntrusted
,
6652 PRUint8 optional_argc
)
6654 NS_ASSERTION(!aWantsUntrusted
|| optional_argc
> 0,
6655 "Won't check if this is chrome, you want to set "
6656 "aWantsUntrusted to PR_FALSE or make the aWantsUntrusted "
6657 "explicit by making optional_argc non-zero.");
6659 if (IsOuterWindow() && mInnerWindow
&&
6660 !nsContentUtils::CanCallerAccess(mInnerWindow
)) {
6661 return NS_ERROR_DOM_SECURITY_ERR
;
6664 nsIEventListenerManager
* manager
= GetListenerManager(PR_TRUE
);
6665 NS_ENSURE_STATE(manager
);
6667 PRInt32 flags
= aUseCapture
? NS_EVENT_FLAG_CAPTURE
: NS_EVENT_FLAG_BUBBLE
;
6669 if (aWantsUntrusted
||
6670 (optional_argc
== 0 && !nsContentUtils::IsChromeDoc(mDoc
))) {
6671 flags
|= NS_PRIV_EVENT_UNTRUSTED_PERMITTED
;
6674 return manager
->AddEventListenerByType(aListener
, aType
, flags
, nsnull
);
6678 nsGlobalWindow::AddEventListenerByIID(nsIDOMEventListener
* aListener
,
6681 nsIEventListenerManager
* manager
= GetListenerManager(PR_TRUE
);
6682 NS_ENSURE_STATE(manager
);
6683 return manager
->AddEventListenerByIID(aListener
, aIID
, NS_EVENT_FLAG_BUBBLE
);
6687 nsGlobalWindow::RemoveEventListenerByIID(nsIDOMEventListener
* aListener
,
6690 FORWARD_TO_INNER(RemoveEventListenerByIID
, (aListener
, aIID
),
6691 NS_ERROR_NOT_INITIALIZED
);
6693 if (mListenerManager
) {
6694 mListenerManager
->RemoveEventListenerByIID(aListener
, aIID
,
6695 NS_EVENT_FLAG_BUBBLE
);
6698 return NS_ERROR_FAILURE
;
6701 nsIEventListenerManager
*
6702 nsGlobalWindow::GetListenerManager(PRBool aCreateIfNotFound
)
6704 FORWARD_TO_INNER_CREATE(GetListenerManager
, (aCreateIfNotFound
), nsnull
);
6706 if (!mListenerManager
) {
6707 if (!aCreateIfNotFound
) {
6711 static NS_DEFINE_CID(kEventListenerManagerCID
,
6712 NS_EVENTLISTENERMANAGER_CID
);
6714 mListenerManager
= do_CreateInstance(kEventListenerManagerCID
);
6715 if (mListenerManager
) {
6716 mListenerManager
->SetListenerTarget(
6717 static_cast<nsPIDOMEventTarget
*>(this));
6721 return mListenerManager
;
6725 nsGlobalWindow::GetSystemEventGroup(nsIDOMEventGroup
**aGroup
)
6727 nsIEventListenerManager
* manager
= GetListenerManager(PR_TRUE
);
6728 NS_ENSURE_STATE(manager
);
6729 return manager
->GetSystemEventGroupLM(aGroup
);
6733 nsGlobalWindow::GetContextForEventHandlers(nsresult
* aRv
)
6735 nsIScriptContext
* scx
= GetContext();
6736 *aRv
= scx
? NS_OK
: NS_ERROR_UNEXPECTED
;
6740 //*****************************************************************************
6741 // nsGlobalWindow::nsPIDOMWindow
6742 //*****************************************************************************
6745 nsGlobalWindow::GetPrivateParent()
6747 FORWARD_TO_OUTER(GetPrivateParent
, (), nsnull
);
6749 nsCOMPtr
<nsIDOMWindow
> parent
;
6750 GetParent(getter_AddRefs(parent
));
6752 if (static_cast<nsIDOMWindow
*>(this) == parent
.get()) {
6753 nsCOMPtr
<nsIContent
> chromeElement(do_QueryInterface(mChromeEventHandler
));
6755 return nsnull
; // This is ok, just means a null parent.
6757 nsIDocument
* doc
= chromeElement
->GetDocument();
6759 return nsnull
; // This is ok, just means a null parent.
6761 nsIScriptGlobalObject
*globalObject
= doc
->GetScriptGlobalObject();
6763 return nsnull
; // This is ok, just means a null parent.
6765 parent
= do_QueryInterface(globalObject
);
6769 return static_cast<nsGlobalWindow
*>
6770 (static_cast<nsIDOMWindow
*>(parent
.get()));
6777 nsGlobalWindow::GetPrivateRoot()
6779 FORWARD_TO_OUTER(GetPrivateRoot
, (), nsnull
);
6781 nsCOMPtr
<nsIDOMWindow
> top
;
6782 GetTop(getter_AddRefs(top
));
6784 nsCOMPtr
<nsPIDOMWindow
> ptop
= do_QueryInterface(top
);
6785 NS_ASSERTION(ptop
, "cannot get ptop");
6789 nsIDocShell
*docShell
= ptop
->GetDocShell();
6791 // Get the chrome event handler from the doc shell, since we only
6792 // want to deal with XUL chrome handlers and not the new kind of
6793 // window root handler.
6794 nsCOMPtr
<nsIDOMEventTarget
> chromeEventHandler
;
6795 docShell
->GetChromeEventHandler(getter_AddRefs(chromeEventHandler
));
6797 nsCOMPtr
<nsIContent
> chromeElement(do_QueryInterface(mChromeEventHandler
));
6798 if (chromeElement
) {
6799 nsIDocument
* doc
= chromeElement
->GetDocument();
6801 nsIDOMWindow
*parent
= doc
->GetWindow();
6803 parent
->GetTop(getter_AddRefs(top
));
6808 return static_cast<nsGlobalWindow
*>
6809 (static_cast<nsIDOMWindow
*>(top
));
6814 nsGlobalWindow::GetLocation(nsIDOMLocation
** aLocation
)
6816 FORWARD_TO_OUTER(GetLocation
, (aLocation
), NS_ERROR_NOT_INITIALIZED
);
6818 *aLocation
= nsnull
;
6820 if (!mLocation
&& mDocShell
) {
6821 mLocation
= new nsLocation(mDocShell
);
6823 return NS_ERROR_OUT_OF_MEMORY
;
6827 NS_IF_ADDREF(*aLocation
= mLocation
);
6833 nsGlobalWindow::ActivateOrDeactivate(PRBool aActivate
)
6835 // Set / unset mIsActive on the top level window, which is used for the
6836 // :-moz-window-inactive pseudoclass.
6837 nsCOMPtr
<nsIWidget
> mainWidget
= GetMainWidget();
6841 // Get the top level widget (if the main widget is a sheet, this will
6842 // be the sheet's top (non-sheet) parent).
6843 nsCOMPtr
<nsIWidget
> topLevelWidget
= mainWidget
->GetSheetWindowParent();
6844 if (!topLevelWidget
) {
6845 topLevelWidget
= mainWidget
;
6848 // Get the top level widget's nsGlobalWindow
6849 nsCOMPtr
<nsIDOMWindowInternal
> topLevelWindow
;
6850 if (topLevelWidget
== mainWidget
) {
6851 topLevelWindow
= static_cast<nsIDOMWindowInternal
*>(this);
6853 // This is a workaround for the following problem:
6854 // When a window with an open sheet loses focus, only the sheet window
6855 // receives the NS_DEACTIVATE event. However, it's not the sheet that
6856 // should lose the active styling, but the containing top level window.
6858 topLevelWidget
->GetClientData(clientData
); // clientData is nsXULWindow
6859 nsISupports
* data
= static_cast<nsISupports
*>(clientData
);
6860 nsCOMPtr
<nsIInterfaceRequestor
> req(do_QueryInterface(data
));
6861 topLevelWindow
= do_GetInterface(req
);
6863 if (topLevelWindow
) {
6864 nsCOMPtr
<nsPIDOMWindow
> piWin(do_QueryInterface(topLevelWindow
));
6865 piWin
->SetActive(aActivate
);
6870 NotifyDocumentTree(nsIDocument
* aDocument
, void* aData
)
6872 aDocument
->EnumerateSubDocuments(NotifyDocumentTree
, nsnull
);
6873 aDocument
->DocumentStatesChanged(NS_DOCUMENT_STATE_WINDOW_INACTIVE
);
6878 nsGlobalWindow::SetActive(PRBool aActive
)
6880 nsPIDOMWindow::SetActive(aActive
);
6881 NotifyDocumentTree(mDoc
, nsnull
);
6885 nsGlobalWindow::SetChromeEventHandler(nsPIDOMEventTarget
* aChromeEventHandler
)
6887 SetChromeEventHandlerInternal(aChromeEventHandler
);
6888 if (IsOuterWindow()) {
6889 // update the chrome event handler on all our inner windows
6890 for (nsGlobalWindow
*inner
= (nsGlobalWindow
*)PR_LIST_HEAD(this);
6892 inner
= (nsGlobalWindow
*)PR_NEXT_LINK(inner
)) {
6893 NS_ASSERTION(inner
->mOuterWindow
== this, "bad outer window pointer");
6894 inner
->SetChromeEventHandlerInternal(aChromeEventHandler
);
6896 } else if (mOuterWindow
) {
6897 // Need the cast to be able to call the protected method on a
6898 // superclass. We could make the method public instead, but it's really
6900 static_cast<nsGlobalWindow
*>(mOuterWindow
)->
6901 SetChromeEventHandlerInternal(aChromeEventHandler
);
6905 static PRBool
IsLink(nsIContent
* aContent
)
6907 nsCOMPtr
<nsIDOMHTMLAnchorElement
> anchor
= do_QueryInterface(aContent
);
6908 return (anchor
|| (aContent
&&
6909 aContent
->AttrValueIs(kNameSpaceID_XLink
, nsGkAtoms::type
,
6910 nsGkAtoms::simple
, eCaseMatters
)));
6914 nsGlobalWindow::SetFocusedNode(nsIContent
* aNode
,
6915 PRUint32 aFocusMethod
,
6918 FORWARD_TO_INNER_VOID(SetFocusedNode
, (aNode
, aFocusMethod
, aNeedsFocus
));
6920 NS_ASSERTION(!aNode
|| aNode
->GetCurrentDoc() == mDoc
,
6921 "setting focus to a node from the wrong document");
6923 if (mFocusedNode
!= aNode
) {
6924 UpdateCanvasFocus(PR_FALSE
, aNode
);
6925 mFocusedNode
= aNode
;
6926 mFocusMethod
= aFocusMethod
& FOCUSMETHOD_MASK
;
6927 mShowFocusRingForContent
= PR_FALSE
;
6931 // if a node was focused by a keypress, turn on focus rings for the
6933 if (mFocusMethod
& nsIFocusManager::FLAG_BYKEY
) {
6934 mFocusByKeyOccurred
= PR_TRUE
;
6936 // otherwise, we set mShowFocusRingForContent, as we don't want this to
6937 // be permanent for the window. On Windows, focus rings are only shown
6938 // when the FLAG_SHOWRING flag is used. On other platforms, focus rings
6939 // are only hidden for clicks on links.
6941 !(mFocusMethod
& nsIFocusManager::FLAG_BYMOUSE
) || !IsLink(aNode
) ||
6943 aFocusMethod
& nsIFocusManager::FLAG_SHOWRING
) {
6944 mShowFocusRingForContent
= PR_TRUE
;
6949 mNeedsFocus
= aNeedsFocus
;
6953 nsGlobalWindow::GetFocusMethod()
6955 FORWARD_TO_INNER(GetFocusMethod
, (), 0);
6957 return mFocusMethod
;
6961 nsGlobalWindow::ShouldShowFocusRing()
6963 FORWARD_TO_INNER(ShouldShowFocusRing
, (), PR_FALSE
);
6965 return mShowFocusRings
|| mShowFocusRingForContent
|| mFocusByKeyOccurred
;
6969 nsGlobalWindow::SetKeyboardIndicators(UIStateChangeType aShowAccelerators
,
6970 UIStateChangeType aShowFocusRings
)
6972 FORWARD_TO_INNER_VOID(SetKeyboardIndicators
, (aShowAccelerators
, aShowFocusRings
));
6974 // only change the flags that have been modified
6975 if (aShowAccelerators
!= UIStateChangeType_NoChange
)
6976 mShowAccelerators
= aShowAccelerators
== UIStateChangeType_Set
;
6977 if (aShowFocusRings
!= UIStateChangeType_NoChange
)
6978 mShowFocusRings
= aShowFocusRings
== UIStateChangeType_Set
;
6980 // propagate the indicators to child windows
6981 nsCOMPtr
<nsIDocShellTreeNode
> node
= do_QueryInterface(GetDocShell());
6983 PRInt32 childCount
= 0;
6984 node
->GetChildCount(&childCount
);
6986 for (PRInt32 i
= 0; i
< childCount
; ++i
) {
6987 nsCOMPtr
<nsIDocShellTreeItem
> childShell
;
6988 node
->GetChildAt(i
, getter_AddRefs(childShell
));
6989 nsCOMPtr
<nsPIDOMWindow
> childWindow
= do_GetInterface(childShell
);
6991 childWindow
->SetKeyboardIndicators(aShowAccelerators
, aShowFocusRings
);
6997 // send content state notifications
6998 nsCOMPtr
<nsPresContext
> presContext
;
7000 mDocShell
->GetPresContext(getter_AddRefs(presContext
));
7002 presContext
->EventStateManager()->
7003 SetContentState(mFocusedNode
, NS_EVENT_STATE_FOCUS
);
7010 nsGlobalWindow::GetKeyboardIndicators(PRBool
* aShowAccelerators
,
7011 PRBool
* aShowFocusRings
)
7013 FORWARD_TO_INNER_VOID(GetKeyboardIndicators
, (aShowAccelerators
, aShowFocusRings
));
7015 *aShowAccelerators
= mShowAccelerators
;
7016 *aShowFocusRings
= mShowFocusRings
;
7020 nsGlobalWindow::TakeFocus(PRBool aFocus
, PRUint32 aFocusMethod
)
7022 FORWARD_TO_INNER(TakeFocus
, (aFocus
, aFocusMethod
), PR_FALSE
);
7025 mFocusMethod
= aFocusMethod
& FOCUSMETHOD_MASK
;
7027 if (mHasFocus
!= aFocus
) {
7029 UpdateCanvasFocus(PR_TRUE
, mFocusedNode
);
7032 // if mNeedsFocus is true, then the document has not yet received a
7033 // document-level focus event. If there is a root content node, then return
7034 // true to tell the calling focus manager that a focus event is expected. If
7035 // there is no root content node, the document hasn't loaded enough yet, or
7036 // there isn't one and there is no point in firing a focus event.
7037 if (aFocus
&& mNeedsFocus
&& mDoc
&& mDoc
->GetRootElement() != nsnull
) {
7038 mNeedsFocus
= PR_FALSE
;
7042 mNeedsFocus
= PR_FALSE
;
7047 nsGlobalWindow::SetReadyForFocus()
7049 FORWARD_TO_INNER_VOID(SetReadyForFocus
, ());
7051 PRBool oldNeedsFocus
= mNeedsFocus
;
7052 mNeedsFocus
= PR_FALSE
;
7054 // update whether focus rings need to be shown using the state from the
7056 nsPIDOMWindow
* root
= GetPrivateRoot();
7058 PRBool showAccelerators
, showFocusRings
;
7059 root
->GetKeyboardIndicators(&showAccelerators
, &showFocusRings
);
7060 mShowFocusRings
= showFocusRings
;
7063 nsIFocusManager
* fm
= nsFocusManager::GetFocusManager();
7065 fm
->WindowShown(this, oldNeedsFocus
);
7069 nsGlobalWindow::PageHidden()
7071 FORWARD_TO_INNER_VOID(PageHidden
, ());
7073 // the window is being hidden, so tell the focus manager that the frame is
7074 // no longer valid. Use the persisted field to determine if the document
7075 // is being destroyed.
7077 nsIFocusManager
* fm
= nsFocusManager::GetFocusManager();
7079 fm
->WindowHidden(this);
7081 mNeedsFocus
= PR_TRUE
;
7085 nsGlobalWindow::DispatchSyncHashchange()
7087 FORWARD_TO_INNER(DispatchSyncHashchange
, (), NS_OK
);
7088 NS_ASSERTION(nsContentUtils::IsSafeToRunScript(),
7089 "Must be safe to run script here.");
7091 // Don't do anything if the window is frozen.
7095 // Dispatch the hashchange event, which doesn't bubble and isn't cancelable,
7096 // to the outer window.
7097 return nsContentUtils::DispatchTrustedEvent(mDoc
, GetOuterWindow(),
7098 NS_LITERAL_STRING("hashchange"),
7099 PR_FALSE
, PR_FALSE
);
7103 nsGlobalWindow::DispatchSyncPopState()
7105 FORWARD_TO_INNER(DispatchSyncPopState
, (), NS_OK
);
7107 NS_ASSERTION(nsContentUtils::IsSafeToRunScript(),
7108 "Must be safe to run script here.");
7110 // Check that PopState hasn't been pref'ed off.
7111 if (!nsContentUtils::GetBoolPref(sPopStatePrefStr
, PR_FALSE
))
7114 nsresult rv
= NS_OK
;
7116 // Bail if the window is frozen.
7121 // Bail if there's no document or the document's readystate isn't "complete".
7126 nsIDocument::ReadyState readyState
= mDoc
->GetReadyStateEnum();
7127 if (readyState
!= nsIDocument::READYSTATE_COMPLETE
) {
7131 // Get the document's pending state object -- it contains the data we're
7132 // going to send along with the popstate event. The object is serialized as
7134 nsAString
& stateObjJSON
= mDoc
->GetPendingStateObject();
7136 nsCOMPtr
<nsIVariant
> stateObj
;
7137 // Parse the JSON, if there's any to parse.
7138 if (!stateObjJSON
.IsEmpty()) {
7139 // Get the JSContext associated with our document. We need this for
7141 nsCOMPtr
<nsIDocument
> document
= do_QueryInterface(mDocument
);
7142 NS_ENSURE_TRUE(document
, NS_ERROR_FAILURE
);
7144 // Get the JSContext from the document, like we do in
7145 // nsContentUtils::GetContextFromDocument().
7146 nsIScriptGlobalObject
*sgo
= document
->GetScopeObject();
7147 NS_ENSURE_TRUE(sgo
, NS_ERROR_FAILURE
);
7149 nsIScriptContext
*scx
= sgo
->GetContext();
7150 NS_ENSURE_TRUE(scx
, NS_ERROR_FAILURE
);
7152 JSContext
*cx
= (JSContext
*) scx
->GetNativeContext();
7154 // If our json call triggers a JS-to-C++ call, we want that call to use cx
7155 // as the context. So we push cx onto the context stack.
7156 nsCxPusher cxPusher
;
7158 jsval jsStateObj
= JSVAL_NULL
;
7159 // Root the container which will hold our decoded state object.
7160 nsAutoGCRoot
root(&jsStateObj
, &rv
);
7161 NS_ENSURE_SUCCESS(rv
, rv
);
7163 // Deserialize the state object into an nsIVariant.
7164 nsCOMPtr
<nsIJSON
> json
= do_GetService("@mozilla.org/dom/json;1");
7165 NS_ENSURE_TRUE(cxPusher
.Push(cx
), NS_ERROR_FAILURE
);
7166 rv
= json
->DecodeToJSVal(stateObjJSON
, cx
, &jsStateObj
);
7167 NS_ENSURE_SUCCESS(rv
, rv
);
7170 nsCOMPtr
<nsIXPConnect
> xpconnect
= do_GetService(nsIXPConnect::GetCID());
7171 NS_ENSURE_TRUE(xpconnect
, NS_ERROR_FAILURE
);
7172 rv
= xpconnect
->JSValToVariant(cx
, &jsStateObj
, getter_AddRefs(stateObj
));
7173 NS_ENSURE_SUCCESS(rv
, rv
);
7176 // Obtain a presentation shell for use in creating a popstate event.
7177 nsIPresShell
*shell
= mDoc
->GetShell();
7178 nsRefPtr
<nsPresContext
> presContext
;
7180 presContext
= shell
->GetPresContext();
7183 // Create a new popstate event
7184 nsCOMPtr
<nsIDOMEvent
> domEvent
;
7185 rv
= nsEventDispatcher::CreateEvent(presContext
, nsnull
,
7186 NS_LITERAL_STRING("popstateevent"),
7187 getter_AddRefs(domEvent
));
7188 NS_ENSURE_SUCCESS(rv
, rv
);
7190 nsCOMPtr
<nsIPrivateDOMEvent
> privateEvent
= do_QueryInterface(domEvent
);
7191 NS_ENSURE_TRUE(privateEvent
, NS_ERROR_FAILURE
);
7193 // Initialize the popstate event, which does bubble but isn't cancellable.
7194 nsCOMPtr
<nsIDOMPopStateEvent
> popstateEvent
= do_QueryInterface(domEvent
);
7195 rv
= popstateEvent
->InitPopStateEvent(NS_LITERAL_STRING("popstate"),
7198 NS_ENSURE_SUCCESS(rv
, rv
);
7200 rv
= privateEvent
->SetTrusted(PR_TRUE
);
7201 NS_ENSURE_SUCCESS(rv
, rv
);
7203 nsCOMPtr
<nsIDOMEventTarget
> outerWindow
=
7204 do_QueryInterface(GetOuterWindow());
7205 NS_ENSURE_TRUE(outerWindow
, NS_ERROR_UNEXPECTED
);
7207 rv
= privateEvent
->SetTarget(outerWindow
);
7208 NS_ENSURE_SUCCESS(rv
, rv
);
7210 PRBool dummy
; // default action
7211 return DispatchEvent(popstateEvent
, &dummy
);
7214 // Find an nsICanvasFrame under aFrame. Only search the principal
7215 // child lists. aFrame must be non-null.
7216 static nsCanvasFrame
* FindCanvasFrame(nsIFrame
* aFrame
)
7218 nsCanvasFrame
* canvasFrame
= do_QueryFrame(aFrame
);
7223 nsIFrame
* kid
= aFrame
->GetFirstChild(nsnull
);
7225 canvasFrame
= FindCanvasFrame(kid
);
7229 kid
= kid
->GetNextSibling();
7235 //-------------------------------------------------------
7236 // Tells the HTMLFrame/CanvasFrame that is now has focus
7238 nsGlobalWindow::UpdateCanvasFocus(PRBool aFocusChanged
, nsIContent
* aNewContent
)
7240 // this is called from the inner window so use GetDocShell
7241 nsIDocShell
* docShell
= GetDocShell();
7245 nsCOMPtr
<nsIEditorDocShell
> editorDocShell
= do_QueryInterface(docShell
);
7246 if (editorDocShell
) {
7248 editorDocShell
->GetEditable(&editable
);
7253 nsCOMPtr
<nsIPresShell
> presShell
;
7254 docShell
->GetPresShell(getter_AddRefs(presShell
));
7255 if (!presShell
|| !mDocument
)
7258 nsCOMPtr
<nsIDocument
> doc(do_QueryInterface(mDocument
));
7259 Element
*rootElement
= doc
->GetRootElement();
7261 if ((mHasFocus
|| aFocusChanged
) &&
7262 (mFocusedNode
== rootElement
|| aNewContent
== rootElement
)) {
7263 nsIFrame
* frame
= rootElement
->GetPrimaryFrame();
7265 frame
= frame
->GetParent();
7266 nsCanvasFrame
* canvasFrame
= do_QueryFrame(frame
);
7268 canvasFrame
->SetHasFocus(mHasFocus
&& rootElement
== aNewContent
);
7273 // Look for the frame the hard way
7274 nsIFrame
* frame
= presShell
->GetRootFrame();
7276 nsCanvasFrame
* canvasFrame
= FindCanvasFrame(frame
);
7278 canvasFrame
->SetHasFocus(PR_FALSE
);
7284 //*****************************************************************************
7285 // nsGlobalWindow::nsIDOMViewCSS
7286 //*****************************************************************************
7289 nsGlobalWindow::GetComputedStyle(nsIDOMElement
* aElt
,
7290 const nsAString
& aPseudoElt
,
7291 nsIDOMCSSStyleDeclaration
** aReturn
)
7293 FORWARD_TO_OUTER(GetComputedStyle
, (aElt
, aPseudoElt
, aReturn
),
7294 NS_ERROR_NOT_INITIALIZED
);
7296 NS_ENSURE_ARG_POINTER(aReturn
);
7300 return NS_ERROR_DOM_NOT_SUPPORTED_ERR
;
7307 nsCOMPtr
<nsIPresShell
> presShell
;
7308 mDocShell
->GetPresShell(getter_AddRefs(presShell
));
7314 nsRefPtr
<nsComputedDOMStyle
> compStyle
;
7315 nsresult rv
= NS_NewComputedDOMStyle(aElt
, aPseudoElt
, presShell
,
7316 getter_AddRefs(compStyle
));
7317 NS_ENSURE_SUCCESS(rv
, rv
);
7319 *aReturn
= compStyle
.forget().get();
7324 //*****************************************************************************
7325 // nsGlobalWindow::nsIDOMAbstractView
7326 //*****************************************************************************
7329 nsGlobalWindow::GetDocument(nsIDOMDocumentView
** aDocumentView
)
7331 NS_ENSURE_ARG_POINTER(aDocumentView
);
7333 nsresult rv
= NS_OK
;
7336 rv
= CallQueryInterface(mDocument
, aDocumentView
);
7339 *aDocumentView
= nsnull
;
7345 //*****************************************************************************
7346 // nsGlobalWindow::nsIDOMStorageWindow
7347 //*****************************************************************************
7350 nsGlobalWindow::GetSessionStorage(nsIDOMStorage
** aSessionStorage
)
7352 FORWARD_TO_INNER(GetSessionStorage
, (aSessionStorage
), NS_ERROR_UNEXPECTED
);
7354 nsIPrincipal
*principal
= GetPrincipal();
7355 nsIDocShell
* docShell
= GetDocShell();
7357 if (!principal
|| !docShell
) {
7361 if (mSessionStorage
) {
7363 if (PR_LOG_TEST(gDOMLeakPRLog
, PR_LOG_DEBUG
)) {
7364 PR_LogPrint("nsGlobalWindow %p has %p sessionStorage", this, mSessionStorage
.get());
7367 nsCOMPtr
<nsPIDOMStorage
> piStorage
= do_QueryInterface(mSessionStorage
);
7369 PRBool canAccess
= piStorage
->CanAccess(principal
);
7370 NS_ASSERTION(canAccess
,
7371 "window %x owned sessionStorage "
7372 "that could not be accessed!");
7374 mSessionStorage
= nsnull
;
7379 if (!mSessionStorage
) {
7380 *aSessionStorage
= nsnull
;
7382 nsString documentURI
;
7383 nsCOMPtr
<nsIDOM3Document
> document3
= do_QueryInterface(mDoc
);
7385 document3
->GetDocumentURI(documentURI
);
7387 nsresult rv
= docShell
->GetSessionStorageForPrincipal(principal
,
7390 getter_AddRefs(mSessionStorage
));
7391 NS_ENSURE_SUCCESS(rv
, rv
);
7394 if (PR_LOG_TEST(gDOMLeakPRLog
, PR_LOG_DEBUG
)) {
7395 PR_LogPrint("nsGlobalWindow %p tried to get a new sessionStorage %p", this, mSessionStorage
.get());
7399 if (!mSessionStorage
) {
7400 return NS_ERROR_DOM_NOT_SUPPORTED_ERR
;
7405 if (PR_LOG_TEST(gDOMLeakPRLog
, PR_LOG_DEBUG
)) {
7406 PR_LogPrint("nsGlobalWindow %p returns %p sessionStorage", this, mSessionStorage
.get());
7410 NS_ADDREF(*aSessionStorage
= mSessionStorage
);
7415 nsGlobalWindow::GetGlobalStorage(nsIDOMStorageList
** aGlobalStorage
)
7417 NS_ENSURE_ARG_POINTER(aGlobalStorage
);
7420 if (!sGlobalStorageList
) {
7421 nsresult rv
= NS_NewDOMStorageList(&sGlobalStorageList
);
7422 NS_ENSURE_SUCCESS(rv
, rv
);
7425 *aGlobalStorage
= sGlobalStorageList
;
7426 NS_IF_ADDREF(*aGlobalStorage
);
7430 return NS_ERROR_DOM_NOT_SUPPORTED_ERR
;
7435 nsGlobalWindow::GetLocalStorage(nsIDOMStorage
** aLocalStorage
)
7437 FORWARD_TO_INNER(GetLocalStorage
, (aLocalStorage
), NS_ERROR_UNEXPECTED
);
7439 NS_ENSURE_ARG(aLocalStorage
);
7441 if (!mLocalStorage
) {
7442 *aLocalStorage
= nsnull
;
7446 PRPackedBool unused
;
7447 if (!nsDOMStorage::CanUseStorage(&unused
))
7448 return NS_ERROR_DOM_SECURITY_ERR
;
7450 nsIPrincipal
*principal
= GetPrincipal();
7454 nsCOMPtr
<nsIDOMStorageManager
> storageManager
=
7455 do_GetService("@mozilla.org/dom/storagemanager;1", &rv
);
7456 NS_ENSURE_SUCCESS(rv
, rv
);
7458 nsString documentURI
;
7459 nsCOMPtr
<nsIDOM3Document
> document3
= do_QueryInterface(mDoc
);
7461 document3
->GetDocumentURI(documentURI
);
7463 rv
= storageManager
->GetLocalStorageForPrincipal(principal
,
7465 getter_AddRefs(mLocalStorage
));
7466 NS_ENSURE_SUCCESS(rv
, rv
);
7469 NS_ADDREF(*aLocalStorage
= mLocalStorage
);
7474 nsGlobalWindow::GetMoz_indexedDB(nsIIDBFactory
** _retval
)
7477 mIndexedDB
= mozilla::dom::indexedDB::IDBFactory::Create();
7478 NS_ENSURE_TRUE(mIndexedDB
, NS_ERROR_FAILURE
);
7481 nsCOMPtr
<nsIIDBFactory
> request(mIndexedDB
);
7482 request
.forget(_retval
);
7486 //*****************************************************************************
7487 // nsGlobalWindow::nsIInterfaceRequestor
7488 //*****************************************************************************
7491 nsGlobalWindow::GetInterface(const nsIID
& aIID
, void **aSink
)
7493 NS_ENSURE_ARG_POINTER(aSink
);
7496 if (aIID
.Equals(NS_GET_IID(nsIDocCharset
))) {
7497 FORWARD_TO_OUTER(GetInterface
, (aIID
, aSink
), NS_ERROR_NOT_INITIALIZED
);
7500 nsCOMPtr
<nsIDocCharset
> docCharset(do_QueryInterface(mDocShell
));
7502 *aSink
= docCharset
;
7503 NS_ADDREF(((nsISupports
*) *aSink
));
7507 else if (aIID
.Equals(NS_GET_IID(nsIWebNavigation
))) {
7508 FORWARD_TO_OUTER(GetInterface
, (aIID
, aSink
), NS_ERROR_NOT_INITIALIZED
);
7511 nsCOMPtr
<nsIWebNavigation
> webNav(do_QueryInterface(mDocShell
));
7514 NS_ADDREF(((nsISupports
*) *aSink
));
7519 else if (aIID
.Equals(NS_GET_IID(nsIWebBrowserPrint
))) {
7520 FORWARD_TO_OUTER(GetInterface
, (aIID
, aSink
), NS_ERROR_NOT_INITIALIZED
);
7523 nsCOMPtr
<nsIContentViewer
> viewer
;
7524 mDocShell
->GetContentViewer(getter_AddRefs(viewer
));
7526 nsCOMPtr
<nsIWebBrowserPrint
> webBrowserPrint(do_QueryInterface(viewer
));
7527 if (webBrowserPrint
) {
7528 *aSink
= webBrowserPrint
;
7529 NS_ADDREF(((nsISupports
*) *aSink
));
7535 else if (aIID
.Equals(NS_GET_IID(nsIScriptEventManager
))) {
7537 nsIScriptEventManager
* mgr
= mDoc
->GetScriptEventManager();
7540 NS_ADDREF(((nsISupports
*) *aSink
));
7544 else if (aIID
.Equals(NS_GET_IID(nsIDOMWindowUtils
))) {
7545 FORWARD_TO_OUTER(GetInterface
, (aIID
, aSink
), NS_ERROR_NOT_INITIALIZED
);
7547 nsCOMPtr
<nsISupports
> utils(do_QueryReferent(mWindowUtils
));
7550 NS_ADDREF(((nsISupports
*) *aSink
));
7552 nsDOMWindowUtils
*utilObj
= new nsDOMWindowUtils(this);
7553 nsCOMPtr
<nsISupports
> utilsIfc
=
7554 NS_ISUPPORTS_CAST(nsIDOMWindowUtils
*, utilObj
);
7556 mWindowUtils
= do_GetWeakReference(utilsIfc
);
7558 NS_ADDREF(((nsISupports
*) *aSink
));
7563 return QueryInterface(aIID
, aSink
);
7566 return *aSink
? NS_OK
: NS_ERROR_NO_INTERFACE
;
7570 nsGlobalWindow::FireOfflineStatusEvent()
7575 if (NS_IsOffline()) {
7576 name
.AssignLiteral("offline");
7578 name
.AssignLiteral("online");
7580 // The event is fired at the body element, or if there is no body element,
7582 nsCOMPtr
<nsISupports
> eventTarget
= mDoc
.get();
7583 nsCOMPtr
<nsIDOMHTMLDocument
> htmlDoc
= do_QueryInterface(mDoc
);
7585 nsCOMPtr
<nsIDOMHTMLElement
> body
;
7586 htmlDoc
->GetBody(getter_AddRefs(body
));
7592 nsCOMPtr
<nsIDOMElement
> documentElement
;
7593 mDocument
->GetDocumentElement(getter_AddRefs(documentElement
));
7594 if(documentElement
) {
7595 eventTarget
= documentElement
;
7598 nsContentUtils::DispatchTrustedEvent(mDoc
, eventTarget
, name
, PR_TRUE
, PR_FALSE
);
7602 nsGlobalWindow::Observe(nsISupports
* aSubject
, const char* aTopic
,
7603 const PRUnichar
* aData
)
7605 if (!nsCRT::strcmp(aTopic
, NS_IOSERVICE_OFFLINE_STATUS_TOPIC
)) {
7607 // if an even number of notifications arrive while we're frozen,
7608 // we don't need to fire.
7609 mFireOfflineStatusChangeEventOnThaw
= !mFireOfflineStatusChangeEventOnThaw
;
7611 FireOfflineStatusEvent();
7616 if (IsInnerWindow() && !nsCRT::strcmp(aTopic
, "dom-storage-changed")) {
7617 nsIPrincipal
*principal
;
7620 principal
= GetPrincipal();
7622 // A global storage object changed, check to see if it's one
7623 // this window can access.
7625 nsCOMPtr
<nsIURI
> codebase
;
7626 principal
->GetURI(getter_AddRefs(codebase
));
7632 nsCAutoString currentDomain
;
7633 rv
= codebase
->GetAsciiHost(currentDomain
);
7634 if (NS_FAILED(rv
)) {
7638 if (!nsDOMStorageList::CanAccessDomain(NS_ConvertUTF16toUTF8(aData
),
7640 // This window can't reach the global storage object for the
7641 // domain for which the change happened, so don't fire any
7642 // events in this window.
7648 nsAutoString
domain(aData
);
7651 // This window is frozen, rather than firing the events here,
7652 // store the domain in which the change happened and fire the
7653 // events if we're ever thawed.
7655 if (!mPendingStorageEventsObsolete
) {
7656 mPendingStorageEventsObsolete
= new nsDataHashtable
<nsStringHashKey
, PRBool
>;
7657 NS_ENSURE_TRUE(mPendingStorageEventsObsolete
, NS_ERROR_OUT_OF_MEMORY
);
7659 rv
= mPendingStorageEventsObsolete
->Init();
7660 NS_ENSURE_SUCCESS(rv
, rv
);
7663 mPendingStorageEventsObsolete
->Put(domain
, PR_TRUE
);
7668 nsRefPtr
<nsDOMStorageEventObsolete
> event
= new nsDOMStorageEventObsolete();
7669 NS_ENSURE_TRUE(event
, NS_ERROR_OUT_OF_MEMORY
);
7671 rv
= event
->InitStorageEvent(NS_LITERAL_STRING("storage"), PR_FALSE
, PR_FALSE
, domain
);
7672 NS_ENSURE_SUCCESS(rv
, rv
);
7674 nsCOMPtr
<nsIDOMHTMLDocument
> htmlDoc(do_QueryInterface(mDocument
));
7676 nsCOMPtr
<nsIDOMEventTarget
> target
;
7679 nsCOMPtr
<nsIDOMHTMLElement
> body
;
7680 htmlDoc
->GetBody(getter_AddRefs(body
));
7682 target
= do_QueryInterface(body
);
7689 PRBool defaultActionEnabled
;
7690 target
->DispatchEvent((nsIDOMStorageEventObsolete
*)event
, &defaultActionEnabled
);
7695 if (IsInnerWindow() && !nsCRT::strcmp(aTopic
, "dom-storage2-changed")) {
7696 nsIPrincipal
*principal
;
7699 nsCOMPtr
<nsIDOMStorageEvent
> event
= do_QueryInterface(aSubject
, &rv
);
7700 NS_ENSURE_SUCCESS(rv
, rv
);
7702 nsCOMPtr
<nsIDOMStorage
> changingStorage
;
7703 rv
= event
->GetStorageArea(getter_AddRefs(changingStorage
));
7704 NS_ENSURE_SUCCESS(rv
, rv
);
7706 nsCOMPtr
<nsPIDOMStorage
> pistorage
= do_QueryInterface(changingStorage
);
7707 nsPIDOMStorage::nsDOMStorageType storageType
= pistorage
->StorageType();
7709 principal
= GetPrincipal();
7710 switch (storageType
)
7712 case nsPIDOMStorage::SessionStorage
:
7714 if (SameCOMIdentity(mSessionStorage
, changingStorage
)) {
7715 // Do not fire any events for the same storage object, it's not shared
7716 // among windows, see nsGlobalWindow::GetSessionStoarge()
7720 nsCOMPtr
<nsIDOMStorage
> storage
= mSessionStorage
;
7722 nsIDocShell
* docShell
= GetDocShell();
7723 if (principal
&& docShell
) {
7724 // No need to pass documentURI here, it's only needed when we want
7725 // to create a new storage, the third paramater would be PR_TRUE
7726 docShell
->GetSessionStorageForPrincipal(principal
,
7729 getter_AddRefs(storage
));
7733 if (!pistorage
->IsForkOf(storage
)) {
7734 // This storage event is coming from a different doc shell,
7735 // i.e. it is a clone, ignore this event.
7740 if (PR_LOG_TEST(gDOMLeakPRLog
, PR_LOG_DEBUG
)) {
7741 PR_LogPrint("nsGlobalWindow %p with sessionStorage %p passing event from %p", this, mSessionStorage
.get(), pistorage
.get());
7747 case nsPIDOMStorage::LocalStorage
:
7749 if (SameCOMIdentity(mLocalStorage
, changingStorage
)) {
7750 // Do not fire any events for the same storage object, it's not shared
7751 // among windows, see nsGlobalWindow::GetLocalStoarge()
7755 // Allow event fire only for the same principal storages
7756 // XXX We have to use EqualsIgnoreDomain after bug 495337 lands
7757 nsIPrincipal
*storagePrincipal
= pistorage
->Principal();
7760 rv
= storagePrincipal
->Equals(principal
, &equals
);
7761 NS_ENSURE_SUCCESS(rv
, rv
);
7773 // This window is frozen, rather than firing the events here,
7774 // store the domain in which the change happened and fire the
7775 // events if we're ever thawed.
7777 mPendingStorageEvents
.AppendElement(event
);
7781 PRBool defaultActionEnabled
;
7782 DispatchEvent((nsIDOMStorageEvent
*)event
, &defaultActionEnabled
);
7787 NS_WARNING("unrecognized topic in nsGlobalWindow::Observe");
7788 return NS_ERROR_FAILURE
;
7791 static PLDHashOperator
7792 FirePendingStorageEvents(const nsAString
& aKey
, PRBool aData
, void *userArg
)
7794 nsGlobalWindow
*win
= static_cast<nsGlobalWindow
*>(userArg
);
7796 nsCOMPtr
<nsIDOMStorage
> storage
;
7797 win
->GetSessionStorage(getter_AddRefs(storage
));
7800 win
->Observe(storage
, "dom-storage-changed",
7801 aKey
.IsEmpty() ? nsnull
: PromiseFlatString(aKey
).get());
7804 return PL_DHASH_NEXT
;
7808 nsGlobalWindow::FireDelayedDOMEvents()
7810 FORWARD_TO_INNER(FireDelayedDOMEvents
, (), NS_ERROR_UNEXPECTED
);
7812 for (PRUint32 i
= 0; i
< mPendingStorageEvents
.Length(); ++i
) {
7813 Observe(mPendingStorageEvents
[i
], "dom-storage2-changed", nsnull
);
7816 if (mPendingStorageEventsObsolete
) {
7817 // Fire pending storage events.
7818 mPendingStorageEventsObsolete
->EnumerateRead(FirePendingStorageEvents
, this);
7820 delete mPendingStorageEventsObsolete
;
7821 mPendingStorageEventsObsolete
= nsnull
;
7824 if (mApplicationCache
) {
7825 static_cast<nsDOMOfflineResourceList
*>(mApplicationCache
.get())->FirePendingEvents();
7828 if (mFireOfflineStatusChangeEventOnThaw
) {
7829 mFireOfflineStatusChangeEventOnThaw
= PR_FALSE
;
7830 FireOfflineStatusEvent();
7833 nsCOMPtr
<nsIDocShellTreeNode
> node
=
7834 do_QueryInterface(GetDocShell());
7836 PRInt32 childCount
= 0;
7837 node
->GetChildCount(&childCount
);
7839 for (PRInt32 i
= 0; i
< childCount
; ++i
) {
7840 nsCOMPtr
<nsIDocShellTreeItem
> childShell
;
7841 node
->GetChildAt(i
, getter_AddRefs(childShell
));
7842 NS_ASSERTION(childShell
, "null child shell");
7844 nsCOMPtr
<nsPIDOMWindow
> pWin
= do_GetInterface(childShell
);
7846 nsGlobalWindow
*win
=
7847 static_cast<nsGlobalWindow
*>
7848 (static_cast<nsPIDOMWindow
*>(pWin
));
7849 win
->FireDelayedDOMEvents();
7857 //*****************************************************************************
7858 // nsGlobalWindow: Window Control Functions
7859 //*****************************************************************************
7861 nsIDOMWindowInternal
*
7862 nsGlobalWindow::GetParentInternal()
7864 FORWARD_TO_OUTER(GetParentInternal
, (), nsnull
);
7866 nsIDOMWindowInternal
*parentInternal
= nsnull
;
7868 nsCOMPtr
<nsIDOMWindow
> parent
;
7869 GetParent(getter_AddRefs(parent
));
7871 if (parent
&& parent
!= static_cast<nsIDOMWindow
*>(this)) {
7872 nsCOMPtr
<nsIDOMWindowInternal
> tmp(do_QueryInterface(parent
));
7873 NS_ASSERTION(parent
, "Huh, parent not an nsIDOMWindowInternal?");
7875 parentInternal
= tmp
;
7878 return parentInternal
;
7883 nsGlobalWindow::CloseBlockScriptTerminationFunc(nsISupports
*aRef
)
7885 nsGlobalWindow
* pwin
= static_cast<nsGlobalWindow
*>
7886 (static_cast<nsPIDOMWindow
*>(aRef
));
7887 pwin
->mBlockScriptedClosingFlag
= PR_FALSE
;
7891 nsGlobalWindow::OpenInternal(const nsAString
& aUrl
, const nsAString
& aName
,
7892 const nsAString
& aOptions
, PRBool aDialog
,
7893 PRBool aContentModal
, PRBool aCalledNoScript
,
7894 PRBool aDoJSFixups
, nsIArray
*argv
,
7895 nsISupports
*aExtraArgument
,
7896 nsIPrincipal
*aCalleePrincipal
,
7897 JSContext
*aJSCallerContext
,
7898 nsIDOMWindow
**aReturn
)
7900 FORWARD_TO_OUTER(OpenInternal
, (aUrl
, aName
, aOptions
, aDialog
,
7901 aContentModal
, aCalledNoScript
, aDoJSFixups
,
7902 argv
, aExtraArgument
, aCalleePrincipal
,
7903 aJSCallerContext
, aReturn
),
7904 NS_ERROR_NOT_INITIALIZED
);
7909 argv
->GetLength(&argc
);
7911 NS_PRECONDITION(!aExtraArgument
|| (!argv
&& argc
== 0),
7912 "Can't pass in arguments both ways");
7913 NS_PRECONDITION(!aCalledNoScript
|| (!argv
&& argc
== 0),
7914 "Can't pass JS args when called via the noscript methods");
7915 NS_PRECONDITION(!aJSCallerContext
|| !aCalledNoScript
,
7916 "Shouldn't have caller context when called noscript");
7920 nsCOMPtr
<nsIWebBrowserChrome
> chrome
;
7921 GetWebBrowserChrome(getter_AddRefs(chrome
));
7923 // No chrome means we don't want to go through with this open call
7924 // -- see nsIWindowWatcher.idl
7925 return NS_ERROR_NOT_AVAILABLE
;
7928 NS_ASSERTION(mDocShell
, "Must have docshell here");
7930 const PRBool checkForPopup
=
7931 !aDialog
&& !WindowExists(aName
, !aCalledNoScript
);
7933 // Note: it's very important that this be an nsXPIDLCString, since we want
7934 // .get() on it to return nsnull until we write stuff to it. The window
7935 // watcher expects a null URL string if there is no URL to load.
7937 nsresult rv
= NS_OK
;
7939 // It's important to do this security check before determining whether this
7940 // window opening should be blocked, to ensure that we don't FireAbuseEvents
7941 // for a window opening that wouldn't have succeeded in the first place.
7942 if (!aUrl
.IsEmpty()) {
7943 AppendUTF16toUTF8(aUrl
, url
);
7945 /* Check whether the URI is allowed, but not for dialogs --
7946 see bug 56851. The security of this function depends on
7947 window.openDialog being inaccessible from web scripts */
7948 if (url
.get() && !aDialog
)
7949 rv
= SecurityCheckURL(url
.get());
7955 PopupControlState abuseLevel
= gPopupControlState
;
7956 if (checkForPopup
) {
7957 abuseLevel
= RevisePopupAbuseLevel(abuseLevel
);
7958 if (abuseLevel
>= openAbused
) {
7959 if (aJSCallerContext
) {
7960 // If script in some other window is doing a window.open on us and
7961 // it's being blocked, then it's OK to close us afterwards, probably.
7962 // But if we're doing a window.open on ourselves and block the popup,
7963 // prevent this window from closing until after this script terminates
7964 // so that whatever popup blocker UI the app has will be visible.
7965 if (mContext
== GetScriptContextFromJSContext(aJSCallerContext
)) {
7966 mBlockScriptedClosingFlag
= PR_TRUE
;
7967 mContext
->SetTerminationFunction(CloseBlockScriptTerminationFunc
,
7968 static_cast<nsPIDOMWindow
*>
7973 FireAbuseEvents(PR_TRUE
, PR_FALSE
, aUrl
, aName
, aOptions
);
7974 return aDoJSFixups
? NS_OK
: NS_ERROR_FAILURE
;
7978 nsCOMPtr
<nsIDOMWindow
> domReturn
;
7980 nsCOMPtr
<nsIWindowWatcher
> wwatch
=
7981 do_GetService(NS_WINDOWWATCHER_CONTRACTID
, &rv
);
7982 NS_ENSURE_TRUE(wwatch
, rv
);
7984 NS_ConvertUTF16toUTF8
options(aOptions
);
7985 NS_ConvertUTF16toUTF8
name(aName
);
7987 const char *options_ptr
= aOptions
.IsEmpty() ? nsnull
: options
.get();
7988 const char *name_ptr
= aName
.IsEmpty() ? nsnull
: name
.get();
7991 // Reset popup state while opening a window to prevent the
7992 // current state from being active the whole time a modal
7994 nsAutoPopupStatePusher
popupStatePusher(openAbused
, PR_TRUE
);
7996 if (!aCalledNoScript
) {
7997 nsCOMPtr
<nsPIWindowWatcher
> pwwatch(do_QueryInterface(wwatch
));
7998 NS_ASSERTION(pwwatch
,
7999 "Unable to open windows from JS because window watcher "
8001 NS_ENSURE_TRUE(pwwatch
, NS_ERROR_UNEXPECTED
);
8003 rv
= pwwatch
->OpenWindowJS(this, url
.get(), name_ptr
, options_ptr
,
8005 getter_AddRefs(domReturn
));
8007 // Push a null JSContext here so that the window watcher won't screw us
8008 // up. We do NOT want this case looking at the JS context on the stack
8009 // when searching. Compare comments on
8010 // nsIDOMWindowInternal::OpenWindow and nsIWindowWatcher::OpenWindow.
8011 nsCOMPtr
<nsIJSContextStack
> stack
;
8013 if (!aContentModal
) {
8014 stack
= do_GetService(sJSStackContractID
);
8018 rv
= stack
->Push(nsnull
);
8019 NS_ENSURE_SUCCESS(rv
, rv
);
8022 rv
= wwatch
->OpenWindow(this, url
.get(), name_ptr
, options_ptr
,
8023 aExtraArgument
, getter_AddRefs(domReturn
));
8028 NS_ASSERTION(!cx
, "Unexpected JSContext popped!");
8033 NS_ENSURE_SUCCESS(rv
, rv
);
8037 domReturn
.swap(*aReturn
);
8040 nsCOMPtr
<nsIDOMChromeWindow
> chrome_win(do_QueryInterface(*aReturn
));
8042 // A new non-chrome window was created from a call to
8043 // window.open() from JavaScript, make sure there's a document in
8044 // the new window. We do this by simply asking the new window for
8045 // its document, this will synchronously create an empty document
8046 // if there is no document in the window.
8047 // XXXbz should this just use EnsureInnerWindow()?
8050 nsCOMPtr
<nsPIDOMWindow
> pidomwin(do_QueryInterface(*aReturn
));
8052 nsIDOMDocument
*temp
= pidomwin
->GetExtantDocument();
8054 NS_ASSERTION(temp
, "No document in new window!!!");
8058 nsCOMPtr
<nsIDOMDocument
> doc
;
8059 (*aReturn
)->GetDocument(getter_AddRefs(doc
));
8063 if (checkForPopup
) {
8064 if (abuseLevel
>= openControlled
) {
8065 nsGlobalWindow
*opened
= static_cast<nsGlobalWindow
*>(*aReturn
);
8066 if (!opened
->IsPopupSpamWindow()) {
8067 opened
->SetPopupSpamWindow(PR_TRUE
);
8068 ++gOpenPopupSpamCount
;
8071 if (abuseLevel
>= openAbused
)
8072 FireAbuseEvents(PR_FALSE
, PR_TRUE
, aUrl
, aName
, aOptions
);
8080 nsGlobalWindow::CloseWindow(nsISupports
*aWindow
)
8082 nsCOMPtr
<nsPIDOMWindow
> win(do_QueryInterface(aWindow
));
8084 nsGlobalWindow
* globalWin
=
8085 static_cast<nsGlobalWindow
*>
8086 (static_cast<nsPIDOMWindow
*>(win
));
8088 // Need to post an event for closing, otherwise window and
8089 // presshell etc. may get destroyed while creating frames, bug 338897.
8090 nsCloseEvent::PostCloseEvent(globalWin
);
8091 // else if OOM, better not to close. That might cause a crash.
8096 nsGlobalWindow::ClearWindowScope(nsISupports
*aWindow
)
8098 nsCOMPtr
<nsIScriptGlobalObject
> sgo(do_QueryInterface(aWindow
));
8099 nsIScriptContext
*scx
= sgo
->GetContext();
8101 scx
->ClearScope(sgo
->GetGlobalJSObject(), PR_TRUE
);
8105 //*****************************************************************************
8106 // nsGlobalWindow: Timeout Functions
8107 //*****************************************************************************
8109 PRUint32 sNestingLevel
;
8112 nsGlobalWindow::SetTimeoutOrInterval(nsIScriptTimeoutHandler
*aHandler
,
8114 PRBool aIsInterval
, PRInt32
*aReturn
)
8116 FORWARD_TO_INNER(SetTimeoutOrInterval
, (aHandler
, interval
, aIsInterval
, aReturn
),
8117 NS_ERROR_NOT_INITIALIZED
);
8119 // If we don't have a document (we could have been unloaded since
8120 // the call to setTimeout was made), do nothing.
8125 PRUint32 nestingLevel
= sNestingLevel
+ 1;
8126 if (interval
< DOM_MIN_TIMEOUT_VALUE
) {
8127 if (aIsInterval
|| nestingLevel
>= DOM_CLAMP_TIMEOUT_NESTING_LEVEL
) {
8128 // Don't allow timeouts less than DOM_MIN_TIMEOUT_VALUE from
8131 interval
= DOM_MIN_TIMEOUT_VALUE
;
8133 else if (interval
< 0) {
8134 // Clamp negative intervals to 0.
8140 NS_ASSERTION(interval
>= 0, "DOM_MIN_TIMEOUT_VALUE lies");
8141 PRUint32 realInterval
= interval
;
8143 // Make sure we don't proceed with a interval larger than our timer
8145 if (realInterval
> PR_IntervalToMilliseconds(DOM_MAX_TIMEOUT_VALUE
)) {
8146 realInterval
= PR_IntervalToMilliseconds(DOM_MAX_TIMEOUT_VALUE
);
8149 nsTimeout
*timeout
= new nsTimeout();
8151 return NS_ERROR_OUT_OF_MEMORY
;
8153 // Increment the timeout's reference count to represent this function's hold
8158 timeout
->mInterval
= realInterval
;
8160 timeout
->mScriptHandler
= aHandler
;
8162 // Get principal of currently executing code, save for execution of timeout.
8163 // If our principals subsume the subject principal then use the subject
8164 // principal. Otherwise, use our principal to avoid running script in
8165 // elevated principals.
8167 nsCOMPtr
<nsIPrincipal
> subjectPrincipal
;
8169 rv
= nsContentUtils::GetSecurityManager()->
8170 GetSubjectPrincipal(getter_AddRefs(subjectPrincipal
));
8171 if (NS_FAILED(rv
)) {
8174 return NS_ERROR_FAILURE
;
8177 PRBool subsumes
= PR_FALSE
;
8178 nsCOMPtr
<nsIPrincipal
> ourPrincipal
= GetPrincipal();
8180 // Note the direction of this test: We don't allow setTimeouts running with
8181 // chrome privileges on content windows, but we do allow setTimeouts running
8182 // with content privileges on chrome windows (where they can't do very much,
8184 rv
= ourPrincipal
->Subsumes(subjectPrincipal
, &subsumes
);
8185 if (NS_FAILED(rv
)) {
8188 return NS_ERROR_FAILURE
;
8192 timeout
->mPrincipal
= subjectPrincipal
;
8194 timeout
->mPrincipal
= ourPrincipal
;
8197 PRTime delta
= (PRTime
)realInterval
* PR_USEC_PER_MSEC
;
8199 if (!IsFrozen() && !mTimeoutsSuspendDepth
) {
8200 // If we're not currently frozen, then we set timeout->mWhen to be the
8201 // actual firing time of the timer (i.e., now + delta). We also actually
8202 // create a timer and fire it off.
8204 timeout
->mWhen
= PR_Now() + delta
;
8206 timeout
->mTimer
= do_CreateInstance("@mozilla.org/timer;1", &rv
);
8207 if (NS_FAILED(rv
)) {
8213 rv
= timeout
->mTimer
->InitWithFuncCallback(TimerCallback
, timeout
,
8215 nsITimer::TYPE_ONE_SHOT
);
8216 if (NS_FAILED(rv
)) {
8222 // The timeout is now also held in the timer's closure.
8225 // If we are frozen, however, then we instead simply set timeout->mWhen to
8226 // be the "time remaining" in the timeout (i.e., the interval itself). We
8227 // don't create a timer for it, since that will happen when we are thawed
8228 // and the timeout will then get a timer and run to completion.
8230 timeout
->mWhen
= delta
;
8233 timeout
->mWindow
= this;
8236 timeout
->mNestingLevel
= nestingLevel
;
8239 // No popups from timeouts by default
8240 timeout
->mPopupState
= openAbused
;
8242 if (gRunningTimeoutDepth
== 0 && gPopupControlState
< openAbused
) {
8243 // This timeout is *not* set from another timeout and it's set
8244 // while popups are enabled. Propagate the state to the timeout if
8245 // its delay (interval) is equal to or less than what
8246 // "dom.disable_open_click_delay" is set to (in ms).
8249 nsContentUtils::GetIntPref("dom.disable_open_click_delay");
8251 if (interval
<= delay
) {
8252 timeout
->mPopupState
= gPopupControlState
;
8256 InsertTimeoutIntoList(timeout
);
8258 timeout
->mPublicId
= ++mTimeoutPublicIdCounter
;
8259 *aReturn
= timeout
->mPublicId
;
8261 // Our hold on the timeout is expiring. Note that this should not actually
8262 // free the timeout (since the list should have taken ownership as well).
8270 nsGlobalWindow::SetTimeoutOrInterval(PRBool aIsInterval
, PRInt32
*aReturn
)
8272 // This needs to forward to the inner window, but since the current
8273 // inner may not be the inner in the calling scope, we need to treat
8274 // this specially here as we don't want timeouts registered in a
8275 // dying inner window to get registered and run on the current inner
8276 // window. To get this right, we need to forward this call to the
8277 // inner window that's calling window.setTimeout().
8279 if (IsOuterWindow()) {
8280 nsGlobalWindow
* callerInner
= CallerInnerWindow();
8281 NS_ENSURE_TRUE(callerInner
, NS_ERROR_NOT_AVAILABLE
);
8283 // If the caller and the callee share the same outer window,
8284 // forward to the callee inner. Else, we forward to the current
8285 // inner (e.g. someone is calling setTimeout() on a reference to
8286 // some other window).
8288 if (callerInner
->GetOuterWindow() == this &&
8289 callerInner
->IsInnerWindow()) {
8290 return callerInner
->SetTimeoutOrInterval(aIsInterval
, aReturn
);
8293 FORWARD_TO_INNER(SetTimeoutOrInterval
, (aIsInterval
, aReturn
),
8294 NS_ERROR_NOT_INITIALIZED
);
8297 PRInt32 interval
= 0;
8298 PRBool isInterval
= aIsInterval
;
8299 nsCOMPtr
<nsIScriptTimeoutHandler
> handler
;
8300 nsresult rv
= NS_CreateJSTimeoutHandler(this,
8303 getter_AddRefs(handler
));
8305 return (rv
== NS_ERROR_DOM_TYPE_ERR
) ? NS_OK
: rv
;
8307 return SetTimeoutOrInterval(handler
, interval
, isInterval
, aReturn
);
8312 nsGlobalWindow::RunTimeout(nsTimeout
*aTimeout
)
8314 // If a modal dialog is open for this window, return early. Pending
8315 // timeouts will run when the modal dialog is dismissed.
8316 if (IsInModalState() || mTimeoutsSuspendDepth
) {
8322 NS_ASSERTION(IsInnerWindow(), "Timeout running on outer window!");
8323 NS_ASSERTION(!IsFrozen(), "Timeout running on a window in the bfcache!");
8325 nsTimeout
*nextTimeout
, *timeout
;
8326 nsTimeout
*last_expired_timeout
, *last_insertion_point
;
8327 nsTimeout dummy_timeout
;
8328 PRUint32 firingDepth
= mTimeoutFiringDepth
+ 1;
8330 // Make sure that the window and the script context don't go away as
8331 // a result of running timeouts
8332 nsCOMPtr
<nsIScriptGlobalObject
> windowKungFuDeathGrip(this);
8334 // A native timer has gone off. See which of our timeouts need
8336 PRTime now
= PR_Now();
8339 if (aTimeout
&& aTimeout
->mWhen
> now
) {
8340 // The OS timer fired early (yikes!), and possibly out of order
8341 // too. Set |deadline| to be the time when the OS timer *should*
8342 // have fired so that any timers that *should* have fired before
8343 // aTimeout *will* be fired now. This happens most of the time on
8346 deadline
= aTimeout
->mWhen
;
8351 // The timeout list is kept in deadline order. Discover the latest
8352 // timeout whose deadline has expired. On some platforms, native
8353 // timeout events fire "early", so we need to test the timer as well
8355 last_expired_timeout
= nsnull
;
8356 for (timeout
= FirstTimeout(); IsTimeout(timeout
); timeout
= timeout
->Next()) {
8357 if (((timeout
== aTimeout
) || (timeout
->mWhen
<= deadline
)) &&
8358 (timeout
->mFiringDepth
== 0)) {
8359 // Mark any timeouts that are on the list to be fired with the
8360 // firing depth so that we can reentrantly run timeouts
8361 timeout
->mFiringDepth
= firingDepth
;
8362 last_expired_timeout
= timeout
;
8366 // Maybe the timeout that the event was fired for has been deleted
8367 // and there are no others timeouts with deadlines that make them
8368 // eligible for execution yet. Go away.
8369 if (!last_expired_timeout
) {
8373 // Insert a dummy timeout into the list of timeouts between the
8374 // portion of the list that we are about to process now and those
8375 // timeouts that will be processed in a future call to
8376 // win_run_timeout(). This dummy timeout serves as the head of the
8377 // list for any timeouts inserted as a result of running a timeout.
8378 dummy_timeout
.mFiringDepth
= firingDepth
;
8379 PR_INSERT_AFTER(&dummy_timeout
, last_expired_timeout
);
8381 // Don't let ClearWindowTimeouts throw away our stack-allocated
8383 dummy_timeout
.AddRef();
8384 dummy_timeout
.AddRef();
8386 last_insertion_point
= mTimeoutInsertionPoint
;
8387 mTimeoutInsertionPoint
= &dummy_timeout
;
8389 for (timeout
= FirstTimeout();
8390 timeout
!= &dummy_timeout
&& !IsFrozen();
8391 timeout
= nextTimeout
) {
8392 nextTimeout
= timeout
->Next();
8394 if (timeout
->mFiringDepth
!= firingDepth
) {
8395 // We skip the timeout since it's on the list to run at another
8401 if (mTimeoutsSuspendDepth
) {
8402 // Some timer did suspend us. Make sure the
8403 // rest of the timers get executed later.
8404 timeout
->mFiringDepth
= 0;
8408 // The timeout is on the list to run at this depth, go ahead and
8411 // Get the script context (a strong ref to prevent it going away)
8412 // for this timeout and ensure the script language is enabled.
8413 nsCOMPtr
<nsIScriptContext
> scx
= GetScriptContextInternal(
8414 timeout
->mScriptHandler
->GetScriptTypeID());
8417 // No context means this window was closed or never properly
8418 // initialized for this language.
8422 // The "scripts disabled" concept is still a little vague wrt
8423 // multiple languages. Prepare for the day when languages can be
8424 // disabled independently of the other languages...
8425 if (!scx
->GetScriptsEnabled()) {
8426 // Scripts were enabled once in this window (unless aTimeout ==
8427 // nsnull) but now scripts are disabled (we might be in
8428 // print-preview, for instance), this means we shouldn't run any
8429 // timeouts at this point.
8431 // If scripts are enabled for this language in this window again
8432 // we'll fire the timeouts that are due at that point.
8436 // This timeout is good to run
8437 nsTimeout
*last_running_timeout
= mRunningTimeout
;
8438 mRunningTimeout
= timeout
;
8439 timeout
->mRunning
= PR_TRUE
;
8441 // Push this timeout's popup control state, which should only be
8442 // eabled the first time a timeout fires that was created while
8443 // popups were enabled and with a delay less than
8444 // "dom.disable_open_click_delay".
8445 nsAutoPopupStatePusher
popupStatePusher(timeout
->mPopupState
);
8447 // Clear the timeout's popup state, if any, to prevent interval
8448 // timeouts from repeatedly opening poups.
8449 timeout
->mPopupState
= openAbused
;
8451 // Hold on to the timeout in case mExpr or mFunObj releases its
8455 ++gRunningTimeoutDepth
;
8456 ++mTimeoutFiringDepth
;
8458 PRBool trackNestingLevel
= !timeout
->mInterval
;
8459 PRUint32 nestingLevel
;
8460 if (trackNestingLevel
) {
8461 nestingLevel
= sNestingLevel
;
8462 sNestingLevel
= timeout
->mNestingLevel
;
8465 nsCOMPtr
<nsIScriptTimeoutHandler
> handler(timeout
->mScriptHandler
);
8466 void *scriptObject
= handler
->GetScriptObject();
8467 if (!scriptObject
) {
8468 // Evaluate the timeout expression.
8469 const PRUnichar
*script
= handler
->GetHandlerText();
8470 NS_ASSERTION(script
, "timeout has no script nor handler text!");
8472 const char *filename
= nsnull
;
8473 PRUint32 lineNo
= 0;
8474 handler
->GetLocation(&filename
, &lineNo
);
8476 NS_TIME_FUNCTION_MARK("(file: %s, line: %d)", filename
, lineNo
);
8478 PRBool is_undefined
;
8479 scx
->EvaluateString(nsDependentString(script
),
8480 GetScriptGlobal(handler
->GetScriptTypeID()),
8481 timeout
->mPrincipal
, filename
, lineNo
,
8482 handler
->GetScriptVersion(), nsnull
,
8485 // Let the script handler know about the "secret" final argument that
8486 // indicates timeout lateness in milliseconds
8487 PRTime lateness
= now
- timeout
->mWhen
;
8489 // Make sure to cast the unsigned PR_USEC_PER_MSEC to signed
8490 // PRTime to make the division do the right thing on 64-bit
8491 // platforms whether lateness is positive or negative.
8492 handler
->SetLateness((PRIntervalTime
)(lateness
/
8493 (PRTime
)PR_USEC_PER_MSEC
));
8495 nsCOMPtr
<nsIVariant
> dummy
;
8496 nsCOMPtr
<nsISupports
> me(static_cast<nsIDOMWindow
*>(this));
8497 scx
->CallEventHandler(me
,
8498 GetScriptGlobal(handler
->GetScriptTypeID()),
8499 scriptObject
, handler
->GetArgv(),
8500 // XXXmarkh - consider allowing CallEventHandler to
8502 getter_AddRefs(dummy
));
8505 handler
= nsnull
; // drop reference before dropping timeout refs.
8507 if (trackNestingLevel
) {
8508 sNestingLevel
= nestingLevel
;
8511 --mTimeoutFiringDepth
;
8512 --gRunningTimeoutDepth
;
8514 mRunningTimeout
= last_running_timeout
;
8515 timeout
->mRunning
= PR_FALSE
;
8517 // We ignore any failures from calling EvaluateString() or
8518 // CallEventHandler() on the context here since we're in a loop
8519 // where we're likely to be running timeouts whose OS timers
8520 // didn't fire in time and we don't want to not fire those timers
8521 // now just because execution of one timer failed. We can't
8522 // propagate the error to anyone who cares about it from this
8523 // point anyway, and the script context should have already reported
8524 // the script error in the usual way - so we just drop it.
8526 // If all timeouts were cleared and |timeout != aTimeout| then
8527 // |timeout| may be the last reference to the timeout so check if
8528 // it was cleared before releasing it.
8529 PRBool timeout_was_cleared
= timeout
->mCleared
;
8533 if (timeout_was_cleared
) {
8534 // The running timeout's window was cleared, this means that
8535 // ClearAllTimeouts() was called from a *nested* call, possibly
8536 // through a timeout that fired while a modal (to this window)
8537 // dialog was open or through other non-obvious paths.
8539 mTimeoutInsertionPoint
= last_insertion_point
;
8544 PRBool isInterval
= PR_FALSE
;
8546 // If we have a regular interval timer, we re-schedule the
8547 // timeout, accounting for clock drift.
8548 if (timeout
->mInterval
) {
8549 // Compute time to next timeout for interval timer.
8550 PRTime nextInterval
= (PRTime
)timeout
->mInterval
* PR_USEC_PER_MSEC
;
8552 // Make sure nextInterval is at least DOM_MIN_TIMEOUT_VALUE.
8553 // Note: We must cast the rhs expression to PRTime to work
8554 // around what looks like a compiler bug on x86_64.
8555 if (nextInterval
< (PRTime
)(DOM_MIN_TIMEOUT_VALUE
* PR_USEC_PER_MSEC
)) {
8556 nextInterval
= DOM_MIN_TIMEOUT_VALUE
* PR_USEC_PER_MSEC
;
8559 // If we're running pending timeouts because they've been temporarily
8560 // disabled (!aTimeout), set the next interval to be relative to "now",
8561 // and not to when the timeout that was pending should have fired. Also
8562 // check if the next interval timeout is overdue. If so, then restart
8563 // the interval from now.
8564 if (!aTimeout
|| nextInterval
+ timeout
->mWhen
<= now
)
8565 nextInterval
+= now
;
8567 nextInterval
+= timeout
->mWhen
;
8569 PRTime delay
= nextInterval
- PR_Now();
8571 // And make sure delay is nonnegative; that might happen if the timer
8572 // thread is firing our timers somewhat early.
8577 if (timeout
->mTimer
) {
8578 timeout
->mWhen
= nextInterval
;
8580 // Reschedule the OS timer. Don't bother returning any error
8581 // codes if this fails since the callers of this method
8582 // doesn't care about them nobody who cares about them
8585 // Make sure to cast the unsigned PR_USEC_PER_MSEC to signed
8586 // PRTime to make the division do the right thing on 64-bit
8587 // platforms whether delay is positive or negative (which we
8588 // know is always positive here, but cast anyways for
8590 nsresult rv
= timeout
->mTimer
->
8591 InitWithFuncCallback(TimerCallback
, timeout
,
8592 (PRInt32
)(delay
/ (PRTime
)PR_USEC_PER_MSEC
),
8593 nsITimer::TYPE_ONE_SHOT
);
8595 if (NS_FAILED(rv
)) {
8596 NS_ERROR("Error initializing timer for DOM timeout!");
8598 // We failed to initialize the new OS timer, this timer does
8599 // us no good here so we just cancel it (just in case) and
8600 // null out the pointer to the OS timer, this will release the
8601 // OS timer. As we continue executing the code below we'll end
8602 // up deleting the timeout since it's not an interval timeout
8603 // any more (since timeout->mTimer == nsnull).
8604 timeout
->mTimer
->Cancel();
8605 timeout
->mTimer
= nsnull
;
8607 // Now that the OS timer no longer has a reference to the
8608 // timeout we need to drop that reference.
8612 NS_ASSERTION(IsFrozen() || mTimeoutsSuspendDepth
,
8613 "How'd our timer end up null if we're not frozen or "
8616 timeout
->mWhen
= delay
;
8617 isInterval
= PR_TRUE
;
8621 if (timeout
->mTimer
) {
8622 if (timeout
->mInterval
) {
8623 isInterval
= PR_TRUE
;
8625 // The timeout still has an OS timer, and it's not an
8626 // interval, that means that the OS timer could still fire (if
8627 // it didn't already, i.e. aTimeout == timeout), cancel the OS
8628 // timer and release its reference to the timeout.
8629 timeout
->mTimer
->Cancel();
8630 timeout
->mTimer
= nsnull
;
8636 // Running a timeout can cause another timeout to be deleted, so
8637 // we need to reset the pointer to the following timeout.
8638 nextTimeout
= timeout
->Next();
8640 PR_REMOVE_LINK(timeout
);
8643 // Reschedule an interval timeout. Insert interval timeout
8644 // onto list sorted in deadline order.
8646 InsertTimeoutIntoList(timeout
);
8649 // Release the timeout struct since it's possibly out of the list
8653 // Take the dummy timeout off the head of the list
8654 PR_REMOVE_LINK(&dummy_timeout
);
8656 mTimeoutInsertionPoint
= last_insertion_point
;
8660 nsTimeout::Release()
8665 // language specific cleanup done as mScriptHandler destructs...
8667 // Kill the timer if it is still alive.
8685 nsGlobalWindow::ClearTimeoutOrInterval(PRInt32 aTimerID
)
8687 FORWARD_TO_INNER(ClearTimeoutOrInterval
, (aTimerID
), NS_ERROR_NOT_INITIALIZED
);
8689 PRUint32 public_id
= (PRUint32
)aTimerID
;
8692 for (timeout
= FirstTimeout();
8694 timeout
= timeout
->Next()) {
8695 if (timeout
->mPublicId
== public_id
) {
8696 if (timeout
->mRunning
) {
8697 /* We're running from inside the timeout. Mark this
8698 timeout for deferred deletion by the code in
8700 timeout
->mInterval
= 0;
8703 /* Delete the timeout from the pending timeout list */
8704 PR_REMOVE_LINK(timeout
);
8706 if (timeout
->mTimer
) {
8707 timeout
->mTimer
->Cancel();
8708 timeout
->mTimer
= nsnull
;
8720 // A JavaScript specific version.
8722 nsGlobalWindow::ClearTimeoutOrInterval()
8724 FORWARD_TO_INNER(ClearTimeoutOrInterval
, (), NS_ERROR_NOT_INITIALIZED
);
8726 nsresult rv
= NS_OK
;
8727 nsAXPCNativeCallContext
*ncc
= nsnull
;
8729 rv
= nsContentUtils::XPConnect()->
8730 GetCurrentNativeCallContext(&ncc
);
8731 NS_ENSURE_SUCCESS(rv
, rv
);
8734 return NS_ERROR_NOT_AVAILABLE
;
8736 JSContext
*cx
= nsnull
;
8738 rv
= ncc
->GetJSContext(&cx
);
8739 NS_ENSURE_SUCCESS(rv
, rv
);
8743 ncc
->GetArgc(&argc
);
8746 // No arguments, return early.
8751 jsval
*argv
= nsnull
;
8753 ncc
->GetArgvPtr(&argv
);
8757 JSAutoRequest
ar(cx
);
8759 // XXXjst: Can we deal with this w/o using GetCurrentNativeCallContext()
8760 if (argv
[0] == JSVAL_VOID
|| !::JS_ValueToInt32(cx
, argv
[0], &timer_id
) ||
8762 // Undefined or non-positive number passed as argument, return
8763 // early. Make sure that JS_ValueToInt32 didn't set an exception.
8765 ::JS_ClearPendingException(cx
);
8769 return ClearTimeoutOrInterval(timer_id
);
8773 nsGlobalWindow::ClearAllTimeouts()
8775 nsTimeout
*timeout
, *nextTimeout
;
8777 for (timeout
= FirstTimeout(); IsTimeout(timeout
); timeout
= nextTimeout
) {
8778 /* If RunTimeout() is higher up on the stack for this
8779 window, e.g. as a result of document.write from a timeout,
8780 then we need to reset the list insertion point for
8781 newly-created timeouts in case the user adds a timeout,
8782 before we pop the stack back to RunTimeout. */
8783 if (mRunningTimeout
== timeout
)
8784 mTimeoutInsertionPoint
= nsnull
;
8786 nextTimeout
= timeout
->Next();
8788 if (timeout
->mTimer
) {
8789 timeout
->mTimer
->Cancel();
8790 timeout
->mTimer
= nsnull
;
8792 // Drop the count since the timer isn't going to hold on
8797 // Set timeout->mCleared to true to indicate that the timeout was
8798 // cleared and taken out of the list of timeouts
8799 timeout
->mCleared
= PR_TRUE
;
8801 // Drop the count since we're removing it from the list.
8805 // Clear out our list
8806 PR_INIT_CLIST(&mTimeouts
);
8810 nsGlobalWindow::InsertTimeoutIntoList(nsTimeout
*aTimeout
)
8812 NS_ASSERTION(IsInnerWindow(),
8813 "InsertTimeoutIntoList() called on outer window!");
8815 // Start at mLastTimeout and go backwards. Don't go further than
8816 // mTimeoutInsertionPoint, though. This optimizes for the common case of
8817 // insertion at the end.
8818 nsTimeout
* prevSibling
;
8819 for (prevSibling
= LastTimeout();
8820 IsTimeout(prevSibling
) && prevSibling
!= mTimeoutInsertionPoint
&&
8821 prevSibling
->mWhen
> aTimeout
->mWhen
;
8822 prevSibling
= prevSibling
->Prev()) {
8823 /* Do nothing; just searching */
8826 // Now link in aTimeout after prevSibling.
8827 PR_INSERT_AFTER(aTimeout
, prevSibling
);
8829 aTimeout
->mFiringDepth
= 0;
8831 // Increment the timeout's reference count since it's now held on to
8838 nsGlobalWindow::TimerCallback(nsITimer
*aTimer
, void *aClosure
)
8840 nsTimeout
*timeout
= (nsTimeout
*)aClosure
;
8842 // Hold on to the timeout to ensure it doesn't go away while it's
8843 // being handled (aka kungFuDeathGrip).
8846 timeout
->mWindow
->RunTimeout(timeout
);
8848 // Drop our reference to the timeout now that we're done with it.
8852 //*****************************************************************************
8853 // nsGlobalWindow: Helper Functions
8854 //*****************************************************************************
8857 nsGlobalWindow::GetTreeOwner(nsIDocShellTreeOwner
**aTreeOwner
)
8859 FORWARD_TO_OUTER(GetTreeOwner
, (aTreeOwner
), NS_ERROR_NOT_INITIALIZED
);
8861 nsCOMPtr
<nsIDocShellTreeItem
> docShellAsItem(do_QueryInterface(mDocShell
));
8863 // If there's no docShellAsItem, this window must have been closed,
8864 // in that case there is no tree owner.
8866 if (!docShellAsItem
) {
8867 *aTreeOwner
= nsnull
;
8872 return docShellAsItem
->GetTreeOwner(aTreeOwner
);
8876 nsGlobalWindow::GetTreeOwner(nsIBaseWindow
**aTreeOwner
)
8878 FORWARD_TO_OUTER(GetTreeOwner
, (aTreeOwner
), NS_ERROR_NOT_INITIALIZED
);
8880 nsCOMPtr
<nsIDocShellTreeItem
> docShellAsItem(do_QueryInterface(mDocShell
));
8881 nsCOMPtr
<nsIDocShellTreeOwner
> treeOwner
;
8883 // If there's no docShellAsItem, this window must have been closed,
8884 // in that case there is no tree owner.
8886 if (docShellAsItem
) {
8887 docShellAsItem
->GetTreeOwner(getter_AddRefs(treeOwner
));
8891 *aTreeOwner
= nsnull
;
8895 return CallQueryInterface(treeOwner
, aTreeOwner
);
8899 nsGlobalWindow::GetWebBrowserChrome(nsIWebBrowserChrome
**aBrowserChrome
)
8901 nsCOMPtr
<nsIDocShellTreeOwner
> treeOwner
;
8902 GetTreeOwner(getter_AddRefs(treeOwner
));
8904 nsCOMPtr
<nsIWebBrowserChrome
> browserChrome(do_GetInterface(treeOwner
));
8905 NS_IF_ADDREF(*aBrowserChrome
= browserChrome
);
8910 nsIScrollableFrame
*
8911 nsGlobalWindow::GetScrollFrame()
8913 FORWARD_TO_OUTER(GetScrollFrame
, (), nsnull
);
8919 nsCOMPtr
<nsIPresShell
> presShell
;
8920 mDocShell
->GetPresShell(getter_AddRefs(presShell
));
8922 return presShell
->GetRootScrollFrameAsScrollable();
8928 nsGlobalWindow::BuildURIfromBase(const char *aURL
, nsIURI
**aBuiltURI
,
8929 PRBool
*aFreeSecurityPass
,
8930 JSContext
**aCXused
)
8932 nsIScriptContext
*scx
= GetContextInternal();
8933 JSContext
*cx
= nsnull
;
8935 *aBuiltURI
= nsnull
;
8936 *aFreeSecurityPass
= PR_FALSE
;
8941 NS_ASSERTION(scx
, "opening window missing its context");
8942 NS_ASSERTION(mDocument
, "opening window missing its document");
8943 if (!scx
|| !mDocument
)
8944 return NS_ERROR_FAILURE
;
8946 nsCOMPtr
<nsIDOMChromeWindow
> chrome_win
=
8947 do_QueryInterface(static_cast<nsIDOMWindow
*>(this));
8949 if (nsContentUtils::IsCallerChrome() && !chrome_win
) {
8950 // If open() is called from chrome on a non-chrome window, we'll
8951 // use the context from the window on which open() is being called
8952 // to prevent giving chrome priveleges to new windows opened in
8953 // such a way. This also makes us get the appropriate base URI for
8954 // the below URI resolution code.
8956 cx
= (JSContext
*)scx
->GetNativeContext();
8958 // get the JSContext from the call stack
8959 nsCOMPtr
<nsIThreadJSContextStack
> stack(do_GetService(sJSStackContractID
));
8964 /* resolve the URI, which could be relative to the calling window
8965 (note the algorithm to get the base URI should match the one
8966 used to actually kick off the load in nsWindowWatcher.cpp). */
8967 nsCAutoString
charset(NS_LITERAL_CSTRING("UTF-8")); // default to utf-8
8968 nsIURI
* baseURI
= nsnull
;
8969 nsCOMPtr
<nsIURI
> uriToLoad
;
8970 nsCOMPtr
<nsIDOMWindow
> sourceWindow
;
8973 nsIScriptContext
*scriptcx
= nsJSUtils::GetDynamicScriptContext(cx
);
8975 sourceWindow
= do_QueryInterface(scriptcx
->GetGlobalObject());
8978 if (!sourceWindow
) {
8979 sourceWindow
= do_QueryInterface(NS_ISUPPORTS_CAST(nsIDOMWindow
*, this));
8980 *aFreeSecurityPass
= PR_TRUE
;
8984 nsCOMPtr
<nsIDOMDocument
> domDoc
;
8985 sourceWindow
->GetDocument(getter_AddRefs(domDoc
));
8986 nsCOMPtr
<nsIDocument
> doc(do_QueryInterface(domDoc
));
8988 baseURI
= doc
->GetDocBaseURI();
8989 charset
= doc
->GetDocumentCharacterSet();
8995 return NS_NewURI(aBuiltURI
, nsDependentCString(aURL
), charset
.get(), baseURI
);
8999 nsGlobalWindow::SecurityCheckURL(const char *aURL
)
9003 nsCOMPtr
<nsIURI
> uri
;
9005 if (NS_FAILED(BuildURIfromBase(aURL
, getter_AddRefs(uri
), &freePass
, &cx
)))
9006 return NS_ERROR_FAILURE
;
9008 if (!freePass
&& NS_FAILED(nsContentUtils::GetSecurityManager()->
9009 CheckLoadURIFromScript(cx
, uri
)))
9010 return NS_ERROR_FAILURE
;
9016 nsGlobalWindow::FlushPendingNotifications(mozFlushType aType
)
9019 mDoc
->FlushPendingNotifications(aType
);
9024 nsGlobalWindow::EnsureSizeUpToDate()
9026 // If we're a subframe, make sure our size is up to date. It's OK that this
9027 // crosses the content/chrome boundary, since chrome can have pending reflows
9029 nsGlobalWindow
*parent
=
9030 static_cast<nsGlobalWindow
*>(GetPrivateParent());
9032 parent
->FlushPendingNotifications(Flush_Layout
);
9037 nsGlobalWindow::SaveWindowState(nsISupports
**aState
)
9039 NS_PRECONDITION(IsOuterWindow(), "Can't save the inner window's state");
9043 if (!mContext
|| !mJSObject
) {
9044 // The window may be getting torn down; don't bother saving state.
9048 nsGlobalWindow
*inner
= GetCurrentInnerWindowInternal();
9049 NS_ASSERTION(inner
, "No inner window to save");
9051 // Don't do anything else to this inner window! After this point, all
9052 // calls to SetTimeoutOrInterval will create entries in the timeout
9053 // list that will only run after this window has come out of the bfcache.
9054 // Also, while we're frozen, we won't dispatch online/offline events
9058 // Remember the outer window's XPConnect prototype.
9059 nsCOMPtr
<nsIClassInfo
> ci
=
9060 do_QueryInterface((nsIScriptGlobalObject
*)this);
9061 nsCOMPtr
<nsIXPConnectJSObjectHolder
> proto
;
9062 nsresult rv
= nsContentUtils::XPConnect()->
9063 GetWrappedNativePrototype((JSContext
*)mContext
->GetNativeContext(),
9064 mJSObject
, ci
, getter_AddRefs(proto
));
9065 NS_ENSURE_SUCCESS(rv
, rv
);
9067 nsCOMPtr
<nsISupports
> state
= new WindowStateHolder(inner
,
9072 NS_ENSURE_TRUE(state
, NS_ERROR_OUT_OF_MEMORY
);
9074 #ifdef DEBUG_PAGE_CACHE
9075 printf("saving window state, state = %p\n", (void*)state
);
9078 state
.swap(*aState
);
9083 nsGlobalWindow::RestoreWindowState(nsISupports
*aState
)
9085 NS_ASSERTION(IsOuterWindow(), "Cannot restore an inner window");
9087 if (!mContext
|| !mJSObject
) {
9088 // The window may be getting torn down; don't bother restoring state.
9092 nsCOMPtr
<WindowStateHolder
> holder
= do_QueryInterface(aState
);
9093 NS_ENSURE_TRUE(holder
, NS_ERROR_FAILURE
);
9095 #ifdef DEBUG_PAGE_CACHE
9096 printf("restoring window state, state = %p\n", (void*)holder
);
9099 // And we're ready to go!
9100 nsGlobalWindow
*inner
= GetCurrentInnerWindowInternal();
9102 // if a link is focused, refocus with the FLAG_SHOWRING flag set. This makes
9103 // it easy to tell which link was last clicked when going back a page.
9104 nsIContent
* focusedNode
= inner
->GetFocusedNode();
9105 if (IsLink(focusedNode
)) {
9106 nsIFocusManager
* fm
= nsFocusManager::GetFocusManager();
9108 nsCOMPtr
<nsIDOMElement
> focusedElement(do_QueryInterface(focusedNode
));
9109 fm
->SetFocus(focusedElement
, nsIFocusManager::FLAG_NOSCROLL
|
9110 nsIFocusManager::FLAG_SHOWRING
);
9116 holder
->DidRestoreWindow();
9122 nsGlobalWindow::SuspendTimeouts(PRUint32 aIncrease
,
9123 PRBool aFreezeChildren
)
9125 FORWARD_TO_INNER_VOID(SuspendTimeouts
, (aIncrease
, aFreezeChildren
));
9127 PRBool suspended
= (mTimeoutsSuspendDepth
!= 0);
9128 mTimeoutsSuspendDepth
+= aIncrease
;
9131 nsDOMThreadService
* dts
= nsDOMThreadService::get();
9133 dts
->SuspendWorkersForGlobal(static_cast<nsIScriptGlobalObject
*>(this));
9136 PRTime now
= PR_Now();
9137 for (nsTimeout
*t
= FirstTimeout(); IsTimeout(t
); t
= t
->Next()) {
9138 // Change mWhen to be the time remaining for this timer.
9144 // Drop the XPCOM timer; we'll reschedule when restoring the state.
9146 t
->mTimer
->Cancel();
9149 // Drop the reference that the timer's closure had on this timeout, we'll
9150 // add it back in ResumeTimeouts. Note that it shouldn't matter that we're
9151 // passing null for the context, since this shouldn't actually release this
9158 // Suspend our children as well.
9159 nsCOMPtr
<nsIDocShellTreeNode
> node(do_QueryInterface(GetDocShell()));
9161 PRInt32 childCount
= 0;
9162 node
->GetChildCount(&childCount
);
9164 for (PRInt32 i
= 0; i
< childCount
; ++i
) {
9165 nsCOMPtr
<nsIDocShellTreeItem
> childShell
;
9166 node
->GetChildAt(i
, getter_AddRefs(childShell
));
9167 NS_ASSERTION(childShell
, "null child shell");
9169 nsCOMPtr
<nsPIDOMWindow
> pWin
= do_GetInterface(childShell
);
9171 nsGlobalWindow
*win
=
9172 static_cast<nsGlobalWindow
*>
9173 (static_cast<nsPIDOMWindow
*>(pWin
));
9174 NS_ASSERTION(win
->IsOuterWindow(), "Expected outer window");
9175 nsGlobalWindow
* inner
= win
->GetCurrentInnerWindowInternal();
9177 // This is a bit hackish. Only freeze/suspend windows which are truly our
9179 nsCOMPtr
<nsIContent
> frame
= do_QueryInterface(pWin
->GetFrameElementInternal());
9180 if (!mDoc
|| !frame
|| mDoc
!= frame
->GetOwnerDoc() || !inner
) {
9184 win
->SuspendTimeouts(aIncrease
, aFreezeChildren
);
9186 if (inner
&& aFreezeChildren
) {
9195 nsGlobalWindow::ResumeTimeouts(PRBool aThawChildren
)
9197 FORWARD_TO_INNER(ResumeTimeouts
, (), NS_ERROR_NOT_INITIALIZED
);
9199 NS_ASSERTION(mTimeoutsSuspendDepth
, "Mismatched calls to ResumeTimeouts!");
9200 --mTimeoutsSuspendDepth
;
9201 PRBool shouldResume
= (mTimeoutsSuspendDepth
== 0);
9205 nsDOMThreadService
* dts
= nsDOMThreadService::get();
9207 dts
->ResumeWorkersForGlobal(static_cast<nsIScriptGlobalObject
*>(this));
9210 // Restore all of the timeouts, using the stored time remaining
9211 // (stored in timeout->mWhen).
9213 PRTime now
= PR_Now();
9216 PRBool _seenDummyTimeout
= PR_FALSE
;
9219 for (nsTimeout
*t
= FirstTimeout(); IsTimeout(t
); t
= t
->Next()) {
9220 // There's a chance we're being called with RunTimeout on the stack in which
9221 // case we have a dummy timeout in the list that *must not* be resumed. It
9222 // can be identified by a null mWindow.
9225 NS_ASSERTION(!_seenDummyTimeout
, "More than one dummy timeout?!");
9226 _seenDummyTimeout
= PR_TRUE
;
9231 // Make sure to cast the unsigned PR_USEC_PER_MSEC to signed
9232 // PRTime to make the division do the right thing on 64-bit
9233 // platforms whether t->mWhen is positive or negative (which is
9234 // likely to always be positive here, but cast anyways for
9237 NS_MAX(((PRUint32
)(t
->mWhen
/ (PRTime
)PR_USEC_PER_MSEC
)),
9238 (PRUint32
)DOM_MIN_TIMEOUT_VALUE
);
9240 // Set mWhen back to the time when the timer is supposed to
9244 t
->mTimer
= do_CreateInstance("@mozilla.org/timer;1");
9245 NS_ENSURE_TRUE(t
->mTimer
, NS_ERROR_OUT_OF_MEMORY
);
9247 rv
= t
->mTimer
->InitWithFuncCallback(TimerCallback
, t
, delay
,
9248 nsITimer::TYPE_ONE_SHOT
);
9249 if (NS_FAILED(rv
)) {
9254 // Add a reference for the new timer's closure.
9259 // Resume our children as well.
9260 nsCOMPtr
<nsIDocShellTreeNode
> node
=
9261 do_QueryInterface(GetDocShell());
9263 PRInt32 childCount
= 0;
9264 node
->GetChildCount(&childCount
);
9266 for (PRInt32 i
= 0; i
< childCount
; ++i
) {
9267 nsCOMPtr
<nsIDocShellTreeItem
> childShell
;
9268 node
->GetChildAt(i
, getter_AddRefs(childShell
));
9269 NS_ASSERTION(childShell
, "null child shell");
9271 nsCOMPtr
<nsPIDOMWindow
> pWin
= do_GetInterface(childShell
);
9273 nsGlobalWindow
*win
=
9274 static_cast<nsGlobalWindow
*>
9275 (static_cast<nsPIDOMWindow
*>(pWin
));
9277 NS_ASSERTION(win
->IsOuterWindow(), "Expected outer window");
9278 nsGlobalWindow
* inner
= win
->GetCurrentInnerWindowInternal();
9280 // This is a bit hackish. Only thaw/resume windows which are truly our
9282 nsCOMPtr
<nsIContent
> frame
= do_QueryInterface(pWin
->GetFrameElementInternal());
9283 if (!mDoc
|| !frame
|| mDoc
!= frame
->GetOwnerDoc() || !inner
) {
9287 if (inner
&& aThawChildren
) {
9291 rv
= win
->ResumeTimeouts(aThawChildren
);
9292 NS_ENSURE_SUCCESS(rv
, rv
);
9301 nsGlobalWindow::TimeoutSuspendCount()
9303 FORWARD_TO_INNER(TimeoutSuspendCount
, (), 0);
9304 return mTimeoutsSuspendDepth
;
9308 nsGlobalWindow::GetScriptTypeID(PRUint32
*aScriptType
)
9310 NS_ERROR("No default script type here - ask some element");
9311 return nsIProgrammingLanguage::UNKNOWN
;
9315 nsGlobalWindow::SetScriptTypeID(PRUint32 aScriptType
)
9317 NS_ERROR("Can't change default script type for a document");
9318 return NS_ERROR_NOT_IMPLEMENTED
;
9322 nsGlobalWindow::SetHasOrientationEventListener()
9324 nsCOMPtr
<nsIAccelerometer
> ac
=
9325 do_GetService(NS_ACCELEROMETER_CONTRACTID
);
9328 mHasAcceleration
= PR_TRUE
;
9329 ac
->AddWindowListener(this);
9333 // nsGlobalChromeWindow implementation
9335 NS_IMPL_CYCLE_COLLECTION_CLASS(nsGlobalChromeWindow
)
9336 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsGlobalChromeWindow
,
9338 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mBrowserDOMWindow
)
9339 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mMessageManager
)
9340 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
9342 DOMCI_DATA(ChromeWindow
, nsGlobalChromeWindow
)
9343 DOMCI_DATA(InnerChromeWindow
, nsGlobalChromeWindow
)
9345 // QueryInterface implementation for nsGlobalChromeWindow
9346 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsGlobalChromeWindow
)
9347 NS_INTERFACE_MAP_ENTRY(nsIDOMChromeWindow
)
9348 WINDOW_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(ChromeWindow
)
9349 NS_INTERFACE_MAP_END_INHERITING(nsGlobalWindow
)
9351 NS_IMPL_ADDREF_INHERITED(nsGlobalChromeWindow
, nsGlobalWindow
)
9352 NS_IMPL_RELEASE_INHERITED(nsGlobalChromeWindow
, nsGlobalWindow
)
9355 nsGlobalChromeWindow::GetWindowState(PRUint16
* aWindowState
)
9357 *aWindowState
= nsIDOMChromeWindow::STATE_NORMAL
;
9359 nsCOMPtr
<nsIWidget
> widget
= GetMainWidget();
9364 nsresult rv
= widget
->GetSizeMode(&aMode
);
9365 NS_ENSURE_SUCCESS(rv
, rv
);
9369 case nsSizeMode_Minimized
:
9370 *aWindowState
= nsIDOMChromeWindow::STATE_MINIMIZED
;
9372 case nsSizeMode_Maximized
:
9373 *aWindowState
= nsIDOMChromeWindow::STATE_MAXIMIZED
;
9375 case nsSizeMode_Fullscreen
:
9376 *aWindowState
= nsIDOMChromeWindow::STATE_FULLSCREEN
;
9378 case nsSizeMode_Normal
:
9379 *aWindowState
= nsIDOMChromeWindow::STATE_NORMAL
;
9382 NS_WARNING("Illegal window state for this chrome window");
9390 nsGlobalChromeWindow::Maximize()
9392 nsCOMPtr
<nsIWidget
> widget
= GetMainWidget();
9393 nsresult rv
= NS_OK
;
9396 rv
= widget
->SetSizeMode(nsSizeMode_Maximized
);
9403 nsGlobalChromeWindow::Minimize()
9405 nsCOMPtr
<nsIWidget
> widget
= GetMainWidget();
9406 nsresult rv
= NS_OK
;
9409 rv
= widget
->SetSizeMode(nsSizeMode_Minimized
);
9415 nsGlobalChromeWindow::Restore()
9417 nsCOMPtr
<nsIWidget
> widget
= GetMainWidget();
9418 nsresult rv
= NS_OK
;
9421 rv
= widget
->SetSizeMode(nsSizeMode_Normal
);
9428 nsGlobalChromeWindow::GetAttention()
9430 return GetAttentionWithCycleCount(-1);
9434 nsGlobalChromeWindow::GetAttentionWithCycleCount(PRInt32 aCycleCount
)
9436 nsCOMPtr
<nsIWidget
> widget
= GetMainWidget();
9437 nsresult rv
= NS_OK
;
9440 rv
= widget
->GetAttention(aCycleCount
);
9447 nsGlobalChromeWindow::BeginWindowMove(nsIDOMEvent
*aMouseDownEvent
)
9449 nsCOMPtr
<nsIWidget
> widget
= GetMainWidget();
9454 nsCOMPtr
<nsIPrivateDOMEvent
> privEvent
= do_QueryInterface(aMouseDownEvent
);
9455 NS_ENSURE_TRUE(privEvent
, NS_ERROR_FAILURE
);
9456 nsEvent
*internalEvent
= privEvent
->GetInternalNSEvent();
9457 NS_ENSURE_TRUE(internalEvent
&&
9458 internalEvent
->eventStructType
== NS_MOUSE_EVENT
,
9460 nsMouseEvent
*mouseEvent
= static_cast<nsMouseEvent
*>(internalEvent
);
9462 return widget
->BeginMoveDrag(mouseEvent
);
9465 //Note: This call will lock the cursor, it will not change as it moves.
9466 //To unlock, the cursor must be set back to CURSOR_AUTO.
9468 nsGlobalChromeWindow::SetCursor(const nsAString
& aCursor
)
9470 FORWARD_TO_OUTER_CHROME(SetCursor
, (aCursor
), NS_ERROR_NOT_INITIALIZED
);
9472 nsresult rv
= NS_OK
;
9475 // use C strings to keep the code/data size down
9476 NS_ConvertUTF16toUTF8
cursorString(aCursor
);
9478 if (cursorString
.Equals("auto"))
9479 cursor
= NS_STYLE_CURSOR_AUTO
;
9481 nsCSSKeyword keyword
= nsCSSKeywords::LookupKeyword(aCursor
);
9482 if (eCSSKeyword_UNKNOWN
== keyword
||
9483 !nsCSSProps::FindKeyword(keyword
, nsCSSProps::kCursorKTable
, cursor
)) {
9484 // XXX remove the following three values (leave return NS_OK) after 1.8
9485 // XXX since they should have been -moz- prefixed (covered by FindKeyword).
9486 // XXX (also remove |cursorString| at that point?).
9487 if (cursorString
.Equals("grab"))
9488 cursor
= NS_STYLE_CURSOR_GRAB
;
9489 else if (cursorString
.Equals("grabbing"))
9490 cursor
= NS_STYLE_CURSOR_GRABBING
;
9491 else if (cursorString
.Equals("spinning"))
9492 cursor
= NS_STYLE_CURSOR_SPINNING
;
9498 nsRefPtr
<nsPresContext
> presContext
;
9500 mDocShell
->GetPresContext(getter_AddRefs(presContext
));
9504 // Need root widget.
9505 nsCOMPtr
<nsIPresShell
> presShell
;
9506 mDocShell
->GetPresShell(getter_AddRefs(presShell
));
9507 NS_ENSURE_TRUE(presShell
, NS_ERROR_FAILURE
);
9509 nsIViewManager
* vm
= presShell
->GetViewManager();
9510 NS_ENSURE_TRUE(vm
, NS_ERROR_FAILURE
);
9513 vm
->GetRootView(rootView
);
9514 NS_ENSURE_TRUE(rootView
, NS_ERROR_FAILURE
);
9516 nsIWidget
* widget
= rootView
->GetNearestWidget(nsnull
);
9517 NS_ENSURE_TRUE(widget
, NS_ERROR_FAILURE
);
9519 // Call esm and set cursor.
9520 rv
= presContext
->EventStateManager()->SetCursor(cursor
, nsnull
,
9521 PR_FALSE
, 0.0f
, 0.0f
,
9529 nsGlobalChromeWindow::GetBrowserDOMWindow(nsIBrowserDOMWindow
**aBrowserWindow
)
9531 FORWARD_TO_OUTER_CHROME(GetBrowserDOMWindow
, (aBrowserWindow
),
9532 NS_ERROR_NOT_INITIALIZED
);
9534 NS_ENSURE_ARG_POINTER(aBrowserWindow
);
9536 *aBrowserWindow
= mBrowserDOMWindow
;
9537 NS_IF_ADDREF(*aBrowserWindow
);
9542 nsGlobalChromeWindow::SetBrowserDOMWindow(nsIBrowserDOMWindow
*aBrowserWindow
)
9544 FORWARD_TO_OUTER_CHROME(SetBrowserDOMWindow
, (aBrowserWindow
),
9545 NS_ERROR_NOT_INITIALIZED
);
9547 mBrowserDOMWindow
= aBrowserWindow
;
9552 nsGlobalChromeWindow::NotifyDefaultButtonLoaded(nsIDOMElement
* aDefaultButton
)
9555 NS_ENSURE_ARG(aDefaultButton
);
9557 // Don't snap to a disabled button.
9558 nsCOMPtr
<nsIDOMXULControlElement
> xulControl
=
9559 do_QueryInterface(aDefaultButton
);
9560 NS_ENSURE_TRUE(xulControl
, NS_ERROR_FAILURE
);
9562 nsresult rv
= xulControl
->GetDisabled(&disabled
);
9563 NS_ENSURE_SUCCESS(rv
, rv
);
9567 // Get the button rect in screen coordinates.
9568 nsCOMPtr
<nsIContent
> content(do_QueryInterface(aDefaultButton
));
9569 NS_ENSURE_TRUE(content
, NS_ERROR_FAILURE
);
9570 nsIFrame
*frame
= content
->GetPrimaryFrame();
9571 NS_ENSURE_TRUE(frame
, NS_ERROR_FAILURE
);
9572 nsIntRect buttonRect
= frame
->GetScreenRect();
9574 // Get the widget rect in screen coordinates.
9575 nsIWidget
*widget
= GetNearestWidget();
9576 NS_ENSURE_TRUE(widget
, NS_ERROR_FAILURE
);
9577 nsIntRect widgetRect
;
9578 rv
= widget
->GetScreenBounds(widgetRect
);
9579 NS_ENSURE_SUCCESS(rv
, rv
);
9581 // Convert the buttonRect coordinates from screen to the widget.
9582 buttonRect
-= widgetRect
.TopLeft();
9583 rv
= widget
->OnDefaultButtonLoaded(buttonRect
);
9584 if (rv
== NS_ERROR_NOT_IMPLEMENTED
)
9588 return NS_ERROR_NOT_IMPLEMENTED
;
9593 nsGlobalChromeWindow::GetMessageManager(nsIChromeFrameMessageManager
** aManager
)
9595 FORWARD_TO_INNER_CHROME(GetMessageManager
, (aManager
), NS_ERROR_FAILURE
);
9596 if (!mMessageManager
) {
9597 nsIScriptContext
* scx
= GetContextInternal();
9598 NS_ENSURE_STATE(scx
);
9599 JSContext
* cx
= (JSContext
*)scx
->GetNativeContext();
9600 NS_ENSURE_STATE(cx
);
9601 nsCOMPtr
<nsIChromeFrameMessageManager
> globalMM
=
9602 do_GetService("@mozilla.org/globalmessagemanager;1");
9604 new nsFrameMessageManager(PR_TRUE
,
9609 static_cast<nsFrameMessageManager
*>(globalMM
.get()),
9611 NS_ENSURE_TRUE(mMessageManager
, NS_ERROR_OUT_OF_MEMORY
);
9613 CallQueryInterface(mMessageManager
, aManager
);
9617 // nsGlobalModalWindow implementation
9619 // QueryInterface implementation for nsGlobalModalWindow
9620 NS_IMPL_CYCLE_COLLECTION_CLASS(nsGlobalModalWindow
)
9621 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsGlobalModalWindow
,
9623 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mReturnValue
)
9624 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
9626 DOMCI_DATA(ModalContentWindow
, nsGlobalModalWindow
)
9627 DOMCI_DATA(InnerModalContentWindow
, nsGlobalModalWindow
)
9629 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsGlobalModalWindow
)
9630 NS_INTERFACE_MAP_ENTRY(nsIDOMModalContentWindow
)
9631 WINDOW_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(ModalContentWindow
)
9632 NS_INTERFACE_MAP_END_INHERITING(nsGlobalWindow
)
9634 NS_IMPL_ADDREF_INHERITED(nsGlobalModalWindow
, nsGlobalWindow
)
9635 NS_IMPL_RELEASE_INHERITED(nsGlobalModalWindow
, nsGlobalWindow
)
9638 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsGlobalModalWindow
,
9640 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mReturnValue
)
9641 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
9645 nsGlobalModalWindow::GetDialogArguments(nsIArray
**aArguments
)
9647 FORWARD_TO_INNER_MODAL_CONTENT_WINDOW(GetDialogArguments
, (aArguments
),
9648 NS_ERROR_NOT_INITIALIZED
);
9650 PRBool subsumes
= PR_FALSE
;
9651 nsIPrincipal
*self
= GetPrincipal();
9652 if (self
&& NS_SUCCEEDED(self
->Subsumes(mArgumentsOrigin
, &subsumes
)) &&
9654 NS_IF_ADDREF(*aArguments
= mArguments
);
9656 *aArguments
= nsnull
;
9663 nsGlobalModalWindow::GetReturnValue(nsIVariant
**aRetVal
)
9665 FORWARD_TO_OUTER_MODAL_CONTENT_WINDOW(GetReturnValue
, (aRetVal
), NS_OK
);
9667 NS_IF_ADDREF(*aRetVal
= mReturnValue
);
9673 nsGlobalModalWindow::SetReturnValue(nsIVariant
*aRetVal
)
9675 FORWARD_TO_OUTER_MODAL_CONTENT_WINDOW(SetReturnValue
, (aRetVal
), NS_OK
);
9677 mReturnValue
= aRetVal
;
9683 nsGlobalModalWindow::SetNewDocument(nsIDocument
*aDocument
,
9684 nsISupports
*aState
)
9686 // If we're loading a new document into a modal dialog, clear the
9687 // return value that was set, if any, by the current document.
9689 mReturnValue
= nsnull
;
9692 return nsGlobalWindow::SetNewDocument(aDocument
, aState
);
9695 //*****************************************************************************
9696 // nsGlobalWindow: Creator Function (This should go away)
9697 //*****************************************************************************
9700 NS_NewScriptGlobalObject(PRBool aIsChrome
, PRBool aIsModalContentWindow
,
9701 nsIScriptGlobalObject
**aResult
)
9705 nsGlobalWindow
*global
;
9708 global
= new nsGlobalChromeWindow(nsnull
);
9709 } else if (aIsModalContentWindow
) {
9710 global
= new nsGlobalModalWindow(nsnull
);
9712 global
= new nsGlobalWindow(nsnull
);
9715 NS_ENSURE_TRUE(global
, NS_ERROR_OUT_OF_MEMORY
);
9717 NS_ADDREF(*aResult
= global
);
9722 //*****************************************************************************
9723 //*** nsNavigator: Object Management
9724 //*****************************************************************************
9726 nsNavigator::nsNavigator(nsIDocShell
*aDocShell
)
9727 : mDocShell(aDocShell
)
9731 nsNavigator::~nsNavigator()
9735 //*****************************************************************************
9736 // nsNavigator::nsISupports
9737 //*****************************************************************************
9740 DOMCI_DATA(Navigator
, nsNavigator
)
9742 // QueryInterface implementation for nsNavigator
9743 NS_INTERFACE_MAP_BEGIN(nsNavigator
)
9744 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIDOMNavigator
)
9745 NS_INTERFACE_MAP_ENTRY(nsIDOMNavigator
)
9746 NS_INTERFACE_MAP_ENTRY(nsIDOMClientInformation
)
9747 NS_INTERFACE_MAP_ENTRY(nsIDOMNavigatorGeolocation
)
9748 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Navigator
)
9749 NS_INTERFACE_MAP_END
9752 NS_IMPL_ADDREF(nsNavigator
)
9753 NS_IMPL_RELEASE(nsNavigator
)
9757 nsNavigator::SetDocShell(nsIDocShell
*aDocShell
)
9759 mDocShell
= aDocShell
;
9761 mPlugins
->SetDocShell(aDocShell
);
9763 // if there is a page transition, make sure delete the geolocation object
9766 mGeolocation
->Shutdown();
9767 mGeolocation
= nsnull
;
9771 //*****************************************************************************
9772 // nsNavigator::nsIDOMNavigator
9773 //*****************************************************************************
9776 nsNavigator::GetUserAgent(nsAString
& aUserAgent
)
9779 nsCOMPtr
<nsIHttpProtocolHandler
>
9780 service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX
"http", &rv
));
9781 if (NS_SUCCEEDED(rv
)) {
9783 rv
= service
->GetUserAgent(ua
);
9784 CopyASCIItoUTF16(ua
, aUserAgent
);
9791 nsNavigator::GetAppCodeName(nsAString
& aAppCodeName
)
9794 nsCOMPtr
<nsIHttpProtocolHandler
>
9795 service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX
"http", &rv
));
9796 if (NS_SUCCEEDED(rv
)) {
9797 nsCAutoString appName
;
9798 rv
= service
->GetAppName(appName
);
9799 CopyASCIItoUTF16(appName
, aAppCodeName
);
9806 nsNavigator::GetAppVersion(nsAString
& aAppVersion
)
9808 if (!nsContentUtils::IsCallerTrustedForRead()) {
9809 const nsAdoptingCString
& override
=
9810 nsContentUtils::GetCharPref("general.appversion.override");
9813 CopyUTF8toUTF16(override
, aAppVersion
);
9819 nsCOMPtr
<nsIHttpProtocolHandler
>
9820 service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX
"http", &rv
));
9821 if (NS_SUCCEEDED(rv
)) {
9823 rv
= service
->GetAppVersion(str
);
9824 CopyASCIItoUTF16(str
, aAppVersion
);
9828 aAppVersion
.AppendLiteral(" (");
9830 rv
= service
->GetPlatform(str
);
9834 AppendASCIItoUTF16(str
, aAppVersion
);
9836 aAppVersion
.Append(PRUnichar(')'));
9843 nsNavigator::GetAppName(nsAString
& aAppName
)
9845 if (!nsContentUtils::IsCallerTrustedForRead()) {
9846 const nsAdoptingCString
& override
=
9847 nsContentUtils::GetCharPref("general.appname.override");
9850 CopyUTF8toUTF16(override
, aAppName
);
9855 aAppName
.AssignLiteral("Netscape");
9860 nsNavigator::GetLanguage(nsAString
& aLanguage
)
9863 nsCOMPtr
<nsIHttpProtocolHandler
>
9864 service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX
"http", &rv
));
9865 if (NS_SUCCEEDED(rv
)) {
9867 rv
= service
->GetLanguage(lang
);
9868 CopyASCIItoUTF16(lang
, aLanguage
);
9875 nsNavigator::GetPlatform(nsAString
& aPlatform
)
9877 if (!nsContentUtils::IsCallerTrustedForRead()) {
9878 const nsAdoptingCString
& override
=
9879 nsContentUtils::GetCharPref("general.platform.override");
9882 CopyUTF8toUTF16(override
, aPlatform
);
9888 nsCOMPtr
<nsIHttpProtocolHandler
>
9889 service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX
"http", &rv
));
9890 if (NS_SUCCEEDED(rv
)) {
9891 // sorry for the #if platform ugliness, but Communicator is
9892 // likewise hardcoded and we're seeking backward compatibility
9895 aPlatform
.AssignLiteral("Win64");
9896 #elif defined(WIN32)
9897 aPlatform
.AssignLiteral("Win32");
9898 #elif defined(XP_MACOSX) && defined(__ppc__)
9899 aPlatform
.AssignLiteral("MacPPC");
9900 #elif defined(XP_MACOSX) && defined(__i386__)
9901 aPlatform
.AssignLiteral("MacIntel");
9902 #elif defined(XP_MACOSX) && defined(__x86_64__)
9903 aPlatform
.AssignLiteral("MacIntel");
9904 #elif defined(XP_OS2)
9905 aPlatform
.AssignLiteral("OS/2");
9907 // XXX Communicator uses compiled-in build-time string defines
9908 // to indicate the platform it was compiled *for*, not what it is
9909 // currently running *on* which is what this does.
9911 rv
= service
->GetOscpu(plat
);
9912 CopyASCIItoUTF16(plat
, aPlatform
);
9920 nsNavigator::GetOscpu(nsAString
& aOSCPU
)
9922 if (!nsContentUtils::IsCallerTrustedForRead()) {
9923 const nsAdoptingCString
& override
=
9924 nsContentUtils::GetCharPref("general.oscpu.override");
9927 CopyUTF8toUTF16(override
, aOSCPU
);
9933 nsCOMPtr
<nsIHttpProtocolHandler
>
9934 service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX
"http", &rv
));
9935 if (NS_SUCCEEDED(rv
)) {
9936 nsCAutoString oscpu
;
9937 rv
= service
->GetOscpu(oscpu
);
9938 CopyASCIItoUTF16(oscpu
, aOSCPU
);
9945 nsNavigator::GetVendor(nsAString
& aVendor
)
9948 nsCOMPtr
<nsIHttpProtocolHandler
>
9949 service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX
"http", &rv
));
9950 if (NS_SUCCEEDED(rv
)) {
9951 nsCAutoString vendor
;
9952 rv
= service
->GetVendor(vendor
);
9953 CopyASCIItoUTF16(vendor
, aVendor
);
9961 nsNavigator::GetVendorSub(nsAString
& aVendorSub
)
9964 nsCOMPtr
<nsIHttpProtocolHandler
>
9965 service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX
"http", &rv
));
9966 if (NS_SUCCEEDED(rv
)) {
9967 nsCAutoString vendor
;
9968 rv
= service
->GetVendorSub(vendor
);
9969 CopyASCIItoUTF16(vendor
, aVendorSub
);
9976 nsNavigator::GetProduct(nsAString
& aProduct
)
9979 nsCOMPtr
<nsIHttpProtocolHandler
>
9980 service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX
"http", &rv
));
9981 if (NS_SUCCEEDED(rv
)) {
9982 nsCAutoString product
;
9983 rv
= service
->GetProduct(product
);
9984 CopyASCIItoUTF16(product
, aProduct
);
9991 nsNavigator::GetProductSub(nsAString
& aProductSub
)
9993 if (!nsContentUtils::IsCallerTrustedForRead()) {
9994 const nsAdoptingCString
& override
=
9995 nsContentUtils::GetCharPref("general.productSub.override");
9998 CopyUTF8toUTF16(override
, aProductSub
);
10001 // 'general.useragent.productSub' backwards compatible with 1.8 branch.
10002 const nsAdoptingCString
& override2
=
10003 nsContentUtils::GetCharPref("general.useragent.productSub");
10006 CopyUTF8toUTF16(override2
, aProductSub
);
10013 nsCOMPtr
<nsIHttpProtocolHandler
>
10014 service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX
"http", &rv
));
10015 if (NS_SUCCEEDED(rv
)) {
10016 nsCAutoString productSub
;
10017 rv
= service
->GetProductSub(productSub
);
10018 CopyASCIItoUTF16(productSub
, aProductSub
);
10025 nsNavigator::GetSecurityPolicy(nsAString
& aSecurityPolicy
)
10031 nsNavigator::GetMimeTypes(nsIDOMMimeTypeArray
**aMimeTypes
)
10034 mMimeTypes
= new nsMimeTypeArray(this);
10036 return NS_ERROR_OUT_OF_MEMORY
;
10040 NS_ADDREF(*aMimeTypes
= mMimeTypes
);
10046 nsNavigator::GetPlugins(nsIDOMPluginArray
**aPlugins
)
10049 mPlugins
= new nsPluginArray(this, mDocShell
);
10051 return NS_ERROR_OUT_OF_MEMORY
;
10055 NS_ADDREF(*aPlugins
= mPlugins
);
10060 // values for the network.cookie.cookieBehavior pref are documented in
10061 // nsCookieService.cpp.
10062 #define COOKIE_BEHAVIOR_REJECT 2
10065 nsNavigator::GetCookieEnabled(PRBool
*aCookieEnabled
)
10068 (nsContentUtils::GetIntPref("network.cookie.cookieBehavior",
10069 COOKIE_BEHAVIOR_REJECT
) !=
10070 COOKIE_BEHAVIOR_REJECT
);
10076 nsNavigator::GetOnLine(PRBool
* aOnline
)
10078 NS_PRECONDITION(aOnline
, "Null out param");
10080 *aOnline
= !NS_IsOffline();
10085 nsNavigator::GetBuildID(nsAString
& aBuildID
)
10087 if (!nsContentUtils::IsCallerTrustedForRead()) {
10088 const nsAdoptingCString
& override
=
10089 nsContentUtils::GetCharPref("general.buildID.override");
10092 CopyUTF8toUTF16(override
, aBuildID
);
10097 nsCOMPtr
<nsIXULAppInfo
> appInfo
=
10098 do_GetService("@mozilla.org/xre/app-info;1");
10100 return NS_ERROR_NOT_IMPLEMENTED
;
10102 nsCAutoString buildID
;
10103 nsresult rv
= appInfo
->GetAppBuildID(buildID
);
10107 aBuildID
.Truncate();
10108 AppendASCIItoUTF16(buildID
, aBuildID
);
10113 nsNavigator::JavaEnabled(PRBool
*aReturn
)
10115 // Return true if we have a handler for "application/x-java-vm",
10116 // otherwise return false.
10117 *aReturn
= PR_FALSE
;
10120 mMimeTypes
= new nsMimeTypeArray(this);
10122 return NS_ERROR_OUT_OF_MEMORY
;
10125 RefreshMIMEArray();
10128 mMimeTypes
->GetLength(&count
);
10129 for (PRUint32 i
= 0; i
< count
; i
++) {
10131 nsIDOMMimeType
* type
= mMimeTypes
->GetItemAt(i
, &rv
);
10132 nsAutoString mimeString
;
10133 if (type
&& NS_SUCCEEDED(type
->GetType(mimeString
))) {
10134 if (mimeString
.EqualsLiteral("application/x-java-vm")) {
10135 *aReturn
= PR_TRUE
;
10145 nsNavigator::TaintEnabled(PRBool
*aReturn
)
10147 *aReturn
= PR_FALSE
;
10152 nsNavigator::LoadingNewDocument()
10154 // Release these so that they will be recreated for the
10155 // new document (if requested). The plugins or mime types
10156 // arrays may have changed. See bug 150087.
10157 mMimeTypes
= nsnull
;
10162 mGeolocation
->Shutdown();
10163 mGeolocation
= nsnull
;
10168 nsNavigator::RefreshMIMEArray()
10170 nsresult rv
= NS_OK
;
10172 rv
= mMimeTypes
->Refresh();
10176 //*****************************************************************************
10177 // nsNavigator::nsIDOMClientInformation
10178 //*****************************************************************************
10181 nsNavigator::RegisterContentHandler(const nsAString
& aMIMEType
,
10182 const nsAString
& aURI
,
10183 const nsAString
& aTitle
)
10185 nsCOMPtr
<nsIWebContentHandlerRegistrar
> registrar
=
10186 do_GetService(NS_WEBCONTENTHANDLERREGISTRAR_CONTRACTID
);
10187 if (registrar
&& mDocShell
) {
10188 nsCOMPtr
<nsIDOMWindow
> contentDOMWindow(do_GetInterface(mDocShell
));
10189 if (contentDOMWindow
)
10190 return registrar
->RegisterContentHandler(aMIMEType
, aURI
, aTitle
,
10198 nsNavigator::RegisterProtocolHandler(const nsAString
& aProtocol
,
10199 const nsAString
& aURI
,
10200 const nsAString
& aTitle
)
10202 nsCOMPtr
<nsIWebContentHandlerRegistrar
> registrar
=
10203 do_GetService(NS_WEBCONTENTHANDLERREGISTRAR_CONTRACTID
);
10204 if (registrar
&& mDocShell
) {
10205 nsCOMPtr
<nsIDOMWindow
> contentDOMWindow(do_GetInterface(mDocShell
));
10206 if (contentDOMWindow
)
10207 return registrar
->RegisterProtocolHandler(aProtocol
, aURI
, aTitle
,
10216 nsNavigator::MozIsLocallyAvailable(const nsAString
&aURI
,
10217 PRBool aWhenOffline
,
10218 PRBool
*aIsAvailable
)
10220 nsCOMPtr
<nsIURI
> uri
;
10221 nsresult rv
= NS_NewURI(getter_AddRefs(uri
), aURI
);
10222 NS_ENSURE_SUCCESS(rv
, rv
);
10224 // This method of checking the cache will only work for http/https urls
10226 rv
= uri
->SchemeIs("http", &match
);
10227 NS_ENSURE_SUCCESS(rv
, rv
);
10229 rv
= uri
->SchemeIs("https", &match
);
10230 NS_ENSURE_SUCCESS(rv
, rv
);
10231 if (!match
) return NS_ERROR_DOM_BAD_URI
;
10234 // Same origin check
10235 nsCOMPtr
<nsIJSContextStack
> stack
= do_GetService(sJSStackContractID
);
10236 NS_ENSURE_TRUE(stack
, NS_ERROR_FAILURE
);
10238 JSContext
*cx
= nsnull
;
10239 rv
= stack
->Peek(&cx
);
10240 NS_ENSURE_TRUE(cx
, NS_ERROR_FAILURE
);
10242 rv
= nsContentUtils::GetSecurityManager()->CheckSameOrigin(cx
, uri
);
10243 NS_ENSURE_SUCCESS(rv
, rv
);
10245 // these load flags cause an error to be thrown if there is no
10246 // valid cache entry, and skip the load if there is.
10247 // if the cache is busy, assume that it is not yet available rather
10248 // than waiting for it to become available.
10249 PRUint32 loadFlags
= nsIChannel::INHIBIT_CACHING
|
10250 nsICachingChannel::LOAD_NO_NETWORK_IO
|
10251 nsICachingChannel::LOAD_ONLY_IF_MODIFIED
|
10252 nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE_IF_BUSY
;
10254 if (aWhenOffline
) {
10255 loadFlags
|= nsICachingChannel::LOAD_CHECK_OFFLINE_CACHE
|
10256 nsICachingChannel::LOAD_ONLY_FROM_CACHE
|
10257 nsIRequest::LOAD_FROM_CACHE
;
10260 nsCOMPtr
<nsIChannel
> channel
;
10261 rv
= NS_NewChannel(getter_AddRefs(channel
), uri
,
10262 nsnull
, nsnull
, nsnull
, loadFlags
);
10263 NS_ENSURE_SUCCESS(rv
, rv
);
10265 nsCOMPtr
<nsIInputStream
> stream
;
10266 rv
= channel
->Open(getter_AddRefs(stream
));
10267 NS_ENSURE_SUCCESS(rv
, rv
);
10272 rv
= channel
->GetStatus(&status
);
10273 NS_ENSURE_SUCCESS(rv
, rv
);
10275 if (NS_SUCCEEDED(status
)) {
10276 nsCOMPtr
<nsIHttpChannel
> httpChannel
= do_QueryInterface(channel
);
10277 rv
= httpChannel
->GetRequestSucceeded(aIsAvailable
);
10278 NS_ENSURE_SUCCESS(rv
, rv
);
10280 *aIsAvailable
= PR_FALSE
;
10286 //*****************************************************************************
10287 // nsNavigator::nsIDOMNavigatorGeolocation
10288 //*****************************************************************************
10290 NS_IMETHODIMP
nsNavigator::GetGeolocation(nsIDOMGeoGeolocation
**_retval
)
10292 NS_ENSURE_ARG_POINTER(_retval
);
10295 if (mGeolocation
) {
10296 NS_ADDREF(*_retval
= mGeolocation
);
10301 return NS_ERROR_FAILURE
;
10303 nsCOMPtr
<nsIDOMWindow
> contentDOMWindow(do_GetInterface(mDocShell
));
10304 if (!contentDOMWindow
)
10305 return NS_ERROR_FAILURE
;
10307 mGeolocation
= new nsGeolocation();
10309 return NS_ERROR_FAILURE
;
10311 if (NS_FAILED(mGeolocation
->Init(contentDOMWindow
)))
10312 return NS_ERROR_FAILURE
;
10314 NS_ADDREF(*_retval
= mGeolocation
);