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"
225 #include "nsRefreshDriver.h"
228 static PRLogModuleInfo
* gDOMLeakPRLog
;
231 using namespace mozilla::dom
;
232 using mozilla::TimeStamp
;
233 using mozilla::TimeDuration
;
235 nsIDOMStorageList
*nsGlobalWindow::sGlobalStorageList
= nsnull
;
237 static nsIEntropyCollector
*gEntropyCollector
= nsnull
;
238 static PRInt32 gRefCnt
= 0;
239 static PRInt32 gOpenPopupSpamCount
= 0;
240 static PopupControlState gPopupControlState
= openAbused
;
241 static PRInt32 gRunningTimeoutDepth
= 0;
242 static PRPackedBool gMouseDown
= PR_FALSE
;
243 static PRPackedBool gDragServiceDisabled
= PR_FALSE
;
244 static FILE *gDumpFile
= nsnull
;
245 static PRUint64 gNextWindowID
= 0;
248 static PRUint32 gSerialCounter
= 0;
252 PRInt32 gTimeoutCnt
= 0;
255 #if !(defined(NS_DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
256 static PRBool gDOMWindowDumpEnabled
= PR_FALSE
;
259 #if defined(DEBUG_bryner) || defined(DEBUG_chb)
260 #define DEBUG_PAGE_CACHE
263 // The shortest interval/timeout we permit
264 #define DOM_MIN_TIMEOUT_VALUE 10 // 10ms
266 // The number of nested timeouts before we start clamping. HTML5 says 1, WebKit
268 #define DOM_CLAMP_TIMEOUT_NESTING_LEVEL 5
270 // The longest interval (as PRIntervalTime) we permit, or that our
271 // timer code can handle, really. See DELAY_INTERVAL_LIMIT in
272 // nsTimerImpl.h for details.
273 #define DOM_MAX_TIMEOUT_VALUE PR_BIT(8 * sizeof(PRIntervalTime) - 1)
275 #define FORWARD_TO_OUTER(method, args, err_rval) \
277 if (IsInnerWindow()) { \
278 nsGlobalWindow *outer = GetOuterWindowInternal(); \
280 NS_WARNING("No outer window available!"); \
283 return outer->method args; \
287 #define FORWARD_TO_OUTER_VOID(method, args) \
289 if (IsInnerWindow()) { \
290 nsGlobalWindow *outer = GetOuterWindowInternal(); \
292 NS_WARNING("No outer window available!"); \
295 outer->method args; \
300 #define FORWARD_TO_OUTER_CHROME(method, args, err_rval) \
302 if (IsInnerWindow()) { \
303 nsGlobalWindow *outer = GetOuterWindowInternal(); \
305 NS_WARNING("No outer window available!"); \
308 return ((nsGlobalChromeWindow *)outer)->method args; \
312 #define FORWARD_TO_INNER_CHROME(method, args, err_rval) \
314 if (IsOuterWindow()) { \
315 if (!mInnerWindow) { \
316 NS_WARNING("No inner window available!"); \
319 return ((nsGlobalChromeWindow *)mInnerWindow)->method args; \
323 #define FORWARD_TO_OUTER_MODAL_CONTENT_WINDOW(method, args, err_rval) \
325 if (IsInnerWindow()) { \
326 nsGlobalWindow *outer = GetOuterWindowInternal(); \
328 NS_WARNING("No outer window available!"); \
331 return ((nsGlobalModalWindow *)outer)->method args; \
335 #define FORWARD_TO_INNER(method, args, err_rval) \
337 if (IsOuterWindow()) { \
338 if (!mInnerWindow) { \
339 NS_WARNING("No inner window available!"); \
342 return GetCurrentInnerWindowInternal()->method args; \
346 #define FORWARD_TO_INNER_MODAL_CONTENT_WINDOW(method, args, err_rval) \
348 if (IsOuterWindow()) { \
349 if (!mInnerWindow) { \
350 NS_WARNING("No inner window available!"); \
353 return ((nsGlobalModalWindow*)GetCurrentInnerWindowInternal())->method args; \
357 #define FORWARD_TO_INNER_VOID(method, args) \
359 if (IsOuterWindow()) { \
360 if (!mInnerWindow) { \
361 NS_WARNING("No inner window available!"); \
364 GetCurrentInnerWindowInternal()->method args; \
369 // Same as FORWARD_TO_INNER, but this will create a fresh inner if an
370 // inner doesn't already exists.
371 #define FORWARD_TO_INNER_CREATE(method, args, err_rval) \
373 if (IsOuterWindow()) { \
374 if (!mInnerWindow) { \
378 nsCOMPtr<nsIDOMDocument> doc; \
379 nsresult fwdic_nr = GetDocument(getter_AddRefs(doc)); \
380 NS_ENSURE_SUCCESS(fwdic_nr, err_rval); \
381 if (!mInnerWindow) { \
385 return GetCurrentInnerWindowInternal()->method args; \
390 static NS_DEFINE_CID(kXULControllersCID
, NS_XULCONTROLLERS_CID
);
392 static const char sJSStackContractID
[] = "@mozilla.org/js/xpc/ContextStack;1";
394 static const char kCryptoContractID
[] = NS_CRYPTO_CONTRACTID
;
395 static const char kPkcs11ContractID
[] = NS_PKCS11_CONTRACTID
;
397 static const char sPopStatePrefStr
[] = "browser.history.allowPopState";
400 IsAboutBlank(nsIURI
* aURI
)
402 NS_PRECONDITION(aURI
, "Must have URI");
404 // GetSpec can be expensive for some URIs, so check the scheme first.
405 PRBool isAbout
= PR_FALSE
;
406 if (NS_FAILED(aURI
->SchemeIs("about", &isAbout
)) || !isAbout
) {
412 return str
.EqualsLiteral("about:blank");
415 class nsDummyJavaPluginOwner
: public nsIPluginInstanceOwner
418 nsDummyJavaPluginOwner(nsIDocument
*aDocument
)
419 : mDocument(aDocument
)
425 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
426 NS_DECL_NSIPLUGININSTANCEOWNER
428 NS_IMETHOD
GetURL(const char *aURL
, const char *aTarget
,
429 nsIInputStream
*aPostStream
,
430 void *aHeadersData
, PRUint32 aHeadersDataLen
);
431 NS_IMETHOD
ShowStatus(const PRUnichar
*aStatusMsg
);
432 NPError
ShowNativeContextMenu(NPMenu
* menu
, void* event
);
433 NPBool
ConvertPoint(double sourceX
, double sourceY
, NPCoordinateSpace sourceSpace
,
434 double *destX
, double *destY
, NPCoordinateSpace destSpace
);
435 void SendIdleEvent();
437 NS_DECL_CYCLE_COLLECTION_CLASS(nsDummyJavaPluginOwner
)
440 nsCOMPtr
<nsIPluginInstance
> mInstance
;
441 nsCOMPtr
<nsIDocument
> mDocument
;
444 NS_IMPL_CYCLE_COLLECTION_2(nsDummyJavaPluginOwner
, mDocument
, mInstance
)
446 // QueryInterface implementation for nsDummyJavaPluginOwner
447 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDummyJavaPluginOwner
)
448 NS_INTERFACE_MAP_ENTRY(nsISupports
)
449 NS_INTERFACE_MAP_ENTRY(nsIPluginInstanceOwner
)
452 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDummyJavaPluginOwner
)
453 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDummyJavaPluginOwner
)
457 nsDummyJavaPluginOwner::Destroy()
459 // If we have a plugin instance, stop it and destroy it now.
462 mInstance
->InvalidateOwner();
470 nsDummyJavaPluginOwner::SetInstance(nsIPluginInstance
*aInstance
)
472 mInstance
= aInstance
;
478 nsDummyJavaPluginOwner::GetInstance(nsIPluginInstance
*&aInstance
)
480 NS_IF_ADDREF(aInstance
= mInstance
);
486 nsDummyJavaPluginOwner::GetWindow(NPWindow
*&aWindow
)
494 nsDummyJavaPluginOwner::GetMode(PRInt32
*aMode
)
496 // This is wrong, but there's no better alternative.
499 return NS_ERROR_NOT_IMPLEMENTED
;
503 nsDummyJavaPluginOwner::CreateWidget(void)
505 return NS_ERROR_NOT_IMPLEMENTED
;
509 nsDummyJavaPluginOwner::GetURL(const char *aURL
, const char *aTarget
,
510 nsIInputStream
*aPostStream
,
511 void *aHeadersData
, PRUint32 aHeadersDataLen
)
513 return NS_ERROR_NOT_IMPLEMENTED
;
517 nsDummyJavaPluginOwner::ShowStatus(const char *aStatusMsg
)
519 return NS_ERROR_NOT_IMPLEMENTED
;
523 nsDummyJavaPluginOwner::ShowStatus(const PRUnichar
*aStatusMsg
)
525 return NS_ERROR_NOT_IMPLEMENTED
;
529 nsDummyJavaPluginOwner::ShowNativeContextMenu(NPMenu
* menu
, void* event
)
531 return NPERR_GENERIC_ERROR
;
535 nsDummyJavaPluginOwner::ConvertPoint(double sourceX
, double sourceY
, NPCoordinateSpace sourceSpace
,
536 double *destX
, double *destY
, NPCoordinateSpace destSpace
)
542 nsDummyJavaPluginOwner::GetDocument(nsIDocument
**aDocument
)
544 NS_IF_ADDREF(*aDocument
= mDocument
);
550 nsDummyJavaPluginOwner::InvalidateRect(NPRect
*invalidRect
)
552 return NS_ERROR_NOT_IMPLEMENTED
;
556 nsDummyJavaPluginOwner::InvalidateRegion(NPRegion invalidRegion
)
558 return NS_ERROR_NOT_IMPLEMENTED
;
562 nsDummyJavaPluginOwner::ForceRedraw()
564 return NS_ERROR_NOT_IMPLEMENTED
;
568 nsDummyJavaPluginOwner::GetNetscapeWindow(void *value
)
570 return NS_ERROR_NOT_IMPLEMENTED
;
574 nsDummyJavaPluginOwner::SetEventModel(PRInt32 eventModel
)
576 return NS_ERROR_NOT_IMPLEMENTED
;
580 nsDummyJavaPluginOwner::SendIdleEvent()
585 * An indirect observer object that means we don't have to implement nsIObserver
586 * on nsGlobalWindow, where any script could see it.
588 class nsGlobalWindowObserver
: public nsIObserver
{
590 nsGlobalWindowObserver(nsGlobalWindow
* aWindow
) : mWindow(aWindow
) {}
592 NS_IMETHOD
Observe(nsISupports
* aSubject
, const char* aTopic
, const PRUnichar
* aData
)
596 return mWindow
->Observe(aSubject
, aTopic
, aData
);
598 void Forget() { mWindow
= nsnull
; }
600 nsGlobalWindow
* mWindow
;
603 NS_IMPL_ISUPPORTS1(nsGlobalWindowObserver
, nsIObserver
)
605 nsTimeout::nsTimeout()
609 extern int gTimeoutCnt
;
615 memset(this, 0, sizeof(*this));
617 MOZ_COUNT_CTOR(nsTimeout
);
620 nsTimeout::~nsTimeout()
624 extern int gTimeoutCnt
;
630 MOZ_COUNT_DTOR(nsTimeout
);
633 NS_IMPL_CYCLE_COLLECTION_CLASS(nsTimeout
)
634 NS_IMPL_CYCLE_COLLECTION_UNLINK_NATIVE_0(nsTimeout
)
635 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_BEGIN(nsTimeout
)
636 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR_AMBIGUOUS(mWindow
,
637 nsIScriptGlobalObject
)
638 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mPrincipal
)
639 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mScriptHandler
)
640 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
641 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsTimeout
, AddRef
)
642 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsTimeout
, Release
)
644 nsPIDOMWindow::nsPIDOMWindow(nsPIDOMWindow
*aOuterWindow
)
645 : mFrameElement(nsnull
), mDocShell(nsnull
), mModalStateDepth(0),
646 mRunningTimeout(nsnull
), mMutationBits(0), mIsDocumentLoaded(PR_FALSE
),
647 mIsHandlingResizeEvent(PR_FALSE
), mIsInnerWindow(aOuterWindow
!= nsnull
),
648 mMayHavePaintEventListener(PR_FALSE
), mMayHaveTouchEventListener(PR_FALSE
),
649 mMayHaveAudioAvailableEventListener(PR_FALSE
), mIsModalContentWindow(PR_FALSE
),
650 mIsActive(PR_FALSE
), mInnerWindow(nsnull
), mOuterWindow(aOuterWindow
) {}
652 nsPIDOMWindow::~nsPIDOMWindow() {}
654 //*****************************************************************************
655 //*** nsGlobalWindow: Object Management
656 //*****************************************************************************
658 nsGlobalWindow::nsGlobalWindow(nsGlobalWindow
*aOuterWindow
)
659 : nsPIDOMWindow(aOuterWindow
),
661 mDidInitJavaProperties(PR_FALSE
),
662 mFullScreen(PR_FALSE
),
665 mHavePendingClose(PR_FALSE
),
666 mHadOriginalOpener(PR_FALSE
),
667 mIsPopupSpam(PR_FALSE
),
668 mBlockScriptedClosingFlag(PR_FALSE
),
669 mFireOfflineStatusChangeEventOnThaw(PR_FALSE
),
670 mCreatingInnerWindow(PR_FALSE
),
672 mNeedsFocus(PR_TRUE
),
674 #if defined(XP_MAC) || defined(XP_MACOSX)
675 mShowAccelerators(PR_FALSE
),
676 mShowFocusRings(PR_FALSE
),
678 mShowAccelerators(PR_TRUE
),
679 mShowFocusRings(PR_TRUE
),
681 mShowFocusRingForContent(PR_FALSE
),
682 mFocusByKeyOccurred(PR_FALSE
),
683 mHasAcceleration(PR_FALSE
),
684 mNotifiedIDDestroyed(PR_FALSE
),
685 mTimeoutInsertionPoint(nsnull
),
686 mTimeoutPublicIdCounter(1),
687 mTimeoutFiringDepth(0),
689 mPendingStorageEventsObsolete(nsnull
),
690 mTimeoutsSuspendDepth(0),
693 , mSetOpenerWindowCalled(PR_FALSE
)
695 , mCleanedUp(PR_FALSE
)
696 , mCallCleanUpAfterModalDialogCloses(PR_FALSE
)
697 , mWindowID(gNextWindowID
++)
699 nsLayoutStatics::AddRef();
701 // Initialize the PRCList (this).
704 // Initialize timeout storage
705 PR_INIT_CLIST(&mTimeouts
);
708 // |this| is an inner window, add this inner window to the outer
709 // window list of inners.
710 PR_INSERT_AFTER(this, aOuterWindow
);
712 mObserver
= new nsGlobalWindowObserver(this);
714 NS_ADDREF(mObserver
);
715 nsCOMPtr
<nsIObserverService
> os
= mozilla::services::GetObserverService();
717 // Watch for online/offline status changes so we can fire events. Use
718 // a strong reference.
719 os
->AddObserver(mObserver
, NS_IOSERVICE_OFFLINE_STATUS_TOPIC
,
722 // Watch for dom-storage-changed so we can fire storage
723 // events. Use a strong reference.
724 os
->AddObserver(mObserver
, "dom-storage2-changed", PR_FALSE
);
725 os
->AddObserver(mObserver
, "dom-storage-changed", PR_FALSE
);
729 // |this| is an outer window. Outer windows start out frozen and
730 // remain frozen until they get an inner window, so freeze this
731 // outer window here.
737 // We could have failed the first time through trying
738 // to create the entropy collector, so we should
739 // try to get one until we succeed.
743 #if !(defined(NS_DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
745 static const char* prefName
= "browser.dom.window.dump.enabled";
746 nsContentUtils::AddBoolPrefVarCache(prefName
, &gDOMWindowDumpEnabled
);
747 gDOMWindowDumpEnabled
= nsContentUtils::GetBoolPref(prefName
);
751 if (gDumpFile
== nsnull
) {
752 const nsAdoptingCString
& fname
=
753 nsContentUtils::GetCharPref("browser.dom.window.dump.file");
754 if (!fname
.IsEmpty()) {
755 // if this fails to open, Dump() knows to just go to stdout
757 gDumpFile
= fopen(fname
, "wb+");
763 if (!gEntropyCollector
) {
764 CallGetService(NS_ENTROPYCOLLECTOR_CONTRACTID
, &gEntropyCollector
);
768 printf("++DOMWINDOW == %d (%p) [serial = %d] [outer = %p]\n", gRefCnt
,
769 static_cast<void*>(static_cast<nsIScriptGlobalObject
*>(this)),
770 ++gSerialCounter
, static_cast<void*>(aOuterWindow
));
771 mSerial
= gSerialCounter
;
776 gDOMLeakPRLog
= PR_NewLogModule("DOMLeak");
779 PR_LOG(gDOMLeakPRLog
, PR_LOG_DEBUG
,
780 ("DOMWINDOW %p created outer=%p", this, aOuterWindow
));
784 nsGlobalWindow::~nsGlobalWindow()
787 NS_IF_RELEASE(gEntropyCollector
);
791 if (mLastOpenedURI
) {
792 mLastOpenedURI
->GetSpec(url
);
795 printf("--DOMWINDOW == %d (%p) [serial = %d] [outer = %p] [url = %s]\n",
796 gRefCnt
, static_cast<void*>(static_cast<nsIScriptGlobalObject
*>(this)),
797 mSerial
, static_cast<void*>(mOuterWindow
), url
.get());
802 PR_LOG(gDOMLeakPRLog
, PR_LOG_DEBUG
,
803 ("DOMWINDOW %p destroyed", this));
807 nsCOMPtr
<nsIObserverService
> os
= mozilla::services::GetObserverService();
809 os
->RemoveObserver(mObserver
, NS_IOSERVICE_OFFLINE_STATUS_TOPIC
);
810 os
->RemoveObserver(mObserver
, "dom-storage2-changed");
811 os
->RemoveObserver(mObserver
, "dom-storage-changed");
814 // Drop its reference to this dying window, in case for some bogus reason
815 // the object stays around.
817 NS_RELEASE(mObserver
);
820 if (IsOuterWindow()) {
821 // An outer window is destroyed with inner windows still possibly
822 // alive, iterate through the inner windows and null out their
823 // back pointer to this outer, and pull them out of the list of
827 while ((w
= (nsGlobalWindow
*)PR_LIST_HEAD(this)) != this) {
828 NS_ASSERTION(w
->mOuterWindow
== this, "Uh, bad outer window pointer?");
830 w
->mOuterWindow
= nsnull
;
832 PR_REMOVE_AND_INIT_LINK(w
);
835 if (mListenerManager
) {
836 mListenerManager
->Disconnect();
837 mListenerManager
= nsnull
;
840 // An inner window is destroyed, pull it out of the outer window's
841 // list if inner windows.
843 PR_REMOVE_LINK(this);
845 // If our outer window's inner window is this window, null out the
846 // outer window's reference to this window that's being deleted.
847 nsGlobalWindow
*outer
= GetOuterWindowInternal();
848 if (outer
&& outer
->mInnerWindow
== this) {
849 outer
->mInnerWindow
= nsnull
;
853 mDocument
= nsnull
; // Forces Release
856 NS_ASSERTION(!mArguments
, "mArguments wasn't cleaned up properly!");
861 nsCycleCollector_DEBUG_wasFreed(static_cast<nsIScriptGlobalObject
*>(this));
864 delete mPendingStorageEventsObsolete
;
866 nsLayoutStatics::Release();
871 nsGlobalWindow::ShutDown()
873 NS_IF_RELEASE(sGlobalStorageList
);
875 if (gDumpFile
&& gDumpFile
!= stdout
) {
883 nsGlobalWindow::CleanupCachedXBLHandlers(nsGlobalWindow
* aWindow
)
885 if (aWindow
->mCachedXBLPrototypeHandlers
.IsInitialized() &&
886 aWindow
->mCachedXBLPrototypeHandlers
.Count() > 0) {
887 aWindow
->mCachedXBLPrototypeHandlers
.Clear();
889 nsCOMPtr
<nsISupports
> supports
;
890 aWindow
->QueryInterface(NS_GET_IID(nsCycleCollectionISupports
),
891 getter_AddRefs(supports
));
892 NS_ASSERTION(supports
, "Failed to QI to nsCycleCollectionISupports?!");
894 nsContentUtils::DropJSObjects(supports
);
899 nsGlobalWindow::MaybeForgiveSpamCount()
901 if (IsOuterWindow() &&
904 SetPopupSpamWindow(PR_FALSE
);
905 --gOpenPopupSpamCount
;
906 NS_ASSERTION(gOpenPopupSpamCount
>= 0,
907 "Unbalanced decrement of gOpenPopupSpamCount");
912 nsGlobalWindow::CleanUp(PRBool aIgnoreModalDialog
)
914 if (IsOuterWindow() && !aIgnoreModalDialog
) {
915 nsGlobalWindow
* inner
= GetCurrentInnerWindowInternal();
916 nsCOMPtr
<nsIDOMModalContentWindow
>
917 dlg(do_QueryInterface(static_cast<nsPIDOMWindow
*>(inner
)));
919 // The window we're trying to clean up is the outer window of a
920 // modal dialog. Defer cleanup until the window closes, and let
921 // ShowModalDialog take care of calling CleanUp.
922 mCallCleanUpAfterModalDialogCloses
= PR_TRUE
;
927 // Guarantee idempotence.
930 mCleanedUp
= PR_TRUE
;
937 mLocationbar
= nsnull
;
938 mPersonalbar
= nsnull
;
940 mScrollbars
= nsnull
;
943 mApplicationCache
= nsnull
;
948 mOpener
= nsnull
; // Forces Release
951 nsCycleCollector_DEBUG_shouldBeFreed(mContext
);
953 mContext
= nsnull
; // Forces Release
955 mChromeEventHandler
= nsnull
; // Forces Release
956 mParentTarget
= nsnull
;
958 nsGlobalWindow
*inner
= GetCurrentInnerWindowInternal();
961 inner
->CleanUp(aIgnoreModalDialog
);
964 if (mHasAcceleration
) {
965 nsCOMPtr
<nsIAccelerometer
> ac
= do_GetService(NS_ACCELEROMETER_CONTRACTID
);
967 ac
->RemoveWindowListener(this);
970 if (mIsChrome
&& static_cast<nsGlobalChromeWindow
*>(this)->mMessageManager
) {
971 static_cast<nsFrameMessageManager
*>(
972 static_cast<nsGlobalChromeWindow
*>(
973 this)->mMessageManager
.get())->Disconnect();
976 mInnerWindowHolder
= nsnull
;
978 mArgumentsLast
= nsnull
;
979 mArgumentsOrigin
= nsnull
;
981 CleanupCachedXBLHandlers(this);
984 nsCycleCollector_DEBUG_shouldBeFreed(static_cast<nsIScriptGlobalObject
*>(this));
989 nsGlobalWindow::ClearControllers()
993 mControllers
->GetControllerCount(&count
);
996 nsCOMPtr
<nsIController
> controller
;
997 mControllers
->GetControllerAt(count
, getter_AddRefs(controller
));
999 nsCOMPtr
<nsIControllerContext
> context
= do_QueryInterface(controller
);
1001 context
->SetCommandContext(nsnull
);
1004 mControllers
= nsnull
;
1008 class ClearScopeEvent
: public nsRunnable
1011 ClearScopeEvent(nsGlobalWindow
*innerWindow
)
1012 : mInnerWindow(innerWindow
) {
1017 mInnerWindow
->ReallyClearScope(this);
1022 nsRefPtr
<nsGlobalWindow
> mInnerWindow
;
1026 nsGlobalWindow::ReallyClearScope(nsRunnable
*aRunnable
)
1028 NS_ASSERTION(IsInnerWindow(), "Must be an inner window");
1030 nsIScriptContext
*jsscx
= GetContextInternal();
1031 if (jsscx
&& jsscx
->GetExecutingScript()) {
1033 aRunnable
= new ClearScopeEvent(this);
1035 // The only reason that we clear scope here is to try to prevent
1036 // leaks. Failing to clear scope might mean that we'll leak more
1037 // but if we don't have enough memory to allocate a ClearScopeEvent
1038 // we probably don't have to worry about this anyway.
1043 NS_DispatchToMainThread(aRunnable
);
1047 NotifyWindowIDDestroyed("inner-window-destroyed");
1048 nsIScriptContext
*scx
= GetContextInternal();
1050 scx
->ClearScope(mJSObject
, PR_TRUE
);
1055 nsGlobalWindow::FreeInnerObjects(PRBool aClearScope
)
1057 NS_ASSERTION(IsInnerWindow(), "Don't free inner objects on an outer window");
1059 // Kill all of the workers for this window.
1060 nsDOMThreadService
* dts
= nsDOMThreadService::get();
1062 nsIScriptContext
*scx
= GetContextInternal();
1064 JSContext
*cx
= scx
? (JSContext
*)scx
->GetNativeContext() : nsnull
;
1066 // Have to suspend this request here because CancelWorkersForGlobal will
1067 // lock until the worker has died and that could cause a deadlock.
1068 JSAutoSuspendRequest
asr(cx
);
1070 dts
->CancelWorkersForGlobal(static_cast<nsIScriptGlobalObject
*>(this));
1075 mChromeEventHandler
= nsnull
;
1077 if (mListenerManager
) {
1078 mListenerManager
->Disconnect();
1079 mListenerManager
= nsnull
;
1085 NS_ASSERTION(mDoc
, "Why is mDoc null?");
1087 // Remember the document's principal.
1088 mDocumentPrincipal
= mDoc
->NodePrincipal();
1093 nsCycleCollector_DEBUG_shouldBeFreed(nsCOMPtr
<nsISupports
>(do_QueryInterface(mDocument
)));
1096 // Make sure that this is called before we null out the document.
1097 NotifyDOMWindowDestroyed(this);
1099 // Remove our reference to the document and the document principal.
1103 if (mApplicationCache
) {
1104 static_cast<nsDOMOfflineResourceList
*>(mApplicationCache
.get())->Disconnect();
1105 mApplicationCache
= nsnull
;
1108 mIndexedDB
= nsnull
;
1111 // NB: This might not clear our scope, but fire an event to do so
1113 ReallyClearScope(nsnull
);
1116 if (mDummyJavaPluginOwner
) {
1117 // Tear down the dummy java plugin.
1119 // XXXjst: On a general note, should windows with java stuff in
1120 // them ever even make it into the fast-back cache?
1122 mDummyJavaPluginOwner
->Destroy();
1124 mDummyJavaPluginOwner
= nsnull
;
1127 CleanupCachedXBLHandlers(this);
1130 nsCycleCollector_DEBUG_shouldBeFreed(static_cast<nsIScriptGlobalObject
*>(this));
1134 //*****************************************************************************
1135 // nsGlobalWindow::nsISupports
1136 //*****************************************************************************
1138 #define WINDOW_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(_class) \
1139 if (aIID.Equals(NS_GET_IID(nsIClassInfo)) || \
1140 aIID.Equals(NS_GET_IID(nsXPCClassInfo))) { \
1141 foundInterface = NS_GetDOMClassInfoInstance(IsInnerWindow() \
1142 ? eDOMClassInfo_Inner##_class##_id \
1143 : eDOMClassInfo_##_class##_id);\
1144 if (!foundInterface) { \
1145 *aInstancePtr = nsnull; \
1146 return NS_ERROR_OUT_OF_MEMORY; \
1150 NS_IMPL_CYCLE_COLLECTION_CLASS(nsGlobalWindow
)
1152 DOMCI_DATA(Window
, nsGlobalWindow
)
1153 DOMCI_DATA(InnerWindow
, nsGlobalWindow
)
1155 // QueryInterface implementation for nsGlobalWindow
1156 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsGlobalWindow
)
1157 // Make sure this matches the cast in nsGlobalWindow::FromWrapper()
1158 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIScriptGlobalObject
)
1159 NS_INTERFACE_MAP_ENTRY(nsIDOMWindowInternal
)
1160 NS_INTERFACE_MAP_ENTRY(nsIDOMWindow
)
1161 NS_INTERFACE_MAP_ENTRY(nsIDOMWindow2
)
1162 NS_INTERFACE_MAP_ENTRY(nsIDOMJSWindow
)
1163 NS_INTERFACE_MAP_ENTRY(nsIScriptGlobalObject
)
1164 NS_INTERFACE_MAP_ENTRY(nsIScriptObjectPrincipal
)
1165 NS_INTERFACE_MAP_ENTRY(nsPIDOMEventTarget
)
1166 NS_INTERFACE_MAP_ENTRY(nsIDOMEventTarget
)
1167 NS_INTERFACE_MAP_ENTRY(nsIDOM3EventTarget
)
1168 NS_INTERFACE_MAP_ENTRY(nsIDOMNSEventTarget
)
1169 NS_INTERFACE_MAP_ENTRY(nsPIDOMWindow
)
1170 NS_INTERFACE_MAP_ENTRY(nsIDOMViewCSS
)
1171 NS_INTERFACE_MAP_ENTRY(nsIDOMAbstractView
)
1172 NS_INTERFACE_MAP_ENTRY(nsIDOMStorageWindow
)
1173 NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference
)
1174 NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor
)
1175 WINDOW_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Window
)
1176 NS_INTERFACE_MAP_END
1179 NS_IMPL_CYCLE_COLLECTING_ADDREF_AMBIGUOUS(nsGlobalWindow
, nsIScriptGlobalObject
)
1180 NS_IMPL_CYCLE_COLLECTING_RELEASE_AMBIGUOUS(nsGlobalWindow
,
1181 nsIScriptGlobalObject
)
1184 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsGlobalWindow
)
1185 if (tmp
->mDoc
&& nsCCUncollectableMarker::InGeneration(
1186 cb
, tmp
->mDoc
->GetMarkedCCGeneration())) {
1187 return NS_SUCCESS_INTERRUPTED_TRAVERSE
;
1190 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mContext
)
1192 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mControllers
)
1193 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mArguments
)
1194 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mArgumentsLast
)
1196 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mInnerWindowHolder
)
1198 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mOpenerScriptPrincipal
)
1199 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mListenerManager
)
1201 for (nsTimeout
* timeout
= tmp
->FirstTimeout();
1202 tmp
->IsTimeout(timeout
);
1203 timeout
= timeout
->Next()) {
1204 cb
.NoteNativeChild(timeout
, &NS_CYCLE_COLLECTION_NAME(nsTimeout
));
1207 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mSessionStorage
)
1208 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mApplicationCache
)
1209 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDocumentPrincipal
)
1210 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDoc
)
1212 // Traverse stuff from nsPIDOMWindow
1213 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mChromeEventHandler
)
1214 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mParentTarget
)
1215 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDocument
)
1216 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFrameElement
)
1218 // Traverse mDummyJavaPluginOwner
1219 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDummyJavaPluginOwner
)
1221 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mFocusedNode
)
1223 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
1225 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindow
)
1226 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mContext
)
1228 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mControllers
)
1229 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mArguments
)
1230 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mArgumentsLast
)
1232 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mInnerWindowHolder
)
1234 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOpenerScriptPrincipal
)
1235 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mListenerManager
)
1236 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mSessionStorage
)
1237 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mApplicationCache
)
1238 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDocumentPrincipal
)
1240 // Unlink stuff from nsPIDOMWindow
1241 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mChromeEventHandler
)
1242 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mParentTarget
)
1243 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDocument
)
1244 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFrameElement
)
1246 // Unlink mDummyJavaPluginOwner
1247 if (tmp
->mDummyJavaPluginOwner
) {
1248 tmp
->mDummyJavaPluginOwner
->Destroy();
1249 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDummyJavaPluginOwner
)
1252 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mFocusedNode
)
1254 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
1258 TraceData(TraceCallback
& aCallback
, void* aClosure
) :
1259 callback(aCallback
), closure(aClosure
) {}
1261 TraceCallback
& callback
;
1265 static PLDHashOperator
1266 TraceXBLHandlers(const void* aKey
, void* aData
, void* aClosure
)
1268 TraceData
* data
= static_cast<TraceData
*>(aClosure
);
1269 data
->callback(nsIProgrammingLanguage::JAVASCRIPT
, aData
, data
->closure
);
1270 return PL_DHASH_NEXT
;
1273 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsGlobalWindow
)
1274 if (tmp
->mCachedXBLPrototypeHandlers
.IsInitialized()) {
1275 TraceData
data(aCallback
, aClosure
);
1276 tmp
->mCachedXBLPrototypeHandlers
.EnumerateRead(TraceXBLHandlers
, &data
);
1278 NS_IMPL_CYCLE_COLLECTION_TRACE_END
1280 NS_IMPL_CYCLE_COLLECTION_ROOT_BEGIN(nsGlobalWindow
)
1281 nsGlobalWindow::CleanupCachedXBLHandlers(tmp
);
1282 NS_IMPL_CYCLE_COLLECTION_ROOT_END
1284 //*****************************************************************************
1285 // nsGlobalWindow::nsIScriptGlobalObject
1286 //*****************************************************************************
1289 nsGlobalWindow::SetScriptContext(PRUint32 lang_id
, nsIScriptContext
*aScriptContext
)
1291 NS_ASSERTION(lang_id
== nsIProgrammingLanguage::JAVASCRIPT
,
1292 "We don't support this language ID");
1293 NS_ASSERTION(IsOuterWindow(), "Uh, SetScriptContext() called on inner window!");
1295 NS_ASSERTION(!aScriptContext
|| !mContext
, "Bad call to SetContext()!");
1297 if (aScriptContext
) {
1298 // should probably assert the context is clean???
1299 aScriptContext
->WillInitializeContext();
1301 nsresult rv
= aScriptContext
->InitContext();
1302 NS_ENSURE_SUCCESS(rv
, rv
);
1305 // This window is a [i]frame, don't bother GC'ing when the
1306 // frame's context is destroyed since a GC will happen when the
1307 // frameset or host document is destroyed anyway.
1309 aScriptContext
->SetGCOnDestruction(PR_FALSE
);
1313 mContext
= aScriptContext
;
1318 nsGlobalWindow::EnsureScriptEnvironment(PRUint32 aLangID
)
1320 NS_ASSERTION(aLangID
== nsIProgrammingLanguage::JAVASCRIPT
,
1321 "We don't support this language ID");
1322 FORWARD_TO_OUTER(EnsureScriptEnvironment
, (aLangID
), NS_ERROR_NOT_INITIALIZED
);
1327 NS_ASSERTION(!GetCurrentInnerWindowInternal(),
1328 "mJSObject is null, but we have an inner window?");
1330 nsCOMPtr
<nsIScriptRuntime
> scriptRuntime
;
1331 nsresult rv
= NS_GetScriptRuntimeByID(aLangID
, getter_AddRefs(scriptRuntime
));
1332 NS_ENSURE_SUCCESS(rv
, rv
);
1334 nsCOMPtr
<nsIScriptContext
> context
;
1335 rv
= scriptRuntime
->CreateContext(getter_AddRefs(context
));
1336 NS_ENSURE_SUCCESS(rv
, rv
);
1338 return SetScriptContext(aLangID
, context
);
1342 nsGlobalWindow::GetScriptContext(PRUint32 lang
)
1344 NS_ASSERTION(lang
== nsIProgrammingLanguage::JAVASCRIPT
,
1345 "We don't support this language ID");
1347 FORWARD_TO_OUTER(GetScriptContext
, (lang
), nsnull
);
1352 nsGlobalWindow::GetScriptGlobal(PRUint32 lang
)
1354 NS_ASSERTION(lang
== nsIProgrammingLanguage::JAVASCRIPT
,
1355 "We don't support this language ID");
1360 nsGlobalWindow::GetContext()
1362 FORWARD_TO_OUTER(GetContext
, (), nsnull
);
1364 // check GetContext is indeed identical to GetScriptContext()
1365 NS_ASSERTION(mContext
== GetScriptContext(nsIProgrammingLanguage::JAVASCRIPT
),
1366 "GetContext confused?");
1371 nsGlobalWindow::GetGlobalJSObject()
1373 NS_ASSERTION(mJSObject
== GetScriptGlobal(nsIProgrammingLanguage::JAVASCRIPT
),
1374 "GetGlobalJSObject confused?");
1375 return FastGetGlobalJSObject();
1379 nsGlobalWindow::WouldReuseInnerWindow(nsIDocument
*aNewDocument
)
1381 // We reuse the inner window when:
1382 // a. We are currently at our original document.
1383 // b. At least one of the following conditions are true:
1384 // -- We are not currently a content window (i.e., we're currently a chrome
1386 // -- The new document is the same as the old document. This means that we're
1387 // getting called from document.open().
1388 // -- The new document has the same origin as what we have loaded right now.
1390 if (!mDoc
|| !aNewDocument
) {
1394 if (!mDoc
->IsInitialDocument()) {
1398 NS_ASSERTION(IsAboutBlank(mDoc
->GetDocumentURI()),
1399 "How'd this happen?");
1401 // Great, we're the original document, check for one of the other
1403 if (mDoc
== aNewDocument
) {
1404 // aClearScopeHint is false.
1409 if (NS_SUCCEEDED(mDoc
->NodePrincipal()->Equals(aNewDocument
->NodePrincipal(),
1412 // The origin is the same.
1416 nsCOMPtr
<nsIDocShellTreeItem
> treeItem(do_QueryInterface(mDocShell
));
1419 PRInt32 itemType
= nsIDocShellTreeItem::typeContent
;
1420 treeItem
->GetItemType(&itemType
);
1422 // If we're a chrome window, then we want to reuse the inner window.
1423 return itemType
== nsIDocShellTreeItem::typeChrome
;
1426 // No treeItem: don't reuse the current inner window.
1431 nsGlobalWindow::SetOpenerScriptPrincipal(nsIPrincipal
* aPrincipal
)
1433 FORWARD_TO_OUTER_VOID(SetOpenerScriptPrincipal
, (aPrincipal
));
1436 if (!mDoc
->IsInitialDocument()) {
1437 // We have a document already, and it's not the original one. Bail out.
1438 // Do NOT set mOpenerScriptPrincipal in this case, just to be safe.
1443 // We better have an about:blank document loaded at this point. Otherwise,
1444 // something is really weird.
1445 nsCOMPtr
<nsIURI
> uri
;
1446 mDoc
->NodePrincipal()->GetURI(getter_AddRefs(uri
));
1447 NS_ASSERTION(uri
&& IsAboutBlank(uri
) &&
1448 IsAboutBlank(mDoc
->GetDocumentURI()),
1449 "Unexpected original document");
1452 // Set the opener principal on our document; given the above check, this
1454 mDoc
->SetPrincipal(aPrincipal
);
1457 mOpenerScriptPrincipal
= aPrincipal
;
1461 nsGlobalWindow::GetOpenerScriptPrincipal()
1463 FORWARD_TO_OUTER(GetOpenerScriptPrincipal
, (), nsnull
);
1465 return mOpenerScriptPrincipal
;
1469 PushPopupControlState(PopupControlState aState
, PRBool aForce
)
1471 PopupControlState oldState
= gPopupControlState
;
1473 if (aState
< gPopupControlState
|| aForce
) {
1474 gPopupControlState
= aState
;
1481 PopPopupControlState(PopupControlState aState
)
1483 gPopupControlState
= aState
;
1487 nsGlobalWindow::PushPopupControlState(PopupControlState aState
,
1488 PRBool aForce
) const
1490 return ::PushPopupControlState(aState
, aForce
);
1494 nsGlobalWindow::PopPopupControlState(PopupControlState aState
) const
1496 ::PopPopupControlState(aState
);
1500 nsGlobalWindow::GetPopupControlState() const
1502 return gPopupControlState
;
1505 #define WINDOWSTATEHOLDER_IID \
1506 {0x0b917c3e, 0xbd50, 0x4683, {0xaf, 0xc9, 0xc7, 0x81, 0x07, 0xae, 0x33, 0x26}}
1508 class WindowStateHolder
: public nsISupports
1511 NS_DECLARE_STATIC_IID_ACCESSOR(WINDOWSTATEHOLDER_IID
)
1514 WindowStateHolder(nsGlobalWindow
*aWindow
,
1515 nsIXPConnectJSObjectHolder
*aHolder
,
1516 nsNavigator
*aNavigator
,
1517 nsIXPConnectJSObjectHolder
*aOuterProto
,
1518 nsIXPConnectJSObjectHolder
*aOuterRealProto
);
1520 nsGlobalWindow
* GetInnerWindow() { return mInnerWindow
; }
1521 nsIXPConnectJSObjectHolder
*GetInnerWindowHolder()
1522 { return mInnerWindowHolder
; }
1524 nsNavigator
* GetNavigator() { return mNavigator
; }
1525 nsIXPConnectJSObjectHolder
* GetOuterProto() { return mOuterProto
; }
1526 nsIXPConnectJSObjectHolder
* GetOuterRealProto() { return mOuterRealProto
; }
1528 void DidRestoreWindow()
1530 mInnerWindow
= nsnull
;
1532 mInnerWindowHolder
= nsnull
;
1533 mNavigator
= nsnull
;
1534 mOuterProto
= nsnull
;
1535 mOuterRealProto
= nsnull
;
1539 ~WindowStateHolder();
1541 nsGlobalWindow
*mInnerWindow
;
1542 // We hold onto this to make sure the inner window doesn't go away. The outer
1543 // window ends up recalculating it anyway.
1544 nsCOMPtr
<nsIXPConnectJSObjectHolder
> mInnerWindowHolder
;
1545 nsRefPtr
<nsNavigator
> mNavigator
;
1546 nsCOMPtr
<nsIXPConnectJSObjectHolder
> mOuterProto
;
1547 nsCOMPtr
<nsIXPConnectJSObjectHolder
> mOuterRealProto
;
1550 NS_DEFINE_STATIC_IID_ACCESSOR(WindowStateHolder
, WINDOWSTATEHOLDER_IID
)
1552 WindowStateHolder::WindowStateHolder(nsGlobalWindow
*aWindow
,
1553 nsIXPConnectJSObjectHolder
*aHolder
,
1554 nsNavigator
*aNavigator
,
1555 nsIXPConnectJSObjectHolder
*aOuterProto
,
1556 nsIXPConnectJSObjectHolder
*aOuterRealProto
)
1557 : mInnerWindow(aWindow
),
1558 mNavigator(aNavigator
),
1559 mOuterProto(aOuterProto
),
1560 mOuterRealProto(aOuterRealProto
)
1562 NS_PRECONDITION(aWindow
, "null window");
1563 NS_PRECONDITION(aWindow
->IsInnerWindow(), "Saving an outer window");
1565 mInnerWindowHolder
= aHolder
;
1567 aWindow
->SuspendTimeouts();
1570 WindowStateHolder::~WindowStateHolder()
1573 // This window was left in the bfcache and is now going away. We need to
1575 // Note that FreeInnerObjects may already have been called on the
1576 // inner window if its outer has already had SetDocShell(null)
1577 // called. In this case the contexts will all be null and the
1578 // PR_TRUE for aClearScope won't do anything; this is OK since
1579 // SetDocShell(null) already did it.
1580 mInnerWindow
->FreeInnerObjects(PR_TRUE
);
1584 NS_IMPL_ISUPPORTS1(WindowStateHolder
, WindowStateHolder
)
1587 nsGlobalWindow::SetNewDocument(nsIDocument
* aDocument
,
1588 nsISupports
* aState
)
1592 NS_PRECONDITION(mDocumentPrincipal
== nsnull
,
1593 "mDocumentPrincipal prematurely set!");
1596 NS_ERROR("SetNewDocument(null) called!");
1598 return NS_ERROR_INVALID_ARG
;
1601 if (IsInnerWindow()) {
1602 if (!mOuterWindow
) {
1603 return NS_ERROR_NOT_INITIALIZED
;
1606 // Refuse to set a new document if the call came from an inner
1607 // window that's not the current inner window.
1608 if (mOuterWindow
->GetCurrentInnerWindow() != this) {
1609 return NS_ERROR_NOT_AVAILABLE
;
1612 return GetOuterWindowInternal()->SetNewDocument(aDocument
, aState
);
1615 NS_PRECONDITION(IsOuterWindow(), "Must only be called on outer windows");
1618 // This outer is now getting its first inner, thaw the outer now
1619 // that it's ready and is getting an inner window.
1624 // XXX Brain transplant outer window JSObject and create new one!
1626 NS_ASSERTION(!GetCurrentInnerWindow() ||
1627 GetCurrentInnerWindow()->GetExtantDocument() == mDocument
,
1628 "Uh, mDocument doesn't match the current inner window "
1631 nsresult rv
= NS_OK
;
1633 nsCOMPtr
<nsIDocument
> oldDoc(do_QueryInterface(mDocument
));
1635 nsIScriptContext
*scx
= GetContextInternal();
1636 NS_ENSURE_TRUE(scx
, NS_ERROR_NOT_INITIALIZED
);
1638 JSContext
*cx
= (JSContext
*)scx
->GetNativeContext();
1640 // clear smartcard events, our document has gone away.
1642 mCrypto
->SetEnableSmartCardEvents(PR_FALSE
);
1646 // First document load.
1648 // Get our private root. If it is equal to us, then we need to
1649 // attach our global key bindings that handles browser scrolling
1650 // and other browser commands.
1651 nsIDOMWindowInternal
*internal
= nsGlobalWindow::GetPrivateRoot();
1653 if (internal
== static_cast<nsIDOMWindowInternal
*>(this)) {
1654 nsCOMPtr
<nsIXBLService
> xblService
= do_GetService("@mozilla.org/xbl;1");
1656 nsCOMPtr
<nsPIDOMEventTarget
> piTarget
=
1657 do_QueryInterface(mChromeEventHandler
);
1658 xblService
->AttachGlobalKeyHandler(piTarget
);
1663 /* No mDocShell means we're already been partially closed down. When that
1664 happens, setting status isn't a big requirement, so don't. (Doesn't happen
1665 under normal circumstances, but bug 49615 describes a case.) */
1667 nsContentUtils::AddScriptRunner(
1668 NS_NewRunnableMethod(this, &nsGlobalWindow::ClearStatus
));
1670 PRBool reUseInnerWindow
= WouldReuseInnerWindow(aDocument
);
1672 // Remember the old document's principal.
1673 nsIPrincipal
*oldPrincipal
= nsnull
;
1675 oldPrincipal
= oldDoc
->NodePrincipal();
1678 // Drop our reference to the navigator object unless we're reusing
1679 // the existing inner window or the new document is from the same
1680 // origin as the old document.
1681 if (!reUseInnerWindow
&& mNavigator
&& oldPrincipal
) {
1683 rv
= oldPrincipal
->Equals(aDocument
->NodePrincipal(), &equal
);
1685 if (NS_FAILED(rv
) || !equal
) {
1686 // Different origins. Release the navigator object so it gets
1687 // recreated for the new document. The plugins or mime types
1688 // arrays may have changed. See bug 150087.
1689 mNavigator
->SetDocShell(nsnull
);
1691 mNavigator
= nsnull
;
1695 if (mNavigator
&& aDocument
!= oldDoc
) {
1696 // We didn't drop our reference to our old navigator object and
1697 // we're loading a new document. Notify the navigator object about
1698 // the new document load so that it can make sure it is ready for
1699 // the new document.
1701 mNavigator
->LoadingNewDocument();
1704 // Set mDocument even if this is an outer window to avoid
1705 // having to *always* reach into the inner window to find the
1707 mDocument
= do_QueryInterface(aDocument
);
1711 mLastOpenedURI
= aDocument
->GetDocumentURI();
1714 mContext
->WillInitializeContext();
1716 nsGlobalWindow
*currentInner
= GetCurrentInnerWindowInternal();
1718 nsRefPtr
<nsGlobalWindow
> newInnerWindow
;
1720 PRBool thisChrome
= IsChromeWindow();
1721 nsCOMPtr
<nsIXPConnectJSObjectHolder
> navigatorHolder
;
1724 PRBool isChrome
= PR_FALSE
;
1726 nsCxPusher cxPusher
;
1727 if (!cxPusher
.Push(cx
)) {
1728 return NS_ERROR_FAILURE
;
1731 JSAutoRequest
ar(cx
);
1733 nsCOMPtr
<WindowStateHolder
> wsh
= do_QueryInterface(aState
);
1734 NS_ASSERTION(!aState
|| wsh
, "What kind of weird state are you giving me here?");
1736 // Make sure to clear scope on the outer window *before* we
1737 // initialize the new inner window. If we don't, things
1738 // (Object.prototype etc) could leak from the old outer to the new
1740 mContext
->ClearScope(mJSObject
, PR_FALSE
);
1742 // This code should not be called during shutdown any more (now that
1743 // we don't ever call SetNewDocument(nsnull), so no need to null
1745 nsIXPConnect
*xpc
= nsContentUtils::XPConnect();
1746 nsCOMPtr
<nsIXPConnectWrappedNative
> wrapper
;
1747 if (reUseInnerWindow
) {
1748 // We're reusing the current inner window.
1749 NS_ASSERTION(!currentInner
->IsFrozen(),
1750 "We should never be reusing a shared inner window");
1751 newInnerWindow
= currentInner
;
1753 if (aDocument
!= oldDoc
) {
1754 nsCommonWindowSH::InvalidateGlobalScopePolluter(cx
, currentInner
->mJSObject
);
1758 newInnerWindow
= wsh
->GetInnerWindow();
1759 mInnerWindowHolder
= wsh
->GetInnerWindowHolder();
1761 NS_ASSERTION(newInnerWindow
, "Got a state without inner window");
1763 // These assignments addref.
1764 mNavigator
= wsh
->GetNavigator();
1767 // Update mNavigator's docshell pointer now.
1768 mNavigator
->SetDocShell(mDocShell
);
1769 mNavigator
->LoadingNewDocument();
1771 } else if (thisChrome
) {
1772 newInnerWindow
= new nsGlobalChromeWindow(this);
1774 } else if (mIsModalContentWindow
) {
1775 newInnerWindow
= new nsGlobalModalWindow(this);
1777 newInnerWindow
= new nsGlobalWindow(this);
1780 if (currentInner
&& currentInner
->mJSObject
) {
1781 if (mNavigator
&& !aState
) {
1782 // Hold on to the navigator wrapper so that we can set
1783 // window.navigator in the new window to point to the same
1784 // object (assuming we didn't change origins etc). See bug
1785 // 163645 for more on why we need this.
1787 nsIDOMNavigator
* navigator
=
1788 static_cast<nsIDOMNavigator
*>(mNavigator
.get());
1789 nsContentUtils::WrapNative(cx
, currentInner
->mJSObject
, navigator
,
1790 &NS_GET_IID(nsIDOMNavigator
), &nav
,
1791 getter_AddRefs(navigatorHolder
));
1796 // This is redundant if we're restoring from a previous inner window.
1797 nsIScriptGlobalObject
*sgo
=
1798 (nsIScriptGlobalObject
*)newInnerWindow
.get();
1800 // Freeze the outer window and null out the inner window so
1801 // that initializing classes on the new inner doesn't end up
1802 // reaching into the old inner window for classes etc.
1804 // [This happens with Object.prototype when XPConnect creates
1805 // a temporary global while initializing classes; the reason
1806 // being that xpconnect creates the temp global w/o a parent
1807 // and proto, which makes the JS engine look up classes in
1808 // cx->globalObject, i.e. this outer window].
1810 mInnerWindow
= nsnull
;
1813 mCreatingInnerWindow
= PR_TRUE
;
1814 // Every script context we are initialized with must create a
1816 void *&newGlobal
= (void *&)newInnerWindow
->mJSObject
;
1817 nsCOMPtr
<nsIXPConnectJSObjectHolder
> &holder
= mInnerWindowHolder
;
1818 rv
= mContext
->CreateNativeGlobalForInner(sgo
, isChrome
,
1819 aDocument
->NodePrincipal(),
1821 getter_AddRefs(holder
));
1822 NS_ASSERTION(NS_SUCCEEDED(rv
) && newGlobal
&& holder
,
1823 "Failed to get script global and holder");
1825 mCreatingInnerWindow
= PR_FALSE
;
1828 NS_ENSURE_SUCCESS(rv
, rv
);
1831 if (currentInner
&& currentInner
->mJSObject
) {
1832 PRBool termFuncSet
= PR_FALSE
;
1834 if (oldDoc
== aDocument
) {
1835 // Suspend the current context's request before Pop() resumes the old
1836 // context's request.
1837 JSAutoSuspendRequest
asr(cx
);
1839 // Pop our context here so that we get the correct one for the
1840 // termination function.
1843 JSContext
*oldCx
= nsContentUtils::GetCurrentJSContext();
1845 nsIScriptContext
*callerScx
;
1846 if (oldCx
&& (callerScx
= GetScriptContextFromJSContext(oldCx
))) {
1847 // We're called from document.open() (and document.open() is
1848 // called from JS), clear the scope etc in a termination
1849 // function on the calling context to prevent clearing the
1851 NS_ASSERTION(!currentInner
->IsFrozen(),
1852 "How does this opened window get into session history");
1854 JSAutoRequest
ar(oldCx
);
1856 callerScx
->SetTerminationFunction(ClearWindowScope
,
1857 static_cast<nsIDOMWindow
*>
1860 termFuncSet
= PR_TRUE
;
1863 // Re-push our context.
1867 // Don't clear scope on our current inner window if it's going to be
1868 // held in the bfcache.
1869 if (!currentInner
->IsFrozen()) {
1870 // Skip the ClearScope if we set a termination function to do
1871 // it ourselves, later.
1872 currentInner
->FreeInnerObjects(!termFuncSet
);
1876 mInnerWindow
= newInnerWindow
;
1879 mContext
->CreateOuterObject(this, newInnerWindow
);
1880 mContext
->DidInitializeContext();
1881 mJSObject
= (JSObject
*)mContext
->GetNativeGlobal();
1883 // XXX New global object and brain transplant!
1884 rv
= xpc
->GetWrappedNativeOfJSObject(cx
, mJSObject
,
1885 getter_AddRefs(wrapper
));
1886 NS_ENSURE_SUCCESS(rv
, rv
);
1888 // Restore our object's prototype to its original value so we're sure to
1889 // update it under ReparentWrappedNativeIfFound.
1891 wrapper
->GetJSObjectPrototype(&proto
);
1892 if (!JS_SetPrototype(cx
, mJSObject
, proto
)) {
1893 NS_ERROR("Can't set prototype");
1894 return NS_ERROR_UNEXPECTED
;
1897 nsCOMPtr
<nsIXPConnectJSObjectHolder
> holder
;
1898 xpc
->ReparentWrappedNativeIfFound(cx
, currentInner
->mJSObject
,
1899 newInnerWindow
->mJSObject
,
1901 getter_AddRefs(holder
));
1904 if (nsIXPConnectJSObjectHolder
*holder
= wsh
->GetOuterRealProto()) {
1905 holder
->GetJSObject(&proto
);
1910 if (!JS_SetPrototype(cx
, mJSObject
, proto
)) {
1911 NS_ERROR("can't set prototype");
1912 return NS_ERROR_FAILURE
;
1918 if (!aState
&& !reUseInnerWindow
) {
1919 // Loading a new page and creating a new inner window, *not*
1920 // restoring from session history.
1922 // InitClassesWithNewWrappedGlobal() (via CreateNativeGlobalForInner)
1923 // for the new inner window
1924 // sets the global object in cx to be the new wrapped global. We
1925 // don't want that, but re-initializing the outer window will
1926 // fix that for us. And perhaps more importantly, this will
1927 // ensure that the outer window gets a new prototype so we don't
1928 // leak prototype properties from the old inner window to the
1930 mContext
->InitOuterWindow();
1932 // Now that both the the inner and outer windows are initialized
1933 // let the script context do its magic to hook them together.
1934 mContext
->ConnectToInner(newInnerWindow
, mJSObject
);
1936 nsCOMPtr
<nsIContent
> frame
= do_QueryInterface(GetFrameElementInternal());
1937 if (frame
&& frame
->GetOwnerDoc()) {
1938 nsPIDOMWindow
* parentWindow
= frame
->GetOwnerDoc()->GetWindow();
1939 if (parentWindow
&& parentWindow
->TimeoutSuspendCount()) {
1940 SuspendTimeouts(parentWindow
->TimeoutSuspendCount());
1945 // Tell the contexts we have completed setting up the doc.
1946 // Add an extra ref in case we release mContext during GC.
1947 nsCOMPtr
<nsIScriptContext
> kungFuDeathGrip(mContext
);
1948 nsCOMPtr
<nsIDOMDocument
> dd(do_QueryInterface(aDocument
));
1949 mContext
->DidSetDocument(dd
, newInnerWindow
->mJSObject
);
1951 // Now that the prototype is all set up, install the global scope
1952 // polluter. This must happen after the above prototype fixup. If
1953 // the GSP was to be installed on the inner window's real
1954 // prototype (as it would be if this was done before the prototype
1955 // fixup above) we would end up holding the GSP alive (through
1956 // XPConnect's internal marking of wrapper prototypes) as long as
1957 // the inner window was around, and if the GSP had properties on
1958 // it that held an element alive we'd hold the document alive,
1959 // which could hold event handlers alive, which hold the context
1962 if ((!reUseInnerWindow
|| aDocument
!= oldDoc
) && !aState
) {
1963 nsCOMPtr
<nsIHTMLDocument
> html_doc(do_QueryInterface(mDocument
));
1964 nsCommonWindowSH::InstallGlobalScopePolluter(cx
, newInnerWindow
->mJSObject
,
1969 aDocument
->SetScriptGlobalObject(newInnerWindow
);
1973 if (reUseInnerWindow
) {
1974 if (newInnerWindow
->mDoc
!= aDocument
) {
1975 newInnerWindow
->mDocument
= do_QueryInterface(aDocument
);
1976 newInnerWindow
->mDoc
= aDocument
;
1978 // We're reusing the inner window for a new document. In this
1979 // case we don't clear the inner window's scope, but we must
1980 // make sure the cached document property gets updated.
1982 // XXXmarkh - tell other languages about this?
1983 ::JS_DeleteProperty(cx
, currentInner
->mJSObject
, "document");
1986 rv
= newInnerWindow
->InnerSetNewDocument(aDocument
);
1987 NS_ENSURE_SUCCESS(rv
, rv
);
1989 // Initialize DOM classes etc on the inner window.
1990 rv
= mContext
->InitClasses(mJSObject
);
1991 NS_ENSURE_SUCCESS(rv
, rv
);
1993 if (navigatorHolder
) {
1994 // Restore window.navigator onto the new inner window.
1996 ::JS_DefineProperty(cx
, newInnerWindow
->mJSObject
, "navigator",
1997 nav
, nsnull
, nsnull
,
1998 JSPROP_ENUMERATE
| JSPROP_PERMANENT
|
2001 // The Navigator's prototype object keeps a reference to the
2002 // window in which it was first created and can thus cause that
2003 // window to stay alive for too long. Reparenting it here allows
2004 // the window to be collected sooner.
2005 nsIDOMNavigator
* navigator
=
2006 static_cast<nsIDOMNavigator
*>(mNavigator
);
2009 ReparentWrappedNativeIfFound(cx
, JSVAL_TO_OBJECT(nav
),
2010 newInnerWindow
->mJSObject
,
2012 getter_AddRefs(navigatorHolder
));
2017 newInnerWindow
->DefineArgumentsProperty(mArguments
);
2018 newInnerWindow
->mArguments
= mArguments
;
2019 newInnerWindow
->mArgumentsOrigin
= mArgumentsOrigin
;
2021 mArguments
= nsnull
;
2022 mArgumentsOrigin
= nsnull
;
2025 // Give the new inner window our chrome event handler (since it
2026 // doesn't have one).
2027 newInnerWindow
->mChromeEventHandler
= mChromeEventHandler
;
2031 mContext
->DidInitializeContext();
2034 rv
= xpc
->GetWrappedNativeOfJSObject(cx
, mJSObject
,
2035 getter_AddRefs(wrapper
));
2036 NS_ENSURE_SUCCESS(rv
, rv
);
2039 rv
= xpc
->UpdateXOWs((JSContext
*)GetContextInternal()->GetNativeContext(),
2040 wrapper
, nsIXPConnect::XPC_XOW_NAVIGATED
);
2041 NS_ENSURE_SUCCESS(rv
, rv
);
2043 if (!aState
&& !reUseInnerWindow
) {
2044 nsContentUtils::AddScriptRunner(
2045 NS_NewRunnableMethod(this, &nsGlobalWindow::DispatchDOMWindowCreated
));
2052 nsGlobalWindow::DispatchDOMWindowCreated()
2054 if (!mDoc
|| !mDocument
) {
2058 // Fire DOMWindowCreated at chrome event listeners
2059 nsContentUtils::DispatchChromeEvent(mDoc
, mDocument
, NS_LITERAL_STRING("DOMWindowCreated"),
2060 PR_TRUE
/* bubbles */,
2061 PR_FALSE
/* not cancellable */);
2063 nsCOMPtr
<nsIObserverService
> observerService
=
2064 mozilla::services::GetObserverService();
2065 if (observerService
) {
2066 nsAutoString origin
;
2067 nsIPrincipal
* principal
= mDoc
->NodePrincipal();
2068 nsContentUtils::GetUTFOrigin(principal
, origin
);
2070 NotifyObservers(static_cast<nsIDOMWindow
*>(this),
2071 nsContentUtils::IsSystemPrincipal(principal
) ?
2072 "chrome-document-global-created" :
2073 "content-document-global-created",
2079 nsGlobalWindow::ClearStatus()
2081 SetStatus(EmptyString());
2082 SetDefaultStatus(EmptyString());
2086 nsGlobalWindow::InnerSetNewDocument(nsIDocument
* aDocument
)
2088 NS_PRECONDITION(IsInnerWindow(), "Must only be called on inner windows");
2091 if (aDocument
&& gDOMLeakPRLog
&&
2092 PR_LOG_TEST(gDOMLeakPRLog
, PR_LOG_DEBUG
)) {
2093 nsIURI
*uri
= aDocument
->GetDocumentURI();
2097 PR_LogPrint("DOMWINDOW %p SetNewDocument %s", this, spec
.get());
2101 mDocument
= do_QueryInterface(aDocument
);
2103 mLocalStorage
= nsnull
;
2104 mSessionStorage
= nsnull
;
2107 mLastOpenedURI
= aDocument
->GetDocumentURI();
2110 // Clear our mutation bitfield.
2117 nsGlobalWindow::SetDocShell(nsIDocShell
* aDocShell
)
2119 NS_ASSERTION(IsOuterWindow(), "Uh, SetDocShell() called on inner window!");
2121 if (aDocShell
== mDocShell
)
2124 // SetDocShell(nsnull) means the window is being torn down. Drop our
2125 // reference to the script context, allowing it to be deleted
2126 // later. Meanwhile, keep our weak reference to the script object
2127 // (mJSObject) so that it can be retrieved later (until it is
2128 // finalized by the JS GC).
2131 NS_ASSERTION(PR_CLIST_IS_EMPTY(&mTimeouts
),
2132 "Uh, outer window holds timeouts!");
2134 // Call FreeInnerObjects on all inner windows, not just the current
2135 // one, since some could be held by WindowStateHolder objects that
2137 for (nsRefPtr
<nsGlobalWindow
> inner
= (nsGlobalWindow
*)PR_LIST_HEAD(this);
2139 inner
= (nsGlobalWindow
*)PR_NEXT_LINK(inner
)) {
2140 NS_ASSERTION(inner
->mOuterWindow
== this, "bad outer window pointer");
2141 inner
->FreeInnerObjects(PR_TRUE
);
2144 // Make sure that this is called before we null out the document.
2145 NotifyDOMWindowDestroyed(this);
2147 NotifyWindowIDDestroyed("outer-window-destroyed");
2149 nsGlobalWindow
*currentInner
= GetCurrentInnerWindowInternal();
2152 NS_ASSERTION(mDoc
, "Must have doc!");
2154 // Remember the document's principal.
2155 mDocumentPrincipal
= mDoc
->NodePrincipal();
2157 // Release our document reference
2163 mContext
->ClearScope(mJSObject
, PR_TRUE
);
2168 mChromeEventHandler
= nsnull
; // force release now
2171 // We got no new document after someone called
2172 // SetArguments(), drop our reference to the arguments.
2173 mArguments
= nsnull
;
2174 mArgumentsLast
= nsnull
;
2175 mArgumentsOrigin
= nsnull
;
2180 mContext
->FinalizeContext();
2185 nsCycleCollector_DEBUG_shouldBeFreed(mContext
);
2186 nsCycleCollector_DEBUG_shouldBeFreed(static_cast<nsIScriptGlobalObject
*>(this));
2190 mDocShell
= aDocShell
; // Weak Reference
2193 mNavigator
->SetDocShell(aDocShell
);
2195 mHistory
->SetDocShell(aDocShell
);
2197 mFrames
->SetDocShell(aDocShell
);
2199 mScreen
->SetDocShell(aDocShell
);
2201 // tell our member elements about the new browserwindow
2202 nsCOMPtr
<nsIWebBrowserChrome
> browserChrome
;
2203 GetWebBrowserChrome(getter_AddRefs(browserChrome
));
2205 mMenubar
->SetWebBrowserChrome(browserChrome
);
2208 mToolbar
->SetWebBrowserChrome(browserChrome
);
2211 mLocationbar
->SetWebBrowserChrome(browserChrome
);
2214 mPersonalbar
->SetWebBrowserChrome(browserChrome
);
2217 mStatusbar
->SetWebBrowserChrome(browserChrome
);
2220 mScrollbars
->SetWebBrowserChrome(browserChrome
);
2224 MaybeForgiveSpamCount();
2227 // Get our enclosing chrome shell and retrieve its global window impl, so
2228 // that we can do some forwarding to the chrome document.
2229 nsCOMPtr
<nsIDOMEventTarget
> chromeEventHandler
;
2230 mDocShell
->GetChromeEventHandler(getter_AddRefs(chromeEventHandler
));
2231 mChromeEventHandler
= do_QueryInterface(chromeEventHandler
);
2232 if (!mChromeEventHandler
) {
2233 // We have no chrome event handler. If we have a parent,
2234 // get our chrome event handler from the parent. If
2235 // we don't have a parent, then we need to make a new
2236 // window root object that will function as a chrome event
2237 // handler and receive all events that occur anywhere inside
2239 nsCOMPtr
<nsIDOMWindow
> parentWindow
;
2240 GetParent(getter_AddRefs(parentWindow
));
2241 if (parentWindow
.get() != static_cast<nsIDOMWindow
*>(this)) {
2242 nsCOMPtr
<nsPIDOMWindow
> piWindow(do_QueryInterface(parentWindow
));
2243 mChromeEventHandler
= piWindow
->GetChromeEventHandler();
2245 else NS_NewWindowRoot(this, getter_AddRefs(mChromeEventHandler
));
2251 nsGlobalWindow::SetOpenerWindow(nsIDOMWindowInternal
* aOpener
,
2252 PRBool aOriginalOpener
)
2254 FORWARD_TO_OUTER_VOID(SetOpenerWindow
, (aOpener
, aOriginalOpener
));
2256 NS_ASSERTION(!aOriginalOpener
|| !mSetOpenerWindowCalled
,
2257 "aOriginalOpener is true, but not first call to "
2258 "SetOpenerWindow!");
2259 NS_ASSERTION(aOpener
|| !aOriginalOpener
,
2260 "Shouldn't set mHadOriginalOpener if aOpener is null");
2262 mOpener
= do_GetWeakReference(aOpener
);
2263 NS_ASSERTION(mOpener
|| !aOpener
, "Opener must support weak references!");
2265 if (aOriginalOpener
) {
2266 mHadOriginalOpener
= PR_TRUE
;
2270 mSetOpenerWindowCalled
= PR_TRUE
;
2275 nsGlobalWindow::UpdateParentTarget()
2277 nsCOMPtr
<nsIFrameLoaderOwner
> flo
= do_QueryInterface(mChromeEventHandler
);
2279 nsRefPtr
<nsFrameLoader
> fl
= flo
->GetFrameLoader();
2281 mParentTarget
= fl
->GetTabChildGlobalAsEventTarget();
2284 if (!mParentTarget
) {
2285 mParentTarget
= mChromeEventHandler
;
2290 nsGlobalWindow::PreHandleEvent(nsEventChainPreVisitor
& aVisitor
)
2292 NS_PRECONDITION(IsInnerWindow(), "PreHandleEvent is used on outer window!?");
2293 static PRUint32 count
= 0;
2294 PRUint32 msg
= aVisitor
.mEvent
->message
;
2296 aVisitor
.mCanHandle
= PR_TRUE
;
2297 aVisitor
.mForceContentDispatch
= PR_TRUE
; //FIXME! Bug 329119
2298 if ((msg
== NS_MOUSE_MOVE
) && gEntropyCollector
) {
2299 //Chances are this counter will overflow during the life of the
2300 //process, but that's OK for our case. Means we get a little
2302 if (count
++ % 100 == 0) {
2303 //Since the high bits seem to be zero's most of the time,
2304 //let's only take the lowest half of the point structure.
2307 myCoord
[0] = aVisitor
.mEvent
->refPoint
.x
;
2308 myCoord
[1] = aVisitor
.mEvent
->refPoint
.y
;
2309 gEntropyCollector
->RandomUpdate((void*)myCoord
, sizeof(myCoord
));
2310 gEntropyCollector
->RandomUpdate((void*)&(aVisitor
.mEvent
->time
),
2313 } else if (msg
== NS_RESIZE_EVENT
) {
2314 mIsHandlingResizeEvent
= PR_TRUE
;
2315 } else if (msg
== NS_MOUSE_BUTTON_DOWN
&&
2316 NS_IS_TRUSTED_EVENT(aVisitor
.mEvent
)) {
2317 gMouseDown
= PR_TRUE
;
2318 } else if (msg
== NS_MOUSE_BUTTON_UP
&&
2319 NS_IS_TRUSTED_EVENT(aVisitor
.mEvent
)) {
2320 gMouseDown
= PR_FALSE
;
2321 if (gDragServiceDisabled
) {
2322 nsCOMPtr
<nsIDragService
> ds
=
2323 do_GetService("@mozilla.org/widget/dragservice;1");
2325 gDragServiceDisabled
= PR_FALSE
;
2331 aVisitor
.mParentTarget
= GetParentTarget();
2336 nsGlobalWindow::PostHandleEvent(nsEventChainPostVisitor
& aVisitor
)
2338 NS_PRECONDITION(IsInnerWindow(), "PostHandleEvent is used on outer window!?");
2340 // Return early if there is nothing to do.
2341 switch (aVisitor
.mEvent
->message
) {
2342 case NS_RESIZE_EVENT
:
2343 case NS_PAGE_UNLOAD
:
2350 /* mChromeEventHandler and mContext go dangling in the middle of this
2351 function under some circumstances (events that destroy the window)
2352 without this addref. */
2353 nsCOMPtr
<nsPIDOMEventTarget
> kungFuDeathGrip1(mChromeEventHandler
);
2354 nsCOMPtr
<nsIScriptContext
> kungFuDeathGrip2(GetContextInternal());
2356 if (aVisitor
.mEvent
->message
== NS_RESIZE_EVENT
) {
2357 mIsHandlingResizeEvent
= PR_FALSE
;
2358 } else if (aVisitor
.mEvent
->message
== NS_PAGE_UNLOAD
&&
2359 NS_IS_TRUSTED_EVENT(aVisitor
.mEvent
)) {
2360 // Execute bindingdetached handlers before we tear ourselves
2363 NS_ASSERTION(mDoc
, "Must have doc");
2364 mDoc
->BindingManager()->ExecuteDetachedHandlers();
2366 mIsDocumentLoaded
= PR_FALSE
;
2367 } else if (aVisitor
.mEvent
->message
== NS_LOAD
&&
2368 NS_IS_TRUSTED_EVENT(aVisitor
.mEvent
)) {
2369 // This is page load event since load events don't propagate to |window|.
2370 // @see nsDocument::PreHandleEvent.
2371 mIsDocumentLoaded
= PR_TRUE
;
2373 nsCOMPtr
<nsIContent
> content(do_QueryInterface(GetFrameElementInternal()));
2374 nsCOMPtr
<nsIDocShellTreeItem
> treeItem
=
2375 do_QueryInterface(GetDocShell());
2377 PRInt32 itemType
= nsIDocShellTreeItem::typeChrome
;
2380 treeItem
->GetItemType(&itemType
);
2383 if (content
&& GetParentInternal() &&
2384 itemType
!= nsIDocShellTreeItem::typeChrome
) {
2385 // If we're not in chrome, or at a chrome boundary, fire the
2386 // onload event for the frame element.
2388 nsEventStatus status
= nsEventStatus_eIgnore
;
2389 nsEvent
event(NS_IS_TRUSTED_EVENT(aVisitor
.mEvent
), NS_LOAD
);
2390 event
.flags
|= NS_EVENT_FLAG_CANT_BUBBLE
;
2392 // Most of the time we could get a pres context to pass in here,
2393 // but not always (i.e. if this window is not shown there won't
2394 // be a pres context available). Since we're not firing a GUI
2395 // event we don't need a pres context anyway so we just pass
2396 // null as the pres context all the time here.
2398 nsEventDispatcher::Dispatch(content
, nsnull
, &event
, nsnull
, &status
);
2406 nsGlobalWindow::DispatchDOMEvent(nsEvent
* aEvent
,
2407 nsIDOMEvent
* aDOMEvent
,
2408 nsPresContext
* aPresContext
,
2409 nsEventStatus
* aEventStatus
)
2412 nsEventDispatcher::DispatchDOMEvent(static_cast<nsPIDOMWindow
*>(this),
2413 aEvent
, aDOMEvent
, aPresContext
,
2418 nsGlobalWindow::OnFinalize(PRUint32 aLangID
, void *aObject
)
2420 NS_ASSERTION(aLangID
== nsIProgrammingLanguage::JAVASCRIPT
,
2421 "We don't support this language ID");
2423 if (aObject
== mJSObject
) {
2429 nsGlobalWindow::SetScriptsEnabled(PRBool aEnabled
, PRBool aFireTimeouts
)
2431 FORWARD_TO_INNER_VOID(SetScriptsEnabled
, (aEnabled
, aFireTimeouts
));
2433 if (aEnabled
&& aFireTimeouts
) {
2434 // Scripts are enabled (again?) on this context, run timeouts that
2435 // fired on this context while scripts were disabled.
2436 void (nsGlobalWindow::*run
)() = &nsGlobalWindow::RunTimeout
;
2437 NS_DispatchToCurrentThread(NS_NewRunnableMethod(this, run
));
2442 nsGlobalWindow::SetArguments(nsIArray
*aArguments
, nsIPrincipal
*aOrigin
)
2444 FORWARD_TO_OUTER(SetArguments
, (aArguments
, aOrigin
),
2445 NS_ERROR_NOT_INITIALIZED
);
2447 // Hold on to the arguments so that we can re-set them once the next
2448 // document is loaded.
2449 mArguments
= aArguments
;
2450 mArgumentsOrigin
= aOrigin
;
2452 nsGlobalWindow
*currentInner
= GetCurrentInnerWindowInternal();
2454 if (!mIsModalContentWindow
) {
2455 mArgumentsLast
= aArguments
;
2456 } else if (currentInner
) {
2457 // SetArguments() is being called on a modal content window that
2458 // already has an inner window. This can happen when loading
2459 // javascript: URIs as modal content dialogs. In this case, we'll
2460 // set up the dialog window, both inner and outer, before we call
2461 // SetArguments() on the window, so to deal with that, make sure
2462 // here that the arguments are propagated to the inner window.
2464 currentInner
->mArguments
= aArguments
;
2465 currentInner
->mArgumentsOrigin
= aOrigin
;
2468 return currentInner
?
2469 currentInner
->DefineArgumentsProperty(aArguments
) : NS_OK
;
2473 nsGlobalWindow::DefineArgumentsProperty(nsIArray
*aArguments
)
2476 nsIScriptContext
*ctx
= GetOuterWindowInternal()->mContext
;
2477 NS_ENSURE_TRUE(aArguments
&& ctx
&&
2478 (cx
= (JSContext
*)ctx
->GetNativeContext()),
2479 NS_ERROR_NOT_INITIALIZED
);
2481 if (mIsModalContentWindow
) {
2482 // Modal content windows don't have an "arguments" property, they
2483 // have a "dialogArguments" property which is handled
2484 // separately. See nsCommonWindowSH::NewResolve().
2489 return GetContextInternal()->SetProperty(mJSObject
, "arguments", aArguments
);
2492 //*****************************************************************************
2493 // nsGlobalWindow::nsIScriptObjectPrincipal
2494 //*****************************************************************************
2497 nsGlobalWindow::GetPrincipal()
2500 // If we have a document, get the principal from the document
2501 return mDoc
->NodePrincipal();
2504 if (mDocumentPrincipal
) {
2505 return mDocumentPrincipal
;
2508 // If we don't have a principal and we don't have a document we
2509 // ask the parent window for the principal. This can happen when
2510 // loading a frameset that has a <frame src="javascript:xxx">, in
2511 // that case the global window is used in JS before we've loaded
2512 // a document into the window.
2514 nsCOMPtr
<nsIScriptObjectPrincipal
> objPrincipal
=
2515 do_QueryInterface(GetParentInternal());
2518 return objPrincipal
->GetPrincipal();
2524 //*****************************************************************************
2525 // nsGlobalWindow::nsIDOMWindow
2526 //*****************************************************************************
2529 nsGlobalWindow::GetDocument(nsIDOMDocument
** aDocument
)
2531 // This method *should* forward calls to the outer window, but since
2532 // there's nothing here that *depends* on anything in the outer
2533 // (GetDocShell() eliminates that dependency), we won't do that to
2534 // avoid the extra virtual function call.
2536 // lazily instantiate an about:blank document if necessary, and if
2537 // we have what it takes to do so. Note that domdoc here is the same
2538 // thing as our mDocument, but we don't have to explicitly set the
2539 // member variable because the docshell has already called
2540 // SetNewDocument().
2541 nsIDocShell
*docShell
;
2542 if (!mDocument
&& (docShell
= GetDocShell()))
2543 nsCOMPtr
<nsIDOMDocument
> domdoc(do_GetInterface(docShell
));
2545 NS_IF_ADDREF(*aDocument
= mDocument
);
2550 //*****************************************************************************
2551 // nsGlobalWindow::nsIDOMWindowInternal
2552 //*****************************************************************************
2555 nsGlobalWindow::GetWindow(nsIDOMWindowInternal
** aWindow
)
2557 FORWARD_TO_OUTER(GetWindow
, (aWindow
), NS_ERROR_NOT_INITIALIZED
);
2559 *aWindow
= static_cast<nsIDOMWindowInternal
*>(this);
2560 NS_ADDREF(*aWindow
);
2565 nsGlobalWindow::GetSelf(nsIDOMWindowInternal
** aWindow
)
2567 FORWARD_TO_OUTER(GetSelf
, (aWindow
), NS_ERROR_NOT_INITIALIZED
);
2569 *aWindow
= static_cast<nsIDOMWindowInternal
*>(this);
2570 NS_ADDREF(*aWindow
);
2575 nsGlobalWindow::GetNavigator(nsIDOMNavigator
** aNavigator
)
2577 FORWARD_TO_OUTER(GetNavigator
, (aNavigator
), NS_ERROR_NOT_INITIALIZED
);
2579 *aNavigator
= nsnull
;
2582 mNavigator
= new nsNavigator(mDocShell
);
2584 return NS_ERROR_OUT_OF_MEMORY
;
2588 NS_ADDREF(*aNavigator
= mNavigator
);
2594 nsGlobalWindow::GetScreen(nsIDOMScreen
** aScreen
)
2596 FORWARD_TO_OUTER(GetScreen
, (aScreen
), NS_ERROR_NOT_INITIALIZED
);
2600 if (!mScreen
&& mDocShell
) {
2601 mScreen
= new nsScreen(mDocShell
);
2603 return NS_ERROR_OUT_OF_MEMORY
;
2607 NS_IF_ADDREF(*aScreen
= mScreen
);
2613 nsGlobalWindow::GetHistory(nsIDOMHistory
** aHistory
)
2615 FORWARD_TO_OUTER(GetHistory
, (aHistory
), NS_ERROR_NOT_INITIALIZED
);
2619 if (!mHistory
&& mDocShell
) {
2620 mHistory
= new nsHistory(mDocShell
);
2622 return NS_ERROR_OUT_OF_MEMORY
;
2626 NS_IF_ADDREF(*aHistory
= mHistory
);
2631 nsGlobalWindow::GetParent(nsIDOMWindow
** aParent
)
2633 FORWARD_TO_OUTER(GetParent
, (aParent
), NS_ERROR_NOT_INITIALIZED
);
2639 nsCOMPtr
<nsIDocShellTreeItem
> docShellAsItem(do_QueryInterface(mDocShell
));
2640 NS_ENSURE_TRUE(docShellAsItem
, NS_ERROR_FAILURE
);
2642 nsCOMPtr
<nsIDocShellTreeItem
> parent
;
2643 docShellAsItem
->GetSameTypeParent(getter_AddRefs(parent
));
2646 nsCOMPtr
<nsIScriptGlobalObject
> globalObject(do_GetInterface(parent
));
2647 NS_ENSURE_SUCCESS(CallQueryInterface(globalObject
.get(), aParent
),
2651 *aParent
= static_cast<nsIDOMWindowInternal
*>(this);
2652 NS_ADDREF(*aParent
);
2658 nsGlobalWindow::GetTop(nsIDOMWindow
** aTop
)
2660 FORWARD_TO_OUTER(GetTop
, (aTop
), NS_ERROR_NOT_INITIALIZED
);
2662 nsresult ret
= NS_OK
;
2666 nsCOMPtr
<nsIDocShellTreeItem
> docShellAsItem(do_QueryInterface(mDocShell
));
2667 nsCOMPtr
<nsIDocShellTreeItem
> root
;
2668 docShellAsItem
->GetSameTypeRootTreeItem(getter_AddRefs(root
));
2671 nsCOMPtr
<nsIScriptGlobalObject
> globalObject(do_GetInterface(root
));
2672 CallQueryInterface(globalObject
.get(), aTop
);
2680 nsGlobalWindow::GetContent(nsIDOMWindow
** aContent
)
2682 FORWARD_TO_OUTER(GetContent
, (aContent
), NS_ERROR_NOT_INITIALIZED
);
2686 nsCOMPtr
<nsIDocShellTreeItem
> primaryContent
;
2688 if (!nsContentUtils::IsCallerChrome()) {
2689 // If we're called by non-chrome code, make sure we don't return
2690 // the primary content window if the calling tab is hidden. In
2691 // such a case we return the same-type root in the hidden tab,
2692 // which is "good enough", for now.
2693 nsCOMPtr
<nsIBaseWindow
> baseWin(do_QueryInterface(mDocShell
));
2696 PRBool visible
= PR_FALSE
;
2697 baseWin
->GetVisibility(&visible
);
2700 nsCOMPtr
<nsIDocShellTreeItem
> treeItem(do_QueryInterface(mDocShell
));
2702 treeItem
->GetSameTypeRootTreeItem(getter_AddRefs(primaryContent
));
2707 if (!primaryContent
) {
2708 nsCOMPtr
<nsIDocShellTreeOwner
> treeOwner
;
2709 GetTreeOwner(getter_AddRefs(treeOwner
));
2710 NS_ENSURE_TRUE(treeOwner
, NS_ERROR_FAILURE
);
2712 treeOwner
->GetPrimaryContentShell(getter_AddRefs(primaryContent
));
2715 nsCOMPtr
<nsIDOMWindowInternal
> domWindow(do_GetInterface(primaryContent
));
2716 NS_IF_ADDREF(*aContent
= domWindow
);
2722 nsGlobalWindow::GetPrompter(nsIPrompt
** aPrompt
)
2724 FORWARD_TO_OUTER(GetPrompter
, (aPrompt
), NS_ERROR_NOT_INITIALIZED
);
2727 return NS_ERROR_FAILURE
;
2729 nsCOMPtr
<nsIPrompt
> prompter(do_GetInterface(mDocShell
));
2730 NS_ENSURE_TRUE(prompter
, NS_ERROR_NO_INTERFACE
);
2732 NS_ADDREF(*aPrompt
= prompter
);
2737 nsGlobalWindow::GetMenubar(nsIDOMBarProp
** aMenubar
)
2739 FORWARD_TO_OUTER(GetMenubar
, (aMenubar
), NS_ERROR_NOT_INITIALIZED
);
2744 mMenubar
= new nsMenubarProp();
2746 return NS_ERROR_OUT_OF_MEMORY
;
2749 nsCOMPtr
<nsIWebBrowserChrome
> browserChrome
;
2750 GetWebBrowserChrome(getter_AddRefs(browserChrome
));
2752 mMenubar
->SetWebBrowserChrome(browserChrome
);
2755 NS_ADDREF(*aMenubar
= mMenubar
);
2761 nsGlobalWindow::GetToolbar(nsIDOMBarProp
** aToolbar
)
2763 FORWARD_TO_OUTER(GetToolbar
, (aToolbar
), NS_ERROR_NOT_INITIALIZED
);
2768 mToolbar
= new nsToolbarProp();
2770 return NS_ERROR_OUT_OF_MEMORY
;
2773 nsCOMPtr
<nsIWebBrowserChrome
> browserChrome
;
2774 GetWebBrowserChrome(getter_AddRefs(browserChrome
));
2776 mToolbar
->SetWebBrowserChrome(browserChrome
);
2779 NS_ADDREF(*aToolbar
= mToolbar
);
2785 nsGlobalWindow::GetLocationbar(nsIDOMBarProp
** aLocationbar
)
2787 FORWARD_TO_OUTER(GetLocationbar
, (aLocationbar
), NS_ERROR_NOT_INITIALIZED
);
2789 *aLocationbar
= nsnull
;
2791 if (!mLocationbar
) {
2792 mLocationbar
= new nsLocationbarProp();
2793 if (!mLocationbar
) {
2794 return NS_ERROR_OUT_OF_MEMORY
;
2797 nsCOMPtr
<nsIWebBrowserChrome
> browserChrome
;
2798 GetWebBrowserChrome(getter_AddRefs(browserChrome
));
2800 mLocationbar
->SetWebBrowserChrome(browserChrome
);
2803 NS_ADDREF(*aLocationbar
= mLocationbar
);
2809 nsGlobalWindow::GetPersonalbar(nsIDOMBarProp
** aPersonalbar
)
2811 FORWARD_TO_OUTER(GetPersonalbar
, (aPersonalbar
), NS_ERROR_NOT_INITIALIZED
);
2813 *aPersonalbar
= nsnull
;
2815 if (!mPersonalbar
) {
2816 mPersonalbar
= new nsPersonalbarProp();
2817 if (!mPersonalbar
) {
2818 return NS_ERROR_OUT_OF_MEMORY
;
2821 nsCOMPtr
<nsIWebBrowserChrome
> browserChrome
;
2822 GetWebBrowserChrome(getter_AddRefs(browserChrome
));
2824 mPersonalbar
->SetWebBrowserChrome(browserChrome
);
2827 NS_ADDREF(*aPersonalbar
= mPersonalbar
);
2833 nsGlobalWindow::GetStatusbar(nsIDOMBarProp
** aStatusbar
)
2835 FORWARD_TO_OUTER(GetStatusbar
, (aStatusbar
), NS_ERROR_NOT_INITIALIZED
);
2837 *aStatusbar
= nsnull
;
2840 mStatusbar
= new nsStatusbarProp();
2842 return NS_ERROR_OUT_OF_MEMORY
;
2845 nsCOMPtr
<nsIWebBrowserChrome
> browserChrome
;
2846 GetWebBrowserChrome(getter_AddRefs(browserChrome
));
2848 mStatusbar
->SetWebBrowserChrome(browserChrome
);
2851 NS_ADDREF(*aStatusbar
= mStatusbar
);
2857 nsGlobalWindow::GetScrollbars(nsIDOMBarProp
** aScrollbars
)
2859 FORWARD_TO_OUTER(GetScrollbars
, (aScrollbars
), NS_ERROR_NOT_INITIALIZED
);
2861 *aScrollbars
= nsnull
;
2864 mScrollbars
= new nsScrollbarsProp(this);
2866 return NS_ERROR_OUT_OF_MEMORY
;
2869 nsCOMPtr
<nsIWebBrowserChrome
> browserChrome
;
2870 GetWebBrowserChrome(getter_AddRefs(browserChrome
));
2872 mScrollbars
->SetWebBrowserChrome(browserChrome
);
2875 NS_ADDREF(*aScrollbars
= mScrollbars
);
2881 nsGlobalWindow::GetClosed(PRBool
* aClosed
)
2883 FORWARD_TO_OUTER(GetClosed
, (aClosed
), NS_ERROR_NOT_INITIALIZED
);
2885 // If someone called close(), or if we don't have a docshell, we're
2887 *aClosed
= mIsClosed
|| !mDocShell
;
2893 nsGlobalWindow::GetFrames(nsIDOMWindowCollection
** aFrames
)
2895 FORWARD_TO_OUTER(GetFrames
, (aFrames
), NS_ERROR_NOT_INITIALIZED
);
2899 if (!mFrames
&& mDocShell
) {
2900 mFrames
= new nsDOMWindowList(mDocShell
);
2902 return NS_ERROR_OUT_OF_MEMORY
;
2906 *aFrames
= static_cast<nsIDOMWindowCollection
*>(mFrames
);
2907 NS_IF_ADDREF(*aFrames
);
2912 nsGlobalWindow::GetApplicationCache(nsIDOMOfflineResourceList
**aApplicationCache
)
2914 FORWARD_TO_INNER(GetApplicationCache
, (aApplicationCache
), NS_ERROR_UNEXPECTED
);
2916 NS_ENSURE_ARG_POINTER(aApplicationCache
);
2918 if (!mApplicationCache
) {
2919 nsCOMPtr
<nsIWebNavigation
> webNav(do_QueryInterface(GetDocShell()));
2921 return NS_ERROR_FAILURE
;
2924 nsCOMPtr
<nsIURI
> uri
;
2925 nsresult rv
= webNav
->GetCurrentURI(getter_AddRefs(uri
));
2926 NS_ENSURE_SUCCESS(rv
, rv
);
2928 nsCOMPtr
<nsIDocument
> doc
= do_QueryInterface(mDocument
);
2929 nsCOMPtr
<nsIURI
> manifestURI
;
2930 nsContentUtils::GetOfflineAppManifest(doc
, getter_AddRefs(manifestURI
));
2932 nsIScriptContext
* scriptContext
= GetContext();
2933 NS_ENSURE_STATE(scriptContext
);
2935 nsRefPtr
<nsDOMOfflineResourceList
> applicationCache
=
2936 new nsDOMOfflineResourceList(manifestURI
, uri
, this, scriptContext
);
2937 NS_ENSURE_TRUE(applicationCache
, NS_ERROR_OUT_OF_MEMORY
);
2939 applicationCache
->Init();
2941 mApplicationCache
= applicationCache
;
2944 NS_IF_ADDREF(*aApplicationCache
= mApplicationCache
);
2950 nsGlobalWindow::GetCrypto(nsIDOMCrypto
** aCrypto
)
2952 FORWARD_TO_OUTER(GetCrypto
, (aCrypto
), NS_ERROR_NOT_INITIALIZED
);
2955 mCrypto
= do_CreateInstance(kCryptoContractID
);
2958 NS_IF_ADDREF(*aCrypto
= mCrypto
);
2964 nsGlobalWindow::GetPkcs11(nsIDOMPkcs11
** aPkcs11
)
2971 nsGlobalWindow::GetControllers(nsIControllers
** aResult
)
2973 FORWARD_TO_OUTER(GetControllers
, (aResult
), NS_ERROR_NOT_INITIALIZED
);
2975 if (!mControllers
) {
2977 mControllers
= do_CreateInstance(kXULControllersCID
, &rv
);
2978 NS_ENSURE_SUCCESS(rv
, rv
);
2980 // Add in the default controller
2981 nsCOMPtr
<nsIController
> controller
= do_CreateInstance(
2982 NS_WINDOWCONTROLLER_CONTRACTID
, &rv
);
2983 NS_ENSURE_SUCCESS(rv
, rv
);
2985 mControllers
->InsertControllerAt(0, controller
);
2986 nsCOMPtr
<nsIControllerContext
> controllerContext
= do_QueryInterface(controller
);
2987 if (!controllerContext
) return NS_ERROR_FAILURE
;
2989 controllerContext
->SetCommandContext(static_cast<nsIDOMWindow
*>(this));
2992 *aResult
= mControllers
;
2993 NS_ADDREF(*aResult
);
2998 nsGlobalWindow::GetOpener(nsIDOMWindowInternal
** aOpener
)
3000 FORWARD_TO_OUTER(GetOpener
, (aOpener
), NS_ERROR_NOT_INITIALIZED
);
3004 nsCOMPtr
<nsPIDOMWindow
> opener
= do_QueryReferent(mOpener
);
3009 // First, check if we were called from a privileged chrome script
3010 if (nsContentUtils::IsCallerTrustedForRead()) {
3011 NS_ADDREF(*aOpener
= opener
);
3015 nsCOMPtr
<nsPIDOMWindow
> openerPwin(do_QueryInterface(opener
));
3020 // First, ensure that we're not handing back a chrome window.
3021 nsGlobalWindow
*win
= static_cast<nsGlobalWindow
*>(openerPwin
.get());
3022 if (win
->IsChromeWindow()) {
3026 // We don't want to reveal the opener if the opener is a mail window,
3027 // because opener can be used to spoof the contents of a message (bug 105050).
3028 // So, we look in the opener's root docshell to see if it's a mail window.
3029 nsCOMPtr
<nsIDocShellTreeItem
> docShellAsItem
=
3030 do_QueryInterface(openerPwin
->GetDocShell());
3032 if (docShellAsItem
) {
3033 nsCOMPtr
<nsIDocShellTreeItem
> openerRootItem
;
3034 docShellAsItem
->GetRootTreeItem(getter_AddRefs(openerRootItem
));
3035 nsCOMPtr
<nsIDocShell
> openerRootDocShell(do_QueryInterface(openerRootItem
));
3036 if (openerRootDocShell
) {
3038 nsresult rv
= openerRootDocShell
->GetAppType(&appType
);
3039 if (NS_SUCCEEDED(rv
) && appType
!= nsIDocShell::APP_TYPE_MAIL
) {
3045 NS_IF_ADDREF(*aOpener
);
3050 nsGlobalWindow::SetOpener(nsIDOMWindowInternal
* aOpener
)
3052 // check if we were called from a privileged chrome script.
3053 // If not, opener is settable only to null.
3054 if (aOpener
&& !nsContentUtils::IsCallerTrustedForWrite()) {
3058 SetOpenerWindow(aOpener
, PR_FALSE
);
3064 nsGlobalWindow::GetStatus(nsAString
& aStatus
)
3066 FORWARD_TO_OUTER(GetStatus
, (aStatus
), NS_ERROR_NOT_INITIALIZED
);
3073 nsGlobalWindow::SetStatus(const nsAString
& aStatus
)
3075 FORWARD_TO_OUTER(SetStatus
, (aStatus
), NS_ERROR_NOT_INITIALIZED
);
3078 * If caller is not chrome and dom.disable_window_status_change is true,
3079 * prevent setting window.status by exiting early
3082 if (!CanSetProperty("dom.disable_window_status_change")) {
3088 nsCOMPtr
<nsIWebBrowserChrome
> browserChrome
;
3089 GetWebBrowserChrome(getter_AddRefs(browserChrome
));
3091 browserChrome
->SetStatus(nsIWebBrowserChrome::STATUS_SCRIPT
,
3092 PromiseFlatString(aStatus
).get());
3099 nsGlobalWindow::GetDefaultStatus(nsAString
& aDefaultStatus
)
3101 FORWARD_TO_OUTER(GetDefaultStatus
, (aDefaultStatus
),
3102 NS_ERROR_NOT_INITIALIZED
);
3104 aDefaultStatus
= mDefaultStatus
;
3109 nsGlobalWindow::SetDefaultStatus(const nsAString
& aDefaultStatus
)
3111 FORWARD_TO_OUTER(SetDefaultStatus
, (aDefaultStatus
),
3112 NS_ERROR_NOT_INITIALIZED
);
3115 * If caller is not chrome and dom.disable_window_status_change is true,
3116 * prevent setting window.defaultStatus by exiting early
3119 if (!CanSetProperty("dom.disable_window_status_change")) {
3123 mDefaultStatus
= aDefaultStatus
;
3125 nsCOMPtr
<nsIWebBrowserChrome
> browserChrome
;
3126 GetWebBrowserChrome(getter_AddRefs(browserChrome
));
3127 if (browserChrome
) {
3128 browserChrome
->SetStatus(nsIWebBrowserChrome::STATUS_SCRIPT_DEFAULT
,
3129 PromiseFlatString(aDefaultStatus
).get());
3136 nsGlobalWindow::GetName(nsAString
& aName
)
3138 FORWARD_TO_OUTER(GetName
, (aName
), NS_ERROR_NOT_INITIALIZED
);
3141 nsCOMPtr
<nsIDocShellTreeItem
> docShellAsItem(do_QueryInterface(mDocShell
));
3143 docShellAsItem
->GetName(getter_Copies(name
));
3150 nsGlobalWindow::SetName(const nsAString
& aName
)
3152 FORWARD_TO_OUTER(SetName
, (aName
), NS_ERROR_NOT_INITIALIZED
);
3154 nsresult result
= NS_OK
;
3155 nsCOMPtr
<nsIDocShellTreeItem
> docShellAsItem(do_QueryInterface(mDocShell
));
3157 result
= docShellAsItem
->SetName(PromiseFlatString(aName
).get());
3161 // Helper functions used by many methods below.
3163 nsGlobalWindow::DevToCSSIntPixels(PRInt32 px
)
3166 return px
; // assume 1:1
3168 nsRefPtr
<nsPresContext
> presContext
;
3169 mDocShell
->GetPresContext(getter_AddRefs(presContext
));
3173 return presContext
->DevPixelsToIntCSSPixels(px
);
3177 nsGlobalWindow::CSSToDevIntPixels(PRInt32 px
)
3180 return px
; // assume 1:1
3182 nsRefPtr
<nsPresContext
> presContext
;
3183 mDocShell
->GetPresContext(getter_AddRefs(presContext
));
3187 return presContext
->CSSPixelsToDevPixels(px
);
3191 nsGlobalWindow::DevToCSSIntPixels(nsIntSize px
)
3194 return px
; // assume 1:1
3196 nsRefPtr
<nsPresContext
> presContext
;
3197 mDocShell
->GetPresContext(getter_AddRefs(presContext
));
3202 presContext
->DevPixelsToIntCSSPixels(px
.width
),
3203 presContext
->DevPixelsToIntCSSPixels(px
.height
));
3207 nsGlobalWindow::CSSToDevIntPixels(nsIntSize px
)
3210 return px
; // assume 1:1
3212 nsRefPtr
<nsPresContext
> presContext
;
3213 mDocShell
->GetPresContext(getter_AddRefs(presContext
));
3218 presContext
->CSSPixelsToDevPixels(px
.width
),
3219 presContext
->CSSPixelsToDevPixels(px
.height
));
3224 nsGlobalWindow::GetInnerWidth(PRInt32
* aInnerWidth
)
3226 FORWARD_TO_OUTER(GetInnerWidth
, (aInnerWidth
), NS_ERROR_NOT_INITIALIZED
);
3228 NS_ENSURE_STATE(mDocShell
);
3230 EnsureSizeUpToDate();
3232 nsCOMPtr
<nsIBaseWindow
> docShellWin(do_QueryInterface(mDocShell
));
3233 nsRefPtr
<nsPresContext
> presContext
;
3234 mDocShell
->GetPresContext(getter_AddRefs(presContext
));
3236 if (docShellWin
&& presContext
) {
3237 PRInt32 width
, notused
;
3238 docShellWin
->GetSize(&width
, ¬used
);
3239 *aInnerWidth
= nsPresContext::
3240 AppUnitsToIntCSSPixels(presContext
->DevPixelsToAppUnits(width
));
3249 nsGlobalWindow::SetInnerWidth(PRInt32 aInnerWidth
)
3251 FORWARD_TO_OUTER(SetInnerWidth
, (aInnerWidth
), NS_ERROR_NOT_INITIALIZED
);
3253 NS_ENSURE_STATE(mDocShell
);
3256 * If caller is not chrome and the user has not explicitly exempted the site,
3257 * prevent setting window.innerWidth by exiting early
3260 if (!CanMoveResizeWindows() || IsFrame()) {
3264 nsCOMPtr
<nsIDocShellTreeItem
> docShellAsItem(do_QueryInterface(mDocShell
));
3265 NS_ENSURE_TRUE(docShellAsItem
, NS_ERROR_FAILURE
);
3267 nsCOMPtr
<nsIDocShellTreeOwner
> treeOwner
;
3268 docShellAsItem
->GetTreeOwner(getter_AddRefs(treeOwner
));
3269 NS_ENSURE_TRUE(treeOwner
, NS_ERROR_FAILURE
);
3271 NS_ENSURE_SUCCESS(CheckSecurityWidthAndHeight(&aInnerWidth
, nsnull
),
3274 PRInt32 width
= CSSToDevIntPixels(aInnerWidth
);
3276 nsCOMPtr
<nsIBaseWindow
> docShellAsWin(do_QueryInterface(mDocShell
));
3277 PRInt32 notused
, height
= 0;
3278 docShellAsWin
->GetSize(¬used
, &height
);
3280 NS_ENSURE_SUCCESS(treeOwner
->SizeShellTo(docShellAsItem
, width
, height
),
3287 nsGlobalWindow::GetInnerHeight(PRInt32
* aInnerHeight
)
3289 FORWARD_TO_OUTER(GetInnerHeight
, (aInnerHeight
), NS_ERROR_NOT_INITIALIZED
);
3291 NS_ENSURE_STATE(mDocShell
);
3293 EnsureSizeUpToDate();
3295 nsCOMPtr
<nsIBaseWindow
> docShellWin(do_QueryInterface(mDocShell
));
3296 nsRefPtr
<nsPresContext
> presContext
;
3297 mDocShell
->GetPresContext(getter_AddRefs(presContext
));
3299 if (docShellWin
&& presContext
) {
3300 PRInt32 height
, notused
;
3301 docShellWin
->GetSize(¬used
, &height
);
3302 *aInnerHeight
= nsPresContext::
3303 AppUnitsToIntCSSPixels(presContext
->DevPixelsToAppUnits(height
));
3311 nsGlobalWindow::SetInnerHeight(PRInt32 aInnerHeight
)
3313 FORWARD_TO_OUTER(SetInnerHeight
, (aInnerHeight
), NS_ERROR_NOT_INITIALIZED
);
3315 NS_ENSURE_STATE(mDocShell
);
3318 * If caller is not chrome and the user has not explicitly exempted the site,
3319 * prevent setting window.innerHeight by exiting early
3322 if (!CanMoveResizeWindows() || IsFrame()) {
3326 nsCOMPtr
<nsIDocShellTreeItem
> docShellAsItem(do_QueryInterface(mDocShell
));
3327 NS_ENSURE_TRUE(docShellAsItem
, NS_ERROR_FAILURE
);
3329 nsCOMPtr
<nsIDocShellTreeOwner
> treeOwner
;
3330 docShellAsItem
->GetTreeOwner(getter_AddRefs(treeOwner
));
3331 NS_ENSURE_TRUE(treeOwner
, NS_ERROR_FAILURE
);
3333 NS_ENSURE_SUCCESS(CheckSecurityWidthAndHeight(nsnull
, &aInnerHeight
),
3336 PRInt32 height
= CSSToDevIntPixels(aInnerHeight
);
3338 nsCOMPtr
<nsIBaseWindow
> docShellAsWin(do_QueryInterface(mDocShell
));
3339 PRInt32 width
= 0, notused
;
3340 docShellAsWin
->GetSize(&width
, ¬used
);
3342 NS_ENSURE_SUCCESS(treeOwner
->SizeShellTo(docShellAsItem
, width
, height
),
3349 nsGlobalWindow::GetOuterSize(nsIntSize
* aSizeCSSPixels
)
3351 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
3352 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
3353 NS_ENSURE_TRUE(treeOwnerAsWin
, NS_ERROR_FAILURE
);
3355 nsGlobalWindow
* rootWindow
=
3356 static_cast<nsGlobalWindow
*>(GetPrivateRoot());
3358 rootWindow
->FlushPendingNotifications(Flush_Layout
);
3361 nsIntSize sizeDevPixels
;
3362 NS_ENSURE_SUCCESS(treeOwnerAsWin
->GetSize(&sizeDevPixels
.width
,
3363 &sizeDevPixels
.height
),
3366 *aSizeCSSPixels
= DevToCSSIntPixels(sizeDevPixels
);
3371 nsGlobalWindow::GetOuterWidth(PRInt32
* aOuterWidth
)
3373 FORWARD_TO_OUTER(GetOuterWidth
, (aOuterWidth
), NS_ERROR_NOT_INITIALIZED
);
3375 nsIntSize sizeCSSPixels
;
3376 nsresult rv
= GetOuterSize(&sizeCSSPixels
);
3377 NS_ENSURE_SUCCESS(rv
, rv
);
3379 *aOuterWidth
= sizeCSSPixels
.width
;
3384 nsGlobalWindow::GetOuterHeight(PRInt32
* aOuterHeight
)
3386 FORWARD_TO_OUTER(GetOuterHeight
, (aOuterHeight
), NS_ERROR_NOT_INITIALIZED
);
3388 nsIntSize sizeCSSPixels
;
3389 nsresult rv
= GetOuterSize(&sizeCSSPixels
);
3390 NS_ENSURE_SUCCESS(rv
, rv
);
3392 *aOuterHeight
= sizeCSSPixels
.height
;
3397 nsGlobalWindow::SetOuterSize(PRInt32 aLengthCSSPixels
, PRBool aIsWidth
)
3400 * If caller is not chrome and the user has not explicitly exempted the site,
3401 * prevent setting window.outerWidth by exiting early
3404 if (!CanMoveResizeWindows() || IsFrame()) {
3408 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
3409 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
3410 NS_ENSURE_TRUE(treeOwnerAsWin
, NS_ERROR_FAILURE
);
3412 NS_ENSURE_SUCCESS(CheckSecurityWidthAndHeight(
3413 aIsWidth
? &aLengthCSSPixels
: nsnull
,
3414 aIsWidth
? nsnull
: &aLengthCSSPixels
),
3417 PRInt32 width
, height
;
3418 NS_ENSURE_SUCCESS(treeOwnerAsWin
->GetSize(&width
, &height
), NS_ERROR_FAILURE
);
3420 PRInt32 lengthDevPixels
= CSSToDevIntPixels(aLengthCSSPixels
);
3422 width
= lengthDevPixels
;
3424 height
= lengthDevPixels
;
3426 return treeOwnerAsWin
->SetSize(width
, height
, PR_TRUE
);
3430 nsGlobalWindow::SetOuterWidth(PRInt32 aOuterWidth
)
3432 FORWARD_TO_OUTER(SetOuterWidth
, (aOuterWidth
), NS_ERROR_NOT_INITIALIZED
);
3434 return SetOuterSize(aOuterWidth
, PR_TRUE
);
3438 nsGlobalWindow::SetOuterHeight(PRInt32 aOuterHeight
)
3440 FORWARD_TO_OUTER(SetOuterHeight
, (aOuterHeight
), NS_ERROR_NOT_INITIALIZED
);
3442 return SetOuterSize(aOuterHeight
, PR_FALSE
);
3446 nsGlobalWindow::GetScreenX(PRInt32
* aScreenX
)
3448 FORWARD_TO_OUTER(GetScreenX
, (aScreenX
), NS_ERROR_NOT_INITIALIZED
);
3450 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
3451 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
3452 NS_ENSURE_TRUE(treeOwnerAsWin
, NS_ERROR_FAILURE
);
3456 NS_ENSURE_SUCCESS(treeOwnerAsWin
->GetPosition(&x
, &y
),
3459 *aScreenX
= DevToCSSIntPixels(x
);
3464 nsGlobalWindow::GetInnerScreenRect()
3469 nsGlobalWindow
* rootWindow
=
3470 static_cast<nsGlobalWindow
*>(GetPrivateRoot());
3472 rootWindow
->FlushPendingNotifications(Flush_Layout
);
3475 nsCOMPtr
<nsIPresShell
> presShell
;
3476 mDocShell
->GetPresShell(getter_AddRefs(presShell
));
3479 nsIFrame
* rootFrame
= presShell
->GetRootFrame();
3483 return rootFrame
->GetScreenRectInAppUnits();
3487 nsGlobalWindow::GetMozInnerScreenX(float* aScreenX
)
3489 FORWARD_TO_OUTER(GetMozInnerScreenX
, (aScreenX
), NS_ERROR_NOT_INITIALIZED
);
3491 nsRect r
= GetInnerScreenRect();
3492 *aScreenX
= nsPresContext::AppUnitsToFloatCSSPixels(r
.x
);
3497 nsGlobalWindow::GetMozInnerScreenY(float* aScreenY
)
3499 FORWARD_TO_OUTER(GetMozInnerScreenY
, (aScreenY
), NS_ERROR_NOT_INITIALIZED
);
3501 nsRect r
= GetInnerScreenRect();
3502 *aScreenY
= nsPresContext::AppUnitsToFloatCSSPixels(r
.y
);
3507 nsGlobalWindow::GetMozPaintCount(PRUint64
* aResult
)
3509 FORWARD_TO_OUTER(GetMozPaintCount
, (aResult
), NS_ERROR_NOT_INITIALIZED
);
3516 nsCOMPtr
<nsIPresShell
> presShell
;
3517 mDocShell
->GetPresShell(getter_AddRefs(presShell
));
3521 *aResult
= presShell
->GetPaintCount();
3526 nsGlobalWindow::MozRequestAnimationFrame()
3528 FORWARD_TO_INNER(MozRequestAnimationFrame
, (), NS_ERROR_NOT_INITIALIZED
);
3534 mDoc
->ScheduleBeforePaintEvent();
3539 nsGlobalWindow::GetMozAnimationStartTime(PRInt64
*aTime
)
3541 FORWARD_TO_INNER(GetMozAnimationStartTime
, (aTime
), NS_ERROR_NOT_INITIALIZED
);
3544 nsIPresShell
* presShell
= mDoc
->GetShell();
3546 *aTime
= presShell
->GetPresContext()->RefreshDriver()->
3547 MostRecentRefreshEpochTime() / PR_USEC_PER_MSEC
;
3552 // If all else fails, just be compatible with Date.now()
3553 *aTime
= JS_Now() / PR_USEC_PER_MSEC
;
3558 nsGlobalWindow::SetScreenX(PRInt32 aScreenX
)
3560 FORWARD_TO_OUTER(SetScreenX
, (aScreenX
), NS_ERROR_NOT_INITIALIZED
);
3563 * If caller is not chrome and the user has not explicitly exempted the site,
3564 * prevent setting window.screenX by exiting early
3567 if (!CanMoveResizeWindows() || IsFrame()) {
3571 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
3572 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
3573 NS_ENSURE_TRUE(treeOwnerAsWin
, NS_ERROR_FAILURE
);
3575 NS_ENSURE_SUCCESS(CheckSecurityLeftAndTop(&aScreenX
, nsnull
),
3579 NS_ENSURE_SUCCESS(treeOwnerAsWin
->GetPosition(&x
, &y
),
3582 x
= CSSToDevIntPixels(aScreenX
);
3584 NS_ENSURE_SUCCESS(treeOwnerAsWin
->SetPosition(x
, y
),
3591 nsGlobalWindow::GetScreenY(PRInt32
* aScreenY
)
3593 FORWARD_TO_OUTER(GetScreenY
, (aScreenY
), NS_ERROR_NOT_INITIALIZED
);
3595 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
3596 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
3597 NS_ENSURE_TRUE(treeOwnerAsWin
, NS_ERROR_FAILURE
);
3601 NS_ENSURE_SUCCESS(treeOwnerAsWin
->GetPosition(&x
, &y
),
3604 *aScreenY
= DevToCSSIntPixels(y
);
3609 nsGlobalWindow::SetScreenY(PRInt32 aScreenY
)
3611 FORWARD_TO_OUTER(SetScreenY
, (aScreenY
), NS_ERROR_NOT_INITIALIZED
);
3614 * If caller is not chrome and the user has not explicitly exempted the site,
3615 * prevent setting window.screenY by exiting early
3618 if (!CanMoveResizeWindows() || IsFrame()) {
3622 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
3623 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
3624 NS_ENSURE_TRUE(treeOwnerAsWin
, NS_ERROR_FAILURE
);
3626 NS_ENSURE_SUCCESS(CheckSecurityLeftAndTop(nsnull
, &aScreenY
),
3630 NS_ENSURE_SUCCESS(treeOwnerAsWin
->GetPosition(&x
, &y
),
3633 y
= CSSToDevIntPixels(aScreenY
);
3635 NS_ENSURE_SUCCESS(treeOwnerAsWin
->SetPosition(x
, y
),
3641 // NOTE: Arguments to this function should have values scaled to
3642 // CSS pixels, not device pixels.
3644 nsGlobalWindow::CheckSecurityWidthAndHeight(PRInt32
* aWidth
, PRInt32
* aHeight
)
3647 if (!nsContentUtils::IsCallerTrustedForWrite()) {
3648 // if attempting to resize the window, hide any open popups
3649 nsCOMPtr
<nsIDocument
> doc(do_QueryInterface(mDocument
));
3650 nsContentUtils::HidePopupsInDocument(doc
);
3654 // This one is easy. Just ensure the variable is greater than 100;
3655 if ((aWidth
&& *aWidth
< 100) || (aHeight
&& *aHeight
< 100)) {
3656 // Check security state for use in determing window dimensions
3658 if (!nsContentUtils::IsCallerTrustedForWrite()) {
3660 if (aWidth
&& *aWidth
< 100) {
3663 if (aHeight
&& *aHeight
< 100) {
3672 // NOTE: Arguments to this function should have values scaled to
3673 // CSS pixels, not device pixels.
3675 nsGlobalWindow::CheckSecurityLeftAndTop(PRInt32
* aLeft
, PRInt32
* aTop
)
3677 // This one is harder. We have to get the screen size and window dimensions.
3679 // Check security state for use in determing window dimensions
3681 if (!nsContentUtils::IsCallerTrustedForWrite()) {
3683 // if attempting to move the window, hide any open popups
3684 nsCOMPtr
<nsIDocument
> doc(do_QueryInterface(mDocument
));
3685 nsContentUtils::HidePopupsInDocument(doc
);
3688 nsGlobalWindow
* rootWindow
=
3689 static_cast<nsGlobalWindow
*>(GetPrivateRoot());
3691 rootWindow
->FlushPendingNotifications(Flush_Layout
);
3694 nsCOMPtr
<nsIBaseWindow
> treeOwner
;
3695 GetTreeOwner(getter_AddRefs(treeOwner
));
3697 nsCOMPtr
<nsIDOMScreen
> screen
;
3698 GetScreen(getter_AddRefs(screen
));
3700 if (treeOwner
&& screen
) {
3701 PRInt32 screenLeft
, screenTop
, screenWidth
, screenHeight
;
3702 PRInt32 winLeft
, winTop
, winWidth
, winHeight
;
3704 // Get the window size
3705 treeOwner
->GetPositionAndSize(&winLeft
, &winTop
, &winWidth
, &winHeight
);
3707 // convert those values to CSS pixels
3708 // XXX four separate retrievals of the prescontext
3709 winLeft
= DevToCSSIntPixels(winLeft
);
3710 winTop
= DevToCSSIntPixels(winTop
);
3711 winWidth
= DevToCSSIntPixels(winWidth
);
3712 winHeight
= DevToCSSIntPixels(winHeight
);
3714 // Get the screen dimensions
3715 // XXX This should use nsIScreenManager once it's fully fleshed out.
3716 screen
->GetAvailLeft(&screenLeft
);
3717 screen
->GetAvailWidth(&screenWidth
);
3718 screen
->GetAvailHeight(&screenHeight
);
3719 #if defined(XP_MAC) || defined(XP_MACOSX)
3720 /* The mac's coordinate system is different from the assumed Windows'
3721 system. It offsets by the height of the menubar so that a window
3722 placed at (0,0) will be entirely visible. Unfortunately that
3723 correction is made elsewhere (in Widget) and the meaning of
3724 the Avail... coordinates is overloaded. Here we allow a window
3725 to be placed at (0,0) because it does make sense to do so.
3727 screen
->GetTop(&screenTop
);
3729 screen
->GetAvailTop(&screenTop
);
3733 if (screenLeft
+screenWidth
< *aLeft
+winWidth
)
3734 *aLeft
= screenLeft
+screenWidth
- winWidth
;
3735 if (screenLeft
> *aLeft
)
3736 *aLeft
= screenLeft
;
3739 if (screenTop
+screenHeight
< *aTop
+winHeight
)
3740 *aTop
= screenTop
+screenHeight
- winHeight
;
3741 if (screenTop
> *aTop
)
3756 nsGlobalWindow::GetPageXOffset(PRInt32
* aPageXOffset
)
3758 return GetScrollX(aPageXOffset
);
3762 nsGlobalWindow::GetPageYOffset(PRInt32
* aPageYOffset
)
3764 return GetScrollY(aPageYOffset
);
3768 nsGlobalWindow::GetScrollMaxXY(PRInt32
* aScrollMaxX
, PRInt32
* aScrollMaxY
)
3770 FORWARD_TO_OUTER(GetScrollMaxXY
, (aScrollMaxX
, aScrollMaxY
),
3771 NS_ERROR_NOT_INITIALIZED
);
3773 FlushPendingNotifications(Flush_Layout
);
3774 nsIScrollableFrame
*sf
= GetScrollFrame();
3778 nsRect scrollRange
= sf
->GetScrollRange();
3781 *aScrollMaxX
= NS_MAX(0,
3782 (PRInt32
)floor(nsPresContext::AppUnitsToFloatCSSPixels(scrollRange
.XMost())));
3784 *aScrollMaxY
= NS_MAX(0,
3785 (PRInt32
)floor(nsPresContext::AppUnitsToFloatCSSPixels(scrollRange
.YMost())));
3791 nsGlobalWindow::GetScrollMaxX(PRInt32
* aScrollMaxX
)
3793 NS_ENSURE_ARG_POINTER(aScrollMaxX
);
3795 return GetScrollMaxXY(aScrollMaxX
, nsnull
);
3799 nsGlobalWindow::GetScrollMaxY(PRInt32
* aScrollMaxY
)
3801 NS_ENSURE_ARG_POINTER(aScrollMaxY
);
3803 return GetScrollMaxXY(nsnull
, aScrollMaxY
);
3807 nsGlobalWindow::GetScrollXY(PRInt32
* aScrollX
, PRInt32
* aScrollY
,
3810 FORWARD_TO_OUTER(GetScrollXY
, (aScrollX
, aScrollY
, aDoFlush
),
3811 NS_ERROR_NOT_INITIALIZED
);
3814 FlushPendingNotifications(Flush_Layout
);
3816 EnsureSizeUpToDate();
3819 nsIScrollableFrame
*sf
= GetScrollFrame();
3823 nsPoint scrollPos
= sf
->GetScrollPosition();
3824 if (scrollPos
!= nsPoint(0,0) && !aDoFlush
) {
3825 // Oh, well. This is the expensive case -- the window is scrolled and we
3826 // didn't actually flush yet. Repeat, but with a flush, since the content
3827 // may get shorter and hence our scroll position may decrease.
3828 return GetScrollXY(aScrollX
, aScrollY
, PR_TRUE
);
3832 *aScrollX
= nsPresContext::AppUnitsToIntCSSPixels(scrollPos
.x
);
3834 *aScrollY
= nsPresContext::AppUnitsToIntCSSPixels(scrollPos
.y
);
3840 nsGlobalWindow::GetScrollX(PRInt32
* aScrollX
)
3842 NS_ENSURE_ARG_POINTER(aScrollX
);
3844 return GetScrollXY(aScrollX
, nsnull
, PR_FALSE
);
3848 nsGlobalWindow::GetScrollY(PRInt32
* aScrollY
)
3850 NS_ENSURE_ARG_POINTER(aScrollY
);
3852 return GetScrollXY(nsnull
, aScrollY
, PR_FALSE
);
3856 nsGlobalWindow::GetLength(PRUint32
* aLength
)
3858 nsCOMPtr
<nsIDOMWindowCollection
> frames
;
3859 if (NS_SUCCEEDED(GetFrames(getter_AddRefs(frames
))) && frames
) {
3860 return frames
->GetLength(aLength
);
3862 return NS_ERROR_FAILURE
;
3866 nsGlobalWindow::DispatchCustomEvent(const char *aEventName
)
3868 PRBool defaultActionEnabled
= PR_TRUE
;
3869 nsCOMPtr
<nsIDocument
> doc(do_QueryInterface(mDocument
));
3870 nsContentUtils::DispatchTrustedEvent(doc
,
3871 static_cast<nsIScriptGlobalObject
*>(this),
3872 NS_ConvertASCIItoUTF16(aEventName
),
3873 PR_TRUE
, PR_TRUE
, &defaultActionEnabled
);
3875 return defaultActionEnabled
;
3878 static already_AddRefed
<nsIDocShellTreeItem
>
3879 GetCallerDocShellTreeItem()
3881 JSContext
*cx
= nsContentUtils::GetCurrentJSContext();
3882 nsIDocShellTreeItem
*callerItem
= nsnull
;
3885 nsCOMPtr
<nsIWebNavigation
> callerWebNav
=
3886 do_GetInterface(nsJSUtils::GetDynamicScriptGlobal(cx
));
3889 CallQueryInterface(callerWebNav
, &callerItem
);
3897 nsGlobalWindow::WindowExists(const nsAString
& aName
,
3898 PRBool aLookForCallerOnJSStack
)
3900 NS_PRECONDITION(IsOuterWindow(), "Must be outer window");
3901 NS_PRECONDITION(mDocShell
, "Must have docshell");
3903 nsCOMPtr
<nsIDocShellTreeItem
> caller
;
3904 if (aLookForCallerOnJSStack
) {
3905 caller
= GetCallerDocShellTreeItem();
3908 nsCOMPtr
<nsIDocShellTreeItem
> docShell
= do_QueryInterface(mDocShell
);
3909 NS_ASSERTION(docShell
,
3910 "Docshell doesn't implement nsIDocShellTreeItem?");
3916 nsCOMPtr
<nsIDocShellTreeItem
> namedItem
;
3917 docShell
->FindItemWithName(PromiseFlatString(aName
).get(), nsnull
, caller
,
3918 getter_AddRefs(namedItem
));
3919 return namedItem
!= nsnull
;
3922 already_AddRefed
<nsIWidget
>
3923 nsGlobalWindow::GetMainWidget()
3925 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
3926 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
3928 nsIWidget
*widget
= nsnull
;
3930 if (treeOwnerAsWin
) {
3931 treeOwnerAsWin
->GetMainWidget(&widget
);
3938 nsGlobalWindow::GetNearestWidget()
3940 nsIDocShell
* docShell
= GetDocShell();
3941 NS_ENSURE_TRUE(docShell
, nsnull
);
3942 nsCOMPtr
<nsIPresShell
> presShell
;
3943 docShell
->GetPresShell(getter_AddRefs(presShell
));
3944 NS_ENSURE_TRUE(presShell
, nsnull
);
3945 nsIFrame
* rootFrame
= presShell
->GetRootFrame();
3946 NS_ENSURE_TRUE(rootFrame
, nsnull
);
3947 return rootFrame
->GetView()->GetNearestWidget(nsnull
);
3951 nsGlobalWindow::SetFullScreen(PRBool aFullScreen
)
3953 FORWARD_TO_OUTER(SetFullScreen
, (aFullScreen
), NS_ERROR_NOT_INITIALIZED
);
3955 NS_ENSURE_TRUE(mDocShell
, NS_ERROR_FAILURE
);
3957 PRBool rootWinFullScreen
;
3958 GetFullScreen(&rootWinFullScreen
);
3959 // Only chrome can change our fullScreen mode.
3960 if (aFullScreen
== rootWinFullScreen
||
3961 !nsContentUtils::IsCallerTrustedForWrite()) {
3965 // SetFullScreen needs to be called on the root window, so get that
3966 // via the DocShell tree, and if we are not already the root,
3967 // call SetFullScreen on that window instead.
3968 nsCOMPtr
<nsIDocShellTreeItem
> treeItem
= do_QueryInterface(mDocShell
);
3969 nsCOMPtr
<nsIDocShellTreeItem
> rootItem
;
3970 treeItem
->GetRootTreeItem(getter_AddRefs(rootItem
));
3971 nsCOMPtr
<nsIDOMWindowInternal
> window
= do_GetInterface(rootItem
);
3973 return NS_ERROR_FAILURE
;
3974 if (rootItem
!= treeItem
)
3975 return window
->SetFullScreen(aFullScreen
);
3977 // make sure we don't try to set full screen on a non-chrome window,
3978 // which might happen in embedding world
3980 treeItem
->GetItemType(&itemType
);
3981 if (itemType
!= nsIDocShellTreeItem::typeChrome
)
3982 return NS_ERROR_FAILURE
;
3984 // If we are already in full screen mode, just return.
3985 if (mFullScreen
== aFullScreen
)
3988 // dispatch a "fullscreen" DOM event so that XUL apps can
3989 // respond visually if we are kicked into full screen mode
3990 if (!DispatchCustomEvent("fullscreen")) {
3994 // Prevent chrome documents which are still loading from resizing
3995 // the window after we set fullscreen mode.
3996 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
3997 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
3998 nsCOMPtr
<nsIXULWindow
> xulWin(do_GetInterface(treeOwnerAsWin
));
3999 if (aFullScreen
&& xulWin
) {
4000 xulWin
->SetIntrinsicallySized(PR_FALSE
);
4003 // Set this before so if widget sends an event indicating its
4004 // gone full screen, the state trap above works.
4005 mFullScreen
= aFullScreen
;
4007 nsCOMPtr
<nsIWidget
> widget
= GetMainWidget();
4009 widget
->MakeFullScreen(aFullScreen
);
4015 nsGlobalWindow::GetFullScreen(PRBool
* aFullScreen
)
4017 FORWARD_TO_OUTER(GetFullScreen
, (aFullScreen
), NS_ERROR_NOT_INITIALIZED
);
4019 // Get the fullscreen value of the root window, to always have the value
4020 // accurate, even when called from content.
4021 nsCOMPtr
<nsIDocShellTreeItem
> treeItem
= do_QueryInterface(mDocShell
);
4023 nsCOMPtr
<nsIDocShellTreeItem
> rootItem
;
4024 treeItem
->GetRootTreeItem(getter_AddRefs(rootItem
));
4025 if (rootItem
!= treeItem
) {
4026 nsCOMPtr
<nsIDOMWindowInternal
> window
= do_GetInterface(rootItem
);
4028 return window
->GetFullScreen(aFullScreen
);
4032 // We are the root window, or something went wrong. Return our internal value.
4033 *aFullScreen
= mFullScreen
;
4038 nsGlobalWindow::DOMWindowDumpEnabled()
4040 #if !(defined(NS_DEBUG) || defined(MOZ_ENABLE_JS_DUMP))
4041 // In optimized builds we check a pref that controls if we should
4042 // enable output from dump() or not, in debug builds it's always
4044 return gDOMWindowDumpEnabled
;
4051 nsGlobalWindow::Dump(const nsAString
& aStr
)
4053 if (!DOMWindowDumpEnabled()) {
4057 char *cstr
= ToNewUTF8String(aStr
);
4059 #if defined(XP_MAC) || defined(XP_MACOSX)
4060 // have to convert \r to \n so that printing to the console works
4061 char *c
= cstr
, *cEnd
= cstr
+ strlen(cstr
);
4070 FILE *fp
= gDumpFile
? gDumpFile
: stdout
;
4073 nsMemory::Free(cstr
);
4080 nsGlobalWindow::EnsureReflowFlushAndPaint()
4082 NS_ASSERTION(mDocShell
, "EnsureReflowFlushAndPaint() called with no "
4088 nsCOMPtr
<nsIPresShell
> presShell
;
4089 mDocShell
->GetPresShell(getter_AddRefs(presShell
));
4094 // Flush pending reflows.
4096 mDoc
->FlushPendingNotifications(Flush_Layout
);
4099 // Unsuppress painting.
4100 presShell
->UnsuppressPainting();
4104 nsGlobalWindow::GetTextZoom(float *aZoom
)
4106 FORWARD_TO_OUTER(GetTextZoom
, (aZoom
), NS_ERROR_NOT_INITIALIZED
);
4109 nsCOMPtr
<nsIContentViewer
> contentViewer
;
4110 mDocShell
->GetContentViewer(getter_AddRefs(contentViewer
));
4111 nsCOMPtr
<nsIMarkupDocumentViewer
> markupViewer(do_QueryInterface(contentViewer
));
4114 return markupViewer
->GetTextZoom(aZoom
);
4117 return NS_ERROR_FAILURE
;
4121 nsGlobalWindow::SetTextZoom(float aZoom
)
4123 FORWARD_TO_OUTER(SetTextZoom
, (aZoom
), NS_ERROR_NOT_INITIALIZED
);
4126 nsCOMPtr
<nsIContentViewer
> contentViewer
;
4127 mDocShell
->GetContentViewer(getter_AddRefs(contentViewer
));
4128 nsCOMPtr
<nsIMarkupDocumentViewer
> markupViewer(do_QueryInterface(contentViewer
));
4131 return markupViewer
->SetTextZoom(aZoom
);
4133 return NS_ERROR_FAILURE
;
4138 nsGlobalWindow::MakeScriptDialogTitle(nsAString
&aOutTitle
)
4140 aOutTitle
.Truncate();
4142 // Try to get a host from the running principal -- this will do the
4143 // right thing for javascript: and data: documents.
4145 nsresult rv
= NS_OK
;
4146 NS_ASSERTION(nsContentUtils::GetSecurityManager(),
4147 "Global Window has no security manager!");
4148 if (nsContentUtils::GetSecurityManager()) {
4149 nsCOMPtr
<nsIPrincipal
> principal
;
4150 rv
= nsContentUtils::GetSecurityManager()->
4151 GetSubjectPrincipal(getter_AddRefs(principal
));
4153 if (NS_SUCCEEDED(rv
) && principal
) {
4154 nsCOMPtr
<nsIURI
> uri
;
4155 rv
= principal
->GetURI(getter_AddRefs(uri
));
4157 if (NS_SUCCEEDED(rv
) && uri
) {
4158 // remove user:pass for privacy and spoof prevention
4160 nsCOMPtr
<nsIURIFixup
> fixup(do_GetService(NS_URIFIXUP_CONTRACTID
));
4162 nsCOMPtr
<nsIURI
> fixedURI
;
4163 rv
= fixup
->CreateExposableURI(uri
, getter_AddRefs(fixedURI
));
4164 if (NS_SUCCEEDED(rv
) && fixedURI
) {
4166 fixedURI
->GetHost(host
);
4168 if (!host
.IsEmpty()) {
4169 // if this URI has a host we'll show it. For other
4170 // schemes (e.g. file:) we fall back to the localized
4173 nsCAutoString prepath
;
4174 fixedURI
->GetPrePath(prepath
);
4176 NS_ConvertUTF8toUTF16
ucsPrePath(prepath
);
4177 const PRUnichar
*formatStrings
[] = { ucsPrePath
.get() };
4178 nsXPIDLString tempString
;
4179 nsContentUtils::FormatLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES
,
4181 formatStrings
, NS_ARRAY_LENGTH(formatStrings
),
4183 aOutTitle
= tempString
;
4189 else { // failed to get subject principal
4190 NS_WARNING("No script principal? Who is calling alert/confirm/prompt?!");
4194 if (aOutTitle
.IsEmpty()) {
4195 // We didn't find a host so use the generic heading
4196 nsXPIDLString tempString
;
4197 nsContentUtils::GetLocalizedString(nsContentUtils::eCOMMON_DIALOG_PROPERTIES
,
4198 "ScriptDlgGenericHeading",
4200 aOutTitle
= tempString
;
4204 if (aOutTitle
.IsEmpty()) {
4205 NS_WARNING("could not get ScriptDlgGenericHeading string from string bundle");
4206 aOutTitle
.AssignLiteral("[Script]");
4212 nsGlobalWindow::CanMoveResizeWindows()
4214 if (!CanSetProperty("dom.disable_window_move_resize"))
4217 if (gMouseDown
&& !gDragServiceDisabled
) {
4218 nsCOMPtr
<nsIDragService
> ds
=
4219 do_GetService("@mozilla.org/widget/dragservice;1");
4221 gDragServiceDisabled
= PR_TRUE
;
4229 nsGlobalWindow::Alert(const nsAString
& aString
)
4231 FORWARD_TO_OUTER(Alert
, (aString
), NS_ERROR_NOT_INITIALIZED
);
4233 // Reset popup state while opening a modal dialog, and firing events
4234 // about the dialog, to prevent the current state from being active
4235 // the whole time a modal dialog is open.
4236 nsAutoPopupStatePusher
popupStatePusher(openAbused
, PR_TRUE
);
4238 // Special handling for alert(null) in JS for backwards
4241 NS_NAMED_LITERAL_STRING(null_str
, "null");
4243 const nsAString
*str
= DOMStringIsNull(aString
) ? &null_str
: &aString
;
4245 // Before bringing up the window, unsuppress painting and flush
4247 EnsureReflowFlushAndPaint();
4250 MakeScriptDialogTitle(title
);
4252 // Remove non-terminating null characters from the
4253 // string. See bug #310037.
4255 nsContentUtils::StripNullChars(*str
, final
);
4258 nsCOMPtr
<nsIPromptService
> promptSvc
= do_GetService("@mozilla.org/embedcomp/prompt-service;1", &rv
);
4259 NS_ENSURE_SUCCESS(rv
, rv
);
4261 return promptSvc
->Alert(this, title
.get(), final
.get());
4265 nsGlobalWindow::Confirm(const nsAString
& aString
, PRBool
* aReturn
)
4267 FORWARD_TO_OUTER(Confirm
, (aString
, aReturn
), NS_ERROR_NOT_INITIALIZED
);
4269 // Reset popup state while opening a modal dialog, and firing events
4270 // about the dialog, to prevent the current state from being active
4271 // the whole time a modal dialog is open.
4272 nsAutoPopupStatePusher
popupStatePusher(openAbused
, PR_TRUE
);
4274 *aReturn
= PR_FALSE
;
4276 // Before bringing up the window, unsuppress painting and flush
4278 EnsureReflowFlushAndPaint();
4281 MakeScriptDialogTitle(title
);
4283 // Remove non-terminating null characters from the
4284 // string. See bug #310037.
4286 nsContentUtils::StripNullChars(aString
, final
);
4289 nsCOMPtr
<nsIPromptService
> promptSvc
= do_GetService("@mozilla.org/embedcomp/prompt-service;1", &rv
);
4290 NS_ENSURE_SUCCESS(rv
, rv
);
4292 return promptSvc
->Confirm(this, title
.get(), final
.get(), aReturn
);
4296 nsGlobalWindow::Prompt(const nsAString
& aMessage
, const nsAString
& aInitial
,
4299 SetDOMStringToNull(aReturn
);
4301 // Reset popup state while opening a modal dialog, and firing events
4302 // about the dialog, to prevent the current state from being active
4303 // the whole time a modal dialog is open.
4304 nsAutoPopupStatePusher
popupStatePusher(openAbused
, PR_TRUE
);
4306 // Before bringing up the window, unsuppress painting and flush
4308 EnsureReflowFlushAndPaint();
4311 MakeScriptDialogTitle(title
);
4313 // Remove non-terminating null characters from the
4314 // string. See bug #310037.
4315 nsAutoString fixedMessage
, fixedInitial
;
4316 nsContentUtils::StripNullChars(aMessage
, fixedMessage
);
4317 nsContentUtils::StripNullChars(aInitial
, fixedInitial
);
4320 nsCOMPtr
<nsIPromptService
> promptSvc
= do_GetService("@mozilla.org/embedcomp/prompt-service;1", &rv
);
4321 NS_ENSURE_SUCCESS(rv
, rv
);
4323 // Pass in the default value, if any.
4324 PRUnichar
*inoutValue
= ToNewUnicode(fixedInitial
);
4327 rv
= promptSvc
->Prompt(this, title
.get(), fixedMessage
.get(),
4328 &inoutValue
, nsnull
, &dummy
, &ok
);
4329 NS_ENSURE_SUCCESS(rv
, rv
);
4331 nsAdoptingString
outValue(inoutValue
);
4333 if (ok
&& outValue
) {
4334 aReturn
.Assign(outValue
);
4341 nsGlobalWindow::Focus()
4343 FORWARD_TO_OUTER(Focus
, (), NS_ERROR_NOT_INITIALIZED
);
4345 nsIFocusManager
* fm
= nsFocusManager::GetFocusManager();
4349 nsCOMPtr
<nsIBaseWindow
> baseWin
= do_QueryInterface(mDocShell
);
4351 PRBool isVisible
= PR_FALSE
;
4353 baseWin
->GetVisibility(&isVisible
);
4357 // A hidden tab is being focused, ignore this call.
4362 * If caller is not chrome and dom.disable_window_flip is true,
4363 * prevent bringing a window to the front if the window is not the
4364 * currently active window, but do change the currently focused
4365 * window in the focus controller so that focus is in the right
4366 * place when the window is activated again.
4370 CanSetProperty("dom.disable_window_flip") ||
4371 RevisePopupAbuseLevel(gPopupControlState
) < openAbused
;
4373 nsCOMPtr
<nsIDOMWindow
> activeWindow
;
4374 fm
->GetActiveWindow(getter_AddRefs(activeWindow
));
4376 nsCOMPtr
<nsIDocShellTreeItem
> treeItem
= do_QueryInterface(mDocShell
);
4377 NS_ASSERTION(treeItem
, "What happened?");
4378 nsCOMPtr
<nsIDocShellTreeItem
> rootItem
;
4379 treeItem
->GetRootTreeItem(getter_AddRefs(rootItem
));
4380 nsCOMPtr
<nsIDOMWindow
> rootWin
= do_GetInterface(rootItem
);
4381 PRBool isActive
= (rootWin
== activeWindow
);
4383 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
4384 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
4385 if (treeOwnerAsWin
&& (canFocus
|| isActive
)) {
4386 PRBool isEnabled
= PR_TRUE
;
4387 if (NS_SUCCEEDED(treeOwnerAsWin
->GetEnabled(&isEnabled
)) && !isEnabled
) {
4388 NS_WARNING( "Should not try to set the focus on a disabled window" );
4392 // XXXndeakin not sure what this is for or if it should go somewhere else
4393 nsCOMPtr
<nsIEmbeddingSiteWindow
> embeddingWin(do_GetInterface(treeOwnerAsWin
));
4395 embeddingWin
->SetFocus();
4401 nsCOMPtr
<nsIPresShell
> presShell
;
4402 // Don't look for a presshell if we're a root chrome window that's got
4403 // about:blank loaded. We don't want to focus our widget in that case.
4404 // XXXbz should we really be checking for IsInitialDocument() instead?
4405 PRBool lookForPresShell
= PR_TRUE
;
4406 PRInt32 itemType
= nsIDocShellTreeItem::typeContent
;
4407 treeItem
->GetItemType(&itemType
);
4408 if (itemType
== nsIDocShellTreeItem::typeChrome
&&
4409 GetPrivateRoot() == static_cast<nsIDOMWindowInternal
*>(this) &&
4411 nsCOMPtr
<nsIDocument
> doc(do_QueryInterface(mDocument
));
4412 NS_ASSERTION(doc
, "Bogus doc?");
4413 nsIURI
* ourURI
= doc
->GetDocumentURI();
4415 lookForPresShell
= !IsAboutBlank(ourURI
);
4419 if (lookForPresShell
) {
4420 mDocShell
->GetEldestPresShell(getter_AddRefs(presShell
));
4423 nsCOMPtr
<nsIDocShellTreeItem
> parentDsti
;
4424 treeItem
->GetParent(getter_AddRefs(parentDsti
));
4426 // set the parent's current focus to the frame containing this window.
4427 nsCOMPtr
<nsIDOMWindow
> parent(do_GetInterface(parentDsti
));
4429 nsCOMPtr
<nsIDOMDocument
> parentdomdoc
;
4430 parent
->GetDocument(getter_AddRefs(parentdomdoc
));
4432 nsCOMPtr
<nsIDocument
> parentdoc
= do_QueryInterface(parentdomdoc
);
4436 nsCOMPtr
<nsIDocument
> doc
= do_QueryInterface(mDocument
);
4437 nsIContent
* frame
= parentdoc
->FindContentForSubDocument(doc
);
4438 nsCOMPtr
<nsIDOMElement
> frameElement
= do_QueryInterface(frame
);
4440 PRUint32 flags
= nsIFocusManager::FLAG_NOSCROLL
;
4442 flags
|= nsIFocusManager::FLAG_RAISE
;
4443 return fm
->SetFocus(frameElement
, flags
);
4446 else if (canFocus
) {
4447 // if there is no parent, this must be a toplevel window, so raise the
4448 // window if canFocus is true
4449 return fm
->SetActiveWindow(this);
4456 nsGlobalWindow::Blur()
4458 FORWARD_TO_OUTER(Blur
, (), NS_ERROR_NOT_INITIALIZED
);
4460 // If embedding apps don't implement nsIEmbeddingSiteWindow2, we
4461 // shouldn't throw exceptions to web content.
4462 nsresult rv
= NS_OK
;
4464 nsCOMPtr
<nsIDocShellTreeOwner
> treeOwner
;
4465 GetTreeOwner(getter_AddRefs(treeOwner
));
4466 nsCOMPtr
<nsIEmbeddingSiteWindow2
> siteWindow(do_GetInterface(treeOwner
));
4468 // This method call may cause mDocShell to become nsnull.
4469 rv
= siteWindow
->Blur();
4471 // if the root is focused, clear the focus
4472 nsIFocusManager
* fm
= nsFocusManager::GetFocusManager();
4473 nsCOMPtr
<nsIDocument
> doc
= do_QueryInterface(mDocument
);
4474 if (fm
&& mDocument
) {
4475 nsCOMPtr
<nsIDOMElement
> element
;
4476 fm
->GetFocusedElementForWindow(this, PR_FALSE
, nsnull
, getter_AddRefs(element
));
4477 nsCOMPtr
<nsIContent
> content
= do_QueryInterface(element
);
4478 if (content
== doc
->GetRootElement())
4479 fm
->ClearFocus(this);
4487 nsGlobalWindow::Back()
4489 FORWARD_TO_OUTER(Back
, (), NS_ERROR_NOT_INITIALIZED
);
4491 nsCOMPtr
<nsIWebNavigation
> webNav(do_QueryInterface(mDocShell
));
4492 NS_ENSURE_TRUE(webNav
, NS_ERROR_FAILURE
);
4494 return webNav
->GoBack();
4498 nsGlobalWindow::Forward()
4500 FORWARD_TO_OUTER(Forward
, (), NS_ERROR_NOT_INITIALIZED
);
4502 nsCOMPtr
<nsIWebNavigation
> webNav(do_QueryInterface(mDocShell
));
4503 NS_ENSURE_TRUE(webNav
, NS_ERROR_FAILURE
);
4505 return webNav
->GoForward();
4509 nsGlobalWindow::Home()
4511 FORWARD_TO_OUTER(Home
, (), NS_ERROR_NOT_INITIALIZED
);
4516 nsAdoptingString homeURL
=
4517 nsContentUtils::GetLocalizedStringPref(PREF_BROWSER_STARTUP_HOMEPAGE
);
4519 if (homeURL
.IsEmpty()) {
4520 // if all else fails, use this
4522 printf("all else failed. using %s as the home page\n", DEFAULT_HOME_PAGE
);
4524 CopyASCIItoUTF16(DEFAULT_HOME_PAGE
, homeURL
);
4529 // Firefox lets the user specify multiple home pages to open in
4530 // individual tabs by separating them with '|'. Since we don't
4531 // have the machinery in place to easily open new tabs from here,
4532 // simply truncate the homeURL at the first '|' character to
4533 // prevent any possibilities of leaking the users list of home
4534 // pages to the first home page.
4536 // Once bug https://bugzilla.mozilla.org/show_bug.cgi?id=221445 is
4537 // fixed we can revisit this.
4538 PRInt32 firstPipe
= homeURL
.FindChar('|');
4540 if (firstPipe
> 0) {
4541 homeURL
.Truncate(firstPipe
);
4547 nsCOMPtr
<nsIWebNavigation
> webNav(do_QueryInterface(mDocShell
));
4548 NS_ENSURE_TRUE(webNav
, NS_ERROR_FAILURE
);
4549 rv
= webNav
->LoadURI(homeURL
.get(),
4550 nsIWebNavigation::LOAD_FLAGS_NONE
,
4554 NS_ENSURE_SUCCESS(rv
, NS_ERROR_FAILURE
);
4559 nsGlobalWindow::Stop()
4561 FORWARD_TO_OUTER(Stop
, (), NS_ERROR_NOT_INITIALIZED
);
4563 nsCOMPtr
<nsIWebNavigation
> webNav(do_QueryInterface(mDocShell
));
4567 return webNav
->Stop(nsIWebNavigation::STOP_ALL
);
4571 nsGlobalWindow::Print()
4574 FORWARD_TO_OUTER(Print
, (), NS_ERROR_NOT_INITIALIZED
);
4576 nsCOMPtr
<nsIWebBrowserPrint
> webBrowserPrint
;
4577 if (NS_SUCCEEDED(GetInterface(NS_GET_IID(nsIWebBrowserPrint
),
4578 getter_AddRefs(webBrowserPrint
)))) {
4580 nsCOMPtr
<nsIPrintSettingsService
> printSettingsService
=
4581 do_GetService("@mozilla.org/gfx/printsettings-service;1");
4583 nsCOMPtr
<nsIPrintSettings
> printSettings
;
4584 if (printSettingsService
) {
4585 PRBool printSettingsAreGlobal
=
4586 nsContentUtils::GetBoolPref("print.use_global_printsettings", PR_FALSE
);
4588 if (printSettingsAreGlobal
) {
4589 printSettingsService
->GetGlobalPrintSettings(getter_AddRefs(printSettings
));
4591 nsXPIDLString printerName
;
4592 printSettings
->GetPrinterName(getter_Copies(printerName
));
4593 if (printerName
.IsEmpty()) {
4594 printSettingsService
->GetDefaultPrinterName(getter_Copies(printerName
));
4595 printSettings
->SetPrinterName(printerName
);
4597 printSettingsService
->InitPrintSettingsFromPrinter(printerName
, printSettings
);
4598 printSettingsService
->InitPrintSettingsFromPrefs(printSettings
,
4600 nsIPrintSettings::kInitSaveAll
);
4602 printSettingsService
->GetNewPrintSettings(getter_AddRefs(printSettings
));
4606 webBrowserPrint
->Print(printSettings
, nsnull
);
4609 PRBool savePrintSettings
=
4610 nsContentUtils::GetBoolPref("print.save_print_settings", PR_FALSE
);
4611 if (printSettingsAreGlobal
&& savePrintSettings
) {
4612 printSettingsService
->
4613 SavePrintSettingsToPrefs(printSettings
,
4615 nsIPrintSettings::kInitSaveAll
);
4616 printSettingsService
->
4617 SavePrintSettingsToPrefs(printSettings
,
4619 nsIPrintSettings::kInitSavePrinterName
);
4622 webBrowserPrint
->GetGlobalPrintSettings(getter_AddRefs(printSettings
));
4623 webBrowserPrint
->Print(printSettings
, nsnull
);
4626 #endif //NS_PRINTING
4632 nsGlobalWindow::MoveTo(PRInt32 aXPos
, PRInt32 aYPos
)
4634 FORWARD_TO_OUTER(MoveTo
, (aXPos
, aYPos
), NS_ERROR_NOT_INITIALIZED
);
4637 * If caller is not chrome and the user has not explicitly exempted the site,
4638 * prevent window.moveTo() by exiting early
4641 if (!CanMoveResizeWindows() || IsFrame()) {
4645 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
4646 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
4647 NS_ENSURE_TRUE(treeOwnerAsWin
, NS_ERROR_FAILURE
);
4649 NS_ENSURE_SUCCESS(CheckSecurityLeftAndTop(&aXPos
, &aYPos
),
4652 // mild abuse of a "size" object so we don't need more helper functions
4653 nsIntSize
devPos(CSSToDevIntPixels(nsIntSize(aXPos
, aYPos
)));
4655 NS_ENSURE_SUCCESS(treeOwnerAsWin
->SetPosition(devPos
.width
, devPos
.height
),
4662 nsGlobalWindow::MoveBy(PRInt32 aXDif
, PRInt32 aYDif
)
4664 FORWARD_TO_OUTER(MoveBy
, (aXDif
, aYDif
), NS_ERROR_NOT_INITIALIZED
);
4667 * If caller is not chrome and the user has not explicitly exempted the site,
4668 * prevent window.moveBy() by exiting early
4671 if (!CanMoveResizeWindows() || IsFrame()) {
4675 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
4676 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
4677 NS_ENSURE_TRUE(treeOwnerAsWin
, NS_ERROR_FAILURE
);
4679 // To do this correctly we have to convert what we get from GetPosition
4680 // into CSS pixels, add the arguments, do the security check, and
4681 // then convert back to device pixels for the call to SetPosition.
4684 NS_ENSURE_SUCCESS(treeOwnerAsWin
->GetPosition(&x
, &y
), NS_ERROR_FAILURE
);
4686 // mild abuse of a "size" object so we don't need more helper functions
4687 nsIntSize
cssPos(DevToCSSIntPixels(nsIntSize(x
, y
)));
4689 cssPos
.width
+= aXDif
;
4690 cssPos
.height
+= aYDif
;
4692 NS_ENSURE_SUCCESS(CheckSecurityLeftAndTop(&cssPos
.width
,
4696 nsIntSize
newDevPos(CSSToDevIntPixels(cssPos
));
4698 NS_ENSURE_SUCCESS(treeOwnerAsWin
->SetPosition(newDevPos
.width
,
4706 nsGlobalWindow::ResizeTo(PRInt32 aWidth
, PRInt32 aHeight
)
4708 FORWARD_TO_OUTER(ResizeTo
, (aWidth
, aHeight
), NS_ERROR_NOT_INITIALIZED
);
4711 * If caller is not chrome and the user has not explicitly exempted the site,
4712 * prevent window.resizeTo() by exiting early
4715 if (!CanMoveResizeWindows() || IsFrame()) {
4719 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
4720 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
4721 NS_ENSURE_TRUE(treeOwnerAsWin
, NS_ERROR_FAILURE
);
4723 NS_ENSURE_SUCCESS(CheckSecurityWidthAndHeight(&aWidth
, &aHeight
),
4726 nsIntSize
devSz(CSSToDevIntPixels(nsIntSize(aWidth
, aHeight
)));
4728 NS_ENSURE_SUCCESS(treeOwnerAsWin
->SetSize(devSz
.width
, devSz
.height
, PR_TRUE
),
4735 nsGlobalWindow::ResizeBy(PRInt32 aWidthDif
, PRInt32 aHeightDif
)
4737 FORWARD_TO_OUTER(ResizeBy
, (aWidthDif
, aHeightDif
), NS_ERROR_NOT_INITIALIZED
);
4740 * If caller is not chrome and the user has not explicitly exempted the site,
4741 * prevent window.resizeBy() by exiting early
4744 if (!CanMoveResizeWindows() || IsFrame()) {
4748 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
4749 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
4750 NS_ENSURE_TRUE(treeOwnerAsWin
, NS_ERROR_FAILURE
);
4752 PRInt32 width
, height
;
4753 NS_ENSURE_SUCCESS(treeOwnerAsWin
->GetSize(&width
, &height
), NS_ERROR_FAILURE
);
4755 // To do this correctly we have to convert what we got from GetSize
4756 // into CSS pixels, add the arguments, do the security check, and
4757 // then convert back to device pixels for the call to SetSize.
4759 nsIntSize
cssSize(DevToCSSIntPixels(nsIntSize(width
, height
)));
4761 cssSize
.width
+= aWidthDif
;
4762 cssSize
.height
+= aHeightDif
;
4764 NS_ENSURE_SUCCESS(CheckSecurityWidthAndHeight(&cssSize
.width
,
4768 nsIntSize
newDevSize(CSSToDevIntPixels(cssSize
));
4770 NS_ENSURE_SUCCESS(treeOwnerAsWin
->SetSize(newDevSize
.width
,
4779 nsGlobalWindow::SizeToContent()
4781 FORWARD_TO_OUTER(SizeToContent
, (), NS_ERROR_NOT_INITIALIZED
);
4788 * If caller is not chrome and the user has not explicitly exempted the site,
4789 * prevent window.sizeToContent() by exiting early
4792 if (!CanMoveResizeWindows() || IsFrame()) {
4796 // The content viewer does a check to make sure that it's a content
4797 // viewer for a toplevel docshell.
4799 nsCOMPtr
<nsIContentViewer
> cv
;
4800 mDocShell
->GetContentViewer(getter_AddRefs(cv
));
4801 nsCOMPtr
<nsIMarkupDocumentViewer
> markupViewer(do_QueryInterface(cv
));
4802 NS_ENSURE_TRUE(markupViewer
, NS_ERROR_FAILURE
);
4803 NS_ENSURE_SUCCESS(markupViewer
->SizeToContent(), NS_ERROR_FAILURE
);
4809 nsGlobalWindow::GetWindowRoot(nsIDOMEventTarget
**aWindowRoot
)
4811 nsCOMPtr
<nsPIWindowRoot
> root
= GetTopWindowRoot();
4812 return CallQueryInterface(root
, aWindowRoot
);
4815 already_AddRefed
<nsPIWindowRoot
>
4816 nsGlobalWindow::GetTopWindowRoot()
4818 nsIDOMWindowInternal
*rootWindow
= GetPrivateRoot();
4819 nsCOMPtr
<nsPIDOMWindow
> piWin(do_QueryInterface(rootWindow
));
4823 nsCOMPtr
<nsPIWindowRoot
> window
= do_QueryInterface(piWin
->GetChromeEventHandler());
4824 return window
.forget();
4828 nsGlobalWindow::Scroll(PRInt32 aXScroll
, PRInt32 aYScroll
)
4830 return ScrollTo(aXScroll
, aYScroll
);
4834 nsGlobalWindow::ScrollTo(PRInt32 aXScroll
, PRInt32 aYScroll
)
4836 FlushPendingNotifications(Flush_Layout
);
4837 nsIScrollableFrame
*sf
= GetScrollFrame();
4840 // Here we calculate what the max pixel value is that we can
4841 // scroll to, we do this by dividing maxint with the pixel to
4842 // twips conversion factor, and substracting 4, the 4 comes from
4843 // experimenting with this value, anything less makes the view
4844 // code not scroll correctly, I have no idea why. -- jst
4845 const PRInt32 maxpx
= nsPresContext::AppUnitsToIntCSSPixels(0x7fffffff) - 4;
4847 if (aXScroll
> maxpx
) {
4851 if (aYScroll
> maxpx
) {
4854 sf
->ScrollTo(nsPoint(nsPresContext::CSSPixelsToAppUnits(aXScroll
),
4855 nsPresContext::CSSPixelsToAppUnits(aYScroll
)),
4856 nsIScrollableFrame::INSTANT
);
4863 nsGlobalWindow::ScrollBy(PRInt32 aXScrollDif
, PRInt32 aYScrollDif
)
4865 FlushPendingNotifications(Flush_Layout
);
4866 nsIScrollableFrame
*sf
= GetScrollFrame();
4869 nsPoint scrollPos
= sf
->GetScrollPosition();
4870 // It seems like it would make more sense for ScrollBy to use
4871 // SMOOTH mode, but tests seem to depend on the synchronous behaviour.
4872 // Perhaps Web content does too.
4873 return ScrollTo(nsPresContext::AppUnitsToIntCSSPixels(scrollPos
.x
) + aXScrollDif
,
4874 nsPresContext::AppUnitsToIntCSSPixels(scrollPos
.y
) + aYScrollDif
);
4881 nsGlobalWindow::ScrollByLines(PRInt32 numLines
)
4883 FlushPendingNotifications(Flush_Layout
);
4884 nsIScrollableFrame
*sf
= GetScrollFrame();
4886 // It seems like it would make more sense for ScrollByLines to use
4887 // SMOOTH mode, but tests seem to depend on the synchronous behaviour.
4888 // Perhaps Web content does too.
4889 sf
->ScrollBy(nsIntPoint(0, numLines
), nsIScrollableFrame::LINES
,
4890 nsIScrollableFrame::INSTANT
);
4897 nsGlobalWindow::ScrollByPages(PRInt32 numPages
)
4899 FlushPendingNotifications(Flush_Layout
);
4900 nsIScrollableFrame
*sf
= GetScrollFrame();
4902 // It seems like it would make more sense for ScrollByPages to use
4903 // SMOOTH mode, but tests seem to depend on the synchronous behaviour.
4904 // Perhaps Web content does too.
4905 sf
->ScrollBy(nsIntPoint(0, numPages
), nsIScrollableFrame::PAGES
,
4906 nsIScrollableFrame::INSTANT
);
4913 nsGlobalWindow::ClearTimeout()
4915 return ClearTimeoutOrInterval();
4919 nsGlobalWindow::ClearInterval()
4921 return ClearTimeoutOrInterval();
4925 nsGlobalWindow::SetTimeout(PRInt32
*_retval
)
4927 return SetTimeoutOrInterval(PR_FALSE
, _retval
);
4931 nsGlobalWindow::SetInterval(PRInt32
*_retval
)
4933 return SetTimeoutOrInterval(PR_TRUE
, _retval
);
4937 nsGlobalWindow::SetResizable(PRBool aResizable
)
4945 ReportUseOfDeprecatedMethod(nsGlobalWindow
* aWindow
, const char* aWarning
)
4947 nsCOMPtr
<nsIDocument
> doc
= do_QueryInterface(aWindow
->GetExtantDocument());
4948 nsContentUtils::ReportToConsole(nsContentUtils::eDOM_PROPERTIES
,
4951 doc
? doc
->GetDocumentURI() : nsnull
,
4952 EmptyString(), 0, 0,
4953 nsIScriptError::warningFlag
,
4958 nsGlobalWindow::CaptureEvents(PRInt32 aEventFlags
)
4960 ReportUseOfDeprecatedMethod(this, "UseOfCaptureEventsWarning");
4965 nsGlobalWindow::ReleaseEvents(PRInt32 aEventFlags
)
4967 ReportUseOfDeprecatedMethod(this, "UseOfReleaseEventsWarning");
4972 nsGlobalWindow::RouteEvent(nsIDOMEvent
* aEvt
)
4974 ReportUseOfDeprecatedMethod(this, "UseOfRouteEventWarning");
4979 nsGlobalWindow::EnableExternalCapture()
4981 return NS_ERROR_FAILURE
;
4985 nsGlobalWindow::DisableExternalCapture()
4987 return NS_ERROR_FAILURE
;
4991 PRBool
IsPopupBlocked(nsIDOMDocument
* aDoc
)
4993 nsCOMPtr
<nsIPopupWindowManager
> pm
=
4994 do_GetService(NS_POPUPWINDOWMANAGER_CONTRACTID
);
5000 PRBool blocked
= PR_TRUE
;
5001 nsCOMPtr
<nsIDocument
> doc(do_QueryInterface(aDoc
));
5004 PRUint32 permission
= nsIPopupWindowManager::ALLOW_POPUP
;
5005 pm
->TestPermission(doc
->GetDocumentURI(), &permission
);
5006 blocked
= (permission
== nsIPopupWindowManager::DENY_POPUP
);
5013 nsGlobalWindow::FirePopupBlockedEvent(nsIDOMDocument
* aDoc
,
5014 nsIDOMWindow
*aRequestingWindow
, nsIURI
*aPopupURI
,
5015 const nsAString
&aPopupWindowName
,
5016 const nsAString
&aPopupWindowFeatures
)
5019 // Fire a "DOMPopupBlocked" event so that the UI can hear about
5021 nsCOMPtr
<nsIDOMDocumentEvent
> docEvent(do_QueryInterface(aDoc
));
5022 nsCOMPtr
<nsIDOMEvent
> event
;
5023 docEvent
->CreateEvent(NS_LITERAL_STRING("PopupBlockedEvents"),
5024 getter_AddRefs(event
));
5026 nsCOMPtr
<nsIDOMPopupBlockedEvent
> pbev(do_QueryInterface(event
));
5027 pbev
->InitPopupBlockedEvent(NS_LITERAL_STRING("DOMPopupBlocked"),
5028 PR_TRUE
, PR_TRUE
, aRequestingWindow
,
5029 aPopupURI
, aPopupWindowName
,
5030 aPopupWindowFeatures
);
5031 nsCOMPtr
<nsIPrivateDOMEvent
> privateEvent(do_QueryInterface(event
));
5032 privateEvent
->SetTrusted(PR_TRUE
);
5034 nsCOMPtr
<nsIDOMEventTarget
> targ(do_QueryInterface(aDoc
));
5035 PRBool defaultActionEnabled
;
5036 targ
->DispatchEvent(event
, &defaultActionEnabled
);
5041 void FirePopupWindowEvent(nsIDOMDocument
* aDoc
)
5043 // Fire a "PopupWindow" event
5044 nsCOMPtr
<nsIDocument
> doc(do_QueryInterface(aDoc
));
5045 nsContentUtils::DispatchTrustedEvent(doc
, aDoc
,
5046 NS_LITERAL_STRING("PopupWindow"),
5052 nsGlobalWindow::CanSetProperty(const char *aPrefName
)
5054 // Chrome can set any property.
5055 if (nsContentUtils::IsCallerTrustedForWrite()) {
5059 // If the pref is set to true, we can not set the property
5061 return !nsContentUtils::GetBoolPref(aPrefName
, PR_TRUE
);
5065 nsGlobalWindow::PopupWhitelisted()
5067 if (!IsPopupBlocked(mDocument
))
5070 nsCOMPtr
<nsIDOMWindow
> parent
;
5072 if (NS_FAILED(GetParent(getter_AddRefs(parent
))) ||
5073 parent
== static_cast<nsIDOMWindow
*>(this))
5078 return static_cast<nsGlobalWindow
*>
5079 (static_cast<nsIDOMWindow
*>
5080 (parent
.get()))->PopupWhitelisted();
5084 * Examine the current document state to see if we're in a way that is
5085 * typically abused by web designers. The window.open code uses this
5086 * routine to determine whether to allow the new window.
5087 * Returns a value from the PopupControlState enum.
5090 nsGlobalWindow::RevisePopupAbuseLevel(PopupControlState aControl
)
5092 FORWARD_TO_OUTER(RevisePopupAbuseLevel
, (aControl
), aControl
);
5094 NS_ASSERTION(mDocShell
, "Must have docshell");
5096 nsCOMPtr
<nsIDocShellTreeItem
> item(do_QueryInterface(mDocShell
));
5098 NS_ASSERTION(item
, "Docshell doesn't implement nsIDocShellTreeItem?");
5100 PRInt32 type
= nsIDocShellTreeItem::typeChrome
;
5101 item
->GetItemType(&type
);
5102 if (type
!= nsIDocShellTreeItem::typeContent
)
5105 PopupControlState abuse
= aControl
;
5107 case openControlled
:
5109 case openOverridden
:
5110 if (PopupWhitelisted())
5111 abuse
= PopupControlState(abuse
- 1);
5112 case openAllowed
: break;
5114 NS_WARNING("Strange PopupControlState!");
5117 // limit the number of simultaneously open popups
5118 if (abuse
== openAbused
|| abuse
== openControlled
) {
5119 PRInt32 popupMax
= nsContentUtils::GetIntPref("dom.popup_maximum", -1);
5120 if (popupMax
>= 0 && gOpenPopupSpamCount
>= popupMax
)
5121 abuse
= openOverridden
;
5127 /* If a window open is blocked, fire the appropriate DOM events.
5128 aBlocked signifies we just blocked a popup.
5129 aWindow signifies we just opened what is probably a popup.
5132 nsGlobalWindow::FireAbuseEvents(PRBool aBlocked
, PRBool aWindow
,
5133 const nsAString
&aPopupURL
,
5134 const nsAString
&aPopupWindowName
,
5135 const nsAString
&aPopupWindowFeatures
)
5137 // fetch the URI of the window requesting the opened window
5139 nsCOMPtr
<nsIDOMWindow
> topWindow
;
5140 GetTop(getter_AddRefs(topWindow
));
5144 nsCOMPtr
<nsIDOMDocument
> topDoc
;
5145 topWindow
->GetDocument(getter_AddRefs(topDoc
));
5147 nsCOMPtr
<nsIURI
> popupURI
;
5149 // build the URI of the would-have-been popup window
5150 // (see nsWindowWatcher::URIfromURL)
5152 // first, fetch the opener's base URI
5154 nsIURI
*baseURL
= 0;
5156 JSContext
*cx
= nsContentUtils::GetCurrentJSContext();
5157 nsCOMPtr
<nsIDOMWindow
> contextWindow
;
5160 nsIScriptContext
*currentCX
= nsJSUtils::GetDynamicScriptContext(cx
);
5162 contextWindow
= do_QueryInterface(currentCX
->GetGlobalObject());
5166 contextWindow
= static_cast<nsIDOMWindow
*>(this);
5168 nsCOMPtr
<nsIDOMDocument
> domdoc
;
5169 contextWindow
->GetDocument(getter_AddRefs(domdoc
));
5170 nsCOMPtr
<nsIDocument
> doc(do_QueryInterface(domdoc
));
5172 baseURL
= doc
->GetDocBaseURI();
5174 // use the base URI to build what would have been the popup's URI
5175 nsCOMPtr
<nsIIOService
> ios(do_GetService(NS_IOSERVICE_CONTRACTID
));
5177 ios
->NewURI(NS_ConvertUTF16toUTF8(aPopupURL
), 0, baseURL
,
5178 getter_AddRefs(popupURI
));
5180 // fire an event chock full of informative URIs
5182 FirePopupBlockedEvent(topDoc
, this, popupURI
, aPopupWindowName
,
5183 aPopupWindowFeatures
);
5185 FirePopupWindowEvent(topDoc
);
5189 nsGlobalWindow::Open(const nsAString
& aUrl
, const nsAString
& aName
,
5190 const nsAString
& aOptions
, nsIDOMWindow
**_retval
)
5192 return OpenInternal(aUrl
, aName
, aOptions
,
5193 PR_FALSE
, // aDialog
5194 PR_FALSE
, // aContentModal
5195 PR_TRUE
, // aCalledNoScript
5196 PR_FALSE
, // aDoJSFixups
5197 nsnull
, nsnull
, // No args
5198 GetPrincipal(), // aCalleePrincipal
5199 nsnull
, // aJSCallerContext
5204 nsGlobalWindow::OpenJS(const nsAString
& aUrl
, const nsAString
& aName
,
5205 const nsAString
& aOptions
, nsIDOMWindow
**_retval
)
5207 return OpenInternal(aUrl
, aName
, aOptions
,
5208 PR_FALSE
, // aDialog
5209 PR_FALSE
, // aContentModal
5210 PR_FALSE
, // aCalledNoScript
5211 PR_TRUE
, // aDoJSFixups
5212 nsnull
, nsnull
, // No args
5213 GetPrincipal(), // aCalleePrincipal
5214 nsContentUtils::GetCurrentJSContext(), // aJSCallerContext
5218 // like Open, but attaches to the new window any extra parameters past
5219 // [features] as a JS property named "arguments"
5221 nsGlobalWindow::OpenDialog(const nsAString
& aUrl
, const nsAString
& aName
,
5222 const nsAString
& aOptions
,
5223 nsISupports
* aExtraArgument
, nsIDOMWindow
** _retval
)
5225 return OpenInternal(aUrl
, aName
, aOptions
,
5227 PR_FALSE
, // aContentModal
5228 PR_TRUE
, // aCalledNoScript
5229 PR_FALSE
, // aDoJSFixups
5230 nsnull
, aExtraArgument
, // Arguments
5231 GetPrincipal(), // aCalleePrincipal
5232 nsnull
, // aJSCallerContext
5237 nsGlobalWindow::OpenDialog(const nsAString
& aUrl
, const nsAString
& aName
,
5238 const nsAString
& aOptions
, nsIDOMWindow
** _retval
)
5240 if (!nsContentUtils::IsCallerTrustedForWrite()) {
5241 return NS_ERROR_DOM_SECURITY_ERR
;
5244 nsAXPCNativeCallContext
*ncc
= nsnull
;
5245 nsresult rv
= nsContentUtils::XPConnect()->
5246 GetCurrentNativeCallContext(&ncc
);
5247 NS_ENSURE_SUCCESS(rv
, rv
);
5250 return NS_ERROR_NOT_AVAILABLE
;
5252 JSContext
*cx
= nsnull
;
5254 rv
= ncc
->GetJSContext(&cx
);
5255 NS_ENSURE_SUCCESS(rv
, rv
);
5258 jsval
*argv
= nsnull
;
5260 // XXX - need to get this as nsISupports?
5261 ncc
->GetArgc(&argc
);
5262 ncc
->GetArgvPtr(&argv
);
5264 // Strip the url, name and options from the args seen by scripts.
5265 PRUint32 argOffset
= argc
< 3 ? argc
: 3;
5266 nsCOMPtr
<nsIArray
> argvArray
;
5267 rv
= NS_CreateJSArgv(cx
, argc
- argOffset
, argv
+ argOffset
,
5268 getter_AddRefs(argvArray
));
5269 NS_ENSURE_SUCCESS(rv
, rv
);
5271 return OpenInternal(aUrl
, aName
, aOptions
,
5273 PR_FALSE
, // aContentModal
5274 PR_FALSE
, // aCalledNoScript
5275 PR_FALSE
, // aDoJSFixups
5276 argvArray
, nsnull
, // Arguments
5277 GetPrincipal(), // aCalleePrincipal
5278 cx
, // aJSCallerContext
5283 nsGlobalWindow::GetFrames(nsIDOMWindow
** aFrames
)
5285 FORWARD_TO_OUTER(GetFrames
, (aFrames
), NS_ERROR_NOT_INITIALIZED
);
5288 NS_ADDREF(*aFrames
);
5290 FlushPendingNotifications(Flush_ContentAndNotify
);
5296 nsGlobalWindow::CallerInnerWindow()
5298 JSContext
*cx
= nsContentUtils::GetCurrentJSContext();
5300 NS_ERROR("Please don't call this method from C++!");
5305 JSObject
*scope
= ::JS_GetScopeChain(cx
);
5309 nsCOMPtr
<nsIXPConnectWrappedNative
> wrapper
;
5310 nsContentUtils::XPConnect()->
5311 GetWrappedNativeOfJSObject(cx
, ::JS_GetGlobalForObject(cx
, scope
),
5312 getter_AddRefs(wrapper
));
5316 // The calling window must be holding a reference, so we can just return a
5317 // raw pointer here and let the QI's addref be balanced by the nsCOMPtr
5318 // destructor's release.
5319 nsCOMPtr
<nsPIDOMWindow
> win
= do_QueryWrappedNative(wrapper
);
5321 return GetCurrentInnerWindowInternal();
5322 return static_cast<nsGlobalWindow
*>(win
.get());
5327 * Class used to represent events generated by calls to Window.postMessage,
5328 * which asynchronously creates and dispatches events.
5330 class PostMessageEvent
: public nsRunnable
5335 PostMessageEvent(nsGlobalWindow
* aSource
,
5336 const nsAString
& aCallerOrigin
,
5337 const nsAString
& aMessage
,
5338 nsGlobalWindow
* aTargetWindow
,
5339 nsIURI
* aProvidedOrigin
,
5340 PRBool aTrustedCaller
)
5342 mCallerOrigin(aCallerOrigin
),
5344 mTargetWindow(aTargetWindow
),
5345 mProvidedOrigin(aProvidedOrigin
),
5346 mTrustedCaller(aTrustedCaller
)
5348 MOZ_COUNT_CTOR(PostMessageEvent
);
5353 MOZ_COUNT_DTOR(PostMessageEvent
);
5357 nsRefPtr
<nsGlobalWindow
> mSource
;
5358 nsString mCallerOrigin
;
5360 nsRefPtr
<nsGlobalWindow
> mTargetWindow
;
5361 nsCOMPtr
<nsIURI
> mProvidedOrigin
;
5362 PRBool mTrustedCaller
;
5366 PostMessageEvent::Run()
5368 NS_ABORT_IF_FALSE(mTargetWindow
->IsOuterWindow(),
5369 "should have been passed an outer window!");
5370 NS_ABORT_IF_FALSE(!mSource
|| mSource
->IsOuterWindow(),
5371 "should have been passed an outer window!");
5373 nsRefPtr
<nsGlobalWindow
> targetWindow
;
5374 if (mTargetWindow
->IsClosedOrClosing() ||
5375 !(targetWindow
= mTargetWindow
->GetCurrentInnerWindowInternal()) ||
5376 targetWindow
->IsClosedOrClosing())
5379 NS_ABORT_IF_FALSE(targetWindow
->IsInnerWindow(),
5380 "we ordered an inner window!");
5382 // Ensure that any origin which might have been provided is the origin of this
5383 // window's document. Note that we do this *now* instead of when postMessage
5384 // is called because the target window might have been navigated to a
5385 // different location between then and now. If this check happened when
5386 // postMessage was called, it would be fairly easy for a malicious webpage to
5387 // intercept messages intended for another site by carefully timing navigation
5388 // of the target window so it changed location after postMessage but before
5390 if (mProvidedOrigin
) {
5391 // Get the target's origin either from its principal or, in the case the
5392 // principal doesn't carry a URI (e.g. the system principal), the target's
5394 nsIPrincipal
* targetPrin
= targetWindow
->GetPrincipal();
5397 nsCOMPtr
<nsIURI
> targetURI
;
5398 if (NS_FAILED(targetPrin
->GetURI(getter_AddRefs(targetURI
))))
5401 targetURI
= targetWindow
->mDoc
->GetDocumentURI();
5406 // Note: This is contrary to the spec with respect to file: URLs, which
5407 // the spec groups into a single origin, but given we intentionally
5408 // don't do that in other places it seems better to hold the line for
5409 // now. Long-term, we want HTML5 to address this so that we can
5410 // be compliant while being safer.
5411 nsIScriptSecurityManager
* ssm
= nsContentUtils::GetSecurityManager();
5413 ssm
->CheckSameOriginURI(mProvidedOrigin
, targetURI
, PR_TRUE
);
5420 nsCOMPtr
<nsIDOMDocumentEvent
> docEvent
=
5421 do_QueryInterface(targetWindow
->mDocument
);
5424 nsCOMPtr
<nsIDOMEvent
> event
;
5425 docEvent
->CreateEvent(NS_LITERAL_STRING("MessageEvent"),
5426 getter_AddRefs(event
));
5430 nsCOMPtr
<nsIDOMMessageEvent
> message
= do_QueryInterface(event
);
5431 nsresult rv
= message
->InitMessageEvent(NS_LITERAL_STRING("message"),
5432 PR_FALSE
/* non-bubbling */,
5433 PR_TRUE
/* cancelable */,
5442 // We can't simply call dispatchEvent on the window because doing so ends
5443 // up flipping the trusted bit on the event, and we don't want that to
5444 // happen because then untrusted content can call postMessage on a chrome
5445 // window if it can get a reference to it.
5447 nsIPresShell
*shell
= targetWindow
->mDoc
->GetShell();
5448 nsRefPtr
<nsPresContext
> presContext
;
5450 presContext
= shell
->GetPresContext();
5452 nsCOMPtr
<nsIPrivateDOMEvent
> privEvent
= do_QueryInterface(message
);
5453 privEvent
->SetTrusted(mTrustedCaller
);
5454 nsEvent
*internalEvent
= privEvent
->GetInternalNSEvent();
5456 nsEventStatus status
= nsEventStatus_eIgnore
;
5457 nsEventDispatcher::Dispatch(static_cast<nsPIDOMWindow
*>(mTargetWindow
),
5466 nsGlobalWindow::PostMessageMoz(const nsAString
& aMessage
, const nsAString
& aOrigin
)
5468 // NB: Since much of what this method does must happen at event dispatch time,
5469 // this method does not forward to the inner window, unlike most other
5470 // methods. We do this because the only time we need to refer to this
5471 // window, we need a reference to the outer window (the PostMessageEvent
5472 // ctor call), and we don't want to pay the price of forwarding to the
5473 // inner window for no actual benefit. Furthermore, this function must
5474 // only be called from script anyway, which should only have references to
5475 // outer windows (and if script has an inner window we've already lost).
5476 NS_ABORT_IF_FALSE(IsOuterWindow(), "only call this method on outer windows");
5479 // Window.postMessage is an intentional subversion of the same-origin policy.
5480 // As such, this code must be particularly careful in the information it
5481 // exposes to calling code.
5483 // http://www.whatwg.org/specs/web-apps/current-work/multipage/section-crossDocumentMessages.html
5486 // First, get the caller's window
5487 nsRefPtr
<nsGlobalWindow
> callerInnerWin
= CallerInnerWindow();
5488 if (!callerInnerWin
)
5490 NS_ABORT_IF_FALSE(callerInnerWin
->IsInnerWindow(),
5491 "should have gotten an inner window here");
5493 // Compute the caller's origin either from its principal or, in the case the
5494 // principal doesn't carry a URI (e.g. the system principal), the caller's
5495 // document. We must get this now instead of when the event is created and
5496 // dispatched, because ultimately it is the identity of the calling window
5497 // *now* that determines who sent the message (and not an identity which might
5498 // have changed due to intervening navigations).
5499 nsIPrincipal
* callerPrin
= callerInnerWin
->GetPrincipal();
5503 nsCOMPtr
<nsIURI
> callerOuterURI
;
5504 if (NS_FAILED(callerPrin
->GetURI(getter_AddRefs(callerOuterURI
))))
5507 nsAutoString origin
;
5508 if (callerOuterURI
) {
5509 // if the principal has a URI, use that to generate the origin
5510 nsContentUtils::GetUTFOrigin(callerPrin
, origin
);
5513 // otherwise use the URI of the document to generate origin
5514 nsCOMPtr
<nsIDocument
> doc
= do_QueryInterface(callerInnerWin
->mDocument
);
5517 callerOuterURI
= doc
->GetDocumentURI();
5518 // if the principal has a URI, use that to generate the origin
5519 nsContentUtils::GetUTFOrigin(callerOuterURI
, origin
);
5522 // Convert the provided origin string into a URI for comparison purposes.
5523 // "*" indicates no specific origin is required.
5524 nsCOMPtr
<nsIURI
> providedOrigin
;
5525 if (!aOrigin
.EqualsASCII("*")) {
5526 if (NS_FAILED(NS_NewURI(getter_AddRefs(providedOrigin
), aOrigin
)))
5527 return NS_ERROR_DOM_SYNTAX_ERR
;
5528 if (NS_FAILED(providedOrigin
->SetUserPass(EmptyCString())) ||
5529 NS_FAILED(providedOrigin
->SetPath(EmptyCString())))
5533 // Create and asynchronously dispatch a runnable which will handle actual DOM
5534 // event creation and dispatch.
5535 nsRefPtr
<PostMessageEvent
> event
=
5536 new PostMessageEvent(nsContentUtils::IsCallerChrome()
5538 : callerInnerWin
->GetOuterWindowInternal(),
5543 nsContentUtils::IsCallerTrustedForWrite());
5544 return NS_DispatchToCurrentThread(event
);
5547 class nsCloseEvent
: public nsRunnable
{
5549 nsRefPtr
<nsGlobalWindow
> mWindow
;
5551 nsCloseEvent(nsGlobalWindow
*aWindow
)
5558 PostCloseEvent(nsGlobalWindow
* aWindow
) {
5559 nsCOMPtr
<nsIRunnable
> ev
= new nsCloseEvent(aWindow
);
5560 nsresult rv
= NS_DispatchToCurrentThread(ev
);
5561 if (NS_SUCCEEDED(rv
))
5562 aWindow
->MaybeForgiveSpamCount();
5568 mWindow
->ReallyCloseWindow();
5575 nsGlobalWindow::CanClose()
5580 // Ask the content viewer whether the toplevel window can close.
5581 // If the content viewer returns false, it is responsible for calling
5582 // Close() as soon as it is possible for the window to close.
5583 // This allows us to not close the window while printing is happening.
5585 nsCOMPtr
<nsIContentViewer
> cv
;
5586 mDocShell
->GetContentViewer(getter_AddRefs(cv
));
5589 nsresult rv
= cv
->PermitUnload(PR_FALSE
, &canClose
);
5590 if (NS_SUCCEEDED(rv
) && !canClose
)
5593 rv
= cv
->RequestWindowClose(&canClose
);
5594 if (NS_SUCCEEDED(rv
) && !canClose
)
5602 nsGlobalWindow::Close()
5604 FORWARD_TO_OUTER(Close
, (), NS_ERROR_NOT_INITIALIZED
);
5606 if (IsFrame() || !mDocShell
|| IsInModalState()) {
5607 // window.close() is called on a frame in a frameset, on a window
5608 // that's already closed, or on a window for which there's
5609 // currently a modal dialog open. Ignore such calls.
5614 if (mHavePendingClose
) {
5615 // We're going to be closed anyway; do nothing since we don't want
5620 if (mBlockScriptedClosingFlag
)
5622 // A script's popup has been blocked and we don't want
5623 // the window to be closed directly after this event,
5624 // so the user can see that there was a blocked popup.
5628 // Don't allow scripts from content to close windows
5629 // that were not opened by script
5630 if (!mHadOriginalOpener
&& !nsContentUtils::IsCallerTrustedForWrite()) {
5632 nsContentUtils::GetBoolPref("dom.allow_scripts_to_close_windows",
5635 // We're blocking the close operation
5636 // report localized error msg in JS console
5637 nsContentUtils::ReportToConsole(
5638 nsContentUtils::eDOM_PROPERTIES
,
5639 "WindowCloseBlockedWarning",
5640 nsnull
, 0, // No params
5641 nsnull
, // No URI. Not clear which URI we should be using
5643 EmptyString(), 0, 0, // No source, or column/line number
5644 nsIScriptError::warningFlag
,
5645 "DOM Window"); // Better name for the category?
5651 if (!mInClose
&& !mIsClosed
&& !CanClose())
5654 // Fire a DOM event notifying listeners that this window is about to
5655 // be closed. The tab UI code may choose to cancel the default
5656 // action for this event, if so, we won't actually close the window
5657 // (since the tab UI code will close the tab in stead). Sure, this
5658 // could be abused by content code, but do we care? I don't think
5661 PRBool wasInClose
= mInClose
;
5664 if (!DispatchCustomEvent("DOMWindowClose")) {
5665 // Someone chose to prevent the default action for this event, if
5666 // so, let's not close this window after all...
5668 mInClose
= wasInClose
;
5672 return FinalClose();
5676 nsGlobalWindow::ForceClose()
5678 if (IsFrame() || !mDocShell
) {
5679 // This may be a frame in a frameset, or a window that's already closed.
5680 // Ignore such calls.
5685 if (mHavePendingClose
) {
5686 // We're going to be closed anyway; do nothing since we don't want
5693 DispatchCustomEvent("DOMWindowClose");
5695 return FinalClose();
5699 nsGlobalWindow::FinalClose()
5702 // Flag that we were closed.
5703 mIsClosed
= PR_TRUE
;
5705 nsCOMPtr
<nsIJSContextStack
> stack
=
5706 do_GetService(sJSStackContractID
);
5708 JSContext
*cx
= nsnull
;
5715 nsIScriptContext
*currentCX
= nsJSUtils::GetDynamicScriptContext(cx
);
5717 if (currentCX
&& currentCX
== GetContextInternal()) {
5718 // We ignore the return value here. If setting the termination function
5719 // fails, it's better to fail to close the window than it is to crash
5720 // (which is what would tend to happen if we did this synchronously
5722 rv
= currentCX
->SetTerminationFunction(CloseWindow
,
5723 static_cast<nsIDOMWindow
*>
5725 if (NS_SUCCEEDED(rv
)) {
5726 mHavePendingClose
= PR_TRUE
;
5733 // We may have plugins on the page that have issued this close from their
5734 // event loop and because we currently destroy the plugin window with
5735 // frames, we crash. So, if we are called from Javascript, post an event
5736 // to really close the window.
5737 rv
= NS_ERROR_FAILURE
;
5738 if (!nsContentUtils::IsCallerChrome()) {
5739 rv
= nsCloseEvent::PostCloseEvent(this);
5742 if (NS_FAILED(rv
)) {
5743 ReallyCloseWindow();
5746 mHavePendingClose
= PR_TRUE
;
5754 nsGlobalWindow::ReallyCloseWindow()
5756 FORWARD_TO_OUTER_VOID(ReallyCloseWindow
, ());
5758 // Make sure we never reenter this method.
5759 mHavePendingClose
= PR_TRUE
;
5761 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
5762 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
5764 // If there's no treeOwnerAsWin, this window must already be closed.
5766 if (treeOwnerAsWin
) {
5768 // but if we're a browser window we could be in some nasty
5769 // self-destroying cascade that we should mostly ignore
5771 nsCOMPtr
<nsIDocShellTreeItem
> docItem(do_QueryInterface(mDocShell
));
5773 nsCOMPtr
<nsIBrowserDOMWindow
> bwin
;
5774 nsCOMPtr
<nsIDocShellTreeItem
> rootItem
;
5775 docItem
->GetRootTreeItem(getter_AddRefs(rootItem
));
5776 nsCOMPtr
<nsIDOMWindow
> rootWin(do_GetInterface(rootItem
));
5777 nsCOMPtr
<nsIDOMChromeWindow
> chromeWin(do_QueryInterface(rootWin
));
5779 chromeWin
->GetBrowserDOMWindow(getter_AddRefs(bwin
));
5782 /* Normally we destroy the entire window, but not if
5783 this DOM window belongs to a tabbed browser and doesn't
5784 correspond to a tab. This allows a well-behaved tab
5785 to destroy the container as it should but is a final measure
5786 to prevent an errant tab from doing so when it shouldn't.
5787 This works because we reach this code when we shouldn't only
5788 in the particular circumstance that we belong to a tab
5789 that has just been closed (and is therefore already missing
5790 from the list of browsers) (and has an unload handler
5791 that closes the window). */
5792 // XXXbz now that we have mHavePendingClose, is this needed?
5793 PRBool isTab
= PR_FALSE
;
5794 if (rootWin
== this ||
5795 !bwin
|| (bwin
->IsTabContentWindow(GetOuterWindowInternal(),
5797 treeOwnerAsWin
->Destroy();
5806 nsGlobalWindow::EnterModalState()
5808 nsCOMPtr
<nsIDOMWindow
> top
;
5809 GetTop(getter_AddRefs(top
));
5812 NS_ERROR("Uh, EnterModalState() called w/o a reachable top window?");
5817 nsGlobalWindow
* topWin
=
5818 static_cast<nsGlobalWindow
*>(static_cast<nsIDOMWindow
*>(top
.get()));
5819 if (topWin
->mModalStateDepth
== 0) {
5820 NS_ASSERTION(!mSuspendedDoc
, "Shouldn't have mSuspendedDoc here!");
5822 mSuspendedDoc
= do_QueryInterface(topWin
->GetExtantDocument());
5823 if (mSuspendedDoc
&& mSuspendedDoc
->EventHandlingSuppressed()) {
5824 mSuspendedDoc
->SuppressEventHandling();
5826 mSuspendedDoc
= nsnull
;
5829 topWin
->mModalStateDepth
++;
5831 JSContext
*cx
= nsContentUtils::GetCurrentJSContext();
5833 nsIScriptContext
*scx
;
5834 if (cx
&& (scx
= GetScriptContextFromJSContext(cx
))) {
5835 scx
->EnterModalState();
5841 nsGlobalWindow::RunPendingTimeoutsRecursive(nsGlobalWindow
*aTopWindow
,
5842 nsGlobalWindow
*aWindow
)
5844 nsGlobalWindow
*inner
;
5846 // Return early if we're frozen or have no inner window.
5847 if (!(inner
= aWindow
->GetCurrentInnerWindowInternal()) ||
5848 inner
->IsFrozen()) {
5852 inner
->RunTimeout(nsnull
);
5854 // Check again if we're frozen since running pending timeouts
5855 // could've frozen us.
5856 if (inner
->IsFrozen()) {
5860 nsCOMPtr
<nsIDOMWindowCollection
> frames
;
5861 aWindow
->GetFrames(getter_AddRefs(frames
));
5868 if (NS_FAILED(frames
->GetLength(&length
)) || !length
) {
5872 for (i
= 0; i
< length
&& aTopWindow
->mModalStateDepth
== 0; i
++) {
5873 nsCOMPtr
<nsIDOMWindow
> child
;
5874 frames
->Item(i
, getter_AddRefs(child
));
5880 nsGlobalWindow
*childWin
=
5881 static_cast<nsGlobalWindow
*>
5882 (static_cast<nsIDOMWindow
*>
5885 RunPendingTimeoutsRecursive(aTopWindow
, childWin
);
5889 class nsPendingTimeoutRunner
: public nsRunnable
5892 nsPendingTimeoutRunner(nsGlobalWindow
*aWindow
)
5895 NS_ASSERTION(mWindow
, "mWindow is null.");
5900 nsGlobalWindow::RunPendingTimeoutsRecursive(mWindow
, mWindow
);
5906 nsRefPtr
<nsGlobalWindow
> mWindow
;
5910 nsGlobalWindow::LeaveModalState()
5912 nsCOMPtr
<nsIDOMWindow
> top
;
5913 GetTop(getter_AddRefs(top
));
5916 NS_ERROR("Uh, LeaveModalState() called w/o a reachable top window?");
5921 nsGlobalWindow
*topWin
=
5922 static_cast<nsGlobalWindow
*>
5923 (static_cast<nsIDOMWindow
*>
5926 topWin
->mModalStateDepth
--;
5928 if (topWin
->mModalStateDepth
== 0) {
5929 nsCOMPtr
<nsIRunnable
> runner
= new nsPendingTimeoutRunner(topWin
);
5930 if (NS_FAILED(NS_DispatchToCurrentThread(runner
)))
5931 NS_WARNING("failed to dispatch pending timeout runnable");
5933 if (mSuspendedDoc
) {
5934 nsCOMPtr
<nsIDocument
> currentDoc
=
5935 do_QueryInterface(topWin
->GetExtantDocument());
5936 mSuspendedDoc
->UnsuppressEventHandlingAndFireEvents(currentDoc
== mSuspendedDoc
);
5937 mSuspendedDoc
= nsnull
;
5941 JSContext
*cx
= nsContentUtils::GetCurrentJSContext();
5943 nsIScriptContext
*scx
;
5944 if (cx
&& (scx
= GetScriptContextFromJSContext(cx
))) {
5945 scx
->LeaveModalState();
5950 nsGlobalWindow::IsInModalState()
5952 nsCOMPtr
<nsIDOMWindow
> top
;
5953 GetTop(getter_AddRefs(top
));
5956 NS_ERROR("Uh, IsInModalState() called w/o a reachable top window?");
5961 return static_cast<nsGlobalWindow
*>
5962 (static_cast<nsIDOMWindow
*>
5963 (top
.get()))->mModalStateDepth
!= 0;
5968 nsGlobalWindow::NotifyDOMWindowDestroyed(nsGlobalWindow
* aWindow
) {
5969 nsCOMPtr
<nsIObserverService
> observerService
=
5970 do_GetService(NS_OBSERVERSERVICE_CONTRACTID
);
5971 if (observerService
) {
5973 NotifyObservers(static_cast<nsIScriptGlobalObject
*>(aWindow
),
5974 DOM_WINDOW_DESTROYED_TOPIC
, nsnull
);
5978 class WindowDestroyedEvent
: public nsRunnable
5981 WindowDestroyedEvent(PRUint64 aID
, const char* aTopic
) :
5982 mID(aID
), mTopic(aTopic
) {}
5986 nsCOMPtr
<nsIObserverService
> observerService
=
5987 do_GetService("@mozilla.org/observer-service;1");
5988 if (observerService
) {
5989 nsCOMPtr
<nsISupportsPRUint64
> wrapper
=
5990 do_CreateInstance(NS_SUPPORTS_PRUINT64_CONTRACTID
);
5992 wrapper
->SetData(mID
);
5993 observerService
->NotifyObservers(wrapper
, mTopic
.get(), nsnull
);
6005 nsGlobalWindow::NotifyWindowIDDestroyed(const char* aTopic
)
6007 nsRefPtr
<nsIRunnable
> runnable
= new WindowDestroyedEvent(mWindowID
, aTopic
);
6008 nsresult rv
= NS_DispatchToCurrentThread(runnable
);
6009 if (NS_SUCCEEDED(rv
)) {
6010 mNotifiedIDDestroyed
= PR_TRUE
;
6015 nsGlobalWindow::InitJavaProperties()
6017 nsIScriptContext
*scx
= GetContextInternal();
6019 if (mDidInitJavaProperties
|| IsOuterWindow() || !scx
|| !mJSObject
) {
6023 // Set mDidInitJavaProperties to true here even if initialization
6024 // can fail. If it fails, we won't try again...
6025 mDidInitJavaProperties
= PR_TRUE
;
6027 // Check whether the plugin supports NPRuntime, if so, init through
6030 nsCOMPtr
<nsIPluginHost
> host(do_GetService(MOZ_PLUGIN_HOST_CONTRACTID
));
6035 mDummyJavaPluginOwner
= new nsDummyJavaPluginOwner(mDoc
);
6036 if (!mDummyJavaPluginOwner
) {
6040 host
->InstantiateDummyJavaPlugin(mDummyJavaPluginOwner
);
6042 // It's possible for us (or the Java plugin, rather) to process
6043 // events during the above call, which can lead to this window being
6044 // torn down or what not, so re-check that the dummy plugin is still
6046 if (!mDummyJavaPluginOwner
) {
6050 nsCOMPtr
<nsIPluginInstance
> dummyPlugin
;
6051 mDummyJavaPluginOwner
->GetInstance(*getter_AddRefs(dummyPlugin
));
6054 // A dummy plugin was instantiated. This means we have a Java
6055 // plugin that supports NPRuntime. For such a plugin, the plugin
6056 // instantiation code defines the Java properties for us, so we're
6062 // No NPRuntime enabled Java plugin found, null out the owner we
6063 // would have used in that case as it's no longer needed.
6064 mDummyJavaPluginOwner
= nsnull
;
6068 nsGlobalWindow::GetCachedXBLPrototypeHandler(nsXBLPrototypeHandler
* aKey
)
6070 void* handler
= nsnull
;
6071 if (mCachedXBLPrototypeHandlers
.IsInitialized()) {
6072 mCachedXBLPrototypeHandlers
.Get(aKey
, &handler
);
6078 nsGlobalWindow::CacheXBLPrototypeHandler(nsXBLPrototypeHandler
* aKey
,
6079 nsScriptObjectHolder
& aHandler
)
6081 if (!mCachedXBLPrototypeHandlers
.IsInitialized() &&
6082 !mCachedXBLPrototypeHandlers
.Init()) {
6083 NS_ERROR("Failed to initiailize hashtable!");
6087 if (!mCachedXBLPrototypeHandlers
.Count()) {
6088 // Can't use macros to get the participant because nsGlobalChromeWindow also
6089 // runs through this code. Use QueryInterface to get the correct objects.
6090 nsXPCOMCycleCollectionParticipant
* participant
;
6091 CallQueryInterface(this, &participant
);
6092 NS_ASSERTION(participant
,
6093 "Failed to QI to nsXPCOMCycleCollectionParticipant!");
6095 nsCOMPtr
<nsISupports
> thisSupports
;
6096 QueryInterface(NS_GET_IID(nsCycleCollectionISupports
),
6097 getter_AddRefs(thisSupports
));
6098 NS_ASSERTION(thisSupports
, "Failed to QI to nsCycleCollectionISupports!");
6100 nsresult rv
= nsContentUtils::HoldJSObjects(thisSupports
, participant
);
6101 if (NS_FAILED(rv
)) {
6102 NS_ERROR("nsContentUtils::HoldJSObjects failed!");
6107 mCachedXBLPrototypeHandlers
.Put(aKey
, aHandler
);
6111 nsGlobalWindow::GetFrameElement(nsIDOMElement
** aFrameElement
)
6113 FORWARD_TO_OUTER(GetFrameElement
, (aFrameElement
), NS_ERROR_NOT_INITIALIZED
);
6115 *aFrameElement
= nsnull
;
6117 nsCOMPtr
<nsIDocShellTreeItem
> docShellTI(do_QueryInterface(mDocShell
));
6123 nsCOMPtr
<nsIDocShellTreeItem
> parent
;
6124 docShellTI
->GetSameTypeParent(getter_AddRefs(parent
));
6126 if (!parent
|| parent
== docShellTI
) {
6127 // We're at a chrome boundary, don't expose the chrome iframe
6128 // element to content code.
6133 *aFrameElement
= mFrameElement
;
6134 NS_IF_ADDREF(*aFrameElement
);
6139 // Helper for converting window.showModalDialog() options (list of ';'
6140 // separated name (:|=) value pairs) to a format that's parsable by
6141 // our normal window opening code.
6144 ConvertDialogOptions(const nsAString
& aOptions
, nsAString
& aResult
)
6146 nsAString::const_iterator end
;
6147 aOptions
.EndReading(end
);
6149 nsAString::const_iterator iter
;
6150 aOptions
.BeginReading(iter
);
6152 while (iter
!= end
) {
6154 while (nsCRT::IsAsciiSpace(*iter
) && iter
!= end
) {
6158 nsAString::const_iterator name_start
= iter
;
6160 // Skip characters until we find whitespace, ';', ':', or '='
6161 while (iter
!= end
&& !nsCRT::IsAsciiSpace(*iter
) &&
6168 nsAString::const_iterator name_end
= iter
;
6171 while (nsCRT::IsAsciiSpace(*iter
) && iter
!= end
) {
6176 // No value found, skip the ';' and keep going.
6182 nsAString::const_iterator value_start
= iter
;
6183 nsAString::const_iterator value_end
= iter
;
6185 if (*iter
== ':' || *iter
== '=') {
6186 // We found name followed by ':' or '='. Look for a value.
6188 iter
++; // Skip the ':' or '='
6191 while (nsCRT::IsAsciiSpace(*iter
) && iter
!= end
) {
6197 // Skip until we find whitespace, or ';'.
6198 while (iter
!= end
&& !nsCRT::IsAsciiSpace(*iter
) &&
6206 while (nsCRT::IsAsciiSpace(*iter
) && iter
!= end
) {
6211 const nsDependentSubstring
& name
= Substring(name_start
, name_end
);
6212 const nsDependentSubstring
& value
= Substring(value_start
, value_end
);
6214 if (name
.LowerCaseEqualsLiteral("center")) {
6215 if (value
.LowerCaseEqualsLiteral("on") ||
6216 value
.LowerCaseEqualsLiteral("yes") ||
6217 value
.LowerCaseEqualsLiteral("1")) {
6218 aResult
.AppendLiteral(",centerscreen=1");
6220 } else if (name
.LowerCaseEqualsLiteral("dialogwidth")) {
6221 if (!value
.IsEmpty()) {
6222 aResult
.AppendLiteral(",width=");
6223 aResult
.Append(value
);
6225 } else if (name
.LowerCaseEqualsLiteral("dialogheight")) {
6226 if (!value
.IsEmpty()) {
6227 aResult
.AppendLiteral(",height=");
6228 aResult
.Append(value
);
6230 } else if (name
.LowerCaseEqualsLiteral("dialogtop")) {
6231 if (!value
.IsEmpty()) {
6232 aResult
.AppendLiteral(",top=");
6233 aResult
.Append(value
);
6235 } else if (name
.LowerCaseEqualsLiteral("dialogleft")) {
6236 if (!value
.IsEmpty()) {
6237 aResult
.AppendLiteral(",left=");
6238 aResult
.Append(value
);
6240 } else if (name
.LowerCaseEqualsLiteral("resizable")) {
6241 if (value
.LowerCaseEqualsLiteral("on") ||
6242 value
.LowerCaseEqualsLiteral("yes") ||
6243 value
.LowerCaseEqualsLiteral("1")) {
6244 aResult
.AppendLiteral(",resizable=1");
6246 } else if (name
.LowerCaseEqualsLiteral("scroll")) {
6247 if (value
.LowerCaseEqualsLiteral("off") ||
6248 value
.LowerCaseEqualsLiteral("no") ||
6249 value
.LowerCaseEqualsLiteral("0")) {
6250 aResult
.AppendLiteral(",scrollbars=0");
6263 nsGlobalWindow::ShowModalDialog(const nsAString
& aURI
, nsIVariant
*aArgs
,
6264 const nsAString
& aOptions
,
6265 nsIVariant
**aRetVal
)
6269 NS_ENSURE_TRUE(mDocShell
, NS_ERROR_FAILURE
);
6271 nsCOMPtr
<nsIDOMWindow
> dlgWin
;
6272 nsAutoString
options(NS_LITERAL_STRING("-moz-internal-modal=1,status=1"));
6274 ConvertDialogOptions(aOptions
, options
);
6276 options
.AppendLiteral(",scrollbars=1,centerscreen=1,resizable=0");
6278 // Before bringing up the window, unsuppress painting and flush
6280 EnsureReflowFlushAndPaint();
6282 nsresult rv
= OpenInternal(aURI
, EmptyString(), options
,
6283 PR_FALSE
, // aDialog
6284 PR_TRUE
, // aContentModal
6285 PR_TRUE
, // aCalledNoScript
6286 PR_TRUE
, // aDoJSFixups
6287 nsnull
, aArgs
, // args
6288 GetPrincipal(), // aCalleePrincipal
6289 nsnull
, // aJSCallerContext
6290 getter_AddRefs(dlgWin
));
6292 NS_ENSURE_SUCCESS(rv
, rv
);
6295 nsCOMPtr
<nsIPrincipal
> subjectPrincipal
;
6296 rv
= nsContentUtils::GetSecurityManager()->
6297 GetSubjectPrincipal(getter_AddRefs(subjectPrincipal
));
6298 if (NS_FAILED(rv
)) {
6302 PRBool canAccess
= PR_TRUE
;
6304 if (subjectPrincipal
) {
6305 nsCOMPtr
<nsIScriptObjectPrincipal
> objPrincipal
=
6306 do_QueryInterface(dlgWin
);
6307 nsCOMPtr
<nsIPrincipal
> dialogPrincipal
;
6310 dialogPrincipal
= objPrincipal
->GetPrincipal();
6312 rv
= subjectPrincipal
->Subsumes(dialogPrincipal
, &canAccess
);
6313 NS_ENSURE_SUCCESS(rv
, rv
);
6315 // Uh, not sure what kind of dialog this is. Prevent access to
6316 // be on the safe side...
6318 canAccess
= PR_FALSE
;
6322 nsCOMPtr
<nsPIDOMWindow
> win(do_QueryInterface(dlgWin
));
6325 nsPIDOMWindow
*inner
= win
->GetCurrentInnerWindow();
6327 nsCOMPtr
<nsIDOMModalContentWindow
> dlgInner(do_QueryInterface(inner
));
6330 dlgInner
->GetReturnValue(aRetVal
);
6334 nsRefPtr
<nsGlobalWindow
> winInternal
=
6335 static_cast<nsGlobalWindow
*>(win
.get());
6336 if (winInternal
->mCallCleanUpAfterModalDialogCloses
) {
6337 winInternal
->mCallCleanUpAfterModalDialogCloses
= PR_FALSE
;
6338 winInternal
->CleanUp(PR_TRUE
);
6345 class CommandDispatcher
: public nsRunnable
6348 CommandDispatcher(nsIDOMXULCommandDispatcher
* aDispatcher
,
6349 const nsAString
& aAction
)
6350 : mDispatcher(aDispatcher
), mAction(aAction
) {}
6354 return mDispatcher
->UpdateCommands(mAction
);
6357 nsCOMPtr
<nsIDOMXULCommandDispatcher
> mDispatcher
;
6362 nsGlobalWindow::UpdateCommands(const nsAString
& anAction
)
6364 nsPIDOMWindow
*rootWindow
= nsGlobalWindow::GetPrivateRoot();
6368 nsCOMPtr
<nsIDOMXULDocument
> xulDoc
=
6369 do_QueryInterface(rootWindow
->GetExtantDocument());
6370 // See if we contain a XUL document.
6372 // Retrieve the command dispatcher and call updateCommands on it.
6373 nsCOMPtr
<nsIDOMXULCommandDispatcher
> xulCommandDispatcher
;
6374 xulDoc
->GetCommandDispatcher(getter_AddRefs(xulCommandDispatcher
));
6375 if (xulCommandDispatcher
) {
6376 nsContentUtils::AddScriptRunner(new CommandDispatcher(xulCommandDispatcher
,
6385 nsGlobalWindow::GetBlurSuppression()
6387 nsCOMPtr
<nsIBaseWindow
> treeOwnerAsWin
;
6388 GetTreeOwner(getter_AddRefs(treeOwnerAsWin
));
6389 PRBool suppress
= PR_FALSE
;
6391 treeOwnerAsWin
->GetBlurSuppression(&suppress
);
6396 nsGlobalWindow::GetSelection(nsISelection
** aSelection
)
6398 FORWARD_TO_OUTER(GetSelection
, (aSelection
), NS_ERROR_NOT_INITIALIZED
);
6400 NS_ENSURE_ARG_POINTER(aSelection
);
6401 *aSelection
= nsnull
;
6406 nsCOMPtr
<nsIPresShell
> presShell
;
6407 mDocShell
->GetPresShell(getter_AddRefs(presShell
));
6412 *aSelection
= presShell
->GetCurrentSelection(nsISelectionController::SELECTION_NORMAL
);
6414 NS_IF_ADDREF(*aSelection
);
6420 nsGlobalWindow::Find(const nsAString
& aStr
, PRBool aCaseSensitive
,
6421 PRBool aBackwards
, PRBool aWrapAround
, PRBool aWholeWord
,
6422 PRBool aSearchInFrames
, PRBool aShowDialog
,
6425 FORWARD_TO_OUTER(Find
, (aStr
, aCaseSensitive
, aBackwards
, aWrapAround
,
6426 aWholeWord
, aSearchInFrames
, aShowDialog
, aDidFind
),
6427 NS_ERROR_NOT_INITIALIZED
);
6429 nsresult rv
= NS_OK
;
6430 *aDidFind
= PR_FALSE
;
6432 nsCOMPtr
<nsIWebBrowserFind
> finder(do_GetInterface(mDocShell
));
6433 NS_ENSURE_TRUE(finder
, NS_ERROR_FAILURE
);
6435 // Set the options of the search
6436 rv
= finder
->SetSearchString(PromiseFlatString(aStr
).get());
6437 NS_ENSURE_SUCCESS(rv
, rv
);
6438 finder
->SetMatchCase(aCaseSensitive
);
6439 finder
->SetFindBackwards(aBackwards
);
6440 finder
->SetWrapFind(aWrapAround
);
6441 finder
->SetEntireWord(aWholeWord
);
6442 finder
->SetSearchFrames(aSearchInFrames
);
6444 // the nsIWebBrowserFind is initialized to use this window
6445 // as the search root, but uses focus to set the current search
6446 // frame. If we're being called from JS (as here), this window
6447 // should be the current search frame.
6448 nsCOMPtr
<nsIWebBrowserFindInFrames
> framesFinder(do_QueryInterface(finder
));
6450 framesFinder
->SetRootSearchFrame(this); // paranoia
6451 framesFinder
->SetCurrentSearchFrame(this);
6454 // The Find API does not accept empty strings. Launch the Find Dialog.
6455 if (aStr
.IsEmpty() || aShowDialog
) {
6456 // See if the find dialog is already up using nsIWindowMediator
6457 nsCOMPtr
<nsIWindowMediator
> windowMediator
=
6458 do_GetService(NS_WINDOWMEDIATOR_CONTRACTID
);
6460 nsCOMPtr
<nsIDOMWindowInternal
> findDialog
;
6462 if (windowMediator
) {
6463 windowMediator
->GetMostRecentWindow(NS_LITERAL_STRING("findInPage").get(),
6464 getter_AddRefs(findDialog
));
6468 // The Find dialog is already open, bring it to the top.
6469 rv
= findDialog
->Focus();
6470 } else { // Open a Find dialog
6472 nsCOMPtr
<nsIDOMWindow
> dialog
;
6473 rv
= OpenDialog(NS_LITERAL_STRING("chrome://global/content/finddialog.xul"),
6474 NS_LITERAL_STRING("_blank"),
6475 NS_LITERAL_STRING("chrome, resizable=no, dependent=yes"),
6476 finder
, getter_AddRefs(dialog
));
6480 // Launch the search with the passed in search string
6481 rv
= finder
->FindNext(aDidFind
);
6482 NS_ENSURE_SUCCESS(rv
, rv
);
6489 Is8bit(const nsAString
& aString
)
6491 static const PRUnichar EIGHT_BIT
= PRUnichar(~0x00FF);
6493 nsAString::const_iterator done_reading
;
6494 aString
.EndReading(done_reading
);
6496 // for each chunk of |aString|...
6497 PRUint32 fragmentLength
= 0;
6498 nsAString::const_iterator iter
;
6499 for (aString
.BeginReading(iter
); iter
!= done_reading
;
6500 iter
.advance(PRInt32(fragmentLength
))) {
6501 fragmentLength
= PRUint32(iter
.size_forward());
6502 const PRUnichar
* c
= iter
.get();
6503 const PRUnichar
* fragmentEnd
= c
+ fragmentLength
;
6505 // for each character in this chunk...
6506 while (c
< fragmentEnd
)
6507 if (*c
++ & EIGHT_BIT
)
6515 nsGlobalWindow::Atob(const nsAString
& aAsciiBase64String
,
6516 nsAString
& aBinaryData
)
6518 aBinaryData
.Truncate();
6520 if (!Is8bit(aAsciiBase64String
)) {
6521 return NS_ERROR_DOM_INVALID_CHARACTER_ERR
;
6524 PRUint32 dataLen
= aAsciiBase64String
.Length();
6526 NS_LossyConvertUTF16toASCII
base64(aAsciiBase64String
);
6527 if (base64
.Length() != dataLen
) {
6528 return NS_ERROR_OUT_OF_MEMORY
;
6531 PRInt32 resultLen
= dataLen
;
6532 if (!base64
.IsEmpty() && base64
[dataLen
- 1] == '=') {
6533 if (base64
.Length() > 1 && base64
[dataLen
- 2] == '=') {
6534 resultLen
= dataLen
- 2;
6536 resultLen
= dataLen
- 1;
6540 resultLen
= ((resultLen
* 3) / 4);
6541 // Add 4 extra bytes (one is needed for sure for null termination)
6542 // to the malloc size just to make sure we don't end up writing past
6543 // the allocated memory (the PL_Base64Decode API should really
6544 // provide a guaranteed way to figure this out w/o needing to do the
6546 char *dest
= static_cast<char *>(nsMemory::Alloc(resultLen
+ 4));
6548 return NS_ERROR_OUT_OF_MEMORY
;
6551 char *bin_data
= PL_Base64Decode(base64
.get(), dataLen
, dest
);
6553 nsresult rv
= NS_OK
;
6556 CopyASCIItoUTF16(Substring(bin_data
, bin_data
+ resultLen
), aBinaryData
);
6558 rv
= NS_ERROR_DOM_INVALID_CHARACTER_ERR
;
6561 nsMemory::Free(dest
);
6567 nsGlobalWindow::Btoa(const nsAString
& aBinaryData
,
6568 nsAString
& aAsciiBase64String
)
6570 aAsciiBase64String
.Truncate();
6572 if (!Is8bit(aBinaryData
)) {
6573 return NS_ERROR_DOM_INVALID_CHARACTER_ERR
;
6576 char *bin_data
= ToNewCString(aBinaryData
);
6578 return NS_ERROR_OUT_OF_MEMORY
;
6581 PRInt32 resultLen
= ((aBinaryData
.Length() + 2) / 3) * 4;
6583 char *base64
= PL_Base64Encode(bin_data
, aBinaryData
.Length(), nsnull
);
6585 nsMemory::Free(bin_data
);
6587 return NS_ERROR_OUT_OF_MEMORY
;
6590 CopyASCIItoUTF16(nsDependentCString(base64
, resultLen
), aAsciiBase64String
);
6593 nsMemory::Free(bin_data
);
6598 //*****************************************************************************
6599 // nsGlobalWindow::nsIDOMEventTarget
6600 //*****************************************************************************
6603 nsGlobalWindow::AddEventListener(const nsAString
& aType
,
6604 nsIDOMEventListener
* aListener
,
6607 FORWARD_TO_INNER_CREATE(AddEventListener
, (aType
, aListener
, aUseCapture
),
6608 NS_ERROR_NOT_AVAILABLE
);
6610 return AddEventListener(aType
, aListener
, aUseCapture
, PR_FALSE
, 0);
6614 nsGlobalWindow::RemoveEventListener(const nsAString
& aType
,
6615 nsIDOMEventListener
* aListener
,
6618 return RemoveGroupedEventListener(aType
, aListener
, aUseCapture
, nsnull
);
6622 nsGlobalWindow::DispatchEvent(nsIDOMEvent
* aEvent
, PRBool
* _retval
)
6624 FORWARD_TO_INNER(DispatchEvent
, (aEvent
, _retval
), NS_OK
);
6627 return NS_ERROR_FAILURE
;
6630 // Obtain a presentation shell
6631 nsIPresShell
*shell
= mDoc
->GetShell();
6632 nsRefPtr
<nsPresContext
> presContext
;
6634 // Retrieve the context
6635 presContext
= shell
->GetPresContext();
6638 nsEventStatus status
= nsEventStatus_eIgnore
;
6640 nsEventDispatcher::DispatchDOMEvent(GetOuterWindow(), nsnull
, aEvent
,
6641 presContext
, &status
);
6643 *_retval
= (status
!= nsEventStatus_eConsumeNoDefault
);
6647 //*****************************************************************************
6648 // nsGlobalWindow::nsIDOM3EventTarget
6649 //*****************************************************************************
6652 nsGlobalWindow::AddGroupedEventListener(const nsAString
& aType
,
6653 nsIDOMEventListener
*aListener
,
6655 nsIDOMEventGroup
*aEvtGrp
)
6657 FORWARD_TO_INNER_CREATE(AddGroupedEventListener
,
6658 (aType
, aListener
, aUseCapture
, aEvtGrp
),
6659 NS_ERROR_NOT_AVAILABLE
);
6661 nsIEventListenerManager
* manager
= GetListenerManager(PR_TRUE
);
6662 NS_ENSURE_STATE(manager
);
6663 PRInt32 flags
= aUseCapture
? NS_EVENT_FLAG_CAPTURE
: NS_EVENT_FLAG_BUBBLE
;
6664 return manager
->AddEventListenerByType(aListener
, aType
, flags
, aEvtGrp
);
6668 nsGlobalWindow::RemoveGroupedEventListener(const nsAString
& aType
,
6669 nsIDOMEventListener
*aListener
,
6671 nsIDOMEventGroup
*aEvtGrp
)
6673 FORWARD_TO_INNER(RemoveGroupedEventListener
,
6674 (aType
, aListener
, aUseCapture
, aEvtGrp
),
6675 NS_ERROR_NOT_INITIALIZED
);
6677 if (mListenerManager
) {
6678 PRInt32 flags
= aUseCapture
? NS_EVENT_FLAG_CAPTURE
: NS_EVENT_FLAG_BUBBLE
;
6680 mListenerManager
->RemoveEventListenerByType(aListener
, aType
, flags
,
6687 nsGlobalWindow::CanTrigger(const nsAString
& type
, PRBool
*_retval
)
6689 return NS_ERROR_NOT_IMPLEMENTED
;
6693 nsGlobalWindow::IsRegisteredHere(const nsAString
& type
, PRBool
*_retval
)
6695 return NS_ERROR_NOT_IMPLEMENTED
;
6699 nsGlobalWindow::AddEventListener(const nsAString
& aType
,
6700 nsIDOMEventListener
*aListener
,
6701 PRBool aUseCapture
, PRBool aWantsUntrusted
,
6702 PRUint8 optional_argc
)
6704 NS_ASSERTION(!aWantsUntrusted
|| optional_argc
> 0,
6705 "Won't check if this is chrome, you want to set "
6706 "aWantsUntrusted to PR_FALSE or make the aWantsUntrusted "
6707 "explicit by making optional_argc non-zero.");
6709 if (IsOuterWindow() && mInnerWindow
&&
6710 !nsContentUtils::CanCallerAccess(mInnerWindow
)) {
6711 return NS_ERROR_DOM_SECURITY_ERR
;
6714 nsIEventListenerManager
* manager
= GetListenerManager(PR_TRUE
);
6715 NS_ENSURE_STATE(manager
);
6717 PRInt32 flags
= aUseCapture
? NS_EVENT_FLAG_CAPTURE
: NS_EVENT_FLAG_BUBBLE
;
6719 if (aWantsUntrusted
||
6720 (optional_argc
== 0 && !nsContentUtils::IsChromeDoc(mDoc
))) {
6721 flags
|= NS_PRIV_EVENT_UNTRUSTED_PERMITTED
;
6724 return manager
->AddEventListenerByType(aListener
, aType
, flags
, nsnull
);
6728 nsGlobalWindow::AddEventListenerByIID(nsIDOMEventListener
* aListener
,
6731 nsIEventListenerManager
* manager
= GetListenerManager(PR_TRUE
);
6732 NS_ENSURE_STATE(manager
);
6733 return manager
->AddEventListenerByIID(aListener
, aIID
, NS_EVENT_FLAG_BUBBLE
);
6737 nsGlobalWindow::RemoveEventListenerByIID(nsIDOMEventListener
* aListener
,
6740 FORWARD_TO_INNER(RemoveEventListenerByIID
, (aListener
, aIID
),
6741 NS_ERROR_NOT_INITIALIZED
);
6743 if (mListenerManager
) {
6744 mListenerManager
->RemoveEventListenerByIID(aListener
, aIID
,
6745 NS_EVENT_FLAG_BUBBLE
);
6748 return NS_ERROR_FAILURE
;
6751 nsIEventListenerManager
*
6752 nsGlobalWindow::GetListenerManager(PRBool aCreateIfNotFound
)
6754 FORWARD_TO_INNER_CREATE(GetListenerManager
, (aCreateIfNotFound
), nsnull
);
6756 if (!mListenerManager
) {
6757 if (!aCreateIfNotFound
) {
6761 static NS_DEFINE_CID(kEventListenerManagerCID
,
6762 NS_EVENTLISTENERMANAGER_CID
);
6764 mListenerManager
= do_CreateInstance(kEventListenerManagerCID
);
6765 if (mListenerManager
) {
6766 mListenerManager
->SetListenerTarget(
6767 static_cast<nsPIDOMEventTarget
*>(this));
6771 return mListenerManager
;
6775 nsGlobalWindow::GetSystemEventGroup(nsIDOMEventGroup
**aGroup
)
6777 nsIEventListenerManager
* manager
= GetListenerManager(PR_TRUE
);
6778 NS_ENSURE_STATE(manager
);
6779 return manager
->GetSystemEventGroupLM(aGroup
);
6783 nsGlobalWindow::GetContextForEventHandlers(nsresult
* aRv
)
6785 nsIScriptContext
* scx
= GetContext();
6786 *aRv
= scx
? NS_OK
: NS_ERROR_UNEXPECTED
;
6790 //*****************************************************************************
6791 // nsGlobalWindow::nsPIDOMWindow
6792 //*****************************************************************************
6795 nsGlobalWindow::GetPrivateParent()
6797 FORWARD_TO_OUTER(GetPrivateParent
, (), nsnull
);
6799 nsCOMPtr
<nsIDOMWindow
> parent
;
6800 GetParent(getter_AddRefs(parent
));
6802 if (static_cast<nsIDOMWindow
*>(this) == parent
.get()) {
6803 nsCOMPtr
<nsIContent
> chromeElement(do_QueryInterface(mChromeEventHandler
));
6805 return nsnull
; // This is ok, just means a null parent.
6807 nsIDocument
* doc
= chromeElement
->GetDocument();
6809 return nsnull
; // This is ok, just means a null parent.
6811 nsIScriptGlobalObject
*globalObject
= doc
->GetScriptGlobalObject();
6813 return nsnull
; // This is ok, just means a null parent.
6815 parent
= do_QueryInterface(globalObject
);
6819 return static_cast<nsGlobalWindow
*>
6820 (static_cast<nsIDOMWindow
*>(parent
.get()));
6827 nsGlobalWindow::GetPrivateRoot()
6829 FORWARD_TO_OUTER(GetPrivateRoot
, (), nsnull
);
6831 nsCOMPtr
<nsIDOMWindow
> top
;
6832 GetTop(getter_AddRefs(top
));
6834 nsCOMPtr
<nsPIDOMWindow
> ptop
= do_QueryInterface(top
);
6835 NS_ASSERTION(ptop
, "cannot get ptop");
6839 nsIDocShell
*docShell
= ptop
->GetDocShell();
6841 // Get the chrome event handler from the doc shell, since we only
6842 // want to deal with XUL chrome handlers and not the new kind of
6843 // window root handler.
6844 nsCOMPtr
<nsIDOMEventTarget
> chromeEventHandler
;
6845 docShell
->GetChromeEventHandler(getter_AddRefs(chromeEventHandler
));
6847 nsCOMPtr
<nsIContent
> chromeElement(do_QueryInterface(mChromeEventHandler
));
6848 if (chromeElement
) {
6849 nsIDocument
* doc
= chromeElement
->GetDocument();
6851 nsIDOMWindow
*parent
= doc
->GetWindow();
6853 parent
->GetTop(getter_AddRefs(top
));
6858 return static_cast<nsGlobalWindow
*>
6859 (static_cast<nsIDOMWindow
*>(top
));
6864 nsGlobalWindow::GetLocation(nsIDOMLocation
** aLocation
)
6866 FORWARD_TO_INNER(GetLocation
, (aLocation
), NS_ERROR_NOT_INITIALIZED
);
6868 *aLocation
= nsnull
;
6870 nsIDocShell
*docShell
= GetDocShell();
6871 if (!mLocation
&& docShell
) {
6872 mLocation
= new nsLocation(docShell
);
6874 return NS_ERROR_OUT_OF_MEMORY
;
6878 NS_IF_ADDREF(*aLocation
= mLocation
);
6884 nsGlobalWindow::ActivateOrDeactivate(PRBool aActivate
)
6886 // Set / unset mIsActive on the top level window, which is used for the
6887 // :-moz-window-inactive pseudoclass.
6888 nsCOMPtr
<nsIWidget
> mainWidget
= GetMainWidget();
6892 // Get the top level widget (if the main widget is a sheet, this will
6893 // be the sheet's top (non-sheet) parent).
6894 nsCOMPtr
<nsIWidget
> topLevelWidget
= mainWidget
->GetSheetWindowParent();
6895 if (!topLevelWidget
) {
6896 topLevelWidget
= mainWidget
;
6899 // Get the top level widget's nsGlobalWindow
6900 nsCOMPtr
<nsIDOMWindowInternal
> topLevelWindow
;
6901 if (topLevelWidget
== mainWidget
) {
6902 topLevelWindow
= static_cast<nsIDOMWindowInternal
*>(this);
6904 // This is a workaround for the following problem:
6905 // When a window with an open sheet loses focus, only the sheet window
6906 // receives the NS_DEACTIVATE event. However, it's not the sheet that
6907 // should lose the active styling, but the containing top level window.
6909 topLevelWidget
->GetClientData(clientData
); // clientData is nsXULWindow
6910 nsISupports
* data
= static_cast<nsISupports
*>(clientData
);
6911 nsCOMPtr
<nsIInterfaceRequestor
> req(do_QueryInterface(data
));
6912 topLevelWindow
= do_GetInterface(req
);
6914 if (topLevelWindow
) {
6915 nsCOMPtr
<nsPIDOMWindow
> piWin(do_QueryInterface(topLevelWindow
));
6916 piWin
->SetActive(aActivate
);
6921 NotifyDocumentTree(nsIDocument
* aDocument
, void* aData
)
6923 aDocument
->EnumerateSubDocuments(NotifyDocumentTree
, nsnull
);
6924 aDocument
->DocumentStatesChanged(NS_DOCUMENT_STATE_WINDOW_INACTIVE
);
6929 nsGlobalWindow::SetActive(PRBool aActive
)
6931 nsPIDOMWindow::SetActive(aActive
);
6932 NotifyDocumentTree(mDoc
, nsnull
);
6935 void nsGlobalWindow::MaybeUpdateTouchState()
6937 FORWARD_TO_INNER_VOID(MaybeUpdateTouchState
, ());
6939 nsIFocusManager
* fm
= nsFocusManager::GetFocusManager();
6941 nsCOMPtr
<nsIDOMWindow
> focusedWindow
;
6942 fm
->GetFocusedWindow(getter_AddRefs(focusedWindow
));
6944 if(this == focusedWindow
) {
6949 void nsGlobalWindow::UpdateTouchState()
6951 FORWARD_TO_INNER_VOID(UpdateTouchState
, ());
6953 nsCOMPtr
<nsIWidget
> mainWidget
= GetMainWidget();
6957 if (mMayHaveTouchEventListener
) {
6958 mainWidget
->RegisterTouchWindow();
6960 mainWidget
->UnregisterTouchWindow();
6965 nsGlobalWindow::SetChromeEventHandler(nsPIDOMEventTarget
* aChromeEventHandler
)
6967 SetChromeEventHandlerInternal(aChromeEventHandler
);
6968 if (IsOuterWindow()) {
6969 // update the chrome event handler on all our inner windows
6970 for (nsGlobalWindow
*inner
= (nsGlobalWindow
*)PR_LIST_HEAD(this);
6972 inner
= (nsGlobalWindow
*)PR_NEXT_LINK(inner
)) {
6973 NS_ASSERTION(inner
->mOuterWindow
== this, "bad outer window pointer");
6974 inner
->SetChromeEventHandlerInternal(aChromeEventHandler
);
6976 } else if (mOuterWindow
) {
6977 // Need the cast to be able to call the protected method on a
6978 // superclass. We could make the method public instead, but it's really
6980 static_cast<nsGlobalWindow
*>(mOuterWindow
)->
6981 SetChromeEventHandlerInternal(aChromeEventHandler
);
6985 static PRBool
IsLink(nsIContent
* aContent
)
6987 nsCOMPtr
<nsIDOMHTMLAnchorElement
> anchor
= do_QueryInterface(aContent
);
6988 return (anchor
|| (aContent
&&
6989 aContent
->AttrValueIs(kNameSpaceID_XLink
, nsGkAtoms::type
,
6990 nsGkAtoms::simple
, eCaseMatters
)));
6994 nsGlobalWindow::SetFocusedNode(nsIContent
* aNode
,
6995 PRUint32 aFocusMethod
,
6998 FORWARD_TO_INNER_VOID(SetFocusedNode
, (aNode
, aFocusMethod
, aNeedsFocus
));
7000 NS_ASSERTION(!aNode
|| aNode
->GetCurrentDoc() == mDoc
,
7001 "setting focus to a node from the wrong document");
7003 if (mFocusedNode
!= aNode
) {
7004 UpdateCanvasFocus(PR_FALSE
, aNode
);
7005 mFocusedNode
= aNode
;
7006 mFocusMethod
= aFocusMethod
& FOCUSMETHOD_MASK
;
7007 mShowFocusRingForContent
= PR_FALSE
;
7011 // if a node was focused by a keypress, turn on focus rings for the
7013 if (mFocusMethod
& nsIFocusManager::FLAG_BYKEY
) {
7014 mFocusByKeyOccurred
= PR_TRUE
;
7016 // otherwise, we set mShowFocusRingForContent, as we don't want this to
7017 // be permanent for the window. On Windows, focus rings are only shown
7018 // when the FLAG_SHOWRING flag is used. On other platforms, focus rings
7019 // are only hidden for clicks on links.
7021 !(mFocusMethod
& nsIFocusManager::FLAG_BYMOUSE
) || !IsLink(aNode
) ||
7023 aFocusMethod
& nsIFocusManager::FLAG_SHOWRING
) {
7024 mShowFocusRingForContent
= PR_TRUE
;
7029 mNeedsFocus
= aNeedsFocus
;
7033 nsGlobalWindow::GetFocusMethod()
7035 FORWARD_TO_INNER(GetFocusMethod
, (), 0);
7037 return mFocusMethod
;
7041 nsGlobalWindow::ShouldShowFocusRing()
7043 FORWARD_TO_INNER(ShouldShowFocusRing
, (), PR_FALSE
);
7045 return mShowFocusRings
|| mShowFocusRingForContent
|| mFocusByKeyOccurred
;
7049 nsGlobalWindow::SetKeyboardIndicators(UIStateChangeType aShowAccelerators
,
7050 UIStateChangeType aShowFocusRings
)
7052 FORWARD_TO_INNER_VOID(SetKeyboardIndicators
, (aShowAccelerators
, aShowFocusRings
));
7054 // only change the flags that have been modified
7055 if (aShowAccelerators
!= UIStateChangeType_NoChange
)
7056 mShowAccelerators
= aShowAccelerators
== UIStateChangeType_Set
;
7057 if (aShowFocusRings
!= UIStateChangeType_NoChange
)
7058 mShowFocusRings
= aShowFocusRings
== UIStateChangeType_Set
;
7060 // propagate the indicators to child windows
7061 nsCOMPtr
<nsIDocShellTreeNode
> node
= do_QueryInterface(GetDocShell());
7063 PRInt32 childCount
= 0;
7064 node
->GetChildCount(&childCount
);
7066 for (PRInt32 i
= 0; i
< childCount
; ++i
) {
7067 nsCOMPtr
<nsIDocShellTreeItem
> childShell
;
7068 node
->GetChildAt(i
, getter_AddRefs(childShell
));
7069 nsCOMPtr
<nsPIDOMWindow
> childWindow
= do_GetInterface(childShell
);
7071 childWindow
->SetKeyboardIndicators(aShowAccelerators
, aShowFocusRings
);
7077 // send content state notifications
7078 nsCOMPtr
<nsPresContext
> presContext
;
7080 mDocShell
->GetPresContext(getter_AddRefs(presContext
));
7082 presContext
->EventStateManager()->
7083 SetContentState(mFocusedNode
, NS_EVENT_STATE_FOCUS
);
7090 nsGlobalWindow::GetKeyboardIndicators(PRBool
* aShowAccelerators
,
7091 PRBool
* aShowFocusRings
)
7093 FORWARD_TO_INNER_VOID(GetKeyboardIndicators
, (aShowAccelerators
, aShowFocusRings
));
7095 *aShowAccelerators
= mShowAccelerators
;
7096 *aShowFocusRings
= mShowFocusRings
;
7100 nsGlobalWindow::TakeFocus(PRBool aFocus
, PRUint32 aFocusMethod
)
7102 FORWARD_TO_INNER(TakeFocus
, (aFocus
, aFocusMethod
), PR_FALSE
);
7105 mFocusMethod
= aFocusMethod
& FOCUSMETHOD_MASK
;
7107 if (mHasFocus
!= aFocus
) {
7109 UpdateCanvasFocus(PR_TRUE
, mFocusedNode
);
7112 // if mNeedsFocus is true, then the document has not yet received a
7113 // document-level focus event. If there is a root content node, then return
7114 // true to tell the calling focus manager that a focus event is expected. If
7115 // there is no root content node, the document hasn't loaded enough yet, or
7116 // there isn't one and there is no point in firing a focus event.
7117 if (aFocus
&& mNeedsFocus
&& mDoc
&& mDoc
->GetRootElement() != nsnull
) {
7118 mNeedsFocus
= PR_FALSE
;
7122 mNeedsFocus
= PR_FALSE
;
7127 nsGlobalWindow::SetReadyForFocus()
7129 FORWARD_TO_INNER_VOID(SetReadyForFocus
, ());
7131 PRBool oldNeedsFocus
= mNeedsFocus
;
7132 mNeedsFocus
= PR_FALSE
;
7134 // update whether focus rings need to be shown using the state from the
7136 nsPIDOMWindow
* root
= GetPrivateRoot();
7138 PRBool showAccelerators
, showFocusRings
;
7139 root
->GetKeyboardIndicators(&showAccelerators
, &showFocusRings
);
7140 mShowFocusRings
= showFocusRings
;
7143 nsIFocusManager
* fm
= nsFocusManager::GetFocusManager();
7145 fm
->WindowShown(this, oldNeedsFocus
);
7149 nsGlobalWindow::PageHidden()
7151 FORWARD_TO_INNER_VOID(PageHidden
, ());
7153 // the window is being hidden, so tell the focus manager that the frame is
7154 // no longer valid. Use the persisted field to determine if the document
7155 // is being destroyed.
7157 nsIFocusManager
* fm
= nsFocusManager::GetFocusManager();
7159 fm
->WindowHidden(this);
7161 mNeedsFocus
= PR_TRUE
;
7165 nsGlobalWindow::DispatchSyncHashchange()
7167 FORWARD_TO_INNER(DispatchSyncHashchange
, (), NS_OK
);
7168 NS_ASSERTION(nsContentUtils::IsSafeToRunScript(),
7169 "Must be safe to run script here.");
7171 // Don't do anything if the window is frozen.
7175 // Dispatch the hashchange event, which doesn't bubble and isn't cancelable,
7176 // to the outer window.
7177 return nsContentUtils::DispatchTrustedEvent(mDoc
, GetOuterWindow(),
7178 NS_LITERAL_STRING("hashchange"),
7179 PR_FALSE
, PR_FALSE
);
7183 nsGlobalWindow::DispatchSyncPopState()
7185 FORWARD_TO_INNER(DispatchSyncPopState
, (), NS_OK
);
7187 NS_ASSERTION(nsContentUtils::IsSafeToRunScript(),
7188 "Must be safe to run script here.");
7190 // Check that PopState hasn't been pref'ed off.
7191 if (!nsContentUtils::GetBoolPref(sPopStatePrefStr
, PR_FALSE
))
7194 nsresult rv
= NS_OK
;
7196 // Bail if the window is frozen.
7201 // Bail if there's no document or the document's readystate isn't "complete".
7206 nsIDocument::ReadyState readyState
= mDoc
->GetReadyStateEnum();
7207 if (readyState
!= nsIDocument::READYSTATE_COMPLETE
) {
7211 // Get the document's pending state object -- it contains the data we're
7212 // going to send along with the popstate event. The object is serialized as
7214 nsAString
& stateObjJSON
= mDoc
->GetPendingStateObject();
7216 nsCOMPtr
<nsIVariant
> stateObj
;
7217 // Parse the JSON, if there's any to parse.
7218 if (!stateObjJSON
.IsEmpty()) {
7219 // Get the JSContext associated with our document. We need this for
7221 nsCOMPtr
<nsIDocument
> document
= do_QueryInterface(mDocument
);
7222 NS_ENSURE_TRUE(document
, NS_ERROR_FAILURE
);
7224 // Get the JSContext from the document, like we do in
7225 // nsContentUtils::GetContextFromDocument().
7226 nsIScriptGlobalObject
*sgo
= document
->GetScopeObject();
7227 NS_ENSURE_TRUE(sgo
, NS_ERROR_FAILURE
);
7229 nsIScriptContext
*scx
= sgo
->GetContext();
7230 NS_ENSURE_TRUE(scx
, NS_ERROR_FAILURE
);
7232 JSContext
*cx
= (JSContext
*) scx
->GetNativeContext();
7234 // If our json call triggers a JS-to-C++ call, we want that call to use cx
7235 // as the context. So we push cx onto the context stack.
7236 nsCxPusher cxPusher
;
7238 jsval jsStateObj
= JSVAL_NULL
;
7239 // Root the container which will hold our decoded state object.
7240 nsAutoGCRoot
root(&jsStateObj
, &rv
);
7241 NS_ENSURE_SUCCESS(rv
, rv
);
7243 // Deserialize the state object into an nsIVariant.
7244 nsCOMPtr
<nsIJSON
> json
= do_GetService("@mozilla.org/dom/json;1");
7245 NS_ENSURE_TRUE(cxPusher
.Push(cx
), NS_ERROR_FAILURE
);
7246 rv
= json
->DecodeToJSVal(stateObjJSON
, cx
, &jsStateObj
);
7247 NS_ENSURE_SUCCESS(rv
, rv
);
7250 nsCOMPtr
<nsIXPConnect
> xpconnect
= do_GetService(nsIXPConnect::GetCID());
7251 NS_ENSURE_TRUE(xpconnect
, NS_ERROR_FAILURE
);
7252 rv
= xpconnect
->JSValToVariant(cx
, &jsStateObj
, getter_AddRefs(stateObj
));
7253 NS_ENSURE_SUCCESS(rv
, rv
);
7256 // Obtain a presentation shell for use in creating a popstate event.
7257 nsIPresShell
*shell
= mDoc
->GetShell();
7258 nsRefPtr
<nsPresContext
> presContext
;
7260 presContext
= shell
->GetPresContext();
7263 // Create a new popstate event
7264 nsCOMPtr
<nsIDOMEvent
> domEvent
;
7265 rv
= nsEventDispatcher::CreateEvent(presContext
, nsnull
,
7266 NS_LITERAL_STRING("popstateevent"),
7267 getter_AddRefs(domEvent
));
7268 NS_ENSURE_SUCCESS(rv
, rv
);
7270 nsCOMPtr
<nsIPrivateDOMEvent
> privateEvent
= do_QueryInterface(domEvent
);
7271 NS_ENSURE_TRUE(privateEvent
, NS_ERROR_FAILURE
);
7273 // Initialize the popstate event, which does bubble but isn't cancellable.
7274 nsCOMPtr
<nsIDOMPopStateEvent
> popstateEvent
= do_QueryInterface(domEvent
);
7275 rv
= popstateEvent
->InitPopStateEvent(NS_LITERAL_STRING("popstate"),
7278 NS_ENSURE_SUCCESS(rv
, rv
);
7280 rv
= privateEvent
->SetTrusted(PR_TRUE
);
7281 NS_ENSURE_SUCCESS(rv
, rv
);
7283 nsCOMPtr
<nsIDOMEventTarget
> outerWindow
=
7284 do_QueryInterface(GetOuterWindow());
7285 NS_ENSURE_TRUE(outerWindow
, NS_ERROR_UNEXPECTED
);
7287 rv
= privateEvent
->SetTarget(outerWindow
);
7288 NS_ENSURE_SUCCESS(rv
, rv
);
7290 PRBool dummy
; // default action
7291 return DispatchEvent(popstateEvent
, &dummy
);
7294 // Find an nsICanvasFrame under aFrame. Only search the principal
7295 // child lists. aFrame must be non-null.
7296 static nsCanvasFrame
* FindCanvasFrame(nsIFrame
* aFrame
)
7298 nsCanvasFrame
* canvasFrame
= do_QueryFrame(aFrame
);
7303 nsIFrame
* kid
= aFrame
->GetFirstChild(nsnull
);
7305 canvasFrame
= FindCanvasFrame(kid
);
7309 kid
= kid
->GetNextSibling();
7315 //-------------------------------------------------------
7316 // Tells the HTMLFrame/CanvasFrame that is now has focus
7318 nsGlobalWindow::UpdateCanvasFocus(PRBool aFocusChanged
, nsIContent
* aNewContent
)
7320 // this is called from the inner window so use GetDocShell
7321 nsIDocShell
* docShell
= GetDocShell();
7325 nsCOMPtr
<nsIEditorDocShell
> editorDocShell
= do_QueryInterface(docShell
);
7326 if (editorDocShell
) {
7328 editorDocShell
->GetEditable(&editable
);
7333 nsCOMPtr
<nsIPresShell
> presShell
;
7334 docShell
->GetPresShell(getter_AddRefs(presShell
));
7335 if (!presShell
|| !mDocument
)
7338 nsCOMPtr
<nsIDocument
> doc(do_QueryInterface(mDocument
));
7339 Element
*rootElement
= doc
->GetRootElement();
7341 if ((mHasFocus
|| aFocusChanged
) &&
7342 (mFocusedNode
== rootElement
|| aNewContent
== rootElement
)) {
7343 nsIFrame
* frame
= rootElement
->GetPrimaryFrame();
7345 frame
= frame
->GetParent();
7346 nsCanvasFrame
* canvasFrame
= do_QueryFrame(frame
);
7348 canvasFrame
->SetHasFocus(mHasFocus
&& rootElement
== aNewContent
);
7353 // Look for the frame the hard way
7354 nsIFrame
* frame
= presShell
->GetRootFrame();
7356 nsCanvasFrame
* canvasFrame
= FindCanvasFrame(frame
);
7358 canvasFrame
->SetHasFocus(PR_FALSE
);
7364 //*****************************************************************************
7365 // nsGlobalWindow::nsIDOMViewCSS
7366 //*****************************************************************************
7369 nsGlobalWindow::GetComputedStyle(nsIDOMElement
* aElt
,
7370 const nsAString
& aPseudoElt
,
7371 nsIDOMCSSStyleDeclaration
** aReturn
)
7373 FORWARD_TO_OUTER(GetComputedStyle
, (aElt
, aPseudoElt
, aReturn
),
7374 NS_ERROR_NOT_INITIALIZED
);
7376 NS_ENSURE_ARG_POINTER(aReturn
);
7380 return NS_ERROR_DOM_NOT_SUPPORTED_ERR
;
7387 nsCOMPtr
<nsIPresShell
> presShell
;
7388 mDocShell
->GetPresShell(getter_AddRefs(presShell
));
7394 nsRefPtr
<nsComputedDOMStyle
> compStyle
;
7395 nsresult rv
= NS_NewComputedDOMStyle(aElt
, aPseudoElt
, presShell
,
7396 getter_AddRefs(compStyle
));
7397 NS_ENSURE_SUCCESS(rv
, rv
);
7399 *aReturn
= compStyle
.forget().get();
7404 //*****************************************************************************
7405 // nsGlobalWindow::nsIDOMAbstractView
7406 //*****************************************************************************
7409 nsGlobalWindow::GetDocument(nsIDOMDocumentView
** aDocumentView
)
7411 NS_ENSURE_ARG_POINTER(aDocumentView
);
7413 nsresult rv
= NS_OK
;
7416 rv
= CallQueryInterface(mDocument
, aDocumentView
);
7419 *aDocumentView
= nsnull
;
7425 //*****************************************************************************
7426 // nsGlobalWindow::nsIDOMStorageWindow
7427 //*****************************************************************************
7430 nsGlobalWindow::GetSessionStorage(nsIDOMStorage
** aSessionStorage
)
7432 FORWARD_TO_INNER(GetSessionStorage
, (aSessionStorage
), NS_ERROR_UNEXPECTED
);
7434 nsIPrincipal
*principal
= GetPrincipal();
7435 nsIDocShell
* docShell
= GetDocShell();
7437 if (!principal
|| !docShell
) {
7441 if (mSessionStorage
) {
7443 if (PR_LOG_TEST(gDOMLeakPRLog
, PR_LOG_DEBUG
)) {
7444 PR_LogPrint("nsGlobalWindow %p has %p sessionStorage", this, mSessionStorage
.get());
7447 nsCOMPtr
<nsPIDOMStorage
> piStorage
= do_QueryInterface(mSessionStorage
);
7449 PRBool canAccess
= piStorage
->CanAccess(principal
);
7450 NS_ASSERTION(canAccess
,
7451 "window %x owned sessionStorage "
7452 "that could not be accessed!");
7454 mSessionStorage
= nsnull
;
7459 if (!mSessionStorage
) {
7460 *aSessionStorage
= nsnull
;
7462 nsString documentURI
;
7463 nsCOMPtr
<nsIDOM3Document
> document3
= do_QueryInterface(mDoc
);
7465 document3
->GetDocumentURI(documentURI
);
7467 nsresult rv
= docShell
->GetSessionStorageForPrincipal(principal
,
7470 getter_AddRefs(mSessionStorage
));
7471 NS_ENSURE_SUCCESS(rv
, rv
);
7474 if (PR_LOG_TEST(gDOMLeakPRLog
, PR_LOG_DEBUG
)) {
7475 PR_LogPrint("nsGlobalWindow %p tried to get a new sessionStorage %p", this, mSessionStorage
.get());
7479 if (!mSessionStorage
) {
7480 return NS_ERROR_DOM_NOT_SUPPORTED_ERR
;
7485 if (PR_LOG_TEST(gDOMLeakPRLog
, PR_LOG_DEBUG
)) {
7486 PR_LogPrint("nsGlobalWindow %p returns %p sessionStorage", this, mSessionStorage
.get());
7490 NS_ADDREF(*aSessionStorage
= mSessionStorage
);
7495 nsGlobalWindow::GetGlobalStorage(nsIDOMStorageList
** aGlobalStorage
)
7497 NS_ENSURE_ARG_POINTER(aGlobalStorage
);
7500 if (!sGlobalStorageList
) {
7501 nsresult rv
= NS_NewDOMStorageList(&sGlobalStorageList
);
7502 NS_ENSURE_SUCCESS(rv
, rv
);
7505 *aGlobalStorage
= sGlobalStorageList
;
7506 NS_IF_ADDREF(*aGlobalStorage
);
7510 return NS_ERROR_DOM_NOT_SUPPORTED_ERR
;
7515 nsGlobalWindow::GetLocalStorage(nsIDOMStorage
** aLocalStorage
)
7517 FORWARD_TO_INNER(GetLocalStorage
, (aLocalStorage
), NS_ERROR_UNEXPECTED
);
7519 NS_ENSURE_ARG(aLocalStorage
);
7521 if (!mLocalStorage
) {
7522 *aLocalStorage
= nsnull
;
7526 PRPackedBool unused
;
7527 if (!nsDOMStorage::CanUseStorage(&unused
))
7528 return NS_ERROR_DOM_SECURITY_ERR
;
7530 nsIPrincipal
*principal
= GetPrincipal();
7534 nsCOMPtr
<nsIDOMStorageManager
> storageManager
=
7535 do_GetService("@mozilla.org/dom/storagemanager;1", &rv
);
7536 NS_ENSURE_SUCCESS(rv
, rv
);
7538 nsString documentURI
;
7539 nsCOMPtr
<nsIDOM3Document
> document3
= do_QueryInterface(mDoc
);
7541 document3
->GetDocumentURI(documentURI
);
7543 rv
= storageManager
->GetLocalStorageForPrincipal(principal
,
7545 getter_AddRefs(mLocalStorage
));
7546 NS_ENSURE_SUCCESS(rv
, rv
);
7549 NS_ADDREF(*aLocalStorage
= mLocalStorage
);
7554 nsGlobalWindow::GetMoz_indexedDB(nsIIDBFactory
** _retval
)
7557 mIndexedDB
= mozilla::dom::indexedDB::IDBFactory::Create();
7558 NS_ENSURE_TRUE(mIndexedDB
, NS_ERROR_FAILURE
);
7561 nsCOMPtr
<nsIIDBFactory
> request(mIndexedDB
);
7562 request
.forget(_retval
);
7566 //*****************************************************************************
7567 // nsGlobalWindow::nsIInterfaceRequestor
7568 //*****************************************************************************
7571 nsGlobalWindow::GetInterface(const nsIID
& aIID
, void **aSink
)
7573 NS_ENSURE_ARG_POINTER(aSink
);
7576 if (aIID
.Equals(NS_GET_IID(nsIDocCharset
))) {
7577 FORWARD_TO_OUTER(GetInterface
, (aIID
, aSink
), NS_ERROR_NOT_INITIALIZED
);
7580 nsCOMPtr
<nsIDocCharset
> docCharset(do_QueryInterface(mDocShell
));
7582 *aSink
= docCharset
;
7583 NS_ADDREF(((nsISupports
*) *aSink
));
7587 else if (aIID
.Equals(NS_GET_IID(nsIWebNavigation
))) {
7588 FORWARD_TO_OUTER(GetInterface
, (aIID
, aSink
), NS_ERROR_NOT_INITIALIZED
);
7591 nsCOMPtr
<nsIWebNavigation
> webNav(do_QueryInterface(mDocShell
));
7594 NS_ADDREF(((nsISupports
*) *aSink
));
7599 else if (aIID
.Equals(NS_GET_IID(nsIWebBrowserPrint
))) {
7600 FORWARD_TO_OUTER(GetInterface
, (aIID
, aSink
), NS_ERROR_NOT_INITIALIZED
);
7603 nsCOMPtr
<nsIContentViewer
> viewer
;
7604 mDocShell
->GetContentViewer(getter_AddRefs(viewer
));
7606 nsCOMPtr
<nsIWebBrowserPrint
> webBrowserPrint(do_QueryInterface(viewer
));
7607 if (webBrowserPrint
) {
7608 *aSink
= webBrowserPrint
;
7609 NS_ADDREF(((nsISupports
*) *aSink
));
7615 else if (aIID
.Equals(NS_GET_IID(nsIScriptEventManager
))) {
7617 nsIScriptEventManager
* mgr
= mDoc
->GetScriptEventManager();
7620 NS_ADDREF(((nsISupports
*) *aSink
));
7624 else if (aIID
.Equals(NS_GET_IID(nsIDOMWindowUtils
))) {
7625 FORWARD_TO_OUTER(GetInterface
, (aIID
, aSink
), NS_ERROR_NOT_INITIALIZED
);
7627 nsCOMPtr
<nsISupports
> utils(do_QueryReferent(mWindowUtils
));
7630 NS_ADDREF(((nsISupports
*) *aSink
));
7632 nsDOMWindowUtils
*utilObj
= new nsDOMWindowUtils(this);
7633 nsCOMPtr
<nsISupports
> utilsIfc
=
7634 NS_ISUPPORTS_CAST(nsIDOMWindowUtils
*, utilObj
);
7636 mWindowUtils
= do_GetWeakReference(utilsIfc
);
7638 NS_ADDREF(((nsISupports
*) *aSink
));
7643 return QueryInterface(aIID
, aSink
);
7646 return *aSink
? NS_OK
: NS_ERROR_NO_INTERFACE
;
7650 nsGlobalWindow::FireOfflineStatusEvent()
7655 if (NS_IsOffline()) {
7656 name
.AssignLiteral("offline");
7658 name
.AssignLiteral("online");
7660 // The event is fired at the body element, or if there is no body element,
7662 nsCOMPtr
<nsISupports
> eventTarget
= mDoc
.get();
7663 nsCOMPtr
<nsIDOMHTMLDocument
> htmlDoc
= do_QueryInterface(mDoc
);
7665 nsCOMPtr
<nsIDOMHTMLElement
> body
;
7666 htmlDoc
->GetBody(getter_AddRefs(body
));
7672 nsCOMPtr
<nsIDOMElement
> documentElement
;
7673 mDocument
->GetDocumentElement(getter_AddRefs(documentElement
));
7674 if(documentElement
) {
7675 eventTarget
= documentElement
;
7678 nsContentUtils::DispatchTrustedEvent(mDoc
, eventTarget
, name
, PR_TRUE
, PR_FALSE
);
7682 nsGlobalWindow::Observe(nsISupports
* aSubject
, const char* aTopic
,
7683 const PRUnichar
* aData
)
7685 if (!nsCRT::strcmp(aTopic
, NS_IOSERVICE_OFFLINE_STATUS_TOPIC
)) {
7687 // if an even number of notifications arrive while we're frozen,
7688 // we don't need to fire.
7689 mFireOfflineStatusChangeEventOnThaw
= !mFireOfflineStatusChangeEventOnThaw
;
7691 FireOfflineStatusEvent();
7696 if (IsInnerWindow() && !nsCRT::strcmp(aTopic
, "dom-storage-changed")) {
7697 nsIPrincipal
*principal
;
7700 principal
= GetPrincipal();
7702 // A global storage object changed, check to see if it's one
7703 // this window can access.
7705 nsCOMPtr
<nsIURI
> codebase
;
7706 principal
->GetURI(getter_AddRefs(codebase
));
7712 nsCAutoString currentDomain
;
7713 rv
= codebase
->GetAsciiHost(currentDomain
);
7714 if (NS_FAILED(rv
)) {
7718 if (!nsDOMStorageList::CanAccessDomain(NS_ConvertUTF16toUTF8(aData
),
7720 // This window can't reach the global storage object for the
7721 // domain for which the change happened, so don't fire any
7722 // events in this window.
7728 nsAutoString
domain(aData
);
7731 // This window is frozen, rather than firing the events here,
7732 // store the domain in which the change happened and fire the
7733 // events if we're ever thawed.
7735 if (!mPendingStorageEventsObsolete
) {
7736 mPendingStorageEventsObsolete
= new nsDataHashtable
<nsStringHashKey
, PRBool
>;
7737 NS_ENSURE_TRUE(mPendingStorageEventsObsolete
, NS_ERROR_OUT_OF_MEMORY
);
7739 rv
= mPendingStorageEventsObsolete
->Init();
7740 NS_ENSURE_SUCCESS(rv
, rv
);
7743 mPendingStorageEventsObsolete
->Put(domain
, PR_TRUE
);
7748 nsRefPtr
<nsDOMStorageEventObsolete
> event
= new nsDOMStorageEventObsolete();
7749 NS_ENSURE_TRUE(event
, NS_ERROR_OUT_OF_MEMORY
);
7751 rv
= event
->InitStorageEvent(NS_LITERAL_STRING("storage"), PR_FALSE
, PR_FALSE
, domain
);
7752 NS_ENSURE_SUCCESS(rv
, rv
);
7754 nsCOMPtr
<nsIDOMHTMLDocument
> htmlDoc(do_QueryInterface(mDocument
));
7756 nsCOMPtr
<nsIDOMEventTarget
> target
;
7759 nsCOMPtr
<nsIDOMHTMLElement
> body
;
7760 htmlDoc
->GetBody(getter_AddRefs(body
));
7762 target
= do_QueryInterface(body
);
7769 PRBool defaultActionEnabled
;
7770 target
->DispatchEvent((nsIDOMStorageEventObsolete
*)event
, &defaultActionEnabled
);
7775 if (IsInnerWindow() && !nsCRT::strcmp(aTopic
, "dom-storage2-changed")) {
7776 nsIPrincipal
*principal
;
7779 nsCOMPtr
<nsIDOMStorageEvent
> event
= do_QueryInterface(aSubject
, &rv
);
7780 NS_ENSURE_SUCCESS(rv
, rv
);
7782 nsCOMPtr
<nsIDOMStorage
> changingStorage
;
7783 rv
= event
->GetStorageArea(getter_AddRefs(changingStorage
));
7784 NS_ENSURE_SUCCESS(rv
, rv
);
7786 nsCOMPtr
<nsPIDOMStorage
> pistorage
= do_QueryInterface(changingStorage
);
7787 nsPIDOMStorage::nsDOMStorageType storageType
= pistorage
->StorageType();
7789 principal
= GetPrincipal();
7790 switch (storageType
)
7792 case nsPIDOMStorage::SessionStorage
:
7794 if (SameCOMIdentity(mSessionStorage
, changingStorage
)) {
7795 // Do not fire any events for the same storage object, it's not shared
7796 // among windows, see nsGlobalWindow::GetSessionStoarge()
7800 nsCOMPtr
<nsIDOMStorage
> storage
= mSessionStorage
;
7802 nsIDocShell
* docShell
= GetDocShell();
7803 if (principal
&& docShell
) {
7804 // No need to pass documentURI here, it's only needed when we want
7805 // to create a new storage, the third paramater would be PR_TRUE
7806 docShell
->GetSessionStorageForPrincipal(principal
,
7809 getter_AddRefs(storage
));
7813 if (!pistorage
->IsForkOf(storage
)) {
7814 // This storage event is coming from a different doc shell,
7815 // i.e. it is a clone, ignore this event.
7820 if (PR_LOG_TEST(gDOMLeakPRLog
, PR_LOG_DEBUG
)) {
7821 PR_LogPrint("nsGlobalWindow %p with sessionStorage %p passing event from %p", this, mSessionStorage
.get(), pistorage
.get());
7827 case nsPIDOMStorage::LocalStorage
:
7829 if (SameCOMIdentity(mLocalStorage
, changingStorage
)) {
7830 // Do not fire any events for the same storage object, it's not shared
7831 // among windows, see nsGlobalWindow::GetLocalStoarge()
7835 // Allow event fire only for the same principal storages
7836 // XXX We have to use EqualsIgnoreDomain after bug 495337 lands
7837 nsIPrincipal
*storagePrincipal
= pistorage
->Principal();
7840 rv
= storagePrincipal
->Equals(principal
, &equals
);
7841 NS_ENSURE_SUCCESS(rv
, rv
);
7853 // This window is frozen, rather than firing the events here,
7854 // store the domain in which the change happened and fire the
7855 // events if we're ever thawed.
7857 mPendingStorageEvents
.AppendElement(event
);
7861 PRBool defaultActionEnabled
;
7862 DispatchEvent((nsIDOMStorageEvent
*)event
, &defaultActionEnabled
);
7867 NS_WARNING("unrecognized topic in nsGlobalWindow::Observe");
7868 return NS_ERROR_FAILURE
;
7871 static PLDHashOperator
7872 FirePendingStorageEvents(const nsAString
& aKey
, PRBool aData
, void *userArg
)
7874 nsGlobalWindow
*win
= static_cast<nsGlobalWindow
*>(userArg
);
7876 nsCOMPtr
<nsIDOMStorage
> storage
;
7877 win
->GetSessionStorage(getter_AddRefs(storage
));
7880 win
->Observe(storage
, "dom-storage-changed",
7881 aKey
.IsEmpty() ? nsnull
: PromiseFlatString(aKey
).get());
7884 return PL_DHASH_NEXT
;
7888 nsGlobalWindow::FireDelayedDOMEvents()
7890 FORWARD_TO_INNER(FireDelayedDOMEvents
, (), NS_ERROR_UNEXPECTED
);
7892 for (PRUint32 i
= 0; i
< mPendingStorageEvents
.Length(); ++i
) {
7893 Observe(mPendingStorageEvents
[i
], "dom-storage2-changed", nsnull
);
7896 if (mPendingStorageEventsObsolete
) {
7897 // Fire pending storage events.
7898 mPendingStorageEventsObsolete
->EnumerateRead(FirePendingStorageEvents
, this);
7900 delete mPendingStorageEventsObsolete
;
7901 mPendingStorageEventsObsolete
= nsnull
;
7904 if (mApplicationCache
) {
7905 static_cast<nsDOMOfflineResourceList
*>(mApplicationCache
.get())->FirePendingEvents();
7908 if (mFireOfflineStatusChangeEventOnThaw
) {
7909 mFireOfflineStatusChangeEventOnThaw
= PR_FALSE
;
7910 FireOfflineStatusEvent();
7913 nsCOMPtr
<nsIDocShellTreeNode
> node
=
7914 do_QueryInterface(GetDocShell());
7916 PRInt32 childCount
= 0;
7917 node
->GetChildCount(&childCount
);
7919 for (PRInt32 i
= 0; i
< childCount
; ++i
) {
7920 nsCOMPtr
<nsIDocShellTreeItem
> childShell
;
7921 node
->GetChildAt(i
, getter_AddRefs(childShell
));
7922 NS_ASSERTION(childShell
, "null child shell");
7924 nsCOMPtr
<nsPIDOMWindow
> pWin
= do_GetInterface(childShell
);
7926 nsGlobalWindow
*win
=
7927 static_cast<nsGlobalWindow
*>
7928 (static_cast<nsPIDOMWindow
*>(pWin
));
7929 win
->FireDelayedDOMEvents();
7937 //*****************************************************************************
7938 // nsGlobalWindow: Window Control Functions
7939 //*****************************************************************************
7941 nsIDOMWindowInternal
*
7942 nsGlobalWindow::GetParentInternal()
7944 FORWARD_TO_OUTER(GetParentInternal
, (), nsnull
);
7946 nsIDOMWindowInternal
*parentInternal
= nsnull
;
7948 nsCOMPtr
<nsIDOMWindow
> parent
;
7949 GetParent(getter_AddRefs(parent
));
7951 if (parent
&& parent
!= static_cast<nsIDOMWindow
*>(this)) {
7952 nsCOMPtr
<nsIDOMWindowInternal
> tmp(do_QueryInterface(parent
));
7953 NS_ASSERTION(parent
, "Huh, parent not an nsIDOMWindowInternal?");
7955 parentInternal
= tmp
;
7958 return parentInternal
;
7963 nsGlobalWindow::CloseBlockScriptTerminationFunc(nsISupports
*aRef
)
7965 nsGlobalWindow
* pwin
= static_cast<nsGlobalWindow
*>
7966 (static_cast<nsPIDOMWindow
*>(aRef
));
7967 pwin
->mBlockScriptedClosingFlag
= PR_FALSE
;
7971 nsGlobalWindow::OpenInternal(const nsAString
& aUrl
, const nsAString
& aName
,
7972 const nsAString
& aOptions
, PRBool aDialog
,
7973 PRBool aContentModal
, PRBool aCalledNoScript
,
7974 PRBool aDoJSFixups
, nsIArray
*argv
,
7975 nsISupports
*aExtraArgument
,
7976 nsIPrincipal
*aCalleePrincipal
,
7977 JSContext
*aJSCallerContext
,
7978 nsIDOMWindow
**aReturn
)
7980 FORWARD_TO_OUTER(OpenInternal
, (aUrl
, aName
, aOptions
, aDialog
,
7981 aContentModal
, aCalledNoScript
, aDoJSFixups
,
7982 argv
, aExtraArgument
, aCalleePrincipal
,
7983 aJSCallerContext
, aReturn
),
7984 NS_ERROR_NOT_INITIALIZED
);
7989 argv
->GetLength(&argc
);
7991 NS_PRECONDITION(!aExtraArgument
|| (!argv
&& argc
== 0),
7992 "Can't pass in arguments both ways");
7993 NS_PRECONDITION(!aCalledNoScript
|| (!argv
&& argc
== 0),
7994 "Can't pass JS args when called via the noscript methods");
7995 NS_PRECONDITION(!aJSCallerContext
|| !aCalledNoScript
,
7996 "Shouldn't have caller context when called noscript");
8000 nsCOMPtr
<nsIWebBrowserChrome
> chrome
;
8001 GetWebBrowserChrome(getter_AddRefs(chrome
));
8003 // No chrome means we don't want to go through with this open call
8004 // -- see nsIWindowWatcher.idl
8005 return NS_ERROR_NOT_AVAILABLE
;
8008 NS_ASSERTION(mDocShell
, "Must have docshell here");
8010 const PRBool checkForPopup
=
8011 !aDialog
&& !WindowExists(aName
, !aCalledNoScript
);
8013 // Note: it's very important that this be an nsXPIDLCString, since we want
8014 // .get() on it to return nsnull until we write stuff to it. The window
8015 // watcher expects a null URL string if there is no URL to load.
8017 nsresult rv
= NS_OK
;
8019 // It's important to do this security check before determining whether this
8020 // window opening should be blocked, to ensure that we don't FireAbuseEvents
8021 // for a window opening that wouldn't have succeeded in the first place.
8022 if (!aUrl
.IsEmpty()) {
8023 AppendUTF16toUTF8(aUrl
, url
);
8025 /* Check whether the URI is allowed, but not for dialogs --
8026 see bug 56851. The security of this function depends on
8027 window.openDialog being inaccessible from web scripts */
8028 if (url
.get() && !aDialog
)
8029 rv
= SecurityCheckURL(url
.get());
8035 PopupControlState abuseLevel
= gPopupControlState
;
8036 if (checkForPopup
) {
8037 abuseLevel
= RevisePopupAbuseLevel(abuseLevel
);
8038 if (abuseLevel
>= openAbused
) {
8039 if (aJSCallerContext
) {
8040 // If script in some other window is doing a window.open on us and
8041 // it's being blocked, then it's OK to close us afterwards, probably.
8042 // But if we're doing a window.open on ourselves and block the popup,
8043 // prevent this window from closing until after this script terminates
8044 // so that whatever popup blocker UI the app has will be visible.
8045 if (mContext
== GetScriptContextFromJSContext(aJSCallerContext
)) {
8046 mBlockScriptedClosingFlag
= PR_TRUE
;
8047 mContext
->SetTerminationFunction(CloseBlockScriptTerminationFunc
,
8048 static_cast<nsPIDOMWindow
*>
8053 FireAbuseEvents(PR_TRUE
, PR_FALSE
, aUrl
, aName
, aOptions
);
8054 return aDoJSFixups
? NS_OK
: NS_ERROR_FAILURE
;
8058 nsCOMPtr
<nsIDOMWindow
> domReturn
;
8060 nsCOMPtr
<nsIWindowWatcher
> wwatch
=
8061 do_GetService(NS_WINDOWWATCHER_CONTRACTID
, &rv
);
8062 NS_ENSURE_TRUE(wwatch
, rv
);
8064 NS_ConvertUTF16toUTF8
options(aOptions
);
8065 NS_ConvertUTF16toUTF8
name(aName
);
8067 const char *options_ptr
= aOptions
.IsEmpty() ? nsnull
: options
.get();
8068 const char *name_ptr
= aName
.IsEmpty() ? nsnull
: name
.get();
8071 // Reset popup state while opening a window to prevent the
8072 // current state from being active the whole time a modal
8074 nsAutoPopupStatePusher
popupStatePusher(openAbused
, PR_TRUE
);
8076 if (!aCalledNoScript
) {
8077 nsCOMPtr
<nsPIWindowWatcher
> pwwatch(do_QueryInterface(wwatch
));
8078 NS_ASSERTION(pwwatch
,
8079 "Unable to open windows from JS because window watcher "
8081 NS_ENSURE_TRUE(pwwatch
, NS_ERROR_UNEXPECTED
);
8083 rv
= pwwatch
->OpenWindowJS(this, url
.get(), name_ptr
, options_ptr
,
8085 getter_AddRefs(domReturn
));
8087 // Push a null JSContext here so that the window watcher won't screw us
8088 // up. We do NOT want this case looking at the JS context on the stack
8089 // when searching. Compare comments on
8090 // nsIDOMWindowInternal::OpenWindow and nsIWindowWatcher::OpenWindow.
8091 nsCOMPtr
<nsIJSContextStack
> stack
;
8093 if (!aContentModal
) {
8094 stack
= do_GetService(sJSStackContractID
);
8098 rv
= stack
->Push(nsnull
);
8099 NS_ENSURE_SUCCESS(rv
, rv
);
8102 rv
= wwatch
->OpenWindow(this, url
.get(), name_ptr
, options_ptr
,
8103 aExtraArgument
, getter_AddRefs(domReturn
));
8108 NS_ASSERTION(!cx
, "Unexpected JSContext popped!");
8113 NS_ENSURE_SUCCESS(rv
, rv
);
8117 domReturn
.swap(*aReturn
);
8120 nsCOMPtr
<nsIDOMChromeWindow
> chrome_win(do_QueryInterface(*aReturn
));
8122 // A new non-chrome window was created from a call to
8123 // window.open() from JavaScript, make sure there's a document in
8124 // the new window. We do this by simply asking the new window for
8125 // its document, this will synchronously create an empty document
8126 // if there is no document in the window.
8127 // XXXbz should this just use EnsureInnerWindow()?
8130 nsCOMPtr
<nsPIDOMWindow
> pidomwin(do_QueryInterface(*aReturn
));
8132 nsIDOMDocument
*temp
= pidomwin
->GetExtantDocument();
8134 NS_ASSERTION(temp
, "No document in new window!!!");
8138 nsCOMPtr
<nsIDOMDocument
> doc
;
8139 (*aReturn
)->GetDocument(getter_AddRefs(doc
));
8143 if (checkForPopup
) {
8144 if (abuseLevel
>= openControlled
) {
8145 nsGlobalWindow
*opened
= static_cast<nsGlobalWindow
*>(*aReturn
);
8146 if (!opened
->IsPopupSpamWindow()) {
8147 opened
->SetPopupSpamWindow(PR_TRUE
);
8148 ++gOpenPopupSpamCount
;
8151 if (abuseLevel
>= openAbused
)
8152 FireAbuseEvents(PR_FALSE
, PR_TRUE
, aUrl
, aName
, aOptions
);
8160 nsGlobalWindow::CloseWindow(nsISupports
*aWindow
)
8162 nsCOMPtr
<nsPIDOMWindow
> win(do_QueryInterface(aWindow
));
8164 nsGlobalWindow
* globalWin
=
8165 static_cast<nsGlobalWindow
*>
8166 (static_cast<nsPIDOMWindow
*>(win
));
8168 // Need to post an event for closing, otherwise window and
8169 // presshell etc. may get destroyed while creating frames, bug 338897.
8170 nsCloseEvent::PostCloseEvent(globalWin
);
8171 // else if OOM, better not to close. That might cause a crash.
8176 nsGlobalWindow::ClearWindowScope(nsISupports
*aWindow
)
8178 nsCOMPtr
<nsIScriptGlobalObject
> sgo(do_QueryInterface(aWindow
));
8179 nsIScriptContext
*scx
= sgo
->GetContext();
8181 scx
->ClearScope(sgo
->GetGlobalJSObject(), PR_TRUE
);
8185 //*****************************************************************************
8186 // nsGlobalWindow: Timeout Functions
8187 //*****************************************************************************
8189 PRUint32 sNestingLevel
;
8192 nsGlobalWindow::SetTimeoutOrInterval(nsIScriptTimeoutHandler
*aHandler
,
8194 PRBool aIsInterval
, PRInt32
*aReturn
)
8196 FORWARD_TO_INNER(SetTimeoutOrInterval
, (aHandler
, interval
, aIsInterval
, aReturn
),
8197 NS_ERROR_NOT_INITIALIZED
);
8199 // If we don't have a document (we could have been unloaded since
8200 // the call to setTimeout was made), do nothing.
8205 PRUint32 nestingLevel
= sNestingLevel
+ 1;
8206 if (interval
< DOM_MIN_TIMEOUT_VALUE
) {
8207 if (aIsInterval
|| nestingLevel
>= DOM_CLAMP_TIMEOUT_NESTING_LEVEL
) {
8208 // Don't allow timeouts less than DOM_MIN_TIMEOUT_VALUE from
8211 interval
= DOM_MIN_TIMEOUT_VALUE
;
8213 else if (interval
< 0) {
8214 // Clamp negative intervals to 0.
8220 NS_ASSERTION(interval
>= 0, "DOM_MIN_TIMEOUT_VALUE lies");
8221 PRUint32 realInterval
= interval
;
8223 // Make sure we don't proceed with a interval larger than our timer
8225 if (realInterval
> PR_IntervalToMilliseconds(DOM_MAX_TIMEOUT_VALUE
)) {
8226 realInterval
= PR_IntervalToMilliseconds(DOM_MAX_TIMEOUT_VALUE
);
8229 nsTimeout
*timeout
= new nsTimeout();
8231 return NS_ERROR_OUT_OF_MEMORY
;
8233 // Increment the timeout's reference count to represent this function's hold
8238 timeout
->mInterval
= realInterval
;
8240 timeout
->mScriptHandler
= aHandler
;
8242 // Get principal of currently executing code, save for execution of timeout.
8243 // If our principals subsume the subject principal then use the subject
8244 // principal. Otherwise, use our principal to avoid running script in
8245 // elevated principals.
8247 nsCOMPtr
<nsIPrincipal
> subjectPrincipal
;
8249 rv
= nsContentUtils::GetSecurityManager()->
8250 GetSubjectPrincipal(getter_AddRefs(subjectPrincipal
));
8251 if (NS_FAILED(rv
)) {
8254 return NS_ERROR_FAILURE
;
8257 PRBool subsumes
= PR_FALSE
;
8258 nsCOMPtr
<nsIPrincipal
> ourPrincipal
= GetPrincipal();
8260 // Note the direction of this test: We don't allow setTimeouts running with
8261 // chrome privileges on content windows, but we do allow setTimeouts running
8262 // with content privileges on chrome windows (where they can't do very much,
8264 rv
= ourPrincipal
->Subsumes(subjectPrincipal
, &subsumes
);
8265 if (NS_FAILED(rv
)) {
8268 return NS_ERROR_FAILURE
;
8272 timeout
->mPrincipal
= subjectPrincipal
;
8274 timeout
->mPrincipal
= ourPrincipal
;
8277 TimeDuration delta
= TimeDuration::FromMilliseconds(realInterval
);
8279 if (!IsFrozen() && !mTimeoutsSuspendDepth
) {
8280 // If we're not currently frozen, then we set timeout->mWhen to be the
8281 // actual firing time of the timer (i.e., now + delta). We also actually
8282 // create a timer and fire it off.
8284 timeout
->mWhen
= TimeStamp::Now() + delta
;
8286 timeout
->mTimer
= do_CreateInstance("@mozilla.org/timer;1", &rv
);
8287 if (NS_FAILED(rv
)) {
8293 rv
= timeout
->mTimer
->InitWithFuncCallback(TimerCallback
, timeout
,
8295 nsITimer::TYPE_ONE_SHOT
);
8296 if (NS_FAILED(rv
)) {
8302 // The timeout is now also held in the timer's closure.
8305 // If we are frozen, however, then we instead simply set
8306 // timeout->mTimeRemaining to be the "time remaining" in the timeout (i.e.,
8307 // the interval itself). We don't create a timer for it, since that will
8308 // happen when we are thawed and the timeout will then get a timer and run
8311 timeout
->mTimeRemaining
= delta
;
8314 timeout
->mWindow
= this;
8317 timeout
->mNestingLevel
= nestingLevel
;
8320 // No popups from timeouts by default
8321 timeout
->mPopupState
= openAbused
;
8323 if (gRunningTimeoutDepth
== 0 && gPopupControlState
< openAbused
) {
8324 // This timeout is *not* set from another timeout and it's set
8325 // while popups are enabled. Propagate the state to the timeout if
8326 // its delay (interval) is equal to or less than what
8327 // "dom.disable_open_click_delay" is set to (in ms).
8330 nsContentUtils::GetIntPref("dom.disable_open_click_delay");
8332 if (interval
<= delay
) {
8333 timeout
->mPopupState
= gPopupControlState
;
8337 InsertTimeoutIntoList(timeout
);
8339 timeout
->mPublicId
= ++mTimeoutPublicIdCounter
;
8340 *aReturn
= timeout
->mPublicId
;
8342 // Our hold on the timeout is expiring. Note that this should not actually
8343 // free the timeout (since the list should have taken ownership as well).
8351 nsGlobalWindow::SetTimeoutOrInterval(PRBool aIsInterval
, PRInt32
*aReturn
)
8353 // This needs to forward to the inner window, but since the current
8354 // inner may not be the inner in the calling scope, we need to treat
8355 // this specially here as we don't want timeouts registered in a
8356 // dying inner window to get registered and run on the current inner
8357 // window. To get this right, we need to forward this call to the
8358 // inner window that's calling window.setTimeout().
8360 if (IsOuterWindow()) {
8361 nsGlobalWindow
* callerInner
= CallerInnerWindow();
8362 NS_ENSURE_TRUE(callerInner
, NS_ERROR_NOT_AVAILABLE
);
8364 // If the caller and the callee share the same outer window,
8365 // forward to the callee inner. Else, we forward to the current
8366 // inner (e.g. someone is calling setTimeout() on a reference to
8367 // some other window).
8369 if (callerInner
->GetOuterWindow() == this &&
8370 callerInner
->IsInnerWindow()) {
8371 return callerInner
->SetTimeoutOrInterval(aIsInterval
, aReturn
);
8374 FORWARD_TO_INNER(SetTimeoutOrInterval
, (aIsInterval
, aReturn
),
8375 NS_ERROR_NOT_INITIALIZED
);
8378 PRInt32 interval
= 0;
8379 PRBool isInterval
= aIsInterval
;
8380 nsCOMPtr
<nsIScriptTimeoutHandler
> handler
;
8381 nsresult rv
= NS_CreateJSTimeoutHandler(this,
8384 getter_AddRefs(handler
));
8386 return (rv
== NS_ERROR_DOM_TYPE_ERR
) ? NS_OK
: rv
;
8388 return SetTimeoutOrInterval(handler
, interval
, isInterval
, aReturn
);
8393 nsGlobalWindow::RunTimeout(nsTimeout
*aTimeout
)
8395 // If a modal dialog is open for this window, return early. Pending
8396 // timeouts will run when the modal dialog is dismissed.
8397 if (IsInModalState() || mTimeoutsSuspendDepth
) {
8403 NS_ASSERTION(IsInnerWindow(), "Timeout running on outer window!");
8404 NS_ASSERTION(!IsFrozen(), "Timeout running on a window in the bfcache!");
8406 nsTimeout
*nextTimeout
, *timeout
;
8407 nsTimeout
*last_expired_timeout
, *last_insertion_point
;
8408 nsTimeout dummy_timeout
;
8409 PRUint32 firingDepth
= mTimeoutFiringDepth
+ 1;
8411 // Make sure that the window and the script context don't go away as
8412 // a result of running timeouts
8413 nsCOMPtr
<nsIScriptGlobalObject
> windowKungFuDeathGrip(this);
8415 // A native timer has gone off. See which of our timeouts need
8417 TimeStamp now
= TimeStamp::Now();
8420 if (aTimeout
&& aTimeout
->mWhen
> now
) {
8421 // The OS timer fired early (yikes!), and possibly out of order
8422 // too. Set |deadline| to be the time when the OS timer *should*
8423 // have fired so that any timers that *should* have fired before
8424 // aTimeout *will* be fired now. This happens most of the time on
8427 deadline
= aTimeout
->mWhen
;
8432 // The timeout list is kept in deadline order. Discover the latest
8433 // timeout whose deadline has expired. On some platforms, native
8434 // timeout events fire "early", so we need to test the timer as well
8436 last_expired_timeout
= nsnull
;
8437 for (timeout
= FirstTimeout(); IsTimeout(timeout
); timeout
= timeout
->Next()) {
8438 if (((timeout
== aTimeout
) || (timeout
->mWhen
<= deadline
)) &&
8439 (timeout
->mFiringDepth
== 0)) {
8440 // Mark any timeouts that are on the list to be fired with the
8441 // firing depth so that we can reentrantly run timeouts
8442 timeout
->mFiringDepth
= firingDepth
;
8443 last_expired_timeout
= timeout
;
8447 // Maybe the timeout that the event was fired for has been deleted
8448 // and there are no others timeouts with deadlines that make them
8449 // eligible for execution yet. Go away.
8450 if (!last_expired_timeout
) {
8454 // Insert a dummy timeout into the list of timeouts between the
8455 // portion of the list that we are about to process now and those
8456 // timeouts that will be processed in a future call to
8457 // win_run_timeout(). This dummy timeout serves as the head of the
8458 // list for any timeouts inserted as a result of running a timeout.
8459 dummy_timeout
.mFiringDepth
= firingDepth
;
8460 dummy_timeout
.mWhen
= now
;
8461 PR_INSERT_AFTER(&dummy_timeout
, last_expired_timeout
);
8463 // Don't let ClearWindowTimeouts throw away our stack-allocated
8465 dummy_timeout
.AddRef();
8466 dummy_timeout
.AddRef();
8468 last_insertion_point
= mTimeoutInsertionPoint
;
8469 mTimeoutInsertionPoint
= &dummy_timeout
;
8471 for (timeout
= FirstTimeout();
8472 timeout
!= &dummy_timeout
&& !IsFrozen();
8473 timeout
= nextTimeout
) {
8474 nextTimeout
= timeout
->Next();
8476 if (timeout
->mFiringDepth
!= firingDepth
) {
8477 // We skip the timeout since it's on the list to run at another
8483 if (mTimeoutsSuspendDepth
) {
8484 // Some timer did suspend us. Make sure the
8485 // rest of the timers get executed later.
8486 timeout
->mFiringDepth
= 0;
8490 // The timeout is on the list to run at this depth, go ahead and
8493 // Get the script context (a strong ref to prevent it going away)
8494 // for this timeout and ensure the script language is enabled.
8495 nsCOMPtr
<nsIScriptContext
> scx
= GetScriptContextInternal(
8496 timeout
->mScriptHandler
->GetScriptTypeID());
8499 // No context means this window was closed or never properly
8500 // initialized for this language.
8504 // The "scripts disabled" concept is still a little vague wrt
8505 // multiple languages. Prepare for the day when languages can be
8506 // disabled independently of the other languages...
8507 if (!scx
->GetScriptsEnabled()) {
8508 // Scripts were enabled once in this window (unless aTimeout ==
8509 // nsnull) but now scripts are disabled (we might be in
8510 // print-preview, for instance), this means we shouldn't run any
8511 // timeouts at this point.
8513 // If scripts are enabled for this language in this window again
8514 // we'll fire the timeouts that are due at that point.
8518 // This timeout is good to run
8519 nsTimeout
*last_running_timeout
= mRunningTimeout
;
8520 mRunningTimeout
= timeout
;
8521 timeout
->mRunning
= PR_TRUE
;
8523 // Push this timeout's popup control state, which should only be
8524 // eabled the first time a timeout fires that was created while
8525 // popups were enabled and with a delay less than
8526 // "dom.disable_open_click_delay".
8527 nsAutoPopupStatePusher
popupStatePusher(timeout
->mPopupState
);
8529 // Clear the timeout's popup state, if any, to prevent interval
8530 // timeouts from repeatedly opening poups.
8531 timeout
->mPopupState
= openAbused
;
8533 // Hold on to the timeout in case mExpr or mFunObj releases its
8537 ++gRunningTimeoutDepth
;
8538 ++mTimeoutFiringDepth
;
8540 PRBool trackNestingLevel
= !timeout
->mInterval
;
8541 PRUint32 nestingLevel
;
8542 if (trackNestingLevel
) {
8543 nestingLevel
= sNestingLevel
;
8544 sNestingLevel
= timeout
->mNestingLevel
;
8547 nsCOMPtr
<nsIScriptTimeoutHandler
> handler(timeout
->mScriptHandler
);
8548 void *scriptObject
= handler
->GetScriptObject();
8549 if (!scriptObject
) {
8550 // Evaluate the timeout expression.
8551 const PRUnichar
*script
= handler
->GetHandlerText();
8552 NS_ASSERTION(script
, "timeout has no script nor handler text!");
8554 const char *filename
= nsnull
;
8555 PRUint32 lineNo
= 0;
8556 handler
->GetLocation(&filename
, &lineNo
);
8558 NS_TIME_FUNCTION_MARK("(file: %s, line: %d)", filename
, lineNo
);
8560 PRBool is_undefined
;
8561 scx
->EvaluateString(nsDependentString(script
),
8562 GetScriptGlobal(handler
->GetScriptTypeID()),
8563 timeout
->mPrincipal
, filename
, lineNo
,
8564 handler
->GetScriptVersion(), nsnull
,
8567 // Let the script handler know about the "secret" final argument that
8568 // indicates timeout lateness in milliseconds
8569 TimeDuration lateness
= now
- timeout
->mWhen
;
8571 handler
->SetLateness(lateness
.ToMilliseconds());
8573 nsCOMPtr
<nsIVariant
> dummy
;
8574 nsCOMPtr
<nsISupports
> me(static_cast<nsIDOMWindow
*>(this));
8575 scx
->CallEventHandler(me
,
8576 GetScriptGlobal(handler
->GetScriptTypeID()),
8577 scriptObject
, handler
->GetArgv(),
8578 // XXXmarkh - consider allowing CallEventHandler to
8580 getter_AddRefs(dummy
));
8583 handler
= nsnull
; // drop reference before dropping timeout refs.
8585 if (trackNestingLevel
) {
8586 sNestingLevel
= nestingLevel
;
8589 --mTimeoutFiringDepth
;
8590 --gRunningTimeoutDepth
;
8592 mRunningTimeout
= last_running_timeout
;
8593 timeout
->mRunning
= PR_FALSE
;
8595 // We ignore any failures from calling EvaluateString() or
8596 // CallEventHandler() on the context here since we're in a loop
8597 // where we're likely to be running timeouts whose OS timers
8598 // didn't fire in time and we don't want to not fire those timers
8599 // now just because execution of one timer failed. We can't
8600 // propagate the error to anyone who cares about it from this
8601 // point anyway, and the script context should have already reported
8602 // the script error in the usual way - so we just drop it.
8604 // If all timeouts were cleared and |timeout != aTimeout| then
8605 // |timeout| may be the last reference to the timeout so check if
8606 // it was cleared before releasing it.
8607 PRBool timeout_was_cleared
= timeout
->mCleared
;
8611 if (timeout_was_cleared
) {
8612 // The running timeout's window was cleared, this means that
8613 // ClearAllTimeouts() was called from a *nested* call, possibly
8614 // through a timeout that fired while a modal (to this window)
8615 // dialog was open or through other non-obvious paths.
8617 mTimeoutInsertionPoint
= last_insertion_point
;
8622 PRBool isInterval
= PR_FALSE
;
8624 // If we have a regular interval timer, we re-schedule the
8625 // timeout, accounting for clock drift.
8626 if (timeout
->mInterval
) {
8627 // Compute time to next timeout for interval timer.
8628 // Make sure nextInterval is at least DOM_MIN_TIMEOUT_VALUE.
8629 TimeDuration nextInterval
=
8630 TimeDuration::FromMilliseconds(NS_MAX(timeout
->mInterval
,
8631 PRUint32(DOM_MIN_TIMEOUT_VALUE
)));
8633 // If we're running pending timeouts because they've been temporarily
8634 // disabled (!aTimeout), set the next interval to be relative to "now",
8635 // and not to when the timeout that was pending should have fired. Also
8636 // check if the next interval timeout is overdue. If so, then restart
8637 // the interval from now.
8638 TimeStamp firingTime
;
8639 if (!aTimeout
|| timeout
->mWhen
+ nextInterval
<= now
)
8640 firingTime
= now
+ nextInterval
;
8642 firingTime
= timeout
->mWhen
+ nextInterval
;
8644 TimeDuration delay
= firingTime
- TimeStamp::Now();
8646 // And make sure delay is nonnegative; that might happen if the timer
8647 // thread is firing our timers somewhat early.
8648 if (delay
< TimeDuration(0)) {
8649 delay
= TimeDuration(0);
8652 if (timeout
->mTimer
) {
8653 timeout
->mWhen
= firingTime
;
8655 // Reschedule the OS timer. Don't bother returning any error
8656 // codes if this fails since the callers of this method
8657 // doesn't care about them nobody who cares about them
8660 // Make sure to cast the unsigned PR_USEC_PER_MSEC to signed
8661 // PRTime to make the division do the right thing on 64-bit
8662 // platforms whether delay is positive or negative (which we
8663 // know is always positive here, but cast anyways for
8665 nsresult rv
= timeout
->mTimer
->
8666 InitWithFuncCallback(TimerCallback
, timeout
,
8667 delay
.ToMilliseconds(),
8668 nsITimer::TYPE_ONE_SHOT
);
8670 if (NS_FAILED(rv
)) {
8671 NS_ERROR("Error initializing timer for DOM timeout!");
8673 // We failed to initialize the new OS timer, this timer does
8674 // us no good here so we just cancel it (just in case) and
8675 // null out the pointer to the OS timer, this will release the
8676 // OS timer. As we continue executing the code below we'll end
8677 // up deleting the timeout since it's not an interval timeout
8678 // any more (since timeout->mTimer == nsnull).
8679 timeout
->mTimer
->Cancel();
8680 timeout
->mTimer
= nsnull
;
8682 // Now that the OS timer no longer has a reference to the
8683 // timeout we need to drop that reference.
8687 NS_ASSERTION(IsFrozen() || mTimeoutsSuspendDepth
,
8688 "How'd our timer end up null if we're not frozen or "
8691 timeout
->mTimeRemaining
= delay
;
8692 isInterval
= PR_TRUE
;
8696 if (timeout
->mTimer
) {
8697 if (timeout
->mInterval
) {
8698 isInterval
= PR_TRUE
;
8700 // The timeout still has an OS timer, and it's not an
8701 // interval, that means that the OS timer could still fire (if
8702 // it didn't already, i.e. aTimeout == timeout), cancel the OS
8703 // timer and release its reference to the timeout.
8704 timeout
->mTimer
->Cancel();
8705 timeout
->mTimer
= nsnull
;
8711 // Running a timeout can cause another timeout to be deleted, so
8712 // we need to reset the pointer to the following timeout.
8713 nextTimeout
= timeout
->Next();
8715 PR_REMOVE_LINK(timeout
);
8718 // Reschedule an interval timeout. Insert interval timeout
8719 // onto list sorted in deadline order.
8721 InsertTimeoutIntoList(timeout
);
8724 // Release the timeout struct since it's possibly out of the list
8728 // Take the dummy timeout off the head of the list
8729 PR_REMOVE_LINK(&dummy_timeout
);
8731 mTimeoutInsertionPoint
= last_insertion_point
;
8735 nsTimeout::Release()
8740 // language specific cleanup done as mScriptHandler destructs...
8742 // Kill the timer if it is still alive.
8760 nsGlobalWindow::ClearTimeoutOrInterval(PRInt32 aTimerID
)
8762 FORWARD_TO_INNER(ClearTimeoutOrInterval
, (aTimerID
), NS_ERROR_NOT_INITIALIZED
);
8764 PRUint32 public_id
= (PRUint32
)aTimerID
;
8767 for (timeout
= FirstTimeout();
8769 timeout
= timeout
->Next()) {
8770 if (timeout
->mPublicId
== public_id
) {
8771 if (timeout
->mRunning
) {
8772 /* We're running from inside the timeout. Mark this
8773 timeout for deferred deletion by the code in
8775 timeout
->mInterval
= 0;
8778 /* Delete the timeout from the pending timeout list */
8779 PR_REMOVE_LINK(timeout
);
8781 if (timeout
->mTimer
) {
8782 timeout
->mTimer
->Cancel();
8783 timeout
->mTimer
= nsnull
;
8795 // A JavaScript specific version.
8797 nsGlobalWindow::ClearTimeoutOrInterval()
8799 FORWARD_TO_INNER(ClearTimeoutOrInterval
, (), NS_ERROR_NOT_INITIALIZED
);
8801 nsresult rv
= NS_OK
;
8802 nsAXPCNativeCallContext
*ncc
= nsnull
;
8804 rv
= nsContentUtils::XPConnect()->
8805 GetCurrentNativeCallContext(&ncc
);
8806 NS_ENSURE_SUCCESS(rv
, rv
);
8809 return NS_ERROR_NOT_AVAILABLE
;
8811 JSContext
*cx
= nsnull
;
8813 rv
= ncc
->GetJSContext(&cx
);
8814 NS_ENSURE_SUCCESS(rv
, rv
);
8818 ncc
->GetArgc(&argc
);
8821 // No arguments, return early.
8826 jsval
*argv
= nsnull
;
8828 ncc
->GetArgvPtr(&argv
);
8832 JSAutoRequest
ar(cx
);
8834 // XXXjst: Can we deal with this w/o using GetCurrentNativeCallContext()
8835 if (argv
[0] == JSVAL_VOID
|| !::JS_ValueToInt32(cx
, argv
[0], &timer_id
) ||
8837 // Undefined or non-positive number passed as argument, return
8838 // early. Make sure that JS_ValueToInt32 didn't set an exception.
8840 ::JS_ClearPendingException(cx
);
8844 return ClearTimeoutOrInterval(timer_id
);
8848 nsGlobalWindow::ClearAllTimeouts()
8850 nsTimeout
*timeout
, *nextTimeout
;
8852 for (timeout
= FirstTimeout(); IsTimeout(timeout
); timeout
= nextTimeout
) {
8853 /* If RunTimeout() is higher up on the stack for this
8854 window, e.g. as a result of document.write from a timeout,
8855 then we need to reset the list insertion point for
8856 newly-created timeouts in case the user adds a timeout,
8857 before we pop the stack back to RunTimeout. */
8858 if (mRunningTimeout
== timeout
)
8859 mTimeoutInsertionPoint
= nsnull
;
8861 nextTimeout
= timeout
->Next();
8863 if (timeout
->mTimer
) {
8864 timeout
->mTimer
->Cancel();
8865 timeout
->mTimer
= nsnull
;
8867 // Drop the count since the timer isn't going to hold on
8872 // Set timeout->mCleared to true to indicate that the timeout was
8873 // cleared and taken out of the list of timeouts
8874 timeout
->mCleared
= PR_TRUE
;
8876 // Drop the count since we're removing it from the list.
8880 // Clear out our list
8881 PR_INIT_CLIST(&mTimeouts
);
8885 nsGlobalWindow::InsertTimeoutIntoList(nsTimeout
*aTimeout
)
8887 NS_ASSERTION(IsInnerWindow(),
8888 "InsertTimeoutIntoList() called on outer window!");
8890 // Start at mLastTimeout and go backwards. Don't go further than
8891 // mTimeoutInsertionPoint, though. This optimizes for the common case of
8892 // insertion at the end.
8893 nsTimeout
* prevSibling
;
8894 for (prevSibling
= LastTimeout();
8895 IsTimeout(prevSibling
) && prevSibling
!= mTimeoutInsertionPoint
&&
8896 // This condition needs to match the one in SetTimeoutOrInterval that
8897 // determines whether to set mWhen or mTimeRemaining.
8898 ((IsFrozen() || mTimeoutsSuspendDepth
) ?
8899 prevSibling
->mTimeRemaining
> aTimeout
->mTimeRemaining
:
8900 prevSibling
->mWhen
> aTimeout
->mWhen
);
8901 prevSibling
= prevSibling
->Prev()) {
8902 /* Do nothing; just searching */
8905 // Now link in aTimeout after prevSibling.
8906 PR_INSERT_AFTER(aTimeout
, prevSibling
);
8908 aTimeout
->mFiringDepth
= 0;
8910 // Increment the timeout's reference count since it's now held on to
8917 nsGlobalWindow::TimerCallback(nsITimer
*aTimer
, void *aClosure
)
8919 nsTimeout
*timeout
= (nsTimeout
*)aClosure
;
8921 // Hold on to the timeout to ensure it doesn't go away while it's
8922 // being handled (aka kungFuDeathGrip).
8925 timeout
->mWindow
->RunTimeout(timeout
);
8927 // Drop our reference to the timeout now that we're done with it.
8931 //*****************************************************************************
8932 // nsGlobalWindow: Helper Functions
8933 //*****************************************************************************
8936 nsGlobalWindow::GetTreeOwner(nsIDocShellTreeOwner
**aTreeOwner
)
8938 FORWARD_TO_OUTER(GetTreeOwner
, (aTreeOwner
), NS_ERROR_NOT_INITIALIZED
);
8940 nsCOMPtr
<nsIDocShellTreeItem
> docShellAsItem(do_QueryInterface(mDocShell
));
8942 // If there's no docShellAsItem, this window must have been closed,
8943 // in that case there is no tree owner.
8945 if (!docShellAsItem
) {
8946 *aTreeOwner
= nsnull
;
8951 return docShellAsItem
->GetTreeOwner(aTreeOwner
);
8955 nsGlobalWindow::GetTreeOwner(nsIBaseWindow
**aTreeOwner
)
8957 FORWARD_TO_OUTER(GetTreeOwner
, (aTreeOwner
), NS_ERROR_NOT_INITIALIZED
);
8959 nsCOMPtr
<nsIDocShellTreeItem
> docShellAsItem(do_QueryInterface(mDocShell
));
8960 nsCOMPtr
<nsIDocShellTreeOwner
> treeOwner
;
8962 // If there's no docShellAsItem, this window must have been closed,
8963 // in that case there is no tree owner.
8965 if (docShellAsItem
) {
8966 docShellAsItem
->GetTreeOwner(getter_AddRefs(treeOwner
));
8970 *aTreeOwner
= nsnull
;
8974 return CallQueryInterface(treeOwner
, aTreeOwner
);
8978 nsGlobalWindow::GetWebBrowserChrome(nsIWebBrowserChrome
**aBrowserChrome
)
8980 nsCOMPtr
<nsIDocShellTreeOwner
> treeOwner
;
8981 GetTreeOwner(getter_AddRefs(treeOwner
));
8983 nsCOMPtr
<nsIWebBrowserChrome
> browserChrome(do_GetInterface(treeOwner
));
8984 NS_IF_ADDREF(*aBrowserChrome
= browserChrome
);
8989 nsIScrollableFrame
*
8990 nsGlobalWindow::GetScrollFrame()
8992 FORWARD_TO_OUTER(GetScrollFrame
, (), nsnull
);
8998 nsCOMPtr
<nsIPresShell
> presShell
;
8999 mDocShell
->GetPresShell(getter_AddRefs(presShell
));
9001 return presShell
->GetRootScrollFrameAsScrollable();
9007 nsGlobalWindow::BuildURIfromBase(const char *aURL
, nsIURI
**aBuiltURI
,
9008 PRBool
*aFreeSecurityPass
,
9009 JSContext
**aCXused
)
9011 nsIScriptContext
*scx
= GetContextInternal();
9012 JSContext
*cx
= nsnull
;
9014 *aBuiltURI
= nsnull
;
9015 *aFreeSecurityPass
= PR_FALSE
;
9020 NS_ASSERTION(scx
, "opening window missing its context");
9021 NS_ASSERTION(mDocument
, "opening window missing its document");
9022 if (!scx
|| !mDocument
)
9023 return NS_ERROR_FAILURE
;
9025 nsCOMPtr
<nsIDOMChromeWindow
> chrome_win
=
9026 do_QueryInterface(static_cast<nsIDOMWindow
*>(this));
9028 if (nsContentUtils::IsCallerChrome() && !chrome_win
) {
9029 // If open() is called from chrome on a non-chrome window, we'll
9030 // use the context from the window on which open() is being called
9031 // to prevent giving chrome priveleges to new windows opened in
9032 // such a way. This also makes us get the appropriate base URI for
9033 // the below URI resolution code.
9035 cx
= (JSContext
*)scx
->GetNativeContext();
9037 // get the JSContext from the call stack
9038 nsCOMPtr
<nsIThreadJSContextStack
> stack(do_GetService(sJSStackContractID
));
9043 /* resolve the URI, which could be relative to the calling window
9044 (note the algorithm to get the base URI should match the one
9045 used to actually kick off the load in nsWindowWatcher.cpp). */
9046 nsCAutoString
charset(NS_LITERAL_CSTRING("UTF-8")); // default to utf-8
9047 nsIURI
* baseURI
= nsnull
;
9048 nsCOMPtr
<nsIURI
> uriToLoad
;
9049 nsCOMPtr
<nsIDOMWindow
> sourceWindow
;
9052 nsIScriptContext
*scriptcx
= nsJSUtils::GetDynamicScriptContext(cx
);
9054 sourceWindow
= do_QueryInterface(scriptcx
->GetGlobalObject());
9057 if (!sourceWindow
) {
9058 sourceWindow
= do_QueryInterface(NS_ISUPPORTS_CAST(nsIDOMWindow
*, this));
9059 *aFreeSecurityPass
= PR_TRUE
;
9063 nsCOMPtr
<nsIDOMDocument
> domDoc
;
9064 sourceWindow
->GetDocument(getter_AddRefs(domDoc
));
9065 nsCOMPtr
<nsIDocument
> doc(do_QueryInterface(domDoc
));
9067 baseURI
= doc
->GetDocBaseURI();
9068 charset
= doc
->GetDocumentCharacterSet();
9074 return NS_NewURI(aBuiltURI
, nsDependentCString(aURL
), charset
.get(), baseURI
);
9078 nsGlobalWindow::SecurityCheckURL(const char *aURL
)
9082 nsCOMPtr
<nsIURI
> uri
;
9084 if (NS_FAILED(BuildURIfromBase(aURL
, getter_AddRefs(uri
), &freePass
, &cx
)))
9085 return NS_ERROR_FAILURE
;
9087 if (!freePass
&& NS_FAILED(nsContentUtils::GetSecurityManager()->
9088 CheckLoadURIFromScript(cx
, uri
)))
9089 return NS_ERROR_FAILURE
;
9095 nsGlobalWindow::FlushPendingNotifications(mozFlushType aType
)
9098 mDoc
->FlushPendingNotifications(aType
);
9103 nsGlobalWindow::EnsureSizeUpToDate()
9105 // If we're a subframe, make sure our size is up to date. It's OK that this
9106 // crosses the content/chrome boundary, since chrome can have pending reflows
9108 nsGlobalWindow
*parent
=
9109 static_cast<nsGlobalWindow
*>(GetPrivateParent());
9111 parent
->FlushPendingNotifications(Flush_Layout
);
9116 nsGlobalWindow::SaveWindowState(nsISupports
**aState
)
9118 NS_PRECONDITION(IsOuterWindow(), "Can't save the inner window's state");
9122 if (!mContext
|| !mJSObject
) {
9123 // The window may be getting torn down; don't bother saving state.
9127 nsGlobalWindow
*inner
= GetCurrentInnerWindowInternal();
9128 NS_ASSERTION(inner
, "No inner window to save");
9130 // Don't do anything else to this inner window! After this point, all
9131 // calls to SetTimeoutOrInterval will create entries in the timeout
9132 // list that will only run after this window has come out of the bfcache.
9133 // Also, while we're frozen, we won't dispatch online/offline events
9137 // Remember the outer window's prototype.
9138 JSContext
*cx
= (JSContext
*)mContext
->GetNativeContext();
9139 JSAutoRequest
req(cx
);
9141 nsIXPConnect
*xpc
= nsContentUtils::XPConnect();
9143 nsCOMPtr
<nsIClassInfo
> ci
=
9144 do_QueryInterface((nsIScriptGlobalObject
*)this);
9145 nsCOMPtr
<nsIXPConnectJSObjectHolder
> proto
;
9146 nsresult rv
= xpc
->GetWrappedNativePrototype(cx
, mJSObject
, ci
,
9147 getter_AddRefs(proto
));
9148 NS_ENSURE_SUCCESS(rv
, rv
);
9150 JSObject
*realProto
= JS_GetPrototype(cx
, mJSObject
);
9151 nsCOMPtr
<nsIXPConnectJSObjectHolder
> realProtoHolder
;
9153 rv
= xpc
->HoldObject(cx
, realProto
, getter_AddRefs(realProtoHolder
));
9154 NS_ENSURE_SUCCESS(rv
, rv
);
9157 nsCOMPtr
<nsISupports
> state
= new WindowStateHolder(inner
,
9162 NS_ENSURE_TRUE(state
, NS_ERROR_OUT_OF_MEMORY
);
9165 proto
->GetJSObject(&wnProto
);
9166 if (!JS_SetPrototype(cx
, mJSObject
, wnProto
)) {
9167 return NS_ERROR_FAILURE
;
9170 #ifdef DEBUG_PAGE_CACHE
9171 printf("saving window state, state = %p\n", (void*)state
);
9174 state
.swap(*aState
);
9179 nsGlobalWindow::RestoreWindowState(nsISupports
*aState
)
9181 NS_ASSERTION(IsOuterWindow(), "Cannot restore an inner window");
9183 if (!mContext
|| !mJSObject
) {
9184 // The window may be getting torn down; don't bother restoring state.
9188 nsCOMPtr
<WindowStateHolder
> holder
= do_QueryInterface(aState
);
9189 NS_ENSURE_TRUE(holder
, NS_ERROR_FAILURE
);
9191 #ifdef DEBUG_PAGE_CACHE
9192 printf("restoring window state, state = %p\n", (void*)holder
);
9195 // And we're ready to go!
9196 nsGlobalWindow
*inner
= GetCurrentInnerWindowInternal();
9198 // if a link is focused, refocus with the FLAG_SHOWRING flag set. This makes
9199 // it easy to tell which link was last clicked when going back a page.
9200 nsIContent
* focusedNode
= inner
->GetFocusedNode();
9201 if (IsLink(focusedNode
)) {
9202 nsIFocusManager
* fm
= nsFocusManager::GetFocusManager();
9204 nsCOMPtr
<nsIDOMElement
> focusedElement(do_QueryInterface(focusedNode
));
9205 fm
->SetFocus(focusedElement
, nsIFocusManager::FLAG_NOSCROLL
|
9206 nsIFocusManager::FLAG_SHOWRING
);
9212 holder
->DidRestoreWindow();
9218 nsGlobalWindow::SuspendTimeouts(PRUint32 aIncrease
,
9219 PRBool aFreezeChildren
)
9221 FORWARD_TO_INNER_VOID(SuspendTimeouts
, (aIncrease
, aFreezeChildren
));
9223 PRBool suspended
= (mTimeoutsSuspendDepth
!= 0);
9224 mTimeoutsSuspendDepth
+= aIncrease
;
9227 nsDOMThreadService
* dts
= nsDOMThreadService::get();
9229 dts
->SuspendWorkersForGlobal(static_cast<nsIScriptGlobalObject
*>(this));
9232 TimeStamp now
= TimeStamp::Now();
9233 for (nsTimeout
*t
= FirstTimeout(); IsTimeout(t
); t
= t
->Next()) {
9234 // Set mTimeRemaining to be the time remaining for this timer.
9236 t
->mTimeRemaining
= t
->mWhen
- now
;
9238 t
->mTimeRemaining
= TimeDuration(0);
9240 // Drop the XPCOM timer; we'll reschedule when restoring the state.
9242 t
->mTimer
->Cancel();
9245 // Drop the reference that the timer's closure had on this timeout, we'll
9246 // add it back in ResumeTimeouts. Note that it shouldn't matter that we're
9247 // passing null for the context, since this shouldn't actually release this
9254 // Suspend our children as well.
9255 nsCOMPtr
<nsIDocShellTreeNode
> node(do_QueryInterface(GetDocShell()));
9257 PRInt32 childCount
= 0;
9258 node
->GetChildCount(&childCount
);
9260 for (PRInt32 i
= 0; i
< childCount
; ++i
) {
9261 nsCOMPtr
<nsIDocShellTreeItem
> childShell
;
9262 node
->GetChildAt(i
, getter_AddRefs(childShell
));
9263 NS_ASSERTION(childShell
, "null child shell");
9265 nsCOMPtr
<nsPIDOMWindow
> pWin
= do_GetInterface(childShell
);
9267 nsGlobalWindow
*win
=
9268 static_cast<nsGlobalWindow
*>
9269 (static_cast<nsPIDOMWindow
*>(pWin
));
9270 NS_ASSERTION(win
->IsOuterWindow(), "Expected outer window");
9271 nsGlobalWindow
* inner
= win
->GetCurrentInnerWindowInternal();
9273 // This is a bit hackish. Only freeze/suspend windows which are truly our
9275 nsCOMPtr
<nsIContent
> frame
= do_QueryInterface(pWin
->GetFrameElementInternal());
9276 if (!mDoc
|| !frame
|| mDoc
!= frame
->GetOwnerDoc() || !inner
) {
9280 win
->SuspendTimeouts(aIncrease
, aFreezeChildren
);
9282 if (inner
&& aFreezeChildren
) {
9291 nsGlobalWindow::ResumeTimeouts(PRBool aThawChildren
)
9293 FORWARD_TO_INNER(ResumeTimeouts
, (), NS_ERROR_NOT_INITIALIZED
);
9295 NS_ASSERTION(mTimeoutsSuspendDepth
, "Mismatched calls to ResumeTimeouts!");
9296 --mTimeoutsSuspendDepth
;
9297 PRBool shouldResume
= (mTimeoutsSuspendDepth
== 0);
9301 nsDOMThreadService
* dts
= nsDOMThreadService::get();
9303 dts
->ResumeWorkersForGlobal(static_cast<nsIScriptGlobalObject
*>(this));
9306 // Restore all of the timeouts, using the stored time remaining
9307 // (stored in timeout->mTimeRemaining).
9309 TimeStamp now
= TimeStamp::Now();
9312 PRBool _seenDummyTimeout
= PR_FALSE
;
9315 for (nsTimeout
*t
= FirstTimeout(); IsTimeout(t
); t
= t
->Next()) {
9316 // There's a chance we're being called with RunTimeout on the stack in which
9317 // case we have a dummy timeout in the list that *must not* be resumed. It
9318 // can be identified by a null mWindow.
9321 NS_ASSERTION(!_seenDummyTimeout
, "More than one dummy timeout?!");
9322 _seenDummyTimeout
= PR_TRUE
;
9327 // XXXbz the combination of the way |delay| and |t->mWhen| are set here
9328 // makes no sense. Are we trying to impose that min timeout value or
9331 NS_MAX(PRInt32(t
->mTimeRemaining
.ToMilliseconds()),
9332 DOM_MIN_TIMEOUT_VALUE
);
9334 // Set mWhen back to the time when the timer is supposed to
9336 t
->mWhen
= now
+ t
->mTimeRemaining
;
9338 t
->mTimer
= do_CreateInstance("@mozilla.org/timer;1");
9339 NS_ENSURE_TRUE(t
->mTimer
, NS_ERROR_OUT_OF_MEMORY
);
9341 rv
= t
->mTimer
->InitWithFuncCallback(TimerCallback
, t
, delay
,
9342 nsITimer::TYPE_ONE_SHOT
);
9343 if (NS_FAILED(rv
)) {
9348 // Add a reference for the new timer's closure.
9353 // Resume our children as well.
9354 nsCOMPtr
<nsIDocShellTreeNode
> node
=
9355 do_QueryInterface(GetDocShell());
9357 PRInt32 childCount
= 0;
9358 node
->GetChildCount(&childCount
);
9360 for (PRInt32 i
= 0; i
< childCount
; ++i
) {
9361 nsCOMPtr
<nsIDocShellTreeItem
> childShell
;
9362 node
->GetChildAt(i
, getter_AddRefs(childShell
));
9363 NS_ASSERTION(childShell
, "null child shell");
9365 nsCOMPtr
<nsPIDOMWindow
> pWin
= do_GetInterface(childShell
);
9367 nsGlobalWindow
*win
=
9368 static_cast<nsGlobalWindow
*>
9369 (static_cast<nsPIDOMWindow
*>(pWin
));
9371 NS_ASSERTION(win
->IsOuterWindow(), "Expected outer window");
9372 nsGlobalWindow
* inner
= win
->GetCurrentInnerWindowInternal();
9374 // This is a bit hackish. Only thaw/resume windows which are truly our
9376 nsCOMPtr
<nsIContent
> frame
= do_QueryInterface(pWin
->GetFrameElementInternal());
9377 if (!mDoc
|| !frame
|| mDoc
!= frame
->GetOwnerDoc() || !inner
) {
9381 if (inner
&& aThawChildren
) {
9385 rv
= win
->ResumeTimeouts(aThawChildren
);
9386 NS_ENSURE_SUCCESS(rv
, rv
);
9395 nsGlobalWindow::TimeoutSuspendCount()
9397 FORWARD_TO_INNER(TimeoutSuspendCount
, (), 0);
9398 return mTimeoutsSuspendDepth
;
9402 nsGlobalWindow::GetScriptTypeID(PRUint32
*aScriptType
)
9404 NS_ERROR("No default script type here - ask some element");
9405 return nsIProgrammingLanguage::UNKNOWN
;
9409 nsGlobalWindow::SetScriptTypeID(PRUint32 aScriptType
)
9411 NS_ERROR("Can't change default script type for a document");
9412 return NS_ERROR_NOT_IMPLEMENTED
;
9416 nsGlobalWindow::SetHasOrientationEventListener()
9418 nsCOMPtr
<nsIAccelerometer
> ac
=
9419 do_GetService(NS_ACCELEROMETER_CONTRACTID
);
9422 mHasAcceleration
= PR_TRUE
;
9423 ac
->AddWindowListener(this);
9427 // nsGlobalChromeWindow implementation
9429 NS_IMPL_CYCLE_COLLECTION_CLASS(nsGlobalChromeWindow
)
9430 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsGlobalChromeWindow
,
9432 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mBrowserDOMWindow
)
9433 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mMessageManager
)
9434 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
9436 DOMCI_DATA(ChromeWindow
, nsGlobalChromeWindow
)
9437 DOMCI_DATA(InnerChromeWindow
, nsGlobalChromeWindow
)
9439 // QueryInterface implementation for nsGlobalChromeWindow
9440 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsGlobalChromeWindow
)
9441 NS_INTERFACE_MAP_ENTRY(nsIDOMChromeWindow
)
9442 WINDOW_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(ChromeWindow
)
9443 NS_INTERFACE_MAP_END_INHERITING(nsGlobalWindow
)
9445 NS_IMPL_ADDREF_INHERITED(nsGlobalChromeWindow
, nsGlobalWindow
)
9446 NS_IMPL_RELEASE_INHERITED(nsGlobalChromeWindow
, nsGlobalWindow
)
9449 nsGlobalChromeWindow::GetWindowState(PRUint16
* aWindowState
)
9451 *aWindowState
= nsIDOMChromeWindow::STATE_NORMAL
;
9453 nsCOMPtr
<nsIWidget
> widget
= GetMainWidget();
9458 nsresult rv
= widget
->GetSizeMode(&aMode
);
9459 NS_ENSURE_SUCCESS(rv
, rv
);
9463 case nsSizeMode_Minimized
:
9464 *aWindowState
= nsIDOMChromeWindow::STATE_MINIMIZED
;
9466 case nsSizeMode_Maximized
:
9467 *aWindowState
= nsIDOMChromeWindow::STATE_MAXIMIZED
;
9469 case nsSizeMode_Fullscreen
:
9470 *aWindowState
= nsIDOMChromeWindow::STATE_FULLSCREEN
;
9472 case nsSizeMode_Normal
:
9473 *aWindowState
= nsIDOMChromeWindow::STATE_NORMAL
;
9476 NS_WARNING("Illegal window state for this chrome window");
9484 nsGlobalChromeWindow::Maximize()
9486 nsCOMPtr
<nsIWidget
> widget
= GetMainWidget();
9487 nsresult rv
= NS_OK
;
9490 rv
= widget
->SetSizeMode(nsSizeMode_Maximized
);
9497 nsGlobalChromeWindow::Minimize()
9499 nsCOMPtr
<nsIWidget
> widget
= GetMainWidget();
9500 nsresult rv
= NS_OK
;
9503 rv
= widget
->SetSizeMode(nsSizeMode_Minimized
);
9509 nsGlobalChromeWindow::Restore()
9511 nsCOMPtr
<nsIWidget
> widget
= GetMainWidget();
9512 nsresult rv
= NS_OK
;
9515 rv
= widget
->SetSizeMode(nsSizeMode_Normal
);
9522 nsGlobalChromeWindow::GetAttention()
9524 return GetAttentionWithCycleCount(-1);
9528 nsGlobalChromeWindow::GetAttentionWithCycleCount(PRInt32 aCycleCount
)
9530 nsCOMPtr
<nsIWidget
> widget
= GetMainWidget();
9531 nsresult rv
= NS_OK
;
9534 rv
= widget
->GetAttention(aCycleCount
);
9541 nsGlobalChromeWindow::BeginWindowMove(nsIDOMEvent
*aMouseDownEvent
)
9543 nsCOMPtr
<nsIWidget
> widget
= GetMainWidget();
9548 nsCOMPtr
<nsIPrivateDOMEvent
> privEvent
= do_QueryInterface(aMouseDownEvent
);
9549 NS_ENSURE_TRUE(privEvent
, NS_ERROR_FAILURE
);
9550 nsEvent
*internalEvent
= privEvent
->GetInternalNSEvent();
9551 NS_ENSURE_TRUE(internalEvent
&&
9552 internalEvent
->eventStructType
== NS_MOUSE_EVENT
,
9554 nsMouseEvent
*mouseEvent
= static_cast<nsMouseEvent
*>(internalEvent
);
9556 return widget
->BeginMoveDrag(mouseEvent
);
9559 //Note: This call will lock the cursor, it will not change as it moves.
9560 //To unlock, the cursor must be set back to CURSOR_AUTO.
9562 nsGlobalChromeWindow::SetCursor(const nsAString
& aCursor
)
9564 FORWARD_TO_OUTER_CHROME(SetCursor
, (aCursor
), NS_ERROR_NOT_INITIALIZED
);
9566 nsresult rv
= NS_OK
;
9569 // use C strings to keep the code/data size down
9570 NS_ConvertUTF16toUTF8
cursorString(aCursor
);
9572 if (cursorString
.Equals("auto"))
9573 cursor
= NS_STYLE_CURSOR_AUTO
;
9575 nsCSSKeyword keyword
= nsCSSKeywords::LookupKeyword(aCursor
);
9576 if (eCSSKeyword_UNKNOWN
== keyword
||
9577 !nsCSSProps::FindKeyword(keyword
, nsCSSProps::kCursorKTable
, cursor
)) {
9578 // XXX remove the following three values (leave return NS_OK) after 1.8
9579 // XXX since they should have been -moz- prefixed (covered by FindKeyword).
9580 // XXX (also remove |cursorString| at that point?).
9581 if (cursorString
.Equals("grab"))
9582 cursor
= NS_STYLE_CURSOR_GRAB
;
9583 else if (cursorString
.Equals("grabbing"))
9584 cursor
= NS_STYLE_CURSOR_GRABBING
;
9585 else if (cursorString
.Equals("spinning"))
9586 cursor
= NS_STYLE_CURSOR_SPINNING
;
9592 nsRefPtr
<nsPresContext
> presContext
;
9594 mDocShell
->GetPresContext(getter_AddRefs(presContext
));
9598 // Need root widget.
9599 nsCOMPtr
<nsIPresShell
> presShell
;
9600 mDocShell
->GetPresShell(getter_AddRefs(presShell
));
9601 NS_ENSURE_TRUE(presShell
, NS_ERROR_FAILURE
);
9603 nsIViewManager
* vm
= presShell
->GetViewManager();
9604 NS_ENSURE_TRUE(vm
, NS_ERROR_FAILURE
);
9607 vm
->GetRootView(rootView
);
9608 NS_ENSURE_TRUE(rootView
, NS_ERROR_FAILURE
);
9610 nsIWidget
* widget
= rootView
->GetNearestWidget(nsnull
);
9611 NS_ENSURE_TRUE(widget
, NS_ERROR_FAILURE
);
9613 // Call esm and set cursor.
9614 rv
= presContext
->EventStateManager()->SetCursor(cursor
, nsnull
,
9615 PR_FALSE
, 0.0f
, 0.0f
,
9623 nsGlobalChromeWindow::GetBrowserDOMWindow(nsIBrowserDOMWindow
**aBrowserWindow
)
9625 FORWARD_TO_OUTER_CHROME(GetBrowserDOMWindow
, (aBrowserWindow
),
9626 NS_ERROR_NOT_INITIALIZED
);
9628 NS_ENSURE_ARG_POINTER(aBrowserWindow
);
9630 *aBrowserWindow
= mBrowserDOMWindow
;
9631 NS_IF_ADDREF(*aBrowserWindow
);
9636 nsGlobalChromeWindow::SetBrowserDOMWindow(nsIBrowserDOMWindow
*aBrowserWindow
)
9638 FORWARD_TO_OUTER_CHROME(SetBrowserDOMWindow
, (aBrowserWindow
),
9639 NS_ERROR_NOT_INITIALIZED
);
9641 mBrowserDOMWindow
= aBrowserWindow
;
9646 nsGlobalChromeWindow::NotifyDefaultButtonLoaded(nsIDOMElement
* aDefaultButton
)
9649 NS_ENSURE_ARG(aDefaultButton
);
9651 // Don't snap to a disabled button.
9652 nsCOMPtr
<nsIDOMXULControlElement
> xulControl
=
9653 do_QueryInterface(aDefaultButton
);
9654 NS_ENSURE_TRUE(xulControl
, NS_ERROR_FAILURE
);
9656 nsresult rv
= xulControl
->GetDisabled(&disabled
);
9657 NS_ENSURE_SUCCESS(rv
, rv
);
9661 // Get the button rect in screen coordinates.
9662 nsCOMPtr
<nsIContent
> content(do_QueryInterface(aDefaultButton
));
9663 NS_ENSURE_TRUE(content
, NS_ERROR_FAILURE
);
9664 nsIFrame
*frame
= content
->GetPrimaryFrame();
9665 NS_ENSURE_TRUE(frame
, NS_ERROR_FAILURE
);
9666 nsIntRect buttonRect
= frame
->GetScreenRect();
9668 // Get the widget rect in screen coordinates.
9669 nsIWidget
*widget
= GetNearestWidget();
9670 NS_ENSURE_TRUE(widget
, NS_ERROR_FAILURE
);
9671 nsIntRect widgetRect
;
9672 rv
= widget
->GetScreenBounds(widgetRect
);
9673 NS_ENSURE_SUCCESS(rv
, rv
);
9675 // Convert the buttonRect coordinates from screen to the widget.
9676 buttonRect
-= widgetRect
.TopLeft();
9677 rv
= widget
->OnDefaultButtonLoaded(buttonRect
);
9678 if (rv
== NS_ERROR_NOT_IMPLEMENTED
)
9682 return NS_ERROR_NOT_IMPLEMENTED
;
9687 nsGlobalChromeWindow::GetMessageManager(nsIChromeFrameMessageManager
** aManager
)
9689 FORWARD_TO_INNER_CHROME(GetMessageManager
, (aManager
), NS_ERROR_FAILURE
);
9690 if (!mMessageManager
) {
9691 nsIScriptContext
* scx
= GetContextInternal();
9692 NS_ENSURE_STATE(scx
);
9693 JSContext
* cx
= (JSContext
*)scx
->GetNativeContext();
9694 NS_ENSURE_STATE(cx
);
9695 nsCOMPtr
<nsIChromeFrameMessageManager
> globalMM
=
9696 do_GetService("@mozilla.org/globalmessagemanager;1");
9698 new nsFrameMessageManager(PR_TRUE
,
9703 static_cast<nsFrameMessageManager
*>(globalMM
.get()),
9705 NS_ENSURE_TRUE(mMessageManager
, NS_ERROR_OUT_OF_MEMORY
);
9707 CallQueryInterface(mMessageManager
, aManager
);
9711 // nsGlobalModalWindow implementation
9713 // QueryInterface implementation for nsGlobalModalWindow
9714 NS_IMPL_CYCLE_COLLECTION_CLASS(nsGlobalModalWindow
)
9715 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(nsGlobalModalWindow
,
9717 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mReturnValue
)
9718 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
9720 DOMCI_DATA(ModalContentWindow
, nsGlobalModalWindow
)
9721 DOMCI_DATA(InnerModalContentWindow
, nsGlobalModalWindow
)
9723 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsGlobalModalWindow
)
9724 NS_INTERFACE_MAP_ENTRY(nsIDOMModalContentWindow
)
9725 WINDOW_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(ModalContentWindow
)
9726 NS_INTERFACE_MAP_END_INHERITING(nsGlobalWindow
)
9728 NS_IMPL_ADDREF_INHERITED(nsGlobalModalWindow
, nsGlobalWindow
)
9729 NS_IMPL_RELEASE_INHERITED(nsGlobalModalWindow
, nsGlobalWindow
)
9732 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(nsGlobalModalWindow
,
9734 NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mReturnValue
)
9735 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
9739 nsGlobalModalWindow::GetDialogArguments(nsIArray
**aArguments
)
9741 FORWARD_TO_INNER_MODAL_CONTENT_WINDOW(GetDialogArguments
, (aArguments
),
9742 NS_ERROR_NOT_INITIALIZED
);
9744 PRBool subsumes
= PR_FALSE
;
9745 nsIPrincipal
*self
= GetPrincipal();
9746 if (self
&& NS_SUCCEEDED(self
->Subsumes(mArgumentsOrigin
, &subsumes
)) &&
9748 NS_IF_ADDREF(*aArguments
= mArguments
);
9750 *aArguments
= nsnull
;
9757 nsGlobalModalWindow::GetReturnValue(nsIVariant
**aRetVal
)
9759 FORWARD_TO_OUTER_MODAL_CONTENT_WINDOW(GetReturnValue
, (aRetVal
), NS_OK
);
9761 NS_IF_ADDREF(*aRetVal
= mReturnValue
);
9767 nsGlobalModalWindow::SetReturnValue(nsIVariant
*aRetVal
)
9769 FORWARD_TO_OUTER_MODAL_CONTENT_WINDOW(SetReturnValue
, (aRetVal
), NS_OK
);
9771 mReturnValue
= aRetVal
;
9777 nsGlobalModalWindow::SetNewDocument(nsIDocument
*aDocument
,
9778 nsISupports
*aState
)
9780 // If we're loading a new document into a modal dialog, clear the
9781 // return value that was set, if any, by the current document.
9783 mReturnValue
= nsnull
;
9786 return nsGlobalWindow::SetNewDocument(aDocument
, aState
);
9789 //*****************************************************************************
9790 // nsGlobalWindow: Creator Function (This should go away)
9791 //*****************************************************************************
9794 NS_NewScriptGlobalObject(PRBool aIsChrome
, PRBool aIsModalContentWindow
,
9795 nsIScriptGlobalObject
**aResult
)
9799 nsGlobalWindow
*global
;
9802 global
= new nsGlobalChromeWindow(nsnull
);
9803 } else if (aIsModalContentWindow
) {
9804 global
= new nsGlobalModalWindow(nsnull
);
9806 global
= new nsGlobalWindow(nsnull
);
9809 NS_ENSURE_TRUE(global
, NS_ERROR_OUT_OF_MEMORY
);
9811 NS_ADDREF(*aResult
= global
);
9816 //*****************************************************************************
9817 //*** nsNavigator: Object Management
9818 //*****************************************************************************
9820 nsNavigator::nsNavigator(nsIDocShell
*aDocShell
)
9821 : mDocShell(aDocShell
)
9825 nsNavigator::~nsNavigator()
9828 mMimeTypes
->Invalidate();
9830 mPlugins
->Invalidate();
9833 //*****************************************************************************
9834 // nsNavigator::nsISupports
9835 //*****************************************************************************
9838 DOMCI_DATA(Navigator
, nsNavigator
)
9840 // QueryInterface implementation for nsNavigator
9841 NS_INTERFACE_MAP_BEGIN(nsNavigator
)
9842 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports
, nsIDOMNavigator
)
9843 NS_INTERFACE_MAP_ENTRY(nsIDOMNavigator
)
9844 NS_INTERFACE_MAP_ENTRY(nsIDOMClientInformation
)
9845 NS_INTERFACE_MAP_ENTRY(nsIDOMNavigatorGeolocation
)
9846 NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(Navigator
)
9847 NS_INTERFACE_MAP_END
9850 NS_IMPL_ADDREF(nsNavigator
)
9851 NS_IMPL_RELEASE(nsNavigator
)
9855 nsNavigator::SetDocShell(nsIDocShell
*aDocShell
)
9857 mDocShell
= aDocShell
;
9859 mPlugins
->SetDocShell(aDocShell
);
9861 // if there is a page transition, make sure delete the geolocation object
9864 mGeolocation
->Shutdown();
9865 mGeolocation
= nsnull
;
9869 //*****************************************************************************
9870 // nsNavigator::nsIDOMNavigator
9871 //*****************************************************************************
9874 nsNavigator::GetUserAgent(nsAString
& aUserAgent
)
9877 nsCOMPtr
<nsIHttpProtocolHandler
>
9878 service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX
"http", &rv
));
9879 if (NS_SUCCEEDED(rv
)) {
9881 rv
= service
->GetUserAgent(ua
);
9882 CopyASCIItoUTF16(ua
, aUserAgent
);
9889 nsNavigator::GetAppCodeName(nsAString
& aAppCodeName
)
9892 nsCOMPtr
<nsIHttpProtocolHandler
>
9893 service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX
"http", &rv
));
9894 if (NS_SUCCEEDED(rv
)) {
9895 nsCAutoString appName
;
9896 rv
= service
->GetAppName(appName
);
9897 CopyASCIItoUTF16(appName
, aAppCodeName
);
9904 nsNavigator::GetAppVersion(nsAString
& aAppVersion
)
9906 if (!nsContentUtils::IsCallerTrustedForRead()) {
9907 const nsAdoptingCString
& override
=
9908 nsContentUtils::GetCharPref("general.appversion.override");
9911 CopyUTF8toUTF16(override
, aAppVersion
);
9917 nsCOMPtr
<nsIHttpProtocolHandler
>
9918 service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX
"http", &rv
));
9919 if (NS_SUCCEEDED(rv
)) {
9921 rv
= service
->GetAppVersion(str
);
9922 CopyASCIItoUTF16(str
, aAppVersion
);
9926 aAppVersion
.AppendLiteral(" (");
9928 rv
= service
->GetPlatform(str
);
9932 AppendASCIItoUTF16(str
, aAppVersion
);
9934 aAppVersion
.Append(PRUnichar(')'));
9941 nsNavigator::GetAppName(nsAString
& aAppName
)
9943 if (!nsContentUtils::IsCallerTrustedForRead()) {
9944 const nsAdoptingCString
& override
=
9945 nsContentUtils::GetCharPref("general.appname.override");
9948 CopyUTF8toUTF16(override
, aAppName
);
9953 aAppName
.AssignLiteral("Netscape");
9958 nsNavigator::GetLanguage(nsAString
& aLanguage
)
9961 nsCOMPtr
<nsIHttpProtocolHandler
>
9962 service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX
"http", &rv
));
9963 if (NS_SUCCEEDED(rv
)) {
9965 rv
= service
->GetLanguage(lang
);
9966 CopyASCIItoUTF16(lang
, aLanguage
);
9973 nsNavigator::GetPlatform(nsAString
& aPlatform
)
9975 if (!nsContentUtils::IsCallerTrustedForRead()) {
9976 const nsAdoptingCString
& override
=
9977 nsContentUtils::GetCharPref("general.platform.override");
9980 CopyUTF8toUTF16(override
, aPlatform
);
9986 nsCOMPtr
<nsIHttpProtocolHandler
>
9987 service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX
"http", &rv
));
9988 if (NS_SUCCEEDED(rv
)) {
9989 // sorry for the #if platform ugliness, but Communicator is
9990 // likewise hardcoded and we're seeking backward compatibility
9993 aPlatform
.AssignLiteral("Win64");
9994 #elif defined(WIN32)
9995 aPlatform
.AssignLiteral("Win32");
9996 #elif defined(XP_MACOSX) && defined(__ppc__)
9997 aPlatform
.AssignLiteral("MacPPC");
9998 #elif defined(XP_MACOSX) && defined(__i386__)
9999 aPlatform
.AssignLiteral("MacIntel");
10000 #elif defined(XP_MACOSX) && defined(__x86_64__)
10001 aPlatform
.AssignLiteral("MacIntel");
10002 #elif defined(XP_OS2)
10003 aPlatform
.AssignLiteral("OS/2");
10005 // XXX Communicator uses compiled-in build-time string defines
10006 // to indicate the platform it was compiled *for*, not what it is
10007 // currently running *on* which is what this does.
10008 nsCAutoString plat
;
10009 rv
= service
->GetOscpu(plat
);
10010 CopyASCIItoUTF16(plat
, aPlatform
);
10018 nsNavigator::GetOscpu(nsAString
& aOSCPU
)
10020 if (!nsContentUtils::IsCallerTrustedForRead()) {
10021 const nsAdoptingCString
& override
=
10022 nsContentUtils::GetCharPref("general.oscpu.override");
10025 CopyUTF8toUTF16(override
, aOSCPU
);
10031 nsCOMPtr
<nsIHttpProtocolHandler
>
10032 service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX
"http", &rv
));
10033 if (NS_SUCCEEDED(rv
)) {
10034 nsCAutoString oscpu
;
10035 rv
= service
->GetOscpu(oscpu
);
10036 CopyASCIItoUTF16(oscpu
, aOSCPU
);
10043 nsNavigator::GetVendor(nsAString
& aVendor
)
10046 nsCOMPtr
<nsIHttpProtocolHandler
>
10047 service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX
"http", &rv
));
10048 if (NS_SUCCEEDED(rv
)) {
10049 nsCAutoString vendor
;
10050 rv
= service
->GetVendor(vendor
);
10051 CopyASCIItoUTF16(vendor
, aVendor
);
10059 nsNavigator::GetVendorSub(nsAString
& aVendorSub
)
10062 nsCOMPtr
<nsIHttpProtocolHandler
>
10063 service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX
"http", &rv
));
10064 if (NS_SUCCEEDED(rv
)) {
10065 nsCAutoString vendor
;
10066 rv
= service
->GetVendorSub(vendor
);
10067 CopyASCIItoUTF16(vendor
, aVendorSub
);
10074 nsNavigator::GetProduct(nsAString
& aProduct
)
10077 nsCOMPtr
<nsIHttpProtocolHandler
>
10078 service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX
"http", &rv
));
10079 if (NS_SUCCEEDED(rv
)) {
10080 nsCAutoString product
;
10081 rv
= service
->GetProduct(product
);
10082 CopyASCIItoUTF16(product
, aProduct
);
10089 nsNavigator::GetProductSub(nsAString
& aProductSub
)
10091 if (!nsContentUtils::IsCallerTrustedForRead()) {
10092 const nsAdoptingCString
& override
=
10093 nsContentUtils::GetCharPref("general.productSub.override");
10096 CopyUTF8toUTF16(override
, aProductSub
);
10099 // 'general.useragent.productSub' backwards compatible with 1.8 branch.
10100 const nsAdoptingCString
& override2
=
10101 nsContentUtils::GetCharPref("general.useragent.productSub");
10104 CopyUTF8toUTF16(override2
, aProductSub
);
10111 nsCOMPtr
<nsIHttpProtocolHandler
>
10112 service(do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX
"http", &rv
));
10113 if (NS_SUCCEEDED(rv
)) {
10114 nsCAutoString productSub
;
10115 rv
= service
->GetProductSub(productSub
);
10116 CopyASCIItoUTF16(productSub
, aProductSub
);
10123 nsNavigator::GetSecurityPolicy(nsAString
& aSecurityPolicy
)
10129 nsNavigator::GetMimeTypes(nsIDOMMimeTypeArray
**aMimeTypes
)
10132 mMimeTypes
= new nsMimeTypeArray(this);
10134 return NS_ERROR_OUT_OF_MEMORY
;
10138 NS_ADDREF(*aMimeTypes
= mMimeTypes
);
10144 nsNavigator::GetPlugins(nsIDOMPluginArray
**aPlugins
)
10147 mPlugins
= new nsPluginArray(this, mDocShell
);
10149 return NS_ERROR_OUT_OF_MEMORY
;
10153 NS_ADDREF(*aPlugins
= mPlugins
);
10158 // values for the network.cookie.cookieBehavior pref are documented in
10159 // nsCookieService.cpp.
10160 #define COOKIE_BEHAVIOR_REJECT 2
10163 nsNavigator::GetCookieEnabled(PRBool
*aCookieEnabled
)
10166 (nsContentUtils::GetIntPref("network.cookie.cookieBehavior",
10167 COOKIE_BEHAVIOR_REJECT
) !=
10168 COOKIE_BEHAVIOR_REJECT
);
10174 nsNavigator::GetOnLine(PRBool
* aOnline
)
10176 NS_PRECONDITION(aOnline
, "Null out param");
10178 *aOnline
= !NS_IsOffline();
10183 nsNavigator::GetBuildID(nsAString
& aBuildID
)
10185 if (!nsContentUtils::IsCallerTrustedForRead()) {
10186 const nsAdoptingCString
& override
=
10187 nsContentUtils::GetCharPref("general.buildID.override");
10190 CopyUTF8toUTF16(override
, aBuildID
);
10195 nsCOMPtr
<nsIXULAppInfo
> appInfo
=
10196 do_GetService("@mozilla.org/xre/app-info;1");
10198 return NS_ERROR_NOT_IMPLEMENTED
;
10200 nsCAutoString buildID
;
10201 nsresult rv
= appInfo
->GetAppBuildID(buildID
);
10205 aBuildID
.Truncate();
10206 AppendASCIItoUTF16(buildID
, aBuildID
);
10211 nsNavigator::JavaEnabled(PRBool
*aReturn
)
10213 // Return true if we have a handler for "application/x-java-vm",
10214 // otherwise return false.
10215 *aReturn
= PR_FALSE
;
10218 mMimeTypes
= new nsMimeTypeArray(this);
10220 return NS_ERROR_OUT_OF_MEMORY
;
10223 RefreshMIMEArray();
10226 mMimeTypes
->GetLength(&count
);
10227 for (PRUint32 i
= 0; i
< count
; i
++) {
10229 nsIDOMMimeType
* type
= mMimeTypes
->GetItemAt(i
, &rv
);
10230 nsAutoString mimeString
;
10231 if (type
&& NS_SUCCEEDED(type
->GetType(mimeString
))) {
10232 if (mimeString
.EqualsLiteral("application/x-java-vm")) {
10233 *aReturn
= PR_TRUE
;
10243 nsNavigator::TaintEnabled(PRBool
*aReturn
)
10245 *aReturn
= PR_FALSE
;
10250 nsNavigator::LoadingNewDocument()
10252 // Release these so that they will be recreated for the
10253 // new document (if requested). The plugins or mime types
10254 // arrays may have changed. See bug 150087.
10256 mMimeTypes
->Invalidate();
10257 mMimeTypes
= nsnull
;
10261 mPlugins
->Invalidate();
10267 mGeolocation
->Shutdown();
10268 mGeolocation
= nsnull
;
10273 nsNavigator::RefreshMIMEArray()
10275 nsresult rv
= NS_OK
;
10277 rv
= mMimeTypes
->Refresh();
10281 //*****************************************************************************
10282 // nsNavigator::nsIDOMClientInformation
10283 //*****************************************************************************
10286 nsNavigator::RegisterContentHandler(const nsAString
& aMIMEType
,
10287 const nsAString
& aURI
,
10288 const nsAString
& aTitle
)
10290 nsCOMPtr
<nsIWebContentHandlerRegistrar
> registrar
=
10291 do_GetService(NS_WEBCONTENTHANDLERREGISTRAR_CONTRACTID
);
10292 if (registrar
&& mDocShell
) {
10293 nsCOMPtr
<nsIDOMWindow
> contentDOMWindow(do_GetInterface(mDocShell
));
10294 if (contentDOMWindow
)
10295 return registrar
->RegisterContentHandler(aMIMEType
, aURI
, aTitle
,
10303 nsNavigator::RegisterProtocolHandler(const nsAString
& aProtocol
,
10304 const nsAString
& aURI
,
10305 const nsAString
& aTitle
)
10307 nsCOMPtr
<nsIWebContentHandlerRegistrar
> registrar
=
10308 do_GetService(NS_WEBCONTENTHANDLERREGISTRAR_CONTRACTID
);
10309 if (registrar
&& mDocShell
) {
10310 nsCOMPtr
<nsIDOMWindow
> contentDOMWindow(do_GetInterface(mDocShell
));
10311 if (contentDOMWindow
)
10312 return registrar
->RegisterProtocolHandler(aProtocol
, aURI
, aTitle
,
10321 nsNavigator::MozIsLocallyAvailable(const nsAString
&aURI
,
10322 PRBool aWhenOffline
,
10323 PRBool
*aIsAvailable
)
10325 nsCOMPtr
<nsIURI
> uri
;
10326 nsresult rv
= NS_NewURI(getter_AddRefs(uri
), aURI
);
10327 NS_ENSURE_SUCCESS(rv
, rv
);
10329 // This method of checking the cache will only work for http/https urls
10331 rv
= uri
->SchemeIs("http", &match
);
10332 NS_ENSURE_SUCCESS(rv
, rv
);
10334 rv
= uri
->SchemeIs("https", &match
);
10335 NS_ENSURE_SUCCESS(rv
, rv
);
10336 if (!match
) return NS_ERROR_DOM_BAD_URI
;
10339 // Same origin check
10340 nsCOMPtr
<nsIJSContextStack
> stack
= do_GetService(sJSStackContractID
);
10341 NS_ENSURE_TRUE(stack
, NS_ERROR_FAILURE
);
10343 JSContext
*cx
= nsnull
;
10344 rv
= stack
->Peek(&cx
);
10345 NS_ENSURE_TRUE(cx
, NS_ERROR_FAILURE
);
10347 rv
= nsContentUtils::GetSecurityManager()->CheckSameOrigin(cx
, uri
);
10348 NS_ENSURE_SUCCESS(rv
, rv
);
10350 // these load flags cause an error to be thrown if there is no
10351 // valid cache entry, and skip the load if there is.
10352 // if the cache is busy, assume that it is not yet available rather
10353 // than waiting for it to become available.
10354 PRUint32 loadFlags
= nsIChannel::INHIBIT_CACHING
|
10355 nsICachingChannel::LOAD_NO_NETWORK_IO
|
10356 nsICachingChannel::LOAD_ONLY_IF_MODIFIED
|
10357 nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE_IF_BUSY
;
10359 if (aWhenOffline
) {
10360 loadFlags
|= nsICachingChannel::LOAD_CHECK_OFFLINE_CACHE
|
10361 nsICachingChannel::LOAD_ONLY_FROM_CACHE
|
10362 nsIRequest::LOAD_FROM_CACHE
;
10365 nsCOMPtr
<nsIChannel
> channel
;
10366 rv
= NS_NewChannel(getter_AddRefs(channel
), uri
,
10367 nsnull
, nsnull
, nsnull
, loadFlags
);
10368 NS_ENSURE_SUCCESS(rv
, rv
);
10370 nsCOMPtr
<nsIInputStream
> stream
;
10371 rv
= channel
->Open(getter_AddRefs(stream
));
10372 NS_ENSURE_SUCCESS(rv
, rv
);
10377 rv
= channel
->GetStatus(&status
);
10378 NS_ENSURE_SUCCESS(rv
, rv
);
10380 if (NS_SUCCEEDED(status
)) {
10381 nsCOMPtr
<nsIHttpChannel
> httpChannel
= do_QueryInterface(channel
);
10382 rv
= httpChannel
->GetRequestSucceeded(aIsAvailable
);
10383 NS_ENSURE_SUCCESS(rv
, rv
);
10385 *aIsAvailable
= PR_FALSE
;
10391 //*****************************************************************************
10392 // nsNavigator::nsIDOMNavigatorGeolocation
10393 //*****************************************************************************
10395 NS_IMETHODIMP
nsNavigator::GetGeolocation(nsIDOMGeoGeolocation
**_retval
)
10397 NS_ENSURE_ARG_POINTER(_retval
);
10400 if (mGeolocation
) {
10401 NS_ADDREF(*_retval
= mGeolocation
);
10406 return NS_ERROR_FAILURE
;
10408 nsCOMPtr
<nsIDOMWindow
> contentDOMWindow(do_GetInterface(mDocShell
));
10409 if (!contentDOMWindow
)
10410 return NS_ERROR_FAILURE
;
10412 mGeolocation
= new nsGeolocation();
10414 return NS_ERROR_FAILURE
;
10416 if (NS_FAILED(mGeolocation
->Init(contentDOMWindow
)))
10417 return NS_ERROR_FAILURE
;
10419 NS_ADDREF(*_retval
= mGeolocation
);